इसे छोड़कर कंटेंट पर जाएं

चरण 1 — निर्माण

चरण 1 Terraform के साथ F5 Distributed Cloud पर एक आधिकारिक प्राथमिक DNS ज़ोन को डिप्लॉय करता है, जो Azure Blob Storage में रिमोट स्टेट द्वारा समर्थित है। यह पृष्ठ प्लान की प्रत्येक फ़ाइल दिखाता है, आवश्यक वेरिएबल और सीक्रेट की व्याख्या करता है, और स्थानीय रन तथा GitHub Actions पाइपलाइन दोनों को कवर करता है।

आप क्या डिप्लॉय करते हैं

Section titled “आप क्या डिप्लॉय करते हैं”
  • आपके डेलिगेटेड डोमेन के लिए xcsh_dns_zone, system नेमस्पेस में, A रिकॉर्ड (www, app, api) के एक demo-records ग्रुप के साथ।
  • Terraform स्टेट एक Azure Blob Storage कंटेनर में संग्रहीत, ताकि आपकी मशीन और CI के बीच एक ही स्टेट साझा हो।

प्लान terraform/ के अंतर्गत रहता है: एक पतला रूट मॉड्यूल जो इनपुट को dns-zone मॉड्यूल में वायर करता है।

Terraform और प्रोवाइडर को पिन करता है। प्रोवाइडर की बाधा >= 3.62.0 है — वह रिलीज़ जहाँ सिस्टम-ओनली DNS संसाधन अपना नेमस्पेस स्वचालित रूप से डिफ़ॉल्ट करते हैं।

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"
}
}
}

प्रोवाइडर कोड में कोई तर्क नहीं लेता — यह एनवायरनमेंट से प्रमाणित होता है, इसलिए कोई सीक्रेट कमिट नहीं होता।

# 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" {}

एक आंशिक azurerm बैकएंड: कोई भी एनवायरनमेंट-विशिष्ट मान हार्डकोड नहीं हैं। निर्देशांक init समय पर आपूर्ति किए जाते हैं (स्थानीय फ़ाइल से, या CI में GitHub Actions वेरिएबल से)।

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" {}
}

domain आवश्यक है (रनटाइम पर आपूर्ति, कभी हार्डकोड नहीं); a_records प्रत्येक रिकॉर्ड नाम को उसके IPv4 पतों पर मैप करता है। कोई namespace वेरिएबल नहीं है — प्रोवाइडर API स्पेक की बाधा से DNS ऑब्जेक्ट को system नेमस्पेस में फिक्स करता है, इसलिए इसे यहाँ कभी कॉन्फ़िगर नहीं किया जाता।

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 और dns-zone मॉड्यूल

Section titled “main.tf और dns-zone मॉड्यूल”

रूट मॉड्यूल इनपुट को ./modules/dns-zone में वायर करता है:

module "dns_zone" {
source = "./modules/dns-zone"
domain = var.domain
labels = var.labels
a_records = var.a_records
}

मॉड्यूल ज़ोन बनाता है (नेमस्पेस छोड़ा गया है — प्रोवाइडर इसे system पर डिफ़ॉल्ट करता है)। एक dynamic "rr_set" ब्लॉक a_records मैप को प्रति एंट्री एक रिकॉर्ड सेट में बदलता है:

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
}
}
}
}
}
}

रूट outputs.tf मॉड्यूल से ज़ोन नाम और F5 XC आइडेंटिफ़ायर को पुनः एक्सपोर्ट करता है।

आवश्यक वेरिएबल और सीक्रेट

Section titled “आवश्यक वेरिएबल और सीक्रेट”

कोई भी एनवायरनमेंट-विशिष्ट मान .tf फ़ाइलों में बेक नहीं किया गया है। सब कुछ रनटाइम पर आपूर्ति किया जाता है — CI में GitHub Actions वेरिएबल और सीक्रेट से, या स्थानीय फ़ाइलों और एनवायरनमेंट वेरिएबल से।

मानउद्देश्यCI स्रोतस्थानीय स्रोत
resource_group_name, storage_account_name, container_name, keyazurerm बैकएंड निर्देशांकरिपॉजिटरी वेरिएबल TFSTATE_RESOURCE_GROUP, TFSTATE_STORAGE_ACCOUNT, TFSTATE_CONTAINER, TFSTATE_KEY (-backend-config के माध्यम से पास)backend.hcl (backend.hcl.example कॉपी करें; gitignored)
domainTerraform इनपुटरिपॉजिटरी वेरिएबल DNS_DOMAIN (TF_VAR_domain के रूप में)terraform.tfvars (उदाहरण कॉपी करें) या TF_VAR_domain
ARM_ACCESS_KEYazurerm बैकएंड ऑथ (स्टोरेज अकाउंट की)रिपॉजिटरी सीक्रेटexport ARM_ACCESS_KEY=...
XCSH_API_URL, XCSH_API_TOKENxcsh प्रोवाइडर ऑथरिपॉजिटरी सीक्रेटexport XCSH_API_URL=... XCSH_API_TOKEN=...

रेपो में शिप होने वाली दो उदाहरण फ़ाइलें:

resource_group_name = "f5-sales-demo-tfstate"
storage_account_name = "f5salesdemotfstate"
container_name = "tfstate"
key = "dns.tfstate"

Azure स्टेट बैकएंड बूटस्ट्रैप करें

Section titled “Azure स्टेट बैकएंड बूटस्ट्रैप करें”

बैकएंड स्टोरेज अपना बूटस्ट्रैप स्वयं स्टोर नहीं कर सकता, इसलिए इसे एक बार, बैंड से बाहर, प्रमाणित Azure CLI सेशन के साथ बनाएं। रेपो scripts/bootstrap-azure-state.sh शिप करता है:

Terminal window
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"

फिर स्थानीय रन के लिए की एक्सपोर्ट करें, और इसे (प्रोवाइडर क्रेडेंशियल सहित) GitHub सीक्रेट के रूप में सेट करें:

Terminal window
export ARM_ACCESS_KEY="$KEY"
gh secret set ARM_ACCESS_KEY -R f5-sales-demo/dns
gh secret set XCSH_API_URL -R f5-sales-demo/dns
gh secret set XCSH_API_TOKEN -R f5-sales-demo/dns

स्थानीय रूप से डिप्लॉय करें

Section titled “स्थानीय रूप से डिप्लॉय करें”
  1. इनपुट कॉन्फ़िगर करें। उदाहरण कॉपी करें और अपने मान भरें:

    Terminal window
    cp terraform/backend.hcl.example terraform/backend.hcl
    cp terraform/terraform.tfvars.example terraform/terraform.tfvars
  2. क्रेडेंशियल एक्सपोर्ट करें:

    Terminal window
    export XCSH_API_URL="https://<tenant>.console.ves.volterra.io"
    export XCSH_API_TOKEN="<api-token>"
    export ARM_ACCESS_KEY="<storage-account-key>"
  3. आंशिक कॉन्फ़िग के साथ बैकएंड को इनिशियलाइज़ करें:

    Terminal window
    cd terraform
    terraform init -backend-config=backend.hcl
  4. फ़ॉर्मेटिंग जाँचें और वैलिडेट करें:

    Terminal window
    terraform fmt -check -recursive
    terraform validate
  5. प्लान और अप्लाई करें:

    Terminal window
    terraform plan
    terraform apply

एक सफल अप्लाई ज़ोन बनाता है और स्टेट को Azure कंटेनर में लिखता है। यह पुष्टि करने के लिए कि यह रिज़ॉल्व होता है, चरण 2 — वैलिडेट पर जाएं।

.github/workflows/terraform.yml वर्कफ़्लो प्रत्येक पुल रिक्वेस्ट पर एक प्लान और main में मर्ज पर एक अप्लाई चलाता है। यह बैकएंड निर्देशांक और इनपुट रिपॉजिटरी वेरिएबल से और क्रेडेंशियल सीक्रेट से पढ़ता है, प्रत्येक को केवल उस स्टेप में इंजेक्ट करता है जिसे इसकी आवश्यकता है, और साझा स्टेट ब्लॉब पर दो अप्लाई कभी रेस न करें इसके लिए कंकरेंसी ग्रुप पर रन सीरियलाइज़ करता है।

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-color

एक्शन कमिट SHA पर पिन किए गए हैं (संस्करण टिप्पणियों के साथ), और सीक्रेट पूरे जॉब के बजाय init, plan, और apply स्टेप तक सीमित हैं।