K8S - ConfigMap的简介和使用

什么是configMap

Kubernetes中的ConfigMap 是用于存储非敏感数据的API对象,用于将配置数据与应用程序的镜像分离。ConfigMap可以包含键值对、文件或者环境变量等配置信息,应用程序可以通过挂载ConfigMap来访问其中的数据,从而实现应用配置的动态管理。ConfigMap的使用有助于提高应用程序的可移植性、可伸缩性和可维护性。

简单来讲, configmap 是用来存储app的配置或者容器的环境变量的, 避免这些配置hard code 在容器内。

但是configMap 并不适合存放敏感数据(例如帐号密码) , 敏感数据应该存放在secret manager中。

configMap的创建

1. by kubectl command line

我们可以用 kubectl create configMap -h 查看官方的一些示例

bash 复制代码
Aliases:
configmap, cm

Examples:
  # Create a new config map named my-config based on folder bar
  kubectl create configmap my-config --from-file=path/to/bar
  
  # Create a new config map 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
  
  # Create a new config map named my-config with key1=config1 and key2=config2
  kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2
  
  # Create a new config map named my-config from the key=value pairs in the file
  kubectl create configmap my-config --from-file=path/to/bar
  
  # Create a new config map named my-config from an env file
  kubectl create configmap my-config --from-env-file=path/to/foo.env --from-env-file=path/to/bar.env

可见, 用命令行创建configMap的都必须提供一个or 若干文件,甚至可以是文件夹, 而且真正的内容都要写在文件中的。

而-from-literal 可以在不提供文件的情况下直接在命令指定key value

例子1 基于文件夹
bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI/test$ cd ..
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ ls test/
db1.config  db2.config
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ cat test/db1.config 
db1.hostname=db1
db1.port=3309

gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ cat test/db2.config 
db2.hostname=db1
db2.port=3309

gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ kubectl create cm test-dir-config --from-file=test/
configmap/test-dir-config created

上面我创建了两个config files 在test 文件夹中, 并用folder 名创建了1个configMap item

查看 configMap 的items

bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ kubectl get cm
NAME                DATA   AGE
kube-root-ca.crt    1      172d
test-dir-config     2      2m28s

可以见到 test-dir-config 被创建出来了

查看 configMap的内容

bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ kubectl describe cm test-dir-config
Name:         test-dir-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
db1.config:
----
db1.hostname=db1
db1.port=3309


db2.config:
----
db2.hostname=db1
db2.port=3309



BinaryData
====

Events:  <none>
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ 

可以到这个configMap item 中有两个item, 注意的是

db.hostname 这种细节不是key

keys 只有两个

db1.config

db2.config

里面的内容的整体是key 对应的value!

例子2 基于某个文件

我们在另1个folder test2 created 了1个文件pgsql.yml

bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ ls test2
pgsql.yml
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ cat test2/pgsql.yml 
hostname:
  db3.hostname
port:
  3310

注意格式是yaml的

这时我们创建1个configmap item

bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ kubectl create cm db3.config --from-file=test2/pgsql.yml
configmap/db3.config created

查看configMap item

bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ kubectl get cm
NAME                DATA   AGE
db3.config          1      67s
kube-root-ca.crt    1      172d
test-dir-config     2      52m

新建的configMap item 名字是db3.config

查看内容

bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ kubectl describe cm db3.config
Name:         db3.config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
pgsql.yml:
----
hostname:
  db3.hostname
port:
  3310

BinaryData
====

Events:  <none>

key 是 pgsql.yml

这时我们再创建1个configMap item

bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ kubectl create cm db4.config --from-file=db4-config=test2/pgsql.yml
configmap/db4.config created

注意这里的 --from-fille=db4-config=test2/pgsql.yaml

db4-config 是指定key的名字, overwrite掉 文件名作为key

bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ kubectl get cm
NAME                DATA   AGE
db3.config          1      5m33s
db4.config          1      85s
kube-root-ca.crt    1      172d
test-dir-config     2      57m
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ kubectl describe cm db4.config
Name:         db4.config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
db4-config:
----
hostname:
  db3.hostname
port:
  3310

BinaryData
====

Events:  <none>

再查看内容:

这时的key 已经是 db4-config了

例子3 直接在命令行带上key value 的值
bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ kubectl create cm db5.config --from-literal=hostname=db5.hostname --from-literal=port=3311
configmap/db5.config created
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ kubectl get cm
NAME                DATA   AGE
cloud-user-config   1      33d
db3.config          1      36m
db4.config          1      32m
db5.config          2      3s
kube-root-ca.crt    1      172d
test-dir-config     2      88m
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/CLI$ kubectl describe cm db5.config
Name:         db5.config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
port:
----
3311
hostname:
----
db5.hostname

BinaryData
====

Events:  <none>

注意这句命令创建了 1个 configmap item, 但是里面有两对KV

分别是

key: hostname

key: port

2. by yaml file

在项目中, 更常用定义资源应该是yaml file 格式

为了实现与上面命令同样的效果, 我们创建了1个yaml file, 内容如下

yaml 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/yaml$ ls
db6-config.yaml
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/yaml$ cat db6-config.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: db6.config
data:
  hostname: db6.hostname
  port: "3311"g

apply 资源

bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/yaml$ kubectl apply -f db6-config.yaml 
configmap/db6.config created

查看configMap items

bash 复制代码
configmap/db6.config created
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/yaml$ kubectl get cm
NAME                DATA   AGE
db3.config          1      85m
db4.config          1      81m
db5.config          2      48m
db6.config          2      33s
kube-root-ca.crt    1      172d
test-dir-config     2      137m

查看内容

bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/configMap/yaml$ kubectl describe cm db6.config
Name:         db6.config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
hostname:
----
db6.hostname
port:
----
3311

BinaryData
====

Events:  <none>

可见 效果时间一样的

configMap的使用

在yaml 里大概有两种使用方法

  1. 利用configMapKeyRef 读取配置
  2. 利用volumes 把配置写入1个文件
1. 利用configMapKeyRef 读取配置

例子:

我们首先准备1个springboot serice - cloud order

令其的actuator/info 接口可以return 当前环境的所有环境变量

java 复制代码
@Component
@Slf4j
public class AppVersionInfo implements InfoContributor {

    @Value("${pom.version}") // https://stackoverflow.com/questions/3697449/retrieve-version-from-maven-pom-xml-in-code
    private String appVersion;

    @Autowired
    private String hostname;

    @Autowired
    private InfoService infoservice;

    @Value("${spring.datasource.url}")
    private String dbUrl;

    @Override
    // https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-endpoints-info
    public void contribute(Info.Builder builder) {
        log.info("AppVersionInfo: contribute ...");
        builder.withDetail("app", "Cloud Order Service")
                .withDetail("version", appVersion)
                .withDetail("hostname",hostname)
                .withDetail("dbUrl", dbUrl)
                .withDetail("description", "This is a simple Spring Boot application to for cloud order.")
                .withDetail("SystemVariables", infoservice.getSystemVariables());

    }
}
java 复制代码
@Service
public class InfoService {

        public String getHostName() {
            return "unknown";
        }

        public HashMap<String, String> getSystemVariables() {
            Map<String, String> envVariables = System.getenv();

            //envVariables.forEach((key, value) -> systemVariables.put(key, value));
            return new HashMap<>(envVariables);
        }
}

然后我们利用yaml 创建1个configMap

cloud-order-configmap.yaml

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: cloud-order-app-tag-config
data:
  APP_TAG: cloud-order-app-tag

里面指定一了1个KV 对

部署

bash 复制代码
kubectl apply -f cloud-order-configmap.yaml

然后再编写 deployment 的yaml

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  labels: # label of this deployment
    app: cloud-order # custom defined
    author: nvd11
  name: deployment-cloud-order # name of this deployment
  namespace: default
spec:
  replicas: 3            # desired replica count, Please note that the replica Pods in a Deployment are typically distributed across multiple nodes.
  revisionHistoryLimit: 10 # The number of old ReplicaSets to retain to allow rollback
  selector: # label of the Pod that the Deployment is managing,, it's mandatory, without it , we will get this error 
            # error: error validating data: ValidationError(Deployment.spec.selector): missing required field "matchLabels" in io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector ..
    matchLabels:
      app: cloud-order
  strategy: # Strategy of upodate
    type: RollingUpdate # RollingUpdate or Recreate
    rollingUpdate:
      maxSurge: 25% # The maximum number of Pods that can be created over the desired number of Pods during the update
      maxUnavailable: 25% # The maximum number of Pods that can be unavailable during the update
  template: # Pod template
    metadata:
      labels:
        app: cloud-order # label of the Pod that the Deployment is managing. must match the selector, otherwise, will get the error Invalid value: map[string]string{"app":"bq-api-xxx"}: `selector` does not match template `labels`
    spec: # specification of the Pod
      containers:
      - image: europe-west2-docker.pkg.dev/jason-hsbc/my-docker-repo/cloud-order:1.0.2 # image of the container
        imagePullPolicy: IfNotPresent
        name: container-cloud-order
        env: # set env varaibles
        - name: APP_ENVIRONMENT # name of the environment variable
          value: prod # value of the environment variable
        - name: APP_TAG 
          valueFrom: # value from config map
            configMapKeyRef: 
              name: cloud-order-app-tag-config # name of the configMap item
              key: APP_TAG # key from the config map item
            
      restartPolicy: Always # Restart policy for all containers within the Pod
      terminationGracePeriodSeconds: 10 # The period of time in seconds given to the Pod to terminate gracefully

注意, 我们在环境变量那里 新增了1个item , 环境变量的名字是 APP_TAG, 而 环境变量的value 是从 configmap 里获取的

部署成功后

测试api /actuator/info

bash 复制代码
ateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ curl http://www.jp-gcp-vms.cloud:8085/cloud-order/actuator/info | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1777    0  1777    0     0   3067      0 --:--:-- --:--:-- --:--:--  3063
{
  "app": "Cloud Order Service",
  "version": "1.0.2",
  "hostname": "deployment-cloud-order-c56db7848-lt5wc",
  "dbUrl": "jdbc:mysql://192.168.0.42:3306/demo_cloud_order?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true",
  "description": "This is a simple Spring Boot application to for cloud order.",
  "SystemVariables": {
    "PATH": "/usr/java/openjdk-17/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "CLUSTERIP_CLOUD_ORDER_SERVICE_HOST": "10.98.117.97",
    "CLUSTERIP_BQ_API_SERVICE_SERVICE_PORT": "8080",
    "KUBERNETES_PORT": "tcp://10.96.0.1:443",
    "JAVA_HOME": "/usr/java/openjdk-17",
    "KUBERNETES_SERVICE_HOST": "10.96.0.1",
    "LANG": "C.UTF-8",
    "CLUSTERIP_CLOUD_ORDER_PORT": "tcp://10.98.117.97:8080",
    "CLUSTERIP_BQ_API_SERVICE_PORT_8080_TCP": "tcp://10.100.68.154:8080",
    "CLUSTERIP_CLOUD_ORDER_PORT_8080_TCP": "tcp://10.98.117.97:8080",
    "CLUSTERIP_BQ_API_SERVICE_PORT_8080_TCP_PROTO": "tcp",
    "PWD": "/app",
    "JAVA_VERSION": "17.0.2",
    "_": "/usr/java/openjdk-17/bin/java",
    "CLUSTERIP_CLOUD_ORDER_PORT_8080_TCP_ADDR": "10.98.117.97",
    "KUBERNETES_PORT_443_TCP": "tcp://10.96.0.1:443",
    "KUBERNETES_PORT_443_TCP_ADDR": "10.96.0.1",
    "CLUSTERIP_CLOUD_ORDER_PORT_8080_TCP_PORT": "8080",
    "CLUSTERIP_BQ_API_SERVICE_PORT": "tcp://10.100.68.154:8080",
    "CLUSTERIP_BQ_API_SERVICE_PORT_8080_TCP_PORT": "8080",
    "KUBERNETES_PORT_443_TCP_PROTO": "tcp",
    "APP_ENVIRONMENT": "prod",
    "KUBERNETES_SERVICE_PORT": "443",
    "CLUSTERIP_CLOUD_ORDER_SERVICE_PORT": "8080",
    "CLUSTERIP_BQ_API_SERVICE_PORT_8080_TCP_ADDR": "10.100.68.154",
    "APP_TAG": "cloud-order-app-tag",
    "HOSTNAME": "deployment-cloud-order-c56db7848-lt5wc",
    "CLUSTERIP_CLOUD_ORDER_PORT_8080_TCP_PROTO": "tcp",
    "CLUSTERIP_BQ_API_SERVICE_SERVICE_HOST": "10.100.68.154",
    "KUBERNETES_PORT_443_TCP_PORT": "443",
    "KUBERNETES_SERVICE_PORT_HTTPS": "443",
    "SHLVL": "1",
    "HOME": "/root"
  }
}

查看 APP_TAG 的那一行, 的确能正确地获取configmap 里的配置信息!

2. 利用volumes 把配置写入1个文件

在这个例子中

我们再利用yaml 创建另1个configMap

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: cloud-order-os-version-config
data:
  OS_VERSION: ubuntu-x.x

部署

bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ kubectl apply -f cloud-order-configmap2.yaml
configmap/cloud-order-os-version-config created

修改 cloud order service 的deployment yaml

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  labels: # label of this deployment
    app: cloud-order # custom defined
    author: nvd11
  name: deployment-cloud-order # name of this deployment
  namespace: default
spec:
  replicas: 3            # desired replica count, Please note that the replica Pods in a Deployment are typically distributed across multiple nodes.
  revisionHistoryLimit: 10 # The number of old ReplicaSets to retain to allow rollback
  selector: # label of the Pod that the Deployment is managing,, it's mandatory, without it , we will get this error 
            # error: error validating data: ValidationError(Deployment.spec.selector): missing required field "matchLabels" in io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector ..
    matchLabels:
      app: cloud-order
  strategy: # Strategy of upodate
    type: RollingUpdate # RollingUpdate or Recreate
    rollingUpdate:
      maxSurge: 25% # The maximum number of Pods that can be created over the desired number of Pods during the update
      maxUnavailable: 25% # The maximum number of Pods that can be unavailable during the update
  template: # Pod template
    metadata:
      labels:
        app: cloud-order # label of the Pod that the Deployment is managing. must match the selector, otherwise, will get the error Invalid value: map[string]string{"app":"bq-api-xxx"}: `selector` does not match template `labels`
    spec: # specification of the Pod
      containers:
      - image: europe-west2-docker.pkg.dev/jason-hsbc/my-docker-repo/cloud-order:1.0.2 # image of the container
        imagePullPolicy: IfNotPresent
        name: container-cloud-order
        env: # set env varaibles
        - name: APP_ENVIRONMENT # name of the environment variable
          value: prod # value of the environment variable
        - name: APP_TAG 
          valueFrom: # value from config map
            configMapKeyRef: 
              name: cloud-order-app-tag-config # name of the configMap item
              key: APP_TAG # key from the config map item
        volumeMounts: # volume mount
          - name: config-volume
            mountPath: /app/config
      volumes:
        - name: config-volume
          configMap:
            name: cloud-order-os-version-config # name of the config map
            items:
              - key: OS_VERSION # key of the config map item
                path: os-version.conf # name of the file, it will only contain the content of the key
            
            
      restartPolicy: Always # Restart policy for all containers within the Pod
      terminationGracePeriodSeconds: 10 # The period of time in seconds given to the Pod to terminate gracefully

注意我们在这里新增了1个卷 把configmap cloud-order-os-version-config 指定某个key的value 保存到1个文件中 os-version.conf

而在container 的配置中, 我们 吧这个卷mount 在 /app/config 路径下

重新部署:

bash 复制代码
gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ kubectl apply -f deployment-cloud-order.yaml 
deployment.apps/deployment-cloud-order configured
gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ kubectl get pods
NAME                                         READY   STATUS    RESTARTS         AGE
deployment-bq-api-service-6f6ffc7866-8djx9   1/1     Running   0                26h
deployment-bq-api-service-6f6ffc7866-g4854   1/1     Running   9 (3d21h ago)    45d
deployment-bq-api-service-6f6ffc7866-lwxt7   1/1     Running   11 (3d21h ago)   47d
deployment-bq-api-service-6f6ffc7866-mxwcq   1/1     Running   8 (3d21h ago)    45d
deployment-cloud-order-7cb8466d48-2kcnn      1/1     Running   0                8s
deployment-cloud-order-7cb8466d48-57w6n      1/1     Running   0                7s
deployment-cloud-order-7cb8466d48-d6jk7      1/1     Running   0                5s

进入容器:

bash 复制代码
gateman@MoreFine-S500:~$ kubectl exec -it deployment-cloud-order-7cb8466d48-d6jk7 /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
bash-4.4# cd /app/config
bash-4.4# ls
os-version.conf
bash-4.4# cat os-version.conf 
ubuntu-x.x

可以见到configmap的内容的确放入了 容器内的对应的目录下

相关推荐
菜地里的小菜鸟3 天前
failed to get imageFs info: non-existent label “docker-images
k8s·failedtogetimagefsin·k8s报错
菜地里的小菜鸟4 天前
kubectl debug
k8s·kubectldebug
腾飞开源6 天前
01_K8s干货笔记之认识K8s
运维·笔记·云原生·容器·kubernetes·k8s·容器化部署
小匠石钧知9 天前
02_在多个RockyLinux10虚拟机上安装k8s集群
云原生·容器·kubernetes·k8s
ShirleyWang01215 天前
让headlamp控制台能访问
linux·服务器·python·k8s·k3s
spider_xcxc15 天前
K8s 部署学习笔记
docker·容器·kubernetes·云计算·k8s
ShirleyWang01215 天前
Day02 K3s NGF(Nginx Gateway Fabric)单 Worker 环境网关更新与故障处置 SOP
linux·服务器·python·k8s·k3s
ShirleyWang01215 天前
DAY01 K3s 私有化部署排障复盘与 SOP
linux·服务器·k8s·k3s·企业部署
XUHUOJUN19 天前
AKS 不是安装在 Windows Server 上,而是运行在 Windows Server 之上的 Azure 平台能力
windows·架构·k8s·azure local·azure stack
Geek-Chow19 天前
Connecting kubectl to a Private EKS Cluster Over an Internal Domain
kubernetes·k8s·aws