เทมเพลตแบบแยกส่วน

เสร็จสมบูรณ์เมื่อ

การทําให้เป็นโมดูลาร์ของเทมเพลต เป็นแนวทางปฏิบัติที่ดีที่สุดที่แบ่งเทมเพลตขนาดใหญ่ที่ซับซ้อนออกเป็นส่วนประกอบที่เล็กลงและนํากลับมาใช้ใหม่ได้ วิธีนี้ช่วยเพิ่มความสามารถในการบํารุงรักษา ส่งเสริมการนํากลับมาใช้ใหม่ และทําให้เทมเพลตง่ายต่อการทดสอบและทําความเข้าใจ

เหตุใดจึงต้องทําให้เทมเพลตเป็นโมดูล

ประโยชน์ของการทําให้เป็นโมดูลาร์:

  • การนํากลับมาใช้ใหม่: สร้างเทมเพลตเครือข่ายเพียงครั้งเดียวและใช้กับหลายโครงการ
  • การบํารุงรักษา: อัปเดตโมดูลหนึ่งโมดูลแทนการแก้ไขเทมเพลตขนาดใหญ่หลายรายการ
  • การทํางานร่วมกันเป็นทีม: ทีมต่างๆ สามารถเป็นเจ้าของโมดูลที่แตกต่างกันได้ (เครือข่าย ความปลอดภัย การประมวลผล)
  • การทดสอบ: ทดสอบแต่ละโมดูลแยกกันก่อนเขียน
  • การแยกข้อกังวล: แต่ละเทมเพลตมุ่งเน้นไปที่โดเมนโครงสร้างพื้นฐานเฉพาะ
  • การควบคุมเวอร์ชัน: ติดตามการเปลี่ยนแปลงของแต่ละส่วนประกอบอย่างอิสระ

ตัวอย่างในโลกแห่งความเป็นจริง: สร้างเทมเพลตแยกต่างหากสําหรับ:

  • โมดูลเครือข่าย: เครือข่ายเสมือน, ซับเน็ต, NSG, ตารางเส้นทาง
  • โมดูลการจัดเก็บข้อมูล: บัญชีที่เก็บข้อมูล คอนเทนเนอร์ Blob การแชร์ไฟล์
  • โมดูลการประมวลผล: เครื่องเสมือน ชุดความพร้อมใช้งาน โหลดบาลานเซอร์
  • โมดูลความปลอดภัย: Key Vault, ข้อมูลประจําตัวที่มีการจัดการ, การกําหนด RBAC

เทมเพลตที่เชื่อมโยง

แม่แบบที่เชื่อมโยง ช่วยให้คุณสามารถอ้างอิงไฟล์แม่แบบภายนอกจากแม่แบบหลักได้ นี่เป็นวิธีการหลักในการสร้างสถาปัตยกรรมเทมเพลต ARM แบบแยกส่วน

วิธีการทํางาน:

  1. จัดเก็บเทมเพลตย่อยในตําแหน่งที่สามารถเข้าถึงได้ (ที่เก็บข้อมูล Azure, GitHub เป็นต้น)
  2. เทมเพลตหลักอ้างอิงเทมเพลตภายนอกผ่าน URI
  3. Resource Manager ดาวน์โหลดและดําเนินการเทมเพลตที่เชื่อมโยงระหว่างการปรับใช้

วากยสัมพันธ์: เพิ่มทรัพยากรการปรับใช้ไปยังเทมเพลตหลักของคุณ:

"resources": [
  {
    "apiVersion": "2022-09-01",
    "name": "linkedTemplate",
    "type": "Microsoft.Resources/deployments",
    "properties": {
      "mode": "Incremental",
      "templateLink": {
        "uri": "https://mystorageaccount.blob.core.windows.net/templates/networking.json",
        "contentVersion": "1.0.0.0"
      },
      "parameters": {
        "vnetName": {
          "value": "[parameters('virtualNetworkName')]"
        },
        "location": {
          "value": "[parameters('location')]"
        }
      }
    }
  }
]

คุณสมบัติที่สําคัญ:

  • ประเภท:Microsoft.Resources/deployments ระบุการปรับใช้ที่ซ้อนกันหรือเชื่อมโยง
  • โหมด: โหมดการปรับใช้ (ส่วนเพิ่มหรือเสร็จสมบูรณ์)
  • templateLink: ชี้ไปที่ URI เทมเพลตภายนอก
  • พารามิเตอร์: ค่าที่ส่งผ่านไปยังเทมเพลตที่เชื่อมโยง

ตัวอย่างที่สมบูรณ์พร้อมเทมเพลตที่เชื่อมโยงหลายแบบ:

"resources": [
  {
    "name": "networkingDeployment",
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2022-09-01",
    "properties": {
      "mode": "Incremental",
      "templateLink": {
        "uri": "[concat(parameters('templateBaseUrl'), '/networking.json')]"
      },
      "parameters": {
        "vnetName": { "value": "[parameters('vnetName')]" }
      }
    }
  },
  {
    "name": "storageDeployment",
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2022-09-01",
    "dependsOn": [
      "[resourceId('Microsoft.Resources/deployments', 'networkingDeployment')]"
    ],
    "properties": {
      "mode": "Incremental",
      "templateLink": {
        "uri": "[concat(parameters('templateBaseUrl'), '/storage.json')]"
      }
    }
  }
]

เทมเพลตที่ซ้อนกัน

เทมเพลตที่ซ้อนกันช่วยให้คุณสามารถฝังเทมเพลตที่สมบูรณ์ได้โดยตรงภายในเทมเพลตหลักโดยใช้templateคุณสมบัติแทนtemplateLink

เมื่อใดที่ควรใช้เทมเพลตที่ซ้อนกัน:

  • สถานการณ์ง่ายๆ: ส่วนประกอบขนาดเล็กในตัวเองที่ไม่ต้องการไฟล์ภายนอก
  • ตรรกะส่วนตัว: ตรรกะของเทมเพลตที่คุณไม่ต้องการเปิดเผยต่อภายนอก
  • การสร้างแบบไดนามิก: สร้างเนื้อหาเทมเพลตโดยทางโปรแกรมระหว่างการปรับใช้

ข้อเสียเปรียบ: การซ้อนคอมโพเนนต์ขนาดใหญ่จะสร้างไฟล์หลักขนาดใหญ่ ทําให้ดูแลรักษาและอ่านได้ยากขึ้น

"resources": [
  {
    "apiVersion": "2022-09-01",
    "name": "nestedStorageTemplate",
    "type": "Microsoft.Resources/deployments",
    "properties": {
      "mode": "Incremental",
      "template": {
        "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "resources": [
          {
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2023-01-01",
            "name": "[variables('storageName')]",
            "location": "[parameters('location')]",
            "sku": {
              "name": "Standard_LRS"
            },
            "kind": "StorageV2",
            "properties": {
              "supportsHttpsTrafficOnly": true
            }
          }
        ]
      }
    }
  }
]

ข้อจํากัดที่สําคัญ:

โน้ต

ขอบเขตเทมเพลตที่ซ้อนกัน: เทมเพลตที่ซ้อนกันสามารถใช้พารามิเตอร์และตัวแปรจากเทมเพลตหลักเท่านั้น คุณไม่สามารถกําหนดพารามิเตอร์หรือตัวแปรใหม่ภายในเทมเพลตที่ซ้อนกันได้

เทมเพลตที่เชื่อมโยงกับเทมเพลตที่ซ้อนกัน:

คุณสมบัติ เทมเพลตที่เชื่อมโยง เทมเพลตที่ซ้อนกัน
ตำแหน่ง ไฟล์ภายนอก (URI) อินไลน์ภายในเทมเพลตหลัก
ความสามารถในการนํากลับมาใช้ใหม่ สูง - ใช้ในทุกโครงการ ต่ํา - ผูกกับเทมเพลตหลัก
ความสามารถในการดูแลรักษา ง่าย - แยกไฟล์ ยากขึ้น - ฝังอยู่ในไฟล์หลัก
พารามิเตอร์ สามารถกําหนดพารามิเตอร์ของตัวเองได้ ใช้พารามิเตอร์เทมเพลตหลักเท่านั้น
ตัว แปร สามารถกําหนดตัวแปรของตัวเองได้ ใช้ตัวแปรเทมเพลตหลักเท่านั้น
ขนาด ไม่มีผลกระทบต่อเทมเพลตหลัก เพิ่มขนาดเทมเพลตหลัก
ที่ดีที่สุดสําหรับ สถาปัตยกรรมโมดูลาร์การผลิต ส่วนประกอบที่เรียบง่ายและครั้งเดียว

การแนะนํา: ใช้ เทมเพลตที่เชื่อมโยง สําหรับสถานการณ์การใช้งานจริงและ เทมเพลตที่ซ้อนกัน สําหรับส่วนประกอบที่เรียบง่ายและไม่สามารถนํากลับมาใช้ใหม่ได้เท่านั้น

โหมดการปรับใช้

เมื่อปรับใช้เทมเพลต คุณต้องเลือก โหมดการปรับใช้ ที่กําหนดวิธีที่ Resource Manager จัดการกับทรัพยากรที่มีอยู่ในกลุ่มทรัพยากรเป้าหมาย

สามตัวเลือกการปรับใช้

โหมดตรวจสอบความถูกต้อง

วัตถุประสงค์: ทดสอบเทมเพลตโดยไม่ต้องทําการเปลี่ยนแปลง

หน้าที่:

  • คอมไพล์เทมเพลตและตรวจสอบไวยากรณ์ JSON
  • ตรวจสอบตรรกะการปรับใช้ (ไม่มีการขึ้นต่อกันแบบวงกลม)
  • ตรวจสอบให้แน่ใจว่าทรัพยากรประเภทและเวอร์ชัน API ทั้งหมดถูกต้อง
  • ไม่ปรับใช้ ทรัพยากรใดๆ

ควรใช้เมื่อใด: ก่อนการปรับใช้การผลิตเพื่อตรวจจับข้อผิดพลาดตั้งแต่เนิ่นๆ

ตัวอย่างคําสั่ง:

az deployment group validate \
  --resource-group myResourceGroup \
  --template-file main.json \
  --parameters @parameters.json

โหมดส่วนเพิ่ม (ค่าเริ่มต้น)

วัตถุประสงค์: เพิ่มหรืออัปเดตทรัพยากรโดยไม่ส่งผลกระทบต่อทรัพยากรที่มีอยู่

หน้าที่:

  • ปรับใช้ทรัพยากร ที่กําหนดไว้ในเทมเพลต
  • ปล่อยให้ทรัพยากรที่ไม่เปลี่ยนแปลง ไม่ได้กําหนดไว้ในเทมเพลต
  • อัปเดต ทรัพยากรหากมีการเปลี่ยนแปลงการกําหนดค่า

สถานการณ์ตัวอย่าง:

  • เทมเพลตกําหนด VM1, VM2, Storage1
  • กลุ่มทรัพยากรมี VM1, VM3, Storage1
  • หลังการปรับใช้: VM1 (อัปเดต), VM2 (เพิ่ม), VM3 (ไม่เปลี่ยนแปลง), Storage1 (อัปเดต)

ควรใช้เมื่อใด:

  • การเพิ่มทรัพยากรใหม่ให้กับสภาพแวดล้อมที่มีอยู่
  • การอัปเดตทรัพยากรเฉพาะโดยไม่เสี่ยงต่อผู้อื่น
  • สภาพแวดล้อมการพัฒนาและการทดสอบ

โหมดสมบูรณ์

วัตถุประสงค์: ตรวจสอบให้แน่ใจว่ากลุ่มทรัพยากรตรงกับเทมเพลตทุกประการ (idempotency)

หน้าที่:

  • ปรับใช้ทรัพยากร ที่กําหนดไว้ในเทมเพลต
  • ลบทรัพยากร ที่ไม่ได้กําหนดไว้ในเทมเพลต
  • กลุ่มทรัพยากรมีเฉพาะสิ่งที่อยู่ในเทมเพลตเท่านั้น

สถานการณ์ตัวอย่าง:

  • เทมเพลตกําหนด VM1, VM2, Storage1
  • กลุ่มทรัพยากรมี VM1, VM3, Storage1, VM4
  • หลังการปรับใช้: VM1 (อัปเดต), VM2 (เพิ่ม), Storage1 (อัปเดต), VM3 (ลบ), VM4 (ลบ)

ควรใช้เมื่อใด:

  • สภาพแวดล้อมการผลิตที่ต้องการการควบคุมของรัฐอย่างเข้มงวด
  • บรรลุอุดมการณ์ (ผลการปรับใช้เดียวกันทุกครั้ง)
  • การลบทรัพยากรที่ไม่ต้องการหรือด้วยตนเอง

คำเตือน

โหมดสมบูรณ์สามารถลบทรัพยากรได้ ทดสอบอย่างละเอียดก่อนใช้ในการผลิต!

การตั้งค่าโหมดการปรับใช้

Azure CLI:

# Incremental (default)
az deployment group create \
  --resource-group myResourceGroup \
  --template-file main.json \
  --mode Incremental

# Complete
az deployment group create \
  --resource-group myResourceGroup \
  --template-file main.json \
  --mode Complete

พาวเวอร์เชลล์:

# Incremental
New-AzResourceGroupDeployment `
  -ResourceGroupName myResourceGroup `
  -TemplateFile main.json `
  -Mode Incremental

# Complete
New-AzResourceGroupDeployment `
  -ResourceGroupName myResourceGroup `
  -TemplateFile main.json `
  -Mode Complete

แนวทางปฏิบัติที่ดีที่สุด

โน้ต

หนึ่งกลุ่มทรัพยากรต่อการปรับใช้: ใช้กลุ่มทรัพยากรเฉพาะสําหรับแต่ละแอปพลิเคชันเชิงตรรกะหรือสภาพแวดล้อมเพื่อลดความซับซ้อนในการจัดการและหลีกเลี่ยงการลบโดยไม่ได้ตั้งใจ

โน้ต

ข้อจํากัดของเทมเพลตที่เชื่อมโยง/ซ้อนกัน: คุณสามารถใช้ โหมดส่วนเพิ่ม ได้เฉพาะสําหรับทั้งเทมเพลตที่เชื่อมโยงและแบบซ้อนกันเท่านั้น โหมดสมบูรณ์ไม่ได้รับการสนับสนุนสําหรับการปรับใช้รอง

คำแนะนำ:

  • พัฒนาการ: ใช้โหมดส่วนเพิ่มเพื่อความยืดหยุ่นและการทําซ้ําที่รวดเร็วขึ้น
  • การผลิต: ใช้โหมดสมบูรณ์กับไปป์ไลน์ CI/CD เพื่อให้แน่ใจว่าสถานะสอดคล้องกัน
  • ก่อนโหมดสมบูรณ์: ตรวจสอบความถูกต้องก่อนเสมอและทดสอบในสภาพแวดล้อมที่ไม่ใช่การผลิต
  • ล็อคทรัพยากร: ใช้การล็อกกับทรัพยากรที่สําคัญเพื่อป้องกันการลบโดยไม่ได้ตั้งใจ

เทมเพลตและพารามิเตอร์ภายนอก

เทมเพลตภายนอก เป็นรากฐานสําหรับสถาปัตยกรรมเทมเพลต ARM แบบแยกส่วนอย่างแท้จริง คุณจัดเก็บเทมเพลตย่อยในตําแหน่งที่เข้าถึงได้และอ้างอิงผ่าน URI

ข้อกําหนดการช่วยสําหรับการเข้าถึงเทมเพลต

Resource Manager ต้องสามารถเข้าถึงเทมเพลตที่เชื่อมโยง ระหว่างการปรับใช้:

สิ่งที่ได้ผล:

  • ที่เก็บข้อมูล Azure Blob : สาธารณะหรือส่วนตัวด้วยโทเค็น SAS
  • จีทฮับ: ที่เก็บสาธารณะหรือส่วนตัวที่มีโทเค็นการเข้าถึง
  • ปลายทาง HTTPS : URL HTTPS ที่เข้าถึงได้แบบสาธารณะ
  • อินสแตนซ์คอนเทนเนอร์ Azure: การโฮสต์ไฟล์เทมเพลตในคอนเทนเนอร์

สิ่งที่ไม่ได้ผล:

  • ไฟล์ในเครื่อง: ไฟล์บนคอมพิวเตอร์หรือเครือข่ายท้องถิ่นของคุณ
  • โปรโตคอล File://: เส้นทางระบบไฟล์ภายในเครื่อง
  • HTTP (ไม่ปลอดภัย): รองรับเฉพาะ HTTPS เท่านั้น

templateLink: อ้างอิงไฟล์เทมเพลตภายนอก

พารามิเตอร์ลิงค์: อ้างอิงไฟล์พารามิเตอร์ภายนอก (ทางเลือกแทนพารามิเตอร์แบบอินไลน์)

สําคัญ

คุณไม่สามารถใช้ทั้งพารามิเตอร์แบบอินไลน์และพารามิเตอร์ลิงก์พร้อมกันได้ เลือกหนึ่งวิธี

ตัวอย่างที่สมบูรณ์ด้วย templateLink:

"resources": [
  {
    "name": "linkedStorageDeployment",
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2022-09-01",
    "properties": {
      "mode": "Incremental",
      "templateLink": {
        "uri": "https://mystorageaccount.blob.core.windows.net/templates/storage.json?sv=2021-06-08&sr=b&sig=ABC123...&se=2025-12-31T23:59:59Z&sp=r",
        "contentVersion": "1.0.0.0"
      },
      "parameters": {
        "storageAccountName": {
          "value": "[variables('storageAccountName')]"
        },
        "location": {
          "value": "[parameters('location')]"
        },
        "sku": {
          "value": "Standard_GRS"
        }
      }
    }
  }
]

ส่วนประกอบที่สําคัญ:

  • URI: URL HTTPS แบบเต็มไปยังเทมเพลตที่ลิงก์ (รวมถึงโทเค็น SAS หากใช้ที่เก็บข้อมูลส่วนตัว)
  • เนื้อหาเวอร์ชัน: เวอร์ชันของเทมเพลตที่ลิงก์ (ต้องตรงกับสิ่งที่อยู่ในไฟล์เทมเพลตที่ลิงก์)
  • พารามิเตอร์: ค่าที่ส่งผ่านไปยังเทมเพลตที่เชื่อมโยง (สามารถอ้างอิงพารามิเตอร์/ตัวแปรเทมเพลตหลักได้)

การใช้ไฟล์พารามิเตอร์ภายนอก

ทางเลือกแทนพารามิเตอร์แบบอินไลน์:

{
  "name": "linkedDeployment",
  "type": "Microsoft.Resources/deployments",
  "apiVersion": "2022-09-01",
  "properties": {
    "mode": "Incremental",
    "templateLink": {
      "uri": "https://mystorageaccount.blob.core.windows.net/templates/main.json"
    },
    "parametersLink": {
      "uri": "https://mystorageaccount.blob.core.windows.net/parameters/prod.json"
    }
  }
}

ประโยชน์:

  • แยกไฟล์พารามิเตอร์ตามสภาพแวดล้อม (dev.json, staging.json, prod.json)
  • พารามิเตอร์ที่ละเอียดอ่อนที่จัดเก็บไว้อย่างปลอดภัยในไฟล์พารามิเตอร์
  • ง่ายต่อการจัดการการปรับใช้หลายสภาพแวดล้อม

การรักษาความปลอดภัยแม่แบบภายนอก

เทมเพลตภายนอกไม่จําเป็นต้องเป็นแบบสาธารณะ คุณสามารถจัดเก็บไว้ในบัญชีพื้นที่จัดเก็บข้อมูลส่วนตัวและใช้ โทเค็นลายเซ็นการเข้าถึงที่ใช้ร่วมกัน (SAS) เพื่อการเข้าถึงที่ปลอดภัย

ขั้นตอนในการรักษาความปลอดภัยเทมเพลต

  1. จัดเก็บเทมเพลตในที่เก็บข้อมูล Azure Blob ส่วนตัว:
# Create storage account and container
az storage account create \
  --name mytemplatestorage \
  --resource-group myResourceGroup \
  --location eastus \
  --sku Standard_LRS

az storage container create \
  --name templates \
  --account-name mytemplatestorage \
  --public-access off
  1. อัปโหลดไฟล์เทมเพลต:
az storage blob upload \
  --account-name mytemplatestorage \
  --container-name templates \
  --name networking.json \
  --file ./templates/networking.json
  1. สร้างโทเค็น SAS เมื่อหมดอายุ:
# Create SAS token valid for 30 days
az storage blob generate-sas \
  --account-name mytemplatestorage \
  --container-name templates \
  --name networking.json \
  --permissions r \
  --expiry 2025-12-31T23:59:59Z \
  --https-only \
  --output tsv
  1. ใช้โทเค็น SAS ใน URI ของ templateLink:
"templateLink": {
  "uri": "https://mytemplatestorage.blob.core.windows.net/templates/networking.json?sv=2021-06-08&sr=b&sig=ABC123...&se=2025-12-31T23:59:59Z&sp=r"
}

ข้อควรพิจารณาด้านความปลอดภัย

การบันทึกโทเค็น SAS:

  • แม้ว่าโทเค็นจะถูกส่งผ่านอย่างปลอดภัย แต่ URI (รวมถึงโทเค็น SAS) จะถูกบันทึกไว้ในการดําเนินการปรับใช้
  • ทุกคนที่มีสิทธิ์อ่านกลุ่มทรัพยากรจะมองเห็นบันทึกการปรับใช้

แนวทางปฏิบัติที่ดีที่สุดสําหรับการรักษาความปลอดภัย:

  • กําหนดวันหมดอายุ: สร้างโทเค็น SAS แบบจํากัดเวลา (30-90 วัน)
  • ใช้สิทธิ์แบบอ่านอย่างเดียว: โทเค็น SAS ควรให้สิทธิ์การอ่าน (r) เท่านั้น
  • หมุนเวียนโทเค็นอย่างสม่ําเสมอ: สร้างโทเค็นใหม่และอัปเดตเทมเพลตเป็นระยะ
  • ใช้ Azure Key Vault: จัดเก็บโทเค็น SAS ใน Key Vault และอ้างอิงในเทมเพลต
  • ข้อมูลประจําตัวที่มีการจัดการ: พิจารณาใช้ข้อมูลประจําตัวที่มีการจัดการสําหรับการเข้าถึงเทมเพลตแทนโทเค็น SAS
  • ปลายทางส่วนตัว: ใช้จุดสิ้นสุดส่วนตัวของ Azure Storage เพื่อความปลอดภัยเครือข่ายเพิ่มเติม

ตัวอย่างที่มีการอ้างอิง Key Vault:

"templateLink": {
  "uri": "[concat('https://mytemplatestorage.blob.core.windows.net/templates/networking.json', reference(resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), 'storageAccountSasToken')).secretValue)]"
}

วิธีการนี้ป้องกันไม่ให้โทเค็น SAS อยู่ในโค้ดเทมเพลตและบันทึกการปรับใช้ของคุณ