Deep Environment Parity CDNT 2019

Deep Environment Parity CDNT 2019

CNDT 2019での発表資料になります。
Day 2 Room H 12:00 - 12:40

検証環境を作成し、検証し問題なければリリースするというフローはよくあるフローかと思います。
検証を行う前提として、検証環境と本番環境の差がないことが理想かと思います。
では、検証環境と本番環境の差をなくすためにはどうしたらよいのでしょうか
DockerやKubernetesを使えば解決ですか?
いいえ、それだけでは不足しています。
今回、差をなくすための取り組みとして行った下記のトピックについて話します。

* コードの実行パスの一致
* 実行環境の一致
* データの一致

Aa777465acd82d13333678f3fc082c59?s=128

Spring_MT

July 23, 2019
Tweet

Transcript

  1. 環境の⼀致について 春⼭ 誠 HARUYAMA MAKOTO Jul, 23, 2019 Cloud Native

    Days Tokyo 2019
  2. SpringMT Spring_MT HARUYAMA MAKOTO DeNA Network Service Unit, Service Incubation

    Div., Rerep Gr. 春⼭ 誠
  3. None
  4. 環境の⼀致について

  5. みなさんはいくつ環境使ってますか?

  6. 複数環境がある場合がほとんど 開発環境 検証環境 1 検証環境 2 本番環境 その他の環境

  7. 多くの場合、それぞれの環境に
 なんらかの差がある \設定が違う∕ \データが違う∕ \実⾏環境が違う∕ 本番環境 その他の環境

  8. 環境間に差があると
 本番環境に⼼から安⼼してデプロイできない • 環境に合わせて微妙にデプロイのフローが 違う… • 検証環境で確認したから
 間違いなく本番環境でもOKと⾔い切れる? 本番環境

  9. ‒LeanとDevOpsの科学 p110-111より “コードのデプロイにおける負荷が⼤きければ⼤きい ほど、ITパフォーマンス、組織のパフォーマンス、 組織⽂化のレベルが低いのである。”

  10. そもそも
 なぜ環境に差が⽣まれるのだろうか?

  11. 環境の差とは コードの差 実⾏環境の差 データの差 1 2 3

  12. これらの差をなくし
 環境間の差ができないようにする コードの差 実⾏環境の差 データの差 1 2 3 なくす なくす

    なくす
  13. 環境の差をつくらないためにやったこと

  14. コードの⼀致 実⾏環境の⼀致 データの⼀致 1 2 3

  15. コードを⼀致させるとはどういうことか 環境による
 条件分岐をなくす 全ての環境で
 同じコードを使う

  16. 環境による条件分岐をなくす

  17. 環境間の差は設定データの切り替えで実現する 環境による条件分岐をなくす 環境に依存する条件分岐を書かない 環境に依存する条件分岐があると、検証環境で確認した ことが本番環境でも確認できたとはいいきれない 特定の環境のみで起こるような障害を防ぐために、環境 ごとの差は設定データの切り替えによって実現する NG OK

  18. すべての環境で同じコードを使う

  19. 全ての環境で同じDockerイメージを使う すべての環境で同じコードを使う 全ての環境で同じDocker イメージが使えるようにDockerイメージの作り⽅を⼯夫する

  20. コードを動かすために必要なものは
 すべてDockerイメージに含める すべての環境で同じコードを使う

  21. Dockerイメージの作成フロー すべての環境で同じコードを使う  ! "     

        ςετ     ! "          ςετ   
  22. Dockerイメージを作るときのポイント すべての環境で同じコードを使う Dockerイメージのビルドは⼀回にする 検証完了したので本番⽤のDocker イメージビルドしますではなく、検証完了したときの Docker イメージをそのまま本番環境にも適⽤する コードをpushするたびにDockerイメージを作る Dockerイメージを作れないとリリースできないので毎回作りきる 作成したDockerイメージは全て保存する

    いつでも使える状態で保存しておく
  23. コードの⼀致 実⾏環境の⼀致 データの⼀致 1 2 3

  24. Dockerイメージを動かすための
 Kubernetes

  25. kubernetesでDockerイメージを動かす Dockerイメージを動かすためのKubernetes

  26. Kubernetesクラスタの分け⽅について

  27. クラスタは環境ごとに作成する Kubernetesクラスタの分け⽅について 環境同⼠が影響を受けな いように独⽴させる 環境同⼠が影響を受けないように、 独⽴したものとして扱いたく環境毎 にネームスペースでの分割はせずに クラスタでわける

  28. Kubernetesクラスタを ⼀致させるためにやったこと

  29. 環境の基本の構成は変えない Kubernetesクラスタを⼀致させるためにやったこと 環境ごとの差異を作らないように、環 境の基本の構成は変えない

  30. ただ、環境の構成の量は変えたい時がある Kubernetesクラスタを⼀致させるためにやったこと 例: 検証環境ではPodの数を減 らしたい 環境ごとに変えなければいけない設定だけを 簡単に管理する 例:開発環境はここは1つでいい↑

  31. 環境ごとに変えざるを得ない箇所がある Kubernetesクラスタを⼀致させるためにやったこと 環境を識別するためのRRP_STAGEという環境変数 RRP_STAGEでDockerコンテナ起動時の設定の切り替えを⾏う Ingressのhost名の設定

  32. この変えたい場所だけをうまく管理したい Kubernetesクラスタを⼀致させるためにやったこと kustomize 共通な設定を定義しつつ、overlayで各環境毎の設定を上書き可能 • kubernetesのyamlのまま管理でき、kubernetesの設定以上に覚えることが ない • baseを本番環境にして、その他の環境ではそれに対してパッチを当てていく

  33. パッチの例 Kubernetesクラスタを⼀致させるためにやったこと replicasの数に応じた変更 replicasの数に応じてHPAの設定やDeploymentで要求する resourceの値を変更 Webサーバーのworker数の変更 リソース状況をみてインフラ側で制御できるよう環境変数 で管理

  34. Dockerイメージの反映 Kubernetesクラスタを⼀致させるためにやったこと kustomizeのimagesフィールドを更新してapplyするだけ kustomizeのimagesフィールドは結構柔軟に設定できるようになっていたのでset imageする⽅法から切り替えました Dockerイメージ名は全ての環境で同じ Doclerイメージの指定は全ての環境で⼀致

  35. コードの⼀致 実⾏環境の⼀致 データの⼀致 1 2 3

  36. サービスを構成するさまざまなデータ

  37. データのいろいろ サービスを構成するさまざまなデータ サービスに直接関係するデータ • 設定データ • マスターデータ • ユーザーデータ

  38. 設定データ データあデータのいろいろ⼀致 実⾏環境でコードを動かすために必要なデー タ • ファイルや環境変数で管理されている • サーバーのポート番号 • DBのパスワード

    • Service Accountのクレデン シャル 例
  39. マスターデータ データのいろいろ サービスのコンテンツに関するデータ(運営側 が⽤意) • コードの振る舞いには影響しない • ログインボーナスの設定 • イベント開始や終了の設定

    • 運営からのお知らせ 例
  40. ユーザーデータ データのいろいろ ユーザーが作成したデータ • twitterでのつぶやき • Facebookでの投稿 • Instagramの投稿などなど 例

  41. データの⼀致をどう考えるか

  42. ユーザーデータの⼀致はコストが⼤ データの⼀致をどう考えるか ユーザーのデータの量の問題 • ユーザーデータは量が膨⼤になりがち • ユーザーのアクションに応じて変わっていくので同期のタイミングも難しい ユーザーの個⼈情報保護の問題 • 個⼈情報の管理やセキュリティの⾯から、ユーザーの個⼈情報に該当するも

    のは検証環境に持っていくこと⾃体NG
  43. データの⼀致 データの⼀致をどう考えるか 設定データとマスターデータの⼀致 この2つのデータが⼀致していれば、ユーザーデータは⼿間はかかるが再現可能

  44. 設定データの⼀致

  45. 設定データの切り分け 設定データの⼀致 設定ファイル サーバー側 ファイル保存⽤のGCSの認証情報 管理画⾯のレイアウトの⾊ MASTER_KEY MySQLのホストやパスワード 環境変数 インフラ側

  46. 環境変数 設定データの⼀致 kubernetesのマニフェストで管理 環境間で違う値を使う場合はkustomizeでパッチを当てる

  47. 設定ファイル 設定データの⼀致 Docker イメージの中に全部いれておく 起動時に⾃分の環境を識別して、環境に応じた設定ファイルを読み込む

  48. 設定ファイルの管理 設定データの⼀致 設定ファイルに秘匿情報を含めて管理 RailsのEncrypted Credentialsを使って暗号化して管理
 復号化するためのkeyは環境変数でインフラ側で管理している 環境を識別する環境変数を使って
 読み込む設定ファイルを切り替える

  49. 設定ファイルの管理 設定データの⼀致 各環境ごとに独⽴させて管理 同じように⾒えているだけで同じものではないので同じような 設定があってもまとめない

  50. 設定ファイルの切り替え 設定データの⼀致 Entrykitのprehookを使って設定ファイルを切り替える

  51. 切り替えるためのスクリプト 設定データの⼀致

  52. マスターデータの⼀致

  53. ReRepでのマスターデータ マスターデータの⼀致 例 ミッションという機能 • ミッションの説明⽂ • 達成条件 • ミッションの説明画像

  54. マスターデータを⼀致させるために必要なこと マスターデータの⼀致 全ての環境で利⽤可能な内容にする 環境間で持ち運びできる形式で管理する ⼀度反映したマスターデータは変更しない 前の状態に依存しないで反映できるようにする

  55. マスターデータの内容

  56. マスターデータの内容 マスターデータの内容 DBに⼊れるもの テキストで管理 バイナリで管理 バイナリ(画像)で管理し、ファ イルストレージに⼊れるもの

  57. 反映するときの注意 マスターデータの内容 テキストとバイナリは同時にサービスに反映される

  58. マスターデータの⽣成と反映

  59. マスターデータの⽣成 マスターデータの⽣成と反映 ① ② ③ ❶ ❷ ❷

  60. バージョンID マスターデータの⽣成と反映 バージョンを識別するユニークなID • さらに、テキストとバイナリのデータを同じバージョンとして扱うためにも 必要 • gitのハッシュ値を使ってバージョンIDを⽣成 • ユニークかつ推測不可能な⽂字列

  61. テキストのマスターデータ

  62. テキストのマスターデータ⽣成 テキストのマスターデータ

  63. テキストのマスターデータの⽣成 テキストのマスターデータ テーブルごとにJSONファイルでまとめる テーブル定義に⼀対⼀で対応したデータをテーブルごとにJSONファイルとして作る JSONファイルはzipで1ファイルにまとめる zipの中にバージョンを⽰すファイルを⽤意しバージョンIDを⼊れる

  64. Zipファイル バイナリ(画像)のマスターデータの⽣成と反映

  65. サービスへの反映 テキストのマスターデータ Zipファイルになったテキストのマスターデー タを専⽤の管理機能からアップロードするこ とで反映を⾏う • DBへの反映の際は全てDELETE してから改めてINSERTする • 1トランザクションで実⾏

    • 決めたキーを使って関連付け • マスタデータの中でデータ作成者がユニークなキーを作り それを元に関連付けを⾏う
  66. バイナリ(画像)のマスターデータの⽣成と反映

  67. バイナリ(画像)のマスターデータ⽣成 バイナリ(画像)のマスターデータ

  68. バイナリ(画像)のマスターデータの⽣成 バイナリ(画像)のマスターデータの⽣成と反映 ファイルストレージにバージョンIDでディレクトリを作り そこに画像をアップロードする • アップロードが終わると、利⽤可能な状態になる

  69. サービスへの反映 バイナリ(画像)のマスターデータの⽣成と反映 テキストの反映により新しいバージョンが登録されるとAPIが返す ベースURLが変わり新しい画像に切り替わる 画像はマスタデータ⽣成時にすでにストレージにアップロードしてあり、ベースのURLが変われば画 像も切り替わる
 ⼀度uploadしたバージョンは残っているので、マスターデータを古いバージョンにすれば追従して 古い画像になる クライアントはAPI経由で最新の画像のベースURLを取得する ハージョンのIDを含んだURLになっていて、最新のベースのURLをAPI経由で取得可能

  70. キャッシュクリア バイナリ(画像)のマスターデータの⽣成と反映 画像のキャッシュクリアが必要ない 画像はimmutableに管理していて、同じようにみえていても実体は別になる
 キャッシュクリアをする必要がなく、キャッシュに関する障害は起こりえない

  71. 環境の⼀致を⽬指した結果

  72. 環境の⼀致を⽬指した結果 開発環境 検証環境 1 検証環境 2 本番環境 その他の環境

  73. 障害が少ないサービスにできた(当社⽐) 障害数 9件 / 年 • 考慮外のユーザーデータによる障害 : 5件 •

    マスターデータのミス : 1件 • 作業ミス : 1件 • 環境での出し分け : 1件 • インフラ起因の障害 : 1件
  74. データも含め⼀⽇に数回リリースできる体制に 障害の対応時間も短くなった 障害発⽣時において、改修 -> 検証 -> 本番反映 のサイクルが最短20分位で完了

  75. 環境作成が容易になった 好きなように組み合わせて環境を建てられる ユーザーデータ以外は全てimmutableな状態で管理されているので、好きなように組み 合わせて数分で環境を建てられる

  76. デプロイ作業が統⼀された 環境が⼀致していると、反映⼿順も⼀致する 新しく⼊った⼈でもすぐに本番反映を⾏える

  77. これから

  78. Twelve-Factor App
 Beyond The Twelve-Factor App 環境の差は以下のギャップによって⽣まれる • 時間 •

    ⼈ • リソース・ツール 今回の環境の⼀致の取り組みは⼈とリソース・ツールのギャップを埋めるもの
  79. 次は時間のギャップを埋める CDパイプラインの構築 ⾊々なツールを検証中 サービスのデプロイのフローもあるんですが、監査やセキュリティとかも含めて対応し ていく

  80. Twitterアカウント DeNAxTechの宣伝 DeNA のエンジニアの技術情報を発信しているTwitterアカウント DeNAxTechがあるの で、興味があればぜひフォローをお願いします DeNAxTech https://twitter.com/DeNAxTech/

  81. ありがとうございました