【免费下载链接】charts
⚠️(OBSOLETE) Curated applications for Kubernetes
本文以stable/prometheus-operatorChart 的 hack/README.md 为主线,系统讲解该仓库中两套自动化同步脚本——sync_prometheus_rules.py与sync_grafana_dashboards.py——是如何把上游 Kubernetes 监控社区的告警规则与 Grafana 看板「导入」为 Helm 模板的,并结合仓库源码逐层剖析其分组拆分、条件开关、变量替换等实现细节,最后给出基于 minikube 的本地端到端验证方案。读完本文,你将掌握这套「上游维护、脚本同步、Chart 二次封装」的监控资产维护工作流,能够独立完成规则与看板的新增导入和问题排查。
一、hack 目录的定位与整体结构
在stable/prometheus-operatorChart 中,hack目录存放的并不是 Chart 运行时的模板,而是一组面向 Chart 维护者的开发辅助工具。它解决的问题非常具体:Prometheus Operator Chart 内置了大量来自上游社区的默认告警规则与 Grafana 看板,这些内容体量大、更新频繁,如果全部手写维护既容易出错也难以跟上上游节奏,因此仓库采用「脚本抓取上游 → 按分组拆文件 → 生成 Helm 模板」的半自动同步策略。
hack目录下共包含以下内容(见 hack 目录):
| 文件 / 目录 | 作用 |
|---|---|
sync_prometheus_rules.py | 从指定 URL 抓取 Prometheus 告警/聚合规则,按 group 名拆分为独立模板文件 |
sync_grafana_dashboards.py | 从指定 URL 抓取 Grafana 看板 JSON,按看板名拆分为独立模板文件 |
requirements.txt | 两个脚本的 Python 依赖(PyYAML、requests) |
minikube/ | 本地 minikube 验证环境,包含启动脚本与专用 values 配置 |
minikube/README.md | minikube 环境的使用说明 |
minikube/cmd.sh | 一键完成 minikube 重置、Helm 初始化、etcd 证书注入、Chart 安装、端口转发的脚本 |
minikube/values.yaml | 面向本地验证的 Chart values 覆盖(etcd 证书挂载与 HTTPS 抓取) |
两个脚本的运行依赖记录在 requirements.txt 中,锁定版本为PyYAML==5.1.2与requests==2.22.0,即安装时执行:
pip install -r stable/prometheus-operator/hack/requirements.txt二、sync_prometheus_rules.py:告警规则同步脚本
2.1 脚本职责与数据源
sync_prometheus_rules.py 的文档字符串写得很直白:Fetch alerting and aggregation rules from provided urls into this chart——从指定 URL 抓取规则,导入当前 Chart。其核心流程是:请求远程 YAML → 解析出规则分组 → 将每个 group 写入一个独立的.yaml模板文件。
脚本内置的数据源列表(charts变量)同时考虑了 Kubernetes 版本兼容性,按目标集群版本将规则拆分到不同目录:
charts = [ { 'source': 'https://raw.githubusercontent.com/coreos/kube-prometheus/master/manifests/prometheus-rules.yaml', 'destination': '../templates/prometheus/rules-1.14', 'min_kubernetes': '1.14.0-0' }, { 'source': 'https://raw.githubusercontent.com/etcd-io/etcd/master/Documentation/op-guide/etcd3_alert.rules.yml', 'destination': '../templates/prometheus/rules-1.14', 'min_kubernetes': '1.14.0-0' }, { 'source': 'https://raw.githubusercontent.com/coreos/kube-prometheus/release-0.1/manifests/prometheus-rules.yaml', 'destination': '../templates/prometheus/rules', 'min_kubernetes': '1.10.0-0', 'max_kubernetes': '1.14.0-0' }, { 'source': 'https://raw.githubusercontent.com/etcd-io/etcd/master/Documentation/op-guide/etcd3_alert.rules.yml', 'destination': '../templates/prometheus/rules', 'min_kubernetes': '1.10.0-0', 'max_kubernetes': '1.14.0-0' }, ]从中可以读出两条关键设计:
- 版本分桶:Kubernetes
>= 1.14的集群使用templates/prometheus/rules-1.14目录,1.10 ~ 1.14之间使用templates/prometheus/rules目录;未指定max_kubernetes时,脚本会在运行时自动补齐为9.9.9-9(见main()中的if ('max_kubernetes' not in chart)分支),相当于「无上限」。 - etcd 规则特殊处理:etcd 官方规则文件没有
spec层,脚本通过yaml_text['spec']['groups'] if yaml_text.get('spec') else yaml_text['groups']兼容两种结构。
2.2 按 group 拆分:一个 group 一个文件
拆分的入口是write_group_to_file()函数。对每个规则分组,它先调用fix_expr()清理表达式中的尾随空白与换行,并将多行表达式转成 YAML 字面量风格(|-),保证生成文件的排版可读:
def fix_expr(rules): """Remove trailing whitespaces and line breaks, which happen to creep in due to yaml import specifics; convert multiline expressions to literal style, |-""" for rule in rules: rule['expr'] = rule['expr'].rstrip() if '\n' in rule['expr']: rule['expr'] = LiteralStr(rule['expr'])随后通过yaml_str_repr()将规则结构序列化为字符串,文件名直接取group['name'] + '.yaml'。最终产物在仓库中真实存在,例如 k8s.rules.yaml 即由k8s.rules这个 group 生成,其文件头带有明确的生成标记:
Generated from 'k8s.rules' group from https://raw.githubusercontent.com/coreos/kube-prometheus/master/manifests/prometheus-rules.yaml Do not change in-place! ...所有生成文件均位于 templates/prometheus/rules-1.14 目录下,包含alertmanager.rules.yaml、general.rules.yaml、kube-apiserver.rules.yaml、node-exporter.yaml、etcd.yaml等 20 余个文件,每个文件对应一个独立的规则组。
2.3 条件开关:condition_map 与 alert_condition_map
导入的规则并非无条件全量启用,而是与 Chart 的values.yaml配置项联动。脚本通过两个映射表实现「模板条件化」:
(1)group 级开关condition_map:为每个规则组绑定一段 Helm 模板布尔表达式,例如:
k8s.rules→.Values.defaultRules.rules.k8skube-apiserver.rules→.Values.kubeApiServer.enabled .Values.defaultRules.rules.kubeApiserver(同时要求 API Server 组件启用且规则开关打开)etcd→.Values.kubeEtcd.enabled .Values.defaultRules.rules.etcd
这些开关最终拼接到模板头部的渲染条件中。以生成的 k8s.rules.yaml 为例:
{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} {{- if and (semverCompare ">=1.14.0-0" $kubeTargetVersion) (semverCompare "<9.9.9-9" $kubeTargetVersion) .Values.defaultRules.create .Values.defaultRules.rules.k8s }}即:版本满足要求、defaultRules.create为真、对应规则组开关为真三者同时满足时才渲染该 PrometheusRule。
(2)单条 alert 级开关alert_condition_map:对个别关键告警单独加{{- if }}包裹,避免「组件未部署但告警仍在」的误报。脚本注释点明了设计动机——"there are more alerts which are left enabled, because they'll never fire without metrics"(其余告警保持启用,因为缺少指标时它们永远不会触发)。映射表如下:
| 告警名 | 条件 |
|---|---|
KubeAPIDown | .Values.kubeApiServer.enabled |
KubeControllerManagerDown | .Values.kubeControllerManager.enabled |
KubeSchedulerDown | .Values.kubeScheduler.enabled |
KubeStateMetricsDown | .Values.kubeStateMetrics.enabled |
KubeletDown | .Values.prometheusOperator.kubeletService.enabled |
PrometheusOperatorDown | .Values.prometheusOperator.enabled |
NodeExporterDown | .Values.nodeExporter.enabled |
CoreDNSDown | .Values.kubeDns.enabled |
AlertmanagerDown | .Values.alertmanager.enabled |
add_rules_conditions()函数会在规则文本中定位- alert: <名称>起始行,在其前插入{{- if <条件> }},并向后查找该 alert 块的结束位置补上{{- end }};由于上游规则顺序可能变化,它还包含一段「遇到嵌套{{- if则回退结束位置」的防御逻辑,确保括号匹配正确。
2.4 变量替换:replacement_map 与 Helm 转义
上游规则中写死的标签值(如job="prometheus-k8s"、namespace="monitoring")在 Helm 场景下必须参数化,这一任务由replacement_map完成:
replacement_map = { 'job="prometheus-operator"': { 'replacement': 'job="{{ $operatorJob }}"', 'init': '{{- $operatorJob := printf "%s-%s" (include "prometheus-operator.fullname" .) "operator" }}'}, 'job="prometheus-k8s"': { 'replacement': 'job="{{ $prometheusJob }}"', 'init': '{{- $prometheusJob := printf "%s-%s" (include "prometheus-operator.fullname" .) "prometheus" }}'}, 'job="alertmanager-main"': { 'replacement': 'job="{{ $alertmanagerJob }}"', 'init': '{{- $alertmanagerJob := printf "%s-%s" (include "prometheus-operator.fullname" .) "alertmanager" }}'}, 'namespace="monitoring"': { 'replacement': 'namespace="{{ $namespace }}"', 'init': '{{- $namespace := printf "%s" (include "prometheus-operator.namespace" .) }}'}, 'alertmanager-$1': { 'replacement': '$1', 'init': ''}, 'https://github.com/kubernetes-monitoring/kubernetes-mixin/tree/master/runbook.md#': { 'replacement': '{{ .Values.defaultRules.runbookUrl }}', 'init': ''}, 'job="kube-state-metrics"': { 'replacement': 'job="kube-state-metrics", namespace=~"{{ $targetNamespace }}"', 'limitGroup': ['kubernetes-apps'], 'init': '{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }}'}, 'job="kubelet"': { 'replacement': 'job="kubelet", namespace=~"{{ $targetNamespace }}"', 'limitGroup': ['kubernetes-storage'], 'init': '{{- $targetNamespace := .Values.defaultRules.appNamespacesTarget }}'}, }几点实现细节值得注意:
limitGroup字段限定了替换仅发生在指定 group 内(如appNamespacesTarget只作用于kubernetes-apps与kubernetes-storage两个组),防止误伤其他规则的job="kubelet"表达式;- 每次替换若带有
init,会累积进该文件头部的变量初始化行,保证替换出的变量在使用前已被定义; - 由于生成的是 Helm 模板,规则表达式中的
{{/}}会与 Helm 语法冲突,escape()函数通过{{→{{{{` 的方式转义,避免模板渲染时被误解析。
2.5 输出模板的标准头
每个生成文件的头部由header模板字符串统一渲染,包含生成来源注释、Kubernetes 版本判断、defaultRules.create与 group 条件、资源元数据(name / namespace / labels / annotations),以及 PrometheusRule 的spec.groups起始标记。其中资源名通过printf "%s-%s" (include "prometheus-operator.fullname" .) "<group名>" | trunc 63 | trimSuffix "-"生成,自动规避 Kubernetes 名称 63 字符上限。文件尾部统一追加{{- end }}收尾,与头部的{{- if }}配对。
三、sync_grafana_dashboards.py:Grafana 看板同步脚本
3.1 脚本职责与数据源
sync_grafana_dashboards.py 与规则脚本是同一设计思路的姊妹实现,职责为Fetch dashboards from provided urls into this chart。数据源与版本分桶策略完全对齐:
charts = [ { 'source': 'https://raw.githubusercontent.com/coreos/kube-prometheus/master/manifests/grafana-dashboardDefinitions.yaml', 'destination': '../templates/grafana/dashboards-1.14', 'type': 'yaml', 'min_kubernetes': '1.14.0-0' }, { 'source': 'https://raw.githubusercontent.com/etcd-io/etcd/master/Documentation/op-guide/grafana.json', 'destination': '../templates/grafana/dashboards-1.14', 'type': 'json', 'min_kubernetes': '1.14.0-0' }, ... ]与规则脚本相比,它多了一个type字段,用于区分两类上游格式:
- yaml(kube-prometheus):
grafana-dashboardDefinitions.yaml是items数组结构,每项data下以看板名.json为 key 存放看板 JSON 字符串,脚本取resource.replace('.json', '')作为模板文件名; - json(etcd):
grafana.json可能是完整看板结构,也可能是嵌套的看板名 → 内容字典。脚本通过bool(json_text.get('annotations'))探测是否为扁平结构:若是完整看板则直接用源文件名命名,否则遍历字典逐项拆分。
3.2 看板级条件开关
看板同样按需开关,condition_map将看板名映射到组件开关:
| 看板名 | 条件 |
|---|---|
grafana-coredns-k8s | .Values.coreDns.enabled |
etcd | .Values.kubeEtcd.enabled |
apiserver | .Values.kubeApiServer.enabled |
controller-manager | .Values.kubeControllerManager.enabled |
kubelet | .Values.kubelet.enabled |
proxy | .Values.kubeProxy.enabled |
scheduler | .Values.kubeScheduler.enabled |
node-rsrc-use/node-cluster-rsrc-use | .Values.nodeExporter.enabled |
prometheus-remote-write | .Values.prometheus.prometheusSpec.remoteWriteDashboards |
生成文件为ConfigMap模板,头部渲染条件为版本 +.Values.grafana.enabled+.Values.grafana.defaultDashboardsEnabled+ 组件开关的组合:
{{- if and (semverCompare ">=%(min_kubernetes)s" $kubeTargetVersion) (semverCompare "<%(max_kubernetes)s" $kubeTargetVersion) .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled%(condition)s }}ConfigMap 的 data 字段以看板名.json: |-字面量形式内嵌完整看板 JSON,并通过grafana.sidecar.dashboards.label标签(默认值为1)供 Grafana sidecar 自动发现加载。产物目录为 templates/grafana/dashboards-1.14,其中包含apiserver.yaml、kubelet.yaml、node-rsrc-use.yaml、prometheus-remote-write.yaml等 20 余个看板模板。
3.3 唯一的「本仓库维护」例外:CoreDNS 看板
README 特别强调:k8s-coredns.yaml 是唯一一个由本仓库直接维护、无需走导入流程即可直接修改的看板。该文件头部明确写着Added manually, can be changed in-place,与其余文件头部的Generated from ... Do not change in-place!形成鲜明对比。需要自定义 CoreDNS 监控看板时,直接编辑该文件即可;而修改其他看板必须遵循上游流程(见下一节),避免下次同步时改动被覆盖。
四、上游规则更新流程:从 kubernetes-mixin 到本仓库
README 给出了两条完整的「上游维护 → 同步导入」流水线,这是理解整个 hack 机制的关键。
4.1 kube-prometheus 规则与看板
kube-prometheus 的规则和看板实际源自 kubernetes-mixin 项目(jsonnet 编写的监控配置),因此修改需要逐级向上提交:
- 在
kubernetes-mixin的 master 或 release 分支提交规则/看板修改(修改位于其rules与dashboards目录); - 在你自己 fork 的
coreos/kube-prometheus仓库中运行导入,将 mixin 变更编译为最终的prometheus-rules.yaml/grafana-dashboardDefinitions.yaml:
jb update make generate-in-docker- 将导入结果以 PR 形式合入
coreos/kube-prometheus的 master 或 release 分支; - 在本仓库的 fork 中运行
sync_prometheus_rules.py(或sync_grafana_dashboards.py)拉取更新后的上游文件; - 将脚本生成的变更以 PR 形式提交到本仓库。
4.2 etcd 规则与看板
etcd 的规则与看板由 etcd-io/etcd 官方维护,路径为Documentation/op-guide/etcd3_alert.rules.yml与Documentation/op-guide/grafana.json。修改流程更短:
- 向 etcd 仓库提交并合入 PR;
- 在本仓库 fork 中运行
sync_prometheus_rules.py/sync_grafana_dashboards.py; - 将变更以 PR 提交到本仓库。
4.3 小结:两条流水线对比
| 环节 | kube-prometheus(规则/看板) | etcd(规则/看板) |
|---|---|---|
| 上游根来源 | kubernetes-mixin(jsonnet) | etcd 官方仓库(yml/json) |
| 编译/导入 | jb update+make generate-in-docker(在 kube-prometheus fork 中) | 无 |
| 中间载体 | kube-prometheus 的manifests/prometheus-rules.yaml、grafana-dashboardDefinitions.yaml | Documentation/op-guide/下文件 |
| 本仓库同步 | 运行sync_prometheus_rules.py/sync_grafana_dashboards.py | 同左 |
| 提交方式 | PR 至本仓库 | 同左 |
五、生成产物如何被 Chart 消费:defaultRules 配置速查
同步脚本的最终产物是templates/prometheus/rules-1.14与templates/grafana/dashboards-1.14下的模板文件,而它们是否渲染、渲染哪些组,全部由 values.yaml 中的defaultRules段落控制(见该文件第 29 行起):
defaultRules: create: true rules: alertmanager: true etcd: true general: true k8s: true kubeApiserver: true kubeApiserverAvailability: true kubeApiserverError: true kubeApiserverSlos: true kubelet: true kubePrometheusGeneral: true kubePrometheusNodeAlerting: true kubePrometheusNodeRecording: true kubernetesAbsent: true kubernetesApps: true kubernetesResources: true kubernetesStorage: true kubernetesSystem: true kubeScheduler: true kubeStateMetrics: true network: true node: true prometheus: true prometheusOperator: true time: true ## Runbook url prefix for default rules runbookUrl: https://github.com/kubernetes-monitoring/kubernetes-mixin/tree/master/runbook.md# ## Reduce app namespace alert scope appNamespacesTarget: ".*" ## Labels for default rules labels: {} ## Annotations for default rules annotations: {}实际使用要点:
defaultRules.create: false可整体关闭所有内置规则,只保留自定义规则;- 各
rules.*子开关与脚本condition_map一一对应,按需裁剪(例如不需要节点告警可设node: false); runbookUrl会被替换进告警的 runbook 链接,默认指向 kubernetes-mixin 的 runbook 文档;appNamespacesTarget(默认.*)配合limitGroup机制,用于收窄kubernetes-apps、kubernetes-storage两组规则中job="kube-state-metrics"、job="kubelet"的匹配命名空间范围;labels/annotations会透传到所有生成的 PrometheusRule 上。
此外,Chart 还支持通过additionalPrometheusRules直接提供自定义规则(见 values.yaml 第 67-75 行示例),这部分内容不会被同步脚本覆盖。
六、本地验证:minikube 一键环境
为验证同步产物与整个 Chart 在真实集群中的表现,hack 目录提供了完整的 minikube 测试方案,说明见 minikube/README.md:使用 cmd.sh 依次执行命令,即可搭建本地可用集群并 hack 出一份可用的 etcd 抓取配置。
6.1 命令清单
脚本支持五个子命令(按 README 建议的序列执行):
| 命令 | 作用 |
|---|---|
reset-minikube | 删除并重建 minikube,使用适合运行 Prometheus Operator 的配置 |
init-helm | 初始化 Helm 并更新仓库,仅在每次 minikube 重建后执行一次 |
init-etcd-secret | 从 API Server 中提取 etcd 证书,在 monitoring 命名空间创建etcd-certsSecret |
prometheus-operator | 安装或升级 prometheus-operator Chart |
port-forward | 转发 Prometheus(9090)、Alertmanager(9093)、Grafana(3000) 端口 |
核心命令使用示例:
./stable/prometheus-operator/hack/minikube/cmd.sh reset-minikube ./stable/prometheus-operator/hack/minikube/cmd.sh init-helm ./stable/prometheus-operator/hack/minikube/cmd.sh init-etcd-secret ./stable/prometheus-operator/hack/minikube/cmd.sh prometheus-operator ./stable/prometheus-operator/hack/minikube/cmd.sh port-forward6.2 关键设计点解读
- minikube 启动参数:
reset-minikube使用--kubernetes-version=v1.13.3、--memory=4096,并额外注入kubelet.authentication-token-webhook=true、kubelet.authorization-mode=Webhook、scheduler.address=0.0.0.0、controller-manager.address=0.0.0.0,原因是默认安装方式无法抓取 kubelet、scheduler、controller-manager 组件(脚本帮助文本中的原话),这些参数正是为了让各组件监听地址与抓取路径可达;脚本中保留了 Windows 下--vm-driver hyperv的注释示例,Windows 用户需自行取消注释启用。 - etcd 证书注入:
init-etcd-secret通过kubectl exec进入kube-apiserver-minikube容器,读取/var/lib/minikube/certs/下的etcd/ca.crt、apiserver-etcd-client.crt、apiserver-etcd-client.key,生成名为etcd-certs的 Secret。README 特别警告:该 Secret 缺失时 Prometheus 将无法启动。 - 安装命令细节:
prometheus-operator使用helm upgrade --install并搭配--set grafana.podAnnotations.redeploy-hack="$(cat /proc/sys/kernel/random/uuid)",每次安装注入随机 annotation 强制触发 Grafana 滚动更新,确保看板 sidecar 重新加载最新配置。 - 专用 values:minikube/values.yaml 将
etcd-certsSecret 挂载进 Prometheus,并把kubeEtcd.serviceMonitor的抓取协议切换为 HTTPS、指定 CA/证书/密钥文件路径:
prometheus: prometheusSpec: secrets: [etcd-certs] kubeEtcd: serviceMonitor: scheme: https caFile: /etc/prometheus/secrets/etcd-certs/ca.crt certFile: /etc/prometheus/secrets/etcd-certs/client.crt keyFile: /etc/prometheus/secrets/etcd-certs/client.key- 端口验证:
port-forward命令打通三个服务后,即可在浏览器分别访问localhost:9090(Prometheus)、localhost:9093(Alertmanager)、localhost:3000(Grafana,默认账号密码见 Chart 文档)检查规则加载、告警状态与看板渲染效果。
七、小结:维护者视角的工作流全景
把以上内容串起来,可以得到本仓库监控资产维护的完整闭环:
- 上游变更:规则/看板修改首先落在 kubernetes-mixin 或 etcd 官方仓库(通过
jb update+make generate-in-docker编译中间产物); - 本仓库同步:在 fork 中运行 sync_prometheus_rules.py 与 sync_grafana_dashboards.py,脚本按 group/看板名拆分文件、附加版本与组件开关条件、替换硬编码标签并转义 Helm 语法,最终以 PR 合入本仓库;
- 用户消费:用户通过 values.yaml 的
defaultRules.rules.*开关按需裁剪内置规则,通过grafana.defaultDashboardsEnabled控制看板装载;如需定制 CoreDNS 看板,可直接修改唯一的例外文件 k8s-coredns.yaml; - 本地验证:开发者使用 minikube/cmd.sh 复现上述全流程,在本地集群中确认规则生效、告警可达、看板正常。
这套机制的价值在于:监控资产的「权威来源」始终是上游社区,Chart 仓库只负责版本化、条件化与打包,既避免了大量 YAML/JSON 的重复维护,又通过condition_map等机制让用户拥有充分的裁剪自由度——这正是 Prometheus Operator Chart 能持续跟随社区演进的重要工程基础。
【免费下载链接】charts
⚠️(OBSOLETE) Curated applications for Kubernetes
相关推荐
TemplateStudio模板同步机制:LocalTemplatesSource与VsixTemplatesSource的工作原理
TemplateStudio模板同步机制:LocalTemplatesSource与VsixTemplatesSource的工作原理 TemplateStudi
gsd-core 的 Archived Changeset 归档机制:如何安全留存已发布版本的 CHANGELOG 片段
gsd core 的 Archived Changeset 归档机制:如何安全留存已发布版本的 CHANGELOG 片段 导读 本文讲解 gsd core 仓库
Dism++ 通用安装脚本 sut:离线系统原生整合的原理、制作流程与规则定制指南
Dism++ 通用安装脚本 sut:离线系统原生整合的原理、制作流程与规则定制指南 sut 是 Dism++ 提供的一套通用安装脚本体系,用于把软件以 原生整合
后端文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考