Gunosy Tech Blog

Gunosy Tech Blogは株式会社Gunosyのエンジニアが知見を共有する技術ブログです。

2021 年の SRE チームの活動について

はじめに

SRE 部の茂木です。
こちらの記事は Gunosy Advent Calendar 2021 - Adventar の 21 日目の記事となります。

前回の記事はサンドバーグさんの 改めてドライブレコーダーを作ってみた - Gunosy Tech Blog でした。
かなりマニアックな内容となっていましたね。

さて、2017 年頃から 「SRE」という単語が世の中に出回ってから、数多くの実践が各企業で行われてきました。ですがその業務内容を詳細に公表している企業はそう多くはありません。
私は Gunosy に来てから正式な SRE チームに所属することになりましたが、
常にSRE の定義とは、難しいものがあるなと日々感じています(各社によって責任範囲や求められることがかなり違うため) 。

そこで今回は、 2021 年の Gunosy のSRE チームがどのような活動をしてきたかを、大きく分けて 2 つ紹介したいと考えています。

全社技術標準化

弊社では全ての環境が AWS に存在し、kubernetes(以後 k8s) が複数プロダクトで利用されています。
SRE チームの仕事の一つは、複数のプロダクトで使われている技術のナレッジを集めることです。
更にそれらを他プロダクトで、素早く安全に使えるように整えていくことです。

2021 年で、最近どのような取り組みをしたかをまとめてみました。

  • helm の本格的な導入と移行
  • Datadog pipelines の導入と module 化
  • conftest の導入

helm の本格的な導入と移行

弊社では terraform を以前から導入しているのもあり、EKS 導入初期は terraform の kubernetes provider を使って resource を作成していました。

当初は

  • インフラをコード化するツールを terraform に統一できること
    • 管理するツールをなるべく減らしたかった
  • k8s の yaml 管理ツールのデファクトといい切れるツールがない状況に見えた
    • kustomize, helm, マイナーどころだと ksonnet などの用な多数のツールが天下を争っていた

ということが原因で、ここで判断を間違えて後で乗り換えるよりは、もう少し様子を見ようと判断し、 terraform に寄せていました。
しかし近年では、最近の k8s 系のエコシステムは、ほぼ helm を使って導入できる状態になっていると言えるため、本格的な移行を行っています。

以下 helm に移行してよかった点、悪かった点をまとめます。

  • helm にして良かった点
    • バージョンアップする際のメンテナンスコストが減った点
      • terraform で管理していると version update した時に、rbac の修正が必要になるケースがあり、そのたびに terraform で書き下した resource に手を入れる必要があった
      • helm で管理すると chart の version を上げると、関連リソースも合わせて自動で変更が入っているので楽
    • 初期導入のコストが減った点
      • 既にかなり多くの resource が helm に対応しているため、初期導入の手間は少なく、terraform と比較して resource の定義漏れも発生しない
  • helm にして悪かった点
    • terraform で定義された resource を参照しづらくなった点
      • terraform 側でも利用されている、AWS Secret Manager/Parameter Store で定義された value をそのまま参照はできない
    • 結局中身の yaml をかなり読み込まないと使えない点
      • 小さい Chart ならさほどでもないが、resource 定義が膨大だと、そこそこ読むのが大変である

上記の点を総合的に考えると helm に舵を切ったのは良かったなと感じております。

Datadog pipelines の導入と module 化

k8s で運用している Deployment/Daemonset/Job の各種ログは、 Datadog logs に集約しています。
デフォルトで json 形式のログや、いくつかの resource については pipeline が実装されておりますが、一部は未対応なので自前で実装する必要があります。

この pipeline を実装しない場合、log status が error として誤検知してしまい、例えば「error level のログが出たらアラートを鳴らしたい」 というケースで、対応不要なアラートが発生してしまいます。

したがって Datadog pipeline の実装を terraform で module として提供することで、色々なプロダクトで使えるようにしています。

# kubernetes 界隈でよく使われている logger である klog(元の名前を glog) をいい感じに parse する module
module "glog_pipeline" {
  source = "git@github.com:gunosy/terraform-datadog-modules.git//pipeline/glog?ref=vx.x.x"
  name   = "glog pipeline"
  query  = "source:my-api-server AND environment:development"
}

このような module 以外にも多数の terraform module を作成しています。

conftest の導入

各インフラレイヤーを安全に運用するために、現在の環境がプラクティスに沿ったものであるかどうかを確認するために導入しました。 例えば以下のようなユースケースを想定しています

  • k8s で Deployment を運用する上で、考慮するべき点や良いプラクティスを踏襲しているかどうかをチェックしたい
  • AWS resource を作成、運用する上で、考慮するべき点や良いプラクティス予めチェックしておきたい

一部を抜粋すると、以下のような rule を定義しています。

package k8s

# 全体で使う util 関数を定義
import data.util

# Deployment にて、limits(CPU) が指定が空だと怒られる
deny_no_limits_cpu[msg] {
    input.kind == "Deployment"
    containers := input.spec.template.spec.containers[_]
    not containers.resources.limits.cpu
    name := util.get_k8s_resource_name(input)
    msg := sprintf("k8s deployment(= %s) should have .spec.template.spec.resources.limits.cpu fields", [name])
}

# Deployment にて、limits(memory) が指定が空だと怒られる
deny_no_limits_memory[msg] {
    input.kind == "Deployment"
    containers := input.spec.template.spec.containers[_]
    not containers.resources.limits.memory
    name := util.get_k8s_resource_name(input)
    msg := sprintf("k8s deployment(= %s) should have .spec.template.spec.resources.limits.memory fields", [name])
}

# k8s 1.22 からの Ingress resource は apiVersion = "networking.k8s.io/v1" でないとダメなので、それ以外の指定が行われている場合は、通知だけ行う
warn_k8s_v1_22_deprecated_api_version_Ingress[msg] {
    input.kind == "Ingress"
    not input.apiVersion == "networking.k8s.io/v1"
    name := util.get_k8s_resource_name(input)
    msg := sprintf("k8s apiVersion(= %s) name(= %s) will no longer be served in v1.22. See: https://kubernetes.io/docs/reference/using-api/deprecation-guide/#ingress-v122", [input.apiVersion, name])
}

このような policy を1 つの共通 repository にまとめ、サーバーサイドの CI で conftest を実行するようにしています。
サーバーサイドでは skaffold を通して yaml を一つにまとめているので、その yaml ファイル全体を conftest の入力として与えています。

このような CI を作ることで、サーバーサイドのメンバーが書く yaml ファイルが、運用ルールに沿ったものであるかどうかを常にチェックするようにしています。

SLI/SLO アラート週次ふりかえり

弊社では以前より、エンドユーザーの体験を向上し続けるために SLI/SLO を定義し、導入してきました。

SLI や SLO で「プロダクトの健全性」を定義、数値化することで、現状把握を定量的に行うことができ、 それに対する判断基準を設けることで、今チームが何をするべきか(機能開発を続けるか、安定性を向上させるか)がわかると考えているからです。

2021 年では、定義された SLI/SLO を Dashboard にまとめて、週次でプロダクトチームと「SLI/SLO アラートふりかえり会」という形で開催しています。
紆余曲折ありましたが、現在は Google Docs にこのような形でまとめています。

f:id:mgi:20211221090510p:plain
SLI/SLO ふりかえり

また、アラート発生が放置されると

  • 真に重大なアラートを見逃してしまう可能性が高まる
  • 対応するべきアラート、そうでないアラートが暗黙的に生まれ、新規メンバーへの負荷が高まる
  • 所謂オオカミ少年状態になり、アラートの信頼性が落ちる

という状態になりかねないため、週に 20 回以上発生し何も対応が行われなかったアラートについては、まとめてふりかえりの対象としています。 やや画像が小さいですが、議題に上がったアラートや SLI/SLO の対応などは、このような形でスプレットシートで管理しています。 (更に良いやり方は模索中です)

f:id:mgi:20211221023035p:plain
アラート対応表

SRE チーム側で対応を Suggest することはあれど、最終的にはプロダクトチームが対応を判断するという責任境界でやっています。

おわりに

いかがだったでしょうか。
弊社ではまだまだ紹介しきれいていない SRE の仕事が沢山あります。
どんなことをやっているか気になった方は、まずはカジュアル面談でお気軽に話してみませんか?

スムーズな運用に向け、Gunosyで開発環境を支えるSREを募集! - Gunosyのインフラエンジニアの求人 - Wantedly

明日は hong さんによる「Swift Concurrencyの気になるところ」の予定です。
お楽しみに。