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)填充环境变量。
通过valueFrom进行使用: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
填充的环境变量可以直接拿到cmd字段作为命令行参数使用:
如下例,Pod启动后,会打印hello world。
apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: example-config
              key: example.property.1
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: example-config
              key: example.property.2
  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
在/etc/config目录下会创建3个文件:直接指定的键值对,创建的文件名为key、文件内容就是value;配置文件则原样不变。
 
若ConfigMap中有多个文件::
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-cfgmap
data:
  app.conf: file data
  ......
只想把app.conf文件从ConfigMap挂载到Pod,其他文件不可见,有三种方式:
(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      # 指定生成的配置文件名称
(3)挂载ConfigMap到一个其它路径,然后通过软连接的方式链接到需要的文件。
 
ConfigMap注意要点
  1. 虽然ConfigMap文件没有大小限制。但是在Etcd里面数据的写入是有大小限制的,现在是限制在1MB以内;
  2. ConfigMap.metadata里面是有namespace字段的。Pod只能引用相同Namespace中的ConfigMap;
  3. Pod引用ConfigMap时,假如不存在,那么这个Pod无法创建成功的;
  4. 把ConfigMap里面所有的信息导入成环境变量时,如果ConfigMap里有些key是无效的(比如key里带有数字),那么这个环境变量会直接被忽略,不会注入容器,但是这个Pod本身是可以创建的。
  5. 只有通过apiserver创建的Pod才能使用ConfigMap,kubelet通过manifest创建的static pod不能使用ConfigMap。
二、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)填充环境变量。
通过valueFrom进行使用:secretKeyRef字段中,name是指定Secret名,key是Secret.data里面的key。
apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
    - name: mycontainer
      image: redis
      env:
        - name: SECRET_USERNAME
          valueFrom:
            secretKeyRef:
              name: example-secret   
              key: username          
        - name: SECRET_PASSWORD
          valueFrom:
            secretKeyRef:
              name: example-secret
              key: password
(2)通过volume挂载的方式直接把Secret中的内容挂到容器的某一个目录下:
apiVersion: v1
kind: Pod
metadata:
  name: mypod
  namespace: default
spec:
  containers:
  - image: redis
    name: mypod
    volumeMounts:
    - mountPath: /etc/foo
      name: foo
      readOnly: true
  volumes:
  - name: foo
    secret:
      defaultMode: 420      
      secretName: example-secret
注意:defalutMode指定默认文件权限时,由于json文件不支持八进制,使用时应使用十进制
k8s会自动把default-token-xxxxx挂载到容器 /var/run/secrets/kubernetes.io/serviceaccount目录下。该secret包括三个文件:ca.crt、namespace(空文件)、token,它们保存了认证相关信息
(3)拉取镜像文件。
通过命令创建:
kubectl create secret docker-registry xxxxx   --docker-server=reg.harbor.com --docker-username=xxxx --docker-password=xxxxxx -n xxxxx
将私有镜像仓库的信息存储在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,Pod创建时系统会自动注入此Secret。
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2020-05-21T07:52:58Z"
  name: default
  namespace: default
  resourceVersion: "182"
  selfLink: /api/v1/namespaces/default/serviceaccounts/default
  uid: 517ca0ab-a675-4f3d-a2b4-6bb3d26ab8a7
secrets:
- name: default-token-848wt
imagePullSecrets: 
- name: image-test-secret

Secret注意要点:

  1. Secret的文件大小限制和ConfigMap一样,也是1MB;
  2. Secret采用了base-64编码,安全程度不高。推荐可以使用开源的vault来解决敏感信息的加密和权限管理。
  3. Secret读取不要用list/watch,否则会把namespace下的所有Secret全部拉取下来。推荐使用GET的方法,只获取需要的那个Secret。

参考资料:

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

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

原文地址:https://www.cnblogs.com/yangyuliufeng/p/14217926.html