kubectl apply 和 kubectl create 之間的區別
1. 概述
Kubernetes 是容器化應用程式的編排工具。它使用kubectl
命令列與叢集互動。
在本教程中,我們將透過正在運行的叢集中的一些範例來了解kubectl create
和kubectl apply
命令之間的差異。
2. Kubernetes 設定
Kubernetes (K8s)需要建立叢集並對其架構有很好的理解。此外,我們應該有信心透過kubectl
指令使用 API。
2.1.集群設定
我們可以透過不同的方式設定 K8s 叢集。一個很好的學習經驗是Kubeadm
和連接同一網路上多個虛擬機器的本地 K8s 叢集。我們可能想嘗試使用Archlinux或任何其他 Linux 發行版。
儘管如此,我們可以使用輕量級的 K8s 發行版來快速啟動。這至少可以讓我們節省叢集配置設定的時間。
如果我們想要跳過叢集設定並使用常用指令,我們可以使用 K8s 遊樂場,例如Killercoda或Play with Kubernetes 。
2.2. kubectl
無論如何,我們都必須安裝kubectl
。它可以在命令列上運行,但嚴格來說它並不是 K8s 元件。它使用 K8s 叢集配置與 K8s API 進行通訊。
3. 聲明式與命令式
在討論create
和apply,
讓我們看看如何管理叢集中的物件。
3.1.對像管理
K8s 是關於管理叢集中的物件。我們可能會新增或更新執行 Web 應用程式或資料庫等的 pod。我們應用建立、讀取、替換和刪除等操作。
3.2.命令式命令和物件配置
命令式管理意味著使用動詞驅動的命令。例如,我們建立一個 Nginx 部署:
$ kubectl create deployment nginx --image nginx
同樣,我們可以將相同的概念擴展到設定檔:
$ kubectl create -f nginx.yaml
3.3.聲明性物件配置
使用聲明性命令,我們只需要一個設定檔或檔案清單。 K8s 管理與集群中已有內容的差異。在本例中我們使用apply
語法:
$ kubectl apply -f deployment.yaml
4. kubectl create
正如我們已經看到的, kubectl create
是一個命令式指令。我們可以創造許多資源,例如服務、秘密、入口等。
為了簡單起見,我們將透過 YAML 設定檔deployment.yaml
看到一個簡單的 Nginx 部署:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
minReadySeconds: 5
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
我們現在可以使用create
命令:
$ kubectl create -f deployment.yaml
K8s 通知我們資源創建:
deployment.apps/nginx-deployment created
我們可以使用kubectl get pods
指令仔細檢查 Nginx 容器是否正在運作:
NAME READY STATUS RESTARTS AGE
nginx-deployment-86dcfdf4c6-zhkw8 1/1 Running 0 88s
4.1.建立相同資源時出錯
例如,如果我們現在嘗試建立相同的部署,我們將收到錯誤:
Error from server (AlreadyExists): error when creating "deployment.yaml": deployments.apps "nginx-deployment" already exists
4.2.建立前修改對象
這是在創建物件之前修改物件的選項。假設我們想使用不同的 Nginx 版本:
$ kubectl create -f deployment.yaml -o yaml --dry-run=client | kubectl set image --local -f - 'nginx=nginx:1.25.2' -o yaml | kubectl create -f -
我們還可以輸出文件並在第二步中進行編輯:
$ kubectl create -f deployment.yaml -o yaml --dry-run=client > deployment_1.yaml && kubectl create --edit -f deployment_1.yaml
這將開啟預設文字編輯器,其中包含新部署的 YAML 檔案。
4.3.一次一個指令
現在我們的資源已經在叢集中運行了,我們可能想要跟進並對它們進行一些操作。
與我們在創建之前修改的方式類似,K8s 建議一次使用一個命令式命令與資源進行互動。
因此,假設我們希望將部署擴展到5
副本。我們可以使用scale
命令:
$ kubectl scale --replicas=5 deployment nginx-deployment
相反,我們應該建立另一個 YAML 文件,例如前一個文件中的deployment_scale.yaml
,並將其新增至部署規範:
...
spec:
replicas: 2
...
如果我們想更新,我們現在可以使用replace
命令:
$ kubectl replace -f deployment_scale.yml
同樣,我們可能想要使用delete
命令來刪除物件:
$ kubectl delete -f deployment.yml
4.4.命令選項
讓我們來看看一些create
選項:
-
dry-run
允許創建物件而無需發送或持久化到伺服器 - 建立前
edit
修改資源 -
selector
來標識我們要過濾的選擇器 -
save-config
添加有關物件最新版本的信息,使其可由apply
命令使用
5. kubectl apply
如果我們想要管理叢集中資源的生命週期, kubectl apply
指令為我們提供了更大的彈性。
5.1.將create
替換為apply
我們可以用 apply 取代create
指令apply:
$ kubectl apply -f deployment.yaml
部署也有效。那麼,這兩個命令有什麼差別呢?
5.2.應用相同資源沒有錯誤
使用具有相同配置的apply
命令會產生未更改的狀態:
deployment.apps/nginx-deployment unchanged
相反,使用不同的輸入,我們將獲得新的配置響應:
deployment.apps/nginx-deployment configured
5.3.物件不可知論
apply
指令適用於任何對象,因此它在對象定義中是聲明性的。我們知道 YAML 檔案中的物件kind
。它可以是服務、pod 等。因此,在kubectl
命令中,我們避免聲明資源的類型。
5.4.追蹤物件的歷史記錄
與apply
指令相關的是元資料定義中的kubectl.kubernetes.io/last-applied-configuration
欄位。我們可以從YAML檔案配置中看到:
$ kubectl apply view-last-applied -f deployment.yaml -o yaml
輸出對應於目前部署:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations: {}
name: nginx-deployment
namespace: default
spec:
minReadySeconds: 5
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
name: nginx
ports:
- containerPort: 80
5.5.每一次變更都有新的修訂
值得注意的是,我們可以使用get
命令查看最後應用的配置:
$ kubectl get deployments.apps nginx-deployment -o yaml
為了簡潔起見,我們在輸出中省略了last-applied-configuration
欄位:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
kubectl.kubernetes.io/last-applied-configuration: |
...
creationTimestamp: "2023-09-18T14:58:34Z"
generation: 1
name: nginx-deployment
namespace: default
resourceVersion: "154473"
uid: a154ad80-db02-4ec4-888d-0c56281c4816
...
假設我們現在將副本更新為5
。這將建立部署的新版本。例如,我們可以看到generation
和resourceVersion
的變化:
...
generation: 2
name: nginx-deployment
namespace: default
resourceVersion: "156401"
...
這使得 K8s 能夠更新活動物件的定義。它的工作原理是將當前版本與下一個版本進行比較。
5.6.從create
移動到apply
如果我們在create
指令中不使用save-config
選項,稍後可以繼續使用apply
指令。
K8s 將警告我們並設定最後應用的配置,並顯示以下訊息:
Warning: resource deployments/nginx-deployment is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply.
kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
5.7.命令選項
create
選項在這裡仍然有效。讓我們看看apply
命令的其他一些選項:
-
prune
刪除資源對象 -
grace-period
設定我們給予資源終止的時間
6. kubectl
中apply
和create
指令有何不同
我們已經看到kubectl create
作為命令式命令。此外,如果我們想要更改物件定義,我們需要使用另一個命令,例如kubectl replace
。它並不嚴格要求 YAML 模板。
相反, kubectl apply
聲明性指令與物件類型相符。 K8s 知道如何根據上次應用的配置進行更改。
但是,使用apply
命令, 合併不同版本之間的變更可能很困難,並且會導致意外結果。
值得注意的是,帶有–save-config
選項的create
指令的行為與apply
指令類似。
七、結論
在本文中,我們了解了kubectl
物件管理如何與kubectl create
和kubectl apply
配合使用。
apply
指令更加靈活,可以動態套用變更。儘管語法簡單,但create
指令是命令式的。
無論如何,我們需要確保不要混淆不同的策略。現在都是成熟的指揮了,關鍵是選擇一個方向。