定制 Openshift 3.11 监控系统 Cluster Monitoring Operator

本文介绍如何对 Openshift (OCP/OKD) 3.11 的监控系统 cluster monitoring operator 进行简单定制, 扩展平台监控的范围.

Cluster Monitoring Operator 介绍

Openshift 3.11 以及后续的 4.x 平台都使用预定义配置的 cluster monitoring operator 来做平台监控. Cluster monitoring operator 管理 prometheus operator, grafana, kube-state-metrics 和 node-exporter. 而 prometheus operator 再负责管理 prometheus 和 alertmanager. 各组件之间的关系如下图所示:

通过检查 prometheus 的配置可以发现其 scrape 对象包括

  • prometheus
  • prometheus operator
  • cluster monitoring operator
  • alertmanager
  • kubernete apiserver
  • kubelet
  • kube-controller
  • kube-state-metrics
  • node-exporter
  • etcd (可选择启用)

对于一个中小型 Openshift 集群的平台层面 (不包含应用特定 metrics), 用这些对象的 metrics 来做平台监控其实也差不多够用了. 然而 Openshift 监控套件的预定义配置并没有覆盖非系统级的 namespace.

举个例子, 我的应用 pod 跑在 myproj project/namespace 下. 虽然 kube-state-metrics 会收集 myproj 名字空间下资源 (deployment/statefulset/pod) 的状态信息, 但是预定义的 alert rules 只选取 openshift-.\*|kube-.\*|default|logging 这些 namespace 的 metrics 来进行评估. 导致的结果是: 虽然收集了应用 namespace 下的资源状态信息, 却无法实现告警.

遗憾的是 Openshift 并不支持用户扩展其平台监控套装的监控范围. 文档原文如下

Explicitly unsupported cases include:

  • Creating additional ServiceMonitor objects in the openshift-monitoring namespace, thereby extending the targets the cluster monitoring Prometheus instance scrapes. This can cause collisions and load differences that cannot be accounted for, therefore the Prometheus setup can be unstable.
  • Creating additional ConfigMap objects, that cause the cluster monitoring Prometheus instance to include additional alerting and recording rules. Note that this behavior is known to cause a breaking behavior if applied, as Prometheus 2.0 will ship with a new rule file syntax.

如果想让监控覆盖到用户的 namespace, RedHat 给出的建议是另外单独部署 prometheus 套件. 对于大型集群, 这可能是一个合理的建议. 但是对于一个小型集群, 如果本身就只有几个用户级别的 namespace, 总共十几或几十个 pod, 你让我再单独来一套 prometheus? 实在是很蛋疼.

如果你使用的是订阅版本的 Openshift Container Platform, 为了避免维保/技术支持的麻烦, 请遵循 RedHat 的建议. 如果你使用的是社区版本的 OKD, 可以继续往下看: 如何改造 cluster monitoring operator 来满足定制化需求.

定制化方案

需求

下面这些应该是非常基本的定制化需求

  • 调整部分默认告警规则的覆盖范围. 例如 KubePodNotReady, 除了覆盖系统级别的 namespace, 还需要覆盖所有应用 namespace
  • 调整部分默认告警规则的触发状态持续时间, 像 KubePodCrashLooping, KubeNodeNotReady 默认设置状态持续 1h 才会触发告警, 黄花菜都凉了吧
  • 调整默认 target scrape interval. 例如调整 kube-state-metrics 的刮取间隔为 1m
  • 添加自定义告警规则
  • 添加自定义 service monitor 来包含用户应用

再次吐槽 RedHat 的产品, 经常弄一些跟玩具一样的东西出来, 性能/稳定性/扩展性/可定制性上有诸多限制. 类似的还有 Openshift 平台的 EFK 日志系统, Openshift 3 的 IPSec 方案 (经过生产验证了吗? 就敢往文档里面写? #185) 等, 我就不一一点了

添加自定义配置

上面需求中的第四和第五项属于添加自定义配置, 比较容易实现.

Prometheus 规则和监控 target 配置都是通过自定义资源 (Custom Resource) 来管理

  • prometheusrules.monitoring.coreos.com 类型资源 针对 prometheus rules
  • servicemonitors.monitoring.coreos.com 类型资源针对 target 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
oc get prometheusrules.monitoring.coreos.com
NAME AGE
prometheus-k8s-rules 1d

oc get servicemonitors.monitoring.coreos.com
NAME AGE
alertmanager 1d
cluster-monitoring-operator 1d
kube-apiserver 1d
kube-controllers 1d
kube-state-metrics 1d
kubelet 1d
node-exporter 1d
prometheus 1d
prometheus-operator 1d

如果需要添加自定义规则和自定义监控目标, 创建相应的 CR 即可. 不过要注意, 不要试图修改默认 CR 来实现自定义配置, 具体原因后面会分析.

修改默认配置

需求中的 1-3 项属于修改默认配置. 如果尝试修改默认 CR, 你会发现你的更改会被 cluster monitoring operator 自动重置. 一个很自然的想法是能不能重新构建 cluster monitoring operator 镜像, 覆盖掉这些默认 CR 的配置文件来实现需求?

1
2
3
4
# 获取 cluster monitoring operator 源代码
go get -u github.com/openshift/cluster-monitoring-operator/...
cd $GOPATH/src/github.com/openshift/cluster-monitoring-operator/
git checkout release-3.11

简单检查一下 cluster monitoring operator 的源码就可以发现其实并不可行, 原因是这些预定义配置文件会被 go-bindata 用来生成 go 代码, 最终会成为 operator binary 的一部分. 即这些配置文件 "固化" 在二进制文件中了. 我猜想这也是 RedHat 不提供针对 cluster monitoring operator 定制化配置的原因之一.

查看Makefile可以大致了解: ${ASSERTS} 这个目标会执行 ./hack/build-jsonnet.sh来产生所有预定义配置, 而 pkg/manifests/bindata.go 这个目标会利用预定义配置生成 go 代码. 因此只需要修改 ./hack/build-jsonnet.sh 脚本替换预定义配置即可实现需求.

hack目录下建立路径来存放需要定制的配置文件. 把预定义文件复制过来, 然后按照需要修改

1
2
3
mkdir -p hack/customization/assets/{prometheus-k8s,kube-state-metrics}
cp assets/prometheus-k8s/rules.yaml hack/customization/assets/prometheus-k8s/rules.yaml
cp assets/kube-state-metrics/service-monitor.yaml hack/customization/assets/kube-state-metrics/service-monitor.yaml

需求三修改 kube-state-metrics target 的刮取时间间隔需要修改service-monitor.yaml的 interval 字段.

需求一和二修改默认告警规则触发的状态持续时间和 namespace 覆盖范围需要修改rules.yaml中 alert rule 的定义. 例如我调整了下面告警的状态持续时间, 并且将原来针对系统级 namepace 的过滤条件删除:

  • kube-state-metrics job 相关
    • KubePodCrashLooping
    • KubePodNotReady
    • KubeDeploymentGenerationMismatch
    • KubeDeploymentReplicasMismatch
    • KubeStatefulSetReplicasMismatch
    • KubeStatefulSetGenerationMismatch
    • KubeDaemonSetRolloutStuck
    • KubeDaemonSetNotScheduled
    • KubeDaemonSetMisScheduled
    • KubeCPUOvercommit
    • KubeMemOvercommit
    • KubeQuotaExceeded
    • KubeNodeNotReady
  • kubelet job 相关
    • KubeletDown
  • node-export job 相关
    • NodeExportDown
  • 其他
    • TargetDown

然后修改hack/build-jsonnet.sh文件, 添加脚本代码用自定义配置替换默认配置

1
2
3
4
5
6
7
8
9
...
done

# hack: my customized files
cat hack/customization/assets/prometheus-k8s/rules.yaml > assets/prometheus-k8s/rules.yaml
cat hack/customization/assets/kube-state-metrics/service-monitor.yaml > assets/kube-state-metrics/service-monitor.yaml

# These manifests are generated by kube-prmoetheus, but are not necessary in
...

构建定制化镜像

1
2
3
4
5
6
7
# build operator binary
make generate
make crossbuild

# build image and push
docker build -t quay.svc.vopsdev.com/openshift3/ose-cluster-monitoring-operator:v3.11-rev1 .
docker push quay.svc.vopsdev.com/openshift3/ose-cluster-monitoring-operator:v3.11-rev1

测试

在 inventory 文件中通过openshift_cluster_monitoring_operator_image参数指定定制镜像 quay.svc.vopsdev.com/openshift3/ose-cluster-monitoring-operator:v3.11-rev1. 重新部署集群监控套装. 部署完成后, 创建 CR 添加自定义告警规则和监控对象

1
2
3
4
ansible-playbook -i inventory playbooks/openshift-monitoring/config.yml

oc apply -f customized-servicemonitor.yaml -n openshift-monitoring
oc apply -f customized-rules.yaml -n openshift-monitoring

登录 prometheus 界面确认自定义配置已经生效

  1. 调整 kube-state-metrics 的 metrics 收集周期:

  2. 扩展默认告警规则到所有 namespace 并调整持续时间:

  3. 自定义 target 配置:

  4. 自定义告警规则