// Module included in the following assemblies:
//
// assembly-using-the-cluster-operator.adoc

[id='ref-operator-cluster-{context}']
= Cluster Operator configuration

You can configure the Cluster Operator using supported environment variables, and through its logging configuration.

The environment variables relate to container configuration for the deployment of the Cluster Operator image.
For more information on `image` configuration, see, xref:con-common-configuration-images-reference[].

`STRIMZI_NAMESPACE`:: A comma-separated list of namespaces that the operator should operate in.
When not set, set to empty string, or set to `*`, the Cluster Operator will operate in all namespaces.
The Cluster Operator deployment might use the link:https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/#the-downward-api[Kubernetes Downward API^]
to set this automatically to the namespace the Cluster Operator is deployed in.
+
.Example configuration for Cluster Operator namespaces
[source,yaml,options="nowrap"]
----
env:
  - name: STRIMZI_NAMESPACE
    valueFrom:
      fieldRef:
        fieldPath: metadata.namespace
----

[[STRIMZI_FULL_RECONCILIATION_INTERVAL_MS]] `STRIMZI_FULL_RECONCILIATION_INTERVAL_MS`:: Optional, default is 120000 ms. The interval between periodic reconciliations, in milliseconds.

`STRIMZI_OPERATION_TIMEOUT_MS`:: Optional, default 300000 ms.
The timeout for internal operations, in milliseconds. This value should be
increased when using Strimzi on clusters where regular Kubernetes operations take longer than usual (because of slow downloading of Docker images, for example).

`STRIMZI_OPERATIONS_THREAD_POOL_SIZE`:: Optional, default 10
The worker thread pool size, which is used for various asynchronous and blocking operations that are run by the cluster operator.

`STRIMZI_OPERATOR_NAMESPACE`:: The name of the namespace where the Strimzi Cluster Operator is running.
Do not configure this variable manually. Use the Kubernetes Downward API.
+
[source,yaml,options="nowrap"]
----
env:
  - name: STRIMZI_OPERATOR_NAMESPACE
    valueFrom:
      fieldRef:
        fieldPath: metadata.namespace
----

`STRIMZI_OPERATOR_NAMESPACE_LABELS`:: Optional.
The labels of the namespace where the Strimzi Cluster Operator is running.
Namespace labels are used to configure the namespace selector in network policies to allow the Strimzi Cluster Operator to only have access to the operands from the namespace with these labels.
When not set, the namespace selector in network policies is configured to allow access to the Strimzi Cluster Operator from any namespace in the Kubernetes cluster.
+
[source,yaml,options="nowrap"]
----
env:
  - name: STRIMZI_OPERATOR_NAMESPACE_LABELS
    value: label1=value1,label2=value2
----

`STRIMZI_LABELS_EXCLUSION_PATTERN`:: Optional, default regex pattern is `^app.kubernetes.io/(?!part-of).*`.
Specifies the regex exclusion pattern used to filter labels propagation from the main custom resource to its subresources.
The labels exclusion filter is not applied to labels in template sections such as `spec.kafka.template.pod.metadata.labels`.
+
[source,yaml,options="nowrap"]
----
env:
  - name: STRIMZI_LABELS_EXCLUSION_PATTERN
    value: "^key1.*"
----

`STRIMZI_CUSTOM_{COMPONENT_NAME}_LABELS`:: Optional.
One or more custom labels to apply to all the pods created by the `{COMPONENT_NAME}` custom resource.  
The Cluster Operator labels the pods when the custom resource is created or is next reconciled.
+
Environment variables exist for the following components:
+
* `KAFKA`
* `KAFKA_CONNECT`
* `KAFKA_CONNECT_BUILD`
* `ZOOKEEPER`
* `ENTITY_OPERATOR`
* `KAFKA_MIRROR_MAKER2`
* `KAFKA_MIRROR_MAKER`
* `CRUISE_CONTROL`
* `KAFKA_BRIDGE`
* `KAFKA_EXPORTER`
* `JMX_TRANS`

`STRIMZI_CUSTOM_RESOURCE_SELECTOR`:: Optional.
Specifies label selector used to filter the custom resources handled by the operator.
The operator will operate only on those custom resources which will have the specified labels set.
Resources without these labels will not be seen by the operator.
The label selector applies to `Kafka`, `KafkaConnect`, `KafkaBridge`, `KafkaMirrorMaker`, and `KafkaMirrorMaker2` resources.
`KafkaRebalance` and `KafkaConnector` resources will be operated only when their corresponding Kafka and Kafka Connect clusters have the matching labels.
+
[source,yaml,options="nowrap"]
----
env:
  - name: STRIMZI_CUSTOM_RESOURCE_SELECTOR
    value: label1=value1,label2=value2
----

`STRIMZI_KAFKA_IMAGES`:: Required.
This provides a mapping from Kafka version to the corresponding Docker image containing a Kafka broker of that version.
The required syntax is whitespace or comma separated `_<version>_=_<image>_` pairs.
For example `{KafkaVersionLower}={DockerKafkaImagePrevious}, {KafkaVersionHigher}={DockerKafkaImageCurrent}`.
This is used when a `Kafka.spec.kafka.version` property is specified but not the `Kafka.spec.kafka.image` in the `Kafka` resource.

`STRIMZI_DEFAULT_KAFKA_INIT_IMAGE`:: Optional, default `{DockerKafkaInit}`.
The image name to use as default for the init container started before the broker for initial configuration work (that is, rack support), if no image is specified as the `kafka-init-image` in the `Kafka` resource.

`STRIMZI_KAFKA_CONNECT_IMAGES`:: Required.
This provides a mapping from the Kafka version to the corresponding Docker image containing a Kafka connect of that version.
The required syntax is whitespace or comma separated `_<version>_=_<image>_` pairs.
For example `{KafkaVersionLower}={DockerKafkaImagePrevious}, {KafkaVersionHigher}={DockerKafkaImageCurrent}`.
This is used when a `KafkaConnect.spec.version` property is specified but not the `KafkaConnect.spec.image`.

`STRIMZI_KAFKA_MIRROR_MAKER_IMAGES`:: Required.
This provides a mapping from the Kafka version to the corresponding Docker image containing a Kafka mirror maker of that version.
The required syntax is whitespace or comma separated `_<version>_=_<image>_` pairs.
For example `{KafkaVersionLower}={DockerKafkaImagePrevious}, {KafkaVersionHigher}={DockerKafkaImageCurrent}`.
This is used when a `KafkaMirrorMaker.spec.version` property is specified but not the `KafkaMirrorMaker.spec.image`.

`STRIMZI_DEFAULT_TOPIC_OPERATOR_IMAGE`:: Optional, default `{DockerTopicOperator}`.
The image name to use as the default when deploying the topic operator,
if no image is specified as the `Kafka.spec.entityOperator.topicOperator.image` in `Kafka` resource.

`STRIMZI_DEFAULT_USER_OPERATOR_IMAGE`:: Optional, default `{DockerUserOperator}`.
The image name to use as the default when deploying the user operator,
if no image is specified as the `Kafka.spec.entityOperator.userOperator.image` in the `Kafka` resource.

`STRIMZI_DEFAULT_TLS_SIDECAR_ENTITY_OPERATOR_IMAGE`:: Optional, default `{DockerEntityOperatorStunnel}`.
The image name to use as the default when deploying the sidecar container which provides TLS support for the Entity Operator, if
no image is specified as the `Kafka.spec.entityOperator.tlsSidecar.image` in the `Kafka` resource.

`STRIMZI_IMAGE_PULL_POLICY`:: Optional.
The `ImagePullPolicy` which will be applied to containers in all pods managed by Strimzi Cluster Operator.
The valid values are `Always`, `IfNotPresent`, and `Never`.
If not specified, the Kubernetes defaults will be used.
Changing the policy will result in a rolling update of all your Kafka, Kafka Connect, and Kafka MirrorMaker clusters.

`STRIMZI_IMAGE_PULL_SECRETS`:: Optional.
A comma-separated list of `Secret` names.
The secrets referenced here contain the credentials to the container registries where the container images are pulled from.
The secrets are used in the `imagePullSecrets` field for all `Pods` created by the Cluster Operator.
Changing this list results in a rolling update of all your Kafka, Kafka Connect, and Kafka MirrorMaker clusters.

`STRIMZI_KUBERNETES_VERSION`:: Optional.
Overrides the Kubernetes version information detected from the API server.
+
.Example configuration for Kubernetes version override
[source,yaml,options="nowrap"]
----
env:
  - name: STRIMZI_KUBERNETES_VERSION
    value: |
           major=1
           minor=16
           gitVersion=v1.16.2
           gitCommit=c97fe5036ef3df2967d086711e6c0c405941e14b
           gitTreeState=clean
           buildDate=2019-10-15T19:09:08Z
           goVersion=go1.12.10
           compiler=gc
           platform=linux/amd64
----

`KUBERNETES_SERVICE_DNS_DOMAIN`:: Optional.
Overrides the default Kubernetes DNS domain name suffix.
+
By default, services assigned in the Kubernetes cluster have a DNS domain name that uses the default suffix `cluster.local`.
+
For example, for broker _kafka-0_:
+
[source,shell,subs="+quotes"]
----
_<cluster-name>_-kafka-0._<cluster-name>_-kafka-brokers._<namespace>_.svc._cluster.local_
----
+
The DNS domain name is added to the Kafka broker certificates used for hostname verification.
+
If you are using a different DNS domain name suffix in your cluster, change the `KUBERNETES_SERVICE_DNS_DOMAIN` environment variable from the default to the one you are using in order to establish a connection with the Kafka brokers.

`STRIMZI_CONNECT_BUILD_TIMEOUT_MS`:: Optional, default 300000 ms.
The timeout for building new Kafka Connect images with additional connectots, in milliseconds.
This value should be increased when using Strimzi to build container images containing many connectors or using a slow container registry.

`STRIMZI_NETWORK_POLICY_GENERATION` :: Optional, default `true`.
Controls whether Strimzi generates network policy resources.
Network policies allow connections between Kafka components.

Set this environment variable to `false` to disable network policy generation. You might do this, for example, if you want to use custom network policies. Custom network policies allow more control over maintaining the connections between components.

`STRIMZI_FEATURE_GATES`:: Optional.
Enables or disables features and functionality controlled by feature gates.
For more information about each feature gate, see xref:ref-operator-cluster-feature-gates-{context}[].

[id='ref-operator-cluster-feature-gates-{context}']
== Feature gates

Strimzi operators support _feature gates_ to enable or disable certain features and functionality.
Enabling a feature gate changes the behavior of the relevant operator and introduces the feature to your Strimzi deployment.

Feature gates have a default state of either _enabled_ or _disabled_.
To modify a feature gate's default state, use the `STRIMZI_FEATURE_GATES` environment variable in the operator's configuration.
You can modify multiple feature gates using this single environment variable.

Feature gates have three stages of maturity:

* Alpha — typically disabled by default
* Beta — typically enabled by default
* General Availability (GA) — typically enabled by default

Alpha stage features might be experimental or unstable, subject to change, or not sufficiently tested for production use.
Beta stage features are well tested and their functionality is not likely to change.
GA stage features are stable and should not change in future.
Alpha and beta stage features are removed if they do not prove to be useful.

NOTE: Feature gates might be removed when they reach GA. This means that the feature was incorporated into the Strimzi core features and can no longer be disabled.

.All feature gates and the Strimzi versions when they moved to alpha, beta, or GA
[cols="4*",options="header",stripes="none",separator=¦]
|===

¦Feature gate
¦Alpha
¦Beta
¦GA

¦`ControlPlaneListener`
¦0.23.0
¦ -
¦ -

¦`ServiceAccountPatching`
¦0.24.0
¦ -
¦ -

|===

[discrete]
=== Configuring feature gates

You configure feature gates using the `STRIMZI_FEATURE_GATES` environment variable in the operator's configuration.
Specify a comma-separated list of feature gate names and prefixes.
A `+` prefix enables the feature gate and a `-` prefix  disables it.

.Example feature gate configuration that enables `FeatureGate1` and disables `FeatureGate2`
[source,yaml,options="nowrap"]
----
env:
  - name: STRIMZI_FEATURE_GATES
    value: +FeatureGate1,-FeatureGate2
----

=== Control plane listener feature gate

Use the `ControlPlaneListener` feature gate to change the communication paths used for inter-broker communications within your Kafka cluster.

The Kubernetes control plane manages the workloads running on the worker nodes.
Services such as the Kubernetes API server and the controller manager run on the control plane.
The Kubernetes data plane provides resources to containers, including CPU, memory, network, and storage.

In Strimzi, control plane traffic consists of controller connections that maintain the desired state of the Kafka cluster.
Data plane traffic mainly consists of data replication between the leader broker and the follower brokers.

When the `ControlPlaneListener` feature gate is disabled, control plane and data plane traffic go through the same internal listener on port 9091.
This was the default behavior before the feature gate was introduced.

When `ControlPlaneListener` is enabled, control plane traffic goes through a dedicated _control plane listener_ on port 9090.
Data plane traffic continues to use the internal listener on port 9091.

Using control plane listeners might improve performance because important controller connections, such as partition leadership changes, are not delayed by data replication across brokers.

.Enabling the control plane listener feature gate

The `ControlPlaneListener` feature gate is in the alpha stage and has a default state of _disabled_.
To enable it, specify `+ControlPlaneListener` in the `STRIMZI_FEATURE_GATES` environment variable in the Cluster Operator configuration.

This feature gate must be disabled when:

* Upgrading from Strimzi 0.22 and earlier
* Downgrading to Strimzi 0.22 and earlier

NOTE: The `ControlPlaneListener` feature gate was introduced in Strimzi 0.23.0 and is expected to remain in the alpha stage for a number of releases before moving to the beta stage.

=== Service Account patching feature gate

By default, the Cluster Operator does not update service accounts.
To allow the Cluster Operator to apply updates, enable the `ServiceAccountPatching` feature gate.

Add `+ServiceAccountPatching` to the `STRIMZI_FEATURE_GATES` environment variable in the Cluster Operator configuration.

The feature gate is currently in the alpha phase and disabled by default.
With the feature gate enabled, the Cluster Operator applies updates to service account configuration in every reconciliation.
For example, you can change service account labels and annotations after the operands are already created.

NOTE: The `ServiceAccountPatching` feature gate was introduced in Strimzi 0.24.0 and is expected to remain in the alpha phase for a number of releases before it moves to the beta phase and is enabled by default.

== Logging configuration by ConfigMap

The Cluster Operator's logging is configured by the `strimzi-cluster-operator` `ConfigMap`.

A `ConfigMap` containing logging configuration is created when installing the Cluster Operator.
This `ConfigMap` is described in the file `install/cluster-operator/050-ConfigMap-strimzi-cluster-operator.yaml`.
You configure Cluster Operator logging by changing the data field `log4j2.properties` in this `ConfigMap`.

To update the logging configuration, you can edit the `050-ConfigMap-strimzi-cluster-operator.yaml` file and then run the following command:
[source,shell,subs=+quotes]
kubectl create -f _install/cluster-operator/050-ConfigMap-strimzi-cluster-operator.yaml_

Alternatively, edit the `ConfigMap` directly:
[source,shell,subs=+quotes]
kubectl edit configmap strimzi-cluster-operator

To change the frequency of the reload interval, set a time in seconds in the `monitorInterval` option in the created `ConfigMap`.

If the `ConfigMap` is missing when the Cluster Operator is deployed, the default logging values are used.

If the `ConfigMap` is accidentally deleted after the Cluster Operator is deployed, the most recently loaded logging configuration is used.
Create a new `ConfigMap` to load a new logging configuration.

NOTE: Do not remove the `monitorInterval` option from the ConfigMap.

== Restricting Cluster Operator access with network policy

The Cluster Operator can run in the same namespace as the resources it manages, or in a separate namespace.
By default, the `STRIMZI_OPERATOR_NAMESPACE` environment variable is configured to use the Kubernetes Downward API to find which namespace the Cluster Operator is running in.
If the Cluster Operator is running in the same namespace as the resources, only local access is required, and allowed by Strimzi.

If the Cluster Operator is running in a separate namespace to the resources it manages, any namespace in the Kubernetes cluster is allowed access to the Cluster Operator unless network policy is configured.
Use the optional `STRIMZI_OPERATOR_NAMESPACE_LABELS` environment variable to establish network policy for the Cluster Operator using namespace labels.
By adding namespace labels, access to the Cluster Operator is restricted to the namespaces specified.

.Network policy configured for the Cluster Operator deployment
[source,yaml,options="nowrap"]
----
#...
env:
  # ...
  - name: STRIMZI_OPERATOR_NAMESPACE_LABELS
    value: label1=value1,label2=value2
  #...
----

== Periodic reconciliation

Although the Cluster Operator reacts to all notifications about the desired cluster resources received from the Kubernetes cluster,
if the operator is not running, or if a notification is not received for any reason, the desired resources will get out of sync with the state of the running Kubernetes cluster.

In order to handle failovers properly, a periodic reconciliation process is executed by the Cluster Operator so that it can compare the state of the desired resources with the current cluster deployments in order to have a consistent state across all of them.
You can set the time interval for the periodic reconciliations using the xref:STRIMZI_FULL_RECONCILIATION_INTERVAL_MS[] variable.

= Provisioning Role-Based Access Control (RBAC)

For the Cluster Operator to function it needs permission within the Kubernetes cluster to interact with resources such as `Kafka`, `KafkaConnect`, and so on, as well as the managed resources, such as `ConfigMaps`, `Pods`, `Deployments`, `StatefulSets` and `Services`.
Such permission is described in terms of Kubernetes role-based access control (RBAC) resources:

* `ServiceAccount`,
* `Role` and `ClusterRole`,
* `RoleBinding` and `ClusterRoleBinding`.

In addition to running under its own `ServiceAccount` with a `ClusterRoleBinding`, the Cluster Operator manages some RBAC resources for the components that need access to Kubernetes resources.

Kubernetes also includes privilege escalation protections that prevent components operating under one `ServiceAccount` from granting other `ServiceAccounts` privileges that the granting `ServiceAccount` does not have.
Because the Cluster Operator must be able to create the `ClusterRoleBindings`, and `RoleBindings` needed by resources it manages, the Cluster Operator must also have those same privileges.

[id='delegated-privileges-{context}']
== Delegated privileges

When the Cluster Operator deploys resources for a desired `Kafka` resource it also creates `ServiceAccounts`, `RoleBindings`, and `ClusterRoleBindings`, as follows:

* The Kafka broker pods use a `ServiceAccount` called `_cluster-name_-kafka`
  - When the rack feature is used, the `strimzi-_cluster-name_-kafka-init` `ClusterRoleBinding` is used to grant this `ServiceAccount` access to the nodes within the cluster via a `ClusterRole` called `strimzi-kafka-broker`
  - When the rack feature is not used and the cluster is not exposed via nodeport, no binding is created
* The ZooKeeper pods use a `ServiceAccount` called `_cluster-name_-zookeeper`
* The Entity Operator pod uses a `ServiceAccount` called `_cluster-name_-entity-operator`
    - The Topic Operator produces Kubernetes events with status information, so the `ServiceAccount` is bound to a `ClusterRole` called `strimzi-entity-operator` which grants this access via the `strimzi-entity-operator` `RoleBinding`
* The pods for `KafkaConnect` resource uses a `ServiceAccount` called `_cluster-name_-cluster-connect`
* The pods for `KafkaMirrorMaker` use a `ServiceAccount` called `_cluster-name_-mirror-maker`
* The pods for `KafkaMirrorMaker2` use a `ServiceAccount` called `_cluster-name_-mirrormaker2`
* The pods for `KafkaBridge` use a `ServiceAccount` called `_cluster-name_-bridge`

== `ServiceAccount`

The Cluster Operator is best run using a `ServiceAccount`:

[source,yaml,options="nowrap"]
.Example `ServiceAccount` for the Cluster Operator
----
include::../install/cluster-operator/010-ServiceAccount-strimzi-cluster-operator.yaml[]
----

The `Deployment` of the operator then needs to specify this in its `spec.template.spec.serviceAccountName`:

[source,yaml,numbered,options="nowrap",highlight='12']
.Partial example of `Deployment` for the Cluster Operator
----
include::../install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml[lines=1..13]
      # ...
----

Note line 12, where the `strimzi-cluster-operator` `ServiceAccount` is specified as the `serviceAccountName`.

== `ClusterRoles`

The Cluster Operator needs to operate using `ClusterRoles` that gives access to the necessary resources.
Depending on the Kubernetes cluster setup, a cluster administrator might be needed to create the `ClusterRoles`.

NOTE: Cluster administrator rights are only needed for the creation of the `ClusterRoles`.
The Cluster Operator will not run under the cluster admin account.

The `ClusterRoles` follow the _principle of least privilege_ and contain only those privileges needed by the Cluster Operator to operate Kafka, Kafka Connect, and ZooKeeper clusters. The first set of assigned privileges allow the Cluster Operator to manage Kubernetes resources such as `StatefulSets`, `Deployments`, `Pods`, and `ConfigMaps`.

Cluster Operator uses ClusterRoles to grant permission at the namespace-scoped resources level and cluster-scoped resources level:

[source,yaml,options="nowrap"]
.`ClusterRole` with namespaced resources for the Cluster Operator
----
include::../install/cluster-operator/020-ClusterRole-strimzi-cluster-operator-role.yaml[]
----

The second includes the permissions needed for cluster-scoped resources.

[source,yaml,options="nowrap"]
.`ClusterRole` with cluster-scoped resources for the Cluster Operator
----
include::../install/cluster-operator/021-ClusterRole-strimzi-cluster-operator-role.yaml[]
----

The `strimzi-kafka-broker` `ClusterRole` represents the access needed by the init container in Kafka pods that is used for the rack feature. As described in the xref:delegated-privileges-str[Delegated privileges] section, this role is also needed by the Cluster Operator in order to be able to delegate this access.

[source,yaml,options="nowrap"]
.`ClusterRole` for the Cluster Operator allowing it to delegate access to Kubernetes nodes to the Kafka broker pods
----
include::../install/cluster-operator/030-ClusterRole-strimzi-kafka-broker.yaml[]
----

The `strimzi-topic-operator` `ClusterRole` represents the access needed by the Topic Operator. As described in the xref:delegated-privileges-str[Delegated privileges] section, this role is also needed by the Cluster Operator in order to be able to delegate this access.

[source,yaml,options="nowrap"]
.`ClusterRole` for the Cluster Operator allowing it to delegate access to events to the Topic Operator
----
include::../install/cluster-operator/031-ClusterRole-strimzi-entity-operator.yaml[]
----

The `strimzi-kafka-client` `ClusterRole` represents the access needed by the components based on Kafka clients which use the client rack-awareness.
As described in the xref:delegated-privileges-str[Delegated privileges] section, this role is also needed by the Cluster Operator in order to be able to delegate this access.

[source,yaml,options="nowrap"]
.`ClusterRole` for the Cluster Operator allowing it to delegate access to Kubernetes nodes to the Kafka client based pods
----
include::../install/cluster-operator/033-ClusterRole-strimzi-kafka-client.yaml[]
----

== `ClusterRoleBindings`

The operator needs `ClusterRoleBindings` and `RoleBindings` which associates its `ClusterRole` with its `ServiceAccount`:
`ClusterRoleBindings` are needed for `ClusterRoles` containing cluster-scoped resources.

[source,yaml,options="nowrap"]
.Example `ClusterRoleBinding` for the Cluster Operator
----
include::../install/cluster-operator/021-ClusterRoleBinding-strimzi-cluster-operator.yaml[]
----

`ClusterRoleBindings` are also needed for the `ClusterRoles` needed for delegation:

[source,yaml,options="nowrap"]
.Example `ClusterRoleBinding` for the Cluster Operator for the Kafka broker rack-awareness
----
include::../install/cluster-operator/030-ClusterRoleBinding-strimzi-cluster-operator-kafka-broker-delegation.yaml[]
----

and

[source,yaml,options="nowrap"]
.Example `ClusterRoleBinding` for the Cluster Operator for the Kafka client rack-awareness
----
include::../install/cluster-operator/033-ClusterRoleBinding-strimzi-cluster-operator-kafka-client-delegation.yaml[]
----

`ClusterRoles` containing only namespaced resources are bound using `RoleBindings` only.

[source,yaml,options="nowrap"]
----
include::../install/cluster-operator/020-RoleBinding-strimzi-cluster-operator.yaml[]
----

[source,yaml,options="nowrap"]
----
include::../install/cluster-operator/031-RoleBinding-strimzi-cluster-operator-entity-operator-delegation.yaml[]
----
