ConfigBundleOperator can be deployed as a Kubernetes workload together with the RBAC resources and custom resource definition required for it to operate.
The deployment consists of several Kubernetes resources that work together:
flowchart LR
CRD["CustomResourceDefinition<br/>ConfigBundle"]
CR["ClusterRole<br/>cluster-wide permissions"]
CRB["ClusterRoleBinding"]
SA["ServiceAccount<br/>configbundleopeartor-service-account"]
R["Role<br/>namespace-scoped permissions"]
RB["RoleBinding"]
D["Deployment<br/>configbundleoperator"]
P["Pod"]
C["Operator Container"]
CRD -->|"defines"| CB["ConfigBundle"]
CRB -->|"binds"| CR
CRB -->|"to"| SA
RB -->|"binds"| R
RB -->|"to"| SA
D -->|"creates"| P
P -->|"uses"| SA
P -->|"runs"| C
C -->|"watches / reconciles"| CB
The resources can be grouped into four logical parts:
| Component | Purpose |
|---|---|
CustomResourceDefinition |
Defines the ConfigBundle API |
ServiceAccount |
Provides an identity for the operator |
| RBAC resources | Define and grant the operator's permissions |
Deployment |
Runs the operator |
Custom Resource Definition¶
The ConfigBundle CRD introduces a Kubernetes-native API for the operator.
flowchart LR
A["CustomResourceDefinition"]
B["ConfigBundle API"]
C["ConfigBundle Resources"]
A -->|"defines"| B
B -->|"creates"| C
Once the CRD is installed, Kubernetes recognizes resources using the
ConfigBundle kind and the operator can watch them through the Kubernetes API.
The operator therefore does not need a separate configuration mechanism. Configuration is represented directly as a Kubernetes resource.
ServiceAccount¶
The operator runs under a dedicated ServiceAccount:
The ServiceAccount provides the identity used by the operator when communicating with the Kubernetes API.
flowchart TB
A["ConfigBundleOperator Pod"]
B["ServiceAccount"]
C["Kubernetes API Server"]
A -->|"uses identity"| B
B -->|"authenticated requests"| C
The ServiceAccount itself does not define what the operator is allowed to do.
Permissions are provided separately through Kubernetes RBAC.
RBAC¶
This gives the operator a combination of cluster-wide and namespace-scoped permissions.
flowchart TB
SA["ServiceAccount<br/>configbundleopeartor-service-account"]
CR["ClusterRole<br/>cluster-wide permissions"]
CRB["ClusterRoleBinding"]
R["Role<br/>namespace: default"]
RB["RoleBinding"]
CRB -->|"binds"| CR
CRB -->|"grants to"| SA
RB -->|"binds"| R
RB -->|"grants to"| SA
The important distinction is that a Role is namespaced, while a
ClusterRole can provide permissions for cluster-scoped resources and can
also be bound for access across namespaces.
ClusterRole¶
The ClusterRole defines permissions that are required beyond a single namespace.
In this deployment, the cluster-level permissions include access required by the operator and its framework to interact with cluster-scoped Kubernetes resources.
Conceptually:
flowchart LR
A["ClusterRole"]
B["Cluster-wide Kubernetes Resources"]
C["ServiceAccount"]
A -->|"defines permissions"| B
A -->|"granted through ClusterRoleBinding"| C
The ClusterRole does not grant permissions by itself.
It only defines them.
The actual authorization relationship is established by the
ClusterRoleBinding.
ClusterRoleBinding¶
The ClusterRoleBinding connects the ClusterRole to the operator's ServiceAccount.
flowchart LR
A["ClusterRole"]
B["ClusterRoleBinding"]
C["ServiceAccount"]
A --> B
B --> C
Therefore, when the operator makes an API request using this ServiceAccount, Kubernetes evaluates the permissions granted through the ClusterRoleBinding.
Role¶
The deployment also contains a namespaced Role.
This Role is associated with the default namespace and provides permissions
that are scoped to that namespace.
flowchart LR
A["Role<br/>namespace: default"]
B["Namespace-scoped resources"]
C["RoleBinding"]
D["ServiceAccount"]
A -->|"defines permissions for"| B
A --> C
C --> D
Unlike the ClusterRole, the Role itself is limited to its namespace.
This is useful when the operator needs permissions for resources inside a specific namespace without making every permission cluster-wide.
RoleBinding¶
The RoleBinding connects the namespaced Role to the same ServiceAccount used by the operator.
flowchart LR
A["Role"]
B["RoleBinding<br/>namespace: default"]
C["ServiceAccount"]
A --> B
B --> C
The effective permission set of the ServiceAccount is therefore composed of the permissions granted through both bindings.
flowchart TB
CR["ClusterRole"]
CRB["ClusterRoleBinding"]
R["Role<br/>default"]
RB["RoleBinding<br/>default"]
SA["ServiceAccount"]
CR --> CRB
CRB --> SA
R --> RB
RB --> SA
SA --> E["Effective Permissions"]
Deployment¶
The Deployment is responsible for running the operator itself.
flowchart TB
D["Deployment<br/>configbundleoperator"]
P["Pod"]
C["Operator Container"]
SA["ServiceAccount"]
D -->|"manages"| P
P -->|"runs"| C
P -->|"uses"| SA
The Deployment provides the desired state for the operator workload. Kubernetes ensures that the requested Pod is running and recreates it when necessary. The Pod then runs the operator container.
Pod Identity¶
The Pod runs using the dedicated ServiceAccount rather than the default identity.
flowchart LR
D["Deployment"]
P["Operator Pod"]
SA["Operator ServiceAccount"]
API["Kubernetes API Server"]
D --> P
P -->|"serviceAccountName"| SA
SA -->|"authenticated API requests"| API
This is important because all Kubernetes API operations performed by the operator are evaluated against the permissions granted to this ServiceAccount.
The container therefore does not need separate Kubernetes credentials.
Operator and Kubernetes API¶
Once the Pod is running, the operator communicates with the Kubernetes API using its ServiceAccount identity.
flowchart LR
OP["ConfigBundleOperator"]
SA["ServiceAccount"]
RBAC["RBAC Authorization"]
API["Kubernetes API Server"]
OP -->|"uses"| SA
SA -->|"request"| RBAC
RBAC -->|"authorize"| API
The API Server is the central point through which the operator observes and modifies Kubernetes resources.
The operator does not communicate directly with etcd or other Kubernetes control-plane components.
ConfigBundle Reconciliation¶
After deployment, the operator watches the ConfigBundle resources and
reconciles them with their managed ConfigMap resources.
flowchart LR
CB["ConfigBundle<br/>Desired State"]
OP["ConfigBundleOperator"]
CM["ConfigMap<br/>Actual State"]
CB -->|"observe"| OP
CM -->|"observe"| OP
OP -->|"create / update / replace"| CM
CM -. "drift" .-> OP
The operator therefore behaves as a controller rather than as a one-time deployment script.
Complete Architecture¶
Putting the deployment resources, RBAC, workload, and managed resources together gives the following architecture:
flowchart TB
subgraph Definition["API Definition"]
CRD["CustomResourceDefinition"]
CB["ConfigBundle"]
CRD -->|"defines"| CB
end
subgraph Identity["Identity"]
SA["ServiceAccount"]
end
subgraph RBAC["RBAC"]
CR["ClusterRole"]
CRB["ClusterRoleBinding"]
R["Role<br/>default"]
RB["RoleBinding<br/>default"]
CR --> CRB
CRB --> SA
R --> RB
RB --> SA
end
subgraph Workload["Operator Workload"]
D["Deployment"]
P["Pod"]
C["Operator Container"]
D --> P
P --> C
P -->|"uses"| SA
end
subgraph Managed["Managed Resources"]
CM["ConfigMap"]
end
C -->|"watch / reconcile"| CB
C -->|"create / update / replace"| CM
CB -->|"desired state"| C
CM -->|"actual state"| C
Complete Request Flow¶
The complete interaction can be summarized as:
sequenceDiagram
participant User
participant API as Kubernetes API Server
participant Operator as ConfigBundleOperator
participant RBAC as RBAC
participant CM as ConfigMap
User->>API: Create ConfigBundle
Operator->>API: Watch / read ConfigBundle
API-->>Operator: ConfigBundle
Operator->>RBAC: API request using ServiceAccount
RBAC-->>Operator: Authorized
Operator->>API: Read ConfigMap
API-->>Operator: Current state
Operator->>Operator: Compare desired and actual state
alt ConfigMap does not exist
Operator->>API: Create ConfigMap
API-->>CM: ConfigMap created
else Configuration differs
Operator->>API: Update / replace ConfigMap
API-->>CM: ConfigMap updated
else Configuration matches
Operator->>Operator: No action
end
API-->>Operator: Resource changes / events
Operator->>Operator: Reconcile again
Resource Relationships¶
The deployment can ultimately be understood through three separate relationships.
1. Workload relationship¶
flowchart LR
D["Deployment"]
P["Pod"]
C["Container"]
D --> P
P --> C
The Deployment keeps the operator workload running.
2. Authorization relationship¶
flowchart LR
CR["ClusterRole"]
CRB["ClusterRoleBinding"]
R["Role"]
RB["RoleBinding"]
SA["ServiceAccount"]
CR --> CRB
CRB --> SA
R --> RB
RB --> SA
The RBAC resources determine what the operator is allowed to do.
3. Reconciliation relationship¶
flowchart LR
CB["ConfigBundle<br/>Desired State"]
OP["Operator"]
CM["ConfigMap<br/>Actual State"]
CB --> OP
CM --> OP
OP --> CM
CM -. "Drift" .-> OP
The operator uses its identity and permissions to maintain the managed resources.
Deployment Lifecycle¶
The resources themselves are established in a logical order:
flowchart TD
A["Install CRD"]
B["Create ServiceAccount"]
C["Create RBAC Resources"]
D["Create Deployment"]
E["Pod Starts"]
F["Operator Connects to Kubernetes API"]
G["Operator Watches ConfigBundles"]
H["Reconciliation Begins"]
A --> B
B --> C
C --> D
D --> E
E --> F
F --> G
G --> H
Once the operator reaches the reconciliation stage, the Deployment's role is mainly to keep the operator process running.
The ongoing management of ConfigBundle and ConfigMap resources is performed
by the operator itself.
Summary¶
The deployment is built around a simple separation of concerns:
flowchart TB
A["CRD"]
B["Identity"]
C["Authorization"]
D["Workload"]
E["Reconciliation"]
A -->|"defines API"| E
B -->|"identifies"| D
C -->|"authorizes"| B
D -->|"runs"| E
- The CRD defines the
ConfigBundleAPI. - The ServiceAccount provides the operator's Kubernetes identity.
- The Role and ClusterRole define permissions.
- The RoleBinding and ClusterRoleBinding grant those permissions to the ServiceAccount.
- The Deployment runs the operator.
- The operator watches
ConfigBundleresources and reconciles their correspondingConfigMapresources.
Together, these resources form the complete Kubernetes deployment required to run ConfigBundleOperator.