Slide 1

Slide 1 text

15年以上動くECシステムを クラウドネイティブにするために やっていること 2021.12.09 Pepabo Tech Conference #18 ペパボECテックカンファレンス 1

Slide 2

Slide 2 text

1. カラーミーショップの可用性における課題 2. 課題解決のためにはクラウドネイティブ化が必要だった 3. やってきたこと 1. 複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト 2. VM時代のアーキテクチャをKubernetes上で活かすために 4. おわりに 2 アジェンダ

Slide 3

Slide 3 text

カラーミーショップの 可用性における課題 3

Slide 4

Slide 4 text

4 自己紹介 技術部 技術基盤チーム 2019年 中途入社 高橋 拓也 Takahashi Takuya インフラエンジニア (プライベート|ハイブリッド)クラウドのあれこれや サービスの可用性を上げること全般を担当 ● Twitter : @takutaka1220 ● GitHub: takutakahashi

Slide 5

Slide 5 text

5 カラーミーショップの可用性における課題 ● 障害が発生すると... ○ お客様の利益を奪ってしまう ○ サービスのプレゼンスを損なってしまう ○ CS の方々の顧客対応の時間を増やしてしまう ○ エンジニアの工数を奪ってしまう ○ なぜ守ってあげられなかったんだ... と夜も眠れなくなる ○ またなにか障害が起こってしまうのでは... と夜も眠れなくなる 障害っていやですよね

Slide 6

Slide 6 text

6 カラーミーショップの可用性における課題 ● お客様に影響の出ない範囲での障害 ○ プラットフォームのハイパーバイザ故障によるインスタンス数の低下 ○ ログパーサが失敗しログ集約サーバへの転送ができなくなる ● 全ショップが閲覧不可となる障害例 ○ ショップ閲覧/決済サービスが何らかの原因により全インスタンス利用不可能になる ○ LB (HAProxy が動くインスタンス) が何らかの原因により利用不可能となる 大小さまざまな障害がある

Slide 7

Slide 7 text

7 カラーミーショップの可用性における課題 ● 障害への備えは考えうる限り万全に実施している ○ CI によるテスト自動化 ○ 監視、アラート設定、オンコールの実施 ○ 可用性に関する取り組みの強化 ■ アプリケーションレイヤでの取り組み強化 ● 前半のお話をご覧ください ■ インフラ、アーキテクチャレイヤの取り組み強化 ● 私達の取り組みはこちら 障害への対策

Slide 8

Slide 8 text

8 カラーミーショップの可用性における課題 ● 障害への備えは考えうる限り万全に実施している ○ CI によるテスト自動化 ○ 監視、アラート設定、オンコールの実施 ○ 可用性に関する取り組みの強化 ■ アプリケーションレイヤでの取り組み強化 ● 前半のお話をご覧ください ■ インフラ、アーキテクチャレイヤの取り組み強化 ● 私達の取り組みはこちら 障害への対策 アプリケーションレイヤでの取り組みにより 障害の種が少しずつ取り除かれている

Slide 9

Slide 9 text

9 カラーミーショップの可用性における課題 ● 障害への備えは考えうる限り万全に実施している ○ CI によるテスト自動化 ○ 監視、アラート設定、オンコールの実施 ○ 可用性に関する取り組みの強化 ■ アプリケーションレイヤでの取り組み強化 ● 前半のお話をご覧ください ■ インフラ、アーキテクチャレイヤの取り組み強化 ● 私達の取り組みはこちら 障害への対策 どんな障害が発生しても早急に復旧できる環境を整備する必要がある これがインフラで 解決したい課題

Slide 10

Slide 10 text

10 カラーミーショップの可用性における課題 ● 障害の影響度 = 発生ポイントの重要度 * 障害発生率 * 影響範囲 * 復旧時間 ● 発生ポイントはハンドリング不能と仮定する ● 障害発生率はアプリケーションレイヤでの施策が進行中 ● インフラでは、影響範囲を狭く、復旧時間を短くすることで影響度を最小化する 予測不可能な障害への対応策

Slide 11

Slide 11 text

11 カラーミーショップの可用性における課題 ● 障害の影響度 = 発生ポイントの重要度 * 障害発生率 * 影響範囲 * 復旧時間 ● 発生ポイントはハンドリング不能と仮定する ● 障害発生率はアプリケーションレイヤでの施策が進行中 ● インフラでは、影響範囲を狭く、復旧時間を短くすることで影響度を最小化する 予測不可能な障害への対応策 目的達成のために、 ShopSet という仕組みを作って運用することにした

Slide 12

Slide 12 text

12 カラーミーショップの可用性における課題 ● ショップの閲覧から商品購入までのコンポーネントをまとめた単位 ● これらを Kubernetes (k8s) 上で動作させる ShopSetについて軽く説明 ShopSet shop service cart service colorme api service reverse proxy

Slide 13

Slide 13 text

13 カラーミーショップの可用性における課題 ● 10% のリクエストを一部の ShopSet に送信してカナリアリリース ShopSetについて軽く説明 ShopSet 1 ShopSet 2 10% 90%

Slide 14

Slide 14 text

14 カラーミーショップの可用性における課題 ● (プライベート|パブリック)クラウドで冗長構成 ShopSetについて軽く説明 ShopSet on-prem ShopSet on EKS 50% 50%

Slide 15

Slide 15 text

15 カラーミーショップの可用性における課題 ● 商品閲覧から購入に関わる全システムを Kubernetes (k8s) 上に構築 ● 全システムのまとまりを ShopSet と名付ける ● Operator により ShopSet の構築コストを限りなくゼロにする ShopSetについて軽く説明

Slide 16

Slide 16 text

16 カラーミーショップの可用性における課題 ● k8s 上に ShopSet を管理してくれる Operator をデプロイする ● Operator は ShopSet リソースを解釈し適切なリソース群をデプロイする ● 人間は ShopSet リソースをデプロイするだけで全ての管理が完結するようになる Operator により ShopSet の構築コストを限りなくゼロにする k8s operator shop cart proxy shopset watch deploy api

Slide 17

Slide 17 text

17 カラーミーショップの可用性における課題 ● 商品閲覧から購入に関わる全システムを k8s 上に構築 ○ カラーミーショップはショップ閲覧、カート機能など複数のシステムに分かれている ● 全システムのまとまりを ShopSet と名付ける ● Operator により ShopSet の構築コストを限りなくゼロにする ShopSetについて軽く説明 ShopSet の実現のためには、 Operator の存在が不可欠 カラーミーショップを k8s に載せていくぞ!

Slide 18

Slide 18 text

18 カラーミーショップの可用性における課題 ● ShopSet の Deep Dive な内容は以下の資料をご覧ください ● https://speakerdeck.com/takutakahashi/karamisiyotupufalse-ke-yong-xing-xiang-shang-falsetamefalse-inhurashua-xin ShopSetについてもっと知りたい方は

Slide 19

Slide 19 text

カラーミーショップを k8s で動かすために 必要なことは? 19

Slide 20

Slide 20 text

20 カラーミーショップを k8s で動かすために必要なことは? ● 現行システムは仮想マシン (VM) で動いている ● VM と同じ考え方を k8s に持っていくと良くないことが起こる ○ コンテナには ssh できない! ○ IP がコロコロ変わる! ○ プロセスが死ぬことは当たり前! ○ etc... k8s で動かすことがゴールではない k8s で動作させるメリットを最大限享受できる アプリケーション構成に変更する必要がある

Slide 21

Slide 21 text

21 カラーミーショップを k8s で動かすために必要なことは? ● そもそも k8s で良く動かすためには ○ システムは互いに素結合であり、Service Discovery で相互に参照する ○ システムはイミュータブルである ○ 不必要なステートを排除し、データはマネージドサービスで持つ ○ システムをいかなるタイミングでも作成、削除されることができる状態に保つ ● 上記の構成を運用しやすい状態に保ち続ける ○ 障害発生時にはどこで障害が発生したのか切り分けられる ○ 監視やアラートを設定できる どういう構成を追い求めるべき?

Slide 22

Slide 22 text

22 カラーミーショップを k8s で動かすために必要なことは? ● そもそも k8s で良く動かすためには ○ システムは互いに素結合であり、Service Discovery で相互に参照する ○ システムはイミュータブルである ○ 不必要なステートを排除し、データはマネージドサービスで持つ ○ システムをいかなるタイミングでも作成、削除されることができる状態に保つ ● 上記の構成を運用しやすい状態に保ち続ける ○ 障害発生時にはどこで障害が発生したのか切り分けられる ○ 監視やアラートを設定できる どういう構成を追い求めるべき? これはつまり、クラウドネイティブであるということ

Slide 23

Slide 23 text

課題解決のためには クラウドネイティブ化が 必要だった 23 と、いうわけで

Slide 24

Slide 24 text

カラーミーショップを k8s で動かすために やっていること 24

Slide 25

Slide 25 text

25 カラーミーショップを k8s で動かすためにやったこと ● 個別のシステムに以下の変更を加えている (一部抜粋) ○ ステートフルからステートレスのアーキテクチャへの変更 ■ 消失して困るファイル(データ、ログ、キャッシュ) をコンテナ内に持たない ○ 固定 IP (inbound, outbound) を期待する実装の削除 ■ リクエストを(送る|受ける)クラスタは無限に増える ○ 環境変数とテンプレートエンジンを用いた環境切り替え ■ env (production, staging) の関心をコードからなくす k8s にデプロイされるシステムへの変更

Slide 26

Slide 26 text

26 カラーミーショップを k8s で動かすためにやったこと ● 個別のシステムに以下の変更を加えている ○ ステートフルからステートレスのアーキテクチャへの変更 ■ 消失して困るファイル(データ、ログ、キャッシュ) をコンテナ内に持たない ○ 固定 IP (inbound, outbound) を期待する実装の削除 ■ リクエストを(送る|受ける)クラスタは無限に増える ○ 環境変数とテンプレートエンジンを用いた環境切り替え ■ env (production, staging) の関心をコードからなくす k8s にデプロイされるシステムへの変更 詳しい施策内容を一部抜粋して 解説します

Slide 27

Slide 27 text

27 複雑なミドルウェアを コンテナ化するための コンテナイメージ振る舞いテスト

Slide 28

Slide 28 text

28 自己紹介 技術部プラットフォームグループ 2018年 中途入社 菅原 千晶 Sugawara Chiaki 2018年にWeb業界未経験でペパボカレッジ6期とし てメーカー系SEから現職。 カラーミーショップ担当SREとして運用改善やk8s 導入・CI/CD pipeline整備などを経験。 @ch1aki @ch11aki

Slide 29

Slide 29 text

29 複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト ● カラーミーショップのリバースプロキ シ(Nginx)は複雑 ○ 1万件以上の独自ドメインのTLS終端 ■ ngx_mrubyで証明書管理API、Redis から動的に証明書取得 ○ 複数ロールへプロキシ ■ 複数のアプリケーションロール ■ オプションでロリポップ!MCなど ○ ロールによってヘッダの変更や ngx_mrubyでCookieをフィルタ ○ rate limit等 複数のアクセス制限機能 背景(1/2) 証明書API
 ショップ ページ カート API ロリポップ! マネージドクラウド 外部サイト . . . コンテナ化 request 動的証明書 応答

Slide 30

Slide 30 text

30 複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト ● 並行稼働しながら緩やかに新アーキテクチャに移行するため、コンテナ化の際には 既存のミドルウェア設計を踏襲する方針を選択 ● コンテナ化の際のテスト項目が膨大&環境用意が面倒 ○ 設定可能な数十個の環境変数 ○ 正常系に加え一部ロールの障害時に意図したフォールバックの挙動のテストのため、複数 パターンの構成でコンテナを起動 ○ よくあるミス:環境変数名ミス、テンプレート記法ミス、ファイルの配置漏れ、etc... 複数パターンの構成で、コンテナイメージと依存ロールを起動しリクエストを実行して 想定通りの挙動をするかを楽にテストしたい 背景(2/2)

Slide 31

Slide 31 text

31 複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト ● infrataster ○ サーバーの振る舞いテストツール ○ 振る舞いのテストに止まり目的に合わない&更新が止まっている? ● container-structure-test ○ コンテナイメージの構造をテストするためのツール ○ 単体のイメージのテストに止まるため目的に合わない ● Testcontainers ○ 統合テスト向けにコンテナを簡単に操作可能な複数言語で実装があるライブラリ ○ 利用目的が異なるため、作成したコンテナに対するテストコードが冗長になりがち 既存のソリューションを調査

Slide 32

Slide 32 text

32 複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト ● Cybozu Inside Out, 複雑怪奇な nginx を Go と Docker でユニットテストする ○ https://blog.cybozu.io/entry/2020/04/16/080000 ○ nginxをユニットテストするためにDockerとGoを利用 ○ testerコンテナ内でGoのテストを実行、nginxの設定をマウントしたコンテナ を作成、自身がmockサーバーになりテストを実行 →既存のソリューションで課題をすべて解決してくれるものはなかったが、やりた いことに一番近そう これを参考に汎用的なコンテナイメージの振る舞いテストツールを作ることにした 最終的に参考にしたもの

Slide 33

Slide 33 text

33 複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト ● テストの基本的なアーキテクチャは参考元(※)を踏襲 ● nginxに限らず様々なプロジェクトで利用できるように、 ○ go package化 ○ 任意のimage tag、任意の環境変数を設定可能 ● http mock server作成機能に加え、redis mock server作成などを追加 ● テスト対象コンテナへのhttpリクエストの実行をアサーションメソッドとして実装 containertester(仮) ※ https://blog.cybozu.io/entry/2020/04/16/080000

Slide 34

Slide 34 text

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")) }

Slide 35

Slide 35 text

35 複雑なミドルウェアをコンテナ化するためのコンテナイメージ振る舞いテスト ● 設定項目や外部依存が多い複雑なミドルウェアのコンテナイメージ開発は大変 ● 複雑なコンテナイメージ開発を振る舞いのテストによって効率化する方法を選択 ● テストライブラリとして実装し、Goのテストとして記述可能にした ● テストの効率・メンテナンス性・網羅性が上がった事で、今後の品質&開発生産性 向上が期待できる まとめ

Slide 36

Slide 36 text

36 レガシーなアーキテクチャを Kubernetes上で活かすために

Slide 37

Slide 37 text

37 自己紹介 EC事業部 カラーミーショップグループ アプリストアチーム 2019年 中途入社 神﨑 拓人 Kanzaki Takuto アプリストアチームとしての活動の傍ら可用性向上 プロジェクトとして主に既存アプリケーションの Kubernetes化を担当。 @windyakin @MITLicense

Slide 38

Slide 38 text

38 レガシーなアーキテクチャをKubernetes上で活かすために ● カラーミーショップは他ECサービスに比べてショップページの自由度が高い ○ ショップオーナーがページごとにテンプレートを自由にカスタマイズできる ● テンプレートエンジンは高速化のためにファイルキャッシュを吐き出す ○ 中間ファイル的なものでレンダリングの高速化に使われる カラーミーショップの「テンプレート機能」 ファイルストレージに キャッシュされる

Slide 39

Slide 39 text

39 レガシーなアーキテクチャをKubernetes上で活かすために ● Kubernetes 上での最小アプリケーション動作単位「Pod」 ○ 単体・複数のコンテナを寄せ集めて動作させている ● Pod は割とカジュアルに作成・削除される ○ Docker イメージを差し替えたいとき(アプリケーションのアップデート) ○ Pod の台数を増やす・減らすとき(スケールアップ・ダウン) ● Pod の再作成が行われるとDockerイメージに含まれるファイル以外は消える ○ キャッシュファイルは Pod が立ち上がっている間だけ維持される ○ 再作成後はキャッシュファイルがクリアされてしまう KubernetesでのPodのライフサイクルとファイルキャッシュは相性がよくない

Slide 40

Slide 40 text

40 レガシーなアーキテクチャをKubernetes上で活かすために ● 当初は「対応しなくてもそんなに影響ないのでは?」説が出ていた ○ Pod が再作成されても Pod にアクセスがあれば徐々に溜まっていく ○ 一方で Virtual Machine ではたまり続けるキャッシュに対する課題もあった ● キャッシュがない状態になるとどれぐらい影響があるのか計測することに ○ キャッシュがない Virtual Machine を新たに用意して本番に投入しメトリクスを取得 k8s に移行した時に影響が出やすいと判断しキャッシュを活かす方法を模索することに キャッシュのライフサイクルの変更によってどれほどの影響が出るかを調査 ● 他VMより20〜30%ほど遅い ● これが30〜40分ほど続く

Slide 41

Slide 41 text

41 レガシーなアーキテクチャをKubernetes上で活かすために 1. k8s の機能 Persistent Volume(永続ボリューム) により解決する案 ○ 大容量ストレージを持った Node 上にて永続ボリュームをマウントする ○ それまで立ち上げていたPodの数を超えて作成すると結局キャッシュがない状態になる → スケジューリングによる性能劣化など新たな懸念材料などが生まれてしまう 2. キャッシュファイルをオンラインストレージでホストする案 ○ Pod にあるキャッシュファイルを定期的にオンラインストレージにアップロード ○ Pod の起動時にキャッシュをオンラインストレージからダウンロードしてくる → これを実現するアプリケーションを実装をすることに ファイルキャッシュをk8s上で保持するのためのアプローチ

Slide 42

Slide 42 text

42 レガシーなアーキテクチャをKubernetes上で活かすために ● BigQuery からアクセスが多いショップを割り出す ● アクセス上位のキャッシュを Amazon S3 にアップロードしていく ● Pod の起動時に Init Container で Amazon S3 にあるキャッシュを落としてくる キャッシュマネージャアプリケーションの作成とリリース

Slide 43

Slide 43 text

43 まとめ ● 小さなアプリケーションの開発によって既存のアーキ テクチャを活用しつつも新たなプラットフォームへの 移行をすることができた ● 今回お話した施策の詳細は後日ペパボテックブログに て公開予定 ペパボテックブログ https://tech.pepabo.com/

Slide 44

Slide 44 text

おわりに 44

Slide 45

Slide 45 text

おわりに 今後のShopSetにご期待ください ● 今回紹介した取り組みはほんの一部で、他に もチームでは色々な課題を解決していってい ます ● これからもカラーミーショップ全体の可用性 の向上に向けて様々な施策を実施します 💪 45

Slide 46

Slide 46 text

46 Thank You! Thank you for listening!