Kubernetes 管理資源

2022-05-26 15:28 更新

管理資源

你已經(jīng)部署了應(yīng)用并通過服務(wù)暴露它。然后呢? Kubernetes 提供了一些工具來幫助管理你的應(yīng)用部署,包括擴(kuò)縮容和更新。 我們將更深入討論的特性包括 配置文件和 標(biāo)簽。

組織資源配置 

許多應(yīng)用需要?jiǎng)?chuàng)建多個(gè)資源,例如 Deployment 和 Service。 可以通過將多個(gè)資源組合在同一個(gè)文件中(在 YAML 中以 ?---? 分隔) 來簡化對(duì)它們的管理。例如:

apiVersion: v1
kind: Service
metadata:
  name: my-nginx-svc
  labels:
    app: nginx
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

可以用創(chuàng)建單個(gè)資源相同的方式來創(chuàng)建多個(gè)資源:

kubectl apply -f https://k8s.io/examples/application/nginx-app.yaml
service/my-nginx-svc created
deployment.apps/my-nginx created

資源將按照它們?cè)谖募械捻樞騽?chuàng)建。 因此,最好先指定服務(wù),這樣在控制器(例如 Deployment)創(chuàng)建 Pod 時(shí)能夠 確保調(diào)度器可以將與服務(wù)關(guān)聯(lián)的多個(gè) Pod 分散到不同節(jié)點(diǎn)。

?kubectl create? 也接受多個(gè) ?-f? 參數(shù):

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

還可以指定目錄路徑,而不用添加多個(gè)單獨(dú)的文件:

kubectl apply -f https://k8s.io/examples/application/nginx/

?kubectl ?將讀取任何后綴為 ?.yaml?、?.yml? 或者 ?.json? 的文件。

建議的做法是,將同一個(gè)微服務(wù)或同一應(yīng)用層相關(guān)的資源放到同一個(gè)文件中, 將同一個(gè)應(yīng)用相關(guān)的所有文件按組存放到同一個(gè)目錄中。 如果應(yīng)用的各層使用 DNS 相互綁定,那么你可以將堆棧的所有組件一起部署。

還可以使用 URL 作為配置源,便于直接使用已經(jīng)提交到 Github 上的配置文件進(jìn)行部署:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/zh/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx created

kubectl 中的批量操作

資源創(chuàng)建并不是 ?kubectl ?可以批量執(zhí)行的唯一操作。 ?kubectl ?還可以從配置文件中提取資源名,以便執(zhí)行其他操作, 特別是刪除你之前創(chuàng)建的資源:

kubectl delete -f https://k8s.io/examples/application/nginx-app.yaml
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted

在僅有兩種資源的情況下,可以使用"資源類型/資源名"的語法在命令行中 同時(shí)指定這兩個(gè)資源:

kubectl delete deployments/my-nginx services/my-nginx-svc

對(duì)于資源數(shù)目較大的情況,你會(huì)發(fā)現(xiàn)使用 ?-l? 或 ?--selector? 指定篩選器(標(biāo)簽查詢)能很容易根據(jù)標(biāo)簽篩選資源:

kubectl delete deployment,services -l app=nginx
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted

由于 ?kubectl ?用來輸出資源名稱的語法與其所接受的資源名稱語法相同, 你可以使用 ?$()? 或 ?xargs ?進(jìn)行鏈?zhǔn)讲僮鳎?

kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service)
kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service | xargs -i kubectl get {}
NAME           TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)      AGE
my-nginx-svc   LoadBalancer   10.0.0.208   <pending>     80/TCP       0s

上面的命令中,我們首先使用 ?examples/application/nginx/? 下的配置文件創(chuàng)建資源, 并使用 ?-o name? 的輸出格式(以"資源/名稱"的形式打印每個(gè)資源)打印所創(chuàng)建的資源。 然后,我們通過 ?grep ?來過濾 "service",最后再打印 ?kubectl get? 的內(nèi)容。

如果你碰巧在某個(gè)路徑下的多個(gè)子路徑中組織資源,那么也可以遞歸地在所有子路徑上 執(zhí)行操作,方法是在 ?--filename,-f? 后面指定 ?--recursive? 或者 ?-R?。

例如,假設(shè)有一個(gè)目錄路徑為 ?project/k8s/development?,它保存開發(fā)環(huán)境所需的 所有清單,并按資源類型組織:

project/k8s/development
├── configmap
│   └── my-configmap.yaml
├── deployment
│   └── my-deployment.yaml
└── pvc
    └── my-pvc.yaml

默認(rèn)情況下,對(duì) ?project/k8s/development? 執(zhí)行的批量操作將停止在目錄的第一級(jí), 而不是處理所有子目錄。 如果我們?cè)噲D使用以下命令在此目錄中創(chuàng)建資源,則會(huì)遇到一個(gè)錯(cuò)誤:

kubectl apply -f project/k8s/development
error: you must provide one or more resources by argument or filename (.json|.yaml|.yml|stdin)

正確的做法是,在 ?--filename,-f? 后面標(biāo)明 ?--recursive? 或者 ?-R? 之后:

kubectl apply -f project/k8s/development --recursive
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created

?--recursive? 可以用于接受 ?--filename,-f? 參數(shù)的任何操作,例如: ?kubectl {create,get,delete,describe,rollout}? 等。

有多個(gè) ?-f? 參數(shù)出現(xiàn)的時(shí)候,?--recursive? 參數(shù)也能正常工作:

kubectl apply -f project/k8s/namespaces -f project/k8s/development --recursive
namespace/development created
namespace/staging created
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created

有效地使用標(biāo)簽

到目前為止我們使用的示例中的資源最多使用了一個(gè)標(biāo)簽。 在許多情況下,應(yīng)使用多個(gè)標(biāo)簽來區(qū)分集合。

例如,不同的應(yīng)用可能會(huì)為 ?app ?標(biāo)簽設(shè)置不同的值。 但是,類似 guestbook 示例 這樣的多層應(yīng)用,還需要區(qū)分每一層。前端可以帶以下標(biāo)簽:

     labels:
        app: guestbook
        tier: frontend

Redis 的主節(jié)點(diǎn)和從節(jié)點(diǎn)會(huì)有不同的 ?tier ?標(biāo)簽,甚至還有一個(gè)額外的 ?role ?標(biāo)簽:

     labels:
        app: guestbook
        tier: backend
        role: master

以及

     labels:
        app: guestbook
        tier: backend
        role: slave

標(biāo)簽允許我們按照標(biāo)簽指定的任何維度對(duì)我們的資源進(jìn)行切片和切塊:

kubectl apply -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml
kubectl get pods -Lapp -Ltier -Lrole
NAME                           READY     STATUS    RESTARTS   AGE       APP         TIER       ROLE
guestbook-fe-4nlpb             1/1       Running   0          1m        guestbook   frontend   <none>
guestbook-fe-ght6d             1/1       Running   0          1m        guestbook   frontend   <none>
guestbook-fe-jpy62             1/1       Running   0          1m        guestbook   frontend   <none>
guestbook-redis-master-5pg3b   1/1       Running   0          1m        guestbook   backend    master
guestbook-redis-slave-2q2yf    1/1       Running   0          1m        guestbook   backend    slave
guestbook-redis-slave-qgazl    1/1       Running   0          1m        guestbook   backend    slave
my-nginx-divi2                 1/1       Running   0          29m       nginx       <none>     <none>
my-nginx-o0ef1                 1/1       Running   0          29m       nginx       <none>     <none>
kubectl get pods -lapp=guestbook,role=slave
NAME                          READY     STATUS    RESTARTS   AGE
guestbook-redis-slave-2q2yf   1/1       Running   0          3m
guestbook-redis-slave-qgazl   1/1       Running   0          3m

金絲雀部署(Canary Deployments) 

另一個(gè)需要多標(biāo)簽的場景是用來區(qū)分同一組件的不同版本或者不同配置的多個(gè)部署。 常見的做法是部署一個(gè)使用金絲雀發(fā)布來部署新應(yīng)用版本 (在 Pod 模板中通過鏡像標(biāo)簽指定),保持新舊版本應(yīng)用同時(shí)運(yùn)行。 這樣,新版本在完全發(fā)布之前也可以接收實(shí)時(shí)的生產(chǎn)流量。

例如,你可以使用 ?track ?標(biāo)簽來區(qū)分不同的版本。

主要穩(wěn)定的發(fā)行版將有一個(gè) ?track ?標(biāo)簽,其值為 ?stable?:

     name: frontend
     replicas: 3
     ...
     labels:
        app: guestbook
        tier: frontend
        track: stable
     ...
     image: gb-frontend:v3

然后,你可以創(chuàng)建 guestbook 前端的新版本,讓這些版本的 ?track ?標(biāo)簽帶有不同的值 (即 ?canary?),以便兩組 Pod 不會(huì)重疊:

     name: frontend-canary
     replicas: 1
     ...
     labels:
        app: guestbook
        tier: frontend
        track: canary
     ...
     image: gb-frontend:v4

前端服務(wù)通過選擇標(biāo)簽的公共子集(即忽略 ?track ?標(biāo)簽)來覆蓋兩組副本, 以便流量可以轉(zhuǎn)發(fā)到兩個(gè)應(yīng)用:

  selector:
     app: guestbook
     tier: frontend

你可以調(diào)整 ?stable ?和 ?canary ?版本的副本數(shù)量,以確定每個(gè)版本將接收 實(shí)時(shí)生產(chǎn)流量的比例(在本例中為 3:1)。 一旦有信心,你就可以將新版本應(yīng)用的 ?track ?標(biāo)簽的值從 ?canary ?替換為 ?stable?,并且將老版本應(yīng)用刪除。

想要了解更具體的示例,請(qǐng)查看 Ghost 部署教程。

更新標(biāo)簽 

有時(shí),現(xiàn)有的 pod 和其它資源需要在創(chuàng)建新資源之前重新標(biāo)記。 這可以用 ?kubectl label? 完成。 例如,如果想要將所有 nginx pod 標(biāo)記為前端層,運(yùn)行:

kubectl label pods -l app=nginx tier=fe
pod/my-nginx-2035384211-j5fhi labeled
pod/my-nginx-2035384211-u2c7e labeled
pod/my-nginx-2035384211-u3t6x labeled

首先用標(biāo)簽 "app=nginx" 過濾所有的 Pod,然后用 "tier=fe" 標(biāo)記它們。 想要查看你剛才標(biāo)記的 Pod,請(qǐng)運(yùn)行:

kubectl get pods -l app=nginx -L tier
NAME                        READY     STATUS    RESTARTS   AGE       TIER
my-nginx-2035384211-j5fhi   1/1       Running   0          23m       fe
my-nginx-2035384211-u2c7e   1/1       Running   0          23m       fe
my-nginx-2035384211-u3t6x   1/1       Running   0          23m       fe

這將輸出所有 "app=nginx" 的 Pod,并有一個(gè)額外的描述 Pod 的 tier 的標(biāo)簽列 (用參數(shù) ?-L? 或者 ?--label-columns? 標(biāo)明)。

更新注解 

有時(shí),你可能希望將注解附加到資源中。注解是 API 客戶端(如工具、庫等) 用于檢索的任意非標(biāo)識(shí)元數(shù)據(jù)。這可以通過 ?kubectl annotate? 來完成。例如:

kubectl annotate pods my-nginx-v4-9gw19 description='my frontend running nginx'
kubectl get pods my-nginx-v4-9gw19 -o yaml
apiVersion: v1
kind: pod
metadata:
  annotations:
    description: my frontend running nginx
...

擴(kuò)縮你的應(yīng)用

當(dāng)應(yīng)用上的負(fù)載增長或收縮時(shí),使用 ?kubectl ?能夠?qū)崿F(xiàn)應(yīng)用規(guī)模的擴(kuò)縮。 例如,要將 nginx 副本的數(shù)量從 3 減少到 1,請(qǐng)執(zhí)行以下操作:

kubectl scale deployment/my-nginx --replicas=1
deployment.extensions/my-nginx scaled

現(xiàn)在,你的 Deployment 管理的 Pod 只有一個(gè)了。

kubectl get pods -l app=nginx
NAME                        READY     STATUS    RESTARTS   AGE
my-nginx-2035384211-j5fhi   1/1       Running   0          30m

想要讓系統(tǒng)自動(dòng)選擇需要 nginx 副本的數(shù)量,范圍從 1 到 3,請(qǐng)執(zhí)行以下操作:

kubectl autoscale deployment/my-nginx --min=1 --max=3
horizontalpodautoscaler.autoscaling/my-nginx autoscaled

就地更新資源 

有時(shí),有必要對(duì)你所創(chuàng)建的資源進(jìn)行小范圍、無干擾地更新。

kubectl apply

建議在源代碼管理中維護(hù)一組配置文件 (參見配置即代碼), 這樣,它們就可以和應(yīng)用代碼一樣進(jìn)行維護(hù)和版本管理。 然后,你可以用 ?kubectl apply? 將配置變更應(yīng)用到集群中。

這個(gè)命令將會(huì)把推送的版本與以前的版本進(jìn)行比較,并應(yīng)用你所做的更改, 但是不會(huì)自動(dòng)覆蓋任何你沒有指定更改的屬性。

kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx configured

注意,?kubectl apply? 將為資源增加一個(gè)額外的注解,以確定自上次調(diào)用以來對(duì)配置的更改。 執(zhí)行時(shí),?kubectl apply? 會(huì)在以前的配置、提供的輸入和資源的當(dāng)前配置之間 找出三方差異,以確定如何修改資源。

目前,新創(chuàng)建的資源是沒有這個(gè)注解的,所以,第一次調(diào)用 ?kubectl apply? 時(shí) 將使用提供的輸入和資源的當(dāng)前配置雙方之間差異進(jìn)行比較。 在第一次調(diào)用期間,它無法檢測(cè)資源創(chuàng)建時(shí)屬性集的刪除情況。 因此,kubectl 不會(huì)刪除它們。

所有后續(xù)的 ?kubectl apply? 操作以及其他修改配置的命令,如 ?kubectl replace? 和 ?kubectl edit?,都將更新注解,并允許隨后調(diào)用的 ?kubectl apply? 使用三方差異進(jìn)行檢查和執(zhí)行刪除。

Note: 想要使用 apply,請(qǐng)始終使用 ?kubectl apply? 或 ?kubectl create --save-config? 創(chuàng)建資源。

kubectl edit

或者,你也可以使用 ?kubectl edit? 更新資源:

kubectl edit deployment/my-nginx

這相當(dāng)于首先 ?get ?資源,在文本編輯器中編輯它,然后用更新的版本 ?apply ?資源:

kubectl get deployment my-nginx -o yaml > /tmp/nginx.yaml
vi /tmp/nginx.yaml
# do some edit, and then save the file

kubectl apply -f /tmp/nginx.yaml
deployment.apps/my-nginx configured

rm /tmp/nginx.yaml

這使你可以更加容易地進(jìn)行更重大的更改。 請(qǐng)注意,可以使用 ?EDITOR ?或 ?KUBE_EDITOR ?環(huán)境變量來指定編輯器。

想要了解更多信息,請(qǐng)參考 kubectl edit 文檔。

kubectl patch

你可以使用 ?kubectl patch? 來更新 API 對(duì)象。此命令支持 JSON patch、 JSON merge patch、以及 strategic merge patch。

破壞性的更新 

在某些情況下,你可能需要更新某些初始化后無法更新的資源字段,或者你可能只想立即進(jìn)行遞歸更改, 例如修復(fù) Deployment 創(chuàng)建的不正常的 Pod。若要更改這些字段,請(qǐng)使用 ?replace --force?, 它將刪除并重新創(chuàng)建資源。在這種情況下,你可以修改原始配置文件:

kubectl replace -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml --force
deployment.apps/my-nginx deleted
deployment.apps/my-nginx replaced

在不中斷服務(wù)的情況下更新應(yīng)用

在某些時(shí)候,你最終需要更新已部署的應(yīng)用,通常都是通過指定新的鏡像或鏡像標(biāo)簽, 如上面的金絲雀發(fā)布的場景中所示。?kubectl ?支持幾種更新操作, 每種更新操作都適用于不同的場景。

我們將指導(dǎo)你通過 Deployment 如何創(chuàng)建和更新應(yīng)用。

假設(shè)你正運(yùn)行的是 1.14.2 版本的 nginx:

kubectl create deployment my-nginx --image=nginx:1.14.2
deployment.apps/my-nginx created

要更新到 1.16.1 版本,只需使用我們前面學(xué)到的 kubectl 命令將 ?.spec.template.spec.containers[0].image? 從 ?nginx:1.14.2? 修改為 ?nginx:1.16.1?。

kubectl edit deployment/my-nginx

沒錯(cuò),就是這樣!Deployment 將在后臺(tái)逐步更新已經(jīng)部署的 nginx 應(yīng)用。 它確保在更新過程中,只有一定數(shù)量的舊副本被開閉,并且只有一定基于所需 Pod 數(shù)量的新副本被創(chuàng)建。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)