無印吉澤

Site Reliability Engineering(SRE)、ソフトウェア開発、クラウドコンピューティングなどについて、吉澤が調べたり試したことを書いていくブログです。

Building Secure and Reliable Systems 読書メモ - Chapter 3 & 4

f:id:muziyoshiz:20200430014145p:plain:w320

SRS 本の読書メモの続きです。Chapter 5 が結構長いので、とりあえず Chapter 3〜4 の読書メモを書きました。

SRS 本はこちらから無償でダウンロードできます。

前回までの読書メモはこちら。

Part II. Designing Systems

Part II (Chapter 3〜10) では、セキュリティと信頼性に関する要求を実装するための最もコスト効率の良い方法、すなわちソフトウェア開発サイクルのできるだけ早い段階、システムの設計時にそれらに着手するということにフォーカスする。

Chapter 3. Case Study: Safe Proxies

この章は Google でのケーススタディ(Safe proxies)の簡単な紹介のみ。このケーススタディに含まれる要素は、Chapter 4 以降で詳しく紹介される。

Safe proxies とは、認可された人に対して、物理サーバや仮想マシン、特定のアプリケーションへのアクセスや状態変更を許可するためのフレームワーク。Google では、システムへの SSH 接続の必要なしに、リスクのあるコマンドのレビュー、承認、実行を行うことが出来る。

Safe proxies は本番環境への単一のエントリーポイントとなり、以下のようなことを可能にする(Figure 3-1 に Safe proxy model が図示されている)。

  • fleet 内でのすべての操作の監査
  • リソースへのアクセス制御
  • 人的ミスが本番環境へ大規模に広がることに対する保護

Zero Touch Prod という Google のプロジェクトがある。その目的は、本番環境に対する変更はすべて自動的に行われるか、ソフトウェアによって事前検証されるか、監査済みの breakglass mechanism を通して実行されるようにすることにある。Safe proxies はこれらの原則を達成するために用いられるツールセットの一つである。

Safe proxies の導入によって生じる摩擦を減らすために、この章の著者らはエンジニアと密に連携し、緊急時には brakeglass mechanism を通してエンジニアがシステムにアクセスできるようにしている。breakglass mechanism とは、緊急時にセキュリティポリシーをバイパスして操作できるようにするためのメカニズムのこと(火災報知器を鳴らすときにガラスを割る=breakglassからの連想)。breakglass mechanism は権限が強いゆえに、Multi-Party Authorization (MPA) や厳密な監査ログなどとセットで実現される。これらの詳細は Chapter 5 に書かれている。

Google Tool Proxy(Safe proxies と呼ばれるプロクシ群の1つ?)は、CLI の実行をプロクシするツールである。エンジニアはマシン上で直接コマンドを実行できない。Tool Proxy が任意のコマンドを gRPC で受け取り、ポリシーと照らし合わせ、監査ログを記録し、MPA を要求した後にコマンドを実行する。文中では borg CLI を例に挙げている。

Chapter 4. Design Tradeoffs

セキュリティ、信頼性、および機能面での要求の間のトレードオフに関する章。

セキュリティと信頼性を後回しにして一時的に開発速度を上げても、あとから重大なコストとリスクを生じる。しかし、システムのライフサイクルの初期からこれらを考慮した設計にすることで、この三者をすべて満たすことができる、というのがこの章での主張。

典型的には、機能要件(feature requirements, functional requirements)が最初に作られ、これがシステム設計に関する決定の推進力になる。それに対して、特定の機能に紐付かない、セキュリティや信頼性に関するものは非機能要件に含まれる。また、開発やデプロイのベロシティに関する要件も非機能要件に含まれる。

機能要件は仕様を書き出して、実装して、仕様通りかをテストする、という流れがわかりやすいが、セキュリティや信頼性についてはそれが難しい。信頼性とセキュリティは、システムデザインから現れてくる特性(emergent property)であり、単一の機能を実装するという類のものではない。コラム "Reliability and Security as Emergent Properties of System Design"に、この特性に関係する要素がいくつか挙げられている。

システムの初期段階から信頼性とセキュリティについて考える方法の一例として、Google で用いられている Design document template がある。このテンプレートには信頼性およびセキュリティに関するセクションがあり、p.47以降で各セクションが詳しく紹介されている。

機能要件と非機能要件のバランス、トレードオフの解決は難しい。"Example: Payment Processing" では支払い処理を例に挙げて、reliability risk を避けようとすると、security risks が出てくる、というケースを説明している。

Google ではマイクロサービスのための社内向けフレームワーク(Google Web Application Framework)を進化させてきた。

Google Web Application Framework は、アプリケーションコードがコーディングガイドラインやベストプラクティスに一致するかどうかのチェック(conformance checks)を静的または動的に適用することができる。また、開発やデプロイで必要となる共通タスクが最初から組み込まれている。フレームワークにこれらの機能が含まれているため、それを開発者が自分で作った場合に起こる脆弱性の混入を防いでくれる。

また、ビルドから SLA の計測まで自動化されていることで、error budget を消費した製品についてはリリースを止めることもできる(コラム "Reliability and Security Benefits of Software Development Frameworks" 内の記載)。

セキュリティと信頼性に対する優先度を上げることは、他の優先すべきこと(機能要件)を妨げない。むしろ上記の検査などが自動化されていれば、開発速度は上がる。セキュリティ問題に柔軟に対応できる設計ということは、新機能を追加しやすい設計ということでもある。

開発初期のベロシティ(Initial Velocity)と、長期的なベロシティ(Sustained Velocity)を区別して考える必要がある。開発初期のベロシティを重視してセキュリティと信頼性を考慮しないと、長期的にはスローダウンする。そのため、セキュリティと信頼性をチームの文化に埋め込む必要がある(チームの文化については Chapter 21)。

ここまでの感想

Chapter 3〜4 を読むと、Google はそのスケールメリットを生かして、セキュリティと信頼性に関わるツールやフレームワークを共通化しているということがよくわかります。しかし、このアプローチは Google ほどの規模がないと難しそうですし、普通の会社はどうしたらいいんだろう……というのが、ここまで読んだ率直な感想でした。

あと、個人的には Chapter 4 の文章がところどころ胸に刺さりました。例えば、コラム "Cost of Adding Reliability and Security to Existing Systems" の以下の記載。

Accommodating security and reliability requirements in an existing system often requires significant design changes, major refactorings, or even partial rewrites, and can become very expensive and time-consuming. Furthermore, such changes might have to be made under time pressure in response to a security or reliability incident— but making significant design changes to a deployed system in a hurry comes with a significant risk of introducing additional flaws.

既存システムのセキュリティと信頼性の要件を満たすためには、多くの場合、大幅な設計変更、大規模なリファクタリング、あるいは部分的な書き換えが必要となり、非常に高価で時間のかかる作業になることがあります。 さらに、このような変更は、セキュリティや信頼性のインシデントに対応するために、時間的なプレッシャーの中で行わなければならないかもしれませんが、デプロイされたシステムの大幅な設計変更を急いで行うことは、さらなる不具合を導入する大きなリスクを伴います。

あとは "Initial Velocity Versus Sustained Velocity" の節にある以下の文章も個人的には刺さりました。

Furthermore, tests retrofitted to a mature system can sometimes fall into the trap of exercising the current buggy behavior more than the correct, intended behavior.

さらに、成熟したシステムにあとから組み込まれたテストは、正しい、意図された振る舞いをテストするというより、現在のバグった振る舞いを再現していることをテストする、という罠に陥ることがあります。

そういうことってありますよね……。

いまあるシステムにとっては何の慰めにもならない文章ばかりですが、これから作るシステムについてはせめて最初からセキュリティと信頼性について考えよう、と思わせてくれる内容でした。

Building Secure and Reliable Systems 読書メモ - Chapter 1 & 2

f:id:muziyoshiz:20200430014145p:plain:w320

今月中旬に、Google SRE による SRE 本の3冊目 "Building Secure and Reliable Systems" が無償公開されました。

www.publickey1.jp

以下のサイトから PDF, EPUB, MOBI 形式でダウンロードできます。過去の2冊は HTML で公開されていますが、今回は電子書籍のデータ形式での公開のようです。

landing.google.com

日本語版は、もし出版されたとしても2年後くらいになりそうなので、僕もそろそろ重い腰を上げて読み始めました。

導入にあたる Part I(Chapter 1 & 2)まで読み終わったので、ここまでの読書メモと感想を書いておきます。久しぶりに洋書読んでて結構疲れたので、自分への動機づけのために、今後、何章か読むたびに読書メモを書いていこうと思います。

読書メモ

以下、内容に関する僕の理解と、僕が特に重要と思った箇所のメモです。また、一部はメモに加えて、原文を引用しています。

あくまで内容の一部ですし、まだ全部読み終わってないので誤解も多いと思います。気になったキーワードがあったら原著をあたってください。

Foreword by Royal Hansen (Vice President, Security Engineering)

SRE モデル(DevOps の SRE-like version)が一般的になるにつれ、SRE が取り組んでいる問題領域は、同様の原動力をセキュリティの問題にももたらすのではないかと気づいた。いくつかの組織はこの2つを "DevSecOps" と呼ばれるアプローチに統合している。

SRE と security engineer には似たところが多い。SRE はチーム間を結びつけるモデル(error budget などのこと?)を作ったが、security engineer にも同様のものが必要。Hansen 氏とその同僚は、セキュリティは first-class であるべきと主張してきた。大企業内でのセキュリティに対するアプローチはこの20年間で劇的に変わった。

SRE が信頼性をソフトウェアのライフサイクルに組み込んだように、セキュリティもソフトウェアのライフサイクルに組み込むことが重要と思う。

Foreword by Michael Wildpaner (Senior Director, Site Reliability Engineering)

Site Reliability Engineering と Security Engineering はシステムの可用性を保つことに関係している。セキュリティインシデントはユーザーの信頼を壊し、システムの可用性を壊す。システムセキュリティは SRE の心の常にトップを占める。

Gmail の SRE テックリードの一人だったときに、SRE が、悪い設計や悪い実装によるセキュリティへの悪影響を防ぐ最後の壁として働くのを目にした。

Google の SRE に関する過去の2冊の書籍は、信頼性とセキュリティの交点(intersection of reliability and security)についての詳細は触れなかった。本書はそのギャップを埋め、セキュリティに特化したトピックにも紙面を取っている。

Preface

本書の目的は、セキュリティと信頼性に特化した実践者からの、システム設計、実装、およびメンテナンスに関する知見を提供すること。

We argue that everyone should be thinking about the fundamentals of reliability and security from the very beginning of the development process, and integrating those principles early in the system lifecycle.

私達は、すべての人々がその開発プロセスの初期から、信頼性とセキュリティの基盤について考え、それらの原則をシステムライフサイクルに統合すべきと強く考えている。

Because security and reliability are everyone’s responsibility, we’re targeting a broad audience: people who design, implement, and maintain systems. We’re challenging the dividing lines between the traditional professional roles of developers, architects, Site Reliability Engineers (SREs), systems administrators, and security engineers.

セキュリティと信頼性は全員の義務であるという考えから、本書は広い範囲の読者を対象としている。私達は従来の役割の線引き(開発者、アーキテクト、SRE、システム管理者、セキュリティエンジニア)を超えた話をしようとしている。自分のいまの立場とは関係なく、それぞれの立場に立って読んでみてほしい。

Chapter 1 と 2 を最初に読み、そのあとはあなたが最も興味を持った章を読むことをお勧めする。

Chapter 1. The Intersection of Security and Reliability

Google で2012年に起きた、社内システムの障害の事例。ある WiFi パスワード変更の告知がきっかけで、社内向けのパスワードマネージャ(数年前に作られたまま放置状態)に想定外の高負荷がかかりダウン。その信頼性の低さに反して、サーバ再起動のためのセキュリティが厳重で、最終的に金庫を電動ドリルで開けて HSM を取り出す羽目になった。

セキュリティと信頼性は、真に信用に足るシステムの重要な構成要素だが、セキュリティと信頼性の両方を満たすシステムを作るのは難しい。共通点もあるが、設計時に考慮すべき点は異なる。両者の微妙な連携が崩れると予想外の結果が生じる。

信頼性を上げるための設計が、セキュリティに影響する。トレードオフがある。冗長性を上げると攻撃対象が増える。インシデント対応のためにログの情報量を増やすと、ログも攻撃の対象になりうる。

Both security and reliability are concerned with the confidentiality, integrity, and availability of systems, but they view these properties through different lenses. The key difference between the two viewpoints is the presence or lack of a malicious adversary.

セキュリティと信頼性は、いずれも CIA(機密性、完全性、可用性)に関係するが、悪意ある攻撃者を想定するかどうか、という点が大きな違い。

セキュリティと信頼性は、いずれもシステムの設計から現れる特性である。いずれもシステムの設計初期から考慮しなければならないが、一見無害に思える変更で容易に壊れてしまう。その他にもいくつかの共通点がある。

  • Invisibility
    • いずれもうまく行っているときは目に見えず、問題が生じたときだけ目につく
    • いずれも、損なった場合の損害が大きい
  • Assessment
    • いずれも悪影響が起きたときのコストを評価する必要があるが、セキュリティの方はその評価が更に難しい
  • Simplicity
    • いずれも、システム設計をできるだけシンプルに保つことで達成しやすくなる
  • Evolution
    • 市場の要求に答えるための機能追加などによりシステムは徐々に複雑になり、その影響は読みづらい
    • セキュリティに関しては攻撃手段も日々進化する
  • Resilience
    • システムが複雑になるにつれ、システムが回復性を持つと証明することは難しくなっていく
    • Defense in depth(多重防御、縦深防御)、Distinct failure domains(障害の影響範囲の明確化)、The princeple of least privilege(最小限の権限の原則)などで脅威による影響を狭める
  • From Design to Production
    • 本番へのデプロイ後も設計を維持する必要がある。コードレビューや共通フレームワークの活用、テスト、デプロイのためのシステムでそれを助ける
  • Investigating Systems and Logging
    • セキュリティと信頼性を完全に維持することは難しいため、それが崩れたときに検知する仕組みが必要
    • 検知のためにはログは多く、詳細なほどいいが、コストや情報漏えいのリスクとのトレードオフがある
  • Crisis response
    • Google は Incident Management at Google (IMAG) と呼ばれるプログラムに体系化している。IMAG はアメリカ政府の Incident Command System (ICS) をモデルにしている
    • ある危機が起きてから次の危機が起こるまでには長いインターバルがあるため、その間にスキルとモチベーションを維持するために Disaster Recovery Testing program (DiRT) を定期的に実行している。内部システム障害をシミュレートし、チームでの対処を強制する
  • Recovery
    • 障害からの復旧は迅速に行いたいが、全体に同時にデプロイすると、新たな不具合や脆弱性も同様に全体へデプロイされる危険がある
    • 変更を段階的にデプロイし、問題が起きたらすぐ発見できる仕組みが必要

Chapter 2. Understanding Adversaries

実際の攻撃者の分類についての詳細な解説。古典的なイメージのハッカーから離れて、実際の攻撃者、国家的な組織や犯罪者などについて詳しく知ることで、防御について考えることができる。

また、インサイダー(内部関係者)によるリスクにかなりのページを割いている。悪意あるインサイダーだけでなく、操作ミスなどによる影響もここに含む。Table 2-1. General categories of insiders and examples と Table 2-2. Framework for modeling insider risk はこのテーマについて話すときの必須資料になりそう。

インサイダーへの対策として、以下のコンセプトを取り上げている。これらは3章以降で詳しく説明される。

  • Least privilege
  • Zero trust
  • Multi-party authorization
  • Business justifications
  • Auditing and detection
  • Recoverability

攻撃者について理解するために、攻撃方法についての知識を得る方法を紹介している。

  • セキュリティファームによる threat intelligence(脅威情報)
    • 攻撃者やマルウェアの分析レポート、Indicators of compromise (IOCs)
  • Cyber Kill Chain (TM)
    • 攻撃者の行動を、攻撃者が最終的な目標達成までに取るステージという形で理解するためのフレームワーク
  • 攻撃方法をカタログ化したフレームワーク

著者らが見出した、リスクを評価する上での心構え。

  • You may not realize you’re a target. (自分たちが狙われる明確な理由はなさそうでも、他の攻撃の土台としてターゲットになりうる)
  • Attack sophistication is not a true predictor of success. (複雑な攻撃方法を気にするより、基本的な攻撃方法から対処せよ)
  • Don’t underestimate your adversary. (攻撃者があなたにかける労力を過小評価するな)
  • Attribution is hard. (攻撃者を特定しようとはせずに、攻撃者の取りうる行動、TTP への対処に集中せよ)
  • Attackers aren’t always afraid of being caught. (攻撃者は国をまたぐことも多く、もし特定できても逮捕は難しい)

ここまでの感想

自分の経験上も SRE とセキュリティって強い関連性があると思います。たいていの会社ではセキュリティエンジニアって希少で、セキュリティ上の問題が起こると SRE は必ず何らかの形で動くことになるんじゃないでしょうか?

本書の序文でもセキュリティエンジニアについて言及されていましたが、ここまで読んだ限りでは、ここから SRE とセキュリティエンジニアの連携の話が始まるのか、SRE がセキュリティエンジニアの役割を兼ねる話が始まるのかはよくわかりませんでした。あと、いわゆる情シスとの関係ってどうなんでしょう? Chapter 3 以降で詳しい話が出てくると思うので、この先が楽しみです。

本書は全体的に具体例が多く、読んでいて飽きないです。ただ、その分、読んでいると余計なことをいろいろ考えてしまいます。

特に、Chapter 1 の冒頭にあるパスワードマネージャの障害の話。勝手な想像ですけど、最初はなにかの片手間で作ったようなシステムが、いつの間にか全社で使われるようになって、あとから社内監査で文句を言われてセキュリティが強化された、とかですよねきっと……。具体例があるあるすぎて、つい我が身を振り返ってしまいます。

次は?

Chapter 6 と 21 あたりが気になってます。次は、これらの章か、Chapter 6 の前提知識になりそうな Chapter 3〜5 あたりを読んでいこうと思います。

  • Chapter 6. Design for Understandability
  • Chapter 21. Defining a Healthy Security and Reliability Culture

目次を読むだけでも刺さる単語がいくつか出てきて、自分の現場にも持ち帰れる知見がありそうです。

Ansible で文字列比較の結果を boolean 変数に代入する方法

f:id:muziyoshiz:20160331232512p:plain:w300

きっかけ

今回は、時々つまづく Ansible の変数の仕様に関するメモです。

最近、Amazon Linux 1(そろそろ完全に廃止しないといけない……)と Amazon Linux 2 で処理を分岐させたいことがあり、同僚にこういう書き方でできるよと教えてもらいました。

- name: Task for Amazon Linux 2
  debug: msg="Task for Amazon Linux 2"
  when: (ansible_distribution_file_variety == "Amazon" and ansible_distribution_major_version == "2")

以前は ansible_distribution_major_version がいずれも NA になっていたようなのですが、現在は Amazon Linux 2 なら "2" が返されるようです。

ただ、毎回この長い when を書くのは面倒なので、以下のように playbook の冒頭で定義するようにしてみました。

- hosts: hogehoge
  vars:
    amzn2: (ansible_distribution_file_variety == "Amazon" and ansible_distribution_major_version == "2")
  tasks:
    - name: Task for Amazon Linux 2
      debug: msg="Task for Amazon Linux 2"
      when: amzn2
    - name: Task NOT for Amazon Linux 2
      debug: msg="Task NOT for Amazon Linux 2"
      when: not amzn2

しかし、この書き方をすると、以下の DEPRECATION WARNING が出てしまいます。

TASK [Task for Amazon Linux 2] ***************************************************************************************
[DEPRECATION WARNING]: evaluating (ansible_distribution_file_variety == "Amazon" and
ansible_distribution_major_version == "2") as a bare variable, this behaviour will go away and you might need to add
|bool to the expression in the future. Also see CONDITIONAL_BARE_VARS configuration toggle.. This feature will be
removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [hogehoge] => {
    "msg": "Task for Amazon Linux 2"
}

TASK [Task NOT for Amazon Linux 2] ***********************************************************************************
skipping: [hogehoge]

なるほど。じゃあ、面倒ですけど、警告文にあるように |bool を書き足します。

- hosts: hogehoge
  vars:
    amzn2: (ansible_distribution_file_variety == "Amazon" and ansible_distribution_major_version == "2")
  tasks:
    - name: Task for Amazon Linux 2
      debug: msg="Task for Amazon Linux 2"
      when: amzn2|bool
    - name: Task NOT for Amazon Linux 2
      debug: msg="Task NOT for Amazon Linux 2"
      when: not amzn2|bool

すると、DEPRECATION WARNING は出なくなったのですが、実行結果が期待と真逆になってしまいました……なんで?

TASK [Task for Amazon Linux 2] ***************************************************************************************
skipping: [hogehoge]

TASK [Task NOT for Amazon Linux 2] ***********************************************************************************
ok: [hogehoge] => {
    "msg": "Task NOT for Amazon Linux 2"
}

結論

文字列比較の結果を代入する際に "{{ }}" で囲むと、文字列ではなく boolean として代入されます。DEPRECATION WARNING にある |bool は不要です。

上の例で言うと、

  vars:
    amzn2: "{{ ansible_distribution_file_variety == \"Amazon\" and ansible_distribution_major_version == \"2\" }}"

と書くと、以下のように DEPRECATION WARNING が出ず、実行結果も期待通りになりました。

TASK [Task for Amazon Linux 2] ***************************************************************************************
ok: [hogehoge] => {
    "msg": "Task for Amazon Linux 2"
}

TASK [Task NOT for Amazon Linux 2] ***********************************************************************************
skipping: [hogehoge]

実験

文字列比較の内容は何でもいいので、("1" == "1") という単純な条件式で実験します。以下の実験は、Ansible 2.9 の最新版(2.9.6)で行いました。

いろいろな方法での代入

まず、代入した値をそのまま debug モジュールで出力してみます。

playbook:

- hosts: localhost
  connection: local
  vars:
    var1: True
    var2: False
    var3: "True"
    var4: "False"
    var5: ("1" == "1")
    var6: ("1" == "1")|bool
    var7: "{{ ('1' == '1') }}"
    var8: "{{ ('1' == '1')|bool }}"
  tasks:
    - name: Print vars
      debug: msg="{{ item }}"
      with_items:
        - "{{ var1 }}"
        - "{{ var2 }}"
        - "{{ var3 }}"
        - "{{ var4 }}"
        - "{{ var5 }}"
        - "{{ var6 }}"
        - "{{ var7 }}"
        - "{{ var8 }}"

結果:

% ansible-playbook test.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match
'all'

PLAY [localhost] *****************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [localhost]

TASK [Print vars] ****************************************************************************************************
ok: [localhost] => (item=True) => {
    "msg": true
}
ok: [localhost] => (item=False) => {
    "msg": false
}
ok: [localhost] => (item=True) => {
    "msg": true
}
ok: [localhost] => (item=False) => {
    "msg": false
}
ok: [localhost] => (item=("1" == "1")) => {
    "msg": "(\"1\" == \"1\")"
}
ok: [localhost] => (item=("1" == "1")|bool) => {
    "msg": "(\"1\" == \"1\")|bool"
}
ok: [localhost] => (item=True) => {
    "msg": true
}
ok: [localhost] => (item=True) => {
    "msg": true
}

PLAY RECAP ***********************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
変数名 代入方法 結果
var1 True を代入 boolean true
var2 False を代入 boolean false
var3 "True" という文字列を代入 boolean true
var4 "False" という文字列を代入 boolean false
var5 条件式を代入 条件式の文字列
var6 条件式を |bool 付きで代入 条件式の文字列
var7 条件式を "{{ }}" で囲んで代入 boolean true
var8 条件式に |bool を付けた上で "{{ }}" で囲んで代入 boolean true

条件式を "{{ }}" で囲めば、その結果が boolean として代入されるし、囲まなければ文字列として代入されることがわかります。いずれにせよ、代入の時点で |bool の有無は全く関係ないようです。

when 節への文字列の渡し方

代入時に boolean になっている場合は当然成功するので、ここからは代入時に文字列になってしまった場合のみを考えます。

|bool の有無と、結果が True になるかどうかの4通りで実験しました。Playbook が長くなるので、以下には var1 のタスクだけ記載しています。

---
- hosts: localhost
  connection: local
  vars:
    var1: ("1" == "1")
    var2: ("1" == "1")|bool
    var3: ("1" == "2")
    var4: ("1" == "2")|bool
  tasks:
    - name: 1. var1 should be printed
      debug: msg="{{ var1 }}"
      when: var1

    - name: 2. var1 should NOT be printed
      debug: msg="{{ var1 }}"
      when: not var1

    - name: 3. var1 should be printed
      debug: msg="{{ var1 }}"
      when: var1|bool

    - name: 4. var1 should NOT be printed
      debug: msg="{{ var1 }}"
      when: not var1|bool

    - name: 5. var1 should NOT be printed
      debug: msg="{{ var1 }}"
      when: not (var1|bool)

    - name: 6. var1 should be printed
      debug: msg="{{ var1 }}"
      when: "{{ var1 }}"

    - name: 7. var1 should NOT be printed
      debug: msg="{{ var1 }}"
      when: "{{ not var1 }}"

# Template error
#    - name: 8. var1 should NOT be printed
#      debug: msg="{{ var1 }}"
#      when: not "{{ var1 }}"

    - name: 9. var1 should be printed
      debug: msg="{{ var1 }}"
      when: "{{ var1|bool }}"

    - name: 10. var1 should NOT be printed
      debug: msg="{{ var1 }}"
      when: "{{ not var1|bool }}"

    - name: 11. var1 should NOT be printed
      debug: msg="{{ var1 }}"
      when: not "{{ var1|bool }}"

結果はこうなりました。

% ansible-playbook test.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match
'all'

PLAY [localhost] *****************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [localhost]

TASK [1. var1 should be printed] *************************************************************************************
[DEPRECATION WARNING]: evaluating u'var1' as a bare variable, this behaviour will go away and you might need to add
|bool to the expression in the future. Also see CONDITIONAL_BARE_VARS configuration toggle. This feature will be
removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [localhost] => {
    "msg": "(\"1\" == \"1\")"
}

TASK [2. var1 should NOT be printed] *********************************************************************************
skipping: [localhost]

TASK [3. var1 should be printed] *************************************************************************************
skipping: [localhost]

TASK [4. var1 should NOT be printed] *********************************************************************************
ok: [localhost] => {
    "msg": "(\"1\" == \"1\")"
}

TASK [5. var1 should NOT be printed] *********************************************************************************
ok: [localhost] => {
    "msg": "(\"1\" == \"1\")"
}

TASK [6. var1 should be printed] *************************************************************************************
[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{
var1 }}
ok: [localhost] => {
    "msg": "(\"1\" == \"1\")"
}

TASK [7. var1 should NOT be printed] *********************************************************************************
[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{
not var1 }}
skipping: [localhost]

TASK [9. var1 should be printed] *************************************************************************************
[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{
var1|bool }}
skipping: [localhost]

TASK [10. var1 should NOT be printed] ********************************************************************************
[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{
not var1|bool }}
ok: [localhost] => {
    "msg": "(\"1\" == \"1\")"
}

TASK [11. var1 should NOT be printed] ********************************************************************************
[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: not
"{{ var1|bool }}"
skipping: [localhost]

まとめると、1番の when: varX または 6番の when: {{ varX }} の書き方をすると、DEPRECATION WARNING は出るが、想定通りの結果になりました。それ以外は、文字列の中身に関わらず同じ結果になりました。

when の書き方 var1 var2 var3 var4
1. varX ok ok skipping skipping
2. not varX skipping skipping skipping skipping
3. varX|bool skipping skipping skipping skipping
4. not varX|bool ok ok ok ok
5. not (varX|bool) ok ok ok ok
6. {{ varX }} ok ok skipping skipping
7. {{ not varX }} skipping skipping skipping skipping
9. {{ varX|bool }} skipping skipping skipping skipping
10. {{ not varX|bool }} ok ok ok ok
11. not {{ varX|bool }} skipping skipping skipping skipping

結局、この DEPRECATION WARNING で |bool を付けろ、と言っている意味はわからずじまいでした。誰か詳しい人いたら教えてください……。

[DEPRECATION WARNING]: evaluating (ansible_distribution_file_variety == "Amazon" and ansible_distribution_major_version == "2") as a bare variable, this behaviour will go away and you might need to add |bool to the expression in the future. Also see CONDITIONAL_BARE_VARS configuration toggle.. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.

過去の「Ansible のこの仕様なんなん?」と思って書いた記事

muziyoshiz.hatenablog.com

muziyoshiz.hatenablog.com

muziyoshiz.hatenablog.com

SRE NEXT 2020 の個人的おすすめセッション動画

f:id:muziyoshiz:20200127000336p:plain:w640

SRE NEXT 2020 のセッション動画が公開されました!

SRE NEXT 2020 の参加者には、2/23(日)に「SRE NEXT 2020 参加者特典のご案内(セッション動画限定公開)」という Subject のメールが届いていると思います。

このメールに書かれている YouTube の URL から、全セッションの動画を見ることができます!

いい機会なので、今回は SRE NEXT 2020 のセッションのなかから、個人的に動画を見ることをおすすめしたいものをご紹介します。これらの動画は3月中旬以降に一般公開される予定ですので、SRE NEXT に参加されていなかった方はひとまずプレゼン資料を読んでお待ちください 🙇

※2020-03-16追記
動画の一般公開が始まりましたので、この記事にも、セッション動画へのリンクを追加しました。

今回のおすすめの基準

有志の方がまとめてくださった 【SRE Next 2020】発表資料まとめ - Qiita から辿って、プレゼン資料を一通りすべて読みました。

そして、そのなかで自分が特に参考にしたいと思った(=僕の現状にマッチした)セッションの動画を 1.5 倍速で再生して見まくりました。今回は、その中で特に参考になったものをおすすめとしてご紹介します。ちなみに、全員見ていそうな基調講演やパネルディスカッションは除外しました。

今回ご紹介していないセッションについても、どれも濃い内容でしたので、一通りスライドを読んで、興味のあるキーワードを含むセッションの動画を見てみることをおすすめします。

※2020-03-16追記
SRE NEXT 公式サイトのタイムテーブルにも、各セッションのスライドと動画が表示されるようになりました。スライドを見るなら、いまはこちらから見たほうが楽です。神アプデ!

sre-next.dev

SRE 入門

[A7] サイト信頼性エンジニアリングの原則

ymotongpoo.hatenablog.com

SRE NEXT サイト内の紹介文

Google の山口さんによる講演。SRE が守るべき基本的なセオリーを1つずつ取り上げて解説されている講演で、SRE 入門としておすすめです。特にポストモーテムの重要性を詳しく解説しています。

スライドは公開されていないのですが、上記のブログ記事でその内容が詳しく紹介されています。

メルカリのマイクロサービスの事例

個人的に、メルカリのマイクロサービス化は先進的な事例として以前から注目しています。今回も非常に勉強になりました。

メルカリの SRE は、マイクロサービスの基盤を担当する Microservices Platform チームと、サービス開発者と協働する SRE チームに分かれているのですが、SRE NEXT 2020 ではそれぞれのチームの方による発表がありました。

[B7] SRE Practices in Mercari Microservices

SRE NEXT サイト内の紹介文

Microservices Platform チームのテックリードの deeeet さんによる講演。

Microservices Platform チームの活動でどういうことを工夫しているかを、SLI/SLO, On-call, Toil という3つの観点から紹介されていました。個人的にはこちらが今回のベストセッションでした!

以下は内容のメモです。

  • そもそもなぜメルカリがマイクロサービス化を進めているか
    • Successful Software Developmentの三角形
      • マイクロサービス化によって可能になることをシンプルな図で表しているもの
      • ArchitectureがOrganizationを可能にし、このArchitectureとOrganizationが、Processを可能にする
        • 実現したいのはProcess=Continuous delivery/deployment
      • マイクロサービスはその技術だけじゃなく、どういう組織を作るかということが重要
    • SRE と Platform Team の違いを KPI から説明
      • SRE は、SLI/SLO を KPI として追ってる
      • Platform Team は、deploy/developer/day など、開発効率の指標を KPI として追ってる
    • 2つの信頼性
      • Reliabilities for platform → 講演前半の話
      • Reliabilities for microservices → 講演後半の話
  • SLI/SLOを導入するにあたって重要だと考えている点
    • 適切なプロジェクトマネジメントが行われているかどうか。プロダクトバックログ、スプリント、といったフローに沿って開発しているかどうか
      • 好き勝手に各自が開発していたら、SLI/SLOは機能しない
    • プロダクトバックログの優先度を決める基準の一つとしてSLI/SLOが使われてこそ意味がある
  • SLI/SLO
    • SLO Document
    • ここで重要なのは Approver(s) と Revisit date
      • Approver(s): SLOを満たせなかったときに、実際に開発を止める判断をできる人
      • Revisit date: SLI/SLO を更新する日。定義した時点で Revisit dateを決めて、Google Calendarに登録してしまう
    • SLI specification と implementationを分けて書くのも良いプラクティス
      • エンジニアだと how を先に考えがちだが、what を先に考えるべき
    • このドキュメントを GitHub に置いて、GitHub のプルリクで更新
    • SLO Documentの具体例:Spinnaker(Platformチームが、社内のエンジニアに提供するサービス)
      • マイクロサービスのデプロイの基盤として使っている
      • Spinnaker に対する SLO を設定している
        • パイプラインの成功率、パイプラインの実行時間
    • SLI/SLO の revisit meeting
      • 社内の Slack に対するエゴサーチと、開発者に対する Google Form でのアンケート
      • SRE Workbook の SLO Decision Matrix に従って SLO を更新している
  • On-call
    • オンコールを誰がするかは、マイクロサービスによってどういう組織に作っていきたいかによる
    • メルカリでは、運用を含めたソフトウェアサイクルを自分たちで回せる、クロスファンクショナルなチームを作っていくこと。だからサービスチームがオンコール対応する
      • 100個くらいあるマイクロサービスを運用チームが見るのは現実的に不可能
    • k8s のネームスペースを、サービス用と、基盤用で分けている。そこを責任分界点にしている
    • アラートの設定基準
      • RED でアラート、USE で調査
      • Actionable Alert=Alert 1個につき、必ずPlaybookを1個用意する
        • コンポーネントのPlaybookもGitHubで管理している
  • Toil
    • 自分たちはあまりToilという単語を使っていなくて、外部要因で発生するタスクのことをReactive Taskと呼んでいる
      • Toilもその1つとして扱っている
      • サービスが成長し続ける限り、reactive taskはゼロにはならない、ということを念頭に置くのが大事
    • PlatformチームがReactive Tasksへの向き合い方をどう変化させてきたか?
  • マイクロサービスのreliabilityのために僕らが取り組んでいること
    • Platformチームがベストプラクティスを提供し、サービスチーム自身がソフトウェアサイクルを回せるようになってもらう(self-service)
    • 2つのベストプラクティス:Design Doc, Production Readiness Check
      • マイクロサービスの開発前にDesign Docを書いてもらう(テンプレートを提供している)
      • 本番運用のために、アプリケーションが満たすべきことをチェックリスト(Production Readiness Check)で確認
        • Production Readiness Checkは、GitHubのissue templateとして準備している
        • サービスチームはリリース前にissueを作り、それを自分たちでチェックして、そのレビューをSREなどに依頼できるようになっている

[C1] 絶え間なく変化するメルカリ・メルペイにおけるSREの組織と成長

SRE NEXT サイト内の紹介文

前半はメルカリの SRE チームの EM を担当されている渋谷さん、後半はメルペイの SRE の EM を担当されている高木さんによる講演。ちなみに、渋谷さんは SRE NEXT 2020 のコアスタッフとして Web サイトなどを担当してくれました。

前半の講演のなかで、SRE チームのこれまでの組織体制と、今年の1月に行われた SRE チームの編成のマイナーアップデートについてご紹介されていました。僕は前半の組織体制の話について、興味深く聞きました。

以下は前半の内容のメモです。

  • メルカリ・メルペイそれぞれのチーム体制
    • SREチームとMicroservices Platformチームの住み分け
    • SREもマイクロサービス化に貢献している→chocon(チョコン)というプロクシを開発
  • メルカリのマイクロサービス移行の進捗 (2019年冬) - Mercari Engineering Blog
  • いままではSREが本番環境を支えるいわば「門番」だった
    • 門番モデルではSREチームがボトルネックになるリスクがある
    • マイクロサービス化により開発チームのスケーラビリティが上がっていくのに追従していけるよう、SREチームの体制もアップデートしたいと考えた
  • 今月(2020年1月)から、SREチームの編成をマイナーアップデートした
    • SRE Core:DatastoreやMail/SMS deliveryなどの共通基盤を担う
    • SRE Edge:クライアントから直接リクエストを受ける部分に近いCDN、ロードバランサ、ゲートウェイなどを担う
    • SRE Advocacy:マイクロサービス開発チームの一員として、信頼性向上やオペレーションを担う

負荷テスト

[B2] 計画的に負荷リスクを排除するためのキャパシティプランニング

SRE NEXT サイト内の紹介文

タップル誕生の SRE の赤野さんによる講演。

負荷試験の実行環境を、バックエンドエンジニアなら誰でも作れるようにセルフサービス化しています。さらに、その負荷試験の結果を施策の導入可否にまで影響させているとのこと。ここまで実現しているのは本当にすごい!

以下は内容のメモです。

  • タップルSREが負荷的な観点でのセキュアベースになるための取り組み
  • 定期的に負荷試験を実施できる環境づくり
    • 負荷試験用のAWSアカウントを別に用意
      • できるだけ本番環境に影響が出ない、という安心感を得るため
      • LocustクラスタをFargateで稼働
      • バックエンドエンジニアなら誰でも負荷試験環境を構築できるようにスクリプトを整備
    • 限界値を把握するためのロードテスト、スパイクテスト
      • いくつかのテストの種類
      • ECSタスク数ごとのスパイク限界値を測定→予定されたスパイクアクセスに対応できるか確認したいため
      • 性能劣化をチェックするテスト→SREは実施前のテスト計画のレビューと、テスト結果のレビューのみしている
    • SREが決めたSLOはあったが、UXを考慮したSLOではなかった
    • レイテンシSLOを決めるにあたって、API遅延体感チェック会を実施
      • SLOを満たさない場合はリリースしないようにしたい、という目的でこの会を開催した
      • 「全体リクエストのレイテンシのp90が223ms以下で、1ヶ月のうち99%以上稼働」に決定
      • 現在もこのSLOで運用している
  • 施策開発フローに負荷レビューを組み込む
    • 施策のロードマップを立てた段階で、SREが、負荷の観点から実現可能かをチェック
    • すべての施策についてはレビューしきれないので、「DAU増加」か「カードのフリック数の増加」を狙いとした施策のみレビューしている
    • レビューに必要な情報はプランナーに提出してもらっている
    • PUSHについてはレビュー結果をもとに、ECSタスク数や、PUSHを分割する・しないを判断する

障害対応

[A3] freee のエンジニアは障害から何を学び、どう改善しているのか?

SRE NEXT サイト内の紹介文

freee の SRE 坂井さんによる講演。過去に発生した障害をきっかけに、障害対応フローをどのように整備したかを解説してくださいました。自分たちの障害対応フローを見直すうえで、とても参考になりそうです。

以下は内容のメモです。

  • 今日のゴール
    • 障害対応に課題を感じている人が、改善のための第一歩を踏み出そうと思えるようになること
  • freeeのプロダクトは、お金や人に関する情報を扱うものが多い
    • 会計freeeは電子決済等代行業に当たる
    • 2019年に上場し、以前にも増して、障害に対してよりシビアな対応が求められる
  • 障害をゼロにすることは難しい
    • 障害を受け入れながらも、安定したプロダクト、という相反するものを目指す
  • 自分が入社した頃(2016年)から、障害対応フローがどう変わってきたか
    • 徐々にポストモーテムを書くようになるが、フォーマットや情報の粒度、書く場所もバラバラ → 障害対応の学びが属人的
    • SOC1取得に向けた準備を始めた2018年に、準備の一環で障害対応フローが策定された(レベル1〜5の障害定義など)
    • 2018年10月(月末)に起きた障害で全サービス停止
    • 障害から得られた組織としての学び
      • 障害対応フローのブラッシュアップ(初動対応、役割、社内外コミュニケーション)
      • 障害対応エリアの設置(物理的に集まれるエリア「ブリッジ」)
      • 初動の省力化(チャットボットでのドキュメント検索、ポストモーテムの自動作成、関係者への通知の自動化)
  • 振り返りのためのいろいろな取り組み
    • freeeの開発文化「失敗して攻めよう」
    • 失敗.js
    • 割れ窓を改善し隊
    • alertを振り返り隊(今年から始めた新しい取り組みで、成果が出るかはこれから)
  • まとめ
    • 自分たちの組織やプロダクトに合った障害対応フローを作る
    • 大きな障害は学びの宝庫
    • 障害からの学びが属人的にならないように工夫する

SLI/SLO

[C4] SLO Review

SRE NEXT サイト内の紹介文

Quipper の SRE であり、SRE NEXT 2020 のコアスタッフでもあった chaspy さんの講演。

2019年に Quipper 社内で SLO をどうやって徐々に導入していったか、という事例紹介です。内容ももちろん勉強になるんですが、chaspy さんはとにかく話がうまくて、聞いてて面白いです。

以下は内容のメモ。

  • 最近受講した:Coursera の Site Reliability Engineering: Measuring and Managing Reliability コース
  • エラーバジェット導入に向けて、SLO導入をどういうステップを踏んで実現したか
    • エラーバジェット導入は今後の課題
  • reliabilityとagilityのバランスを取るためのツールがSLO
    • マイクロサービスに取り組むなら必須のツール
    • 依存先のサービスの信頼性を、依存元が超えることはできない
  • Quipperでのケーススタディ
    • いろいろなツールでメトリクスを取り、すべてをDataDogに送っている
      • Synthetics Clients:Pingdom
      • Frontend:Centry
      • Load Balancer:Nginx, envoy
      • Application:New Relic
    • 今年のSREチームの目標:Self-Contained
      • 開発チームが自分たち自身のみでプロダクト開発を完結できること、を目指している
      • そのための支援をSREチームがしていく
      • すでに提供している:Design Doc、Production Readiness Check、インフラ管理の移譲(Terraform)
      • その延長でSLI/SLOにも取り組んでいる
    • 2019年に行った取り組み
      • Define the Ownership
        • 多拠点に複数の開発チーム。各マイクロサービスに誰がオーナーシップを持つのかの定義から
        • Design Docでステークホルダーを明確化(Design DocはSREがレビューする)
        • オーナーを決める文化が根付いてきたので、この活動はおすすめ
      • SLO review by myself
        • まずは自分(chaspyさん自身)でやってみた
        • 誰でもできる方法
          • 週1でSlackにリマインダを飛ばして、その時点でのSLIをDataDog上で確認し、GitHub Issueに記録する
        • Availability Table、どれくらいの稼働率が良いのかの肌感を得た(99.9%くらいが良さそう)
        • SLO reviewや、ペアプロやユニットテストのような「良い習慣」なのではないかと気づいた
      • SLO review with Devs
        • 開発者からいろいろ要望が出てきて対応した
          • Dos detector(Rate limitting)がSLIのノイズになる
          • マイクロサービスで同じドメイン名を共有している(パスは違う)場合に、ログにパスを付与
      • Set Error Budget Policy
        • 今年の4月くらいからエラーバジェットを決めて、エグゼクティブと合意してやっていけたらと思ってる
  • SLO導入に向けておすすめするポイント
    • 最初のSLIはSREが設定したほうがいい。プロダクトに詳しいのは開発者だが、今取れる情報についてはSREのほうが詳しい
      • AvailabilityやLatencyなど、当然見ると思われるものを最初に設定しておけばよかったと反省している
    • SLI/SLOの設定もコードしたほうが良い(Terraform)
    • 少ない時間で成果を出すことを意識する
      • ドキュメントを最初から書いておけば楽だったと思う
      • 15チームにそれぞれ説明して、徐々に導入していった

開発者と SRE

[C6] Designing fault-tolerant microservices with SRE and circuit breaker centric architecture

SRE NEXT サイト内の紹介文

Cookpad の海外チームの SRE を担当している渡辺さんによる講演。

この講演での話題は、新しい技術スタック(機械学習関係)を採用した、試作的なプロダクトを導入するケースです。その試作的なプロダクトがメインのサービスに与える影響の範囲を限定しつつ、どうやって試作を行うチームの生産性を損なわないようにしたか、という事例紹介でした。

マイクロサービスの特徴がうまくマッチした事例として、こういうケースがあるのか!と参考になりました。

以下は内容のメモです。

  • Cookpad Global(Cookpad のグローバルサービス)
    • 23 backend developers
    • 5 SREs
  • Search-v2, ML APIs:新規機能、実験的な機能
    • これを入れていくときのアプローチについての講演
    • 特殊な状況での事例紹介
  • 独立性の高いチームと、既存のチームの間での衝突を少なくするために、circuit breaker、SLOを導入している
  • technology stackをcookpadでは制限している
    • しかし、新しい機能では、rails以外の言語を使う必要が出てきた
  • 24/7サポートには8人のエンジニアが欲しい。いろいろな本で8人と書かれている
  • 関係者の間での調整のためにdesign documentを書く
  • それにプラスアルファで、目的別の対策
  • Delegation and resource isolationも必要
    • AWSアカウントを分離して、VPC peering
    • 自分たちが使う技術の範囲は自分たちで運用する(SREが管理するのではなく、MLのdevelopersが管理する)
  • circuit breaker
    • Traefik
    • SLOに応じて設定。そのSLOはDesign Docで調整
  • 開発者がSLOを決めるのは難しい。だからSREがavailability classを提供している
    • availability classを定義し、それぞれのサービスの目標値を決める。それをcircuit breakerの設定に反映させる
  • PrometheusとAlertmanagerのコンフィグはJsonnetで書いている
    • よく使う設定はSREがライブラリ化してる
  • Search-v2についてはオンコール対応不要にした
    • 動かないときはSearch-v1にフォールバックするようにした
  • Bonus Track
    • オンコールローテーションルールは、そのチームのメンバーの好き好きによって決めるべきで、組織全体の統一ルールを作るべきではない
    • Cookpadのバックエンドエンジニアは世界中にいるので、1日を午前午後で分けて、営業時間内だけオンコール対応している
    • SREも日本とイギリスで分散しているので、同様にローテーションしている

[D4] 100万回線のIoT通信を支えるソラコムにおけるOpsDevの実践

SRE NEXT サイト内の紹介文

ソラコムの OpsDev エンジニア(DevOps エンジニアの誤記じゃないです)の酒井さんによる講演。開発者が全員で運用し、サポートまで行う現場の事例紹介でした。

以下は内容のメモです。

  • OpsDev Engineer≒SRE
  • 開発と運用の基本原則
    • 開発者:全員がDevOpsを実践。運用もする
    • OpsDevエンジニア(≒SRE):運用作業の傍ら、運用作業省力化のための開発をする
    • チーム全体で運用に責任を持つ
  • 運用しやすいシステムを作るための基本的な原則
    • Horizontal Scalability:小さいサーバを横に並べることでスケールアウトできる設計
    • Built-in Resilience:障害を前提とした設計、障害が起きたシステムを単独でプロセス再起動できる設計
  • サポートプライマリ制度:サポート・運用タスクについてはエンジニアが交代制で対応する
    • お客様と直接コミュニケーションすることで改善点に気づける、モチベーションが上がる、自身の問い合わせスキルが上がる
  • 一部のエンジニアは嫌がるのでは?トレードオフがあるのでは?
    • ソラコムのリーダーシップステートメントで、上記のような行動を推奨
      • リーダーシップステートメントに沿って行動することで評価も上がる
    • サポート・運用タスクのタスクコントロールを工夫
  • インシデント対応
    • なにか怪しいことがあったら #andon チャンネルで報告。間違った報告でも責めない
    • チャットボットで障害対応をサポート(障害報告書のひな型作成など)
    • ポストモーテム:2週間のイテレーションの最後に関係者全員で andon 振り返り

ちなみに、過去に SRE Lounge #8 で酒井さんの講演を聞いたことがあって、その時の内容を以下の記事にまとめています。SRE NEXT の講演に含まれていない内容もありますので、興味が湧いた方はこちらもどうぞ。

muziyoshiz.hatenablog.com