初めに
前回の記事では、既存 OCI resource を Crossplane に近づける入口として、Observe-only、Platform API、GitOps 連携を整理しました。
Observe-only は既存 resource を壊さず観察する入口であり、Platform API は Bucket のような実装部品を利用者向けの能力として見せる考え方でした。
今回は、最後の判断です。
Crossplane を使うべきか。
Terraform とどう分担するか。
誰が ProviderConfig、Secret、Composite Resource、Managed Resource、OCI IAM を管理するか。
削除時にどの順番で外すか。
このあたりを曖昧にしたまま導入すると、技術的には動いても、運用で迷いやすくなります。
この記事では、Crossplane と OCI Provider を導入する前に確認したい判断軸を整理します。
この記事のゴール
この記事のゴールは、次の質問に答えられるようになることです。
Terraform と Crossplane は何が違うのか
どちらが向いている場面か
ProviderConfig と Secret の責任境界をどう分けるか
namespace と OCI IAM をどう対応させるか
削除時に何を先に消して、何を最後に残すべきか
結論から言うと、比較のポイントは「どちらが優れているか」ではありません。
ポイントは、どの運用時間軸を採用したいか です。
Terraform と Crossplane は時間軸が違う
Terraform は、plan と apply を中心に考える tool です。
Terraform の公式ドキュメントでは、terraform plan は実行計画を作り、変更内容を事前に確認する command と説明されています。
また、terraform apply は、その plan で提案された操作を実行する command です。
つまり、Terraform の中心には、次の流れがあります。
configuration を書く
terraform plan で差分を見る
terraform apply で変更する
state で管理対象を追跡する
一方、Crossplane は Kubernetes controller として動き続けます。
利用者や GitOps tool が Kubernetes API に desired state を置くと、Crossplane Provider がその resource を observe し、外部 resource と状態合わせを続けます。
Kubernetes resource を apply する
Crossplane Provider が observe する
必要なら外部 resource を作成・更新・削除する
status / conditions に結果を書く
この違いは、優劣ではありません。
一回の変更を plan / apply で明示的に扱いたいのか、Kubernetes API 上の desired state と外部状態を継続的に合わせたいのか、という時間軸の違いです。
Terraform が向いている場面
Terraform が向いている場面は、明示的な変更計画と apply の単位を重視したい場合です。
たとえば、次のようなケースです。
単発または低頻度の infrastructure 変更
plan review を中心にした運用
Kubernetes control plane を運用したくない環境
既存の Terraform module と state 管理がすでに安定している環境
Crossplane Provider の対応範囲が要件を満たさない resource
この場合、Crossplane を無理に入れる必要はありません。
特に、単発構築や少数 resource の管理だけが目的であれば、Kubernetes cluster、Crossplane core、Provider、ProviderConfig、RBAC、GitOps まで持つのは重くなることがあります。
大事なのは、Terraform を「古いもの」として捨てることではありません。
Terraform が得意な変更単位と、Crossplane が得意な継続制御を分けて見ることです。
Crossplane が向いている場面
Crossplane が向いている場面は、Kubernetes API を運用の入口にしたい場合です。
たとえば、次のようなケースです。
Kubernetes と GitOps が運用の中心にある
複数チームへ共通 API を提供したい
OCI の細かい field を利用者に直接見せたくない
ProviderConfig や namespace で認証境界を分けたい
既存 resource を Observe-only から段階移行したい
状態を READY / SYNCED / conditions として継続的に見たい
Crossplane の Managed Resource は、Provider が扱う外部 service を Kubernetes resource として表します。
Crossplane の公式ドキュメントでも、Managed Resource は Provider 内の external service を表し、Provider が外部 resource を作成する、と説明されています。
また、spec.forProvider は外部 resource の source of truth として扱われます。
そのため、Crossplane に管理させるということは、Kubernetes 側の desired state を中心に運用する、という意味になります。
Platform API を作りたい場合は、この性質が効いてきます。
利用者には TeamStorage や AppBucket のような API を見せ、裏側では Composition が Managed Resource、ProviderConfig、policy、outputs を組み立てます。
判断は四つの観点で見る
Crossplane を導入するかどうかは、次の四つの観点で見ると整理しやすいです。
Reconcile
継続的な状態合わせが必要か
Boundary
認証、namespace、IAM の責任境界を分けたいか
Abstraction
Provider API ではなく、利用者向け Platform API を見せたいか
Fit
Kubernetes / GitOps / Provider 対応範囲と運用が合っているか
この四つがそろうほど、Crossplane は選びやすくなります。
逆に、どれも当てはまらないなら、Terraform や既存運用を続ける方が自然です。
継続的に状態を見たい
チーム別に責任境界を分けたい
利用者向け API を作りたい
Kubernetes / GitOps 運用がある
-> Crossplane を検討しやすい
単発作成だけでよい
Kubernetes を運用したくない
既存 Terraform が安定している
Provider 対応範囲が足りない
-> Terraform / 既存運用を優先しやすい
導入判断は、技術の好みではなく、運用モデルとの相性で見るのが安全です。
namespace 分離は責任境界と合わせて考える
Crossplane をチーム利用に広げる場合、namespace の切り方が重要になります。
たとえば、team-a と team-b がそれぞれ OCI resource を使う場合、次のように分けられます。
| namespace | 置くもの | 責任境界 |
|---|---|---|
team-a |
Secret、namespaced ProviderConfig、XR / Claim、namespaced Managed Resource |
team-a の認証と要求 |
team-b |
Secret、namespaced ProviderConfig、XR / Claim、namespaced Managed Resource |
team-b の認証と要求 |
platform |
XRD、Composition、Function、共通 policy | platform team の標準 API |
crossplane-system |
Crossplane core、Provider runtime | control plane の実行基盤 |
| OCI IAM | compartment policy、dynamic group など | OCI 側の最小権限 |
ここで大事なのは、Kubernetes namespace と OCI IAM を別々に見ないことです。
OCI Provider の quickstart では、modern namespaced resource は default で ClusterProviderConfig を使い、必要に応じて namespace ごとの ProviderConfig を作る形が説明されています。
つまり、共通 credentials を使うのか、team ごとの credentials に分けるのかを先に決める必要があります。
Kubernetes 側で namespace を分けても、OCI 側の IAM が広すぎると責任境界は弱くなります。
逆に、OCI IAM を細かく分けても、Kubernetes 側で Secret や ProviderConfig を誰でも触れる状態なら、同じく境界は弱くなります。
Kubernetes RBAC と OCI IAM は、同じ責任境界にそろえて考える必要があります。
Secret、ProviderConfig、XR の権限を分ける
責任境界で特に重要なのは、次の三つです。
Secret
OCI credentials を保持する
ProviderConfig
どの credentials で OCI API を呼ぶかを決める
XR / Claim
利用者が要求する Platform API object
利用者が XR や Claim を作れることと、Secret を読めることは別です。
利用者が TeamStorage を作れるからといって、OCI API key を読める必要はありません。
また、ProviderConfig を変更できる人は限定した方が安全です。
ProviderConfig の参照先を変えると、どの資格情報で OCI API を呼ぶかが変わります。
RBAC を考えるときは、次のように分けて見ると分かりやすいです。
利用者
XR / Claim を作成できる
Secret は読めない
ProviderConfig は変更できない
Platform team
XRD / Composition / policy を管理する
ProviderConfig の利用ルールを決める
Operator / Admin
Secret / ProviderConfig / Provider runtime を保護する
この分離ができていないと、Platform API を作っても、実際の責任境界は曖昧になります。
Provider は controller でもある
Lifecycle を考えるとき、Provider を単なる package として見ないことが重要です。
Provider は CRD を追加するだけでなく、Managed Resource を observe / create / update / delete する controller でもあります。
そのため、Provider を先に消すと、残っている Managed Resource の状態合わせや削除が止まる可能性があります。
OCI Provider の quickstart でも、Managed Resource を削除する前に Provider を削除しないよう注意されています。
削除順序の基本は、次の通りです。
1. Managed Resource を棚卸しする
2. conditions と finalizer を確認する
3. 外部 resource を残すか消すかを決める
4. Managed Resource を削除する
5. 外部 OCI resource が残っていないか確認する
6. service provider を削除する
7. ProviderConfig / Secret を整理する
8. family provider を最後に削除する
ここで大事なのは、削除を「kubectl delete すれば終わり」と見ないことです。
Crossplane の Managed Resource には finalizer が付きます。
外部 resource の削除が完了するまで、Kubernetes object が残ることがあります。
kubectl describe で conditions、events、finalizer を確認し、OCI Console や OCI CLI で外部側も確認します。
lifecycle は作成前に決める
削除や ownership は、resource を作った後に考えると遅いことがあります。
作成前に、次の問いを決めておくと運用しやすくなります。
誰が作成を承認するか
誰が利用するか
誰が変更できるか
誰が削除を承認するか
削除後に誰が OCI 側を確認するか
問題が起きたとき、ProviderConfig / Secret / IAM のどこを見るか
Crossplane は継続的に状態を合わせる仕組みです。
そのため、作成時点の YAML だけでなく、変更、削除、障害対応まで含めて owner を決める必要があります。
特に、managementPolicies に Delete を含めるかどうか、deletionPolicy をどうするか、Observe-only から完全管理へ移るかどうかは、運用責任とセットで考えます。
最後に見る全体像
ここまでを一枚の絵として見ると、Crossplane による OCI Platform API は次のように整理できます。
利用者
TeamStorage / AppBucket などの Platform API を作る
Platform API
XRD / XR / Claim として Kubernetes API に見える
Composition
標準設定、命名、policy、outputs を Managed Resource へ変換する
Managed Resource
OCI Bucket、IAM policy、network などを宣言する
ProviderConfig
認証と責任境界を決める
OCI Provider
OCI API と reconcile する
OCI
実際の cloud resource を保持する
この全体像が必要なら、Crossplane は強い候補になります。
逆に、単に一回だけ OCI resource を作るためなら、ここまでの control plane を持つ必要があるかを考えた方がよいです。
Q&A で確認したいこと
最後に、Q&A で議論しやすい問いを整理します。
自分たちの環境では、どの resource を継続的に reconcile したいか
どの resource は Terraform のままでよいか
利用者に見せたい API は何か
Secret と ProviderConfig の owner は誰か
OCI IAM の境界は namespace と合っているか
Observe-only から始める resource はあるか
Delete まで Crossplane に任せてよい resource はどれか
Crossplane は、すべての infrastructure 管理を置き換えるためのものではありません。
Kubernetes API を入口にして、Platform API、GitOps、継続的な状態合わせを使いたい場面で効果が出ます。
そのため、導入判断では「何を作れるか」だけでなく、「誰が使い、誰が守り、誰が消すか」まで見ることが重要です。
まとめ
今回は、Crossplane と OCI Provider の導入判断として、Terraform との分担、責任境界、Lifecycle を整理しました。
ポイントは、次の三つです。
Terraform と Crossplane は優劣ではなく、運用時間軸が違う
Crossplane は Platform API と継続的な reconcile が必要な場面に向く
責任境界と削除順序を決めてから、管理範囲を広げる
Crossplane を導入するかどうかは、技術名ではなく運用モデルで判断します。
Kubernetes API を入口にして、チーム向け API、認証境界、GitOps、状態監視をまとめたいなら、Crossplane は有力な選択肢になります。
一方で、単発作成や既存 Terraform 運用で十分な範囲は、無理に置き換えなくてもよいです。
この判断軸を持っておくと、Crossplane を「新しい IaC tool」としてではなく、Cloud Native Control Plane を作るための部品として扱いやすくなります。