Kubernetes:瞭解 Deployment

痴者工良發表於2021-11-30

本文為作者的 Kubernetes 系列電子書的一部分,電子書已經開源,歡迎關注,電子書瀏覽地址:

https://k8s.whuanle.cn【適合國內訪問】

https://ek8s.whuanle.cn 【gitbook】

Deployment 是 Kubernetes 提供的一種自我修復機制來解決機器故障維護的問題。前面提到了單獨部署 Pod,但是這種方式只適合臨時的 Pod,用於測試除錯。如果要用於生產,則需要 Deployment 等控制器管理部署 Pod,維護 Pod 的副本數量以及 Pod 監控和維護。

對於 Kubernetes 物件的部署,例如 Pod、Deployment、Service 等,有三種部署方式:

  • Using Generators (Run, Expose)
  • Using Imperative way (Create)
  • Using Declarative way (Apply)

在 2.1 章中,我們已經學習了 Run 和 apply 等,在本篇以及後面的章節中,我們會一步步深入學習這些部署方式。

本篇包含或需要掌握以下內容:

  • 建立 Deployment
  • 修改 Deployment
  • 檢視 Deployment 、Pod、Services、副本

在本篇文章中,我們將部署一個 Nginx 例項,並學會 部署以及管理 Deployment、Pod。

Deployment

當我們單獨使用 docker 部署應用時,為了應用掛了後能夠重啟,我們可以使用 --restart=always 引數,例如:

docker run -itd --restart=always -p 666:80 nginx:latest

但是這種方式只能單純重啟容器,並不具備從機器故障中恢復的能力,即當一臺伺服器掛了後,此伺服器上所有的容器全部掛掉。

Kubernetes Deployment 是一種 Pod 管理方式,它可以指揮 Kubernetes 如何建立和更新你部署的應用例項,建立 Deployment 後,Kubernetes master 會將應用程式排程到叢集中的各個節點上。Kubernetes Deployment 提供了一種與眾不同的應用程式管理方法。

Deployment 的建立,有兩種方法,一種是直接使用命令建立(kubectl create),一種是通過 YAML(kubectl apply),後面我們會介紹這兩種建立方法。

建立 Deployment

在 Kubernetes 中,Pod 是排程的最小單位,一個 Pod 中包含多個 容器,所以我們的各種操作都是在 Pod 之上。

我們來使用 deployment 部署一個 Pod,這個 Pod 包含一個 Nginx 容器。

kubectl create deployment nginx --image=nginx:latest

格式:

kubectl create deployment {deployment物件名稱} --images={映象名稱和標籤}

此時,nginx 容器會以 Pod 的方式部署到節點中,但是被部署到哪個節點是隨機的,如果你只有一個 worker 節點,則 Pod 必定在這個 Worker 節點上。當然,我們可以獲取到具體的排程資訊,從中檢視 Pod 被排程到哪個節點。

root@instance-1:~# kubectl get deployments -o wide
NAME    READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
nginx   1/1     1            1           52s   nginx        nginx:latest   app=nginx
root@instance-1:~# kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
nginx-55649fd747-s4824   1/1     Running   0          61s   192.168.56.4   instance-2              

可以看到, Pod 在 instance-2 中執行著。

Deployment 會為我們自動建立 Pod,Pod 由 {deployment名稱}-{隨機名稱} 組成。

[Info] 提示

還有一個地方也說一下,kubectl get xxx 時,帶不帶 s 都沒關係,例如 kubectl get nodes / kubectl get node 都是一樣的。

不過,一般從語義上,我們獲取全部物件時,可以使用 kubectl get nodes,獲取具體的物件時,可以使用 kubectl get node nginx。類似的,kubectl describe nodes 、kubectl describe node nginx。實際上加不加 s 都一樣。

kubectl apply/create

當我們建立一個 deployment 時,kubectl create 和 kubectl apply 效果是一樣的,但是 apply 還具有更新(update) 的功能。

kubectl apply 會在以前的配置、提供的輸入和資源的當前配置之間 找出三方差異,以確定如何修改資源,kubectl apply 命令將會把推送的版本與以前的版本進行比較,並應用你所做的更改, 但是不會自動覆蓋任何你沒有指定更改的屬性

另外還有 kubectl replace 、kubectl editkubectl replace 是破壞性更新/替換,容易導致問題;kubectl edit 可以更新 Deployment 等已存在的物件。

根據 Kubernetes 官方的文件說明,應始終使用 kubectl apply 或 kubectl create --save-config 建立資源

前面已經學習了 kubectl create,這裡學習一下 kubectl apply

通過 YAML 檔案部署 nginx:

kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml

很多開源軟體提供了 YAML 檔案,我們通過 YAML 檔案可以快速部署服務,如 Redis、Consul 等。

這裡再說一下建立 Deployment 的區別。

如果使用 create 建立,命令格式:

kubectl create deployment {deployment的名字} --image={映象名稱}

如果使用 apply 命令建立,YAML 中需要指定一些資訊,可定製性很高。

kind: Deployment
... ...
medatada:
    name:nginx
... ...
    spec:
      containers:
      - image: nginx:latest

然後執行 kubectl apply -f xxx.yaml 檔案。

一個是 kubectl create deployment ;另一個是 kubectl apply -f,在 yaml 中指定 kind: Deployment

如果我們只需要快速建立,使用命令形式就行;如何生產生產,還是得使用 YAML 檔案,並於留存記錄。

要刪除一個物件,可以使用 kubectl delete -f {名稱}.yaml,如刪除 calico。

kubectl delete -f calico.yaml

檢查 YAML

有時我們不知道我們的建立命令或 yaml 是否正確,可以使用 --dry-run=client ,--dry-run=client 引數來表示當前內容只是預覽而不真正提交。

kubectl create deployment testnginx --image=nginx:latest --dry-run=client

在一些 k8s 認證中,我們沒時間一點點寫 yaml ,但是又需要定製,此時可以使用 --dry-run=client -o yaml ,既可以不生效 Deployment,又可以匯出 yaml 檔案。

[Info] 提示

-o wide 可以檢視物件更多的欄位資訊;kubectl describe 可以檢視物件的全部詳細資訊;-o yaml 或 -o json 可以檢視物件的定義/描述檔案。

--dry-run 取值必須為none、server或client。如果客戶端策略,只列印將要傳送的物件,而不傳送它。如果是伺服器策略,提交伺服器端請求而不持久化資源。

命令示例如下:

kubectl create deployment testnginx --image=nginx:latest --dry-run=client -o yaml
# -o json 可以輸出 json 格式

toyaml

使用這樣的方法,可以快速獲得需要的 YAML 模板,然後複製到 YAML 檔案,根據需要改動、定製。除了 deployment,其它 kubernetes 物件也可以使用這種方法。

檢視 Deployment

我們以 Deployment 的方式部署 Pod ,就會建立一個 Deployment 物件,獲得 deployment 列表:

kubectl get deployments
kubectl get deployments -o wide
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   1/1     1            1           2m24s

NAME    READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES         SELECTOR
nginx   1/1     1            1           2m42s   nginx        nginx:latest   app=nginx

在 kubectl get ... 後面加上 -o wide 可以獲得更多的標籤資訊。

使用 kubectl get events 可以獲得叢集中最近發生的事件,如建立 Deployment 到部署容器過程的詳細事件記錄。

Successfully assigned default/nginx-55649fd747-wdrjj to instance-2
Pulling image "nginx:latest"
Successfully pulled image "nginx:latest" in 8.917597859s
Created container nginx
Started container nginx
Created pod: nginx-55649fd747-wdrjj
Scaled up replica set nginx-55649fd747 to 1

使用 kubectl describe deployment nginx 可以獲得更加詳細的資訊,是各種資訊的集合。

describe命令

檢視 Pod

我們沒有直接建立 Pod,而是通過 Deployment 建立,接下來我們需要了解如何檢視 Pod 。

kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-55649fd747-msw8g   1/1     Running   0          4h16m

可以看到一個 Pod 名為 nginx- ,因為我們是利用 Deployment 部署 Pod 的,沒有指定這個 Pod 的名稱,所以預設 Pod 名稱以 Deployment 名稱為字首。

我們檢視這個 pods 被部署到了哪個節點上:

kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP              NODE         
nginx-55649fd747-msw8g   1/1     Running   0          4h19m   192.168.56.57   instance-2

可以看到,這個 Pod 在 instances-2 這個節點上,同時這個 Pod 也有一個 IP,Kubernetes 會為每個 Pod 分配一個唯一的 IP,這個 IP 可以在節點上訪問,其它 Pod 也可以通過 IP 訪問此 Pod。

由於這個 Pod 裡面的容器是 Nginx(80埠),所以我們可以訪問這個 IP 可以開啟 Nginx 頁面。

root@instance-1:~# curl 192.168.56.57

相關文章