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