K8s 安全抽象:Secret

歡迎訪問博客原文

Secret 是對敏感信息的抽象,例如:密碼、token、SSH key,其他對象可引用Secret。

Pod 使用 Secret 有兩種場景:

  • 作爲 volume 中的文件被掛載到 Pod 中一個或多個容器中
  • 拉取鏡像時需要使用 secret 作爲安全憑證

Secret 分類

Secret 可分爲三類:

  • docker-registry: 創建一個給 Docker Registry 使用的 secret,實際是保存了賬戶密碼。
  • generic:從本地 file, directory 或者 literal value 創建一個 secret。
  • tls:創建一個 TLS secret。

創建 generic secret

通過 literal(字面量)創建

創建一個order數據庫的secret,包含賬戶密碼兩個字段。

kubectl create secret generic db-order-secret --from-literal=username=admin --from-literal=password=123456

literal 中若包含特殊字符則需要進行轉義,如"123456!" 需設置爲 “123456​\!”

查看secret,describe secret db-order-secret,查看時隱藏了字段值,僅展示了字節數。

對應的API對象爲 Opaque([oʊˈpeɪk]),譯爲"不透明物",等同於"敏感數據"。

Name:         db-order-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  6 bytes
username:  5 bytes

再看看其yaml形態:

kubectl get secret db-order-secret -o yaml

其中字段是base64編碼後的值。

apiVersion: v1
data:
  password: MTIzNDU2
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2020-03-14T04:21:29Z"
  name: db-order-secret
  namespace: default
  resourceVersion: "28023453"
  selfLink: /api/v1/namespaces/default/secrets/db-order-secret
  uid: 5c60f906-ec8e-4277-8b96-caa75ef6589a
type: Opaque

解碼password字段,值爲123456

$ echo MTIzNDU2 | base64 --decode
123456

通過文件創建

在當前目錄創建一個RSA 公私鑰對作爲例子。

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): ./id_rsa
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ./id_rsa.
Your public key has been saved in ./id_rsa.pub.

將私鑰創建爲secret,公鑰可分發給另一方。

kubectl create secret generic rsa-key-secret --from-file=./id_rsa

通過yaml創建

通過yaml提供元數據以創建secret,字段需用base64先編碼,如: echo -n admin | base64

apiVersion: v1
kind: Secret
metadata:
  name: db-user-secret
type: Opaque
data:
  username: YWRtaW4=
  password: MTIzNDU2

然後創建Secret即可。

kubectl apply -f ./secret.yaml

Pod 中應用Secret

下面的例子演示了Secret 的三種應用方式。

  • 作爲volume直接掛載,在容器中可直接使用
  • 在環境變量中使用secret
  • 向特定目錄映射secret

下面是Pod yaml。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx
    env:
      - name: SECRET_USERNAME
      # 使用secret 做環境變量
        valueFrom:
          secretKeyRef:
            name: db-user-secret
            key: username
    volumeMounts:
    # 將secret作爲volume掛載
    - name: volume1
      mountPath: "/etc/foo1"
      readOnly: true
    # 向特定目錄映射secret  
    - name: volume2
      mountPath: "/etc/foo2"
      readOnly: true
  volumes:
  - name: volume1
    secret:
      secretName: db-user-secret
  - name: volume2
    secret:
      secretName: db-user-secret
      items:
      - key: username
        path: usernameFile

創建Pod,然後進入Pod驗證效果。

  • 做環境變量
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: db-user-secret
            key: username

結果如下:

$ env | grep SECRET_USERNAME
SECRET_USERNAME=admin
  • 掛載到容器
    volumeMounts:
    - name: volume1
      mountPath: "/etc/foo1"
      readOnly: true

效果如下:

$ ls -l /etc/foo1
total 0
lrwxrwxrwx 1 root root 15 Mar 14 07:49 password -> ..data/password
lrwxrwxrwx 1 root root 15 Mar 14 07:49 username -> ..data/username
  • 向特定目錄映射secret
spec:
    volumeMounts:
    - name: volume2
      mountPath: "/etc/foo2"
      readOnly: true
  volumes:
  - name: volume2
    secret:
      secretName: db-user-secret
      items:
      - key: username
        path: usernameFile

將 username 字段映射到了 /etc/foo2/usernameFile

$ cat /etc/foo2/usernameFile
admin

創建 docker-registry secret 拉取鏡像

構建、部署時需要拉取鏡像,可以向Pod提供一個secret專門用於拉取鏡像。

以騰訊雲鏡像倉庫爲例,ccr.ccs.tencentyun.com/easyk8s/nginx 是一個私有的demo鏡像。

利用下面yaml跑一個簡單Pod:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx-container
    image: ccr.ccs.tencentyun.com/easyk8s/nginx:1.17

運行後Pod Event如下,出現 Error: ErrImagePull

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-aCIiPd6t-1584194450616)(https://imgcdn.chenyongjun.vip/2020/03/14/2.png)]

接下來創建一個secret專門用於拉取鏡像。

kubectl create secret docker-registry registry-tecent-secret \
--docker-server=ccr.ccs.tencentyun.com \
--docker-username=name \
--docker-password=password

在 Pod 中使用 secret。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx-container
    image: ccr.ccs.tencentyun.com/easyk8s/nginx:1.17
  imagePullSecrets:
  - name: registry-tecent-secret

應用yaml後Pod成功創建。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-F28N8FX3-1584194450617)(https://imgcdn.chenyongjun.vip/2020/03/14/3.png)]

通過kubectl get secret registry-tecent-secret -o yaml 拿到的 registry-tecent-secret 的yaml結構如下:

apiVersion: v1
data:
  .dockerconfigjson: eyJhdXR...
kind: Secret
metadata:
  creationTimestamp: "2020-03-14T05:01:04Z"
  name: registry-tecent-secret
  namespace: default
  resourceVersion: "28027921"
  selfLink: /api/v1/namespaces/default/secrets/registry-tecent-secret
  uid: a05ae3c0-b504-448b-bc78-8c540b2dda6c
type: kubernetes.io/dockerconfigjson

其中 .dockerconfigjson 通過base64解碼後可以拿到docker-registry的賬戶密碼。

創建tls secret

存儲用於SSL通訊的私鑰文件和證書文件,下面以nginx爲例子。

預先準備好nginx ssl 通訊所需的key和crt文件.

kubectl create secret tls nginx-ssl-secret \
--key=nginx.key \
--cert=nginx.crt

下面是 secret 的數據,其類型爲:kubernetes.io/tls

$ kubectl describe secret/nginx-ssl-secret
Name:         nginx-ssl-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  4241 bytes
tls.key:  1679 bytes

在nginx pod 中應用該secret,作爲volume映射到容器中。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx
    volumeMounts:
    - name: nginx-crt
      mountPath: /etc/nginx/ssl
      readOnly: true
  volumes:
  - name: nginx-crt
    secret:
      secretName: nginx-ssl-secret

運行Pod後進入Pod查看 /etc/nginx/ssl 目錄,可看到映射的證書、私鑰文件,不過名字從 nginx.crt, nginx.key 變爲了 tls.crt, tls.key

$ ls -l /etc/nginx/ssl/
total 0
lrwxrwxrwx 1 root root 14 Mar 14 08:42 tls.crt -> ..data/tls.crt
lrwxrwxrwx 1 root root 14 Mar 14 08:42 tls.key -> ..data/tls.key

接着可以在nginx配置中使用這兩個文件完成ssl通訊配置。

常用 Secret 示意圖

在這裏插入圖片描述


歡迎關注公衆號 [陳一樂],一起學習,一起成長

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