深入k8s:Pod對象中重要概念及用法

01d8ab5f19a419a801215aa02565b7.jpg@1280w_1l_0o_100sh

Pod對象基本概念

Pod,實際上是在扮演傳統基礎設施裏“虛擬機”的角色;而容器,則是這個虛擬機裏運行的用戶程序。

Kubernetes 集羣中的 Pod 可被用於以下兩個主要用途:

  • 運行單個容器的 Pod。"每個 Pod 一個容器"模型是最常見的 Kubernetes 用例;在這種情況下,可以將 Pod 看作單個容器的包裝器,並且 Kubernetes 直接管理 Pod,而不是容器。
  • 運行多個協同工作的容器的 Pod。 Pod 可能封裝由多個緊密耦合且需要共享資源的共處容器組成的應用程序。一個Pod可能包含一個或者多個緊密相連的應用,這些應用可能是在同一個物理主機或虛擬機上。同一個Pod中的應用可以共享磁盤,磁盤是Pod級的,應用可以通過文件系統調用,額外的,一個Pod可能會定義頂級的cgroup隔離。

Pod的生命週期

Pod 生命週期的變化,主要體現在 Pod API 對象的 Status 部分,它有如下幾種可能的情況:

  1. Pending。這個狀態意味着,Pod 的 YAML 文件已經提交給了 Kubernetes,API 對象已經被創建並保存在 Etcd 當中。但是,這個 Pod 裏有些容器因爲某種原因而不能被順利創建。比如,調度不成功。
  2. Running。這個狀態下,Pod 已經調度成功,跟一個具體的節點綁定。它包含的容器都已經創建成功,並且至少有一個正在運行中。
  3. Succeeded。這個狀態意味着,Pod 裏的所有容器都正常運行完畢,並且已經退出了。這種情況在運行一次性任務時最爲常見。
  4. Failed。這個狀態下,Pod 裏至少有一個容器以不正常的狀態(非 0 的返回碼)退出。這個狀態的出現,意味着你得想辦法 Debug 這個容器的應用,比如查看 Pod 的 Events 和日誌。
  5. Unknown。這是一個異常狀態,意味着 Pod 的狀態不能持續地被 kubelet 彙報給 kube-apiserver,這很有可能是主從節點(Master 和 Kubelet)間的通信出現了問題。

Pod 對象的 Status 字段,還可以再細分出一組 Conditions。這些細分狀態的值包括:PodScheduled、Ready、Initialized,以及 Unschedulable。它們主要用於描述造成當前 Status 的具體原因是什麼。

Pod中的資源限制

Kubernetes通過cgroups限制容器的CPU和內存等計算資源,包括requests和limits。

如果 Pod 運行所在的節點具有足夠的可用資源,容器可能(且可以)使用超出對應資源 request 屬性所設置的資源量,request屬性主要目的是爲容器預留資源。不過,容器不可以使用超出其資源 limit 屬性所設置的資源量。

Pod 中的每個容器都可以指定以下的一個或者多個值:

  • spec.containers[].resources.limits.cpu
  • spec.containers[].resources.limits.memory
  • spec.containers[].resources.limits.hugepages-<size>
  • spec.containers[].resources.requests.cpu
  • spec.containers[].resources.requests.memory
  • spec.containers[].resources.requests.hugepages-<size>

CPU 資源的約束和請求以 cpu 爲單位。Kubernetes 中的一個 cpu 等於雲平臺上的 1 個 vCPU/核和裸機 Intel 處理器上的 **1 個超線程 **。CPU 總是按絕對數量來請求的,不可以使用相對數量; 0.1 的 CPU 在單核、雙核、48 核的機器上的意義是一樣的。

內存的約束和請求以字節爲單位。你可以使用以下後綴之一以一般整數或定點整數形式來表示內存: E、P、T、G、M、K。

如果沒有設置一個CPU或內存的限制,那麼這個container在當節點使用的資源是沒有上限的。但是如果設置了默認container資源限制,那麼就會被限制在默認值之下。

Pod中的網絡資源

Pod是一個邏輯概念,是一組共享了某些資源的容器。Pod 裏的所有容器,共享的是同一個 Network Namespace,並且可以聲明共享同一個 Volume。

在 Kubernetes 項目裏有一箇中間容器,這個容器叫作 Infra 容器。Infra 容器永遠都是第一個被創建的容器,而其他用戶定義的容器,則通過 Join Network Namespace 的方式,與 Infra 容器關聯在一起。

在 Kubernetes 項目裏,Infra 容器一定要佔用極少的資源,所以它使用的是一個非常特殊的鏡像,叫作:k8s.gcr.io/pause。這個鏡像是一個用匯編語言編寫的、永遠處於“暫停”狀態的容器,解壓後的大小也只有 100~200 KB 左右。

img

如上圖所示,這個 Pod 裏有兩個用戶容器 A 和 B,還有一個 Infra 容器。在 Infra 容器“Hold 住”Network Namespace 後,用戶容器就可以加入到 Infra 容器的 Network Namespace 當中了。

這也就意味着,對於 Pod 裏的容器 A 和容器 B 來說:

  • 它們可以直接使用 localhost 進行通信;
  • 它們可以直接使用 localhost 進行通信;
  • 它們看到的網絡設備跟 Infra 容器看到的完全一樣;
  • 一個 Pod 只有一個 IP 地址,也就是這個 Pod 的 Network Namespace 對應的 IP 地址;
  • 當然,其他的所有網絡資源,都是一個 Pod 一份,並且被該 Pod 中的所有容器共享;
  • Pod 的生命週期只跟 Infra 容器一致,而與容器 A 和 B 無關。

所以對於同一個 Pod 裏面的所有用戶容器來說,它們的進出流量,也可以認爲都是通過 Infra 容器完成的。

Pod中的Volume

Volume也是設計在 Pod 層級。一個 Volume 對應的宿主機目錄對於 Pod 來說就只有一個,Pod 裏的容器只要聲明掛載這個 Volume,就一定可以共享這個 Volume 對應的宿主機目錄。

apiVersion: v1
kind: Pod
metadata:
  name: two-containers
spec:
  restartPolicy: Never
  volumes:
  - name: shared-data
    hostPath:      
      path: /data
  containers:
  - name: nginx-container
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
  - name: debian-container
    image: debian
    volumeMounts:
    - name: shared-data
      mountPath: /pod-data
    command: ["/bin/sh"]
    args: ["-c", "echo Hello from the debian container > /pod-data/index.html"]

在這個例子中,debian-container 和 nginx-container 都聲明掛載了 shared-data 這個 Volume。而 shared-data 是 hostPath 類型。所以,它對應在宿主機上的目錄就是:/data。而這個目錄,其實就被同時綁定掛載進了上述兩個容器當中。這樣,nginx-container 可以從它的 /usr/share/nginx/html 目錄中,讀取到 debian-container 生成的 index.html 文件。

注意:這裏有多個container,那麼如果想進入其中一個container中,可以用如下命令:

kubectl exec -it two-containers  --container  debian-container -- /bin/bash

Pod中重要字段含義與用法

NodeSelector

是一個供用戶將 Pod 與 Node 進行綁定的字段,用法如下所示:

apiVersion: v1
kind: Pod
...
spec:
 nodeSelector:
   disktype: ssd

這樣所創建的Pod只能運行在攜帶了“disktype: ssd”標籤(Label)的節點上;否則,它將調度失敗。

HostAliases

定義了 Pod 的 hosts 文件(比如 /etc/hosts)裏的內容

apiVersion: v1
kind: Pod
...
spec:
  hostAliases:
  - ip: "10.1.2.3"
    hostnames:
    - "foo.remote"
    - "bar.remote"
...

這樣,這個 Pod 啓動後,/etc/hosts 文件的內容將如下所示:

cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1 localhost
...
10.244.135.10 hostaliases-pod
10.1.2.3 foo.remote
10.1.2.3 bar.remote

在k8s項目中, 如果要設置hosts 文件裏的內容,一定要通過這種方法。否則,如果直接修改了 hosts 文件的話,在 Pod 被刪除重建之後,kubelet 會自動覆蓋掉被修改的內容。

shareProcessNamespace

表示這個 Pod 裏的容器要共享 PID Namespace。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  shareProcessNamespace: true
  containers:
  - name: nginx
    image: nginx
  - name: shell
    image: busybox
    stdin: true
    tty: true

在這個 YAML 文件中定義了兩個容器:一個是 nginx 容器,一個是開啓了 tty 和 stdin 的 shell 容器。

在這個pod被創建後,我們可以使用attach命令進入到container中與之進行交互:

# 創建
$ kubectl create -f nginx.yaml
# 連接到shell
$ kubectl attach -it nginx -c shell
#查看正在運行的進程
/ # ps ax
PID   USER     TIME  COMMAND
    1 root      0:00 /pause
    8 root      0:00 nginx: master process nginx -g daemon off;
   14 101       0:00 nginx: worker process
   15 root      0:00 sh
   21 root      0:00 ps ax

從上面輸出結果可以看到整個 Pod 裏的每個容器的進程,對於所有容器來說都是可見的:它們共享了同一個 PID Namespace。

除此之外,我們還可以定義共享宿主機的 Network、IPC 和 PID Namespace。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  hostNetwork: true
  hostIPC: true
  hostPID: true
  containers:
  - name: nginx
    image: nginx
  - name: shell
    image: busybox
    stdin: true
    tty: true

這個 Pod 裏的所有容器,會直接使用宿主機的網絡、直接與宿主機進行 IPC 通信、看到宿主機里正在運行的所有進程。

ImagePullPolicy

定義了鏡像拉取的策略,它是一個 Container 級別的屬性。

ImagePullPolicy 的值默認是 IfNotPresent,即每次創建 Pod 都重新拉取一次鏡像。另外,當容器的鏡像是類似於 nginx 或者 nginx:latest 這樣的名字時,ImagePullPolicy 會被認爲Always ,即總是會去拉取最新的鏡像。

Lifecycle

可以在容器狀態發生變化時觸發一系列“鉤子”。

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
      preStop:
        exec:
          command: ["/usr/sbin/nginx","-s","quit"]

上面的配置中,postStart指的是在容器啓動後,立刻執行一個指定的操作;preStop是容器被殺死之前(比如,收到了 SIGKILL 信號)。

Pod中的init containers

一個Pod中可以有多個container,所以它也能有一個或多個init container,init container能在其他container開始前運行。每個init container都會運行完成後下一個container才能開始。

如果Pod中的init container運行失敗,Kubernetes 會重啓Pod直到init container運行成功;如果這個Pod的restartPolicy策略是Never,那麼Kubernetes 在init container運行失敗後將不會啓動。

下面我們舉個例子:

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]

這個pod中運行了兩個init container,init-myservice和init-mydb,他們都會在容器運行時執行一個命令,只有當這個命令執行完成了才能繼續往下運行。

啓動這個pod:

kubectl apply -f myapp.yaml

查看pod狀態:

kubectl get -f myapp.yaml

NAME        READY     STATUS     RESTARTS   AGE
myapp-pod   0/1       Init:0/2   0          6m

可以看到這個pod一直在init中。

我們查看一下詳情:

kubectl describe -f myapp.yaml

...
Init Containers:
  init-myservice:
[...]
    State:         Running
[...]
  init-mydb:
[...]
    State:         Waiting
      Reason:      PodInitializing
    Ready:         False
...
Containers:
  myapp-container:
    ...
    State:          Waiting
      Reason:       PodInitializing
    Ready:          False
    Restart Count:  0
    Environment:    <none>
...
Events:
  Type    Reason     Age        From                     Message
  ----    ------     ----       ----                     -------
  Normal  Scheduled  <unknown>  default-scheduler        Successfully assigned default/myapp-pod to 192.168.13.130
  Normal  Pulling    41s        kubelet, 192.168.13.130  Pulling image "busybox:1.28"
  Normal  Pulled     27s        kubelet, 192.168.13.130  Successfully pulled image "busybox:1.28"
  Normal  Created    27s        kubelet, 192.168.13.130  Created container init-myservice
  Normal  Started    27s        kubelet, 192.168.13.130  Started container init-myservice

我們可以看到init container是依次往下執行,init-myservice處於running,init-mydb處於Waiting狀態。myapp-container也是處於Waiting狀態。

我們查看一下日誌:

kubectl logs myapp-pod -c init-myservice

Server:    10.68.0.2
Address 1: 10.68.0.2 kube-dns.kube-system.svc.cluster.local

waiting for myservice
nslookup: can't resolve 'myservice.default.svc.cluster.local'
Server:    10.68.0.2
Address 1: 10.68.0.2 kube-dns.kube-system.svc.cluster.local
...


kubectl logs myapp-pod -c init-mydb

Error from server (BadRequest): container "init-mydb" in pod "myapp-pod" is waiting to start: PodInitializing

可以看到init-myservice一直在循環執行nslookup,init-mydb還沒初始化。

現在我們實現兩個service:

---
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377

在上面這個yaml運行之後,我們在看看myapp pod狀態

kubectl get -f myapp.yaml

NAME        READY     STATUS    RESTARTS   AGE
myapp-pod   1/1       Running   0          9m

發現已經成功運行。

Pod中的Projected Volume

Projected Volume是用來爲容器提供預先定義好的數據。

到目前爲止,Kubernetes 支持的 Projected Volume 一共有四種:

  1. Secret;
  2. ConfigMap;
  3. Downward API;
  4. ServiceAccountToken。

Secret

作用是把 Pod 想要訪問的加密數據,存放到 Etcd 中。然後,你就可以通過在 Pod 的容器裏掛載 Volume 的方式,訪問到這些 Secret 裏保存的信息了。

先申明一下user和pass:

$ cat ./username.txt
admin
$ cat ./password.txt
c1oudc0w!

$ kubectl create secret generic user --from-file=./username.txt
$ kubectl create secret generic pass --from-file=./password.txt

username.txt 和 password.txt 文件裏,存放的就是用戶名和密碼;而 user 和 pass,則是我爲 Secret 對象指定的名字。

如果要查看secret的話,使用kubectl get就可以

$ kubectl get secrets
NAME           TYPE                                DATA      AGE
user          Opaque                                1         51s
pass          Opaque                                1         51s

除此之外,還可以使用YAML 文件的方式來創建這個 Secret 對象,比如:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  user: YWRtaW4=
  pass: MWYyZDFlMmU2N2Rm

需要注意的是,Secret 對象要求這些數據必須是經過 Base64 轉碼的,以免出現明文密碼的安全隱患。

然後創建一個pod,使用secret

如下:

apiVersion: v1
kind: Pod
metadata:
  name: test-projected-volume 
spec:
  containers:
  - name: test-secret-volume
    image: busybox
    args:
    - sleep
    - "86400"
    volumeMounts:
    - name: mysql-cred
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: mysql-cred
    projected:
      sources:
      - secret:
          name: user
      - secret:
          name: pass

然後在容器中,查看:

$ kubectl exec -it test-projected-volume -- /bin/sh
$ ls /projected-volume/
user
pass
$ cat /projected-volume/user
root
$ cat /projected-volume/pass
1f2d1e2e67df

像這樣通過掛載方式進入到容器裏的 Secret,一旦其對應的 Etcd 裏的數據被更新,這些 Volume 裏的文件內容,同樣也會被更新。

ConfigMap

ConfigMap 保存的是不需要加密的、應用所需的配置信息。

比如,一個 Java 應用所需的配置文件(.properties 文件),就可以通過下面這樣的方式保存在 ConfigMap 裏:

# .properties文件的內容
$ cat example/ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

# 從.properties文件創建ConfigMap
$ kubectl create configmap ui-config --from-file=example/ui.properties

# 查看這個ConfigMap裏保存的信息(data)
$ kubectl get configmaps ui-config -o yaml
apiVersion: v1
data:
  ui.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice
kind: ConfigMap
metadata:
  name: ui-config
  ...

Downward API

可以讓 Pod 裏的容器能夠直接獲取到這個 Pod API 對象本身的信息。

apiVersion: v1
kind: Pod
metadata:
  name: test-downwardapi-volume
  labels:
    zone: us-est-coast
    cluster: test-cluster1
    rack: rack-22
spec:
  containers:
    - name: client-container
      image: k8s.gcr.io/busybox
      command: ["sh", "-c"]
      args:
      - while true; do
          if [[ -e /etc/podinfo/labels ]]; then
            echo -en '\n\n'; cat /etc/podinfo/labels; fi;
          sleep 5;
        done;
      volumeMounts:
        - name: podinfo
          mountPath: /etc/podinfo
          readOnly: false
  volumes:
    - name: podinfo
      projected:
        sources:
        - downwardAPI:
            items:
              - path: "labels"
                fieldRef:
                  fieldPath: metadata.labels

通過這樣的聲明方式,當前 Pod 的 Labels 字段的值,就會被 Kubernetes 自動掛載成爲容器裏的 /etc/podinfo/labels 文件。

Downward API 支持的字段已經非常豐富了,比如:

1. 使用fieldRef可以聲明使用:
spec.nodeName - 宿主機名字
status.hostIP - 宿主機IP
metadata.name - Pod的名字
metadata.namespace - Pod的Namespace
status.podIP - Pod的IP
spec.serviceAccountName - Pod的Service Account的名字
metadata.uid - Pod的UID
metadata.labels['<KEY>'] - 指定<KEY>的Label值
metadata.annotations['<KEY>'] - 指定<KEY>的Annotation值
metadata.labels - Pod的所有Label
metadata.annotations - Pod的所有Annotation

2. 使用resourceFieldRef可以聲明使用:
容器的CPU limit
容器的CPU request
容器的memory limit
容器的memory request

Service Account

Service Account 對象的作用,就是 Kubernetes 系統內置的一種“服務賬戶”,它是 Kubernetes 進行權限分配的對象。

Service Account 的授權信息和文件保存在它所綁定的一個特殊的 Secret 對象ServiceAccountToken中。

如果你查看一下任意一個運行在 Kubernetes 集羣裏的 Pod,就會發現,每一個 Pod,都已經自動聲明一個類型是 Secret、名爲 default-token-xxxx 的 Volume,然後 自動掛載在每個容器的一個固定目錄上。比如:

$ kubectl describe pod nginx-deployment-5c678cfb6d-lg9lw
Containers:
...
  Mounts:
    /var/run/secrets/kubernetes.io/serviceaccount from default-token-s8rbq (ro)
Volumes:
  default-token-s8rbq:
  Type:       Secret (a volume populated by a Secret)
  SecretName:  default-token-s8rbq
  Optional:    false

這個 Secret 類型的 Volume,正是默認 Service Account 對應的 ServiceAccountToken。

一旦 Pod 創建完成,容器裏的應用就可以直接從這個默認 ServiceAccountToken 的掛載目錄裏訪問到授權信息和文件。這個容器內的路徑在 Kubernetes 裏是固定的,即:/var/run/secrets/kubernetes.io/serviceaccount。

Pod中的健康檢查和恢復機制

Pod中的健康檢查是kubectl在對Container的一個定期的檢查。主要有三種實現方式:

  • 命令執行ExecAction:在Container中會定期的執行一行命令,如果這個命令能執行成功,那麼就認爲是健康的;
  • TCP Socket Action:對Container中的ip和端口進行TCP檢查,如果端口是通的,那麼就認爲是健康的;
  • HTTP GET Action:通過http請求的方式來檢查Container中的服務是否正常。

下面我們看一個命令執行的例子:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: test-liveness-exec
spec:
  containers:
  - name: liveness
    image: busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

在這個 Pod 中在 /tmp 目錄下創建了一個 healthy 文件30 s 過後,它會把這個文件刪除掉。並且還定義了livenessProbe,然後會根據執行的命令在容器啓動 5 s 後開始執行(initialDelaySeconds: 5),每 5 s 執行一次(periodSeconds: 5),如果命令執行成功就認爲是健康的。

創建好後,可以過30s看一下狀態:

kubectl describe pod test-liveness-exec


FirstSeen LastSeen    Count   From            SubobjectPath           Type        Reason      Message
--------- --------    -----   ----            -------------           --------    ------      -------
2s        2s      1   {kubelet worker0}   spec.containers{liveness}   Warning     Unhealthy   Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory

event裏面會報告容器是不健康的。

然後在看一下Pod狀態:

$ kubectl get pod test-liveness-exec
NAME           READY     STATUS    RESTARTS   AGE
liveness-exec   1/1       Running   1          1m

發現Pod已經被重啓過一次了。這也就是Pod 恢復機制,它是 Pod 的 Spec 部分的一個標準字段(pod.spec.restartPolicy),默認值是 Always,即:任何時候這個容器發生了異常,它一定會被重新創建。

注意:Pod 的恢復過程,永遠都是發生在當前節點上,而不會跑到別的節點上去。

Pod 恢復機制有以下幾種:

  • Always:在任何情況下,只要容器不在運行狀態,就自動重啓容器;

  • OnFailure: 只在容器 異常時才自動重啓容器;

  • Never: 從來不重啓容器

只要 Pod 的 restartPolicy 指定的策略允許重啓異常的容器(比如:Always),那麼這個 Pod 就會保持 Running 狀態,並進行容器重啓。

對於包含多個容器的 Pod,只有它裏面所有的容器都進入異常狀態後,Pod 纔會進入 Failed 狀態。

Pod 預設置:PodPreset

比如可以先定義一個 PodPreset 對象:


apiVersion: settings.k8s.io/v1alpha1
kind: PodPreset
metadata:
  name: allow-database
spec:
  selector:
    matchLabels:
      role: frontend
  env:
    - name: DB_PORT
      value: "6379"
  volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
    - name: cache-volume
      emptyDir: {}

在這個 PodPreset 的定義中,首先是一個 selector,表示只會作用於 selector 所定義的、帶有“role: frontend”標籤的 Pod 對象。

然後定義了env、volumeMounts等。

然後我們再寫一個yaml:

apiVersion: v1
kind: Pod
metadata:
  name: website
  labels:
    app: website
    role: frontend
spec:
  containers:
    - name: website
      image: nginx
      ports:
        - containerPort: 80

那麼創建的適合,先創建PodPreset,然後再創建website的Pod,然後查看一下這個 Pod 的 API 對象:

$ kubectl get pod website -o yaml
apiVersion: v1
kind: Pod
metadata:
  name: website
  labels:
    app: website
    role: frontend
  annotations:
    podpreset.admission.kubernetes.io/podpreset-allow-database: "resource version"
spec:
  containers:
    - name: website
      image: nginx
      volumeMounts:
        - mountPath: /cache
          name: cache-volume
      ports:
        - containerPort: 80
      env:
        - name: DB_PORT
          value: "6379"
  volumes:
    - name: cache-volume
      emptyDir: {}

PodPreset 裏定義的內容,只會在 Pod API 對象被創建之前追加在這個對象本身上,而不會影響任何 Pod 的控制器的定義。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章