百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

在Kubernetes中使用ConfigMap(kubectl set env)

zhezhongyun 2025-05-11 03:03 54 浏览

在《为Kubernetes安装Dashboard》中,我们已经使用VirtualBox安装了CentOS 7.9,并在其上安装了Docker 20.10.11、Kubernetes 1.23.3和kubernetes-dashboard v2.4.0。在此基础之上,我们进一步来了解Kubernetes中ConfigMap的使用。

集中化的配置管理能力,对于一个微服务体系结构的系统是至关重要的。我们无法想象当面对数千台物理服务器中运行的数万个容器时,我们需要找到并登录到容器中去修改配置的场景。

ConfigMap作为Kubernetes内置的配置管理组件,在一定程度上解决了配置的集中管理能力。

创建一个ConfigMap资源

首先,我们在虚拟机中创建一个目录,用来存放本章节中需要使用到的一些文件:

mkdir -p ~/kubernetes/configmap/
cd ~/kubernetes/configmap/

然后,我们在此创建“demo-cm.yaml”文件,用以描述ConfigMap的一些信息:

vi demo-cm.yaml

将以下内容保存到文件中:

apiVersion: v1
kind: ConfigMap
metadata:
  name: demo
data:
  MY_CONF: hello

最后,我们执行以下命令,创建ConfigMap资源:

kubectl apply -f demo-cm.yaml

执行结果如下:

configmap/demo created

我们可通过以下命令来查看当前系统中“default”命名空间下的ConfigMap资源:

kubectl get configmaps

输出结果为:

NAME               DATA   AGE
demo               1      65s
kube-root-ca.crt   1      5d21h

其中,名称为“demo”的即为我们刚创建的ConfigMap。

我们可通过以下命令来查看这个ConfigMap的信息:

kubectl describe configmap demo

输出结果为:

Name:         demo
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
MY_CONF:
----
hello

BinaryData
====

Events:  <none>

我们可看到配置项“MY_CONF”的值为“hello”。
接下来,我们创建一个POD来使用这个ConfigMap。

创建一个POD来使用ConfigMap

为了体验下ConfigMap的使用,我们首先需要创建一个POD,并通过这个POD使用刚创建的ConfigMap,来直观地感受ConfigMap在POD中的呈现。
因此,我们对POD本身没有什么要求,它只要能持续地运行在那里就可以了。因此,我们需要基于镜像“centos:7”创建一个可以持续运行的镜像。

首先,我们创建一个Shell脚本,在其中编写一个死循环,作为在容器中运行的主程序:

vi endless-loop.sh

将以下内容写入到文件中:

#!/bin/bash

while [ 1 ]
do
  sleep 1
done

然后,我们来创建一个以此脚本作为主程序的镜像。首先,我们创建Dockerfile文件:

vi endless-loop.dockerfile

将以下内容写入到Dockerfile文件中:

FROM centos:7
COPY ./endless-loop.sh /opt/
WORKDIR /opt/
CMD /bin/bash endless-loop.sh

现在,我们执行以下命令来创建Docker镜像:

docker image build -t endless-loop:test -f endless-loop.dockerfile .

执行结果如下:

Sending build context to Docker daemon  4.096kB
Step 1/4 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/4 : COPY ./endless-loop.sh /opt/
 ---> 920452a78377
Step 3/4 : WORKDIR /opt/
 ---> Running in 41acd739fe5f
Removing intermediate container 41acd739fe5f
 ---> 53a9cc112964
Step 4/4 : CMD /bin/bash endless-loop.sh
 ---> Running in 735a9295b59d
Removing intermediate container 735a9295b59d
 ---> b628de4edc20
Successfully built b628de4edc20
Successfully tagged endless-loop:test

我们先通过这个镜像来启动一个容器,确保容器不会立刻退出:

docker container run --name endless-loop -d endless-loop:test

我们执行以下命令,检查容器的运行情况:

docker ps -a | grep endless-loop

执行结果为:

2fc873bcf37f   endless-loop:test                                   "/bin/sh -c '/bin/ba…"   About a minute ago   Up About a minute

说明程序正在持续运行,也就是说刚才制作的镜像是符合预期的。

现在,我们清理掉这个容器:

docker container stop endless-loop
docker container rm endless-loop

到此为止,我们已经有了用于体验ConfigMap的镜像。现在,我们基于此镜像创建一个POD,并使用之前的ConfigMap。

首先,我们编写“demo-rc.yaml”,用以在Kubernetes中创建一个ReplicationController,来帮我们管理容器:

vi demo-rc.yaml

将以下内容写入到文件中:

apiVersion: v1
kind: ReplicationController
metadata:
  name: demo
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: demo
        image: endless-loop:test
        imagePullPolicy: Never
        envFrom:
        - configMapRef:
            name: demo

执行以下命令创建ReplicationController:

kubectl apply -f demo-rc.yaml

执行结果为:

replicationcontroller/demo created

说明ReplicationController已成功创建,现在我们执行以下命令来检查其运行情况:

kubectl get rc demo

执行结果为:

NAME   DESIRED   CURRENT   READY   AGE
demo   1         1         1       2m46s

表示ReplicationController运行正常,且已创建了POD。

现在,我们执行以下命令,列出上一个被拉起的容器:

docker container ls -l

执行结果为:

CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS     NAMES
27cb5c5b1c50   b628de4edc20   "/bin/sh -c '/bin/ba…"   3 minutes ago   Up 3 minutes             k8s_demo_demo-sd8fm_default_25212cbd-8386-44c7-b477-c6d386901156_0

根据容器的名称,我们可以看出这个容器即使Kubernetes刚创建的容器。接下来我们通过容器的唯一标识登录到容器中:

docker exec -it 27cb5c5b1c50 /bin/bash

然后,我们通过以下命令来检查环境变量的值:

echo $MY_CONF

输出结果为:

hello

说明我们已经成功地将ConfigMap中配置的内容应用到POD中容器的环境变量中了。

ConfigMap的用法

刚才我们所尝试的用法,是将ConfigMap的值映射到POD的环境变量中。除此之外,ConfigMap还可以通过卷的形式被挂载到容器中或者配置成为容器中应用的启动参数。而且即使以环境变量的形式,也可以通过使用“env”属性来指定使用哪些值,并将其映射到容器中的哪个名称的环境变量。
另外,创建ConfigMap也不止通过YAML文件一种方法,也可以通过命令中通过字面量的形式创建,或使用文件等。即:

创建ConfigMap的方法:

  • 通过YAML文件
  • 通过字面量
  • 通过文件或目录

使用ConfigMap的方法:

  • 映射到容器的环境变量
  • 以卷的形式挂载给容器
  • 映射到容器运行的主程序的命令行参数

使用字面量创建ConfigMap

我们可通过以下命令来创建包含“key1”和“key2”两个配置项的ConfigMap,其值分别为“value1”和“value2”:

kubectl create configmap literal-configs --from-literal=key1=value1 --from-literal=key2=value2

执行结果为:

configmap/literal-configs created

我们可通过以下命令来查看ConfigMap的详细信息:

kubectl describe configmap literal-configs

执行结果为:

Name:         literal-configs
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
key1:
----
value1
key2:
----
value2

BinaryData
====

Events:  <none>

可以看到,该ConfigMap中有配置项“key1”的值为“value1”,“key2”的值为“value2”。

使用文件创建ConfigMap

使用文件来创建ConfigMap有两种方法:

  • 为ConfigMap中的每个配置项指定一个文件,这个文件中的内容即为配置项的值。
  • 直接指定一个目录,则目录中每个文件的名称即为配置项的名称,文件的内容即为配置项的值。

我们首先来创建一个包含“hello”的文本文件:

echo hello > say.txt

然后我们创建一个目录,并在目录中创建名为“application.yml”的文件:

mkdir conf-dir
vi conf-dir/application.yml

将以下内容输入到文件中:

server:
  port: 8080

然后,我们执行以下命令创建ConfigMap:

kubectl create configmap file-configs --from-file=say=say.txt --from-file=conf-dir

输出结果为:

configmap/file-configs created

ConfigMap已被成功创建,我们可查看其详细信息:

kubectl describe configmap file-configs

输出结果为:

Name:         file-configs
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
application.yml:
----
server:
  port: 8080

say:
----
hello


BinaryData
====

Events:  <none>

由此可见,我们指定的配置项“say”的值即为文件“say.txt”的内容,而目录“conf-dir”中的“application.yml”的文件名成为了另一个配置项,其内容即为这个文件的值。

至此,我们已经了解了ConfigMap的各种创建方式。最后,我们在通过卷的形式将ConfigMap中的配置挂载给POD。

将ConfigMap的配置挂载给POD

我们继续使用刚才的“endless-loop:test”镜像。

首先,我们来编辑一份YAML配置:

vi demo-volume-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: demo-volume
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: demo-volume
    spec:
      containers:
      - name: demo-volume
        image: endless-loop:test
        imagePullPolicy: Never
        volumeMounts:
        - name: config-files
          mountPath: /opt/config-files
      volumes:
      - name: config-files
        configMap:
          name: file-configs

执行以下命令,创建ReplicationController:

kubectl apply -f demo-volume-rc.yaml

执行结果为:

replicationcontroller/demo-volume created

查看ReplicationController的状态:

kubectl get rc demo-volume

执行结果为:

NAME          DESIRED   CURRENT   READY   AGE
demo-volume   1         1         1       77s

说明ReplicationController运行正常,再查看POD状态:

kubectl get pods

执行结果为:

NAME                READY   STATUS    RESTARTS   AGE
demo-sd8fm          1/1     Running   0          176m
demo-volume-2qf4d   1/1     Running   0          2m9s

说明POD运行正常,然后找到上一个被创建的Docker容器:

docker ps -a -l

执行结果为:

CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS     NAMES
80e401edd797   b628de4edc20   "/bin/sh -c '/bin/ba…"   2 minutes ago   Up 2 minutes             k8s_demo-volume_demo-volume-2qf4d_default_ab041f62-e3df-4038-8280-eb65d9f4d299_0

通过容器的唯一标识,我们登录到容器中:

docker exec -it 80e401edd797 /bin/bash

在容器中查看挂载配置的目录中的文件:

ll /opt/config-files

输出结果为:

lrwxrwxrwx 1 root root 22 Feb  3 17:35 application.yml -> ..data/application.yml
lrwxrwxrwx 1 root root 10 Feb  3 17:35 say -> ..data/say

说明配置已经通过文件的形式被挂载到了POD中。之后我们可以分别查看两个文件的内容。

查看application.yml文件的内容:

cat /opt/config-files/application.yml

输出结果为:

server:
  port: 8080

查看say文件的内容:

cat /opt/config-files/say

输出结果为:

hello

两个文件的内容均与之前的配置一致。至此,以卷的形式将ConfigMap挂载到POD已经完成。

在命令行参数中使用ConfigMap

在这里,我们继续使用之前的“endless-loop:test”镜像,以及之前创建的名为“literal-configs”的ConfigMap。

我们首先创建ReplicationController的YAML文件:

vi demo-cmd-rc.yaml

将以下内容写入到文件中:

apiVersion: v1
kind: ReplicationController
metadata:
  name: demo-cmd
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: demo-cmd
    spec:
      containers:
      - name: demo-cmd
        image: endless-loop:test
        imagePullPolicy: Never
        envFrom:
        - configMapRef:
            name: literal-configs
        command:
        - /bin/bash
        - -c
        - /bin/bash /opt/endless-loop.sh $(key1) $(key2)

然后,执行以下命令创建ReplicationController:

kubectl apply -f demo-cmd-rc.yaml

输出结果为:

replicationcontroller/demo-cmd created

查看ReplicationController的状态:

kubectl get rc demo-cmd

输出结果为:

NAME       DESIRED   CURRENT   READY   AGE
demo-cmd   1         1         1       3m16s

ReplicationController运行正常,继续查看POD状态:

kubectl get rc demo-cmd

执行结果为:

NAME                READY   STATUS    RESTARTS   AGE
demo-cmd-dp9rr      1/1     Running   0          3m50s
demo-sd8fm          1/1     Running   0          3h48m
demo-volume-2qf4d   1/1     Running   0          54m

可见名为“demo-cmd-dp9rr”的POD已经启动成功,我们再获取上一个被创建的容器:

docker container ls -a -l

执行结果为:

CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS     NAMES
4752902d8055   b628de4edc20   "/bin/bash -c '/bin/…"   5 minutes ago   Up 5 minutes             k8s_demo-cmd_demo-cmd-dp9rr_default_b0b41dd3-aad2-45d1-98c3-5d20b4b765a8_0

我们通过容器的唯一标识登录到容器中:

docker exec -it 4752902d8055 /bin/bash

在容器中执行以下命令:

ps -ef

输出结果为:

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 18:25 ?        00:00:00 /bin/bash /opt/endless-loop.sh value1 value2
root       381     0  0 18:31 pts/0    00:00:00 /bin/bash
root       407     1  0 18:31 ?        00:00:00 sleep 1
root       408   381  0 18:31 pts/0    00:00:00 ps -ef

可以看到,PID为“1”的进程,其启动参数中包含了配置在“literal-configs”中的“key1”和“key2”对应的配置的值。至此,我们已经成功地在容器主程序的命令行中使用ConfigMap的配置作为参数使用。

到此,ConfigMap的各种创建和使用方法我们均已操作完成,下面我们来对环境进行清理。

清理环境

在清理环境时,我们只需要删除对应的ReplicationController和ConfigMap即可。

首先,我们删除之前创建的ReplicationController:

kubectl delete rc demo demo-volume demo-cmd

执行结果为:

replicationcontroller "demo" deleted
replicationcontroller "demo-volume" deleted
replicationcontroller "demo-cmd" deleted

三个ReplicationController均已删除成功。然后我们查看POD,确保各POD也已被清理:

kubectl get pods

执行结果为:

No resources found in default namespace.

可见,相应的POD也已被清理掉。接下来我们清理之前创建的ConfigMap:

kubectl delete cm demo file-configs literal-configs

执行结果为:

configmap "demo" deleted
configmap "file-configs" deleted
configmap "literal-configs" deleted

三个ConfigMap也已被清理掉。

最后,我们将用于测试的Docker镜像清理掉即可:

docker image rm endless-loop:test

执行结果为:

Untagged: endless-loop:test
Deleted: sha256:b628de4edc20584151b35c9ce9a52361ea2817960c1d33dc36b86b96f43903cf
Deleted: sha256:53a9cc112964809a04b193db3c9a86909f588b303b80992689ef045328c30ce7
Deleted: sha256:920452a783774eafe837b08de071520310c1226e380f5a0ee98ca237a001b1b7
Deleted: sha256:4aa58aac0ed84d437c2fd8562b5d56bbba78a4871426d6d962541315804817ed

至此,我们已经清理掉之前创建的所有资源。

相关推荐

Python入门学习记录之一:变量_python怎么用变量

写这个,主要是对自己学习python知识的一个总结,也是加深自己的印象。变量(英文:variable),也叫标识符。在python中,变量的命名规则有以下三点:>变量名只能包含字母、数字和下划线...

python变量命名规则——来自小白的总结

python是一个动态编译类编程语言,所以程序在运行前不需要如C语言的先行编译动作,因此也只有在程序运行过程中才能发现程序的问题。基于此,python的变量就有一定的命名规范。python作为当前热门...

Python入门学习教程:第 2 章 变量与数据类型

2.1什么是变量?在编程中,变量就像一个存放数据的容器,它可以存储各种信息,并且这些信息可以被读取和修改。想象一下,变量就如同我们生活中的盒子,你可以把东西放进去,也可以随时拿出来看看,甚至可以换成...

绘制学术论文中的“三线表”具体指导

在科研过程中,大家用到最多的可能就是“三线表”。“三线表”,一般主要由三条横线构成,当然在变量名栏里也可以拆分单元格,出现更多的线。更重要的是,“三线表”也是一种数据记录规范,以“三线表”形式记录的数...

Python基础语法知识--变量和数据类型

学习Python中的变量和数据类型至关重要,因为它们构成了Python编程的基石。以下是帮助您了解Python中的变量和数据类型的分步指南:1.变量:变量在Python中用于存储数据值。它们充...

一文搞懂 Python 中的所有标点符号

反引号`无任何作用。传说Python3中它被移除是因为和单引号字符'太相似。波浪号~(按位取反符号)~被称为取反或补码运算符。它放在我们想要取反的对象前面。如果放在一个整数n...

Python变量类型和运算符_python中变量的含义

别再被小名词坑哭了:Python新手常犯的那些隐蔽错误,我用同事的真实bug拆给你看我记得有一次和同事张姐一起追查一个看似随机崩溃的脚本,最后发现罪魁祸首竟然是她把变量命名成了list。说实话...

从零开始:深入剖析 Spring Boot3 中配置文件的加载顺序

在当今的互联网软件开发领域,SpringBoot无疑是最为热门和广泛应用的框架之一。它以其强大的功能、便捷的开发体验,极大地提升了开发效率,成为众多开发者构建Web应用程序的首选。而在Spr...

Python中下划线 ‘_’ 的用法,你知道几种

Python中下划线()是一个有特殊含义和用途的符号,它可以用来表示以下几种情况:1在解释器中,下划线(_)表示上一个表达式的值,可以用来进行快速计算或测试。例如:>>>2+...

解锁Shell编程:变量_shell $变量

引言:开启Shell编程大门Shell作为用户与Linux内核之间的桥梁,为我们提供了强大的命令行交互方式。它不仅能执行简单的文件操作、进程管理,还能通过编写脚本实现复杂的自动化任务。无论是...

一文学会Python的变量命名规则!_python的变量命名有哪些要求

目录1.变量的命名原则3.内置函数尽量不要做变量4.删除变量和垃圾回收机制5.结语1.变量的命名原则①由英文字母、_(下划线)、或中文开头②变量名称只能由英文字母、数字、下画线或中文字所组成。③英文字...

更可靠的Rust-语法篇-区分语句/表达式,略览if/loop/while/for

src/main.rs://函数定义fnadd(a:i32,b:i32)->i32{a+b//末尾表达式}fnmain(){leta:i3...

C++第五课:变量的命名规则_c++中变量的命名规则

变量的命名不是想怎么起就怎么起的,而是有一套固定的规则的。具体规则:1.名字要合法:变量名必须是由字母、数字或下划线组成。例如:a,a1,a_1。2.开头不能是数字。例如:可以a1,但不能起1a。3....

Rust编程-核心篇-不安全编程_rust安全性

Unsafe的必要性Rust的所有权系统和类型系统为我们提供了强大的安全保障,但在某些情况下,我们需要突破这些限制来:与C代码交互实现底层系统编程优化性能关键代码实现某些编译器无法验证的安全操作Rus...

探秘 Python 内存管理:背后的神奇机制

在编程的世界里,内存管理就如同幕后的精密操控者,确保程序的高效运行。Python作为一种广泛使用的编程语言,其内存管理机制既巧妙又复杂,为开发者们提供了便利的同时,也展现了强大的底层控制能力。一、P...