当前位置: 首页 > news >正文

K8S配置管理:ConfigMap与Secret

一、概述

在前面的两篇文章(K8S里的“豌豆荚”:Pod,K8S中的神秘任务Job与CronJob)中我们学习了Kubernetes 里的三种 API 对象:Pod、Job 和 CronJob,虽然没有比其他对象更高级,但使用它们也可以在集群里编排运行一些实际的业务了。不过想让业务更顺利地运行,有一个问题不容忽视,那就是应用的配置管理。配置管理是一个至关重要的环节。想象一下,你开发了一个超棒的微服务应用,它依赖于数据库连接地址、各种密钥以及一些个性化的配置参数。当你把这个应用容器化并部署到 K8S 集群中时,如果这些配置信息都硬编码在容器镜像里,那后续的维护和升级工作将会是一场噩梦。比如,当数据库地址发生变更,难道你要重新构建整个镜像,再重新部署吗?这显然既耗时又费力。这时候,ConfigMap 和 Secret 就闪亮登场啦!接下来就深度揭秘ConfigMap与Secret。

二、ConfigMap是什么?

ConfigMap 是 Kubernetes 里专门用于存储非敏感配置数据的资源对象 ,它就像是一个公开的配置仓库,以键值对(Key-Value)的形式保存配置信息,支持纯文本、JSON、XML 等多种格式,可以将应用程序的配置与容器镜像分离,让配置的管理更加灵活和独立。比如,你有一个 Java Web 应用,它需要连接数据库,数据库的地址、端口这些配置信息就可以存储在 ConfigMap 中。这样,当数据库地址发生变化时,你只需要修改 ConfigMap 中的配置,而不需要重新构建容器镜像,极大地提高了应用的可维护性。同时,ConfigMap 还可以在多个 Pod 之间共享,实现配置的统一管理,减少了重复配置的工作。 从本质上来说,ConfigMap 解决了配置与应用耦合的问题,让应用可以更加专注于业务逻辑的实现,而不用担心配置的变化对应用本身造成影响,就像为应用穿上了一层 “配置隔离衣”,使其在不同的环境中都能轻松应对配置的差异。

2.1 创建方式大揭秘

2.1.1 命令行创建

通过kubectl create configmap命令 ,我们可以快速创建 ConfigMap。结合--from-literal 、--from-file 、--from-env-file等参数,能实现从不同来源创建 ConfigMap。

  • 从字面量创建:使用--from-literal参数可以直接在命令行中指定键值对。比如,我们要创建一个名为my-config的 ConfigMap,包含key1=value1和key2=value2两个键值对,可以使用以下命令:
kubectl create configmap my-config --from-literal=key1=value1 --from-literal=key2=value2

执行这个命令后,Kubernetes 会在集群中创建一个名为my-config的 ConfigMap,其中包含我们指定的两个键值对。这种方式非常适合创建一些简单的、临时的配置,比如设置一些环境变量。

2.1.2  YAML 文件创建

YAML 文件创建 ConfigMap 可以让配置更加结构化和可维护 ,适合在生产环境中使用。下面是一个 YAML 文件创建 ConfigMap 的结构示例:

apiVersion: v1
kind: ConfigMap
metadata:name: my-configmapnamespace: default
data:user: 'zhangsan'path: '/etc/app'
  • apiVersion:指定 Kubernetes API 的版本,这里使用v1,表示这是一个稳定的 API 版本。不同的 Kubernetes 版本可能支持不同的 API 版本,在创建资源时,需要根据实际情况选择合适的版本。​
  • kind:指定资源类型,这里是ConfigMap,表示我们要创建的是一个 ConfigMap 对象。​
  • metadata:包含 ConfigMap 的元数据,如name指定 ConfigMap 的名称,在同一个命名空间中,名称必须唯一;namespace指定 ConfigMap 所属的命名空间,默认是default命名空间。命名空间可以帮助我们将不同的应用或项目隔离开来,便于管理和维护。​
  • data:用于存储实际的配置数据,以键值对的形式呈现。这里的key1和key2是简单的键值对,而config.properties是一个多行的配置内容,使用|符号表示后面的内容是一个多行字符串,适合存储完整的配置文件内容。​

使用 YAML 文件创建 ConfigMap 时,首先需要将上述内容保存为一个.yaml文件,比如configmap.yaml,然后执行以下命令:

kubectl apply -f configmap.yaml

Kubernetes 会读取这个 YAML 文件,并根据其中的定义创建 ConfigMap。如果 ConfigMap 已经存在,kubectl apply命令会更新它的配置。

创建成功后,我们还是可以用 kubectl get、kubectl describe 来查看 ConfigMap 的状态。可以发现 ConfigMap 的 Key-Value 信息就已经存入了 etcd 数据库,后续就可以被其他 API 对象使用。

三、Secret是什么?

了解了 ConfigMap 对象,我们再来看 Secret 对象就会容易很多,它和 ConfigMap 的结构和用法很类似,但也有着本质的区别,ConfigMap 主要处理非敏感的配置数据,就像一个公开的信息展示板;而 Secret 则如同一个坚固的保险箱,专门用于存储敏感信息,如数据库密码、API 访问令牌、私钥等。这些敏感信息一旦泄露,可能会导致严重的安全问题,比如数据库被恶意访问、应用程序被非法调用等。Secret 的存在,使得这些敏感数据可以与容器镜像和 Pod 的定义分离,大大降低了敏感信息暴露的风险。在一个应用中,数据库的用户名和密码就可以存储在 Secret 中,而不是直接写在应用代码或者镜像里,这样即使镜像被获取,敏感的数据库凭证也能得到保护。

3.1 创建方式大揭秘

3.1.1 命令行创建

通过 kubectl 命令创建:使用kubectl create secret命令可以创建不同类型的 Secret 。以创建 Opaque 类型的 Secret 为例,如果要存储数据库的用户名和密码,可以使用--from-literal参数从字面量创建。假设用户名是admin,密码是123456,命令如下:

kubectl create secret generic db-secret --from-literal=username=dbuser--from-literal=password=dbpassword

这里的generic表示创建的是 Opaque 类型的 Secret,db-secret是 Secret 的名称,--from-literal后面跟着的是键值对,分别表示用户名和密码。

3.1.2 通过 YAML 文件创建

使用 YAML 文件创建 Secret 可以让配置更加清晰和可维护 。下面是一个创建 Secret 的 YAML 文件示例:

apiVersion: v1
kind: Secret
metadata:name: my-secretnamespace: default
data:username: ZGJ1c2Vy  # base64编码后的dbuserpassword: ZGJwYXNzd29yZA==  # base64编码后的dbpassword

我们从上面的yaml文件会发现,这里的“username”值是一串“乱码”,而不是刚才在命令行里写的明文 “dbuser”。这串“乱码”就是 Secret 与 ConfigMap 的不同之处,不让用户直接看到原始数据,起到一定的 保密作用。不过它的手法非常简单,只是做了 Base64 编码,根本算不上真正的加密,所以我们完全可以绕开 kubectl,自己用 Linux 小工具“base64”来对数据编码,然后写入 YAML 文 件,比如:

echo -n "dbpassword" | base64
ZGJwYXNzd29yZA==

要注意这条命令里的 echo ,必须要加参数 -n 去掉字符串里隐含的换行符,否则 Base64 编 码出来的字符串就是错误的。

这样一个存储敏感信息的 Secret 对象也就创建好了,而且因为它是保密的,使用 kubectl describe 不能直接看到内容,只能看到数据的大小,你可以和 ConfigMap 对比一下。

四、ConfigMap/Secret在pod中的使用

现在通过编写 YAML 文件,我们创建了 ConfigMap 和 Secret 对象,该怎么在 Kubernetes 里 应用它们呢?

因为 ConfigMap 和 Secret 只是一些存储在 etcd 里的字符串,所以如果想要在运行时产生效果,就必须要以某种方式“注入”到 Pod 里,让应用去读取。在这方面的处理上 Kubernetes 和 Docker 是一样的,也是两种途径:环境变量加载文件

4.1 以环境变量的方式使用 ConfigMap/Secret

了解Pod的都知道,描述容器的字段“containers”里有一个“env”,它定义了 Pod 里容 器能够看到的环境变量。下面我就把引用了 ConfigMap 和 Secret 对象的 Pod 列出来,给大家做个示范:

apiVersion: v1
kind: Pod
metadata:name: my-pod
spec:containers:- name: my-containerimage: nginx:latestenv:- name: USERvalueFrom:configMapKeyRef:name: my-configmapkey: user- name: USERNAMEvalueFrom:secretKeyRef:name: my-secretkey: username

“valueFrom”字段指定了环境变量值的来源,可以是“configMapKeyRef”或者 “secretKeyRef”,然后你要再进一步指定应用的 ConfigMap/Secret 的“name”和它里面的 “key”,要当心的是这个“name”字段是 API 对象的名字,而不是 Key-Value 的名字。

通过上面yaml文件来观看可能不是那么直观,因为 ConfigMap 和 Secret 在 Pod 里的组合关系不像 Job/CronJob 那么简单直接,所以我还是用画图来表示它们的引用关系:

从这张图你就应该能够比较清楚地看出 Pod 与 ConfigMap、Secret 的“松耦合”关系,它们不是直接嵌套包含,而是使用“KeyRef”字段间接引用对象,这样,同一段配置信息就可以在不同 的对象之间共享。

4.2 以 Volume 的方式使用 ConfigMap/Secret

Kubernetes 为 Pod 定义了一个“Volume”的概念,可以翻译成是“存储卷”。如果把 Pod 理解成是一个虚拟机,那么 Volume 就相当于是虚拟机里的磁盘。

我们可以为 Pod“挂载(mount)”多个 Volume,里面存放供 Pod 访问的数据,这种方式有点 类似 docker run -v,虽然用法复杂了一些,但功能也相应强大一些。 在 Pod 里挂载 Volume 很容易,只需要在“spec”里增加一个“volumes”字段,然后再定义卷的 名字和引用的 ConfigMap/Secret 就可以了。要注意的是 Volume 属于 Pod,不属于容器,所 以它和字段“containers”是同级的,都属于“spec”。

下面让我们来定义两个 Volume,分别引用 ConfigMap 和 Secret,名字是 cm-vol 和 sec-vol:

spec:volumes:- name: cm-volconfigMap:name: my-configmap- name: sec-volsecret:secretName: my-secret

有了 Volume 的定义之后,就可以在容器里挂载了,这要用到“volumeMounts”字段,正如它的字面含义,可以把定义好的 Volume 挂载到容器里的某个路径下,所以需要在里面用 “mountPath”“name”明确地指定挂载路径和 Volume 的名字。

containers:
- volumeMounts:- mountPath: /tmp/cm-itemsname: cm-vol- mountPath: /tmp/sec-itemsname: sec-vol

把“volumes”和“volumeMounts”字段都写好之后,配置信息就可以加载成文件了。这里我还 是画了图来表示它们的引用关系:

通过上面的图可以看到看到,挂载 Volume 的方式和环境变量又不太相同。环境变量是直接引用了 ConfigMap/Secret,而 Volume 又多加了一个环节,需要先用 Volume 引用 ConfigMap/Secret,然后在容器里挂载 Volume,有点“兜圈子”“弯弯绕”。

这种方式的好处在于:以 Volume 的概念统一抽象了所有的存储,不仅现在支持 ConfigMap/Secret,以后还能够支持临时卷、持久卷、动态卷、快照卷等许多形式的存储,扩展性非常好。

五、小结

通过上面的分享相信大家也了解到了在 Kubernetes 里管理配置信息的 API 对象 ConfigMap 和 Secret,它们分别代表了明文信息和机密敏感信息,存储在 etcd 里,在需要的时候可以注入 Pod 供 Pod 使用。

Tips: 为了大家快速高效的学习,已经将文章提交到了git仓库,涵盖后端大部分技术,以及后端学习路线,仓库内容会持续更新,建议 Star 收藏 以便随时查看https://gitee.com/bxlj/java-article。

http://www.dtcms.com/a/389091.html

相关文章:

  • 奥威BI+ChatBI:数据智能时代的一体化解决方案
  • 微服务与云原生实战:Spring Cloud Alibaba 与 Kubernetes 深度整合指南
  • 从慕尼黑到新大陆:知行科技「智驾」与「机器人」的双行线
  • VINTF中manifest.xml和compatibility_matrix.xml的作用
  • AI时代云原生数据库一体机的思考
  • 配置manifest.xml和compatibility_matrix.xml
  • Prometheus高可用监控架构性能优化实践指南
  • 低代码平台与云原生开发理念是否契合?
  • 红队测试手册:使用 promptfoo 深入探索大语言模型安全
  • el-date-picker设置默认值
  • 结语:Electron 开发的完整路径
  • 数据结构系列之线性表
  • Vue2 生命周期钩子详解:beforeCreate、created、mounted、beforeDestroy 用法顺序与坑点指南
  • electron nodejs安装electron 以及解压打包
  • 每日一题:链表排序(归并排序实现)
  • 团体程序设计天梯赛-练习集 L1-032 Left-pad
  • AI的出现,能否代替IT从业者
  • 一个基于Java+Vue开发的灵活用工系统:技术实现与架构解析
  • 原神望陇村遗迹 解谜
  • 半导体制造常提到的Fan-in晶圆级封装是什么?
  • MySQL 专题(五):日志体系(Redo Log、Undo Log、Binlog)原理与应用
  • 锂电池取代铅酸电池作为及其老化率计算常用算法
  • FreeRtos面试问题合集
  • Codeforces Round 1051 Div.2 补题
  • tokenizer截断丢失信息,如何处理?
  • Mybatis学习笔记03-XML映射配置
  • 时空预测论文分享:模仿式生成 动态局部化 解耦混淆因子表征 零样本/少样本迁移
  • 更新!Windows 11 25H2 四合一版【版本号:26200.5074】
  • CentOS 7.9 离线部署 KVM + WebVirtMgr,通过WebVirtMgr创建虚拟机教程
  • Python实现在模型上进行点云(下)采样