Skip to content

Commit

Permalink
Enable leader election for admission controller
Browse files Browse the repository at this point in the history
Since admission controllers now run the certificate controller, leader election must be enabled to prevent any interference.
  • Loading branch information
timuthy committed Jan 5, 2024
1 parent a34b517 commit 1a2b35c
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ app.kubernetes.io/instance: {{ .Release.Name }}
{{- printf "%s:%s" .repository .tag }}
{{- end }}
{{- end }}

{{- define "leaderelectionid" -}}
gardener-extension-admission-calico
{{- end -}}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ spec:
- --kubeconfig={{ required ".Values.global.projectedKubeconfig.baseMountPath is required" .Values.global.projectedKubeconfig.baseMountPath }}/kubeconfig
{{- end }}
- --health-bind-address=:{{ .Values.global.healthPort }}
- --leader-election-id={{ include "leaderelectionid" . }}
{{- if .Values.global.virtualGarden.enabled }}
env:
- name: SOURCE_CLUSTER
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,32 @@ rules:
- update
- patch
- delete
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- create
- list
- watch
- apiGroups:
- coordination.k8s.io
resources:
- leases
resourceNames:
- {{ include "leaderelectionid" . }}
verbs:
- update
- get
- apiGroups:
- ""
- events.k8s.io
resources:
- events
verbs:
- create
- patch
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
Expand Down
56 changes: 38 additions & 18 deletions cmd/gardener-extension-admission-calico/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,14 @@ import (
gardenerhealthz "github.com/gardener/gardener/pkg/healthz"
"github.com/gardener/gardener/pkg/logger"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
componentbaseconfig "k8s.io/component-base/config"
"k8s.io/component-base/version"
"k8s.io/component-base/version/verflag"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/cluster"
"sigs.k8s.io/controller-runtime/pkg/healthz"
logf "sigs.k8s.io/controller-runtime/pkg/log"
Expand All @@ -50,17 +53,20 @@ func NewControllerManagerCommand(ctx context.Context) *cobra.Command {
var (
restOpts = &controllercmd.RESTOptions{}
mgrOpts = &controllercmd.ManagerOptions{
WebhookServerPort: 443,
HealthBindAddress: ":8081",
WebhookCertDir: "/tmp/admission-calico-cert",
LeaderElection: true,
LeaderElectionID: controllercmd.LeaderElectionNameID(Name),
LeaderElectionNamespace: os.Getenv("LEADER_ELECTION_NAMESPACE"),
WebhookServerPort: 443,
HealthBindAddress: ":8081",
WebhookCertDir: "/tmp/admission-calico-cert",
}
// options for the webhook server
webhookServerOptions = &webhookcmd.ServerOptions{
Namespace: os.Getenv("WEBHOOK_CONFIG_NAMESPACE"),
}
webhookSwitches = admissioncmd.GardenWebhookSwitchOptions()
webhookOptions = webhookcmd.NewAddToManagerOptions(
"admission-calico",
Name,
"",
nil,
webhookServerOptions,
Expand Down Expand Up @@ -96,32 +102,46 @@ func NewControllerManagerCommand(ctx context.Context) *cobra.Command {
Burst: 130,
}, restOpts.Completed().Config)

mgr, err := manager.New(restOpts.Completed().Config, mgrOpts.Completed().Options())
if err != nil {
return fmt.Errorf("could not instantiate manager: %w", err)
}

install.Install(mgr.GetScheme())

if err := calicoinstall.AddToScheme(mgr.GetScheme()); err != nil {
return fmt.Errorf("could not update manager scheme: %w", err)
}
managerOptions := mgrOpts.Completed().Options()

// Operators can enable the source cluster option via SOURCE_CLUSTER environment variable.
// In-cluster config will be used if no SOURCE_KUBECONFIG is specified.
//
// The source cluster is for instance used by Gardener's certificate controller, to maintain certificate
// secrets in a different cluster ('runtime-garden') than the cluster where the webhook configurations
// are maintained ('virtual-garden').
var sourceCluster cluster.Cluster
var sourceClusterConfig *rest.Config
if sourceClusterEnabled := os.Getenv("SOURCE_CLUSTER"); sourceClusterEnabled != "" {
log.Info("Configuring source cluster option")
config, err := clientcmd.BuildConfigFromFlags("", os.Getenv("SOURCE_KUBECONFIG"))
var err error
sourceClusterConfig, err = clientcmd.BuildConfigFromFlags("", os.Getenv("SOURCE_KUBECONFIG"))
if err != nil {
return err
}
managerOptions.LeaderElectionConfig = sourceClusterConfig
} else {
// Restrict the cache for secrets to the configured namespace to avoid the need for cluster-wide list/watch permissions.
managerOptions.Cache = cache.Options{
ByObject: map[client.Object]cache.ByObject{
&corev1.Secret{}: {Namespaces: map[string]cache.Config{webhookOptions.Server.Completed().Namespace: {}}},
},
}
}

sourceCluster, err = cluster.New(config, func(opts *cluster.Options) {
mgr, err := manager.New(restOpts.Completed().Config, managerOptions)
if err != nil {
return fmt.Errorf("could not instantiate manager: %w", err)
}

install.Install(mgr.GetScheme())

if err := calicoinstall.AddToScheme(mgr.GetScheme()); err != nil {
return fmt.Errorf("could not update manager scheme: %w", err)
}

var sourceCluster cluster.Cluster
if sourceClusterConfig != nil {
log.Info("Configuring source cluster option")
sourceCluster, err = cluster.New(sourceClusterConfig, func(opts *cluster.Options) {
opts.Logger = log
opts.Cache.DefaultNamespaces = map[string]cache.Config{v1beta1constants.GardenNamespace: {}}
})
Expand Down

0 comments on commit 1a2b35c

Please sign in to comment.