Pemeriksaan Pra-Penerbangan untuk Penghantaran AZD

March 31, 2026 ยท View on GitHub

Navigasi Bab:

Pengenalan

Panduan menyeluruh ini menyediakan skrip dan prosedur pengesahan pra-penerapan untuk memastikan kejayaan penghantaran Azure Developer CLI sebelum ia bermula. Pelajari untuk melaksanakan pemeriksaan automatik untuk pengesahan, ketersediaan sumber, kuota, pematuhan keselamatan, dan keperluan prestasi bagi mengelakkan kegagalan penghantaran serta mengoptimumkan kadar kejayaan penghantaran.

Matlamat Pembelajaran

Dengan menyelesaikan panduan ini, anda akan:

  • Menguasai teknik dan skrip pengesahan automatik pra-penerapan
  • Memahami strategi pemeriksaan komprehensif untuk pengesahan, kebenaran, dan kuota
  • Melaksanakan prosedur pengesahan ketersediaan dan kapasiti sumber
  • Mengkonfigurasi pemeriksaan keselamatan dan pematuhan polisi organisasi
  • Merancang aliran kerja anggaran kos dan pengesahan bajet
  • Membina automasi pemeriksaan pra-penerbangan tersuai untuk saluran CI/CD

Hasil Pembelajaran

Setelah selesai, anda akan dapat:

  • Mencipta dan melaksanakan skrip pengesahan pra-penerbangan yang komprehensif
  • Merancang aliran kerja pemeriksaan automatik untuk senario penghantaran yang berbeza
  • Melaksanakan prosedur dan polisi pengesahan khusus persekitaran
  • Mengkonfigurasi pemantauan proaktif dan pemberitahuan bagi kesediaan penghantaran
  • Menyelesaikan masalah sebelum penghantaran dan melaksanakan tindakan pembetulan
  • Mengintegrasikan pemeriksaan pra-penerbangan ke dalam saluran DevOps dan aliran kerja automasi

Jadual Kandungan


Gambaran Keseluruhan

Pemeriksaan pra-penerbangan adalah pengesahan penting yang dijalankan sebelum penghantaran untuk memastikan:

  • Ketersediaan sumber dan kuota di rantau sasaran
  • Pengesahan dan kebenaran disediakan dengan betul
  • Kesahihan templat dan ketepatan parameter
  • Kesambungan rangkaian dan kebergantungan
  • Pematuhan keselamatan mengikut polisi organisasi
  • Anggaran kos dalam had bajet

Bila Perlu Menjalankan Pemeriksaan Pra-penerbangan

  • Sebelum penghantaran pertama ke persekitaran baru
  • Selepas perubahan templat yang signifikan
  • Sebelum penghantaran produksi
  • Apabila menukar rantau Azure
  • Sebahagian daripada saluran CI/CD

Skrip Pra-penerbangan Automatik

Pemeriksa Pra-penerbangan PowerShell

#!/usr/bin/env pwsh
<#
.SYNOPSIS
    Comprehensive pre-flight checks for AZD deployments
.DESCRIPTION
    Validates authentication, permissions, quotas, and resource availability before deployment
.PARAMETER EnvironmentName
    AZD environment name to validate
.PARAMETER ResourceGroup
    Target resource group (optional, will be derived if not provided)
.PARAMETER Location
    Target Azure region
.EXAMPLE
    .\preflight-check.ps1 -EnvironmentName "production" -Location "eastus"
#>

param(
    [Parameter(Mandatory = $true)]
    [string]$EnvironmentName,
    
    [Parameter(Mandatory = $false)]
    [string]$ResourceGroup,
    
    [Parameter(Mandatory = $true)]
    [string]$Location,
    
    [Parameter(Mandatory = $false)]
    [switch]$Detailed
)

# Kod warna untuk output
$Red = "`e[31m"
$Green = "`e[32m"
$Yellow = "`e[33m"
$Blue = "`e[34m"
$Reset = "`e[0m"

function Write-Status {
    param($Message, $Status, $Details = "")
    
    $statusIcon = switch ($Status) {
        "Success" { "${Green}โœ“${Reset}" }
        "Warning" { "${Yellow}โš ${Reset}" }
        "Error" { "${Red}โœ—${Reset}" }
        "Info" { "${Blue}โ„น${Reset}" }
    }
    
    Write-Host "$statusIcon $Message" -NoNewline
    if ($Details) {
        Write-Host " - $Details" -ForegroundColor Gray
    } else {
        Write-Host ""
    }
}

function Test-Prerequisites {
    Write-Host "${Blue}=== Prerequisites Check ===${Reset}"
    
    # Semak pemasangan AZD
    try {
        $azdVersion = azd version --output json | ConvertFrom-Json
        Write-Status "AZD CLI installed" "Success" "Version: $($azdVersion.azd.version)"
    }
    catch {
        Write-Status "AZD CLI not found" "Error" "Install from https://aka.ms/azd-install"
        return $false
    }
    
    # Semak pemasangan Azure CLI
    try {
        $azVersion = az version --output json | ConvertFrom-Json
        Write-Status "Azure CLI installed" "Success" "Version: $($azVersion.'azure-cli')"
    }
    catch {
        Write-Status "Azure CLI not found" "Error" "Install from https://aka.ms/azcli"
        return $false
    }
    
    # Semak versi PowerShell
    if ($PSVersionTable.PSVersion.Major -ge 7) {
        Write-Status "PowerShell version" "Success" "Version: $($PSVersionTable.PSVersion)"
    }
    else {
        Write-Status "PowerShell version" "Warning" "Consider upgrading to PowerShell 7+"
    }
    
    return $true
}

function Test-Authentication {
    Write-Host "`n${Blue}=== Authentication Check ===${Reset}"
    
    try {
        # Semak pengesahan AZD
        $azdAuth = azd auth login --check-status --output json 2>$null | ConvertFrom-Json
        if ($azdAuth.status -eq "Logged-in") {
            Write-Status "AZD authentication" "Success" "User: $($azdAuth.principalName)"
        }
        else {
            Write-Status "AZD authentication" "Error" "Run 'azd auth login'"
            return $false
        }
        
        # Semak pengesahan Azure CLI
        $azAccount = az account show --output json | ConvertFrom-Json
        Write-Status "Azure CLI authentication" "Success" "Subscription: $($azAccount.name)"
        
        # Sahkan akses langganan
        $subscriptionId = $azAccount.id
        $subscription = az account subscription show --subscription-id $subscriptionId --output json | ConvertFrom-Json
        Write-Status "Subscription access" "Success" "State: $($subscription.state)"
        
        return $true
    }
    catch {
        Write-Status "Authentication failed" "Error" $_.Exception.Message
        return $false
    }
}

function Test-Permissions {
    Write-Host "`n${Blue}=== Permissions Check ===${Reset}"
    
    try {
        # Dapatkan penugasan peranan pengguna semasa
        $roleAssignments = az role assignment list --assignee (az account show --query user.name --output tsv) --output json | ConvertFrom-Json
        
        $hasContributor = $roleAssignments | Where-Object { 
            $_.roleDefinitionName -eq "Contributor" -or 
            $_.roleDefinitionName -eq "Owner" -or
            $_.roleDefinitionName -eq "User Access Administrator"
        }
        
        if ($hasContributor) {
            Write-Status "Required permissions" "Success" "Contributor or higher role found"
        }
        else {
            Write-Status "Required permissions" "Warning" "May need Contributor role for deployment"
        }
        
        # Uji penciptaan kumpulan sumber (jika ditentukan)
        if ($ResourceGroup) {
            $rgExists = az group exists --name $ResourceGroup --output tsv
            if ($rgExists -eq "true") {
                Write-Status "Resource group access" "Success" "Resource group '$ResourceGroup' exists"
            }
            else {
                # Uji keupayaan untuk mencipta kumpulan sumber
                try {
                    az group create --name "preflight-test-rg" --location $Location --output none
                    az group delete --name "preflight-test-rg" --yes --output none
                    Write-Status "Resource group creation" "Success" "Can create resource groups"
                }
                catch {
                    Write-Status "Resource group creation" "Error" "Cannot create resource groups"
                    return $false
                }
            }
        }
        
        return $true
    }
    catch {
        Write-Status "Permissions check failed" "Error" $_.Exception.Message
        return $false
    }
}

function Test-QuotasAndLimits {
    Write-Host "`n${Blue}=== Quotas and Limits Check ===${Reset}"
    
    try {
        # Semak kuota pengkomputeran
        $computeUsage = az vm list-usage --location $Location --output json | ConvertFrom-Json
        
        # Semak kuota tertentu
        $coreQuota = $computeUsage | Where-Object { $_.name.value -eq "cores" }
        if ($coreQuota) {
            $usagePercent = [math]::Round(($coreQuota.currentValue / $coreQuota.limit) * 100, 2)
            if ($usagePercent -lt 80) {
                Write-Status "Compute cores quota" "Success" "$($coreQuota.currentValue)/$($coreQuota.limit) ($usagePercent%)"
            }
            else {
                Write-Status "Compute cores quota" "Warning" "$($coreQuota.currentValue)/$($coreQuota.limit) ($usagePercent%)"
            }
        }
        
        # Semak had Perkhidmatan Aplikasi
        try {
            $appServiceUsage = az appservice list-locations --sku S1 --output json | ConvertFrom-Json
            if ($appServiceUsage | Where-Object { $_.name -eq $Location }) {
                Write-Status "App Service availability" "Success" "Available in $Location"
            }
            else {
                Write-Status "App Service availability" "Warning" "May not be available in $Location"
            }
        }
        catch {
            Write-Status "App Service quota check" "Warning" "Could not verify App Service limits"
        }
        
        # Semak had akaun penyimpanan
        $storageAccounts = az storage account list --output json | ConvertFrom-Json
        $accountCount = ($storageAccounts | Measure-Object).Count
        if ($accountCount -lt 200) {
            Write-Status "Storage account limit" "Success" "$accountCount/250 storage accounts"
        }
        else {
            Write-Status "Storage account limit" "Warning" "$accountCount/250 storage accounts"
        }
        
        return $true
    }
    catch {
        Write-Status "Quota check failed" "Warning" $_.Exception.Message
        return $true # Tidak menghalang
    }
}

function Test-NetworkConnectivity {
    Write-Host "`n${Blue}=== Network Connectivity Check ===${Reset}"
    
    # Uji titik akhir Azure
    $endpoints = @(
        "https://management.azure.com/",
        "https://login.microsoftonline.com/",
        "https://graph.microsoft.com/",
        "https://vault.azure.net/"
    )
    
    foreach ($endpoint in $endpoints) {
        try {
            $response = Invoke-WebRequest -Uri $endpoint -Method Head -TimeoutSec 10 -UseBasicParsing
            Write-Status "Connectivity to $endpoint" "Success" "Status: $($response.StatusCode)"
        }
        catch {
            Write-Status "Connectivity to $endpoint" "Error" $_.Exception.Message
        }
    }
    
    # Uji resolusi DNS
    try {
        $dnsResult = Resolve-DnsName "management.azure.com" -ErrorAction Stop
        Write-Status "DNS resolution" "Success" "Resolved successfully"
    }
    catch {
        Write-Status "DNS resolution" "Error" "Cannot resolve Azure endpoints"
        return $false
    }
    
    return $true
}

function Test-TemplateValidation {
    Write-Host "`n${Blue}=== Template Validation ===${Reset}"
    
    # Semak jika azure.yaml wujud
    if (Test-Path "azure.yaml") {
        Write-Status "azure.yaml found" "Success"
        
        # Bahagikan azure.yaml
        try {
            $azureYaml = Get-Content "azure.yaml" -Raw | ConvertFrom-Yaml
            Write-Status "azure.yaml parsing" "Success"
            
            # Sahkan perkhidmatan
            if ($azureYaml.services) {
                $serviceCount = ($azureYaml.services | Get-Member -MemberType NoteProperty).Count
                Write-Status "Services defined" "Success" "$serviceCount services found"
            }
            else {
                Write-Status "Services defined" "Warning" "No services defined in azure.yaml"
            }
        }
        catch {
            Write-Status "azure.yaml parsing" "Error" "Invalid YAML format"
            return $false
        }
    }
    else {
        Write-Status "azure.yaml not found" "Error" "Run 'azd init' to create configuration"
        return $false
    }
    
    # Semak untuk fail infrastruktur
    if (Test-Path "infra") {
        $bicepFiles = Get-ChildItem -Path "infra" -Filter "*.bicep" -Recurse
        if ($bicepFiles.Count -gt 0) {
            Write-Status "Infrastructure templates" "Success" "$($bicepFiles.Count) Bicep files found"
            
            # Sahkan main.bicep jika ia wujud
            if (Test-Path "infra/main.bicep") {
                try {
                    az bicep build --file "infra/main.bicep" --stdout | Out-Null
                    Write-Status "Bicep template validation" "Success" "main.bicep is valid"
                }
                catch {
                    Write-Status "Bicep template validation" "Error" "main.bicep has errors"
                    return $false
                }
            }
        }
        else {
            Write-Status "Infrastructure templates" "Warning" "No Bicep files found in infra/"
        }
    }
    else {
        Write-Status "Infrastructure directory" "Error" "infra/ directory not found"
        return $false
    }
    
    # ๐Ÿงช BARU: Uji pratonton infrastruktur (laju selamat tanpa kesan)
    try {
        Write-Status "Infrastructure preview test" "Info" "Running safe dry-run validation..."
        $previewResult = azd provision --preview 2>$null
        if ($LASTEXITCODE -eq 0) {
            Write-Status "Infrastructure preview" "Success" "Preview completed - no deployment errors detected"
        }
        else {
            Write-Status "Infrastructure preview" "Warning" "Preview detected potential issues - review before deployment"
        }
    }
    catch {
        Write-Status "Infrastructure preview" "Warning" "Could not run preview - ensure azd is latest version"
    }
    
    return $true
}

function Test-RegionalAvailability {
    Write-Host "`n${Blue}=== Regional Availability Check ===${Reset}"
    
    try {
        # Semak jika lokasi sah
        $locations = az account list-locations --output json | ConvertFrom-Json
        $validLocation = $locations | Where-Object { $_.name -eq $Location -or $_.displayName -eq $Location }
        
        if ($validLocation) {
            Write-Status "Azure region" "Success" "Location '$Location' is valid"
        }
        else {
            Write-Status "Azure region" "Error" "Location '$Location' is not valid"
            return $false
        }
        
        # Semak ketersediaan perkhidmatan di rantau
        $services = @("Microsoft.Web", "Microsoft.Sql", "Microsoft.Storage", "Microsoft.KeyVault")
        
        foreach ($service in $services) {
            try {
                $providers = az provider show --namespace $service --output json | ConvertFrom-Json
                $resourceTypes = $providers.resourceTypes | Where-Object { $_.locations -contains $Location }
                
                if ($resourceTypes) {
                    Write-Status "$service availability" "Success" "Available in $Location"
                }
                else {
                    Write-Status "$service availability" "Warning" "May not be available in $Location"
                }
            }
            catch {
                Write-Status "$service availability" "Warning" "Could not verify availability"
            }
        }
        
        return $true
    }
    catch {
        Write-Status "Regional availability check failed" "Error" $_.Exception.Message
        return $false
    }
}

function Test-CostEstimation {
    Write-Host "`n${Blue}=== Cost Estimation Check ===${Reset}"
    
    # Anggaran kos asas (perlu Azure Pricing API untuk anggaran tepat)
    Write-Status "Cost estimation" "Info" "Use Azure Pricing Calculator for detailed estimates"
    Write-Status "Monitoring setup" "Info" "Set up Azure Cost Management alerts"
    
    # Semak jika bajet wujud
    try {
        $budgets = az consumption budget list --output json 2>$null | ConvertFrom-Json
        if ($budgets -and $budgets.Count -gt 0) {
            Write-Status "Budget monitoring" "Success" "$($budgets.Count) budgets configured"
        }
        else {
            Write-Status "Budget monitoring" "Warning" "No budgets configured - consider setting up cost alerts"
        }
    }
    catch {
        Write-Status "Budget check" "Warning" "Could not check budget configuration"
    }
    
    return $true
}

function Test-SecurityCompliance {
    Write-Host "`n${Blue}=== Security & Compliance Check ===${Reset}"
    
    # Semak amalan keselamatan biasa
    try {
        # Semak jika Key Vault dikonfigurasi
        if (Select-String -Path "infra/*.bicep" -Pattern "Microsoft.KeyVault" -Quiet) {
            Write-Status "Key Vault usage" "Success" "Key Vault detected in templates"
        }
        else {
            Write-Status "Key Vault usage" "Warning" "Consider using Key Vault for secrets"
        }
        
        # Semak penggunaan identiti terurus
        if (Select-String -Path "infra/*.bicep" -Pattern "managedIdentity|SystemAssigned" -Quiet) {
            Write-Status "Managed Identity" "Success" "Managed Identity detected"
        }
        else {
            Write-Status "Managed Identity" "Warning" "Consider using Managed Identity"
        }
        
        # Semak penguatkuasaan HTTPS
        if (Select-String -Path "infra/*.bicep" -Pattern "httpsOnly.*true|requireHttps.*true" -Quiet) {
            Write-Status "HTTPS enforcement" "Success" "HTTPS enforcement detected"
        }
        else {
            Write-Status "HTTPS enforcement" "Warning" "Ensure HTTPS is enforced"
        }
        
        return $true
    }
    catch {
        Write-Status "Security compliance check" "Warning" "Could not perform security validation"
        return $true
    }
}

# Pelaksanaan utama
function Invoke-PreflightCheck {
    Write-Host "${Green}AZD Pre-flight Check${Reset}" -ForegroundColor Green
    Write-Host "Environment: $EnvironmentName"
    Write-Host "Location: $Location"
    if ($ResourceGroup) { Write-Host "Resource Group: $ResourceGroup" }
    Write-Host "Time: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
    Write-Host ""
    
    $allPassed = $true
    $results = @{}
    
    # Jalankan semua pemeriksaan
    $results["Prerequisites"] = Test-Prerequisites
    $results["Authentication"] = Test-Authentication
    $results["Permissions"] = Test-Permissions
    $results["QuotasAndLimits"] = Test-QuotasAndLimits
    $results["NetworkConnectivity"] = Test-NetworkConnectivity
    $results["TemplateValidation"] = Test-TemplateValidation
    $results["RegionalAvailability"] = Test-RegionalAvailability
    $results["CostEstimation"] = Test-CostEstimation
    $results["SecurityCompliance"] = Test-SecurityCompliance
    
    # Rumusan
    Write-Host "`n${Blue}=== Pre-flight Check Summary ===${Reset}"
    
    $passedCount = 0
    $totalCount = $results.Count
    
    foreach ($result in $results.GetEnumerator()) {
        if ($result.Value) {
            Write-Status $result.Key "Success"
            $passedCount++
        }
        else {
            Write-Status $result.Key "Error"
            $allPassed = $false
        }
    }
    
    Write-Host ""
    if ($allPassed) {
        Write-Host "${Green}โœ“ All pre-flight checks passed ($passedCount/$totalCount)${Reset}"
        Write-Host "${Green}โœ“ Ready for deployment!${Reset}"
        exit 0
    }
    else {
        Write-Host "${Red}โœ— Some pre-flight checks failed ($passedCount/$totalCount)${Reset}"
        Write-Host "${Red}โœ— Please resolve issues before deployment${Reset}"
        exit 1
    }
}

# Jalankan pemeriksaan pra-penerbangan
Invoke-PreflightCheck

Pemeriksa Pra-penerbangan Bash

#!/bin/bash
# Versi Bash bagi pemeriksaan pra-penerbangan untuk sistem Unix/Linux

set -euo pipefail

# Kod warna
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # Tiada Warna

# Pembolehubah global
ENVIRONMENT_NAME=""
LOCATION=""
RESOURCE_GROUP=""
DETAILED=false

print_status() {
    local message=\$1
    local status=\$2
    local details=${3:-""}
    
    case $status in
        "success")
            echo -e "${GREEN}โœ“${NC} $message${details:+ - $details}"
            ;;
        "warning")
            echo -e "${YELLOW}โš ${NC} $message${details:+ - $details}"
            ;;
        "error")
            echo -e "${RED}โœ—${NC} $message${details:+ - $details}"
            ;;
        "info")
            echo -e "${BLUE}โ„น${NC} $message${details:+ - $details}"
            ;;
    esac
}

check_prerequisites() {
    echo -e "${BLUE}=== Prerequisites Check ===${NC}"
    
    # Semak pemasangan AZD
    if command -v azd >/dev/null 2>&1; then
        local azd_version=$(azd version --output json | jq -r '.azd.version')
        print_status "AZD CLI installed" "success" "Version: $azd_version"
    else
        print_status "AZD CLI not found" "error" "Install from https://aka.ms/azd-install"
        return 1
    fi
    
    # Semak pemasangan Azure CLI
    if command -v az >/dev/null 2>&1; then
        local az_version=$(az version --output json | jq -r '."azure-cli"')
        print_status "Azure CLI installed" "success" "Version: $az_version"
    else
        print_status "Azure CLI not found" "error" "Install from https://aka.ms/azcli"
        return 1
    fi
    
    # Semak pemasangan jq
    if command -v jq >/dev/null 2>&1; then
        print_status "jq installed" "success"
    else
        print_status "jq not found" "warning" "Install jq for better JSON parsing"
    fi
    
    return 0
}

check_authentication() {
    echo -e "\n${BLUE}=== Authentication Check ===${NC}"
    
    # Semak pengesahan AZD
    if azd auth login --check-status >/dev/null 2>&1; then
        local principal_name=$(azd auth login --check-status --output json 2>/dev/null | jq -r '.principalName // "Unknown"')
        print_status "AZD authentication" "success" "User: $principal_name"
    else
        print_status "AZD authentication" "error" "Run 'azd auth login'"
        return 1
    fi
    
    # Semak pengesahan Azure CLI
    if az account show >/dev/null 2>&1; then
        local subscription_name=$(az account show --query 'name' --output tsv)
        print_status "Azure CLI authentication" "success" "Subscription: $subscription_name"
    else
        print_status "Azure CLI authentication" "error" "Run 'az login'"
        return 1
    fi
    
    return 0
}

check_template_validation() {
    echo -e "\n${BLUE}=== Template Validation ===${NC}"
    
    # Semak azure.yaml
    if [[ -f "azure.yaml" ]]; then
        print_status "azure.yaml found" "success"
        
        # Pengesahan asas YAML
        if python3 -c "import yaml; yaml.safe_load(open('azure.yaml'))" 2>/dev/null; then
            print_status "azure.yaml parsing" "success"
        else
            print_status "azure.yaml parsing" "error" "Invalid YAML format"
            return 1
        fi
    else
        print_status "azure.yaml not found" "error" "Run 'azd init' to create configuration"
        return 1
    fi
    
    # Semak fail infrastruktur
    if [[ -d "infra" ]]; then
        local bicep_count=$(find infra -name "*.bicep" | wc -l)
        if [[ $bicep_count -gt 0 ]]; then
            print_status "Infrastructure templates" "success" "$bicep_count Bicep files found"
            
            # Sahkan main.bicep jika wujud
            if [[ -f "infra/main.bicep" ]]; then
                if az bicep build --file "infra/main.bicep" --stdout >/dev/null 2>&1; then
                    print_status "Bicep template validation" "success" "main.bicep is valid"
                else
                    print_status "Bicep template validation" "error" "main.bicep has errors"
                    return 1
                fi
            fi
        else
            print_status "Infrastructure templates" "warning" "No Bicep files found"
        fi
    else
        print_status "Infrastructure directory" "error" "infra/ directory not found"
        return 1
    fi
    
    return 0
}

check_regional_availability() {
    echo -e "\n${BLUE}=== Regional Availability Check ===${NC}"
    
    # Semak jika lokasi sah
    if az account list-locations --query "[?name=='$LOCATION' || displayName=='$LOCATION']" --output tsv | grep -q .; then
        print_status "Azure region" "success" "Location '$LOCATION' is valid"
    else
        print_status "Azure region" "error" "Location '$LOCATION' is not valid"
        return 1
    fi
    
    # Semak ketersediaan perkhidmatan
    local services=("Microsoft.Web" "Microsoft.Sql" "Microsoft.Storage" "Microsoft.KeyVault")
    
    for service in "${services[@]}"; do
        if az provider show --namespace "$service" --query "resourceTypes[?locations[?contains(@, '$LOCATION')]]" --output tsv | grep -q .; then
            print_status "$service availability" "success" "Available in $LOCATION"
        else
            print_status "$service availability" "warning" "May not be available in $LOCATION"
        fi
    done
    
    return 0
}

main() {
    # Tafsir argumen baris perintah
    while [[ $# -gt 0 ]]; do
        case \$1 in
            --environment-name)
                ENVIRONMENT_NAME="\$2"
                shift 2
                ;;
            --location)
                LOCATION="\$2"
                shift 2
                ;;
            --resource-group)
                RESOURCE_GROUP="\$2"
                shift 2
                ;;
            --detailed)
                DETAILED=true
                shift
                ;;
            *)
                echo "Unknown option: \$1"
                exit 1
                ;;
        esac
    done
    
    # Sahkan parameter yang diperlukan
    if [[ -z "$ENVIRONMENT_NAME" || -z "$LOCATION" ]]; then
        echo "Usage: \$0 --environment-name <name> --location <location> [--resource-group <rg>] [--detailed]"
        exit 1
    fi
    
    echo -e "${GREEN}AZD Pre-flight Check${NC}"
    echo "Environment: $ENVIRONMENT_NAME"
    echo "Location: $LOCATION"
    [[ -n "$RESOURCE_GROUP" ]] && echo "Resource Group: $RESOURCE_GROUP"
    echo "Time: $(date '+%Y-%m-%d %H:%M:%S')"
    echo ""
    
    # Jalankan pemeriksaan
    local all_passed=true
    
    check_prerequisites || all_passed=false
    check_authentication || all_passed=false
    check_template_validation || all_passed=false
    check_regional_availability || all_passed=false
    
    # Ringkasan
    echo -e "\n${BLUE}=== Pre-flight Check Summary ===${NC}"
    
    if $all_passed; then
        echo -e "${GREEN}โœ“ All pre-flight checks passed${NC}"
        echo -e "${GREEN}โœ“ Ready for deployment!${NC}"
        exit 0
    else
        echo -e "${RED}โœ— Some pre-flight checks failed${NC}"
        echo -e "${RED}โœ— Please resolve issues before deployment${NC}"
        exit 1
    fi
}

# Jalankan fungsi utama
main "$@"

Senarai Semak Pengesahan Manual

Senarai Semak Pra-Penerapan

Cetak senarai ini dan sahkan setiap item sebelum penghantaran:

โœ… Persediaan Persekitaran

  • AZD CLI dipasang dan dikemas kini ke versi terkini
  • Azure CLI dipasang dan diautentikasi
  • Langganan Azure yang betul dipilih
  • Nama persekitaran unik dan mengikut konvensyen penamaan
  • Kumpulan sumber sasaran dikenal pasti atau boleh diwujudkan

โœ… Pengesahan & Kebenaran

  • Berjaya diautentikasi dengan azd auth login
  • Pengguna mempunyai peranan Contributor pada langganan/kumpulan sumber sasaran
  • Prinsipal perkhidmatan dikonfigurasikan untuk CI/CD (jika berkenaan)
  • Tiada sijil atau kelayakan yang telah tamat tempoh

โœ… Pengesahan Templat

  • azure.yaml wujud dan merupakan YAML yang sah
  • Semua perkhidmatan yang ditakrif dalam azure.yaml mempunyai kod sumber yang sepadan
  • Templat Bicep dalam direktori infra/ ada
  • main.bicep boleh dikompil tanpa ralat (az bicep build --file infra/main.bicep)
  • ๐Ÿงช Pratonton infrastruktur berjalan dengan jayanya (azd provision --preview)
  • Semua parameter yang diperlukan ada nilai lalai atau akan disediakan
  • Tiada rahsia yang dikodkan secara kekal dalam templat

โœ… Perancangan Sumber

  • Rantau Azure sasaran dipilih dan disahkan
  • Perkhidmatan Azure yang diperlukan tersedia di rantau sasaran
  • Kuota mencukupi bagi sumber yang dirancang
  • Konflik penamaan sumber diperiksa
  • Kebergantungan antara sumber difahami

โœ… Rangkaian & Keselamatan

  • Sambungan rangkaian ke titik akhir Azure disahkan
  • Tetapan firewall/proksi dikonfigurasikan jika perlu
  • Key Vault dikonfigurasikan untuk pengurusan rahsia
  • Identiti terurus digunakan di mana boleh
  • Penguatkuasaan HTTPS diaktifkan untuk aplikasi web

โœ… Pengurusan Kos

  • Anggaran kos dikira menggunakan Kalkulator Harga Azure
  • Amaran bajet dikonfigurasikan jika diperlukan
  • SKU yang sesuai dipilih untuk jenis persekitaran
  • Kapasiti berpelepasan dipertimbangkan untuk beban kerja produksi

โœ… Pemantauan & Kebolehpantauan

  • Application Insights dikonfigurasikan dalam templat
  • Ruang kerja Log Analytics dirancang
  • Peraturan amaran ditakrif untuk metrik kritikal
  • Titik pemeriksaan kesihatan diimplimentasikan dalam aplikasi

โœ… Sandaran & Pemulihan

  • Strategi sandaran ditakrif untuk sumber data
  • Objektif masa pemulihan (RTO) didokumentasikan
  • Objektif titik pemulihan (RPO) didokumentasikan
  • Pelan pemulihan bencana disediakan untuk produksi

Pengesahan Persekitaran

Pengesahan Persekitaran Pembangunan

#!/bin/bash
# Pengesahan khusus persekitaran pembangunan

validate_dev_environment() {
    echo "=== Development Environment Validation ==="
    
    # Semak konfigurasi mesra pembangunan
    if grep -q "sku.*Free\|sku.*F1\|sku.*Basic" infra/*.bicep; then
        echo "โœ“ Development-appropriate SKUs detected"
    else
        echo "โš  Consider using lower-cost SKUs for development"
    fi
    
    # Semak konfigurasi penutupan automatik
    if grep -q "autoShutdown\|deallocate" infra/*.bicep; then
        echo "โœ“ Auto-shutdown configuration found"
    else
        echo "โ„น Consider adding auto-shutdown for cost savings"
    fi
    
    # Sahkan konfigurasi pangkalan data pembangunan
    if grep -q "Basic\|S0\|S1" infra/*.bicep; then
        echo "โœ“ Development database tiers configured"
    else
        echo "โš  Consider using Basic/Standard tiers for development databases"
    fi
}

Pengesahan Persekitaran Produksi

#!/bin/bash
# Pengesahan khusus persekitaran pengeluaran

validate_prod_environment() {
    echo "=== Production Environment Validation ==="
    
    # Semak konfigurasi ketersediaan tinggi
    if grep -q "zoneRedundant.*true\|Premium\|Standard_GRS" infra/*.bicep; then
        echo "โœ“ High availability configurations detected"
    else
        echo "โš  Consider enabling high availability for production"
    fi
    
    # Semak konfigurasi sandaran
    if grep -q "backup\|retention\|pointInTimeRestore" infra/*.bicep; then
        echo "โœ“ Backup configurations found"
    else
        echo "โš  Ensure backup strategies are implemented"
    fi
    
    # Sahkan tetapan pemantauan
    if grep -q "Microsoft.Insights\|Application_Type.*web" infra/*.bicep; then
        echo "โœ“ Monitoring and observability configured"
    else
        echo "โš  Add comprehensive monitoring for production"
    fi
    
    # Semak konfigurasi keselamatan
    if grep -q "Microsoft.KeyVault\|managedIdentity\|httpsOnly.*true" infra/*.bicep; then
        echo "โœ“ Security best practices implemented"
    else
        echo "โš  Review security configurations for production"
    fi
}

Pengesahan Sumber

Skrip Pengesahan Kuota

#!/usr/bin/env python3
"""
Azure quota and limit validation script
"""

import json
import subprocess
import sys
from typing import Dict, List, Tuple

def run_command(command: List[str]) -> Dict:
    """Run Azure CLI command and return JSON result"""
    try:
        result = subprocess.run(command, capture_output=True, text=True, check=True)
        return json.loads(result.stdout)
    except subprocess.CalledProcessError as e:
        print(f"Error running command {' '.join(command)}: {e}")
        return {}
    except json.JSONDecodeError as e:
        print(f"Error parsing JSON: {e}")
        return {}

def check_compute_quotas(location: str) -> bool:
    """Check compute quotas in specified location"""
    print(f"\n=== Compute Quotas Check ({location}) ===")
    
    usage = run_command(['az', 'vm', 'list-usage', '--location', location])
    
    if not usage:
        print("โŒ Could not retrieve compute usage information")
        return False
    
    critical_quotas = ['cores', 'virtualMachines', 'standardDSv3Family']
    
    for quota_item in usage:
        if quota_item['name']['value'] in critical_quotas:
            current = quota_item['currentValue']
            limit = quota_item['limit']
            usage_percent = (current / limit) * 100 if limit > 0 else 0
            
            status = "โœ…" if usage_percent < 80 else "โš ๏ธ" if usage_percent < 95 else "โŒ"
            print(f"{status} {quota_item['name']['localizedValue']}: {current}/{limit} ({usage_percent:.1f}%)")
            
            if usage_percent >= 95:
                return False
    
    return True

def check_storage_limits(location: str) -> bool:
    """Check storage account limits"""
    print(f"\n=== Storage Limits Check ({location}) ===")
    
    # Dapatkan akaun storan dalam langganan
    accounts = run_command(['az', 'storage', 'account', 'list'])
    
    if accounts is None:
        print("โŒ Could not retrieve storage account information")
        return False
    
    account_count = len(accounts)
    max_accounts = 250  # Had Azure lalai
    
    usage_percent = (account_count / max_accounts) * 100
    status = "โœ…" if usage_percent < 80 else "โš ๏ธ" if usage_percent < 95 else "โŒ"
    
    print(f"{status} Storage Accounts: {account_count}/{max_accounts} ({usage_percent:.1f}%)")
    
    return usage_percent < 95

def check_network_limits(location: str) -> bool:
    """Check network-related limits"""
    print(f"\n=== Network Limits Check ({location}) ===")
    
    # Semak rangkaian maya
    vnets = run_command(['az', 'network', 'vnet', 'list'])
    if vnets is not None:
        vnet_count = len(vnets)
        print(f"โœ… Virtual Networks: {vnet_count}/1000")
    
    # Semak alamat IP awam
    public_ips = run_command(['az', 'network', 'public-ip', 'list'])
    if public_ips is not None:
        ip_count = len(public_ips)
        print(f"โœ… Public IP Addresses: {ip_count}/1000")
    
    return True

def main():
    if len(sys.argv) != 2:
        print("Usage: python3 quota_check.py <location>")
        sys.exit(1)
    
    location = sys.argv[1]
    
    print("๐Ÿ” Azure Quota and Limits Validation")
    print(f"๐Ÿ“ Location: {location}")
    print(f"โฐ Time: {subprocess.run(['date'], capture_output=True, text=True).stdout.strip()}")
    
    all_passed = True
    
    # Jalankan pemeriksaan
    all_passed &= check_compute_quotas(location)
    all_passed &= check_storage_limits(location)
    all_passed &= check_network_limits(location)
    
    # Ringkasan
    print(f"\n=== Quota Check Summary ===")
    if all_passed:
        print("โœ… All quota checks passed - sufficient capacity available")
        sys.exit(0)
    else:
        print("โŒ Some quota limits are near capacity - consider requesting increases")
        sys.exit(1)

if __name__ == "__main__":
    main()

Pemeriksaan Keselamatan & Pematuhan

Skrip Pengesahan Keselamatan

#!/bin/bash
# Pengesahan keselamatan dan pematuhan untuk penempatan AZD

check_security_practices() {
    echo "=== Security Best Practices Check ==="
    
    local issues_found=0
    
    # Semak penggunaan Key Vault
    if grep -r "Microsoft.KeyVault" infra/ >/dev/null 2>&1; then
        echo "โœ… Key Vault detected in infrastructure"
    else
        echo "โš ๏ธ  Key Vault not found - consider using for secrets management"
        ((issues_found++))
    fi
    
    # Semak penggunaan identiti terurus
    if grep -r "managedIdentity\|SystemAssigned\|UserAssigned" infra/ >/dev/null 2>&1; then
        echo "โœ… Managed Identity configuration detected"
    else
        echo "โš ๏ธ  Managed Identity not found - consider using for service authentication"
        ((issues_found++))
    fi
    
    # Semak penguatkuasaan HTTPS
    if grep -r "httpsOnly.*true\|requireHttps.*true" infra/ >/dev/null 2>&1; then
        echo "โœ… HTTPS enforcement detected"
    else
        echo "โš ๏ธ  HTTPS enforcement not found - ensure secure connections"
        ((issues_found++))
    fi
    
    # Semak versi minimum TLS
    if grep -r "minimumTlsVersion.*'TLS1_2'" infra/ >/dev/null 2>&1; then
        echo "โœ… Minimum TLS 1.2 configuration detected"
    else
        echo "โš ๏ธ  Minimum TLS version not specified - consider requiring TLS 1.2+"
        ((issues_found++))
    fi
    
    # Semak had akses awam
    if grep -r "allowBlobPublicAccess.*false\|publicNetworkAccess.*Disabled" infra/ >/dev/null 2>&1; then
        echo "โœ… Public access restrictions detected"
    else
        echo "โš ๏ธ  Public access restrictions not found - consider limiting public access"
        ((issues_found++))
    fi
    
    # Semak kumpulan keselamatan rangkaian
    if grep -r "Microsoft.Network/networkSecurityGroups" infra/ >/dev/null 2>&1; then
        echo "โœ… Network Security Groups detected"
    else
        echo "โ„น๏ธ  Network Security Groups not found - may be acceptable depending on architecture"
    fi
    
    return $issues_found
}

check_compliance_requirements() {
    echo -e "\n=== Compliance Requirements Check ==="
    
    # Semak penyulitan data
    if grep -r "encryption\|encryptionAtRest\|transparentDataEncryption" infra/ >/dev/null 2>&1; then
        echo "โœ… Encryption configurations detected"
    else
        echo "โš ๏ธ  Encryption configurations not found - ensure data is encrypted"
    fi
    
    # Semak pencatatan audit
    if grep -r "Microsoft.Insights.*auditingSettings\|diagnosticSettings" infra/ >/dev/null 2>&1; then
        echo "โœ… Audit logging configurations detected"
    else
        echo "โš ๏ธ  Audit logging not found - consider enabling for compliance"
    fi
    
    # Semak dasar sandaran dan pengekalan
    if grep -r "backup.*Policy\|retentionPolicy\|retention.*Days" infra/ >/dev/null 2>&1; then
        echo "โœ… Backup and retention policies detected"
    else
        echo "โš ๏ธ  Backup/retention policies not found - required for data governance"
    fi
}

# Pelaksanaan utama
main() {
    echo "๐Ÿ”’ Security and Compliance Validation"
    echo "๐Ÿ“ Checking infra/ directory for security best practices"
    echo ""
    
    if [[ ! -d "infra" ]]; then
        echo "โŒ infra/ directory not found"
        exit 1
    fi
    
    local security_issues
    security_issues=$(check_security_practices)
    check_compliance_requirements
    
    echo -e "\n=== Security Check Summary ==="
    if [[ $security_issues -eq 0 ]]; then
        echo "โœ… All security checks passed"
        exit 0
    else
        echo "โš ๏ธ  $security_issues security recommendations found"
        echo "โ„น๏ธ  Review recommendations before deploying to production"
        exit 1
    fi
}

main "$@"

Integrasi dengan CI/CD

Integrasi GitHub Actions

name: AZD Pre-flight Checks

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment to validate'
        required: true
        default: 'development'
        type: choice
        options:
        - development
        - staging
        - production
      location:
        description: 'Azure region'
        required: true
        default: 'eastus'

jobs:
  preflight:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Install AZD
      uses: Azure/setup-azd@v0.1.0
    
    - name: Install Azure CLI
      uses: azure/setup-azure@v3
    
    - name: Azure Login
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}
    
    - name: Run Pre-flight Checks
      run: |
        chmod +x ./scripts/preflight-check.sh
        ./scripts/preflight-check.sh \
          --environment-name ${{ github.event.inputs.environment }} \
          --location ${{ github.event.inputs.location }}
    
    - name: Security Validation
      run: |
        chmod +x ./scripts/security-check.sh
        ./scripts/security-check.sh
    
    - name: Upload Results
      uses: actions/upload-artifact@v3
      if: always()
      with:
        name: preflight-results
        path: preflight-results.json

Integrasi Azure DevOps

trigger: none

parameters:
- name: environment
  displayName: Environment
  type: string
  default: development
  values:
  - development
  - staging
  - production

- name: location
  displayName: Azure Region
  type: string
  default: eastus

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: AzureCLI@2
  displayName: 'Install AZD'
  inputs:
    azureSubscription: $(serviceConnection)
    scriptType: bash
    scriptLocation: inlineScript
    inlineScript: |
      curl -fsSL https://aka.ms/install-azd.sh | bash
      export PATH=$PATH:~/.azd/bin

- task: Bash@3
  displayName: 'Run Pre-flight Checks'
  inputs:
    targetType: filePath
    filePath: './scripts/preflight-check.sh'
    arguments: '--environment-name ${{ parameters.environment }} --location ${{ parameters.location }}'

- task: PublishTestResults@2
  displayName: 'Publish Pre-flight Results'
  condition: always()
  inputs:
    testResultsFormat: 'JUnit'
    testResultsFiles: 'preflight-results.xml'
    testRunTitle: 'Pre-flight Validation'

Ringkasan Amalan Terbaik

โœ… Amalan Terbaik Pemeriksaan Pra-penerbangan

  1. Automasi Di Mana Mungkin

    • Integrasikan pemeriksaan ke dalam saluran CI/CD
    • Gunakan skrip untuk pengesahan yang boleh diulang
    • Simpan keputusan untuk rekod audit
  2. Pengesahan Khusus Persekitaran

    • Pemeriksaan berbeza untuk dev/staging/produksi
    • Keperluan keselamatan sesuai mengikut persekitaran
    • Pengoptimuman kos untuk persekitaran bukan produksi
  3. Liputan Komprehensif

    • Pengesahan dan kebenaran
    • Kuota sumber dan ketersediaan
    • Pengesahan templat dan sintaks
    • Keperluan keselamatan dan pematuhan
  4. Laporan Jelas

    • Penunjuk status berwarna
    • Mesej ralat terperinci dengan langkah pembetulan
    • Laporan ringkas untuk penilaian cepat
  5. Gagal Dengan Pantas

    • Hentikan penghantaran jika pemeriksaan kritikal gagal
    • Berikan panduan jelas untuk penyelesaian
    • Mudahkan pelaksanaan semula pemeriksaan

Perangkap Lazim Pra-penerbangan

  1. Melepaskan pengesahan untuk penghantaran "cepat"
  2. Pemeriksaan kebenaran tidak mencukupi sebelum penghantaran
  3. Mengabaikan had kuota sehingga penghantaran gagal
  4. Tidak mengesahkan templat dalam saluran CI/CD
  5. Ketiadaan pengesahan keselamatan untuk persekitaran produksi
  6. Anggaran kos tidak mencukupi menyebabkan kejutan bajet

Petua Pro: Jalankan pemeriksaan pra-penerbangan sebagai tugasan berasingan dalam saluran CI/CD anda sebelum tugasan penghantaran sebenar. Ini membolehkan anda mengesan masalah lebih awal dan memberikan maklum balas lebih cepat kepada pembangun.


Navigasi


Penafian:
Dokumen ini telah diterjemahkan menggunakan perkhidmatan terjemahan AI Co-op Translator. Walaupun kami berusaha untuk ketepatan, sila ambil maklum bahawa terjemahan automatik mungkin mengandungi kesilapan atau ketidaktepatan. Dokumen asal dalam bahasa asalnya harus dianggap sebagai sumber yang sahih. Untuk maklumat penting, terjemahan profesional oleh manusia adalah disyorkan. Kami tidak bertanggungjawab atas sebarang salah faham atau salah tafsir yang timbul daripada penggunaan terjemahan ini.