MODULE 25 Compute · 20–25% ~3 giờ Administrator

Azure Container Instances

Chạy container trên Azure nhanh nhất — không cần quản lý VM hay Kubernetes. Hiểu Docker platform, so sánh container vs VM, triển khai ACI và container groups để chạy workload linh hoạt với chi phí tối thiểu.

Lý Thuyết Cốt Lõi

1. Container vs VM — Nền Tảng Docker

Container và Virtual Machine đều là công nghệ ảo hóa nhưng ở các lớp khác nhau. Hiểu sự khác biệt giúp chọn đúng công nghệ cho từng workload.

Tiêu chí Virtual Machine Container
Ảo hóa Hardware (Hypervisor) OS kernel (namespaces/cgroups)
Khởi động Vài phút (boot OS đầy đủ) Vài giây (process start)
Kích thước GB (cả OS image) MB (chỉ app + dependencies)
Isolation Mạnh — kernel riêng Nhẹ hơn — chia sẻ kernel host
Tài nguyên Cao (RAM/CPU dành riêng) Thấp (chia sẻ OS resources)
Portability Trung bình (phụ thuộc hypervisor) Cao — chạy giống nhau mọi nơi
Phù hợp Legacy app, full OS access, high isolation Microservices, CI/CD, batch jobs
Docker Platform — Các Thành Phần
  • Docker Engine: runtime chạy container trên host OS
  • Dockerfile: script định nghĩa cách build image từng bước
  • Docker Image: template read-only — layers của filesystem
  • Docker Container: instance đang chạy của image (có writable layer)
  • Docker Hub / ACR: registry lưu trữ và phân phối images
  • docker-compose: định nghĩa multi-container app bằng YAML
Azure Container Registry (ACR)
  • • Private Docker registry được quản lý bởi Azure
  • • Tích hợp với Entra ID — không cần quản lý credentials thủ công
  • • Geo-replication: đồng bộ images qua nhiều region
  • • ACR Tasks: build image trực tiếp trên cloud (không cần local Docker)
  • • Vulnerability scanning: quét lỗ hổng bảo mật tự động
  • • SKUs: Basic / Standard / Premium (geo-replication, private endpoint)
Quy tắc chọn: Dùng container khi app đã được containerized hoặc muốn portable. Dùng VM khi app cần full OS access, driver đặc biệt, hoặc license Windows theo VM. Dùng ACI cho container đơn lẻ không cần orchestration. Dùng AKS khi cần orchestration phức tạp, autoscale, hoặc >10 containers.

2. Azure Container Instances (ACI) — Serverless Containers

ACI là cách nhanh nhất và đơn giản nhất để chạy container trên Azure — không cần cấu hình VM, không cần Kubernetes cluster. Tính phí theo giây sử dụng thực tế (vCPU và memory).

Tốc độ

Container khởi động trong vài giây. Không cần provision VM hay cài đặt runtime. Pull image từ ACR hoặc Docker Hub và chạy ngay.

Chi phí

Tính theo giây — chỉ trả tiền khi container đang chạy. Không tốn phí khi container dừng. Phù hợp batch job chạy không liên tục.

Bảo mật

Hypervisor-level isolation — mỗi container group chạy trên kernel riêng. Hỗ trợ VNet integration, Managed Identity, Secret từ Key Vault.

Thông số kỹ thuật ACI
  • CPU: 0.1 → 4 vCPU (theo bước 0.1)
  • Memory: 0.1 → 16 GB (theo bước 0.1)
  • GPU: hỗ trợ NVIDIA GPU (K80, P100, V100)
  • OS: Linux hoặc Windows containers
  • Restart policy: Always / OnFailure / Never
  • Storage: Azure Files mount, emptyDir, secret volume
  • DNS label: tên miền công khai name.region.azurecontainer.io
Use Cases phù hợp ACI
  • Batch processing: xử lý file, ETL pipeline, report generation
  • CI/CD build agent: chạy build/test và tự xóa sau khi xong
  • Event-driven tasks: kích hoạt bởi Logic Apps, Event Grid
  • Dev/Test environment: tạo env tạm thời, xóa sau khi test
  • API prototype: test container image trước khi lên AKS/App Service
  • Machine learning inference: chạy model trong container

3. Container Groups — Multi-Container Pods

Container Group là đơn vị scheduling của ACI — tương đương Kubernetes Pod. Nhiều container trong cùng 1 group chia sẻ localhost network, storage volumes, và lifecycle. Chỉ hỗ trợ trên Linux containers.

Đặc điểm Container Group
  • • Tất cả containers trong group chạy trên cùng host node
  • • Chia sẻ IP address và port namespace
  • • Containers giao tiếp với nhau qua localhost
  • • Volume mount chung: Azure Files, emptyDir, secret, configMap
  • • Group có 1 public IP — port mapping từng container
  • • CPU/Memory cấp phát cho toàn group, chia giữa containers
Mô hình Sidecar Container
  • App container: chứa logic nghiệp vụ chính (vd: web API)
  • Sidecar container: hỗ trợ app container (cùng group)
  • Logging sidecar: đọc log file từ shared volume, đẩy lên Azure Monitor
  • Proxy sidecar: Envoy proxy xử lý TLS termination và circuit breaker
  • Init container: chạy trước app container (setup, migration DB)
So sánh ACI vs AKS vs App Service Container
Tiêu chí ACI AKS App Service (container)
Quản lý Serverless — không cần cluster Managed Kubernetes cluster PaaS — quản lý như web app
Scale Manual / qua Logic Apps HPA, KEDA, cluster autoscaler Autoscale theo plan
Chi phí Per-second, rẻ nhất cho burst Node pool VM (trả cả khi idle) Theo plan (Standard+)
Use case Batch, short-lived, dev/test Production microservices phức tạp Web app, API đơn giản

4. Networking, Storage & Bảo Mật ACI

Networking Options
  • Public IP: ACI nhận IP công khai, truy cập từ internet
  • DNS label: myapp.southeastasia.azurecontainer.io
  • VNet deployment: ACI trong subnet riêng — chỉ private IP
  • Port mapping: expose port cụ thể (TCP/UDP) ra ngoài
  • Không có Load Balancer: chỉ 1 IP per group — dùng Application Gateway phía trước nếu cần LB
Volume Types
  • Azure Files: SMB share — persistent storage, tồn tại sau khi container xóa
  • emptyDir: temporary storage — mất khi container restart
  • secret: inject Kubernetes-style secrets vào filesystem
  • gitRepo: clone git repo vào container lúc khởi động
  • • Mount path: /mnt/data trong container
Bảo mật ACI
  • Managed Identity: container dùng identity để access Azure resources
  • Environment variables: inject config — dùng secureValue cho secrets
  • Private registry: pull image từ ACR với Managed Identity hoặc credential
  • VNet isolation: container không có public IP khi deploy vào VNet
  • Non-root user: chạy container với USER non-root trong Dockerfile
Logs & Monitoring
  • az container logs: xem stdout/stderr của container
  • az container exec: shell vào container đang chạy để debug
  • az container attach: attach live output stream
  • Log Analytics workspace: gửi container logs lên Azure Monitor
  • Metrics: CPU/memory usage qua Azure Monitor

Bài Tập Thực Hành (Lab)

Lab 25-A: ACI từ Docker Hub Lab 25-B: ACR + ACI từ private registry Lab 25-C: Container Group YAML Lab 25-D: Azure Files volume mount
1

Tạo Resource Group và chạy ACI đầu tiên từ Docker Hub

Azure CLI— Chạy được trên PowerShell, CMD, Bash hoặc Azure Cloud Shell
# Tạo Resource Group
az group create \
  --name rg-az104-m25 \
  --location southeastasia \
  --tags Course=AZ-104 Module=25 Environment=Lab

# Chạy ACI đơn giản từ public Docker Hub image (nginx)
az container create \
  --name aci-nginx-m25 \
  --resource-group rg-az104-m25 \
  --image nginx:latest \
  --cpu 0.5 \
  --memory 0.5 \
  --ports 80 \
  --ip-address Public \
  --dns-name-label "aci-nginx-m25-$(date +%s | tail -c 6)" \
  --os-type Linux \
  --restart-policy Always

# Xem trạng thái container
az container show \
  --name aci-nginx-m25 \
  --resource-group rg-az104-m25 \
  --query "{name:name, state:instanceView.state, ip:ipAddress.ip, fqdn:ipAddress.fqdn, cpu:containers[0].resources.requests.cpu, memory:containers[0].resources.requests.memoryInGb}" \
  --output table

# Xem logs container
az container logs \
  --name aci-nginx-m25 \
  --resource-group rg-az104-m25
Verify Portal: Azure Portal → Container instances → aci-nginx-m25 → Overview: xác nhận State = Running, Public IP và FQDN hiển thị. Mở trình duyệt truy cập FQDN → xác nhận trang nginx welcome page xuất hiện. Vào Containers → Logs xem access log.
2

Tạo Azure Container Registry và đẩy image lên ACR

Bash— Linux/macOS/Cloud Shell, KHÔNG chạy CMD
# Tên ACR phải unique toàn cầu, chỉ chữ và số
ACR_NAME="acraz104m25$(date +%s | tail -c 6)"
echo "ACR name: $ACR_NAME"

# Tạo Azure Container Registry (Basic SKU)
az acr create \
  --name "$ACR_NAME" \
  --resource-group rg-az104-m25 \
  --sku Basic \
  --admin-enabled true \
  --location southeastasia

# Lấy login server
ACR_SERVER=$(az acr show \
  --name "$ACR_NAME" \
  --resource-group rg-az104-m25 \
  --query loginServer --output tsv)

echo "ACR Login Server: $ACR_SERVER"

# Build image trực tiếp trên ACR (dùng ACR Tasks — không cần Docker local)
# Sử dụng Dockerfile từ sample GitHub repo
az acr build \
  --registry "$ACR_NAME" \
  --image "myapp:v1.0" \
  https://github.com/Azure-Samples/aci-helloworld

# Liệt kê images trong ACR
az acr repository list \
  --name "$ACR_NAME" \
  --output table

az acr repository show-tags \
  --name "$ACR_NAME" \
  --repository myapp \
  --output table

# Lấy credentials ACR để pull image
ACR_USERNAME=$(az acr credential show \
  --name "$ACR_NAME" \
  --query username --output tsv)

ACR_PASSWORD=$(az acr credential show \
  --name "$ACR_NAME" \
  --query "passwords[0].value" --output tsv)

echo "ACR Username: $ACR_USERNAME"

# Chạy ACI từ private ACR image
az container create \
  --name aci-myapp-m25 \
  --resource-group rg-az104-m25 \
  --image "$ACR_SERVER/myapp:v1.0" \
  --cpu 0.5 \
  --memory 0.5 \
  --ports 80 \
  --ip-address Public \
  --dns-name-label "aci-myapp-m25-$(date +%s | tail -c 6)" \
  --registry-login-server "$ACR_SERVER" \
  --registry-username "$ACR_USERNAME" \
  --registry-password "$ACR_PASSWORD" \
  --os-type Linux \
  --environment-variables APP_ENV=Lab APP_VERSION=v1.0

# Kiểm tra container mới
az container show \
  --name aci-myapp-m25 \
  --resource-group rg-az104-m25 \
  --query "{state:instanceView.state, fqdn:ipAddress.fqdn}" \
  --output table
Verify Portal: Portal → Container registries → acraz104m25... → Repositories → xác nhận myapp với tag v1.0. Vào Container instances → aci-myapp-m25 → truy cập FQDN → xác nhận app "Hello World from Azure Container Instances!" hiển thị đúng.
3

Triển khai Container Group nhiều container bằng YAML

Bash— Linux/macOS/Cloud Shell, KHÔNG chạy CMD
# Tạo YAML định nghĩa container group: app + sidecar logger
cat > /tmp/container-group-m25.yaml << 'EOF'
apiVersion: '2021-10-01'
location: southeastasia
name: cg-az104-m25
properties:
  containers:
  - name: app-container
    properties:
      image: nginx:alpine
      resources:
        requests:
          cpu: 0.5
          memoryInGb: 0.5
      ports:
      - port: 80
        protocol: TCP
      environmentVariables:
      - name: APP_NAME
        value: HoaTranLab-Demo
      - name: APP_SECRET
        secureValue: SuperSecretPassword123
      volumeMounts:
      - name: shared-logs
        mountPath: /var/log/nginx
  - name: logger-sidecar
    properties:
      image: busybox:latest
      resources:
        requests:
          cpu: 0.1
          memoryInGb: 0.1
      command:
      - sh
      - -c
      - "while true; do cat /shared-logs/access.log 2>/dev/null || echo 'waiting for logs...'; sleep 10; done"
      volumeMounts:
      - name: shared-logs
        mountPath: /shared-logs
  volumes:
  - name: shared-logs
    emptyDir: {}
  ipAddress:
    type: Public
    ports:
    - port: 80
      protocol: TCP
    dnsNameLabel: cg-az104-m25-demo
  osType: Linux
  restartPolicy: Always
tags:
  Course: AZ-104
  Module: "25"
type: Microsoft.ContainerInstance/containerGroups
EOF

# Deploy container group từ YAML
az container create \
  --resource-group rg-az104-m25 \
  --file /tmp/container-group-m25.yaml

# Xem trạng thái container group
az container show \
  --name cg-az104-m25 \
  --resource-group rg-az104-m25 \
  --query "{state:instanceView.state, containers:containers[].name, ip:ipAddress.ip}" \
  --output json

# Xem logs của từng container trong group
az container logs \
  --name cg-az104-m25 \
  --resource-group rg-az104-m25 \
  --container-name app-container

az container logs \
  --name cg-az104-m25 \
  --resource-group rg-az104-m25 \
  --container-name logger-sidecar

# Exec vào container để kiểm tra
az container exec \
  --name cg-az104-m25 \
  --resource-group rg-az104-m25 \
  --container-name app-container \
  --exec-command "/bin/sh"
Verify Portal: Portal → Container instances → cg-az104-m25 → Containers: xác nhận 2 containers (app-container và logger-sidecar) đều ở trạng thái Running. Vào tab Logs từng container → xác nhận secureValue không hiện trong logs. Truy cập IP → xác nhận nginx đang chạy.
4

Mount Azure Files volume — Persistent storage cho container

Bash— Linux/macOS/Cloud Shell, KHÔNG chạy CMD
STORAGE_NAME="staz104m25$(date +%s | tail -c 6)"
SHARE_NAME="aci-data"

# Tạo Storage Account cho Azure Files
az storage account create \
  --name "$STORAGE_NAME" \
  --resource-group rg-az104-m25 \
  --location southeastasia \
  --sku Standard_LRS \
  --kind StorageV2 \
  --https-only true

# Tạo Azure File Share
az storage share create \
  --name "$SHARE_NAME" \
  --account-name "$STORAGE_NAME" \
  --quota 5

# Lấy storage key
STORAGE_KEY=$(az storage account keys list \
  --resource-group rg-az104-m25 \
  --account-name "$STORAGE_NAME" \
  --query "[0].value" --output tsv)

# Tạo file test trên share để kiểm tra mount
az storage file upload \
  --account-name "$STORAGE_NAME" \
  --account-key "$STORAGE_KEY" \
  --share-name "$SHARE_NAME" \
  --source /tmp/container-group-m25.yaml \
  --path "test-file.yaml"

# Chạy ACI với Azure Files volume mount
az container create \
  --name aci-files-m25 \
  --resource-group rg-az104-m25 \
  --image alpine:latest \
  --cpu 0.25 \
  --memory 0.25 \
  --command-line "sh -c 'ls /mnt/data && echo \"Files mounted successfully\" && cat /mnt/data/test-file.yaml | head -5 && sleep 300'" \
  --azure-file-volume-account-name "$STORAGE_NAME" \
  --azure-file-volume-account-key "$STORAGE_KEY" \
  --azure-file-volume-share-name "$SHARE_NAME" \
  --azure-file-volume-mount-path /mnt/data \
  --os-type Linux \
  --restart-policy Never

# Chờ container chạy và xem kết quả
sleep 15
az container logs \
  --name aci-files-m25 \
  --resource-group rg-az104-m25
Verify Portal: Portal → Container instances → aci-files-m25 → Logs: xác nhận output "Files mounted successfully" và nội dung file YAML được in ra. Vào Storage accounts → File shares → aci-data → xác nhận file test-file.yaml vẫn tồn tại sau khi container kết thúc (persistent storage).
5

Cleanup — Dọn dẹp tài nguyên

Azure CLI— Chạy được trên PowerShell, CMD, Bash hoặc Azure Cloud Shell
# Xóa toàn bộ Resource Group (ACI, ACR, Storage Account)
az group delete --name rg-az104-m25 --yes --no-wait

# Xác nhận đang xóa
az group show --name rg-az104-m25 --query "properties.provisioningState" -o tsv
# Kết quả mong đợi: Deleting

Kết Quả Đầu Ra

Phân biệt Container vs VM rõ ràng

So sánh isolation level, boot time, kích thước, tài nguyên và use case phù hợp cho từng công nghệ ảo hóa

Nắm vững Docker platform

Hiểu Dockerfile, Image, Container, Registry — biết build image qua ACR Tasks không cần Docker local

Triển khai ACI từ public và private registry

Chạy container từ Docker Hub, tạo ACR, build và push image, deploy ACI từ private registry với credentials

Container Group và sidecar pattern

Định nghĩa multi-container group bằng YAML, hiểu shared network/storage, triển khai logger sidecar

Persistent storage với Azure Files

Mount Azure File Share vào container — dữ liệu tồn tại sau khi container xóa, chia sẻ giữa nhiều containers

Chọn đúng compute service

So sánh ACI vs AKS vs App Service Container — biết khi nào dùng ACI, khi nào cần AKS cho orchestration phức tạp

Ứng Dụng Thực Tế

Tình huống 1: Công ty kế toán — Batch job xuất báo cáo thuế cuối tháng

Mỗi cuối tháng cần chạy job xử lý dữ liệu từ hàng nghìn hóa đơn, xuất PDF báo cáo VAT cho từng khách hàng. Job chạy ~2 giờ, sau đó không cần resource.

Giải pháp

ACI với restart policy = Never. Container đọc dữ liệu từ Azure SQL, xuất PDF vào Azure Files share. Kích hoạt tự động bằng Logic Apps vào ngày 1 hàng tháng. Container tự terminate sau khi hoàn tất.

Triển khai

Container 2 vCPU, 4 GB RAM. Azure Files mount tại /output để lưu PDF. Managed Identity lấy SQL connection string từ Key Vault. Container group trong VNet — không public IP. ACR Premium lưu image.

Lợi ích

Chi phí ~5,000đ/lần chạy (tính theo giây thực tế). So với VM chạy 24/7: tiết kiệm >95%. Không quản lý VM. PDF output tồn tại trong Azure Files dài hạn. Tự động hoàn toàn — không cần IT thủ công.

Tình huống 2: Startup SaaS — CI/CD build agent tự scale theo demand

Team dev 15 người có lúc đồng thời trigger 10 build pipeline, lúc khác không có build nào. CI agent cần co giãn linh hoạt mà không lãng phí VM luôn chạy.

Giải pháp

ACI làm ephemeral build agent cho Azure DevOps. Mỗi pipeline job tạo 1 ACI mới (custom Docker image chứa build tools), chạy build + test, push artifact, rồi tự xóa. Container group với sidecar artifact uploader.

Triển khai

ACR Premium lưu build agent image. ACI 1 vCPU, 2 GB RAM per build. Azure DevOps YAML pipeline dùng pool: {name: "Azure Container Instance"}. emptyDir volume chia sẻ workspace giữa build và sidecar upload containers.

Lợi ích

Zero idle cost — không trả tiền lúc không build. Mỗi build trong môi trường sạch — không artifact pollution giữa các build. Parallel build không giới hạn (tùy ngân sách). Build time giảm 30% nhờ container nhỏ, khởi động nhanh.

Tình huống 3: Công ty logistics — AI inference container xử lý ảnh đơn hàng

Hệ thống phân loại tự động đơn hàng bằng AI: chụp ảnh nhãn hàng, container chạy model AI phân loại, kết quả đưa vào hệ thống WMS. Traffic không đều — bùng phát lúc nhận hàng buổi sáng.

Giải pháp

ACI với GPU (K80) chạy ONNX model inference. Event Grid trigger từ Blob Storage (ảnh mới upload) → Logic App → tạo ACI → inference → ghi kết quả vào Azure SQL → ACI tự xóa. Container group: main inference + sidecar result-writer.

Triển khai

ACI 1 vCPU, 4 GB RAM + GPU K80. Container image trong ACR Premium (geo-replicated). Model file mount từ Azure Files. Managed Identity cho Blob và SQL access. VNet deployment — không IP công khai. Log Analytics cho monitoring AI inference latency.

Lợi ích

Accuracy phân loại 97% so với nhân viên thủ công 85%. Chi phí GPU inference ~2,000đ/1,000 ảnh. Xử lý 500 ảnh/giờ lúc cao điểm mà không cần GPU VM luôn chạy. Dữ liệu không rời VNet nội bộ — đáp ứng yêu cầu bảo mật của đối tác logistics nước ngoài.

Zalo