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 client命令版本与正在使用的Kubernetes集群版本相同或较新。
出现以下错误:
error: SchemaError(io.k8s.api.admissionregistration.v1beta1.ServiceReference): invalid object doesn't have additional properties
可能意味着客户端版本太旧,需要升级。 用于安装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
# 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 =
# 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
ConfigMap与Secrets类似。 可以使用相同的方法在容器中创建和共享它们。 它们之间的唯一最大区别是对base64编码的混淆。 ConfigMap用于非敏感数据(配置数据),例如配置文件和环境变量,并且是从通用容器映像创建自定义运行服务的好方法。
可以使用与Secrets相同的方式来创建ConfigMap。 您可以手动编写ConfigMap的YAML表示并将其加载到Kubernetes中,也可以使用kubectl create configmap命令从命令行创建它。 下面的示例使用后一种方法创建ConfigMap,但不传递文字字符串(如上述Secret中的--from-literal =
首先,创建一个名为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 =
如前所述,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
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。
您有两个秘密需要添加到部署中:
对于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手动指定环境变量名称。
如上所述, 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实例。 您有两个秘密,一个秘密持有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
使用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名称将与此示例不同。
使用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
|
+--------------------+----------+
本练习说明了如何创建Kubernetes Secrets和ConfigMap以及如何通过将它们作为环境变量或文件添加到正在运行的容器实例内部来使用这些Secrets和ConfigMaps。 这使得将容器的各个实例的配置与容器映像分开保持容易。 通过分离配置数据,可以将开销减少为仅针对特定类型的实例维护单个映像,同时保留了创建具有多种配置的实例的灵活性。
翻译自: https://opensource.com/article/19/6/introduction-kubernetes-secrets-and-configmaps
configmap