如何在Ubuntu16.04上使用Kubernetes部署PHP应用程序
作为 Write for DOnations 计划的一部分,作者选择了 Open Internet/Free Speech 来接收捐赠。
介绍
Kubernetes 是一个开源的容器编排系统。 它允许您创建、更新和扩展容器,而无需担心停机时间。
为了运行 PHP 应用程序,Nginx 充当 PHP-FPM 的代理。 将此设置容器化在单个容器中可能是一个繁琐的过程,但 Kubernetes 将帮助在单独的容器中管理这两个服务。 使用 Kubernetes 将使您的容器保持可重用和可交换,并且每次有新版本的 Nginx 或 PHP 时您都不必重新构建容器映像。
在本教程中,您将在 Kubernetes 集群上部署 PHP 7 应用程序,其中 Nginx 和 PHP-FPM 在单独的容器中运行。 您还将学习如何使用 DigitalOcean 的块存储 系统将配置文件和应用程序代码保存在容器映像之外。 这种方法将允许您通过传递配置卷而不是重建映像来为任何需要 Web/代理服务器的应用程序重用 Nginx 映像。
注意: 本教程已经在使用 Kubeadm 制作的 Kubernetes 集群上进行了测试,与 DigitalOcean Managed Kubernetes (DOKS) 产品有很大不同。 如果您使用 DOKS,请查看我们的官方 DigitalOcean Kubernetes 产品文档 以获取最新信息和教程。
先决条件
- 对 Kubernetes 对象的基本了解。 查看我们的 Kubernetes 简介 文章了解更多信息。
- 在 Ubuntu 16.04 上运行的 Kubernetes 集群。 您可以按照 How To Create a Kubernetes 1.10 Cluster Using Kubeadm on Ubuntu 16.04 教程进行设置。
- 一个 DigitalOcean 帐户和一个具有读写权限的 API 访问令牌来创建我们的存储卷。 如果您没有 API 访问令牌,您可以 从此处 创建它。
- 您的应用程序代码托管在可公开访问的 URL 上,例如 Github。
第 1 步 — 创建 PHP-FPM 和 Nginx 服务
在这一步中,您将创建 PHP-FPM 和 Nginx 服务。 服务允许从集群内访问一组 pod。 集群中的服务可以直接通过它们的名称进行通信,而不需要 IP 地址。 PHP-FPM 服务将允许访问 PHP-FPM pod,而 Nginx 服务将允许访问 Nginx pod。
由于 Nginx pod 将代理 PHP-FPM pod,因此您需要告诉服务如何找到它们。 您将利用 Kubernetes 的自动服务发现来使用人类可读的名称将请求路由到适当的服务,而不是使用 IP 地址。
要创建服务,您将创建一个对象定义文件。 每个 Kubernetes 对象定义都是一个 YAML 文件,其中至少包含以下各项:
apiVersion
:定义所属的Kubernetes API版本。kind
:这个文件代表的 Kubernetes 对象。 例如,pod
或service
。metadata
:这包含对象的name
以及您可能希望应用于它的任何labels
。spec
:这包含一个特定的配置,具体取决于您正在创建的对象的类型,例如容器映像或可访问容器的端口。
首先,您将创建一个目录来保存您的 Kubernetes 对象定义。
SSH 到您的 主节点 并创建 definitions
目录来保存您的 Kubernetes 对象定义。
mkdir definitions
导航到新创建的 definitions
目录:
cd definitions
通过创建 php_service.yaml
文件来创建您的 PHP-FPM 服务:
nano php_service.yaml
将 kind
设置为 Service
以指定此对象是服务:
php_service.yaml
... apiVersion: v1 kind: Service
将服务命名为 php
,因为它将提供对 PHP-FPM 的访问:
php_service.yaml
... metadata: name: php
您将使用标签对不同的对象进行逻辑分组。 在本教程中,您将使用标签将对象分组为“层”,例如前端或后端。 PHP pod 将在此服务之后运行,因此您将其标记为 tier: backend
。
php_service.yaml
... labels: tier: backend
服务通过使用 selector
标签来确定要访问的 pod。 匹配这些标签的 pod 将被服务,与该 pod 是在服务之前还是之后创建的无关。 您将在本教程的后面部分为您的 pod 添加标签。
使用 tier: backend
标签将 pod 分配到后端层。 您还将添加 app: php
标签以指定此 pod 运行 PHP。 在 metadata
部分之后添加这两个标签。
php_service.yaml
... spec: selector: app: php tier: backend
接下来,指定用于访问此服务的端口。 您将在本教程中使用端口 9000
。 将其添加到 spec
下的 php_service.yaml
文件中:
php_service.yaml
... ports: - protocol: TCP port: 9000
您完成的 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
点击 CTRL + o
保存文件,然后点击 CTRL + x
退出 nano
。
现在您已经为您的服务创建了对象定义,要运行该服务,您将使用 kubectl apply
命令和 -f
参数并指定您的 php_service.yaml
文件。
创建您的服务:
kubectl apply -f php_service.yaml
此输出确认服务创建:
Outputservice/php created
验证您的服务是否正在运行:
kubectl get svc
您将看到您的 PHP-FPM 服务正在运行:
OutputNAME 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
Kubernetes 支持多种 服务类型。 您的 php
服务使用默认服务类型 ClusterIP
。 此服务类型分配一个内部 IP,并使该服务只能从集群内访问。
现在 PHP-FPM 服务已准备就绪,您将创建 Nginx 服务。 使用编辑器创建并打开一个名为 nginx_service.yaml
的新文件:
nano nginx_service.yaml
此服务将针对 Nginx pod,因此您将其命名为 nginx
。 您还将添加一个 tier: backend
标签,因为它属于后端层:
nginx_service.yaml
apiVersion: v1 kind: Service metadata: name: nginx labels: tier: backend
与 php
服务类似,使用选择器标签 app: nginx
和 tier: backend
定位 pod。 使该服务可在端口 80(默认 HTTP 端口)上访问。
nginx_service.yaml
... spec: selector: app: nginx tier: backend ports: - protocol: TCP port: 80
Nginx 服务将从您的 Droplet 的公共 IP 地址公开访问互联网。 your_public_ip
可以在您的 DigitalOcean Cloud Panel 中找到。 在 spec.externalIPs
下,添加:
nginx_service.yaml
... spec: externalIPs: - your_public_ip
您的 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
保存并关闭文件。 创建 Nginx 服务:
kubectl apply -f nginx_service.yaml
服务运行时,您将看到以下输出:
Outputservice/nginx created
您可以通过执行以下命令查看所有正在运行的服务:
kubectl get svc
您将看到输出中列出的 PHP-FPM 和 Nginx 服务:
OutputNAME 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
请注意,如果要删除服务,可以运行:
kubectl delete svc/service_name
现在您已经创建了 PHP-FPM 和 Nginx 服务,您需要指定存储应用程序代码和配置文件的位置。
第 2 步 — 安装 DigitalOcean 存储插件
Kubernetes 提供了不同的存储插件,可以为您的环境创建存储空间。 在此步骤中,您将安装 DigitalOcean 存储插件 以在 DigitalOcean 上创建 块存储。 安装完成后,它将添加一个名为 do-block-storage
的存储类,您将使用它来创建块存储。
您将首先配置一个 Kubernetes Secret 对象来存储您的 DigitalOcean API 令牌。 Secret 对象用于与同一命名空间中的其他 Kubernetes 对象共享敏感信息,例如 SSH 密钥和密码。 命名空间提供了一种在逻辑上分离 Kubernetes 对象的方法。
使用编辑器打开一个名为 secret.yaml
的文件:
nano secret.yaml
您将命名您的秘密对象 digitalocean
并将其添加到 kube-system
namespace
。 kube-system
命名空间是 Kubernetes 内部服务的默认命名空间,也被 DigitalOcean 存储插件用来启动各种组件。
秘密.yaml
apiVersion: v1 kind: Secret metadata: name: digitalocean namespace: kube-system
Secret 使用 data
或 stringData
密钥来保存所需信息,而不是 spec
密钥。 data
参数保存在检索时自动解码的 base64 编码数据。 stringData
参数保存非编码数据,在创建或更新时自动编码,检索 Secret 时不输出数据。 为方便起见,您将在本教程中使用 stringData
。
将 access-token
添加为 stringData
:
秘密.yaml
... stringData: access-token: your-api-token
保存并退出文件。
您的 secret.yaml
文件将如下所示:
秘密.yaml
apiVersion: v1 kind: Secret metadata: name: digitalocean namespace: kube-system stringData: access-token: your-api-token
创建秘密:
kubectl apply -f secret.yaml
创建 Secret 后,您将看到以下输出:
Outputsecret/digitalocean created
您可以使用以下命令查看密钥:
kubectl -n kube-system get secret digitalocean
输出将类似于以下内容:
OutputNAME TYPE DATA AGE digitalocean Opaque 1 41s
Opaque
类型表示这个 Secret 是只读的,这是 stringData
Secrets 的标准。 您可以在 秘密设计规范 上阅读更多相关信息。 DATA
字段显示存储在此 Secret 中的项目数。 在这种情况下,它显示 1
因为您存储了一个密钥。
现在你的 Secret 已经就位,安装 DigitalOcean 块存储插件:
kubectl apply -f https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v0.3.0.yaml
您将看到类似于以下内容的输出:
Outputstorageclass.storage.k8s.io/do-block-storage created serviceaccount/csi-attacher created clusterrole.rbac.authorization.k8s.io/external-attacher-runner created clusterrolebinding.rbac.authorization.k8s.io/csi-attacher-role created service/csi-attacher-doplug-in created statefulset.apps/csi-attacher-doplug-in created serviceaccount/csi-provisioner created clusterrole.rbac.authorization.k8s.io/external-provisioner-runner created clusterrolebinding.rbac.authorization.k8s.io/csi-provisioner-role created service/csi-provisioner-doplug-in created statefulset.apps/csi-provisioner-doplug-in created serviceaccount/csi-doplug-in created clusterrole.rbac.authorization.k8s.io/csi-doplug-in created clusterrolebinding.rbac.authorization.k8s.io/csi-doplug-in created daemonset.apps/csi-doplug-in created
现在您已经安装了 DigitalOcean 存储插件,您可以创建块存储来保存您的应用程序代码和配置文件。
第 3 步 — 创建持久卷
准备好 Secret 并安装块存储插件后,您现在可以创建 Persistent Volume。 持久卷或 PV 是指定大小的块存储,独立于 pod 的生命周期而存在。 使用持久卷将允许您管理或更新您的 pod,而不必担心丢失您的应用程序代码。 通过使用 PersistentVolumeClaim
或 PVC 访问持久卷,它将 PV 安装在所需的路径上。
使用编辑器打开一个名为 code_volume.yaml
的文件:
nano code_volume.yaml
通过将以下参数和值添加到文件中来命名 PVC code
:
code_volume.yaml
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: code
PVC 的 spec
包含以下项目:
accessModes
因用例而异。 它们是:
resources
– 您需要的存储空间
DigitalOcean 块存储仅挂载到单个节点,因此您将 accessModes
设置为 ReadWriteOnce
。 本教程将指导您添加少量应用程序代码,因此在此用例中 1GB 就足够了。 如果您计划在卷上存储大量代码或数据,您可以修改 storage
参数以满足您的要求。 您可以在创建卷后增加存储量,但不支持收缩磁盘。
code_volume.yaml
... spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi
接下来,指定 Kubernetes 将用于配置卷的存储类。 您将使用由 DigitalOcean 块存储插件创建的 do-block-storage
类。
code_volume.yaml
... storageClassName: do-block-storage
您的 code_volume.yaml
文件将如下所示:
code_volume.yaml
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: code spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: do-block-storage
保存并退出文件。
使用 kubectl
创建 code
PersistentVolumeClaim:
kubectl apply -f code_volume.yaml
以下输出告诉您对象已成功创建,您已准备好将 1GB PVC 挂载为卷。
Outputpersistentvolumeclaim/code created
要查看可用的持久卷 (PV):
kubectl get pv
您将看到列出的 PV:
OutputNAME 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
上面的字段是您的配置文件的概述,除了 Reclaim Policy
和 Status
。 Reclaim Policy
定义了在访问它的 PVC 被删除后对 PV 所做的事情。 Delete
从 Kubernetes 以及 DigitalOcean 基础设施中删除 PV。 您可以从 Kubernetes PV 文档 中了解有关 Reclaim Policy
和 Status
的更多信息。
您已使用 DigitalOcean 块存储插件成功创建了持久卷。 现在您的 Persistent Volume 已准备就绪,您将使用 Deployment 创建您的 pod。
第 4 步 — 创建 PHP-FPM 部署
在此步骤中,您将学习如何使用 Deployment 创建 PHP-FPM pod。 部署提供了一种使用 ReplicaSets 创建、更新和管理 pod 的统一方法。 如果更新没有按预期工作,部署将自动将其 pod 回滚到以前的映像。
Deployment spec.selector
键将列出它将管理的 Pod 的标签。 它还将使用 template
键来创建所需的 pod。
这一步还将介绍Init Containers的使用。 Init Containers 在 pod 的 template
键下指定的常规容器之前运行一个或多个命令。 在本教程中,您的 Init 容器将使用 wget
从 GitHub Gist 获取示例 index.php
文件。 这些是示例文件的内容:
索引.php
<?php echo phpinfo();
要创建部署,请使用编辑器打开一个名为 php_deployment.yaml
的新文件:
nano php_deployment.yaml
此部署将管理您的 PHP-FPM pod,因此您将部署对象命名为 php
。 Pod 属于后端层,因此您将使用 tier: backend
标签将 Deployment 分组到该组中:
php_deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: php labels: tier: backend
对于 Deployment spec
,您将使用 replicas
参数指定要创建多少个此 Pod 的副本。 replicas
的数量将根据您的需求和可用资源而有所不同。 您将在本教程中创建一个副本:
php_deployment.yaml
... spec: replicas: 1
此 Deployment 将管理与 app: php
和 tier: backend
标签匹配的 pod。 在 selector
键下添加:
php_deployment.yaml
... selector: matchLabels: app: php tier: backend
接下来,部署 spec
需要 template
用于您的 pod 对象定义。 该模板将定义创建 pod 的规范。 首先,您将添加为 php
服务 selectors
和部署的 matchLabels
指定的标签。 在template.metadata.labels
下添加app: php
和tier: backend
:
php_deployment.yaml
... template: metadata: labels: app: php tier: backend
一个 pod 可以有多个容器和卷,但每个都需要一个名称。 您可以通过为每个卷指定挂载路径来选择性地将卷挂载到容器。
首先,指定容器将访问的卷。 您创建了一个名为 code
的 PVC 来保存您的应用程序代码,因此也将此卷命名为 code
。 在 spec.template.spec.volumes
下,添加以下内容:
php_deployment.yaml
... spec: volumes: - name: code persistentVolumeClaim: claimName: code
接下来,指定要在此 pod 中运行的容器。 您可以在 Docker 商店 上找到各种镜像,但在本教程中,您将使用 php:7-fpm
镜像。
在 spec.template.spec.containers
下,添加以下内容:
php_deployment.yaml
... containers: - name: php image: php:7-fpm
接下来,您将挂载容器需要访问的卷。 此容器将运行您的 PHP 代码,因此它需要访问 code
卷。 您还将使用 mountPath
指定 /code
作为安装点。
在 spec.template.spec.containers.volumeMounts
下,添加:
php_deployment.yaml
... volumeMounts: - name: code mountPath: /code
现在您已经挂载了您的卷,您需要在该卷上获取您的应用程序代码。 您之前可能使用过 FTP/SFTP 或通过 SSH 连接克隆代码来完成此操作,但此步骤将向您展示如何使用 Init Container 复制代码。
根据设置过程的复杂程度,您可以使用单个 initContainer
来运行构建应用程序的脚本,也可以为每个命令使用一个 initContainer
。 确保卷已安装到 initContainer
。
在本教程中,您将使用带有 busybox
的单个 Init Container 来下载代码。 busybox
是一个包含 wget
实用程序的小图像,您将使用它来完成此操作。
在 spec.template.spec
下,添加您的 initContainer
并指定 busybox
图像:
php_deployment.yaml
... initContainers: - name: install image: busybox
您的 Init Container 需要访问 code
卷,以便它可以下载该位置的代码。 在 spec.template.spec.initContainers
下,将卷 code
挂载到 /code
路径:
php_deployment.yaml
... volumeMounts: - name: code mountPath: /code
每个 Init Container 都需要运行一个 command
。 您的 Init Container 将使用 wget
从 Github 下载 代码 到 /code
工作目录。 -O
选项为下载的文件命名,您将把这个文件命名为 index.php
。
注意: 一定要相信你提取的代码。 在将其拉到您的服务器之前,请检查源代码以确保您对代码的作用感到满意。
在 spec.template.spec.initContainers
中的 install
容器下,添加以下行:
php_deployment.yaml
... command: - wget - "-O" - "/code/index.php" - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php
您完成的 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
保存文件并退出编辑器。
使用 kubectl
创建 PHP-FPM 部署:
kubectl apply -f php_deployment.yaml
创建部署后,您将看到以下输出:
Outputdeployment.apps/php created
总而言之,这个部署将从下载指定的镜像开始。 然后它将从您的 PersistentVolumeClaim
请求 PersistentVolume
并串行运行您的 initContainers
。 完成后,容器将运行并将 volumes
挂载到指定的挂载点。 完成所有这些步骤后,您的 pod 将启动并运行。
您可以通过运行以下命令查看您的部署:
kubectl get deployments
您将看到输出:
OutputNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE php 1 1 1 0 19s
此输出可以帮助您了解部署的当前状态。 Deployment
是 控制器 中的一个,它保持所需状态。 您创建的 template
指定 DESIRED
状态将有名为 php
的 pod 的 1 个 replicas
。 CURRENT
字段表示有多少副本正在运行,因此这应该与 DESIRED
状态相匹配。 您可以在 Kubernetes 部署文档 中阅读有关其余字段的信息。
您可以使用以下命令查看此 Deployment 启动的 pod:
kubectl get pods
此命令的输出取决于自创建部署以来经过的时间。 如果您在创建后不久运行它,输出可能如下所示:
OutputNAME READY STATUS RESTARTS AGE php-86d59fd666-bf8zd 0/1 Init:0/1 0 9s
这些列代表以下信息:
Ready
:运行此 pod 的replicas
的数量。Status
:pod 的状态。Init
表示 Init Containers 正在运行。 在此输出中,1 个 Init 容器中有 0 个已完成运行。Restarts
:这个进程重启了多少次来启动 pod。 如果您的任何 Init 容器发生故障,此数字将增加。 部署将重新启动它,直到它达到所需的状态。
根据启动脚本的复杂程度,状态可能需要几分钟才能更改为 podInitializing
:
OutputNAME READY STATUS RESTARTS AGE php-86d59fd666-lkwgn 0/1 podInitializing 0 39s
这意味着 Init Containers 已经完成并且容器正在初始化。 如果在所有容器都在运行时运行该命令,您将看到 pod 状态更改为 Running
。
OutputNAME READY STATUS RESTARTS AGE php-86d59fd666-lkwgn 1/1 Running 0 1m
您现在看到您的 pod 正在成功运行。 如果您的 pod 没有启动,您可以使用以下命令进行调试:
- 查看一个pod的详细信息:
kubectl describe pods pod-name
- 查看 pod 生成的日志:
kubectl logs pod-name
- 查看 pod 中特定容器的日志:
kubectl logs pod-name container-name
您的应用程序代码已挂载,PHP-FPM 服务现在已准备好处理连接。 您现在可以创建 Nginx 部署。
第 5 步 — 创建 Nginx 部署
在这一步中,您将使用 ConfigMap 来配置 Nginx。 ConfigMap 以键值格式保存您的配置,您可以在其他 Kubernetes 对象定义中引用该格式。 如果需要,这种方法将使您能够灵活地重用图像或使用不同的 Nginx 版本交换图像。 更新 ConfigMap 会自动将更改复制到任何挂载它的 pod。
使用编辑器为您的 ConfigMap 创建一个 nginx_configMap.yaml
文件:
nano nginx_configMap.yaml
将 ConfigMap 命名为 nginx-config
并将其分组到 tier: backend
微服务中:
nginx_configMap.yaml
apiVersion: v1 kind: ConfigMap metadata: name: nginx-config labels: tier: backend
接下来,您将为 ConfigMap 添加 data
。 将键命名为 config
并将 Nginx 配置文件的内容添加为值。 您可以使用 本教程 中的示例 Nginx 配置。
因为 Kubernetes 可以将请求路由到服务的适当主机,所以您可以在 fastcgi_pass
参数中输入 PHP-FPM 服务的名称,而不是其 IP 地址。 将以下内容添加到您的 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; } }
您的 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; } }
保存文件并退出编辑器。
创建 ConfigMap:
kubectl apply -f nginx_configMap.yaml
您将看到以下输出:
Outputconfigmap/nginx-config created
您已经完成了 ConfigMap 的创建,现在可以构建您的 Nginx 部署。
首先在编辑器中打开一个新的 nginx_deployment.yaml
文件:
nano nginx_deployment.yaml
将部署命名为 nginx
并添加标签 tier: backend
:
nginx_deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: tier: backend
在部署 spec
中指定您想要一个 replicas
。 此 Deployment 将管理标签为 app: nginx
和 tier: backend
的 Pod。 添加以下参数和值:
nginx_deployment.yaml
... spec: replicas: 1 selector: matchLabels: app: nginx tier: backend
接下来,添加吊舱 template
。 您需要使用为部署 selector.matchLabels
添加的相同标签。 添加以下内容:
nginx_deployment.yaml
... template: metadata: labels: app: nginx tier: backend
让 Nginx 访问您之前创建的 code
PVC。 在 spec.template.spec.volumes
下,添加:
nginx_deployment.yaml
... spec: volumes: - name: code persistentVolumeClaim: claimName: code
Pod 可以将 ConfigMap 挂载为卷。 指定文件名和键将创建一个文件,其值作为内容。 要使用 ConfigMap,请将 path
设置为将保存 key
内容的文件的名称。 您想从键 config
创建一个文件 site.conf
。 在 spec.template.spec.volumes
下,添加以下内容:
nginx_deployment.yaml
... - name: config configMap: name: nginx-config items: - key: config path: site.conf
Warning:如果没有指定文件,key
的内容将替换卷的mountPath
。 这意味着如果没有明确指定路径,您将丢失目标文件夹中的所有内容。
接下来,您将指定要从中创建 pod 的映像。 本教程将使用 nginx:1.7.9
镜像来保证稳定性,但您可以在 Docker 商店 上找到其他 Nginx 镜像。 另外,使 Nginx 在端口 80 上可用。 在 spec.template.spec
下添加:
nginx_deployment.yaml
... containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80
Nginx 和 PHP-FPM 需要访问同一路径下的文件,因此将 code
卷挂载到 /code
:
nginx_deployment.yaml
... volumeMounts: - name: code mountPath: /code
nginx:1.7.9
镜像会自动加载/etc/nginx/conf.d
目录下的所有配置文件。 在此目录中挂载 config
卷将创建文件 /etc/nginx/conf.d/site.conf
。 在 volumeMounts
下添加以下内容:
nginx_deployment.yaml
... - name: config mountPath: /etc/nginx/conf.d
您的 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
保存文件并退出编辑器。
创建 Nginx 部署:
kubectl apply -f nginx_deployment.yaml
以下输出表明您的部署现已创建:
Outputdeployment.apps/nginx created
使用以下命令列出您的部署:
kubectl get deployments
您将看到 Nginx 和 PHP-FPM 部署:
OutputNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx 1 1 1 0 16s php 1 1 1 1 7m
列出两个 Deployment 管理的 pod:
kubectl get pods
您将看到正在运行的 pod:
OutputNAME READY STATUS RESTARTS AGE nginx-7bf5476b6f-zppml 1/1 Running 0 32s php-86d59fd666-lkwgn 1/1 Running 0 7m
现在所有 Kubernetes 对象都处于活动状态,您可以在浏览器上访问 Nginx 服务。
列出正在运行的服务:
kubectl get services -o wide
获取 Nginx 服务的外部 IP:
OutputNAME 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
在您的浏览器上,通过输入 http://your_public_ip
访问您的服务器。 您将看到 php_info()
的输出,并确认您的 Kubernetes 服务已启动并正在运行。
结论
在本指南中,您将 PHP-FPM 和 Nginx 服务容器化,以便您可以独立管理它们。 这种方法不仅可以随着您的成长提高项目的可扩展性,还可以让您有效地使用资源。 您还将应用程序代码存储在一个卷上,以便您将来可以轻松地更新您的服务。