八、Kubernetes 入門實踐

本文是《Docker必知必會系列》第八篇,原文發佈於個人博客:悟塵紀

上一篇:Docker必知必會系列(七):Docker Compose 入門實踐

Kubernetes 介紹

Kubernetes (K8s) 是一個可移植的、可擴展的開源平臺,用於管理容器化的工作負載和服務。是目前最主流的容器化管理平臺,獲得各大主流雲服務廠商支持。

Kubernetes 基於 Google 在大規模運行生產經驗技術基礎上,結合社區中最好的想法和實踐構建的開源平臺。

爲什麼需要 Kubernetes

在生產環境中,您需要管理運行應用程序的容器,並確保不會停機。例如,如果一個容器發生故障,則需要啓動另一個容器。如果有個系統工具來處理這些需求,會不會更容易?這就是 Kubernetes!

Kubernetes 爲您提供了一個可彈性運行分佈式系統的框架。滿足您的擴展、故障轉移、部署模式等要求。

Kubernetes 爲您提供:

  • 服務發現和負載均衡
    Kubernetes 可以使用 DNS 名稱或自己的 IP 地址公開容器,並提供負載均衡來分配網絡流量。

  • 存儲編排
    Kubernetes 允許您自動掛載您選擇的存儲系統,例如本地存儲、公共雲提供商等。

  • 自動部署和回滾
    您可以使用 Kubernetes 描述已部署容器的所需狀態,它可以以受控的速率將實際狀態更改爲所需狀態。例如,Kubernetes 可以自動化爲您的部署創建新容器,刪除現有容器並將它們的所有資源用於新容器。

  • 自動二進制打包
    Kubernetes 允許您指定每個容器所需 CPU 和內存(RAM)。當容器指定了資源請求時,Kubernetes 可以做出更好的決策來管理容器的資源。

  • 自我修復
    Kubernetes 重新啓動失敗的容器、替換容器、殺死不響應用戶定義的運行狀況檢查的容器,並且在準備好服務之前不將其通告給客戶端。

  • 密鑰與配置管理
    Kubernetes 允許您存儲和管理敏感信息,例如密碼、OAuth 令牌和 ssh 密鑰。您可以在不重建容器鏡像的情況下部署和更新密鑰和應用程序配置,也無需在堆棧配置中暴露密鑰。

Kubernetes 不是傳統的、包羅萬象的 PaaS(平臺即服務)系統。Kubernetes 提供了構建開發人員平臺的基礎,但是在重要的地方保留了用戶的選擇和靈活性。很多雲服務商基於K8s來構建自己的PaaS平臺。

部署 Kubernetes

您可以在本地機器、雲、本地數據中心上部署 Kubernetes 集羣,或選擇一個託管的 Kubernetes 集羣。還可以跨各種雲提供商或裸機環境創建自定義解決方案。

爲了學習 Kubernetes,建議使用基於 Docker 的解決方案:Docker 是 Kubernetes 社區支持或生態系統中用來在本地計算機上設置 Kubernetes 集羣的一種工具。如果是爲了生產環境,您應該認真評估適當的解決方案,具體請參照官方文檔

Docker Desktop 啓用 Kubernetes

在 Docker Desktop 的 Preferences 頁面,點擊 Kubernetes,選擇 Enable Kubernetes,待左下角的 Kubernetes 狀態變爲 running時,Kubernetes 即已啓動成功。

在 Docker Desktop 中啓用 Kubernetes

在控制檯執行 kubectl version,能夠正常輸出信息,則說明Kubernetes 已經成功啓動。

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"16+", GitVersion:"v1.16.6-beta.0", GitCommit:"e7f962ba86f4ce7033828210ca3556393c377bcc", GitTreeState:"clean", BuildDate:"2020-01-15T08:26:26Z", GoVersion:"go1.13.5", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"16+", GitVersion:"v1.16.6-beta.0", GitCommit:"e7f962ba86f4ce7033828210ca3556393c377bcc", GitTreeState:"clean", BuildDate:"2020-01-15T08:18:29Z", GoVersion:"go1.13.5", Compiler:"gc", Platform:"linux/amd64"}

安裝 Dashboard

Dashboard 是官方提供的基於網頁的 Kubernetes 用戶管理界面。您可以使用 Dashboard 將容器應用部署到 Kubernetes 集羣中,也可以對容器應用排錯,還能管理集羣資源。您可以使用 Dashboard 獲取運行在集羣中的應用的概覽信息,也可以創建或者修改 Kubernetes 資源(如 Deployment,Job,DaemonSet 等等)。例如,您可以對 Deployment 實現彈性伸縮、發起滾動升級、重啓 Pod 或者使用嚮導創建新的應用。

默認情況下不會部署 Dashboard。可以通過以下命令部署:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml

在要訪問 Dashboard 的機器上執行 kubectl proxy 命令,然後就可以通過 http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/ 地址訪問 Dashboard了。

當前,Dashboard 僅支持使用 Bearer 令牌登錄。 接下來,我們將創建一個名爲 admin-user 的服務賬號,併爲其創建 ClusterRoleBinding。

將以下內容複製到 dashboard-adminuser.yaml 文件中。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard

然後執行:

kubectl apply -f dashboard-adminuser.yaml

找到可以用來登錄的令牌:

$ kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
Name:         admin-user-token-8mgwp
Namespace:    kubernetes-dashboard
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: admin-user
              kubernetes.io/service-account.uid: c32b99ea-a002-4e00-afdf-58ce40fbe5eb

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  20 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IkJPNFJmTFJ1ajBKYm4xMGpvV01vYnRRSDdzRnFmd1ZsbUpPQ0lvdFNJWFkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3......povxntPXVTJomVTN7mJ-6vBm8m-kCUF6nxA14c8s5Kis22XPGyPgiUmXNAagXJPJH3cFVO0exs5JVzdj3gtvRXQ

複製 token 並將其粘貼到登錄屏幕上的 Token 字段中。點擊登錄按鈕,就可以以管理員身份登錄了。

登錄 Kubernetes dashboard

Kubernetes 入門實踐

一旦運行了 Kubernetes 集羣,就可以在其上部署容器化應用程序。 爲此,您需要創建 Kubernetes Deployment 配置。Deployment 指揮 Kubernetes 如何創建和更新應用程序的實例。創建 Deployment 後,Kubernetes master 將應用程序實例調度到集羣中的各個節點上。

創建應用程序實例後,Kubernetes Deployment 控制器會持續監視這些實例。 如果託管實例的節點關閉或被刪除,則 Deployment 控制器會將該實例替換爲羣集中另一個節點上的實例。 這提供了一種自我修復機制來解決機器故障維護問題。

環境檢查

通過運行 kubectl version 命令,檢查 kubectl 是否已配置爲與您的集羣通信。運行 kubectl get nodes 命令,查看集羣中的節點及pods。

$ kubectl get nodes
NAME             STATUS   ROLES    AGE    VERSION
docker-desktop   Ready    master   112m   v1.16.6-beta.0

$ kubectl get pods
No resources found in default namespace.

在這裏,我們看到可用的節點(本例中爲1)。 Kubernetes 將根據 Node 可用資源選擇將我們的應用程序部署到何處。

基於kubectl部署第一個應用

讓我們使用 kubectl create deploy 命令在 Kubernetes 上部署我們的第一個應用程序。

創建一個名爲 k8s-nginx 的 deployment(需要提供部署名稱和應用程序鏡像位置):

$ kubectl create deployment --image nginx k8s-nginx
deployment.apps/k8s-nginx created

查看正在運行的 pods,會看到只有一個 pods 正在運行:

$ kubectl get pods
NAME                         READY   STATUS              RESTARTS   AGE
k8s-nginx-5c86f54778-92824   0/1     ContainerCreating   0          11s

查看創建的 deployment:

$ kubectl get deployment
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
k8s-nginx   0/1     1            0           24s

擴展部署,讓 2 個 nginx pods 同時運行:

$ kubectl scale deployment --replicas 2 k8s-nginx
deployment.apps/k8s-nginx scaled

列出 pods ,會看到已經變成 2 個 pods 正在運行:

$ kubectl get pods
NAME                         READY   STATUS    RESTARTS   AGE
k8s-nginx-5c86f54778-92824   0/1     Running   0          67s
k8s-nginx-5c86f54778-j7dch   0/1     Running   0          6s

將 pods 暴露到互聯網上:

kubectl expose deployment k8s-nginx --port=8086 --type=LoadBalancer
service/k8s-nginx exposed

查看已經創建的服務,獲取服務地址:

$ kubectl get services
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
k8s-nginx    LoadBalancer   10.100.197.113   <none>        8086/TCP   74s

要清理這兩個自動複製的容器,需要刪除 deployment:

$ kubectl delete deployment k8s-nginx
deployment.apps "k8s-nginx" deleted
# 再次列出 pods 會發現容器已經被清理。
$ kubectl get pods
No resources found in default namespace.

基於 Deployments 管理應用

可以通過創建一個Kubernetes Deployment 對象來運行一個應用,在YAML文件中描述Deployment。

首先,創建 deployment 描述文件 k8s-nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8s-nginx-deployment    # 創建名爲 k8s-nginx-deployment 的 Deployment
  labels:
    app: k8s-nginx
spec:
  replicas: 3	   				# 創建 3 個 Pods
  selector:						# 定義 Deployment 如何查找要管理的 Pods
    matchLabels:
      app: k8s-nginx
  template:
    metadata:
      labels:					# 將 Pod 標記爲 k8s-nginx
        app: k8s-nginx
    spec:
      containers:
      - name: k8s-nginx			# 指定創建的容器名字爲 k8s-nginx
        image: nginx			# 指定運行 Docker Hub 中 nginx 最新版本鏡像
        ports:					# 暴露端口
        - containerPort: 8189

通過 kubectl apply 命令創建 Deployment:

$ kubectl apply -f k8s-nginx-deployment.yaml
deployment.apps/k8s-nginx-deployment created

運行 kubectl get deployments 以檢查 Deployment 是否已創建:

$ kubectl get deployments
NAME                   READY   UP-TO-DATE   AVAILABLE   AGE
k8s-nginx-deployment   3/3     3            3           47s

幾秒鐘後,Deployment 已創建所有三個副本,並且所有副本都是最新的(它們包含最新的 Pod 模板)並且可用。

更新 Deployment

讓我們更新 nginx Pods,以使用 nginx:1.9.1 鏡像 ,而不是最新版本 。

$ kubectl --record deployment.apps/k8s-nginx-deployment set image deployment.v1.apps/k8s-nginx-deployment k8s-nginx=nginx:1.9.1
deployment.apps/k8s-nginx-deployment image updated
deployment.apps/k8s-nginx-deployment image updated

查看狀態更新:

$ kubectl rollout status deployment.v1.apps/k8s-nginx-deployment
Waiting for deployment "k8s-nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "k8s-nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "k8s-nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "k8s-nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "k8s-nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "k8s-nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "k8s-nginx-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "k8s-nginx-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "k8s-nginx-deployment" successfully rolled out

更新成功後,可以通過運行 kubectl get deployments來查看 Deployment 。

$ kubectl get deployments
NAME                   READY   UP-TO-DATE   AVAILABLE   AGE
k8s-nginx-deployment   3/3     3            3           14m

運行 get pods 現在應僅顯示新的 Pods:

$ kubectl get pods
NAME                                    READY   STATUS    RESTARTS   AGE
k8s-nginx-deployment-785b758787-jsbtl   1/1     Running   0          2m31s
k8s-nginx-deployment-785b758787-xdsl4   1/1     Running   0          4m12s
k8s-nginx-deployment-785b758787-zxd7b   1/1     Running   0          2m28s

下次要更新這些 Pods 時,只需再次更新 Deployment Pod 模板。

Deployment 可確保在更新時僅關閉一定數量的 Pods。默認情況下,它確保至少 75%所需 Pods 運行(25%最大不可用)。Deployment 還確保僅創建一定數量的 Pods 高於期望的 Pods 數。默認情況下,它可確保最多增加 25% 期望 Pods 數(25%最大增量)。

如果仔細查看上述 Deployment ,將看到它首先創建了一個新的 Pod,然後刪除了一些舊的 Pods,並創建了新的 Pods。它不會殺死老 Pods,直到有足夠的數量新的 Pods 已經出現,並沒有創造新的 Pods,直到足夠數量的舊 Pods 被殺死。它確保至少 2 個 Pods 可用,並且總共最多 4 個 Pods 可用。

獲取 Deployment 的更多信息

$ kubectl describe deployments
kubectl describe deployments
Name:                   k8s-nginx-deployment
......
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  16m    deployment-controller  Scaled up replica set k8s-nginx-deployment-99f6477fd to 3
  Normal  ScalingReplicaSet  6m39s  deployment-controller  Scaled up replica set k8s-nginx-deployment-785b758787 to 1
  Normal  ScalingReplicaSet  4m57s  deployment-controller  Scaled down replica set k8s-nginx-deployment-99f6477fd to 2
  Normal  ScalingReplicaSet  4m57s  deployment-controller  Scaled up replica set k8s-nginx-deployment-785b758787 to 2
  Normal  ScalingReplicaSet  4m54s  deployment-controller  Scaled down replica set k8s-nginx-deployment-99f6477fd to 1
  Normal  ScalingReplicaSet  4m54s  deployment-controller  Scaled up replica set k8s-nginx-deployment-785b758787 to 3
  Normal  ScalingReplicaSet  4m49s  deployment-controller  Scaled down replica set k8s-nginx-deployment-99f6477fd to 0

可以看到,當第一次創建 Deployment 時,它創建了一個 ReplicaSet (nginx-deployment-99f6477fd)並將其直接擴展至 3 個副本。更新 Deployment 時,它創建了一個新的 ReplicaSet (nginx-deployment-785b758787),並將其擴展爲 1,然後將舊 ReplicaSet 縮小到 2,以便至少有 2 個 Pod 可用,並且最多創建 4 個 Pod。然後,它繼續向上和向下擴展新的和舊的 ReplicaSet ,具有相同的滾動更新策略。最後,將有 3 個可用的副本在新的 ReplicaSet 中,舊 ReplicaSet 將縮小到 0。

有時,可能需要回滾 Deployment ;例如,當 Deployment 不穩定時,例如循環崩潰。默認情況下,所有 Deployment 歷史記錄都保留在系統中,以便可以隨時回滾(可以通過修改修改歷史記錄限制來更改該限制)。

也可以通過設置自動縮放器,基於現有 Pods 的 CPU 利用率設置要運行 Pods的最小和最大值。

還可以在觸發一個或多個更新之前暫停 Deployment ,然後繼續它。這允許在暫停和恢復之間應用多個修補程序,而不會觸發不必要的 Deployment 。

關於 Deployment 的更多信息,請查閱官方文檔:Deployments

參考

相關文章

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