From 29bea2491bb65f0b1a93240c5c0327e9fe394bb7 Mon Sep 17 00:00:00 2001 From: Sam Day Date: Fri, 1 May 2026 15:28:47 +1000 Subject: [PATCH 1/3] k8s-control-plane: resolve advertised hostname --- .../templates/apiserver/advertise-address.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/charts/k8s-control-plane/templates/apiserver/advertise-address.yaml b/charts/k8s-control-plane/templates/apiserver/advertise-address.yaml index 0e7d8ebe..0ce7bacc 100644 --- a/charts/k8s-control-plane/templates/apiserver/advertise-address.yaml +++ b/charts/k8s-control-plane/templates/apiserver/advertise-address.yaml @@ -15,7 +15,13 @@ spec: - pipefail - -c - | + {{- if $.Values.externalHostname }} + until ip=$(getent ahostsv4 {{ $.Values.externalHostname | quote }} | awk '{print $1; exit}') && [[ -n "$ip" ]]; do + sleep 5 + done + {{- else }} ip=$(kubectl get svc apiserver -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + {{- end }} kubectl create configmap advertise-address --from-literal=value="$ip" --dry-run=client --output yaml \ | kubectl apply -f- kubectl patch cert apiserver --type merge -p "{\"spec\":{\"ipAddresses\":[\"$ip\",\"{{ $.Values.serviceIP }}\"]}}" From af8558e6b863e3abfed97c2c1750cd618482dfbc Mon Sep 17 00:00:00 2001 From: Sam Day Date: Fri, 1 May 2026 15:28:47 +1000 Subject: [PATCH 2/3] node-joiner: join nodes by declared name --- apps/node-joiner/join.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/node-joiner/join.sh b/apps/node-joiner/join.sh index c50c8da5..2c227623 100755 --- a/apps/node-joiner/join.sh +++ b/apps/node-joiner/join.sh @@ -24,7 +24,7 @@ APISERVER_HOST=${APISERVER_URL%%:*} sshpass -p "$NODE_PASSWORD" ssh $SSH_OPTS "root@$NODE_IP" bash -s <&1 -set -uxo pipefail +set -euo pipefail # cloud-init exits 2 on "recoverable error" for cosmetic module warnings, # which Ubuntu 24.04 reliably trips. Treat any exit as "wait complete". cloud-init status --wait || true @@ -38,5 +38,5 @@ tailscale up --accept-routes --login-server=${HEADSCALE_URL} --auth-key=${TS_AUT APISERVER_IP=\$(getent hosts ${APISERVER_HOST} | awk '{print \$1; exit}') echo "\${APISERVER_IP} ${APISERVER_HOST}" >> /etc/hosts -kubeadm join ${APISERVER_URL} --token ${BOOTSTRAP_TOKEN} --discovery-token-ca-cert-hash sha256:${CA_HASH} +kubeadm join ${APISERVER_URL} --node-name ${NODE_NAME} --token ${BOOTSTRAP_TOKEN} --discovery-token-ca-cert-hash sha256:${CA_HASH} EOF From c95247977d9bb35f305e5e5aaef11d7aa2b1f0b2 Mon Sep 17 00:00:00 2001 From: Sam Day Date: Fri, 1 May 2026 15:28:47 +1000 Subject: [PATCH 3/3] cloud-cluster: add edge au-east control plane --- .../edge-au-east-apiserver-proxy.yaml | 107 +++++++ .../edge-au-east-control-plane-values.yaml | 47 +++ .../edge-au-east-control-plane.yaml | 37 +++ .../edge-au-east-node-bootstrap-token.yaml | 33 +++ .../edge-au-east-node-joiner.yaml | 274 ++++++++++++++++++ hub/cluster/cloud-cluster/kustomization.yaml | 7 + hub/cluster/headscale/acls.json | 11 + hub/cluster/headscale/main.tf | 42 +++ hub/cluster/headscale/tofu.yaml | 2 + 9 files changed, 560 insertions(+) create mode 100644 hub/cluster/cloud-cluster/edge-au-east-apiserver-proxy.yaml create mode 100644 hub/cluster/cloud-cluster/edge-au-east-control-plane-values.yaml create mode 100644 hub/cluster/cloud-cluster/edge-au-east-control-plane.yaml create mode 100644 hub/cluster/cloud-cluster/edge-au-east-node-bootstrap-token.yaml create mode 100644 hub/cluster/cloud-cluster/edge-au-east-node-joiner.yaml diff --git a/hub/cluster/cloud-cluster/edge-au-east-apiserver-proxy.yaml b/hub/cluster/cloud-cluster/edge-au-east-apiserver-proxy.yaml new file mode 100644 index 00000000..f2e74eb0 --- /dev/null +++ b/hub/cluster/cloud-cluster/edge-au-east-apiserver-proxy.yaml @@ -0,0 +1,107 @@ +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: edge-au-east-apiserver-proxy + namespace: cloud-cluster +spec: + chart: + spec: + chart: charts/resources + reconcileStrategy: Revision + sourceRef: + kind: GitRepository + name: infra + namespace: flux-system + dependsOn: + - name: edge-foundation + driftDetection: + mode: enabled + interval: 1h + kubeConfig: + secretRef: + name: admin-kubeconfig + storageNamespace: edge + targetNamespace: edge + valuesFrom: + - kind: Secret + name: edge-au-east-apiserver-ts-auth + valuesKey: authkey + targetPath: apiserverTsAuth.stringData.authkey + values: + apiserverTsAuth: + kind: Secret + metadata: + name: apiserver-ts-auth + stringData: + authkey: "" + apiserverTsState: + kind: Secret + metadata: + name: apiserver-ts-state + type: Opaque + tsApiserverServiceAccount: + kind: ServiceAccount + metadata: + name: ts-apiserver + tsApiserverRole: + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: ts-apiserver + rules: + - apiGroups: [""] + resourceNames: [apiserver-ts-state] + resources: [secrets] + verbs: [get, update, patch] + tsApiserverRoleBinding: + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: ts-apiserver + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ts-apiserver + subjects: + - kind: ServiceAccount + name: ts-apiserver + tsApiserver: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: ts-apiserver + spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: ts-apiserver + template: + metadata: + labels: + app: ts-apiserver + spec: + serviceAccountName: ts-apiserver + containers: + - name: tailscale + image: ghcr.io/tailscale/tailscale:v1.86.5 + env: + - name: TS_DEST_IP + value: "172.27.23.43" + - name: TS_EXTRA_ARGS + value: --login-server=https://headscale.tail22d0a0.ts.net + - name: TS_HOSTNAME + value: edge-au-east-apiserver + - name: TS_AUTHKEY + valueFrom: + secretKeyRef: + name: apiserver-ts-auth + key: authkey + - name: TS_KUBE_SECRET + value: apiserver-ts-state + - name: TS_USERSPACE + value: "false" + securityContext: + capabilities: + add: [NET_ADMIN] diff --git a/hub/cluster/cloud-cluster/edge-au-east-control-plane-values.yaml b/hub/cluster/cloud-cluster/edge-au-east-control-plane-values.yaml new file mode 100644 index 00000000..b6237f5a --- /dev/null +++ b/hub/cluster/cloud-cluster/edge-au-east-control-plane-values.yaml @@ -0,0 +1,47 @@ +apiServer: + service: + spec: + clusterIP: 172.27.23.43 + type: ClusterIP +bootstrapTokens: + - extraGroups: [system:bootstrappers:kubeadm:default-node-token] + # token ID+secret is set from HelmRelease spec.valuesFrom +clusterCIDRs: [172.24.0.0/16] +clusterDNS: [172.23.0.10] +clusterName: edge-au-east +etcd: + clientSecret: + create: false + name: au-east-apiserver-etcd-client + endpoints: + - https://etcd-0.etcd.etcd.svc:2379 + - https://etcd-1.etcd.etcd.svc:2379 + - https://etcd-2.etcd.etcd.svc:2379 + prefix: /edge:au-east/ +externalHostname: edge-au-east-apiserver.tailnet.hub.samcday.com +konnectivity: + agent: + image: registry.k8s.io/kas-network-proxy/proxy-agent:v0.34.0 + server: + image: registry.k8s.io/kas-network-proxy/proxy-server:v0.34.0 +parentClusterDomain: cluster.local +scheduler: + config: + profiles: + - pluginConfig: + - name: NodeResourcesFit + args: + scoringStrategy: + type: MostAllocated + resources: + - name: cpu + weight: 1 + - name: memory + weight: 100 + deployment: + spec: + replicas: 1 + strategy: + type: Recreate +serviceCIDRs: [172.23.0.0/16] +serviceIP: 172.23.0.1 diff --git a/hub/cluster/cloud-cluster/edge-au-east-control-plane.yaml b/hub/cluster/cloud-cluster/edge-au-east-control-plane.yaml new file mode 100644 index 00000000..aff33cd3 --- /dev/null +++ b/hub/cluster/cloud-cluster/edge-au-east-control-plane.yaml @@ -0,0 +1,37 @@ +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: edge-au-east-control-plane + namespace: cloud-cluster +spec: + chart: + spec: + chart: charts/k8s-control-plane + reconcileStrategy: Revision + sourceRef: + kind: GitRepository + name: infra + namespace: flux-system + dependsOn: + - name: edge-foundation + interval: 1h + kubeConfig: + secretRef: + name: admin-kubeconfig + storageNamespace: edge + targetNamespace: edge + upgrade: + # Jobs in this chart have ttlSecondsAfterFinished and get GC'd between chart + # upgrades; force recreates missing resources instead of failing to patch. + force: true + valuesFrom: + - kind: ConfigMap + name: edge-au-east-control-plane-values + - kind: Secret + name: edge-au-east-node-bootstrap-token + valuesKey: id + targetPath: bootstrapTokens[0].id + - kind: Secret + name: edge-au-east-node-bootstrap-token + valuesKey: secret + targetPath: bootstrapTokens[0].secret diff --git a/hub/cluster/cloud-cluster/edge-au-east-node-bootstrap-token.yaml b/hub/cluster/cloud-cluster/edge-au-east-node-bootstrap-token.yaml new file mode 100644 index 00000000..59cca8cd --- /dev/null +++ b/hub/cluster/cloud-cluster/edge-au-east-node-bootstrap-token.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +kind: Secret +metadata: + name: edge-au-east-node-bootstrap-token + namespace: cloud-cluster +stringData: + id: ENC[AES256_GCM,data:+ZyXTr0S,iv:1MeaBsV9vSi4bjup9TNJIsEHg/F9XbhVG7Kd6/Z7Ubw=,tag:JlF9SQvB2IYAQ8szaK2LvA==,type:str] + secret: ENC[AES256_GCM,data:sd2haB4qgp9zcwGoWRI9lQ==,iv:9rWQDn7ewiJjHIezzvfRqQhI6oWX1JdVF2RPO8WWGQE=,tag:ef+4FOAeWLON3VCF8vK34Q==,type:str] + token: ENC[AES256_GCM,data:GmNgZHQo6cS7I5713AWiIkukMvwHaoY=,iv:plflI1eitJpsRPws3obYW26uESysAG//AI/+wLdPoo8=,tag:xsPte2NtBT/EIVaZS70IaA==,type:str] +sops: + age: + - recipient: age1tu8l2llfk32g0c4mvklqazjkj977h9xwvx3ntwt2ucdert8sufgq2g8mgs + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIYUhEbmIwbHBudi9jQ1kw + ZDdEWUZpWitObVZpUUdNSFloWVFDS0d3N1M4CnB4RmhlOXBYWHErUTVsT3VEd2lh + cVlXbmdrNDBZbVFlOEc0OG91dUEvV2cKLS0tIFN0M1R4T1FqN2MrVE8rZGZhbTlm + b3JIb2t2NG81c2JhemdTZ1kxUnZuZVkK43Jbw6lWmKqDljo/gkt4yvJ6Zh0HSCJN + sji/xyq8gtPV3h5R4qG7wIEAJFR31WiU8t2DBe7F56+2qC8s58YHdg== + -----END AGE ENCRYPTED FILE----- + - recipient: age14taxy23wzym2r9jndzsq5h8dx2f5cj5vtusfet2ggjjepp8pkfdqf6mus0 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHL0xtVEZjeUN6TjgxMmlN + aVU0cDMwQjdDVklBcm1ud1lRSlFuamIweUdBCkxVRWg0MTVjUlplZU42R0dqZGlO + WXl6RDZMQktSekdLNjFEamF1RWFnNDAKLS0tIHNuUlU5emdySU5maGtHNE1zcitk + MnZ3RjRnbzJQOG5aQjQxcThYT3pJbTAKB8tH4XQ8pPVkguib9478JR3BOFAw/KhF + NIbLPosI4CWt7HIJwDl8NfD/W+jow+HhQ/BihU17qOSSRc9EM5oC7g== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-05-01T04:33:17Z" + mac: ENC[AES256_GCM,data:YbhWGBJRj19cCD3Z7tTJDEkP+M6ju1MMz823SUqc1/ARGH37mq3tdu+AAEljixO/aewfbvQFBlFkNkCEUoSMhdTuhdcJAajq/pQPVjJeqRmoyuFulWLhrSPCAxHm+e5dXKhHUNoixJv2JoVQp0B5LgjV+zPvqZ1ni7qSEJcGI6s=,iv:63GbyrMi1RkTbLCIQ1VgyN4Mr2oOdd2AUeH6M4Q7mL8=,tag:wVcFum/UlEVwwCUQzTBJSw==,type:str] + encrypted_regex: ^(data|stringData)$ + version: 3.11.0 diff --git a/hub/cluster/cloud-cluster/edge-au-east-node-joiner.yaml b/hub/cluster/cloud-cluster/edge-au-east-node-joiner.yaml new file mode 100644 index 00000000..47bbcbf3 --- /dev/null +++ b/hub/cluster/cloud-cluster/edge-au-east-node-joiner.yaml @@ -0,0 +1,274 @@ +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: edge-au-east-node-joiner + namespace: cloud-cluster +spec: + chart: + spec: + chart: charts/resources + reconcileStrategy: Revision + sourceRef: + kind: GitRepository + name: infra + namespace: flux-system + dependsOn: + - name: edge-au-east-apiserver-proxy + - name: edge-au-east-control-plane + driftDetection: + mode: enabled + interval: 1h + kubeConfig: + secretRef: + name: admin-kubeconfig + storageNamespace: edge + targetNamespace: edge + valuesFrom: + - kind: Secret + name: edge-au-east-node-ts-auth + valuesKey: key + targetPath: nodeTsAuth.stringData.key + - kind: Secret + name: edge-au-east-node-bootstrap-token + valuesKey: token + targetPath: nodeBootstrapToken.stringData.token + values: + nodeTsAuth: + kind: Secret + metadata: + name: node-ts-auth + stringData: + key: "" + nodeBootstrapToken: + kind: Secret + metadata: + name: node-bootstrap-token + stringData: + token: "" + nodeJoinerServiceAccount: + kind: ServiceAccount + metadata: + name: node-joiner + nodeJoinerRole: + apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: node-joiner + rules: + - apiGroups: [batch] + resources: [jobs] + verbs: [get, list, watch, create, delete] + nodeJoinerRoleBinding: + apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: node-joiner + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: node-joiner + subjects: + - kind: ServiceAccount + name: node-joiner + nodeJoinerHook: + kind: ConfigMap + metadata: + name: node-joiner-hook + data: + hook.sh: | + #!/bin/bash + set -euo pipefail + + if [[ "${1:-}" == "--config" ]]; then + cat <<'YAML' + configVersion: v1 + kubernetes: + - name: edge-nodes + apiVersion: v1 + kind: Node + labelSelector: + matchExpressions: + - key: blc.samcday.com/asg + operator: Exists + executeHookOnEvent: [Added, Modified, Deleted] + executeHookOnSynchronization: true + jqFilter: | + { + name: .metadata.name, + ip: ((.status.addresses // []) | map(select(.type=="ExternalIP"))[0].address // ""), + ready: ((.status.conditions // []) | any(.type=="Ready" and .status=="True")), + } + YAML + exit 0 + fi + + # shell-operator uses KUBECONFIG to watch the child cluster. Unset it + # for kubectl calls that create parent-cluster Jobs via the pod SA. + unset KUBECONFIG + + NAMESPACE=edge + TEMPLATE=/hooks/job-template.yaml + + reconcile() { + local op=$1 name=$2 ip=$3 ready=$4 + local job="join-$name" + + if [[ -z "$name" ]]; then + return + fi + + if [[ "$op" == "Deleted" || "$ready" == "true" ]]; then + kubectl -n "$NAMESPACE" delete job "$job" --ignore-not-found + return + fi + + if [[ -z "$ip" ]]; then + echo "node $name: no ExternalIP yet, waiting for next event" + return + fi + + if kubectl -n "$NAMESPACE" get job "$job" >/dev/null 2>&1; then + return + fi + + echo "creating join job for $name ($ip)" + local template manifest + template=$(<"$TEMPLATE") + manifest=${template//\$\{NODE_NAME\}/$name} + manifest=${manifest//\$\{NODE_IP\}/$ip} + kubectl -n "$NAMESPACE" create -f - <<<"$manifest" + } + + jq -c '.[]' "$BINDING_CONTEXT_PATH" | while read -r row; do + type=$(jq -r '.type' <<<"$row") + case "$type" in + Synchronization) + jq -c '.objects[]? // empty' <<<"$row" | while read -r obj; do + reconcile "Synchronization" \ + "$(jq -r '.filterResult.name // ""' <<<"$obj")" \ + "$(jq -r '.filterResult.ip // ""' <<<"$obj")" \ + "$(jq -r '.filterResult.ready // false' <<<"$obj")" + done + ;; + Event) + reconcile \ + "$(jq -r '.watchEvent // ""' <<<"$row")" \ + "$(jq -r '.filterResult.name // ""' <<<"$row")" \ + "$(jq -r '.filterResult.ip // ""' <<<"$row")" \ + "$(jq -r '.filterResult.ready // false' <<<"$row")" + ;; + esac + done + job-template.yaml: | + apiVersion: batch/v1 + kind: Job + metadata: + name: join-${NODE_NAME} + labels: + app.kubernetes.io/component: node-joiner + bl.samcday.com/node: ${NODE_NAME} + spec: + backoffLimit: 30 + ttlSecondsAfterFinished: 3600 + template: + metadata: + labels: + app.kubernetes.io/component: node-joiner + bl.samcday.com/node: ${NODE_NAME} + spec: + restartPolicy: OnFailure + volumes: + - name: edge-kubeconfig + secret: + secretName: admin-kubeconfig + defaultMode: 256 + items: + - key: value + path: kubeconfig + containers: + - name: join + image: ghcr.io/samcday/infra-node-joiner:2026042921 # {"$imagepolicy": "flux-system:node-joiner:tag"} + env: + - name: NODE_NAME + value: "${NODE_NAME}" + - name: NODE_IP + value: "${NODE_IP}" + - name: HEADSCALE_URL + value: https://headscale.tail22d0a0.ts.net + - name: APISERVER_URL + value: edge-au-east-apiserver.tailnet.hub.samcday.com:6443 + - name: TS_AUTH_KEY + valueFrom: + secretKeyRef: + name: node-ts-auth + key: key + - name: BOOTSTRAP_TOKEN + valueFrom: + secretKeyRef: + name: node-bootstrap-token + key: token + - name: CA_HASH + valueFrom: + configMapKeyRef: + name: ca-hash + key: hash + volumeMounts: + - name: edge-kubeconfig + mountPath: /etc/edge-kubeconfig + readOnly: true + nodeJoiner: + apiVersion: apps/v1 + kind: Deployment + metadata: + name: node-joiner + spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app.kubernetes.io/name: node-joiner + template: + metadata: + labels: + app.kubernetes.io/name: node-joiner + spec: + serviceAccountName: node-joiner + containers: + - name: shell-operator + image: ghcr.io/flant/shell-operator:v1.4.16 + env: + - name: KUBECONFIG + value: /etc/edge-kubeconfig/kubeconfig + - name: SHELL_OPERATOR_HOOKS_DIR + value: /hooks + - name: SHELL_OPERATOR_TMP_DIR + value: /tmp/shell-operator + - name: LOG_LEVEL + value: info + volumeMounts: + - name: edge-kubeconfig + mountPath: /etc/edge-kubeconfig + readOnly: true + - name: hooks + mountPath: /hooks + readOnly: true + - name: tmp + mountPath: /tmp + resources: + requests: { cpu: 20m, memory: 128Mi } + limits: { memory: 256Mi } + volumes: + - name: edge-kubeconfig + secret: + secretName: admin-kubeconfig + defaultMode: 256 + items: + - key: value + path: kubeconfig + - name: hooks + configMap: + name: node-joiner-hook + defaultMode: 493 + - name: tmp + emptyDir: {} diff --git a/hub/cluster/cloud-cluster/kustomization.yaml b/hub/cluster/cloud-cluster/kustomization.yaml index af96a10d..8cc460f8 100644 --- a/hub/cluster/cloud-cluster/kustomization.yaml +++ b/hub/cluster/cloud-cluster/kustomization.yaml @@ -4,6 +4,9 @@ configMapGenerator: - name: control-plane-values files: - values.yaml=control-plane-values.yaml + - name: edge-au-east-control-plane-values + files: + - values.yaml=edge-au-east-control-plane-values.yaml namespace: cloud-cluster resources: - ../../../.kustomize-config @@ -12,6 +15,10 @@ resources: - csi-driver.yaml - descheduler.yaml - edge.yaml + - edge-au-east-apiserver-proxy.yaml + - edge-au-east-control-plane.yaml + - edge-au-east-node-joiner.yaml + - edge-au-east-node-bootstrap-token.yaml - etcdetcetc.yaml - external-dns.yaml - fastboop.yaml diff --git a/hub/cluster/headscale/acls.json b/hub/cluster/headscale/acls.json index 81131a7f..64bfd82b 100644 --- a/hub/cluster/headscale/acls.json +++ b/hub/cluster/headscale/acls.json @@ -36,6 +36,15 @@ "action": "accept", "src": ["tag:cloud-cluster-node"], "dst": ["tag:cloud-cluster-apiserver:*"] + }, + // Allow edge-au-east nodes to access only their hosted apiserver. + { + "action": "accept", + "src": ["tag:edge-au-east-node"], + "dst": [ + "tag:edge-au-east-apiserver:6443", + "tag:edge-au-east-apiserver:8091" + ] } ], "autoApprovers": { @@ -61,6 +70,8 @@ "tag:hub-subnet-router": [], "tag:cloud-cluster-apiserver": [], "tag:cloud-cluster-node": [], + "tag:edge-au-east-apiserver": [], + "tag:edge-au-east-node": [], "tag:simonet": [] } } diff --git a/hub/cluster/headscale/main.tf b/hub/cluster/headscale/main.tf index f63f0675..6fc93fcb 100644 --- a/hub/cluster/headscale/main.tf +++ b/hub/cluster/headscale/main.tf @@ -24,6 +24,10 @@ resource "headscale_user" "conduit" { name = "conduit" } +resource "headscale_user" "edge_au_east" { + name = "edge-au-east" +} + resource "headscale_user" "hub" { name = "hub" } @@ -66,6 +70,22 @@ resource "headscale_pre_auth_key" "conduit_client_stable" { ephemeral = false } +resource "headscale_pre_auth_key" "edge_au_east_apiserver" { + user = headscale_user.edge_au_east.id + time_to_expire = "520w" + reusable = true + ephemeral = false + acl_tags = ["tag:edge-au-east-apiserver"] +} + +resource "headscale_pre_auth_key" "edge_au_east_nodes" { + user = headscale_user.edge_au_east.id + time_to_expire = "520w" + reusable = true + ephemeral = true + acl_tags = ["tag:edge-au-east-node"] +} + resource "headscale_pre_auth_key" "subnet-router" { user = headscale_user.hub.id time_to_expire = "521w" @@ -118,6 +138,28 @@ resource "kubernetes_secret" "conduit_client_preauth" { } } +resource "kubernetes_secret" "edge_au_east_apiserver_preauth" { + metadata { + name = "edge-au-east-apiserver-ts-auth" + namespace = "cloud-cluster" + } + + data = { + authkey = headscale_pre_auth_key.edge_au_east_apiserver.key + } +} + +resource "kubernetes_secret" "edge_au_east_node_preauth" { + metadata { + name = "edge-au-east-node-ts-auth" + namespace = "cloud-cluster" + } + + data = { + key = headscale_pre_auth_key.edge_au_east_nodes.key + } +} + resource "headscale_pre_auth_key" "simonet-router" { user = headscale_user.simonet.id time_to_expire = "520w" diff --git a/hub/cluster/headscale/tofu.yaml b/hub/cluster/headscale/tofu.yaml index 33238c6e..9280916c 100644 --- a/hub/cluster/headscale/tofu.yaml +++ b/hub/cluster/headscale/tofu.yaml @@ -35,6 +35,8 @@ rules: resourceNames: - apiserver-ts-auth - node-ts-auth + - edge-au-east-apiserver-ts-auth + - edge-au-east-node-ts-auth - conduit-ts-auth verbs: [create, patch, update, get] ---