5.2 ConfigMap和 Secret

ConfigMap 可以用来存储非机密性的数据到键值对中,这些信息会被存储到 etcd,不会分节点,任何节点都可以使用到。使用时,将其用作环境变量、命令行参数或者存储卷中的配置文件送入到 Pod 中,主要目的是解耦你的应用程序和配置,这样不必维护那些 .json 等配置文件,也可以避免不小心将带有机密信息的配置文件上传到代码仓库中。但是 ConfigMap 中的内容都是非加密的,可以很容易地看到全部信息,如果需要加密,则使用 secret。

ConfigMap

创建 configMap

创建 configMap 的命令格式:

kubectl create configmap <map-name> <data-source>
kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run=server|client|none]

如果忘记了,可以使用 kubect create configmap --help 快速获取文档说明。

如果以文件(--from-file)形式创建 ConfigMap,则为 key,文件内容为 value,--from-file 也可以指定目录。

如果以键值对(--from-literal)形式创建 ConfigMap,可直接创建 key=value

可以根据文件内容、目录或键值对创建 ConfigMap,ConfigMap 可以指定多个来源。当基于目录创建一个 ConfigMap时,每个文件的基名是该目录中的有效密钥,这些文件将被打包到 ConfigMap中。

这三点都是从哪里生成 k-v 到 ConfigMap,不要纠结于字面。

直接使用键值对创建 ConfigMap:

kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2

查看 ConfigMap:

root@master:~# kubectl get configmap my-config
Data
====
key1:
----
config1
key2:
----
config2

--from-literal 表示,当前使用键值对赋值的形式创建 ConfigMap。

通过文件内容生成 ConfigMap,文件内容示例:

enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30

设置文件名称为 c.txt。

文件中的内容使用键值对形式。

创建 ConfigMap:

kubectl create configmap my-config1 --from-file=c.txt

查看 ConfigMap:

root@master:~# kubectl describe configmap my-config1
Data
====
c.txt:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30

多个文件:

kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt

通过目录创建 ConfigMap,创建目录和文件,其目录结构如下:

├── config
│   ├── a.txt
│   └── b.txt
root@master:~# cat config/a.txt 
a=666
root@master:~# cat config/b.txt 
b=666

创建 ConfigMap:

kubectl create configmap my-config2 --from-file=config/

查看 ConfigMap:

root@master:~# kubectl describe configmap my-config2
Data
====
a.txt:
----
a=666

b.txt:
----
b=666

注意,通过 文件 或目录创建的 ConfigMap 中,文件名称为 Key,而文件内容为 Value,所以 a=666 是文件的值,里面不能再分为 Key a、Value B,a=666 是一个值。

或者改成下面这样会更容易理解:

====
name.txt:
----
痴者工良

url.txt:
----
k8s.whuanle.cn

下面将介绍怎么使用 ConfigMap。

在环境变量中使用

前面我们已经创建了 my-config、 my-config1、 my-config2 三个配置,我们希望些这配置,能够以环境变量的形式传递到 容器中,那么定义 Pod 时其 YAML 模板如下:

env:
 - name:letter
   valueFrom:
     configMapKeyRef:
       name: my-config2
       key: a.txt

注:key 为 | 之前的名称,例如 a.txt,文件名;

或者:

      envFrom:
      - configMapRef:
          name: my-config2

如果要整个 configMap 的内容全部导入,则使用 envFrom,如果要只使用一部分,可以用 valueFrom。

那么我们来真实启动一个 Nginx Pod:

apiVersion: v1
kind: Pod
metadata: 
  name: nginx
spec: 
  containers:
  - name: nginx
    image: nginx:latest
    env: 
    - name: myconfig_a
      valueFrom: 
        configMapKeyRef: 
          name: my-config2
          key: a.txt
    - name: myconfig_b
      valueFrom:
        configMapKeyRef: 
          name: my-config2
          key:  b.txt

[Info] 提示

如果 ConfigMap 通过文件或目录创建的,那么每个文件的环境变量是打包一起的。所以:

        configMapKeyRef: 
          name: my-config2
          key: a.txt

a.txt 中的环境变量映射到 myconfig_a。

kubectl apply -f configMapNginx.yaml

打印 Pod 中的环境变量:

root@master:~# kubectl exec nginx -- printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=nginx
myconfig_a=a=666

myconfig_b=b=666

不过这样映射会有的奇怪,因此使用环境变量使用 ConfigMap 时,都是使用 K/V 的数据,而不使用通过文件、目录的数据。

ConfigMap 卷

configMap 卷 提供了向 Pod 注入配置数据的方法。其主要用途是给 Pod 中的容器传递配置,在 Pod 中显示为文件。

Pod 的 YAML 文件示例:

apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
    - name: configmap-pod
      image: busybox
      command: ["ls"]
      args: ["/etc/config"]
      volumeMounts:
        - name: config-vol
          mountPath: /etc/config
  volumes:
    - name: config-vol
      configMap:
        name: my-config

查看此 Pod 的日志:

root@master:~# kubectl logs  configmap-pod
key1
key2

key1 文件中存储了 值,ConfigMap my-config 中有 key1=config1key2=config2 两个配置,则在 key1文件中,其值为 config1。

但是这样好像没啥意思,既然要映射为文件,应该创建有意思的内容。

下面创建一个 config.json 文件:

{
    "name": "痴者工良",
    "url": "k8s.whuanle.cn"
}

创建 ConfigMap:

kubectl create configmap my-config3 --from-file=config.json
root@master:~# kubectl describe configmap my-config3
Name:         my-config3

config.json:
----
{
  "name": "痴者工良",
  "url": "k8s.whuanle.cn"
}

映射为 Pod 中的文件:

apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
    - name: configmap-pod
      image: busybox
      command: ["cat"]
      args: ["/etc/config/config.json"]
      volumeMounts:
        - name: config-vol
          mountPath: /etc/config
  volumes:
    - name: config-vol
      configMap:
        name: my-config3

查看容器中被映射的文件:

root@master:~# kubectl logs configmap-pod
{
    "name": "痴者工良",
    "url": "k8s.whuanle.cn"
}
# cat /etc/config/config.json

[Success] 提示

通过 ConfigMap 卷映射到容器中,如果使用的是 mountPath 挂载到目录,则 ConfigMap 更新内容时,容器中的配置文件内容也会被更新,但是可能需要几分钟。如果挂载的目录是容器中已经存在的,则可能无法同步更新,因此挂载 ConfigMap 到容器中的时,需要使用一个新的目录。

多键值对

前面提到,如果有个 a.txt 文件:

key1=value1
key2=value2
... ...

如果使用 --from-file 等导入 ConfigMap 中,并不会达到我们想要同时导入多个值的效果,导入后会变成 a.txt="key1=value1... ..."。它更可能使用 JSON、YAML 文件来表达,如:

{
    "ConnectString": "mysql=192.168.0.1;user=admin... ..."
}

然后使用 kubectl create configmap test --from-file=sql.config ,然后在 Pod 中使用 sql.config 这个环境变量或卷文件使用 Json 配置。

如果要将 a.txt 中的多行键值对拆分出来,可以使用 --from-env-file

当然,这个文件有一定的规则:

  • 以 # 开头的行会被忽略;可以使用空行分隔,空行也会被忽略;
  • 具有意义的行必须是 {键}={值} 的形式;
  • 引号不会被特殊处理,即不会被转义或不需要你提前转义。

关于上面这三点,创建 a.txt 示例文件:

enemies=aliens
lives=3
allowed="true"

导入命令格式:

kubectl create configmap my-config3 --from-env-file=a.txt

生成结果:

... ...
data:
  allowed: '"true"'
  enemies: aliens
  lives: "3"
... ...

[Info] 提示

命令中只能出现一个 --from-env-file,多个 --from-env-file 同时使用,只有最后一个有效。

Secret

Secret 卷用来给 Pod 传递敏感信息,例如密码、密钥等。Secret卷实际上不是用于存储的,Secret 中存储的信息,会以环境变量、文件等的形式显示在 Pod 中。在 4.3 章的 Ingress 中,就讲解过使用 Secret 为 Ingress 增加 TLS 加密访问(HTTPS)。

Secret 的信息存储在 etcd 中,但是 Secret 一般情况下也不是加密存储的,关于如何加密 Secret 后面的章节会介绍到。

说明: 使用前你必须在 Kubernetes API 中创建 Secret。

Secret 的类型很多,这里将官方文档中列举的 secret 类型复制一份:

内置类型 用法
Opaque 用户定义的任意数据
kubernetes.io/service-account-token 服务账号令牌
kubernetes.io/dockercfg ~/.dockercfg 文件的序列化形式
kubernetes.io/dockerconfigjson ~/.docker/config.json 文件的序列化形式
kubernetes.io/basic-auth 用于基本身份认证的凭据
kubernetes.io/ssh-auth 用于 SSH 身份认证的凭据
kubernetes.io/tls 用于 TLS 客户端或者服务器端的数据
bootstrap.kubernetes.io/token 启动引导令牌数据

这里只讲解一部分常用的 secret 类型,如需了解更多详细知识,请参考官方文档:https://kubernetes.io/zh/docs/concepts/configuration/secret/

使用 kubectl 命令创建 Secret 时,命令格式如下:

kubectl create secret {类型} {secret名称}

其中,普通类型/Qpaque 类型的类型名称是 generic,而不是 qpaque

使用 kubectl creatte secret generic 命令创建 secret 时,导入键值对的格式跟 ConfigMap 一致,这里就不再多说了,下面介绍一些其他常用的 Secret 类型。

TLS

在 4.3 章的 Ingrss 中,已经聊到过,这里就不再细谈。

通过证书创建 Secret 的命令如下所示:

kubectl create secret tls tls-secret --cert=1_k1.whuanle.cn_bundle.crt --key=2_k1.whuanle.cn.key

使用 YAML 表示:

apiVersion: v1
data:
  tls.crt: ...
  tls.key: ...
kind: Secret
metadata:
  name: tls-secret
type: kubernetes.io/tls

Nginx 配置 Https 证书,使用的便是 crt、key 文件,其它类型的证书请读者自行查阅文档。

基本身份认证 Secret

其类型为 kubernetes.io/basic-auth,它是用来存储账号密码的,spec.data 中必须包含 username 和 password 两个字段,其 YAML 文件示例如下所示:

apiVersion: v1
kind: Secret
metadata:
  name: secret-basic-auth
type: kubernetes.io/basic-auth
stringData:
  username: admin
  password: t0p-Secret

如果我们查看数据:

root@master:~# kubectl get secret secret-basic-auth  -o yaml
apiVersion: v1
data:
  password: dDBwLVNlY3JldA==
  username: YWRtaW4=
kind: Secret
... ...

username 和 password 等会被使用 base64 编码,但是并不是加密屏蔽,这些信息可以被直接用 base64 还原。

SSH 身份认证 Secret

其类型是 kubernetes.io/ssh-auth,用来存储一段 ssh 密钥。

其 YAML 示例如下:

apiVersion: v1
kind: Secret
metadata:
  name: secret-ssh-auth
type: kubernetes.io/ssh-auth
data:
  # 此例中的实际数据被截断
  ssh-privatekey: |
          MIIEpQIBAAKCAQEAulqb/Y ...

使用 Secret

前面已经介绍过 Ingress 使用 Secret,这里就不再复述。

在 Pod 中使用 Secret 有环境变量和文件两种形式,将 Secret 挂载到 Pod 的目录下,

apiVersion: v1
kind: Pod
metadata:
  name: secret1
spec:
  containers:
  - name: secret1
    image: nginx
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: secret-basic-auth

这里使用之前创建的基于身份认证的 Secret,有 username、password 两个字段。

创建 Pod,然后查看映射到 Pod 的文件:

root@master:~# kubectl exec secret1 -- ls /etc/foo
password
username

root@master:~# kubectl exec secret1 -- cat /etc/foo/username
adminroot
@master:~# kubectl exec secret1 -- cat /etc/foo/password
t0p-Secret

可以看到,Secret 中每一个 字段/Key,会生成一个文件名,Value 是文件内容。

如果以环境变量的方式使用 Secret,其 YAML 跟 ConfigMap 类似,文件示例如下:

apiVersion: v1
kind: Pod
metadata:
  name: mysecret2
spec:
  containers:
  - name: mysecret
    image: nginx
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: secret-basic-auth
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: secret-basic-auth
            key: password
  restartPolicy: Never

会将 secret-basic-auth 中的 username 和 password 两个字段映射到 Pod 的 SECRET_USERNAMESECRET_PASSWORD 两个环境变量中。

查看 Pod 中的环境变量:

root@master:~# kubectl exec mysecret2 -- env
SECRET_USERNAME=admin
SECRET_PASSWORD=t0p-Secret

同时使用 ConfigMap、Secret

在集群中有 db-config 和 db-secret 两个名为 ConfigMap 和 Secret 的对象,现在需要创建一个名为 mydb 的 Pod,并且使用 mysql:5.7 这个镜像,要求把 db-config 和 db-secret 中的所有键值对以环境变量的形式映射到容器中。

其 YAML 示例如下:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: mydb
  name: mydb
spec:
  containers:
  - image: mysql:5.7
    name: mydb
    envFrom:
    - configMapRef:
        name: db-config
    - secretRef:
        name: db-secret
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
Copyright © 痴者工良 2021 all right reserved,powered by Gitbook文档最后更新时间: 2021-11-14 13:21:46

results matching ""

    No results matching ""