Kubernetes 部署 PHP-fpm 與 nginx 多容器應用

實驗前提
需要你有 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 ./
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章