Secret
ConfigMap
這個資源對象是Kubernetes
當中非常重要的一個對象,一般情況下ConfigMap
是用來存儲一些非安全的配置信息,如果涉及到一些安全相關的數據的話用ConfigMap
就非常不妥了,因為ConfigMap
是名為存儲的,我們說這個時候我們就需要用到另外一個資源對象了:Secret
,Secret
用來保存敏感信息,例如密碼、OAuth 令牌和 ssh key等等,將這些信息放在Secret
中比放在Pod
的定義中或者docker
鏡像中來說更加安全和靈活。
Secret
有三種類型:
- Opaque:base64 編碼格式的 Secret,用來存儲密碼、密鑰等;但數據也可以通過base64 –decode解碼得到原始數據,所有加密性很弱。
- kubernetes.io/dockerconfigjson:用來存儲私有docker registry的認證信息。
- kubernetes.io/service-account-token:用於被
serviceaccount
引用,serviceaccout 創建時Kubernetes會默認創建對應的secret。Pod如果使用了serviceaccount,對應的secret會自動掛載到Pod目錄/run/secrets/kubernetes.io/serviceaccount
中。
Opaque Secret
Opaque 類型的數據是一個 map 類型,要求value是base64
編碼格式,比如我們來創建一個用戶名為 admin,密碼為 admin321 的 Secret 對象,首先我們先把這用戶名和密碼做 base64 編碼,
$ echo -n "admin" | base64 YWRtaW4= $ echo -n "admin321" | base64 YWRtaW4zMjE=
然后我們就可以利用上面編碼過后的數據來編寫一個YAML
文件:(secret-demo.yaml)
apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: username: YWRtaW4= password: YWRtaW4zMjE=
然后同樣的我們就可以使用kubectl
命令來創建了:
$ kubectl create -f secret-demo.yaml
secret "mysecret" created
利用get secret
命令查看:
$ kubectl get secret
NAME TYPE DATA AGE
default-token-n9w2d kubernetes.io/service-account-token 3 33d
mysecret Opaque 2 40s
其中
default-token-cty7pdefault-token-n9w2d
為創建集群時默認創建的 secret,被serviceacount/default 引用。
使用describe
命令,查看詳情:
$ kubectl describe secret mysecret
Name: mysecret
Namespace: default
Labels: <none> Annotations: <none> Type: Opaque Data ==== password: 8 bytes username: 5 bytes
我們可以看到利用describe
命令查看到的Data
沒有直接顯示出來,如果想看到Data
里面的詳細信息,同樣我們可以輸出成YAML
文件進行查看:
$ kubectl get secret mysecret -o yaml
apiVersion: v1
data:
password: YWRtaW4zMjE= username: YWRtaW4= kind: Secret metadata: creationTimestamp: 2018-06-19T15:27:06Z name: mysecret namespace: default resourceVersion: "3694084" selfLink: /api/v1/namespaces/default/secrets/mysecret uid: 39c139f5-73d5-11e8-a101-525400db4df7 type: Opaque
創建好Secret
對象后,有兩種方式來使用它:
- 以環境變量的形式
- 以Volume的形式掛載
環境變量
首先我們來測試下環境變量的方式,同樣的,我們來使用一個簡單的busybox
鏡像來測試下:(secret1-pod.yaml)
apiVersion: v1 kind: Pod metadata: name: secret1-pod spec: containers: - name: secret1 image: busybox command: [ "/bin/sh", "-c", "env" ] env: - name: USERNAME valueFrom: secretKeyRef: name: mysecret key: username - name: PASSWORD valueFrom: secretKeyRef: name: mysecret key: password
主要上面環境變量中定義的secretKeyRef
關鍵字,和我們上節課的configMapKeyRef
是不是比較類似,一個是從Secret
對象中獲取,一個是從ConfigMap
對象中獲取,創建上面的Pod
:
$ kubectl create -f secret1-pod.yaml
pod "secret1-pod" created
然后我們查看Pod
的日志輸出:
$ kubectl logs secret1-pod
... USERNAME=admin PASSWORD=admin321 ...
可以看到有 USERNAME 和 PASSWORD 兩個環境變量輸出出來。
Volume 掛載
同樣的我們用一個Pod
來驗證下Volume
掛載,創建一個Pod
文件:(secret2-pod.yaml)
apiVersion: v1 kind: Pod metadata: name: secret2-pod spec: containers: - name: secret2 image: busybox command: ["/bin/sh", "-c", "ls /etc/secrets"] volumeMounts: - name: secrets mountPath: /etc/secrets volumes: - name: secrets secret: secretName: mysecret
創建Pod
:
$ kubectl create -f secret-pod2.yaml
pod "secret2-pod" created
然后我們查看輸出日志:
$ kubectl logs secret2-pod
password
username
可以看到secret
把兩個key掛載成了兩個對應的文件。當然如果想要掛載到指定的文件上面,是不是也可以使用上一節課的方法:在secretName
下面添加items
指定 key 和 path,這個大家可以參考上節課ConfigMap
中的方法去測試下。
kubernetes.io/dockerconfigjson
除了上面的Opaque
這種類型外,我們還可以來創建用戶docker registry
認證的Secret
,直接使用kubectl create
命令創建即可,如下:
$ kubectl create secret docker-registry myregistry --docker-server=DOCKER_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL secret "myregistry" created
然后查看Secret
列表:
$ kubectl get secret
NAME TYPE DATA AGE
default-token-n9w2d kubernetes.io/service-account-token 3 33d
myregistry kubernetes.io/dockerconfigjson 1 15s
mysecret Opaque 2 34m
注意看上面的TYPE
類型,myregistry
是不是對應的kubernetes.io/dockerconfigjson
,同樣的可以使用describe
命令來查看詳細信息:
$ kubectl describe secret myregistry
Name: myregistry
Namespace: default
Labels: <none> Annotations: <none> Type: kubernetes.io/dockerconfigjson Data ==== .dockerconfigjson: 152 bytes
同樣的可以看到Data
區域沒有直接展示出來,如果想查看的話可以使用-o yaml
來輸出展示出來:
$ kubectl get secret myregistry -o yaml
apiVersion: v1
data:
.dockerconfigjson: eyJhdXRocyI6eyJET0NLRVJfU0VSVkVSIjp7InVzZXJuYW1lIjoiRE9DS0VSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFUl9QQVNTV09SRCIsImVtYWlsIjoiRE9DS0VSX0VNQUlMIiwiYXV0aCI6IlJFOURTMFZTWDFWVFJWSTZSRTlEUzBWU1gxQkJVMU5YVDFKRSJ9fX0= kind: Secret metadata: creationTimestamp: 2018-06-19T16:01:05Z name: myregistry namespace: default resourceVersion: "3696966" selfLink: /api/v1/namespaces/default/secrets/myregistry uid: f91db707-73d9-11e8-a101-525400db4df7 type: kubernetes.io/dockerconfigjson
可以把上面的data.dockerconfigjson
下面的數據做一個base64
解碼,看看里面的數據是怎樣的呢?
$ echo eyJhdXRocyI6eyJET0NLRVJfU0VSVkVSIjp7InVzZXJuYW1lIjoiRE9DS0VSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFUl9QQVNTV09SRCIsImVtYWlsIjoiRE9DS0VSX0VNQUlMIiwiYXV0aCI6IlJFOURTMFZTWDFWVFJWSTZSRTlEUzBWU1gxQkJVMU5YVDFKRSJ9fX0= | base64 -d {"auths":{"DOCKER_SERVER":{"username":"DOCKER_USER","password":"DOCKER_PASSWORD","email":"DOCKER_EMAIL","auth":"RE9DS0VSX1VTRVI6RE9DS0VSX1BBU1NXT1JE"}}}
如果我們需要拉取私有倉庫中的docker
鏡像的話就需要使用到上面的myregistry
這個Secret
:
apiVersion: v1 kind: Pod metadata: name: foo spec: containers: - name: foo image: 192.168.1.100:5000/test:v1 imagePullSecrets: - name: myregistrykey
我們需要拉取私有倉庫鏡像192.168.1.100:5000/test:v1
,我們就需要針對該私有倉庫來創建一個如上的Secret
,然后在Pod
的 YAML 文件中指定imagePullSecrets
,我們會在后面的私有倉庫搭建的課程中跟大家詳細說明的。
kubernetes.io/service-account-token
另外一種Secret
類型就是kubernetes.io/service-account-token
,用於被serviceaccount
引用。serviceaccout 創建時 Kubernetes 會默認創建對應的 secret。Pod 如果使用了 serviceaccount,對應的secret會自動掛載到Pod的/run/secrets/kubernetes.io/serviceaccount
目錄中。
這里我們使用一個nginx
鏡像來驗證一下,大家想一想為什么不是呀busybox
鏡像來驗證?當然也是可以的,但是我們就不能在command
里面來驗證了,因為token是需要Pod
運行起來過后才會被掛載上去的,直接在command
命令中去查看肯定是還沒有 token 文件的。
$ kubectl run secret-pod3 --image nginx:1.7.9
deployment.apps "secret-pod3" created $ kubectl get pods NAME READY STATUS RESTARTS AGE ... secret-pod3-78c8c76db8-7zmqm 1/1 Running 0 13s ... $ kubectl exec secret-pod3-78c8c76db8-7zmqm ls /run/secrets/kubernetes.io/serviceaccount ca.crt namespace token $ kubectl exec secret-pod3-78c8c76db8-7zmqm cat /run/secrets/kubernetes.io/serviceaccount/token eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tbjl3MmQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjMzY2FkOWQxLTU5MmYtMTFlOC1hMTAxLTUyNTQwMGRiNGRmNyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.0FpzPD8WO_fwnMjwpGIOphdVu4K9wUINwpXpBOJAQ-Tawd0RTbAUHcgYy3sEHSk9uvgnl1FJRQpbQN3yVR_DWSIlAtbmd4dIPxK4O7ZVdd4UnmC467cNXEBqL1sDWLfS5f03d7D1dw1ljFJ_pJw2P65Fjd13reKJvvTQnpu5U0SDcfxj675-Z3z-iOO3XSalZmkFIw2MfYMzf_WpxW0yMFCVkUZ8tBSTegA9-NJZededceA_VCOdKcUjDPrDo-CNti3wZqax5WPw95Ou8RJDMAIS5EcVym7M2_zjGiqHEL3VTvcwXbdFKxsNX-1VW6nr_KKuMGKOyx-5vgxebl71QQ
Secret 與 ConfigMap 對比
最后我們來對比下Secret
和ConfigMap
這兩種資源對象的異同點:
相同點:
- key/value的形式
- 屬於某個特定的namespace
- 可以導出到環境變量
- 可以通過目錄/文件形式掛載
- 通過 volume 掛載的配置信息均可熱更新
不同點:
- Secret 可以被 ServerAccount 關聯
- Secret 可以存儲 docker register 的鑒權信息,用在 ImagePullSecret 參數中,用於拉取私有倉庫的鏡像
- Secret 支持 Base64 加密
- Secret 分為 kubernetes.io/service-account-token、kubernetes.io/dockerconfigjson、Opaque 三種類型,而 Configmap 不區分類型