iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 13
0
DevOps

從題目中學習k8s系列 第 13

【從題目中學習k8s】-【Day13】第五題 - Secret


title: 【從題目中學習k8s】-【Day13】第五題 - Secret
description: 以無比的恆毅力堅持30天鍊成鐵人--連續30天,一天發表一篇IT技術文章

【從題目中學習k8s】-【Day13】第五題 - Secret

tags: DevOps CICD K8s Docker

Question

Create a kubetnetes Secret as follows:

Name: super-secret

Credential: alice or username:bob

Create a Pod named pod-secrets-via-file using the redis image which mounts a secret named super-secret at /secrets

Create a second Pod named pod-secrets-via-env using the redis image,which exports credential/username as TOPSECRET/CREDENTIALS


概念

這題又來了一個新的東西,叫做Secret,那麼Secret是甚麼呢?

SecretsKubernetes 提供開發者存放敏感資訊的方式。像是密碼、OAuth tokens及 ssh keys。將這些資訊存在放Secret中比直接放在Pod YAML或Image中更加安全和靈活。

Secret使用

要使用Secret,Pod 必須引用Secret。Pod 有三種方式來引用Secret

  • Secret作為容器的環境變數
  • Secret製作為一個檔案,Pod以Volume的形式將此檔案掛載 (mount)到容器上
  • kubelet在為Pod pull Docker Image時使用,透過指定Pod的spec.ImagePullSecrets來參考它 (將Image存放於Private Registry中)

Secret創建

下面介紹如何在集群中創建Secret

1. 以kubeclt創建Secret

kubeclt創建Secret又分為檔案形式命令形式

1.1 檔案形式

將機密資料,例如帳號密碼存在本機端的./username.txt./password.txt檔案中

$ echo -n 'admin' > ./username.txt
$ echo -n '1f2d1e2e67df' > ./password.txt

kubectl create secret generic命令創建Secret

$ kubectl create secret generic <secret-name> --from-file=<file-name> --from-file=<file-name>
## 例如
$ kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
secret "db-user-pass" created

K8s設置默認的key名就是檔案名稱,從上面的例子來看就是username.txt=admin (username.txt是檔名,admin是檔案內容),password.txt=1f2d1e2e67df。你也可以透過--from-file=<key>=<source>來設置key名。

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

你可以用kubectl getkubectl describe查看創建的Secret,但是會發現帳號密碼無法顯示,只會顯示 Secret 的 bytes數,這是為了防止機密資料暴露給旁觀者或存在系統log中。

1.2 命令形式

$ kubectl create secret generic <secret-name> --from-literal=<key>=<value>
## 例如
$ kubectl create secret generic test-secret --from-literal=DB_User=root \
--from-literal=DB_Password=toor

2. 以YAML創建Secret

寫一個Secret的YAML,範例如下:

$ cat secret.yaml

apiVersion: v1
kind: Secret
metadata: 
  name: test-secret
data:
  DB_Host: mysql
  DB_User: root
  DB_Password: toor

但若直接create這個 Secret,會發現有error,這是因為Secret是保存隱密的資料,所以Secret會將data以 base64 的方式編碼,所以需要先把 data 轉成 base64 的格式:

$ cat secret.yaml

apiVersion: v1
kind: Secret
metadata: 
  name: test-secret
data:
  DB_Host: bXlzcWw=
  DB_User: cm9vdA==
  DB_Password: dG9vcg==

base64 編碼指令:
echo -n "<string-want-to-encode>" | base64
base64 解碼指令:
echo -n "<string-want-to-decode>" | base64 --decode

將資料編碼完成後,再將Secret創立

kubectl apply -f secret-def.yaml

Secret掛載

Secret掛載是我們前面提到使用Secret的其中兩種方式,那麼具體要如何操作呢?我們往下看~

1. 將Secret作為容器的環境變數

這種方法比較簡單,直接在Pod中以spec.env.valueFrom.secretKeyRef欄位參考到Secret即可。例如:

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

創建完成後,進入該容器並輸入相關指令即可看到Secret的設置結果

2. 將Secret製作為一個檔案,Pod以Volume的形式將此檔案掛載(mount)到容器上

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

這邊會用到volume的概念,但是我們還沒介紹過,所以大家有個印象Secret能透過這種方式使用即可,後面我們會再介紹到的~


Secret就介紹到這裡啦~ 我們回到題目。
有了Secret概念後這題應該就看得懂了,解題方法如下:

  1. 首先,創建一個Secret
  2. 接著創建兩個Pod
  3. 其中一個Podmount此Secret,另一個Pod將Secret作為環境變數使用

Answer

創建Secret

$ kubectl create secret generic super-secret --from-literal=credentail=alice --from-literal=username=bob

Pod 1

$ kubectl run pod-secrets-via-file --image=redis --dry-run=client -o yaml > q5-1-pod.yaml

$ vim q5-1-pod.yaml

apiVersion: v1    
kind: Pod 
metadata:
  creationTimestamp: null
  labels:
    run: pod-secrets-via-file
  name: pod-secrets-via-file
spec:
  containers:
  - image: redis
    name: pod-secrets-via-file
    resources: {}
    volumeMounts:
    - name: foo
      mountPath: /secrets
  volumes:
  - name: foo
    secret:
      secretName: super-secret
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

Pod 2

$ kubectl run pod-secrets-via-env --image=redis --dry-run=client -o yaml > q5-2-pod.yaml

$ vim q5-2-pod.yaml

apiVersion: v1             
kind: Pod 
metadata:
  creationTimestamp: null
  labels:
    run: pod-secrets-via-env
  name: pod-secrets-via-env
spec:
  containers:
  - image: redis
    name: pod-secrets-via-env
    resources: {}
    env: 
    - name: TOPSECRET
      valueFrom:
        secretKeyRef:
          name: super-secret
          key: credential
    - name: CREDENTIALS
      valueFrom:
        secretKeyRef:
          name: super-secret
          key: username
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

最後創建這兩個Pod

$ kubectl apply -f q5-1-pod.yaml q5-2-pod.yaml

結論

這題的考點在Secret,而且Secret應用的兩種方式一次在這題中出現,稍微麻煩一點,需要創建兩個以上的YAML文件,但是只要能掌握Secret的創建方式和使用方式就應該沒太大問題!好啦,今天就到這囉~ 謝謝大家~

參考資料

Secrets
敏感的資料怎麼存在k8s?! - Secrets
Kubernetes — Secret

Thank you!

You can find me on

  • george4908090@gmail.com

上一篇
【從題目中學習k8s】-【Day12】第四題 - Pod & Namespace
下一篇
【從題目中學習k8s】-【Day14】第六題 - etcd backup
系列文
從題目中學習k8s31

1 則留言

0
00886093302
iT邦新手 5 級 ‧ 2021-04-02 09:15:41

credentail credential 好像有寫錯
Error: couldn't find key credential in Secret default/super-secret
應該是credential

我要留言

立即登入留言