How to Change the Scope of a Kubernetes API Resource with Operator-SDK

Kubernetes API Resource Operator-SDK CustomResourceDefinition Namespaced Cluster Scope

2 min read | by Jordi Prats

When creating a new API resource using the operator-sdk we can use the namespaced flag to make it Namespaced:

$ operator-sdk create api --group group \
                          --version v1 \
                          --kind Example \
                          --resource \
                          --controller

Or in the cluster scope:

$ operator-sdk create api --group group \
                          --version v1 \
                          --kind Example \
                          --resource \
                          --controller \
                          --namespaced=false

Maybe because we forgot to add the flag or because we have changed our mind, we don't need delete the object to change the scope of it, let's see how.

If we check the CRD definition we can see where it is defined whether an object is namespaced or not:

---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  annotations:
    controller-gen.kubebuilder.io/version: v0.10.0
  creationTimestamp: null
  name: example.group.pet2cattle.com
spec:
  group: group.pet2cattle.com
  names:
    kind: Example
    listKind: ExampleList
    plural: examples
    singular: example
  scope: Namespaced
(...)

To change it we'll have to look at is .go definition. We'll be able to find it looking for a file following this pattern: api/<version>/<kind>_types.go thus for the example above it would be api/v1/example_types.go:

To check the scope we'll have to add the following annotation just above where the type is defined:

//+kubebuilder:resource:scope=Cluster

It's going to look like this:

(...)

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:resource:scope=Cluster

// Example is the Schema for the Examples API
type Example struct {
  metav1.TypeMeta   `json:",inline"`
  metav1.ObjectMeta `json:"metadata,omitempty"`

  Spec   ExampleSpec   `json:"spec,omitempty"`
  Status ExampleStatus `json:"status,omitempty"`
}

(...)

To update the CRD manifest we'll have to run:

make manifests

This command is going to regenerate the CustomResourceDefinition manifests, updating the spec.scope as follows:

---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  annotations:
    controller-gen.kubebuilder.io/version: v0.10.0
  creationTimestamp: null
  name: example.group.pet2cattle.com
spec:
  group: group.pet2cattle.com
  names:
    kind: Example
    listKind: ExampleList
    plural: examples
    singular: example
  scope: Cluster
(...)

Posted on 05/04/2023