《kubernetes in action》学习笔记——7、ConfigMap和Secret

7、ConfigMap和Secret

    • ConfigMap
    • Secret 传递敏感信息

ConfigMap

ConfigMap
主要有三种用法

  1. 向容器传递命令参数
  2. 为每个容器设置自定义环境变量
  3. 通过特殊类型的数据卷将配置文件挂载到容器

1、向容器传递命令行参数
容器中运行完整指令由两部分组成:命令与参数
Dockerfile中两种指令分别定义命令与参数这两个部分

  • ENTRYPOINT 定义容器启动时被调用的可执行程序
  • CMD 指定传递给ENTRYPOINT的参数

虽然可以直接使用CMD指令指定镜像运行时想要执行的命令,但正确的做法依旧是借助ENTRYPOINT指令,仅仅用CMD指定所需要的默认参数。这样镜像可以直接运行,无需再添加任何参数。
docker run
或添加一些参数,覆盖Dockerfile中任何CMD指定的默认参数
docker run

shell与exec的区别
上述两条指令都支持以下两种形式

  • shell 形式——如 ENTRYPOINT node app.js
  • exec形式——如 ENTRYPOINT [“node”, “aap.js”]

可以从容器中运行额进程列表看出两者的区别
shell形式是先启动一个shell,然后node 再再shell进程中启动
exec形式是直接运行node进程,因此可以直接采用exec形式的ENTRYPOINT 指令

  • 使用指令kubectl 创建 ConfigMap

使用kubectl create ConfigMap -h 来查看关于创建ConfigMap的帮助信息

  • 使用 --from-literal参数,直接使用字符串来创建 kubectl create configmap cm-name
    –from-literal=key1=value1
    – from-literal 可以多次使用
  • 使用 --from-file参数,直接使用单个文件来创建 kubectl create configmap cm-name1
    –from-file=path/filename
    –from-file 同样可以多次使用,创建后,文件名则为key,文件内容为value 也可以手动指定键名 --from-file=keyname=path/filename
  • 使用 --from-file参数,使用文件夹来创建 kubectl create configmap cm-name2
    –from-file=path/dirname 目录下的所有文件都将作为configmap的映射条目,创建后,文件名为key,文件内容为value

在使用命令创建configmap时,以上三种方式可以混合使用
可通过kubectl describe configmap cm-name
或 kubectl get configmap cm-name -o yaml 来获取configmap的内容

使用ConfigMap
向容器传递ConfigMap条目,作为环境变量
cm-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: cm-pod
spec:
  containers:
  - image: nginx
    name: nginx
    env:
    - name: CMTEST    # 环境变量的名称
      valueFrom:
        configMapKeyRef:
          name: cm-1  # ConfigMap 的名称
          key: key1   # ConfigMap中对应条目的key
可通过 kubectl  exec -it cm-pod  -c nginx  -- /bin/bash  进入nginx容器,echo $CMTEST 查看变量的值

在pod中引用不存在的ConfigMap
如果创建pod时,引用的ConfigMap不存在,此时不存在ConfigMap的容器将会启动失败,其他容器可以正常运行,如果之后创建了这个ConfigMap,失败容器将会自动启动,无须再重新创建pod。
也可设置对ConfigMap的引用是可选,设置 configMapKeyRef.optional: true(默认是false)即可,这样就算ConfigMap不存在,容易也能正常启动

一次性传递ConfigMap的所有条目作为环境变量
如果ConfigMap的条目不少,一条一条的为其设置成环境变量台麻烦,kubernetes提供了一次性暴露所有ConfigMap的所有条目作为环境变量的的方法。

spec:
  containers:
  - image: nginx
    envFrom:     # 使用的envFrom 而非env
    - perfix: CONFIG_   # 为所有环境变量添加前缀,如果不设置,将会与ConfigMap中的键名一致
      configMapRef:
        name: cm-name   # 引用名为cm-name 的ConfigMap

注意:kubernetes不会主动转换键名,如果键名不是一个合法的环境变量名,创建环境变量时将会忽略对应的条目,且不会有发出事件通知。

作为命令行参数
在字段pod.spec.containers.args 中无法直接使用ConfigMap的条目,但是可以利用ConfigMap初始化某个环境变量,然后再再参数中引用该字段

apiVersion: v1
kind: Pod
metadata:
  name: cm-pod
spec:
  containers:
  - image: nginx
    name: nginx
    env:
    - name: CMTEST    # 环境变量的名称
      valueFrom:
        configMapKeyRef:
          name: cm-1  # ConfigMap 的名称
          key: key1   # ConfigMap中对应条目的key
    args: ["$(CMTEST)"]     # 在参数中引用环境变量

使用configMap数据卷将条目暴露为文件
configMap数据卷可以将ConfigMap中的每个条目暴露为一个文件,运行在容器中的程序可以访问文件获取对应的条目值,比较适合内容多的配置文件,少量内容的配置文件当然也可以这样使用。

apiVersion: v1
kind: Pod
metadata:
  name: cm-volume-item
spec:
  containers:
  - image: nginx
    name: cm-volume-item
    volumeMounts:
    - name: tmp               # 多个挂载,第一个挂载 tmp
      mountPath: /tmp
      readOnly: true
    - name: etc-config        # 多个挂载,第一个挂载 etc-config
      mountPath:  /etc/config
  volumes:
  - name: tmp
    configMap:
      name: cm-3
      items:   # 单独挂载ConfigMap中的某一个条目
      - key: literal_key
        path: ./literal_key
  - name: etc-config
    configMap:
      name: cm-3
      items:   # items是一个数组,所以可多个挂载ConfigMap中的多个条目
      - key: ss1
        path: ss/ss/ss1   # 还可以再指定路径
      - key: ss2
        path: ss2/ss2

ConfigMap独立条目作为文件被挂载,且不隐藏原文件夹中的其他文件
通常挂载之后,源目录下的内容将访问不到,只能访问挂载的内容。如果刚好程序也要使用原目录下的文件,则这样会带来未知的后果。volumeMount额外的subPath 可以将文件挂载二不影响文件夹中其他的文件。

apiVersion: v1
kind: Pod
metadata:
  name: cm-volume-subpath
spec:
  containers:
  - image: nginx
    name: cm-volume-subpath
    volumeMounts:
    - name: etc-config
      mountPath:  /etc/hosts   # 该文件必须在容器中存在
      subPath: ss1     # 在ConfigMap  cm-3中条目的键名
  volumes:
  - name: etc-config
    configMap: 
      name: cm-3

设置权限

volumes:
- volumes:
  configMap:
    name: test
    defaultMode: "6600"   # 权限设置为 "-rw-rw----"
    需要注意的,subPath 单独挂载一个文件,是不支持热更新的。但当挂载整个ConfigMap数据卷时,ConfigMap更新后,容器中的内容也会更新。进到容器中查看挂载文件夹下,各文件的属性,会发现它们是属于链接文件 ..data/xxx  。如果要更新指定的一个文件,可以先把数据卷挂载到另一个目录,然后创建符号链接指向目标文件,符号链接可以再容器中原生创建,也可以在容器启动的时候创建。
    容器一个很重要的特性就是不变性,从同一个镜像创建的pod,他们之间没有任何差异,但是通过修改被运行容器使用的configMap数据,会打破这种不变性。但其中的关键是,应用是否支持重载配置,如果应用不支持重载配置,ConfigMap更新之前创建的pod会使用旧的配置文件,但是新创建的pod就会使用更新后的的配置,所以会导致运行中的容器的配置不同,并且不单是新建的pod,如果因为某些原因,pod中运行的容器发生重启,也将会使用新配置。因此,如果应用程序不支持热更新,那么修改某些运行pod的所使用的ConfigMap并不是一个好主意。
    如果应用程序支持热更新,那修改ConfigMap就不算什么了,但需要注意的是,因为configMap数据卷中的文件更新行为对于运行中的pod而言,不是同步的,所以它们还是会保持一段时间配置不一致的情况,可能长达一分钟。

Secret 传递敏感信息

Secret 与ConfigMap类似,都是采用键值对的形式,Secret与ConfigMap使用方法与ConfigMap类似

  • 将Secret 条目作为环境变量传递给容器
  • 将Secret条目暴露为数据卷的文件

kubernetes 通过仅仅将Secret分发到需要访问Secret的pod所在的机器节点来保障安全性。另外,Secret只会保存在节点的内存中,永远不写入物理存储,这样在节点上删除Secret时就不需要搽除磁盘了。

默认令牌Secret 介绍
对任意一个pod,使用命令kubectl describe pod 输出都会包含以下信息

Volumes:
  default-token-8wzm5:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-8wzm5
    Optional:    false

并且还可看到secret数据卷被挂载的路径

Mounts:
  /var/run/secrets/kubernetes.io/serviceaccount from default-token-8wzm5 (ro)

每个pod都会自动挂载一个secret数据卷,由于Secret也是一个资源对象,所以可以采用kubectl describe secret default-token-8wzm5 来获取一些详细信息。

Name:         default-token-8wzm5
Namespace:    default
Labels:       >
Annotations:  kubernetes.io/service-account.name: default
              kubernetes.io/service-account.uid: 3b82d73e-92fe-419a-afb4-25767b7690e8

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJ ... #(太长了,就不展示了)

可以看到secret包含三个条目,ca.crt、namespace、token。包含了pod内部安全访问kubernetes API服务所需要的全部信息。
default-token Secret默认会被挂载至每一个容器,可以通过设置pod定义中的aotomountServiceAccountToken 字段为false。或者设置pod使用的服务账户中相同自动为false来关闭这种默认行为。

创建 Secret
需要创建私钥与证书,由于要确保私钥的安全性,可将其与证书同时存入Secret
在本地生产私钥

openssl  genrsa  -out test.key  2048

生产证书

openssl req  -new -x509 -key test.key -out test.cert -days s650 -subj /CN=www.test.com

创建Secret

kubectl  create secret generic test-secret  --from-file=test.key  --from-file=test.cert

查看Secret

kubectl  get secret

查看test-secret 的描述信息

kubectl  describe  secret test-secret

使用Secret

spec:
  containers:
  - image: xxx
    name: xxx
    volumeMount:
    - name: test-key
      mountPath: xxx
  volumes:
  - name: test-key
   secret:
     secretName: test-secret

镜像拉取Secret
在docker hub上海支持创建私有镜像,从一个私有仓库中拉取一个私有镜像需要做两件事

  • 创建包含docker镜像仓库证书的Secret
  • pod定义中的imagePullSecrets 字段引用该Secret

创建一个docker镜像仓库的证书

kubectl  create  secret  docker-registry mydockerhubsecret \
--docker-username=myusername  --docker-password=mypassword \
--docker-[email protected]

这里创建了一个docker-registry 类型的secret ,通过kubectl describe 查看发现,其只有一个条目 .dockerconfigjson ,相当于用户主目录下的.dockerconfigjson文件,这文件通常在运行 docker login 命令时由Docker主动创建

在pod中使用docker-registry Secret
pull-private-image-secret.yaml

apiVersion: v1
kind: Pod
metadata:
   name: test-docker-registry-secret
spec:
  imagePullSecrets:
  - name: mydockerhubsecret  # 能够从私有仓库中拉取镜像
  containers:
  - image: bqwu/ubuntu:v1
    name: ubuntu-test
    command: ["/bin/bash", "-c", "while true; do sleep 3; done"]

(本文章是学习《kubernetes in action》 一书时做的笔记,由于本人是刚学习k8s,且自学方式就是把它敲一遍,然后加一些自己的理解。所以会发现很多内容是跟书中内容一模一样,如果本文是对本书的侵权,敬请谅解,告知后会删除。如果引用或转载,请注明出处——谢谢)

你可能感兴趣的:(k8s)