k8s配置中心-configmap,Secret密碼
- 2021 年 12 月 9 日
- 筆記
k8s配置中心-configmap,Secret
在生產環境中經常會遇到需要修改配置文件的情況,傳統的修改方式不僅會影響到服務的正常運行,而且操作步驟也很繁瑣。為了解決這個問題,kubernetes項目從1.2版本引入了ConfigMap功能,用於將應用的配置資訊與程式的分離。這種方式不僅可以實現應用程式被的復用,而且還可以通過不同的配置實現更靈活的功能。在創建容器時,用戶可以將應用程式打包為容器鏡像後,通過環境變數或者外接掛載文件的方式進行配置注入。ConfigMap && Secret 是K8S中的針對應用的配置中心,它有效的解決了應用掛載的問題,並且支援加密以及熱更新等功能,可以說是一個k8s提供的一件非常好用的功能。
創建ConfigMap
# 創建名稱空間
apiVersion: v1
kind: Namespace
metadata:
name: sg-bs
labels:
app: sg-bs
---
# ConfigMap是名稱空間級資源
apiVersion: v1
kind: ConfigMap
metadata:
name: test-configmap
namespace: sg-bs
data: # 健 : 值
level: debug
使用ConfigMap
## 使用掛載方式,將配置文件掛載到容器中
# 使用
kind: Deployment
apiVersion: apps/v1
metadata:
name: nginx-config
spec:
selector:
matchLabels:
app: nginx-config
template:
metadata:
labels:
app: nginx-config
spec:
containers:
- name: nginx
image: nginx
volumeMounts: # 掛載
- mountPath: /etc/nginx/conf.d # 掛載路徑
name: nginx-config-configmap # 存儲卷名字
volumes:
- name: nginx-config
persistentVolumeClaim:
claimName: nginx-config
- name: nginx-config-configmap
configMap:
name: test-configmap # ConfigMap名字
items:
- key: level
path: level # 最終路徑為:/etc/nginx/conf.d/level
subPath參數
# configmap熱更新
## 修改configmap中的文件,可以同步到所有的掛載此configmap的容器中(僅僅同步到容器中),但是如果使用subPath參數,則熱更新失效。
## configMap掛載會直接覆蓋原來的目錄,如果不覆蓋則需要使用subPath參數(subPath參數只能夠針對文件,同時不支援熱更新)
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
default.conf: |
server {
listen 80;
listen [::]:80;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.php;
}
location ~ \.php$ {
root /usr/share/nginx/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
}
index.php: |
<?php
phpinfo();
?>
---
kind: Service
apiVersion: v1
metadata:
name: nginx-config
spec:
ports:
- port: 80
targetPort: 80
nodePort: 30089
selector:
app: nginx-config
type: NodePort
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: nginx-config
spec:
selector:
matchLabels:
app: nginx-config
template:
metadata:
labels:
app: nginx-config
spec:
containers:
- name: php
image: alvinos/php:wordpress-v2
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nginx-config-configmap
- name: nginx
image: alvinos/nginx:wordpress-v2
volumeMounts:
- mountPath: /usr/share/nginx/html/index.php
name: nginx-config-configmap
subPath: index.php
- mountPath: /etc/nginx/conf.d
name: nginx-config-configmap
volumes:
- name: nginx-config-configmap
configMap:
name: nginx-config
items:
- key: index.php
path: index.php
Secret
Secret解決了密碼、token、密鑰等敏感數據的配置問題,而不需要把這些敏感數據暴露到鏡像或者Pod Spec中。Secret可以以Volume或者環境變數的方式使用。
Secret用來保存敏感數據,保存之前就必須將文件進行base64加密,掛載到pod中,自動解密。
默認使用Opaque類型。
Secret有四種類型:
Service Account :用來訪問Kubernetes API,由Kubernetes自動創建,並且會自動掛載到Pod的/run/secrets/kubernetes.io/serviceaccount目錄中;
Opaque :base64編碼格式的Secret,用來存儲密碼、密鑰等;
kubernetes.io/dockerconfigjson :用來存儲私有docker registry的認證資訊
tls類型:訪問證書
官方文檔
//kubernetes.io/zh/docs/concepts/configuration/secret/
編寫secret清單
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: YWRtaW4xMjMK
username: YWRtaW4K
使用secret
Secret 可以作為數據卷被掛載,或作為環境變數 暴露出來以供 Pod 中的容器使用。它們也可以被系統的其他部分使用,而不直接暴露在 Pod 內。 例如,它們可以保存憑據,系統的其他部分將用它來代表你與外部系統進行交互。
在 Pod 中使用 Secret 文件
在 Pod 中使用存放在卷中的 Secret:
- 創建一個 Secret 或者使用已有的 Secret。多個 Pod 可以引用同一個 Secret。
- 修改你的 Pod 定義,在
spec.volumes[]下增加一個卷。可以給這個卷隨意命名, 它的spec.volumes[].secret.secretName必須是 Secret 對象的名字。 - 將
spec.containers[].volumeMounts[]加到需要用到該 Secret 的容器中。 指定spec.containers[].volumeMounts[].readOnly = true和spec.containers[].volumeMounts[].mountPath為你想要該 Secret 出現的尚未使用的目錄。 - 修改你的鏡像並且/或者命令行,讓程式從該目錄下尋找文件。 Secret 的
data映射中的每一個鍵都對應mountPath下的一個文件名。
這是一個在 Pod 中使用存放在掛載卷中 Secret 的例子:
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
您想要用的每個 Secret 都需要在 spec.volumes 中引用。
如果 Pod 中有多個容器,每個容器都需要自己的 volumeMounts 配置塊, 但是每個 Secret 只需要一個 spec.volumes。
您可以打包多個文件到一個 Secret 中,或者使用的多個 Secret,怎樣方便就怎樣來。
將 Secret 鍵名映射到特定路徑
我們還可以控制 Secret 鍵名在存儲卷中映射的的路徑。 你可以使用 spec.volumes[].secret.items 欄位修改每個鍵對應的目標路徑:
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:
- key: username
path: my-group/my-username
將會發生什麼呢:
usernameSecret 存儲在/etc/foo/my-group/my-username文件中而不是/etc/foo/username中。passwordSecret 沒有被映射
如果使用了 spec.volumes[].secret.items,只有在 items 中指定的鍵會被映射。 要使用 Secret 中所有鍵,就必須將它們都列在 items 欄位中。 所有列出的鍵名必須存在於相應的 Secret 中。否則,不會創建卷。
Secret 文件許可權
你還可以指定 Secret 將擁有的許可權模式位。如果不指定,默認使用 0644。 你可以為整個 Secret 卷指定默認模式;如果需要,可以為每個密鑰設定重載值。
例如,您可以指定如下默認模式:
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 目錄,而所有通過該 Secret 卷掛載 所創建的文件的許可權都是 0400。
請注意,JSON 規範不支援八進位符號,因此使用 256 值作為 0400 許可權。 如果你使用 YAML 而不是 JSON,則可以使用八進位符號以更自然的方式指定許可權。
注意,如果你通過 kubectl exec 進入到 Pod 中,你需要沿著符號鏈接來找到 所期望的文件模式。例如,下面命令檢查 Secret 文件的訪問模式:
kubectl exec mypod -it sh
cd /etc/foo
ls -l
輸出類似於:
total 0
lrwxrwxrwx 1 root root 15 May 18 00:18 password -> ..data/password
lrwxrwxrwx 1 root root 15 May 18 00:18 username -> ..data/username
沿著符號鏈接,可以查看文件的訪問模式:
cd /etc/foo/..data
ls -l
輸出類似於:
total 8
-r-------- 1 root root 12 May 18 00:18 password
-r-------- 1 root root 5 May 18 00:18 username
你還可以使用映射,如上一個示例,並為不同的文件指定不同的許可權,如下所示:
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
在這裡,位於 /etc/foo/my-group/my-username 的文件的許可權值為 0777。 由於 JSON 限制,必須以十進位格式指定模式,即 511。
請注意,如果稍後讀取此許可權值,可能會以十進位格式顯示。
使用來自卷中的 Secret 值
在掛載了 Secret 卷的容器內,Secret 鍵名顯示為文件名,並且 Secret 的值 使用 base-64 解碼後存儲在這些文件中。 這是在上面的示例容器內執行的命令的結果:
ls /etc/foo/
輸出類似於:
username
password
cat /etc/foo/username
輸出類似於:
admin
cat /etc/foo/password
輸出類似於:
1f2d1e2e67df
容器中的程式負責從文件中讀取 secret。
