task4233のめも

書きたいことをつらつらと

NTTコミュニケーションズ SREエンジニア体験 参加記

はじめに

2020年2月15日(土)にNTTコミュニケーションズにて開催された「SREエンジニア体験」に参加しました。

午前中にSREエンジニアに関する座学を, 午後にGCPを用いたハンズオンを行いました。

ここで, SREについてかなりの知見が得られたので, 参加記としてまとめることとしました。

午前 - 座学

SREとは

SRE(Site Realiability Engineering)とは, システムの信頼性を担保するエンジニアリングのことです。

SREは, 品質の維持かつ高速なリリースサイクルの実現を目的とします。具体的には, アプリケーション基盤の構築および運用やリリースプロセスの整備(共通化)が挙げられます。

SREについては, 以下の本がおすすめです。

SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム

用語: SLI, SLO, SLAについて

SLOのすすめによると, それぞれの要素について以下のように書かれています。

SLI(Service Level Indicator)とは, サービスレベルの指標のことです。具体的には「リクエストの成功率」や「月間利用可能率」などが挙げられます。

SLO(Service Level Objective)とは, サービスレベルの目標のことです。具体的には「各四半期中の全リクエストの成功率は99.99%以上とする」が挙げられます。
この値は, 定期的にクライアントにヒアリングをしながら定期的に見直す必要があります。例えば, 満足度を指標としている場合は, 満足度を計る狩野モデルを用いて, 満足度が低い場合はSLOを引き上げるといった変更が必要になります。

SLA(Service Level Agreement)とは, サービスレベルに関する合意のことです。具体的には「SLOが満たされなかった場合, 利用料の50%を返金する」といったものが挙げられます。

従来の運用

従来の運用では, Dev*1Ops*2がチームとして分離しています。この運用では, Devは新機能や修正のためにシステムの変更を望むのに対し, Opsはシステム安定のためにシステムの変更を望みません。

システムの変更は必要なので, レビュープロセスやリリースプロセスを厳格化することで障害を減らそうとします。この結果, システムの規模が大きくなればなるほど, 運用コストも比例して増加します

また, SLAに違反しないようサービスの停止を極端に嫌い, 過度に慎重になります。

以上の要因により, サービスのリリースが遅くなる訳です。

SREによる運用

SREによる運用では, システムの規模に比例して運用コストが増加しません。なぜなら, リリースに応じた正常性確認を自動化するためです。システムの規模に応じて時間がかかる理由は, 正常性確認を手動で行っているためなので, 自動化は運用コストの膨張防止に大きく貢献します。

そして, 障害発生を0にするのは誤りであると考え, 障害発生時には影響を最小化する運用を行います*3。そのため, SLAに基づいたサービス品質を目指して, 早急にシステム障害から復旧できる仕組みを実装します。

また, SLOに違反しない限りはサービス断を許容し, 余った時間*4で新機能のリリースといった挑戦的なことを行います。

SLO違反を防ぐ仕組み

余った時間を用いると言えど, SLOに違反しては問題です。
そこで, SLO違反を検知する機構としてCanary Releaseが適用できます。

Canary Releaseとは, 新しいバージョンに流すトラフィックを制限することで, 新しいバージョンに問題があっても全体のSLOを担保するリリース手法です。例えば, 新しいバージョンに流すトラフィックを全体のトラフィックの1%に留めれば, 新しいバージョンが100%機能しなくとも全体へのダメージは1%を超えることはありません。

Canary Releaseには, OSSツールのIstioが利用できます。

CI/CD

CI(Continuous Integration)およびCD(Continuous Delivery)のことです。

CI(Continuous Integration)

リリースまでのパイプラインで言えば, Test/Buildの自動化がCIに該当します。

CIによる恩恵は, 品質の保証と開発者への情報提供です。 前者は, deployされたコードがtestを通っていることが保証されているので, 最低限の品質は保証されているという意味です。後者は, エンジニアがpushしたコードのフィードバックを即時にもらえるという意味です。

具体的なワークフローとしては以下の3つが挙げられます。

  • Run test localy
    • ローカル環境で動かないものは基本的にpushしないという発想
  • Build Servers
    • pushをトリガーとしてサーバ側でテストを含めた自動化が為されていること
  • Quality Control
    • ソフトウェア品質を高めることを目的とした性能測定および静的解析
    • i.e.) Lint toolやStyle Guide, 脆弱性情報を用いたコードの解析

CIのツール(ドキュメント)は以下の通りです。

CD(Continuous Delivery)

リリースまでのパイプラインで言えば, Deploy, Test*5, Approveの自動化がCDに該当します。

CDによる恩恵は, ソフトウェアがいつでもリリースできる状態にあることです。CDでは, deployおよびtest等をまとめて行うため, リリースできる状態が保証されます。

CDのdeployには以下の通り, deploy strategyという手法を状況に応じて使い分けます。

  • Rolling update
    • 新しいバージョンをクラスタ内で部分的に追加し, 問題がなければ古いバージョンを順番にクラスタから消していく手法
  • A/B testing
    • Traficを2つのバージョンのユニットA/Bに分けて調査をする手法
    • 2つのバージョンの性能評価のために用いられる
  • Blue/Green Deployment
    • Dev用にtest traficを流すためのGreen Podと, User用にuser traficを流すBlue Podを用意
    • Green Podで問題なさそうなら, user trafficをGreen Podに流す手法
  • Canary Release
    • 現行サーバの他にBaselineという比較用の現行サーバとCanaryという新しいバージョンのサーバを用意
    • Routerによってtrafficの操作を行い, BaselineおよびCanaryに全体の数パーセント程度のtrafficを流して比較することで新しいバージョンの検証をする手法

CDのツール(ドキュメント)は以下の通りです。

午後 - ハンズオン

こちらのGoogleのチュートリアルを参考にした, 段階的にCI/CDを実現していく形式のハンズオンを行いました。

手動deploy

最初は, 以下の通り手動でdeployしました。

  1. アプリケーションのコンテナ化
    • コンテナのimageIDを取得
  2. 作成したcontainer imageをcontainer repositoryにpush
    • docker imageIDとrepository nameを紐づけ
    • repository nameでpush
  3. kebernetesにmanifestを適用
    • manifestであるyamlファイルを編集して適用

CI/CDパイプラインの構築

手順としては少ないですが, 複数のdeployをする場合は大変ですし, ヒューマンエラーでミスをする可能性もあります。そこで, CI/CDパイプラインを構築することとしました。

変更点は以下の通りです。

  • アプリケーションのコンテナ化およびcontainer repositoryへのpushの自動化(CI)
    • appリポジトリへのpushを起点とするGCP Cloud Buildのトリガを設定
    • 設定用のyamlファイルはこちら
    • yamlファイルでは, docker buildおよびpushをする設定が書かれています
  • アプリケーションdeployの自動化(CD)
    • envリポジトリへのpushを起点とするGCP Cloud Buildのトリガを設定
    • 設定用のyamlファイルはこちら
    • yamlファイルには, kubernetesへのmanifestの適用およびproductionブランチへのpushをする設定が書かれています

ここで, envリポジトリにcandidateブランチおよびproductionブランチがあることが分かります。これらのブランチを分けている理由は, 昔のmanifestを適用することで簡単にGKE上で過去の状態を復元できるようにするためです。

各ブランチの役割は以下の通りです

  • candidateブランチ
    • これから本番環境にdeployするためのコードを保存
    • 最新版を本番環境にdeployするときはこちらを変更
  • productionブランチ
    • 本番環境にdeployされたコードを保存 − candidateブランチが本番環境に適応された段階でcandidateブランチからproductionブランチにpushされる

ログのモニタリング環境構築

自動化したはいいものの, アプリケーションの挙動を見守る必要があるはずです。そこで, ログをモニタリングするための機構を構築します。

ログのモニタリング時には, 以下の4つのシグナルを意識すると良いそうです。

  • リソース(Resources)
  • 使用率(Utilization)
    • リソースが処理中でbusyだった時間の平均
  • 飽和状態(Saturation)
    • リソースにサービスできない余分な作業がある度合い(処理できてないものは大抵キューに入れられいる)
  • エラー(Errors)
    • エラーイベントの数

そして, モニタリングを実現するには, PrometheusおよびGrafanaを用います。それぞれの役割は以下の通りです。

  • Prometheus
    • システムの監視や警告を行う
  • Grafana

また, 変更点は以下の通りです。

おわりに

CI/CDの構築を実践しながら学べるイベントでした。 GCPのサービスは課金が怖くてあまり触っていませんでしたが, これを機に無料枠で少しずつ触ってみようと思えました。 CI/CDを組むようなサービスを構築することは少ないですが, アーキテクチャを学べたのは良かったです。

来年もあればぜひ参加してみてはいかがでしょうか? (これ毎回言ってる気がしますね)

*1:開発者のこと

*2:運用者のこと

*3:経験上どう頑張ってもバグが消えないことは分かっているはずです。

*4:Error Budgetという

*5:こちらはDeployされたものを対象としたTest