Alertmanagerでk8sクラスタの障害を通知する
Table of Contents
以前導入したkube-prometehus-stackに含まれるAlertmanagerを使って、k8sに起こった障害をメールで通知する
はじめに
以前の記事では、kube-prometheus-stack
というk8sの監視で役立つサービスをまとめてデプロイできるhelm chartを利用して、k8sのシステム監視を導入した。
今回は、このkube-prometheus-stack
に含まれるAlertmanagerを有効化して、システムの障害をメール通知する設定を行う。
PrometheusのコンソールでAlertの項目を眺めていたところエラーを見つけたので、まずはその対処から始めていく。
Prometheus上でエラーが出ていた件
PrometheusのコンソールからAlertの項目を確認すると、下記ののAlertがFiring状態になっていた。
- etcdMembersDown
- etcdInsufficientMembers
- KubeControllerManagerDown
- KubeProxyDown
- KubeSchedulerDown
因みに下記のAlertはFiring状態でも問題ない。
- Watchdog
- InfoInhibitor
Prometheusのコンソールから「Status」→「Targets」と進むと下記のエラーが出ており、どうやら各種エンドポイントに対して疎通が取れていないことが原因のようだ。
GitHubのIssueを調べていたら、ピンポイントのコメントを見つけたので、これらを参考に対応していく。
[prometheus-kube-stack] Target Kubelet 0/0 up and others are down · Issue #204 · prometheus-community/helm-charts
[kube-prometheus-stack] KubeScheduler & Etcd & CubeController-Manager Targets Down - Prometheus Operator · Issue #1966 · prometheus-community/helm-charts
原因はこれらサービスがローカルループバックのみにbindしていて、外部からアクセスできないということらしい。
etcd/kube-controller-manager/kube-scheduler
control planeにSSHログインし、下記のファイルのbind-address/listen-metrics-urlsとlivenessProbe/startupProbeのhostアドレスを0.0.0.0に変更する。
- /etc/kubernetes/manifests/kube-controller-manager.yaml
- /etc/kubernetes/manifests/kube-scheduler.yaml
- /etc/kubernetes/manifests/etcd.yaml
以下、kube-controller-manager.yaml
とetcd.yaml
の書き換え例
spec:
containers:
- command:
...
- --bind-address=0.0.0.0
...
livenessProbe:
failureThreshold: 8
httpGet:
host: 0.0.0.0
path: /healthz
port: 10257
scheme: HTTPS
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
name: kube-controller-manager
resources:
requests:
cpu: 200m
startupProbe:
failureThreshold: 24
httpGet:
host: 0.0.0.0
path: /healthz
port: 10257
scheme: HTTPS
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
spec:
containers:
- command:
...
- --listen-metrics-urls=http://0.0.0.0:2381
...
livenessProbe:
failureThreshold: 8
httpGet:
host: 0.0.0.0
path: /health?exclude=NOSPACE&serializable=true
port: 2381
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
name: etcd
resources:
requests:
cpu: 100m
memory: 100Mi
startupProbe:
failureThreshold: 24
httpGet:
host: 0.0.0.0
path: /health?serializable=false
port: 2381
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
kube-proxy
kubectl edit cm/kube-proxy -n kube-system
エディタが立ち上がるので、metricsBindAddress
を0.0.0.0:10249
に変更後
kubectl delete pod -l k8s-app=kube-proxy -n kube-system
とすると、再度kube-proxyが立ち上がってくるので待つ。
ここまでで、先程出ていたエラーは解決しているはず。
手順
ここから、Alertmanagerの設定をしていく。 とは言っても、values弄って変更を適用するだけ。
helmの変数定義
alertmanager:
## Deploy alertmanager
##
enabled: true
...
config:
global:
resolve_timeout: 5m
smtp_smarthost: 'sample.com:465'
smtp_from: 'alertmanager@sample.com'
smtp_auth_username: 'alertmanager@sample.com'
smtp_auth_password: 'xxx'
smtp_require_tls: false
...
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 24h
receiver: alert-email
...
receivers:
- name: 'alert-email'
email_configs:
- to: 'xxx@sample.com'
...
replicas: 2
適用。リリース名とnamespaceはお使いの環境に合わせて。
helm upgrade -f values-monitoring.yaml kube-prometheus-stack prometheus-community/kube-prometheus-stack -n monitoring
レプリカ数を2としている理由は後述。
Alertmanagerがdisabled表示されてしまう
NodePortなりで公開後にAlertmanagerのコンソールにアクセスすると、Cluster Statusがdisabledとなっていた。
Alertmanager Cluster Status is Disabled · Issue #1452 · prometheus-community/helm-charts
どうやらレプリカ数が2以上(冗長化構成)でないと、ここがdisabledになるらしい。まあ折角なので冗長化することにした。
通知が重複してしまう
Alertmanagerのレプリカ数を2にして、試しに以下のjobをcreateしてみたところ、同じ通知が2つ飛んできた。
apiVersion: batch/v1
kind: Job
metadata:
name: always-fail-job
spec:
template:
spec:
restartPolicy: Never
containers:
- name: always-fail-container
image: busybox
command: ["sh", "-c", "exit 1"]
backoffLimit: 0
Alertmanagerを冗長構成にして動作させるときは、それぞれのAlertmanagerに協調動作させるために、引数--cluster.peer
としてpeerの情報を入れてやる必要があるらしい。
helmでデプロイしている場合は、clusterDomain
としてその設定を差し込めるようだった。
...
## The clusterDomain value will be added to the cluster.peer option of the alertmanager.
## Without this specified option cluster.peer will have value alertmanager-monitoring-alertmanager-0.alertmanager-operated:9094 (default value)
## With this specified option cluster.peer will have value alertmanager-monitoring-alertmanager-0.alertmanager-operated.namespace.svc.cluster-domain:9094
clusterDomain: "cluster.local"
...
おわりに
kube-prometehus-stackのおかげで簡単に障害通知を行うことができた。
当然だが今回のような構成では、全てのPodが死んでしまうレベルの障害には気付けない。そのため実用上はSaaSの外形監視などを併用するのが良いと思う。
自分はブログとmisskeyのエンドポイントに対して、UptimeRobotというSaaSの死活監視で定期的にhttpの疎通確認をすることにした。ステータスは以下から確認でき、疎通が取れなくなると通知が飛んでくる。