はじめに
こんにちは!
本記事は「本気で学ぶKubernetes」シリーズの第23回です。このシリーズでは、Kubernetesの基礎から実践まで、段階的に学んでいきます。
このシリーズは、第1回から順に読むことで体系的に学べる構成にしています。
まだご覧になっていない方は、ぜひ最初からご覧ください!
今回はこれまで学んできたKubernetes技術を踏まえて、どのように実務で運用していくべきか、またベストプラクティスに則った運用はどうなのかについて触れていきたいと思います。
この記事は人間がKubernetesの公式ドキュメントを読み漁りながら書いていますのでご安心ください!
TL;DR
忙しい方のために要点だけ図示しておきます!
この記事で扱うこと・扱わないこと
この記事はこれまでの記事のように、技術紹介をするというよりはKubernetes運用のベストプラクティスについて触れてどうすれば、効率的に活用していけるのかを中心にまとめていきます。
ですのでKubernetes実務で使う際に「何をやるべきで、何をやらないべきか」を明確にするのが今回のゴールとします。
kubectl は"主役"ではない
このシリーズでは kubectl apply や kubectl create を使ってDeploymentやService、Sercretなど色々なリソースを作成してきました。
学習段階や開発環境では確かにこれで問題ないと思いますが、実運用や本番環境を見据えた際にこれらのコマンドを都度実行してリソースを更新していくのはあまり推奨されることではないと思います。
kubetclの推奨される役割
実運用におけるkubectl の主な用途は、ズバリ「状態確認」と「デバッグ」になると思います。
これまでの記事の中でもPodの状態を見たり、Podのログを見たりなどのコマンドを実行してしました。
初めての方はコマンドについてまとめた記事からご覧いただくとイメージがつきやすいと思います!
【本気で学ぶKubernetes】Kubernetesの基本ツール・コマンドの使い分けまとめ
# Podの状態を確認
kubectl get pods -A
# 詳細情報を見る
kubectl describe pod my-app-xxxx
# ログを確認
kubectl logs my-app-xxxx
# コンテナに入ってデバッグ
kubectl exec -it my-app-xxxx -- bash
つまり、kubectl はリソースを「変更する」ツールではなく、「見る」ためのツールとして運用するのが安全な使い方になると思います。
もちろんスピードを意識して意図的に使う場面もあるとは思います。
なぜ kubectl apply を避けるべきなのか
理由はシンプルで、人間がコマンドを打つと事故が起きるからです。
例えば、開発環境のつもりで本番環境のクラスタに kubectl apply してしまったり。contextや namespaceの切り替え忘れは誰でも一度は経験するミスです。
これはKubernetesに限りませんが、長くシステム開発や運用に携わっていると開発環境だけに適用するつもりが、危うくステージングや本番環境にまで変更を適用しそうになってヒヤッとした経験はあるのではないでしょうか?
Kubernetesでは多数のYAMLファイルを作成する都合、手元のファイルとGitリポジトリの内容が乖離していたり、「誰がいつ何を変更したか」の履歴が残らなかったり、問題が起きたときにロールバックする方法がなかったりなどがあります。
Argo CDといったGitOpsを導入する理由はまさにここにあると思います。
Argo CDについては以下の記事でもまとめているのでぜひご覧ください!
【本気で学ぶKubernetes】GitOpsでKubernetesを宣言的に管理する!Argo CDに入門してみる
kubectlは「read」中心で使い、変更は必ず Git 経由で行う。
これがKubernetes運用における鉄則と言っても良いのかもしれません。(一般的にシステム開発のコード管理も同じかなとは思います)
運用の入口を Git に一本化する(GitOps)
以前の記事でも紹介したArgo CDの本質は「便利なデプロイツール」ではなく、人間が直接クラスタを触らないための安全装置であると思います。
Kubernetesクラスタの状態を変更したい場合は、必ずGitリポジトリを更新しますし、更新するArgo CDが自動的にクラスタに反映してくれます。
変更履歴はGitに残るうえ、変更内容のレビュー行なって問題が起きたら都度差し戻すことも可能です。
Argo CDは「drift(手動変更)」を検知することができますので、仮に誰かが直接クラスタを変更したとしても、Argo CDがGitの状態に戻すように動いてくれます。
なぜ kubectx / kubens が必要になるのか
kubectx と kubens は、Kubernetesを扱う人にとって定番ツールです。
複数のクラスタを切り替えたり、namespace を頻繁に変更したりする場合に便利だと思います。
# 開発環境に切り替え
kubectx gke-dev
# 本番環境のnamespaceに切り替え
kubectx gke-prod
kubens production
kubectxが必要になってしまう時点で、人間が直接複数のクラスタを操作しているということは変わりないので、ここまでの話から言うと理想的な状態ではないですね。
これらのツールは「人間が kubectlで複数の環境を直接触る」前提のツールであるため、GitOpsが完全に導入されればkubectlで直接変更を加えることがなくなるので、当然kubectxの出番も減っていきます。
Kubernetesを使った新規開発やあまり知見がないチームによる開発においては、GitOpsの導入コストから一時的にkubectxやkubensを使うことは当然考えられます。
将来的な安定運用を目指すならGitOpsは導入すべきですし、その際にこれらのコマンドは移行までを乗り切るための補助ツールとして大活躍すると思います。
環境差分の管理(Kustomize入門)
長くなったのでざっくり要約です!
実務でKubernetesを使う場合、開発環境と本番環境で設定を変えたいケースがよくあります。
例えば、開発環境ではPodを1つだけ起動して、本番環境では3つ起動したい。開発環境ではログレベルをDEBUGにして、本番環境ではINFOにしたい。
こういった「ベースは同じだけど、環境ごとに微妙に違う設定」をどう管理するかが課題になります。
愚直にやるなら、deployment-dev.yaml と deployment-prod.yaml を別々に用意する方法もありますが、共通部分を変更したいときに両方のファイルを修正する必要があります。
Kustomizeとは
Kustomizeは、Kubernetesのマニフェストをテンプレート化せずに、ベース + 差分の形で管理できるツールです。
ベースとなるマニフェストは普通のKubernetesのYAMLとして用意し、それに対して上書きしたい差分を定義します。
kubectlにはKustomizeがビルトインされているので、追加のツールをインストールすることなく使用することができます。
HelmとKustomizeの違い
環境ごとに設定を変える方法として、以前の記事で紹介した「Helm」もあります。
【本気で学ぶKubernetes】Helmでアプリを一発デプロイ!パッケージ管理入門
HelmとKustomize、どちらも環境ごとに設定値を変えるための機能がありますがアプローチ異なっています。
Helmの本質は「テンプレートエンジン」です。values.yaml に値を定義して、マニフェストのテンプレートに埋め込みます。
柔軟に使うことはできますが、values.yaml を見ただけでは最終的にどんなマニフェストが生成されるか分かりづらいことがあります。
一方、Kustomizeは「ベース + パッチ」の考え方となっていて、ベースのマニフェストに対して「何を上書きするか」が明確なので、変更内容が分かりやすいです。
既存のレガシー構成を段階的に移行したい場合や、「このマニフェストが最終的にどうなるか」を人間が追いやすくしたい場合は、Kustomizeの方が扱いやすいと思います。
Kustomize の基本構成
多く使用される典型的なディレクトリは以下のような構成になっています。
k8s/
base/
deployment.yaml
service.yaml
kustomization.yaml
overlays/
dev/
kustomization.yaml
patch.yaml
prod/
kustomization.yaml
patch.yaml
base/ に共通のマニフェストを置いて、overlays/dev/ や overlays/prod/ で環境ごとの差分を定義します。
例えば、開発環境では1レプリカ、本番環境では3レプリカにしたい場合、overlays/prod/patch.yaml で replicas: 3 だけを上書きします。
適用するときも以下のように実行します。
# 開発環境
kubectl apply -k k8s/overlays/dev
# 本番環境
kubectl apply -k k8s/overlays/prod
ただし実運用においてもArgo CD は Kustomize をネイティブでサポートしているので、リポジトリのパスを指定するだけで自動的に適用することができます。
もちろんKustomizeを使う場合はHelmを使わないではなく、併用して使うといったこともあります。
Helmで雛形を作ってからKustomizeで微調整をしてくなども選択肢の1つだと思います。
componentsでより柔軟な構成にする
Kustomize v3.7.0以降では components という機能があります。
これは例えば、Redisを有効にするかどうか、外部データベースに接続するかどうかといった「環境によって有効/無効を切り替えたい機能」を components として定義しておくことで、それぞれのoverlayにて必要なリソースだけをインポートして使うことができます。
k8s/
base/
components/
redis/
monitoring/
overlays/
dev/ # redisだけ有効
prod/ # redis + monitoring両方有効
認証・権限設計の分離が重要
役割分担を明確にする
Kubernetesとクラウドの認証・権限管理は、しっかり分けて考える必要があります。
Kubernetes 内の権限は RBAC(Role-Based Access Control)で管理します。「どのServiceAccountがどのリソースにアクセスできるか」を定義するやつですね。
RBACも以前まとめているのでぜひ参考にして下さい!
【本気で学ぶKubernetes】RBAC入門!Pod権限の正しい分け方
一方、クラウドAPIへの権限は Workload Identity(GKEの場合)で管理します。
前回の記事で学んだ通り、Pod内のアプリケーションがCloud StorageやBigQueryにアクセスする際の認証です。
【本気で学ぶKubernetes】Workload Identity入門 - PodからGoogle Cloudリソースに安全にアクセスする
GKEを扱う場合は登場人物が多いからこそ、リソースの認証や権限設計は適切に行なっていく必要があります!
どちらも責任範囲は明確なので以下の区分けになりそうですね。
- GKE内のリソースへのアクセス:KSAのRBAC
- Google Cloudリソースへのアクセス:KSAへのIAM
それぞれどの範囲のリソースまでのアクセスを制御できるのかはしっかりおさえておきましょう!
インフラとアプリケーションの責務分離(Terraform vs GitOps)
長くなったのでざっくり要約です!
インフラ構築といえばIaCとしてコード管理できるTerraformが定番だと思います。
たいしてKubernetesもマニフェストを作成して宣言的にリソースを構築し、さらにはGitOpsでリソースへの自動反映を行うこともできます。
こちらもそれぞれの責務をしっかり理解しておく必要があります。
Terraformが管理すべきもの
Terraformは主に「インフラレイヤー」を管理します。
具体的には以下のようなものが挙げられます。
- GKEクラスタ本体の作成と設定
- VPC、サブネット、ファイアウォールルールなどのネットワーク構成
- Cloud SQL、Cloud Storage、Memorystore などのマネージドサービスの作成と設定
- Google Service Account の作成とIAMロールの付与
上記に挙げた要素はいずれも「クラスタ全体に影響する」「変更頻度が低い」「複数のアプリケーションで共有する」という特徴があります。
Terraformの plan → apply という適用フローは、慎重にレビューを行い変更を確認してから適用するのに向いています。
GitOps(Argo CD)が管理すべきもの
一方GitOpsは「アプリケーションレイヤー」を管理します。
- Deployment、Service、Ingress(アプリケーション固有のもの)
- ConfigMap、Secret
- Kubernetes Service Account
- HPAの設定など
これらは「特定のアプリケーションに紐づく」「変更頻度が高い」「アプリケーションのデプロイと同時に管理したい」という特徴があります。導入するアプリケーションに大きく左右される部分になります。
境界線が曖昧になりがちなもの
実務で迷いやすいのが、Ingress ControllerやPrometheus/Grafanaといった「プラットフォーム的な機能」をどちらで管理するかになります。
Ingress Controllerは、HTTPやHTTPSのトラフィックをクラスタ内のServiceにルーティングするL7ロードバランサーです。nginx-ingressやGKE Ingressなど、いくつかの実装があります。
このIngress Controllerの場合、一般的には以下のような分け方が多いようです。
- Ingress Controller自体(nginx-ingress、GKE Ingressなど):Terraform
- 各アプリケーションのIngressリソース:GitOps
Prometheus/Grafanaなどの監視スタックは、チームによっても管理方法が分かれるようです。
- クラスタ作成時にTerraform Kubernetes/Helm Providerでセットアップしたい:Terraform
- Argo CDのApp of Appsパターンで監視スタックをデプロイ:GitOps
どちらもGKEクラスタ内のPodとして動くアプリケーションなので、「インフラリソース」ではありません。ただし、「クラスタ全体で使う基盤的な機能」という性質を持っていますので、どちらで管理すべきか迷うポイントかなと思います。
チームによってルール決めはあると思いますが、TerraformはGKEクラスタやArgo CD用のクラスタ自体を作成して、Ingress Controllerや監視スタックは全てGitOps(Argo CD等)で管理する方が、圧倒的に幸せになれるかなと思います。
周辺ツールの位置づけ
GitOpsやKubernetes運用の周辺には、たくさんのツールがあります。
全部を深掘りすると正直キリがないので、ここでは簡単にどういうものがあるかだけ整理しておきたいと思います。
Flux
これはArgo CDと同じくGitOpsを実現するためのツールです。
Argo CDよりもシンプルで軽量な印象のツールとなっていて、UIがないためコマンドライン中心の運用になります。どちらを選ぶかは好みやチームの文化次第かなと思います。
KRO(Kube Resource Orchestrator)
Googleが開発しているKubernetes拡張でYAMLを「開発者に書かせない」ためのものです。
Platform Engineeringという文脈で注目されているツールの1つで、「開発者はKubernetesの詳細を知らなくていい」という思想で作られています。
例えば、開発者が「Redisが欲しい」と宣言すれば、事前に用意されたテンプレート(から、Deployment、Service、ConfigMapなどが自動生成されるため、開発者はYAMLを意識する必要がなくなります。
小規模なチームや開発者が全員Kubernetesに精通している場合は、KROでうける恩恵よりも導入コストの方が大きいと思うので、開発者に学習コストをかけさせたくない場合に検討するツールの1つという位置付けかなと思います。
Crossplane
Kubernetes APIを拡張してマニフェストでクラウドリソース(VMやデータベース、ネットワークなど)を管理できるツールです。
Infrastructure as Code on Kubernetesみたいな位置づけです。
まとめ
今回は実務で事故を起こさないためのKubernetes運用のベストプラクティスを整理して見ました。
今までの記事でまとめてきたようなKubernetesのリソースを技術的に利用するためのスキルも大事ですが、それ以上に「どう運用するか」の設計も重要だと思います。
運用上の使い分けなどは実務で経験を積んでようやく分かってくることの方が多いです。今回触れた内容は基礎的なことではありますが、理解しているかどうかだけでもKubernetesの運用に大きく差が出る部分になりますのでぜひおさえておきましょう!
次回はさらに踏み込んで、SRE視点でGKEをどのように運用していくかについて触れていければと思います。
それでは、また次回!


