Kubernetes環境でCI/CDを実現する「GitOps」について。 @さくらの夕べ Docker/Kubernetesナイト
お受けした質問の一部はこちらのツイートに紐づく形で回答しています→https://twitter.com/amaya382/status/1140575485878886400
Kubernetesを最⼤限に活かすためのGitOps⼊⾨@さくらの⼣べ Docker/Kubernetesナイト技術本部 伊藤⻯⼀ (@amaya382)2019/6/17
View Slide
⾃⼰紹介伊藤⻯⼀• しごと• 所属: 技術本部 アプリケーショングループ• 新規プロジェクト×2でKubernetesを導⼊中• 1つはAPIサーバのデプロイ先、バッチ処理実⾏環境として• 1つはスケーラブルなデータ処理基盤として• こじん• Twitter: @amaya382• Kubernetesに関する同⼈誌を書いたり• 技術書典7もKubernetes関係で模索中2
対象者とゴール前提• k8s・CI/CDの基本的な概念をある程度理解している対象者• k8s上にアプリをデプロイするベストプラクティスを知りたい⼈ゴール• GitOpsの概念を知る• 既存のCI/CDとの違い• GitOps導⼊に必要な諸々を知る• あわよくば、「kubectlで⼿動デプロイするのは⼩学⽣までだよねーwww」ぐらいの⼼意気を⼿に⼊れる3
GitOpsの概要とゴール k8s環境を前提としたCI/CDの戦略• 原典: https://www.weave.works/technologies/gitops/全ての設定をコード化、Gitで管理• 属⼈化したHackを防ぐ• デプロイ状態の確認を容易に• 開発だけでなく、運⽤作業もGitの操作で統⼀適切な関⼼の分離• 権限の分離• セキュリティリスクの抑制4例えば…Git Revertでサービス巻き戻し
GitOpsの概要とゴール k8s環境を前提としたCI/CDの戦略• 原典: https://www.weave.works/technologies/gitops/全ての設定をコード化、Gitで管理• 属⼈化したHackを防ぐ• デプロイ状態の確認を容易に• 開発だけでなく、運⽤作業もGitの操作で統⼀適切な関⼼の分離• 権限の分離• セキュリティリスクの抑制5CIの権限は最低限に
GitOpsを従来のCI/CDと⽐較する6
CI/CDを振り返るCI/CDの⽬的は?• 変更があった際に必要な処理の⾃動化CIとCDは似ているが、役割が少し異なる• CI(ContinuousIntegration)• ⾃動的なテスト実⾏・ビルド成果物(DockerImage、npmパッケージ等)アップロード• CD(ContinuousDelivery/Deployment)• ⾃動的なアプリデプロイ※2つまとめてCIと呼ぶことも多い7Push Hookビルド・テスト実⾏コード変更Hookデプロイ実⾏開発者Deploy
CI/CDを振り返るCI/CDの⽬的は?• 変更があった際に必要な処理の⾃動化CIとCDは似ているが、役割が少し異なる• CI(ContinuousIntegration)• ⾃動的なテスト実⾏・ビルド成果物(DockerImage、npmパッケージ等)アップロード• CD(ContinuousDelivery/Deployment)• ⾃動的なアプリデプロイ※2つまとめてCIと呼ぶことも多い8Push Hookビルド・テスト実⾏コード変更Hookデプロイ実⾏開発者DeployCI
CI/CDを振り返るCI/CDの⽬的は?• 変更があった際に必要な処理の⾃動化CIとCDは似ているが、役割が少し異なる• CI(ContinuousIntegration)• ⾃動的なテスト実⾏・ビルド成果物(DockerImage、npmパッケージ等)アップロード• CD(ContinuousDelivery/Deployment)• ⾃動的なアプリデプロイ※2つまとめてCIと呼ぶことも多い9Push Hookビルド・テスト実⾏コード変更Hookデプロイ実⾏開発者DeployCD
k8s環境へアプリデプロイkubectl applyコマンド• いい感じに新規作成または部分更新してくれる• ただし、⼿動では「apply漏れ」・「デプロイ先間違い」・「権限管理問題」等が発⽣10Apply開発環境で試してみよう? ? 環境
k8s環境へアプリデプロイkubectl applyコマンド• いい感じに新規作成または部分更新してくれる• ただし、⼿動では「apply漏れ」・「デプロイ先間違い」・「権限管理問題」等が発⽣11Apply? ? 環境本番本番環境だった!!
k8s環境で従来のCI/CD (CIOps)「CI/CDでkubectlすればいいじゃん」 サービスの世代管理が困難 意図したデプロイ状況になっているか分からない 属⼈化したHackが発⽣ パワフルな権限を持つCI ※GitOpsと対⽐して、従来のCI/CDをCIOpsと呼ぶ• Push型12Apply開発環境本番環境Apply
k8s環境で従来のCI/CD (CIOps)「CI/CDでkubectlすればいいじゃん」 サービスの世代管理が困難 意図したデプロイ状況になっているか分からない 属⼈化したHackが発⽣ パワフルな権限を持つCI ※GitOpsと対⽐して、従来のCI/CDをCIOpsと呼ぶ• Push型13Apply開発環境本番環境Apply変更をデプロイするだけ状態を管理できるわけではない
k8s環境で従来のCI/CD (CIOps)「CI/CDでkubectlすればいいじゃん」 サービスの世代管理が困難 意図したデプロイ状況になっているか分からない 属⼈化したHackが発⽣ パワフルな権限を持つCI ※GitOpsと対⽐して、従来のCI/CDをCIOpsと呼ぶ• Push型14Apply開発環境本番環境Apply誰も触れない秘伝のタレ
k8s環境で従来のCI/CD (CIOps)「CI/CDでkubectlすればいいじゃん」 サービスの世代管理が困難 意図したデプロイ状況になっているか分からない 属⼈化したHackが発⽣ パワフルな権限を持つCI ※GitOpsと対⽐して、従来のCI/CDをCIOpsと呼ぶ• Push型15Apply開発環境本番環境Apply⾼セキュリティリスク
GitOpsとはDevOps技術の1つで、Gitを利⽤しk8sに特化したCI/CD戦略• SingleSourceofTruthとして、サービスの状態を1つのGitリポジトリで持つ• 関⼼ (CI/CD) の分離• 権限の分離16SingleSourceofTruth(Manifestファイル群)SSoTと同期• アプリAを2つ• アプリBを4つ• GET /users はアプリAへ• POST /comments はアプリBへ• ロードバランサが必要
Docker RegistryGitOpsとはDevOps技術の1つで、Gitを利⽤しk8sに特化したCI/CD戦略• SingleSourceofTruthとして、サービスの状態を1つのGitリポジトリで持つ• 関⼼ (CI/CD) の分離• 権限の分離17SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)アプリソースコード CIツールCDツール
Docker RegistryGitOpsとはDevOps技術の1つで、Gitを利⽤しk8sに特化したCI/CD戦略• SingleSourceofTruthとして、サービスの状態を1つのGitリポジトリで持つ• 関⼼ (CI/CD) の分離• 権限の分離18SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)CIHookアプリイメージ更新開発者(Dev)アプリソースコード CIツールCDツール
Docker RegistryGitOpsとはDevOps技術の1つで、Gitを利⽤しk8sに特化したCI/CD戦略• SingleSourceofTruthとして、サービスの状態を1つのGitリポジトリで持つ• 関⼼ (CI/CD) の分離• 権限の分離19SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)CDアプリソースコード CIツールCDツール
Docker RegistryGitOpsとはDevOps技術の1つで、Gitを利⽤しk8sに特化したCI/CD戦略• SingleSourceofTruthとして、サービスの状態を1つのGitリポジトリで持つ• 関⼼ (CI/CD) の分離• 権限の分離20SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)アプリソースコード CIツールCDツールCDCI
Docker RegistryGitOpsとはDevOps技術の1つで、Gitを利⽤しk8sに特化したCI/CD戦略• SingleSourceofTruthとして、サービスの状態を1つのGitリポジトリで持つ• 関⼼ (CI/CD) の分離• 権限の分離21SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)アプリソースコード CIツールCDツールデプロイ実⾏
Docker RegistryGitOpsの全体像22SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)アプリソースコード CIツールCDツール1. コードをPush
Docker RegistryGitOpsの全体像23SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)アプリソースコード CIツールCDツール2. CI動作開始
Docker RegistryGitOpsの全体像24SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)アプリソースコード CIツールCDツール3. ビルド成果物をアップロード
Docker RegistryGitOpsの全体像25SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)アプリソースコード CIツールCDツール4. 更新を反映するPRを作成
Docker RegistryGitOpsの全体像26SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)アプリソースコード CIツールCDツール5. 更新を確認・承認
Docker RegistryGitOpsの全体像27SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)アプリソースコード CIツールCDツール6. SSoTが更新
Docker RegistryGitOpsの全体像28SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)アプリソースコード CIツールCDツール7. SSoTが更新を検知・反映
GitOpsの全体像SingleSourceofTruthとして、サービスの状態を1つのGitリポジトリで持つ• コードベースでリソース管理できるk8sと相性CIとCDの分離• CI• テストやビルドに注⼒• Push型• 実⾏環境への権限は不要• CD• デプロイに注⼒• Pull型• ⾃⾝の実⾏環境への権限のみ持つ29apiVersion: apps/v1kind: Deploymentmetadata:labels:app: debugkitname: debugkitspec:replicas: 1selector:matchLabels:app: debugkittemplate:metadata:labels:app: debugkitspec:containers:- image: amaya382/k8s-debugkitname: k8s-debugkit
GitOpsの全体像SingleSourceofTruthとして、サービスの状態を1つのGitリポジトリで持つ• コードベースでリソース管理できるk8sと相性CIとCDの分離• CI• テストやビルドに注⼒• Push型• 実⾏環境への権限は不要• CD• デプロイに注⼒• Pull型• ⾃⾝の実⾏環境への権限のみ持つ30CICD
実際に使うには31
どうやって導⼊するん?• 「ツール選択」• 「アプリとManifest⽤Gitリポジトリの作成」• 「Manifest作成」• 「アプリ側の準備 (CI)」• 「k8s側の準備 (CD)」32
どうやって導⼊するん?「ツール選択」Gitリポジトリ• GitHub/GitHubEnterprise/GitLab/Bitbucket/GitBucket/...• 選ぶポイント:どれを使ってもGitOpsには⼤差なし、よく使ってるやつでokCI• CircleCI/TravisCI/Jenkins/Drone/ConcourceCI/...• 選ぶポイント:どれを使ってもGitOpsには⼤差なし、よく使ってるやつでok• (GitリポジトリやDockerRegistryのCIでも可)33
どうやって導⼊するん?「ツール選択」CD• WeaveFlux/ArgoCD/JenkinsX/...• 選ぶポイント: GitOpsに対応していること、対応しているテンプレートエンジン、権限管理、対応しているデプロイ⽅法 (e.g.,Blue-Green)、UIやCLIの使いやすさManifestテンプレートエンジン• Helm/kustomize/...• 選ぶポイント:対応しているCDツール、扱いやすさ• ※ksonnetは開発中⽌の⾒込みなので注意• ※Helm3は未知数34
どうやって導⼊するん?「アプリとManifest⽤Gitリポジトリの作成」• アプリごとのリポジトリ• Manifestリポジトリはプロジェクトで1つ(Single Source of Truth)「Manifest作成」• k8sのManifestを作成• 開発⽤・本番⽤といった環境の切り替えにはテンプレートを利⽤• e.g.,接続先DB、レプリカ数35アプリソースコードSingleSourceofTruth(Manifestファイル群)
どうやって導⼊するん?「アプリとManifest⽤Gitリポジトリの作成」• アプリごと• Manifestリポジトリはプロジェクトで1つ(Single Source of Truth)「Manifest作成」• k8sのManifestを作成• 開発⽤・本番⽤といった環境の切り替えにはテンプレートを利⽤• e.g.,接続先DB、レプリカ数36アプリソースコードSingleSourceofTruth(Manifestファイル群)apiVersion: apps/v1kind: Deploymentmetadata:labels:app: debugkitname: debugkitspec:replicas: 1selector:matchLabels:app: debugkittemplate:metadata:labels:app: debugkitspec:containers:- image: amaya382/k8s-debugkitname: k8s-debugkit
どうやって導⼊するん?「アプリとManifest⽤Gitリポジトリの作成」• アプリごとのリポジトリ• Manifestリポジトリはプロジェクトで1つ(Single Source of Truth)「Manifest作成」• k8sのManifestを作成• 開発⽤・本番⽤といった環境の切り替えにはテンプレートエンジンを利⽤• e.g.,接続先DB、レプリカ数37アプリソースコードSingleSourceofTruth(Manifestファイル群)
どうやって導⼊するん?「アプリ側の準備 (CI)」• 各アプリのDockerImageをDockerRegistryにプッシュ• 同時に、「新しいDockerImageを利⽤するManifest」のプルリクエストをManifestリポジトリに作成38Docker RegistrySingleSourceofTruth(Manifestファイル群)デプロイ要求(PR作成)アプリイメージ更新CIツールCI設定
どうやって導⼊するん?「k8s側の準備 (CD)」• クラスタ別にCDツールをインストール• Manifestリポジトリを利⽤するCD設定を追加39環境ごとにPullすることで最低限の権限で動作SingleSourceofTruth(Manifestファイル群)CDツールCDツール開発環境本番環境CD設定CD設定
どんな感じにサイクル回すん?アプリ単体の更新1. 開発者が各アプリリポジトリに変更をPush(実際にはプルリクエストを経由)2. CIが動作1. ビルドし、DockerImageをDockerRegistryへPush2. 新しいDockerImageを使うように変更するプルリクエストを作成3. 運⽤者がプルリクエストを確認・承認4. SSoTが更新される5. CDがSSoTの変化を検知・反映40従来のデプロイ作業をプルリクエスト承認で⾏う
Docker Registryどんな感じにサイクル回すん?41SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)アプリソースコード CIツールCDツール1. コードをPush⼈⼿⾃動
Docker Registryどんな感じにサイクル回すん?42SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)アプリソースコード CIツールCDツール2. CI動作開始2-2. 更新を反映するPRを作成⼈⼿⾃動2-1. ビルド成果物をアップロードPR
Docker Registryどんな感じにサイクル回すん?43SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)アプリソースコード CIツールCDツール3. 更新を確認・承認⼈⼿⾃動PR
Docker Registryどんな感じにサイクル回すん?44SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)アプリソースコード CIツールCDツール4. SSoTが更新⼈⼿⾃動
Docker Registryどんな感じにサイクル回すん?45SingleSourceofTruth(Manifestファイル群)アプリの更新デプロイ要求(PR作成)Hookアプリイメージ更新開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)アプリソースコード CIツールCDツール5. SSoTが更新を検知・反映⼈⼿⾃動
どんな感じにサイクル回すん?サービス構成の更新1. 開発者がManifestリポジトリを更新するプルリクエストを作成2. 運⽤者がプルリクエストを確認・承認3. SSoTが更新される4. CDがSSoTの変化を検知・反映46
どんな感じにサイクル回すん?47SingleSourceofTruth(Manifestファイル群)構成変更要求(PR作成)開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)CDツール1. サービス構成を変更するPRを作成⼈⼿⾃動PR
どんな感じにサイクル回すん?48SingleSourceofTruth(Manifestファイル群)構成変更要求(PR作成)開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)CDツール2. 更新を確認・承認⼈⼿⾃動PR
どんな感じにサイクル回すん?49SingleSourceofTruth(Manifestファイル群)構成変更要求(PR作成)開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)CDツール3. SSoTが更新⼈⼿⾃動
どんな感じにサイクル回すん?50SingleSourceofTruth(Manifestファイル群)構成変更要求(PR作成)開発者(Dev)デプロイ実⾏(PR承認)運⽤者(Ops)CDツール4. SSoTが更新を検知・反映⼈⼿⾃動
残る課題• 全体が揃うと⼀気に動き出すモデルなので、最初のセットアップがやや⼤変• 適切なブランチ戦略が必要• どのような変更をどの環境への変更としたいか• サービスによりその戦略は異なる• e.g.,• 似たようなプロダクション環境が⼤量に必要になる場合• バージョンごとにプロダクション環境を維持し続けていく場合51
まとめ DevOps技術の1つで、Gitを利⽤しk8sに特化したCI/CD戦略How• SingleSourceofTruthとして、デプロイ状態を1つのGitリポジトリで管理• 関⼼ (CI/CD) の分離Result• 全ての設定をコード化、Gitで管理• 属⼈化したHackを防ぐ• Gitリポジトリの状態 == デプロイの状態• 開発だけでなく、運⽤作業もGitの操作で統⼀• 適切な関⼼の分離• 権限の分離• セキュリティリスクの抑制52運⽤者(Ops)開発者(Dev)
ベストプラクティス・ Pitfall集 CDツールって1箇所に設置すれば集中管理できて楽じゃん!• 別クラスタの稼働状況に依存させるべきではない別クラスタへのアクセス権限をもたせるべきではない• 環境ごとに設置し、Pull型を維持すべき k8s外のリソースは?• 考慮されていないので難しい• k8s上のCDツールではk8s外リソースのデプロイを管理しないほうが良い• e.g.,TerraformでSaaSのRDBを構築• Manifestにはサービスへのアクセス情報だけ保持 (e.g.,HeadlessService)• ≒k8s内のServiceDiscovery対象には⼊れておく53
ベストプラクティス・ Pitfall集 あれ?反映できてない?• 即座に更新されるリソース・されないリソース• e.g.,環境変数の更新→Podを再起動しないと反映されない• CDツールが判断して全てを適切に更新してくれるのが理想• ⚠更新ポリシーに注意する必要がある (模索中) 複数アプリの場合、Manifestの更新がバラバラになりそうだけど…?• そもそもアプリ側がバラバラにデプロイできるように設計するべき• e.g.,API互換性の管理はURLの /v1/とか54
ベストプラクティス・ Pitfall集 Helmでデプロイまでできるよね?• 「どのHelmパッケージがデプロイされているのか」を別途管理しなければならなくなってしまう• GitOpsでは、Helmはテンプレートエンジンとしてのみ使う• なのでTiller(2.x系にあるk8s内部に設置するリソース)は不要 CredentialsをGitリポジトリに含めるとかありえん!!!• せやな!!!• SealedSecret• https://github.com/bitnami-labs/sealed-secrets• Credentialsを暗号化した状態でManifestリポジトリに含めるk8s側で⾃動的に復号される55
ベストプラクティス・ Pitfall集 IstioやPrometheus、Exporterみたいなやつらの管理は?• 例えばCDツールにはbootstrap問題• 上記のような場合は別リポジトリに切り出し Manifest書くの⼤変そう…• kubectlのcreatedry-runやgetexportでテンプレート作成• 公式APIDocが便利• https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/56
参考⽂献• GitOps• https://www.weave.works/technologies/gitops/• GitOpsではじめるKubernetes CI/CD Pipeline• https://www.slideshare.net/linecorp/gitopskubernetes-cicd-pipeline• Kubernetesで作るコンテナベースCI★CDの⼣べ/ochacafe#1• https://speakerdeck.com/hhiroshell/ochacafe-number-157