【k8s】 projected volume

Projected volume

這是什么意思呢?在 Kubernetes 中,有幾種特殊的 Volume,它們存在的意義不是為了存放容器里的數(shù)據(jù),也不是用來進行容器和宿主機之間的數(shù)據(jù)交換。這些特殊 Volume 的作用,是為容器提供預先定義好的數(shù)據(jù)。所以,從容器的角度來看,這些 Volume 里的信息就是仿佛是被 Kubernetes“投射”(Project)進入容器當中的。這正是 Projected Volume 的含義。

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

  • Secret;
  • ConfigMap;
  • Downward API;
  • ServiceAccountToken。

Secret
它的作用,是幫你把 Pod 想要訪問的加密數(shù)據(jù),存放到 Etcd 中。然后,你就可以通過在 Pod 的容器里掛載 Volume 的方式,訪問到這些 Secret 里保存的信息了。

Secret 最典型的使用場景,莫過于存放數(shù)據(jù)庫的 Credential 信息,比如下面這個例子:

#方案1:command創(chuàng)建
$ 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

#方案2:采樣yaml創(chuàng)建
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  user: YWRtaW4=
  pass: MWYyZDFlMmU2N2Rm
$ kubectl get secrets
NAME           TYPE                                DATA      AGE
user          Opaque                                1         51s
pass          Opaque                                1         51s

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

在這個 Pod 中,我定義了一個簡單的容器。它聲明掛載的 Volume,并不是常見的 emptyDir 或者 hostPath 類型,而是 projected 類型。而這個 Volume 的數(shù)據(jù)來源(sources),則是名為 user 和 pass 的 Secret 對象,分別對應的是數(shù)據(jù)庫的用戶名和密碼。

ConfigMap

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

# 從.properties文件創(chuàng)建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 文件。而這個容器的啟動命令,則是不斷打印出 /etc/podinfo/labels 里的內容。所以,當我創(chuàng)建了這個 Pod 之后,就可以通過 kubectl logs 指令,查看到這些 Labels 字段被打印出來,如下所示:

$ kubectl create -f dapi-volume.yaml
$ kubectl logs test-downwardapi-volume
cluster="test-cluster1"
rack="rack-22"
zone="us-est-coast"

目前,Downward API 支持的字段已經(jīng)非常豐富了,比如:

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

ServiceAccountToken
K8S系統(tǒng)內置的服務賬號,用于授權給指定用戶訪問
Server的權限。這種授權給用戶的信息綁定在一個特殊的Secret對象中,稱為ServiceAccountToken。

如果你查看一下任意一個運行在 Kubernetes 集群里的 Pod,就會發(fā)現(xiàn),每一個 Pod,都已經(jīng)自動聲明一個類型是 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。所以說,Kubernetes 其實在每個 Pod 創(chuàng)建的時候,自動在它的 spec.volumes 部分添加上了默認 ServiceAccountToken 的定義,然后自動給每個容器加上了對應的 volumeMounts 字段。這個過程對于用戶來說是完全透明的。

這樣,一旦 Pod 創(chuàng)建完成,容器里的應用就可以直接從這個默認 ServiceAccountToken 的掛載目錄里訪問到授權信息和文件。這個容器內的路徑在 Kubernetes 里是固定的,即:/var/run/secrets/kubernetes.io/serviceaccount ,而這個 Secret 類型的 Volume 里面的內容如下所示:

$ ls /var/run/secrets/kubernetes.io/serviceaccount 
ca.crt namespace  token
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容