diff --git a/chart/templates/clusterrole.yaml b/chart/templates/clusterrole.yaml index f54b56b..a24da84 100644 --- a/chart/templates/clusterrole.yaml +++ b/chart/templates/clusterrole.yaml @@ -11,5 +11,5 @@ rules: verbs: [ "get" ] - apiGroups: [ "coordination.k8s.io" ] resources: [ "leases" ] - verbs: [ "create", "get", "delete" ] + verbs: [ "create", "delete", "get" ] {{- end }} diff --git a/chart/templates/daemonset.yaml b/chart/templates/daemonset.yaml index 9287b7f..8d11e50 100644 --- a/chart/templates/daemonset.yaml +++ b/chart/templates/daemonset.yaml @@ -8,6 +8,10 @@ spec: selector: matchLabels: app.kubernetes.io/name: {{ include "kubeip.name" . }} + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 template: metadata: labels: @@ -20,6 +24,11 @@ spec: {{- if .Values.daemonSet.nodeSelector }} {{- toYaml .Values.daemonSet.nodeSelector | nindent 8 }} {{- end }} + tolerations: + - operator: "Exists" + effect: "NoSchedule" + - operator: "Exists" + effect: "NoExecute" containers: - name: kubeip image: "{{ .Values.image.repository }}" diff --git a/chart/values.yaml b/chart/values.yaml index cd96d49..08dca3c 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -17,10 +17,10 @@ serviceAccount: name: kubeip-service-account annotations: gcpServiceAccountEmail: kubeip-service-account@workload-id-117715.iam.gserviceaccount.com -# annotations: -# awsRoleArn: "your-aws-role-arn" -# gcpServiceAccountEmail: "your-google-service-account-email" - + # annotations: + # awsRoleArn: "your-aws-role-arn" + # gcpServiceAccountEmail: "your-google-service-account-email" + # Role-Based Access Control (RBAC) configuration. rbac: @@ -40,3 +40,7 @@ daemonSet: resources: requests: cpu: 100m + memory: 64Mi + limits: + cpu: 100m + memory: 128Mi diff --git a/cmd/main.go b/cmd/main.go index 98e4b96..3256a14 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -139,6 +139,7 @@ func assignAddress(c context.Context, log *logrus.Entry, client kubernetes.Inter func run(c context.Context, log *logrus.Entry, cfg *config.Config) error { ctx, cancel := context.WithCancel(c) defer cancel() + // add debug mode to context if cfg.DevelopMode { ctx = context.WithValue(ctx, developModeKey, true) @@ -167,43 +168,37 @@ func run(c context.Context, log *logrus.Entry, cfg *config.Config) error { if err != nil { return errors.Wrap(err, "initializing assigner") } - // assign static public IP address - errorCh := make(chan error, 1) // buffered channel to avoid goroutine leak - go func() { - defer close(errorCh) // close the channel when the goroutine exits to avoid goroutine leak - e := assignAddress(ctx, log, clientset, assigner, n, cfg) - if e != nil { - errorCh <- e - } - }() - for { - select { - case err = <-errorCh: - if err != nil { - return errors.Wrap(err, "assigning static public IP address") - } - case <-ctx.Done(): - log.Infof("kubeip agent gracefully stopped") - if cfg.ReleaseOnExit { - log.Infof("releasing static public IP address") - err = func() error { - releaseCtx, releaseCancel := context.WithTimeout(context.Background(), unassignTimeout) // release the static public IP address within 5 minutes - defer releaseCancel() - // use a different context for releasing the static public IP address since the main context is canceled - if err = assigner.Unassign(releaseCtx, n.Instance, n.Zone); err != nil { - return errors.Wrap(err, "failed to release static public IP address") - } - return nil - }() - if err != nil { - return err //nolint:wrapcheck - } - log.Infof("static public IP address released") - } - return nil + err = assignAddress(ctx, log, clientset, assigner, n, cfg) + if err != nil { + return errors.Wrap(err, "assigning static public IP address") + } + + // pause the agent to prevent it from exiting immediately after assigning the static public IP address + // wait for the context to be done: SIGTERM, SIGINT + <-ctx.Done() + log.Infof("shutting down kubeip agent") + + // release the static public IP address on exit + if cfg.ReleaseOnExit { + log.Infof("releasing static public IP address") + if releaseErr := releaseIP(assigner, n); releaseErr != nil { //nolint:contextcheck + return releaseErr } + log.Infof("static public IP address released") } + return nil +} + +func releaseIP(assigner address.Assigner, n *types.Node) error { + releaseCtx, releaseCancel := context.WithTimeout(context.Background(), unassignTimeout) + defer releaseCancel() + + if err := assigner.Unassign(releaseCtx, n.Instance, n.Zone); err != nil { + return errors.Wrap(err, "failed to release static public IP address") + } + + return nil } func runCmd(c *cli.Context) error { @@ -213,7 +208,8 @@ func runCmd(c *cli.Context) error { cfg := config.NewConfig(c) if err := run(ctx, log, cfg); err != nil { - log.Fatalf("eks-lens agent failed: %v", err) + log.WithError(err).Error("error running kubeip agent") + return err } return nil diff --git a/examples/aws/eks.tf b/examples/aws/eks.tf index f3aa18a..eaa7432 100644 --- a/examples/aws/eks.tf +++ b/examples/aws/eks.tf @@ -260,7 +260,8 @@ resource "kubernetes_daemonset" "kubeip_daemonset" { } resources { requests = { - cpu = "100m" + cpu = "10m" + memory = "32Mi" } } } diff --git a/examples/gcp/gke.tf b/examples/gcp/gke.tf index a6a12b0..0b37eaf 100644 --- a/examples/gcp/gke.tf +++ b/examples/gcp/gke.tf @@ -336,7 +336,8 @@ resource "kubernetes_daemonset" "kubeip_daemonset" { } resources { requests = { - cpu = "100m" + cpu = "10m" + memory = "32Mi" } } }