はじめに
このブログではPrometheus のSLO generator であるSloth に関して取り上げたいと思っている。正直、業務後の深夜に書いているのでGrafana でDashboards を生成したら感動的なラストシーンということにしてほしい。今回は取り上げないが最近、バージョン1.0.0 になったOpenSLOの 周辺知識も気になっている。OpenSLOについて | フューチャー技術ブログ などはOpenSLOに関して2022 年5月現在で日本語で書かれている文章だと最高に良いと思います。
SLIを計測しSLOを設定する
いきなり、Slothの話をするのも流石に不親切なのでSRE的な話を少しだけします。ITサービスの運用に置いて、信頼性100%と、信頼性99.99%では大きな違いがあります。信頼性100%を実現するためには、99.99%とは異なり膨大な工数を投入する必要があるが、ほとんどのユーザーにとっては「99.999%」が「100%」になったからといって、大きなメリットがないことのほうが多いのである。つまり、100%を目指すことは効率的ではない場面が多いため、各サービスごとに適切な可用性を設定する必要だ。
はじめに、SLIですが、これは「Service Level indicator」の略で、提供されているサービスのレベルの性質を定義した計測量である。一般的には以下をSLIとして用いる。
- リクエストのレイテンシ(リクエストに対するレスポンスを返すまでにかかった時間)
- エラー率(受信したリクエストを正常に処理できなかった比率)
- システムスループット(単位時間あたりに処理できるリクエスト数)
- 可用性(サービスが利用できる時間の比率)
次に、SLOですが、これは「Service Level Objective」の略で、SLIで計測されるサービスレベルの目標値、または目標値の範囲を指します。例えば、SLOを「年99.99%」と設定すると、「1年のうち52分は稼働しなくてもよい」ということになる。例えば、「1年の間にサービスが30分停止する障害」が生じたとしても、SLOの範囲であればそれは想定の範囲であり、問題ではなくなる。
同様の用語で、SLA というのがある。これは「Service Level Agreement」の略で、こちらはITサービスの契約において「この稼働率を下回る場合、金銭的な保証を行う」ことを示す値です。SLIは測定値、SLOは補償を伴わない目標値である点で意味合いが異なる。
Sloth の特徴
で、Sloth はPrometheusベースのSLOを作成するために、複雑な仕様やプロセスを把握して使用する必要がないように。迅速、簡単、かつ信頼性の高いPrometheus SLO generator(生成)してくれる。生成された記録とアラートのルールに基づき、信頼性の高い均一なSLOの実装を実現します。Kubernetes でCRDなどを用いてサポートしており、OpenSLOも限定的にサポートしています。
Sloth が生成するPrometheusのルールは3つのカテゴリーに分類されます。1つ目がSLIです。SlothにおけるSLOはルールはベースとなるもので、ユーザーから提供されたクエリを使用して、エラーサービスレベル(可用性)が何であるかを示すために使用される値を取得するものです。異なる時間帯に対して複数のルールを作成し、これらの異なる結果がアラートに使用されます。2つ目がMetadataです。これらは、残りのエラーバジェットやSLO目標パーセントのような有益なメトリックとして使用されます。これらは、Grafanaダッシュボードなど、SLOの可視化に非常に便利です。3つ目がAlerts でSLIルールに基づくマルチウィンドウ・マルチバーンアラートです。Sloth はサービスレベル仕様書を受け取り、仕様書の各SLOについて、上記のカテゴリーで3つのルールグループを作成します。
Metrics
Slothが生成したルールは、SLO間で同じメトリック名を共有します。しかし、ラベルは異なるサービス、SLOを識別するためのキーとなる。このようにして、異なるチームやサービス間で、すべてのSLOを記述する統一された方法を得ることが出来ます。
Slothが作成し、利用可能なすべてのメトリック名を取得するには、次のクエリを使用します。
count({sloth_id!=""}) by (__name__)
Alert
Slothの SLOアラートは、マルチウィンドウ・マルチバーン方式を採用し、Critical/page
とWarning/ticket
の2種類のアラートを生成します。
また、時間帯によって4種類のAlertを使用します(が割愛)。また、Sloth は自らAlertを発するのではなく、Slothが生成したAlertルールを使ってPrometheusがAlertを発する。
Prometheusに接続されたalertmanagerを介してSlack、Pagerdutyなど に通知をトリガーします。
sloth.dev
やっていく
Getting started - Sloth を参考にKubernetes上に構築をやっていく
Promethus 周りのインストール
# Get Helm Repository Info helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update # Install Helm Chart :https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack#configuration helm install [RELEASE_NAME] prometheus-community/kube-prometheus-stack
Sloth のインストール
Sloth のhelm はこちらにあるので参照してください。 github.com
helm repo add sloth https://slok.github.io/sloth helm repo update helm install [RELEASE_NAME] sloth/sloth
もしくはCRDをデプロイしていきましょう
# Sloth CRD is required $ kubectl apply -f ./pkg/kubernetes/gen/crd/sloth.slok.dev_prometheusservicelevels.yaml # Prometheus Operator Rules CRD is required $ kubectl apply -f ./test/integration/crd/prometheus-operator-crd.yaml
help
コマンドをインストールしたらhelp を見る良い習慣です。
sloth help usage: sloth [<flags>] <command> [<args> ...] Easy SLO generator. Flags: --help Show context-sensitive help (also try --help-long and --help-man). --debug Enable debug mode. --no-log Disable logger. --no-color Disable logger color. --logger=default Selects the logger type. Commands: help [<command>...] Show help. generate [<flags>] Generates Prometheus SLOs. kubernetes-controller [<flags>] Runs Sloth in Kubernetes controller/operator mode. validate --input=INPUT [<flags>] Validates the SLO manifests and generation of Prometheus SLOs. version Shows version.
generated
get-started.ymlと同じ例ですが、Kubernetes で実行するのでCRDを使用した例です。 Kubernetesのprometheus-operator PrometheusRules CRDにPrometheusのルールを生成します。
k8s-getting-started.yml をsloth generate
させます。ちなみにnamespace を namespace: default
にして実行いたします。
$ sloth generate -i k8s-getting-started.yml INFO[0000] SLI plugins loaded plugins=0 svc=storage.FileSLIPlugin version=1912e6a window=30d INFO[0000] SLO period windows loaded svc=alert.WindowsRepo version=1912e6a window=30d windows=2 INFO[0000] Generating from Kubernetes Prometheus spec version=1912e6a window=30d INFO[0000] Multiwindow-multiburn alerts generated out=- slo=myservice-requests-availability svc=generate.prometheus.Service version=1912e6a window=30d INFO[0000] SLI recording rules generated out=- rules=8 slo=myservice-requests-availability svc=generate.prometheus.Service version=1912e6a window=30d INFO[0000] Metadata recording rules generated out=- rules=7 slo=myservice-requests-availability svc=generate.prometheus.Service version=1912e6a window=30d INFO[0000] SLO alert rules generated out=- rules=2 slo=myservice-requests-availability svc=generate.prometheus.Service version=1912e6a window=30d ~~~
k8s-getting-started.yml を元にさまざまなファイルが生成されています!眠いので解説はしません
# This example shows the same example as getting-started.yml but using Sloth Kubernetes CRD. # It will generate the Prometheus rules in a Kubernetes prometheus-operator PrometheusRules CRD. # # `sloth generate -i ./examples/k8s-getting-started.yml` # apiVersion: sloth.slok.dev/v1 kind: PrometheusServiceLevel metadata: name: sloth-slo-my-service namespace: monitoring spec: service: "myservice" labels: owner: "myteam" repo: "myorg/myservice" tier: "2" slos: - name: "requests-availability" objective: 99.9 description: "Common SLO based on availability for HTTP request responses." sli: events: errorQuery: sum(rate(http_request_duration_seconds_count{job="myservice",code=~"(5..|429)"}[{{.window}}])) totalQuery: sum(rate(http_request_duration_seconds_count{job="myservice"}[{{.window}}])) alerting: name: MyServiceHighErrorRate labels: category: "availability" annotations: summary: "High error rate on 'myservice' requests responses" pageAlert: labels: severity: pageteam routing_key: myteam ticketAlert: labels: severity: "slack" slack_channel: "#alerts-myteam"
validate
構文チェックも可能です
$ sloth validate --input=k8s-getting-started.yml INFO[0000] SLI plugins loaded plugins=0 svc=storage.FileSLIPlugin version=1912e6a window=30d INFO[0000] SLO period windows loaded svc=alert.WindowsRepo version=1912e6a window=30d windows=2 INFO[0000] Validation succeeded slo-specs=1 version=1912e6a window=30d
deploy
generate したものをapply していきます
$ sloth generate -i k8s-getting-started.yml | kubectl apply -f -
Grafana へのログイン
kube-prometheus のGrafanaは初期ID/PASS のadmin:admin
ではないのでパスワードを確認する(ArgoCD でも似たように初期パスワードを取得できる)
# user:password -> admin:prom-operator $ kubectl get secret sloth-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo prom-operator
Grafana へのDashBoard の追加
SLO / Detail dashboard for Grafana | Grafana Labs
入門失敗
Dashboards を生成したら感動的なラストシーン!?このダッシュボードには、各SLOの詳細が表示されますが
これには、http_request_duration_seconds_count
にデータが入ってないわ。。。
errorQuery: sum(rate(http_request_duration_seconds_count{job="myservice",code=~"(5..|429)"}[{{.window}}])) totalQuery: sum(rate(http_request_duration_seconds_count{job="myservice"}[{{.window}}]))
Dashboards - Sloth にしたいんですけど,,, もう眠いので一旦、終わって公開します。 Sloth はとりあえず動かすためのチュートリアルが絶妙に弱くてPrometheusをある程度理解してないとうまく動かせないなーって思いました(小物として)。