EngineeringSolution ArchitectPlatform and DevOps

Session 04 - GitOps & Environment Management

GitOps Principles

GitOps lấy Git repository làm single source of truth cho cả application code và infrastructure state.

4 nguyên tắc cốt lõi:

  1. Declarative - Toàn bộ hệ thống mô tả dưới dạng declarative (YAML, Bicep, HCL)
  2. Versioned & Immutable - Mọi thay đổi qua Git commit, có audit trail
  3. Pulled Automatically - Agent trong cluster tự pull và apply thay đổi
  4. Continuously Reconciled - Agent liên tục so sánh desired state vs actual state

Flux vs ArgoCD

Tiêu chíFlux v2ArgoCD
ArchitectureSet of controllersServer + UI
UIKhông có built-in (dùng Weave GitOps)Web UI đẹp, đầy đủ
Multi-tenancyNative (Kustomize-based)AppProject-based
Helm supportHelmRelease CRDNative Helm support
KustomizeNative, first-classSupported
NotificationBuilt-in (Slack, Teams, webhook)Notification engine
Image automationBuilt-in image reflectorArgo Image Updater (separate)
Learning curveTrung bình (CLI-focused)Thấp (UI trực quan)
RBACKubernetes RBACBuilt-in RBAC + SSO
Resource usageNhẹ hơnNặng hơn (server + redis + dex)

Trade-off: ArgoCD phù hợp team cần UI trực quan, dễ onboard thành viên mới. Flux phù hợp team thích CLI-first, muốn lightweight, và tích hợp sâu với Kustomize.

Environment Strategy

Cấu trúc GitOps Repository

gitops-repo/
  base/                       # Shared manifests
    deployment.yaml
    service.yaml
    kustomization.yaml
  overlays/
    dev/
      kustomization.yaml      # Dev-specific patches
      replicas-patch.yaml
    staging/
      kustomization.yaml
      replicas-patch.yaml
    production/
      kustomization.yaml
      replicas-patch.yaml
      hpa-patch.yaml          # HPA chỉ production
yaml
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml

# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base
patchesStrategicMerge:
  - replicas-patch.yaml
  - hpa-patch.yaml
namespace: myapp-prod
commonLabels:
  env: production
yaml
# overlays/production/replicas-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-api
spec:
  replicas: 3
  template:
    spec:
      resources:
        limits:
          cpu: "1"
          memory: "512Mi"
        requests:
          cpu: "250m"
          memory: "256Mi"

Branching Strategies

Trunk-Based Development vs GitFlow

Tiêu chíTrunk-BasedGitFlow
Branch chínhmain (trunk)main + develop
Feature branchShort-lived (< 2 ngày)Long-lived
ReleaseTag on main hoặc release branch ngắnrelease/* branch
HotfixFix on main, cherry-pickhotfix/* branch
CI/CDDeploy từ main liên tụcDeploy từ release branch
Merge conflictÍt (branch ngắn)Nhiều (branch dài)
Phù hợpTeam mature, CI/CD mạnhTeam lớn, release cycle dài

Trade-off phân tích:

  • Trunk-based yêu cầu feature flags, test coverage cao, CI pipeline nhanh. Reward: deploy frequency cao, feedback loop ngắn.
  • GitFlow dễ quản lý release, phù hợp mobile app hoặc on-premise software. Cost: merge hell, delayed integration.

Recommendation cho .NET web app: Trunk-based development + feature flags + short-lived branches.

Environment Parity

Giữ các environment càng giống nhau càng tốt:

yaml
# docker-compose.override.yml - local dev giả lập production
services:
  api:
    build: .
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ConnectionStrings__Default=Server=db;Database=myapp;User=sa;Password=Dev@12345;TrustServerCertificate=true
    depends_on:
      - db
      - redis

  db:
    image: mcr.microsoft.com/mssql/server:2022-latest
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=Dev@12345

  redis:
    image: redis:7-alpine
AspectDevStagingProduction
DatabaseSQL Server containerAzure SQL BasicAzure SQL S2+
CacheRedis containerAzure Cache BasicAzure Cache Standard
SSLSelf-signedAzure managed certCustom domain cert
Replicas113+
LoggingConsoleApplication InsightsApplication Insights + Log Analytics

Secret Management

Nguyên tắc

  • Never commit secrets vào Git
  • Dùng external secret store (Key Vault, Sealed Secrets)
  • Mỗi environment có secret riêng
  • Rotate secrets định kỳ

Azure Key Vault Integration

csharp
// Program.cs - load secrets từ Key Vault
builder.Configuration.AddAzureKeyVault(
    new Uri(builder.Configuration["KeyVault:VaultUri"]!),
    new DefaultAzureCredential());

Kubernetes - External Secrets Operator

yaml
# ExternalSecret syncs từ Azure Key Vault → Kubernetes Secret
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: myapp-secrets
  namespace: myapp-prod
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: azure-keyvault
    kind: ClusterSecretStore
  target:
    name: myapp-secrets
    creationPolicy: Owner
  data:
    - secretKey: ConnectionStrings__Default
      remoteRef:
        key: SqlConnectionString
    - secretKey: Redis__Password
      remoteRef:
        key: RedisPassword

Promotion Workflow

yaml
# GitHub Actions - promote image từ staging → production
name: Promote to Production

on:
  workflow_dispatch:
    inputs:
      image_tag:
        description: 'Image tag to promote'
        required: true

jobs:
  promote:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
        with:
          repository: myorg/gitops-repo
          token: ${{ secrets.GITOPS_PAT }}

      - name: Update production image tag
        run: |
          cd overlays/production
          kustomize edit set image myapp-api=myacr.azurecr.io/myapp-api:${{ inputs.image_tag }}

      - name: Commit and push
        run: |
          git config user.name "github-actions"
          git config user.email "actions@github.com"
          git add .
          git commit -m "promote: myapp-api:${{ inputs.image_tag }} → production"
          git push

      # GitOps agent (Flux/ArgoCD) sẽ tự động detect và deploy

Tip: Dùng Pull Request thay vì direct push cho production promotion - thêm một lớp review trước khi deploy.