k8s ConfigMap & Secret

一、ConfigMap
ConfigMap中包含了Map单词(Map其实就是key:value),主要是管理一些可变配置信息,如应用的配置文件、应用里面的环境变量、命令行参数。它可以让一些可变配置和容器进行解耦,保证了容器的可移植性。
 
kubectl命令创建ConfigMap时,可以指定文件、指定目录或直接指定键值对。
指定文件和目录的命令如下:
kubectl create configmap XXX  --from-file=XXX -n kube-system
若指定的是文件,文件名就是Map中的key,文件内容就是Map中的value。
若指定的是目录,目录中的每个配置文件名都被会被设置为key。
直接指定键值对的命令如下:
kubectl create configmap XXX  --from-literal=key=value --from-literal=key=value
指定的数据键值对,会直接映射到Map的key:value
 
被创建的ConfigMap除了apiVersion、kind、metadata外,还包括data部分
以下面的配置清单为例,可以看到它管理了两个直接指定的键值对和一个配置文件
kind: ConfigMap
apiVersion: v1
metadata:
  name: five-nginx
  namespace: default
data:
  example.property.1: hello
  example.property.2: world
  example.property.file: |-
    property.1=value-1
    property.2=value-2
    property.3=value-3
 
Pod里使用ConfigMap有以下几种方式:
(1)填充环境变量。
通过configMapKeyRef指定ConfigMapKeySelector
ConfigMapKeyRef字段中,name是指定ConfigMap名,key是ConfigMap.data里面的key。
apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh", "-c", "env" ]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: example-config       # 需使用的ConfigMap名称,必须已存在
              key: example.property.1    # 对应ConfigMap data的key
  restartPolicy: Never
(2)通过Volume挂载的方式将ConfigMap里的内容直接挂到容器的某一个目录下面去
apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh","-c","ls -l /etc/config/path/" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: example-config
  restartPolicy: Never
创建的文件可以通过defaultMode指定默认文件权限,注意:由于json文件不支持八进制,使用时应使用十进制
直接指定的键值对,创建的文件名为key、文件内容就是value;配置文件则原样不变。
 
若ConfigMap中有多个文件:
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-cfgmap
data:
  app.conf: file data
  ......
只想把其中一个文件从ConfigMap挂载到Pod,可以通过subPath的方式,具体配置有两种方法:
(1)ConfigMap中的key、 volumeMounts.mountPath和volumeMounts.subPath名称一定要保持一致,否则会挂载不成功。
apiVersion: v1
kind: Pod
metadata:
  name: test-pd-plus-cfgmap
spec:
  containers:
  - image: ubuntu
    name: bash
    volumeMounts:
    - mountPath: /usr/local/app.conf
      name: cfgmap
      subPath: app.conf
  volumes:
  - name: cfgmap
    configMap:
      name: test-cfgmap
(2)这种方式使用ConfigMap,就不再要求ConfigMap中的key跟挂载的文件名必须一致,但需要在items指定key和path对应关系:
apiVersion: v1
kind: Pod
metadata:
  name: test-pd-plus-cfgmap
spec:
  containers:
  - image: ubuntu
    name: bash
    volumeMounts:
    - mountPath: /usr/local/app.conf
      name: cfgmap
      subPath: app.conf
  volumes:
  - name: cfgmap
    configMap:
      name: test-cfgmap
      items:
      - key: app.conf       # 指定Configmap中的文件对应的key
        path: app.conf      # 指定生成的配置文件名称
 
 
二、Secret
Secret是一个主要用来存储敏感信息的资源对象。采用base-64编码保存。
Secret的创建:
  • 系统创建:比如k8s为每一个namespace的默认用户(default ServiceAccount)创建 Secret,名称为default-token-xxxxx
  • 用户手动创建:使用kubectl命令行工具时,data参数的写法与ConfigMap一致,相对ConfigMap会多一个 type 参数,不指定的话默认是Opaque类型。
kubectl create secret generic xxx —from-file=xxx —type=kubernetes.io/dockerconfigjson
kubectl create secret generic xxx —from-literal=key=value —from-literal=key=value
被创建的Secret除了apiVersion、kind、metadata外,还增加了type字段,指出Secret的类型,包括:
  • Opaque:普通的Secret文件,
  • kubernetes.io/service-account-token:是用于service-account身份认证用的Secret
  • kubernetes.io/dockerconfigjson:拉取私有仓库镜像的用的Secret
  • kubernetes.io/bootstrap.token:用于节点接入集群校验用的Secret
它和ConfigMap一样也有data字段,是存储的Secret的数据,它也是key-value的形式存储的。
apiVersion: v1
kind: Secret
metadata:
  name: example-secret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm
 
Pod里使用Secret有以下几种方式:
(1)填充环境变量。
通过secretKeyRef指定SecretKeySelector    
(2)通过volume挂载的方式直接把Secret中的内容挂到容器的某一个目录下
k8s会自动把default-token-xxxxx挂载到容器 /var/run/secrets/kubernetes.io/serviceaccount目录下。该secret包括三个文件:ca.crt、namespace(空文件)、token,它们保存了认证相关信息
(3)拉取镜像文件
通过命令创建:
kubectl create secret docker-registry ${secret_name} --docker-server=xxx --docker-username=xxx --docker-password=Axxx -n xxx
将私有镜像仓库的信息存储在Secret里面
apiVersion: v1
kind: Secret
metadata:
  name: image-test-secret
  namespace: default
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: xxxxxxx
加密部分的明文为:
{
    "auths": {
        "xxx": {
            "username": "xxxxx",
            "password": "xxxxx",
            "auth": "xxxxxxxxx"
        }
    }
}
其中auth部分的密文是username:passward的base64结果
 
Pod通过Pod.spec.impagePullSecrets字段使用该Secret:
apiVersion: v1
kind: Pod
metadata:
  name: foo
  namespace: default
spec:
  containers:
    - name: foo
      image: janedoe/awesomeapp:v1
  imagePullSecrets:
    - name: image-test-secret
此外,还可以提前在Pod会使用的serviceaccount里配置imagePullSecrets
kubectl -n css patch serviceaccount default -p '{"imagePullSecrets": [{"name": "harbor-css-user"}]}'
Pod创建时系统会自动注入此Secret。
 

三、注意要点

Secret注意要点

Secret采用了base-64编码,安全程度不高。推荐可以使用开源的vault来解决敏感信息的加密和权限管理。

Secret读取不要用list/watch,否则会把namespace下的所有Secret全部拉取下来。推荐使用get,只获取需要的那个Secret。

 

共通的注意要点

虽然ConfigMap/Secret文件没有大小限制。但是在Etcd里面数据的写入是有大小限制的,现在是限制在1MB以内;

只有通过apiserver创建的Pod才能使用ConfigMap/Secret,kubelet通过manifest创建的static Pod不能使用。

把ConfigMap/Secret里面所有的信息导入成环境变量时,如果有些key是无效的(比如key里带有数字),那么这个环境变量会直接被忽略,不会注入容器,但是这个Pod本身是可以创建的。

ConfigMap/Secret具有热更新能力,但只有整个作为Volume挂载到容器中的时候,才能热更新。通过环境变量、通过subPath挂载都不行。Pod内感知到Volume更新的时间与kubelet的--sync-frequency配置有关。

 

参考资料:

[1] https://kubernetes.io/docs/home/

[2] https://edu.aliyun.com/roadmap/cloudnative

posted @ 2020-06-11 15:00  扬羽流风  阅读(350)  评论(0编辑  收藏  举报