なぜ、Kubernetesの操作にAnsibleを持ち込むのか? —— `kubectl apply` の先にある「冪等性の真実」
諸君、お疲れ様。日々のK8s運用で「`kubectl apply` を打つたびに、差分を気にして心がすり減っていないか?」と問いかけたい。
GitOps全盛の昨今、ArgoCDやFluxCDが正攻法であることは認める。しかし、クラウドネイティブな環境においても、「特定のタイミングで、複数の非同期タスクと連動させてリソースを制御したい」という現場の生々しい要求は消えない。
Shellスクリプトで `kubectl` を叩くのはもうやめよう。それは泥沼の始まりだ。今日は、`kubernetes.core` コレクションを使い倒し、AnsibleでK8sリソースを「宣言的」かつ「完璧な冪等性」で制御する極意を伝授する。
—
1. なぜ `kubectl` ではなく `kubernetes.core.k8s` なのか
最大の理由は「状態の確定」にある。
Shellスクリプトの `kubectl apply` は、「何かが起きたらエラー終了する」ことがあっても、「現在のクラスター状態が期待値と合致しているか」をモジュールレベルで保証するロジックを自前で書く必要がある。
Ansibleの `k8s` モジュールは違う。
- 状態の宣言: 「存在すべきリソース」をYAMLで定義するだけで、既存リソースとのDiffを計算し、必要な変更(作成・更新・パッチ)のみをアトミックに適用する。
- 待機ロジックの統合: `wait: yes` を使うことで、Podの起動完了やDeploymentのレプリカ数整合までをモジュール単体で制御できる。
2. 実践:現場で震えるほど役立つ「神設定」構成
AnsibleでK8sを操作する際、まずやるべきはコレクションの最適化だ。環境ごとに認証情報をベタ書きするのは論外。以下のディレクトリ構成を標準とせよ。
.
├── group_vars/
│ └── k8s_cluster.yml # クラスター接続情報の共通化
├── roles/
│ └── k8s_deploy/
│ ├── tasks/
│ │ └── main.yml # メインロジック
│ └── templates/
│ └── app.yaml.j2 # Jinja2で動的に生成するマニフェスト
└── site.yml
【神設定:group_varsでの接続の一元管理】
`ansible.cfg` に頼らず、`group_vars` で認証を抽象化する。
group_vars/k8s_cluster.yml
k8s_auth:
host: “https://api.cluster.internal:6443”
validate_certs: yes
ca_cert: “/etc/ssl/certs/ca.crt”
# 認証は必ずAnsible Vaultで暗号化して読み込むこと
api_key: “{{ vault_k8s_token }}”
3. `k8s` モジュールの真の実力を引き出す「隠れたテクニック」
① `definition` を使った動的マニフェスト生成
YAMLをそのまま `src` で流し込むのは初級者だ。中級者は `lookup(‘template’, …)` を使い、Jinja2で環境変数に応じたリソースを生成する。
- name: Apply Nginx Deployment
kubernetes.core.k8s:
definition: “{{ lookup(‘template’, ‘nginx-deployment.yaml.j2’) | from_yaml }}”
state: present
wait: yes
wait_condition:
type: Available
status: “True”
register: k8s_result
② 冪等性を極める「パッチ適用」
既存のDeploymentを丸ごと入れ替えるのではなく、必要なフィールドだけを修正したい場合、`merge_type` を活用せよ。
- name: Patch Image Version only
kubernetes.core.k8s:
kind: Deployment
name: my-app
namespace: production
merge_type: merge
definition:
spec:
template:
spec:
containers:
- name: app
image: “my-registry/app:{{ new_version }}”
4. チーム開発を加速させる「開発者の心得」
1. `k8s_info` での事前検証:
何かを適用する前に、必ず `k8s_info` モジュールで現在のリソースの状態を確認せよ。これをタスクの先頭に置くことで、無駄なAPI呼び出しを減らし、失敗時のログが劇的に見やすくなる。
2. Lintと静的解析をCIに組み込む:
`ansible-lint` は当然として、`kube-linter` を通してAnsibleが生成する最終的なマニフェストに脆弱性がないかチェックするパイプラインを組め。
3. キーボードショートカット (VS Code + Ansible):
- `Ctrl + Shift + P` -> `Ansible: Create task from template` を使い倒せ。
- Ansibleの YAMLファイルを編集する際は、必ず `yaml.schemas` 設定に `k8s-1.29-swagger.json` などを指定し、オートコンプリートを効かせること。これでタイポによる事故は9割減る。
結論:Ansibleは「オーケストレーター」の「オーケストレーター」たれ
AnsibleでK8sを操作する最大の利点は、「インフラ構築の最終ステップ」と「アプリケーションのデプロイ」を一つのプレイブックに収束させられることにある。DBのプロビジョニングが完了した瞬間に、そのエンドポイントをK8sのSecretとして流し込み、アプリをデプロイする。
この「一気通貫した自動化」こそが、我々SREが目指すべき地平だ。
さあ、`kubectl` の履歴を追う作業は卒業しよう。Ansibleで宣言し、冪等性を担保し、コードでクラスターを支配せよ。質問があればいつでも受け付ける。エンジニアの諸君、健闘を祈る。