LAB 17 ~2 giờ Module 9 Trung bình

Triển Khai ASP.NET Web App lên Azure App Service

Tạo App Service Plan, deploy ứng dụng ASP.NET Core 8 từ GitHub hoặc ZIP deploy, cấu hình deployment slots staging/production, quản lý app settings, và thực hiện blue-green deployment với slot swap.

Mục Tiêu Lab

Tạo App Service Plan với đúng tier và region

Deploy ASP.NET Core 8 Web App bằng ZIP deploy và az webapp deploy

Tạo deployment slot staging và thực hiện slot swap zero-downtime

Cấu hình App Settings và Connection Strings (sticky vs non-sticky)

Xem Application Logs và Live Log Stream để debug

Scale out (manual và auto-scale) App Service Plan

Yêu Cầu Chuẩn Bị

Cần có:
  • Azure CLI 2.50+ đã đăng nhập (az login)
  • .NET 8 SDK: dotnet.microsoft.com/download
  • Git đã cài (git --version)
  • Hoàn thành Lab 01 + Lab 02
Chi phí ước tính:
  • App Service Plan B1: ~$0.018/giờ (~$13.14/tháng)
  • Deployment slots yêu cầu Standard tier (S1+) trở lên
  • S1 tier: ~$0.10/giờ — nhớ xóa sau lab
  • Free tier (F1) không hỗ trợ custom domains, slots

Kịch Bản & Tài Nguyên

Bạn cần deploy ứng dụng web ASP.NET Core 8 lên Azure App Service với quy trình CI/CD đơn giản: code deploy lên staging slot → test → swap sang production — zero downtime, rollback được ngay.

App Service Plan
plan-hoatranlab-lab17
Standard S1
Southeast Asia
Linux
Web App
app-hoatranlab-17xxx
ASP.NET Core 8
Runtime: dotnet:8
Slots
production (default)
staging
Swap → zero downtime
App Settings
ASPNETCORE_ENVIRONMENT
APP_VERSION
Sticky per slot

Các Bước Thực Hiện

1

Tạo Resource Group & App Service Plan

App Service Plan xác định compute resources (CPU, RAM, số instances) và tier (features). Nhiều Web Apps có thể chia sẻ cùng một Plan để tiết kiệm chi phí.

Free (F1)
1 GB RAM, không custom domain
Basic (B1)
1.75 GB RAM, custom domain, SSL
Standard (S1) ✓
1.75 GB RAM, slots, auto-scale
Premium (P1v3)
VNet integration, private endpoint
Cách 1 — Azure Portal
  1. 1.Portal → App Services → + Create → Web App
  2. 2.RG: tạo mới rg-hoatranlab-lab17
  3. 3.Name: app-hoatranlab-17xxx (thay xxx = random)
  4. 4.Runtime stack: .NET 8 (LTS) | OS: Linux | Region: Southeast Asia
  5. 5.App Service Plan: Create new → Name: plan-hoatranlab-lab17 → Tier: Standard S1
  6. 6.Review + Create → Create (đợi ~1 phút)
Cách 2 — Azure CLI
Azure CLI
# Tạo Resource Group
az group create \
  --name rg-hoatranlab-lab17 \
  --location southeastasia

# Tạo App Service Plan Standard S1 (Linux)
az appservice plan create \
  --name plan-hoatranlab-lab17 \
  --resource-group rg-hoatranlab-lab17 \
  --location southeastasia \
  --sku S1 \
  --is-linux

# Tạo Web App (.NET 8 runtime)
SUFFIX=$RANDOM
APP_NAME="app-hoatranlab-17${SUFFIX}"

az webapp create \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --plan plan-hoatranlab-lab17 \
  --runtime "DOTNETCORE:8.0"

echo "Web App URL: https://${APP_NAME}.azurewebsites.net"

# Xác nhận web app đang chạy
az webapp show \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --query "{state:state,defaultHostName:defaultHostName}" \
  --output json
2

Tạo ASP.NET Core App & Deploy bằng ZIP

Cách đơn giản nhất để deploy: dotnet publish → zip → az webapp deploy. Phù hợp cho demo và manual deploy; production nên dùng GitHub Actions hoặc Azure DevOps.

Cách 1 — Portal (Deployment Center)
  1. 1.Vào Web App → Deployment Center (left menu)
  2. 2.Source: GitHub → Authorize → chọn repo
  3. 3.Branch: main → Runtime: .NET 8 → Save
  4. 4.Azure tự tạo GitHub Actions workflow → commit deploy tự động
  5. 5.Xem logs deploy trong Logs tab
  6. 6.Click URL web app → xác nhận app chạy
Cách 2 — CLI (ZIP Deploy)
Bash— Terminal với .NET 8 SDK
# Tạo ASP.NET Core Web App mới
dotnet new webapp -n HoaTranLabApp --framework net8.0
cd HoaTranLabApp

# Sửa nhanh nội dung để phân biệt version
cat > Pages/Index.cshtml << 'EOF'
@page
@model IndexModel

HoaTranLab - Azure App Service Lab 17

Version: 1.0.0 | Slot: Production

Deploy time: @DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") UTC

EOF # Build và publish dotnet publish -c Release -o ./publish # Zip artifacts cd publish zip -r ../deploy.zip . cd .. # Deploy lên production slot az webapp deploy \ --resource-group rg-hoatranlab-lab17 \ --name $APP_NAME \ --src-path deploy.zip \ --type zip # Verify: mở browser echo "Mở: https://${APP_NAME}.azurewebsites.net" curl -s "https://${APP_NAME}.azurewebsites.net" | head -20
Kết quả (Output)— az webapp deploy thành công
Getting scm site credentials for zip deployment
Starting zip deployment. This operation can take a while to complete ...
Deployment endpoint responded with status code 202
You can track the url status: https://app-hoatranlab-17xxxx.scm.azurewebsites.net/api/deployments/latest
{
  "complete": true,
  "deployer": "ZipDeploy",
  "id": "latest",
  "message": "Deployment successful.",
  "status": 4
}
3

Cấu Hình App Settings & Connection Strings

App Settings trong Azure App Service được inject vào ứng dụng dưới dạng environment variables — ghi đè appsettings.json. Slot settings (sticky) không bị swap khi swap slots, giúp staging và production dùng database khác nhau.

Slot setting (sticky): Connection string đến production DB nên là slot setting — khi swap staging↔production, connection string không bị swap. Staging vẫn kết nối staging DB, production vẫn kết nối production DB.
Cách 1 — Azure Portal
  1. 1.Web App → Configuration → tab Application settings
  2. 2.Click + New application setting
  3. 3.Name: APP_VERSION | Value: 1.0.0-production
  4. 4.Tick Deployment slot setting (sticky) → OK
  5. 5.Thêm: ASPNETCORE_ENVIRONMENT = Production (sticky)
  6. 6.Click Save (App sẽ restart)
Cách 2 — Azure CLI
Azure CLI
# Thêm App Settings (non-sticky — sẽ swap cùng slot)
az webapp config appsettings set \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --settings \
    "GREETING=Hello from Azure App Service" \
    "LAB_NAME=AZ-104 Lab 17"

# Thêm sticky settings (không swap cùng slot)
az webapp config appsettings set \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --slot-settings \
    "APP_VERSION=1.0.0-production" \
    "ASPNETCORE_ENVIRONMENT=Production"

# Xem tất cả app settings
az webapp config appsettings list \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --output table

# Thêm Connection String (sticky theo slot)
az webapp config connection-string set \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --connection-string-type SQLServer \
  --slot-settings \
    DefaultConnection="Server=prod-sql.database.windows.net;Database=ProdDB;"
4

Deployment Slots — Staging & Swap Zero-Downtime

Deployment slots cho phép chạy nhiều phiên bản app trên cùng App Service Plan. Workflow tiêu chuẩn: deploy lên staging → warm up → test → swap sang production. Rollback = swap ngược lại.

Cách 1 — Azure Portal

Tạo staging slot:

  1. 1.Web App → Deployment slots+ Add Slot
  2. 2.Name: staging | Clone settings: từ production → Add
  3. 3.URL staging: app-hoatranlab-17xxx-staging.azurewebsites.net

Swap staging → production:

  1. 4.Deployment slots → click Swap
  2. 5.Source: staging | Target: production
  3. 6.Xem Preview changes → Start Swap
  4. 7.Sau swap: production URL hiển thị version staging, staging hiển thị version cũ (rollback ready)
Cách 2 — Azure CLI
Azure CLI
# Tạo staging slot
az webapp deployment slot create \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --slot staging \
  --configuration-source $APP_NAME

# Đặt sticky setting riêng cho staging slot
az webapp config appsettings set \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --slot staging \
  --slot-settings \
    "APP_VERSION=2.0.0-staging" \
    "ASPNETCORE_ENVIRONMENT=Staging"

# Tạo version 2 của app (giả lập new release)
sed -i 's/Version: 1.0.0<\/strong>/Version: 2.0.0<\/strong>/' \
  Pages/Index.cshtml
sed -i 's/Slot: Production/Slot: Staging/' Pages/Index.cshtml

# Deploy version 2 lên staging slot
dotnet publish -c Release -o ./publish
cd publish && zip -r ../deploy-v2.zip . && cd ..

az webapp deploy \
  --resource-group rg-hoatranlab-lab17 \
  --name $APP_NAME \
  --slot staging \
  --src-path deploy-v2.zip \
  --type zip

# Test staging trước khi swap
STAGING_URL="https://${APP_NAME}-staging.azurewebsites.net"
echo "Test staging: $STAGING_URL"
curl -s $STAGING_URL | grep Version

# Swap staging → production (zero downtime)
az webapp deployment slot swap \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --slot staging \
  --target-slot production

# Confirm production đang chạy v2
curl -s "https://${APP_NAME}.azurewebsites.net" | grep Version

# Rollback: swap ngược lại nếu cần
# az webapp deployment slot swap \
#   --name $APP_NAME \
#   --resource-group rg-hoatranlab-lab17 \
#   --slot staging \
#   --target-slot production
5

Logging, Scale Out & Monitoring

Cách 1 — Azure Portal

Bật App Logs:

  1. 1.Web App → App Service Logs → Application Logging: File System → Level: Verbose → Save
  2. 2.Web App → Log stream → xem real-time logs khi truy cập app

Scale Out Manual:

  1. 3.App Service Plan → Scale out (App Service plan)
  2. 4.Manual scale: tăng instance count lên 2 → Apply
  3. 5.Custom autoscale: thêm rule khi CPU > 70% → scale out +1 instance
Cách 2 — Azure CLI
Azure CLI
# Bật app logging vào filesystem
az webapp log config \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --application-logging filesystem \
  --level verbose \
  --web-server-logging filesystem

# Stream logs real-time (Ctrl+C để dừng)
az webapp log tail \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17

# Download logs về local
az webapp log download \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --log-file webapp-logs.zip

# Scale out App Service Plan lên 2 instances
az appservice plan update \
  --name plan-hoatranlab-lab17 \
  --resource-group rg-hoatranlab-lab17 \
  --number-of-workers 2

# Xem metrics (CPU, requests, response time)
az monitor metrics list \
  --resource $(az webapp show \
    --name $APP_NAME \
    --resource-group rg-hoatranlab-lab17 \
    --query id -o tsv) \
  --metric CpuTime \
  --interval PT1H \
  --output table
6

Cấu Hình HTTPS Redirect, Always On & Health Check

Các cài đặt production cần thiết: bắt buộc HTTPS, bật Always On (tránh cold start), cấu hình Health Check để load balancer tự loại instance bệnh.

Cách 1 — Azure Portal
  1. 1.Web App → Configuration → tab General settings
  2. 2.HTTPS Only: On (redirect HTTP → HTTPS tự động)
  3. 3.Always On: On (giữ app warm, tránh cold start 10–30 giây)
  4. 4.Minimum TLS Version: 1.2 → Save
  5. 5.Web App → Health check → Enable → Path: /health → Save
  6. 6.Thử truy cập http:// → bị redirect sang https:// tự động
Cách 2 — Azure CLI
Azure CLI
# Bật HTTPS Only và Always On
az webapp update \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --https-only true

# Cấu hình Always On, TLS 1.2, HTTP/2
az webapp config set \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --always-on true \
  --min-tls-version 1.2 \
  --http20-enabled true

# Cấu hình Health Check endpoint
az webapp config set \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --health-check-path "/health"

# Xác nhận cấu hình
az webapp config show \
  --name $APP_NAME \
  --resource-group rg-hoatranlab-lab17 \
  --query "{httpsOnly:httpsOnly,alwaysOn:alwaysOn,minTlsVersion:minTlsVersion,healthCheckPath:healthCheckPath}" \
  --output json

# Test: HTTP phải redirect sang HTTPS
curl -I "http://${APP_NAME}.azurewebsites.net"
# Expect: HTTP/1.1 301 Moved Permanently
# Location: https://app-hoatranlab-17xxx.azurewebsites.net/

Kết Quả Đầu Ra Lab 17

Web App running .NET 8

https://app-hoatranlab-17xxx.azurewebsites.net hiển thị trang HTML, state: Running

App Settings hoạt động

APP_VERSION, ASPNETCORE_ENVIRONMENT có dấu khóa (sticky) trong Portal Configuration

Staging slot tạo thành công

app-hoatranlab-17xxx-staging.azurewebsites.net chạy version 2.0.0

Slot swap thành công

Production URL hiển thị v2.0.0; staging giữ v1.0.0 sẵn sàng rollback

HTTPS redirect bật

curl -I http://... trả về 301 redirect sang https://... tự động

Log stream hoạt động

az webapp log tail hiển thị real-time HTTP request logs khi truy cập URL

Dọn Dẹp Tài Nguyên

App Service Plan S1 tốn ~$0.10/giờ. Xóa ngay sau khi hoàn thành.

Azure CLI
# Xóa toàn bộ Resource Group (bao gồm App + Plan + slots)
az group delete \
  --name rg-hoatranlab-lab17 \
  --yes \
  --no-wait

# Dọn dẹp files local
rm -rf HoaTranLabApp publish deploy.zip deploy-v2.zip webapp-logs.zip

Câu Hỏi Ôn Tập

1. Deployment slot swap hoạt động như thế nào? Tại sao swap được coi là "zero downtime" deployment?

Gợi ý: Swap thực chất là đổi routing rules giữa hai slots (đổi IP virtual), không restart app. Staging đã được warm up trước — khi swap, traffic được điều hướng sang staging instance đang chạy sẵn, không có cold start. Rollback = swap lần nữa.

2. Slot settings (sticky settings) khác gì với regular app settings khi thực hiện slot swap?

Gợi ý: Sticky settings gắn với slot, KHÔNG đi theo app khi swap. Regular settings đi theo app content khi swap. Ví dụ: Connection String production DB nên sticky ở production slot — sau swap, staging app vẫn dùng staging DB, production app vẫn dùng production DB.

3. Sự khác biệt giữa Scale Up và Scale Out trong App Service? Khi nào nên dùng mỗi loại?

Gợi ý: Scale Up = tăng tier (B1→S1→P1) — nhiều CPU/RAM hơn cho 1 instance; Scale Out = tăng số instances (1→2→3) — load balancing. Scale Up có giới hạn max tier; Scale Out linh hoạt hơn, tốt cho horizontal workloads. Auto-scale chỉ dùng được với Scale Out.

4. Always On là gì và tại sao quan trọng cho production? Free tier có hỗ trợ Always On không?

Gợi ý: Always On giữ app process luôn chạy, tránh bị unload sau 20 phút idle. Không có Always On → request đầu tiên sau idle sẽ chờ cold start (10–30 giây). Free/Shared tier KHÔNG hỗ trợ Always On — yêu cầu Basic (B1) trở lên.

5. Một App Service Plan có thể chứa tối đa bao nhiêu deployment slots? Tier nào bắt đầu hỗ trợ slots?

Gợi ý: Standard S1 = tối đa 5 slots; Premium P1v3 = tối đa 20 slots. Free và Basic tier KHÔNG hỗ trợ slots. Mỗi slot chạy như một app riêng biệt nhưng chia sẻ compute resources của Plan.