はじめに
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 の定義漏れも発生しない
- 既にかなり多くの 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 = "[email protected]: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 にこのような形でまとめています。
また、アラート発生が放置されると
- 真に重大なアラートを見逃してしまう可能性が高まる
- 対応するべきアラート、そうでないアラートが暗黙的に生まれ、新規メンバーへの負荷が高まる
- 所謂オオカミ少年状態になり、アラートの信頼性が落ちる
という状態になりかねないため、週に 20 回以上発生し何も対応が行われなかったアラートについては、まとめてふりかえりの対象としています。 やや画像が小さいですが、議題に上がったアラートや SLI/SLO の対応などは、このような形でスプレットシートで管理しています。 (更に良いやり方は模索中です)
SRE チーム側で対応を Suggest することはあれど、最終的にはプロダクトチームが対応を判断するという責任境界でやっています。
おわりに
いかがだったでしょうか。
弊社ではまだまだ紹介しきれいていない SRE の仕事が沢山あります。
どんなことをやっているか気になった方は、まずはカジュアル面談でお気軽に話してみませんか?
スムーズな運用に向け、Gunosyで開発環境を支えるSREを募集! - Gunosyのインフラエンジニアの求人 - Wantedly
明日は hong さんによる「Swift Concurrencyの気になるところ」の予定です。
お楽しみに。