如何使用Kubernetes运行一个简单的PHP Hello World应用程序 [英] How to run a simple php hello world application using Kubernetes
问题描述
我正在尝试部署和运行一个简单的PHP应用程序,该应用程序将仅通过我的Kubernetes集群(仅是主节点集群)显示一条Hello World
消息,不幸的是,我无法做到这一点.
I'm trying to deploy and run a simple PHP application that will only show a Hello World
message through my Kubernetes cluster which is only a master node cluster, unfortunately, I can't do that.
我正在描述我的项目结构-
我有一个名为kubernetes-test
的根项目目录,在该目录下,我有3个yaml
文件,在该目录下有一个名为code
的目录,我有一个名为index.php
I'm describing my project structure -
I have a root project directory called kubernetes-test
and under that directory, I have 3 yaml
files and one directory called code
under that directory I have a PHP file called index.php
hello-world-service.yaml:
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
tier: backend
spec:
selector:
app: nginx
tier: backend
type: NodePort
ports:
- nodePort: 30500
port: 80
targetPort: 80
nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: nginx
tier: backend
template:
metadata:
labels:
app: nginx
tier: backend
spec:
volumes:
- name: code
hostPath:
path: /code
- name: config
configMap:
name: nginx-config
items:
- key: config
path: site.conf
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
volumeMounts:
- name: code
mountPath: /var/www/html
- name: config
mountPath: /etc/nginx/conf.d
php-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php
labels:
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: php
tier: backend
template:
metadata:
labels:
app: php
tier: backend
spec:
volumes:
- name: code
hostPath:
path: /code
containers:
- name: php
image: php:7-fpm
volumeMounts:
- name: code
mountPath: /var/www/html
code/index.php
<?php
echo 'Hello World';
在我通过互联网找到的所有内容中.
Above all those things I've found through the internet.
当我运行此命令kubectl get pods
那么状态永远显示ContainerCreating
,对于这样的Nginx部署
When I ran this command kubectl get pods
then the status is showing ContainerCreating
forever for the Nginx deployment like this
NAME READY STATUS RESTARTS AGE
nginx-64c9df788f-jxwzx 0/1 ContainerCreating 0 12h
php-55f974bb4-qvv9x 1/1 Running 0 25s
命令: kubectl describe pod nginx-64c9df788f-jxwzx
输出:
Name: nginx-64c9df788f-jxwzx
Namespace: default
Priority: 0
Node: bablu-node/192.168.43.123
Start Time: Mon, 11 May 2020 03:20:58 +0600
Labels: app=nginx
pod-template-hash=64c9df788f
tier=backend
Annotations: <none>
Status: Pending
IP:
IPs: <none>
Controlled By: ReplicaSet/nginx-64c9df788f
Containers:
nginx:
Container ID:
Image: nginx
Image ID:
Port: 80/TCP
Host Port: 0/TCP
State: Waiting
Reason: ContainerCreating
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/etc/nginx/conf.d from config (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-l2zp2 (ro)
/var/www/html from code (rw)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
code:
Type: HostPath (bare host directory volume)
Path: /code
HostPathType:
config:
Type: ConfigMap (a volume populated by a ConfigMap)
Name: nginx-config
Optional: false
default-token-l2zp2:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-l2zp2
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedMount 31m (x14 over 147m) kubelet, bablu-node Unable to attach or mount volumes: unmounted volumes=[config], unattached volumes=[default-token-l2zp2 code config]: timed out waiting for the condition
Warning FailedMount 16m (x82 over 167m) kubelet, bablu-node MountVolume.SetUp failed for volume "config" : configmap "nginx-config" not found
Warning FailedMount 6m53s (x44 over 165m) kubelet, bablu-node Unable to attach or mount volumes: unmounted volumes=[config], unattached volumes=[code config default-token-l2zp2]: timed out waiting for the condition
Warning FailedMount 2m23s (x10 over 163m) kubelet, bablu-node Unable to attach or mount volumes: unmounted volumes=[config], unattached volumes=[config default-token-l2zp2 code]: timed out waiting for the condition
命令:kubectl get events -n default
输出:
LAST SEEN TYPE REASON OBJECT MESSAGE
18m Warning FailedMount pod/nginx-64c9df788f-jxwzx MountVolume.SetUp failed for volume "config" : configmap "nginx-config" not found
8m45s Warning FailedMount pod/nginx-64c9df788f-jxwzx Unable to attach or mount volumes: unmounted volumes=[config], unattached volumes=[code config default-token-l2zp2]: timed out waiting for the condition
4m15s Warning FailedMount pod/nginx-64c9df788f-jxwzx Unable to attach or mount volumes: unmounted volumes=[config], unattached volumes=[config default-token-l2zp2 code]: timed out waiting for the condition
33m Warning FailedMount pod/nginx-64c9df788f-jxwzx Unable to attach or mount volumes: unmounted volumes=[config], unattached volumes=[default-token-l2zp2 code config]: timed out waiting for the condition
18m Normal Scheduled pod/php-55f974bb4-qvv9x Successfully assigned default/php-55f974bb4-qvv9x to bablu-node
18m Normal Pulled pod/php-55f974bb4-qvv9x Container image "php:7-fpm" already present on machine
18m Normal Created pod/php-55f974bb4-qvv9x Created container php
18m Normal Started pod/php-55f974bb4-qvv9x Started container php
18m Normal SuccessfulCreate replicaset/php-55f974bb4 Created pod: php-55f974bb4-qvv9x
18m Normal ScalingReplicaSet deployment/php Scaled up replica set php-55f974bb4 to 1
有人可以帮助我吗? 在此先感谢!
Can anyone please help me? Thanks in advance!!
推荐答案
我运行了您的环境,这是我发现的主要问题:
I ran your environment and here are the main issues I found:
- 首先,您尚未部署nginx-config,但这只是您的第一个问题,很容易解决(下面的示例中有更多内容).
- 第二个问题(我认为是主要问题)是
HostPath
的用法:- 正如我在此处
HostPath
要求容器进程以root用户身份运行. - php-fpm以
www-data
运行,因此如果通过hostPath
挂载此文件夹,他将无法使用/code
上的挂载文件.
- First of all, you don't have the nginx-config deployed, but this would be only your first issue and easily addressable (more on the example below).
- The second (and on my opinion the main) issue, is the usage of
HostPath
:- As I explained here
HostPath
requires that the container process run as root. - php-fpm runs as
www-data
therefore he cannot use the mount files at/code
if this folder is mounted throughhostPath
.
从这里开始,我们的选择是:
From here our options now are:
- 烘烤图像中的php文件(或作为configmap),并在同一pod中(共享一个emptydir文件夹)运行nginx和php,有关此过程的更多信息,请参见本指南:永久卷中从外部存储库下载php文件.这种方法要求nginx和php在同一节点上运行-因为存储是RWO,这意味着只能以读写方式安装在一个节点上.由于您的设置位于单个节点上,因此在本示例中将使用此方法.
- Bake the php file inside the image (or as a configmap) and run both nginx and php in the same pod (sharing an emptydir folder), more about this process in this guide: PHP-FPM, Nginx, Kubernetes, and Docker - while in one hand it involves creating a new Docker image, on the other hand it spare you of configuring a storage provisioner if you don't already have one.
- Use an external storage to mount the file in a Persistent Volume downloading the php file from an external repository. This approach requires nginx and php to run on the same node - because storage is RWO, meaning that can be mount as read-write on only one node. Since your setup is on a single node, I'll use this approach on this example.
我尝试重现您的示例,但是我必须进行一些更改. 这些是文件:
I tried to reproduce as close as your example, but I had to do some changes. Here are the files:
-
cm-nginx.yaml
:
apiVersion: v1 kind: ConfigMap metadata: name: nginx-config labels: tier: backend data: config : | server { index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /code; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } }
-
root /code
指向要查找index.php
的目录
-
fastcgi_pass php:9000
指向在port 9000
上侦听的名为php
服务的服务. root /code
is pointing the directory where to look forindex.php
fastcgi_pass php:9000
pointing to the service calledphp
service listening onport 9000
.- 存储空间:
- 话虽如此,这里是pvc.yaml:
这是可变的,具体取决于您使用的存储类型. Minikube带有开箱即用配置的存储提供程序和storageclass.而且,尽管minikube存储提供程序称为
minikube-hostpath
,它是一种CSI,它不需要在容器级别上的root用户访问即可运行.This is mutable depending on the storage type you are using. Minikube comes with storage provider and storageclass configured out of the box. And although minikube storage provider is called
minikube-hostpath
it's a CSI that will not require root access on container level to run.apiVersion: v1 kind: PersistentVolumeClaim metadata: name: code spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: standard
请注意,
standard
是minikube中内置的动态存储提供程序的名称.我们在这里要做的是创建一个名为code
的PVC,以使我们的应用程序运行.Note that
standard
is the name of the dynamic storage provider built in minikube. What we are doing here is to create a PVC calledcode
for our app to run.-
php.yaml
:
apiVersion: apps/v1 kind: Deployment metadata: name: php labels: tier: backend spec: replicas: 1 selector: matchLabels: app: php tier: backend template: metadata: labels: app: php tier: backend spec: volumes: - name: code persistentVolumeClaim: claimName: code containers: - name: php image: php:7-fpm volumeMounts: - name: code mountPath: /code initContainers: - name: install image: busybox volumeMounts: - name: code mountPath: /code command: - wget - "-O" - "/code/index.php" - https://raw.githubusercontent.com/videofalls/demo/master/index.php
-
在这里,我们使用
busybox
initContainer来获取此php文件(与您使用的php文件相同)并将其保存在已安装的卷/code
中.here we are using a
busybox
initContainer to wget this php file (which is identical to the one you are using) and save it inside the mounted volume/code
.PHP服务
svc-php.yaml
:apiVersion: v1 kind: Service metadata: name: php labels: tier: backend spec: selector: app: php tier: backend ports: - protocol: TCP port: 9000
- Nginx部署
nginx.yaml
: - The Nginx deployment
nginx.yaml
:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: tier: backend spec: replicas: 1 selector: matchLabels: app: nginx tier: backend template: metadata: labels: app: nginx tier: backend spec: volumes: - name: code persistentVolumeClaim: claimName: code - name: config configMap: name: nginx-config items: - key: config path: site.conf containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 volumeMounts: - name: code mountPath: /code - name: config mountPath: /etc/nginx/conf.d
这里的关键点是在
mountPath
/code
上的名为code
的PVC的安装,以及我们创建的configmap被作为site.conf
文件保存在/etc/nginx/conf.d
The key points here, is the mount of the PVC called
code
onmountPath
/code
and the configmap we created being monted as a file calledsite.conf
inside the folder/etc/nginx/conf.d
- Nginx服务
svc-nginx.yaml
:
apiVersion: v1 kind: Service metadata: name: nginx labels: tier: backend spec: type: NodePort selector: app: nginx tier: backend ports: - protocol: TCP port: 80
我正在使用NodePort简化输出测试.
I'm using NodePort to ease the output test.
复制:
- 让我们创建文件:首先创建
configmap
和pvc
,因为它们是Pod正确启动所必需的,然后是服务和部署:
- Let's create the files: first the
configmap
andpvc
, since they are required for the pods to start correctly, then the services and deployments:
$ ls cm-nginx.yaml nginx.yaml php.yaml pvc.yaml svc-nginx.yaml svc-php.yaml $ kubectl apply -f cm-nginx.yaml configmap/nginx-config created $ kubectl apply -f pvc.yaml persistentvolumeclaim/code created $ kubectl get cm NAME DATA AGE nginx-config 1 52s $ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE code Bound pvc-b63559a0-a306-46f2-942b-0a063bc4ab6b 1Gi RWO standard 17s $ kubectl apply -f svc-php.yaml service/php created $ kubectl apply -f svc-nginx.yaml service/nginx created $ kubectl apply -f php.yaml deployment.apps/php created $ kubectl get pods NAME READY STATUS RESTARTS AGE php-69d5c956ff-8tjfn 1/1 Running 0 5s $ kubectl apply -f nginx.yaml deployment.apps/nginx created $ kubectl get pods NAME READY STATUS RESTARTS AGE nginx-6854dcb7db-75zxt 1/1 Running 0 4s php-69d5c956ff-8tjfn 1/1 Running 0 22s $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx NodePort 10.107.16.212 <none> 80:31017/TCP 41s php ClusterIP 10.97.237.214 <none> 9000/TCP 44s $ minikube service nginx --url http://172.17.0.2:31017 $ curl -i http://172.17.0.2:31017 HTTP/1.1 200 OK Server: nginx/1.7.9 Date: Thu, 28 May 2020 19:04:48 GMT Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Connection: keep-alive X-Powered-By: PHP/7.4.6 Demo Test
在这里,我们可以看到
curl
从nginx服务器返回的200 OK
,它由PHP 7提供支持,并包含index.php
文件的内容.Here we can see the
curl
returned200 OK
from nginx server, powered by PHP 7 and the content of theindex.php
file.我希望它可以帮助您更清楚地了解这种情况.
I hope it helps you have a clearer understanding of this scenario.
如果您有任何问题,请在评论中告诉我.
If you have any question, let me know in the comments.
这篇关于如何使用Kubernetes运行一个简单的PHP Hello World应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- Nginx部署
- As I explained here
- 正如我在此处