Kubernetes:全面了解 Deployment
本文為作者的 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 <none> <none>可以看到, 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 wideNAME READY UP-TO-DATE AVAILABLE AGE nginx 1/1 1 1 2m24sNAME 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 podsNAME READY STATUS RESTARTS AGE nginx-55649fd747-msw8g 1/1 Running 0 4h16m可以看到一個 Pod 名為?nginx-?,因為我們是利用 Deployment 部署 Pod 的,沒有指定這個 Pod 的名稱,所以默認 Pod 名稱以 Deployment 名稱為前綴。
我們查看這個 pods 被部署到了哪個節點上:
kubectl get pods -o wideNAME 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 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style>body { ... ...對于沒有指定的 Deployment、Pod、Service 等對象,會默認分配到 default 命名空間中,我們在執行kubectl get {}?時,會獲取 default 命名空間中的對象, 后面加上?--all-namespaces?可以獲得所有命名空間中的對象,使用?--namespace=?可以指定獲取某個命名空間中的對象。
kubectl get pods --all-namespaces # kubectl get pods --namespace=defaultNAMESPACE NAME READY STATUS RESTARTS AGE default nginx-55649fd747-msw8g 1/1 Running 0 4h28m kube-system etcd-instance-1 1/1 Running 1 13d kube-system kube-apiserver-instance-1 1/1 Running 1 13d kube-system kube-controller-manager-instance-1 1/1 Running 1 13d kube-system kube-proxy-bhj76 1/1 Running 1 13d kube-system kube-proxy-pm597 1/1 Running 0 13d kube-system kube-scheduler-instance-1 1/1 Running 1 13d kubernetes-dashboard dashboard-metrics-scraper-856586f554-4nd9v 1/1 Running 1 13d kubernetes-dashboard kubernetes-dashboard-78c79f97b4-288js 1/1 Running 1 13d在 worker 節點上執行?docker ps,可以看到 Nginx 容器:
root@instance-2:~# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fe7433f906a0 nginx "/docker-entrypoint.…" 7 seconds ago Up 6 seconds k8s_nginx_nginx-55649fd747-wdrjj_default_ea41dcc4-94fe-47f9-a804-5b5b1df703e9_0實時修改
使用?kubectl edit?可以實時修改一個對象,這里我們使用前面已經部署好的 Nginx 這個 Deployment,因為創建的 Pod 名稱有點長,我們希望直接改成 nginx。
修改 deployment:
kubectl edit pod nginx-55649fd747-msw8g在 metadata 字段中,找到?name: nginx-55649fd747-msw8g?,修改為合適的名稱。
修改完畢后,會提示:
A copy of your changes has been stored to "/tmp/kubectl-edit-w11bx.yaml" error: At least one of apiVersion, kind and name was changed出于某些原因,直接修改 name 字段是不行的,還需要修改其它地方。
這里讀者了解,可以通過?kubectl edit?實時直接修改對象即可。后面還會介紹另一種修改方法。
導出 yaml
我們可以從已經創建的 Deployment 、Pod、Service 等對象導出 yaml 文件,使用?-o yaml?即可導出(-o json?導出json)。
kubectl get deployment nginx -o yaml # 保存到文件 # kubectl get deployment nginx -o yaml > mynginx.yaml然后終端會打印:
apiVersion: apps/v1 kind: Deployment metadata:annotations:deployment.kubernetes.io/revision: "1"creationTimestamp: "2021-04-21T00:37:13Z"generation: 1labels:app: nginxname: nginxnamespace: default ... ...雖然我們創建對象時的命令很簡單,但是生成的 YAML 很復雜。
我們可以嘗試把 yaml 導出到 mynginx.yaml 文件中,然后我們刪除這個 Deployment。
kubectl get deployment nginx -o yaml > mynginx.yamlkubectl delete deployment nginx然后利用導出的 mynginx.yaml 再創建一個 Deployment。
kubectl apply -f mynginx.yaml多個 容器
一個 Pod 中,是可以包含多個容器的,我們可以使用命令或 YAML 形式創建包含多個容器的 Pod 服務。示例如下:
root@master:~# kubectl create deployment testnginx --image=nginx:latest --image=busybox:latest --dry-run=client -o yaml apiVersion: apps/v1 kind: Deployment metadata:creationTimestamp: nulllabels:app: testnginxname: testnginx spec:replicas: 1selector:matchLabels:app: testnginxstrategy: {}template:metadata:creationTimestamp: nulllabels:app: testnginxspec:containers:- image: nginx:latestname: nginxresources: {}- image: busybox:latestname: busyboxresources: {} status: {}總結
本小章中不只是講解 Deployment,還包含了很多日常管理對象的命令,讀者可多做練習,加深記憶。
總結
以上是生活随笔為你收集整理的Kubernetes:全面了解 Deployment的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何判断一个程序是 32bit 还是 6
- 下一篇: WPF 实现3D翻转倒计时控件~