イベント運営にterraformを使う
この記事は Recruit Advent Calendar 2021 の16日目の記事です。
初めに
普段業務ではクラウド使ったプロダクト開発のあれこれをやっていますが、たまに社内ISUCONやAWS GameDayの運営もやっていたりしています。
積み重ねが生み出した新たな一歩——若手が力を発揮した「R-ISUCON 2021 Summer」 | リクルート メンバーズブログ
社内イベントを実施する上でコンテンツ自体の完成度も重要ですが、円滑にイベントを進行させるもの大事です。
円滑に進行を行うための一、つに運営と参加者のコミュニケーションパスの作成があります。
最近では嬉しいことに社内でイベントを開くと90人近く集まってくれてチームも20チーム以上出来ることがあります。
が、チーム数が多いと準備に必要な量も比例してい多くなります。
更にチームごとに個別の情報を送ったりする必要があるので手動でやるには骨が折れます。
terraformを使う
これらを準備するためにscript書いたりポータルで情報をやり取りできるようにしたりやり方は色々あるかと思います。
社内ISUCONの場合、競技用の環境をAWSで作成するためにTerraformを使っていたので、「折角ならTerraformでチャンネル作ったりメッセージも投稿出来たほうが便利じゃない?」と思い、Terraformを使ってみようと考えてみました。
slack provider
Terraformで利用できるslack providerはコミュニティのものがすでにいくつか存在しています。僕がやりたかったことは大きく以下のとおりです。
- 各チーム向けのprivateチャンネルの作成
- 各チャンネルに対してチームメンバーと運営の招待
コミュニティのものを利用しても良かったのですが、普段terraformを使っているけどproviderの仕組みのことまでちゃんと知らないなと思い、せっかくなので自作してみました。
https://github.com/int-tt/terraform-provider-slack
また、プロバイダーの作成に関しては以下のを記事がとても参考になりました
Terraform Provider実装 入門(1): Custom Providerの基礎 - febc技術メモ
使い方
使い方はとてもシンプルです。以下のようなCSVとterraformのコードを準備して実行するだけです。
もちろんCSVはなくても利用可能です。
id,email team-A,example@example.com
locals { teams = csvdecode(file("./team-list.csv")) team_names = distinct([for t in local.teams : t.id]) } resource "slack_channel" "team-channel" { for_each = toset(local.team_names) name = format("event-name-", trim(replace(lower(each.value), "/[・、 ]/", "-"), "!")) private = true } data "slack_user_with_email" "team-member" { for_each = { for team in local.teams : team.email => team } email = each.value.email } resource "slack_channel_invite" "team-member" { for_each = { for team in local.teams_member : team.email => team } channel_id = slack_channel.team-channel[each.value.id].id user_id = data.slack_user_with_email.team-member[each.value.email].id }
これでチャンネル作成と招待を一気に実行することが出来ます。
また terraform destroy
を使うことで一気にチャンネルのarchiveも実行できます。
やりたいけど出来てないこと
先程slackのメッセージも投稿できるようにしたいって書いてましたが、まだ出来ておらず、イベント運営のときは温かみのある対応をしていました。
APIで投稿するときにはmarkdownでシュッと書いて投稿するのは出来ないので、次のイベント運営の時に気力があれば対応したいなと思います
おわりに
実際に使ってみて感想は便利だったのであってよかったなーというのと、terraform-plugin-sdk よく出来ているなーと感じました。
イベント運営以外にも普段のプロダクト開発におけるslackチャンネル作成や入退室の管理にも使えそうだなと思ったので機会があればやってみたいなと思いました。
prometheus-to-sdを調べた時のメモ
Prometheus to stackdriver
LTする上で prometheus text formatをstackdriver向けに変換してくれる prometheus-to-sd を調べた時のメモです。何もわからんとこから調べたので、もし間違ってたら指摘してもらえると助かります
https://github.com/GoogleCloudPlatform/k8s-stackdriver/tree/master/prometheus-to-sd
prometheus text formatとは
prometheusが扱えるmetrcisのフォーマット
text formatの仕組み
go_gc_duration_seconds{quantile="0.0"} 0.0
metric_name [ - "{" label_name "=" `"` label_value `"` { "," label_name "=" `"` label_value `"` } [ "," ] "}" - ] value [ timestamp ]
https://ja.wikipedia.org/wiki/EBNF EBNFの読み方不明だったので参考
- metric_name: metrics名
- label_name="label_value"(optional): ラベル名とラベルの値 カンマでつなげることで複数定義可能
- value: 値、中身はGoのParseFloat()でパースできる値である必要がある。数値以外では
Nan
+Inf
-Inf
が使える。 - timestamp(optional): timestamp
go_gc_duration_seconds{quantile="0.0"} 0.0
の場合
となる。labelはパーセンタイル等、同一Metricsだが、ラベル付をしたい時任に利用する
HELPとTYPE
これとは別に #HELP
と #TYPE
が存在している
# HELP $MetricName $Description
というような形でMetricsに対して説明を付与することができる
# TYPE $MetricName $MetricType
というような形でMetricsがどんなMetricsなのかを付与できる。
付与できる一覧は以下
- Counter: カウンター、単調増加する値、完了したタスク数のような値で使う
- Gauge: ゲージ、単一の数値、メモリ使用量など
- Histogram: ヒストグラム、
- Summary: 概要、リクエスト期間等でサンプリングできるもの、パーセンタイル等で使える
- Untyped: 型なし
Stackdriveに変換される上でのポイント
prometheus to stackdirverにて変換するときは以下のように変換する
MetricType
COUNTER OR HISTOGRAM
->CUMULATIVE
OTHER
->GAUGE
func extractMetricKind(mType dto.MetricType) string { if mType == dto.MetricType_COUNTER || mType == dto.MetricType_HISTOGRAM { return "CUMULATIVE" } return "GAUGE" }
ValueType
stackdriverで扱う値は ParseFloatでパースできるかどうかしか見てないが、StackdriverのValue Typeでは型があるので変換される
- すでにcustomMetricsが定義されいる場合: 定義されている型に従う(おそらく)
- MetricTypeがHISTOGRAMの場合 -> DISTRIBUTION
- それ以外: INT64
func extractValueType(mType dto.MetricType, originalDescriptor *v3.MetricDescriptor) string { // If MetricDescriptor is created already in the Stackdriver use stored value type. // This is going to work perfectly for "container.googleapis.com" metrics. if originalDescriptor != nil { // TODO(loburm): for custom metrics add logic that can figure value type base on the actual values. return originalDescriptor.ValueType } if mType == dto.MetricType_HISTOGRAM { return "DISTRIBUTION" } return "INT64" }
https://cloud.google.com/monitoring/api/v3/metrics-details?hl=ja#metric-kinds
concourseのMetricsをstackdriverに送ってみる(Prometheus -> stackdirver)
これはRecruit Engineers Advent Calendar22日目の記事です。(許して
最近はConcourse CIを利用してCI/CD環境を準備することが多いのですが、ちゃんと使えば使うほど、プロジェクトの中でも重要度が高まり、ちゃんと運用しないと辛いことになってしまいます。 CI/CD環境もちゃんとモニタリングして運用していくぞ!ということで色々調べていくとconcourseではメトリクスエンドポイントが提供されているのを見つけました。
公式の利用例も公開されていて、かっちょいいダッシュボードが見えるようになっています。 https://metrics.concourse-ci.org/dashboard/db/concourse
メトリクスは
- InfluxDB
- NewRelic
- Prometheus
- Datadog
- Riemann
のフォーマットで提供されていますが、直近ではstackdriverの検証もやっており、concourseのためだけにdatadogやPrometheusを準備するのは面倒だったため、Googleが公開しているPrometheus-to-sd を利用してみます。
exmapleとしてkube-state-metrics
をstackdriverに送るサンプルが公開されているため、これをもとに弄ってみます。
apiVersion: v1 kind: Pod metadata: name: kube-metrics spec: hostNetwork: true containers: - name: kube-state-metrics image: gcr.io/google-containers/kube-state-metrics:v1.4.0 ports: - name: http-metrics containerPort: 8080 readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 5 timeoutSeconds: 5 resources: requests: memory: 200Mi cpu: 100m limits: memory: 300Mi cpu: 200m - name: prometheus-to-sd image: gcr.io/google-containers/prometheus-to-sd:v0.3.2 ports: - name: profiler containerPort: 6060 command: - /monitor - --stackdriver-prefix=custom.googleapis.com - --source=kube-state-metrics:http://localhost:8080 - --pod-id=$(POD_NAME) - --namespace-id=$(POD_NAMESPACE) env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace
concourseの環境はGKE上にhelmで準備します。 https://github.com/helm/charts/tree/master/stable/concourse
今回は 面倒なので prometheusのmetricsをstackdriverに送るところまでがスコープなので 、 prometheus.enabled
にして web-deployment.yaml
に以下のcontainerを追加します。
promethusをenableするとserviceも作成されるので Prometheus-to-sd
はdeploymentで準備してservice経由で取得するのが正しい気もするが、省略します
- name: prometheus-to-sd image: gcr.io/google-containers/prometheus-to-sd:v0.3.2 ports: - name: profiler containerPort: 6060 command: - /monitor - --stackdriver-prefix=custom.googleapis.com - --source=concourse:http://localhost:9391 - --pod-id=$(POD_NAME) - --namespace-id=$(POD_NAMESPACE) env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace
これで設定は終了、これをGKEにデプロイして同じプロジェクトのstackdriver MonitoringからMetricsを確認するとメトリクスが飛んで出来てるのが確認できます
TODO
- pipelineを準備してちゃんと試せていないのでPrometheusと同等のMetricsがちゃんと取得できてるか確認する
- 仕組みちゃんと調べる
- prometheusもstackdriverもまだnoobなので途中経過を書く