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

【一起来学kubernetes】17、Configmap使用详解

    • 前言
    • 概述
    • 核心特性
    • 创建 ConfigMap
    • 使用 ConfigMap
          • 1. **环境变量**
          • 2. **Volume 挂载**
          • 3. **命令行参数**
    • 更新与热重载
    • Docker容器中Java服务使用Configmap
      • **一、通过环境变量注入**
        • **步骤说明**
        • **示例配置**
      • **二、通过 Volume 挂载配置文件**
        • **步骤说明**
        • **示例配置**
      • **三、动态刷新配置(高级场景)**
        • **实现原理**
        • **Spring Boot 示例(热更新)**
      • **四、最佳实践**
      • **五、常见问题排查**
    • 典型应用场景
    • 安全与权限
    • 最佳实践
    • 常见问题
    • 总结
    • 拓展

在这里插入图片描述

前言

在上一篇文章中,我们主要介绍了k8s中针对定时任务的批处理任务的资源:CronJob 和 一次性批处理任务的资源 : Job; 在进行任务处理的过程中,不可或缺的一个东西就是配置,接下来我们就把k8s中用于配置配置信息的工具Configmap进行一个深入的介绍


概述

ConfigMap 是 Kubernetes 中用于存储和管理配置数据的资源对象,允许你在不修改容器镜像的情况下,动态注入配置信息到 Pod 中。其核心思想是将配置与应用程序代码解耦,提升灵活性和可维护性。


核心特性

键值对存储:配置数据以 key-value 形式存储,便于灵活读取。
多 Pod 共享:单个 ConfigMap 可被多个 Pod 或服务共享。
动态更新:支持配置热更新(依赖 Volume 类型及 Kubernetes 版本)。
非敏感数据:适用于存储明文配置(如日志级别、超时设置),敏感数据应使用 Secrets


创建 ConfigMap

方式 1:通过 YAML 文件定义

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config   # 唯一标识符
  namespace: default  # 可选命名空间
data:
  db-host: localhost
  db-port: "5432"
  log-level: info

方式 2:通过 kubectl 命令

kubectl create configmap app-config \
  --from-file=db.conf \
  --from-literal=log-level=debug

--from-file:从文件加载键值对(文件名作为 key)。
--from-literal:直接指定键值对。

方式 3:通过 API 创建
使用 curl 或客户端库直接调用 Kubernetes API。


使用 ConfigMap

ConfigMap 可通过以下三种方式注入 Pod:

1. 环境变量

在 Pod 的 env 字段中引用 ConfigMap:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: my-app
    env:
    - name: DB_HOST
      valueFrom:
        configMapKeyRef:
          name: app-config  # ConfigMap 名称
          key: db-host     # 对应的键
2. Volume 挂载

将 ConfigMap 挂载为目录或文件:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  volumes:
  - name: config-volume
    configMap:
      name: app-config
  containers:
  - name: my-container
    image: my-app
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config   # 挂载到容器内的目录

• 挂载后,容器内 /etc/config 目录下会生成以 key 命名的文件(如 db-host)。

3. 命令行参数

在容器启动命令中动态替换参数:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: my-app
    args:
    - "-db-host=${DB_HOST}"
    - "-log-level=${LOG_LEVEL}"
    env:
    - name: DB_HOST
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: db-host
    - name: LOG_LEVEL
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: log-level

更新与热重载

手动更新:修改 ConfigMap 后,新 Pod 会自动获取最新配置,旧 Pod 需等待调度器重新调度。
热更新:若使用 volumeMounts 挂载 ConfigMap,部分 Volume 类型(如 emptyDir)支持热更新,但需确保容器进程主动监听文件变化。


Docker容器中Java服务使用Configmap

在 Kubernetes Pod 中运行的 Docker 容器内的 Java 服务可以通过以下两种主要方式使用 ConfigMap 配置的变量:


一、通过环境变量注入

步骤说明
  1. 在 Kubernetes Pod 中配置环境变量
    在 Pod 的 env 字段中引用 ConfigMap 的键值对,Kubernetes 会将这些值注入为容器环境变量。

  2. 在 Java 代码中读取环境变量
    使用 System.getenv() 或框架提供的配置绑定功能(如 Spring Boot 的 @Value)获取变量值。

示例配置

Kubernetes Pod YAML

apiVersion: v1
kind: Pod
metadata:
  name: java-app
spec:
  containers:
  - name: java-container
    image: your-java-image
    env:
    - name: DB_HOST
      valueFrom:
        configMapKeyRef:
          name: app-config   # ConfigMap 名称
          key: db-host     # ConfigMap 中的键
    - name: DB_PORT
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: db-port

Java 代码读取(原生方式)

public class ConfigExample {
    public static void main(String[] args) {
        String dbHost = System.getenv("DB_HOST"); // 从环境变量读取
        int dbPort = Integer.parseInt(System.getenv("DB_PORT"));
        System.out.println("Connecting to DB: " + dbHost + ":" + dbPort);
    }
}

Java 代码读取(Spring Boot 方式)

@Configuration
public class AppConfig {
    @Value("${DB_HOST}")
    private String dbHost;

    @Value("${DB_PORT}")
    private int dbPort;

    // Getter 和业务逻辑
}

关键点:确保 Spring Boot 的 application.propertiesapplication.yml 中未定义同名属性,否则会覆盖环境变量。


二、通过 Volume 挂载配置文件

步骤说明
  1. 将 ConfigMap 挂载为目录
    在 Pod 中定义 Volume,并将 ConfigMap 挂载到容器内的目录(如 /app/config)。

  2. Java 服务读取配置文件
    假设 ConfigMap 中的键值对对应配置文件内容(如 application.yml),Java 服务直接读取该文件。

示例配置

Kubernetes Pod YAML

apiVersion: v1
kind: Pod
metadata:
  name: java-app
spec:
  volumes:
  - name: config-volume
    configMap:
      name: app-config   # ConfigMap 名称
  containers:
  - name: java-container
    image: your-java-image
    volumeMounts:
    - name: config-volume
      mountPath: /app/config   # 挂载到容器内的目录

ConfigMap 数据结构

# app-config ConfigMap
data:
  application.yml: |
    db:
      host: localhost
      port: 5432
    log:
      level: info

Java 代码读取配置文件

public class ConfigLoader {
    public static void loadConfig(String filePath) {
        try (InputStream inputStream = new FileInputStream(filePath)) {
            Yaml yaml = new Yaml(new Constructor(Config.class));
            Config config = yaml.load(inputStream);
            System.out.println("DB Host: " + config.getDb().getHost());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 配置类映射 YAML 结构
class Config {
    private Db db;
    private Log log;
    // Getter 和 Setter
}

class Db {
    private String host;
    private int port;
    // Getter 和 Setter
}

class Log {
    private String level;
    // Getter 和 Setter
}

三、动态刷新配置(高级场景)

实现原理
  1. 基于文件监听的热更新
    • 将 ConfigMap 挂载为 Volume,并监控配置文件变化(如 Spring Boot 的 spring.cloud.config监视)。
    • 需容器内进程主动监听文件变动(如 Spring Boot 的 @RefreshScope)。

  2. 使用 Kubernetes ConfigMap 事件监听
    • 通过客户端库监听 ConfigMap 变更事件,动态更新应用配置(适用于自定义框架)。

Spring Boot 示例(热更新)
# application.yml
spring:
  cloud:
    config:
      monitor:
        enabled: true
        poll-interval: 5s
@RestController
@RefreshScope
public class DynamicConfigController {
    @Value("${db.host}")
    private String dbHost;

    @GetMapping("/config")
    public String getDbHost() {
        return dbHost;
    }
}

依赖:需添加 spring-cloud-starter-configspring-boot-starter-actuator 依赖。


四、最佳实践

  1. 优先选择环境变量
    • 简单直接,适合键值对较少的配置(如数据库地址、开关标志)。
    • 与 Kubernetes 生态无缝集成,无需额外代码。

  2. 文件挂载适合复杂配置
    • 当配置结构复杂(如多层级 JSON/YAML)时,将 ConfigMap 映射为配置文件更易管理。
    • 需确保容器内有文件解析逻辑。

  3. 结合 Secrets 处理敏感数据
    • 使用 Secrets 存储密码、API 密钥等敏感信息,避免硬编码。

  4. 配置版本化管理
    • 通过 Git 或 ConfigMap 的 data 字段版本历史跟踪变更。


五、常见问题排查

Q1: ConfigMap 变量未生效?
• 检查 Pod 日志:kubectl logs <pod-name> -c java-container
• 确认 ConfigMap 名称和键名拼写一致。
• 若使用文件挂载,验证挂载路径是否正确(如 /app/config)。

Q2: 如何调试环境变量?
• 在 Pod 中运行命令查看环境变量:

kubectl exec <pod-name> -c java-container -- printenv | grep DB_

通过以上方法,Java 服务可以灵活地集成 Kubernetes ConfigMap,实现配置与代码的解耦,提升部署和维护效率。

典型应用场景

  1. 数据库配置:存储主机、端口、用户名、密码(非敏感部分)。
  2. API 密钥:管理第三方服务的访问令牌(需结合 Secrets)。
  3. 环境变量:动态调整日志级别、超时时间等运行时参数。
  4. 模板配置:注入 Nginx/Redis 配置文件内容。

安全与权限

RBAC 控制:通过 kubectl auth can-i 或 YAML 中的 roles/rolebindings 限制 ConfigMap 的访问权限。
敏感数据:避免存储密码等机密信息,改用 Secrets(加密存储)。
命名空间隔离:ConfigMap 默认作用域为当前命名空间,跨命名空间访问需显式指定。


最佳实践

  1. 命名规范:使用 configmap/<应用>-<环境>(如 configmap/web-prod)。
  2. 分层配置:将复杂配置拆分为多个 ConfigMap,按需组合。
  3. 版本控制:结合 Git 管理 ConfigMap 的变更历史。
  4. 监控日志:通过 kubectl describe configmap 查看变更记录。
  5. 文档化:记录 ConfigMap 中各键值的含义及默认值。

常见问题

Q1: ConfigMap 更新后 Pod 未生效?
A: 确保 Pod 使用了正确的 ConfigMap 名称,并检查是否通过 volumeMounts 挂载。对于热更新,需确认容器进程支持文件变更监听(如 Node.js 的 fs.watch)。

Q2: 如何加密 ConfigMap 数据?
A: Kubernetes 不原生支持加密 ConfigMap,但可通过以下方式实现:
• 使用 Secrets 存储加密数据。
• 在部署前对值进行 Base64 编码,部署后再解码(牺牲可读性)。


总结

ConfigMap 是 Kubernetes 中不可或缺的配置管理工具,通过解耦配置与代码,显著提升了部署和维护的效率。合理使用 ConfigMap 结合 Secrets、RBAC 和自动化工具(如 Helm),可以构建 robust 的云原生应用架构。

拓展

【一起来学kubernetes】15、Job使用详解

【一起来学kubernetes】14、StatefulSet使用详解


http://www.kler.cn/a/590780.html

相关文章:

  • 程序包jakarta.annotation不存在
  • 求余在程序设计中的用处
  • Netty基础—Netty实现消息推送服务
  • IntelliJ IDEA 调试技巧指南
  • apache-maven-3.9.9 详细安装配置教程(2025版)
  • 散货拼柜业务,如何管理多个客户和供应商的财务账单?
  • Android audio(8)-native音频服务的启动与协作(audiopolicyservice和audioflinger)
  • Linux 入门:权限的认识和学习
  • ThreadPoolExecutor 源码分析
  • 【设计模式】3W 学习法深入剖析创建型模式:原理、实战与开源框架应用(含 Java 代码)
  • 电动车出入库管理软件,电动车维修保养售后服务管理系统,佳易王电动车店管理系统操作教程
  • OpenResty/Lua 编码指南/指南
  • 7、vue3做了什么
  • 3.17学习总结
  • vue3 引入element-plus组件后,发现输入的时候没有提示,而且鼠标移到el-button显示unknown的简单解决方法
  • 4.angular 服务
  • SpringBoot第三站:配置嵌入式服务器使用外置的Servlet容器
  • 【软件系统架构】单体架构
  • Android Fresco 框架兼容模块源码深度剖析(六)
  • Pygame实现记忆拼图游戏10