diff --git a/AGENTS.md b/AGENTS.md index 0c12685..d8dcff3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,5 +10,23 @@ I have a DNS rewrite pointing *.internal to 10.0.1.250 which is traefik-internal /dogstore/ is a NFS path that's available to all nodes - secrets are managed by sops + +## Load balancers + +Two LB implementations coexist: k3s klipper (servicelb) and MetalLB. They are +separated by `loadBalancerClass` so they don't conflict. + +- **klipper** handles services with NO `loadBalancerClass`. It creates svclb + DaemonSet pods that bind host ports directly on every node. +- **MetalLB** handles services with `loadBalancerClass: metallb`. Its pool has + `autoAssign: false`, so it only assigns IPs to services that explicitly + request a pool via the `metallb.io/address-pool` annotation. + +| Service | loadBalancerClass | LB | External IPs | +|------------------|-------------------|----------|-------------------------| +| traefik | (none) | klipper | node IPs (10.0.1.2 etc) | +| traefik-internal | metallb | MetalLB | 10.0.1.250 | + +`loadBalancerClass` is immutable on k8s Services. Changing it requires deleting +the Service first, then redeploying (`kubectl delete svc … && helm upgrade`). diff --git a/charts/metallb/templates/pool.yaml b/charts/metallb/templates/pool.yaml index 8f242ec..01b3e06 100644 --- a/charts/metallb/templates/pool.yaml +++ b/charts/metallb/templates/pool.yaml @@ -4,6 +4,7 @@ kind: IPAddressPool metadata: name: {{ .Values.pool.name }} spec: + autoAssign: false addresses: {{- range .Values.pool.addresses }} - {{ . }} diff --git a/charts/metallb/values.yaml b/charts/metallb/values.yaml index 4f21204..db26c20 100644 --- a/charts/metallb/values.yaml +++ b/charts/metallb/values.yaml @@ -1,4 +1,5 @@ metallb: + loadBalancerClass: metallb controller: nodeSelector: node-role.kubernetes.io/control-plane: "true" @@ -7,7 +8,7 @@ metallb: effect: NoSchedule pool: - enabled: false + enabled: true name: internal addresses: - "10.0.1.250-10.0.1.250" diff --git a/charts/traefik-config/templates/helmchartconfig.yaml b/charts/traefik-config/templates/traefik-config.yaml similarity index 67% rename from charts/traefik-config/templates/helmchartconfig.yaml rename to charts/traefik-config/templates/traefik-config.yaml index 95a0653..1f5340a 100644 --- a/charts/traefik-config/templates/helmchartconfig.yaml +++ b/charts/traefik-config/templates/traefik-config.yaml @@ -5,9 +5,11 @@ metadata: namespace: kube-system spec: valuesContent: |- - service: - spec: - loadBalancerClass: io.k3s.klipper + nodeSelector: + node-role.kubernetes.io/control-plane: "true" + tolerations: + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule logs: general: level: WARN @@ -35,7 +37,12 @@ spec: secretKeyRef: name: {{ .Values.cloudflare.secretName }} key: {{ .Values.cloudflare.secretKey }} - persistence: - enabled: true - storageClass: longhorn - size: 128Mi + deployment: + additionalVolumes: + - name: acme + hostPath: + path: /dogstore/service-data/.letsencrypt + type: DirectoryOrCreate + additionalVolumeMounts: + - name: acme + mountPath: /letsencrypt diff --git a/charts/traefik-config/values.yaml b/charts/traefik-config/values.yaml index fc650ed..6676228 100644 --- a/charts/traefik-config/values.yaml +++ b/charts/traefik-config/values.yaml @@ -9,4 +9,4 @@ cloudflare: secretKey: CF_DNS_API_TOKEN letsencrypt: - storagePath: /data/acme.json + storagePath: /letsencrypt/acme.json diff --git a/charts/traefik-internal/templates/traefik-internal.yaml b/charts/traefik-internal/templates/traefik-internal.yaml index 0cc5f3c..0cbe49f 100644 --- a/charts/traefik-internal/templates/traefik-internal.yaml +++ b/charts/traefik-internal/templates/traefik-internal.yaml @@ -82,6 +82,7 @@ metadata: metallb.io/address-pool: internal spec: type: LoadBalancer + loadBalancerClass: metallb loadBalancerIP: {{ .Values.loadBalancerIP }} selector: app: traefik-internal