云原生技术之六ConfigMap和Secret-应用配置文件

举报
tea_year 发表于 2024/11/22 11:08:19 2024/11/22
【摘要】 06-ConfigMap和Secret-应用配置文件Kubernetes 里专门用来管理配置信息的两种对象:ConfigMap 和 Secret,使用它们来灵活地配置、定制我们的应用。 ConfigMap/Secret  首先你要知道,应用程序有很多类别的配置信息,但从数据安全的角度来看可以分成两类:  一类是明文配置,也就是不保密,可以任意查询修改,比如服务端口、运行参数、文件路径等等。 ...

06-ConfigMapSecret-应用配置文件

Kubernetes 里专门用来管理配置信息的两种对象:ConfigMap Secret,使用它们来灵活地配置、定制我们的应用。

 

ConfigMap/Secret  

首先你要知道,应用程序有很多类别的配置信息,但从数据安全的角度来看可以分成两类:  

  • 一类是明文配置,也就是不保密,可以任意查询修改,比如服务端口、运行参数、文件路径等等。  
  • 另一类则是机密配置,由于涉及敏感信息需要保密,不能随便查看,比如密码、密钥、证书等等。  

 

这两类配置信息本质上都是字符串,只是由于安全性的原因,在存放和使用方面有些差异,所以 Kubernetes 也就定义了两个 API 对象,ConfigMap 用来保存明文配置,Secret 用来保存秘密配置  

什么是 ConfigMap  

先来看 ConfigMap,我们仍然可以用命令 kubectl create 来创建一个它的 YAML 样板。注意,它有简写名字“cm”,所以命令行里没必要写出它的全称:  

Bash
export out="--dry-run=client -o yaml"
kubectl create cm info $out

得到的模板文件大概是这个样子:  

YAML
apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: info

 

ConfigMap YAML 和之前我们学过的 PodJob 不一样,除了熟悉的“apiVersion”“kind”“metadata”,居然就没有其他的了,最重要的字段“spec”哪里去了?这是因为 ConfigMap 存储的是配置数据,是静态的字符串,并不是容器,所以它们就不需要用“spec”字段来说明运行时的规格

既然 ConfigMap 要存储数据,我们就需要用另一个含义更明确的字段“data”

要生成带有“data”字段的 YAML 样板,你需要在 kubectl create 后面多加一个参数 --from-literal ,表示从字面值生成一些数据:

Bash
kubectl create cm info --from-literal=k=v $out  

 

注意,因为在 ConfigMap 里的数据都是 Key-Value 结构,所以 --from-literal 参数需要使用 k=v 的形式。  

YAML 样板文件修改一下,再多增添一些 Key-Value,就得到了一个比较完整的 ConfigMap 对象:  

YAML
apiVersion: v1
kind: ConfigMap
metadata:
  name: info
data:
  count: '10'
  debug: 'on'
  path: '/etc/systemd'
  greeting: |
    say hello to kubernetes.
    say hi to the world.    

现在就可以使用 kubectl apply 把这个 YAML 交给 Kubernetes,让它创建 ConfigMap 对象了:  

Bash
kubectl apply -f cm.yaml

创建成功后,我们还是可以用 kubectl getkubectl describe 来查看 ConfigMap 的状态:  

Bash
kubectl  get cm
kubectl describe cm info

 

 

 

 

 

你可以看到,现在 ConfigMap Key-Value 信息就已经存入了 etcd 数据库,后续就可以被其他 API 对象使用。  

 

创建 ConfigMap

使用字面值创建

Bash
kubectl create configmap cm-conf --from-literal=debug=on --from-literal=count=10

从目录创建

Bash
kubectl create configmap nginx-config --from-file=nginx-conf
kubectl  get cm nginx-config
kubectl describe  cm nginx-config

 

从文件创建

Bash
kubectl create configmap nginx-config-2 --from-file=nginx-conf/default.conf

 

 

什么是 Secret  

了解了 ConfigMap 对象,我们再来看 Secret 对象就会容易很多,它和 ConfigMap 的结构和用法很类似,不过在 Kubernetes Secret 对象又细分出很多类,比如 :

Secret 有四种类型:

  • Service Account:用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod /run/secrets/kubernetes.io/serviceaccount 目录中;
  • Opaque[oʊˈpeɪk]base64 编码格式的 Secret,用来存储密码、密钥等;
  • io/dockerconfigjson:用来存储私有 docker registry 的认证信息。
  • TLS(传输层安全):用于存储TLS证书和私钥,以支持加密通信。它可以用于需要TLS证书的场景。

 

对应具体有用途如下:

  • 访问私有镜像仓库的认证信息
  • 身份识别的凭证信息
  • HTTPS 通信的证书和私钥
  • 一般的机密信息(格式由用户自行解释)  

 

我们先创建 Opaque 类型的,创建 YAML 样板的命令是 kubectl create secret generic ,同样,也要使用参数

 --from-literal 给出 Key-Value 值:  

Bash
kubectl create secret generic user --from-literal=username=root $out

得到的 Secret 对象大概是这个样子:  

YAML
apiVersion: v1
kind: Secret
metadata:
  name: user
  
data:
  username: cm9vdA==

 

Secret 对象第一眼的感觉和 ConfigMap 非常相似,只是“kind”字段由“ConfigMap”变成了“Secret”,后面同样也是“data”字段,里面也是 Key-Value 的数据。  

这串乱码就是 Secret ConfigMap 的不同之处,不让用户直接看到原始数据,起到一定的保密作用。不过它的手法非常简单,只是做了 Base64 编码,根本算不上真正的加密,我们可以直接使用 Linux 命令"base64" 来解密 :  

 

Bash
# base64 解码
[root@k8s cm-sc]# echo "cm9vdA==" | base64 -d
root
# base64 编码 注意要加 -n 参数
[root@k8s cm-sc]# echo -n  "mysql" | base64
bXlzcWw=
[root@k8s cm-sc]# echo -n  "123456" | base64
MTIzNDU2

 

我们再来重新编辑 Secret YAML,为它添加两个新的数据,方式可以是参数 --from-literal 自动编码,也可以是自己手动编码:  

YAML
apiVersion: v1
kind: Secret
metadata:
  name: user
  
data:
  username: cm9vdA==
  password: MTIzNDU2
  db: bXlzcWw=

使用 kubectl applykubectl getkubectl describe 创建和查看对象:  

Bash
kubectl apply -f secret.yaml
kubectl  get secrets
kubectl describe secrets user

 

 

 

这样一个存储敏感信息的 Secret 对象也就创建好了,而且因为它是保密的,使用 kubectl describe 不能直接看到内容,只能看到数据的大小,你可以和 ConfigMap 对比一下。  

 

创建Secret

 

  • docker registry 认证的 secret

Bash
kubectl create secret docker-registry myregistry-secret --docker-server=string --docker-username=user --docker-password=password --docker-email=chijj@xxhf.com

 

YAML
apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  imagePullSecrets:
    - name: myregistrykey
  containers:
    - name: foo
      image: reg.xinxianghf/lib/myapp:v1

 

  • TLS secret

 

 

 

如何使用

通过编写 YAML 文件,我们创建了 ConfigMap Secret 对象,该怎么在 Kubernetes 里应用它们呢?

因为 ConfigMap Secret 只是一些存储在 etcd 里的字符串,所以如果想要在运行时产生效果,就必须要以某种方式注入Pod 里,让应用去读取。在这方面的处理上 Kubernetes Docker 是一样的,也是两种途径:环境变量和加载文件。

先看比较简单的环境变量。

以环境变量的方式

“valueFrom”字段指定了环境变量值的来源,可以是“configMapKeyRef”或者“secretKeyRef”,然后你要再进一步指定应用的 ConfigMap/Secret “name”和它里面的“key”

 

由于“valueFrom”字段在 YAML 里的嵌套层次比较深,初次使用最好看一下 kubectl explain 对它的说明:

Bash
kubectl explain pod.spec.containers.env.valueFrom

 

下面是 引用了 ConfigMap Secret 对象的 Pod 定义

 

YAML
apiVersion: v1
kind: Pod
metadata:
  name: env-pod
  labels:
    owner: xxhf
    env: dev
spec:
  containers:
  - name: busy
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["/bin/sleep", "3000"]
    env:
      - name: COUNT   # 环境变量名字
        valueFrom:
          configMapKeyRef:
            name: info   # configmap 名字
            key: count   # info configmap 中定义 count key
      - name: DEBUG
        valueFrom:
          configMapKeyRef:
            name: info
            key: debug
      - name: USERNAME
        valueFrom:
          secretKeyRef:
            name: user   # secret 名字
            key: username    # user secset 中的 username key
      - name: PASSWORD
        valueFrom:
          secretKeyRef:
            name: user
            key: password

 

kubectl apply 创建 Pod,再用 kubectl exec 进入 Pod,验证环境变量是否生效:

Bash
kubectl apply -f env-pod.yaml
kubectl exec -it env-pod  -- sh

echo $COUNT
echo $DEBUG
echo $USERNAME
echo $PASSWORD

 

 

这张截图就显示了 Pod 的运行结果,可以看到在 Pod 里使用 echo 命令确实输出了我们在两个 YAML 里定义的配置信息,也就证明 Pod 对象成功组合了 ConfigMap Secret 对象。

以环境变量的方式使用 ConfigMap/Secret 还是比较简单的,下面来看第二种加载文件的方式。

 

Volume 的方式

Kubernetes Pod 定义了一个“Volume”的概念,可以翻译成是存储卷。如果把 Pod 理解成是一个虚拟机,那么 Volume 就相当于是虚拟机里的磁盘。

 

注意: Volume 属于 Pod,不属于容器,所以它和字段“containers”是同级的,都属于“spec”

下面让我们来定义两个 Volume,分别引用 ConfigMap Secret,名字是 cm-vol sec-vol

YAML
spec:
  volumes:
  - name: cm-vol
    configMap:
      name: info
  - name: sec-vol
    secret:
      secretName: user

使用 “volumeMounts”字段来挂载卷,可以把定义好的 Volume 挂载到容器里的某个路径下,所以需要在里面用“mountPath” “name”明确地指定挂载路径和 Volume 的名字。  

YAML
  containers:
  - name: busy
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["/bin/sleep", "3000"]
    volumeMounts:
    - mountPath: /tmp/configmap
      name: cm-vol
    - mountPath: /tmp/secret
      name: sec-vol

“volumes”“volumeMounts”字段都写好之后,配置信息就可以加载成文件了。

 

下面是 Pod 的完整 YAML 描述,然后使用 kubectl apply 创建它.

 

YAML
apiVersion: v1
kind: Pod
metadata:
  name: env-pod
  labels:
    owner: xxhf
    env: dev
spec:
  volumes:
  - name: cm-vol
    configMap:
      name: info
  - name: sec-vol
    secret:
      secretName: user
  containers:
  - name: busy
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    command: ["/bin/sleep", "3000"]
    volumeMounts:
    - mountPath: /tmp/configmap
      name: cm-vol
    - mountPath: /tmp/secret
      name: sec-vol

创建之后,我们还是用 kubectl exec 进入 Pod,看看配置信息被加载成了什么形式:  

YAML
kubectl apply -f vol-pod.yaml
kubectl  get pod
kubectl exec -it env-pod  -- sh

 

 

ConfigMap Secret 都变成了目录的形式,而它们里面的 Key-Value 变成了一个个的文件,而文件名就是 Key

因为这种形式上的差异,以 Volume 的方式来使用 ConfigMap/Secret,就和环境变量不太一样。

环境变量用法简单,更适合存放简短的字符串,而 Volume 更适合存放大数据量的配置文件,在 Pod 里加载成文件后让应用直接读取使用。

 

 

如果配置文件发生变化,Pod 中加载的数据是否会同步更新 ?

环境变量加载 cm secret 不会热更新 ,只有重启 Pod  才会触发更新

Volume 加载的可以实现 热更新

 

总结

 

Kubernetes 里管理配置信息的 API 对象 ConfigMap Secret,它们分别代表了明文信息和机密敏感信息,存储在 etcd 里,在需要的时候可以注入Pod Pod 使用。

  1. ConfigMap 记录了一些 Key-Value 格式的字符串数据,描述字段是“data”,不是“spec”
  2. Secret ConfigMap 很类似,也使用“data”保存字符串数据,但它要求数据必须是 Base64
    编码,起到一定的保密效果。  
  3. Pod “env.valueFrom” 字段中可以引用 ConfigMap Secret,把它们变成应用可以访
    问的环境变量。
  4. Pod “spec.volumes” 字段中可以引用 ConfigMap Secret,把它们变成存储卷,然后
    “spec.containers.volumeMounts” 字段中加载成文件的形式。
  5. ConfigMap Secret 对存储数据的大小没有限制,但小数据用环境变量比较适合,大数据
    应该用存储卷,可根据具体场景灵活应用。 1MB  etcd

 

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。