2021/12/09のペパボテックカンファレンスで発表した内容です。
15年以上動くECシステムをクラウドネイティブにするためにやっていること2021.12.09 Pepabo Tech Conference #18ペパボECテックカンファレンス1
View Slide
1. カラーミーショップの可用性における課題2. 課題解決のためにはクラウドネイティブ化が必要だった3. やってきたこと1. 複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト2. VM時代のアーキテクチャをKubernetes上で活かすために4. おわりに2アジェンダ
カラーミーショップの可用性における課題3
4自己紹介技術部 技術基盤チーム2019年 中途入社高橋 拓也 Takahashi Takuyaインフラエンジニア(プライベート|ハイブリッド)クラウドのあれこれやサービスの可用性を上げること全般を担当● Twitter : @takutaka1220● GitHub: takutakahashi
5カラーミーショップの可用性における課題● 障害が発生すると...○ お客様の利益を奪ってしまう○ サービスのプレゼンスを損なってしまう○ CS の方々の顧客対応の時間を増やしてしまう○ エンジニアの工数を奪ってしまう○ なぜ守ってあげられなかったんだ... と夜も眠れなくなる○ またなにか障害が起こってしまうのでは... と夜も眠れなくなる障害っていやですよね
6カラーミーショップの可用性における課題● お客様に影響の出ない範囲での障害○ プラットフォームのハイパーバイザ故障によるインスタンス数の低下○ ログパーサが失敗しログ集約サーバへの転送ができなくなる● 全ショップが閲覧不可となる障害例○ ショップ閲覧/決済サービスが何らかの原因により全インスタンス利用不可能になる○ LB (HAProxy が動くインスタンス) が何らかの原因により利用不可能となる大小さまざまな障害がある
7カラーミーショップの可用性における課題● 障害への備えは考えうる限り万全に実施している○ CI によるテスト自動化○ 監視、アラート設定、オンコールの実施○ 可用性に関する取り組みの強化■ アプリケーションレイヤでの取り組み強化● 前半のお話をご覧ください■ インフラ、アーキテクチャレイヤの取り組み強化● 私達の取り組みはこちら障害への対策
8カラーミーショップの可用性における課題● 障害への備えは考えうる限り万全に実施している○ CI によるテスト自動化○ 監視、アラート設定、オンコールの実施○ 可用性に関する取り組みの強化■ アプリケーションレイヤでの取り組み強化● 前半のお話をご覧ください■ インフラ、アーキテクチャレイヤの取り組み強化● 私達の取り組みはこちら障害への対策アプリケーションレイヤでの取り組みにより障害の種が少しずつ取り除かれている
9カラーミーショップの可用性における課題● 障害への備えは考えうる限り万全に実施している○ CI によるテスト自動化○ 監視、アラート設定、オンコールの実施○ 可用性に関する取り組みの強化■ アプリケーションレイヤでの取り組み強化● 前半のお話をご覧ください■ インフラ、アーキテクチャレイヤの取り組み強化● 私達の取り組みはこちら障害への対策どんな障害が発生しても早急に復旧できる環境を整備する必要があるこれがインフラで解決したい課題
10カラーミーショップの可用性における課題● 障害の影響度 = 発生ポイントの重要度 * 障害発生率 * 影響範囲 * 復旧時間● 発生ポイントはハンドリング不能と仮定する● 障害発生率はアプリケーションレイヤでの施策が進行中● インフラでは、影響範囲を狭く、復旧時間を短くすることで影響度を最小化する予測不可能な障害への対応策
11カラーミーショップの可用性における課題● 障害の影響度 = 発生ポイントの重要度 * 障害発生率 * 影響範囲 * 復旧時間● 発生ポイントはハンドリング不能と仮定する● 障害発生率はアプリケーションレイヤでの施策が進行中● インフラでは、影響範囲を狭く、復旧時間を短くすることで影響度を最小化する予測不可能な障害への対応策目的達成のために、 ShopSet という仕組みを作って運用することにした
12カラーミーショップの可用性における課題● ショップの閲覧から商品購入までのコンポーネントをまとめた単位● これらを Kubernetes (k8s) 上で動作させるShopSetについて軽く説明ShopSetshop servicecart servicecolorme api servicereverse proxy
13カラーミーショップの可用性における課題● 10% のリクエストを一部の ShopSet に送信してカナリアリリースShopSetについて軽く説明ShopSet 1 ShopSet 210% 90%
14カラーミーショップの可用性における課題● (プライベート|パブリック)クラウドで冗長構成ShopSetについて軽く説明ShopSeton-premShopSeton EKS50% 50%
15カラーミーショップの可用性における課題● 商品閲覧から購入に関わる全システムを Kubernetes (k8s) 上に構築● 全システムのまとまりを ShopSet と名付ける● Operator により ShopSet の構築コストを限りなくゼロにするShopSetについて軽く説明
16カラーミーショップの可用性における課題● k8s 上に ShopSet を管理してくれる Operator をデプロイする● Operator は ShopSet リソースを解釈し適切なリソース群をデプロイする● 人間は ShopSet リソースをデプロイするだけで全ての管理が完結するようになるOperator により ShopSet の構築コストを限りなくゼロにするk8soperatorshop cart proxyshopsetwatchdeployapi
17カラーミーショップの可用性における課題● 商品閲覧から購入に関わる全システムを k8s 上に構築○ カラーミーショップはショップ閲覧、カート機能など複数のシステムに分かれている● 全システムのまとまりを ShopSet と名付ける● Operator により ShopSet の構築コストを限りなくゼロにするShopSetについて軽く説明ShopSet の実現のためには、 Operator の存在が不可欠カラーミーショップを k8s に載せていくぞ!
18カラーミーショップの可用性における課題● ShopSet の Deep Dive な内容は以下の資料をご覧ください● https://speakerdeck.com/takutakahashi/karamisiyotupufalse-ke-yong-xing-xiang-shang-falsetamefalse-inhurashua-xinShopSetについてもっと知りたい方は
カラーミーショップをk8s で動かすために必要なことは?19
20カラーミーショップを k8s で動かすために必要なことは?● 現行システムは仮想マシン (VM) で動いている● VM と同じ考え方を k8s に持っていくと良くないことが起こる○ コンテナには ssh できない!○ IP がコロコロ変わる!○ プロセスが死ぬことは当たり前!○ etc...k8s で動かすことがゴールではないk8s で動作させるメリットを最大限享受できるアプリケーション構成に変更する必要がある
21カラーミーショップを k8s で動かすために必要なことは?● そもそも k8s で良く動かすためには○ システムは互いに素結合であり、Service Discovery で相互に参照する○ システムはイミュータブルである○ 不必要なステートを排除し、データはマネージドサービスで持つ○ システムをいかなるタイミングでも作成、削除されることができる状態に保つ● 上記の構成を運用しやすい状態に保ち続ける○ 障害発生時にはどこで障害が発生したのか切り分けられる○ 監視やアラートを設定できるどういう構成を追い求めるべき?
22カラーミーショップを k8s で動かすために必要なことは?● そもそも k8s で良く動かすためには○ システムは互いに素結合であり、Service Discovery で相互に参照する○ システムはイミュータブルである○ 不必要なステートを排除し、データはマネージドサービスで持つ○ システムをいかなるタイミングでも作成、削除されることができる状態に保つ● 上記の構成を運用しやすい状態に保ち続ける○ 障害発生時にはどこで障害が発生したのか切り分けられる○ 監視やアラートを設定できるどういう構成を追い求めるべき?これはつまり、クラウドネイティブであるということ
課題解決のためにはクラウドネイティブ化が必要だった23と、いうわけで
カラーミーショップをk8s で動かすためにやっていること24
25カラーミーショップを k8s で動かすためにやったこと● 個別のシステムに以下の変更を加えている (一部抜粋)○ ステートフルからステートレスのアーキテクチャへの変更■ 消失して困るファイル(データ、ログ、キャッシュ) をコンテナ内に持たない○ 固定 IP (inbound, outbound) を期待する実装の削除■ リクエストを(送る|受ける)クラスタは無限に増える○ 環境変数とテンプレートエンジンを用いた環境切り替え■ env (production, staging) の関心をコードからなくすk8s にデプロイされるシステムへの変更
26カラーミーショップを k8s で動かすためにやったこと● 個別のシステムに以下の変更を加えている○ ステートフルからステートレスのアーキテクチャへの変更■ 消失して困るファイル(データ、ログ、キャッシュ) をコンテナ内に持たない○ 固定 IP (inbound, outbound) を期待する実装の削除■ リクエストを(送る|受ける)クラスタは無限に増える○ 環境変数とテンプレートエンジンを用いた環境切り替え■ env (production, staging) の関心をコードからなくすk8s にデプロイされるシステムへの変更詳しい施策内容を一部抜粋して解説します
27複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト
28自己紹介技術部プラットフォームグループ2018年 中途入社菅原 千晶 Sugawara Chiaki2018年にWeb業界未経験でペパボカレッジ6期としてメーカー系SEから現職。カラーミーショップ担当SREとして運用改善やk8s導入・CI/CD pipeline整備などを経験。@ch1aki@ch11aki
29複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト● カラーミーショップのリバースプロキシ(Nginx)は複雑○ 1万件以上の独自ドメインのTLS終端■ ngx_mrubyで証明書管理API、Redisから動的に証明書取得○ 複数ロールへプロキシ■ 複数のアプリケーションロール■ オプションでロリポップ!MCなど○ ロールによってヘッダの変更やngx_mrubyでCookieをフィルタ○ rate limit等 複数のアクセス制限機能背景(1/2)証明書API ショップページカートAPIロリポップ!マネージドクラウド外部サイト...コンテナ化request動的証明書応答
30複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト● 並行稼働しながら緩やかに新アーキテクチャに移行するため、コンテナ化の際には既存のミドルウェア設計を踏襲する方針を選択● コンテナ化の際のテスト項目が膨大&環境用意が面倒○ 設定可能な数十個の環境変数○ 正常系に加え一部ロールの障害時に意図したフォールバックの挙動のテストのため、複数パターンの構成でコンテナを起動○ よくあるミス:環境変数名ミス、テンプレート記法ミス、ファイルの配置漏れ、etc...複数パターンの構成で、コンテナイメージと依存ロールを起動しリクエストを実行して想定通りの挙動をするかを楽にテストしたい背景(2/2)
31複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト● infrataster○ サーバーの振る舞いテストツール○ 振る舞いのテストに止まり目的に合わない&更新が止まっている?● container-structure-test○ コンテナイメージの構造をテストするためのツール○ 単体のイメージのテストに止まるため目的に合わない● Testcontainers○ 統合テスト向けにコンテナを簡単に操作可能な複数言語で実装があるライブラリ○ 利用目的が異なるため、作成したコンテナに対するテストコードが冗長になりがち既存のソリューションを調査
32複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト● Cybozu Inside Out, 複雑怪奇な nginx を Go と Docker でユニットテストする○ https://blog.cybozu.io/entry/2020/04/16/080000○ nginxをユニットテストするためにDockerとGoを利用○ testerコンテナ内でGoのテストを実行、nginxの設定をマウントしたコンテナを作成、自身がmockサーバーになりテストを実行→既存のソリューションで課題をすべて解決してくれるものはなかったが、やりたいことに一番近そうこれを参考に汎用的なコンテナイメージの振る舞いテストツールを作ることにした最終的に参考にしたもの
33複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト● テストの基本的なアーキテクチャは参考元(※)を踏襲● nginxに限らず様々なプロジェクトで利用できるように、○ go package化○ 任意のimage tag、任意の環境変数を設定可能● http mock server作成機能に加え、redis mock server作成などを追加● テスト対象コンテナへのhttpリクエストの実行をアサーションメソッドとして実装containertester(仮)※ https://blog.cybozu.io/entry/2020/04/16/080000
34複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト1. Mockサーバーを起動2. 任意の設定でコンテナを起動3. 起動したコンテナに対してhttpリクエストを実行し結果を検証以上のテストがこれだけのコードで実現containertester(仮)サンプルコードfunc TestReverseProxy(t *testing.T) {app := tester.StartMockAP(t,tester.MockApResponseBody("app server"))defer app.Close(t)nginx := tester.StartContainer(t, tester.ContainerConfig{Image: "nginx-proxy:test",Environment: map[string]string {"APP_SERVER": app.Host(),},})defer nginx.Close(t)nginx.AssertHttpGet(t, tester.ExpectedBody("app server"))}
35複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト● 設定項目や外部依存が多い複雑なミドルウェアのコンテナイメージ開発は大変● 複雑なコンテナイメージ開発を振る舞いのテストによって効率化する方法を選択● テストライブラリとして実装し、Goのテストとして記述可能にした● テストの効率・メンテナンス性・網羅性が上がった事で、今後の品質&開発生産性向上が期待できるまとめ
36レガシーなアーキテクチャをKubernetes上で活かすために
37自己紹介EC事業部 カラーミーショップグループ アプリストアチーム2019年 中途入社神﨑 拓人 Kanzaki Takutoアプリストアチームとしての活動の傍ら可用性向上プロジェクトとして主に既存アプリケーションのKubernetes化を担当。@windyakin@MITLicense
38レガシーなアーキテクチャをKubernetes上で活かすために● カラーミーショップは他ECサービスに比べてショップページの自由度が高い○ ショップオーナーがページごとにテンプレートを自由にカスタマイズできる● テンプレートエンジンは高速化のためにファイルキャッシュを吐き出す○ 中間ファイル的なものでレンダリングの高速化に使われるカラーミーショップの「テンプレート機能」ファイルストレージにキャッシュされる
39レガシーなアーキテクチャをKubernetes上で活かすために● Kubernetes 上での最小アプリケーション動作単位「Pod」○ 単体・複数のコンテナを寄せ集めて動作させている● Pod は割とカジュアルに作成・削除される○ Docker イメージを差し替えたいとき(アプリケーションのアップデート)○ Pod の台数を増やす・減らすとき(スケールアップ・ダウン)● Pod の再作成が行われるとDockerイメージに含まれるファイル以外は消える○ キャッシュファイルは Pod が立ち上がっている間だけ維持される○ 再作成後はキャッシュファイルがクリアされてしまうKubernetesでのPodのライフサイクルとファイルキャッシュは相性がよくない
40レガシーなアーキテクチャをKubernetes上で活かすために● 当初は「対応しなくてもそんなに影響ないのでは?」説が出ていた○ Pod が再作成されても Pod にアクセスがあれば徐々に溜まっていく○ 一方で Virtual Machine ではたまり続けるキャッシュに対する課題もあった● キャッシュがない状態になるとどれぐらい影響があるのか計測することに○ キャッシュがない Virtual Machine を新たに用意して本番に投入しメトリクスを取得k8s に移行した時に影響が出やすいと判断しキャッシュを活かす方法を模索することにキャッシュのライフサイクルの変更によってどれほどの影響が出るかを調査● 他VMより20〜30%ほど遅い● これが30〜40分ほど続く
41レガシーなアーキテクチャをKubernetes上で活かすために1. k8s の機能 Persistent Volume(永続ボリューム) により解決する案○ 大容量ストレージを持った Node 上にて永続ボリュームをマウントする○ それまで立ち上げていたPodの数を超えて作成すると結局キャッシュがない状態になる→ スケジューリングによる性能劣化など新たな懸念材料などが生まれてしまう2. キャッシュファイルをオンラインストレージでホストする案○ Pod にあるキャッシュファイルを定期的にオンラインストレージにアップロード○ Pod の起動時にキャッシュをオンラインストレージからダウンロードしてくる→ これを実現するアプリケーションを実装をすることにファイルキャッシュをk8s上で保持するのためのアプローチ
42レガシーなアーキテクチャをKubernetes上で活かすために● BigQuery からアクセスが多いショップを割り出す● アクセス上位のキャッシュを Amazon S3 にアップロードしていく● Pod の起動時に Init Container で Amazon S3 にあるキャッシュを落としてくるキャッシュマネージャアプリケーションの作成とリリース
43まとめ● 小さなアプリケーションの開発によって既存のアーキテクチャを活用しつつも新たなプラットフォームへの移行をすることができた● 今回お話した施策の詳細は後日ペパボテックブログにて公開予定ペパボテックブログhttps://tech.pepabo.com/
おわりに44
おわりに今後のShopSetにご期待ください● 今回紹介した取り組みはほんの一部で、他にもチームでは色々な課題を解決していっています● これからもカラーミーショップ全体の可用性の向上に向けて様々な施策を実施します 💪45
46Thank You!Thank you for listening!