Skip to content

Migrate ExternalDNS to Azure Workload Identity and v0.23.0 - #193

Merged
clee231 merged 4 commits into
mainfrom
feature/externaldns-workload-identity
Oct 1, 2026
Merged

clee231 merged 4 commits into
mainfrom
feature/externaldns-workload-identity

Conversation

@clee231

@clee231 clee231 commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

ExternalDNS was crash-looping because its Azure client secret had expired. This change migrates the controller to Azure Workload Identity and upgrades Helm chart 1.13.1 to 1.23.0, which runs ExternalDNS v0.23.0.

The Terraform changes federate the existing Azure application with system:serviceaccount:externaldns:externaldns, grant resource-group Reader and zone-scoped DNS Zone Contributor permissions, and correct the legacy Vault stack client ID output reference. The deployment uses a ConfigMap without credentials, preserves TXT owner default and the existing annotation prefix, and explicitly limits updates to acmuic.org with upsert-only policy. Temporary cert-manager HTTP challenge Ingresses are excluded to prevent a private A record from conflicting with the portal CNAME.

Validation:

  • Terraform formatting and validation pass with the pinned Terraform and provider versions.
  • Helm rendering, Kubernetes server-side dry runs, and KubeLinter 0.8.3 on the rendered ExternalDNS resources pass.
  • The legacy password was rotated through Terraform, Vault was updated, and the original controller recovered to 1/1 available.
  • Workload Identity was verified on v0.13.6 before upgrading.
  • v0.23.0 was deployed through Argo CD in dry-run mode and reported all records up to date.
  • DNS writes are enabled with upsert-only. The controller is 1/1 available, uses a projected Azure token, has no Vault sidecar, and Argo CD reports Synced/Healthy. No DNS record sets were deleted.
  • Both Terraform CI plan jobs pass. The full local Azure plan has no infrastructure changes after application.
  • Repository-wide Kubernetes CI lint reports six existing findings in unchanged Plausible, Radius, Vaultwarden, and OIDC manifests. None are in this change.

The live application is temporarily pinned to this PR's deployment commit. The app-of-apps will restore its normal Git HEAD source when this PR is merged. The legacy Azure password and Vault secret remain available for rollback; the running controller uses neither.

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Terraform plan in azure/terraform/stacks/sysadmin-demo in the prod workspace
With var files: azure/terraform/stacks/sysadmin-demo/configuration/prod.tfvars

No changes. Your infrastructure matches the configuration.
No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.

✅ Plan applied in Terraform Apply on Azure #66

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Terraform plan in azure/terraform/stacks/acm-general in the prod workspace
With var files: azure/terraform/stacks/acm-general/configuration/prod.tfvars

No changes. Your infrastructure matches the configuration.
No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.

✅ Plan applied in Terraform Apply on Azure #66

Outputs
azurerm_dns_zone_acm_uic           = {
    id                        = "/subscriptions/2f98793b-7e2f-4f03-ac5b-7b2ec934dcd7/resourceGroups/acm-general/providers/Microsoft.Network/dnsZones/acmuic.org"
    max_number_of_record_sets = 10000
    name                      = "acmuic.org"
    name_servers              = [
        "ns1-06.azure-dns.com.",
        "ns2-06.azure-dns.net.",
        "ns3-06.azure-dns.org.",
        "ns4-06.azure-dns.info.",
    ]
    number_of_record_sets     = 81
    resource_group_name       = "acm-general"
    tags                      = {}
    timeouts                  = null
}
default_resource_group             = "acm-general"
externaldns_sp_clientid            = "f995b4bc-00a0-4912-9a1a-da9f74407cb8"
externaldns_sp_keyid               = "4851f036-2284-446d-80b5-cd53d66bdb54"
externaldns_sp_password            = (sensitive value)
pfsense_service_principal_id       = "/servicePrincipals/732cd17c-42d8-4463-be7f-ca627b6eee87"
pfsense_service_principal_password = (sensitive value)
subscription_id                    = "2f98793b-7e2f-4f03-ac5b-7b2ec934dcd7"
tenant_id                          = "cad5e02f-bae4-42d6-a06e-4377dd3e386f"

@clee231
clee231 merged commit 04288ae into main Oct 1, 2026
4 of 6 checks passed
@clee231
clee231 deleted the feature/externaldns-workload-identity branch October 1, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant