Aller au contenu

Importer des ressources existantes avec Crossplane

Import existing Resources

Import existing resources into your control plane for Crossplane to manage

If you have resources that are already provisioned in a Provider, you can import them as managed resources and let Crossplane manage them. A managed resource's [managementPolicies] field enables importing external resources into Crossplane.

Import resources in observe only mode

Start by importing external resources with an Observe [management policy]

Crossplane imports observe only resources but never changes or deletes the resources.

Warning

The managed resource managementPolicies option is a beta feature.

The Provider determines support for management policies. Refer to the Provider's documentation to see if the Provider supports management policies.

Apply the Observe management policy

  1. Create a new managed resource matching the apiVersion and kind of the resource to import and add managementPolicies: Observe to the spec For example, to import an AWS EC2 Instance, Create a new resource with the managementPolicies: Observe set.
  2. Add the crossplane.io/external-name annotation for the resource. This name must match the ID inside the Provider. For example, for an AWS EC2 Instance use the Instance ID, apply the crossplane.io/external-name annotation with the value i-037556a7512bd1f4b.
  3. Create a name to use for the Kubernetes object. For example, name the Kubernetes object imported-ec2-instance.
  4. If more than one resource inside the Provider shares the same name, identify the specific resource with a unique spec.forProvider field. For example, only import the GCP SQL database in the us-central1 region.
imported-ec2-instance.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Instance
metadata:
  name: imported-ec2-instance
  annotations:
    crossplane.io/external-name: i-037556a7512bd1f4b
spec:
  managementPolicies: ["Observe"]
  forProvider:
    region: eu-west-3
  providerConfigRef:
    name: default
    kind: ProviderConfig 

Warning

If u dont precise providerConfigRef it try to lookup for ClusterProviderConfig

Apply the managed resource

Apply the new managed resource. Crossplane syncs the status of the external resource in the cloud with the newly created managed resource.

kubectl apply -f imported-ec2.yaml
instance.ec2.aws.m.upbound.io/imported-ec2-instance created

View the discovered resource

Crossplane discovers the managed resource and populates the status.atProvider fields with the values from the external resource.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Instance
metadata:
  annotations:
    crossplane.io/external-name: i-037556a7512bd1f4b
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"ec2.aws.m.upbound.io/v1beta1","kind":"Instance","metadata":{"annotations":{"crossplane.io/external-name":"i-037556a7512bd1f4b"},"name":"imported-ec2-instance","namespace":"crossplane-system"},"spec":{"forProvider":{"region":"eu-west-3"},"managementPolicies":["Observe"],"providerConfigRef":{"kind":"ProviderConfig","name":"default"}}}
  creationTimestamp: "2025-11-25T04:34:45Z"
  finalizers:
  - finalizer.managedresource.crossplane.io
  generation: 2
  name: imported-ec2-instance
  namespace: crossplane-system
  resourceVersion: "62176"
  uid: e0aecc43-1878-41ea-a58f-e9f2557f2a3e
spec:
  forProvider:
    region: eu-west-3
  initProvider: {}
  managementPolicies:
  - Observe
  providerConfigRef:
    kind: ProviderConfig
    name: default
status:
  atProvider:
    ami: ami-00769f46ca3bb4381
    arn: arn:aws:ec2:eu-west-3:478084574796:instance/i-037556a7512bd1f4b
    associatePublicIpAddress: false
    availabilityZone: eu-west-3c
    capacityReservationSpecification:
      capacityReservationPreference: open
      capacityReservationTarget: {}
    cpuOptions:
      amdSevSnp: ""
      coreCount: 1
      threadsPerCore: 2
    creditSpecification:
      cpuCredits: unlimited
    disableApiStop: false
    disableApiTermination: false
    ebsOptimized: true
    enclaveOptions:
      enabled: false
    getPasswordData: false
    hibernation: false
    hostId: ""
    iamInstanceProfile: ""
    id: i-037556a7512bd1f4b
    instanceInitiatedShutdownBehavior: stop
    instanceLifecycle: ""
    instanceMarketOptions: {}
    instanceState: stopped
    instanceType: t3.micro
    ipv6AddressCount: 0
    keyName: ""
    launchTemplate: {}
    maintenanceOptions:
      autoRecovery: default
    metadataOptions:
      httpEndpoint: enabled
      httpProtocolIpv6: disabled
      httpPutResponseHopLimit: 2
      httpTokens: required
      instanceMetadataTags: disabled
    monitoring: false
    outpostArn: ""
    passwordData: ""
    placementGroup: ""
    placementGroupId: ""
    placementPartitionNumber: 0
    primaryNetworkInterface:
      deleteOnTermination: true
      networkInterfaceId: eni-05970f9b52533b159
    primaryNetworkInterfaceId: eni-05970f9b52533b159
    privateDns: ip-172-31-42-191.eu-west-3.compute.internal
    privateDnsNameOptions:
      enableResourceNameDnsARecord: true
      enableResourceNameDnsAaaaRecord: false
      hostnameType: ip-name
    privateIp: 172.31.42.191
    publicDns: ""
    publicIp: ""
    region: eu-west-3
    rootBlockDevice:
      deleteOnTermination: true
      deviceName: /dev/xvda
      encrypted: false
      iops: 3000
      kmsKeyId: ""
      throughput: 125
      volumeId: vol-03fdca6cb6fd07a3f
      volumeSize: 8
      volumeType: gp3
    securityGroups:
    - launch-wizard-1
    sourceDestCheck: true
    spotInstanceRequestId: ""
    subnetId: subnet-0df5c09839230c14c
    tags:
      Name: app1
    tagsAll:
      Name: app1
    tenancy: default
    vpcSecurityGroupIds:
    - sg-0d69b6ea8692119d8
  conditions:
  - lastTransitionTime: "2025-11-25T04:34:51Z"
    observedGeneration: 2
    reason: ReconcileSuccess
    status: "True"
    type: Synced
  - lastTransitionTime: "2025-11-25T04:34:51Z"
    reason: Available
    status: "True"
    type: Ready
  - lastTransitionTime: "2025-11-25T04:34:51Z"
    reason: Success
    status: "True"
    type: LastAsyncOperation

Control imported observe only resources

Crossplane can take active control of observe only imported resources by changing the managementPolicies after import. Change the managementPolicies field of the managed resource to ["*"]. Copy any required parameter values from status.atProvider and provide them in spec.forProvider.

Warning

Manually copy the important spec.atProvider values to spec.forProvider.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
metadata:
  name: my-imported-database
  annotations:
    crossplane.io/external-name: my-external-database
spec:
  managementPolicies: ["*"]
  forProvider:
    databaseVersion: POSTGRES_14
    region: us-central1
    settings:
    - diskSize: 100
      tier: db-custom-4-26624
status:
  atProvider:
    databaseVersion: POSTGRES_14
    region: us-central1
    # Removed for brevity
    settings:
    - diskSize: 100
      tier: db-custom-4-26624
      # Removed for brevity
  conditions:
    - lastTransitionTime: "2023-02-22T07:16:51Z"
      reason: Available
      status: "True"
      type: Ready
    - lastTransitionTime: "2023-02-22T11:16:45Z"
      reason: ReconcileSuccess
      status: "True"
      type: Synced

Crossplane now fully manages the imported resource. Crossplane applies any changes to the managed resource in the Provider's external resource.

We can by now specify new tag

Apply new tag on your manifest
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Instance
metadata:
  name: imported-ec2-instance
  annotations:
    crossplane.io/external-name: i-037556a7512bd1f4b
spec:
  managementPolicies: ["*"]
  forProvider:
    region: eu-west-3
    tags:
      company: mathod
      project: app1
      environment: production
  providerConfigRef:
    name: default
    kind: ProviderConfig 
New tag on instance
Name:         imported-ec2-instance
Namespace:    crossplane-system
Labels:       <none>
Annotations:  crossplane.io/external-name: i-037556a7512bd1f4b
API Version:  ec2.aws.m.upbound.io/v1beta1
Kind:         Instance
Metadata:
  Creation Timestamp:  2025-11-25T04:34:45Z
  Finalizers:
    finalizer.managedresource.crossplane.io
  Generation:        6
  Resource Version:  62949
  UID:               e0aecc43-1878-41ea-a58f-e9f2557f2a3e
Spec:
  For Provider:
    Ami:                ami-00769f46ca3bb4381
    Availability Zone:  eu-west-3c
    Capacity Reservation Specification:
      Capacity Reservation Preference:  open
    Credit Specification:
      Cpu Credits:  unlimited
    Ebs Optimized:  true
    Enclave Options:
    Instance Initiated Shutdown Behavior:  stop
    Instance Type:                         t3.micro
    Maintenance Options:
      Auto Recovery:  default
    Metadata Options:
      Http Endpoint:                enabled
      httpProtocolIpv6:             disabled
      Http Put Response Hop Limit:  2
      Http Tokens:                  required
      Instance Metadata Tags:       disabled
    Primary Network Interface:
      Network Interface Id:  eni-05970f9b52533b159
    Private Dns Name Options:
      Enable Resource Name Dns A Record:  true
      Hostname Type:                      ip-name
    Region:                               eu-west-3
    Tags:
      Company:                      mathod
      Crossplane - Kind:            instance.ec2.aws.m.upbound.io
      Crossplane - Name:            imported-ec2-instance
      Crossplane - Providerconfig:  default
      Environment:                  production
      Project:                      app1
    Tenancy:                        default
  Init Provider:
  Management Policies:
    *
  Provider Config Ref:
    Kind:  ProviderConfig
    Name:  default
Status:
  At Provider:
    Ami:                          ami-00769f46ca3bb4381
    Arn:                          arn:aws:ec2:eu-west-3:478084574796:instance/i-037556a7512bd1f4b
    Associate Public Ip Address:  false
    Availability Zone:            eu-west-3c
    Capacity Reservation Specification:
      Capacity Reservation Preference:  open
      Capacity Reservation Target:
    Cpu Options:
      Amd Sev Snp:       
      Core Count:        1
      Threads Per Core:  2
    Credit Specification:
      Cpu Credits:            unlimited
    Disable API Stop:         false
    Disable API Termination:  false
    Ebs Optimized:            true
    Enclave Options:
      Enabled:                             false
    Force Destroy:                         false
    Get Password Data:                     false
    Hibernation:                           false
    Host Id:                               
    Iam Instance Profile:                  
    Id:                                    i-037556a7512bd1f4b
    Instance Initiated Shutdown Behavior:  stop
    Instance Lifecycle:                    
    Instance Market Options:
    Instance State:    stopped
    Instance Type:     t3.micro
    ipv6AddressCount:  0
    Key Name:          
    Launch Template:
    Maintenance Options:
      Auto Recovery:  default
    Metadata Options:
      Http Endpoint:                enabled
      httpProtocolIpv6:             disabled
      Http Put Response Hop Limit:  2
      Http Tokens:                  required
      Instance Metadata Tags:       disabled
    Monitoring:                     false
    Outpost Arn:                    
    Password Data:                  
    Placement Group:                
    Placement Group Id:             
    Placement Partition Number:     0
    Primary Network Interface:
      Delete On Termination:       true
      Network Interface Id:        eni-05970f9b52533b159
    Primary Network Interface Id:  eni-05970f9b52533b159
    Private Dns:                   ip-172-31-42-191.eu-west-3.compute.internal
    Private Dns Name Options:
      Enable Resource Name Dns A Record:     true
      Enable Resource Name Dns Aaaa Record:  false
      Hostname Type:                         ip-name
    Private Ip:                              172.31.42.191
    Public Dns:                              
    Public Ip:                               
    Region:                                  eu-west-3
    Root Block Device:
      Delete On Termination:  true
      Device Name:            /dev/xvda
      Encrypted:              false
      Iops:                   3000
      Kms Key Id:             
      Throughput:             125
      Volume Id:              vol-03fdca6cb6fd07a3f
      Volume Size:            8
      Volume Type:            gp3
    Security Groups:
      launch-wizard-1
    Source Dest Check:         true
    Spot Instance Request Id:  
    Subnet Id:                 subnet-0df5c09839230c14c
    Tags:
      Name:                         app1
      Company:                      mathod
      Crossplane - Kind:            instance.ec2.aws.m.upbound.io
      Crossplane - Name:            imported-ec2-instance
      Crossplane - Providerconfig:  default
      Environment:                  production
      Project:                      app1
    Tags All:
      Name:                         app1
      Company:                      mathod
      Crossplane - Kind:            instance.ec2.aws.m.upbound.io
      Crossplane - Name:            imported-ec2-instance
      Crossplane - Providerconfig:  default
      Environment:                  production
      Project:                      app1
    Tenancy:                        default
    User Data Replace On Change:    false
    Vpc Security Group Ids:
      sg-0d69b6ea8692119d8
  Conditions:
    Last Transition Time:  2025-11-25T04:40:18Z
    Observed Generation:   6
    Reason:                ReconcileSuccess
    Status:                True
    Type:                  Synced
    Last Transition Time:  2025-11-25T04:34:51Z
    Reason:                Available
    Status:                True
    Type:                  Ready
    Last Transition Time:  2025-11-25T04:34:51Z
    Reason:                Success
    Status:                True
    Type:                  LastAsyncOperation
Events:
  Type    Reason                   Age                From                                                 Message
  ----    ------                   ----               ----                                                 -------
  Normal  UpdatedExternalResource  6s (x2 over 114s)  managed/ec2.aws.m.upbound.io/v1beta1, kind=instance  Successfully requested update of external resource

kubectl get instance
NAME                    SYNCED   READY   EXTERNAL-NAME         AGE
imported-ec2-instance   True     True    i-037556a7512bd1f4b   7m55s

kubectl get managed
NAME                                                  SYNCED   READY   EXTERNAL-NAME         AGE
instance.ec2.aws.m.upbound.io/imported-ec2-instance   True     True    i-037556a7512bd1f4b   8m25s

kubectl get instance.ec2.aws.m.upbound.io/imported-ec2-instance
NAME                    SYNCED   READY   EXTERNAL-NAME         AGE
imported-ec2-instance   True     True    i-037556a7512bd1f4b   8m31s

kubectl delete instance.ec2.aws.m.upbound.io/imported-ec2-instance
instance.ec2.aws.m.upbound.io "imported-ec2-instance" deleted from crossplane-system namespace
The instances as been removed from AWS since we deleted the resources !


url: https://docs.crossplane.io/latest/guides/import-existing-resources/
url: https://docs.crossplane.io/latest/managed-resources/managed-resources/#managementpolicies