Proprietary + Confidential
コンテナ移行の前に知っておきたいこと
2021.12.15
kazshinohara@
Google Cloud Japan
Proprietary + Confidential
● GCE でアプリケーションを本番運用していて、そろそろコンテナへ移行したい
● Docker や Kubernetes のことは何となく分かっている
● Google Cloud 上でコンテナに移行した時に、何を考慮しないといけないのか
ざっくり知りたい
本セッションが想定している聞き手
Proprietary + Confidential
1. なぜコンテナ移行するのか?
2. 移行先
3. 移行の進め方
4. 移行後の運用
5. まとめ
アジェンダ
Proprietary + Confidential
なぜコンテナ移行するのか?
01
Proprietary + Confidential
コンテナとは?
Proprietary + Confidential
" コンテナとは、アプリケーション コードに、
ソフトウェア サービスの実行に必要な特定バージョンの
プログラミング言語ランタイムやライブラリなどの
依存関係を加えた軽量のパッケージを指します。 "
https://cloud.google.com/learn/what-are-containers より
コンテナとは?
コンテナ
依存ファイル群
アプリケーションコード
プログラミング言語ランタイム
Proprietary + Confidential
仮想マシン とコンテナ〜仕組みの違い
仮想マシン コンテナ
ゲスト OS
ホスト OS
ハードウェア ハードウェア
ハイパーバイザー
コンテナランタイム
依存ファイル群
アプリケーションコード
プログラミング言語ランタイ
ム
依存ファイル群
アプリケーションコード
プログラミング言語ランタイ
ム
仮想マシン
● ハードウェアレベルで仮想化
● ホストマシンと独立した OS を持つ
コンテナ
● OS レベルでの仮想化
● ホスト OS のカーネルを利用
Proprietary + Confidential
仮想マシン とコンテナ〜開発者目線での違い
比較観点 仮想マシン コンテナ
イメージ形式 QCOW2, QED, RAW, VDI, VHD, VMDK Docker v2/v1, OCI
イメージサイズ 大きめ (GB単位) 小さめ (MB単位)
起動時間 遅め (分単位) 早め (秒単位)
ローカル開発環境 Vagrant Docker / Minikube
環境設定 Ansible / Chef / Puppet Dockerfile
イメージ作成 Packer Docker
デプロイ Terraform / Deployment Manager /
gcloud
kubectl / gcloud
Proprietary + Confidential
コンテナの特徴
軽量
仮想マシンに比べて
軽量でシンプル
数十ミリ秒で起動
ポータビリティ
様々な実行環境に対応し、
デプロイメントが容易
効率性
リソース使用量が少ない
コンピュートリソースを
細分化し、効率的に利用可能
Proprietary + Confidential
コンテナへ移行したいですか?
Proprietary + Confidential
コンテナ移行の恩恵と目的の確認
コンテナの特徴を踏まえるとコンテナへ移行することで、
"開発や運用における生産性やアジリティの向上 "
が期待できる。
コンテナへの移行を検討する前に、
以下のようなモチベーションが自チームにあるのか考える。
- より早いリリースサイクル
- 新機能の追加や既存機能の変更を簡単に
- Immutable Infrastructure の徹底
- 新しい技術の catch up
Proprietary + Confidential
仮想マシンで動いていたアプリケーションであれば原則動く。が、、
コンテナの特徴を活かすため、以下のようなアプリケーションに利用されることが多い。
● ステートフル よりも ステートレス(API サーバーetc.)
● 多機能より単機能(マイクロサービスアーキテクチャ)
● 高速なスケールアウトが必要
● 新規開発(開発 / 運用要件が変わるので)
どんなワークロードに向いているか
Proprietary + Confidential
コンテナ移行のコスト
コンテナ移行にかかるコストを前もって確認、評価する。
● アプリケーションの Rewrite / Re-architect コスト
○ コンテナに最適化されたアプリケーションへの改修
● 学習コスト
○ Docker / Kubernetes などコンテナ関連技術の習熟
● 移行作業自体のコスト
○ サービスへの影響を最小限に押さえた切り替え計画の策定、リソース確保、実行
○ e.g. 本番稼働中の GCE -> GKE への切り替え
Proprietary + Confidential
移行先
02
Proprietary + Confidential
Google Cloud 上でコンテナをホストする際の"主な"選択肢
概要 Kubernetes のマネージドサービス Kubernetes のマネージドサービス コンテナをサーバーレスに利用可能
コンテナの
マシンスペック
特に制限なし
(GCE の仕様に準拠)
最大 28 vCPU / 80 GiB RAM 最大 4 vCPU / 16 GB RAM
永続 Disk なし
互換性のあるOSS Kubernetes Kubernetes Knative
インフラ抽象度 低 中 高
費用 Node (GCE の 仮想マシン) の
インスタンス時間に応じた
従量課金とクラスタ管理手数料
Pod のインスタンス時間に
応じた従量課金と
クラスタ管理手数料
リクエスト処理時間とリクエスト数に応じ
た従量課金
もしくは、コンテナインスタンス
時間に応じた従量課金
GKE Standard GKE Autopilot Cloud Run (managed)
Proprietary + Confidential
GKE を選択する場合 
● 大規模なマイクロサービス
● カーネルレベルのパフォーマンス・チューニング
● 独自メトリクスを使ったスケーリング
● K8s や CNCF のエコシステムを活用したい
● K8s に習熟したインフラ人員がいる、
もしくはこれから揃える
GKE と Cloud Run どちらを選択するか?
Cloud Run を選択する場合 
● とにかくスモールスタートしたい
● パフォーマンスとかスケーリングとかは
Cloud Run にお任せ
● アプリ開発者中心の小規模チーム
● K8s に習熟した専門インフラチームがいない、
これから揃える予定もない
GKE Autopilot の使い所は?
K8s のマネージドサービスでありながら、GKE Standard よりシンプルに運用出来るのが強み。
K8s にチャレンジしたいが、K8s のクラスタ設計や運用にリソースを多く割けない場合や、
パフォーマンス・チューニング、高速なスケーリングなどが必要ない場合におすすめ!!
Proprietary + Confidential
GKE の世界観
OSS な抽象化
されたインフラ
GKE は Google Cloud 上に展開された別のプラットフォーム
GCE の世界観
プロプラなインフラ
GCLB GCE PD Filestore
mapping mapping mapping
Reconciliation loop による状態維持
宣言型 モデルの API
Proprietary + Confidential
Kubernetes では マニフェストという設定ファイルを使う。
従来の命令型 API と違い処理(How)を書くのではなく、
何を達成したいか(What)だけを書く
利用者はコンテナを利用するための
細かいインフラ周りの処理を把握する必要はない。
Kubernetes はマニフェストに書かれた状態を
常に維持しようとする( Reconciliation loop)ため、
人の手を介さずともシステムの健常な状態を維持できる。
(e.g. オートヒーリング )
宣言型 モデル と Reconciliation loop
あるべき状態
現在の状態
マニフェストで定義
K8s のクラスタでの
Live の状態
Proprietary + Confidential
GKE
1. コードを書く
2. Dockerfile 作成(省略可能※後述)
3. $ docker build
4. $ docker push
5. $gcloud container clusters create ~
6. $ kubectl apply -f deployment.yml
7. $ kubectl apply -f service.yaml
8. $ kubectl apply -f hautoscal.yaml
Cloud Run
1. コードを書く
2. Dockerfile 作成(省略可能※後述)
3. $ docker build
4. $ docker push
5. $ gcloud run deploy..
サービス公開までの手数(例)
Proprietary + Confidential
移行の進め方
03
Proprietary + Confidential
1. アプリケーション構成の確認/ コンテナに最適化させる
2. アーキテクチャ設計
3. 実際の移行
大まかな手順
Proprietary + Confidential
GCE で運用する Web アプリケーション(例)
GCE + PD
for Web Application server
(e.g. Nginx && gunicorn && Flask)
Cloud SQL
for dynamic data
(e.g. MySQL)
External HTTP
(S) LB
Cloud Storage
for static contents
Cloud CDN
IAP
for user auth
/static/*
/*
Client
Proprietary + Confidential
アプリケーション構成の確認、
コンテナに最適化させる
Proprietary + Confidential
既存のアプリケーションに、
多数の機能が含まれている場合は
なるべく機能毎にサービスを分割し、
コンテナ化することが望ましい。
コンテナの特徴を活かすため、
出来る限り 1 コンテナ = 単一機能
を目指す。
機能毎に異なるライフサイクルや
非機能要件がある場合、分割は有意義。
複数の機能を持つアプリケーションの場合は分割を考える
機能 A
機能 B
機能 C
機能 D
既存アプリケーション
機能 A の
サービス
(コンテナ)
機能 B の
サービス
(コンテナ)
機能 C の
サービス
(コンテナ)
機能 D の
サービス
(コンテナ)
Proprietary + Confidential
仮想マシンの ローカルストレージで扱うデータが
ある場合、コンテナ化した場合にどこで扱うかを
検討する。
GKE の場合
● GCE の PD
● Cloud Filestore
● GCS
Cloud Run の場合
● Cloud Filestore
● GCS
ローカルストレージの利用有無を確認する
機能 D
例えばユーザーがアップロードした
ファイルをローカルストレージ
に保管していたとする
/var/hoge/application-data/fuga
Proprietary + Confidential
アーキテクチャ設計
Proprietary + Confidential
GKE に移行した Web アプリケーション構成(例)
GKE
for Web Application server
Cloud SQL
for dynamic data
(e.g. MySQL)
External HTTP
(S) LB
Cloud Storage
for static contents
Cloud CDN
IAP
for user auth
Cloud Filestore
for Upload files
Client
Proprietary + Confidential
GKE に移行した Web アプリケーション構成(例)K8s リソース版
サービスA
サービスB
サービスC
サービスD
GCS 用 Proxy
フロントエンド
BackendConfig
for IAP && Cloud CDN
サービス毎のDB
GCS は Ingress の BE に設定
不可のため、GKE の Pod で
Proxy させる
Web page をレンダリングする
フロントエンドと Business logic
を持つAPI サービスに分離
Upload Files 用に
Cloud Filestore を
利用(RWX)
Proprietary + Confidential
● GKE の Node(コンテナが動くところ)は GCE の仮想マシンを使うため、
GCE のアーキテクチャと大枠は変わらない。
● GKE への移行メリット(宣言型 API / Reconcilication Loop)を最大限享受する意味で、
K8s の API でなるべく運用を完結できるよう設計する。
● ただし、K8s API によって Wrap されたことにより、Google Cloud のサービスが
本来備えていながら、利用できない機能もあることに注意が必要。
GKE アーキテクチャ設計のポイント
Proprietary + Confidential
Cloud Run に移行した Web アプリケーション構成(例)
フロントエンド
External HTTP
(S) LB
サービス毎のDB
サービスA
サービスB
サービスC
サービスD
フロントエンドのCloud
Run は Serverless
NEG を
利用し LB の下に。
フロントエンドと
各サービス間はIAM 認証を
利用しセキュアに。
Cloud CDN
IAP
for user auth
Cloud Run 2nd gen
execution environment
を利用しNFS マウント
LB の Backend とし
て Bucket を
設定
Client
Proprietary + Confidential
● Cloud Run 単体でも外部公開は可能だが、 IAP / CDN / GCS との連携を行うため、
Serverless NEG を利用し、HTTP(S)LB と連携させる。
● Cloud Run は VPC 内で動作しないため、 Cloud SQL との接続は、以下のいずれかの方法を使い実現
する。Cloud SQL Auth Proxy を利用する方がシンプルでおすすめ。
○ Cloud SQL Auth Proxy
○ Serverless VPC Access Connector
● Cloud Run へ Cloud Filestore を NFS マウントするためには、 Cloud Run の 2nd gen
execution environment が必要だが、まだ Preview のため注意が必要。
Cloud Run アーキテクチャ設計のポイント
Proprietary + Confidential
実際の移行方式
Proprietary + Confidential
1. 段階的な移行(ストラングラーパターン亜種)
○ 機能ごとに段階的に新環境に移行を行う。
○ 一括移行と比較しリスク低、現実的な方式
2. 一括移行
○ 新環境を併設し、旧環境から DNS 切り替えによる一括の移行を行う。
○ 環境間でのデータの一貫性を担保するのが難しい。 DB を分割せず、
旧 DB を継続利用する等の前提があれば難易度は下がる。
環境毎にやり方はたくさん ...
実際の移行方式
Proprietary + Confidential
段階的な移行(ストラングラーパターンの亜種)のイメージ
2. サービスA を Cloud Run
へ移行、GCE は サービスA
の API を呼び、その結果を元
に Web page の
レンダリングを行う。
1. 元の構成 3. サービスB を Cloud Run
へ移行。移行前の機能は
そのまま旧DB を利用。
4. 同様の手順で
サービスC / D を
Cloud Run へ移行。
5. GCE に残っていたHTTP
Handler / Web page
レンダリングを行う
フロントエンド部分をCloud
Run へ移行。
/static/* /* /static/* /* /static/* /* /static/* /* /static/* /*
Proprietary + Confidential
移行後の運用
04
Proprietary + Confidential
1. 開発のワークフロー の見直し
2. モニタリング / ロギング の見直し
3. GKE のバージョン アップグレード 対応
やること
Proprietary + Confidential
開発のワークフロー の見直し
Proprietary + Confidential
仮想マシン〜開発から初回デプロイまでのフロー(例)
1. アプリ開発(コーディング、ビルド、テスト)
2. 仮想マシンの作成
● Terraform / Vagrant
3. OS 周りの設定、アプリ、依存ライブラリ等の
インストール
● Playbook 作成
● Ansible で仮想マシンに対して
プロビジョニング
4. ゴールデンイメージの作成
● Packer
5. ゴールデンイメージからサーバー作成
● Terraform / Deployment Manager 他
Proprietary + Confidential
コンテナ〜開発から初回デプロイまでのフロー(例)
1. アプリ開発(コーディング、ビルド、テスト)
2. コンテナイメージの作成 / 保管
● Dockerfile の作成
● docker build && docker push
3. コンテナイメージのデプロイ
● kubectl / gcloud / Terraform 他
Proprietary + Confidential
CI/CD のフロー(例)
git repo
trigger gcloud compute ssh….
kubectl apply -f ***.yaml
gcloud run deploy….
Source の Build&&Test&& コンテナ
イメージのビルド、Artifact Registry への Push
Source の Build&&Test、成果物のArtifact
Registry への Push(Option)
Source の Build&&Test&& コンテナ
イメージのビルド、Artifact Registry への Push
GCE は現用の仮想マシン
上でファイルの入れ替えを
行ってプロセスを
リスタート
GKE/Cloud Run は現用の
コンテナを新しい
コンテナに入れ替える
Proprietary + Confidential
同じところ
● アプリケーションを動作させるための 環境設定を定義するファイルが必要
○ 仮想マシン = Ansible Playbook
○ コンテナ = Dockerfile
違うところ
● 仮想マシンは実際に欲しい構成のインスタンスを作って、そこからイメージ作成。
コンテナは設定ファイル( Dockerfile)からイメージを直接作成。
● コンテナの方がより Immutable( 但し Spinnaker のような 3P ツールを使えば、
仮想マシンでもコンテナと似たようなことが出来る)
仮想マシンとコンテナ、ワークフロー差分
Proprietary + Confidential
[参考] Buildpacks
"Google Cloud Platform/buildpacks: Builders and buildpacks designed to run on Google Cloud's container platforms"
https://github.com/GoogleCloudPlatform/buildpacks
$ ls
index.js package.json
## Cloud Build で利用
$ gcloud builds submit --pack image=gcr.io/my-project/my-app
## pack コマンドを通じて利用
$ pack build my-app --builder gcr.io/buildpacks/builder:v1
## Cloud Run のデプロイ時に利用
$ gcloud run deploy SERVICE_NAME --source .
指定したディレクトリ以下を解析し、
Dockerfile なしに適切なコンテナへビルドする。
サポート言語
● Go 1.10+
● Node.js 10+
● Python 3.7+
● Java 8, 11
● .NET Core 3.1+
Proprietary + Confidential
ロギング / モニタリング の見直し
Proprietary + Confidential
Cloud Logging を利用。
● GCE
○ Ops エージェント をインストールして利用。
○ Host 自身の Syslog、任意のログファイルから取得可能。
さらに Host 内で TCP レシーバーを設定可能。
● GKE
○ ロギングエージェントが Node にデフォルトでインストールされており、
特に設定を行わなくてもコンテナの Stdout, Stderr がデフォルトで収集される。
● Cloud Run
○ 特に設定を行わなくてもコンテナの Stdout, Stderr がデフォルトで収集される。
ロギング
Proprietary + Confidential
構造化ログの活用
従来のようにログをファイルへ出力するのではなく、 GKE /
Cloud Run では Stdout, Stderr に対してログを
出力するのがオススメ。
構造化ログを利用することで、
検索しやすい形式でログを出力することが可能。
特殊フィールド (例: severity )は jsonPayload から
削除され、対応フィールドに書き込まれる。
# Build structured log messages as an object.
global_log_fields = {}
# Complete a structured log entry.
entry = dict(
severity="NOTICE",
message="This is the default display field.",
component="arbitrary-property",
**global_log_fields,
)
print(json.dumps(entry))
Proprietary + Confidential
Cloud Monitoring を利用。
● GCE
○ Ops エージェントをインストールすることで CPU やメモリ、ディスクなどのメトリクスが収集され
る。
● GKE
○ メトリクス エージェントが Node にデフォルトでインストールされており、
特に設定を行わなくても Node やコンテナのシステムメトリクスが収集される。
● Cloud Run
○ 特に設定を行わなくても リクエスト数や CPU 使用率など コンテナのシステムメトリクスが収集さ
れる。
モニタリング
Proprietary + Confidential
GKE バージョンアップグレード対応
Proprietary + Confidential
Kubernetes は〜3 ヶ月毎に最新のバージョンをリリース、パッチは〜1 ヶ月毎にリリース
GKE は Kubernetes のリリースに加えてセキュリティおよびバグ修正を提供
Control Plane バージョン
Kubernetes の Control Plane で
使われるバージョン。 Kubernetes
クラスタで使われる大半の
ソフトウェアのバージョンを指す。
Node バージョン
Kubernetes の Nodeで使われる
バージョン。主に OS イメージおよび
Kubelet のバージョンを指す。
GKE バージョンアップグレード
GKE のバージョン ポリシー
● Node は Control Plane よりも新しいバージョンは使えない
● Node は Control Plane から 2 マイナーバージョン古いものまで利用可能
Proprietary + Confidential
つまり、数ヶ月に一度は Node の再作成を伴う、バー
ジョンアップグレードが必要!!
Proprietary + Confidential
アップグレードのパターン
1. リリースチャネルを指定したクラスタ
● 各チャネル毎に設定された頻度に従い、Control Plane も Node も自動アップグレードされる
● 自動アップグレードは無効化できない(リリースチャネルから外すことは可能)
● 自動アップグレードを待たずに手動アップグレードすることも可能
2. 静的にバージョンを指定したクラスタ
● Control Plane
○ 自動アップグレードされる(無効化不可)
● Node
○ デフォルトは自動アップグレードが有効(無効化可能)
○ 自動アップグレードを無効にしてる場合は、ユーザーによる手動アップグレードが必要
Proprietary + Confidential
メンテナンスの時間枠と除外
● メンテナンス時間枠( Maintenance Windows)
○ 自動メンテナンスの実行を許可する定期的な時間枠
■ 32 日周期で最低 48 時間の時間枠
■ 各時間枠は 最低 4 時間以上の連続した時間
● メンテナンス除外(Maintenance Exclusion)
○ 自動メンテナンスの実行を禁止する定期的な時間枠
○ 1 クラスタ 3 つまで
Node pool A( 計 4 Nodes)
> max_surge_upgrade: 2
> max_unavailable_upgrade: 0
Pod Pod
v1.19.15
Pod Pod
v1.19.15
Pod Pod
v1.19.15
Pod Pod
v1.19.15
Pod Pod
v1.19.15
Pod Pod
v1.19.15
Pod Pod
v1.19.15
Pod Pod
v1.19.15
v1.20.10
v1.20.10
Pod Pod
v1.19.15
Pod Pod
v1.19.15
v1.19.15
v1.19.15
v1.20.10
v1.20.10
Pod Pod
Pod Pod
Drain
Pod Pod
v1.19.15
Pod Pod
v1.19.15
v1.20.10
v1.20.10
Pod Pod
Pod Pod
v1.20.10
v1.20.10
v1.20.10
v1.20.10
Pod Pod
Pod Pod
v1.19.15
v1.19.15
v1.20.10
v1.20.10
Pod Pod
Pod Pod
v1.20.10
v1.20.10
Pod Pod
Pod Pod
v1.20.10
v1.20.10
Pod Pod
Pod Pod
Drain
Drain
Drain
新しいバージョンの
Node を 2 つ追加
古いバージョンの
Node をドレイン
Pod を新しい Node に
スケジュール
新しいバージョンの
Node を 2 つ追加
古いバージョンの
Node をドレイン
Pod を新しい Node に
スケジュール
アップグレード開始
アップグレード完了
Proprietary + Confidential
本番環境で無理なく自動アップグレードしていくために
1. 自動アップグレードの前にテストを行う
a. テスト用のクラスタは常設しておく
b. 事前にテスト用クラスタを手動で最新バージョンに上げ、動作確認を行う
2. なるべく Stable channel を使う
a. アップグレード頻度をなるべく少なく
b. Bug などの影響をなるべく少なく
3. メンテナンス時間枠を正しく設定する
4. 除外時間を正しく設定する
a. アップグレードの延期
b. ビジネスのピークタイムを絶対避ける
Proprietary + Confidential
リリースチャネルを使ったアップグレードのワークフロー (例)
4. テスト環境のクラスタで
動作確認テスト
Google サポートに連絡
ロールバック
NG
5. メンテナンス時間枠で
本番環境の自動アップグレード
OK
Available バージョンがリリースされてから、自動
アップグレードが走るまでの目安
Patch バージョン: 1 週
Minor バージョン: 3 週
3. テスト環境のクラスタを
Available バージョンに
手動アップグレード
2. Available バージョン通知を
Cloud Functions で Slack に転送
1. Google Cloud から Pub / Sub へ
Available バージョン通知
Proprietary + Confidential
まとめ
05
Proprietary + Confidential
● コンテナ移行は簡単ではない。コストの方が高くなることも、慎重な検討が必要。
● GCE からコンテナへ移行するのであれば、既存アプリケーションの規模に依るが、
まずは
Cloud Run から始めることを推奨。
コンテナの良さがありながら、運用は非常にシンプル。
● 大規模なアプリケーションであればGKE を推奨するが、K8s に精通した専門の
エンジニアをアサインすることを推奨。居ないなら少なくともGKE standard の
採用は避けた方が無難。
まとめ
Proprietary + Confidential
Thank you.

[External] 2021.12.15 コンテナ移行の前に知っておきたいこと @ gcpug 湘南

  • 1.
  • 2.
    Proprietary + Confidential ●GCE でアプリケーションを本番運用していて、そろそろコンテナへ移行したい ● Docker や Kubernetes のことは何となく分かっている ● Google Cloud 上でコンテナに移行した時に、何を考慮しないといけないのか ざっくり知りたい 本セッションが想定している聞き手
  • 3.
    Proprietary + Confidential 1.なぜコンテナ移行するのか? 2. 移行先 3. 移行の進め方 4. 移行後の運用 5. まとめ アジェンダ
  • 4.
  • 5.
  • 6.
    Proprietary + Confidential "コンテナとは、アプリケーション コードに、 ソフトウェア サービスの実行に必要な特定バージョンの プログラミング言語ランタイムやライブラリなどの 依存関係を加えた軽量のパッケージを指します。 " https://cloud.google.com/learn/what-are-containers より コンテナとは? コンテナ 依存ファイル群 アプリケーションコード プログラミング言語ランタイム
  • 7.
    Proprietary + Confidential 仮想マシンとコンテナ〜仕組みの違い 仮想マシン コンテナ ゲスト OS ホスト OS ハードウェア ハードウェア ハイパーバイザー コンテナランタイム 依存ファイル群 アプリケーションコード プログラミング言語ランタイ ム 依存ファイル群 アプリケーションコード プログラミング言語ランタイ ム 仮想マシン ● ハードウェアレベルで仮想化 ● ホストマシンと独立した OS を持つ コンテナ ● OS レベルでの仮想化 ● ホスト OS のカーネルを利用
  • 8.
    Proprietary + Confidential 仮想マシンとコンテナ〜開発者目線での違い 比較観点 仮想マシン コンテナ イメージ形式 QCOW2, QED, RAW, VDI, VHD, VMDK Docker v2/v1, OCI イメージサイズ 大きめ (GB単位) 小さめ (MB単位) 起動時間 遅め (分単位) 早め (秒単位) ローカル開発環境 Vagrant Docker / Minikube 環境設定 Ansible / Chef / Puppet Dockerfile イメージ作成 Packer Docker デプロイ Terraform / Deployment Manager / gcloud kubectl / gcloud
  • 9.
  • 10.
  • 11.
    Proprietary + Confidential コンテナ移行の恩恵と目的の確認 コンテナの特徴を踏まえるとコンテナへ移行することで、 "開発や運用における生産性やアジリティの向上" が期待できる。 コンテナへの移行を検討する前に、 以下のようなモチベーションが自チームにあるのか考える。 - より早いリリースサイクル - 新機能の追加や既存機能の変更を簡単に - Immutable Infrastructure の徹底 - 新しい技術の catch up
  • 12.
    Proprietary + Confidential 仮想マシンで動いていたアプリケーションであれば原則動く。が、、 コンテナの特徴を活かすため、以下のようなアプリケーションに利用されることが多い。 ●ステートフル よりも ステートレス(API サーバーetc.) ● 多機能より単機能(マイクロサービスアーキテクチャ) ● 高速なスケールアウトが必要 ● 新規開発(開発 / 運用要件が変わるので) どんなワークロードに向いているか
  • 13.
    Proprietary + Confidential コンテナ移行のコスト コンテナ移行にかかるコストを前もって確認、評価する。 ●アプリケーションの Rewrite / Re-architect コスト ○ コンテナに最適化されたアプリケーションへの改修 ● 学習コスト ○ Docker / Kubernetes などコンテナ関連技術の習熟 ● 移行作業自体のコスト ○ サービスへの影響を最小限に押さえた切り替え計画の策定、リソース確保、実行 ○ e.g. 本番稼働中の GCE -> GKE への切り替え
  • 14.
  • 15.
    Proprietary + Confidential GoogleCloud 上でコンテナをホストする際の"主な"選択肢 概要 Kubernetes のマネージドサービス Kubernetes のマネージドサービス コンテナをサーバーレスに利用可能 コンテナの マシンスペック 特に制限なし (GCE の仕様に準拠) 最大 28 vCPU / 80 GiB RAM 最大 4 vCPU / 16 GB RAM 永続 Disk なし 互換性のあるOSS Kubernetes Kubernetes Knative インフラ抽象度 低 中 高 費用 Node (GCE の 仮想マシン) の インスタンス時間に応じた 従量課金とクラスタ管理手数料 Pod のインスタンス時間に 応じた従量課金と クラスタ管理手数料 リクエスト処理時間とリクエスト数に応じ た従量課金 もしくは、コンテナインスタンス 時間に応じた従量課金 GKE Standard GKE Autopilot Cloud Run (managed)
  • 16.
    Proprietary + Confidential GKEを選択する場合  ● 大規模なマイクロサービス ● カーネルレベルのパフォーマンス・チューニング ● 独自メトリクスを使ったスケーリング ● K8s や CNCF のエコシステムを活用したい ● K8s に習熟したインフラ人員がいる、 もしくはこれから揃える GKE と Cloud Run どちらを選択するか? Cloud Run を選択する場合  ● とにかくスモールスタートしたい ● パフォーマンスとかスケーリングとかは Cloud Run にお任せ ● アプリ開発者中心の小規模チーム ● K8s に習熟した専門インフラチームがいない、 これから揃える予定もない GKE Autopilot の使い所は? K8s のマネージドサービスでありながら、GKE Standard よりシンプルに運用出来るのが強み。 K8s にチャレンジしたいが、K8s のクラスタ設計や運用にリソースを多く割けない場合や、 パフォーマンス・チューニング、高速なスケーリングなどが必要ない場合におすすめ!!
  • 17.
    Proprietary + Confidential GKEの世界観 OSS な抽象化 されたインフラ GKE は Google Cloud 上に展開された別のプラットフォーム GCE の世界観 プロプラなインフラ GCLB GCE PD Filestore mapping mapping mapping Reconciliation loop による状態維持 宣言型 モデルの API
  • 18.
    Proprietary + Confidential Kubernetesでは マニフェストという設定ファイルを使う。 従来の命令型 API と違い処理(How)を書くのではなく、 何を達成したいか(What)だけを書く 利用者はコンテナを利用するための 細かいインフラ周りの処理を把握する必要はない。 Kubernetes はマニフェストに書かれた状態を 常に維持しようとする( Reconciliation loop)ため、 人の手を介さずともシステムの健常な状態を維持できる。 (e.g. オートヒーリング ) 宣言型 モデル と Reconciliation loop あるべき状態 現在の状態 マニフェストで定義 K8s のクラスタでの Live の状態
  • 19.
    Proprietary + Confidential GKE 1.コードを書く 2. Dockerfile 作成(省略可能※後述) 3. $ docker build 4. $ docker push 5. $gcloud container clusters create ~ 6. $ kubectl apply -f deployment.yml 7. $ kubectl apply -f service.yaml 8. $ kubectl apply -f hautoscal.yaml Cloud Run 1. コードを書く 2. Dockerfile 作成(省略可能※後述) 3. $ docker build 4. $ docker push 5. $ gcloud run deploy.. サービス公開までの手数(例)
  • 20.
  • 21.
    Proprietary + Confidential 1.アプリケーション構成の確認/ コンテナに最適化させる 2. アーキテクチャ設計 3. 実際の移行 大まかな手順
  • 22.
    Proprietary + Confidential GCEで運用する Web アプリケーション(例) GCE + PD for Web Application server (e.g. Nginx && gunicorn && Flask) Cloud SQL for dynamic data (e.g. MySQL) External HTTP (S) LB Cloud Storage for static contents Cloud CDN IAP for user auth /static/* /* Client
  • 23.
  • 24.
    Proprietary + Confidential 既存のアプリケーションに、 多数の機能が含まれている場合は なるべく機能毎にサービスを分割し、 コンテナ化することが望ましい。 コンテナの特徴を活かすため、 出来る限り1 コンテナ = 単一機能 を目指す。 機能毎に異なるライフサイクルや 非機能要件がある場合、分割は有意義。 複数の機能を持つアプリケーションの場合は分割を考える 機能 A 機能 B 機能 C 機能 D 既存アプリケーション 機能 A の サービス (コンテナ) 機能 B の サービス (コンテナ) 機能 C の サービス (コンテナ) 機能 D の サービス (コンテナ)
  • 25.
    Proprietary + Confidential 仮想マシンのローカルストレージで扱うデータが ある場合、コンテナ化した場合にどこで扱うかを 検討する。 GKE の場合 ● GCE の PD ● Cloud Filestore ● GCS Cloud Run の場合 ● Cloud Filestore ● GCS ローカルストレージの利用有無を確認する 機能 D 例えばユーザーがアップロードした ファイルをローカルストレージ に保管していたとする /var/hoge/application-data/fuga
  • 26.
  • 27.
    Proprietary + Confidential GKEに移行した Web アプリケーション構成(例) GKE for Web Application server Cloud SQL for dynamic data (e.g. MySQL) External HTTP (S) LB Cloud Storage for static contents Cloud CDN IAP for user auth Cloud Filestore for Upload files Client
  • 28.
    Proprietary + Confidential GKEに移行した Web アプリケーション構成(例)K8s リソース版 サービスA サービスB サービスC サービスD GCS 用 Proxy フロントエンド BackendConfig for IAP && Cloud CDN サービス毎のDB GCS は Ingress の BE に設定 不可のため、GKE の Pod で Proxy させる Web page をレンダリングする フロントエンドと Business logic を持つAPI サービスに分離 Upload Files 用に Cloud Filestore を 利用(RWX)
  • 29.
    Proprietary + Confidential ●GKE の Node(コンテナが動くところ)は GCE の仮想マシンを使うため、 GCE のアーキテクチャと大枠は変わらない。 ● GKE への移行メリット(宣言型 API / Reconcilication Loop)を最大限享受する意味で、 K8s の API でなるべく運用を完結できるよう設計する。 ● ただし、K8s API によって Wrap されたことにより、Google Cloud のサービスが 本来備えていながら、利用できない機能もあることに注意が必要。 GKE アーキテクチャ設計のポイント
  • 30.
    Proprietary + Confidential CloudRun に移行した Web アプリケーション構成(例) フロントエンド External HTTP (S) LB サービス毎のDB サービスA サービスB サービスC サービスD フロントエンドのCloud Run は Serverless NEG を 利用し LB の下に。 フロントエンドと 各サービス間はIAM 認証を 利用しセキュアに。 Cloud CDN IAP for user auth Cloud Run 2nd gen execution environment を利用しNFS マウント LB の Backend とし て Bucket を 設定 Client
  • 31.
    Proprietary + Confidential ●Cloud Run 単体でも外部公開は可能だが、 IAP / CDN / GCS との連携を行うため、 Serverless NEG を利用し、HTTP(S)LB と連携させる。 ● Cloud Run は VPC 内で動作しないため、 Cloud SQL との接続は、以下のいずれかの方法を使い実現 する。Cloud SQL Auth Proxy を利用する方がシンプルでおすすめ。 ○ Cloud SQL Auth Proxy ○ Serverless VPC Access Connector ● Cloud Run へ Cloud Filestore を NFS マウントするためには、 Cloud Run の 2nd gen execution environment が必要だが、まだ Preview のため注意が必要。 Cloud Run アーキテクチャ設計のポイント
  • 32.
  • 33.
    Proprietary + Confidential 1.段階的な移行(ストラングラーパターン亜種) ○ 機能ごとに段階的に新環境に移行を行う。 ○ 一括移行と比較しリスク低、現実的な方式 2. 一括移行 ○ 新環境を併設し、旧環境から DNS 切り替えによる一括の移行を行う。 ○ 環境間でのデータの一貫性を担保するのが難しい。 DB を分割せず、 旧 DB を継続利用する等の前提があれば難易度は下がる。 環境毎にやり方はたくさん ... 実際の移行方式
  • 34.
    Proprietary + Confidential 段階的な移行(ストラングラーパターンの亜種)のイメージ 2.サービスA を Cloud Run へ移行、GCE は サービスA の API を呼び、その結果を元 に Web page の レンダリングを行う。 1. 元の構成 3. サービスB を Cloud Run へ移行。移行前の機能は そのまま旧DB を利用。 4. 同様の手順で サービスC / D を Cloud Run へ移行。 5. GCE に残っていたHTTP Handler / Web page レンダリングを行う フロントエンド部分をCloud Run へ移行。 /static/* /* /static/* /* /static/* /* /static/* /* /static/* /*
  • 35.
  • 36.
    Proprietary + Confidential 1.開発のワークフロー の見直し 2. モニタリング / ロギング の見直し 3. GKE のバージョン アップグレード 対応 やること
  • 37.
  • 38.
    Proprietary + Confidential 仮想マシン〜開発から初回デプロイまでのフロー(例) 1.アプリ開発(コーディング、ビルド、テスト) 2. 仮想マシンの作成 ● Terraform / Vagrant 3. OS 周りの設定、アプリ、依存ライブラリ等の インストール ● Playbook 作成 ● Ansible で仮想マシンに対して プロビジョニング 4. ゴールデンイメージの作成 ● Packer 5. ゴールデンイメージからサーバー作成 ● Terraform / Deployment Manager 他
  • 39.
    Proprietary + Confidential コンテナ〜開発から初回デプロイまでのフロー(例) 1.アプリ開発(コーディング、ビルド、テスト) 2. コンテナイメージの作成 / 保管 ● Dockerfile の作成 ● docker build && docker push 3. コンテナイメージのデプロイ ● kubectl / gcloud / Terraform 他
  • 40.
    Proprietary + Confidential CI/CDのフロー(例) git repo trigger gcloud compute ssh…. kubectl apply -f ***.yaml gcloud run deploy…. Source の Build&&Test&& コンテナ イメージのビルド、Artifact Registry への Push Source の Build&&Test、成果物のArtifact Registry への Push(Option) Source の Build&&Test&& コンテナ イメージのビルド、Artifact Registry への Push GCE は現用の仮想マシン 上でファイルの入れ替えを 行ってプロセスを リスタート GKE/Cloud Run は現用の コンテナを新しい コンテナに入れ替える
  • 41.
    Proprietary + Confidential 同じところ ●アプリケーションを動作させるための 環境設定を定義するファイルが必要 ○ 仮想マシン = Ansible Playbook ○ コンテナ = Dockerfile 違うところ ● 仮想マシンは実際に欲しい構成のインスタンスを作って、そこからイメージ作成。 コンテナは設定ファイル( Dockerfile)からイメージを直接作成。 ● コンテナの方がより Immutable( 但し Spinnaker のような 3P ツールを使えば、 仮想マシンでもコンテナと似たようなことが出来る) 仮想マシンとコンテナ、ワークフロー差分
  • 42.
    Proprietary + Confidential [参考]Buildpacks "Google Cloud Platform/buildpacks: Builders and buildpacks designed to run on Google Cloud's container platforms" https://github.com/GoogleCloudPlatform/buildpacks $ ls index.js package.json ## Cloud Build で利用 $ gcloud builds submit --pack image=gcr.io/my-project/my-app ## pack コマンドを通じて利用 $ pack build my-app --builder gcr.io/buildpacks/builder:v1 ## Cloud Run のデプロイ時に利用 $ gcloud run deploy SERVICE_NAME --source . 指定したディレクトリ以下を解析し、 Dockerfile なしに適切なコンテナへビルドする。 サポート言語 ● Go 1.10+ ● Node.js 10+ ● Python 3.7+ ● Java 8, 11 ● .NET Core 3.1+
  • 43.
    Proprietary + Confidential ロギング/ モニタリング の見直し
  • 44.
    Proprietary + Confidential CloudLogging を利用。 ● GCE ○ Ops エージェント をインストールして利用。 ○ Host 自身の Syslog、任意のログファイルから取得可能。 さらに Host 内で TCP レシーバーを設定可能。 ● GKE ○ ロギングエージェントが Node にデフォルトでインストールされており、 特に設定を行わなくてもコンテナの Stdout, Stderr がデフォルトで収集される。 ● Cloud Run ○ 特に設定を行わなくてもコンテナの Stdout, Stderr がデフォルトで収集される。 ロギング
  • 45.
    Proprietary + Confidential 構造化ログの活用 従来のようにログをファイルへ出力するのではなく、GKE / Cloud Run では Stdout, Stderr に対してログを 出力するのがオススメ。 構造化ログを利用することで、 検索しやすい形式でログを出力することが可能。 特殊フィールド (例: severity )は jsonPayload から 削除され、対応フィールドに書き込まれる。 # Build structured log messages as an object. global_log_fields = {} # Complete a structured log entry. entry = dict( severity="NOTICE", message="This is the default display field.", component="arbitrary-property", **global_log_fields, ) print(json.dumps(entry))
  • 46.
    Proprietary + Confidential CloudMonitoring を利用。 ● GCE ○ Ops エージェントをインストールすることで CPU やメモリ、ディスクなどのメトリクスが収集され る。 ● GKE ○ メトリクス エージェントが Node にデフォルトでインストールされており、 特に設定を行わなくても Node やコンテナのシステムメトリクスが収集される。 ● Cloud Run ○ 特に設定を行わなくても リクエスト数や CPU 使用率など コンテナのシステムメトリクスが収集さ れる。 モニタリング
  • 47.
    Proprietary + Confidential GKEバージョンアップグレード対応
  • 48.
    Proprietary + Confidential Kubernetesは〜3 ヶ月毎に最新のバージョンをリリース、パッチは〜1 ヶ月毎にリリース GKE は Kubernetes のリリースに加えてセキュリティおよびバグ修正を提供 Control Plane バージョン Kubernetes の Control Plane で 使われるバージョン。 Kubernetes クラスタで使われる大半の ソフトウェアのバージョンを指す。 Node バージョン Kubernetes の Nodeで使われる バージョン。主に OS イメージおよび Kubelet のバージョンを指す。 GKE バージョンアップグレード GKE のバージョン ポリシー ● Node は Control Plane よりも新しいバージョンは使えない ● Node は Control Plane から 2 マイナーバージョン古いものまで利用可能
  • 49.
    Proprietary + Confidential つまり、数ヶ月に一度はNode の再作成を伴う、バー ジョンアップグレードが必要!!
  • 50.
    Proprietary + Confidential アップグレードのパターン 1.リリースチャネルを指定したクラスタ ● 各チャネル毎に設定された頻度に従い、Control Plane も Node も自動アップグレードされる ● 自動アップグレードは無効化できない(リリースチャネルから外すことは可能) ● 自動アップグレードを待たずに手動アップグレードすることも可能 2. 静的にバージョンを指定したクラスタ ● Control Plane ○ 自動アップグレードされる(無効化不可) ● Node ○ デフォルトは自動アップグレードが有効(無効化可能) ○ 自動アップグレードを無効にしてる場合は、ユーザーによる手動アップグレードが必要
  • 51.
    Proprietary + Confidential メンテナンスの時間枠と除外 ●メンテナンス時間枠( Maintenance Windows) ○ 自動メンテナンスの実行を許可する定期的な時間枠 ■ 32 日周期で最低 48 時間の時間枠 ■ 各時間枠は 最低 4 時間以上の連続した時間 ● メンテナンス除外(Maintenance Exclusion) ○ 自動メンテナンスの実行を禁止する定期的な時間枠 ○ 1 クラスタ 3 つまで
  • 52.
    Node pool A(計 4 Nodes) > max_surge_upgrade: 2 > max_unavailable_upgrade: 0 Pod Pod v1.19.15 Pod Pod v1.19.15 Pod Pod v1.19.15 Pod Pod v1.19.15 Pod Pod v1.19.15 Pod Pod v1.19.15 Pod Pod v1.19.15 Pod Pod v1.19.15 v1.20.10 v1.20.10 Pod Pod v1.19.15 Pod Pod v1.19.15 v1.19.15 v1.19.15 v1.20.10 v1.20.10 Pod Pod Pod Pod Drain Pod Pod v1.19.15 Pod Pod v1.19.15 v1.20.10 v1.20.10 Pod Pod Pod Pod v1.20.10 v1.20.10 v1.20.10 v1.20.10 Pod Pod Pod Pod v1.19.15 v1.19.15 v1.20.10 v1.20.10 Pod Pod Pod Pod v1.20.10 v1.20.10 Pod Pod Pod Pod v1.20.10 v1.20.10 Pod Pod Pod Pod Drain Drain Drain 新しいバージョンの Node を 2 つ追加 古いバージョンの Node をドレイン Pod を新しい Node に スケジュール 新しいバージョンの Node を 2 つ追加 古いバージョンの Node をドレイン Pod を新しい Node に スケジュール アップグレード開始 アップグレード完了
  • 53.
    Proprietary + Confidential 本番環境で無理なく自動アップグレードしていくために 1.自動アップグレードの前にテストを行う a. テスト用のクラスタは常設しておく b. 事前にテスト用クラスタを手動で最新バージョンに上げ、動作確認を行う 2. なるべく Stable channel を使う a. アップグレード頻度をなるべく少なく b. Bug などの影響をなるべく少なく 3. メンテナンス時間枠を正しく設定する 4. 除外時間を正しく設定する a. アップグレードの延期 b. ビジネスのピークタイムを絶対避ける
  • 54.
    Proprietary + Confidential リリースチャネルを使ったアップグレードのワークフロー(例) 4. テスト環境のクラスタで 動作確認テスト Google サポートに連絡 ロールバック NG 5. メンテナンス時間枠で 本番環境の自動アップグレード OK Available バージョンがリリースされてから、自動 アップグレードが走るまでの目安 Patch バージョン: 1 週 Minor バージョン: 3 週 3. テスト環境のクラスタを Available バージョンに 手動アップグレード 2. Available バージョン通知を Cloud Functions で Slack に転送 1. Google Cloud から Pub / Sub へ Available バージョン通知
  • 55.
  • 56.
    Proprietary + Confidential ●コンテナ移行は簡単ではない。コストの方が高くなることも、慎重な検討が必要。 ● GCE からコンテナへ移行するのであれば、既存アプリケーションの規模に依るが、 まずは Cloud Run から始めることを推奨。 コンテナの良さがありながら、運用は非常にシンプル。 ● 大規模なアプリケーションであればGKE を推奨するが、K8s に精通した専門の エンジニアをアサインすることを推奨。居ないなら少なくともGKE standard の 採用は避けた方が無難。 まとめ
  • 57.