- Startseite
- DNS
- Demo
- Phase 1 — Build
Phase 1 — Build
Phase 1 stellt eine autoritative primäre DNS-Zone auf F5 Distributed Cloud mit Terraform bereit, gesichert durch einen Remote State in Azure Blob Storage. Diese Seite zeigt jede Datei im Plan, erläutert die erforderlichen Variablen und Secrets und behandelt sowohl eine lokale Ausführung als auch die GitHub Actions Pipeline.
Was bereitgestellt wird
Abschnitt betitelt „Was bereitgestellt wird“- Eine
xcsh_dns_zonefür Ihre delegierte Domain im Namespacesystem, mit einer Gruppedemo-recordsvon A-Records (www,app,api). - Terraform-State, der in einem Azure Blob Storage Container gespeichert ist, sodass derselbe State zwischen Ihrem Rechner und der CI geteilt wird.
Der Plan
Abschnitt betitelt „Der Plan“Der Plan befindet sich unter terraform/: ein schlankes Stammmodul, das Eingaben in ein
dns-zone-Modul einspeist.
versions.tf
Abschnitt betitelt „versions.tf“Fixiert Terraform und den Provider. Die Provider-Einschränkung lautet >= 3.62.0 — das Release, ab
dem systemexklusive DNS-Ressourcen ihren Namespace automatisch vorbelegen.
terraform { required_version = ">= 1.5"
required_providers { xcsh = { source = "f5-sales-demo/xcsh" # >= 3.62.0: the namespace attribute for system-only DNS resources defaults # to "system" (spec-driven), so it can be omitted. Locally the provider is # consumed via dev_overrides, which ignores this constraint. version = ">= 3.62.0" } }}providers.tf
Abschnitt betitelt „providers.tf“Der Provider nimmt im Code keine Argumente entgegen — er authentifiziert sich aus der Umgebung, sodass keine Secrets eingecheckt werden.
# The xcsh provider authenticates from the environment — no secrets in code.# Export one of the following credential sets before running Terraform:## Token auth: XCSH_API_URL + XCSH_API_TOKEN# P12 auth: XCSH_API_URL + XCSH_P12_FILE + XCSH_P12_PASSWORD# PEM auth: XCSH_API_URL + XCSH_CERT + XCSH_KEY## See terraform/README.md for local dev setup (dev_overrides + env).provider "xcsh" {}backend.tf
Abschnitt betitelt „backend.tf“Ein partielles azurerm-Backend: Es sind keine umgebungsspezifischen Werte fest kodiert. Die
Koordinaten werden zum Zeitpunkt von init angegeben (aus einer lokalen Datei oder aus GitHub
Actions Variablen in der CI).
terraform { # Azure Blob Storage remote state, configured as a PARTIAL backend: # no environment-specific values are hardcoded here. Supply them at init time. # # CI: terraform init -backend-config="resource_group_name=$RG" ... # (values from GitHub Actions repository variables) # Local: terraform init -backend-config=backend.hcl (copy backend.hcl.example; gitignored) # # Auth is the storage account access key via the ARM_ACCESS_KEY environment # variable (never committed). Keyless auth (use_oidc / use_azuread_auth) is not # used: our Contributor-only RBAC cannot assign the "Storage Blob Data # Contributor" role those methods require. backend "azurerm" {}}variables.tf
Abschnitt betitelt „variables.tf“domain ist erforderlich (zur Laufzeit angegeben, niemals fest kodiert); a_records ordnet jeden
Record-Namen seinen IPv4-Adressen zu. Es gibt keine Variable namespace — der Provider fixiert
DNS-Objekte gemäß der Einschränkung der API-Spezifikation auf den Namespace system, daher wird er
hier nicht konfiguriert.
variable "domain" { description = "DNS zone FQDN (required; supplied via TF_VAR_domain / a GitHub variable / tfvars)." type = string}
variable "labels" { description = "Labels applied to managed DNS objects." type = map(string) default = { managed_by = "terraform" use_case = "dns" }}
variable "a_records" { description = "A records: record name (\"\" = apex) to list of IPv4 addresses." type = map(list(string)) default = { www = ["203.0.113.10"] app = ["203.0.113.20"] api = ["203.0.113.30"] }}main.tf und das dns-zone-Modul
Abschnitt betitelt „main.tf und das dns-zone-Modul“Das Stammmodul leitet Eingaben an ./modules/dns-zone weiter:
module "dns_zone" { source = "./modules/dns-zone"
domain = var.domain labels = var.labels a_records = var.a_records}Das Modul erstellt die Zone (der Namespace wird weggelassen — der Provider setzt ihn standardmäßig
auf system). Ein dynamic "rr_set"-Block wandelt die a_records-Map in einen Record-Set pro
Eintrag um:
resource "xcsh_dns_zone" "this" { name = var.domain labels = var.labels
primary { default_soa_parameters {}
rr_set_group { metadata { name = "demo-records" }
dynamic "rr_set" { for_each = var.a_records content { ttl = var.record_ttl a_record { name = rr_set.key values = rr_set.value } } } } }}Das Stamm-outputs.tf exportiert den Zonennamen und den F5 XC-Bezeichner aus dem Modul erneut.
Erforderliche Variablen und Secrets
Abschnitt betitelt „Erforderliche Variablen und Secrets“In den .tf-Dateien sind keine umgebungsspezifischen Werte fest kodiert. Alles wird zur Laufzeit
angegeben — in der CI aus GitHub Actions Variablen und Secrets, oder lokal aus Dateien und
Umgebungsvariablen.
| Wert | Zweck | CI-Quelle | Lokale Quelle |
|---|---|---|---|
resource_group_name, storage_account_name, container_name, key | azurerm-Backend-Koordinaten | Repository-Variablen TFSTATE_RESOURCE_GROUP, TFSTATE_STORAGE_ACCOUNT, TFSTATE_CONTAINER, TFSTATE_KEY (übergeben via -backend-config) | backend.hcl (Kopie von backend.hcl.example; gitignoriert) |
domain | Terraform-Eingabe | Repository-Variable DNS_DOMAIN (als TF_VAR_domain) | terraform.tfvars (Kopie des Beispiels) oder TF_VAR_domain |
ARM_ACCESS_KEY | azurerm-Backend-Authentifizierung (Storage-Account-Schlüssel) | Repository-Secret | export ARM_ACCESS_KEY=... |
XCSH_API_URL, XCSH_API_TOKEN | xcsh-Provider-Authentifizierung | Repository-Secrets | export XCSH_API_URL=... XCSH_API_TOKEN=... |
Die zwei Beispieldateien, die im Repository mitgeliefert werden:
resource_group_name = "f5-sales-demo-tfstate"storage_account_name = "f5salesdemotfstate"container_name = "tfstate"key = "dns.tfstate"domain = "f5-sales-demo.com"
labels = { managed_by = "terraform" use_case = "dns"}
a_records = { www = ["203.0.113.10"] app = ["203.0.113.20"] api = ["203.0.113.30"]}Bootstrap des Azure State Backends
Abschnitt betitelt „Bootstrap des Azure State Backends“Der Backend-Storage kann seinen eigenen Bootstrap nicht speichern, daher erstellen Sie ihn einmalig,
außerhalb der regulären Prozesse, mit einer authentifizierten Azure CLI-Sitzung. Das Repository
enthält scripts/bootstrap-azure-state.sh:
az group create --name f5-sales-demo-tfstate --location eastus2 \ --tags managed_by=terraform use_case=dns purpose=tfstate
az storage account create --name f5salesdemotfstate --resource-group f5-sales-demo-tfstate \ --location eastus2 --sku Standard_LRS --kind StorageV2 \ --min-tls-version TLS1_2 --allow-blob-public-access false
# State safety: keep prior versions and allow recovery of deleted state blobs.az storage account blob-service-properties update \ --account-name f5salesdemotfstate --resource-group f5-sales-demo-tfstate \ --enable-versioning true \ --enable-delete-retention true --delete-retention-days 7 \ --enable-container-delete-retention true --container-delete-retention-days 7
KEY="$(az storage account keys list \ --account-name f5salesdemotfstate --resource-group f5-sales-demo-tfstate \ --query '[0].value' -o tsv)"
az storage container create --name tfstate \ --account-name f5salesdemotfstate --auth-mode key --account-key "$KEY"Exportieren Sie anschließend den Schlüssel für lokale Ausführungen und setzen Sie ihn (zusammen mit den Provider-Anmeldeinformationen) als GitHub Secrets:
export ARM_ACCESS_KEY="$KEY"gh secret set ARM_ACCESS_KEY -R f5-sales-demo/dnsgh secret set XCSH_API_URL -R f5-sales-demo/dnsgh secret set XCSH_API_TOKEN -R f5-sales-demo/dnsLokal bereitstellen
Abschnitt betitelt „Lokal bereitstellen“-
Eingaben konfigurieren. Kopieren Sie die Beispiele und tragen Sie Ihre Werte ein:
Terminal-Fenster cp terraform/backend.hcl.example terraform/backend.hclcp terraform/terraform.tfvars.example terraform/terraform.tfvars -
Anmeldeinformationen exportieren:
Terminal-Fenster export XCSH_API_URL="https://<tenant>.console.ves.volterra.io"export XCSH_API_TOKEN="<api-token>"export ARM_ACCESS_KEY="<storage-account-key>" -
Backend initialisieren mit der partiellen Konfiguration:
Terminal-Fenster cd terraformterraform init -backend-config=backend.hcl -
Formatierung prüfen und validieren:
Terminal-Fenster terraform fmt -check -recursiveterraform validate -
Planen und anwenden:
Terminal-Fenster terraform planterraform apply
Eine erfolgreiche Anwendung erstellt die Zone und schreibt den State in den Azure-Container. Fahren Sie mit Phase 2 — Validieren fort, um zu bestätigen, dass die Auflösung funktioniert.
Kontinuierliche Integration
Abschnitt betitelt „Kontinuierliche Integration“Der Workflow .github/workflows/terraform.yml führt bei jedem Pull Request einen plan und bei
einem Merge in main einen apply aus. Er liest die Backend-Koordinaten und Eingaben aus
Repository-Variablen sowie die Anmeldeinformationen aus Secrets, leitet jede nur an den Schritt
weiter, der sie benötigt, und serialisiert Ausführungen in einer Concurrency-Gruppe, sodass zwei
Applies nie gleichzeitig auf dem gemeinsam genutzten State-Blob ausgeführt werden.
name: Terraform
on: pull_request: branches: [main] paths: ['terraform/**', '.github/workflows/terraform.yml'] push: branches: [main] paths: ['terraform/**']
permissions: contents: read
concurrency: group: terraform-state cancel-in-progress: false
env: TF_IN_AUTOMATION: 'true'
jobs: terraform: name: ${{ github.event_name == 'push' && 'apply' || 'plan' }} runs-on: ubuntu-latest defaults: run: working-directory: terraform steps: - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Setup Terraform uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4.0.1
- name: Init env: ARM_ACCESS_KEY: ${{ secrets.ARM_ACCESS_KEY }} RESOURCE_GROUP: ${{ vars.TFSTATE_RESOURCE_GROUP }} STORAGE_ACCOUNT: ${{ vars.TFSTATE_STORAGE_ACCOUNT }} CONTAINER: ${{ vars.TFSTATE_CONTAINER }} STATE_KEY: ${{ vars.TFSTATE_KEY }} run: | terraform init -input=false \ -backend-config="resource_group_name=${RESOURCE_GROUP}" \ -backend-config="storage_account_name=${STORAGE_ACCOUNT}" \ -backend-config="container_name=${CONTAINER}" \ -backend-config="key=${STATE_KEY}"
- name: Format check run: terraform fmt -check -recursive
- name: Validate run: terraform validate -no-color
- name: Plan if: github.event_name == 'pull_request' env: ARM_ACCESS_KEY: ${{ secrets.ARM_ACCESS_KEY }} XCSH_API_URL: ${{ secrets.XCSH_API_URL }} XCSH_API_TOKEN: ${{ secrets.XCSH_API_TOKEN }} TF_VAR_domain: ${{ vars.DNS_DOMAIN }} run: terraform plan -input=false -no-color
- name: Apply if: github.event_name == 'push' env: ARM_ACCESS_KEY: ${{ secrets.ARM_ACCESS_KEY }} XCSH_API_URL: ${{ secrets.XCSH_API_URL }} XCSH_API_TOKEN: ${{ secrets.XCSH_API_TOKEN }} TF_VAR_domain: ${{ vars.DNS_DOMAIN }} run: terraform apply -input=false -auto-approve -no-colorDie Actions sind auf Commit-SHAs (mit Versionskommentaren) fixiert, und Secrets sind auf die
Schritte init, plan und apply beschränkt, anstatt auf den gesamten Job.