iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 12
5
DevOps

Kubernetes 30天學習筆記系列 第 12

[Day 12] 敏感的資料怎麼存在k8s?! - Secrets

前言

今天的學習筆記將介紹 Kubernetes 另一個元件 SecretsSecrets 協助開發者將一些敏感資訊,像是資料庫帳密、訪問其他台 server 的 Access Token 、SSH Key,用 非明碼的方式(opaque) 存放在 Kubernetes 中。今天的學習筆記內容如下:

  • 介紹什麼是 Secret
  • 實作:Kubernetes 中如何創建 Secret 物件
  • 實作:如何掛載 Secret 物件到 Pods 中

小提醒:今天的程式碼都可以在 demo-secrets 上找到。

什麼是 Secret ?

正如 前言 提及,SecretsKubernetes 提供開發者一種存放敏感資訊的方式。Kubernetes 本身也使用相同的機制( secrets mechanism) 存放 access token,限制 API 的存取權限,確保不會有外部服務隨意操作 Kubernetes API。

Kubernetes 存取敏感資料(sensitive data)有以下幾種常見的使用方式:

  • Secrets 當成 環境變數(environment variables) 使用
  • Secrets File 掛載(mount) 在 Pod 某個檔案路徑底下使用
  • 將這些 sensitive data 統一存放在某一個 Docker Image 中,並將這個 Image 存放在私有的 Image Registry 中,透過 image pull 下載到 Kubernetes Cluster 中,讓其他 Pods 存取。

今天實作的部分,將針對上述提到的前兩點進行介紹。

實作:Kubernetes 中如何創建 Secret 物件

Kubernetes 中,創建 Secrets 物件有以下幾種方法:

1/ 從檔案匯入 sensitive data

我們可以先將 sensitive data 存在某一個檔案中,透過 kubectl create 指令產生一個 Secrets 物件。

以帳號密碼為例,我們先將帳號、密碼分別存入兩個不同的檔案,

$ echo -n "root" > ./username.txt
$ echo -n "rootpass" > ./password.txt

接著使用 kubectl create secret generic 指令創建一個 Secret 物件,

kubectl describe 查看 demo-secret-from-file 物件,

若用 kubectl get 查看所有的 Secrets,

$ kubectl get secrets
NAME                    TYPE                                  DATA      AGE
default-token-cljjb     kubernetes.io/service-account-token   3         4m
demo-secret-from-file   Opaque                                2         3m

會發現除了剛剛創建好的 demo-secret-from-file ,還有一組 default-token-cljjb 物件,這是 Kubernetes 內部幫我們建立好的物件。裡面存放著 一個 token ,開發者可以透過這組 access token 來操控 Kubernetest API

2/ 從指令輸入 sensitive data

我們也可以透過 kuectl create 指令搭配 --from-literal 直接在指令後面輸入資料,以上述的帳密為例,

$ kubectl create secret generic demo-secret-from-literal \
> --from-literal=username=root \
> --from-literal=password=rootpass

secret "hello-secret-literal" created

kubectl describe 查看 demo-secret-from-literal 詳細資料,

3/ 透過 YAML 創建 Secret 物件

我們也可以透過設定檔創建一個 Secret 物件。

首先,須將帳號密碼用 base64 編碼 ,以 username=root, password=rootpass 為例,

$ echo -n "root" | base64
cm9vdA==

$ echo -n "rootpass" | base64
cm9vdHBhc3M=

並把編碼過的資料寫入 my-secret.yaml 中,

apiVersion: v1
kind: Secret
metadata:
  name: demo-secret-from-yaml
type: Opaque
data:
  username: cm9vdA==
  password: cm9vdHBhc3M=

透過 kuectl create 創建一個新物件,

$ kubectl create -f ./my-secret.yaml
secret "demo-secret-from-yaml" created

最後可以用 kubectl get secret 查看今天創建的三個 Secrets 物件,

下個章節將透過這些我們創建好的 Secret 物件,介紹如何將這些 Secrets 物件掛載到 Pods 使用。

如何掛載 Secret 物件到 Pods 中

1/ 將 Secrets 當成 環境變數(environment variables) 使用

my-pod.yaml 為例,

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: webserver
spec:
  containers:
  - name: demo-pod
    image: zxcvbnius/docker-demo
    ports:
    - containerPort: 3000
    env:
    - name: SECRET_USERNAME
      valueFrom:
        secretKeyRef:
          name: demo-secret-from-yaml
          key: username
    - name: SECRET_PASSWORD
      valueFrom:
        secretKeyRef:
          name: demo-secret-from-yaml
          key: password

my-pod.yaml 中,我們設定 env 會去從指定的 Secret 物件 找出相對應的值。值得一提的是,若是該 Secret 物件是從 --from-file 創建,那麼 Kubernetes 會把檔案名稱當成 key ,檔案內容當成 value

使用 kubectl create 創建 my-pod ,指令如下

$ kubectl create -f ./my-pod.yaml
pod "my-pod" created

my-pod 建立好時,

我們可以透過 kubectl exec 進到 my-pod 裡面,

$ kubectl exec -it my-pod -- /bin/bash

查看 SECRET_USERNAMESECRET_PASSWORD,如我們在 demo-secret-from-yaml 設定一致,

2/ 將 Secrets File 掛載(mount) 在 Pod 某個檔案路徑底下使用

我們也可以將 secrets 掛載到,Pod 底下的某個路徑檔案,以 my-pod-with-mounting-secret.yaml 為例,

apiVersion: v1
kind: Pod
metadata:
  name: my-pod-with-mounting-secret
  labels:
    app: webserver
spec:
  containers:
  - name: demo-pod
    image: zxcvbnius/docker-demo
    ports:
    - containerPort: 3000
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/creds
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: demo-secret-from-yaml

如同 創建 my-pod.yaml 一樣,使用 kubectl create 指令創建一個新的 Pod 物件,

$ kubectl create -f ./my-pod-with-mounting-secret.yaml
pod "my-pod-with-mounting-secret" created

透過 kubectl exec 進入 my-pod-with-mounting-secret 這個物件,且可以在我們指定掛載的 /etc/creds 找到存在 demo-secret-from-yaml 中的資料

透過以上兩種方式,我們便能在 Pods 中存取 Secret 物件。

總結

當我們有些敏感資料需要傳入 Kubernetes 時,使用 Secret 是個不錯的選擇 。然而,需要留意的是,一旦建立 Secrets 物件,其他人可以也可以在 Kubernetes Cluster 上存取 Secrets 中的敏感資料。因此,我們需要搭配 Service Account 來限制其他人的存取權限,在之後 [Day 28] 如何在 k8s 管理不同的專案 - Namespaces 也會與大家分享如何設置。我們明年見囉~ :tada:

Q&A

依舊歡迎大家給予建議與討論,如果能按個讚給些鼓勵也是很開心唷 : )

參考連結

勘誤

感謝網友 @herb123456 提醒,base64 是一種編碼方式,非加密方式。


上一篇
[Day 11] 如何確保 Container 運行狀態 - Health Checks
下一篇
[Day 13] Demo: 在 minikube 上架設 Stateless Wordpress
系列文
Kubernetes 30天學習筆記30

1 則留言

1
herb123456
iT邦新手 5 級 ‧ 2018-01-21 00:16:50

想請問

3/ 透過 YAML 創建 Secret 物件

其中的 type: Opaque 是什麼意思呢?

還有沒有其他 type 可設定?

另外base64是一種編碼,而不是加密喔

zxcvbnius iT邦新手 5 級 ‧ 2018-01-21 19:34:19 檢舉

hi @herb123456,

1/ 非常感謝!!沒錯 base64 是一種編碼不是加密,打太快了 Orz

2/ Opaque 是代表不透明的意思,相較於 ConfigMap 是用 plain text 的方式儲存,Secret 是用非明碼的方式儲存。事實上 Kubernetes 官方目前也有想計畫的想提供 Secret 除了 base64 的編碼方式,像是 HSMs 等等... 我們可以拭目以待。

3/ 除了這種 kubectl create secret generic 用來存放 API password, SSL key 等敏感資訊以外。Kubernetes Secret 物件也很常使用在存取 Docker Private Registry 上。

Docker Private Registry

過去若我們要從某台機器上從某個 Docker Private Registry 上拉取資料下來,都需要先 docker login 到該 private registry,在登入成功後需透過每台機器上的 ~/.docker/config.json 管理存取該 Private Registry 的資料,然而 Kubernetes Cluster 底下有許多台機器。不太可能每個都做 docker login 指令,因此 Kubernetes 還提供另外一種 Secret type docker-registry ,讓我們可以在每個 Pod 的設定檔中加入這個 docker-registry secret。讓每個 Pod 不論是被分配到哪個 Node 都可以使用這個 secret 從對應的 Docker Private Registry 順利拉下 Docker Image 。

Create a docker-registry secret

創建指令如下,

$ kubectl create secret docker-registry myprivate-registry-key --docker-server {docker-private-registry-host} --docker-username={docker-username} --docker-password={docker-password} --docker-email={docker-account-email}

將該 Secret 加到 Pod 設定檔

以下面 Pod 設定檔為例,

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: webserver
spec:
  containers:
  - name: pod-demo
    image: {docker-private-registry-host}/docker-img
    imagePullPolicy: Always
    ports:
    - containerPort: 3000
  imagePullSecrets:
  - name: myprivate-registry-key

如此,我們就可以從 Docker Private Registry 上拉下該 Docker Image。好處是,當有多個 Docker Private Registries 時,在 Kubernetes 上也可以透過 Secret 管理。

原來如此,真是詳細的解說。

zxcvbnius iT邦新手 5 級 ‧ 2018-01-23 13:11:03 檢舉

(y)

我要留言

立即登入留言