# Gitops Patterns

> When to activate: GitOps, ArgoCD, Flux, app of apps, sync policy, SOPS, sealed secrets, drift detection, reconciliation

- Skill: `mattakushi432/gitops-patterns` (Agent Skill)
- Install (CLI): `npx skillmds@latest add mattakushi432/gitops-patterns`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mattakushi432/gitops-patterns/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Mattakushi432 (https://skillmd.com/u/mattakushi432)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mattakushi432/gitops-patterns

---

# GitOps Patterns

## Core Principle

```
Git is the single source of truth.
  - Desired state lives in Git (manifests, Helm values, Kustomize overlays)
  - A controller continuously reconciles cluster state to match Git
  - No direct kubectl apply in production — all changes via PR
  - Audit trail = Git history
```

## ArgoCD — App of Apps Pattern

```yaml
# Root app manages all other apps
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: root
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/gitops
    targetRevision: main
    path: apps/
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
```

```yaml
# apps/myapp.yaml — child app
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp-prod
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: prod
  source:
    repoURL: https://github.com/myorg/gitops
    targetRevision: main
    path: environments/prod/myapp
  destination:
    server: https://kubernetes.default.svc
    namespace: prod
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
  ignoreDifferences:
    - group: apps
      kind: Deployment
      jsonPointers:
        - /spec/replicas   # managed by HPA
```

## Repo Structure

```
gitops/
  apps/                    # ArgoCD app definitions (App of Apps)
    myapp.yaml
    database.yaml
  environments/
    prod/
      myapp/
        kustomization.yaml
        deployment-patch.yaml
        values.yaml
    staging/
      myapp/
        kustomization.yaml
        values.yaml
  base/
    myapp/
      deployment.yaml
      service.yaml
      kustomization.yaml
```

## Kustomize Overlay

```yaml
# environments/prod/myapp/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../../base/myapp
patches:
  - path: deployment-patch.yaml
images:
  - name: ghcr.io/myorg/myapp
    newTag: 1.2.3
configMapGenerator:
  - name: myapp-config
    literals:
      - LOG_LEVEL=info
      - REPLICAS=3
```

## Secrets with SOPS + age

```bash
# Generate age key
age-keygen -o ~/.config/sops/age/keys.txt

# .sops.yaml (in repo root)
cat > .sops.yaml <<EOF
creation_rules:
  - path_regex: secrets/.*\.yaml$
    age: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
EOF

# Encrypt secret
sops --encrypt --in-place secrets/prod/db-secret.yaml

# ArgoCD reads SOPS via ksops plugin or ArgoCD-vault-plugin
```

## Flux CD (alternative to ArgoCD)

```yaml
# GitRepository source
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: gitops
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/myorg/gitops
  ref:
    branch: main
  secretRef:
    name: git-credentials
---
# Kustomization (reconciler)
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: myapp-prod
  namespace: flux-system
spec:
  interval: 5m
  path: ./environments/prod/myapp
  prune: true
  sourceRef:
    kind: GitRepository
    name: gitops
  healthChecks:
    - apiVersion: apps/v1
      kind: Deployment
      name: myapp
      namespace: prod
  timeout: 5m
```

## Image Update Automation (Flux)

```yaml
# Auto-update image tag in Git when new image is pushed
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
  name: myapp
spec:
  image: ghcr.io/myorg/myapp
  interval: 1m
---
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
  name: myapp
spec:
  imageRepositoryRef:
    name: myapp
  policy:
    semver:
      range: ">=1.0.0"
---
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageUpdateAutomation
metadata:
  name: myapp
spec:
  interval: 5m
  sourceRef:
    kind: GitRepository
    name: gitops
  git:
    push:
      branch: main
    commit:
      author:
        name: fluxbot
        email: flux@example.com
      messageTemplate: "chore: update myapp to {{range .Updated.Images}}{{.}}{{end}}"
  update:
    path: ./environments/prod
    strategy: Setters
```

## Key Rules
- Never `kubectl apply` directly to production — all changes via PR + GitOps sync
- Use `selfHeal: true` to auto-revert manual changes (drift correction)
- Separate app config repo from source code repo — different change cadence
- Use branch protection + required reviews on the GitOps repo
- Monitor sync status: alert if ArgoCD/Flux shows `OutOfSync` for > 10 minutes

