Gardener Controller Manager
Overview
The gardener-controller-manager (often referred to as "GCM") is a component that runs next to the Gardener API server, similar to the Kubernetes Controller Manager. It runs several controllers that do not require talking to any seed or shoot cluster. Also, as of today, it exposes an HTTP server that is serving several health check endpoints and metrics.
This document explains the various functionalities of the gardener-controller-manager and their purpose.
Controllers
Bastion Controller
Bastion resources have a limited lifetime which can be extended up to a certain amount by performing a heartbeat on them. The Bastion controller is responsible for deleting expired or rotten Bastions.
- "expired" means a
Bastionhas exceeded itsstatus.expirationTimestamp. - "rotten" means a
Bastionis older than the configuredmaxLifetime.
The maxLifetime defaults to 24 hours and is an option in the BastionControllerConfiguration which is part of gardener-controller-managers ControllerManagerControllerConfiguration, see the example config file for details.
The controller also deletes Bastions in case the referenced Shoot:
- no longer exists
- is marked for deletion (i.e., have a non-
nil.metadata.deletionTimestamp) - was migrated to another seed (i.e.,
Shoot.spec.seedNameis different thanBastion.spec.seedName).
The deletion of Bastions triggers the gardenlet to perform the necessary cleanups in the Seed cluster, so some time can pass between deletion and the Bastion actually disappearing. Clients like gardenctl are advised to not re-use Bastions whose deletion timestamp has been set already.
Refer to GEP-15 for more information on the lifecycle of Bastion resources.
CertificateSigningRequest Controller
After the gardenlet gets deployed on the Seed cluster, it needs to establish itself as a trusted party to communicate with the Gardener API server. It runs through a bootstrap flow similar to the kubelet bootstrap process.
On startup, the gardenlet uses a kubeconfig with a bootstrap token which authenticates it as being part of the system:bootstrappers group. This kubeconfig is used to create a CertificateSigningRequest (CSR) against the Gardener API server.
The controller in gardener-controller-manager checks whether the CertificateSigningRequest has the expected organization, common name and usages which the gardenlet would request.
The controller auto-approves CSRs based on the type of gardenlet deployment and validates the appropriate permissions:
Seed Client Certificates (seedclient subresource)
For regular gardenlets managing seed clusters, the controller auto-approves CSRs when:
- The CSR matches the requirements for a seed client certificate (correct organization, common name, and usages)
- The requesting client has permission to create the
certificatesigningrequests/seedclientsubresource
Self-Hosted Shoot Client Certificates (shootclient subresource)
For gardenlets responsible for self-hosted shoots, the controller performs additional security validation:
- The CSR must match the requirements for a shoot client certificate (correct organization, common name, and usages)
- The requesting client must have permission to create the
certificatesigningrequests/shootclientsubresource - Bootstrap Token Validation: The CSR must be requested via a bootstrap token with a specific description format containing the shoot's namespace and name
- Subject Matching: The certificate request's subject must match the shoot metadata extracted from the bootstrap token description
Permission Model
Both types of CSRs rely on the same RBAC setup:
- Clients in the
system:bootstrappersgroup are bound to thegardener.cloud:system:seed-bootstrapperClusterRole - This ClusterRole grants permission to create both
certificatesigningrequests/seedclientandcertificatesigningrequests/shootclientsubresources - The gardenlet's bootstrap kubeconfig contains a bootstrap token that authenticates it as part of the
system:bootstrappersgroup
This dual approval mechanism ensures that both regular seed gardenlets and self-hosted shoot gardenlets can obtain client certificates while maintaining appropriate security controls for each deployment model.
CloudProfile Controller
CloudProfiles are essential when it comes to reconciling Shoots since they contain constraints (like valid machine types, Kubernetes versions, or machine images) and sometimes also some global configuration for the respective environment (typically via provider-specific configuration in .spec.providerConfig).
Consequently, to ensure that CloudProfiles in-use are always present in the system until the last referring Shoot or NamespacedCloudProfile gets deleted, the controller adds a finalizer which is only released when there is no Shoot or NamespacedCloudProfile referencing the CloudProfile anymore.
NamespacedCloudProfile Controller
NamespacedCloudProfiles provide a project-scoped extension to CloudProfiles, allowing for adjustments of a parent CloudProfile (e.g. by overriding expiration dates of Kubernetes versions or machine images). This allows for modifications without global project visibility. Like CloudProfiles do in their spec, NamespacedCloudProfiles also expose the resulting Shoot constraints as a CloudProfileSpec in their status.
The controller ensures that NamespacedCloudProfiles in-use remain present in the system until the last referring Shoot is deleted by adding a finalizer that is only released when there is no Shoot referencing the NamespacedCloudProfile anymore.
ControllerDeployment Controller
Extensions are registered in the garden cluster via ControllerRegistration and deployment of respective extensions are specified via ControllerDeployment. For more info refer to Registering Extension Controllers.
This controller ensures that ControllerDeployment in-use always exists until the last ControllerRegistration referencing them gets deleted. The controller adds a finalizer which is only released when there is no ControllerRegistration referencing the ControllerDeployment anymore.
ControllerRegistration Controller
The ControllerRegistration controller makes sure that the required Gardener Extensions specified by the ControllerRegistration resources are present in the seed clusters. It also takes care of the creation and deletion of ControllerInstallation objects for a given seed cluster. The controller has three reconciliation loops.
"Main" Reconciler
This reconciliation loop watches the Seed objects and determines which ControllerRegistrations are required for them and reconciles the corresponding ControllerInstallation resources to reach the determined state. To begin with, it computes the kind/type combinations of extensions required for the seed. For this, the controller examines a live list of ControllerRegistrations, ControllerInstallations, BackupBuckets, BackupEntrys, Shoots, and Secrets from the garden cluster. For example, it examines the shoots running on the seed and deducts the kind/type, like Infrastructure/gcp. The seed (seed.spec.provider.type) and DNS (seed.spec.dns.provider.type) provider types are considered when calculating the list of required ControllerRegistrations, as well. It also decides whether they should always be deployed based on the .spec.deployment.policy. For the configuration options, please see this section.
Based on these required combinations, each of them are mapped to ControllerRegistration objects and then to their corresponding ControllerInstallation objects (if existing). The controller then creates or updates the required ControllerInstallation objects for the given seed. It also deletes every existing ControllerInstallation whose referenced ControllerRegistration is not part of the required list. For example, if the shoots in the seed are no longer using the DNS provider aws-route53, then the controller proceeds to delete the respective ControllerInstallation object.
"ControllerRegistration Finalizer" Reconciler
This reconciliation loop watches the ControllerRegistration resource and adds finalizers to it when they are created. In case a deletion request comes in for the resource, i.e., if a .metadata.deletionTimestamp is set, it actively scans for a ControllerInstallation resource using this ControllerRegistration, and decides whether the deletion can be allowed. In case no related ControllerInstallation is present, it removes the finalizer and marks it for deletion.
"Seed Finalizer" Reconciler
This loop also watches the Seed object and adds finalizers to it at creation. If a .metadata.deletionTimestamp is set for the seed, then the controller checks for existing ControllerInstallation objects which reference this seed. If no such objects exist, then it removes the finalizer and allows the deletion.
"Extension ClusterRole" Reconciler
This reconciler watches two resources in the garden cluster:
ClusterRoles labelled withauthorization.gardener.cloud/custom-extensions-permissions=trueServiceAccounts in seed namespaces matching the selector provided via theauthorization.gardener.cloud/extensions-serviceaccount-selectorannotation of suchClusterRoles.
Its core task is to maintain a ClusterRoleBinding resource referencing the respective ClusterRole. This gets bound to all ServiceAccounts in seed namespaces whose labels match the selector provided via the authorization.gardener.cloud/extensions-serviceaccount-selector annotation of such ClusterRoles.
You can read more about the purpose of this reconciler in this document.
CredentialsBinding Controller
CredentialsBindings reference Secrets, WorkloadIdentitys and Quotas and are themselves referenced by Shoots.
The controller adds finalizers to the referenced objects to ensure they don't get deleted while still being referenced. Similarly, to ensure that CredentialsBindings in-use are always present in the system until the last referring Shoot gets deleted, the controller adds a finalizer which is only released when there is no Shoot referencing the CredentialsBinding anymore.
Referenced Secrets and WorkloadIdentitys will also be labeled with provider.shoot.gardener.cloud/<type>=true, where <type> is the value of the .provider.type of the CredentialsBinding. Also, all referenced Secrets and WorkloadIdentitys, as well as Quotas, will be labeled with reference.gardener.cloud/credentialsbinding=true to allow for easily filtering for objects referenced by CredentialsBindings.
Event Controller
With the Gardener Event Controller, you can prolong the lifespan of events related to Shoot clusters. This is an optional controller which will become active once you provide the below mentioned configuration.
All events in K8s are deleted after a configurable time-to-live (controlled via a kube-apiserver argument called --event-ttl (defaulting to 1 hour)). The need to prolong the time-to-live for Shoot cluster events frequently arises when debugging customer issues on live systems. This controller leaves events involving Shoots untouched, while deleting all other events after a configured time. In order to activate it, provide the following configuration:
concurrentSyncs: The amount of goroutines scheduled for reconciling events.ttlNonShootEvents: When an event reaches this time-to-live it gets deleted unless it is a Shoot-related event (defaults to1h, equivalent to theevent-ttldefault).
⚠️ In addition, you should also configure the
--event-ttlfor the kube-apiserver to define an upper-limit of how long Shoot-related events should be stored. The--event-ttlshould be larger than thettlNonShootEventsor this controller will have no effect.
ExposureClass Controller
ExposureClass abstracts the ability to expose a Shoot clusters control plane in certain network environments (e.g. corporate networks, DMZ, internet) on all Seeds or a subset of the Seeds. For more information, see ExposureClasses.
Consequently, to ensure that ExposureClasses in-use are always present in the system until the last referring Shoot gets deleted, the controller adds a finalizer which is only released when there is no Shoot referencing the ExposureClass anymore.
Gardenlet Lifecycle Controller
The "Lifecycle" reconciler processes Seed and self-hosted Shoot objects which are enqueued every 10 seconds in order to check if the responsible gardenlet is still responding and operable. Therefore, it checks renewals via Lease objects in the garden cluster which are renewed regularly by the gardenlet.
In case a Lease is not renewed for the configured amount in config.controllers.seed.monitorPeriod.duration:
- The reconciler assumes that the
gardenletstopped operating and updates theGardenletReadycondition toUnknown. - Additionally, the conditions and constraints of all affected
Shootresources are set toUnknownas well, because a strikinggardenletwon't be able to maintain these conditions anymore. - For
Seeds: If the gardenlet's client certificate has expired (identified based on the.status.clientCertificateExpirationTimestampfield in theSeedresource) and if it is managed by aManagedSeed, then this will be triggered for a reconciliation. This will trigger the bootstrapping process again and allows gardenlets to obtain a fresh client certificate.
ManagedSeedSet Controller
ManagedSeedSet objects maintain a stable set of replicas of ManagedSeeds, i.e. they guarantee the availability of a specified number of identical ManagedSeeds on an equal number of identical Shoots. The ManagedSeedSet controller creates and deletes ManagedSeeds and Shoots in response to changes to the replicas and selector fields. For more information, refer to the ManagedSeedSet proposal document.
- The reconciler first gets all the replicas of the given
ManagedSeedSetin theManagedSeedSet's namespace and with the matching selector. Each replica is a struct that contains aManagedSeed, its correspondingSeedandShootobjects. - Then the pending replica is retrieved, if it exists.
- Next it determines the ready, postponed, and deletable replicas.
- A replica is considered
readywhen aSeedowned by aManagedSeedhas been registered either directly or by deployinggardenletinto aShoot, theSeedisReadyand theShoot's status isHealthy. - If a replica is not ready and it is not pending, i.e. it is not specified in the
ManagedSeed'sstatus.pendingReplicafield, then it is added to thepostponedreplicas. - A replica is deletable if it has no scheduled
Shoots and the replica'sShootandManagedSeeddo not have theseedmanagement.gardener.cloud/protect-from-deletionannotation.
- A replica is considered
- Finally, it checks the actual and target replica counts. If the actual count is less than the target count, the controller scales up the replicas by creating new replicas to match the desired target count. If the actual count is more than the target, the controller deletes replicas to match the desired count. Before scale-out or scale-in, the controller first reconciles the pending replica (there can always only be one) and makes sure the replica is ready before moving on to the next one.
Scale-out(actual count < target count)- During the scale-out phase, the controller first creates the
Shootobject from theManagedSeedSet'sspec.shootTemplatefield and adds the replica to thestatus.pendingReplicaof theManagedSeedSet. - For the subsequent reconciliation steps, the controller makes sure that the pending replica is ready before proceeding to the next replica. Once the
Shootis created successfully, theManagedSeedobject is created from theManagedSeedSet'sspec.template. TheManagedSeedobject is reconciled by theManagedSeedcontroller and aSeedobject is created for the replica. Once the replica'sSeedbecomes ready and theShootbecomes healthy, the replica also becomes ready.
- During the scale-out phase, the controller first creates the
Scale-in(actual count > target count)- During the scale-in phase, the controller first determines the replica that can be deleted. From the deletable replicas, it chooses the one with the lowest priority and deletes it. Priority is determined in the following order:
- First, compare replica statuses. Replicas with "less advanced" status are considered lower priority. For example, a replica with
StatusShootReconcilingstatus has a lower value than a replica withStatusShootReconciledstatus. Hence, in this case, a replica with aStatusShootReconcilingstatus will have lower priority and will be considered for deletion. - Then, the replicas are compared with the readiness of their
Seeds. Replicas with non-readySeeds are considered lower priority. - Then, the replicas are compared with the health statuses of their
Shoots. Replicas with "worse" statuses are considered lower priority. - Finally, the replica ordinals are compared. Replicas with lower ordinals are considered lower priority.
- First, compare replica statuses. Replicas with "less advanced" status are considered lower priority. For example, a replica with
- During the scale-in phase, the controller first determines the replica that can be deleted. From the deletable replicas, it chooses the one with the lowest priority and deletes it. Priority is determined in the following order:
Quota Controller
Quota object limits the resources consumed by shoot clusters either per provider secret or per project/namespace.
Consequently, to ensure that Quotas in-use are always present in the system until the last SecretBinding or CredentialsBinding that references them gets deleted, the controller adds a finalizer which is only released when there is no SecretBinding or CredentialsBinding referencing the Quota anymore.
Project Controller
There are multiple controllers responsible for different aspects of Project objects. Please also refer to the Project documentation.
"Main" Reconciler
This reconciler manages a dedicated Namespace for each Project. The namespace name can either be specified explicitly in .spec.namespace (must be prefixed with garden-) or it will be determined by the controller. If .spec.namespace is set, it tries to create it. If it already exists, it tries to adopt it. This will only succeed if the Namespace was previously labeled with gardener.cloud/role=project and project.gardener.cloud/name=<project-name>. This is to prevent end-users from being able to adopt arbitrary namespaces and escalate their privileges, e.g. the kube-system namespace.
After the namespace was created/adopted, the controller creates several ClusterRoles and ClusterRoleBindings that allow the project members to access related resources based on their roles. These RBAC resources are prefixed with gardener.cloud:system:project{-member,-viewer}:<project-name>. Gardener administrators and extension developers can define their own roles. For more information, see Extending Project Roles for more information.
In addition, operators can configure the Project controller to maintain a default ResourceQuota for project namespaces. Quotas can especially limit the creation of user facing resources, e.g. Shoots, SecretBindings, CredentialsBinding, Secrets and thus protect the garden cluster from massive resource exhaustion but also enable operators to align quotas with respective enterprise policies.
⚠️ Gardener itself is not exempted from configured quotas. For example, Gardener creates
Secretsfor every shoot cluster in the project namespace and at the same time increases the available quota count. Please mind this additional resource consumption.
The controller configuration provides a template section controllers.project.quotas where such a ResourceQuota (see the example below) can be deposited.
controllers:
project:
quotas:
- config:
apiVersion: v1
kind: ResourceQuota
spec:
hard:
count/shoots.core.gardener.cloud: "100"
count/secretbindings.core.gardener.cloud: "10"
count/credentialsbindings.security.gardener.cloud: "10"
count/secrets: "800"
projectSelector: {}The Project controller takes the specified config and creates a ResourceQuota with the name gardener in the project namespace. If a ResourceQuota resource with the name gardener already exists, the controller will only update fields in spec.hard which are unavailable at that time. This is done to configure a default Quota in all projects but to allow manual quota increases as the projects' demands increase. spec.hard fields in the ResourceQuota object that are not present in the configuration are removed from the object. Labels and annotations on the ResourceQuota config get merged with the respective fields on existing ResourceQuotas. An optional projectSelector narrows down the amount of projects that are equipped with the given config. If multiple configs match for a project, then only the first match in the list is applied to the project namespace.
The .status.phase of the Project resources is set to Ready or Failed by the reconciler to indicate whether the reconciliation loop was performed successfully. Also, it generates Events to provide further information about its operations.
When a Project is marked for deletion, the controller ensures that there are no Shoots left in the project namespace. Once all Shoots are gone, the Namespace and Project are released.
"Stale Projects" Reconciler
As Gardener is a large-scale Kubernetes as a Service, it is designed for being used by a large amount of end-users. Over time, it is likely to happen that some of the hundreds or thousands of Project resources are no longer actively used.
Gardener offers the "stale projects" reconciler which will take care of identifying such stale projects, marking them with a "warning", and eventually deleting them after a certain time period. This reconciler is enabled by default and works as follows:
- Projects are considered as "stale"/not actively used when all of the following conditions apply: The namespace associated with the
Projectdoes not have any...Shootresources.BackupEntryresources.Secretresources that are referenced by aSecretBindingor aCredentialsBindingthat is in use by aShoot(not necessarily in the same namespace).WorkloadIdentityresources that are referenced by aCredentialsBindingthat is in use by aShoot(not necessarily in the same namespace).Quotaresources that are referenced by aSecretBindingor aCredentialsBindingthat is in use by aShoot(not necessarily in the same namespace).- The time period when the project was used for the last time (
status.lastActivityTimestamp) is longer than the configuredminimumLifetimeDays
If a project is considered "stale", then its .status.staleSinceTimestamp will be set to the time when it was first detected to be stale. If it gets actively used again, this timestamp will be removed. After some time, the .status.staleAutoDeleteTimestamp will be set to a timestamp after which Gardener will auto-delete the Project resource if it still is not actively used.
The component configuration of the gardener-controller-manager offers to configure the following options:
minimumLifetimeDays: Don't consider newly createdProjects as "stale" too early to give people/end-users some time to onboard and get familiar with the system. The "stale project" reconciler won't set any timestamp forProjects younger thanminimumLifetimeDays. When you change this value, then projects marked as "stale" may be no longer marked as "stale" in case they are young enough, or vice versa.staleGracePeriodDays: Don't compute auto-delete timestamps for staleProjects that are unused for less thanstaleGracePeriodDays. This is to not unnecessarily make people/end-users nervous "just because" they haven't actively used theirProjectfor a given amount of time. When you change this value, then already assigned auto-delete timestamps may be removed if the new grace period is not yet exceeded.staleExpirationTimeDays: Expiration time after which staleProjects are finally auto-deleted (after.status.staleSinceTimestamp). If this value is changed and an auto-delete timestamp got already assigned to the projects, then the new value will only take effect if it's increased. Hence, decreasing thestaleExpirationTimeDayswill not decrease already assigned auto-delete timestamps.
Gardener administrators/operators can exclude specific
Projects from the stale check by annotating the relatedNamespaceresource withproject.gardener.cloud/skip-stale-check=true.
"Activity" Reconciler
Since the other two reconcilers are unable to actively monitor the relevant objects that are used in a Project (Shoot, Secret, etc.), there could be a situation where the user creates and deletes objects in a short period of time. In that case, the Stale Project Reconciler could not see that there was any activity on that project and it will still mark it as a Stale, even though it is actively used.
The Project Activity Reconciler is implemented to take care of such cases. An event handler will notify the reconciler for any activity and then it will update the status.lastActivityTimestamp. This update will also trigger the Stale Project Reconciler.
SecretBinding Controller
SecretBindings reference Secrets and Quotas and are themselves referenced by Shoots. The controller adds finalizers to the referenced objects to ensure they don't get deleted while still being referenced. Similarly, to ensure that SecretBindings in-use are always present in the system until the last referring Shoot gets deleted, the controller adds a finalizer which is only released when there is no Shoot referencing the SecretBinding anymore.
Referenced Secrets will also be labeled with provider.shoot.gardener.cloud/<type>=true, where <type> is the value of the .provider.type of the SecretBinding. Also, all referenced Secrets, as well as Quotas, will be labeled with reference.gardener.cloud/secretbinding=true to allow for easily filtering for objects referenced by SecretBindings.
Seed Controller
The Seed controller in the gardener-controller-manager reconciles Seed objects with the help of the following reconcilers.
"Main" Reconciler
This reconciliation loop takes care of seed related operations in the garden cluster. When a new Seed object is created, the reconciler creates a new Namespace in the garden cluster seed-<seed-name>. Namespaces dedicated to single seed clusters allow us to segregate access permissions i.e., a gardenlet must not have permissions to access objects in all Namespaces in the garden cluster. There are objects in a Garden environment which are created once by the operator e.g., default domain secret, alerting credentials, and are required for operations happening in the gardenlet. Therefore, we not only need a seed specific Namespace but also a copy of these "shared" objects.
The "main" reconciler takes care about this replication:
| Kind | Namespace | Label Selector |
|---|---|---|
| Secret | garden | gardener.cloud/role |
"Backup Buckets Check" Reconciler
Every time a BackupBucket object is created or updated, the referenced Seed object is enqueued for reconciliation. It's the reconciler's task to check the status subresource of all existing BackupBuckets that reference this Seed. If at least one BackupBucket has .status.lastError != nil, the BackupBucketsReady condition on the Seed will be set to False, and consequently the Seed is considered as NotReady. If the SeedBackupBucketsCheckControllerConfiguration (which is part of gardener-controller-managers component configuration) contains a conditionThreshold for the BackupBucketsReady, the condition will instead first be set to Progressing and eventually to False once the conditionThreshold expires. See the example config file for details. Once the BackupBucket is healthy again, the seed will be re-queued and the condition will turn true.
"Extensions Check" Reconciler
This reconciler reconciles Seed objects and checks whether all ControllerInstallations referencing them are in a healthy state. Concretely, all three conditions Valid, Installed, and Healthy must have status True and the Progressing condition must have status False. Based on this check, it maintains the ExtensionsReady condition in the respective Seed's .status.conditions list.
"Reference" Reconciler
Seed objects may specify references to other objects in the garden namespace in the garden cluster which are required for certain features. For example, operators can configure additional data for extensions via .spec.resources[]. Such objects need a special protection against deletion requests as long as they are still being referenced by one or multiple seeds.
Therefore, this reconciler checks Seeds for referenced objects and adds the finalizer gardener.cloud/reference-protection to their .metadata.finalizers list. The reconciled Seed also gets this finalizer to enable a proper garbage collection in case the gardener-controller-manager is offline at the moment of an incoming deletion request. When an object is not actively referenced anymore because the Seed specification has changed or all related seeds were deleted (are in deletion), the controller will remove the added finalizer again so that the object can safely be deleted or garbage collected.
This reconciler inspects the following references:
Secrets andConfigMaps from.spec.resources[]
The checks naturally grow with the number of references that are added to the Seed specification.
Shoot Controller
"Conditions" Reconciler
In case the reconciled Shoot is registered via a ManagedSeed as a seed cluster, this reconciler merges the conditions in the respective Seed's .status.conditions into the .status.conditions of the Shoot. This is to provide a holistic view on the status of the registered seed cluster by just looking at the Shoot resource.
"Hibernation" Reconciler
This reconciler is responsible for hibernating or awakening shoot clusters based on the schedules defined in their .spec.hibernation.schedules. It ignores failed Shoots and those marked for deletion.
"Maintenance" Reconciler
This reconciler is responsible for maintaining shoot clusters based on the time window defined in their .spec.maintenance.timeWindow. It might auto-update the Kubernetes version or the operating system versions specified in the worker pools (.spec.provider.workers). It could also add some operation or task annotations. For more information, see Shoot Maintenance.
"Quota" Reconciler
This reconciler might auto-delete shoot clusters in case their referenced SecretBinding or CredentialsBinding is itself referencing a Quota with .spec.clusterLifetimeDays != nil. If the shoot cluster is older than the configured lifetime, then it gets deleted. It maintains the expiration time of the Shoot in the value of the shoot.gardener.cloud/expiration-timestamp annotation. This annotation might be overridden, however only by at most twice the value of the .spec.clusterLifetimeDays.
"Reference" Reconciler
Shoot objects may specify references to other objects in the garden cluster which are required for certain features. For example, users can configure various DNS providers via .spec.dns.providers and usually need to refer to a corresponding Secret with valid DNS provider credentials inside. Such objects need a special protection against deletion requests as long as they are still being referenced by one or multiple shoots.
Therefore, this reconciler checks Shoots for referenced objects and adds the finalizer gardener.cloud/reference-protection to their .metadata.finalizers list. The reconciled Shoot also gets this finalizer to enable a proper garbage collection in case the gardener-controller-manager is offline at the moment of an incoming deletion request. When an object is not actively referenced anymore because the Shoot specification has changed or all related shoots were deleted (are in deletion), the controller will remove the added finalizer again so that the object can safely be deleted or garbage collected.
This reconciler inspects the following references:
- Admission plugin kubeconfig
Secrets (.spec.kubernetes.kubeAPIServer.admissionPlugins[].kubeconfigSecretName) - Audit policy
ConfigMaps (.spec.kubernetes.kubeAPIServer.auditConfig.auditPolicy.configMapRef) - DNS provider
Secrets (.spec.dns.providers[].secretName) - Structured authentication
ConfigMaps (.spec.kubernetes.kubeAPIServer.structuredAuthentication.configMapName) - Structured authorization
ConfigMaps (.spec.kubernetes.kubeAPIServer.structuredAuthorization.configMapName) - Structured authorization kubeconfig
Secrets (.spec.kubernetes.kubeAPIServer.structuredAuthorization.kubeconfigs[].secretName) Secrets andConfigMaps from.spec.resources[]
The checks naturally grow with the number of references that are added to the Shoot specification.
"Retry" Reconciler
This reconciler is responsible for retrying certain failed Shoots. Currently, the reconciler retries only failed Shoots with an error code ERR_INFRA_RATE_LIMITS_EXCEEDED. See Shoot Status for more details.
"Status Label" Reconciler
This reconciler is responsible for maintaining the shoot.gardener.cloud/status label on Shoots. See Shoot Status for more details.
"Migration" Reconciler
This reconciler is triggered for Shoots currently in migration (i.e., .spec.seedName != .status.seedName). It maintains the ReadyForMigration constraint in the .status.constraints[] list. A Shoot is considered ready for migration if the destination Seed is up-to-date and healthy.
The main purpose of this constraint is to allow the gardenlet running in the source seed cluster to check if it can start with the migration flow without that it needs to directly read the destination Seed resource (for which it won't have permissions).
"ShootState Finalizer" Reconciler
This reconciler is responsible for managing a finalizer (core.gardener.cloud/shootstate) on a ShootState. The finalizer ensures the ShootState will exist during migration of Shoot's control plane to another Seed.
The ShootState has to be present until the Migrate and Restore operations finish successfully. Otherwise, in corner cases of prior deletion, subsequent Restore operations of the Shoot will fail due to the missing ShootState resource.