官網文件:
https://kubernetes.io/docs/concepts/configuration/secret/
官網文件的最後面,因為覺得很重要,所以放到前面來
往往因為時程壓力,會用新工具就很厲害了,趕快交差了事
殊不知,離安全還有很長的路…
即使api server設不允許,有權限建pod的user,可以透過建一個mount secret的pod來看到裡面的資料
secrets用來放一些機敏設定、帳號密碼之類的,
也可以餵serets吃檔案
# 產生範例檔
$ echo -n 'admin' > ./username.txt
$ echo -n '1f2d1e2e67df' > ./password.txt
# db-user-pass是object name
# 另外還可以設定:Namespace(預設是default)、Labels、Annotations
# 餵secrets吃檔案
$ kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
secret "db-user-pass" created
# 加完後看一下
$ kubectl get secrets # 查secrets object
$ kubectl describe secrets/db-user-pass # 進一步列出db-user-pass放多少data
#也可以每次加1個
$ kubectl create secret generic mysql-pass --from-literal=password=YOUR_PASSWORD
# 轉成base64編碼
$ echo -n 'admin' | base64
YWRtaW4=
$ echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm
# 換行字元
# macOS: 避免使用 -b 來拆行
# Linux: 應該加-w 0,或者試試 base64 | tr -d '\n'
# 寫一個secret object(yaml語法)
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
# 建Secret,這裡的mysecret是SECRET OBJECT NAME,就像上面的db-user-pass
$ kubectl create -f ./secret.yaml
secret "mysecret" created
# 先輸出成yaml
$ kubectl get secret mysecret -o yaml
apiVersion: v1
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
kind: Secret
metadata:
creationTimestamp: 2016-01-22T18:41:56Z
name: mysecret
namespace: default
resourceVersion: "164619"
selfLink: /api/v1/namespaces/default/secrets/mysecret
uid: cfee02d6-c137-11e5-8d73-42010af00002
type: Opaque
# 因為你是存base64進去,現在看到也是base64:MWYyZDFlMmU2N2Rm
# 轉碼
$ echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
1f2d1e2e67df
官網的說明我也看不懂,我們直接看範例吧:
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: # 在volume裡面mount一個secret object
secretName: mysecret # secret object name
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: # 掛載後,可在 .spec.volumes[].secret.items 中使用
- key: username
path: my-group/my-username # username 會存在/etc/foo/my-group/my-username
# 因為只有設定username,並沒有設定password,所以password就沒有(projected)
volumes:
- name: foo
secret:
secretName: mysecret
defaultMode: 0777
# 也可以用8進位,但JSON不支援8進位表示法
預設是0644,可以設定整個secret volume的權限(中央),細項(地方)再另外設權限
代表10進位 USER(owner) GROUP OTHER USER
0 6 4 4
1:excute
2:write
3:write,excute
4:read
5:read,excute
6:read,write
7:read,write,excute
3個bit,例如:「6」 轉 2進位 => 1(可讀) 1(可寫) 0(不能執行)
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: mycontainer
image: redis
env: # 用在環境變數
- name: SECRET_USERNAME
valueFrom:
secretKeyRef: # secret key reference,就可使用: env[].valueFrom.secretKeyRef
name: mysecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
restartPolicy: Never
# 這樣環境變數就能用囉
$ echo $SECRET_USERNAME
$ echo $SECRET_PASSWORD
# 注意:放在secret的話,cluster管理者可能都能拿到
$ kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub
- name: ssh-test-container
image: mySshImage
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
# 然後,就可以把ssh key掛到pod
/etc/secret-volume/ssh-publickey
/etc/secret-volume/ssh-privatekey
備註:
如果在--from-literal中,你的密碼的有特殊符號
$,!,前面加\,變成\$、\!
*,一樣前面加\,變成\*
例如:S!B*d$zDsb,變成S\!B\*d\$zDsb
$ kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password=S\\!B\\\*d\\$zDsb
kind: Secret
apiVersion: v1
metadata:
name: dotfile-secret
data:
.secret-file: dmFsdWUtMg0KDQo=
---
...中間略...
containers:
- name: dotfile-test-container
image: k8s.gcr.io/busybox
command:
- ls
- "-l"
- "/etc/secret-volume"
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
# 這樣在container dotfile-test-container裡面的
# /etc/secret-volume/.secret-file 就有這個檔案
參考文件:
https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/
https://k8smeetup.github.io/docs/tasks/configure-pod-container/configmap/#使用kubectl创建configmap
也是非常重要的主題,放在後面是怕你學完ConfigMap就懶得學Secrets了
(管他資料重不重要,時程壓力,全放ConfigMap就好了 = =)
利用ConfigMap讓config跟image解耦
兩者很類似,pod跑起來後,就像mount volume
Secrets:機敏資料
ConfigMap:不是密秘的Configuration parameters
特色:
key-value pairs
Kubernetes建置與執行,第11章,ConfigMap和Secret
雖然資訊的書不太需要買,由其是Kubernetes變化這麼快的東西
平常主要還是以官網-kubernetes.io/docs為主,
但是當有哪個主題不太清楚的時候還是可以翻書
這一本書可以買喔,比較固定、基礎的元件都有(可以幫助初學者)
基本指令:
$ kubectl create configmap <map-name> <data-source>(key-value)
官網的文件看不太懂,借課本範例:
$ kubectl create configmap my-config # 你的config map name
# 餵單一檔案
--from-file=my-config.txt # 餵檔案,檔案的形式是key-value
# 也可以給目錄,這個目錄底下的檔案都會餵進去,每個檔案對應到下面的data:
--from-file=configmap/myconfigfile/
--from-literal=extra-param=extra-value # 你也可以在指令加進去
kubectl get configmaps my-config -o yaml
# 輸出的yaml類似下面這樣
apiVersion: v1
data: # 想像成my-cofig/這個目錄裡面的檔案
another-param: another-value # 前面的another-param是key,掛到pod後是一個檔案
my-config.txt: | # 好像餵檔案的就會有| # key,掛到pod後是一個檔案
parameter1 = value1 # 檔案裡的content
parameter2 = value2
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T18:52:05Z
name: my-config # 想像成一個目錄
namespace: default
resourceVersion: "516"
selfLink: /api/v1/namespaces/default/configmaps/my-config
uid: b4952dc3-d670-11e5-8cd0-68f712354985
# busybox-config.yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox-config
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command:
- "/bin/sh"
- "-c"
- "env"
# 也可以寫成一行 command: [ "/bin/sh", "-c", "env" ]
# 也可以在command直接用 $(ANOTHER-PARAM)
env:
- name: ANOTHER-PARAM
valueFrom:
configMapKeyRef:
name: my-config # 你的ConfigMap Object Name
key: another-param # 上面yaml的data:裡面的key,在container看會是一個檔案
volumeMounts:
- name: config-volume # 參考到下面volumes裡的資源
mountPath: /config # 掛到container裡的哪個目錄
volumes:
-name: config-volume
configMap:
name: my-config # 你的ConfigMap Object Name
restartPolicy: Never
$ kubectl apply -f busybox-config.yaml
# 建個目錄
$ mkdir -p configure-pod-container/configmap/kubectl/
# 把檔案game.properties、ui.properties下載到configure-pod-container/configmap/kubectl/
# 可以想像成是原本config檔
$ wget https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl/game.properties -O configure-pod-container/configmap/kubectl/game.properties
$ wget https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl/ui.properties -O configure-pod-container/configmap/kubectl/ui.properties
# 建一個ConfigMap Object: game-config
# 把configure-pod-container/configmap/kubectl/裡的檔案餵進去
$ kubectl create configmap game-config --from-file=configure-pod-container/configmap/kubectl/
$ kubectl describe configmaps game-config
Name: game-config
Namespace: default
Labels: <none>
Annotations: <none>
Data # 在這裡
====
game.properties: 158 bytes # 這個叫key,內容沒列出來
ui.properties: 83 bytes
$ kubectl get configmaps game-config -o yaml
# yaml內容類似如下:
apiVersion: v1
data:
game.properties: | # key
enemies=aliens # 內容 content
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T18:52:05Z
name: game-config # ConfigMap Object Name
namespace: default
resourceVersion: "516"
selfLink: /api/v1/namespaces/default/configmaps/game-config # 用api方式的url
uid: b4952dc3-d670-11e5-8cd0-68f728db1985
$ kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/kubectl/game.properties
$ kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/kubectl/ui.properties
# 下載範例檔
$ wget https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl/game-env-file.properties -O configure-pod-container/configmap/kubectl/game-env-file.properties
$ cat configure-pod-container/configmap/kubectl/game-env-file.properties
enemies=aliens # 也是key-value
lives=3
allowed="true"
$ kubectl create configmap game-config-env-file \
--from-env-file=configure-pod-container/configmap/kubectl/game-env-file.properties
# 看看yaml檔
$ kubectl get configmap game-config-env-file -o yaml
apiVersion: v1
data: # game-env-file.properties裡面的資料就全進來了,而且在最上層
allowed: '"true"' # string,外面用單引號'
enemies: aliens
lives: "3" # 數字也視為string ?
kind: ConfigMap
metadata:
creationTimestamp: 2017-12-27T18:36:28Z
name: game-config-env-file # ConfigMap Object Name
namespace: default
resourceVersion: "809965"
selfLink: /api/v1/namespaces/default/configmaps/game-config-env-file
uid: d9d1ca5b-eb34-11e7-887b-42010a8002b8
$ wget https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl/ui-env-file.properties -O configure-pod-container/configmap/kubectl/ui-env-file.properties
$ kubectl create configmap config-multi-env-files \
--from-env-file=configure-pod-container/configmap/kubectl/game-env-file.properties \
--from-env-file=configure-pod-container/configmap/kubectl/ui-env-file.properties
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "env" ]
# envFrom參考進來後,就能直接用環境變數囉,$(SPECIAL_LEVEL_KEY)
command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
# 也可以用envFrom
envFrom:
- configMapRef: # 參考整個Config Map Object
name: special-config
# 假設要參考到2個以上的ConfigMap Object,而且是指定到key(不是整個object都參考)
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef: # 顧名思義,就是參考 Config Map Object的某個key的item
name: special-config # 第1個object
key: special.how
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: env-config # 第1個object
key: log_level
restartPolicy: Never
一回生、二回熟,勇者們,衝呀呀呀~~~
再來看另一篇官網的教學範例:
https://kubernetes.io/docs/tutorials/configuration/
# 先下載練習用的redis-config
$ curl -OL https://k8s.io/examples/pods/config/redis-config
# 從redis-config建立1個configmap
$ kubectl create configmap example-redis-config --from-file=redis-config
configmap/example-redis-config created
# 把example-redis-config輸出成yaml檔
$ kubectl get configmap example-redis-config -o yaml
apiVersion: v1
data:
redis-config: |
maxmemory 2mb
maxmemory-policy allkeys-lru
kind: ConfigMap
metadata:
creationTimestamp: 2016-03-30T18:14:41Z
name: example-redis-config
namespace: default
resourceVersion: "24686"
selfLink: /api/v1/namespaces/default/configmaps/example-redis-config
uid: 460a2b6e-f6a3-11e5-8ae5-42010af00002
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: kubernetes/redis:v1
env:
- name: MASTER
value: "true"
ports:
- containerPort: 6379
resources:
limits:
cpu: "0.1"
volumeMounts:
- mountPath: /redis-master-data # 空目錄
name: data
- mountPath: /redis-master # config volume 掛載目錄
name: config
volumes:
- name: data
emptyDir: {}
- name: config
configMap: # configmap
name: example-redis-config # 上面產生的
items:
- key: redis-config # example-redis-config裡面的其中一個data:redis-config
path: redis.conf
最後在container裡面會有這個檔案:
$ kubectl create -f https://k8s.io/examples/pods/config/redis-pod.yaml
$ kubectl exec -it redis redis-cli
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "2097152"
127.0.0.1:6379> CONFIG GET maxmemory-policy
1) "maxmemory-policy"
2) "allkeys-lru"
呼,終於看懂了@@~
因為時間太短,文章都很亂,真的很不好意思
英文程度好的大大們,就大概了解後直接看官網文件囉