Microsoft Azure ตั้งแต่ศูนย์ถึงระดับมืออาชีพ: 100 ตัวอย่างด้วย CLI, Bicep และ Python
Microsoft Azure คือแพลตฟอร์มคลาวด์สำหรับรันเว็บไซต์ ฐานข้อมูล คอนเทนเนอร์ ไปป์ไลน์ข้อมูล และบริการ AI โดยไม่ต้องซื้อเซิร์ฟเวอร์ บทความนี้พาคุณจากการเข้าสู่ระบบครั้งแรกไปถึงการตั้งค่าที่พร้อมใช้งานจริงใน 100 ตัวอย่าง คุณจะได้เรียน Azure CLI กลุ่มทรัพยากรและแท็ก โครงสร้างพื้นฐานเป็นโค้ดด้วย Bicep ตัวตนด้วย managed identity และ RBAC เครื่องเสมือน App Service คอนเทนเนอร์และ Kubernetes ที่เก็บข้อมูลด้วย SAS และกฎวงจรชีวิต SQL และ Cosmos DB Functions แบบ serverless เครือข่ายเสมือนและ private endpoint Service Bus และ Event Hubs การเฝ้าดูด้วย Log Analytics และ Application Insights Key Vault และการควบคุมค่าใช้จ่าย หมายเหตุด้านความโปร่งใส: คำสั่งคลาวด์และตัวอย่าง SDK ยังไม่ได้รัน เพราะต้องใช้ subscription ของ Azure ตัวอย่างที่ระบุว่ารันได้ถูกรันบนคอมพิวเตอร์และแสดงผลลัพธ์จริงหลังโค้ด
สิ่งที่ต้องเตรียม
บัญชี Azure ที่มี subscription (การทดลองใช้ฟรีเพียงพอสำหรับตัวอย่างส่วนใหญ่) Azure CLI Python 3.10 ขึ้นไป และโปรแกรมแก้ไขโค้ดอย่าง Visual Studio Code ที่ติดตั้งส่วนขยาย Bicep ใช้ subscription สำหรับทดลองเท่านั้น และอย่าวางความลับจริงในคำสั่งหรือโค้ด ทรัพยากรบางอย่างมีค่าใช้จ่าย จึงควรลบกลุ่มทรัพยากรสำหรับทดลองเมื่อเสร็จ
วิธีใช้ตัวอย่าง
ตัวอย่าง bash ใช้กับ Azure CLI ตัวอย่าง Bicep ใช้กับ Azure CLI หรือ VS Code ตัวอย่าง Python ที่ไม่ต้องใช้ Azure รันได้ด้วย python และแสดงผลลัพธ์จริง ส่วนตัวอย่างที่เรียก Azure ต้องมี subscription ก่อนจึงจะรันได้
หัวข้อที่ 1: เริ่มต้นกับ Azure
Azure จัดระเบียบเป็น subscription กลุ่มทรัพยากร และทรัพยากร เรียนรู้การเข้าสู่ระบบ ตรวจว่าคำสั่งจะทำงานที่ใด และใช้ชื่อที่หาและคิดค่าใช้จ่ายได้ง่าย
Azure CLI และการเข้าสู่ระบบ
Azure CLI เป็นเครื่องมือเดียวสำหรับบริการ Azure ทั้งหมด ติดตั้ง รัน az login และตรวจด้วย az account show คำสั่งจะกระทำกับ subscription ที่เลือกอยู่ จึงควรยืนยันก่อนสร้างหรือลบทรัพยากรใด ๆ
ภูมิภาคและการตั้งชื่อ
ทรัพยากรทุกตัวอยู่ในภูมิภาค จึงควรเลือกภูมิภาคที่ใกล้ผู้ใช้และตรวจว่าบริการที่ต้องการมีที่นั่น ชื่อบัญชีที่เก็บข้อมูลเข้มงวด: 3 ถึง 24 ตัวอักษรเล็กและตัวเลข และต้องไม่ซ้ำกันทั่ว Azure
หลักการตั้งชื่อ
รูปแบบเช่น rg-app-env-region-01 ทำให้ชื่อสม่ำเสมอ คนหาทรัพยากรได้และเข้าใจค่าใช้จ่ายได้ สร้างชื่อด้วยฟังก์ชันเล็ก ๆ และใช้ซ้ำในทุกสคริปต์
ภาพประกอบ
ตัวอย่างที่ 1: ติดตั้ง Azure CLI และเข้าสู่ระบบ
ตั้งค่าเครื่องมือบรรทัดคำสั่งและเข้าสู่ระบบบัญชีของคุณ
winget install -e --id Microsoft.AzureCLI
az --version
az login
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 2: ตรวจสอบ subscription ที่ใช้งานอยู่
ดูว่าคำสั่งของคุณจะเปลี่ยนแปลง subscription ใด
az account show --output table
az account list --query "[].{name:name, id:id, default:isDefault}" --output table
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 3: สร้างกลุ่มทรัพยากร
ภาชนะสำหรับทรัพยากรที่เกี่ยวข้องกันในภูมิภาคเดียว
az group create --name rg-learn-dev --location southeastasia
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 4: แสดงรายการภูมิภาคของ Azure
หาภูมิภาคที่คุณสามารถ deploy ได้
az account list-locations --query "[?metadata.regionCategory=='Recommended'].name" --output tsv
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 5: ตรวจชื่อบัญชีที่เก็บข้อมูล
ชื่อที่เก็บข้อมูลยาว 3 ถึง 24 ตัวอักษรเล็กและตัวเลข
import re
def valid_storage_name(name):
return re.fullmatch(r"[a-z0-9]{3,24}", name) is not None
for candidate in ("stlearndev01", "Store-1", "ab", "a" * 25):
print(repr(candidate), valid_storage_name(candidate))
ผลลัพธ์:
'stlearndev01' True
'Store-1' False
'ab' False
'aaaaaaaaaaaaaaaaaaaaaaaaa' False
ตัวอย่างที่ 6: สร้างชื่อทรัพยากรตามรูปแบบ
ชื่อที่สม่ำเสมอทำให้หาและคิดค่าใช้จ่ายได้ง่าย
def resource_name(kind, app, env, region, index=1):
return f"{kind}-{app}-{env}-{region}-{index:02d}"
print(resource_name("rg", "shop", "dev", "sea"))
print(resource_name("app", "shop", "prod", "sea", 3))
ผลลัพธ์:
rg-shop-dev-sea-01
app-shop-prod-sea-03
หัวข้อที่ 2: กลุ่มทรัพยากร แท็ก และผลลัพธ์ของ CLI
กลุ่มทรัพยากรเก็บทรัพยากรของแอปหรือสภาพแวดล้อมหนึ่ง แท็กบันทึกว่าใครเป็นเจ้าของและมีค่าใช้จ่ายเท่าไร และ CLI กรองและจัดรูปแบบผลลัพธ์สำหรับคนหรือสคริปต์ได้
กลุ่มทรัพยากรและการลบ
วางทรัพยากรที่เกี่ยวข้องไว้ในกลุ่มเดียวเพื่อจัดการและลบพร้อมกัน การลบกลุ่มจะลบทุกอย่างข้างใน จึงใช้ --no-wait เมื่อแน่ใจเท่านั้น และไม่ควรลบกลุ่มที่คุณไม่ได้สร้าง
แท็กสำหรับความเป็นเจ้าของและค่าใช้จ่าย
แท็กคือคู่คีย์และค่า เช่น owner และ costcenter ใส่ตอนสร้างทรัพยากรและตรวจหาที่ขาดด้วยสคริปต์ รายงานค่าใช้จ่ายจัดกลุ่มตามแท็กได้
ผลลัพธ์ คิวรี และค่าเริ่มต้น
ใช้ --output table สำหรับคนและ json สำหรับสคริปต์ --query ใช้ JMESPath กรองฟิลด์ ตั้งกลุ่มและภูมิภาคเริ่มต้นด้วย az configure เพื่อไม่ต้องพิมพ์ซ้ำ
ตัวอย่างที่ 7: ติดแท็กให้กลุ่มทรัพยากร
แท็กบันทึกเจ้าของ ศูนย์ต้นทุน และสภาพแวดล้อม
az group update --name rg-learn-dev \
--tags owner=team-a costcenter=1001 environment=dev
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 8: ตรวจแท็กที่จำเป็น
หาทรัพยากรที่ไม่มีแท็กที่ทีมต้องการ
REQUIRED = {"owner", "costcenter", "environment"}
def missing_tags(tags):
return sorted(REQUIRED - set(tags))
print(missing_tags({"owner": "team-a", "environment": "dev"}))
print(missing_tags({"owner": "x", "costcenter": "1", "environment": "prod"}))
ผลลัพธ์:
['costcenter']
[]
ตัวอย่างที่ 9: ลบกลุ่มทรัพยากรโดยไม่รอ
ลบทรัพยากรทั้งกลุ่มด้วยคำสั่งเดียว
az group delete --name rg-learn-test --yes --no-wait
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 10: เลือกภูมิภาคที่ใกล้ที่สุดตามความหน่วง
เลือกภูมิภาคที่ตอบสนองเร็วที่สุดสำหรับผู้ใช้
latency_ms = {"southeastasia": 42, "japaneast": 71, "eastus": 210, "westeurope": 185}
best = min(latency_ms, key=latency_ms.get)
print("closest region:", best, latency_ms[best], "ms")
ผลลัพธ์:
closest region: southeastasia 42 ms
ตัวอย่างที่ 11: กรองผลลัพธ์ด้วยคิวรี JMESPath
แสดงเฉพาะฟิลด์และแถวที่ต้องการ
az vm list \
--query "[?powerState=='VM running'].{name:name, rg:resourceGroup}" \
--output table
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 12: เลือกรูปแบบผลลัพธ์
ตาราง JSON หรือ YAML สำหรับคนหรือสคริปต์
az group list --output table
az group list --output json
az group list --output yaml
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 13: วนลูปทรัพยากรในสคริปต์
รันคำสั่งหนึ่งครั้งสำหรับทุกกลุ่มทรัพยากร
for rg in $(az group list --query "[].name" -o tsv); do
echo "resource group: $rg"
done
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 14: ตั้งค่ากลุ่มและภูมิภาคเริ่มต้น
ไม่ต้องพิมพ์ตัวเลือกเดิมซ้ำในทุกคำสั่ง
az configure --defaults group=rg-learn-dev location=southeastasia
az configure --list-defaults
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
หัวข้อที่ 3: การเขียนสคริปต์และการอัตโนมัติ
งานที่ทำซ้ำควรอยู่ในสคริปต์ ลูป การลองใหม่ และการอ่าน JSON ทำให้คำสั่งครั้งเดียวกลายเป็นงานอัตโนมัติที่ไปป์ไลน์รันได้อย่างเชื่อถือได้
ลูปบนทรัพยากร
ลูปในเชลล์รันคำสั่งหนึ่งครั้งสำหรับทรัพยากรแต่ละตัวในรายการ ให้รายการสั้น และตรวจผลก่อนเปลี่ยนแปลงอะไร
การอ่านผลลัพธ์ JSON
ขอผลลัพธ์เป็น JSON จาก CLI แล้วอ่านด้วยโปรแกรมแทนการอ่านข้อความ จัดกลุ่มทรัพยากรตามชนิดเพื่อให้ได้สรุปที่อ่านง่าย
การลองใหม่และการถอยหลัง
Azure API จำกัดอัตราของไคลเอนต์ที่เรียกถี่เกินไป ลองใหม่ด้วยเวลารอที่เพิ่มขึ้น เพื่อให้สคริปต์กู้ตัวเองได้โดยไม่ถล่มบริการ
ตัวอย่างที่ 15: แยกผลลัพธ์ JSON ของ CLI
แปลงรายการทรัพยากรเป็นสรุป
import json
sample = """[{"name": "vm-web-01", "type": "Microsoft.Compute/virtualMachines", "location": "southeastasia"},
{"name": "stlearn01", "type": "Microsoft.Storage/storageAccounts", "location": "southeastasia"}]"""
resources = json.loads(sample)
by_type = {}
for r in resources:
by_type.setdefault(r["type"].split("/")[-1], []).append(r["name"])
for kind, names in sorted(by_type.items()):
print(kind, names)
ผลลัพธ์:
storageAccounts ['stlearn01']
virtualMachines ['vm-web-01']
ตัวอย่างที่ 16: ลองเรียกที่ล้มเหลวซ้ำพร้อมการรอ
รอนานขึ้นทุกครั้งหลังคำขอที่ถูกจำกัด
import time
def call_with_retry(fn, attempts=4, base_delay=0.05):
for n in range(attempts):
try:
return fn()
except ConnectionError as e:
if n == attempts - 1:
raise
delay = base_delay * (2 ** n)
print(f"attempt {n + 1} failed ({e}); retrying in {delay:.2f}s")
time.sleep(delay)
state = {"calls": 0}
def flaky_list():
state["calls"] += 1
if state["calls"] < 3:
raise ConnectionError("throttled")
return ["rg-learn-dev"]
print(call_with_retry(flaky_list))
ผลลัพธ์:
attempt 1 failed (throttled); retrying in 0.05s
attempt 2 failed (throttled); retrying in 0.10s
['rg-learn-dev']
ตัวอย่างที่ 17: ตรวจเวอร์ชันและส่วนขยายของ CLI
ทำให้เครื่องมือและส่วนขยายเป็นปัจจุบัน
az version
az extension list --output table
az extension add --name containerapp --upgrade
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 18: สร้าง service principal อย่างปลอดภัย
ตัวตนของแอปสำหรับงานอัตโนมัติ ด้วยขอบเขตแคบที่สุด
# Store the output securely: it contains a password. Never commit it to Git.
az ad sp create-for-rbac --name sp-learn-deploy --role Contributor \
--scopes /subscriptions/<subscription-id>/resourceGroups/rg-learn-dev
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
หัวข้อที่ 4: โครงสร้างพื้นฐานเป็นโค้ดด้วย Bicep
Bicep อธิบายทรัพยากร Azure เป็นโค้ด เทมเพลตตรวจทานได้ มีเวอร์ชัน และ deploy ได้เหมือนเดิมทุกครั้ง ซึ่งปลอดภัยกว่าการคลิกในพอร์टัล
ทรัพยากร พารามิเตอร์ และเอาต์พุต
การประกาศทรัพยากรระบุชนิดและเวอร์ชันของ API และกำหนดพร็อพเพอร์ตี้ พารามิเตอร์ทำให้เทมเพลตใช้ซ้ำได้ และ @secure ไม่ให้รหัสผ่านไปปรากฏในล็อก เอาต์พุตส่งค่าเช่น ID กลับไปยังผู้เรียก
โมดูล เงื่อนไข และลูป
โมดูลแบ่งเทมเพลตขนาดใหญ่เป็นไฟล์ที่ใช้ซ้ำได้ เงื่อนไขสร้างทรัพยากรเฉพาะเมื่อเป็นจริง เช่นในโปรดักชัน ลูปสร้างทรัพยากรหลายตัวจากรายการเดียว
การ deploy อย่างปลอดภัย
ใช้ az deployment group what-if เพื่อดูตัวอย่างการเปลี่ยนแปลงก่อนสร้าง ชื่อที่สร้างด้วย uniqueString หลีกเลี่ยงการชนกันระหว่างสภาพแวดล้อมใน subscription เดียวกัน
ตัวอย่างที่ 19: บัญชีที่เก็บข้อมูลแบบ Bicep ขั้นต่ำ
อธิบายบัญชีที่เก็บข้อมูลเป็นโค้ด
param location string = resourceGroup().location
param storageName string
resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: storageName
location: location
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
minimumTlsVersion: 'TLS1_2'
allowBlobPublicAccess: false
}
}
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 20: พารามิเตอร์ เอาต์พุต และค่าที่ปกปิด
ใช้เทมเพลตซ้ำและไม่ใส่รหัสผ่านในไฟล์
@minLength(3)
@maxLength(24)
param storageName string
@allowed([
'dev'
'test'
'prod'
])
param environment string = 'dev'
@secure()
param adminPassword string
output storageId string = storage.id
resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: storageName
location: resourceGroup().location
sku: { name: environment == 'prod' ? 'Standard_GRS' : 'Standard_LRS' }
kind: 'StorageV2'
}
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 21: deploy โมดูลจาก main.bicep
แบ่งเทมเพลตใหญ่เป็นโมดูลที่ใช้ซ้ำได้
// main.bicep
targetScope = 'resourceGroup'
module network './modules/network.bicep' = {
name: 'networkDeploy'
params: {
prefix: 'shop-dev'
}
}
output vnetId string = network.outputs.vnetId
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 22: ทรัพยากรแบบมีเงื่อนไข
สร้างทรัพยากรเฉพาะในโปรดักชัน
param environment string
resource logs 'Microsoft.OperationalInsights/workspaces@2022-10-01' = if (environment == 'prod') {
name: 'log-shop-prod'
location: resourceGroup().location
properties: {
retentionInDays: 90
}
}
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 23: วนลูปคอนเทนเนอร์ใน Bicep
สร้างคอนเทนเนอร์ blob หลายตัวจากรายการเดียว
param containerNames array = [
'uploads'
'exports'
'backups'
]
resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' existing = {
name: 'stlearndev01'
}
resource containers 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-05-01' = [for name in containerNames: {
name: '${storage.name}/default/${name}'
}]
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 24: ชื่อที่ไม่ซ้ำด้วย uniqueString
สร้างชื่อที่ไม่ชนกันใน subscription
param prefix string = 'shop'
var uniqueSuffix = uniqueString(resourceGroup().id)
var storageName = toLower('st${prefix}${uniqueSuffix}')
output generatedName string = storageName
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 25: deploy ไฟล์ Bicep
สร้างหรืออัปเดตทรัพยากรจากเทมเพลต
az deployment group create \
--resource-group rg-learn-dev \
--template-file main.bicep \
--parameters storageName=stlearndev01 environment=dev
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 26: ดูตัวอย่างการเปลี่ยนแปลงด้วย what-if
ดูก่อนว่าการ deploy จะเพิ่ม แก้ไข หรือลบอะไร
az deployment group what-if \
--resource-group rg-learn-dev \
--template-file main.bicep \
--parameters storageName=stlearndev01
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
หัวข้อที่ 5: ตัวตนและการควบคุมการเข้าถึง
ความปลอดภัยเริ่มจากการกำหนดว่าใครทำอะไรได้ Managed identity ให้แอปมีข้อมูลยืนยันตัวตนโดยไม่ต้องใช้รหัสผ่าน และ RBAC ให้สิทธิ์เฉพาะที่แต่ละตัวตนต้องการ
Managed identity
Managed identity คือบัญชีที่ Azure ดูแลให้แอปของคุณ แอปจึงได้โทเค็นโดยไม่ต้องเก็บความลับ ใช้ user-assigned identity เมื่อทรัพยากรหลายตัวใช้ตัวตนเดียวกัน
RBAC และสิทธิ์น้อยที่สุด
การกำหนดบทบาทเชื่อมตัวตนกับบทบาทในขอบเขต เช่นบัญชีที่เก็บข้อมูลหนึ่งบัญชี เลือกบทบาทในตัวที่ตรงกับงาน และสร้างบทบาทกำหนดเองเฉพาะเมื่อไม่มีบทบาทใดเหมาะ
Service principal และโทเค็น
Service principal คือตัวตนสำหรับงานอัตโนมัติ รหัสผ่านของมันเป็นความลับ จึงเก็บไว้ในที่เก็บความลับของไปป์ไลน์ โทเค็นคือสตริงที่ลงลายเซ็นและมีเวลาหมดอายุ ซึ่งอ่านได้จากส่วนเพย์โหลด
ตัวอย่างที่ 27: ตัวตนแบบ managed identity ที่ผู้ใช้กำหนด
ตัวตนที่แอปใช้โดยไม่ต้องเก็บรหัสผ่าน
param location string = resourceGroup().location
resource appIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: 'id-shop-dev'
location: location
}
output principalId string = appIdentity.properties.principalId
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 28: ให้สิทธิ์อ่านด้วย RBAC
ให้ตัวตนเพียงบทบาทที่จำเป็นเท่านั้น
PRINCIPAL_ID=$(az identity show --name id-shop-dev --resource-group rg-learn-dev --query principalId -o tsv)
az role assignment create \
--assignee-object-id "$PRINCIPAL_ID" \
--assignee-principal-type ServicePrincipal \
--role "Storage Blob Data Reader" \
--scope /subscriptions/<subscription-id>/resourceGroups/rg-learn-dev/providers/Microsoft.Storage/storageAccounts/stlearndev01
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 29: เข้าสู่ระบบ pipeline ด้วย service principal
งานอัตโนมัติเข้าสู่ระบบด้วยความลับจาก pipeline
az login --service-principal \
--username "$AZURE_CLIENT_ID" \
--password "$AZURE_CLIENT_SECRET" \
--tenant "$AZURE_TENANT_ID"
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 30: ตรวจการกำหนดบทบาท
ตรวจว่าใครทำอะไรได้กับทรัพยากรบ้าง
assignments = [
{"principal": "id-shop-dev", "role": "Storage Blob Data Reader", "scope": "stlearndev01"},
{"principal": "sp-learn-deploy", "role": "Contributor", "scope": "rg-learn-dev"},
{"principal": "id-shop-dev", "role": "Key Vault Secrets User", "scope": "kv-shop-dev"},
]
def roles_for(principal):
return sorted(a["role"] for a in assignments if a["principal"] == principal)
print(roles_for("id-shop-dev"))
print(roles_for("nobody"))
ผลลัพธ์:
['Key Vault Secrets User', 'Storage Blob Data Reader']
[]
ตัวอย่างที่ 31: เข้าสู่ระบบบน VM ด้วย managed identity
VM ได้โทเค็นโดยไม่ต้องมีรหัสผ่าน
az login --identity
az account show --query "user.assignedIdentityInfo" -o tsv
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 32: อ่านเวลาหมดอายุของโทเค็น JWT
โทเค็นมีเวลาหมดอายุอยู่ในส่วนเพย์โหลด
import base64
import json
def jwt_payload(token):
part = token.split(".")[1]
part += "=" * (-len(part) % 4)
return json.loads(base64.urlsafe_b64decode(part))
payload = {"aud": "https://management.azure.com/", "exp": 1767225600, "upn": "[email protected]"}
raw = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip("=")
token = f"header.{raw}.signature"
claims = jwt_payload(token)
print("audience:", claims["aud"])
print("expires at unix time:", claims["exp"])
ผลลัพธ์:
audience: https://management.azure.com/
expires at unix time: 1767225600
ตัวอย่างที่ 33: บทบาทกำหนดเองแบบสิทธิ์น้อยที่สุด
อนุญาตเพียงหนึ่งการกระทำบนขอบเขตเดียว
{
"Name": "Blob Uploader",
"IsCustom": true,
"Description": "Can upload blobs to one storage account only.",
"Actions": [],
"DataActions": [
"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write"
],
"AssignableScopes": [
"/subscriptions/<subscription-id>/resourceGroups/rg-learn-dev"
]
}
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 34: สร้างบทบาทกำหนดเอง
ลงทะเบียนนิยามบทบาทใน subscription
az role definition create --role-definition @blob-uploader.json
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
หัวข้อที่ 6: การประมวลผล: เครื่องเสมือนและ App Service
Azure รันโค้ดของคุณบนเครื่องเสมือนหรือแพลตฟอร์มที่จัดการให้ App Service ลดงานเซิร์ฟเวอร์ส่วนใหญ่ ส่วนเครื่องเสมือนให้การควบคุมระบบปฏิบัติการเต็มที่
เครื่องเสมือนและสเกลเซต
เครื่องเสมือนมีขนาด อิมเมจ ดิสก์ และอินเทอร์เฟซเครือข่าย สเกลเซตรันเครื่องเหมือนกันและเพิ่มหรือลดตามความต้องการ ปิดเครื่องพัฒนาตอนกลางคืนเพื่อประหยัดค่าใช้จ่าย
แพลน App Service และเว็บแอป
แพลนกำหนดเครื่องและราคา เว็บแอปรันบนแพลนนั้น deploy โค้ดเป็นไฟล์ zip ตั้งค่าการทำงานด้วยการตั้งค่าแอป และใช้สล็อตสำหรับทดสอบก่อนที่ผู้ใช้จะเห็นการเปลี่ยนแปลง
การตัดสินใจขยายอัตโนมัติ
กฎการขยายเปรียบเทียบเมตริก เช่น CPU เฉลี่ย กับเกณฑ์ แล้วเพิ่มหรือลดอินสแตนซ์ ระยะพักหลังการเปลี่ยนป้องกันไม่ให้ระบบสลับขนาดไปมาอย่างรวดเร็ว
ตัวอย่างที่ 35: สร้าง VM ของ Linux
เริ่มเครื่องเสมือนด้วยขนาดและอิมเมจที่เลือก
az vm create \
--resource-group rg-learn-dev \
--name vm-web-01 \
--image Ubuntu2204 \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 36: แสดงขนาด VM และดิสก์
ตรวจความจุและพื้นที่เก็บข้อมูลก่อนปรับขนาด
az vm list-sizes --location southeastasia --output table | head -n 10
az vm disk list --resource-group rg-learn-dev --output table
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 37: ชุดสเกลของเครื่องเสมือน
รัน VM ที่เหมือนกันซึ่งขยายและหดพร้อมกัน
resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2023-09-01' = {
name: 'vmss-web'
location: resourceGroup().location
sku: {
name: 'Standard_B2s'
capacity: 2
}
properties: {
upgradePolicy: { mode: 'Rolling' }
// osProfile, networkProfile and storageProfile go here
}
}
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 38: ปิดอัตโนมัติสำหรับ VM ของการพัฒนา
ปิดเครื่องทดสอบทุกคืนเพื่อประหยัดค่าใช้จ่าย
az vm auto-shutdown --resource-group rg-learn-dev --name vm-web-01 --time 2100
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 39: สร้าง App Service plan และเว็บแอป
โฮสต์เว็บแอปบนเซิร์ฟเวอร์ Linux ที่ระบบจัดการให้
az appservice plan create --name plan-shop-dev --resource-group rg-learn-dev --sku B1 --is-linux
az webapp create --name app-shop-dev-01 --resource-group rg-learn-dev \
--plan plan-shop-dev --runtime "PYTHON:3.12"
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 40: deploy โค้ดจากไฟล์ zip
อัปโหลดแพ็กเกจแอปไปยังเว็บแอป
zip -r app.zip . -x "*.git*"
az webapp deploy --resource-group rg-learn-dev --name app-shop-dev-01 \
--src-path app.zip --type zip
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 41: การตั้งค่าแอปและสล็อตสำหรับทดสอบ
ทดสอบเวอร์ชันใหม่ก่อนที่ผู้ใช้จะเห็น
az webapp config appsettings set --resource-group rg-learn-dev --name app-shop-dev-01 \
--settings ENVIRONMENT=dev LOG_LEVEL=info
az webapp deployment slot create --resource-group rg-learn-dev --name app-shop-dev-01 --slot staging
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 42: การตัดสินใจขยายจาก CPU
เพิ่มอินสแตนซ์เมื่อยุ่ง และลดเมื่อว่าง
def scale_decision(cpu_samples, instances, minimum=1, maximum=5):
average = sum(cpu_samples) / len(cpu_samples)
if average > 75 and instances < maximum:
return instances + 1, f"scale out (avg CPU {average:.0f}%)"
if average < 25 and instances > minimum:
return instances - 1, f"scale in (avg CPU {average:.0f}%)"
return instances, f"hold (avg CPU {average:.0f}%)"
print(scale_decision([82, 90, 78], 2))
print(scale_decision([10, 12, 15], 2))
print(scale_decision([40, 45, 50], 2))
ผลลัพธ์:
(3, 'scale out (avg CPU 83%)')
(1, 'scale in (avg CPU 12%)')
(2, 'hold (avg CPU 45%)')
หัวข้อที่ 7: คอนเทนเนอร์: Registry, Container Apps และ Kubernetes
คอนเทนเนอร์บรรจุแอปพร้อมทุกอย่างที่ต้องใช้ Azure เก็บอิมเมจใน registry และรันใน Container Apps หรือ Kubernetes ขึ้นอยู่กับการควบคุมที่ต้องการ
Azure Container Registry
Registry คือที่เก็บอิมเมจแบบส่วนตัว สร้างอิมเมจใน Azure ด้วย az acr build เพื่อไม่ให้การสร้างขึ้นกับคอมพิวเตอร์ของคุณ แล้วส่งผลลัพธ์ไปยัง registry
Container Apps และ AKS
Container Apps รันคอนเทนเนอร์โดยไม่ต้องจัดการคลัสเตอร์และลดเป็นศูนย์ได้ AKS คือ Kubernetes ที่จัดการให้สำหรับระบบขนาดใหญ่ AKS ดึงอิมเมจจาก registry ได้ด้วย managed identity จึงไม่ต้องมีรหัสผ่าน
แท็กและการทำความสะอาด
ติดแท็กอิมเมจแต่ละตัวด้วยเวอร์ชัน วันที่ และคอมมิต เพื่อให้ย้อนกลับได้ ตั้งงาน purge ตามกำหนดเวลาเพื่อลบอิมเมจเก่าที่ไม่มีแท็กและควบคุมค่าใช้จ่ายด้านที่เก็บ
ตัวอย่างที่ 43: สร้าง container registry
ที่เก็บอิมเมจคอนเทนเนอร์แบบส่วนตัว
az acr create --resource-group rg-learn-dev --name acrshopdev01 --sku Basic
az acr login --name acrshopdev01
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 44: สร้างและอัปโหลดอิมเมจ
สร้างอิมเมจใน Azure และเก็บไว้ใน registry
az acr build --registry acrshopdev01 --image shop-api:1.0.0 .
az acr repository show-tags --name acrshopdev01 --repository shop-api -o table
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 45: รันแอปคอนเทนเนอร์
รันคอนเทนเนอร์โดยไม่ต้องดูแลเซิร์ฟเวอร์
az containerapp env create --name cae-shop-dev --resource-group rg-learn-dev --location southeastasia
az containerapp create --name ca-shop-api --resource-group rg-learn-dev \
--environment cae-shop-dev \
--image acrshopdev01.azurecr.io/shop-api:1.0.0 \
--target-port 8080 --ingress external --min-replicas 0 --max-replicas 3
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 46: สร้างคลัสเตอร์ AKS
คลัสเตอร์ Kubernetes ที่จัดการให้ และดึงอิมเมจจาก registry
az aks create \
--resource-group rg-learn-dev \
--name aks-shop-dev \
--node-count 2 \
--enable-managed-identity \
--attach-acr acrshopdev01 \
--generate-ssh-keys
az aks get-credentials --resource-group rg-learn-dev --name aks-shop-dev
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 47: deploy ไปยัง Kubernetes
นำ manifest ไปใช้และรอให้การเผยแพร่เสร็จ
kubectl apply -f deployment.yaml
kubectl rollout status deployment/shop-api
kubectl get pods -l app=shop-api
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 48: manifest สำหรับ deployment ของ Kubernetes
อธิบาย pod จำนวนสำเนา และทรัพยากร
apiVersion: apps/v1
kind: Deployment
metadata:
name: shop-api
spec:
replicas: 2
selector:
matchLabels:
app: shop-api
template:
metadata:
labels:
app: shop-api
spec:
containers:
- name: shop-api
image: acrshopdev01.azurecr.io/shop-api:1.0.0
ports:
- containerPort: 8080
resources:
requests:
cpu: 100m
memory: 128Mi
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 49: สร้างแท็กของอิมเมจ
ติดแท็กอิมเมจด้วยเวอร์ชัน วันที่ และคอมมิต
from datetime import date
def image_tag(version, commit, when):
short = commit[:7]
return f"{version}-{when.strftime('%Y%m%d')}-{short}"
print(image_tag("1.4.2", "9f3c1ab7e54d0a12", date(2026, 1, 15)))
ผลลัพธ์:
1.4.2-20260115-9f3c1ab
ตัวอย่างที่ 50: ลบอิมเมจเก่าด้วยงานตามกำหนดเวลา
ลบอิมเมจที่ไม่มีแท็กตามตารางเพื่อประหยัดพื้นที่
az acr task create --name purge-old-images --registry acrshopdev01 \
--cmd "acr purge --filter 'shop-api:.*' --ago 30d --untagged" \
--schedule "0 1 * * *" --context /dev/null
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
หัวข้อที่ 8: ที่เก็บข้อมูล: Blob, คิว และการควบคุมการเข้าถึง
บัญชีที่เก็บข้อมูลเก็บไฟล์ ข้อความ และตาราง รักษาความปลอดภัยการเข้าถึงด้วย Entra ID ใช้ลิงก์ SAS อายุสั้นเมื่อต้องแชร์ และให้กฎวงจรชีวิตย้ายข้อมูลเก่าไปยังชั้นที่ถูกกว่า
Blob และพาธที่ตั้งชื่อ
คอนเทนเนอร์ blob เก็บไฟล์ ใช้พาธที่มีอุปกรณ์และวันที่เพื่อแสดงรายการหรือลบข้อมูลของวันหนึ่งได้เร็ว ปิดการเข้าถึงสาธารณะไว้ เว้นแต่เนื้อหานั้นต้องเปิดเป็นสาธารณะ
ลายเซ็นการเข้าถึงที่ใช้ร่วมกัน
ลิงก์ SAS ให้สิทธิ์จำกัดในช่วงเวลาสั้น ให้เฉพาะสิทธิ์ที่จำเป็น เช่นอ่านอย่างเดียว และเลือกเวลาหมดอายุที่สั้นที่สุดที่ใช้งานได้
กฎวงจรชีวิตและคิว
กฎวงจรชีวิตย้าย blob ไปยังชั้น cool หรือ archive และลบหลังจำนวนวันที่กำหนด คิวเก็บข้อความให้ผู้ทำงานเบื้องหลัง งานที่ช้าจึงไม่บล็อกคำขอเว็บ
ตัวอย่างที่ 51: สร้างบัญชีที่เก็บข้อมูล
ค่าเริ่มต้นที่ปลอดภัย: TLS 1.2 และไม่เปิดให้เข้าถึง blob สาธารณะ
az storage account create \
--name stlearndev01 \
--resource-group rg-learn-dev \
--location southeastasia \
--sku Standard_LRS \
--kind StorageV2 \
--min-tls-version TLS1_2 \
--allow-blob-public-access false
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 52: พาธของ blob แบ่งตามวันที่
จัดข้อมูลตามอุปกรณ์และวันที่เพื่อให้การค้นหาเร็ว
from datetime import datetime
def blob_path(device, when, filename):
return f"telemetry/{device}/{when:%Y/%m/%d}/{when:%H%M%S}-{filename}"
print(blob_path("sensor-7", datetime(2026, 1, 15, 8, 30, 5), "batch.json"))
ผลลัพธ์:
telemetry/sensor-7/2026/01/15/083005-batch.json
ตัวอย่างที่ 53: อัปโหลด blob
คัดลอกไฟล์เข้าคอนเทนเนอร์ด้วย CLI
az storage container create --name uploads --account-name stlearndev01 --auth-mode login
az storage blob upload --account-name stlearndev01 --container-name uploads \
--name reports/2026-01.csv --file ./report.csv --auth-mode login
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 54: อัปโหลดจาก Python ด้วย Entra ID
ใช้ตัวตน Azure แทนคีย์ของบัญชี
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient
client = BlobServiceClient(
account_url="https://stlearndev01.blob.core.windows.net",
credential=DefaultAzureCredential(),
)
blob = client.get_blob_client(container="uploads", blob="reports/2026-01.csv")
with open("report.csv", "rb") as data:
blob.upload_blob(data, overwrite=True)
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 55: สร้าง SAS อายุสั้น
ลิงก์ที่หมดอายุและให้สิทธิ์อ่านเท่านั้น
EXPIRY=$(date -u -d "+1 hour" '+%Y-%m-%dT%H:%MZ')
az storage blob generate-sas --account-name stlearndev01 --container-name uploads \
--name reports/2026-01.csv --permissions r --expiry "$EXPIRY" --auth-mode login --as-user --output tsv
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 56: อธิบายสิทธิ์ของ SAS
อธิบายว่าลายเซ็นการเข้าถึงที่ใช้ร่วมกันอนุญาตอะไรและนานเท่าไร
from datetime import datetime, timedelta, timezone
def describe_sas(permissions, expiry):
names = {"r": "read", "w": "write", "d": "delete", "c": "create"}
allowed = ", ".join(names[p] for p in permissions)
left = expiry - datetime(2026, 1, 15, 8, 0, tzinfo=timezone.utc)
return f"allows {allowed} for {int(left.total_seconds() // 60)} minutes"
print(describe_sas("rw", datetime(2026, 1, 15, 9, 0, tzinfo=timezone.utc)))
ผลลัพธ์:
allows read, write for 60 minutes
ตัวอย่างที่ 57: กฎวงจรชีวิตของ blob
ย้ายข้อมูลเก่าไปยังที่เก็บที่ถูกกว่า แล้วลบเมื่อถึงเวลา
{
"rules": [
{
"enabled": true,
"name": "archive-telemetry",
"type": "Lifecycle",
"definition": {
"filters": { "blobTypes": ["blockBlob"], "prefixMatch": ["telemetry/"] },
"actions": {
"baseBlob": {
"tierToCool": { "daysAfterModificationGreaterThan": 30 },
"delete": { "daysAfterModificationGreaterThan": 365 }
}
}
}
}
]
}
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 58: คิวจัดเก็บสำหรับงานเบื้องหลัง
ใส่งานลงคิวและให้ผู้ทำงานประมวลผลภายหลัง
az storage queue create --name jobs --account-name stlearndev01 --auth-mode login
az storage message put --queue-name jobs --content "resize:photo-42" \
--account-name stlearndev01 --auth-mode login
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
หัวข้อที่ 9: ฐานข้อมูล: Azure SQL และ Cosmos DB
Azure มีฐานข้อมูลเชิงสัมพันธ์ที่จัดการให้ และฐานข้อมูล NoSQL ที่กระจายทั่วโลก เชื่อมต่อด้วยตัวตนแทนรหัสผ่าน และใช้พารามิเตอร์ในคิวรีเสมอ
Azure SQL
Azure SQL คือฐานข้อมูล SQL Server ที่จัดการให้ เปิดการยืนยันตัวตนด้วย Microsoft Entra ID และ private endpoint ฐานข้อมูลจึงไม่มีรหัสผ่านที่เก็บไว้และไม่มีที่อยู่สาธารณะ
คิวรีแบบมีพารามิเตอร์
ส่งอินพุตของผู้ใช้เป็นพารามิเตอร์ อย่าเอาข้อความไปต่อเป็น SQL ฐานข้อมูลจะถือว่าอินพุตเป็นข้อมูล ซึ่งป้องกัน SQL injection
Cosmos DB และคีย์พาร์ติชัน
Cosmos DB เก็บเอกสาร JSON ในคอนเทนเนอร์ คีย์พาร์ติชันกำหนดการกระจายข้อมูลไปยังเครื่อง คีย์ที่มีค่าต่างกันมาก เช่นไอดีลูกค้า ทำให้โหลดสมดุล
ตัวอย่างที่ 59: เซิร์ฟเวอร์และฐานข้อมูล Azure SQL
ฐานข้อมูลเชิงสัมพันธ์ที่จัดการให้ พร้อมเครือข่ายส่วนตัว
az sql server create --name sql-shop-dev-01 --resource-group rg-learn-dev \
--location southeastasia --enable-public-network false --enable-ad-only-auth \
--external-admin-principal-type User --external-admin-name [email protected]
az sql db create --resource-group rg-learn-dev --server sql-shop-dev-01 \
--name shopdb --service-objective S0
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 60: เชื่อมต่อ Azure SQL โดยไม่ใช้รหัสผ่าน
ยืนยันตัวตนด้วย Entra ID แทนรหัสผ่านที่เก็บไว้
import pyodbc
conn = pyodbc.connect(
"Driver={ODBC Driver 18 for SQL Server};"
"Server=tcp:sql-shop-dev-01.database.windows.net,1433;"
"Database=shopdb;Encrypt=yes;"
"Authentication=ActiveDirectoryDefault;"
)
cursor = conn.cursor()
cursor.execute("SELECT TOP 5 name FROM sys.tables")
print([row.name for row in cursor.fetchall()])
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 61: คิวรีแบบมีพารามิเตอร์
ส่งค่าเป็นพารามิเตอร์เพื่อไม่ให้อินพุตเปลี่ยนคิวรี
import sqlite3
conn = sqlite3.connect(":memory:")
conn.execute("CREATE TABLE orders (id INTEGER, customer TEXT, total REAL)")
conn.executemany("INSERT INTO orders VALUES (?, ?, ?)",
[(1, "ana", 120.0), (2, "ben", 75.5)])
customer = "ana' OR '1'='1" # hostile input stays a plain value
rows = conn.execute("SELECT id, total FROM orders WHERE customer = ?", (customer,)).fetchall()
print("matches:", rows)
conn.close()
ผลลัพธ์:
matches: []
ตัวอย่างที่ 62: สร้างคอนเทนเนอร์ Cosmos DB
ฐานข้อมูลที่กระจายทั่วโลกโดยมีคีย์พาร์ติชัน
az cosmosdb create --name cosmos-shop-dev-01 --resource-group rg-learn-dev \
--locations regionName=southeastasia failoverPriority=0
az cosmosdb sql database create --account-name cosmos-shop-dev-01 --resource-group rg-learn-dev \
--name shop
az cosmosdb sql container create --account-name cosmos-shop-dev-01 --resource-group rg-learn-dev \
--database-name shop --name orders --partition-key-path "/customerId"
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 63: เขียนรายการลง Cosmos DB
เก็บเอกสาร JSON ในคอนเทนเนอร์
from azure.cosmos import CosmosClient
from azure.identity import DefaultAzureCredential
client = CosmosClient("https://cosmos-shop-dev-01.documents.azure.com:443/", DefaultAzureCredential())
container = client.get_database_client("shop").get_container_client("orders")
container.upsert_item({"id": "o-1001", "customerId": "ana", "total": 120.0})
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 64: กระจายรายการด้วยแฮชของคีย์พาร์ติชัน
คีย์ที่ดีกระจายข้อมูลเท่า ๆ กันในพาร์ติชัน
import hashlib
def partition_for(key, partitions=4):
digest = hashlib.sha256(key.encode("utf-8")).hexdigest()
return int(digest, 16) % partitions
counts = [0, 0, 0, 0]
for customer in ["ana", "ben", "chai", "dao", "eve", "fon", "gus", "hana"]:
counts[partition_for(customer)] += 1
print("items per partition:", counts)
ผลลัพธ์:
items per partition: [4, 1, 1, 2]
หัวข้อที่ 10: Serverless ด้วย Azure Functions
Azure Functions รันโค้ดชิ้นเล็ก ๆ เมื่อเกิดเหตุการณ์ ไม่ว่าจะเป็นคำขอ HTTP ตัวจับเวลา หรือข้อความในคิว คุณจ่ายตามการทำงานและไม่ต้องจัดการเซิร์ฟเวอร์
ทริกเกอร์และ bindings
ทริกเกอร์เริ่มฟังก์ชัน เช่นคำขอ HTTP หรือตัวจับเวลา Bindings เชื่อมฟังก์ชันกับบริการอื่น เช่นเขียนลงคิว จึงต้องเขียนโค้ดเชื่อมต่อน้อยลง
ตัวจับเวลาและตารางเวลา cron
ทริกเกอร์ตัวจับเวลาใช้นิพจน์ NCRONTAB หกช่อง โดยวินาทีอยู่ก่อน นิพจน์ 0 */5 * * * * รันทุกห้านาที
การประมวลผลแบบ idempotent
คิวอาจส่งข้อความเดียวกันมากกว่าหนึ่งครั้ง บันทึกไอดีที่ประมวลผลแล้วและข้ามรายการซ้ำ เพื่อให้การรันงานสองครั้งไม่เรียกเก็บเงินลูกค้าสองครั้ง
ตัวอย่างที่ 65: สร้างแอปฟังก์ชัน
โค้ดแบบ serverless บนแพลน Consumption
az storage account create --name stfuncshopdev01 --resource-group rg-learn-dev --sku Standard_LRS
az functionapp create --name func-shop-dev-01 --resource-group rg-learn-dev \
--storage-account stfuncshopdev01 --consumption-plan-location southeastasia \
--runtime python --runtime-version 3.12 --functions-version 4 --os-type Linux
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 66: ฟังก์ชันที่ถูกเรียกด้วย HTTP
รันโค้ดเมื่อมีคำขอเว็บเข้ามา
import azure.functions as func
app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)
@app.route(route="hello", methods=["GET"])
def hello(req: func.HttpRequest) -> func.HttpResponse:
name = req.params.get("name", "world")
return func.HttpResponse(f"Hello, {name}!", status_code=200)
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 67: ฟังก์ชันตัวจับเวลาพร้อมตารางเวลา cron
รันโค้ดทุกห้านาทีโดยไม่ต้องมีเซิร์ฟเวอร์
import logging
import azure.functions as func
app = func.FunctionApp()
@app.timer_trigger(schedule="0 */5 * * * *", arg_name="timer", run_on_startup=False)
def every_five_minutes(timer: func.TimerRequest) -> None:
logging.info("checking sensors")
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 68: การรันครั้งถัดไปของนิพจน์ cron
คำนวณว่าตารางเวลาจะทำงานครั้งต่อไปเมื่อใด
def next_minutes(expression, current_minute):
field = expression.split()[1] # minute field, for example */5
step = int(field.removeprefix("*/"))
return step - (current_minute % step) if current_minute % step else step
for minute in (0, 3, 12, 14):
print(f"at minute {minute:2d}: next run in {next_minutes('0 */5 * * * *', minute)} min")
ผลลัพธ์:
at minute 0: next run in 5 min
at minute 3: next run in 2 min
at minute 12: next run in 3 min
at minute 14: next run in 1 min
ตัวอย่างที่ 69: เผยแพร่แอปฟังก์ชัน
นำโค้ด Python ไปใช้บน Azure Functions
func azure functionapp publish func-shop-dev-01 --python
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 70: ฟังก์ชันที่ถูกเรียกจากคิว
ประมวลผลข้อความแต่ละรายการและเขียนผลลัพธ์ลงคิวอื่น
import azure.functions as func
app = func.FunctionApp()
@app.queue_trigger(arg_name="msg", queue_name="jobs", connection="AzureWebJobsStorage")
@app.queue_output(arg_name="out", queue_name="done", connection="AzureWebJobsStorage")
def process(msg: func.QueueMessage, out: func.Out[str]) -> None:
out.set(f"processed:{msg.get_body().decode('utf-8')}")
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 71: การจัดการข้อความแบบ idempotent
ประมวลผลข้อความเพียงครั้งเดียวแม้จะมาถึงซ้ำ
processed_ids = set()
def handle(message):
if message["id"] in processed_ids:
return "skipped duplicate"
processed_ids.add(message["id"])
return f"processed {message['id']}"
events = [{"id": "e1"}, {"id": "e2"}, {"id": "e1"}]
for event in events:
print(handle(event))
ผลลัพธ์:
processed e1
processed e2
skipped duplicate
ตัวอย่างที่ 72: การอ้างอิงความลับจาก Key Vault ในการตั้งค่าแอป
โหลดความลับเข้าแอปโดยไม่ต้องคัดลอก
az functionapp config appsettings set --name func-shop-dev-01 --resource-group rg-learn-dev \
--settings "[email protected](VaultName=kv-shop-dev;SecretName=db-password)"
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
หัวข้อที่ 11: เครือข่าย: เครือข่ายเสมือน NSG และ Private Endpoint
เครือข่ายเสมือนคือเครือข่ายส่วนตัวของคุณภายใน Azure ซับเน็ตแยกชั้น กฎความปลอดภัยจำกัดทราฟิก และ private endpoint ทำให้บริการไม่อยู่บนอินเทอร์เน็ตสาธารณะ
เครือข่ายเสมือนและซับเน็ต
เลือกช่วงที่อยู่ เช่น 10.10.0.0/16 แล้วแบ่งเป็นซับเน็ตสำหรับเว็บและข้อมูล Azure สงวนห้าที่อยู่ในทุกซับเน็ต ดังนั้น /24 ให้ที่อยู่ที่ใช้ได้ 251 ที่อยู่
Network security group
NSG คือรายการกฎอนุญาตและปฏิเสธที่มีลำดับความสำคัญ อนุญาตเฉพาะพอร์ตที่จำเป็น เช่น 443 สำหรับ HTTPS และปฏิเสธที่เหลือโดยค่าเริ่มต้น
Private endpoint และ DNS
Private endpoint ให้บริการมี IP ส่วนตัวภายในเครือข่ายของคุณ โซน DNS ส่วนตัวทำให้ชื่อของบริการแปลงเป็นที่อยู่นั้น แอปจึงไม่ต้องแก้โค้ด
ตัวอย่างที่ 73: เครือข่ายเสมือนและซับเน็ต
เครือข่ายส่วนตัวที่แยกซับเน็ตสำหรับเว็บและข้อมูล
az network vnet create --name vnet-shop-dev --resource-group rg-learn-dev \
--address-prefix 10.10.0.0/16 --subnet-name snet-web --subnet-prefix 10.10.1.0/24
az network vnet subnet create --vnet-name vnet-shop-dev --resource-group rg-learn-dev \
--name snet-data --address-prefixes 10.10.2.0/24
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 74: กฎ network security group
อนุญาตเฉพาะ HTTPS จากอินเทอร์เน็ต
az network nsg create --name nsg-web --resource-group rg-learn-dev
az network nsg rule create --nsg-name nsg-web --resource-group rg-learn-dev \
--name allow-https --priority 100 --direction Inbound --access Allow \
--protocol Tcp --destination-port-ranges 443 --source-address-prefixes Internet
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 75: Private endpoint สำหรับที่เก็บข้อมูล
เข้าถึงบัญชีที่เก็บข้อมูลได้จากภายในเครือข่ายเท่านั้น
az network private-endpoint create --name pe-storage --resource-group rg-learn-dev \
--vnet-name vnet-shop-dev --subnet snet-data \
--private-connection-resource-id $(az storage account show -n stlearndev01 -g rg-learn-dev --query id -o tsv) \
--group-id blob --connection-name conn-storage
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 76: โซน DNS ส่วนตัว
แปลงชื่อ private endpoint ภายในเครือข่ายเสมือน
az network private-dns zone create --resource-group rg-learn-dev \
--name privatelink.blob.core.windows.net
az network private-dns link vnet create --resource-group rg-learn-dev \
--zone-name privatelink.blob.core.windows.net --name link-shop \
--virtual-network vnet-shop-dev --registration-enabled false
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 77: Load balancer สาธารณะ
กระจายทราฟิกขาเข้าไปยังเครื่องเสมือนหลายเครื่อง
az network public-ip create --name pip-lb --resource-group rg-learn-dev --sku Standard
az network lb create --name lb-shop --resource-group rg-learn-dev --sku Standard \
--public-ip-address pip-lb --backend-pool-name be-web
az network lb probe create --lb-name lb-shop --resource-group rg-learn-dev \
--name probe-https --protocol Tcp --port 443
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 78: เครื่องคิดขนาดซับเน็ต
นับจำนวนที่อยู่ที่ใช้ได้ในบล็อก CIDR
import ipaddress
def usable_hosts(cidr):
net = ipaddress.ip_network(cidr)
return net.num_addresses - 5 # Azure reserves 5 addresses in every subnet
for block in ("10.10.1.0/24", "10.10.2.0/27", "10.10.0.0/16"):
print(block, usable_hosts(block))
ผลลัพธ์:
10.10.1.0/24 251
10.10.2.0/27 27
10.10.0.0/16 65531
หัวข้อที่ 12: การส่งข้อความและสตรีม: Service Bus และ Event Hubs
บริการคุยกันผ่านข้อความ Service Bus เหมาะกับข้อความทางธุรกิจที่เชื่อถือได้ ส่วน Event Hubs เหมาะกับสตรีมปริมาณมาก เช่นเทเลเมทรี
คิว Service Bus
คิวเก็บข้อความไว้จนกว่าผู้รับจะปิดข้อความ ปิดข้อความเมื่อประมวลผลเสร็จแล้วเท่านั้น เพื่อให้เมื่อระบบล่มเกิดการลองใหม่แทนการสูญเสียคำสั่งซื้อ ข้อความที่ล้มเหลวบ่อยเกินไปจะไปยังคิว dead-letter
Event Hubs และพาร์ติชัน
Event hub แบ่งสตรีมเป็นพาร์ติชันที่ผู้อ่านหลายคนอ่านขนานกันได้ ส่งเหตุการณ์เป็นชุด และให้แต่ละชุดมีขนาดไม่เกินขีดจำกัด
การเลือกระหว่างสอง
ใช้ Service Bus เมื่อแต่ละข้อความสำคัญและต้องประมวลผลตามที่ตั้งใจพอดี ใช้ Event Hubs เมื่อรวบรวมเหตุการณ์จำนวนมากและประมวลผลตามลำดับภายในพาร์ติชันได้
ตัวอย่างที่ 79: คิว Service Bus
การส่งข้อความที่เชื่อถือได้ระหว่างแอปพร้อม dead-letter
az servicebus namespace create --name sb-shop-dev --resource-group rg-learn-dev --location southeastasia --sku Standard
az servicebus queue create --namespace-name sb-shop-dev --resource-group rg-learn-dev \
--name orders --max-delivery-count 5 --dead-lettering-on-message-expiration true
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 80: ส่งข้อความ Service Bus
ใส่คำสั่งซื้อลงคิวจาก Python
from azure.identity import DefaultAzureCredential
from azure.servicebus import ServiceBusClient, ServiceBusMessage
with ServiceBusClient("sb-shop-dev.servicebus.windows.net", DefaultAzureCredential()) as client:
with client.get_queue_sender("orders") as sender:
sender.send_messages(ServiceBusMessage('{"orderId": "o-1001"}'))
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 81: รับและปิดข้อความ
ลบข้อความเมื่อประมวลผลเสร็จแล้วเท่านั้น
from azure.identity import DefaultAzureCredential
from azure.servicebus import ServiceBusClient
with ServiceBusClient("sb-shop-dev.servicebus.windows.net", DefaultAzureCredential()) as client:
with client.get_queue_receiver("orders", max_wait_time=5) as receiver:
for msg in receiver:
print(str(msg))
receiver.complete_message(msg) # removes it only after processing succeeded
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 82: Event Hubs สำหรับข้อมูลเทเลเมทรี
สตรีมที่รับเหตุการณ์หลายล้านรายการต่อวินาที
az eventhubs namespace create --name evhns-shop-dev --resource-group rg-learn-dev --location southeastasia --sku Standard
az eventhubs eventhub create --name telemetry --namespace-name evhns-shop-dev --resource-group rg-learn-dev \
--partition-count 4 --message-retention 1
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 83: ส่งเป็นชุดไปยัง Event Hubs
จัดเหตุการณ์เป็นชุดเพื่อประสิทธิภาพ
import json
from azure.eventhub import EventData, EventHubProducerClient
from azure.identity import DefaultAzureCredential
producer = EventHubProducerClient(
fully_qualified_namespace="evhns-shop-dev.servicebus.windows.net",
eventhub_name="telemetry",
credential=DefaultAzureCredential(),
)
with producer:
batch = producer.create_batch()
batch.add(EventData(json.dumps({"device": "sensor-7", "temp_c": 21.5})))
producer.send_batch(batch)
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 84: แบ่งข้อความตามขนาดสูงสุด
ให้แต่ละชุดมีขนาดไม่เกินที่กำหนด
def make_batches(messages, limit_bytes=60):
batches, current, size = [], [], 0
for msg in messages:
n = len(msg.encode("utf-8"))
if current and size + n > limit_bytes:
batches.append(current)
current, size = [], 0
current.append(msg)
size += n
if current:
batches.append(current)
return batches
events = [f'{{"id": {i}, "temp": 21.{i}}}' for i in range(6)]
for number, batch in enumerate(make_batches(events), start=1):
print("batch", number, len(batch), "messages")
ผลลัพธ์:
batch 1 2 messages
batch 2 2 messages
batch 3 2 messages
หัวข้อที่ 13: การเฝ้าดู: Log Analytics, Application Insights และการแจ้งเตือน
แก้สิ่งที่มองไม่เห็นไม่ได้ Azure Monitor เก็บล็อกและเมตริก Log Analytics ให้คุณคิวรีด้วย KQL และการแจ้งเตือนบอกทีมว่ามีปัญหา
Log Analytics และ KQL
พื้นที่ทำงาน Log Analytics เก็บล็อกจากทรัพยากรหลายตัว Kusto Query Language กรอง สรุป และทำกราฟ เช่นนับความล้มเหลวต่อชั่วโมง
Application Insights
Application Insights ติดตามคำขอ การพึ่งพา และเหตุการณ์ที่กำหนดเองจากโค้ดของคุณ ใช้หาว่าการเรียกใดช้า ไม่ใช่แค่รู้ว่าแอปช้า
การแจ้งเตือนที่ไม่เกิดการเตือนผิด
การแจ้งเตือนเมตริกทำงานเมื่อค่าข้ามเกณฑ์ ให้เงื่อนไขเป็นจริงต่อเนื่องหลายตัวอย่าง เพื่อให้ค่าพุ่งเพียงครั้งเดียวไม่ปลุกวิศวกรเวร
ตัวอย่างที่ 85: พื้นที่ทำงาน Log Analytics
ที่รวมศูนย์สำหรับคิวรีล็อกจากทุกทรัพยากร
az monitor log-analytics workspace create --resource-group rg-learn-dev \
--workspace-name log-shop-dev --location southeastasia --retention-time 30
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 86: คิวรี KQL สำหรับความล้มเหลว
นับคำขอที่ล้มเหลวต่อชั่วโมงด้วย Kusto Query Language
AppRequests
| where TimeGenerated > ago(24h)
| where Success == false
| summarize failures = count() by bin(TimeGenerated, 1h), ResultCode
| order by TimeGenerated desc
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 87: การตั้งค่าการวินิจฉัย
ส่งล็อกและเมตริกของแพลตฟอร์มไปยังพื้นที่ทำงาน
az monitor diagnostic-settings create \
--name diag-storage \
--resource /subscriptions/<subscription-id>/resourceGroups/rg-learn-dev/providers/Microsoft.Storage/storageAccounts/stlearndev01 \
--workspace log-shop-dev \
--logs '[{"category":"StorageRead","enabled":true}]' \
--metrics '[{"category":"Transaction","enabled":true}]'
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 88: เทเลเมทรีของ Application Insights
ติดตามคำขอและเหตุการณ์ที่กำหนดเองจากโค้ด Python
from opentelemetry import trace
from azure.monitor.opentelemetry import configure_azure_monitor
configure_azure_monitor(connection_string="InstrumentationKey=<key>;IngestionEndpoint=https://southeastasia-1.in.applicationinsights.azure.com/")
tracer = trace.get_tracer("shop")
with tracer.start_as_current_span("checkout") as span:
span.set_attribute("order.total", 120.0)
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 89: การแจ้งเตือนเมตริกเมื่อเวลาตอบสนองสูง
แจ้งทีมเวรเมื่อ API ช้า
az monitor metrics alert create --name alert-slow-api --resource-group rg-learn-dev \
--scopes /subscriptions/<subscription-id>/resourceGroups/rg-learn-dev/providers/Microsoft.Web/sites/app-shop-dev-01 \
--condition "avg HttpResponseTime > 2" --window-size 5m --evaluation-frequency 1m \
--action /subscriptions/<subscription-id>/resourceGroups/rg-learn-dev/providers/microsoft.insights/actionGroups/ag-oncall
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 90: แจ้งเตือนหลังจากค่าผิดปกติหลายครั้งติดต่อกัน
ลดการแจ้งเตือนผิดด้วยการต้องมีค่าผิดปกติต่อเนื่อง
def should_alert(samples, threshold=2.0, required=3):
streak = 0
for value in samples:
streak = streak + 1 if value > threshold else 0
if streak >= required:
return True
return False
print(should_alert([1.0, 2.5, 2.7, 2.9, 1.1]))
print(should_alert([2.5, 1.0, 2.5, 2.5, 1.0]))
ผลลัพธ์:
True
False
หัวข้อที่ 14: ความปลอดภัย: Key Vault ความลับ และการป้องกันภัยคุกคาม
ความลับควรอยู่ในตู้เก็บ ไม่ใช่ในโค้ดหรือล็อก Key Vault เก็บความลับพร้อมการควบคุมการเข้าถึง และ Defender for Cloud เฝ้าดูทรัพยากรเพื่อหาภัยคุกคาม
Key Vault และการเข้าถึง
Key Vault เก็บความลับ คีย์ และใบรับรอง ใช้การควบคุมการเข้าถึงตามบทบาท ให้แต่ละแอปอ่านเฉพาะความลับที่จำเป็น และบันทึกทุกการเข้าถึง
การอ่านความลับอย่างปลอดภัย
DefaultAzureCredential ใช้ managed identity ใน Azure และการเข้าสู่ระบบของคุณบนคอมพิวเตอร์ ทำให้โค้ดเดียวกันทำงานได้ทั้งสองที่ อย่าพิมพ์ความลับ และอย่าเขียนลงล็อก
Defender for Cloud
Defender for Cloud ให้คะแนนสถานะความปลอดภัยและเปิดการป้องกันภัยคุกคามสำหรับ VM บัญชีที่เก็บข้อมูล และ Key Vault ตรวจข้อเสนอแนะสม่ำเสมอ
ตัวอย่างที่ 91: Key Vault และความลับ
เก็บรหัสผ่านในตู้เก็บที่มีการควบคุมการเข้าถึง
az keyvault create --name kv-shop-dev --resource-group rg-learn-dev --location southeastasia \
--enable-rbac-authorization true
az keyvault secret set --vault-name kv-shop-dev --name db-password --value "$DB_PASSWORD"
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 92: อ่านความลับจาก Python
ใช้ DefaultAzureCredential เพื่อดึงความลับ
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
client = SecretClient(vault_url="https://kv-shop-dev.vault.azure.net/", credential=DefaultAzureCredential())
password = client.get_secret("db-password").value
# use the value, never print it
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 93: ปกปิดความลับก่อนเขียนลงล็อก
ซ่อนรหัสผ่านและคีย์ก่อนที่จะเขียนข้อมูลใด ๆ
import re
def redact(text):
text = re.sub(r"(password|secret|token)=\S+", r"\1=***", text, flags=re.IGNORECASE)
text = re.sub(r"(AccountKey=)[^;\s]+", r"\1***", text)
return text
print(redact("connecting with password=hunter2 to host"))
print(redact("AccountKey=abc123==;EndpointSuffix=core.windows.net"))
ผลลัพธ์:
connecting with password=*** to host
AccountKey=***;EndpointSuffix=core.windows.net
ตัวอย่างที่ 94: แพลนของ Defender for Cloud
เปิดการป้องกันภัยคุกคามสำหรับ VM บัญชีที่เก็บข้อมูล และ Key Vault
az security pricing create --name VirtualMachines --tier Standard
az security pricing create --name StorageAccounts --tier Standard
az security pricing create --name KeyVaults --tier Standard
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
หัวข้อที่ 15: DevOps ค่าใช้จ่าย และการกำกับดูแล
ระบบโปรดักชันต้องมีไปป์ไลน์ที่ทำซ้ำได้ วงเงินใช้จ่าย และกฎที่ทรัพยากรใหม่ทุกตัวต้องปฏิบัติตาม แนวทางเหล่านี้ทำให้ Azure เชื่อถือได้และคุ้มค่าเมื่อทีมขยาย
ไปป์ไลน์และการย้อนกลับ
ไปป์ไลน์ทดสอบทุกการเปลี่ยนแปลงและ deploy จากสาขา main ดูอัตราความผิดพลาดและความหน่วงหลังปล่อยเวอร์ชัน และย้อนกลับเมื่อค่าเกินขีดจำกัด
งบประมาณและการประมาณค่าใช้จ่าย
งบประมาณกำหนดวงเงินรายเดือนและส่งการแจ้งเตือนก่อนถึงวงเงิน ประมาณค่าใช้จ่ายจากชั่วโมงและพื้นที่เก็บข้อมูล แล้วเทียบกับบิลจริง และส่งออกรายงานรายวัน
Azure Policy
Policy ตรวจทรัพยากรเทียบกับกฎ เช่นการบังคับให้มีแท็กเจ้าของ เอฟเฟกต์ deny หยุดการสร้างทรัพยากรที่ไม่เป็นไปตามกฎ ซึ่งบังคับใช้มาตรฐานที่ตกลงกันไว้
ตัวอย่างที่ 95: ไปป์ไลน์ Azure DevOps
ทดสอบทุกการ push และ deploy เว็บแอปจาก main
trigger:
branches:
include: [main]
pool:
vmImage: ubuntu-latest
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.12'
- script: pip install -r requirements.txt && pytest
displayName: Test
- task: AzureWebApp@1
inputs:
azureSubscription: sc-shop-dev
appName: app-shop-dev-01
package: '$(System.DefaultWorkingDirectory)'
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 96: งบประมาณรายเดือน
ตั้งวงเงินใช้จ่ายและแจ้งเตือนก่อนถึงวงเงิน
az consumption budget create --budget-name budget-dev --amount 200 \
--category Cost --time-grain Monthly \
--start-date 2026-01-01 --end-date 2026-12-31 \
--resource-group rg-learn-dev
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 97: ประมาณค่าใช้จ่ายรายเดือน
แปลงชั่วโมงการใช้งานและพื้นที่เก็บข้อมูลเป็นค่าใช้จ่ายโดยประมาณ
def monthly_cost(hours_per_day, hourly_rate, storage_gb, storage_rate, days=30):
compute = hours_per_day * days * hourly_rate
storage = storage_gb * storage_rate
return round(compute + storage, 2)
print(monthly_cost(10, 0.05, 120, 0.02))
print(monthly_cost(24, 0.05, 120, 0.02))
ผลลัพธ์:
17.4
38.4
ตัวอย่างที่ 98: ส่งออกข้อมูลค่าใช้จ่าย
ส่งรายงานค่าใช้จ่ายรายวันไปยังบัญชีที่เก็บข้อมูล
az costmanagement export create --name daily-costs \
--scope "/subscriptions/<subscription-id>/resourceGroups/rg-learn-dev" \
--storage-account-id /subscriptions/<subscription-id>/resourceGroups/rg-learn-dev/providers/Microsoft.Storage/storageAccounts/stlearndev01 \
--storage-container exports --timeframe MonthToDate --recurrence Daily \
--recurrence-period from=2026-01-01T00:00:00Z to=2026-12-31T00:00:00Z
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
ตัวอย่างที่ 99: ตัดสินใจย้อนกลับการ deploy
ใช้อัตราความผิดพลาดและความหน่วงตัดสินว่าจะย้อนกลับหรือไม่
def should_roll_back(error_rate, previous_error_rate, latency_ms, latency_limit=800):
if error_rate > 0.05:
return True, "error rate above 5 percent"
if error_rate > previous_error_rate * 2 and error_rate > 0.01:
return True, "error rate doubled since the last release"
if latency_ms > latency_limit:
return True, "latency above limit"
return False, "healthy"
print(should_roll_back(0.02, 0.01, 300))
print(should_roll_back(0.07, 0.01, 300))
ผลลัพธ์:
(False, 'healthy')
(True, 'error rate above 5 percent')
ตัวอย่างที่ 100: บังคับให้มีแท็กด้วย Azure Policy
ปฏิเสธทรัพยากรใหม่ที่ไม่มีแท็ก owner
az policy definition create --name require-owner-tag --display-name "Require owner tag" \
--rules '{"if":{"field":"tags[owner]","exists":"false"},"then":{"effect":"deny"}}' --mode Indexed
az policy assignment create --name require-owner --policy require-owner-tag \
--scope /subscriptions/<subscription-id>/resourceGroups/rg-learn-dev
*ตัวอย่างนี้ยังไม่ได้รันที่นี่ เพราะต้องใช้ subscription ของ Azure หรือเครื่องมือของ Azure*
โปรเจกต์ฝึก: เว็บแอปที่ปลอดภัยพร้อมที่เก็บข้อมูลและการเฝ้าดู
สร้างการตั้งค่าขนาดเล็กที่ปลอดภัยหนึ่งชุด ซึ่งใช้แนวคิดจากหลายหัวข้อ เขียน Bicep และสคริปต์ด้วยตัวเองก่อน แล้วเทียบกับตัวอย่าง ลบกลุ่มทรัพยากรเมื่อเสร็จเพื่อหลีกเลี่ยงค่าใช้จ่าย
1. สร้างกลุ่มทรัพยากรที่มีแท็ก owner และ environment แล้วตรวจแท็กที่ขาดด้วยสคริปต์
2. เขียนเทมเพลต Bicep สำหรับบัญชีที่เก็บข้อมูลที่ใช้ TLS 1.2 และไม่เปิดการเข้าถึง blob สาธารณะ แล้วดูตัวอย่างด้วย what-if ก่อน deploy
3. สร้าง managed identity ที่ผู้ใช้กำหนดเอง และให้บทบาท Storage Blob Data Reader เฉพาะบนบัญชีที่เก็บข้อมูลนั้น
4. deploy เว็บแอปที่อ่าน blob ด้วย managed identity และเพิ่มการแจ้งเตือนเมื่อเวลาตอบสนองเฉลี่ยสูงกว่าสองวินาทีต่อเนื่อง
5. สร้างงบประมาณที่ 80 เปอร์เซ็นต์ของวงเงินรายเดือน แล้วลบกลุ่มทรัพยากรและยืนยันการลบในพอร์ทัล
ขั้นต่อไป
ขั้นต่อไป ศึกษาแนวทางสถาปัตยกรรมของ Azure เลือกใบรับรองตามบทบาทอย่าง AZ-900 หรือ AZ-104 และฝึกไปป์ไลน์โครงสร้างพื้นฐานด้วย GitHub Actions หรือ Azure DevOps รันทุกคำสั่งใน subscription สำหรับทดลองก่อน และอ่านเอกสารของบริการสำหรับเวอร์ชันที่คุณ deploy
สรุป
Azure กลายเป็นแพลตฟอร์มระดับมืออาชีพเมื่อคุณอธิบายด้วยโค้ด ปกป้องด้วยตัวตนแทนรหัสผ่าน เฝ้าดู และควบคุมค่าใช้จ่าย ผ่าน 100 ตัวอย่าง บทความนี้ครอบคลุม Azure CLI กลุ่มทรัพยากรและแท็ก การเขียนสคริปต์ Bicep ตัวตนและ RBAC เครื่องเสมือนและ App Service คอนเทนเนอร์และ Kubernetes ที่เก็บข้อมูล ฐานข้อมูล Functions แบบ serverless เครือข่าย การส่งข้อความ การเฝ้าดู Key Vault และความปลอดภัย และ DevOps พร้อมการกำกับดูแลค่าใช้จ่าย ลองสร้างเว็บแอปที่ปลอดภัยในแบบฝึก และเปลี่ยนทีละการตั้งค่าเพื่อเรียนรู้ว่าแต่ละส่วนทำงานอย่างไร