k8s往secret里导入证书_k8s中secret解析
概覽
Secret是用來保存小片敏感數據的k8s資源,例如密碼,token,或者秘鑰。這類數據當然也可以存放在Pod或者鏡像中,但是放在Secret中是為了更方便的控制如何使用數據,并減少暴露的風險。
用戶可以創建自己的secret,系統也會有自己的secret。
Pod需要先引用才能使用某個secret,Pod有2種方式來使用secret:作為volume的一個域被一個或多個容器掛載;在拉取鏡像的時候被kubelet引用。
內建的Secrets
由ServiceAccount創建的API證書附加的秘鑰
k8s自動生成的用來訪問apiserver的Secret,所有Pod會默認使用這個Secret與apiserver通信
創建自己的Secret
使用kubectl create secret命令創建Secret
假如mougePod要訪問數據庫,需要用戶名密碼,分別存放在2個文件中:username.txt,password.txt
# Create files needed forrest of example.
$echo -n 'admin' > ./username.txt
$echo -n '1f2d1e2e67df' > ./password.txt
kubectl create secret指令將用戶名密碼寫到secret中,并在apiserver創建Secret
$ kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
secret"db-user-pass" created
查看創建結果:
$ kubectl get secrets
NAME TYPE DATA AGE
db-user-pass Opaque 2 51s
$ kubectl describe secrets/db-user-pass
Name: db-user-pass
Namespace: default
Labels:Annotations:Type: Opaque
Data====password.txt:12bytes
username.txt:5 bytes
get或describe指令都不會展示secret的實際內容,這是出于對數據的保護的考慮,如果想查看實際內容請繼續往下看。
手動創建Secret
創建一個secret.yaml文件,內容用base64編碼
$ echo -n 'admin' |base64
YWRtaW4=$echo -n '1f2d1e2e67df' |base64
MWYyZDFlMmU2N2Rm
yaml文件內容:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=password: MWYyZDFlMmU2N2Rm
創建:
$ kubectl create -f ./secret.yaml
secret"mysecret" created
解析Secret中內容
$ 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解碼:
$ echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
1f2d1e2e67df
使用Secret
secret可以作為數據卷掛載或者作為環境變量暴露給Pod中的容器使用,也可以被系統中的其他資源使用。比如可以用secret導入與外部系統交互需要的證書文件等。
在Pod中以文件的形式使用secret
創建一個Secret,多個Pod可以引用同一個Secret
修改Pod的定義,在spec.volumes[]加一個volume,給這個volume起個名字,spec.volumes[].secret.secretName記錄的是要引用的Secret名字
在每個需要使用Secret的容器中添加一項spec.containers[].volumeMounts[],指定spec.containers[].volumeMounts[].readOnly = true,spec.containers[].volumeMounts[].mountPath要指向一個未被使用的系統路徑。
修改鏡像或者命令行使系統可以找到上一步指定的路徑。此時Secret中data字段的每一個key都是指定路徑下面的一個文件名
下面是一個Pod中引用Secret的列子:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:-name: mypod
image: redis
volumeMounts:-name: foo
mountPath:"/etc/foo"readOnly:truevolumes:-name: foo
secret:
secretName: mysecret
每一個被引用的Secret都要在spec.volumes中定義
如果Pod中的多個容器都要引用這個Secret那么每一個容器定義中都要指定自己的volumeMounts,但是Pod定義中聲明一次spec.volumes就好了。
映射secret key到指定的路徑
可以控制secret key被映射到容器內的路徑,利用spec.volumes[].secret.items來修改被映射的具體路徑
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:-name: mypod
image: redis
volumeMounts:-name: foo
mountPath:"/etc/foo"readOnly:truevolumes:-name: foo
secret:
secretName: mysecret
items:-key: username
path: my-group/my-username
發生了什么呢?
username被映射到了文件/etc/foo/my-group/my-username而不是/etc/foo/username
password沒有變
Secret文件權限
可以指定secret文件的權限,類似linux系統文件權限,如果不指定默認權限是0644,等同于linux文件的-rw-r--r--權限
設置默認權限位
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:-name: mypod
image: redis
volumeMounts:-name: foo
mountPath:"/etc/foo"volumes:-name: foo
secret:
secretName: mysecret
defaultMode:256
上述文件表示將secret掛載到容器的/etc/foo路徑,每一個key衍生出的文件,權限位都將是0400
由于JSON不支持八進制數字,因此用十進制數256表示0400,如果用yaml格式的文件那么就很自然的使用八進制了
同理可以單獨指定某個key的權限
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:-name: mypod
image: redis
volumeMounts:-name: foo
mountPath:"/etc/foo"volumes:-name: foo
secret:
secretName: mysecret
items:-key: username
path: my-group/my-username
mode:511
從volume中讀取secret的值
值得注意的一點是,以文件的形式掛載到容器中的secret,他們的值已經是經過base64解碼的了,可以直接讀出來使用。
$ ls /etc/foo/username
password
$cat /etc/foo/username
admin
$cat /etc/foo/password
1f2d1e2e67df
被掛載的secret內容自動更新
也就是如果修改一個Secret的內容,那么掛載了該Secret的容器中也將會取到更新后的值,但是這個時間間隔是由kubelet的同步時間決定的。最長的時間將是一個同步周期加上緩存生命周期(period+ttl)
特例:以subPath形式掛載到容器中的secret將不會自動更新
以環境變量的形式使用Secret
創建一個Secret,多個Pod可以引用同一個Secret
修改pod的定義,定義環境變量并使用env[].valueFrom.secretKeyRef指定secret和相應的key
修改鏡像或命令行,讓它們可以讀到環境變量
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:-name: mycontainer
image: redisenv:-name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username-name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
restartPolicy: Never
容器中讀取環境變量,已經是base64解碼后的值了:
$ echo$SECRET_USERNAME
admin
$echo$SECRET_PASSWORD
1f2d1e2e67df
使用imagePullSecrets
創建一個專門用來訪問鏡像倉庫的secret,當創建Pod的時候由kubelet訪問鏡像倉庫并拉取鏡像,具體描述文檔在
設置自動導入的imagePullSecrets
可以手動創建一個,然后在serviceAccount中引用它。所有經過這個serviceAccount創建的Pod都會默認使用關聯的imagePullSecrets來拉取鏡像,參考文檔
自動掛載手動創建的Secret
詳情
限制
需要被掛載到Pod中的secret需要提前創建,否則會導致Pod創建失敗
secret是有命名空間屬性的,只有在相同namespace的Pod才能引用它
單個Secret容量限制的1Mb,這么做是為了防止創建超大的Secret導致apiserver或kubelet的內存耗盡。但是創建過多的小容量secret同樣也會耗盡內存,這個問題在將來可能會有方案解決
kubelet只支持由API server創建出來的Pod中引用secret,使用特殊方式創建出來的Pod是不支持引用secret的,比如通過kubelet的--manifest-url參數創建的pod,或者--config參數創建的,或者REST API創建的。
通過secretKeyRef引用一個不存在你secret key會導致pod創建失敗
用例
Pod中的ssh keys
創建一個包含ssh keys的secret
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
創建一個Pod,其中的容器可以用volume的形式使用ssh keys
kind: Pod
apiVersion: v1
metadata:
name: secret-test-pod
labels:
name: secret-test
spec:
volumes:- name: secret-volume
secret:
secretName:ssh-key-secret
containers:- name: ssh-test-container
image: mySshImage
volumeMounts:- name: secret-volume
readOnly:truemountPath:"/etc/secret-volume"
Pod中區分生產和測試證書
創建2種不同的證書,分別用在生產和測試環境
$ kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11
secret"prod-db-secret"created
$ kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests
secret"test-db-secret" created
再創建2個不同的Pod
apiVersion: v1
kind: List
items:-kind: Pod
apiVersion: v1
metadata:
name: prod-db-client-pod
labels:
name: prod-db-client
spec:
volumes:- name: secret-volume
secret:
secretName: prod-db-secret
containers:- name: db-client-container
image: myClientImage
volumeMounts:- name: secret-volume
readOnly:truemountPath:"/etc/secret-volume"
-kind: Pod
apiVersion: v1
metadata:
name: test-db-client-pod
labels:
name: test-db-client
spec:
volumes:- name: secret-volume
secret:
secretName: test-db-secret
containers:- name: db-client-container
image: myClientImage
volumeMounts:- name: secret-volume
readOnly:truemountPath:"/etc/secret-volume"
兩個容器中都會有下列的文件
/etc/secret-volume/username/etc/secret-volume/password
以“.”開頭的key可以產生隱藏文件
kind: Secret
apiVersion: v1
metadata:
name: dotfile-secret
data:
.secret-file: dmFsdWUtMg0KDQo=
---kind: Pod
apiVersion: v1
metadata:
name: secret-dotfiles-pod
spec:
volumes:- name: secret-volume
secret:
secretName: dotfile-secret
containers:- name: dotfile-test-container
image: k8s.gcr.io/busybox
command:- ls
- "-l"
- "/etc/secret-volume"volumeMounts:- name: secret-volume
readOnly:truemountPath:"/etc/secret-volume"
會在掛載目錄下產生一個隱藏文件,/etc/secret-volume/.secret-file
最佳實踐
風險
總結
以上是生活随笔為你收集整理的k8s往secret里导入证书_k8s中secret解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 被质疑“割韭菜” 陈赫回应贤合庄经营纠纷
- 下一篇: 近1英寸恐怖大底加持 小米12 Ultr