SiamCafe · Blog
CircleCI Orbs High Availability HA Setup
บทความ

CircleCI Orbs High Availability HA Setup

เผยแพร่ 28 พฤษภาคม 2569

CircleCI Orbs High Availability HA Setup คืออะไร

CircleCI Orbs High Availability HA Setup

CircleCI เป็น CI/CD platform ยอดนิยมที่รองรับ automated build, test และ deploy CircleCI Orbs คือ reusable configuration packages ที่ช่วยลด boilerplate config และแชร์ best practices ข้าม projects High Availability (HA) Setup คือการออกแบบระบบให้มี uptime สูงสุด (99.9%+) โดยไม่มี single point of failure การรวมแนวคิดเหล่านี้ช่วยให้ CI/CD pipeline มีความเสถียร deploy applications ที่มี HA architecture และใช้ Orbs จัดการ infrastructure อย่างมีประสิทธิภาพ

CircleCI Orbs พื้นฐาน

# orbs_basics.py — CircleCI Orbs fundamentals
import json

class CircleCIOrbs:
    CONCEPTS = {
        "orb": {
            "name": "Orb",
            "description": "Reusable package ของ CircleCI config (commands, jobs, executors)",
            "registry": "circleci.com/developer/orbs (public registry)",
        },
        "command": {
            "name": "Command",
            "description": "Reusable step sequence ที่ใช้ใน jobs",
            "example": "aws-cli/setup — ติดตั้งและ configure AWS CLI",
        },
        "job": {
            "name": "Job",
            "description": "Pre-defined job ที่พร้อมใช้ใน workflow",
            "example": "docker/publish — build + push Docker image",
        },
        "executor": {
            "name": "Executor",
            "description": "Pre-configured execution environment",
            "example": "node/default — Node.js environment พร้อมใช้",
        },
    }

    POPULAR_ORBS = {
        "aws-cli": {"name": "aws-cli", "use": "AWS CLI setup and commands", "installs": "2B+"},
        "docker": {"name": "docker", "use": "Build, tag, push Docker images", "installs": "500M+"},
        "kubernetes": {"name": "kubernetes", "use": "Deploy to Kubernetes clusters", "installs": "100M+"},
        "slack": {"name": "slack", "use": "Send notifications to Slack", "installs": "300M+"},
        "terraform": {"name": "terraform", "use": "Terraform plan and apply", "installs": "200M+"},
        "node": {"name": "node", "use": "Node.js environment and caching", "installs": "400M+"},
    }

    BASIC_CONFIG = """
# .circleci/config.yml — Basic Orbs usage
version: 2.1

orbs:
  aws-cli: circleci/aws-cli@4.1
  docker: circleci/docker@2.6
  slack: circleci/slack@4.13

jobs:
  build-and-test:
    docker:
      - image: cimg/python:3.11
    steps:
      - checkout
      - run: pip install -r requirements.txt
      - run: pytest tests/ -v
      - slack/notify:
          event: fail
          template: basic_fail_1

  deploy:
    docker:
      - image: cimg/python:3.11
    steps:
      - checkout
      - aws-cli/setup
      - docker/build:
          image: myapp
          tag: 
      - docker/push:
          image: myapp
          tag: 

workflows:
  build-deploy:
    jobs:
      - build-and-test
      - deploy:
          requires: [build-and-test]
          filters:
            branches:
              only: main
"""

    def show_concepts(self):
        print("=== Orbs Concepts ===\n")
        for key, concept in self.CONCEPTS.items():
            print(f"[{concept['name']}] {concept['description']}")

    def show_popular(self):
        print(f"\n=== Popular Orbs ===")
        for key, orb in self.POPULAR_ORBS.items():
            print(f"  [{orb['name']}] {orb['use']}")

    def show_config(self):
        print(f"\n=== Basic Config ===")
        print(self.BASIC_CONFIG[:500])

orbs = CircleCIOrbs()
orbs.show_concepts()
orbs.show_popular()
orbs.show_config()

HA Architecture Patterns

# ha_patterns.py — High Availability architecture patterns
import json

class HAPatterns:
    PATTERNS = {
        "active_active": {
            "name": "Active-Active",
            "description": "ทุก instance รับ traffic พร้อมกัน load balanced",
            "use": "Web servers, API gateways, stateless services",
            "uptime": "99.99%+",
            "complexity": "Medium-High",
        },
        "active_passive": {
            "name": "Active-Passive (Failover)",
            "description": "Primary instance ทำงาน, secondary standby พร้อม takeover",
            "use": "Databases, stateful services",
            "uptime": "99.9%+",
            "complexity": "Medium",
        },
        "multi_az": {
            "name": "Multi-AZ (Availability Zone)",
            "description": "Deploy ข้าม AZ ใน region เดียว",
            "use": "Cloud workloads (AWS, GCP, Azure)",
            "uptime": "99.99%",
            "complexity": "Medium",
        },
        "multi_region": {
            "name": "Multi-Region",
            "description": "Deploy ข้าม regions (geographic redundancy)",
            "use": "Global applications, disaster recovery",
            "uptime": "99.999%",
            "complexity": "High",
        },
    }

    HA_COMPONENTS = {
        "load_balancer": "ALB/NLB, Nginx, HAProxy — กระจาย traffic",
        "auto_scaling": "EC2 ASG, K8s HPA — scale ตาม load",
        "database_ha": "RDS Multi-AZ, Aurora, PostgreSQL streaming replication",
        "cache_ha": "Redis Sentinel/Cluster, ElastiCache Multi-AZ",
        "dns_failover": "Route53 health checks, Cloudflare load balancing",
        "monitoring": "CloudWatch, Prometheus, PagerDuty — detect failures",
    }

    def show_patterns(self):
        print("=== HA Patterns ===\n")
        for key, pattern in self.PATTERNS.items():
            print(f"[{pattern['name']}] {pattern['description']}")
            print(f"  Use: {pattern['use']} | Uptime: {pattern['uptime']}")
            print()

    def show_components(self):
        print("=== HA Components ===")
        for comp, desc in self.HA_COMPONENTS.items():
            print(f"  [{comp}] {desc}")

ha = HAPatterns()
ha.show_patterns()
ha.show_components()

CircleCI HA Deployment Pipeline

CircleCI Orbs High Availability HA Setup
# ha_pipeline.py — HA deployment with CircleCI
import json

class HAPipeline:
    CONFIG = """
# .circleci/config.yml — HA Deployment Pipeline
version: 2.1

orbs:
  aws-cli: circleci/aws-cli@4.1
  aws-ecs: circleci/aws-ecs@4.0
  kubernetes: circleci/kubernetes@1.3
  slack: circleci/slack@4.13
  rollbar: circleci/rollbar@1.0

executors:
  deploy-executor:
    docker:
      - image: cimg/python:3.11
    environment:
      AWS_REGION: ap-southeast-1

jobs:
  test:
    docker:
      - image: cimg/python:3.11
      - image: cimg/postgres:15.0
    steps:
      - checkout
      - restore_cache:
          keys: [deps-{{ checksum "requirements.txt" }}]
      - run: pip install -r requirements.txt
      - save_cache:
          key: deps-{{ checksum "requirements.txt" }}
          paths: [~/.cache/pip]
      - run: pytest tests/ -v --junitxml=results.xml
      - store_test_results:
          path: results.xml

  build-image:
    executor: deploy-executor
    steps:
      - checkout
      - setup_remote_docker:
          version: 20.10.24
      - run:
          name: Build and push to ECR
          command: |
            aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_URL
            docker build -t $ECR_URL/myapp: .
            docker push $ECR_URL/myapp:

  deploy-blue-green:
    executor: deploy-executor
    steps:
      - aws-cli/setup
      - run:
          name: Blue-Green Deploy to ECS
          command: |
            # Update task definition with new image
            aws ecs update-service \\
              --cluster production \\
              --service myapp-green \\
              --task-definition myapp: \\
              --desired-count 3
            
            # Wait for green deployment stable
            aws ecs wait services-stable \\
              --cluster production \\
              --services myapp-green
            
            # Switch ALB target group
            aws elbv2 modify-listener \\
              --listener-arn $LISTENER_ARN \\
              --default-actions Type=forward, TargetGroupArn=$GREEN_TG_ARN
      - slack/notify:
          event: pass
          template: success_tagged_deploy_1

  health-check:
    executor: deploy-executor
    steps:
      - run:
          name: Post-deploy health check
          command: |
            for i in $(seq 1 10); do
              STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://api.example.com/health)
              if [ "$STATUS" = "200" ]; then
                echo "Health check passed"
                exit 0
              fi
              sleep 10
            done
            echo "Health check failed"
            exit 1

workflows:
  ha-deploy:
    jobs:
      - test
      - build-image:
          requires: [test]
          filters:
            branches:
              only: main
      - deploy-blue-green:
          requires: [build-image]
      - health-check:
          requires: [deploy-blue-green]
"""

    def show_config(self):
        print("=== HA Pipeline Config ===")
        print(self.CONFIG[:800])

    def deployment_strategies(self):
        print(f"\n=== Deployment Strategies for HA ===")
        strategies = [
            {"name": "Blue-Green", "downtime": "Zero", "rollback": "Instant (switch back)", "complexity": "Medium"},
            {"name": "Canary", "downtime": "Zero", "rollback": "Fast (route back)", "complexity": "High"},
            {"name": "Rolling Update", "downtime": "Near-zero", "rollback": "Slow (redeploy)", "complexity": "Low"},
            {"name": "A/B Testing", "downtime": "Zero", "rollback": "Instant", "complexity": "High"},
        ]
        for s in strategies:
            print(f"  [{s['name']}] Downtime: {s['downtime']} | Rollback: {s['rollback']}")

pipeline = HAPipeline()
pipeline.show_config()
pipeline.deployment_strategies()

Infrastructure as Code for HA

# iac_ha.py — Terraform HA infrastructure
import json

class IACHA:
    TERRAFORM = """
# main.tf — HA infrastructure with Terraform
provider "aws" {
  region = "ap-southeast-1"
}

# VPC with Multi-AZ
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0"
  
  name = "ha-vpc"
  cidr = "10.0.0.0/16"
  
  azs             = ["ap-southeast-1a", "ap-southeast-1b", "ap-southeast-1c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
  
  enable_nat_gateway = true
  single_nat_gateway = false  # NAT per AZ for HA
}

# ALB (Application Load Balancer)
resource "aws_lb" "main" {
  name               = "ha-alb"
  internal           = false
  load_balancer_type = "application"
  subnets            = module.vpc.public_subnets
  
  enable_deletion_protection = true
  enable_cross_zone_load_balancing = true
}

# ECS Cluster with Fargate
resource "aws_ecs_cluster" "main" {
  name = "ha-cluster"
  
  setting {
    name  = "containerInsights"
    value = "enabled"
  }
}

# ECS Service (Multi-AZ)
resource "aws_ecs_service" "app" {
  name            = "myapp"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.app.arn
  desired_count   = 3  # Spread across 3 AZs
  launch_type     = "FARGATE"
  
  network_configuration {
    subnets         = module.vpc.private_subnets
    security_groups = [aws_security_group.app.id]
  }
  
  load_balancer {
    target_group_arn = aws_lb_target_group.app.arn
    container_name   = "myapp"
    container_port   = 8080
  }
}

# RDS Multi-AZ
resource "aws_db_instance" "main" {
  identifier     = "ha-postgres"
  engine         = "postgres"
  engine_version = "15"
  instance_class = "db.r6g.large"
  
  multi_az               = true
  storage_encrypted      = true
  backup_retention_period = 7
  
  db_subnet_group_name = aws_db_subnet_group.main.name
}
"""

    def show_terraform(self):
        print("=== Terraform HA Config ===")
        print(self.TERRAFORM[:700])

    def ha_checklist(self):
        print(f"\n=== HA Checklist ===")
        checks = [
            ("Multi-AZ deployment (3 AZs)", True),
            ("Load balancer health checks", True),
            ("Auto-scaling configured", True),
            ("Database Multi-AZ failover", True),
            ("Redis/Cache HA (Sentinel/Cluster)", True),
            ("DNS failover configured", True),
            ("Monitoring + alerting active", True),
            ("Disaster recovery plan documented", True),
            ("Runbook for failover scenarios", True),
        ]
        for name, status in checks:
            icon = "PASS" if status else "TODO"
            print(f"  [{icon:>4}] {name}")

iac = IACHA()
iac.show_terraform()
iac.ha_checklist()

Monitoring & Failover

# monitoring.py — HA monitoring and failover
import json
import random

class HAMonitoring:
    def cluster_status(self):
        print("=== HA Cluster Status ===\n")
        services = [
            {"name": "API Gateway (ALB)", "status": "healthy", "instances": "3/3", "az": "3 AZs"},
            {"name": "App Service (ECS)", "status": "healthy", "instances": "6/6", "az": "3 AZs"},
            {"name": "Database (RDS)", "status": "healthy", "instances": "Primary + Standby", "az": "Multi-AZ"},
            {"name": "Cache (Redis)", "status": "healthy", "instances": "3 nodes", "az": "3 AZs"},
            {"name": "CDN (CloudFront)", "status": "healthy", "instances": "Global", "az": "Edge locations"},
        ]
        for s in services:
            print(f"  [{s['status']:>7}] {s['name']:<25} Instances: {s['instances']}")

    def uptime_metrics(self):
        print(f"\n=== Uptime Metrics ===")
        metrics = {
            "Current uptime": f"{random.uniform(99.95, 99.99):.3f}%",
            "Last 30 days": f"{random.uniform(99.90, 99.99):.3f}%",
            "MTTR": f"{random.randint(1, 10)} minutes",
            "MTBF": f"{random.randint(30, 180)} days",
            "Incidents (30d)": f"{random.randint(0, 3)}",
            "RTO target": "< 5 minutes",
            "RPO target": "< 1 minute",
        }
        for m, v in metrics.items():
            print(f"  {m}: {v}")

    def failover_test(self):
        print(f"\n=== Failover Test Results ===")
        tests = [
            {"scenario": "Single instance failure", "recovery": f"{random.randint(5, 30)}s", "result": "PASS"},
            {"scenario": "AZ failure", "recovery": f"{random.randint(30, 120)}s", "result": "PASS"},
            {"scenario": "Database failover", "recovery": f"{random.randint(30, 90)}s", "result": "PASS"},
            {"scenario": "Region failover", "recovery": f"{random.randint(120, 600)}s", "result": "PASS"},
        ]
        for t in tests:
            print(f"  [{t['result']:>4}] {t['scenario']:<30} Recovery: {t['recovery']}")

mon = HAMonitoring()
mon.cluster_status()
mon.uptime_metrics()
mon.failover_test()

FAQ - คำถามที่พบบ่อย

Q: CircleCI Orbs กับ GitHub Actions reusable workflows อันไหนดี?

A: CircleCI Orbs: mature ecosystem, versioned packages, central registry, reusable across orgs GitHub Actions: larger marketplace, tighter GitHub integration, easier to start ใช้ CircleCI: ถ้าใช้ CircleCI อยู่แล้ว, ต้องการ versioned reusable configs ใช้ GitHub Actions: ถ้าใช้ GitHub, ต้องการ simplicity

Q: HA ต้องใช้ minimum กี่ AZs?

A: 2 AZs: minimum สำหรับ HA (ถ้า 1 AZ ล่ม ยังมี 1 AZ) 3 AZs: แนะนำ (quorum-based systems เช่น etcd, Consul ต้อง 3+) Cost: Multi-AZ เพิ่มค่าใช้จ่าย ~50-100% แต่คุ้มสำหรับ production

Q: Blue-Green กับ Canary อันไหนดี?

A: Blue-Green: ง่ายกว่า, switch 100% traffic ทีเดียว, rollback instant Canary: ค่อยๆ route traffic (1% → 10% → 50% → 100%), ลด blast radius ใช้ Blue-Green: simple apps, small team, ต้องการ fast rollback ใช้ Canary: large scale, ต้อง validate กับ real traffic ก่อน full deploy

Q: HA มีค่าใช้จ่ายเท่าไหร่?

A: Multi-AZ: เพิ่ม ~50-100% (double instances + cross-AZ traffic) Multi-Region: เพิ่ม ~200-400% (full stack per region) ประหยัด: ใช้ spot instances สำหรับ non-critical, reserved instances สำหรับ baseline ROI: downtime 1 ชั่วโมง อาจเสียหาย $10K-$1M+ → HA คุ้มค่าสำหรับ business-critical