はじめに
最近、Infrastructure as Code を Terraform だけではなく、Kubernetes の API として扱う考え方に興味を持ちました。
その中で出てきたのが Crossplane です。
Crossplane の GitHub README では、Crossplane は「コードを書かずに cloud native control plane を構築するための framework」と説明されています。つまり、単にクラウドリソースを作るツールではなく、自分たちのチーム向けに宣言的な API を作るための仕組みです。(GitHub)
この記事では、Crossplane の基本をローカル Kubernetes で学び、その後 Oracle Cloud Infrastructure 用の Crossplane Provider、つまり OCI Provider を使って、最小構成から OCI リソースを管理する学習計画を整理します。
この記事のゴール
この記事の目的は、いきなり複雑な OCI 環境を作ることではありません。
まずは、次のことを自分の言葉で説明できるようになることを目指します。
Crossplane は何をするものか
Provider とは何か
Managed Resource とは何か
ProviderConfig は何を持つのか
XRD / XR / Composition はどう関係するのか
OCI Provider で OCI リソースを Kubernetes から管理する流れ
Terraform と Crossplane の考え方の違い
全体像
今回の学習は、次の2段階で進めます。
Phase 1:
ローカル Kubernetes で Crossplane の基本を学ぶ
Phase 2:
OCI Provider を使って OCI Object Storage Bucket を作る
構成としては以下のようになります。
Local PC
|
+-- kind / minikube / Rancher Desktop
|
+-- Crossplane
|
+-- Provider
+-- Managed Resource
+-- XRD
+-- Composition
+-- XR
OCI
|
+-- Object Storage Bucket
+-- Compartment
+-- VCN
+-- Subnet
最初から VCN、OKE、Database まで作ろうとすると、IAM、ネットワーク、課金、削除順序などに意識を取られます。
そのため、最初の OCI 実験は Object Storage Bucket に絞るのがよいと思います。
Crossplane の基本理解
Crossplane は Kubernetes 上の Control Plane
Crossplane は既存の Kubernetes クラスタにインストールして使います。公式ドキュメントでも、Crossplane をインストールすると Provider、Function、Configuration などの Crossplane リソースをインストールできるようになると説明されています。ローカルに Kubernetes クラスタがない場合は kind を使うこともできます。(Crossplane Documentation)
インストールは Helm で行います。
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane \
--namespace crossplane-system \
--create-namespace \
crossplane-stable/crossplane
kubectl get pods -n crossplane-system
確認ポイントは以下です。
kubectl get pods -n crossplane-system
kubectl get crds | grep crossplane
kubectl api-resources | grep crossplane
ここで理解したいことは、Crossplane が「別の CLI ツール」ではなく、Kubernetes 上で動く control plane であるという点です。
Provider は外部サービスを Kubernetes API に変換する
Crossplane でクラウドリソースを作るには Provider を入れます。
Crossplane 公式ドキュメントでは、Provider は外部サービス上のインフラを作成するためのもので、外部 API への認証、API 呼び出し、Kubernetes controller としての reconcile 処理を担当すると説明されています。Provider をインストールすると、その Provider が扱える外部リソースが Kubernetes API として追加されます。(Crossplane Documentation)
例えば OCI Provider を入れると、OCI の Object Storage、Networking、Compute などを Kubernetes manifest から扱えるようになります。
Managed Resource は実際のクラウドリソースに対応する
Crossplane では、クラウド上の実リソースに対応する Kubernetes オブジェクトを Managed Resource と呼びます。
公式ドキュメントでは、Managed Resource は Provider 内の外部サービスを表し、ユーザーが Managed Resource を作成すると、Provider が外部環境に実際のリソースを作成すると説明されています。(Crossplane Documentation)
例えば OCI Object Storage Bucket の場合、概念的には以下のような関係になります。
Kubernetes object:
Bucket managed resource
OCI external resource:
Object Storage Bucket
重要なのは、spec.forProvider が外部リソースに渡すパラメータの中心になることです。Crossplane では forProvider が外部リソースの source of truth として扱われ、外部側で変更した値を Crossplane が戻す場合があります。(Crossplane Documentation)
OCI Provider の位置づけ
Oracle の crossplane-provider-oci は、OCI 向けの Crossplane Provider です。
GitHub README では、この Provider は Upjet によって生成され、OCI Terraform Resources をベースに XRM 準拠の managed resources を作成すると説明されています。(GitHub)
つまり、OCI Provider を使うと、OCI のリソースを Kubernetes manifest として管理できます。
Kubernetes YAML
|
v
Crossplane OCI Provider
|
v
OCI API
|
v
OCI Resource
OCI Provider は provider-family 方式を採用しています。Quick Start では、まず family provider をインストールし、その後 provider-oci-objectstorage のような service provider を入れる流れになっています。family provider は同じ family 内の ProviderConfig を管理します。(GitHub)
なぜ最初は Object Storage Bucket から始めるのか
OCI Provider は多くの OCI サービスに対応しています。
GitHub Packages でも、provider-family-oci、provider-oci-objectstorage、provider-oci-containerengine、provider-oci-compute、provider-oci-networking など複数の provider package が公開されています。(GitHub)
ただし、学習の最初から Compute、VCN、OKE、Database を作ると、理解すべきことが増えすぎます。
最初は Object Storage Bucket がよいです。
理由は以下です。
構成が小さい
作成と削除を確認しやすい
ネットワーク設計が不要
Crossplane の reconcile を理解しやすい
ProviderConfig の動作確認に向いている
学習計画
Week 1. ローカル Kubernetes に Crossplane を入れる
最初の週は、OCI を触らずに Crossplane だけを学びます。
やることは以下です。
kind / minikube / Rancher Desktop のどれかを用意する
Helm で Crossplane をインストールする
Crossplane の Pod を確認する
CRD が追加されたことを確認する
Provider / Function / Configuration の違いを読む
確認コマンドです。
kubectl get pods -n crossplane-system
kubectl get crds | grep crossplane
kubectl get providers
kubectl get functions
この週のゴールは、以下を理解することです。
Crossplane は Kubernetes 上で動く
Crossplane 自体はクラウドリソースを直接知らない
Provider を追加することで外部サービスを扱えるようになる
Week 2. Provider と Managed Resource を理解する
2週目は、Provider と Managed Resource の関係を理解します。
ここでは、OCI Provider に進む前に、まず次の考え方を整理します。
Provider:
外部サービスと接続する controller
Managed Resource:
外部リソースを表す Kubernetes object
ProviderConfig:
認証情報や接続設定
spec.forProvider:
外部リソースに渡す desired state
status.atProvider:
外部リソースから観測した状態
Crossplane Provider は、Provider pod を作成し、Managed Resource の desired state を監視し、不足している外部リソースを作成します。(Crossplane Documentation)
この週のゴールは、次の流れを理解することです。
YAML を apply する
|
v
Managed Resource が作られる
|
v
Provider が reconcile する
|
v
外部リソースが作られる
|
v
status に結果が反映される
Week 3. Composition を学ぶ
Crossplane の本当に面白いところは、単にクラウドリソースを YAML 化することではありません。
自分たち用の API を作れることです。
Crossplane の Composition は、複数の Kubernetes resources を1つの Composite Resource として作成するためのテンプレートです。公式ドキュメントでは、XRD は XR の schema を定義し、Composition は XR が他のリソースをどのように作るかを設定すると説明されています。(Crossplane Documentation)
関係は以下です。
XRD
XR の schema を定義する
XR
利用者が作る custom API object
Composition
XR から実際に作る Managed Resource を定義する
例えば、利用者には以下のような API だけを見せます。
apiVersion: platform.example.org/v1alpha1
kind: XObjectStorageBucket
metadata:
name: demo-bucket
spec:
bucketName: demo-crossplane-bucket
裏側では Composition が OCI Object Storage Bucket の Managed Resource を生成します。
XObjectStorageBucket
|
v
Composition
|
v
objectstorage.oci.m.upbound.io/Bucket
この週のゴールは、以下を理解することです。
Crossplane は単なる Terraform 代替ではない
Platform API を作るための仕組みである
Week 4. crossplane render で Composition を確認する
Composition を書いたら、すぐにクラスタへ apply する前に crossplane render で確認します。
crossplane render は、Composite Resource に Composition Function を適用した結果をローカルで preview するコマンドです。公式ドキュメントでは、Docker Engine を使って Composition Function を pull / run し、元の XR と生成された managed resources を出力すると説明されています。(Crossplane Documentation)
crossplane render xr.yaml composition.yaml function.yaml
このステップで見るべきことは以下です。
XR の値が Managed Resource に正しく渡っているか
providerConfigRef が意図したものになっているか
namespace が正しいか
生成される apiVersion / kind が正しいか
この週のゴールは、Composition を「apply してから確認する」のではなく、render して設計を確認する習慣をつけることです。
Week 5. OCI Provider を入れる
ここから OCI Provider を使います。
まず provider-family と Object Storage provider をインストールします。
OCI Provider の Quick Start では、sub-provider より先に family provider をインストールすることが推奨されています。sub-provider を先に入れると、Crossplane package-manager が依存解決のために意図しない latest family provider image を取得する可能性があるためです。(GitHub)
以下はイメージです。実際に試すときは、利用時点の最新 release を確認してください。OCI Provider の GitHub Releases では、v1.0.1 が 2026年4月10日に latest として公開されており、v1.0.0 では Crossplane v2 / Upjet v2 対応、namespaced resource、management policies などが説明されています。(GitHub)
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: oracle-provider-family-oci
spec:
package: ghcr.io/oracle/provider-family-oci:v1.0.1
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-oci-objectstorage
spec:
package: ghcr.io/oracle/provider-oci-objectstorage:v1.0.1
確認します。
kubectl get providers
kubectl get providerrevisions
Provider が INSTALLED=True、HEALTHY=True になるまで待ちます。
Week 6. OCI 認証を設定する
OCI Provider を使うには、OCI へ接続するための認証情報が必要です。
Quick Start では、主に次の認証方式が紹介されています。
API Key Authentication
Instance Principal Authentication
Workload Identity Authentication
API Key は従来の方法、Instance Principal は OCI Compute 上で動かす場合、Workload Identity は OKE 環境で使う方法です。(GitHub)
ローカル学習では、まず API Key Authentication が分かりやすいです。
kubectl create secret generic oci-creds \
--namespace=crossplane-system \
--from-literal=credentials='{
"tenancy_ocid": "REPLACE_WITH_YOUR_TENANCY_OCID",
"user_ocid": "REPLACE_WITH_YOUR_USER_OCID",
"private_key": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n",
"fingerprint": "REPLACE_WITH_YOUR_FINGERPRINT",
"region": "REPLACE_WITH_YOUR_REGION",
"auth": "ApiKey"
}'
次に ProviderConfig を作成します。
apiVersion: oci.m.upbound.io/v1beta1
kind: ClusterProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
name: oci-creds
namespace: crossplane-system
key: credentials
OCI Provider の Quick Start では、modern namespaced resources は ClusterProviderConfig.oci.m.upbound.io をデフォルトとして使い、必要に応じて namespace ごとの ProviderConfig.oci.m.upbound.io で認証情報を分離できると説明されています。(GitHub)
Week 7. OCI Object Storage Bucket を作る
次に、OCI Object Storage Bucket を作ります。
OCI Provider の examples には、namespaced resource と cluster-scoped resource の両方の Bucket 例があります。namespaced 版では apiVersion: objectstorage.oci.m.upbound.io/v1alpha1、cluster-scoped 版では apiVersion: objectstorage.oci.upbound.io/v1alpha1 が使われています。(GitHub)
まずは namespaced resource を使うのが、Crossplane v2 以降の学習として分かりやすいです。
apiVersion: objectstorage.oci.m.upbound.io/v1alpha1
kind: Bucket
metadata:
name: bucket1
namespace: crossplane-demo
spec:
forProvider:
compartmentId: ocid1.compartment.oc1..xxxxx
name: bucket1
namespace: REPLACE_WITH_OBJECTSTORAGE_NAMESPACE
providerConfigRef:
name: default
kind: ClusterProviderConfig
適用します。
kubectl create namespace crossplane-demo
kubectl apply -f bucket.yaml
確認します。
kubectl get bucket.objectstorage.oci.m.upbound.io -A
kubectl describe bucket.objectstorage.oci.m.upbound.io bucket1 -n crossplane-demo
kubectl get managed --all-namespaces
Quick Start では、Bucket 作成後に READY と SYNCED が True になることを確認し、失敗時は kubectl describe で原因を見る流れが紹介されています。(GitHub)
Week 8. Observe-only と削除を試す
最後に、managementPolicies を試します。
Crossplane の managed resources では、managementPolicies によって Crossplane が外部リソースに対して実行できる操作を制御できます。公式ドキュメントでは、Create、Delete、Observe、Update、LateInitialize などの policy が説明されています。(Crossplane Documentation)
OCI Provider の Quick Start にも、既存の OCI リソースを observe-only で取り込む例があり、managementPolicies: ["Observe"] と crossplane.io/external-name annotation を使うパターンが紹介されています。(GitHub)
apiVersion: kms.oci.m.upbound.io/v1alpha1
kind: Vault
metadata:
name: vault1
namespace: crossplane-demo
annotations:
crossplane.io/external-name: REPLACE_WITH_EXTERNAL_RESOURCE_OCID
spec:
managementPolicies:
- Observe
forProvider:
compartmentId: REPLACE_WITH_COMPARTMENT_OCID
displayName: vault1
providerConfigRef:
name: default
kind: ProviderConfig
この考え方は重要です。
Create / Update / Delete まで Crossplane に任せるのか
Observe だけにして既存リソースを見るのか
をリソースごとに制御できるからです。
最後に、作成した Bucket を削除します。
kubectl delete -f bucket.yaml
kubectl get bucket.objectstorage.oci.m.upbound.io -A
OCI Provider の Quick Start では、Provider を削除する前に managed resources を削除すること、さらに family provider を sub-provider より先に削除しないことが警告されています。順序を間違えると dangling resource や provider-family の owner reference 問題につながる可能性があります。(GitHub)
Terraform との違い
Crossplane と Terraform は似て見えますが、考え方がかなり違います。
| 観点 | Terraform | Crossplane |
|---|---|---|
| 実行方式 |
plan / apply
|
controller による継続 reconcile |
| 状態管理 | state file | Kubernetes API / status |
| 利用者体験 | CLI 中心 | Kubernetes API / GitOps 中心 |
| 抽象化 | module | XRD / XR / Composition |
| 外部変更への対応 | 次回 plan で検出 | controller が継続的に観測 |
| Platform API | 別途設計が必要 | 中核機能として作れる |
私の理解では、Terraform はインフラ管理者向けの IaC として非常に強く、Crossplane は Kubernetes を中心に Platform API を作るときに強いです。
学習時の注意点
OCI Provider を使うと、実際に OCI リソースが作成されます。
そのため、学習時は以下をおすすめします。
学習専用 compartment を使う
名前に demo / learning を入れる
tag を付ける
Object Storage Bucket から始める
VCN / Compute / OKE / Database は後回しにする
作った manifest と削除手順を同じ場所に残す
Provider より先に managed resources を削除する
特に OKE、Database、Load Balancer などは、コストや削除順序の確認が必要なので、最初のハンズオンには向いていません。
最終的な学習ロードマップ
全体をまとめると、次の順番がよいと思います。
1. kind / minikube / Rancher Desktop に Crossplane を入れる
2. Provider と Managed Resource の関係を理解する
3. ProviderConfig と認証情報の扱いを理解する
4. XRD / XR / Composition を学ぶ
5. crossplane render で Composition の出力を確認する
6. OCI Provider family を入れる
7. provider-oci-objectstorage で Bucket を作る
8. READY / SYNCED / status.atProvider を確認する
9. managementPolicies で Observe-only を試す
10. 最後に自分用の Platform API を作る
最初から大きな OCI 構成を作るよりも、まずは Object Storage Bucket 1個 を Kubernetes manifest から作成し、Crossplane の reconcile を観察するのが理解しやすいです。
まとめ
Crossplane は、単なるクラウドリソース作成ツールではありません。
Kubernetes の上に、自分たち用の cloud native control plane を作るための framework です。OCI Provider を組み合わせることで、OCI のリソースも Kubernetes API として扱えるようになります。
学習の順番としては、以下が一番分かりやすいと思います。
ローカル Kubernetes
↓
Crossplane
↓
Provider / Managed Resource
↓
Composition
↓
OCI Provider
↓
Object Storage Bucket
↓
自分用 Platform API
最初のゴールは、OCI の大きな環境を構築することではなく、YAML を apply すると Provider が OCI API を呼び出し、外部リソースの状態を継続的に reconcile するという流れを理解することです。