1. 程式人生 > 其它 >自從上了K8S,專案更新都不帶停機的!

自從上了K8S,專案更新都不帶停機的!

技術標籤:架構筆記程式人生dockerlinuxjavakubernetes大資料

其實K8S中還有一些高階特性也很值得學習,比如彈性擴縮應用、滾動更新、配置管理、儲存卷、閘道器路由等。今天我們就來了解下這些高階特性,希望對大家有所幫助!

核心概念

首先我們先來了解一些核心概念,瞭解這些核心概念對使用K8S的高階特性很有幫助。

ReplicaSet

ReplicaSet確保任何時間都有指定數量的Pod副本在執行。通常用來保證給定數量的、完全相同的Pod的可用性。建議使用Deployment來管理ReplicaSet,而不是直接使用ReplicaSet。

ConfigMap

ConfigMap是一種API物件,用來將非機密性的資料儲存到鍵值對中。使用時,Pod可以將其用作環境變數、命令列引數或者儲存卷中的配置檔案。使用ConfigMap可以將你的配置資料和應用程式程式碼分開。

Volume

Volume指的是儲存卷,包含可被Pod中容器訪問的資料目錄。容器中的檔案在磁碟上是臨時存放的,當容器崩潰時檔案會丟失,同時無法在多個Pod中共享檔案,通過使用儲存卷可以解決這兩個問題。

常用的儲存卷有如下幾種:

  • configMap:configMap卷提供了向Pod注入配置資料的方法。ConfigMap物件中儲存的資料可以被configMap型別的卷引用,然後被Pod中執行的容器化應用使用。
  • emptyDir:emptyDir卷可用於儲存快取資料。當Pod分派到某個Node上時,emptyDir卷會被建立,並且Pod在該節點上執行期間,卷一直存在。當Pod被從節點上刪除時emptyDir卷中的資料也會被永久刪除。
  • hostPath:hostPath卷能將主機節點檔案系統上的檔案或目錄掛載到你的Pod中。在Minikube中的主機指的是Minikube所在虛擬機器。
  • local:local卷所代表的是某個被掛載的本地儲存裝置,例如磁碟、分割槽或者目錄。local卷只能用作靜態建立的持久卷,尚不支援動態配置。
  • nfs:nfs卷能將NFS(網路檔案系統)掛載到你的Pod中。
  • persistentVolumeClaim:persistentVolumeClaim卷用來將持久卷(PersistentVolume)掛載到Pod中。持久卷(PV)是叢集中的一塊儲存,可以由管理員事先供應,或者使用儲存類(Storage Class)來動態供應,持久卷是叢集資源類似於節點。

Ingress

Ingress類似於K8S中的閘道器服務,是對叢集中服務的外部訪問進行管理的API物件,典型的訪問方式是HTTP。Ingress可以提供負載均衡、SSL終結和基於名稱的虛擬託管。

高階特性

擴縮應用

當流量增加時,我們需要擴容應用程式滿足使用者需求。當流量減少時,需要縮放應用以減少伺服器開銷。在K8S中擴縮是通過改變Deployment中的副本數量來實現的。

  • 獲取所有Deployment可使用如下命令:
kubectl get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-nginx   1/1     1            1           43h
  • 獲取所有ReplicaSet可使用如下命令:
kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
kubernetes-nginx-78bcc44665   1         1         1       43h
  • 對應用進行擴容操作,擴容到4個例項,再檢視所有:
kubectl scale deployments/kubernetes-nginx --replicas=4
[[email protected] root]$ kubectl get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-nginx   4/4     4            4           43h
  • 檢視所有Pod,發現已經有4個執行在不同的IP地址上了;
kubectl get pods -o wide
NAME                                READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
kubernetes-nginx-78bcc44665-8fnnn   1/1     Running   2          43h   172.17.0.3   minikube   <none>           <none>
kubernetes-nginx-78bcc44665-dvq4t   1/1     Running   0          84s   172.17.0.8   minikube   <none>           <none>
kubernetes-nginx-78bcc44665-thzg9   1/1     Running   0          84s   172.17.0.7   minikube   <none>           <none>
kubernetes-nginx-78bcc44665-w7xqd   1/1     Running   0          84s   172.17.0.6   minikube   <none>           <none>
  • 對應用進行縮放操作,縮放到2個例項;
kubectl scale deployments/kubernetes-nginx --replicas=2
NAME                                READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
kubernetes-nginx-78bcc44665-8fnnn   1/1     Running   2          44h   172.17.0.3   minikube   <none>           <none>
kubernetes-nginx-78bcc44665-w7xqd   1/1     Running   0          11m   172.17.0.6   minikube   <none>           <none>

滾動更新

滾動更新允許通過使用新的例項逐步更新Pod例項,零停機進行Deployment更新。K8S不僅可以實現滾動更新,還可以支援回滾操作。

  • 目前運行了4個Nginx1.10版本的例項:
[[email protected] root]$ kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
kubernetes-nginx-78bcc44665-8fnnn   1/1     Running   2          44h
kubernetes-nginx-78bcc44665-jpw2g   1/1     Running   0          5s
kubernetes-nginx-78bcc44665-w7xqd   1/1     Running   0          59m
kubernetes-nginx-78bcc44665-xx8s5   1/1     Running   0          5s
  • 可以通過kubectl describe命令來檢視映象版本號:
[[email protected] root]$ kubectl describe pods |grep Image
    Image:          nginx:1.10
    Image ID:       docker-pullable://[email protected]:6202beb06ea61f44179e02ca965e8e13b961d12640101fca213efbfd145d7575
  • kubectl set image 1.19 1.10 1.19
# 命令格式 kubectl set image Deployment的名稱 容器名稱=容器映象:映象版本號
kubectl set image deployments/kubernetes-nginx nginx=nginx:1.19
# 停止1箇舊例項並建立2個新例項
NAME                                READY   STATUS              RESTARTS   AGE
kubernetes-nginx-66f67cd758-rbcz5   0/1     ContainerCreating   0          11s
kubernetes-nginx-66f67cd758-s9ck8   0/1     ContainerCreating   0          11s
kubernetes-nginx-78bcc44665-8fnnn   1/1     Running             2          45h
kubernetes-nginx-78bcc44665-jpw2g   0/1     Terminating         0          15m
kubernetes-nginx-78bcc44665-w7xqd   1/1     Running             0          75m
kubernetes-nginx-78bcc44665-xx8s5   1/1     Running             0          15m
# 1個例項已被停止2個新例項仍建立中
NAME                                READY   STATUS              RESTARTS   AGE
kubernetes-nginx-66f67cd758-rbcz5   0/1     ContainerCreating   0          30s
kubernetes-nginx-66f67cd758-s9ck8   0/1     ContainerCreating   0          30s
kubernetes-nginx-78bcc44665-8fnnn   1/1     Running             2          45h
kubernetes-nginx-78bcc44665-w7xqd   1/1     Running             0          75m
kubernetes-nginx-78bcc44665-xx8s5   1/1     Running             0          15m
# 4個新例項均已建立完成
NAME                                READY   STATUS    RESTARTS   AGE
kubernetes-nginx-66f67cd758-jn926   1/1     Running   0          48s
kubernetes-nginx-66f67cd758-rbcz5   1/1     Running   0          3m12s
kubernetes-nginx-66f67cd758-s9ck8   1/1     Running   0          3m12s
kubernetes-nginx-66f67cd758-smr7n   1/1     Running   0          44s
  • 此時再使用kubectl describe命令來檢視映象版本號,發現Nginx已經更新至1.19版本:
[[email protected] root]$ kubectl describe pods |grep Image
    Image:          nginx:1.19
    Image ID:       docker-pullable://[email protected]:4cf620a5c81390ee209398ecc18e5fb9dd0f5155cd82adcbae532fec94006fb9
  • 如果想回滾到原來的版本的話,直接使用kubectl rollout undo命令即可。
kubectl rollout undo deployments/kubernetes-nginx

配置管理

ConfigMap允許你將配置檔案與映象檔案分離,以使容器化的應用程式具有可移植性。接下來我們演示下如何將ConfigMap的的屬性注入到Pod的環境變數中去。

  • nginx-config.yaml nginx-config data
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  namespace: default
data:
  nginx-env: test
  • 應用nginx-config.yaml檔案建立ConfigMap:
kubectl create -f nginx-config.yaml
  • 獲取所有ConfigMap:
kubectl get configmap
NAME               DATA   AGE
kube-root-ca.crt   1      2d22h
nginx-config       1      13s
  • 通過yaml格式檢視ConfigMap中的內容:
kubectl get configmaps nginx-config -o yaml
apiVersion: v1
data:
  nginx-env: test
kind: ConfigMap
metadata:
  creationTimestamp: "2021-01-08T01:49:44Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:nginx-env: {}
    manager: kubectl-create
    operation: Update
    time: "2021-01-08T01:49:44Z"
  name: nginx-config
  namespace: default
  resourceVersion: "61322"
  uid: a477567f-2aff-4a04-9a49-f19220baf0d3
  • 新增配置檔案nginx-deployment.yaml用於建立Deployment,部署一個Nginx服務,在Nginx的環境變數中引用ConfigMap中的屬性:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.10
          ports:
            - containerPort: 80
          env:
            - name: NGINX_ENV # 在Nginx中設定環境變數
              valueFrom:
                configMapKeyRef:
                  name: nginx-config # 設定ConfigMap的名稱
                  key: nginx-env # 需要取值的鍵      
  • 應用配置檔案檔案建立Deployment:
kubectl apply -f nginx-deployment.yaml
  • 建立成功後檢視Pod中的環境變數,發現NGINX_ENV變數已經被注入了;
kubectl exec deployments/nginx-deployment -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=nginx-deployment-66fcf997c-xxdsb
NGINX_ENV=test

儲存卷使用

通過儲存卷,我們可以把外部資料掛載到容器中去,供容器中的應用訪問,這樣就算容器崩潰了,資料依然可以存在。

  • 記得之前我們使用Docker部署Nginx的時候,將Nginx的html、logs、conf目錄從外部掛載到了容器中;
docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx  \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx:1.10
  • Minikube可以認為是一臺虛擬機器,我們可以用Minikube的ssh命令來訪問它;
minikube ssh
  • Minikube中預設有一個docker使用者,我們先重置下它的密碼;
sudo passwd docker
  • 在Minikube中建立mydata目錄;
midir /home/docker/mydata
  • 我們需要把Nginx的資料目錄複製到Minikube中去,才能實現目錄的掛載,注意docker使用者只能修改/home/docker目錄中的檔案,我們通過scp命令來複制檔案;
scp -r /home/macro/mydata/nginx [email protected]:/home/docker/mydata/nginx
  • 新增配置檔案nginx-volume-deployment.yaml用於建立Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-volume-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.10
          ports:
            - containerPort: 80
          volumeMounts:
            - mountPath: /usr/share/nginx/html
              name: html-volume
            - mountPath: /var/log/nginx
              name: logs-volume
            - mountPath: /etc/nginx
              name: conf-volume
      volumes:
        - name: html-volume
          hostPath:
            path: /home/docker/mydata/nginx/html
            type: Directory
        - name: logs-volume
          hostPath:
            path: /home/docker/mydata/nginx/logs
            type: Directory
        - name: conf-volume
          hostPath:
            path: /home/docker/mydata/nginx/conf
            type: Directory
  • 應用配置檔案建立Deployment;
kubectl apply -f nginx-volume-deployment.yaml
  • 新增配置檔案nginx-service.yaml用於建立Service;
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080
  • 應用配置檔案建立Service;
kubectl apply -f nginx-service.yaml
  • 檢視下Service服務訪問埠;
[[email protected] nginx]$ kubectl get services
NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes                ClusterIP   10.96.0.1       <none>        443/TCP        6d23h
kubernetes-nginx          NodePort    10.106.227.54   <none>        80:30158/TCP   5d22h
nginx-service             NodePort    10.103.72.111   <none>        80:30080/TCP   7s
  • 通過CURL命令可以訪問Nginx首頁資訊。
curl $(minikube ip):30080

閘道器路由

Ingress可以作為K8S的閘道器來使用,能提供服務路由和負載均衡等功能。

  • Minikube預設沒有啟用Ingress外掛,需要手動開啟;
minikube addons enable ingress
  • 開啟Ingress過程中遇到了一個坑,會在驗證的時候卡主,其實是Minikube內部無法下載Ingress映象導致的:
[[email protected] ~]$ minikube addons enable ingress
* Verifying ingress addon...
  • 解決該問題需要手動下載第三方映象,並標記為需要的映象,並重新啟用Ingress外掛;
# 查詢啟動有問題的Pod
kubectl get pods -n kube-system
# 檢視啟動失敗原因
kubectl describe ingress-nginx-controller-xxx -n kube-system
# 連線到Minikube
minikube ssh
# 原來需要下載的映象(已經無法下載)
docker pull us.gcr.io/k8s-artifacts-prod/ingress-nginx/controller:v0.40.2
# 下載第三方替代映象(直接去DockerHub官網搜尋即可)
docker pull pollyduan/ingress-nginx-controller:v0.40.2
# 修改映象名稱
docker tag pollyduan/ingress-nginx-controller:v0.40.2 us.gcr.io/k8s-artifacts-prod/ingress-nginx/controller:v0.40.2 
  • 重啟外掛後檢查下Ingress是否在執行;
kubectl get pods -n kube-system
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-krpgk        0/1     Completed   0          46h
ingress-nginx-admission-patch-wnxlk         0/1     Completed   3          46h
ingress-nginx-controller-558664778f-wwgws   1/1     Running     2          46h
  • 新增配置檔案nginx-ingress.yaml用於建立Ingress;
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - host: nginx-volume.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx-service
                port:
                  number: 80
  • 應用配置檔案建立Ingress;
kubectl apply -f nginx-ingress.yaml
  • 檢視所有Ingress,此時我們已經可以通過nginx-volume.com來訪問Pod中執行的Nginx服務了;
kubectl get ingress
NAME            CLASS    HOSTS              ADDRESS        PORTS   AGE
nginx-ingress   <none>   nginx-volume.com   192.168.49.2   80      6s
  • 需要修改下host檔案,注意切換到root賬號後修改:
# 切換到root使用者
su -
# 修改host檔案
vi /etc/hosts
# 新增如下記錄
192.168.49.2 nginx-volume.com
  • 最後通過CURL命令可以訪問Nginx首頁資訊。
curl nginx-volume.com

總結

通過K8S擴充套件和管理容器化應用確實十分方便,通過幾個命令我們就可以實現零停機更新,出了故障也不怕,一個命令實現回滾。但是大量的命令列操作總顯得枯燥無味,要是有個視覺化工具可以直接管理K8S就更好了。

推薦閱讀

程式設計師年薪百萬的飛馬計劃你聽說過嗎?

為什麼阿里巴巴的程式設計師成長速度這麼快,看完他們的內部資料我懂了

從事開發一年的程式設計師能拿到多少錢?

位元組跳動總結的設計模式 PDF 火了,完整版開放下載

刷Github時發現了一本阿里大神的演算法筆記!標星70.5K

程式設計師50W年薪的知識體系與成長路線。

關於【暴力遞迴演算法】你所不知道的思路

開闢鴻蒙,誰做系統,聊聊華為微核心

看完三件事❤️

如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:

點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。

關注公眾號 『 Java鬥帝 』,不定期分享原創知識。

同時可以期待後續文章ing