k8s☞10应用配置与密码与信息提供

阅读量: zyh 2020-09-17 11:19:04
Categories: > Tags:

前言

在Pod中应用配置和密码,我们可以创建配置对象ConfigMap和密码对象Secret。

而这两种对象的使用有多种方式:

非加密ConfigMap

https://kubernetes.io/docs/concepts/configuration/configmap/

ConfigMap 常用在两种情况中. 第一种是提供环境变量.第二种是提供配置文件

写法

kind: ConfigMap
apiVersion: v1
metadata:
  name: cm-demo
  namespace: default
data:
  data.1: hello
  data.2: world
  data.conf: |
    property.1=value-1
    property.2=value-2
    property.3=value-3
#immutable: true
immutable: true 表示这是一个不可变更的CM,一旦CM创建,则这个属性不可更改。意味着如果你要更改,则需要删除CM和调用CM的Pod。

上述例子中, 包含两种写法

  data.1: hello
  data.2: world
  data.conf: |
    property.1=value-1
    property.2=value-2
    property.3=value-3

data.conf 是文件名, 管道符 | 下面是文件内容. ✨需要注意的是, data.conf 内容依然要遵循 yaml 的缩进规则

命令式写法

kubectl create cm cm-demo --from-file=data.conf

使用

apiVersion: apps/v1
kind: Deployment
metadata:
  name: busybox
spec:
  replicas: 1
  selector:
    matchLabels:
      run: busybox
  template:
    metadata:
      labels:
        run: busybox 
    spec:
      containers:
      - name: busybox
        image: busybox
        command: ["/bin/sh", "-c", "echo ${DATA1} ${DATA2}"]
        env:
        - name: DATA1
          valueFrom:
            configMapKeyRef:
              name: cm-demo  # 注意,这是ConfigMap对象名
              key: data.1    # 这是ConfigMap里的key
        - name: DATA2
          valueFrom:
            configMapKeyRef:
              name: cm-demo
              key: data.2
        volumeMounts:
        - name: cm-demo-vol
          mountPath: "/etc"  # cm 对象获取的 key 内容文件的根路径。
          readOnly: true
      volumes:
      - name: cm-demo-vol
        configMap:
          name: cm-demo
          items:             # items 就是获取 cm 对象下的所有 key
          - key: "data.conf" # 获取名叫 data.conf 的 key
            path: "data.conf" # 将 data.conf 这个 key 的内容写入到 /etc/data.conf 这个路径文件里

通过上面的写法,可以在容器内找到 /etc/data.conf 。

✨当你更新 cm 对象的时候,cm 对象会把更新内容同步到容器中。更新速度并不是立马就能响应,也是轮询更新。

💥注意:这种方式会清空 mountPath 路径。因为挂载点是目录。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: busybox
spec:
  replicas: 1
  selector:
    matchLabels:
      run: busybox
  template:
    metadata:
      labels:
        run: busybox 
    spec:
      containers:
      - name: busybox
        image: busybox
        command: ["/bin/sh", "-c", "echo ${DATA1} ${DATA2}"]
        env:
        - name: DATA1
          valueFrom:
            configMapKeyRef:
              name: cm-demo  # 注意,这是ConfigMap对象名
              key: data.1    # 这是ConfigMap里的key
        - name: DATA2
          valueFrom:
            configMapKeyRef:
              name: cm-demo
              key: data.2
        volumeMounts:
        - name: cm-demo-vol
          subPath: data.conf         
          mountPath: "/etc/data.conf"
          readOnly: true
      volumes:
      - name: cm-demo-vol
        configMap:
          name: cm-demo

✨这种通过 subPath 获取 cm 的 key data.conf,并针对性的挂载到指定文件 /etc/data.conf 。可以避免挂载点是目录的时候被覆盖。

💥这种方式,cm对象修改无法同步到容器中。

        env:
        - name: DATA1
          valueFrom:
            configMapKeyRef:
              name: cm-demo  # 注意,这是ConfigMap对象名
              key: data.1    # 这是ConfigMap里的key
        - name: DATA2
          valueFrom:
            configMapKeyRef:
              name: cm-demo
              key: data.2
        envFrom:
        - configMapRef:
            name: cm-envs

加密Secret

https://kubernetes.io/docs/concepts/configuration/secret/

secret对象里的值需要写入加密后的.

写法

我们定义一个用户密码对,分别是username和password

secret对象要求值必须进行base64编码加密(当type为Opaque的时候).

[root@k8s00 test-yaml]# echo -n "admin" | base64
YWRtaW4=
[root@k8s00 test-yaml]# echo -n "admin321" | base64
YWRtaW4zMjE=
# 创建 secret 对象 mysecret
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
  namespace: default
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

👀type用来定义不同的类型,比较常用的有:

使用

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: busybox
    command:
    - sleep
    - "3600"
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password
    volumeMounts:
    - name: mysecret-vol
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: mysecret-vol
    secret:
      secretName: mysecret

✨secret 也支持 immutable: true ,即不可变的 secret。

通过在 spec.containers.envFrom.secretRef 中定义一组环境变量,这种方式要求 secret 里的 key 必须都符合 C_IDENTIFIER 规范.

kubectl explain deployment.spec.template.spec.containers.envFrom.secretRef

immutable: true

有以下好处

临时卷

环境变量

测试

在通过上述配置创建好资源后,我们进入pod,进行测试.

[root@k8s00 test-yaml]# kubectl exec -it mypod -- /bin/sh
===可以看到两个加密信息生成了两个软连接,并指向了隐藏文件
/ # ls -l /etc/foo
total 0
lrwxrwxrwx    1 root     root            15 Sep 17 07:18 password -> ..data/password
lrwxrwxrwx    1 root     root            15 Sep 17 07:18 username -> ..data/username
===环境变量
/ # echo ${SECRET_USERNAME}
admin
===文件方式
/ # cat /etc/foo/username
admin 

限制

其它

  1. 命令方式创建

    kubectl create configmap/secret xxx

    这里xxx可以用两种方式:

    • –from-literal== 指定kv
    • –from-file=<文件/目录> 当为目录的时候,会递归将目录里的文件都写入对象中
  2. 在Pod中隐藏配置或者密码文件

    你可以将 secret.data.<key> 写成 secret.data.<.key> 来隐藏它.

信息提供Downward API

https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/

Downward API用来向Pod中运行的容器公开提供容器和Pod的信息。

例子1:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: oom-sims
  namespace: default
  labels:
    app: oom-sims
spec:
  replicas: 1
  selector:
    matchLabels:
      app: oom-sims
  template:
    metadata:
      labels:
        app: oom-sims
    spec:
      volumes:
        - name: dumplog
          emptyDir: {}
      containers:
        - name: oom-sims-container
          image: cloudbeer/oom-sims:1.0
          command: ["/bin/sh", "-c", "java -Xms256m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dumplog/${RANDOM}.dump -jar /app/oom-sims-1.0-SNAPSHOT.jar 1000"]
          resources:
            requests:
              memory: "2Gi"
              cpu: "500m"
            limits:
              memory: "2Gi"
              cpu: "500m"
          volumeMounts:
          - name: dumplog
            mountPath: /dumplog
        - name: dumplogupload
          image: aaa103439/dumplogupload:latest
          env:
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: NODE_IP
            valueFrom:
              fieldRef:
                fieldPath: status.hostIP
          - name: OSS_ENDPOINT
            value: "oss-cn-beijing-internal.aliyuncs.com"
          - name: OSS_ACCESSID
            value: "" # 
          - name: OSS_ACCESSSECRET
            value: ""
          - name: OSS_BUCKET
            value: "juaiit"
          - name: OSS_DUMPER_ROOT
            value: "logs/dump/$(NAMESPACE)"
          - name: APP_NAME # 应用名称,这个名称会附加在文件名后面
            value: $(POD_NAME)_$(NODE_IP)
          - name: DUMPER_ROOT # 会监视这个文件夹下面的文件,-XX:HeapDumpPath = DUMPER_ROOT/xxx.DUMPER_SUFFIX
            value: "/dumplog" 
          - name: DUMPER_SUFFIX # dump 文件后缀
            value: ".dump"
          volumeMounts:
          - name: dumplog
            mountPath: /dumplog

例子2: 将资源限制数据挂载到容器/etc/podinfo

apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-downwardapi-volume-example-2
spec:
  containers:
    - name: client-container
      image: k8s.gcr.io/busybox:1.24
      command: ["sh", "-c"]
      args:
      - while true; do
          echo -en '\n';
          if [[ -e /etc/podinfo/cpu_limit ]]; then
            echo -en '\n'; cat /etc/podinfo/cpu_limit; fi;
          if [[ -e /etc/podinfo/cpu_request ]]; then
            echo -en '\n'; cat /etc/podinfo/cpu_request; fi;
          if [[ -e /etc/podinfo/mem_limit ]]; then
            echo -en '\n'; cat /etc/podinfo/mem_limit; fi;
          if [[ -e /etc/podinfo/mem_request ]]; then
            echo -en '\n'; cat /etc/podinfo/mem_request; fi;
          sleep 5;
        done;
      resources:
        requests:
          memory: "32Mi"
          cpu: "125m"
        limits:
          memory: "64Mi"
          cpu: "250m"
      volumeMounts:
        - name: podinfo
          mountPath: /etc/podinfo
  volumes:
    - name: podinfo
      downwardAPI:
        items:
          - path: "cpu_limit"
            resourceFieldRef:
              containerName: client-container
              resource: limits.cpu
              divisor: 1m
          - path: "cpu_request"
            resourceFieldRef:
              containerName: client-container
              resource: requests.cpu
              divisor: 1m
          - path: "mem_limit"
            resourceFieldRef:
              containerName: client-container
              resource: limits.memory
              divisor: 1Mi
          - path: "mem_request"
            resourceFieldRef:
              containerName: client-container
              resource: requests.memory
              divisor: 1Mi

projected volume使用方式

kubernetes 提供了一种卷类型 projected volume。可以将多个volume挂载到一个位置上。

写法:

        volumeMounts:
        - name: all-in-one
          mountPath: /etc/allinfo
          readonly: true
  volumes:
  - name: all-in-one
    projected:
      sources:
      - secret:
          name: user
      - secret:
          name: pass
      - configmap:
          name: content
      - downwardAPI:
          items:
            - path: "labels"
              fieldRef:
                fieldPath: metadata.labels
            - path: "annotations"
              fieldRef:
                fieldPath: metadata.annotations

user, pass, content, labels, annotations 将会以文件形式存在于容器挂载点 /etc/allinfo 内。

创建Secret对象: secret: user 和 secret: pass

echo -n "admin" > ./username.txt
kubectl create secret generic user --from-file=./username.txt
echo -n "1f2d1e2e67df" > ./username.txt
kubectl create secret generic pass --from-file=./password.txt

创建 ConfigMap对象: content

echo -n "userinfo" > ./content.txt
kubectl create configmap content --from-file=./content.txt

DownwardAPI 临时卷内容直接配置里写入