GeekFactory

int128.hatenablog.com

Cluster AutoscalerをPrometheusでモニタリングする

Cluster Autoscalerを運用していると,ノード数が増減した契機を調査したいことがあります.Cluster Autoscalerは大量のログを出力するため,闇雲にログを追うのは大変です.PrometheusとGrafanaでCluster Autoscalerの動作を可視化しておくと調査しやすくなります.

Cluster Autoscalerにはメトリクスを取得するためのエンドポイントが用意されており,Prometheusと連携することが可能です.具体的なメトリクスはCluster Autoscalerのドキュメントを参照してください.

Prometheusで用意されているServiceMonitorというカスタムリソースを利用すると,監視対象のServiceとPrometheusを紐づけることが可能です.詳しくはPrometheusに関連するリソースの説明が参考になります.

本項では,以下の構成を用いて,Cluster AutoscalerをPrometheusでモニタリングする方法を説明します.

Prometheus (namespace: monitoring)
↓
Cluster Autoscaler ServiceMonitor (namespace: monitoring)
↓
Cluster Autoscaler Service (namespace: kube-system)
↓
Cluster Autoscaler Pod (namespace: kube-system)

Prometheusのセレクタの確認

PrometheusがServiceMonitorを検索する時のセレクタを確認します.

stable/prometheus-operatorチャートを利用する場合,以下の設定値でServiceMonitorの検索対象を指定できます.

  • prometheus.prometheusSpec.serviceMonitorNamespaceSelector
    • ServiceMonitorを検索する時のNamespaceを指定します.デフォルトではすべてのNamespaceを検索します.
  • prometheus.prometheusSpec.serviceMonitorSelector
    • ServiceMonitorを検索する時のセレクタを指定します.
  • prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues
    • 前項のserviceMonitorSelectorが未指定の場合,Helm releaseの値を利用します.

何も指定しない場合は以下のリソースが作成されます.

# kubectl -n monitoring get prometheuses.monitoring.coreos.com prometheus-operator-prometheus -oyaml
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
spec:
  serviceMonitorNamespaceSelector: {}
  serviceMonitorSelector:
    matchLabels:
      release: prometheus-operator

すなわち,何も指定しない場合は release: prometheus-operator というラベルを持つServiceMonitorが検索されます.Cluster AutoscalerのServiceMonitorにこのラベルを付与すると,Prometheusが見つけてくれます.

Cluster Autoscalerのデプロイ

stable/cluster-autoscalerチャートをHelmfileでデプロイします.AWSの場合は以下の記事を参考にしてください.

int128.hatenablog.com

stable/cluster-autoscalerチャートにはServiceMonitorリソースを作成するテンプレートが含まれています.helmfile.yamlserviceMonitorを以下のように設定すると,ServiceMonitorリソースが作成されます.

releases:
  # https://github.com/helm/charts/tree/master/stable/cluster-autoscaler
  - name: cluster-autoscaler
    namespace: kube-system
    chart: stable/cluster-autoscaler
    values:
      - serviceMonitor:
          enabled: true
          namespace: monitoring
          selector:
            release: prometheus-operator

serviceMonitor.namespaceにはPrometheusのNamespaceを指定します.ServiceMonitorはPrometheusと同じNamespaceに存在する必要があります(詳しくはこちらを参照).

serviceMonitor.selectorには前項で調べたセレクタを指定します.

先ほどの設定を適用すると以下のリソースが作成されます.

# kubectl -n monitoring get servicemonitors.monitoring.coreos.com cluster-autoscaler-aws-cluster-autoscaler -oyaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  labels:
    prometheus: kube-prometheus
    release: prometheus-operator
  name: cluster-autoscaler-aws-cluster-autoscaler
  namespace: monitoring

前述のように,Cluster AutoscalerのServiceMonitorに release: prometheus-operator というラベルを付けておくことで,Prometheusが見つけてくれるようになります.

PrometheusとCluster Autoscalerの連携確認

ブラウザでPrometheusのService Discoveryを開きます.以下のようにCluster Autoscalerが認識されていれば成功です.

  • monitoring/cluster-autoscaler-aws-cluster-autoscaler/0 (1/210 active targets)

もしService Discoveryに出てこない場合はセレクタの対応が合っているか確認します.以下のコマンドと睨めっこになると思います.

kubectl -n monitoring get prometheuses.monitoring.coreos.com
kubectl -n monitoring get servicemonitors.monitoring.coreos.com

Grafanaダッシュボードの追加

以下のダッシュボードを利用します.

grafana.com

レビューコメントによると新しいバージョンのCluster Autoscalerでは動かない報告がありますが,私の環境では問題なく動いています.このダッシュボードを利用しているリポジトリもある(skyscrapers/charts)ので大丈夫かと思います.

参考までにスクリーンショットを貼っておきます.

f:id:int128:20191028172133p:plain

ダッシュボードの動作確認が終わったら,ダッシュボードのJSONファイルをConfigMapに追加しておきましょう.GitOpsを利用すると,Gitリポジトリ上のConfigMapを更新したらGrafanaに反映されるので便利です.

apiVersion: v1
kind: ConfigMap
metadata:
  name: grafana-dashboard-cluster-autoscaler
  labels:
     grafana_dashboard: cluster-autoscaler
data:
  grafana-dashboard-cluster-autoscaler.json: |-
    {
      # 以下略

おすすめのダッシュボードがあったらぜひ教えてください!

ffmpegでmovをgifに変換する

QuickTimeで画面収録したmovファイルをgifファイルに変換する方法です。

Docker Hubの jrottenberg/ffmpeg イメージを利用します。以下を実行すると、サイズやフレームレートをそのままにしてファイルを変換します。

docker run --rm -v $PWD:/src jrottenberg/ffmpeg:4.1-alpine -y -i /src/example.mov /src/example.gif

いつも忘れるのでメモ。

実行中のゴルーチンでwg.Add(1)/eg.Go()を実行すると,Wait()は呼び出し後に追加されたゴルーチンも待ってくれるか?

Goで並行処理のコードを書いている時に以下の疑問が思い浮かびました.

  1. sync.WaitGroupを利用する場合,実行中のゴルーチンでwg.Add(1)を実行すると,wg.Wait()は呼び出し後に追加されたゴルーチンも待ってくれるか?
  2. errgroup.Grpupを利用する場合,実行中のゴルーチンでeg.Go()を実行すると,eg.Wait()は呼び出し後に追加されたゴルーチンも待ってくれるか?

答えはどちらもYesです.

実際のコードで確かめてみました.具体的なコードと結果は下記を参照してください.

github.com