• k8s学习笔记之ConfigMap和Secret


    一、简介

    ConfigMap对像是一系列配置的集合,k8s会将这一集合注入到对应的Pod对像中,并为容器成功启动使用。注入的方式一般有两种,一种是挂载存储卷,一种是传递变量。ConfigMap被引用之前必须存在,属于名称空间级别,不能跨名称空间使用,内容明文显示。ConfigMap内容修改后,对应的pod必须重启或者重新加载配置。
    Secret类似于ConfigMap,是用Base64加密,密文显示,一般存放敏感数据。一般有两种创建方式,一种是使用kubectl create创建,一种是用Secret配置文件。

    使用场景

    我们经常都需要为我们的应用程序配置一些特殊的数据,比如密钥、Token 、数据库连接地址或者其他私密的信息。你的应用可能会使用一些特定的配置文件进行配置,比如settings.py文件,或者我们可以在应用的业务逻辑中读取环境变量或者某些标志来处理配置信息。
    我们要做到这个,有好多种方案,比如:
    1.我们可以直接在打包镜像的时候写在应用配置文件里面,但是这种方式的坏处显而易见而且非常明显。
    2.我们可以在配置文件里面通过 env 环境变量传入,但是这样的话我们要修改 env 就必须去修改 yaml 文件,而且需要重启所有的 container 才行。
    3.我们可以在应用启动的时候去数据库或者某个特定的地方拿,没问题!但是第一,实现起来麻烦;第二,如果配置的地方变了怎么办?
    
    当然还有别的方案,但是各种方案都有各自的问题。
    而且,还有一个问题就是,如果说我的一个配置,是要多个应用一起使用的,以上除了第三种方案,都没办法进行配置的共享,就是说我如果要改配置的话,那得一个一个手动改。假如我们有 100 个应用,就得改 100 份配置,以此类推……
    
    kubernetes 对这个问题提供了一个很好的解决方案,就是用 ConfigMap 和 Secret。    

    二、ConfigMap创建及使用

    1.查看命令帮助

    [root@k8s-master-155-221 configmap]# kubectl create  configmap --help
    ......
    Aliases:
    configmap, cm  #可以使用cm替代
    
    Examples:
      # Create a new configmap named my-config based on folder bar
      kubectl create configmap my-config --from-file=path/to/bar  #从目录创建  文件名称为键  文件内容为值?
      
      # Create a new configmap named my-config with specified keys instead of file basenames on disk
      kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt #从文件创建 key1为键 文件内容为值
      
      # Create a new configmap named my-config with key1=config1 and key2=config2
      kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2   #直接命令行给定,键为key1 值为config1
      
      # Create a new configmap named my-config from the key=value pairs in the file
      kubectl create configmap my-config --from-file=path/to/bar   #从文件创建 文件名为键 文件内容为值
      
      # Create a new configmap named my-config from an env file
      kubectl create configmap my-config --from-env-file=path/to/bar.en #不知道,没用过

    2.ConfigMap主要有以下几种方式创建

    通过literal方式创建ConfigMap

    [root@k8s-master-155-221 ~]# mkdir manifests
    [root@k8s-master-155-221 ~]# cd manifests/
    [root@k8s-master-155-221 ~]# kubectl create configmap nginx-config --from-literal=nginx_port=80 --from-literal=server_name=myapp.qiangungun.com  #命令行给定 nginx_port为键 80为值
    configmap/nginx-config created
    [root@k8s-master-155-221 ~]# kubectl describe cm nginx-config
    Name:         nginx-config
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    
    Data
    ====
    sever_name:  #键
    ----
    myapp.qiangungun.com #值
    nginx_port:  #键
    ----
    80  #值
    Events:  <none>
    [root@k8s-master-155-221 ~]# kubectl get cm nginx-config -o yaml
    apiVersion: v1
    data:
      nginx_port: "8088"   #键:值
      server_name: myapp.qiangungun.com #键:值对
    kind: ConfigMap
    metadata:
      ......

    通过file的方式创建

    [root@k8s-master-155-221 manifests]# mkdir configmap
    [root@k8s-master-155-221 manifests]# cd configmap/
    [root@k8s-master-155-221 configmap]# vim www.conf
    server{
      server_name myapp.magedu.com;
      listen 80;
      root /data/web/html;
    }
    [root@k8s-master-155-221 configmap]# kubectl create configmap www --from-file=./www.conf  #直接以文件名称为键,文件内容为值,也可以使用--from-file=key=/path/to/file自定义键
    configmap/www created
    [root@k8s-master-155-221 configmap]# kubectl get configmaps www
    NAME   DATA   AGE
    www    1      23s
    [root@k8s-master-155-221 configmap]# kubectl get configmaps www -o yaml  #或者使用describe命令查看
    apiVersion: v1
    data:
      www.conf: |
        server{
          server_name myapp.magedu.com;
          listen 80;
          root /data/web/html;
        }
    kind: ConfigMap
    metadata:
      creationTimestamp: "2020-01-13T14:21:13Z"
      name: www
      namespace: default
      resourceVersion: "7809631"
      selfLink: /api/v1/namespaces/default/configmaps/www
      uid: f3dd1cd4-360f-11ea-87ad-525400512eca

    通过YAML文件创建

    [root@k8s-master-155-221 configmap]# vim my-configmap.yml
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: customer1
    data:
      key1: value1
      key2: value2
    [root@k8s-master-155-221 configmap]# kubectl apply -f my-configmap.yml
    configmap/customer1 created
    [root@k8s-master-155-221 configmap]# kubectl describe cm customer1 
    Name:         customer1
    Namespace:    default
    Labels:       <none>
    Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                    {"apiVersion":"v1","data":{"key1":"value1","key2":"value2"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"customer1","namespace"...
    
    Data
    ====
    key1:
    ----
    value1
    key2:
    ----
    value2
    Events:  <none>

    3.使用ConfigMap主要有以下几种方式:

    ENV注入:

    [root@k8s-master-155-221 configmap]# vim pod-configmap.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-cm-1
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: httpd
          containerPort: 80
        env:
        - name: NGINX_SERVER_PORT  #pod中显示的变量名称
          valueFrom:
            configMapKeyRef:
              key: nginx_port   #引用的configmap中的键名称      
              name: nginx-config   #引用的configmap的名称
              optional: true      #该选项是否是必须的(true表示必须存在,否则pod无法启动)
        - name: NGINX_SERVER_NAME
          valueFrom:
            configMapKeyRef:
              key: server_name
              name: nginx-config
              optional: true
              
    
    [root@k8s-master-155-221 configmap]# kubectl apply -f pod-configmap.yaml
    pod/pod-cm-1 created
    [root@k8s-master-155-221 configmap]# kubectl get pods |grep pod-cm-1
    pod-cm-1                       1/1     Running   0          3m11s
    [root@k8s-master-155-221 configmap]# kubectl get pods |grep pod-cm-1
    pod-cm-1                       1/1     Running   0          13s
    [root@k8s-master-155-221 configmap]# kubectl exec -it pod-cm-1 -- /bin/sh
    / # env|grep NGINX_SERVER_PORT
    NGINX_SERVER_PORT=80
    / # env|grep NGINX_SERVER_NAME
    NGINX_SERVER_NAME=myapp.qiangungun.com
    / # env|grep NGINX_SERVER_PORT #稍等片刻,等下面的修改完成后操作,端口没有改变,即使用环境变量的方式注入配置只会在pod启动时有效 NGINX_SERVER_PORT=80

    #另起一个回话,修改当前使用的ConfigMap

    [root@k8s-master-155-221 ~]# kubectl edit configmap nginx-config
    # Please edit the object below. Lines beginning with a '#' will be ignored,
    # and an empty file will abort the edit. If an error occurs while saving this file will be
    # reopened with the relevant failures.
    #
    apiVersion: v1
    data:
      nginx_port: "8080" #修改端口为8080
      server_name: myapp.qiangungun.com
    kind: ConfigMap
    metadata:
      ......
    [root@k8s-master-155-221 ~]# kubectl describe cm nginx-config
    Name:         nginx-config
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    
    Data
    ====
    nginx_port:
    ----
    8080
    server_name:
    ----
    myapp.qiangungun.com
    Events:  <none>

    VOLUME挂载

    root@k8s-master-155-221 configmap]# kubectl delete pod pod-cm-1
    pod "pod-cm-1" deleted
    [root@k8s-master-155-221 configmap]# cp pod-configmap.yaml pod-configmap-2.yaml
    [root@k8s-master-155-221 configmap]# vim pod-configmap-2.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-cm-2
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: httpd
          containerPort: 80
        volumeMounts:
        - name: nginx-conf
          mountPath: /etc/nginx/config.d/
          readOnly: true  #是否允许pod去修改
      volumes:
      - name: nginx-conf
        configMap:
          name: nginx-config
    [root@k8s-master-155-221 configmap]# kubectl apply -f pod-configmap-2.yaml
    pod/pod-cm-2 created
    [root@k8s-master-155-221 configmap]# kubectl exec  -it pod-cm-2 -- /bin/sh
    / # ls /etc/nginx/config.d/nginx_port
    /etc/nginx/config.d/nginx_port
    / # cat /etc/nginx/config.d/nginx_port   #注意,是8080,因为之前已经改过一次了
    8080/ #
    / # cat /etc/nginx/config.d/server_name
    myapp.qiangungun.com/ #
    / # cat /etc/nginx/config.d/nginx_port #等下面的修改完成后操作,稍等30秒左右,端口发生改变,及以文件挂载的方式可以同步改变
    8088/ #

    #另起一个回话,修改当前使用的ConfigMap

    [root@k8s-master-155-221 ~]# kubectl edit configmap nginx-config  
            nginx_port: "8088"  #修改端口由8080改为8088
            
    / # cd /etc/nginx/config.d/
    /etc/nginx/config.d # ls -l    #挂载的方式实质是一种映射关系
    total 0
    lrwxrwxrwx    1 root     root            17 Jan 13 15:23 nginx_port -> ..data/nginx_port
    lrwxrwxrwx    1 root     root            18 Jan 13 15:23 server_name -> ..data/server_name

    4.实际示例

    [root@k8s-master-155-221 configmap]# vim pod-configmap-3.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-cm-3
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: httpd
          containerPort: 80
        volumeMounts:
        - name: nginx-conf
          mountPath: /etc/nginx/conf.d/
          readOnly: true
      volumes:
      - name: nginx-conf
        configMap:
          name: www
    [root@k8s-master-155-221 configmap]# kubectl apply -f pod-configmap-3.yaml
    pod/pod-cm-3 created
    [root@k8s-master-155-221 configmap]# kubectl exec -it pod-cm-3 -- /bin/sh
    / # cd /etc/nginx/conf.d/
    /etc/nginx/conf.d # ls
    www.conf   #文件名称即www configmap中的键
    /etc/nginx/conf.d # cat www.conf  #文件内容为www.conf的值
    server{
      server_name myapp.magedu.com;
      listen 80;
      root /data/web/html;
    }
    
    /etc/nginx/conf.d # nginx -T  #查看载入的配置
    ......
    # configuration file /etc/nginx/conf.d/www.conf:
    server{
      server_name myapp.magedu.com;
      listen 80;
      root /data/web/html;
    }
    
    /etc/nginx/conf.d # mkdir -p /data/web/html
    /etc/nginx/conf.d # echo "<h1>Nginx Server configured by CM</h1>" > /data/web/html/index.html

    在集群任意节点上

    [root@k8s-master-155-221 configmap]# kubectl get pods -o wide|grep pod-cm-3
    pod-cm-3                       1/1     Running   0          5m13s   172.17.248.4   172.16.155.224   <none>           <none>
    [root@k8s-master-155-221 configmap]# echo "172.17.248.4 myapp.magedu.com" >> /etc/hosts
    [root@k8s-master-155-221 configmap]# curl myapp.magedu.com
    Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
    [root@k8s-master-155-221 configmap]# kubectl edit cm www 
    apiVersion: v1
    data:
      www.conf: |
        server{
          server_name myapp.magedu.com;
          listen 8080;
          root /data/web/html;
        }
    kind: ConfigMap
    metadata:
      creationTimestamp: "2020-01-13T14:21:13Z"
      name: www
      namespace: default
      resourceVersion: "7809631"
      selfLink: /api/v1/namespaces/default/configmaps/www 
      uid: f3dd1cd4-360f-11ea-87ad-525400512eca

    pod中查看

    /etc/nginx/conf.d # cat www.conf #等上面的修改完成后操作,稍等30秒左右,端口发生改变
      server_name myapp.magedu.com;
      listen 8080;
      root /data/web/html;
    }
    
    /etc/nginx/conf.d # netstat -tnl  #配置虽然改变,但是服务监听端口不会发生改变,需要通过某种方式重载服务
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State
    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN

    三、Secret创建及使用

    通过上面的部分,我们可以看到 ConfigMap 是用来做一些配置信息的,那么如果我们有一些机密信息比如说密钥、密码之类的信息,应该存在哪里呢?看到这个名字大家应该就明白了吧,kubernetes 提供了 Secret 来存储相关的信息。

    Secret命令帮助(secret创建和使用与ConfigMap大同小异,注意区别在于内容被base64加密了)

    [root@k8s-master-155-221 manifests]# kubectl create secret --help
    Create a secret using specified subcommand.
    
    Available Commands:  #secret主要有以下三种类型
      docker-registry 创建一个给 Docker registry 使用的 secret   #docker-registry私有仓库的证书,pod中pod.spec.imagePullSecrets字段使用
      generic         从本地 file, directory 或者 literal value #通用的secret
      tls             创建一个 TLS secret                       #保存私钥和证书

    1.创建secret

    [root@k8s-master-155-221 manifests]# kubectl create secret generic mysql-root-passwd --from-literal=passwd=MyP@ss123
    secret/mysql-root-passwd created
    [root@k8s-master-155-221 manifests]# kubectl describe secrets mysql-root-passwd 
    Name:         mysql-root-passwd
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    
    Type:  Opaque
    
    Data
    ====
    passwd:  9 bytes   #只能看到9个字节 但是看不到内容
    [root@k8s-master-155-221 manifests]# kubectl get secrets mysql-root-passwd -o yaml
    apiVersion: v1
    data:
      passwd: TXlQQHNzMTIz   #实际是base64加密
    kind: Secret
    metadata:
      creationTimestamp: "2020-01-14T01:47:51Z"
      name: mysql-root-passwd
      namespace: default
      resourceVersion: "7896989"
      selfLink: /api/v1/namespaces/default/secrets/mysql-root-passwd
      uid: dfb541fa-366f-11ea-87ad-525400512eca
    type: Opaque
    
    [root@k8s-master-155-221 manifests]# echo "TXlQQHNzMTIz"|base64 -d  #实际上可以被解码的
    MyP@ss123

    2.简单使用

    [root@k8s-master-155-221 configmap]# vim pod-secret-1.yaml
    apiVersion: v1
    kind: Pod
    metadata: 
      name: pod-secret-1
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: httpd
          containerPort: 80
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              key: passwd
              name: mysql-root-passwd
              optional: true
              
    [root@k8s-master-155-221 configmap]# kubectl apply -f pod-secret-1.yaml
    pod/pod-secret-1 created      
    [root@k8s-master-155-221 configmap]# kubectl exec -it pod-secret-1 -- /bin/sh
    / # env|grep MYSQL
    MYSQL_ROOT_PASSWORD=MyP@ss123   #实际是解密后注入进来的,所以不建议使用环境变量的方式注入密码

    其他方式与configmap雷同,不在赘述

    其实目前 Secret 的实现,就是 ConfigMap 把 value 用 base64 encode 了一下.所以,其实不存在任何安全性,只要 decode 一下就能出现原来结果,相当于明文存储. 

    参考文档:

     https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/

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

                       

  • 相关阅读:
    HDFS Java API
    HBase Java API
    Hive JDBC
    map.merge() 方法
    循环的4种形式
    Storm 单词计数
    swagger 2.9.2
    ZooKeeper Java API
    服务器添加静态路由
    Win10局域网共享文件夹“用户名或密码不正确”
  • 原文地址:https://www.cnblogs.com/panwenbin-logs/p/12190765.html
Copyright © 2020-2023  润新知