From e8b4e3306cbd467e06670bbfd6b74fb703a23021 Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Sun, 7 Jan 2024 15:40:27 -0600 Subject: [PATCH] Support specifying an alternate number of replicas for cloudflared Cloudflared should [support HA configurations out of the box](https://blog.cloudflare.com/highly-available-and-highly-scalable-cloudflare-tunnels/) with no extra work from the controller. This also means it should be possible to support a DaemonSet option for cloudflared. --- .../main.go | 22 +++++++++++++------ .../templates/deployment.yaml | 1 + .../values.yaml | 3 +++ .../controlled-cloudflared-connector.go | 8 +++---- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/cmd/cloudflare-tunnel-ingress-controller/main.go b/cmd/cloudflare-tunnel-ingress-controller/main.go index 750bdb1..a6db248 100644 --- a/cmd/cloudflare-tunnel-ingress-controller/main.go +++ b/cmd/cloudflare-tunnel-ingress-controller/main.go @@ -21,12 +21,13 @@ type rootCmdFlags struct { // for annotation on Ingress ingressClass string // for IngressClass.spec.controller - controllerClass string - logLevel int - cloudflareAPIToken string - cloudflareAccountId string - cloudflareTunnelName string - namespace string + controllerClass string + logLevel int + cloudflareAPIToken string + cloudflareAccountId string + cloudflareTunnelName string + namespace string + cloudflaredReplicaCount int32 } func main() { @@ -99,7 +100,13 @@ func main() { case <-done: return case _ = <-ticker.C: - err := controller.CreateControlledCloudflaredIfNotExist(ctx, mgr.GetClient(), tunnelClient, options.namespace) + err := controller.CreateControlledCloudflaredIfNotExist( + ctx, + mgr.GetClient(), + tunnelClient, + options.namespace, + options.cloudflaredReplicaCount, + ) if err != nil { logger.WithName("controlled-cloudflared").Error(err, "create controlled cloudflared") } @@ -119,6 +126,7 @@ func main() { rootCommand.PersistentFlags().StringVar(&options.cloudflareAccountId, "cloudflare-account-id", options.cloudflareAccountId, "cloudflare account id") rootCommand.PersistentFlags().StringVar(&options.cloudflareTunnelName, "cloudflare-tunnel-name", options.cloudflareTunnelName, "cloudflare tunnel name") rootCommand.PersistentFlags().StringVar(&options.namespace, "namespace", options.namespace, "namespace to execute cloudflared connector") + rootCommand.PersistentFlags().Int32Var(&options.cloudflaredReplicaCount, "cloudflared-replica-count", options.cloudflaredReplicaCount, "namespace to execute cloudflared connector") err := rootCommand.Execute() if err != nil { diff --git a/helm/cloudflare-tunnel-ingress-controller/templates/deployment.yaml b/helm/cloudflare-tunnel-ingress-controller/templates/deployment.yaml index 1bc38fa..31c33f5 100644 --- a/helm/cloudflare-tunnel-ingress-controller/templates/deployment.yaml +++ b/helm/cloudflare-tunnel-ingress-controller/templates/deployment.yaml @@ -39,6 +39,7 @@ spec: - --cloudflare-account-id=$(CLOUDFLARE_ACCOUNT_ID) - --cloudflare-tunnel-name=$(CLOUDFLARE_TUNNEL_NAME) - --namespace=$(NAMESPACE) + - --cloudflared-replica-count={{ .Values.cloudflared.replicaCount }} env: - name: CLOUDFLARE_API_TOKEN valueFrom: diff --git a/helm/cloudflare-tunnel-ingress-controller/values.yaml b/helm/cloudflare-tunnel-ingress-controller/values.yaml index c3475b5..04e6b78 100644 --- a/helm/cloudflare-tunnel-ingress-controller/values.yaml +++ b/helm/cloudflare-tunnel-ingress-controller/values.yaml @@ -21,6 +21,9 @@ ingressClass: replicaCount: 1 +cloudflared: + replicaCount: 1 + image: repository: ghcr.io/strrl/cloudflare-tunnel-ingress-controller pullPolicy: IfNotPresent diff --git a/pkg/controller/controlled-cloudflared-connector.go b/pkg/controller/controlled-cloudflared-connector.go index 123b503..8e5feb9 100644 --- a/pkg/controller/controlled-cloudflared-connector.go +++ b/pkg/controller/controlled-cloudflared-connector.go @@ -9,7 +9,6 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -18,6 +17,7 @@ func CreateControlledCloudflaredIfNotExist( kubeClient client.Client, tunnelClient *cloudflarecontroller.TunnelClient, namespace string, + replicas int32, ) error { list := appsv1.DeploymentList{} err := kubeClient.List(ctx, &list, &client.ListOptions{ @@ -39,7 +39,7 @@ func CreateControlledCloudflaredIfNotExist( return errors.Wrap(err, "fetch tunnel token") } - deployment := cloudflaredConnectDeploymentTemplating(token, namespace) + deployment := cloudflaredConnectDeploymentTemplating(token, namespace, replicas) err = kubeClient.Create(ctx, deployment) if err != nil { return errors.Wrap(err, "create controlled-cloudflared-connector deployment") @@ -47,7 +47,7 @@ func CreateControlledCloudflaredIfNotExist( return nil } -func cloudflaredConnectDeploymentTemplating(token string, namespace string) *appsv1.Deployment { +func cloudflaredConnectDeploymentTemplating(token string, namespace string, replicas int32) *appsv1.Deployment { appName := "controlled-cloudflared-connector" return &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ @@ -59,7 +59,7 @@ func cloudflaredConnectDeploymentTemplating(token string, namespace string) *app }, }, Spec: appsv1.DeploymentSpec{ - Replicas: pointer.Int32(1), + Replicas: &replicas, Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{ "app": appName,