Day 17 - Secret
本日共賞
- Secret
希望你知道
Secret
昨天我們提到了 ConfigMap,Secret 儲存的資料是較為敏感的內容 (密碼、金鑰等等),而 ConfigMap 則是儲存像設定之類較不敏感的資料。Secret 概念上類似 ConfigMap,也是希望將資料與應用程式解耦,除此之外,針對較敏感的資料也能有多一層保護而不隨便曝露。
Secret 有三種類型:
Service Account
:由 k8s 自動建立並掛載到 Pod,用來存取 k8s API 使用,你可以在/run/secrets/kubernetes.io/serviceaccount
目錄中找到Opaque
:以 base64 編碼的 Secret,用來儲存 密碼、金鑰等等docker-registry
:如果映像檔是放在私有的 Registry,就需要使用這種類型的 Secret
你可以嘗試利用 Day 14 - Volume (1) 提到過的
kubectl exec
指令進入 Pod 查看/run/secrets/kubernetes.io/serviceaccount
目錄下的 Secret 物件
Opaque
假設你的應用程式需要存取資料庫,這時候你會需要帳號 (username) 與密碼 (password),所以我們可以建立兩個檔案
$ echo -n "admin" > username.txt <=== -n:不換行輸出
$ echo -n "mypassword" > password.txt
接著建立 Secret 物件
$ kubectl create secret generic db-user-pass \
--from-file=./username.txt \
--from-file=./password.txt
secret "db-user-pass" created
查看一下 Secret 的內容
$ kubectl get secrets <=== 利用 get 查看一下
NAME TYPE DATA AGE
db-user-pass Opaque 2 1m
$ kubectl describe secrets/db-user-pass <=== 利用 describe 查看一下
Name: db-user-pass
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password.txt: 10 bytes
username.txt: 5 bytes
這裡可以發現,無論你是使用 get
或是 describe
都不會顯示 username
與 password
的內容。
如果想要使用 yaml 的方式部署 Secret 請先將內容編碼 (base64) 後再填入 yaml 檔
$ echo -n "admin" | base64 <=== 指定 base64 編碼
YWRtaW4= <=== yaml 需要填入這個
$ echo -n "mypassword" | base64
bXlwYXNzd29yZA==
然後編寫 yaml
# secret.yaml
---
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4= <=== 這裡要記得使用 base64 編碼後的資料
password: bXlwYXNzd29yZA== <=== 這裡要記得使用 base64 編碼後的資料
然後部署到 k8s
$ kubectl apply -f secret.yaml
secret "mysecret" created
建立好 Secret 物件後,要如何使用呢?你可以使用 Day 14 - Volume (1) 提到的 Volume 掛載到 Pod 中使用。
# secret.pod.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: secret-nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /tmp/conf <=== 將綁定 mysecret 的 Volume 掛載到 /tmp/conf 目錄下
name: secret-volume
env: <=== 將綁定的 mysecret 以環境變數的方式掛載
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password <=== 指定綁定哪個 key
volumes:
- name: secret-volume
secret:
secretName: mysecret <=== 指定使用名為 mysecret 的 Secret 物件
部署 secret-nginx
到 k8s
$ kubectl apply -f secret.pod.yaml
pod "secret-nginx" created
這裡示範了兩種掛載 Secret 的方式:
1. 將 Secret 指定到環境變數 DB_PASSWORD
中
$ kubectl exec -it secret-nginx bash <=== 連到 secret-nginx Pod
$ env | grep DB_PASSWORD <=== 檢查環境變數 DB_PASSWORD
DB_PASSWORD=mypassword
2. 將 Secret 以 Volume 形式掛載到 /tmp/conf
$ kubectl exec -it secret-nginx bash <=== 連到 secret-nginx Pod
$ ls /tmp/conf <=== 查詢是否有 username 與 password
password username
因此,如果應用程式需要使用到較敏感的資料,我們就可以利用 Secret 儲存這些資料,等到 Pod 運行之後再將這些資料掛到指定目錄下。這樣做會有幾個好處:
- 避免敏感資料被任意讀取
- 可由管理者統一管理
- 可重複使用
docker-registry
如果你要使用的映像檔不是放在公開的 registry,這時候你就需要使用 docker-registry
類型的 Secret 儲存帳號跟密碼,以便 k8s 可以順利下載映像檔。
使用的格式如下
kubectl create secret docker-registry <name> \
--docker-server=<your-registry-server> \
--docker-username=<your-name> \
--docker-password=<your-pword> \
--docker-email=<your-email>
docker-registry
:指定為docker-registry
形態的 Secret--docker-server
:私有 registry server 位置--docker-username
:Docker 帳號--docker-password
:Docker 密碼--docker-email
:Docker Email
這裡會使用 Docker 私有的映像檔做示範,建議可以去申請一個 Docker 帳號,每個帳號可以有一個免費的私有映像檔。因為,各位總不會這麼殘忍要我提供密碼吧…
這裡先假設大家已經建立好私有的映像檔
因此,我以 Docker Hub 為例,建立一個名為 regsecret
的 Secret 物件。
$ kubectl create secret docker-registry regsecret \
--docker-server=https://index.docker.io/v1/ \
--docker-username=<換成你的> \
--docker-password=<換成你的> \
--docker-email=<換成你的>
secret "regsecret" created
我在 Docker Hub 建立了一個私有映像檔 jlptf/privateapp
,接著修改 yaml 的內容
# private-pod.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: private-reg
spec:
containers:
- name: private-reg
image: jlptf/privateapp <=== 指定使用私有映像檔
imagePullPolicy: Always
imagePullSecrets: <=== 下載映像檔時套用先前建立的 Secret 物件
- name: regsecret
然後部署到 k8s
$ kubectl apply -f private-pod.yaml
pod "private-reg" created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
private-reg 1/1 Running 0 18m
到這裡就表示一切進行順利,k8s 也能夠取得私有映像檔進行配置。所以聰明的各位應該能夠聯想到,如果需要存取同一個私有的 registry,其他部署也可以使用同一個 Secret。
本文與部署檔案同步發表於 https://jlptf.github.io/ironman2018-day17/