Introduction to the T Cloud Public Crossplane Provider
Crossplane extends Kubernetes into a control plane for managing cloud infrastructure and services through Kubernetes-style APIs. Running as an operator in virtually any Kubernetes environment (including CCE, OpenShift, and local clusters such as kind), it continuously reconciles declared resources with their desired state. Combined with GitOps workflows and tools such as Helm, Helmfile, and Argo CD, Crossplane provides a Kubernetes-native approach to provisioning and managing T Cloud Public services such as VPC, ECS, CCE, RDS, and OBS.
Crossplane Architecture
When managing cloud resources in Crossplane, there are four key components working together:
- Kubernetes API: Store resources, validate requests, enforce RBAC, notify controllers.
- Crossplane core: Compositions, packages, functions, dependency management, resource orchestration.
- Crossplane Providers: The cloud/service specific implementations(APIs + controllers).
- etcd: Persistent storage of desired and observed state.
When you apply any Crossplane manifest, the Provider reconciles the desired state in Kubernetes with the actual state in the cloud provider's API, creating, updating, or deleting the external resource as needed.

Terraform vs. Crossplane Operations
Crossplane and Terraform both support infrastructure provisioning and management, but they use different approaches to defining, applying, and maintaining infrastructure state:
| Aspect | Terraform-Based Operations | Crossplane-Based Operations |
|---|---|---|
| Primary Model | Infrastructure as Code using Terraform HCL configurations | Kubernetes-native infrastructure management using Custom Resource Definitions (CRDs) |
| Control Plane | Terraform CLI, Terraform Cloud, or automation pipelines | Kubernetes acts as the control plane |
| State Management | Requires separate state files (local or remote backend) | State stored in Kubernetes' etcd |
| Resource Lifecycle | CI/CD pipelines or manual runs | Continuously reconciled by Kubernetes controllers |
| Drift Detection | Periodic terraform plan required | Automatic and continuous reconciliation |
| Operational Model | Push-based execution | Pull-based reconciliation |
| Multi-Cloud Support | Mature and extensive | Limited, but catching up |
| GitOps Integration | Indirect, usually through CI/CD runners | Native fit with GitOps tools like Argo CD |
| Learning Curve | Lower for infrastructure teams | Lower for Kubernetes-centric platform teams, but can be more complex. |
It is crucial to highlight that Crossplane is not a direct replacement for Terraform. Engineering teams should evaluate their infrastructure and engineering needs and determine which tool is best suited to each system and use case. Rather than choosing one over the other, teams may benefit from using both tools where appropriate.
Crossplane Providers
Providers enable Crossplane to interact with external services and manage resources outside the Kubernetes cluster. They define external APIs as Kubernetes custom resource definitions (CRDs), handle authentication with the target service, and provide the controllers that reconcile and manage external resources.
Most Crossplane providers are generated from existing Terraform providers using Upjet code generation framework.
provider-opentelekomcloud
The provider is built using Upjet, which generates Crossplane providers based on the existing Terraform providers. This makes all services supported by the underlying Terraform provider available for configuration through Crossplane.
Some services currently have limitations regarding dynamic value assignment; these are documented in the corresponding issue tracker.
The provider includes hundreds of managed resource types, each represented by a Kubernetes CRD and managed by a corresponding controller. Activating all available managed resource types increases the number of CRDs and controllers in the cluster and adds load to the Kubernetes API server and etcd.
If only a subset of these managed resource types is required, consider using ManagedResourceActivationPolicies to activate only those that are needed. This reduces the number of active managed resource types and limits unnecessary control-plane overhead.
Figure 1: How kube-apiserver reacts when installing Crossplane and the Provider with all controllers enabled
Installing and Configuring the Provider
Installing Crossplane Core
- Create a namespace for Crossplane
kubectl create namespace crossplane-system
- Adding the Crossplane Helm Repository and update it
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
- Deploying Crossplane using Helm
helm install crossplane crossplane-stable/crossplane \
--set provider.defaultActivations={"*.opentelekomcloud.m.crossplane.io"} \
-n crossplane-system
- Verifying that Crossplane is running correct
kubectl -n crossplane-system wait --for=condition=Available deployment --all --timeout=5m
Deploying the T Cloud Public Provider
- Install the Provider Package
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-opentelekomcloud
spec:
package: xpkg.upbound.io/opentelekomcloud/provider-opentelekomcloud:v0.9.0
EOF
Provider is a CRD installed and managed by Crossplane as a package, hence you need Crossplane up and running before installing the Provider.
- Set up AUTH for
ClusterProviderConfig
export CROSSPLANE_CLOUD_CREDENTIALS='{"user_name":"USERNAME","access_key":"MY_AK", "secret_key":"MY_SK","auth_url":"https://iam.eu-de.otc.t-systems.com/v3","domain_name":"MYDOMAIN","tenant_name":"eu-de_PROJECT","swauth":"false","allow_reauth":"true","max_retries":"2","max_backoff_retries":"6","backoff_retry_timeout":"60","insecure":"false"}'
kubectl -n crossplane-system create secret generic provider-secret --from-literal=credentials="${CROSSPLANE_CLOUD_CREDENTIALS}" --dry-run=client -o yaml | kubectl apply -f -
- Create a
ClusterProviderConfig
cat <<EOF | kubectl apply -f -
apiVersion: opentelekomcloud.m.crossplane.io/v1beta1
kind: ClusterProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
name: provider-secret
namespace: crossplane-system
key: credentials
EOF
ClusterProviderConfig is installed and managed by the T Cloud Provider. It may take one or two minutes to become available while the provider initializes its controllers.
- Deploy a
Bucketas a test
cat <<EOF | kubectl apply -f -
apiVersion: obs.opentelekomcloud.m.crossplane.io/v1alpha1
kind: Bucket
metadata:
labels:
testing.upbound.io/example-name: b
name: b
spec:
forProvider:
versioning: true
region: eu-de
bucket: my-crossplane-test-1
tags:
Env: Test
foo: bar
managed: xplane
EOF
kubectl get bucket.obs.opentelekomcloud.m.crossplane.io -o yaml
[...]
spec:
forProvider:
bucket: my-crossplane-test-1
region: eu-de
storageClass: STANDARD
tags:
Env: Test
foo: bar
managed: xplane
versioning: true
initProvider: {}
managementPolicies:
- '*'
providerConfigRef:
kind: ClusterProviderConfig
name: default
status:
atProvider:
acl: private
bucket: my-crossplane-test-1
bucketDomainName: my-crossplane-test-1.obs.eu-de.otc.t-systems.com
bucketVersion: "3.0"
forceDestroy: false
id: my-crossplane-test-1
parallelFs: false
region: eu-de
storageClass: STANDARD
tags:
Env: Test
foo: bar
managed: xplane
versioning: true
ManagedResources (MR)
A managedResource (MR) represents an external service in a Provider. When users create a new managed resource, the Provider reacts by creating an external resource inside the Provider’s environment.
Managed resource fields
Group, Kind and Version
Each managed resource type is exposed through a Kubernetes API identified by its API group, version, and kind. For example, the T Cloud Provider provides the Bucket managed resource for OBS in the obs.opentelekomcloud.m.crossplane.io API group.
apiVersion: obs.opentelekomcloud.m.crossplane.io/v1alpha1
kind: Bucket
spec.forProvider
The spec.forProvider field defines the desired configuration of the external cloud resource and maps to the parameters supported by the provider. For example, an OBS Bucket resource can specify parameters such as region, versioning, and other provider-specific settings in spec.forProvider.
Crossplane treats spec.forProvider as the source of truth for the desired state of the managed resource.
spec:
forProvider:
versioning: true
region: eu-de
bucket: my-crossplane-test-1
status.atProvider
The status.atProvider field contains the observed state of the external cloud resource. For example, after creating an OBS Bucket resource, the provider may populate fields such as storageClass, acl, forceDestroy, and other values observed from the external resource.
status:
atProvider:
acl: private
bucket: my-crossplane-test-1
bucketDomainName: my-crossplane-test-1.obs.eu-de.otc.t-systems.com
bucketVersion: "3.0"
forceDestroy: false
id: my-crossplane-test-1
parallelFs: false
region: eu-de
storageClass: STANDARD
tags:
Env: Test
foo: bar
managed: xplane
versioning: true
In summary, forProvider describes what you want to configure, while atProvider describes what Crossplane observes on the external resource.
Automatic reconciliation
Crossplane and its providers continuously reconcile managed resources against the desired state defined in Kubernetes. The provider observes the state of each ManagedResource through the cloud API and compares it with the desired configuration. If a resource is modified outside Crossplane, the provider detects the configuration drift and restores the desired state unless configured otherwise.
By default, the reconciliation interval is 10 minutes. The interval can be adjusted using a DeploymentRuntimeConfig. When reducing the interval, consider the API rate limits of the services managed by the provider.
Deletion protection
By default, the provider protects resources from accidental deletion or re-creation. External resources are deleted only when the Kubernetes resource is intentionally removed.
### example changing the AZ field for and RDS instance which would lead to re-creation:
Conditions:
Last Transition Time: 2026-06-26T11:00:54Z
Message: observe failed: cannot run plan: plan failed: Instance cannot be destroyed: Resource opentelekomcloud_rds_instance_v3.team-a-db-f4948320f209 has lifecycle.prevent_destroy set, but the plan calls for this resource to be destroyed. To avoid this error and continue with the plan, either disable lifecycle.prevent_destroy or reduce the scope of the plan using the -target flag.
Composite Resources (XR)
A composite resource, or XR, represents a set of Kubernetes resources as a single Kubernetes object. Crossplane creates composite resources when users access a custom self built APIs, defined in the CompositeResourceDefinition (XRD).
Composite Resource Definitions (XRDs) define the schema and API of a custom composite resource. Compositions define how an instance of that composite resource is translated into one or more Kubernetes resources.

Compositions can enable:
- Multi-cloud engineering: Enables composing infrastructure APIs that work consistently across multiple cloud providers.
- Standardized cloud resources: Allows platform teams to define approved infrastructure patterns, ensuring consistency, security, and compliance across the organization.
- Self-service infrastructure: Gives developers simple, application-focused APIs to provision infrastructure without needing deep expertise in cloud platforms.
- Infrastructure abstraction: Hides cloud-provider-specific complexity behind higher-level APIs that align with business and platform requirements.
- Reusable infrastructure patterns: Packages common architectures (such as databases, Kubernetes clusters, or application environments) into reusable building blocks that can be deployed repeatedly and consistently.
Examples
Standardized Database
Consider an organization with multiple development teams that require SQL databases for their applications. With Crossplane, the platform engineering team can define a standardized database API with built-in configuration, security requirements, and organizational policies. Development teams can then provision databases through this API without requiring detailed knowledge of the underlying cloud services, cloud APIs, or Crossplane configuration.
Requirements:
- Database engine: PostgreSQL
- Backups must be enabled.
- Only approved database flavors are permitted.
- Maximum database size: 500 GB
- Network access: internal only
- All resources must be deployed in the same namespace.
- Storage type:
CLOUDSSDonly
The Solution
The platform engineering team defines a custom API using Crossplane composite resources that incorporates the required configuration and constraints. Development teams can then provision a compliant database using a simple Kubernetes manifest:
apiVersion: database.example.org/v1alpha1
kind: DbInstance
metadata:
name: team-a-db
namespace: team-a
spec:
name: team-a-db
availabilityZone: eu-de-01
flavor: small
size: 100
team: team-a
After the manifest is applied, the provider provisions the RDS instance and its required supporting resources, including network and security group resources. The resulting RDS instance has the following specifications:
spec:
forProvider:
availabilityZone:
- eu-de-01
backupStrategy:
- keepDays: 1
startTime: 08:00-09:00
computeSecurityGroupRefs:
name: team-a-db-242c585b634b
namespace: test
computeSecurityGroupSelector:
matchControllerRef: true
db:
- passwordSecretRef:
key: example-rds-key
name: example-rds-secret
port: 8635
type: PostgreSQL
version: "15"
flavor: rds.pg.n1.large.2
name: team-a-db
securityGroupId: 1aead593-d096-4497-92a9-eb48428a9596
subnetId: d4846bc8-e747-4174-899f-886189f83847
subnetRef:
name: team-a-db-e5866498e7ab
namespace: test
subnetSelector:
matchControllerRef: true
tags:
managed-by: crossplane
volume:
- size: 100
type: CLOUDSSD
vpcId: f1835f47-4001-49bd-b1ac-0c3f0f5b15fd
vpcRef:
name: team-a-db-a21435927a98
namespace: test
vpcSelector:
matchControllerRef: true
As demonstrated in the example above, Crossplane and the T Cloud Provider can be used to standardize and abstract Kubernetes and cloud infrastructure. This enables development teams to provision the resources they need through a self-service API without requiring detailed knowledge of the underlying infrastructure.
Appendix
- Official Documentation for Crossplane concepts, installation, managed resources, and compositions.
- T Cloud Provider Quick-Start: Getting started with installing and configuring the provider.
- Provider Configuration: Crossplane documentation for configuring provider credentials and authentication.
- T Cloud Provider Documentation: Configuration, upgrades, resource imports, and other provider-specific topics.
- T Cloud Provider Resource Reference for the managed resource types provided by the T Cloud Provider.
- GitHub issues: Report problems, request support, or track known issues with the T Cloud Provider.