Skip to content

Commit

Permalink
fix webhook ha
Browse files Browse the repository at this point in the history
  • Loading branch information
aleoli authored and adamjensenbot committed Oct 17, 2024
1 parent a087118 commit f380966
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 11 deletions.
8 changes: 5 additions & 3 deletions cmd/ipam/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,11 @@ func run(_ *cobra.Command, _ []string) error {

// Else, initialize the leader election mechanism to manage multiple replicas of the IPAM server running in active-passive mode.
leaderelectionOpts := &leaderelection.Opts{
PodName: os.Getenv("POD_NAME"),
Namespace: podNamespace,
DeploymentName: ptr.To(os.Getenv("DEPLOYMENT_NAME")),
PodInfo: leaderelection.PodInfo{
PodName: os.Getenv("POD_NAME"),
Namespace: podNamespace,
DeploymentName: ptr.To(os.Getenv("DEPLOYMENT_NAME")),
},
LeaderElectorName: leaderElectorName,
LeaseDuration: options.LeaseDuration,
RenewDeadline: options.LeaseRenewDeadline,
Expand Down
6 changes: 4 additions & 2 deletions cmd/virtual-kubelet/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,10 @@ func runRootCommand(ctx context.Context, c *Opts) error {
// The leader election avoids that multiple virtual node targeting the same cluster reflect some resources.
if c.VirtualKubeletLeaseEnabled {
leaderelectionOpts := &leaderelection.Opts{
PodName: c.PodName,
Namespace: c.TenantNamespace,
PodInfo: leaderelection.PodInfo{
PodName: c.PodName,
Namespace: c.TenantNamespace,
},
LeaderElectorName: leaderElectorName,
LeaseDuration: c.VirtualKubeletLeaseLeaseDuration,
RenewDeadline: c.VirtualKubeletLeaseRenewDeadline,
Expand Down
10 changes: 10 additions & 0 deletions cmd/webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/tools/leaderelection/resourcelock"
"k8s.io/klog/v2"
"k8s.io/utils/ptr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log"
Expand All @@ -39,6 +40,7 @@ import (
networkingv1beta1 "github.com/liqotech/liqo/apis/networking/v1beta1"
offloadingv1beta1 "github.com/liqotech/liqo/apis/offloading/v1beta1"
"github.com/liqotech/liqo/pkg/consts"
"github.com/liqotech/liqo/pkg/leaderelection"
argsutils "github.com/liqotech/liqo/pkg/utils/args"
flagsutils "github.com/liqotech/liqo/pkg/utils/flags"
"github.com/liqotech/liqo/pkg/utils/indexer"
Expand Down Expand Up @@ -167,6 +169,14 @@ func main() {
mgr.GetWebhookServer().Register("/mutate/firewallconfigurations", fwcfgwh.NewMutator())
mgr.GetWebhookServer().Register("/validate/routeconfigurations", routecfgwh.NewValidator(mgr.GetClient()))

if leaderElection != nil && *leaderElection {
leaderelection.LabelerOnElection(ctx, mgr, &leaderelection.PodInfo{
PodName: os.Getenv("POD_NAME"),
Namespace: os.Getenv("POD_NAMESPACE"),
DeploymentName: ptr.To(os.Getenv("DEPLOYMENT_NAME")),
})
}

// Start the manager.
klog.Info("starting webhooks manager")
if err := mgr.Start(ctx); err != nil {
Expand Down
24 changes: 24 additions & 0 deletions deployments/liqo/files/liqo-webhook-ClusterRole.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
rules:
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- ""
resources:
- namespaces
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- patch
- update
- watch
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- list
- watch
- apiGroups:
- authentication.liqo.io
Expand Down
6 changes: 6 additions & 0 deletions deployments/liqo/templates/liqo-webhook-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ metadata:
spec:
selector:
{{- include "liqo.selectorLabels" $webhookConfig | nindent 4 }}
{{- if gt .Values.webhook.replicas 1.0 }}
leaderelection.liqo.io/leader: "true"
{{- end }}
type: ClusterIP
ports:
- port: {{ .Values.webhook.port }}
Expand All @@ -34,6 +37,9 @@ metadata:
spec:
selector:
{{- include "liqo.selectorLabels" $webhookConfig | nindent 4 }}
{{- if gt .Values.webhook.replicas 1.0 }}
leaderelection.liqo.io/leader: "true"
{{- end }}
ports:
- name: metrics
port: 8080
Expand Down
6 changes: 6 additions & 0 deletions deployments/liqo/templates/liqo-webook-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,16 @@ spec:
configMapKeyRef:
name: {{ include "liqo.clusterIdConfig" . }}
key: CLUSTER_ID
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: DEPLOYMENT_NAME
value: {{ include "liqo.prefixedName" $webhookConfig }}
resources: {{- toYaml .Values.webhook.pod.resources | nindent 10 }}
volumeMounts:
- name: webhook-certs
Expand Down
16 changes: 16 additions & 0 deletions pkg/leaderelection/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2019-2024 The Liqo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package leaderelection contains the leader election mechanism.
package leaderelection
59 changes: 59 additions & 0 deletions pkg/leaderelection/labeler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2019-2024 The Liqo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package leaderelection

import (
"context"
"os"

"k8s.io/client-go/util/retry"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/manager"
)

// LabelerOnElection is a function that labels the leader pod with the leader label.
func LabelerOnElection(ctx context.Context, mgr manager.Manager, info *PodInfo) {
go func() {
select {
case <-ctx.Done():
return
case <-mgr.Elected():
}

if info.DeploymentName == nil {
return
}

maxRetries := 10
cl := mgr.GetClient()

if err := retry.OnError(retry.DefaultBackoff, func(_ error) bool {
if maxRetries == 0 {
return false
}
maxRetries--
return true
}, func() error {
if err := handleLeaderLabelWithClient(ctx, cl, info); err != nil {
klog.Error(err, "retrying...")
return err
}
return nil
}); err != nil {
klog.Error(err)
os.Exit(1)
}
}()
}
20 changes: 15 additions & 5 deletions pkg/leaderelection/leaderelection.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,16 @@ var (
}
)

// PodInfo contains the information about the pod.
type PodInfo struct {
PodName string
Namespace string
DeploymentName *string
}

// Opts contains the options to configure the leader election mechanism.
type Opts struct {
PodName string
Namespace string
DeploymentName *string
PodInfo
LeaderElectorName string
LeaseDuration time.Duration
RenewDeadline time.Duration
Expand Down Expand Up @@ -92,7 +97,7 @@ func Init(opts *Opts, rc *rest.Config, eb record.EventBroadcaster) (*leaderelect
defer lock.Unlock()
klog.Infof("Leader election: this pod is the leader")
if opts.LabelLeader {
if err := handleLeaderLabel(ctx, rc, scheme, opts); err != nil {
if err := handleLeaderLabel(ctx, rc, scheme, &opts.PodInfo); err != nil {
klog.Errorf("Leader election: unable to handle labeling of leader: %s", err)
os.Exit(1)
}
Expand Down Expand Up @@ -146,7 +151,7 @@ func IsLeader() bool {
}

// handleLeaderLabel labels the current pod as leader and unlabels eventual old leader.
func handleLeaderLabel(ctx context.Context, rc *rest.Config, scheme *runtime.Scheme, opts *Opts) error {
func handleLeaderLabel(ctx context.Context, rc *rest.Config, scheme *runtime.Scheme, opts *PodInfo) error {
klog.Infof("Leader election: labeling this pod as leader and unlabeling eventual old leader")
if opts.DeploymentName == nil {
return fmt.Errorf("deployment name not specified")
Expand All @@ -157,6 +162,11 @@ func handleLeaderLabel(ctx context.Context, rc *rest.Config, scheme *runtime.Sch
return fmt.Errorf("unable to create client: %w", err)
}

return handleLeaderLabelWithClient(ctx, cl, opts)
}

// handleLeaderLabelWithClient labels the current pod as leader and unlabels eventual old leader using the given client.
func handleLeaderLabelWithClient(ctx context.Context, cl client.Client, opts *PodInfo) error {
var deployment appsv1.Deployment
if err := cl.Get(ctx, client.ObjectKey{
Namespace: opts.Namespace,
Expand Down
5 changes: 4 additions & 1 deletion pkg/webhooks/utils/permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// package utils contains the utility functions used by the webhooks and permissions.
// Package utils contains the utility functions used by the webhooks and permissions.
package utils

// +kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=core,resources=events,verbs=create;patch
// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch
// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;update;patch

0 comments on commit f380966

Please sign in to comment.