Kubernetes 1.2 新功能介绍:ConfigMap

本文介绍了Kubernetes中ConfigMap的使用方法,包括其创建、配置及应用场景等关键信息,帮助读者理解如何利用ConfigMap进行配置管理。

20160721150011

什么是ConfigMap


ConfigMap API用于存储已经在kubernetes中部署的配置数据,它主要聚焦:

  • 为已经部署的应用提供动态的、分布式的配置管理
  • 封装配置管理信息,简化kubernetes的部署管理
  • 为kubernetes创建一个灵活的配置管理模型

设计ConfigMap的动机


ConfigMap的设计目标:

  • 描述一个ConfigMap资源
  • 描述ConfigMap作为环境变量的语义
  • 描述ConfigMap作为数据卷文件

ConfigMap基本原理


容器的配置管理——把应用的代码和配置区分开,是被推荐的做法。我们希望能够让应用的开发者在Kubernetes里充分使用这样的模式。ConfigMap的API概念上来说很简单,从数据角度来看,ConfigMap的类型只是键值组。应用可以从不同角度来配置,所以关于给用户如何存储和使用配置数据,我们需要给他们一些弹性。在一个pod里面使用ConfigMap大致有三种方式:

(1)     命令行参数

(2)     环境变量

(3)     数据卷文件

这些不同的方法就需要有不同的数据建模方式来使用数据。为了尽可能提供多的弹性,我们使用ConfigMap来承载既有粗力度也有细粒度的数据。另外,由于应用会从环境变量和包含配置数据的文件读取配置信息,我们建立ConfigMap来支持这两者任何一种的读取方式。

一个简单的ConfigMap


我们先写个最简单的ConfigMap:

20160721150020

上面一个简单的ConfigMap,展示了如何存储一个键值对,接下来我们看一个更复杂的例子:

20160721150027

data的数据域中以键值对的形式定义了配置信息,从这些信息可以看出,ConfigMap既可以定义细粒度的配置信息(etc. example.property.1),也可定义粗粒度的信息(etc. example.property.file)。到目前为止,我们还不能清晰的知道ConfigMap如何的使用,接下来我们创建一个ConfigMap作为示例。

创建ConfigMaps


我们使用kubectl create configmap命令来创建ConfigMap,我们将演示不同的创建方式:从文本,从文件,或者从目录。

从目录创建ConfigMap


下面的例子中,game和ui的配置以键值对的形式分别写在两个文本文件中:

20160721150036

通过kubectl create configmap命令来创建该目录下的ConfigMap:

20160721150044
当使用—from-file选项指定ConfigMap的目录时,kubernetes会扫描目录下的所有文件,并将文件名作为键值对的key值,文件内容作为value值。

接下来我们查看我们的ConfigMap的更多细节:

20160721150052

我们使用kubectl describe命令来展示ConfigMap的更多细节,还可以使用如下方式:

20160721150100

删除ConfigMap:

20160721150108

从文件创建ConfigMap


20160721150118

从文本创建ConfigMap


使用–from-literal选项来指定一个key=value键值对来创建ConfigMap:

20160721150139

使用ConfigMap


我们将使用三个例子来介绍ConfigMap的不同的使用方式和场景。

场景1:ConfigMap以环境变量的形式使用


20160721150148
我们在Pod中使用这个ConfigMap:

20160721150157

创建这个Pod后,执行结果会包含如下两行:

SPECIAL_LEVEL_KEY=very

SPECIAL_TYPE_KEY=charm

场景2:ConfigMap作为命令行参数


我们仍然用刚才的ConfigMap作为例子:

20160721150232

为了将一个数值注入控制台命令行,我们必须使用像上面例子中的环境变量的方式,我们使用$(VAR_NAME)来在容器中的命令中引用这个配置:

20160721150221

执行的结果将是如下:

very charm

场景3:通过数据卷插件来使用ConfigMap


ConfigMap也可以在数据卷里面被使用。再次回到我们的ConfigMap的例子

20160721150232

在数据卷里面使用这个ConfigMap,我们有不同的选项。最基本的就是将文件填入数据卷,这个文件中,键就是文件名,键值就是文件内容:

20160721150239

当这个pod运行的时候,输出是这样的:

very

我们也可以在ConfigMap值被映射的数据卷里控制路径:

20160721150247

它运行后,将输出:

very

真实案例:配置Redis


让我们来看一下真实的案例:用Configmap配置redis。我们想要将redis作为一个缓存用推荐配置来输入redis。Redis 配置应该包括:

maxmemory 2mb
maxmemory-policy allkeys-lru

官方的例子存在与docs/user-guide/configmap/redis目录下,我们可以通过它来创建ConfigMap:

20160721150302

现在,让我们用这个配置来创建一个pod:

20160721150311

注意,这个pod有一个ConfigMap数据卷,它在一个叫redis.conf的文件里替代了 example-redis-config  ConfigMap的 redis-config密钥。这个数据卷增长到redis容器的 /redis-master目录里,在/redis-master/redis.conf里替代了我们的配置文件,/redis-master/redis.conf就是是image为master查找的redis配置文件。

如果我们kubectl exec到这个pod,并且运行redis-cli工具,我们可以检查到我们的配置被正确运用:

20160721150318

限制条件


ConfigMaps必须在pod中被使用之前创建。Controllers可以会被写来容忍某些配置文件数据的缺失。

Configmaps属于namespace。他们只有在相同的namespaces中通过pods被引用。

ConfigMap大小的配额是已经一个设置好的功能。

Kubelet只支持从API服务器的pods使用ConfigMap。这包括了任意的用Kubectl创建的pods,或者间接的通过replication controller创建的pods。它不包括通过Kubelet的 –manifest-url标志创建的pods,也不包括从它的REST API创建的pods(一般不用这些方法创建pods)。

<think>嗯,用户问为什么在之前的配置中,给ConfigMap单独暴露了一个Service,是不是做错了。我需要先回顾之前的配置,看看具体是怎么做的。 在之前的步骤里,用户提到通过ConfigMap存储域名列表,然后创建了一个Service和Endpoints,其中Endpoints使用了占位IP。ServiceMonitor通过标签选择这个Service来发现目标。可能用户觉得ConfigMap和Service的关联不太直观,为什么需要额外创建一个Service呢? 首先,ConfigMap本身只是存储数据,比如域名列表,但Prometheus的ServiceMonitor通常是用来发现Kubernetes中的Service和Pod,所以要让ServiceMonitor能够动态获取目标,可能需要通过Service和Endpoints的机制。因为ServiceMonitor会监视Service,然后根据对应的Endpoints来获取需要监控的目标。 不过,这里的Endpoints是手动配置的,使用了一个占位IP,这看起来可能不太对。因为通常Endpoints是由Service自动关联Pod的,但在这里,用户可能想通过ConfigMap中的域名列表作为监控目标,而不是实际的Pod IP。所以这里可能使用了某种技巧,通过Service和Endpoints来让ServiceMonitor能够发现这些外部域名目标。 但用户的问题在于,为什么要为ConfigMap单独创建一个Service,这是不是错误的做法?可能用户认为ConfigMap和Service的关联没有必要,或者存在误解。 需要解释的是,单独创建的Service并不是直接暴露ConfigMap,而是为了配合ServiceMonitor的发现机制。ServiceMonitor需要选择一个Service,然后通过该Service对应的Endpoints来获取监控目标。但在这里,Endpoints被手动配置为包含占位IP,而实际的目标数据存在ConfigMap中,可能通过某种方式(比如环境变量或volume挂载)被Blackbox Exporter使用? 或者可能之前的配置中存在混淆,正确的做法应该是让ServiceMonitor直接读取ConfigMap中的目标列表,而不是通过Service和Endpoints。但根据Prometheus Operator的设计,ServiceMonitor通常是通过Service来发现监控目标的,因此可能需要通过某种方式将外部目标转换为Endpoints,以便ServiceMonitor能够发现它们。 不过,更常见的做法是使用额外的组件,比如Prometheus的file_sd_configs或者使用自定义的服务发现机制,但在Kubernetes环境中,可能更倾向于使用Service和Endpoints来实现动态发现。 可能之前的配置中存在一个错误,即创建了一个Service和Endpoints,但Endpoints中的IP是占位符,而实际的目标是通过ConfigMap传递的。这种情况下,Blackbox Exporter可能需要读取ConfigMap中的目标列表,而不是通过ServiceMonitor自动发现。或者,ServiceMonitor的配置中通过relabeling从其他来源获取目标,比如ConfigMap。 需要进一步分析之前的配置,特别是ServiceMonitor的定义。在之前的步骤3中,ServiceMonitor的endpoints部分使用了参数target,值为$(TARGETS),这可能引用了ConfigMap中的targets.json。但Prometheus的配置中是否支持直接从ConfigMap中读取变量呢?这可能是一个错误,因为Prometheus的ServiceMonitor不支持直接引用ConfigMap的内容作为参数。正确的做法可能需要通过挂载ConfigMap到Blackbox Exporter的Pod中,然后在probe请求中指定目标。 可能用户之前的配置有误,将域名列表放在ConfigMap中,然后试图通过ServiceMonitor的参数来引用,但实际在Prometheus的配置中,target参数应该是具体的URL,而这里可能需要通过relabeling或其他机制来动态获取这些目标。正确的做法应该是让Blackbox Exporter读取ConfigMap中的目标列表,然后Prometheus去抓取Blackbox Exporter的/probe接口,并传递这些目标作为参数。 或者,可能需要使用Prometheus的HTTP SD(服务发现)功能,从某个HTTP接口动态获取目标列表,而该接口可以由一个自定义的控制器提供,该控制器读取ConfigMap并生成适合Prometheus的SD格式。但这样会增加复杂性。 回到用户的问题,用户认为单独为ConfigMap创建Service可能是不必要的或者错误的。需要解释为什么需要这个Service,或者指出之前的配置中的错误,并给出正确的做法。 总结来说,可能的误解在于:ConfigMap存储目标列表,而Service和Endpoints是用来让ServiceMonitor发现这些目标,但实际上Endpoints中的IP是占位的,真正的目标是通过其他方式传递的。这可能是一个hack,但并不是标准做法。正确的做法可能需要使用不同的服务发现机制,或者使用Prometheus Operator的PodMonitor等其他资源。 因此,在回答用户时,需要指出之前的配置中存在错误,并解释正确的做法应该是如何,例如通过将域名列表作为静态配置挂载到Blackbox Exporter,或者使用其他服务发现方法,而不是通过Service和Endpoints占位符。</think>--- ### **关键问题分析** 您在之前的配置中看到我创建了一个 `Service` 和 `Endpoints`,并将其与 `ConfigMap` 关联,这是为了适配 **Prometheus Operator** 的服务发现逻辑。但这一设计存在 **误区**,需要修正。 --- ### **原方案的问题** 1. **ConfigMap 与 Service 的误解** ConfigMap 仅用于存储域名列表,但 `ServiceMonitor` 无法直接读取 ConfigMap 的内容。之前的配置通过 `Service` 和占位 IP 的 `Endpoints` 欺骗 Prometheus,使其误以为存在可监控的实体目标,实际目标是硬编码在 ConfigMap 中的。 **本质问题**:`Service` 和 `Endpoints` 在此场景下是冗余且误导的,域名列表未真正实现动态发现。 2. **参数传递错误** 原配置中的 `target: $(TARGETS)` 试图从 ConfigMap 注入变量,但 Prometheus 的 `ServiceMonitor` **不支持直接引用 ConfigMap 内容**,这会导致参数解析失败。 --- ### **修正后的方案** #### **核心思路** 1. **Blackbox Exporter 主动加载域名列表** 将域名列表通过 ConfigMap 挂载到 Blackbox Exporter 容器内,作为静态目标文件。 2. **Prometheus 直接抓取 Blackbox Exporter 的探测接口** 无需通过 `ServiceMonitor` 动态发现域名,改用 Prometheus 的 `file_sd_configs` 或 `http_sd_configs` 机制。 --- ### **步骤 1: 调整 Blackbox Exporter 配置** #### 1.1 将域名列表挂载到 Blackbox Exporter ```yaml # blackbox-exporter-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: blackbox-exporter namespace: monitoring spec: template: spec: containers: - name: blackbox-exporter volumeMounts: - name: targets-volume mountPath: /etc/blackbox_exporter/targets volumes: - name: targets-volume configMap: name: domain-targets # 引用存储域名列表的ConfigMap ``` #### 1.2 更新 ConfigMap 格式(兼容 Blackbox 静态文件) ```yaml # domain-targets-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: domain-targets namespace: monitoring data: targets.yaml: | - targets: - https://example.com - https://api.example.com labels: type: http - targets: - tcp://mysql.example.com:3306 labels: type: tcp ``` --- ### **步骤 2: 配置 Prometheus 抓取规则** #### 2.1 直接通过 `file_sd_configs` 读取目标文件 ```yaml # prometheus-config.yaml scrape_configs: - job_name: 'domain-probe' metrics_path: /probe params: module: [http_2xx] # 使用Blackbox模块 file_sd_configs: - files: - /etc/blackbox_exporter/targets/targets.yaml # 挂载到Prometheus的路径 relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: blackbox-exporter.monitoring.svc:9115 # 指向Blackbox Exporter ``` --- ### **步骤 3: 移除冗余的 Service 和 Endpoints** 删除原方案中用于占位的 `domain-monitor` Service 和 Endpoints,直接通过文件服务发现机制加载目标。 --- ### **修正后的架构对比** | 原方案 | 修正方案 | |-------------------------------|---------------------------------| | 通过 Service/Endpoints 欺骗服务发现 | 直接挂载域名列表到 Blackbox Exporter | | 依赖 ServiceMonitor 复杂配置 | 使用 Prometheus 原生文件服务发现 | | 动态更新需手动修改 ConfigMap 和触发重载 | 更新 ConfigMap 后自动加载新目标 | --- ### **动态更新域名列表** ```bash # 修改ConfigMap kubectl edit configmap domain-targets -n monitoring # 重启Blackbox Exporter(可选,如果未启用文件自动重载) kubectl rollout restart deployment/blackbox-exporter -n monitoring ``` --- ### **为什么原方案是错的?** 1. **ServiceMonitor 的误用** `ServiceMonitor` 设计用于发现 Kubernetes 集群内的 Service 和 Pod,而非外部域名。强行关联 Service 和占位 Endpoints 会导致监控目标与实际探测目标脱节。 2. **配置耦合性高** 原方案依赖多层间接引用(ConfigMap → Service → ServiceMonitor),导致维护复杂且易出错。 --- ### **正确方案的优势** - **简洁性**:直接通过文件加载目标,无需冗余抽象层。 - **兼容性**:兼容 Prometheus 原生服务发现机制(如 `file_sd_configs`、`http_sd_configs`)。 - **可维护性**:更新域名列表只需修改 ConfigMap,无需操作 Service 或 Endpoints。 --- ### **验证方法** 1. 检查 Blackbox Exporter 容器内是否存在挂载的 `targets.yaml` 文件: ```bash kubectl exec -it blackbox-exporter-pod -n monitoring -- ls /etc/blackbox_exporter/targets ``` 2. 在 Prometheus UI 的 **Targets** 页面确认 `domain-probe` 任务状态为 **UP**。 --- ### **总结** 原方案因误解 `ServiceMonitor` 的作用而引入冗余组件,修正后通过 **Blackbox Exporter + 文件服务发现** 实现更简洁高效的域名监控。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值