天天看點

《kubernetes-1.8.0》19-examples-secrets《kubernetes-1.8.0》19-examples-secrets

《kubernetes-1.8.0》19-examples-secrets

《kubernetes 1.8.0 測試環境安裝部署》

時間:2017-12-15

一、基礎知識:

secrets

是用來儲存類似于密碼、token、key等敏感資訊的。将這些敏感資訊放在

secrets

裡比直接放在

pod

或者

docker鏡像

中更安全和靈活。

建立:使用者能夠建立

secrets

,同時系統也會自動建立一些

secrets

(内建secrets)

使用:一個

secrets

能夠被兩種方式使用: 通過

volume

挂載到一個或者多個容器中,或者在

kubelet pull docker

鏡像的時候使用(需要login的docker倉庫)

Build-in Secrets

(内建secrets):

這個主要是關聯

Service Account

使用,當建立一個

SA

的時候将自動關聯一個

secrets

,如果想通過某個

sa

賬戶通路

apiserver

可通過該

secrets

進行驗證;

二、建立自定義secrets:

kubectl create secret

建立

secrets

:

要是一些pod需要通路資料庫,使用者名和密碼儲存在本機的

./username.txt

./password.txt

檔案中

建立所需的檔案:

$ mkdir ~/secret-examle
$ cd ~/secret-examle
$ echo -n "admin" > ./username.txt
$ echo -n "1f2d1e2e67df" > ./password.txt
           

使用

kubectl create secret

打包這些檔案到

secrets

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

    :表明從本地檔案,目錄,或者鍵值對建立,還可以使用

    docker-registry

    以及

    tls

  • docker-registry:Create a secret for use with a Docker registry
  • tls:Create a TLS secret

檢視:

[[email protected] secret-examle]# kubectl get secrets
NAME                         TYPE                                  DATA      AGE
...
db-user-pass                 Opaque                                         15s
...

[[email protected] secret-examle]# kubectl describe  secrets db-user-pass 
Name:         db-user-pass
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password.txt:   bytes
username.txt:   bytes
           
  • 從檢視的結果可以發現不管是get還是describe都沒顯示檔案的内容,保護secrets意外暴露或者通過終端日志暴露

手工建立一個secrets

能夠通過yaml或者json檔案建立secrets

先擷取username和password的base64編碼:

$ echo -n "admin" | base64
YWRtaW4=
$ echo -n "1f2d1e2e67df" | base64
MWYyZDFlMmU2N2Rm
           

建立secrets的yaml:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm
           
  • data部分的value為base64加密過的資料
  • Opaque:base64編碼格式的Secret,用來存儲密碼、密鑰等;

應用yaml:

$ kubectl create -f ./secret.yaml
secret "mysecret" created
           

檢視:

[[email protected] secret-examle]# kubectl get secret mysecret -o yaml
apiVersion: v1
data:
  password: MWYyZDFlMmU2N2Rm
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: --T06::Z
  name: mysecret
  namespace: default
  resourceVersion: "3418648"
  selfLink: /api/v1/namespaces/default/secrets/mysecret
  uid: c9804b-e164---bc80ed
type: Opaque
           

decode:

$ echo "MWYyZDFlMmU2N2Rm" | base64 --decode
f2d1e2e67df
           

secrets能夠被以data volume的方式挂載或者以環境變量的方式暴露在pod中的container。也可以用在系統的其他方面,比如可以儲存用于系統其他部分的互動證書;

以檔案的方式在pod中使用secrets:

  1. 建立secrets或者使用現有的,多個pods可以關聯同一個secrets
  2. 修改pod的配置,在

    spec.volumes[]

    部分添加,名字任意,配置

    spec.volumes[].secret.secretName

    為 對應

    secrets

    對象的名字
  3. 在每個需要

    secrets

    container

    添加

    spec.containers[].volumeMounts[]

    部分, 注明

    spec.containers[].volumeMounts[].readOnly = true

    以及注明

    spec.containers[].volumeMounts[].mountPath

    到一個想防止secrets以及未使用的目錄名.
  4. 修改鏡像或者指令行,使得程式能夠去挂載點下找對應的檔案,在secrets的data下的每個key都被映射成一個挂載點下的一個檔案名。

例子1:挂載secrets到一個volume:

mysecret.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret
           
  • 所有用到的secrets 放在

    spec.volumes

  • 如果在pod中有多個container,則每個container需要各自的

    volumeMounts

    ,而每個secrets隻需要一個

    spec.volumes

應用并檢視:

[root@node- secret-examle]# kubectl create -f mysecret.yaml 
pod "mypod" created

[root@node- secret-examle]# kubectl exec  mypod ls /etc/foo/ 
password  username
[root@node- secret-examle]# kubectl exec  mypod cat /etc/foo/password 
f2d1e2e67df
[root@node- secret-examle]# kubectl exec  mypod cat /etc/foo/username
admin
           

将secrets的key映射至指定路徑:

mysecret.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-group/my-username
           
  • username

    :這個key将被存放在

    /etc/foo/my-group/my-username

    目錄下
  • password

    :這個key将不會被映射
  • 一旦聲明了

    spec.volumes[].secret.items

    部分,所有想要被映射的key都必須列出來,否則将不比被挂載到指定的目錄下

應用并檢視:

[root@node- secret-examle]# kubectl delete pod mypod
pod "mypod" deleted
##terminating後

[root@node- secret-examle]# kubectl create -f mysecret.yaml 
pod "mypod" created

[root@node- secret-examle]# kubectl exec mypod ls /etc/foo/
my-group

[root@node- secret-examle]# kubectl exec mypod cat /etc/foo/my-group/my-username
admin
           

設定secrets檔案的權限

可以單獨設定secrets的權限mode bit,如果沒有特别設定,預設權限為0644,json不支援八進制,是以用256 表示 0400.511表示 0777以此類推;

mysecret.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      defaultMode: 256
           
  • defaultMode: 256 :表示設定挂載點下所有檔案權限為

    0400

應用并檢視:

[[email protected] secret-examle]# kubectl exec -ti mypod -- ls -l /etc/foo/ 
total 
lrwxrwxrwx  root root  Dec  : password -> ..data/password
lrwxrwxrwx  root root  Dec  : username -> ..data/username
[[email protected] secret-examle]# kubectl exec -ti mypod -- ls -l /etc/foo/..data/username
-r-------- 1 root root 5 Dec 15 09:06 /etc/foo/..data/username
           
  • 注意這邊挂載點目錄下的檔案為符号連結,真實檔案在挂載點下的

    ..data/

mysecret.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-group/my-username
        mode: 511
           
  • mode: 511:設定單個secrets檔案的權限為 0700

檢視:

[root@node- secret-examle]# kubectl exec -ti mypod -- ls -l /etc/foo/..data/my-group/my-username         
-rwxrwxrwx  root root  Dec  : /etc/foo/..data/my-group/my-username
           

以環境變量的方式在pod中使用secrets:

通過修改

env[].valueFrom.secretKeyRef

将secrets映射至pod中的環境變量

mysecret.yaml

apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: mycontainer
    image: redis
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password
  restartPolicy: Never
           
  • env.name

    :變量名
  • env[].valueFrom.secretKeyRef.name

    :secret名
  • env[].valueFrom.secretKeyRef.name

    :secret的data中的哪個key

應用并檢視:

[root@node- secret-examle]# kubectl exec -ti  secret-env-pod bash
root@secret-env-pod:/data# echo $SECRET_USERNAME
admin
root@secret-env-pod:/data# echo $SECRET_PASSWORD
f2d1e2e67df
           

建立用來imagepull的 secrets:

  1. 用kubelet指令建立
$ kubectl create secret docker-registry myregistrykey \
--docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER \
--docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
secret "myregistrykey" created.
           
  1. 用yaml檔案建立

首先本地用docker login進行登入,登入成功後,将在目前使用者的宿主目錄下建立

~/.docker/config.json

《kubernetes-1.8.0》19-examples-secrets《kubernetes-1.8.0》19-examples-secrets

用base64将

~/.docker/config.json

加密

[root@node- secret-examle]# cat ~/.docker/config.json  | base64 -w 0
ewoJImFJImF1dGgiOiAiWVdSdGFXNDZRV3hoWkdsdV.....S4wLWNlIChsaW51eCkiCgl9Cn0=
           

編輯yaml檔案

myregistrykey.yaml

apiVersion: v1
kind: Secret
metadata:
  name: myregistrykey
  namespace: default
data:
  .dockerconfigjson: ewoJImFJImF1dGgiOiAiWVdSdGFXNDZRV3hoWkdsdV.....S4wLWNlIChsaW51eCkiCgl9Cn0=
type: kubernetes.io/dockerconfigjson
           
  • .dockerconfigjson

    :将base64加密後的那串東西填到這裡
  • type: kubernetes.io/dockerconfigjson

建立并檢視:

[[email protected] secret-examle]# kubectl create -f   myregistrykey.yaml
secret "myregistrykey" created
[[email protected] secret-examle]# kubectl describe secret myregistrykey
Name:         myregistrykey
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/dockerconfigjson

Data
====
.dockerconfigjson:  155 bytes
           

建立一個pod測試

foo.yaml

apiVersion: v1
kind: Pod
metadata:
  name: foo
  namespace: default
spec:
  containers:
    - name: foo
      image: /elk/elasticsearch:v5
  imagePullSecrets:
    - name: myregistrykey
           
  • image: 172.18.169.134/elk/elasticsearch:v5.6.4

    :根據自己的環境修改

前提條件是做了私有倉庫,并設定項目為私有,即必須通過登入才能夠pull;

《kubernetes-1.8.0》19-examples-secrets《kubernetes-1.8.0》19-examples-secrets

應用yaml并檢視:

[[email protected] secret-examle]# kubectl describe pod foo   
Name:         foo
Namespace:    default
Node:         node.131/
...
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              6s    default-scheduler  Successfully assigned foo to node.131
  Normal  SuccessfulMountVolume  6s    kubelet, node.131  MountVolume.SetUp succeeded for volume "default-token-t8j7k"
  Normal  Pulling                5s    kubelet, node.131  pulling image "172.18.169.134/elk/elasticsearch:v5.6.4"
  Normal  Pulled                 5s    kubelet, node.131  Successfully pulled image "172.18.169.134/elk/elasticsearch:v5.6.4"
  Normal  Created                5s    kubelet, node.131  Created container
  Normal  Started                5s    kubelet, node.131  Started container
           

其他一些細節:

* secrets 必須在所應用的pod之前先建立

* secrets 必須和所應用的pod在同一個namespace

* secrets 大小必須效益1MB

用例:帶有ssh key的pod

建立一個secret 包含本機的ssh key:

[[email protected] secret-examle]# kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/root/.ssh/id_rsa --from-file=ssh-publickey=/root/.ssh/id_rsa.pub
secret "ssh-key-secret" created
           
  • 注意,測試環境滿搞搞,正式環境不推薦,将暴露登陸資訊至群集中

建立pod

secret-test-pod.yaml

kind: Pod
apiVersion: v1
metadata:
  name: secret-test-pod
  labels:
    name: secret-test
spec:
  volumes:
  - name: secret-volume
    secret:
      secretName: ssh-key-secret
  containers:
  - name: ssh-test-container
    image: redis
    volumeMounts:
    - name: secret-volume
      readOnly: true
      mountPath: "/etc/secret-volume"
           

應用并測試:

[root@node- secret-examle]# kubectl exec  secret-test-pod cat /etc/secret-volume/ssh-publickey
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDOB8IMzTYPcRb9h2pVoMNBI2Fy5EYPjXOEg11FyI1ffeo+C... root@node-

[root@node- secret-examle]# kubectl exec  secret-test-pod cat /etc/secret-volume/ssh-privatekey
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAzgfCDM02D3EW/YdqVaDDQSNhcuRGD41zhINdRciNX33qPglK
Npks8CIresIAbPdBDc4P6FO0MncuVAoXZVOE4xOUYTcmnXkncwHp6amATMtJNFTc
OSzejJIokVQn9e7nmREU2bCTSUtlnR6804XNm78Tmh9P7dyI863OWEVdGdBKZFFz
G...
           

後續這個container可以用這個建立與主控端的ssh連結

用例:使用區分正式環境和測試環境認證資訊的pod

這個例子說明了其中一個pod使用正式的認證資訊,另一個pod使用測試環境的認證資訊:

$ kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11
secret "prod-db-secret" created
$ kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests
secret "test-db-secret" created
           

建立pod:

apiVersion: v1
kind: List
items:
- kind: Pod
  apiVersion: v1
  metadata:
    name: prod-db-client-pod
    labels:
      name: prod-db-client
  spec:
    volumes:
    - name: secret-volume
      secret:
        secretName: prod-db-secret
    containers:
    - name: db-client-container
      image: myClientImage
      volumeMounts:
      - name: secret-volume
        readOnly: true
        mountPath: "/etc/secret-volume"
- kind: Pod
  apiVersion: v1
  metadata:
    name: test-db-client-pod
    labels:
      name: test-db-client
  spec:
    volumes:
    - name: secret-volume
      secret:
        secretName: test-db-secret
    containers:
    - name: db-client-container
      image: myClientImage
      volumeMounts:
      - name: secret-volume
        readOnly: true
        mountPath: "/etc/secret-volume"
           
  • 有兩個pod,用不同的使用者名密碼通路資料庫
  • 太麻煩了這裡就不做了 ^ ^

預期的效果是:

兩個不同的pod将擁有兩個不同的secrets file(内容):

/etc/secret-volume/username
/etc/secret-volume/password
           

用例:建立隐藏的secret volume(.file)

kind: Secret
apiVersion: v1
metadata:
  name: dotfile-secret
data:
  .secret-file: dmFsdWUtMg0KDQo=
---
kind: Pod
apiVersion: v1
metadata:
  name: secret-dotfiles-pod
spec:
  volumes:
  - name: secret-volume
    secret:
      secretName: dotfile-secret
  containers:
  - name: dotfile-test-container
    image: gcr.io/google_containers/busybox
    command:
    - ls
    - "-l"
    - "/etc/secret-volume"
    volumeMounts:
    - name: secret-volume
      readOnly: true
      mountPath: "/etc/secret-volume"
           
  • 關鍵就在

    .secret-file

    ,用

    .

    開頭的方式建立secret的keyname,後續被挂載的時候也将被挂載成’.’開頭的檔案。。
  • 貌似用ls看不了,用ls -a 一樣可以看到。。算是隐藏吧
  • 挺無聊的,也不做了 ^ ^

最後再生産環境需要注意apiserver通路權限對secrets的控制,

watch

list

将能夠看到

secret

的值,擁有

get

請求就可以利用secret進行相關的使用了。

至此secrets 部分算是寫完了。。

本系列其他内容:

  • 01-環境準備
  • 02-etcd群集搭建
  • 03-kubectl管理工具
  • 04-master搭建
  • 05-node節點搭建
  • 06-addon-calico
  • 07-addon-kubedns
  • 08-addon-dashboard
  • 09-addon-kube-prometheus
  • 10-addon-EFK
  • 11-addon-Harbor
  • 12-addon-ingress-nginx
  • 13-addon-traefik

參考資料:

https://kubernetes.io/docs/concepts/configuration/secret/

繼續閱讀