Slide 1

Slide 1 text

Helm/ArgoCD で実現する Kubernetes における 宣言的リソースデリバリーの実践 鈴木 祥太

Slide 2

Slide 2 text

自己紹介 鈴木 祥太 (@sshota0809) ● 株式会社ユーザベース SRE チーム所属 ○ B2B 向け SaaS Product を横串で担当 ● 最近 Kubernetes の Gateway API に興味を持っています

Slide 3

Slide 3 text

弊社で運用している CI/CD パイプラインが抱えていた課題を Helm / ArgoCD を使った GitOps で解決したお話 今日の話題

Slide 4

Slide 4 text

アジェンダ CI/CD パイプライン の課題 GitOps の採用 GitOps の導入戦略

Slide 5

Slide 5 text

アジェンダ CI/CD パイプライン の課題 GitOps の採用 GitOps の導入戦略

Slide 6

Slide 6 text

パイプラインの全体像 ● Jenkins をメインで利用 ● e2e~開発環境 / 本番環境へのデプロイでパイプラインを分割 ● 各マイクロサービスは各 Kubernetes 環境にデプロイされる ○ e2e & 開発用クラスタ ○ 本番用クラスタ e2e~開発環境用パイプライン 本番環境用パイプライン DockerImage 作成 e2e 用ネームスペースに リソースデプロイ & e2e 実行 開発用ネームスペースに リソースデプロイ 本番用ネームスペースに リソースデプロイ Istio による B/G 切り替え

Slide 7

Slide 7 text

「Kubernetes へのリソースデプロイ」部分をブレイクダウン e2e~開発環境用パイプライン 本番環境用パイプライン DockerImage 作成 e2e 用ネームスペースに リソースデプロイ & e2e 実行 開発用ネームスペースに リソースデプロイ 本番用ネームスペースに リソースデプロイ Istio による B/G 切り替え

Slide 8

Slide 8 text

Kubernetes へのリソースデプロイ YYY ネームスペースにリソースデプロイ テンプレートファイルから マニフェスト生成 マニフェストを Kubernetes へデプロイ

Slide 9

Slide 9 text

Kubernetes へのリソースデプロイ シンプルだがそれぞれのステップで課題が存在 YYY ネームスペースにリソースデプロイ テンプレートファイルから マニフェスト生成 マニフェストを Kubernetes へデプロイ

Slide 10

Slide 10 text

Kubernetes へのリソースデプロイ YYY ネームスペースにリソースデプロイ テンプレートファイルから マニフェスト生成 マニフェストを Kubernetes へデプロイ

Slide 11

Slide 11 text

課題1 テンプレートファイルからマニフェスト生成 templateファイル (Deployment/etc...) 変数ファイル (e2e/開発/本番) envsubst ● envsubst を利用したテンプレート機構 ○ 変数ファイル内で環境変数を export(変数ファイルの実体はシェルスクリプト) ○ export した環境変数を envsubst でテンプレートファイルに埋め込み ● envsubst とは? ○ 指定したファイルに環境変数を export してくれる ○ やれることが良くも悪くもシンプル ■ 当然テンプレートファイル内で if / for 構文などは利用不可 + = マニフェストファイル

Slide 12

Slide 12 text

課題1 テンプレートファイルからマニフェスト生成 ● envsubst を使ったテンプレート機構だと困る例 ○ あるマニフェスト内で開発環境でのみ 「IP_ADDR」 という環境変数をセットしたい ○ 本番環境では環境変数自体不要だが if 文などが使えないため なにかしらの適当な文字列を代入する必要がある apiVersion: apps/v1 kind: Deployment ... spec: ... image: hoge/fuga:v1 env: - name: IP_ADDR value: ${DEV_DAKE_TEIGI_SITAI} #!/usr/bin/env bash export DEV_DAKE_TEIGI_SITAI=10.10.10.10 👌 dev-env.sh #!/usr/bin/env bash export DEV_DAKE_TEIGI_SITAI=tekito-IP 😒 prd-env.sh

Slide 13

Slide 13 text

課題1 テンプレートファイルからマニフェスト生成 テンプレートエンジンの柔軟性が低い

Slide 14

Slide 14 text

Kubernetes へのリソースデプロイ YYY ネームスペースにリソースデプロイ テンプレートファイルから マニフェスト生成 マニフェストを Kubernetes へデプロイ

Slide 15

Slide 15 text

課題2 マニフェストを Kubernetes へデプロイ ● デプロイが非常に手続き的 ○ パイプライン内で実行するシェルスクリプトで kubectl コマンドを直接実行 ■ kubernetes のコンテキスト情報はパイプライン内にベタ書き ■ Jenkins の Worker ノードでコンテキスト情報を管理する必要あり ■ 「どのリソースがどのクラスタにデプロイされているか」という情報を 宣言的に管理できていない ● 実際にクラスタかパイプラインを見て確認する必要がある def DEV_K8S_CONTEXT = 'hoge@dev-gke01' def NAMESPACE = 'hoge’ ... sh "./create-resources.sh -c ${DEV_K8S_CONTEXT} -n ${NAMESPACE}" ... 😒 pipeline.groovy

Slide 16

Slide 16 text

課題2 マニフェストを Kubernetes へデプロイ kubectl コマンドを実行するという 非常に手続き的なデリバリーになってしまっている

Slide 17

Slide 17 text

リッチなテンプレートエンジンを使いつつ 宣言的なリソースデリバリーを実現したい テンプレートエンジンの 柔軟性の低さ 手続き的なデリバリー

Slide 18

Slide 18 text

Helm / ArgoCD を使い GitOps 化することで 宣言的なデリバリーを実現

Slide 19

Slide 19 text

アジェンダ CI/CD パイプライン の課題 GitOps の採用 GitOps の導入戦略

Slide 20

Slide 20 text

  Helm ● Kubernetes のパッケージマネージャ ○ Chart と呼ばれる Go Template を利用したマニフェストのかたまり ○ リポジトリで公開されているChartの検索やダウンロード、インストール ○ Chartのパッケージ化やリポジトリへのアップロード ● Go Template によるリッチなテンプレートエンジン ○ if/for 文、関数などが利用可能 ○ 変数のリストを yaml 形式で記述可能なため可読性が高い

Slide 21

Slide 21 text

テンプレートエンジンの 柔軟性の低さ Go Template による リッチなテンプレート

Slide 22

Slide 22 text

  ArgoCD / GitOps ● ArgoCD ○ GitOps の思想に基づいた CD ツール ○ Helm / Kustomize とのインテグレーションが可能 ● GitOps ○ 宣言的なデリバリー手法(Weaveworks が提唱) ○ Git のリポジトリで管理されているマニフェスト(状態)を Kubernetes クラスタに同期 ■ single source of truth の実現 ● どんなリソースクラスタで動いているか Git 上で管理されている

Slide 23

Slide 23 text

CD CI GitOps パイプライン アプリのソースコー ドリポジトリ Docker レジストリ マニフェスト ファイル マニフェスト リポジトリ イメージ Build 最新のマニフェストを 専用リポジトリに反映 監視 + 差分検知 差分を反映 ● 設計/方針次第ではあるが CI / CD を分離することが可能 ● マニフェストリポジトリに定義されているもの = 実際にクラスタで稼働しているもの

Slide 24

Slide 24 text

手続き的なデリバリー 宣言的なデリバリー

Slide 25

Slide 25 text

ここからは ArgoCD の使い方や特徴について 詳しく説明していきます

Slide 26

Slide 26 text

 ArgoCD アーキテクチャ API Server Repository Service Application Controller 差分検知 & デプロイ multiple k8s cluster 取得 & cache マニフェスト リポジトリ CLI (argocd command) GUI CI/CD Tools

Slide 27

Slide 27 text

credential  ArgoCD を構成する主なリソース project application account rbac repository Cluster ● project ○ 複数の application をまとめた単位 ● application ○ どの git repository をどの Kubernetes クラスタに同期するか設定 ● account / rbac ○ project や application などに対する権限

Slide 28

Slide 28 text

 ArgoCD Application Resouce の例 apiVersion: argoproj.io/v1alpha1 kind: Application metadata: namespace: argocd labels: app: hoge-api spec: project: hoge source: repoURL: [email protected]:sshota0809/hoge-api.git targetRevision: master path: dir1/dir2 destination: server: https://kubernetes.example.com namespace: hoge-api syncPolicy: automated: - prune: true syncOptions: - Validate=true - PruneLast=true ● source ○ 同期元のリポジトリ情報 ● destination ○ 同期先のクラスタ情報 ● syncPolicy ○ 同期の動きを制御する様々なオプション

Slide 29

Slide 29 text

 ArgoCD の特徴 ● ArgoCD 自身のあらゆる設定を Kubernetes のリソースとして宣言的に管理 ● 差分同期の柔軟な制御 ○ Phase / Wave / Healthcheck など ● GUI / CLI / API あらゆるインターフェースで操作可能

Slide 30

Slide 30 text

 ArgoCD リソースの宣言的管理 ● 各種 CRD ○ Application / Project … ● ConfigMap や Secret ○ argocd-rbac-cm / argocd-cm / argocd-secret / cluster / repository ... data: accounts.tech: apikey,login repositories: | - url: https://github.com/sshota0809/hoge.git repository.credentials: | - url: [email protected]:sshota0809 sshPrivateKeySecret: name: git-ssh-key key: sshPrivateKey ... argocd-cm data: policy.csv: | p, tech, clusters, get, *, allow p, tech, projects, get, *, allow p, tech, repositories, get, *, allow p, tech, accounts, get, *, allow p, tech, applications, get, */*, allow p, tech, applications, sync, hoge/*, allow ... argocd-rbac-cm data: accounts.tech.password: xxx accounts.tech.passwordMtime: xxx accounts.tech.tokens: xxx ... argocd-secret

Slide 31

Slide 31 text

 ArgoCD 差分同期の柔軟な制御 ● Sync Phases ○ 同期されるマニフェストに Annotation を記述することで制御可能 ■ argocd.argoproj.io/hook: ● 「PreSync で Init 処理を流す Job リソースを作成」など ● Sync Waves ○ Phase 内でリソースの同期される順番を制御可能(Default: wave 0) ■ argocd.argoproj.io/sync-wave: PreSync Sync PostSync SyncFail ConfigMap Deployment reading ConfigMap Wave -1 Wave 0

Slide 32

Slide 32 text

 ArgoCD 差分同期の柔軟な制御 ● HealthCheck ○ 各リソースに対する HealthCheck が成功してはじめて「同期が成功した」とみなす ■ 標準リソースに対する HealthCheck は Build-In されている ● https://github.com/argoproj/argo-cd/tree/master/resource_customizations ■ Lua でカスタムヘルスチェックを実装することも可能

Slide 33

Slide 33 text

 ArgoCD GUI / CLI / API での操作 ● GUI ○ 使いやすくリッチな GUI が提供されている ■ ArgoCD にあまり詳しくない人たちもスイスイ使える(と思われる) ● CLI ○ argocd コマンドが提供 ■ 各種リソースの作成 / Sync / Sync が成功したか確認(wait)など多彩なコマンド ● API ○ GUI / CLI ともに内部的に API にアクセスをしているだけ ○ API を利用すれば様々な操作が可能

Slide 34

Slide 34 text

 ArgoCD GUI / CLI / API での操作 ● GUI ○ 各種リソースの Read / Create / Sync などが可能

Slide 35

Slide 35 text

 ArgoCD GUI / CLI / API での操作 ● CLI ○ 各種リソースの Read / Create / Sync などが可能 ○ https://argoproj.github.io/argo-cd/user-guide/commands/argocd/ ■ argocd account - Manage account settings ■ argocd app - Manage applications ■ argocd cluster - Manage cluster credentials ■ argocd login - Log in to Argo CD ■ argocd proj - Manage projects ■ argocd repo - Manage repository connection parameters ...

Slide 36

Slide 36 text

アジェンダ CI/CD パイプライン の課題 GitOps の採用 GitOps の導入戦略

Slide 37

Slide 37 text

GitOps における原理 / 原則 / プラクティス ● ググるとたくさんの情報が提唱されている ○ 5 GitOps Best Practices ■ https://blog.argoproj.io/5-gitops-best-practices-d95cb0cbe9ff ○ GitOps in Kubernetes ■ https://platform9.com/blog/gitops-for-kubernetes/ ● ThoughtWorks 社が公開されている TECHNOLOGY RADER では GitOps は HOLD (Proceed with caution)に指定されていたりもする ■ GitOps | Technology Radar | Thoughtworks ● 色々と情報を集めつつ自分たちの環境にあった形で設計を実施

Slide 38

Slide 38 text

特に考慮した 3 つのポイント 同期の 実行戦略 ブランチ 戦略 Helm との インテグレー ション

Slide 39

Slide 39 text

特に考慮した 3 つのポイント 同期の 実行戦略 ブランチ 戦略 Helm との インテグレー ション

Slide 40

Slide 40 text

同期の実行戦略 ● 自動同期 ○ デフォルトでは 180s 毎に差分確認 + 同期を実行(設定変更可能) ■ パラメータで調整可能だが Application 数と同期スパンに応じて負荷がかかる ○ Gitリポジトリの webhook の設定で同期処理の発火も可能 ● 手動実行 ○ GUI を利用した同期 ○ CLI を利用した同期

Slide 41

Slide 41 text

同期の実行戦略 ● パイプライン上で argocd コマンドによる手動同期をすることを選択 ○ 「e2e デプロイ + HealthCheck の正常性確認~e2e 実行~開発環境へのデプロイ + HealthCheck の正常性確認」を 1 本のパイプラインで実行したかった ■ argocd app sync ● 同期オペレーション ■ argocd app wait ● HealthCheck の正常性確認 (--timeout を指定することで timeoutした場合は異常の終了値返却) e2e~開発環境用パイプライン DockerImage 作成 e2e 用ネームスペースにリソースデプロイ & e2e 実行 開発用ネームスペースに リソースデプロイ

Slide 42

Slide 42 text

同期の実行戦略 ● パイプライン上でコマンドによる CD を実行しているため CI / CD を切り離せていない ○ しかし webhook などの自動同期によって CI / CD を分離すると かえってそれらの連携が必要となり一連の流れが複雑化すると考えた ■ 数珠つなぎに次々発火していくイメージ ○ 運用を続けて自分の環境におけるベストを引き続き模索していく e2e DockerImage 作成 e2e 用マニフェスト生成 + Git に push e2e環境へ差分デプロイ e2e e2e~開発環境 e2e実行 開発用マニフェスト生成 + Git に push 開発環境へ差分デプロイ 開発環境

Slide 43

Slide 43 text

特に考慮した 3 つのポイント 同期の 実行戦略 ブランチ 戦略 Helm との インテグレー ション

Slide 44

Slide 44 text

ブランチ戦略 ● 開発や本番といった環境毎にブランチを分けて運用するケースが多い ● 一方でチームではトランクベース開発を基本としている文化がある 開発ブランチ マニフェスト リポジトリ 本番ブランチ 開発クラスタ 本番クラスタ

Slide 45

Slide 45 text

ブランチ戦略 ● 開発方針に則って GitOps でも branch の複雑性を排除するため main ブランチのみの運用とした ○ 環境毎にディレクトリを切ってそこをそれぞれ監視 ○ これに関しても運用を続けてベストな環境を引き続き模索していく ■ ディレクトリ構造がもたらす複雑性 マニフェスト リポジトリ 開発クラスタ 本番クラスタ dev/hoge-api/ prd/hoge-api/

Slide 46

Slide 46 text

特に考慮した 3 つのポイント 同期の 実行戦略 ブランチ 戦略 Helm との インテグレー ション

Slide 47

Slide 47 text

Helm とのインテグレーション ● Helm Chart を参照することでマニフェストを ArgoCD 内で生成可能 →あえて利用せずパイプライン上で helm template コマンドで  マニフェスト生成し Push ■ Git に定義されているリソースがクラスタにデプロイされている 生のマニフェストになる方が直感的だと考えた ■ Helm Chart はあくまで value とテンプレートが分離された状態なので 生のマニフェストと比べると可読性に劣る場合が多いと考えた apiVersion: argoproj.io/v1alpha1 kind: Application ... source: repoURL: https://github.com/helm/charts.git chart: stable/envoy helm: parameters: - name: "replicaCount" value: "1" releaseName: hoge valueFiles: - hoge.yaml ...

Slide 48

Slide 48 text

最終的なパイプラインの構造 e2e~開発環境用パイプライン 本番環境用パイプライン DockerImage 作成 helm コマンドでマニフェスト作成 + Git push argocd sync / wait コマンドで同期 e2e実行 本番をHelm / argocd でデプロイ 開発をHelm / argocd でデプロイ

Slide 49

Slide 49 text

その他 Tips ● 通知 ○ ArgoCD Notifications を利用し Slack 通知を実装 ■ https://argocd-notifications.readthedocs.io/en/stable/ ■ ユーザ定義のステータスに応じて通知や webhook 実行が可能 ● Application リソースの管理 ○ 開発者が自由に Application リソースを定義可能な運用 ○ プロダクト毎のマニフェスト用リポジトリ内で特定ディレクトリ以下は自動同期する設定 ■ 開発者がそのディレクトリ配下に Application リソースを作成 ○ ArgoCD 自身のリソースも ArgoCD によって同期できる プロダクト A マニフェスト repo プロダクト B マニフェスト repo argocd/appliation/ argocd/appliation/ Kind: Application 自動同期 自動同期

Slide 50

Slide 50 text

まとめ CI/CD パイプライン の課題 GitOps の採用 GitOps の導入戦略 テンプレートエン ジンの柔軟性 / 手続き的な デリバリー Helm / ArgoCD を利用 自チームの文化 なども踏まえつつ 戦略を組み立て