本文為作者的 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 edit
。kubectl 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 格式
使用這樣的方法,可以快速獲得需要的 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
可以獲得更加詳細的信息,是各種信息的集合。
查看 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