k8s学习笔记之ConfigMap和Secret

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 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

1.通用类型
[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.TLS类型
[root@k8s-master-155-221 manifests]# kubectl create secret tls ${secret_name} --key nginx.key --cert nginx.crt
3.镜像仓库类型
[root@k8s-master-155-221 manifests]#  kubectl create secret generic  ${secret_name} --from-file=.dockerconfigjson=/root/.docker/config.json --type=kubernetes.io/dockerconfigjson

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/

                   

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
2月前
|
Kubernetes 关系型数据库 MySQL
|
2月前
|
存储 Kubernetes 开发工具
k8s学习--ConfigMap详细解释与应用
ConfigMap 是 Kubernetes 中用于管理非机密配置数据的 API 对象,可将应用配置与容器分离,便于动态管理和更新。它支持四种创建方式:命令行参数、多个文件、文件内的键值对以及 YAML 资源清单文件。ConfigMap 可通过环境变量或挂载为卷的方式传递给 Pod,并且当通过卷挂载时支持热更新。这使得配置管理更加灵活和安全,无需重新部署应用即可更新配置。
106 0
|
4月前
|
运维 Kubernetes 容器
【Azure K8S】演示修复因AKS密钥过期而导致创建服务不成功的问题(The provided client secret keys for app ****** are expired)
【Azure K8S】演示修复因AKS密钥过期而导致创建服务不成功的问题(The provided client secret keys for app ****** are expired)
【Azure K8S】演示修复因AKS密钥过期而导致创建服务不成功的问题(The provided client secret keys for app ****** are expired)
|
2月前
|
存储 Kubernetes 数据安全/隐私保护
k8s学习--Secret详细解释与应用
Secret 支持四种类型: - **Opaque Secrets**:存储任意类型机密数据,需自行加密。 - **Service Account Token Secrets**:自动管理 API 访问令牌。 - **Docker Registry Secrets**:存储 Docker 私有仓库认证信息。 - **TLS Secrets**:存储 TLS 证书和私钥,用于加密通信。
212 0
|
4月前
|
Prometheus Kubernetes 网络协议
k8s学习笔记之CoreDNS
k8s学习笔记之CoreDNS
|
4月前
|
Kubernetes jenkins 持续交付
jenkins学习笔记之二十一:k8s部署jenkins及动态slave
jenkins学习笔记之二十一:k8s部署jenkins及动态slave
|
4月前
|
存储 Kubernetes 安全
在k8S中,Secret 有哪些使用方式?
在k8S中,Secret 有哪些使用方式?
|
4月前
|
存储 Kubernetes 数据安全/隐私保护
Kubernetes(K8S) 配置管理-ConfigMap 介绍
Kubernetes(K8S) 配置管理-ConfigMap 介绍
48 1
|
4月前
|
Kubernetes 数据安全/隐私保护 容器
Kubernetes(K8S) 配置管理 Secret 介绍
Kubernetes(K8S) 配置管理 Secret 介绍
50 1
|
4月前
|
存储 Kubernetes Linux
Kubernetes 的配置资源 ConfigMap(01部分)
Kubernetes 的配置资源 ConfigMap(01部分)