# บทที่ 10: Deployment Strategies

## หัวข้อหลัก

- Deployment Strategies
- Environment Management
- Rollback Strategies
- Monitoring & Observability

---

## 📑 สารบัญ

1. [Deployment Strategies](#1-deployment-strategies)
   - [1.1 All-at-once Deployment](#11-all-at-once-deployment)
   - [1.2 Rolling Deployment](#12-rolling-deployment)
   - [1.3 Blue-Green Deployment](#13-blue-green-deployment)
   - [1.4 Canary Deployment](#14-canary-deployment)
   - [1.5 Feature Flags](#15-feature-flags-feature-toggle)

2. [Environment Management](#2-environment-management)
   - [2.1 Environment Types](#21-environment-types)
   - [2.2 Environment Configuration](#22-environment-configuration)
   - [2.3 Infrastructure as Code](#23-infrastructure-as-code-iac)

3. [Rollback Strategies](#3-rollback-strategies)
   - [3.1 Immediate Rollback](#31-immediate-rollback)
   - [3.2 Kubernetes Rollback](#32-kubernetes-rollback)
   - [3.3 Database Rollback](#33-database-rollback)
   - [3.4 Deployment Manifest Versioning](#34-deployment-manifest-versioning)

4. [Monitoring & Observability](#4-monitoring--observability)
   - [4.1 Health Checks](#41-health-checks)
   - [4.2 Logging](#42-logging)
   - [4.3 Metrics](#43-metrics)
   - [4.4 Alerts](#44-alerts)

---

## 1. Deployment Strategies

### 1.1 All-at-once Deployment

ปล่อยเวอร์ชันใหม่ขึ้นไป Production ทั้งหมดในครั้งเดียว

```
Version 1.0 ─→ [All Servers]
              ↓
            Deploying...
              ↓
Version 2.0 ─→ [All Servers] 100% Traffic
```

**Characteristics:**

- ⏱️ Fastest deployment
- 🔴 Highest risk
- ❌ No rollback capability (ต้อง redeploy)
- 💰 Cheapest (ไม่ต้อง extra instances)

**ตัวอย่าง:**

```bash
# All-at-once deployment
docker pull myapp:v2.0.0
docker stop myapp_container
docker run -d -p 3000:3000 myapp:v2.0.0

# ถ้าเกิดปัญหา ต้อง rollback ด้วยการ redeploy
docker stop myapp_container
docker run -d -p 3000:3000 myapp:v1.0.0
```

**เมื่อใช้:**

- Internal/Dev environments
- Non-critical services
- Maintenance windows
- Scheduled downtime ที่ยอมรับได้

---

### 1.2 Rolling Deployment

ค่อยๆ ปล่อยเวอร์ชันใหม่ Server ทีละตัว (หรือทีละกลุ่ม)

```
Version 1.0 [Server 1, 2, 3, 4]
            ↓ (ขั้น 1)
Version 2.0 [Server 1] + Version 1.0 [Server 2, 3, 4]
            ↓ (ขั้น 2)
Version 2.0 [Server 1, 2] + Version 1.0 [Server 3, 4]
            ↓ (ขั้น 3)
Version 2.0 [Server 1, 2, 3] + Version 1.0 [Server 4]
            ↓ (ขั้น 4)
Version 2.0 [Server 1, 2, 3, 4]
```

**Characteristics:**

- ✅ Zero-downtime deployment
- ✅ Gradual rollout (ค่อยๆ ปล่อยได้)
- ✅ สามารถ Rollback ได้
- ⚠️ ต้องมี Load Balancer
- ⚠️ อาจมี Version incompatibility ระหว่าง servers

**ตัวอย่าง:** Kubernetes Rolling Deployment

**deployment.yaml:**

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1 # สร้าง pod เพิ่มได้ 1 pod
      maxUnavailable: 1 # ปิด pod ได้ 1 pod ต่อครั้ง

  selector:
    matchLabels:
      app: myapp

  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: myapp:v2.0.0
          ports:
            - containerPort: 3000

          # Health checks
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 10

          readinessProbe:
            httpGet:
              path: /ready
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 5
```

**Process:**

```bash
# Original deployment (v1.0)
# Pods running: v1.0, v1.0, v1.0, v1.0

# Update image
kubectl set image deployment/myapp myapp=myapp:v2.0.0

# Monitor rollout
kubectl rollout status deployment/myapp

# If something goes wrong, rollback
kubectl rollout undo deployment/myapp
```

**เมื่อใช้:**

- Production deployments
- Services ที่ต้องมี HA (High Availability)
- Traditional server environments

---

### 1.3 Blue-Green Deployment

ปล่อย Version ใหม่ (Green) ขนานกับ Version เก่า (Blue) แล้วสลับทั้งหมดพร้อมกัน

```
┌──────────────────────────────────────────┐
│            Load Balancer                 │
│          (Router: 100% → Blue)           │
└─────────────────────────────────────────┬┘
                                          │
                                ┌─────────┴─────────┐
                                │                   │
                         ┌──────────────┐  ┌──────────────┐
                         │ Blue Env     │  │ Green Env    │
                         │ (v1.0.0)     │  │ (v2.0.0)     │
                         │ 100% Traffic │  │ 0% Traffic   │
                         │              │  │ (Testing)    │
                         └──────────────┘  └──────────────┘
                                │                   │
                                └─────────┬─────────┘

                    หลังจาก Test สำเร็จ แก้ Router

┌──────────────────────────────────────────┐
│            Load Balancer                 │
│          (Router: 100% → Green)          │
└─────────────────────────────────────────┬┘
                                          │
                                ┌─────────┴─────────┐
                                │                   │
                         ┌──────────────┐  ┌──────────────┐
                         │ Blue Env     │  │ Green Env    │
                         │ (v1.0.0)     │  │ (v2.0.0)     │
                         │ 0% Traffic   │  │ 100% Traffic │
                         │ (Standby)    │  │              │
                         └──────────────┘  └──────────────┘
```

**Characteristics:**

- ✅ Zero-downtime
- ✅ Instant rollback (เพียงสลับ Router)
- ✅ Full environment test ก่อน switch
- ⚠️ ต้องมี Resource เพื่อรอง 2 Environments
- ⚠️ Cost สูง (ต้อง 2x Infrastructure)

**ตัวอย่าง:** AWS ECS Blue-Green Deployment

**.cod-deploy/appspec.yaml:**

```yaml
version: 0.0
Resources:
  # Blue resource
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: mynodes:2 # Green version
        LoadBalancerInfo:
          ContainerName: mynodes
          ContainerPort: 3000
        PlatformVersion: 1.3.0
        NetworkConfiguration:
          AwsvpcConfiguration:
            Subnets:
              - subnet-123456789
            SecurityGroups:
              - sg-123456789
            AssignPublicIp: ENABLED

Hooks:
  - BeforeAllowTraffic: "validateFunction"
  - AfterAllowTraffic: "smokeTestFunction"
```

**Process:**

```bash
# 1. Deploy Green environment
aws ecs update-service \
  --cluster production \
  --service myapp \
  --task-definition myapp:2

# 2. Run tests on Green
./run-smoke-tests.sh https://green.example.com

# 3. If successful, switch router
aws elbv2 modify-target-group-attributes \
  --target-group-arn arn:aws:elasticloadbalancing:... \
  --attributes Key=deregistration_delay.timeout_seconds,Value=0

# 4. Rotate traffic
aws elbv2 describe-target-groups \
  --load-balancer-arn arn:aws:elasticloadbalancing:...

# 5. If issues, rollback (instantly)
# Just switch router back to Blue
```

**เมื่อใช้:**

- Mission-critical applications
- ต้องการ quick rollback
- Application ไม่มี state (stateless)

---

### 1.4 Canary Deployment

ปล่อย Version ใหม่ให้กับ Small group of users ก่อน (Canary) แล้วค่อยๆ เพิ่ม traffic

```
User Requests
       │
       ├─→ 95% Traffic → Version 1.0 (Blue)
       │
       └─→ 5% Traffic  → Version 2.0 (Canary)

                    (Monitor metrics)
                        ↓
       ├─→ 90% Traffic → Version 1.0
       │
       └─→ 10% Traffic → Version 2.0

                    (If no issues)
                        ↓
       ├─→ 50% Traffic → Version 1.0
       │
       └─→ 50% Traffic → Version 2.0

                    (Monitor continues)
                        ↓
       └─→ 100% Traffic → Version 2.0
```

**Characteristics:**

- ✅ Low-risk deployment
- ✅ Real user feedback
- ✅ Easy rollback
- ⚠️ Slow rollout (takes time)
- ⚠️ Complex setup
- ⚠️ ต้องสามารถ split traffic

**ตัวอย่าง:** Istio Canary Deployment

**VirtualService.yaml:**

```yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp
spec:
  hosts:
    - myapp
  http:
    - match:
        - uri:
            prefix: "/"
      route:
        - destination:
            host: myapp
            subset: v1
          weight: 95 # 95% traffic
        - destination:
            host: myapp
            subset: v2
          weight: 5 # 5% traffic
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: myapp
spec:
  host: myapp
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        http1MaxPendingRequests: 100
  subsets:
    - name: v1
      labels:
        version: v1.0.0
    - name: v2
      labels:
        version: v2.0.0
```

**Canary Deployment Script:**

```bash
#!/bin/bash

CANARY_INCREMENTS=(5 10 25 50 75 100)
WAIT_TIME=600  # 10 minutes between each increment

for weight in "${CANARY_INCREMENTS[@]}"; do
  echo "Promoting canary to $weight%..."

  # Update weight in VirtualService
  kubectl patch virtualservice myapp --type merge \
    -p "{\"spec\":{\"http\":[{\"route\":[
      {\"destination\":{\"host\":\"myapp\",\"subset\":\"v1\"},\"weight\":$((100-weight))},
      {\"destination\":{\"host\":\"myapp\",\"subset\":\"v2\"},\"weight\":$weight}
    ]}]}}"

  # Wait and monitor
  echo "Waiting $WAIT_TIME seconds..."
  sleep $WAIT_TIME

  # Check error rate
  ERROR_RATE=$(prometheus_query 'rate(requests_failed[5m])')
  if (( $(echo "$ERROR_RATE > 0.05" | bc -l) )); then
    echo "Error rate too high, rolling back!"
    kubectl rollout undo deployment/myapp-v2
    exit 1
  fi

  echo "✓ Health check passed"
done

echo "✓ Canary deployment complete!"
```

**เมื่อใช้:**

- Major version releases
- High-traffic production systems
- ต้องการ minimize impact
- Data-intensive features

---

### 1.5 Feature Flags (Feature Toggle)

ไม่แน่นลงบนการ deploy แต่ใช้ flags ควบคุม Feature

```typescript
// Feature flag interface
interface FeatureFlags {
  newSearchEnabled: boolean;
  darkModeEnabled: boolean;
  betaFeatureEnabled: boolean;
}

// Configuration
const flags: FeatureFlags = {
  newSearchEnabled: process.env.FEATURE_NEW_SEARCH === 'true',
  darkModeEnabled: process.env.FEATURE_DARK_MODE === 'true',
  betaFeatureEnabled: process.env.FEATURE_BETA === 'true',
};

// Usage
export function renderSearch() {
  if (flags.newSearchEnabled) {
    return <NewSearchComponent />;
  }
  return <OldSearchComponent />;
}

// In components
export function Layout() {
  return (
    <div className={flags.darkModeEnabled ? 'dark' : 'light'}>
      {/* Layout code */}
    </div>
  );
}
```

**Advanced: LaunchDarkly Integration**

```typescript
import * as ld from "@launchdarkly/node-server-sdk";

const client = ld.init(process.env.LD_SDK_KEY);

// Wait for initialization
await client.waitForInitialization();

// Use in middleware
app.use(async (req, res, next) => {
  const user = {
    key: req.user.id,
    name: req.user.name,
    custom: {
      group: req.user.group,
      betaAccess: req.user.betaAccess,
    },
  };

  const showNewSearch = await client.variation(
    "search-v2-enabled",
    user,
    false,
  );

  res.locals.flags = {
    showNewSearch,
  };

  next();
});
```

**Characteristics:**

- ✅ Decouple deploys from releases
- ✅ A/B testing capability
- ✅ Instant enable/disable
- ✅ Gradual rollout
- ⚠️ Code complexity (flags everywhere)
- ⚠️ Dead code accumulation
- ⚠️ Need feature flag service

**เมื่อใช้:**

- A/B testing
- Feature gradual rollout
- Trunk-based development
- Experimentation

---

## 2. Environment Management

### 2.1 Environment Types

```
┌─────────────────────────────────────────────┐
│           Development Environment           │
├─────────────────────────────────────────────┤
│ • Local machine                             │
│ • Loose rules                               │
│ • Any code can be deployed                  │
│ • Purpose: Daily development                │
└─────────────────────────────────────────────┘
         ↓ (Commit)
┌─────────────────────────────────────────────┐
│            Testing Environment              │
├─────────────────────────────────────────────┤
│ • Shared server                             │
│ • Latest code from main branch              │
│ • QA performs testing                       │
│ • Purpose: Quality assurance                │
└─────────────────────────────────────────────┘
         ↓ (Approval)
┌─────────────────────────────────────────────┐
│           Staging Environment               │
├─────────────────────────────────────────────┤
│ • Prod-like configuration                   │
│ • Real database (clone)                     │
│ • Real external services integration        │
│ • Purpose: Final validation                 │
└─────────────────────────────────────────────┘
         ↓ (Sign-off)
┌─────────────────────────────────────────────┐
│          Production Environment             │
├─────────────────────────────────────────────┤
│ • Real users accessing                      │
│ • High availability                         │
│ • Monitoring & alerting active              │
│ • Purpose: Serve users                      │
└─────────────────────────────────────────────┘
```

### 2.2 Environment Configuration

**.env.development**

```
NODE_ENV=development
API_URL=http://localhost:5000
DATABASE_URL=postgresql://localhost/myapp_dev
LOG_LEVEL=debug
AUTH_ENABLED=false
CACHE_ENABLED=false
```

**.env.test**

```
NODE_ENV=test
API_URL=http://localhost:5001
DATABASE_URL=postgresql://localhost/myapp_test
LOG_LEVEL=warn
AUTH_ENABLED=true
CACHE_ENABLED=false
SEED_DATA=true
```

**.env.staging**

```
NODE_ENV=staging
API_URL=https://api-staging.example.com
DATABASE_URL=postgresql://staging-db.example.com/myapp
LOG_LEVEL=info
AUTH_ENABLED=true
CACHE_ENABLED=true
EXTERNAL_API_URL=https://api-staging.external.com
```

**.env.production** (ไม่ store ที่ Git)

```
NODE_ENV=production
API_URL=https://api.example.com
DATABASE_URL=postgresql://prod-db.example.com/myapp
LOG_LEVEL=warn
AUTH_ENABLED=true
CACHE_ENABLED=true
EXTERNAL_API_URL=https://api.external.com
SENTRY_DSN=https://...@sentry.io/...
```

**Load Configuration:**

```javascript
const path = require("path");
require("dotenv").config({
  path: path.join(__dirname, `.env.${process.env.NODE_ENV}`),
});

module.exports = {
  nodeEnv: process.env.NODE_ENV,
  apiUrl: process.env.API_URL,
  databaseUrl: process.env.DATABASE_URL,
  logLevel: process.env.LOG_LEVEL,
  authEnabled: process.env.AUTH_ENABLED === "true",
  cacheEnabled: process.env.CACHE_ENABLED === "true",
};
```

### 2.3 Infrastructure as Code (IaC)

**Terraform: AWS Deployment**

```hcl
# main.tf
provider "aws" {
  region = var.aws_region
}

# ECS Cluster
resource "aws_ecs_cluster" "production" {
  name = var.cluster_name

  setting {
    name  = "containerInsights"
    value = "enabled"
  }
}

# Task Definition
resource "aws_ecs_task_definition" "app" {
  family                   = "myapp"
  network_mode            = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                     = "256"
  memory                  = "512"

  container_definitions = jsonencode([{
    name      = "myapp"
    image     = "${var.ecr_repository}:${var.app_version}"
    essential = true

    portMappings = [{
      containerPort = 3000
      hostPort      = 3000
      protocol      = "tcp"
    }]

    environment = [
      { name = "NODE_ENV", value = var.environment },
      { name = "API_URL", value = var.api_url },
      { name = "LOG_LEVEL", value = var.log_level },
    ]

    logConfiguration = {
      logDriver = "awslogs"
      options = {
        "awslogs-group"         = aws_cloudwatch_log_group.app.name
        "awslogs-region"        = var.aws_region
        "awslogs-stream-prefix" = "ecs"
      }
    }
  }])
}

# ECS Service
resource "aws_ecs_service" "app" {
  name            = "myapp-service"
  cluster         = aws_ecs_cluster.production.id
  task_definition = aws_ecs_task_definition.app.arn
  desired_count   = var.desired_count
  launch_type     = "FARGATE"

  network_configuration {
    subnets          = var.private_subnets
    security_groups  = [aws_security_group.app.id]
    assign_public_ip = false
  }

  load_balancer {
    target_group_arn = aws_lb_target_group.app.arn
    container_name   = "myapp"
    container_port   = 3000
  }

  depends_on = [aws_lb_listener.app]
}

# Auto Scaling
resource "aws_appautoscaling_target" "ecs_target" {
  max_capacity       = var.max_capacity
  min_capacity       = var.min_capacity
  resource_id        = "service/${aws_ecs_cluster.production.name}/${aws_ecs_service.app.name}"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
}

resource "aws_appautoscaling_policy" "ecs_policy_memory" {
  policy_name            = "memory-autoscaling"
  policy_type            = "TargetTrackingScaling"
  resource_id            = aws_appautoscaling_target.ecs_target.resource_id
  scalable_dimension     = aws_appautoscaling_target.ecs_target.scalable_dimension
  service_namespace      = aws_appautoscaling_target.ecs_target.service_namespace

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ECSServiceAverageMemoryUtilization"
    }
    target_value = 70.0
  }
}
```

---

## 3. Rollback Strategies

### 3.1 Immediate Rollback

**Blue-Green Rollback (Fastest)**

```bash
# Current state: Green (v2.0) is active
# Issue detected: Switch back to Blue (v1.0)

LOAD_BALANCER_IP=10.0.0.100
BLUE_IP=10.0.1.1
GREEN_IP=10.0.2.2

# Switch router immediately
aws elbv2 modify-target-group \
  --target-group-arn arn:aws:elasticloadbalancing:... \
  --targets Id=$BLUE_IP:3000 Id=$GREEN_IP:3000 \
  --load-balancer-port 443 \
  --protocol HTTPS \
  > /dev/null 2>&1

echo "✓ Traffic routed back to Blue (v1.0)"
```

**Time to rollback: < 1 second**

### 3.2 Kubernetes Rollback

```bash
# Deployment history
kubectl rollout history deployment/myapp

# Revision 1: Initial deployment
# Revision 2: Update image to v2.0
# Revision 3: Current (v2.0 with bug)

# Rollback to previous revision
kubectl rollout undo deployment/myapp

# Or rollback to specific revision
kubectl rollout undo deployment/myapp --to-revision=2

# Check rollout status
kubectl rollout status deployment/myapp
```

### 3.3 Database Rollback

**Pre-deployment Backup:**

```bash
#!/bin/bash
# pre-deploy-backup.sh

BACKUP_DIR="/var/backups/database"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/backup_$TIMESTAMP.sql"

# Create backup
pg_dump -U postgres production_db > $BACKUP_FILE
gzip $BACKUP_FILE

# Upload to S3
aws s3 cp "$BACKUP_FILE.gz" s3://backups/database/

# Keep only last 7 days
find $BACKUP_DIR -name "*.gz" -mtime +7 -delete

echo "✓ Database backed up to $BACKUP_FILE.gz"
```

**Rollback Process:**

```bash
#!/bin/bash
# rollback-database.sh

BACKUP_FILE=$1

# Be careful!
read -p "Rolling back to $BACKUP_FILE - Continue? (yes/no) " -n 3; echo
[ "$REPLY" != "yes" ] && exit 1

# Stop application
systemctl stop myapp

# Restore database
gunzip -c $BACKUP_FILE | psql -U postgres -d production_db

# Start application
systemctl start myapp

echo "✓ Database rolled back"
```

### 3.4 Deployment Manifest Versioning

**เพื่อให้ rollback ได้เร็ว**

```
deployment/
├── v1.0.0/
│   ├── docker-compose.yml
│   ├── .env
│   └── schema.sql
├── v1.1.0/
│   ├── docker-compose.yml
│   ├── .env
│   └── schema.sql
└── v2.0.0/  (Current)
    ├── docker-compose.yml
    ├── .env
    └── schema.sql
```

**Rollback script:**

```bash
#!/bin/bash
CURRENT_VERSION=$(cat /app/VERSION)
ROLLBACK_VERSION=$1

docker stop $(docker ps -q)
cd "/deployment/$ROLLBACK_VERSION"
docker-compose up -d

echo $ROLLBACK_VERSION > /app/VERSION
```

---

## 4. Monitoring & Observability

### 4.1 Health Checks

```javascript
// health-check endpoint
app.get("/health", (req, res) => {
  const health = {
    status: "UP",
    timestamp: new Date().toISOString(),
    version: process.env.APP_VERSION,
    checks: {
      database: "UP",
      cache: "UP",
      externalAPI: "UP",
    },
  };

  res.status(200).json(health);
});

// readiness endpoint (for K8s)
app.get("/ready", (req, res) => {
  try {
    // Check critical dependencies
    if (db.isConnected && cache.isConnected) {
      res.status(200).json({ ready: true });
    } else {
      res.status(503).json({ ready: false });
    }
  } catch (error) {
    res.status(503).json({ ready: false, error: error.message });
  }
});
```

### 4.2 Logging

```javascript
const winston = require("winston");

const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || "info",
  format: winston.format.json(),
  defaultMeta: {
    service: "myapp",
    version: process.env.APP_VERSION,
    environment: process.env.NODE_ENV,
  },

  transports: [
    new winston.transports.File({ filename: "error.log", level: "error" }),
    new winston.transports.File({ filename: "combined.log" }),
  ],
});

// Usage
logger.info("Application started", {
  port: process.env.PORT,
  environment: process.env.NODE_ENV,
});

logger.error("Database connection failed", {
  error: error.message,
  code: error.code,
  timestamp: new Date(),
});
```

### 4.3 Metrics

**Prometheus metrics:**

```javascript
const prometheus = require("prom-client");

// Create metrics
const httpRequestDuration = new prometheus.Histogram({
  name: "http_request_duration_ms",
  help: "Duration of HTTP requests in ms",
  labelNames: ["method", "route", "status_code"],
  buckets: [0.1, 5, 15, 50, 100, 500],
});

const dbQueryDuration = new prometheus.Histogram({
  name: "db_query_duration_ms",
  help: "Duration of database queries",
  labelNames: ["query_type"],
});

// Middleware
app.use((req, res, next) => {
  const start = Date.now();

  res.on("finish", () => {
    const duration = Date.now() - start;
    httpRequestDuration
      .labels(req.method, req.route?.path, res.statusCode)
      .observe(duration);
  });

  next();
});

// Expose metrics
app.get("/metrics", async (req, res) => {
  res.set("Content-Type", prometheus.register.contentType);
  res.end(await prometheus.register.metrics());
});
```

### 4.4 Alerts

**.alerting-rules.yaml (Prometheus)**

```yaml
groups:
  - name: deployment-alerts
    rules:
      - alert: HighErrorRate
        expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
        for: 5m
        annotations:
          summary: "High error rate detected"
          description: "Error rate is {{ $value }}"

      - alert: DeploymentUnhealthy
        expr: deployment_status{condition="Available"} == 0
        for: 5m
        annotations:
          summary: "Deployment is unhealthy"
          description: "Deployment {{ $labels.deployment }} has 0 available replicas"

      - alert: PodCrashLooping
        expr: rate(pod_container_last_terminated_reason{reason="Error"}[15m]) > 0
        for: 5m
        annotations:
          summary: "Pod crash looping"
          description: "Pod {{ $labels.pod }} is crash looping"

      - alert: HighMemoryUsage
        expr: container_memory_usage_bytes / container_spec_memory_limit_bytes > 0.9
        for: 5m
        annotations:
          summary: "High memory usage"
          description: "Container {{ $labels.container }} memory usage is {{ $value }}"
```

### 4.5 Deployment Status Dashboard

```javascript
// Deploy status endpoint
app.get("/deploy/status", (req, res) => {
  const deploymentInfo = {
    version: process.env.APP_VERSION,
    environment: process.env.NODE_ENV,
    deployedAt: process.env.DEPLOY_TIME,
    deployedBy: process.env.DEPLOYED_BY,
    gitCommit: process.env.GIT_COMMIT,
    gitBranch: process.env.GIT_BRANCH,
    uptime: process.uptime(),
    memory: process.memoryUsage(),
    healthStatus: "healthy",
  };

  res.json(deploymentInfo);
});
```

---

## 5. ตัวอย่าง Complete Deployment Pipeline

### 5.1 GitHub Actions Deployment

**.github/workflows/deploy.yml**

```yaml
name: Deploy to Production

on:
  push:
    tags:
      - "v*"

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: myapp

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      image-tag: ${{ steps.meta.outputs.tags }}

    steps:
      - uses: actions/checkout@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2

      - name: Log in to Container Registry
        uses: docker/login-action@v2
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}

      - name: Build and push Docker image
        uses: docker/build-push-action@v4
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
          cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max

  deploy_staging:
    needs: build
    runs-on: ubuntu-latest
    environment: staging

    steps:
      - uses: actions/checkout@v3

      - name: Deploy to staging
        run: |
          aws ecs update-service \
            --cluster staging \
            --service myapp \
            --force-new-deployment \
            --region us-east-1

      - name: Run smoke tests
        run: |
          ./scripts/smoke-tests.sh https://staging.example.com

      - name: Notify Slack
        uses: slackapi/slack-github-action@v1
        with:
          webhook-url: ${{ secrets.SLACK_WEBHOOK }}
          payload: |
            {
              "text": "Staging Deployment",
              "blocks": [{
                "type": "section",
                "text": {
                  "type": "mrkdwn",
                  "text": "✅ Deployed ${{ github.ref }} to staging"
                }
              }]
            }

  deploy_production:
    needs: [build, deploy_staging]
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://example.com

    steps:
      - uses: actions/checkout@v3

      - name: Create backup
        run: |
          ./scripts/backup-database.sh

      - name: Deploy to production (Blue-Green)
        run: |
          # Update Green environment
          aws ecs update-service \
            --cluster production \
            --service myapp-green \
            --force-new-deployment

          # Wait for Green to be healthy
          aws ecs wait services-stable \
            --cluster production \
            --services myapp-green

          # Switch traffic to Green
          aws elbv2 modify-target-group-attributes \
            --target-group-arn arn:aws:elasticloadbalancing:...

      - name: Run production smoke tests
        run: |
          ./scripts/smoke-tests.sh https://example.com

      - name: Monitor deployment
        run: |
          ./scripts/monitor-deployment.sh 300

      - name: Notify on success
        uses: slackapi/slack-github-action@v1
        if: success()
        with:
          webhook-url: ${{ secrets.SLACK_WEBHOOK }}
          payload: |
            {
              "text": "Production Deployment Successful",
              "blocks": [{
                "type": "section",
                "text": {
                  "type": "mrkdwn",
                  "text": "✅ Version ${{ github.ref }} deployed to production\nCommit: ${{ github.sha }}\nDeployed by: ${{ github.actor }}"
                }
              }]
            }

      - name: Rollback on failure
        if: failure()
        run: |
          echo "Deployment failed, rolling back..."
          aws ecs update-service \
            --cluster production \
            --service myapp-blue \
            --force-new-deployment

          curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
            -H 'Content-Type: application/json' \
            -d '{"text":"❌ Production deployment failed and rolled back"}'
```

---

## 6. Best Practices

```markdown
## Deployment Best Practices

1. **Automate Everything**
   - No manual deployments
   - Deployment scripts version controlled
   - Reproducible deployments

2. **Test Before Deploy**
   - Unit tests ✓
   - Integration tests ✓
   - E2E tests ✓
   - Smoke tests in production-like environment

3. **Implement Health Checks**
   - Liveness probes (ต้อง restart หรือไม่)
   - Readiness probes (สามารถ accept traffic)
   - Custom health checks

4. **Monitoring & Alerting**
   - Real-time metrics
   - Alert on anomalies
   - Post-deploy validation

5. **Deployment Visibility**
   - Clear deployment status
   - Access logs
   - Change log

6. **Rollback Plan**
   - Document rollback procedure
   - Practice rollback
   - < 5 minute recovery time objective (RTO)

7. **Gradual Rollout**
   - Canary deployments
   - Feature flags
   - Blue-Green for critical updates

8. **Infrastructure as Code**
   - Version all configuration
   - Reproducible environments
   - Easy disaster recovery

9. **Database Migrations**
   - Backward compatible migrations
   - Test migrations before deploy
   - Rollback plan for schema changes

10. **Communication**
    - Notify stakeholders
    - Document changes
    - Incident post-mortems
```

---

## สรุป

Deployment Strategies คือครั้งสำคัญ ของการ deliver software ให้ users:

1. **เลือก Strategy ที่เหมาะสม** - ตามความเสี่ยงและ requirements
2. **อัตโนมัติ as much as possible** - Reduce human error
3. **Monitor อย่างต่อเนื่อง** - Detect issues fast
4. **Rollback capability** - Always have a way back
5. **Test thoroughly** - Catch issues early

Deployment ที่ดี = Fast delivery + High quality + Low risk
