Kubernetes(也稱為 k8s)是一個開源的協調系統。它允許使用者以最少的停機時間來部署、擴充和管理容器化應用程式。在本教學中,您將學習如何部署一個 PHP 應用程式到 Kubernetes 叢集上。
Nginx 的作用是作為代理伺服器指向 PHP-FPM,同時執行 PHP 應用程式。在單一容器中管理這兩個服務是一個困難的過程。Kubernetes 幫助我們在兩個不同的容器中管理它們,並減少了麻煩。它還允許使用者重複使用容器,而不用擔心為每個新版本的 PHP/Nginx 建立其容器映像檔。
您將在兩個獨立的容器中執行您的應用程式和代理服務。本教學還將提供有關如何使用本機儲存來建立 Persistent Volume (PV) 和持久性磁碟區宣告 (PVC)。接著,您將使用此 PVC 將您的設定檔和程式碼保留在容器映像檔之外。完成本教學後,您將能夠將 Nginx 映像檔重複用於其他需要代理伺服器的應用程式。您可以透過傳遞設定來實現此目的,而無需為其重新建置映像檔。
先決條件
- 對 Kubernetes (k8s) 及其物件有基本的瞭解。請參閱此指南以獲取 Kubernetes 生態系統的詳細概述.
- 一個在 Ubuntu 18.04 上正常執行的 Kubernetes 叢集。按照本教學來 使用 kubeadm 建立您的 Kubernetes 叢集.
- 此外,您需要將應用程式程式碼託管在公開的 URL 上,例如 GitHub.
步驟 1:建立 PHP-FPM 和 Nginx 服務
此步驟將協助您建立 PHP-FPM 和 Nginx 服務。任何服務都提供對叢集中一組 Pod 的存取。叢集中存在的所有服務都可以透過其名稱相互通訊,而無需 IP 地址。PHP-FPM 服務和 Nginx 服務將分別提供對 PHP-FPM 和 Nginx Pod 的存取。
您需要告訴 PHP-FPM 服務如何找到 Nginx Pod,因為它將作為 PHP-FPM Pod 的代理。為此,您將利用 Kubernetes’ 自動服務發現,並使用易於理解的名稱將請求路由到相應的服務。
為了建立任何服務,您需要建立一個 YAML 檔案,其中包含物件定義。此 YAML 檔案至少包含以下標籤:
apiVersion: 該定義所屬的 Kubernetes API 版本。kind: 此 YAML 檔案建立的 Kubernetes 物件類型。例如:一個service,一個job,或一個pod.metadata: 物件的名稱以及使用者可能想要套用至此物件的不同labels都定義在此標籤下。spec: 此標籤包含您物件的規格說明,例如環境變數 (ENV)、要使用的容器映像檔、可存取容器服務的連接埠。
建立 PHP-FPM 服務
首先,您應該建立一個目錄來存放您的 Kubernetes 物件定義。登入您的主節點並建立一個名為 “definitions:”
|
1 |
mkdir definitions |
將目錄切換到 definitions 目錄:
|
1 |
cd definitions |
接下來,建立您的 PHP-FPM 服務檔案,命名為 php_service.yaml 檔案:
|
1 |
nano php_fpm_service.yaml |
之後,在 apiVersion 和 kind 於 php_fpm_service.yaml 檔案中:
|
1 2 |
apiVersion: v1 kind: Service |
將您的服務命名為 php 或 php-fpm,因為它將提供對您的 PHP-FPM 應用程式的存取:
|
1 2 3 |
… Metadata: name: php |
將您的 php 服務標記為 tier: backend,因為 PHP 應用程式將在此服務背後執行:
|
1 2 3 |
… labels: tier: backend |
服務使用 selector 標籤來確定要存取哪些 Pod。任何符合這些標籤的 Pod,無論該 Pod 是何時建立的,都會受到服務。您將在本教學的後面學習如何將標籤新增到您的 Pod 中。
包含 tier: backend 標籤,將您的 pod 分配到 backend 層,以及 app: php-fpm 標籤,以表示該 pod 運行 PHP-FPM 應用程式。您必須在 metadata 區段之後添加這些標籤:
|
1 2 3 4 5 |
… spec: selector: app: php-fpm tier: backend |
接下來,您需要宣告存取此 php-fpm 服務的連接埠,位於 spec 之下。您可以添加任何您選擇的連接埠,但在本教學中我們將使用連接埠 9000:
|
1 2 3 4 |
... ports: - protocol: TCP port: 9000 |
完成上述步驟後,您的 php_fpm_service.yaml 檔案將如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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 指令以建立 PHP 服務
建立服務的物件定義後,請執行 kubectl apply 指令並加上 -f 參數,指定您的 php_fpm_service.yaml 檔案:
|
1 |
kubectl apply -f php_fpm_service.yaml |
上述指令的輸出應為:
|
1 |
service/php created |
執行以下指令以驗證您的 php-fpm 服務是否正在執行:
|
1 |
$ kubectl get svc |
您將能夠看到 php-fpm 服務已啟動並正在執行:
|
1 2 3 |
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 |
建立 Nginx 服務
既然您的 PHP-FPM 服務已經準備就緒,現在也是建立 Nginx 服務的時候了。在編輯器中為此服務建立並開啟一個名為 nginx_service.yaml 的新 YAML 檔案:
|
1 |
$ nano nginx_service.yaml |
將此服務命名為 nginx,因為它將以 Nginx pod 為目標。此服務也屬於 backend,因此您應該為其添加 tier: backend 標籤:
|
1 2 3 4 5 6 |
apiVersion: v1 kind: Service metadata: name: nginx labels: tier: backend |
如同我們在 php-fpm 服務中所做的那樣,添加選擇器標籤 app: nginx 和 tier: backend 以指定目標 pod。添加預設的 HTTP 連接埠 80 以存取此服務:
|
1 2 3 4 5 6 7 8 |
... spec: selector: app: nginx tier: backend ports: - protocol: TCP port: 80 |
Nginx 服務可以透過公用 IP 位址在網際網路上公開存取。您可以將工作節點的 IP 新增為 your_public_ip。在 spec.externalIPs:
|
1 2 3 4 5 |
... spec: externalIPs: - your_public_ip |
當您完成上述所有步驟後,您的 nginx_service.yaml 檔案應該如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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 |
新增上述所有必要參數後,儲存並關閉檔案。
套用 kubectl 指令以建立 Nginx 服務
|
1 |
kubectl apply -f nginx_service.yaml |
|
1 |
服務/nginx 已建立 |
|
1 |
$ kubectl get svc |
|
1 2 3 4 |
名稱 類型 叢集-IP 外部-IP 連接埠(S) 存活時間 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 |
|
1 |
$ kubectl delete svc/service_name |
步驟 2:建立本機儲存和永續性磁碟區
Kubernetes 提供了各種儲存外掛程式,可協助您為環境建立儲存空間。本步驟將引導您如何建立本機 StorageClass 以及如何進一步使用此 Storage Class 來建立永續性磁碟區。
建立本機儲存
建立一個檔案,例如 storageClass.yaml,在您的編輯器中:
|
1 |
$nano storageClass.yaml |
將 kind 新增為 "storageClass",並將 apiVersion 新增為 "storage.k8s.io/v1",如下所示:
|
1 2 |
kind: StorageClass apiVersion: storage.k8s.io/v1 |
將此 StorageClass 命名為 "my-local-storage",並新增 provisioner 和 volumeBindingMode,如下所示:
|
1 2 3 4 5 |
… metadata: name: my-local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: Immediate |
儲存並退出檔案,您最終的 storageClass.yaml 檔案應該如下所示:
|
1 2 3 4 5 6 |
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: my-local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer |
現在,透過執行 kubectl create 命令來建立 StorageClass,如下所示:
|
1 |
$ kubectl create -f storageClass.yaml |
執行上述命令後,您應該會得到以下輸出:
|
1 |
storageclass.storage.k8s.io/my-local-storage created |
建立本機永續性磁碟區
建立本機儲存後,您可以建立本機永續性磁碟區。永續性磁碟區(也稱為 PV)是特定大小的區塊儲存,獨立於 Pod 的生命週期。本機永續性磁碟區只不過是 Kubernetes 叢集節點上可用的本機磁碟或目錄。此本機永續性磁碟區允許使用者以非常簡單且可移植的方式,透過使用本機永續性磁碟區宣告 (Persistent Volume Claim) 來存取本機儲存。您可以使用我們剛剛建立的此儲存類別來建立此本機永續性磁碟區。開啟一個檔案,例如 persistentVolume.yaml,在您的編輯器中:
|
1 |
$ nano persistentVolume.yaml |
為此永續性磁碟區命名,例如 "my-local-pv":
|
1 2 3 4 |
apiVersion: v1 kind: PersistentVolume metadata: name: my-local-pv |
在建立本機永續性磁碟區時,您可以根據您的使用情況新增儲存容量。在本教學中,我們將使用 5 Gi 作為儲存空間:
|
1 2 3 4 |
… spec: capacity: storage: 5Gi |
新增 accessModes、persistentVolumeReclaimPolicy,並提供與 storageClass.yaml 中相同的 storageClassName:
|
1 2 3 4 5 |
… accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: my-local-storage |
新增 local.path 至您的 Persistent Volume,如下所示:
|
1 2 3 |
… local: path: /mnt/disk/vol |
新增所有必要欄位後,您的 persistentVolume.yaml 檔案應該如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
apiVersion: v1 kind: PersistentVolume metadata: name: my-local-pv spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: my-local-storage local: path: /mnt/disk/vol nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - worker |
準備本機卷冊
現在,我們需要在 “worker” 節點上準備一個本機卷冊,正如我們在 persistentVolume.yaml 檔案中所新增的。在您於 persistentVolume 中設定的節點上執行以下指令。在此案例中,它是 “worker” 節點:
|
1 2 3 |
$ DIRNAME="vol" $ mkdir -p /mnt/disk/$DIRNAME $ chmod 777 /mnt/disk/$DIRNAME |
在您的 persistentVolume.yaml 檔案所在的主節點上執行以下指令:
|
1 |
kubectl create -f persistentVolume.yaml |
您應該會得到以下輸出:
|
1 |
persistentvolume/my-local-pv created |
由於您已成功建立本機儲存空間和永續卷冊,您現在可以繼續建立永續卷冊聲明(Persistent Volume Claim)來存放您的應用程式程式碼和設定檔。
步驟 3:建立永續卷冊
在您管理或更新 Pod 時,您的應用程式程式碼需要保持安全。為此,您將使用在上一步中建立的永續卷冊(Persistent Volume),並透過使用永續卷冊聲明(Persistent Volume Claim,簡稱 PVC)來存取它。此 PVC 會將 PV 掛載到所需的路徑上。
開啟一個檔案,例如 code_volume.yaml,在您的編輯器中:
|
1 |
$ nano code_volume.yaml |
透過在檔案中新增以下參數和值,將您的 PVC 命名為 code:
|
1 2 3 4 |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: code |
PVC 的 spec 區段包含以下項目:
- accessModes:此欄位有各種可能的取值,如下所示:
- ReadWriteOnce – 為單一節點掛載具有讀取和寫入權限的卷冊。
- ReadOnlyMany – 為多個節點掛載僅具有讀取權限的卷冊。
- ReadWriteMany – 為多個節點掛載具有讀取和寫入權限的卷冊。
- resources:定義所需的儲存空間。
由於本地儲存僅掛載到單個節點,您需要將 accessMode 設置為 ReadWriteOnce。在本教學中,您只需添加一小部分應用程式代碼,因此這裡 1GB 的儲存空間就足夠了。但是,如果您希望儲存更大量的數據或代碼,可以根據您的需求修改 storage 參數。請注意,磁碟卷創建後,您將能夠增加儲存大小。但是,不支援減少儲存大小:
|
1 2 3 4 5 6 7 |
... spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi |
現在,聲明 Kubernetes 叢集將用於分配給磁碟卷的儲存類別(storage class)。在此處的 storageClassName 使用在上一步中創建的 my-local-storage 儲存類別:
|
1 2 |
... storageClassName: my-local-storage |
完成上述步驟後,您的 code_volume.yaml 檔案應該如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: code spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: my-local-storage |
現在儲存並退出檔案。
創建 PVC
執行 kubectl apply 命令來創建 code PVC:
|
1 |
$ kubectl apply -f code_volume.yaml |
您應該會得到以下輸出,表示該物件已成功創建,並準備好將您的 1GB PVC 掛載為磁碟卷:
|
1 |
persistentvolumeclaim/code created |
您可以執行以下命令來檢查可用的持久性磁碟卷 (PV):
|
1 |
$ kubectl get pv |
上述命令的輸出應該如下所示:
|
1 2 |
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 |
除了 Reclaim Policy 和 Status 之外,上述所有欄位都是您設定檔的概覽。Reclaim Policy 定義了當存取該 PV 的 PVC 被刪除時,PV 會發生什麼事。Delete 值會將 PV 從 Kubernetes 叢集以及儲存基礎架構中移除。您可以參考 Kubernetes PV 文件 以清楚了解 Reclaim Policy 和 Status。
由於您已成功使用本地儲存創建了持久性磁碟卷,現在可以使用 Deployment 來創建您的 Pod。
步驟 4:為您的 PHP-FPM 應用程式創建 Deployment
此步驟將協助您使用 Deployment。Deployment 使用 ReplicaSet 提供一種穩定的方式來創建、更新和管理您的 Pod。Deployment 會自動將其 Pod 回滾到先前的映像檔。
在 Deployment 中的 spec.selector 鍵列出了它所管理之 Pod 的所有標籤。它還使用 template 鍵來創建所需的 Pod。
在此步驟中,我們還將介紹 Init Containers 的應用。初始化容器(Init Containers)會在 Pod 範本中指定的常規容器之前執行一些命令。在這裡,初始化容器將使用 GitHub Gist (https://gist.github.com/) 來獲取範例 index.php 檔案。該範例檔案的內容為:
|
1 2 |
<?php echo phpinfo(); |
創建 PHP Deployment
在編輯器中打開一個名為 php_deployment.yaml 的新檔案以創建您的 Deployment:
|
1 |
$ nano php_deployment.yaml |
現在,將 Deployment 物件命名為 PHP,因為此 Deployment 將管理您的 PHP-FPM pod。新增標籤 tier: backend,因為該 pod 將屬於 backend 層:
|
1 2 3 4 5 6 |
apiVersion: apps/v1 kind: Deployment metadata: name: php labels: tier: backend |
使用 replica 參數,指定應建立的此 pod 副本數量。副本數量可能會根據您的需求和可用資源而有所不同。在本教學中,您將僅建立該 pod 的一個副本:
|
1 2 3 4 |
... spec: replicas: 1 |
新增 app: php 和 tier:backend 標籤於 selector 鍵下,這表示此 Deployment 將管理與這兩個標籤相匹配的 pod:
|
1 2 3 4 5 |
... selector: matchLabels: app: php tier: backend |
現在,您的 pod’s 物件定義需要在您的 Deployment spec 下有一個 template。此範本定義了建立 pod 所需的規格。首先,新增為 php 服務選擇器 (service selector) 和 Deployment 的 matchLabels 指定的標籤。然後新增 app:php 和 tier:backend 於 template.metadata.labels:
|
1 2 3 4 5 6 7 |
... template: metadata: labels: app: php tier: backend |
首先,您需要指定容器將存取的所有磁碟卷。將此磁碟卷命名為 code,因為您之前已建立了一個名為 code 的 PVC 來存放您的應用程式程式碼:
|
1 2 3 4 5 6 |
... spec: volumes: - name: code persistentVolumeClaim: claimName: code |
接下來,指定容器名稱以及您要在 pod 內執行的映像檔。Docker store (https://hub.docker.com/explore/) 上有各種可用的映像檔,但在本教學中,我們將使用 php:7-fpm 映像檔:
|
1 2 3 4 |
... containers: - name: php image: php:7-fpm |
現在,掛載容器需要存取的磁碟卷。由於此容器將執行您的 PHP 程式碼,因此它需要存取在上一步中建立的 code 磁碟卷。在此步驟中,您還將學習如何使用 Init Container 複製您的應用程式程式碼。
為了下載程式碼,本教學將引導您如何使用帶有 busybox 的單個 Init Container。Busybox 是一個帶有 wget 工具的小型容器,您將使用它來實現此目的。
首先,在 spec.template.spec 下新增您的 initContainer,並指定 busybox 映像檔:
|
1 2 3 4 |
... initContainers: - name: install image: busybox |
然後,為了將程式碼下載到 code 磁碟卷中,您的 Init Container 將需要存取它。將 code 磁碟卷掛載於 /code 路徑,位於 spec.template.spec.initContainers:
|
1 2 3 4 |
... volumeMounts: - name: code mountPath: /code |
每個 Init Container 都需要執行指令。此 Init Container 將使用 wget 下載 code 自 Github 到 /code 目錄中。您可以傳遞 -O 選項來為此下載的檔案命名,您可以將此檔案命名為 index.php.
此外,在 install 容器下方新增以下幾行於 spec.template.spec.initContainers:
|
1 2 3 4 5 6 |
... command: - wget - "-O" - "/code/index.php" - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php |
完成所有這些步驟後,您的 php_deployment.yaml 檔案應該如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
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 |
You can now save the file and exit. Next, create your PHP-FPM Deployment using kubectl apply command:
|
1 |
$ kubectl apply -f php_deployment.yaml |
成功建立 Deployment 後,您應該會看到以下輸出:
|
1 |
deployment.apps/php created |
此 Deployment 首先會下載指定的映像檔,然後它會向您的 PersistentVolume 請求 PersistentVolumeClaim,接著執行您的 initContainers。完成此步驟後,容器將會執行並將儲存卷掛載到指定的掛載點。完成所有這些步驟後,您的 Pod 將會啟動並執行。
您可以執行以下指令來檢視您的 Deployment:
|
1 |
$ kubectl get deployments |
執行上述指令後,您應該會得到以下輸出:
|
1 2 |
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE php 1 1 1 0 19s |
You can understand the current state of the Deployment with the help of this output. A Deployment is a controller that maintains the desired state. The DESIRED 欄位指定它有 1 個名為 php 的 Pod 副本。 CURRENT 欄位表示目前有多少個 DESIRED 狀態的副本正在執行。對於健康的 Pod,這應該與 DESIRED 狀態相符。您可以在 Kubernetes Deployments 文件.
之後,若要檢查正在執行的 Pod 狀態,您可以執行以下指令:
|
1 |
$ kubectl get pods |
此指令的輸出可能會根據您建立 Deployment 後所經過的時間而有所不同。如果是在建立 Deployment 後不久執行,輸出將類似於:
|
1 2 |
NAME READY STATUS RESTARTS AGE php-5d8f6bbf7f-56df2 0/1 Init:0/1 0 9s |
說明:
這些欄位代表的資訊如下:
- Ready:執行此 Pod 的目前/期望副本數量。
- Status: 您的 Pod 狀態。Init:0/1 表示 Init 容器正在運行,且 1 個 Init 容器中有 0 個已完成運行。
- Restarts: 這表示此程序為了啟動 Pod 而重新啟動的次數。
您的 Pod 可能需要幾分鐘的時間才能將狀態變更為 podInitializing,具體取決於您啟動指令碼的複雜程度:
|
1 2 |
名稱 就緒 狀態 重啟次數 存活時間 php-5d8f6bbf7f-56df2 0/1 podInitializing 0 39s |
這表示 Init 容器已成功運行,現在容器正在進行初始化:
|
1 2 |
名稱 就緒 狀態 重啟次數 存活時間 php-5d8f6bbf7f-56df2 1/1 Running 0 4m10s |
如您所見,您的 Pod 現在已啟動並運行。然而,如果您的 Pod 未能啟動,您可以運行以下命令進行偵錯:
1. 檢視 Pod 的詳細資訊:
|
1 |
$ kubectl describe pods pod-name |
2. 檢視 Pod 的記錄檔:
|
1 |
$ kubectl logs pod-name |
3. 檢視 Pod 中特定容器的記錄檔:
|
1 |
$ kubectl logs pod-name container-name |
恭喜!您已成功掛載應用程式程式碼,且 PHP-FPM 服務已準備好處理連線。同樣地,您可以建立您的 Nginx 部署。
步驟 5:建立您的 Nginx 部署
本步驟將引導您如何使用 ConfigMap。 ConfigMap 以鍵值(key-value)格式保存所有必要的設定,這些設定將在其他 Kubernetes 物件定義中使用。透過這種方法,您可以根據需要靈活地重複使用或更換不同版本的 Nginx 映像檔。您可以更新 ConfigMap,它會自動將這些變更複製到任何掛載此 ConfigMap.
首先,在您的編輯器中開啟 nginx_configmap.yaml 檔案:
|
1 |
$ nano nginx_configMap.yaml |
現在,將此 ConfigMap 命名為 nginx-config 並將其新增至 tier: backend 微服務:
|
1 2 3 4 5 6 |
apiVersion: v1 kind: ConfigMap metadata: name: nginx-config labels: tier: backend |
此外,您可以將資料新增至 ConfigMap。新增一個名為 config 的鍵,並將所有 Nginx 設定檔內容作為其值。
由於 Kubernetes 可以將請求路由到服務的對應主機,您可以在 fastcgi_pass 參數下輸入您的 PHP-FPM 服務名稱,而不是其 IP 地址。將以下幾行程式碼新增至您的 nginx_configMap.yaml 檔案中:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
... 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 檔案將如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
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; } } |
您現在可以儲存並退出編輯器。現在執行 kubectl apply 命令以建立 ConfigMap:
|
1 |
$ kubectl apply -f nginx_configMap.yaml |
之後,您應該會在螢幕上看到以下輸出:
|
1 |
configmap/nginx-config created |
您已成功建立 Nginx Configmap。現在您可以建立 Nginx Deployment。
建立 Nginx Deployment
首先,您可以在編輯器中建立一個名為 nginx_deployment.yaml 的新檔案:
|
1 |
$ nano nginx_deployment.yaml |
將此 Deployment 命名為 nginx 並為其新增 tier: backend 標籤:
|
1 2 3 4 5 6 7 |
apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: tier: backend |
之後,透過在 Deployment spec 中新增 replica 欄位來指定副本數量,並為其新增 app: nginx 和 tier: backend 標籤:
|
1 2 3 4 5 6 7 |
... spec: replicas: 1 selector: matchLabels: app: nginx tier: backend |
同樣地,新增 Pod 範本。請確保您新增的標籤與您在 Deployment 的 selector.matchLabels 中新增的標籤相同。您可以新增以下內容:
|
1 2 3 4 5 6 |
... template: metadata: labels: app: nginx tier: backend |
透過在以下位置新增以下參數,讓 Nginx 能夠存取先前建立的 code PVC:spec.template.spec.volumes:
|
1 2 3 4 5 6 |
... spec: volumes: - name: code persistentVolumeClaim: claimName: code |
|
1 2 3 4 5 6 7 |
... - name: config configMap: name: nginx-config items: - key: config path: site.conf |
警告:如果未指定檔案,鍵的內容將會取代 volume’s mountPath。換句話說,如果未明確指定路徑,您將會遺失目標資料夾中的所有內容。
現在,指定您要在 Pod 中使用的名稱、映像檔和連接埠。在這裡,我們將使用 nginx:1.7.9 映像檔和連接埠 80。將它們新增在 spec.template.spec 區段:
|
1 2 3 4 5 6 |
... containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 |
此外,將 code 儲存卷掛載於 /code ,因為 Nginx 和 PHP-FPM 都需要存取相同路徑下的檔案:
|
1 2 3 4 |
... volumeMounts: - name: code mountPath: /code |
這個 nginx-1.7.9 映像檔會自動載入位於 /etc/nginx/conf.d 資料夾下的任何設定檔。現在,如果我們在此目錄中掛載 config 儲存卷,它將會建立 /etc/nginx/conf.d/site.conf。請在 volumeMount 區段下方新增以下內容:
|
1 2 3 |
... - name: config mountPath: /etc/nginx/conf.d |
完成上述所有步驟後,您的 nginx_deployment.yaml 檔案應該如下所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
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 Deployment:
|
1 |
$ kubectl apply -f nginx_deployment.yaml |
成功執行命令後,您應該會看到以下輸出:
|
1 |
deployment.apps/nginx created |
您可以執行以下命令來列出所有的 Deployment:
|
1 |
$ kubectl get deployments |
您現在應該會看到 Nginx 和 PHP-FPM 的 Deployment:
此外,您可以執行以下命令來列出由上述兩個 Deployment 所管理的 Pod:
|
1 |
$ kubectl get pods |
您將會看到您的兩個 Pod 都已啟動並運行,如下所示:
由於此時您所有的 Kubernetes 物件都已處於作用狀態,您現在可以在瀏覽器上存取 Nginx 服務。
執行以下命令以列出服務:
|
1 |
$ kubectl get services -o wide |
現在,使用此 Nginx 服務的 External IP,您可以透過在瀏覽器上輸入 http://your_public_ip 來造訪您的伺服器。您應該能夠看到 php_info() 的輸出,這確認了您的 Kubernetes 服務已啟動並運行。
結論
在本教學中,為了獨立管理您的 PHP-FPM 和 Nginx 服務,您將這兩個服務進行了容器化。透過這樣做,您不僅能提高專案的擴充性,還能有效率地利用資源。您也學習了如何建立本機儲存和 Persistent Volume,以便將應用程式程式碼儲存在磁碟卷上,並在未來輕鬆更新您的服務。透過這樣做,您提高了程式碼的可用性和可維護性。
此外,您可以查看我們其他專注於 Docker 和 Kubernetes 的教學,這些教學可以在我們的 部落格:
- 認識 Kubernetes
- 如何在 Ubuntu 18.04 上使用 Kubeadm 建立 Kubernetes 叢集
- 清理 Docker 資源 – 映像檔、容器和磁碟卷
- 使用 Docker Compose 部署 Laravel、Nginx 和 MySQL
- 如何在公有雲的 Ubuntu 上安裝 & 操作 Docker
祝您運算愉快!



留言
目前尚無留言。成為第一個留言的人吧。