Keburnetes 配置资源管理 Secret ConfigMap

Secret 资源   

用于保存密码文件、tls证书/私钥文件、token令牌字符串、镜像私有仓库认证信息 等需要加密的敏感的信息

Secret资源的 4 种类型

  1. Opaque:默认的Secret资源类型,可以通过选项引用文件、目录、键值对的方式创建Secret资源,并且资源数据的键值会自动转换成base64编码格式
  2. kubernetes.io/tls:用于存储 tls 证书和私钥文件的信息
  3. kubernetes.io/dockerconfigjson:用于存储K8S从harbor等镜像私有仓库拉取镜像时做认证的信息
  4. kubernetes.io/service-account-token:当创建serviceaccount账户资源后K8S会自动创建相关的Secret资源,当Pod访问apiserver时需要使用此Secret资源做认证

Pod 需要先引用才能使用某个 secret,Pod 有 3 种方式来使用 secret:
●作为挂载到一个或多个容器上的卷 中的文件。
●作为容器的环境变量。
●由 kubelet 在为 Pod 拉取镜像时使用。

应用场景:凭据
https://kubernetes.io/docs/concepts/configuration/secret/

创建 Secret资源

kubectl create secret generic|tls|docker-registry <资源名称> 选项
                      generic <资源名称> --from-file=文件|目录    --from-literal=<键名>=<键值>
                      tls <资源名称> --cert=证书文件路径  --key=私有文件路径
                      docker-registry <资源名称> --docker-server=私有仓库URL地址 --docker-username=用户名 --docker-password=密码 --docker-email=邮箱

使用 Secret资源

挂载的方式
在 Pod 资源配置中的 spec.volumes 字段设置 secret 类型的存储卷
在容器配置中用volumeMounts将卷挂载到容器的挂载点目录上,Secret资源数据的键名会作为文件名,Secret资源数据的键值会作为文件内容

容器环境变量引用的方式
在容器配置中用 env.name 字段自定义容器的环境变量名,在 env.valueFrom.secretKeyRef.name/key 字段指定自定义的变量的值从哪个 Secret资源 的 键 获取 值
在容器配置中用 envFrom.secretRef.name 字段指定 Secret资源的名称,使得 Secret资源的 键 和 值 作为容器的环境变量名和环境变量的值


创建 Secret (Opaque类型)

方法1 陈述式 自动转码

1、用kubectl create secret命令创建Secret

echo -n 'zhangsan' > username.txt
echo -n 'abc1234' > password.txt

根据文件内容生成secret 

kubectl create secret generic mysecret --from-file=username.txt --from-file=password.txt
kubectl get secrets

NAME                  TYPE                                  DATA   AGE
default-token-8pqp6   kubernetes.io/service-account-token   3      3d1h
mysecret              Opaque                                2      51s
kubectl describe secret mysecret

Name:         mysecret
Namespace:    default
Labels:       
Annotations:  

Type:  Opaque

Data
====
password.txt:  7 bytes
username.txt:  8 bytes

//get或describe指令都不会展示secret的实际内容,这是出于对数据的保护的考虑

方法2  声明式  注意声明式需要先手动转码!!! 不然明文保存  

内容用 base64 编码,创建Secret

使用echo输出到base64查看转码后结果

echo -n zhangsan | base64
emhhbmdzYW4K=

echo -n abc1234 | base64
YWJjMTIzNAo==
将base64转码后的结构写入yaml文件
vim secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysecret1
type: Opaque
data:
  username: emhhbmdzYW4K=
  password: YWJjMTIzNAo==
kubectl create -f secret.yaml

 由于是base64编码,所以密码可以反推,也不是足够安全。 

kubectl get secrets

NAME                  TYPE                                  DATA   AGE
default-token-8pqp6   kubernetes.io/service-account-token   3      3d1h
mysecret              Opaque                                2      43m
mysecret1             Opaque                                2      6s
kubectl get secret mysecret1 -o yaml

apiVersion: v1
data:
  password: YWJjMTIzNAo==
  username: emhhbmdzYW4K=
kind: Secret
metadata:
  creationTimestamp: 2021-05-24T09:11:18Z
  name: mysecret1
  namespace: default
  resourceVersion: "45641"
  selfLink: /api/v1/namespaces/default/secrets/mysecret1
  uid: fffb7902-bc6f-11eb-acba-000c29d88bba
type: Opaque

创建 Secret (tls类型)

这里使用陈述式创建。tls类型需要指定证书以及秘钥。

cd /etc/kubernetes/pki
#k8s证书文件夹

kubectl create secret tls ca-secret --cert=./ca.crt --key=./ca.key
#根据证书创建tls类型secret

创建 Secret (docker-registry类型)

这里使用陈述式创建。docker-registry类型指定harbor服务器ip,用户,密码,邮箱 。用于从harbor仓库拉取镜像时做认证。

kubectl create secret docker-registry harbor-secret --docker-server=http://192.168.80.105 --docker-username=admin --docker-password=Harbor123456 [email protected]

创建后使用时需要在yaml文件进行更改,添加imagepullsecret指定刚刚创建的 docker-registry类型的secret。这样就能拉取仓库中需要登录信息才能获取的镜像。

Keburnetes 配置资源管理 Secret ConfigMap_第1张图片

注意,secret也存在命名空间。若创建的资源(例如pod.yaml内 容器需要拉取私有镜像)与docker-registry不处于同一个命名空间,拉取仍然会因为没有认证信息而失败。-n 指定命名空间


使用方式 

1、挂载使用方式

将 Secret 挂载到 Volume 中,以 Volume 的形式挂载到 Pod 的某个目录下

vim secret-test.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: secrets #挂载name为secret的存储卷
      mountPath: "/etc/secrets"
      readOnly: true

  volumes: #存储卷
  - name: secrets
    secret: #secret方式
      secretName: mysecret #刚刚创建的secret资源name
kubectl create -f secret-test.yaml
kubectl get pods

NAME         READY   STATUS    RESTARTS   AGE
seret-test   1/1     Running   0          16s
kubectl exec -it seret-test bash
 # cd /etc/secrets/
 # ls
    password.txt  username.txt
 # vi password.txt 
 # vi username.txt 

可见外部加密的信息,挂载后自动解密。

2、变量使用方式

将 Secret 导出到环境变量中

vim secret-test1.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod1
spec:
  containers:
  - name: nginx
    image: nginx
    env: #环境变量
      - name: TEST_USER
        valueFrom: #名为TEST_USER的环境变量的取值,从secret取
          secretKeyRef: #secretKeyRef引用方式
            name: mysecret1 #指明引用哪个secret资源
            key: username #指明引用的secret中的键
      - name: TEST_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret1
            key: password
    envFrom: #也可以不用上面先自定义环境变量name,再从secret中选择键的值为其赋值。而是直接使用secret中的键值对作为环境变量的name与key。
    - secretRef:
        name: mysecret1 #指明引用哪个secret资源
kubectl apply -f secret-test1.yaml
kubectl get pods

NAME         READY   STATUS    RESTARTS   AGE
mypod1       1/1     Running   0          77s
kubectl exec -it mypod bash

 # echo $TEST_USER
    zhangsan
 # echo $TEST_PASSWORD
    abc1234




ConfigMap资源

ConfigMap 资源 (简称 cm)

用于保存 配置文件  环境变量  命令行参数 之类的不需要加密的信息

创建 cm资源

kubectl create cm <资源名称>  --from-file=文件|目录    --from-literal=<键名>=<键值>

查看 cm资源

kubectl get cm <资源名称> -o yaml    或    kubectl  describe cm <资源名称> 

使用 cm资源

挂载的方式
在 Pod 资源配置中的 spec.volumes 字段设置 configMap 类型的存储卷
在容器配置中用volumeMounts将卷挂载到容器的挂载点目录上,cm资源数据的键名会作为文件名,cm资源数据的键值会作为文件内容(以目录形式挂载的cm卷支持热更新)
在容器配置中用volumeMounts.subPath指定文件名,可实现将卷挂载到容器的文件上(以文件形式挂载的cm卷不支持热更新)

容器环境变量引用的方式(不支持热更新)
在容器配置中用 env.name 字段自定义容器的环境变量名,在 env.valueFrom.configMapKeyRef.name/key 字段指定自定义的变量的值从哪个 cm资源 的 键 获取 值
在容器配置中用 envFrom.configMapRef.name 字段指定 cm资源的名称,使得 cm资源的 键 和 值 作为容器的环境变量名和环境变量的值

 Pod 中使用 ConfigMap (通过挂载方式) 

CM的简单示例,创建cm,挂载使用cm中的内容(挂载到容器内的目录,目录方式挂载),热更新

创建网页文件

echo "114514" > index.html

从这个文件创建cm 

kubectl create cm myapp-cm --from-file=./index.html
    更改index.html下的内容

创建pod,创建存储卷时引用刚刚的cm(cm存储了网页文件名以及网页内容),再让pod挂载,即为cm中内容挂载到了pod的网页发布目录,借由pod中nginx 发布。

但是注意,虽然这个cm里面只有一个文件,但是在此处并未指定文件方式挂载,而是默认的目录方式挂载,会把整个目录覆盖。若只需要覆盖某个文件,使用下方实例的文件挂载(加上subpath参数)。

Keburnetes 配置资源管理 Secret ConfigMap_第2张图片

并且支持热更新,只需要更改cm内容,即可实现对pod内资源更改,并不需要对pod本身进行更改

kubectl edit cm myapp-cm
    更改index.html下的内容

Keburnetes 配置资源管理 Secret ConfigMap_第3张图片

CM的简单示例,挂载使用cm中的内容(挂载到容器内的文件,文件方式挂载)

事先准备好nginx.conf文件,写入cm。然后作为存储卷,让pod挂载。

kubectl create cm myapp-cm --from-file=./nginx.conf

由于此时并不能像上一个实例一样覆盖掉整个文件夹,需要只单独覆盖一个文件,所以此时需要加上subPath选项,让系统识别目录中的子文件。

注意,挂载如果使用subpath选项 默认认为是目录,无论文件后缀 

Keburnetes 配置资源管理 Secret ConfigMap_第4张图片

另外,像这种文件方式挂载,无法进行热更新(目录挂载可以)

完整的创建 ConfigMap 方法

 1、使用目录创建

mkdir /opt/configmap/
vim /opt/configmap/game.config

enemy.types=aliens,monsters
player.maximum-lives=5 
vim /opt/configmap/ui.config

color.good=purple
color.bad=yellow
allow.textmode=true
ls /opt/configmap/

game.config
ui.config
kubectl create configmap game-config --from-file=/opt/configmap/

--from-file 指定在目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对,键的名字就是文件名,值就是文件的内容

kubectl get cm

NAME          DATA   AGE
game-config   2      10s

kubectl get cm game-config -o yaml
apiVersion: v1
data:
  game.config: |
    enemy.types=aliens,monsters
    player.maximum-lives=5 
  ui.config: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
kind: ConfigMap
metadata:
  creationTimestamp: 2021-05-25T06:49:18Z
  name: game-config
  namespace: default
  resourceVersion: "87803"
  selfLink: /api/v1/namespaces/default/configmaps/game-config
  uid: 541b5302-bd25-11eb-acba-000c29d88bba

2、使用文件创建 
只要指定为一个文件就可以从单个文件中创建 ConfigMap
--from-file 这个参数可以使用多次,即可以使用两次分别指定上个实例中的那两个配置文件,效果就跟指定整个目录是一样的

kubectl create configmap game-config-2 --from-file=/opt/configmap/game.properties --from-file=/opt/configmap/ui.properties
kubectl get configmaps game-config-2 -o yaml
kubectl describe cm game-config-2

3、使用字面值创建 
使用文字值创建,利用 --from-literal 参数传递配置信息,该参数可以使用多次,格式如下

kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=good
kubectl get configmaps special-config -o yaml

apiVersion: v1
data:
  special.how: very                    #key-value 结构
  special.type: good
kind: ConfigMap
metadata:
  creationTimestamp: 2021-05-25T06:59:37Z
  name: special-config
  namespace: default
  resourceVersion: "88610"
  selfLink: /api/v1/namespaces/default/configmaps/special-config
  uid: c4f45936-bd26-11eb-acba-000c29d88bba
kubectl delete cm --all
kubectl delete pod --all

 Pod 中使用 ConfigMap (通过环境变量方式) 

1、使用 ConfigMap 来替代环境变量
创建ConfigMap配置文件

vim env.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: good
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
  log_level: INFO


上方yaml文件也可以用命令代替(陈述式与声明式写法区别)
kubectl create cm special-config --from-literal=special.how=very --from-literal=special.type=good
kubectl create cm env-config --from-literal=log_level=INFO
kubectl create -f env.yaml
kubectl get cm

NAME             DATA   AGE
env-config       1      6s
special-config   2      6s

创建Pod调用ConfigMap资源

vim test-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: busybox
    image: busybox:1.28.4
    command: [ "/bin/sh", "-c", "env" ]

    env: #定义环境变量,定义名称,值则来自cm
      - name: SPECIAL_HOW_KEY
        valueFrom:
          configMapKeyRef: #引用CM
            name: special-config #上面创建CM的名字
            key: special.how #CM中的键
      - name: SPECIAL_TYPE_KEY
        valueFrom:
          configMapKeyRef: #引用CM
            name: special-config #上面创建CM的名字
            key: special.type #CM中的键

    envFrom: #或者直接把cm内的值作为容器的变量,键值全部从cm取,而不是上面env的键自定义,只有值从cm取
      - configMapRef: #引用CM
          name: env-config
  restartPolicy: Never
kubectl create -f test-pod.yaml
kubectl get pods

NAME         READY   STATUS      RESTARTS   AGE
pod-test     0/1     Completed   0          33s
kubectl logs pod-test

KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.0.0.1:443
HOSTNAME=pod-test
SHLVL=1
SPECIAL_HOW_KEY=very            #赋值变量 SPECIAL_HOW_KEY 的值为 special-config 的 special.how: very
HOME=/root
SPECIAL_TYPE_KEY=good            #赋值变量 SPECIAL_TYPE_KEY 的值为 special-config 的 special.type: good
KUBERNETES_PORT_443_TCP_ADDR=10.0.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
log_level=INFO                    #引入 env-config 的变量 log_level: INFO
KUBERNETES_PORT_443_TCP=tcp://10.0.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.0.0.1
PWD=/

注意这种环境变量方式也不支持热更新。只有文件挂载的目录挂载才可以热更新



2、用 ConfigMap 设置命令行参数 

vim test-pod2.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-pod2
spec:
  containers:
  - name: busybox
    image: busybox:1.28.4
    command: 
    - /bin/sh
    - -c
    - echo "$(SPECIAL_HOW_KEY) $(SPECIAL_TYPE_KEY)"
    env:
      - name: SPECIAL_HOW_KEY
        valueFrom:
          configMapKeyRef:
            name: special-config
            key: special.how
      - name: SPECIAL_TYPE_KEY
        valueFrom:
          configMapKeyRef:
            name: special-config
            key: special.type
    envFrom:
      - configMapRef:
          name: env-config
  restartPolicy: Never
kubectl create -f test-pod2.yaml
kubectl get pods

NAME        READY   STATUS      RESTARTS   AGE
test-pod2   0/1     Completed   0          34s
kubectl logs test-pod2
    very good

 3、通过数据卷插件使用ConfigMap 
在数据卷里面使用 ConfigMap,就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容

vim test-pod3.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-pod3
spec:
  containers:
  - name: busybox
    image: busybox:1.28.4
    command: [ "/bin/sh", "-c", "sleep 36000" ]
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config
  restartPolicy: Never
kubectl create -f test-pod3.yaml 
kubectl get pod

NAME        READY   STATUS      RESTARTS   AGE
test-pod3   1/1     Running     0          5s
kubectl exec -it test-pod3 sh

 # cd /etc/config/
 # ls
    special.how   special.type
 # vi special.how 
 # vi special.type 

ConfigMap 的热更新 

vim test-pod4.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: log-config
  namespace: default
data:
  log_level: INFO
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 1
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-volume
          mountPath: /etc/config
      volumes:
        - name: config-volume
          configMap:
            name: log-config
kubectl apply -f test-pod5.yaml
kubectl get pods

NAME                        READY   STATUS    RESTARTS   AGE
my-nginx-76b6489f44-6dwxh   1/1     Running   0          46s
kubectl exec -it my-nginx-76b6489f44-6dwxh -- cat /etc/config/log_level
    INFO
kubectl edit configmap log-config

apiVersion: v1
data:
  log_level: DEBUG        #INFO 修改成 DEBUG
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"log_level":"DEBUG"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"log-config","namespace":"default"}}            #INFO 修改成 DEBUG
  creationTimestamp: 2021-05-25T07:59:18Z
  name: log-config
  namespace: default
  resourceVersion: "93616"
  selfLink: /api/v1/namespaces/default/configmaps/log-config
  uid: 1b8115de-bd2f-11eb-acba-000c29d88bba


//等大概10秒左右,使用该 ConfigMap 挂载的 Volume 中的数据同步更新 

kubectl exec -it my-nginx-76b6489f44-6dwxh -- cat /etc/config/log_level
    DEBUG

ConfigMap 更新后滚动更新 Pod

更新 ConfigMap 目前并不会触发相关 Pod 的滚动更新,可以通过在 .spec.template.metadata.annotations 中添加 version/config ,每次通过修改 version/config 来触发滚动更新

kubectl patch deployment my-nginx --patch '{"spec": {"template": {"metadata": {"annotations": {"version/config": "20210525" }}}}}'
kubectl get pods

NAME                        READY   STATUS              RESTARTS   AGE
my-nginx-665dd4dc8c-j4k9t   0/1     ContainerCreating   0          4s
my-nginx-76b6489f44-6dwxh   0/1     Terminating         0          10m
kubectl get pods

NAME                        READY   STATUS    RESTARTS   AGE
my-nginx-665dd4dc8c-j4k9t   1/1     Running   0          74s

PS:更新 ConfigMap 后

●使用该 ConfigMap 挂载的 Env 不会同步更新(只有文件挂载才能热更新)。
●使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新。


 

你可能感兴趣的:(kubernetes,容器,云原生,运维,linux)