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)
A basic understanding of Kubernetes objects. Check out our Introduction to Kubernetes article for more information.
对Kubernetes对象的基本了解。 查阅我们的Kubernetes简介文章以获取更多信息。
A Kubernetes cluster running on Ubuntu 18.04. You can set this up by following the How To Create a Kubernetes 1.14 Cluster Using Kubeadm on Ubuntu 18.04 tutorial.
在Ubuntu 18.04上运行的Kubernetes集群。 您可以按照在Ubuntu 18.04上如何使用Kubeadm创建Kubernetes 1.14群集的教程进行设置。
A DigitalOcean account and an API access token with read and write permissions to create our storage volume. If you don’t have your API access token, you can create it from here.
具有读写权限的DigitalOcean帐户和API访问令牌可创建我们的存储卷。 如果您没有API访问令牌,则可以从此处创建它 。
Your application code hosted on a publicly accessible URL, such as Github.
您的应用程序代码托管在可公开访问的URL(例如Github)上 。
第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, apod
orservice
.kind
:此文件表示的Kubernetes对象。 例如,pod
或service
。metadata
: This contains thename
of the object along with anylabels
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
以指定该对象是服务:
apiVersion: v1
kind: Service
Name the service php
since it will provide access to PHP-FPM:
将服务命名为php
因为它将提供对PHP-FPM的访问:
...
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
。
...
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
部分之后添加这两个标签。
...
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
文件中:
...
ports:
- protocol: TCP
port: 9000
Your completed php_service.yaml
file will look like this:
您完成的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
标签,因为它属于后端层:
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: nginx
和tier: backend
。 使此服务可通过端口80
(默认的HTTP端口)访问。
...
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
,添加:
...
spec:
externalIPs:
- your_public_ip
Your nginx_service.yaml
file will look like this:
您的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存储插件还使用它来启动各种组件。
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.
机密使用data
或stringData
密钥而不是spec
密钥来保存所需的信息。 data
参数包含base64编码的数据,该data
在检索时会自动解码。 stringData
参数保存在创建或更新期间自动编码的未编码数据,并且在检索Secrets时不输出数据。 为了方便起见,在本教程中将使用stringData
。
Add the access-token
as stringData
:
将access-token
添加为stringData
:
...
stringData:
access-token: your-api-token
Save and exit the file.
保存并退出文件。
Your secret.yaml
file will look like this:
您的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
:
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 nodeReadWriteOnce
–将卷安装为单个节点可读写ReadOnlyMany
– mounts the volume as read-only by many nodesReadOnlyMany
–将卷装入许多节点为只读ReadWriteMany
– mounts the volume as read-write by many nodesReadWriteMany
–将卷安装为可被许多节点读写
accessModes
which vary by the use case. These are:accessModes
因使用案例而异。 这些是: resources
– the storage space that you requireresources
–您需要的存储空间
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
参数以适合您的要求。 您可以在创建卷后增加存储量,但不支持缩小磁盘。
...
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
类。
...
storageClassName: do-block-storage
Your code_volume.yaml
file will look like this:
您的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 Policy
和Status
除外。 Reclaim Policy
定义了删除PVC访问PVC后对PV的处理方式。 Delete
会从Kubernetes和DigitalOcean基础架构中删除PV。 您可以从Kubernetes PV文档中了解有关Reclaim Policy
和Status
的更多信息 。
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容器将使用wget
从GitHub Gist获取示例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分组到该组中:
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
数将根据您的需求和可用资源而有所不同。 您将在本教程中创建一个副本:
...
spec:
replicas: 1
This Deployment will manage pods that match the app: php
and tier: backend
labels. Under selector
key add:
此部署将管理与app: php
和tier: backend
标签匹配的Pod。 在selector
键下添加:
...
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: php
和tier: backend
:
...
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
,添加以下内容:
...
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
,添加以下内容:
...
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
,添加:
...
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
图像:
...
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
路径:
...
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.initContainers
的install
容器spec.template.spec.initContainers
,添加以下行:
...
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
文件将如下所示:
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.
总而言之,此部署将从下载指定的映像开始。 然后,它会要求PersistentVolume
从PersistentVolumeClaim
和连续运行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的replicas
。 CURRENT
字段指示正在运行多少个副本,因此它应与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 ofreplicas
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
微服务:
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
文件中:
...
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
文件将如下所示:
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
:
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: nginx
和tier: backend
管理pod。 添加以下参数和值:
...
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
添加的相同标签。 添加以下内容:
...
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
,添加:
...
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
,添加以下内容:
...
- 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
添加:
...
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
:
...
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
添加以下内容:
...
- name: config
mountPath: /etc/nginx/conf.d
Your nginx_deployment.yaml
file will look like this:
您的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服务进行了容器化,以便您可以独立管理它们。 这种方法不仅可以随着项目的增长提高项目的可伸缩性,而且还可以使您有效地使用资源。 您还将应用程序代码存储在一个卷上,以便将来可以轻松更新服务。