configmap
Kubernetes有兩種類型的對象,它們可以在啟動時将配置資料注入到容器中:Secrets和ConfigMaps。 密碼和ConfigMap在Kubernetes中的行為類似,兩者的建立方式以及因為它們可以作為已裝載的檔案或卷或環境變量在容器内部公開。
要探索Secrets和ConfigMap,請考慮以下情形:
您正在Kubernetes中運作官方的MariaDB容器映像 ,并且必須進行一些配置才能使容器運作。 該映像需要為MYSQL_ROOT_PASSWORD , MYSQL_ALLOW_EMPTY_PASSWORD或MYSQL_RANDOM_ROOT_PASSWORD設定環境變量以初始化資料庫。 它還允許擴充到MySQL配置檔案my.cnf中通過将自定義配置檔案/etc/mysql/conf.d。
您可以建構自定義映像,設定環境變量并将配置檔案複制到其中,以建立定制的容器映像。 但是,最好的做法是建立和使用通用映像并将配置添加到由此映像建立的容器中。 這是ConfigMap和Secrets的完美用例。 可以在Secret中設定MYSQL_ROOT_PASSWORD ,并将其作為環境變量添加到容器中,并且可以将配置檔案存儲在ConfigMap中,并在啟動時作為檔案安裝到容器中。
讓我們嘗試一下!
但首先:關于Kubectl的快速說明
確定您的kubectl client指令版本與正在使用的Kubernetes叢集版本相同或較新。
出現以下錯誤:
可能意味着用戶端版本太舊,需要更新。 用于安裝Kubectl的Kubernetes文檔包含在各種平台上安裝最新用戶端的說明。
如果您使用的是Mac的Docker,它還會安裝自己的版本的kubectl ,這可能就是問題所在。 您可以使用brew install安裝目前用戶端,替換與Docker附帶的用戶端的符号連結:
$
rm
/ usr
/ local
/ bin
/ kubectl
$ brew
link
--overwrite kubernetes-cli
較新的kubectl用戶端應繼續使用Docker的Kubernetes版本。
機密
機密是一個Kubernetes對象,旨在存儲少量敏感資料。 值得注意的是,密鑰是在Kubernetes中以base64編碼存儲的,是以它們并不是絕對安全的。 確定具有适當的基于角色的通路控制 (RBAC),以保護對Secrets的通路。 即使這樣,也應該使用HashiCorp Vault之類的東西來存儲極其敏感的Secrets資料。 但是,對于MariaDB資料庫的root密碼,base64編碼就可以了。
手動建立秘密
要建立包含MYSQL_ROOT_PASSWORD的Secret,請選擇一個密碼并将其轉換為base64:
# The root password will be "KubernetesRocks!"
$
echo
-n
'KubernetesRocks!'
| base64
S3ViZXJuZXRlc1JvY2tzIQ ==
記下編碼的字元串。 您需要它來為Secret建立YAML檔案:
apiVersion
: v1
kind
: Secret
metadata :
name
: mariadb-root-password
type
: Opaque
data :
password
: S3ViZXJuZXRlc1JvY2tzIQ==
将檔案另存為mysql-secret.yaml并使用kubectl apply指令在Kubernetes中建立Secret:
$ kubectl apply
-f mysql-secret.yaml
secret
/ mariadb-root-password created
檢視新建立的秘密
現在,您已經建立了Secret,使用kubectl describe可以看到它:
$ kubectl describe secret mariadb-root-password
Name: mariadb-root-password
Namespace: secrets-and-configmaps
Labels:
< none
>
Annotations:
Type: Opaque
Data
====
password:
16 bytes
請注意,“ 資料”字段包含您在YAML: password中設定的密鑰。 配置設定給該密鑰的值是您建立的密碼,但不會在輸出中顯示。 取而代之的是,該值的大小顯示在其位置,在這種情況下為16個位元組。
您還可以使用kubectl edit secret <secretname>指令檢視和編輯Secret。 如果您編輯“機密”,将會看到類似以下内容:
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
password:
S3ViZXJuZXRlc1JvY2tzIQ ==
kind: Secret
metadata:
annotations:
kubectl.kubernetes.io
/ last-applied-configuration:
|
{
"apiVersion" :
"v1" ,
"data" :
{
"password" :
"S3ViZXJuZXRlc1JvY2tzIQ=="
} ,
"kind" :
"Secret" ,
"metadata" :
{
"annotations" :
{
} ,
"name" :
"mariadb-root-password" ,
"namespace" :
"secrets-and-configmaps"
} ,
"type" :
"Opaque"
}
creationTimestamp:
2019 -05-29T12:06:09Z
name: mariadb-root-password
namespace: secrets-and-configmaps
resourceVersion:
"85154772"
selfLink:
/ api
/ v1
/ namespaces
/ secrets-and-configmaps
/ secrets
/ mariadb-root-password
uid: 2542dadb-820a-11e9-ae24-005056a1db05
type: Opaque
同樣,帶有密碼密鑰的資料字段是可見的,這一次您可以看到base64編碼的Secret。
解密秘密
假設您需要以純文字格式檢視“機密”,例如,驗證機密是用正确的内容建立的。 您可以通過解碼來實作。
通過提取值并将其管道傳輸到base64,可以很容易地對Secret進行解碼。 在這種情況下,将使用輸出格式-o jsonpath = <path>來使用JSONPath模闆僅提取Secret值。
# Returns the base64 encoded secret string
$ kubectl get secret mariadb-root-password
-o
jsonpath =
'{.data.password}'
S3ViZXJuZXRlc1JvY2tzIQ ==
# Pipe it to `base64 --decode -` to decode:
$ kubectl get secret mariadb-root-password
-o
jsonpath =
'{.data.password}'
| base64
--decode -
KubernetesRocks
!
建立秘密的另一種方法
您也可以使用kubectl create secret指令直接建立Secrets。 MariaDB映像允許通過設定MYSQL_USER和MYSQL_PASSWORD環境變量來使用密碼設定普通資料庫使用者。 一個Secret可以容納多個鍵/值對,是以您可以建立一個Secret來容納兩個字元串。 另外,通過使用kubectl create secret ,您可以讓Kubernetes與base64混淆,這樣您就不必這樣做了。
$ kubectl create secret generic mariadb-user-creds \
--from-literal =
MYSQL_USER =kubeuser\
--from-literal =
MYSQL_PASSWORD =kube-still-rocks
secret
/ mariadb-user-creds created
注意--from-literal ,它将鍵名和值全部設定為一個。 您可以根據需要傳遞多個--from-literal參數,以便在Secret中建立一個或多個鍵/值對。
使用kubectl get secrets指令驗證使用者名和密碼是否已正确建立和存儲:
# Get the username
$ kubectl get secret mariadb-user-creds
-o
jsonpath =
'{.data.MYSQL_USER}'
| base64
--decode -
kubeuser
# Get the password
$ kubectl get secret mariadb-user-creds
-o
jsonpath =
'{.data.MYSQL_PASSWORD}'
| base64
--decode -
kube-still-rocks
ConfigMaps
ConfigMap與Secrets類似。 可以使用相同的方法在容器中建立和共享它們。 它們之間的唯一最大差別是對base64編碼的混淆。 ConfigMap用于非敏感資料(配置資料),例如配置檔案和環境變量,并且是從通用容器映像建立自定義運作服務的好方法。
建立一個ConfigMap
可以使用與Secrets相同的方式來建立ConfigMap。 您可以手動編寫ConfigMap的YAML表示并将其加載到Kubernetes中,也可以使用kubectl create configmap指令從指令行建立它。 下面的示例使用後一種方法建立ConfigMap,但不傳遞文字字元串(如上述Secret中的--from-literal = <key> = <string> ),而是從現有檔案(MySQL)中建立ConfigMap。旨在用于容器中的/etc/mysql/conf.d的配置。 此配置檔案将覆寫MariaDB預設設定為16M的max_allowed_packet設定。
首先,建立一個名為max_allowed_packet.cnf的檔案,其内容如下:
[mysqld]
max_allowed_packet = 64M
這将覆寫my.cnf檔案中的預設設定,并将max_allowed_packet設定為64M。
建立檔案後,您可以使用包含檔案的kubectl create configmap指令建立名為mariadb-config的ConfigMap:
$ kubectl create configmap mariadb-config
--from-file =max_allowed_packet.cnf
configmap
/ mariadb-config created
就像Secrets一樣,ConfigMap将一個或多個鍵/值對存儲在對象的Data哈希中。 預設情況下,使用--from-file = <檔案名> (如上)會将檔案的内容存儲為值,并将檔案名存儲為鍵。 從組織的角度來看這很友善。 但是,也可以顯式設定鍵名。 例如,如果在建立ConfigMap時使用--from-file = max-packet = max_allowed_packet.cnf ,則密鑰為max-packet,而不是檔案名。 如果您有多個檔案要存儲在ConfigMap中,則可以使用附加的--from-file = <filename>參數添加每個檔案 。
檢視新的ConfigMap并讀取資料
如前所述,ConfigMap并不是要存儲敏感資料,是以在建立ConfigMap時不會對資料進行編碼。 這使得檢視和驗證資料以及直接對其進行編輯變得容易。
首先,驗證是否确實建立了ConfigMap:
$ kubectl get configmap mariadb-config
NAME DATA AGE
mariadb-config
1 9m
可以使用kubectl describe指令檢視ConfigMap的内容。 請注意,檔案的全部内容都是可見的,并且鍵名實際上是檔案名max_allowed_packet.cnf 。
$ kubectl describe cm mariadb-config
Name: mariadb-config
Namespace: secrets-and-configmaps
Labels:
< none
>
Annotations:
< none
>
Data
====
max_allowed_packet.cnf:
----
[ mysqld
]
max_allowed_packet = 64M
Events:
< none
>
可以使用kubectl edit指令在Kubernetes中實時編輯 ConfigMap。 這樣做将使用預設編輯器打開一個緩沖區,該編輯器将ConfigMap的内容顯示為YAML。 儲存更改後,它們将立即在Kubernetes中生效。 盡管這并不是最佳實踐,但它可以友善地測試開發中的事物。
假設您希望max_allowed_packet值為32M,而不是max_allowed_packet.cnf檔案中的預設16M或64M。 使用kubectl edit configmap mariadb-config編輯值:
$ kubectl edit configmap mariadb-config
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
max_allowed_packet.cnf:
|
[ mysqld
]
max_allowed_packet = 32M
kind: ConfigMap
metadata:
creationTimestamp:
2019 -05-30T12:02:22Z
name: mariadb-config
namespace: secrets-and-configmaps
resourceVersion:
"85609912"
selfLink:
/ api
/ v1
/ namespaces
/ secrets-and-configmaps
/ configmaps
/ mariadb-config
uid: c83ccfae-82d2-11e9-832f-005056a1102f
儲存更改後,确認資料已更新:
# Note the '.' in max_allowed_packet.cnf needs to be escaped
$ kubectl get configmap mariadb-config
-o
"jsonpath={.data['max_allowed_packet\.cnf']}"
[ mysqld
]
max_allowed_packet = 32M
使用機密和ConfigMap
Secret和ConfigMap可以作為環境變量或容器中的檔案安裝。 對于MariaDB容器,您需要将Secrets挂載為環境變量,将ConfigMap挂載為檔案。 但是,首先,您需要編寫一個MariaDB部署,以便您可以使用。 使用以下指令建立一個名為mariadb-deployment.yaml的檔案:
apiVersion
: apps/v1
kind
: Deployment
metadata :
labels :
app
: mariadb
name
: mariadb-deployment
spec :
replicas
: 1
selector :
matchLabels :
app
: mariadb
template :
metadata :
labels :
app
: mariadb
spec :
containers :
- name
: mariadb
image
: docker.io/mariadb:10.4
ports :
- containerPort
: 3306
protocol
: TCP
volumeMounts :
- mountPath
: /var/lib/mysql
name
: mariadb-volume-1
volumes :
- emptyDir
:
{
}
name
: mariadb-volume-1
這是來自Docker Hub的正式MariaDB 10.4映像的準系統Kubernetes部署。 現在,添加您的Secrets和ConfigMap。
将Secrets作為環境變量添加到Deployment中
您有兩個秘密需要添加到部署中:
- mariadb-root-password (具有一個鍵/值對)
- mariadb-user-creds (具有兩個鍵/值對)
對于
MariaDB的根密碼的秘密,指定秘密,你想通過添加ENV清單/陣列的部署容器規格,設定環境變量的值在你的秘密的關鍵值的關鍵。 在這種情況下,該清單僅包含一個變量MYSQL_ROOT_PASSWORD的條目 。
env :
- name
: MYSQL_ROOT_PASSWORD
valueFrom :
secretKeyRef :
name
: mariadb-root-password
key
: password
請注意,對象的名稱是添加到容器的環境變量的名稱。 所述valueFrom字段secretKeyRef定義為從該環境變量将被設定在源; 也就是說,它将使用您之前設定的mariadb-root-password Secret中密碼密鑰中的值。
将本節添加到mariadb-deployment.yaml檔案中的mariadb容器定義中。 它看起來應該像這樣:
spec :
containers :
- name
: mariadb
image
: docker.io/mariadb:10.4
env :
- name
: MYSQL_ROOT_PASSWORD
valueFrom :
secretKeyRef :
name
: mariadb-root-password
key
: password
ports :
- containerPort
: 3306
protocol
: TCP
volumeMounts :
- mountPath
: /var/lib/mysql
name
: mariadb-volume-1
通過這種方式,您已将變量顯式設定為Secret中特定鍵的值。 通過使用configMapRef而不是secretKeyRef,此方法也可以與ConfigMaps一起使用。
您還可以在Secret或ConfigMap中的所有鍵/值對中設定環境變量,以自動将鍵名用作環境變量名,并将鍵的值用作環境變量的值。 通過在容器規範中使用envFrom而不是env ,可以一次性建立先前建立的mariadb-user-creds Secret的MYSQL_USER和MYSQL_PASSWORD :
envFrom :
- secretRef :
name
: mariadb-user-creds
envFrom是Kubernetes擷取環境變量的來源清單。 再次使用secretRef ,這一次将mariadb-user-creds指定為環境變量的源。 而已! Secret中的所有鍵和值将作為環境變量添加到容器中。
容器規格現在應如下所示:
spec :
containers :
- name
: mariadb
image
: docker.io/mariadb:10.4
env :
- name
: MYSQL_ROOT_PASSWORD
valueFrom :
secretKeyRef :
name
: mariadb-root-password
key
: password
envFrom :
- secretRef :
name
: mariadb-user-creds
ports :
- containerPort
: 3306
protocol
: TCP
volumeMounts :
- mountPath
: /var/lib/mysql
name
: mariadb-volume-1
注意:您可以将mysql-root-password Secret添加到envFrom清單中,并對其進行解析,隻要密碼密鑰名為MYSQL_ROOT_PASSWORD 。 與env一樣, 無法使用envFrom手動指定環境變量名稱。
将max_allowed_packet.cnf檔案作為volumeMount添加到部署中
如上所述, env和envFrom均可用于與容器共享ConfigMap鍵/值對。 但是,對于mariadb-config ConfigMap,整個檔案都将作為鍵的值存儲,并且該檔案必須存在于容器的檔案系統中,MariaDB才能使用它。 幸運的是,Secrets和ConfigMaps都可以作為Kubernetes“卷”的來源,并且可以挂載到容器中,而不是使用檔案系統或塊裝置作為要挂載的卷。
mariadb-deployment.yaml已經指定了一個volume和volumeMount,将一個emptyDir (實際上是臨時的或臨時的)卷安裝到/ var / lib / mysql以存儲MariaDB資料:
<
...
>
volumeMounts :
- mountPath
: /var/lib/mysql
name
: mariadb-volume-1
<
...
>
volumes :
- emptyDir
:
{
}
name
: mariadb-volume-1
<
... >
注意:這不是生産配置。 當Pod重新啟動時, emptyDir卷中的資料将丢失。 這主要用于開發或當卷的内容不需要持久性時使用。
您可以将ConfigMap添加為源,方法是将其添加到卷清單中,然後将其的volumeMount添加到容器定義中:
<
...
>
volumeMounts :
- mountPath
: /var/lib/mysql
name
: mariadb-volume-1
- mountPath
: /etc/mysql/conf.d
name
: mariadb-config
<
...
>
volumes :
- emptyDir
:
{
}
name
: mariadb-volume-1
- configMap :
name
: mariadb-config
items :
- key
: max_allowed_packet.cnf
path
: max_allowed_packet.cnf
name
: mariadb-config-volume
<
... >
該volumeMount是不言自明建立卷裝入為MariaDB的-配置容量 (在它下面的卷清單中指定)的路徑/etc/mysql/conf.d。
然後,在卷清單中, configMap告訴Kubernetes使用mariadb-config ConfigMap,擷取密鑰max_allowed_packet.cnf的内容并将其安裝到路徑max_allowed_packed.cnf 。 卷的名稱是mariadb-config-volume ,在上面的volumeMounts中引用了該卷 。
注意: configMap的路徑是将包含鍵值内容的檔案的名稱。 在這種情況下,您的密鑰也就是檔案名,但不一定必須如此。 還要注意, 項目是一個清單,是以可以引用多個鍵并将它們的值安裝為檔案。 這些檔案都将在裝載路徑建立的volumeMount上述規定:/etc/mysql/conf.d。
從部署中建立MariaDB執行個體
至此,您應該足以建立一個MariaDB執行個體。 您有兩個秘密,一個秘密持有MYSQL_ROOT_PASSWORD ,另一個秘密存儲MYSQL_USER ,以及要添加到容器的MYSQL_PASSWORD環境變量。 您還擁有一個ConfigMap,其中包含一個MySQL配置檔案的内容,該檔案會從其預設設定中覆寫max_allowed_packed值。
您還具有mariadb-deployment.yaml檔案,該檔案描述了具有MariaDB容器的Pod的Kubernetes部署,并将Secrets作為環境變量添加,并将ConfigMap作為在容器中卷安裝的檔案添加。 它看起來應該像這樣:
apiVersion
: apps/v1
kind
: Deployment
metadata :
labels :
app
: mariadb
name
: mariadb-deployment
spec :
replicas
: 1
selector :
matchLabels :
app
: mariadb
template :
metadata :
labels :
app
: mariadb
spec :
containers :
- image
: docker.io/mariadb:10.4
name
: mariadb
env :
- name
: MYSQL_ROOT_PASSWORD
valueFrom :
secretKeyRef :
name
: mariadb-root-password
key
: password
envFrom :
- secretRef :
name
: mariadb-user-creds
ports :
- containerPort
: 3306
protocol
: TCP
volumeMounts :
- mountPath
: /var/lib/mysql
name
: mariadb-volume-1
- mountPath
: /etc/mysql/conf.d
name
: mariadb-config-volume
volumes :
- emptyDir
:
{
}
name
: mariadb-volume-1
- configMap :
name
: mariadb-config
items :
- key
: max_allowed_packet.cnf
path
: max_allowed_packet.cnf
name
: mariadb-config-volume
建立MariaDB執行個體
使用kubectl create指令從YAML檔案建立一個新的MariaDB執行個體:
$ kubectl create
-f mariadb-deployment.yaml
deployment.apps
/ mariadb-deployment created
建立部署後,請使用kubectl get指令檢視正在運作的MariaDB pod:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mariadb-deployment-5465c6655c-7jfqm
1
/
1 Running
0 3m
記下Pod名稱(在此示例中,它是mariadb-deployment-5465c6655c-7jfqm )。 請注意,Pod名稱将與此示例不同。
驗證執行個體是否使用Secrets和ConfigMap
使用kubectl exec指令(使用您的Pod名稱)來驗證Secrets和ConfigMap是否正在使用。 例如,檢查環境變量是否在容器中公開:
$ kubectl
exec
-it mariadb-deployment-5465c6655c-7jfqm
env
|
grep MYSQL
MYSQL_PASSWORD =kube-still-rocks
MYSQL_USER =kubeuser
MYSQL_ROOT_PASSWORD =KubernetesRocks
!
成功! 容器中提供了所有三個環境變量(一個使用env設定來指定Secret, 另一個使用envFrom來安裝來自Secret的所有值),這些變量可以在MariaDB中使用。
抽查檢查max_allowed_packet.cnf檔案是在/etc/mysql/conf.d中建立的,并且其中包含預期的内容:
$ kubectl
exec
-it mariadb-deployment-5465c6655c-7jfqm
ls
/ etc
/ mysql
/ conf.d
max_allowed_packet.cnf
$ kubectl
exec
-it mariadb-deployment-5465c6655c-7jfqm
cat
/ etc
/ mysql
/ conf.d
/ max_allowed_packet.cnf
[ mysqld
]
max_allowed_packet = 32M
最後,驗證MariaDB使用環境變量來設定root使用者密碼,并讀取max_allowed_packet.cnf檔案來設定max_allowed_packet配置變量。 再次使用kubectl exec指令,這一次是在運作容器中擷取一個shell并使用它運作一些mysql指令:
$ kubectl
exec
-it mariadb-deployment-5465c6655c-7jfqm
/
bin
/
sh
# Check that the root password was set correctly
$ mysql
-uroot
-p
${MYSQL_ROOT_PASSWORD}
-e
'show databases;'
+--------------------+
| Database
|
+--------------------+
| information_schema
|
| mysql
|
| performance_schema
|
+--------------------+
# Check that the max_allowed_packet.cnf was parsed
$ mysql
-uroot
-p
${MYSQL_ROOT_PASSWORD}
-e
"SHOW VARIABLES LIKE 'max_allowed_packet';"
+--------------------+----------+
| Variable_name
| Value
|
+--------------------+----------+
| max_allowed_packet
|
33554432
|
+--------------------+----------+
機密和ConfigMap的優點
本練習說明了如何建立Kubernetes Secrets和ConfigMap以及如何通過将它們作為環境變量或檔案添加到正在運作的容器執行個體内部來使用這些Secrets和ConfigMaps。 這使得将容器的各個執行個體的配置與容器映像分開保持容易。 通過分離配置資料,可以将開銷減少為僅針對特定類型的執行個體維護單個映像,同時保留了建立具有多種配置的執行個體的靈活性。
翻譯自: https://opensource.com/article/19/6/introduction-kubernetes-secrets-and-configmaps
configmap