在我们使用 kubernetes 的过程总经常会出现 pod 异常重启的情况。
pod 重启一般情况下分为 2 类,1 类是因为程序自身问题异常退出,另一种则是因为资源限制导致系统 OOMKilled 杀死。
在开发运维巡检系统的过程中就在考虑把 pod 异常重启的信息上报到系统里面存储展示,方便后期追溯和问题排查。
因为自己开发工作量比较大,所以就选择了 Github 上的开源项目进行二次开发。
这里选择的项目是 golang 开发的 https://github.com/airwallex/k8s-pod-restart-info-collector
k8s-pod-restart-info-collector
项目默认是上报重启信息到 slack
,slack 在国外使用的比较多,国内使用钉钉和飞书的比较多,所以这里对程序进行了二次开发。
二次开发
经过修改后,程序会监听 k8s pod 重启然后把重启信息上报到我们的运维巡检系统,巡检系统负责把数据写入 es 并发送报警到钉钉群组。当然你也可以直接把重启信息发送到钉钉群组,这里我因为要去匹配环境 label 信息达到报警屏蔽的目的。
- 扩展环境变量支持
Environment="IGNORE_RESTART_COUNT=300000"
Environment="CLUSTER_NAME= 开发 K8S 集群"
- IGNORE_RESTART_COUNT 此变量为忽略重启次数,也就是 pod 重启达到多少次之后便不在通知上报
- CLUSTER_NAME 为扩展名称,用于上报显示区分环境信息
- 扩展上报信息
因为需要写入 es,所以字段 key 展示加入了更多的信息展示。
核心修改 controller.go
# k8s node 主机获取
pod.Spec.NodeName
# 命名空间获取
pod.Namespace
# 获取总重启次数
func getPodRestartCount(pod *v1.Pod) int {
var restarts int = 0
for i := range pod.Status.ContainerStatuses {container := pod.Status.ContainerStatuses[i]
restarts += int(container.RestartCount)
}
return restarts
}
# 默认上报信息修改, 可以汉化为中文或加入自己的定制环境变量
msg := SlackMessage{Title: fmt.Sprintf("*Pod 重启!*\n*cluster: `%s`, pod: `%s`, namespace: `%s`*", c.alert.ClusterName, pod.Name, pod.Namespace),
Text: podStatus + podEvents + nodeEvents + containerLogs,
Footer: fmt.Sprintf("%s, %s, %s", c.alert.ClusterName, pod.Name, pod.Namespace),
}
# 对于 deploymentName 的获取判断
# 默认是没有上报 deploymentName 的,我们可以通过下面的方式去获取
var deploymentName string
// deployment 判断
if _, ok := pod.Labels["app"]; ok {deploymentName = pod.Labels["app"]
}
# 这种方法获取的前提是你 yaml 部署模板里面要携带你的服务名称,具体看自身业务定制
kibana 出图展示
对于问题排查我们可以查看重启时上报的日志信息
使用 systemd 去管理程序启动,通过环境变量去控制环境信息显示
[Unit]
Description=k8s-pod-restart
After=network.target
[Service]
Type=simple
Restart=always
RestartSec=5
User=root
Environment="IGNORE_RESTART_COUNT=300000"
Environment="CLUSTER_NAME= 开发 K8S 集群"
WorkingDirectory=/usr/local/k8s-pod-restart
ExecStart=/usr/local/k8s-pod-restart/k8s-pod-restart
Environment="RUN_ENV=dev"
[Install]
WantedBy=multi-user.target
k8s pod 重启信息钉钉机器人通知