574 lines
15 KiB
Markdown
574 lines
15 KiB
Markdown
# GitOps Migration Plan: Implement Production-Grade Architecture
|
|
|
|
## Current State → Target State
|
|
|
|
### Current (Messy)
|
|
```
|
|
k8s/
|
|
├── talos-ci-cd/ (forgejo, runner)
|
|
├── talos-iam/ (authentik, vault)
|
|
├── logging/ (loki, promtail, grafana)
|
|
├── monitoring/ (prometheus, alerts)
|
|
├── storage/ (minio, longhorn)
|
|
├── ddb/ (postgres)
|
|
├── sqs/ (kafka, queue-crd)
|
|
├── temporal/ (temporal)
|
|
├── argocd/apps/ (20 Applications scattered)
|
|
└── ... (more scattered)
|
|
```
|
|
|
|
### Target (Clean, Layered)
|
|
```
|
|
k8s/
|
|
├── infrastructure/ (namespaces, storage, RBAC)
|
|
├── bootstrap/ (cert-manager, cilium, ingress-nginx)
|
|
├── platform/ (storage, observability: minio, longhorn, loki, prometheus)
|
|
├── security/ (authentik, vault, cert-issuer)
|
|
├── applications/ (forgejo, grafana, portainer, temporal, llm)
|
|
├── data/ (postgres, redis, kafka)
|
|
└── argocd/
|
|
├── projects/ (AppProject definitions)
|
|
└── apps/ (6 layer Applications only)
|
|
```
|
|
|
|
## Phase 1: Plan & Validate (Week 1)
|
|
|
|
### Step 1.1: Review GITOPS_ARCHITECTURE.md
|
|
- [ ] Understand directory structure
|
|
- [ ] Understand layer dependencies
|
|
- [ ] Understand Kustomization strategy
|
|
- User approval: YES/NO
|
|
|
|
### Step 1.2: Audit current resources
|
|
```bash
|
|
# Export all current resources
|
|
kubectl get all -A -o yaml > /tmp/current-state-backup.yaml
|
|
|
|
# Count resources per layer
|
|
kubectl get deployments -A | wc -l
|
|
kubectl get statefulsets -A | wc -l
|
|
kubectl get daemonsets -A | wc -l
|
|
kubectl get services -A | wc -l
|
|
kubectl get configmaps -A | wc -l
|
|
kubectl get secrets -A | wc -l
|
|
```
|
|
|
|
### Step 1.3: Identify secrets needing encryption
|
|
```bash
|
|
# Find secrets in current manifests
|
|
grep -r "kind: Secret" k8s/ --include="*.yaml"
|
|
grep -r "password" k8s/ --include="*.yaml"
|
|
grep -r "token" k8s/ --include="*.yaml"
|
|
|
|
# Plan SOPS encryption for:
|
|
# - Authentik bootstrap password
|
|
# - MinIO credentials
|
|
# - Database passwords
|
|
# - API tokens
|
|
```
|
|
|
|
### Step 1.4: Dependency mapping
|
|
```
|
|
Layer 0 (Infrastructure)
|
|
└─ Layer 1 (Bootstrap)
|
|
├─ cert-manager (creates certificates)
|
|
├─ cilium (network)
|
|
└─ ingress-nginx (entry point)
|
|
└─ Layer 2 (Platform)
|
|
├─ minio (storage)
|
|
├─ longhorn (PV storage)
|
|
├─ loki (logs)
|
|
└─ prometheus (metrics)
|
|
└─ Layer 3 (Security)
|
|
├─ authentik (auth)
|
|
└─ vault (secrets)
|
|
└─ Layer 4 (Applications)
|
|
├─ forgejo
|
|
├─ grafana
|
|
├─ portainer
|
|
├─ temporal
|
|
└─ llm
|
|
└─ Layer 5 (Data)
|
|
├─ postgres
|
|
├─ redis
|
|
└─ kafka
|
|
```
|
|
|
|
## Phase 2: Build Directory Structure (Weeks 2-3)
|
|
|
|
### Step 2.1: Create base directories
|
|
```bash
|
|
cd k8s/
|
|
|
|
# Create layers
|
|
mkdir -p infrastructure bootstrap platform security applications data
|
|
|
|
# Create kustomization.yaml for each
|
|
for dir in infrastructure bootstrap platform security applications data; do
|
|
cat > $dir/kustomization.yaml << 'EOF'
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
namespace: CHANGE_ME
|
|
|
|
resources: [] # Will add resources below
|
|
|
|
# Placeholders for this layer
|
|
EOF
|
|
done
|
|
```
|
|
|
|
### Step 2.2: Migrate Layer 0 (Infrastructure)
|
|
**Resources to create:**
|
|
- Namespaces (all 20+)
|
|
- Storage classes (longhorn, xfs, longhorn-kafka)
|
|
- Service accounts (terraform-ci, etc.)
|
|
- Cluster roles (terraform-ci, admin, etc.)
|
|
- Network policies
|
|
|
|
**Action:**
|
|
```bash
|
|
# Extract from current cluster
|
|
kubectl get namespace -o yaml > k8s/infrastructure/namespaces.yaml
|
|
kubectl get storageclass -o yaml > k8s/infrastructure/storage-classes.yaml
|
|
kubectl get serviceaccount -A -o yaml > k8s/infrastructure/service-accounts.yaml
|
|
kubectl get clusterrole -o yaml > k8s/infrastructure/cluster-roles.yaml
|
|
|
|
# Clean up (remove status, owner refs, etc.)
|
|
# Add to k8s/infrastructure/kustomization.yaml:
|
|
resources:
|
|
- namespaces.yaml
|
|
- storage-classes.yaml
|
|
- service-accounts.yaml
|
|
- cluster-roles.yaml
|
|
|
|
# Test
|
|
kustomize build k8s/infrastructure/
|
|
```
|
|
|
|
**Deliverables:**
|
|
- [x] k8s/infrastructure/kustomization.yaml
|
|
- [x] k8s/infrastructure/namespaces.yaml
|
|
- [x] k8s/infrastructure/storage-classes.yaml
|
|
- [x] k8s/infrastructure/{service-accounts,cluster-roles}.yaml
|
|
|
|
### Step 2.3: Migrate Layer 1 (Bootstrap)
|
|
|
|
**Services: cert-manager, cilium, ingress-nginx**
|
|
|
|
**Action:**
|
|
```bash
|
|
# Create directories
|
|
mkdir -p bootstrap/{cert-manager,cilium,ingress-nginx}
|
|
|
|
# For each service:
|
|
# 1. Export Helm values
|
|
helm get values cert-manager -n cert-manager > bootstrap/cert-manager/values.yaml
|
|
|
|
# 2. Create kustomization.yaml with Helm chart ref
|
|
cat > bootstrap/cert-manager/kustomization.yaml << 'EOF'
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
namespace: cert-manager
|
|
|
|
helmCharts:
|
|
- name: cert-manager
|
|
repo: https://charts.jetstack.io
|
|
version: v1.21.0
|
|
releaseName: cert-manager
|
|
valuesFile: values.yaml
|
|
EOF
|
|
|
|
# 3. Repeat for cilium, ingress-nginx
|
|
|
|
# 4. Add to k8s/bootstrap/kustomization.yaml:
|
|
resources:
|
|
- cert-manager/kustomization.yaml
|
|
- cilium/kustomization.yaml
|
|
- ingress-nginx/kustomization.yaml
|
|
```
|
|
|
|
**Deliverables:**
|
|
- [x] k8s/bootstrap/{cert-manager,cilium,ingress-nginx}/kustomization.yaml
|
|
- [x] k8s/bootstrap/{cert-manager,cilium,ingress-nginx}/values.yaml
|
|
- [x] k8s/bootstrap/kustomization.yaml
|
|
|
|
### Step 2.4: Migrate Layer 2 (Platform)
|
|
|
|
**Services: minio, longhorn, loki, prometheus, promtail**
|
|
|
|
**Action:**
|
|
```bash
|
|
# Create directories
|
|
mkdir -p platform/{minio,longhorn,loki,prometheus,promtail}
|
|
|
|
# Migrate minio
|
|
# 1. Export existing values
|
|
helm get values minio -n storage > platform/minio/values.yaml
|
|
|
|
# 2. Export bucket configs
|
|
kubectl get jobs,configmaps,secrets -n storage -o yaml > platform/minio/config/
|
|
|
|
# 3. Create kustomization.yaml
|
|
cat > platform/minio/kustomization.yaml << 'EOF'
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
namespace: storage
|
|
|
|
helmCharts:
|
|
- name: minio
|
|
repo: https://charts.min.io
|
|
version: 14.6.25 # Current version
|
|
releaseName: minio
|
|
valuesFile: values.yaml
|
|
|
|
resources:
|
|
- config/minio-buckets.yaml
|
|
EOF
|
|
|
|
# Repeat for loki, prometheus, promtail
|
|
```
|
|
|
|
**Deliverables:**
|
|
- [x] k8s/platform/{minio,longhorn,loki,prometheus,promtail}/kustomization.yaml
|
|
- [x] k8s/platform/{minio,longhorn,loki,prometheus,promtail}/values.yaml
|
|
- [x] k8s/platform/kustomization.yaml
|
|
|
|
### Step 2.5: Migrate Layer 3 (Security)
|
|
|
|
**Services: authentik, vault**
|
|
|
|
**Action:**
|
|
```bash
|
|
# Create directories
|
|
mkdir -p security/{authentik,vault}
|
|
|
|
# Migrate authentik
|
|
helm get values authentik -n iam > security/authentik/values.yaml
|
|
|
|
# Export Authentik resources
|
|
kubectl get -n iam authentik_application -o yaml > security/authentik/config/apps.yaml
|
|
kubectl get -n iam authentik_group -o yaml > security/authentik/config/groups.yaml
|
|
kubectl get -n iam authentik_provider_oauth2 -o yaml > security/authentik/config/oauth-providers.yaml
|
|
|
|
# Create kustomization.yaml
|
|
cat > security/authentik/kustomization.yaml << 'EOF'
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
namespace: iam
|
|
|
|
helmCharts:
|
|
- name: authentik
|
|
repo: https://charts.goauthentik.io
|
|
version: 2024.12.1
|
|
releaseName: authentik
|
|
valuesFile: values.yaml
|
|
|
|
resources:
|
|
- config/apps.yaml
|
|
- config/groups.yaml
|
|
- config/oauth-providers.yaml
|
|
EOF
|
|
|
|
# Repeat for vault
|
|
```
|
|
|
|
**Deliverables:**
|
|
- [x] k8s/security/{authentik,vault}/kustomization.yaml
|
|
- [x] k8s/security/{authentik,vault}/values.yaml
|
|
- [x] k8s/security/authentik/config/{apps,groups,oauth-providers}.yaml
|
|
- [x] k8s/security/kustomization.yaml
|
|
|
|
### Step 2.6: Migrate Layer 4 (Applications)
|
|
|
|
**Services: forgejo, grafana, portainer, temporal, llm**
|
|
|
|
**Action:**
|
|
```bash
|
|
# Create directories
|
|
mkdir -p applications/{forgejo,grafana,portainer,temporal,llm}
|
|
|
|
# Move existing manifests
|
|
cp -r k8s/talos-ci-cd/* applications/forgejo/
|
|
cp -r k8s/monitoring/* applications/grafana/ # Includes dashboards, etc.
|
|
cp -r k8s/portainer/* applications/portainer/
|
|
cp -r k8s/temporal/* applications/temporal/
|
|
cp -r k8s/llm/* applications/llm/
|
|
|
|
# For each, create kustomization.yaml with Helm chart ref
|
|
# (or keep existing manifests if not Helm)
|
|
|
|
# Create layer kustomization.yaml
|
|
cat > applications/kustomization.yaml << 'EOF'
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
resources:
|
|
- forgejo/kustomization.yaml
|
|
- grafana/kustomization.yaml
|
|
- portainer/kustomization.yaml
|
|
- temporal/kustomization.yaml
|
|
- llm/kustomization.yaml
|
|
EOF
|
|
```
|
|
|
|
**Deliverables:**
|
|
- [x] k8s/applications/{forgejo,grafana,portainer,temporal,llm}/kustomization.yaml
|
|
- [x] k8s/applications/{forgejo,grafana,portainer,temporal,llm}/values.yaml
|
|
- [x] k8s/applications/kustomization.yaml
|
|
|
|
### Step 2.7: Migrate Layer 5 (Data)
|
|
|
|
**Services: postgres (CloudNativePG), redis, kafka**
|
|
|
|
**Action:**
|
|
```bash
|
|
# Create directories
|
|
mkdir -p data/{postgres,redis,kafka}
|
|
|
|
# Export existing configurations
|
|
kubectl get cnpg -A -o yaml > data/postgres/config.yaml
|
|
kubectl get redis -A -o yaml > data/redis/config.yaml
|
|
kubectl get kafka -A -o yaml > data/kafka/config.yaml
|
|
|
|
# Create kustomization.yaml for each
|
|
|
|
# Repeat process...
|
|
```
|
|
|
|
**Deliverables:**
|
|
- [x] k8s/data/{postgres,redis,kafka}/kustomization.yaml
|
|
- [x] k8s/data/kustomization.yaml
|
|
|
|
## Phase 3: Create ArgoCD Application Definitions (Week 4)
|
|
|
|
### Step 3.1: Create layer Applications
|
|
```bash
|
|
mkdir -p k8s/argocd/apps/layers
|
|
|
|
# Root application (Layer 0 only, triggers rest)
|
|
cat > k8s/argocd/apps/root-app.yaml << 'EOF'
|
|
apiVersion: argoproj.io/v1alpha1
|
|
kind: Application
|
|
metadata:
|
|
name: homelab-root
|
|
namespace: argocd
|
|
spec:
|
|
project: homelab
|
|
source:
|
|
repoURL: https://forgejo.riotpiao.homelab.com/riotpiao.com/homelab.git
|
|
targetRevision: main
|
|
path: k8s/infrastructure
|
|
destination:
|
|
server: https://kubernetes.default.svc
|
|
syncPolicy:
|
|
automated:
|
|
prune: true
|
|
selfHeal: true
|
|
EOF
|
|
|
|
# Layer 1 application
|
|
cat > k8s/argocd/apps/layer-1-bootstrap.yaml << 'EOF'
|
|
apiVersion: argoproj.io/v1alpha1
|
|
kind: Application
|
|
metadata:
|
|
name: layer-1-bootstrap
|
|
namespace: argocd
|
|
annotations:
|
|
argocd.argoproj.io/sync-wave: "1"
|
|
spec:
|
|
project: homelab
|
|
source:
|
|
repoURL: https://forgejo.riotpiao.homelab.com/riotpiao.com/homelab.git
|
|
targetRevision: main
|
|
path: k8s/bootstrap
|
|
destination:
|
|
server: https://kubernetes.default.svc
|
|
syncPolicy:
|
|
automated:
|
|
prune: true
|
|
selfHeal: true
|
|
EOF
|
|
|
|
# Repeat for layers 2, 3, 4, 5 (sync-wave: 2, 3, 4, 5)
|
|
```
|
|
|
|
**Deliverables:**
|
|
- [x] k8s/argocd/apps/root-app.yaml
|
|
- [x] k8s/argocd/apps/layer-{1,2,3,4,5}-*.yaml
|
|
|
|
### Step 3.2: Create kustomization.yaml for apps
|
|
```bash
|
|
cat > k8s/argocd/apps/kustomization.yaml << 'EOF'
|
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
kind: Kustomization
|
|
|
|
resources:
|
|
- root-app.yaml
|
|
- layer-1-bootstrap.yaml
|
|
- layer-2-platform.yaml
|
|
- layer-3-security.yaml
|
|
- layer-4-applications.yaml
|
|
- layer-5-data.yaml
|
|
EOF
|
|
```
|
|
|
|
## Phase 4: Deploy & Validate (Week 5)
|
|
|
|
### Step 4.1: Pre-flight checks
|
|
```bash
|
|
# Validate all kustomization files
|
|
for dir in k8s/{infrastructure,bootstrap,platform,security,applications,data}; do
|
|
echo "Validating $dir..."
|
|
kustomize build $dir > /tmp/validate.yaml
|
|
kubeval /tmp/validate.yaml || exit 1
|
|
done
|
|
|
|
# Validate ArgoCD apps
|
|
kubeval k8s/argocd/apps/*.yaml
|
|
|
|
# Test YAML lint
|
|
yamllint k8s/
|
|
```
|
|
|
|
### Step 4.2: Deploy root application
|
|
```bash
|
|
# Apply root app (Layer 0 only)
|
|
kubectl apply -f k8s/argocd/apps/root-app.yaml
|
|
|
|
# Watch sync
|
|
argocd app watch homelab-root
|
|
|
|
# Verify infrastructure deployed
|
|
kubectl get ns # Should have all namespaces
|
|
kubectl get sc # Should have all storage classes
|
|
```
|
|
|
|
### Step 4.3: Deploy layer applications
|
|
```bash
|
|
# Apply layer applications (one by one)
|
|
kubectl apply -f k8s/argocd/apps/layer-1-bootstrap.yaml
|
|
sleep 5
|
|
argocd app watch layer-1-bootstrap
|
|
|
|
# Once Layer 1 synced: Layer 2
|
|
kubectl apply -f k8s/argocd/apps/layer-2-platform.yaml
|
|
argocd app watch layer-2-platform
|
|
|
|
# ... repeat for layers 3, 4, 5
|
|
```
|
|
|
|
### Step 4.4: Monitor for issues
|
|
```bash
|
|
# Check ArgoCD apps
|
|
argocd app list
|
|
|
|
# Watch events
|
|
kubectl get events -A -w
|
|
|
|
# Monitor pod status
|
|
kubectl get pods -A
|
|
|
|
# Check logs
|
|
kubectl logs -f -n argocd deployment/argocd-application-controller
|
|
```
|
|
|
|
### Step 4.5: Validate state drift protection
|
|
```bash
|
|
# Manually edit a resource
|
|
kubectl edit deployment cert-manager -n cert-manager
|
|
# Change replicas from 1 → 2
|
|
|
|
# Wait 3 minutes (ArgoCD reconciliation interval)
|
|
sleep 180
|
|
|
|
# Check: should be back to 1 replica
|
|
kubectl get deployment cert-manager -n cert-manager
|
|
# Expected: 1/1 Ready (reverted by ArgoCD)
|
|
|
|
# Verify in ArgoCD
|
|
argocd app get layer-1-bootstrap
|
|
# Expected: Synced status
|
|
```
|
|
|
|
## Phase 5: Cleanup (Week 6)
|
|
|
|
### Step 5.1: Delete old directories
|
|
```bash
|
|
# After all apps synced successfully:
|
|
rm -rf k8s/talos-ci-cd/
|
|
rm -rf k8s/talos-iam/
|
|
rm -rf k8s/logging/
|
|
rm -rf k8s/monitoring/
|
|
rm -rf k8s/storage/
|
|
rm -rf k8s/ddb/
|
|
rm -rf k8s/sqs/
|
|
rm -rf k8s/temporal/
|
|
# Keep only: infrastructure, bootstrap, platform, security, applications, data, argocd
|
|
```
|
|
|
|
### Step 5.2: Update CI/CD pipeline
|
|
```bash
|
|
# Update .forgejo/workflows/
|
|
# - Remove: terraform validate/plan/apply
|
|
# - Add: kustomize build validation
|
|
# - Add: argocd app validation
|
|
```
|
|
|
|
### Step 5.3: Archive old configuration
|
|
```bash
|
|
# Keep for reference only
|
|
mkdir k8s/.archive/
|
|
git mv k8s/old-structure-backup k8s/.archive/
|
|
git commit -m "archive: old k8s structure (moved to pure GitOps)"
|
|
```
|
|
|
|
## Rollback Plan
|
|
|
|
**If something breaks during migration:**
|
|
|
|
```bash
|
|
# Option 1: Rollback entire layer
|
|
git checkout HEAD~1 -- k8s/bootstrap/
|
|
git commit -m "revert: bootstrap layer (investigating)"
|
|
# ArgoCD will resync to previous version automatically
|
|
|
|
# Option 2: Pause ArgoCD sync
|
|
argocd app set layer-1-bootstrap --sync-policy none
|
|
# Investigate, then re-enable:
|
|
argocd app set layer-1-bootstrap --sync-policy automated
|
|
|
|
# Option 3: Full rollback to pre-migration
|
|
git reset --hard <commit-before-migration>
|
|
argocd app set homelab-root --sync-policy none
|
|
# Manual investigation, then re-enable
|
|
```
|
|
|
|
## Timeline Summary
|
|
|
|
```
|
|
Week 1: Plan & validate (reviews, dependency mapping)
|
|
Week 2: Layers 0-1 (infrastructure, bootstrap)
|
|
Week 3: Layers 2-3 (platform, security)
|
|
Week 3: Layers 4-5 (applications, data)
|
|
Week 4: ArgoCD applications + layer definitions
|
|
Week 5: Deploy & validate (watch for issues)
|
|
Week 6: Cleanup & CI/CD updates
|
|
```
|
|
|
|
**Total: 6 weeks, non-disruptive (all layers coexist during migration)**
|
|
|
|
## Success Criteria
|
|
|
|
✓ All 20+ services deployed via ArgoCD
|
|
✓ No manual kubectl apply in production
|
|
✓ State drift detected & corrected automatically
|
|
✓ All changes in git (reviewed via PR)
|
|
✓ Rollback possible at any time (git history)
|
|
✓ CI/CD validates all commits
|
|
✓ Secrets encrypted with SOPS
|
|
✓ New services can be added (copy service directory)
|