Adding Owner References for Existing Resources

Owner references are automatically injected only during creation of resources. Enabling owner reference injection will not update objects created while owner reference injection is disabled

This guide will demonstrate how to retroactively set owner references for existing resources.

A GET request to the owning resource will provide the necessary data to construct an ownerReference or an annotation.

$ kubectl get memcacheds.cache.example.com -o yaml

Example Response (Abbreviated):

apiVersion: cache.example.com/v1alpha1 kind: Memcached metadata:  name: example-memcached  namespace: default  uid: 2a94ff2b-84e0-40ce-8b5e-2b7e4d2bc0e2 

kubectl edit can be used to update the resources by hand. See below for example ownerReference and annotations.

For objects in the same namespace as the Owner (CR)

Dependent resources within the same namespace as the owning CR are tracked with the ownerReference field.

ownerReference structure:

  • apiVersion: {group}/{version}
  • kind: {kind}
  • name: {metadata.name}
  • uid: {metadata.uid}

Example ownerReference:

metadata:  ...(snip)  ownerReferences:  - apiVersion: cache.example.com/v1alpha1  kind: Memcached  name: example-memcached  uid: ad834522-d9a5-4841-beac-991ff3798c00 

For objects which are NOT in the same namespace as the Owner (CR)

An annotation is used instead of an ownerReference if the dependent resource is in a different namespace than the CR, or the dependent resource is a cluster level resource.

annotation structure:

  • operator-sdk/primary-resource: {metadata.namespace}/{metadata.name}
  • operator-sdk/primary-resource-type: {kind}.{group}

NOTE: The {group} can be found by splitting the apiVersion metadata of the CR, into group and version. As an example, apiVersion: cache.example.com/v1alpha1 in the config/samples directory gives us the group cache.example.com.

Example Annotation:

metadata:  ...(snip)  annotations:  operator-sdk/primary-resource: default/example-memcached  operator-sdk/primary-resource-type: Memcached.cache.example.com 

Migration using Ansible assets

If you have many resources to update, it may be easier to use the following Ansible assets, which should be considered an example rather than an officially supported workflow.

To use these assets, create a vars.yml as specified below and copy playbook.yml and each_resource.yml into the same directory. Execute the playbook with:

$ ansible-playbook -i localhost playbook.yml 

vars.yml

This file should be created by the user to configure the playbook, and needs to contain:

  • owning_resource
    • apiVersion
    • kind
    • name
    • namespace
  • resources_to_own (list): For each resource, specify:
    • name
    • namespace (if applicable)
    • apiVersion
    • kind
owning_resource:  apiVersion: cache.example.com/v1alpha1  kind: Memcached  name: example-memcached  namespace: default  resources_to_own:  - name: example-memcached-memcached  namespace: default  apiVersion: apps/v1  kind: Deployment  - name: example-memcached  apiVersion: v1  kind: Namespace 

playbook.yml

This file can be used as-is without user adjustments.

- hosts: localhost   tasks:  - name: Import user variables  include_vars: vars.yml  - name: Retrieve owning resource  kubernetes.core.k8s_info:  api_version: "{{ owning_resource.apiVersion }}"  kind: "{{ owning_resource.kind }}"  name: "{{ owning_resource.name }}"  namespace: "{{ owning_resource.namespace }}"  register: extra_owner_data   - name: Ensure resources are owned  include_tasks: each_resource.yml  loop: "{{ resources_to_own }}"  vars:  to_be_owned: '{{ q("kubernetes.core.k8s",  api_version=item.apiVersion,  kind=item.kind,  resource_name=item.name,  namespace=item.namespace  ).0 }}'  owner_reference:  apiVersion: "{{ owning_resource.apiVersion }}"  kind: "{{ owning_resource.kind }}"  name: "{{ owning_resource.name }}"  uid: "{{ extra_owner_data.resources[0].metadata.uid }}" 

each_resource.yml

This file can be used as-is without user adjustments.

- name: Patch resource with owner reference  when:  - to_be_owned.metadata.namespace is defined  - to_be_owned.metadata.namespace == owning_resource.namespace  - (to_be_owned.metadata.ownerReferences is not defined) or  (owner_reference not in to_be_owned.metadata.ownerReferences)  kubernetes.core.k8s:  state: present  resource_definition:  apiVersion: "{{ to_be_owned.apiVersion }}"  kind: "{{ to_be_owned.kind }}"  metadata:  name: "{{ to_be_owned.metadata.name }}"  namespace: "{{ to_be_owned.metadata.namespace }}"  ownerReferences: "{{ (to_be_owned.metadata.ownerReferences | default([])) + [owner_reference] }}"  - name: Patch resource with owner annotation  when: to_be_owned.metadata.namespace is not defined or to_be_owned.metadata.namespace != owning_resource.namespace  kubernetes.core.k8s:  state: present  resource_definition:  apiVersion: "{{ to_be_owned.apiVersion }}"  kind: "{{ to_be_owned.kind }}"  metadata:  name: "{{ to_be_owned.metadata.name }}"  namespace: "{{ to_be_owned.metadata.namespace | default(omit)}}"  annotations:  operator-sdk/primary-resource: "{{ owning_resource.namespace }}/{{ owning_resource.name }}"  operator-sdk/primary-resource-type: "{{ owning_resource.kind }}.{{ owning_resource.apiVersion.split('/')[0] }}" 
Last modified July 18, 2023: updated owner reference (#6409) (1403d713)