如何使用Kubernetes运行一个简单的PHP Hello World应用程序 [英] How to run a simple php hello world application using Kubernetes

查看:51
本文介绍了如何使用Kubernetes运行一个简单的PHP Hello World应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试部署和运行一个简单的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 through hostPath.

      从这里开始,我们的选择是:

      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 for index.php
        • fastcgi_pass php:9000 pointing to the service called php service listening on port 9000.
          • 存储空间:

          这是可变的,具体取决于您使用的存储类型. 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.

          • 话虽如此,这里是pvc.yaml:
          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 called code 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 on mountPath /code and the configmap we created being monted as a file called site.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.

                  复制:

                  • 让我们创建文件:首先创建configmappvc,因为它们是Pod正确启动所必需的,然后是服务和部署:
                  • Let's create the files: first the configmap and pvc, 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 returned 200 OK from nginx server, powered by PHP 7 and the content of the index.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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆