最簡單 k8s 建立 yaml 和部署 示範

k8s 的設定檔好難,每個人寫的都不一樣,拿來拼拼湊湊試了半天都無法執行,花了很久的時間終於半途而廢看完艱澀難懂的文件,本篇就來將好不容易悟出的設定檔寫法記錄下來。

註:需要先部署好 Kubernetes 和完成 kubectl 安裝

Kind

在 yaml 中有好幾種 Kind (種類),簡短的介紹如下:
  • Pod: 容器組,儲存多個容器,k8s 中的最小單位
  • Deployment: 部署,管理 Pod 的建立、更新、擴展、刪除
  • Service: 服務,讓外部或其他服務存取 Pod
  • StatefulSet: 狀態集合,用來管理需要儲存資料(狀態)的 Pod
  • ConfigMap: 設定檔,儲存執行參數
  • Secret: 用來儲存機密資訊
依據上面的種類,要和平時使用 docker 一樣建立一個能夠讓外部存取的容器最少需要 pod + service, 不過通常不會這樣做,會直接使用 deployment + service,這樣當 pod 出現問題時 deployment 才可以幫我們自動處理,不過我們先使用 pod + service 建立一個最簡單的 yaml 檔案。

pod + service 示範

這裡使用 nginx 做示範,平時使用 docker 將 nginx 建立起來後開啟 80 port 就會看到 nginx 的歡迎畫面,在 k8s 中需要使用下面的設定檔才可以達成:
    
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: my-nginx # 定義標籤,用以辨識
spec: # 定義規格
  containers: # 容器
    - name: nginx # 容器名稱
      image: nginx:latest # 容器映像檔
      ports: # 定義要暴露的連接埠
        - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service # 服務名稱
spec:
  selector:
    app: my-nginx # 指向上方定義的標籤
  type: NodePort
  ports: # 定義要暴露的連接埠
    - protocol: TCP
      port: 80 # Service 內部的連接埠
      nodePort: 30000 # 外部存取的連接埠
    

註: 外部存取的連接埠有限制範圍,port 需要指定在 30000-32767 區間內。

執行

建立或更新(deployment.yaml 為檔案名稱)
    
kubectl apply -f deployment.yaml
    

    
kubectl apply -f .\deployment.yaml
pod/nginx-pod created
service/nginx-service created
    

查看 pod

    
kubectl get pods
    

    
kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          4m3s
    

查看 deployment

(上面的 yaml 沒有建立 deployment)
    
kubectl get deployments
No resources found in default namespace.
    

查看 servicet

    
kubectl get service nginx-service
    

    
kubectl get service
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.152.183.1     <none>        443/TCP        23h
nginx-service   NodePort   10.152.183.20     <none>        80:30000/TCP   4m6s
    

從上面的 port 可以看到 PORT 成功使用 30000

刪除

    
kubectl delete -f deployment.yaml
    

deployment + service 示範

既然我們已經可以正常的使用 pod + service 了,再來就可以把 pod 換成 deployment 了,設定檔稍微修改一下即可:
    
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: my-nginx # 指向 Pod 的標籤
  replicas: 1  # 副本數量

  template: # Pod
    metadata:
      labels:
        app: my-nginx # 定義標籤,用以辨識
    spec:
      containers:
        - name: nginx # 容器名稱
          image: nginx:latest  # 容器映像檔
          ports: # 定義要暴露的連接埠
            - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service # 服務名稱
spec:
  selector:
    app: my-nginx  # 指向上方定義的標籤
  type: NodePort
  ports: # 定義要暴露的連接埠
    - protocol: TCP
      port: 80  # Service 內部的連接埠
      nodePort: 30000  # 外部存取的連接埠

    

接下來就可以使用相同的步驟建立和查看資訊了:
    
kubectl apply -f .\pod_service.yaml
deployment.apps/nginx-deployment created
service/nginx-service created

kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-6b7cc7446b-7qbvd   1/1     Running   0          6s

kubectl get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   1/1     1            1           9s

kubectl get service
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.152.183.1     <none>        443/TCP        23h
nginx-service   NodePort    10.152.183.217   <none>        80:30000/TCP   13s
    

利用 ConfigMap 儲存資料

在 Nginx 中的 etc/nginx/nginx.conf 這個檔案就是基本的設定檔,我們可以利用 ConfigMap 儲存 nginx.conf 這個設定檔的資料,掛載進 Pod 中:
    
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  nginx.conf: |
  
    user  nginx;
    worker_processes  auto;
    
    error_log  /var/log/nginx/error.log notice;
    pid        /var/run/nginx.pid;
    
    
    events {
      worker_connections  1024;
    }
      
      
    http {
      include       /etc/nginx/mime.types;
      default_type  application/octet-stream;
      
      log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
      '$status $body_bytes_sent "$http_referer" '
      '"$http_user_agent" "$http_x_forwarded_for"';
      
      access_log  /var/log/nginx/access.log  main;
      
      sendfile        on;
      
      keepalive_timeout  65;
      
      
      server {
        listen 80;
        server_name example.com;
        
        location /api/users {
          default_type application/json;
          return 200 '[{"id":1,"name":"Ruyut"}]';
        }
      }
      include /etc/nginx/conf.d/*.conf;
    }


---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: my-nginx # 指向 Pod 的標籤
  replicas: 1  # 副本數量

  template: # Pod
    metadata:
      labels:
        app: my-nginx # 定義標籤,用以辨識
    spec:
      containers:
        - name: nginx # 容器名稱
          image: nginx:latest  # 容器映像檔
          ports: # 定義要暴露的連接埠
            - containerPort: 80
          volumeMounts:
            - name: config-volume
              mountPath: /etc/nginx/nginx.conf
              subPath: nginx.conf  # 只掛載 nginx.conf 文件
      volumes:
        - name: config-volume
          configMap:
            name: nginx-config  # 指向前面定義的 ConfigMap


---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service # 服務名稱
spec:
  selector:
    app: my-nginx  # 指向上方定義的標籤
  type: NodePort
  ports: # 定義要暴露的連接埠
    - protocol: TCP
      port: 80  # Service 內部的連接埠
      nodePort: 30000  # 外部存取的連接埠
    

上面的 nginx.conf 設定內容很簡單,就是 80 port 的 /api/users 連結會回傳 json 資料。

參考資料:
kubernetes - pods
kubernetes - service

留言