Skip to content
← অর্কেস্ট্রেশন · মধ্যবর্তী · 10 মিনিট · 05 / 06 EN

GitOps & Deployments

ArgoCD, Helm, Argo Rollouts দিয়ে progressive delivery — cluster state as code, automated sync, এবং এমন deployment যা নীরবে ভুল হয়ে যেতে পারে না।

GitOpsArgoCDHelmArgo Rolloutscanaryblue-greenCD

বাস্তব জীবনের উদাহরণ

একটা version-controlled বিল্ডিং ব্লুপ্রিন্ট: ভল্টে রাখা ব্লুপ্রিন্ট (git)-ই সবসময় source of truth। কোনো contractor যখনই বিল্ডিংয়ে অননুমোদিত পরিবর্তন আনে (cluster drift), সিস্টেম সেটা ধরে ফেলে এবং ব্লুপ্রিন্টে ফিরিয়ে নেয়। বৈধ কোনো পরিবর্তন করতে হলে আপনি ব্লুপ্রিন্ট আপডেট করেন — সরাসরি বিল্ডিং নয়। ArgoCD হলো সেই সিস্টেম যা এটা enforce করে।

গল্পে বুঝি

সমরকন্দ শহরে নতুন একটা বড় লাইব্রেরি বানানো হচ্ছে। শহরের নিয়ম কড়া — বিল্ডিংয়ের আসল, অফিসিয়াল master blueprint শহরের আর্কাইভে তালাবদ্ধ থাকে, আর সেই blueprint-ই একমাত্র সত্য। কোন দেয়াল কোথায়, কোন দরজা কত চওড়া — সব ওখানে আঁকা। ইবনে সিনা হলেন প্রধান foreman। তার কাজ একটাই, কিন্তু সে সেটা অক্লান্তভাবে করে যায়: প্রতিদিন সে আসল বিল্ডিংটা ঘুরে দেখে আর আর্কাইভের master blueprint-এর সাথে মিলিয়ে দেখে, কোথাও এক চুল অমিল পেলেই সেটা ঠিক করে blueprint-এর মতো বানিয়ে দেয়।

একদিন রাতে এক শ্রমিক নিজের বুদ্ধিতে একটা বাড়তি দেয়াল তুলে ফেলল, যেটা blueprint-এ নেই। সকালে ইবনে সিনা এসে দেখল বিল্ডিং আর blueprint মিলছে না — সঙ্গে সঙ্গে সে সেই অননুমোদিত দেয়াল ভেঙে আগের অবস্থায় ফিরিয়ে দিল। কেউ যদি সত্যিই একটা নতুন দেয়াল চায়, তার একটাই পথ: আগে আর্কাইভে গিয়ে master blueprint-এ পরিবর্তনটা আঁকতে হবে, আল-খোয়ারিজমির মতো একজন যাচাই করে অনুমোদন দেবে, তারপরই সেটা বিল্ডিংয়ে ফুটে উঠবে। এভাবে প্রতিটা পরিবর্তনের একটা পরিষ্কার ইতিহাস থেকে যায় — কে, কবে, কী বদলাল, সব blueprint-এই লেখা।

এই গল্পটাই GitOps। আর্কাইভের master blueprint হলো আপনার Git repo — একমাত্র source of truth। foreman ইবনে সিনার ক্রমাগত বিল্ডিং আর blueprint মিলিয়ে দেখা হলো GitOps controller-এর continuous reconciliation — cluster-কে সবসময় Git-এর সাথে মেলানো। রাতের অননুমোদিত দেয়াল ভেঙে ফেলাটা হলো drift অটোমেটিক ঠিক করা — কেউ সরাসরি kubectl edit করলে controller সেটা Git-এর অবস্থায় revert করে দেয়। আর আগে blueprint আঁকতে হবে বলার মানে হলো, পরিবর্তন হয় শুধু commit/PR দিয়ে, সরাসরি cluster হাতে ধরে নয় — ফলে বিনামূল্যে পূর্ণ audit history পাওয়া যায়, আর rollback মানে শুধু আগের commit-এ ফিরে যাওয়া। বাস্তবে Argo CD বা Flux ঠিক এই foreman-এর কাজটাই করে — Git repo watch করে, drift ধরে, আর নীরবে cluster-কে source of truth-এর সাথে মিলিয়ে রাখে।

GitOps Principles

  1. Declarative — desired state ফাইলে বর্ণিত (YAML manifest, Helm chart)
  2. Versioned — সব state git-এ সংরক্ষিত; প্রতিটা পরিবর্তন একটা commit
  3. Pulled — ক্লাস্টারের ভেতরের একটা controller git থেকে pull করে (CI থেকে push করার বদলে)
  4. Reconciled — controller ক্রমাগত নিশ্চিত করে যে cluster state git-এর সাথে মেলে

সুবিধা:

  • Cluster state সবসময় git-এ — বিনামূল্যে audit log
  • একটা deployment রোলব্যাক করা = git revert
  • Drift অটোমেটিক ধরা পড়ে এবং ঠিক হয়
  • CI/CD pipeline থেকে kubectl access লাগে না (attack surface কমে)

Helm

Helm হলো Kubernetes-এর একটা package manager — template + values ফাইল = rendered manifest।

my-chart/
  Chart.yaml           # chart metadata
  values.yaml          # default values
  values-production.yml # environment overrides
  templates/
    deployment.yaml
    service.yaml
    ingress.yaml
    _helpers.tpl       # reusable template snippets
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: { { include "order-service.fullname" . } }
  labels: { { - include "order-service.labels" . | nindent 4 } }
spec:
  replicas: { { .Values.replicaCount } }
  template:
    spec:
      containers:
        - name: { { .Chart.Name } }
          image: '{{ .Values.image.repository }}:{{ .Values.image.tag }}'
          resources: { { - toYaml .Values.resources | nindent 12 } }
# values.yaml
replicaCount: 2
image:
  repository: myorg/order-service
  tag: latest

resources:
  requests:
    memory: 256Mi
    cpu: 250m
  limits:
    memory: 512Mi
    cpu: 1000m
# values-production.yaml — override for production
replicaCount: 5
image:
  tag: '1.2.0' # pin exact version in production

resources:
  requests:
    memory: 512Mi
    cpu: 500m
# Install
helm install order-service ./my-chart \
  -f values.yaml \
  -f values-production.yaml \
  -n production

# Upgrade
helm upgrade order-service ./my-chart \
  -f values.yaml \
  -f values-production.yaml \
  -n production

# Rollback
helm rollback order-service 2 -n production  # rollback to revision 2

# List releases
helm list -n production

ArgoCD

ArgoCD একটা git repo watch করে এবং নিশ্চিত করে যে ক্লাস্টার তার সাথে মেলে। যেকোনো git commit একটা sync ট্রিগার করে।

# Install ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Get initial admin password
kubectl get secret argocd-initial-admin-secret -n argocd -o jsonpath="{.data.password}" | base64 -d

# Access UI
kubectl port-forward svc/argocd-server -n argocd 8080:443

Application definition:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: order-service
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/k8s-config
    targetRevision: main
    path: apps/order-service
    helm:
      valueFiles:
        - values.yaml
        - values-production.yaml

  destination:
    server: https://kubernetes.default.svc
    namespace: production

  syncPolicy:
    automated:
      prune: true # delete resources removed from git
      selfHeal: true # revert manual changes to cluster
    syncOptions:
      - CreateNamespace=true

automated.selfHeal: true থাকলে, যেকোনো ম্যানুয়াল kubectl apply বা kubectl edit সঙ্গে সঙ্গে git-এর সাথে মেলাতে revert হয়ে যায়। Cluster state পুরোপুরি git দিয়ে নিয়ন্ত্রিত।

ArgoCD ApplicationSet — একই app একাধিক cluster/environment-এ deploy করুন:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: order-service
  namespace: argocd
spec:
  generators:
    - list:
        elements:
          - cluster: staging
            url: https://staging.k8s.example.com
            values_file: values-staging.yaml
          - cluster: production
            url: https://production.k8s.example.com
            values_file: values-production.yaml
  template:
    metadata:
      name: 'order-service-{{cluster}}'
    spec:
      source:
        repoURL: https://github.com/myorg/k8s-config
        path: apps/order-service
        helm:
          valueFiles:
            - values.yaml
            - '{{values_file}}'
      destination:
        server: '{{url}}'
        namespace: production

Progressive Delivery with Argo Rollouts

স্ট্যান্ডার্ড Kubernetes rolling update বাইনারি — আপনি হয় পুরনো নয় নতুনে। Argo Rollouts এর সাথে যোগ করে:

  • Canary — নতুন version-এ X% traffic পাঠান, metric দেখুন, ধীরে ধীরে বাড়ান
  • Blue-green — দুই version একসাথে চালান, atomic-ভাবে traffic switch করুন
kubectl apply -n argo-rollouts \
  -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

analysis সহ Canary:

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: order-service
  namespace: production
spec:
  replicas: 5
  strategy:
    canary:
      steps:
        - setWeight: 10 # send 10% to new version
        - pause: { duration: 10m } # wait 10 minutes
        - analysis:
            templates:
              - templateName: success-rate
        - setWeight: 30
        - pause: { duration: 10m }
        - setWeight: 60
        - pause: { duration: 10m }
        - setWeight: 100 # fully roll out

      canaryService: order-service-canary
      stableService: order-service-stable

  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service
          image: myorg/order-service:1.2.0
# AnalysisTemplate — query Prometheus, abort if error rate too high
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: success-rate
  namespace: production
spec:
  metrics:
    - name: success-rate
      interval: 1m
      successCondition: result[0] >= 0.99 # 99%+ success rate
      failureLimit: 3
      provider:
        prometheus:
          address: http://prometheus:9090
          query: |
            sum(rate(http_requests_total{
              job="order-service",
              status!~"5.."
            }[5m])) /
            sum(rate(http_requests_total{
              job="order-service"
            }[5m]))

analysis ফেইল করলে: Argo Rollouts অটোমেটিক রোলব্যাক করে। কোনো মানুষের হস্তক্ষেপ লাগে না।

# Watch rollout progress
kubectl argo rollouts get rollout order-service -n production --watch

# Manually abort
kubectl argo rollouts abort order-service -n production

# Manually promote (skip pause)
kubectl argo rollouts promote order-service -n production

CI/CD Pipeline

# .github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build and push image
        run: |
          docker build -t myorg/order-service:${{ github.sha }} .
          docker push myorg/order-service:${{ github.sha }}

      # Update the image tag in the GitOps repo
      - name: Update image tag
        run: |
          git clone https://x-token:${{ secrets.GITOPS_TOKEN }}@github.com/myorg/k8s-config
          cd k8s-config

          # Update the tag in values file
          sed -i "s/tag: .*/tag: \"${{ github.sha }}\"/" apps/order-service/values-production.yaml

          git config user.email "ci@myorg.com"
          git config user.name "CI"
          git commit -am "deploy order-service ${{ github.sha }}"
          git push

      # ArgoCD detects the git change and syncs automatically

CI pipeline কখনো সরাসরি kubectl বা ক্লাস্টার স্পর্শ করে না। এটা শুধু git আপডেট করে। বাকিটা ArgoCD সামলায়। এর মানে:

  • CI-এর cluster credential লাগে না
  • প্রতিটা deploy একটা git commit (পূর্ণ audit log)
  • Rollback = git revert + ArgoCD sync করে