Kubernetes に Prometheus Operator を導入する
このあたりを参考に Prometheus Operator を導入する
進め方としては
kube-prometheus-stack helm で install する
その後 go の簡単なアプリを書いて prometheus で監視してみる
misskey に対応させる
でいく
kube-prometheus-stack helm で install する
kube-prometheus-stack の CRD がでかすぎて通常の install ができない
そのため、 ServerSideApply=true にする.
これによって、このリソースを「ArgoCD」のみにして、前回のマニフェストを持たなくて良くなる。
また、 nodePort の設定は helm.valueObject で書いている
code: kube-prometheus-stack.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: kube-prometheus-stack-application
spec:
destination:
namespace: monitoring
project: default
source:
targetRevision: 65.2.0
helm:
valuesObject:
prometheus:
service:
type: NodePort
nodePort: 30090
grafana:
service:
type: NodePort
nodePort: 30091
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
サンプル go アプリをデプロイして、計測する
上記を参考に、シンプルな go アプリ(/ が叩かれたら counter を 1 増やす)を作成して、イメージを DockerHub にあげる。
上記を deployment, svc として prometheus-sample-go namespace にデプロイする。
そして、上記の go アプリを監視する ServiceMonitor リソースを prometheus-sample-go に配置した。
monitoring namespace の kube-prometheus-stack は helm chart であるため、そこに prometheus-sampole-go の ServiceMonitor を挟み込むのはめんどくさそうだった。
そのため、 各種アプリケーション namespace 配下に ServiceMonitor などを配置するようにする。
heml のデフォルト設定では、すべての namespace の serviceMonitor を監視するようになっている。
ただし、なぜか serviceMonitorSelector は自動で kube-prometheus-stack デプロイ時の名前がついているため、ServiceMonitor 側にその labels 指定を付ける必要がある。
kubectl -n monitoring get prometheuses.monitoring.coreos.com kube-prometheus-stack-appl-prometheus -o yaml
code: servicemonitor.yaml
# ↑ 参考例
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: service-monitor
labels:
# ❯ kubectl -n monitoring get prometheuses.monitoring.coreos.com kube-prometheus-stack-appl-prometheus -o yaml
# prometheus.spec.serviceMonitorSelector.matchLabels が release: kube-prometheus-stack-application を指定している
# そのため、各 namespace の カスタム ServiceMonitor を設定した場合は labels に上記を指定して監視対象にする必要がある
release: kube-prometheus-stack-application
spec:
# service 側に labels を設定する必要がある
selector:
matchLabels:
app: sample-go-svc
endpoints:
- port: http
path: /metrics
interval: 30s
code: service.yaml
apiVersion: v1
kind: Service
metadata:
name: svc
# serviceMonitor.spec.selector の matchLabels で引っかかるように
# こちらにラベルを設定する必要がある
labels:
app: sample-go-svc
spec:
type: NodePort
selector:
app: sample-go
ports:
- name: http
protocol: TCP
# k8s クラスタ内の clusterIP port
port: 8081
# 8080 が go アプリ内部で待ち受けているポート
targetPort: 8080
nodePort: 30099
設定ファイルを見たい場合は kubectl get secrets -n monitoring prometheus-kube-prometheus-stack-appl-prometheus -o jsonpath="{.data['prometheus\.yaml\.gz']}" | base64 -d | gunzip で
secrets に格納されている prometheus.yaml を確認すればよい。
もしくは http://ganyariya-ubuntu.local:30090/config のように prometheus の config ページをみるとよい。
https://scrapbox.io/files/671487e0c76fcf7b0e2fff1c.png
AlertRule を確認する
アラートルールがなにかについては上記にメモしました。
以下のように書くことでアラートルールを追加できる
code:yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: prometheus-rule
labels:
# prometheus が発見してくれるように labels を設定する
release: kube-prometheus-stack-application
spec:
groups:
- name: sample-go-frequently-access
rules:
# alert とつけた場合はアラートルールになる
# record とつけた場合は recording rule になる
- alert: SampleGoFrequentlyAccess
annotations:
summary: "アクセスしすぎ"
message: "sample-go にアクセスしすぎ"
for: 1m
labels:
severity: critical
expr: increase(ganyariya_sample_http_request_total{path="/"}1m) >= 10 https://scrapbox.io/files/67148890bbd5dfeaa8e42f62.png
AlertManagerConfig を設定する
helm の values.yaml から設定できる。
route はデフォルトルート設定で, その中で特殊な routes を設定する(なんで route のなかに routes を置いたんだ... route と routes を同じ階層にする && route の命名を defaultRoute とかにすればわかりやすそうですが...)
receiver で slack 設定を入れる。
code:yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: kube-prometheus-stack-application
spec:
source:
targetRevision: 65.2.0
helm:
valuesObject:
prometheus:
service:
type: NodePort
nodePort: 30090
grafana:
service:
type: NodePort
nodePort: 30091
alertmanager:
service:
type: NodePort
nodePort: 30092
config:
# デフォルト値をそのまま持ってくる
global:
resolve_timeout: 5m
inhibit_rules:
- source_matchers:
- "severity = critical"
target_matchers:
- "severity =~ warning|info"
equal:
- "namespace"
- "alertname"
- source_matchers:
- "severity = warning"
target_matchers:
- "severity = info"
equal:
- "namespace"
- "alertname"
- source_matchers:
- "alertname = InfoInhibitor"
target_matchers:
- "severity = info"
equal:
- "namespace"
- target_matchers:
- "alertname = InfoInhibitor"
# デフォルトルート設定
route:
# namespace 単位でアラートをグループする
group_wait: 30s
group_interval: 5m
repeat_interval: 12h
receiver: "default"
# 個別ルート設定
routes:
- receiver: "null"
matchers:
# watchdog は常にアラートされるので無視する
- name: alertname
value: "Watchdog"
matchType: "="
# レシーバ設定
receivers:
- name: "default"
slack_configs:
- send_resolved: true
# slack incomming webhook url
channel: "#main"
# alertRule 側の annotations で定義された summary, message を引っ張ってくる
title: "{{ range .Alerts }}{{ .Annotations.summary }}\n{{ end }}"
text: "{{ range .Alerts }}{{ .Annotations.message }}\n{{ end }}"
- name: "null"
destination:
namespace: monitoring
Loki + promtail を設定する
loki, promtail それぞれ単体の helm をインストールしようとしたが、 loki 内の loki-frontend-query がうまく動作しなかったので loki-stack にした。
loki-stack はコミュニティが管理している helm であり、 loki + promtail を簡単にセットアップできる。
grafana + fluent-bit もインストールできるが、デフォルトでは enabled:false になっているため kube-prometheus-stack とコンフリクトしない
Loki がログを集約するシステムがあり、 promtail が各ノードごとに配置される daemonset agent.
code:yaml
❯ kubectl kustomize tools/overlays/helm/loki-stack
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: loki-stack-application
spec:
destination:
namespace: monitoring
project: default
source:
chart: loki-stack
targetRevision: 2.10.2
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
https://scrapbox.io/files/671cdfb93bb8676777eba8fc.png
Save&Test がなんかうまくいかないけど、ちゃんと設定できてる(なぜ...??)
https://scrapbox.io/files/671cdfd5a825842ca6571721.png
各コンテナ・Pod のログがちゃんと取れる && ラベルもついていてとても便利
設定ファイルは secret に入っている。
code: yaml
❯ kubectl get secret -n monitoring loki-stack-application -o=jsonpath='{.data.loki\.yaml}' | base64 --decode
auth_enabled: false
chunk_store_config:
max_look_back_period: 0s
compactor:
shared_store: filesystem
working_directory: /data/loki/boltdb-shipper-compactor
ingester:
chunk_block_size: 262144
chunk_idle_period: 3m
chunk_retain_period: 1m
lifecycler:
ring:
replication_factor: 1
max_transfer_retries: 0
wal:
dir: /data/loki/wal
limits_config:
enforce_metric_name: false
max_entries_limit_per_query: 5000
reject_old_samples: true
reject_old_samples_max_age: 168h
memberlist:
join_members:
- 'loki-stack-application-memberlist'
schema_config:
configs:
- from: "2020-10-24"
index:
period: 24h
prefix: index_
object_store: filesystem
schema: v11
store: boltdb-shipper
server:
grpc_listen_port: 9095
http_listen_port: 3100
storage_config:
boltdb_shipper:
active_index_directory: /data/loki/boltdb-shipper-active
cache_location: /data/loki/boltdb-shipper-cache
cache_ttl: 24h
shared_store: filesystem
filesystem:
directory: /data/loki/chunks
table_manager:
retention_deletes_enabled: false
retention_period: 0s%
code:yaml
❯ kubectl get secret -n monitoring loki-stack-application-promtail -o=jsonpath='{.data.promtail\.yaml}' | base64 --decode
server:
log_level: info
log_format: logfmt
http_listen_port: 3101
clients:
positions:
filename: /run/promtail/positions.yaml
scrape_configs:
- job_name: kubernetes-pods
pipeline_stages:
- cri: {}
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels:
- __meta_kubernetes_pod_controller_name
action: replace
target_label: __tmp_controller_name
- source_labels:
- __meta_kubernetes_pod_label_app_kubernetes_io_name
- __meta_kubernetes_pod_label_app
- __tmp_controller_name
- __meta_kubernetes_pod_name
action: replace
target_label: app
- source_labels:
- __meta_kubernetes_pod_label_app_kubernetes_io_instance
- __meta_kubernetes_pod_label_instance
action: replace
target_label: instance
- source_labels:
- __meta_kubernetes_pod_label_app_kubernetes_io_component
- __meta_kubernetes_pod_label_component
action: replace
target_label: component
- action: replace
source_labels:
- __meta_kubernetes_pod_node_name
target_label: node_name
- action: replace
source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- action: replace
replacement: $1
separator: /
source_labels:
- namespace
- app
target_label: job
- action: replace
source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- action: replace
source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- action: replace
replacement: /var/log/pods/*$1/*.log
separator: /
source_labels:
- __meta_kubernetes_pod_uid
- __meta_kubernetes_pod_container_name
target_label: __path__
- action: replace
regex: true/(.*)
replacement: /var/log/pods/*$1/*.log
separator: /
source_labels:
- __meta_kubernetes_pod_annotationpresent_kubernetes_io_config_hash
- __meta_kubernetes_pod_annotation_kubernetes_io_config_hash
- __meta_kubernetes_pod_container_name
target_label: __path__
limits_config:
tracing:
enabled: false