如何在Ubuntu 18.04上使用Kubernetes部署PHP应用程序

The author selected Electronic Frontier Foundation to receive a donation as part of the Write for DOnations program.

作者选择了电子前沿基金会作为“ Write for DOnations”计划的一部分来接受捐赠。

介绍 (Introduction)

Kubernetes is an open source container orchestration system. It allows you to create, update, and scale containers without worrying about downtime.

Kubernetes是一个开源的容器编排系统。 它使您可以创建,更新和缩放容器,而不必担心停机时间。

To run a PHP application, Nginx acts as a proxy to PHP-FPM. Containerizing this setup in a single container can be a cumbersome process, but Kubernetes will help manage both services in separate containers. Using Kubernetes will allow you to keep your containers reusable and swappable, and you will not have to rebuild your container image every time there’s a new version of Nginx or PHP.

要运行PHP应用程序,Nginx充当PHP-FPM的代理。 将该设置容器化到一个容器中可能是一个繁琐的过程,但是Kubernetes将帮助在单独的容器中管理这两种服务。 使用Kubernetes将使您能够保持容器可重用和可交换,并且不必在每次有新版本的Nginx或PHP时都重建容器映像。

In this tutorial, you will deploy a PHP 7 application on a Kubernetes cluster with Nginx and PHP-FPM running in separate containers. You will also learn how to keep your configuration files and application code outside the container image using DigitalOcean’s Block Storage system. This approach will allow you to reuse the Nginx image for any application that needs a web/proxy server by passing a configuration volume, rather than rebuilding the image.

在本教程中,您将在Kubernetes集群上部署PHP 7应用程序,并且Nginx和PHP-FPM在单独的容器中运行。 您还将学习如何使用DigitalOcean的块存储系统将配置文件和应用程序代码保留在容器映像之外。 通过传递配置卷,而不是重建映像,该方法将允许您将Nginx映像重用于需要Web /代理服务器的任何应用程序。

先决条件 (Prerequisites)

第1步-创建PHP-FPM和Nginx服务 (Step 1 — Creating the PHP-FPM and Nginx Services)

In this step, you will create the PHP-FPM and Nginx services. A service allows access to a set of pods from within the cluster. Services within a cluster can communicate directly through their names, without the need for IP addresses. The PHP-FPM service will allow access to the PHP-FPM pods, while the Nginx service will allow access to the Nginx pods.

在此步骤中,您将创建PHP-FPM和Nginx服务。 服务允许从群集内访问一组Pod。 群集中的服务可以直接通过其名称进行通信,而无需IP地址。 PHP-FPM服务将允许访问PHP-FPM容器,而Nginx服务将允许访问Nginx容器。

Since Nginx pods will proxy the PHP-FPM pods, you will need to tell the service how to find them. Instead of using IP addresses, you will take advantage of Kubernetes’ automatic service discovery to use human-readable names to route requests to the appropriate service.

由于Nginx容器将代理PHP-FPM容器,因此您需要告诉服务如何找到它们。 您将不使用IP地址,而是利用Kubernetes的自动服务发现来使用人类可读的名称将请求路由到适当的服务。

To create the service, you will create an object definition file. Every Kubernetes object definition is a YAML file that contains at least the following items:

要创建服务,您将创建一个对象定义文件。 每个Kubernetes对象定义都是一个YAML文件,其中至少包含以下各项:

  • apiVersion: The version of the Kubernetes API that the definition belongs to.

    apiVersion :该定义所属的Kubernetes API的版本。

  • kind: The Kubernetes object this file represents. For example, a pod or service.

    kind :此文件表示的Kubernetes对象。 例如, podservice

  • metadata: This contains the name of the object along with any labels that you may wish to apply to it.

    metadata :它包含对象的name以及您可能希望对其应用的所有labels

  • spec: This contains a specific configuration depending on the kind of object you are creating, such as the container image or the ports on which the container will be accessible from.

    spec :它包含特定的配置,具体取决于您要创建的对象的类型,例如容器映像或可从中访问容器的端口。

First you will create a directory to hold your Kubernetes object definitions.

首先,您将创建一个目录来保存您的Kubernetes对象定义。

SSH to your master node and create the definitions directory that will hold your Kubernetes object definitions.

SSH到您的主节点,并创建将包含您的Kubernetes对象定义的definitions目录。

  • mkdir definitions

    mkdir定义

Navigate to the newly created definitions directory:

导航到新创建的definitions目录:

  • cd definitions

    cd定义

Make your PHP-FPM service by creating a php_service.yaml file:

通过创建php_service.yaml文件来创建PHP-FPM服务:

  • nano php_service.yaml

    纳米php_service.yaml

Set kind as Service to specify that this object is a service:

kind设置为Service以指定该对象是服务:

php_service.yaml
php_service.yaml
apiVersion: v1
kind: Service

Name the service php since it will provide access to PHP-FPM:

将服务命名为php因为它将提供对PHP-FPM的访问:

php_service.yaml
php_service.yaml
...
metadata:
  name: php

You will logically group different objects with labels. In this tutorial, you will use labels to group the objects into “tiers”, such as frontend or backend. The PHP pods will run behind this service, so you will label it as tier: backend.

您将在逻辑上将带有标签的不同对象分组。 在本教程中,您将使用标签将对象分组为“层”,例如前端或后端。 PHP容器将在此服务之后运行,因此您将其标记为tier: backend

php_service.yaml
php_service.yaml
...
  labels:
    tier: backend

A service determines which pods to access by using selector labels. A pod that matches these labels will be serviced, independent of whether the pod was created before or after the service. You will add labels for your pods later in the tutorial.

服务使用selector标签确定要访问的窗格。 与这些标签匹配的容器将得到服务,而与该容器是在服务之前还是之后创建无关。 您将在本教程的后面部分为豆荚添加标签。

Use the tier: backend label to assign the pod into the back-end tier. You will also add the app: php label to specify that this pod runs PHP. Add these two labels after the metadata section.

使用tier: backend标签将容器分配到后端层。 您还将添加app: php标签,以指定此pod运行PHP。 在metadata部分之后添加这两个标签。

php_service.yaml
php_service.yaml
...
spec:
  selector:
    app: php
    tier: backend

Next, specify the port used to access this service. You will use port 9000 in this tutorial. Add it to the php_service.yaml file under spec:

接下来,指定用于访问此服务的端口。 在本教程中,您将使用端口9000 。 将其添加到spec下的php_service.yaml文件中:

php_service.yaml
php_service.yaml
...
  ports:
    - protocol: TCP
      port: 9000

Your completed php_service.yaml file will look like this:

您完成的php_service.yaml文件将如下所示:

php_service.yaml
php_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: php
  labels:
    tier: backend
spec:
  selector:
    app: php
    tier: backend
  ports:
  - protocol: TCP
    port: 9000

Hit CTRL + O to save the file, and then CTRL + X to exit nano.

CTRL + O保存文件,然后按CTRL + X退出nano

Now that you’ve created the object definition for your service, to run the service you will use the kubectl apply command along with the -f argument and specify your php_service.yaml file.

现在,您已经为服务创建了对象定义,要运行该服务,您将使用kubectl apply命令以及-f参数并指定php_service.yaml文件。

Create your service:

创建您的服务:

  • kubectl apply -f php_service.yaml

    kubectl套用-f php_service.yaml

This output confirms the service creation:

此输出确认服务创建:


   
   
Output
service/php created

Verify that your service is running:

验证您的服务正在运行:

  • kubectl get svc

    kubectl获取svc

You will see your PHP-FPM service running:

您将看到您PHP-FPM服务正在运行:


   
   
Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10m php ClusterIP 10.100.59.238 <none> 9000/TCP 5m

There are various service types that Kubernetes supports. Your php service uses the default service type, ClusterIP. This service type assigns an internal IP and makes the service reachable only from within the cluster.

Kubernetes支持多种服务类型 。 您的php服务使用默认服务类型ClusterIP 。 此服务类型分配一个内部IP,并使该服务仅可从群集内部访问。

Now that the PHP-FPM service is ready, you will create the Nginx service. Create and open a new file called nginx_service.yaml with the editor:

现在,PHP-FPM服务已准备就绪,您将创建Nginx服务。 使用编辑器创建并打开一个名为nginx_service.yaml的新文件:

  • nano nginx_service.yaml

    纳米nginx_service.yaml

This service will target Nginx pods, so you will name it nginx. You will also add a tier: backend label as it belongs in the back-end tier:

该服务将以Nginx pod为目标,因此您将其命名为nginx 。 您还将添加tier: backend标签,因为它属于后端层:

nginx_service.yaml
nginx_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    tier: backend

Similar to the php service, target the pods with the selector labels app: nginx and tier: backend. Make this service accessible on port 80, the default HTTP port.

php服务类似,使用选择器标签app: nginx定位目标容器app: nginxtier: backend 。 使此服务可通过端口80 (默认的HTTP端口)访问。

nginx_service.yaml
nginx_service.yaml
...
spec:
  selector:
    app: nginx
    tier: backend
  ports:
  - protocol: TCP
    port: 80

The Nginx service will be publicly accessible to the internet from your Droplet’s public IP address. your_public_ip can be found from your DigitalOcean Control Panel. Under spec.externalIPs, add:

Nginx服务将从您Droplet的公共IP地址公开访问Internet。 your_public_ip可以在DigitalOcean控制面板中找到your_public_ip 。 在spec.externalIPs ,添加:

nginx_service.yaml
nginx_service.yaml
...
spec:
  externalIPs:
  - your_public_ip

Your nginx_service.yaml file will look like this:

您的nginx_service.yaml文件将如下所示:

nginx_service.yaml
nginx_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    tier: backend
spec:
  selector:
    app: nginx
    tier: backend
  ports:
  - protocol: TCP
    port: 80
  externalIPs:
  - your_public_ip

Save and close the file. Create the Nginx service:

保存并关闭文件。 创建Nginx服务:

  • kubectl apply -f nginx_service.yaml

    kubectl应用-f nginx_service.yaml

You will see the following output when the service is running:

服务运行时,您将看到以下输出:


   
   
Output
service/nginx created

You can view all running services by executing:

您可以通过执行以下命令查看所有正在运行的服务:

  • kubectl get svc

    kubectl获取svc

You will see both the PHP-FPM and Nginx services listed in the output:

您将在输出中看到PHP-FPM和Nginx服务:


   
   
Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13m nginx ClusterIP 10.102.160.47 your_public_ip 80/TCP 50s php ClusterIP 10.100.59.238 <none> 9000/TCP 8m

Please note, if you want to delete a service you can run:

请注意,如果要删除服务,可以运行:

  • kubectl delete svc/service_name

    kubectl删除svc / service_name

Now that you’ve created your PHP-FPM and Nginx services, you will need to specify where to store your application code and configuration files.

现在,您已经创建了PHP-FPM和Nginx服务,您将需要指定存储应用程序代码和配置文件的位置。

步骤2 —安装DigitalOcean存储插件 (Step 2 — Installing the DigitalOcean Storage Plug-In)

Kubernetes provides different storage plug-ins that can create the storage space for your environment. In this step, you will install the DigitalOcean storage plug-in to create block storage on DigitalOcean. Once the installation is complete, it will add a storage class named do-block-storage that you will use to create your block storage.

Kubernetes提供了不同的存储插件,可以为您的环境创建存储空间。 在此步骤中,您将安装DigitalOcean存储插件以在DigitalOcean上创建块存储 。 安装完成后,它将添加一个名为do-block-storage的存储类,您将使用该存储类来创建块存储。

You will first configure a Kubernetes Secret object to store your DigitalOcean API token. Secret objects are used to share sensitive information, like SSH keys and passwords, with other Kubernetes objects within the same namespace. Namespaces provide a way to logically separate your Kubernetes objects.

首先,您将配置一个Kubernetes Secret对象来存储您的DigitalOcean API令牌。 秘密对象用于与同一名称空间内的其他Kubernetes对象共享敏感信息,例如SSH密钥和密码。 命名空间提供了一种逻辑上分离Kubernetes对象的方法。

Open a file named secret.yaml with the editor:

使用编辑器打开一个名为secret.yaml的文件:

  • nano secret.yaml

    纳米秘密

You will name your Secret object digitalocean and add it to the kube-system namespace. The kube-system namespace is the default namespace for Kubernetes’ internal services and is also used by the DigitalOcean storage plug-in to launch various components.

您将命名您的Secret对象digitalocean并将其添加到kube-system命名空间。 kube-system名称空间是Kubernetes内部服务的默认名称空间,DigitalOcean存储插件还使用它来启动各种组件。

secret.yaml
secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: digitalocean
  namespace: kube-system

Instead of a spec key, a Secret uses a data or stringData key to hold the required information. The data parameter holds base64 encoded data that is automatically decoded when retrieved. The stringData parameter holds non-encoded data that is automatically encoded during creation or updates, and does not output the data when retrieving Secrets. You will use stringData in this tutorial for convenience.

机密使用datastringData密钥而不是spec密钥来保存所需的信息。 data参数包含base64编码的数据,该data在检索时会自动解码。 stringData参数保存在创建或更新期间自动编码的未编码数据,并且在检索Secrets时不输出数据。 为了方便起见,在本教程中将使用stringData

Add the access-token as stringData:

access-token添加为stringData

secret.yaml
secret.yaml
...
stringData:
  access-token: your-api-token

Save and exit the file.

保存并退出文件。

Your secret.yaml file will look like this:

您的secret.yaml文件将如下所示:

secret.yaml
secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: digitalocean
  namespace: kube-system
stringData:
  access-token: your-api-token

Create the secret:

创建秘密:

  • kubectl apply -f secret.yaml

    kubectl应用-f secret.yaml

You will see this output upon Secret creation:

创建Secret时,您将看到以下输出:


   
   
Output
secret/digitalocean created

You can view the secret with the following command:

您可以使用以下命令查看机密:

  • kubectl -n kube-system get secret digitalocean

    kubectl -n kube-system获得秘密数字海洋

The output will look similar to this:

输出将类似于以下内容:


   
   
Output
NAME TYPE DATA AGE digitalocean Opaque 1 41s

The Opaque type means that this Secret is read-only, which is standard for stringData Secrets. You can read more about it on the Secret design spec. The DATA field shows the number of items stored in this Secret. In this case, it shows 1 because you have a single key stored.

Opaque类型表示此Secret是只读的,这是stringData Secrets的标准stringData 。 您可以在Secret设计规范中阅读有关它的更多信息。 DATA字段显示此密钥中存储的项目数。 在这种情况下,它显示为1因为您存储了一个密钥。

Now that your Secret is in place, install the DigitalOcean block storage plug-in:

现在您的秘密已经到位,安装DigitalOcean块存储插件

  • kubectl apply -f https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v1.1.0.yaml

    kubectl适用-f https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v1.1.0.yaml

You will see output similar to the following:

您将看到类似于以下内容的输出:


   
   
Output
csidriver.storage.k8s.io/dobs.csi.digitalocean.com created customresourcedefinition.apiextensions.k8s.io/volumesnapshotclasses.snapshot.storage.k8s.io created customresourcedefinition.apiextensions.k8s.io/volumesnapshotcontents.snapshot.storage.k8s.io created customresourcedefinition.apiextensions.k8s.io/volumesnapshots.snapshot.storage.k8s.io created storageclass.storage.k8s.io/do-block-storage created statefulset.apps/csi-do-controller created serviceaccount/csi-do-controller-sa created clusterrole.rbac.authorization.k8s.io/csi-do-provisioner-role created clusterrolebinding.rbac.authorization.k8s.io/csi-do-provisioner-binding created clusterrole.rbac.authorization.k8s.io/csi-do-attacher-role created clusterrolebinding.rbac.authorization.k8s.io/csi-do-attacher-binding created clusterrole.rbac.authorization.k8s.io/csi-do-snapshotter-role created clusterrolebinding.rbac.authorization.k8s.io/csi-do-snapshotter-binding created daemonset.apps/csi-do-node created serviceaccount/csi-do-node-sa created clusterrole.rbac.authorization.k8s.io/csi-do-node-driver-registrar-role created clusterrolebinding.rbac.authorization.k8s.io/csi-do-node-driver-registrar-binding created error: unable to recognize "https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v1.1.0.yaml": no matches for kind "VolumeSnapshotClass" in version "snapshot.storage.k8s.io/v1alpha1"

For this tutorial, it is safe to ignore the errors.

对于本教程,可以忽略这些错误。

Now that you have installed the DigitalOcean storage plug-in, you can create block storage to hold your application code and configuration files.

现在,您已经安装了DigitalOcean存储插件,您可以创建块存储来保存您的应用程序代码和配置文件。

第3步-创建持久卷 (Step 3 — Creating the Persistent Volume)

With your Secret in place and the block storage plug-in installed, you are now ready to create your Persistent Volume. A Persistent Volume, or PV, is block storage of a specified size that lives independently of a pod’s life cycle. Using a Persistent Volume will allow you to manage or update your pods without worrying about losing your application code. A Persistent Volume is accessed by using a PersistentVolumeClaim, or PVC, which mounts the PV at the required path.

设置好Secret并安装块存储插件之后,即可开始创建Persistent Volume了 。 持久卷(PV)是具有指定大小的块存储,其存储空间与容器的生命周期无关。 使用永久卷将使您可以管理或更新Pod,而不必担心丢失应用程序代码。 通过使用PersistentVolumeClaim或PVC访问“永久卷”,该PVC将PV安装在所需的路径上。

Open a file named code_volume.yaml with your editor:

使用编辑器打开一个名为code_volume.yaml的文件:

  • nano code_volume.yaml

    纳米代码_volume.yaml

Name the PVC code by adding the following parameters and values to your file:

通过在文件中添加以下参数和值来命名PVC code

code_volume.yaml
code_volume.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: code

The spec for a PVC contains the following items:

PVC spec包含以下各项:

    • ReadWriteOnce – mounts the volume as read-write by a single node

      ReadWriteOnce –将卷安装为单个节点可读写

    • ReadOnlyMany – mounts the volume as read-only by many nodes

      ReadOnlyMany –将卷装入许多节点为只读

    • ReadWriteMany – mounts the volume as read-write by many nodes

      ReadWriteMany –将卷安装为可被许多节点读写

    accessModes which vary by the use case. These are:

    accessModes因使用案例而异。 这些是:

  • resources – the storage space that you require

    resources –您需要的存储空间

DigitalOcean block storage is only mounted to a single node, so you will set the accessModes to ReadWriteOnce. This tutorial will guide you through adding a small amount of application code, so 1GB will be plenty in this use case. If you plan on storing a larger amount of code or data on the volume, you can modify the storage parameter to fit your requirements. You can increase the amount of storage after volume creation, but shrinking the disk is not supported.

DigitalOcean块存储仅安装到单个节点,因此您将accessModes设置为ReadWriteOnce 。 本教程将指导您添加少量的应用程序代码,因此在此用例中1GB足够了。 如果计划在卷上存储大量代码或数据,则可以修改storage参数以适合您的要求。 您可以在创建卷后增加存储量,但不支持缩小磁盘。

code_volume.yaml
code_volume.yaml
...
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

Next, specify the storage class that Kubernetes will use to provision the volumes. You will use the do-block-storage class created by the DigitalOcean block storage plug-in.

接下来,指定Kubernetes将用于供应卷的存储类。 您将使用由DigitalOcean块存储插件创建的do-block-storage类。

code_volume.yaml
code_volume.yaml
...
  storageClassName: do-block-storage

Your code_volume.yaml file will look like this:

您的code_volume.yaml文件将如下所示:

code_volume.yaml
code_volume.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: code
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: do-block-storage

Save and exit the file.

保存并退出文件。

Create the code PVC using kubectl:

使用kubectl创建code PVC:

  • kubectl apply -f code_volume.yaml

    kubectl应用-f code_volume.yaml

The following output tells you that the object was successfully created, and you are ready to mount your 1GB PVC as a volume.

以下输出告诉您对象已成功创建,并且可以将1GB PVC挂载为卷了。


   
   
Output
persistentvolumeclaim/code created

To view available Persistent Volumes (PV):

要查看可用的永久卷(PV):

  • kubectl get pv

    kubectl获取光伏

You will see your PV listed:

您将看到列出的PV:


   
   
Output
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-ca4df10f-ab8c-11e8-b89d-12331aa95b13 1Gi RWO Delete Bound default/code do-block-storage 2m

The fields above are an overview of your configuration file, except for Reclaim Policy and Status. The Reclaim Policy defines what is done with the PV after the PVC accessing it is deleted. Delete removes the PV from Kubernetes as well as the DigitalOcean infrastructure. You can learn more about the Reclaim Policy and Status from the Kubernetes PV documentation.

上面的字段是您的配置文件的概述, Reclaim PolicyStatus除外。 Reclaim Policy定义了删除PVC访问PVC后对PV的处理方式。 Delete会从Kubernetes和DigitalOcean基础架构中删除PV。 您可以从Kubernetes PV文档中了解有关Reclaim PolicyStatus更多信息

You’ve successfully created a Persistent Volume using the DigitalOcean block storage plug-in. Now that your Persistent Volume is ready, you will create your pods using a Deployment.

您已经使用DigitalOcean块存储插件成功创建了持久卷。 现在您的持久卷已准备就绪,您将使用“部署”创建吊舱。

第4步-创建PHP-FPM部署 (Step 4 — Creating a PHP-FPM Deployment)

In this step, you will learn how to use a Deployment to create your PHP-FPM pod. Deployments provide a uniform way to create, update, and manage pods by using ReplicaSets. If an update does not work as expected, a Deployment will automatically rollback its pods to a previous image.

在这一步中,您将学习如何使用Deployment创建PHP-FPM pod。 部署提供了使用ReplicaSets创建,更新和管理Pod的统一方法。 如果更新无法按预期工作,则Deployment将自动将其Pod回滚到先前的映像。

The Deployment spec.selector key will list the labels of the pods it will manage. It will also use the template key to create the required pods.

Deployment spec.selector键将列出它将管理的spec.selector的标签。 它还将使用template密钥来创建所需的容器。

This step will also introduce the use of Init Containers. Init Containers run one or more commands before the regular containers specified under the pod’s template key. In this tutorial, your Init Container will fetch a sample index.php file from GitHub Gist using wget. These are the contents of the sample file:

此步骤还将介绍初始化容器的使用。 初始化容器在容器的template键下指定的常规容器之前运行一个或多个命令。 在本教程中,您的Init容器将使用wgetGitHub Gist获取示例index.php文件。 这些是示例文件的内容:

index.php
index.php
<?php
echo phpinfo();

To create your Deployment, open a new file called php_deployment.yaml with your editor:

要创建您的部署,请使用编辑器打开一个名为php_deployment.yaml的新文件:

  • nano php_deployment.yaml

    纳米php_deployment.yaml

This Deployment will manage your PHP-FPM pods, so you will name the Deployment object php. The pods belong to the back-end tier, so you will group the Deployment into this group by using the tier: backend label:

此部署将管理您PHP-FPM吊舱,因此您将命名部署对象php 。 这些Pod属于后端层,因此您将使用tier: backend标签将Deployment分组到该组中:

php_deployment.yaml
php_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: php
  labels:
    tier: backend

For the Deployment spec, you will specify how many copies of this pod to create by using the replicas parameter. The number of replicas will vary depending on your needs and available resources. You will create one replica in this tutorial:

对于Deployment spec ,您将指定要使用replicas参数创建的Pod的replicas数。 replicas数将根据您的需求和可用资源而有所不同。 您将在本教程中创建一个副本:

php_deployment.yaml
php_deployment.yaml
...
spec:
  replicas: 1

This Deployment will manage pods that match the app: php and tier: backend labels. Under selector key add:

此部署将管理与app: phptier: backend标签匹配的Pod。 在selector键下添加:

php_deployment.yaml
php_deployment.yaml
...
  selector:
    matchLabels:
      app: php
      tier: backend

Next, the Deployment spec requires the template for your pod’s object definition. This template will define specifications to create the pod from. First, you will add the labels that were specified for the php service selectors and the Deployment’s matchLabels. Add app: php and tier: backend under template.metadata.labels:

接下来,Deployment spec需要您Pod的对象定义template 。 该模板将定义用于创建广告连播的规范。 首先,您将添加为php服务selectors和Deployment的matchLabels指定的标签。 在template.metadata.labels下添加app: phptier: backend

php_deployment.yaml
php_deployment.yaml
...
  template:
    metadata:
      labels:
        app: php
        tier: backend

A pod can have multiple containers and volumes, but each will need a name. You can selectively mount volumes to a container by specifying a mount path for each volume.

容器可以具有多个容器和卷,但是每个容器和容器都需要一个名称。 通过为每个卷指定安装路径,可以有选择地将卷安装到容器。

First, specify the volumes that your containers will access. You created a PVC named code to hold your application code, so name this volume code as well. Under spec.template.spec.volumes, add the following:

首先,指定您的容器将要访问的卷。 您创建了一个PVC命名code来保存您的应用程序代码,因此也要命名该卷code 。 在spec.template.spec.volumes ,添加以下内容:

php_deployment.yaml
php_deployment.yaml
...
    spec:
      volumes:
      - name: code
        persistentVolumeClaim:
          claimName: code

Next, specify the container you want to run in this pod. You can find various images on the Docker store, but in this tutorial you will use the php:7-fpm image.

接下来,指定要在此容器中运行的容器。 您可以在Docker store上找到各种映像,但是在本教程中,您将使用php:7-fpm映像。

Under spec.template.spec.containers, add the following:

spec.template.spec.containers ,添加以下内容:

php_deployment.yaml
php_deployment.yaml
...
      containers:
      - name: php
        image: php:7-fpm

Next, you will mount the volumes that the container requires access to. This container will run your PHP code, so it will need access to the code volume. You will also use mountPath to specify /code as the mount point.

接下来,将安装容器需要访问的卷。 该容器将运行您PHP代码,因此需要访问code卷。 您还将使用mountPath/code指定为安装点。

Under spec.template.spec.containers.volumeMounts, add:

spec.template.spec.containers.volumeMounts ,添加:

php_deployment.yaml
php_deployment.yaml
...
        volumeMounts:
        - name: code
          mountPath: /code

Now that you have mounted your volume, you need to get your application code on the volume. You may have previously used FTP/SFTP or cloned the code over an SSH connection to accomplish this, but this step will show you how to copy the code using an Init Container.

现在已经安装了卷,您需要在卷上获取应用程序代码。 您可能以前使用过FTP / SFTP或通过SSH连接克隆了代码来完成此操作,但是此步骤将向您展示如何使用Init Container复制代码。

Depending on the complexity of your setup process, you can either use a single initContainer to run a script that builds your application, or you can use one initContainer per command. Make sure that the volumes are mounted to the initContainer.

根据设置过程的复杂性,您可以使用一个initContainer来运行用于构建应用程序的脚本,也可以每个命令使用一个initContainer 。 确保将卷安装到initContainer

In this tutorial, you will use a single Init Container with busybox to download the code. busybox is a small image that contains the wget utility that you will use to accomplish this.

在本教程中,您将使用一个带有busybox Init容器来下载代码。 busybox是一个小图像,其中包含将用于完成此任务的wget实用程序。

Under spec.template.spec, add your initContainer and specify the busybox image:

spec.template.spec ,添加initContainer并指定busybox图像:

php_deployment.yaml
php_deployment.yaml
...
      initContainers:
      - name: install
        image: busybox

Your Init Container will need access to the code volume so that it can download the code in that location. Under spec.template.spec.initContainers, mount the volume code at the /code path:

您的Init容器将需要访问code卷,以便它可以在该位置下载代码。 在spec.template.spec.initContainers ,将卷code挂载到/code路径:

php_deployment.yaml
php_deployment.yaml
...
        volumeMounts:
        - name: code
          mountPath: /code

Each Init Container needs to run a command. Your Init Container will use wget to download the code from Github into the /code working directory. The -O option gives the downloaded file a name, and you will name this file index.php.

每个Init容器都需要运行一个command 。 您的Init容器将使用wget 将代码Github下载到/code工作目录中。 -O选项为下载的文件命名,您将把该文件命名为index.php

Note: Be sure to trust the code you’re pulling. Before pulling it to your server, inspect the source code to ensure you are comfortable with what the code does.

注意:请确保信任要提取的代码。 在将其拉到服务器之前,请检查源代码,以确保您对代码的功能感到满意。

Under the install container in spec.template.spec.initContainers, add these lines:

spec.template.spec.initContainersinstall容器spec.template.spec.initContainers ,添加以下行:

php_deployment.yaml
php_deployment.yaml
...
        command:
        - wget
        - "-O"
        - "/code/index.php"
        - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php

Your completed php_deployment.yaml file will look like this:

您完成的php_deployment.yaml文件将如下所示:

php_deployment.yaml
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
        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/do-community/php-kubernetes/master/index.php

Save the file and exit the editor.

保存文件并退出编辑器。

Create the PHP-FPM Deployment with kubectl:

使用kubectl创建PHP-FPM部署:

  • kubectl apply -f php_deployment.yaml

    kubectl套用-f php_deployment.yaml

You will see the following output upon Deployment creation:

创建部署后,您将看到以下输出:


   
   
Output
deployment.apps/php created

To summarize, this Deployment will start by downloading the specified images. It will then request the PersistentVolume from your PersistentVolumeClaim and serially run your initContainers. Once complete, the containers will run and mount the volumes to the specified mount point. Once all of these steps are complete, your pod will be up and running.

总而言之,此部署将从下载指定的映像开始。 然后,它会要求PersistentVolumePersistentVolumeClaim和连续运行initContainers 。 完成后,容器将运行并将volumes安装到指定的安装点。 完成所有这些步骤后,您的Pod将启动并运行。

You can view your Deployment by running:

您可以通过运行以下命令查看部署:

  • kubectl get deployments

    kubectl进行部署

You will see the output:

您将看到输出:


   
   
Output
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE php 1 1 1 0 19s

This output can help you understand the current state of the Deployment. A Deployment is one of the controllers that maintains a desired state. The template you created specifies that the DESIRED state will have 1 replicas of the pod named php. The CURRENT field indicates how many replicas are running, so this should match the DESIRED state. You can read about the remaining fields in the Kubernetes Deployments documentation.

此输出可以帮助您了解部署的当前状态。 Deployment是保持所需状态的控制器之一 。 您创建的template指定DESIRED状态将具有1个名为php的pod的replicasCURRENT字段指示正在运行多少个副本,因此它应与DESIRED状态匹配。 您可以在Kubernetes部署文档中阅读有关其余字段的信息

You can view the pods that this Deployment started with the following command:

您可以使用以下命令查看此部署开始的容器:

  • kubectl get pods

    kubectl得到豆荚

The output of this command varies depending on how much time has passed since creating the Deployment. If you run it shortly after creation, the output will likely look like this:

此命令的输出取决于自创建展开以来经过了多少时间。 如果在创建后不久运行它,则输出可能如下所示:


   
   
Output
NAME READY STATUS RESTARTS AGE php-86d59fd666-bf8zd 0/1 Init:0/1 0 9s

The columns represent the following information:

这些列代表以下信息:

  • Ready: The number of replicas running this pod.

    Ready :运行此容器的replicas数。

  • Status: The status of the pod. Init indicates that the Init Containers are running. In this output, 0 out of 1 Init Containers have finished running.

    Status :窗格的状态。 Init指示Init容器正在运行。 在此输出中,1个初始化容器中的0个已完成运行。

  • Restarts: How many times this process has restarted to start the pod. This number will increase if any of your Init Containers fail. The Deployment will restart it until it reaches a desired state.

    Restarts :此过程已重新启动以启动Pod的次数。 如果您的任何初始化容器失败,则此数字将增加。 部署将重新启动它,直到达到所需状态为止。

Depending on the complexity of your startup scripts, it can take a couple of minutes for the status to change to podInitializing:

根据启动脚本的复杂性,状态可能需要几分钟才能更改为podInitializing


   
   
Output
NAME READY STATUS RESTARTS AGE php-86d59fd666-lkwgn 0/1 podInitializing 0 39s

This means the Init Containers have finished and the containers are initializing. If you run the command when all of the containers are running, you will see the pod status change to Running.

这意味着初始化容器已完成并且容器正在初始化。 如果在所有容器都运行时运行命令,则将看到容器状态更改为正在Running


   
   
Output
NAME READY STATUS RESTARTS AGE php-86d59fd666-lkwgn 1/1 Running 0 1m

You now see that your pod is running successfully. If your pod doesn’t start, you can debug with the following commands:

现在,您可以看到您的pod运行成功。 如果您的Pod无法启动,则可以使用以下命令进行调试:

  • View detailed information of a pod:

    查看窗格的详细信息:
  • kubectl describe pods pod-name

    kubectl描述pods pod名称

  • View logs generated by a pod:

    查看Pod生成的日志:
  • kubectl logs pod-name

    kubectl日志pod-name

  • View logs for a specific container in a pod:

    查看容器中特定容器的日志:
  • kubectl logs pod-name container-name

    kubectl日志pod-name 容器名

Your application code is mounted and the PHP-FPM service is now ready to handle connections. You can now create your Nginx Deployment.

您的应用程序代码已挂载,并且PHP-FPM服务现在可以处理连接了。 现在,您可以创建Nginx部署。

第5步—创建Nginx部署 (Step 5 — Creating the Nginx Deployment)

In this step, you will use a ConfigMap to configure Nginx. A ConfigMap holds your configuration in a key-value format that you can reference in other Kubernetes object definitions. This approach will grant you the flexibility to reuse or swap the image with a different Nginx version if needed. Updating the ConfigMap will automatically replicate the changes to any pod mounting it.

在此步骤中,您将使用ConfigMap配置Nginx。 ConfigMap以键值格式保存您的配置,您可以在其他Kubernetes对象定义中引用它。 如果需要,这种方法将使您能够灵活地重用映像或将其替换为其他Nginx版本。 更新ConfigMap将自动将更改复制到安装它的任何Pod。

Create a nginx_configMap.yaml file for your ConfigMap with your editor:

使用编辑器为ConfigMap创建一个nginx_configMap.yaml文件:

  • nano nginx_configMap.yaml

    纳米nginx_configMap.yaml

Name the ConfigMap nginx-config and group it into the tier: backend micro-service:

将ConfigMap命名为nginx-config并将其分组为以下tier: backend微服务:

nginx_configMap.yaml
nginx_configMap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  labels:
    tier: backend

Next, you will add the data for the ConfigMap. Name the key config and add the contents of your Nginx configuration file as the value. You can use the example Nginx configuration from this tutorial.

接下来,您将添加ConfigMap的data 。 将密钥命名为config ,并将Nginx配置文件的内容添加为值。 您可以使用本教程中的示例Nginx配置。

Because Kubernetes can route requests to the appropriate host for a service, you can enter the name of your PHP-FPM service in the fastcgi_pass parameter instead of its IP address. Add the following to your nginx_configMap.yaml file:

因为Kubernetes可以将请求路由到服务的适当主机,所以您可以在fastcgi_pass参数中输入PHP-FPM服务的名称,而不是其IP地址。 将以下内容添加到您的nginx_configMap.yaml文件中:

nginx_configMap.yaml
nginx_configMap.yaml
...
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;
        }
    }

Your nginx_configMap.yaml file will look like this:

您的nginx_configMap.yaml文件将如下所示:

nginx_configMap.yaml
nginx_configMap.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;
        }
    }

Save the file and exit the editor.

保存文件并退出编辑器。

Create the ConfigMap:

创建ConfigMap:

  • kubectl apply -f nginx_configMap.yaml

    kubectl应用-f nginx_configMap.yaml

You will see the following output:

您将看到以下输出:


   
   
Output
configmap/nginx-config created

You’ve finished creating your ConfigMap and can now build your Nginx Deployment.

您已经完成了ConfigMap的创建,现在可以构建Nginx部署了。

Start by opening a new nginx_deployment.yaml file in the editor:

首先在编辑器中打开一个新的nginx_deployment.yaml文件:

  • nano nginx_deployment.yaml

    纳米nginx_deployment.yaml

Name the Deployment nginx and add the label tier: backend:

命名Deployment nginx并添加标签tier: backend

nginx_deployment.yaml
nginx_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    tier: backend

Specify that you want one replicas in the Deployment spec. This Deployment will manage pods with labels app: nginx and tier: backend. Add the following parameters and values:

在“部署” spec指定要一个replicas 。 此部署将使用标签app: nginxtier: backend管理pod。 添加以下参数和值:

nginx_deployment.yaml
nginx_deployment.yaml
...
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      tier: backend

Next, add the pod template. You need to use the same labels that you added for the Deployment selector.matchLabels. Add the following:

接下来,添加pod template 。 您需要使用为Deployment selector.matchLabels添加的相同标签。 添加以下内容:

nginx_deployment.yaml
nginx_deployment.yaml
...
  template:
    metadata:
      labels:
        app: nginx
        tier: backend

Give Nginx access to the code PVC that you created earlier. Under spec.template.spec.volumes, add:

授予Nginx访问您先前创建的code PVC的权限。 在spec.template.spec.volumes ,添加:

nginx_deployment.yaml
nginx_deployment.yaml
...
    spec:
      volumes:
      - name: code
        persistentVolumeClaim:
          claimName: code

Pods can mount a ConfigMap as a volume. Specifying a file name and key will create a file with its value as the content. To use the ConfigMap, set path to name of the file that will hold the contents of the key. You want to create a file site.conf from the key config. Under spec.template.spec.volumes, add the following:

Pod可以将ConfigMap挂载为卷。 指定文件名和密钥将创建一个以其值为内容的文件。 要使用ConfigMap,请将path设置为将保存key内容的文件的名称。 您想通过键config创建文件site.conf 。 在spec.template.spec.volumes ,添加以下内容:

nginx_deployment.yaml
nginx_deployment.yaml
...
      - name: config
        configMap:
          name: nginx-config
          items:
          - key: config
            path: site.conf

Warning: If a file is not specified, the contents of the key will replace the mountPath of the volume. This means that if a path is not explicitly specified, you will lose all content in the destination folder.

警告 :如果未指定文件,则key的内容将替换卷的mountPath 。 这意味着,如果未明确指定路径,则将丢失目标文件夹中的所有内容。

Next, you will specify the image to create your pod from. This tutorial will use the nginx:1.7.9 image for stability, but you can find other Nginx images on the Docker store. Also, make Nginx available on the port 80. Under spec.template.spec add:

接下来,您将指定要用来创建广告连播的图片。 本教程将使用nginx:1.7.9图像来提高稳定性,但是您可以在Docker商店中找到其他Nginx图像。 另外,使Nginx在端口80上可用。 在spec.template.spec添加:

nginx_deployment.yaml
nginx_deployment.yaml
...
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

Nginx and PHP-FPM need to access the file at the same path, so mount the code volume at /code:

Nginx和PHP-FPM需要在同一路径下访问文件,因此将code卷挂载到/code

nginx_deployment.yaml
nginx_deployment.yaml
...
        volumeMounts:
        - name: code
          mountPath: /code

The nginx:1.7.9 image will automatically load any configuration files under the /etc/nginx/conf.d directory. Mounting the config volume in this directory will create the file /etc/nginx/conf.d/site.conf. Under volumeMounts add the following:

nginx:1.7.9映像将自动加载/etc/nginx/conf.d目录下的所有配置文件。 在此目录中挂载config卷将创建文件/etc/nginx/conf.d/site.conf 。 在volumeMounts添加以下内容:

nginx_deployment.yaml
nginx_deployment.yaml
...
        - name: config
          mountPath: /etc/nginx/conf.d

Your nginx_deployment.yaml file will look like this:

您的nginx_deployment.yaml文件将如下所示:

nginx_deployment.yaml
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
        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

Save the file and exit the editor.

保存文件并退出编辑器。

Create the Nginx Deployment:

创建Nginx部署:

  • kubectl apply -f nginx_deployment.yaml

    kubectl套用-f nginx_deployment.yaml

The following output indicates that your Deployment is now created:

以下输出表明您的部署现已创建:


   
   
Output
deployment.apps/nginx created

List your Deployments with this command:

使用以下命令列出您的部署:

  • kubectl get deployments

    kubectl进行部署

You will see the Nginx and PHP-FPM Deployments:

您将看到Nginx和PHP-FPM部署:


   
   
Output
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx 1 1 1 0 16s php 1 1 1 1 7m

List the pods managed by both of the Deployments:

列出由两个部署管理的窗格:

  • kubectl get pods

    kubectl得到豆荚

You will see the pods that are running:

您将看到正在运行的Pod:


   
   
Output
NAME READY STATUS RESTARTS AGE nginx-7bf5476b6f-zppml 1/1 Running 0 32s php-86d59fd666-lkwgn 1/1 Running 0 7m

Now that all of the Kubernetes objects are active, you can visit the Nginx service on your browser.

现在所有Kubernetes对象都处于活动状态,您可以在浏览器上访问Nginx服务。

List the running services:

列出正在运行的服务:

  • kubectl get services -o wide

    kubectl获得服务-o宽

Get the External IP for your Nginx service:

获取您的Nginx服务的外部IP:


   
   
Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 39m <none> nginx ClusterIP 10.102.160.47 your_public_ip 80/TCP 27m app=nginx,tier=backend php ClusterIP 10.100.59.238 <none> 9000/TCP 34m app=php,tier=backend

On your browser, visit your server by typing in http://your_public_ip. You will see the output of php_info() and have confirmed that your Kubernetes services are up and running.

在浏览器上,输入http:// your_public_ip来访问服务器。 您将看到php_info()的输出,并确认您的Kubernetes服务已启动并正在运行。

结论 (Conclusion)

In this guide, you containerized the PHP-FPM and Nginx services so that you can manage them independently. This approach will not only improve the scalability of your project as you grow, but will also allow you to efficiently use resources as well. You also stored your application code on a volume so that you can easily update your services in the future.

在本指南中,您对PHP-FPM和Nginx服务进行了容器化,以便您可以独立管理它们。 这种方法不仅可以随着项目的增长提高项目的可伸缩性,而且还可以使您有效地使用资源。 您还将应用程序代码存储在一个卷上,以便将来可以轻松更新服务。

翻译自: https://www.digitalocean.com/community/tutorials/how-to-deploy-a-php-application-with-kubernetes-on-ubuntu-18-04

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值