實驗前提
- 需要你有 macOS 開發環境,本文以此為例,其他型別的開發環境請自行搭建。
- 需要你對 YAML 這一專門用來寫配置檔案的語言有所瞭解。
- 需要你對 Docker 有一些基本的瞭解。
- 需要你對 Kubernetes 中的 Node、Pod、ReplicaSet、Deployment、Service、Ingress、ConfigMap 等一些核心基礎概念有一定的瞭解。
YAML 配置檔案下載地址:
- YAML 檔案:jxlwqq/kubernetes-examples。該專案還有其他一些 Kubernetes 的示例。歡迎 Star。
git clone https://github.com/jxlwqq/kubernetes-examples.git
cd deploying-simple-php-app-with-fpm-and-nginx
安裝 Docker for Mac
下載地址:https://hub.docker.com/editions/community/...
啟動並開啟 Kubernetes 功能,功能開啟過程中,Docker 將會自動拉取 Kubernetes 相關映象,所以全程需要科學上網。
為啥不使用 minikube?minikube + virtualbox + kubectl 安裝起來太繁瑣了,而且即使科學上網了你也不一定能搞定。當然阿里雲提供了一篇安裝教程可以參考。
本地埠準備
請確保本地 localhost 的 80 埠沒有被佔用,已在使用的請在實驗期間暫時關閉佔用 80 埠的服務。
切換叢集
如果你本地有多個 Kubernetes 的叢集配置,請先切換至名為 docker-desktop 的叢集:
kubectl config use-context docker-desktop
拉取映象
原始碼在 php-info 目錄中。我這裡已經基於 Dockerfile 製作好了映象,pull 後可以直接使用。
docker pull jxlwqq/php-info
原始碼邏輯很簡單,列印 phpinfo 資訊,Dockerfile 內容如下所示:
php-info/Dockerfile 的程式碼:
FROM php:7.4-fpm
WORKDIR /app
COPY index.php /app
php-info/index.php 的程式碼:
<?php
phpinfo();
部署
kubectl apply -f configmap.yaml # 配置物件,本示例存放 nginx.config
kubectl apply -f php-fpm-nginx-deployment-and-service.yaml # php-fpm 和 nginx 雙容器
kubectl apply -f ingress.yaml # ingress 路由規則
configmap.yaml 檔案解讀:
kind: ConfigMap # 物件型別
apiVersion: v1 # api 版本
metadata: # 後設資料
name: nginx-config # 物件名稱
data: # key-value 資料集合
nginx.conf: | # 將 nginx config 配置寫入 ConfigMap 中,經典的 php-fpm 代理設定,這裡就不再多說了
events {
}
http {
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.php;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
}
}
}
php-fpm-nginx-deployment-and-service.yaml 檔案解讀:
kind: Deployment # 物件型別
apiVersion: apps/v1 # api 版本
metadata: # 後設資料
name: php-fpm-nginx # Deployment 物件名稱
spec: # Deployment 物件規約
selector: # 選擇器
matchLabels: # 標籤匹配
app: php-fpm-nginx
replicas: 1 # 副本數量
template: # 模版
metadata: # Pod 物件的後設資料
labels: # Pod 物件的標籤
app: php-fpm-nginx
spec: # Pod 物件規約
containers: # 這裡設定了兩個容器
- name: php-fpm # 第一個容器名稱
image: jxlwqq/php-info # 容器映象
ports:
- containerPort: 9000 # php-fpm 埠
volumeMounts: # 掛載資料卷
- mountPath: /var/www/html # 掛載兩個容器共享的 volume
name: nginx-www
lifecycle: # 生命週期
postStart: # 當容器處於 postStart 階段時,執行一下命令
exec:
command: ["/bin/sh", "-c", "cp -r /app/. /var/www/html"] # 將 /app/index.php 複製到掛載的 volume
- name: nginx # 第二個容器名稱
image: nginx # 容器映象
ports:
- containerPort: 80 # nginx 埠
volumeMounts: # nginx 容器掛載了兩個 volume,一個是與 php-fpm 容器共享的 volume,另外一個是配置了 nginx.conf 的 volume
- mountPath: /var/www/html # 掛載兩個容器共享的 volume
name: nginx-www
- mountPath: /etc/nginx/nginx.conf # 掛載配置了 nginx.conf 的 volume
subPath: nginx.conf
name: nginx-config
volumes:
- name: nginx-www # 這個 volume 是 php-fpm 容器 和 nginx 容器所共享的,兩個容器都 volumeMounts 了
emptyDir: {}
- name: nginx-config
configMap: # 有人好奇,這裡為啥可以將 configMap 物件透過 volumeMounts 的方式注入到容器中呢,因為本質上 configMap 是一類特殊的 volume
name: nginx-config
---
kind: Service # 物件型別
apiVersion: v1 # api 版本
metadata: # 後設資料
name: php-fpm-nginx
spec:
selector:
app: php-fpm-nginx
ports:
- port: 80
targetPort: 80 # Service 將 nginx 容器的 80 埠暴露出來
ingress.yaml 檔案解讀:
kind: Ingress # 物件型別
apiVersion: networking.k8s.io/v1beta1
metadata:
name: php-fpm-nginx
spec:
rules:
- http:
paths:
- backend:
serviceName: php-fpm-nginx # 流量轉發到名為 php-fpm-nginx 的 Server 是那個
servicePort: 80 # 與 Service 的 port 一致
自動伸縮
kubectl apply -f horizontalpodautoscaler.yaml # hpa 水平自動伸縮物件
horizontalpodautoscaler.yaml 檔案解讀:
kind: HorizontalPodAutoscaler # 物件型別,簡稱 hpa,水平自動伸縮
apiVersion: autoscaling/v2beta2 # autoscaling/v2beta2 與 autoscaling/v1 的 API 有很大的不同,注意識別兩者的差異
metadata:
name: php-fpm-nginx
spec:
scaleTargetRef: # 伸縮的目標物件
apiVersion: apps/v1 # 物件版本
kind: Deployment # 目標物件的型別
name: php-fpm-nginx # 目標物件的名稱
minReplicas: 3 # 最小副本數
maxReplicas: 10 # 最大副本數
metrics: # 指標
- type: Resource # 型別:資源
resource:
name: memory # 記憶體
target:
type: Utilization # 利用率
averageUtilization: 1 # 1% 這個值是為了實驗,具體值請參考業務方實際情況而定
建立 Ingress-nginx 控制器
有了 Ingress 物件還不夠,還需要 Ingress-nginx 控制器。這裡又有一個不太好的比方了,Ingress 物件類似 Nginx 的 nginx.conf 檔案,單單有配置檔案是萬萬不行的,我們需要 Nginx 服務(軟體)本身。
為了讓 Ingress 資源工作,叢集必須有一個正在執行的 Ingress 控制器。 Kubernetes 官方目前支援和維護 GCE 和 nginx 控制器。
這裡我們選擇 Ingress-nginx 控制器:
cd ../ingress-nginx # 切換到 ingress-nginx 目錄
kubectl apply -f ingress-nginx-deployment-and-other-resources-mandatory.yaml
kubectl apply -f ingress-nginx-service.yaml
注:
- ingress-nginx-deployment-and-other-resources-mandatory.yaml 檔案內容來源自:https://github.com/kubernetes/ingress-ngin...
- ingress-nginx-service.yaml 檔案內容來源自:https://github.com/kubernetes/ingress-ngin...
詳細操作說明見:https://github.com/kubernetes/ingress-ngin...
訪問
curl http://localhost
撒花,結束。
清場
刪除本次示例所有的物件:
kubectl delete -f ./
鳴謝
部分內容參考了 https://matthewpalmer.net/kubernetes-app-d...
本作品採用《CC 協議》,轉載必須註明作者和本文連結