Phase 4 implementation (true IaC): - ArgoCD Application: terraform-apply (PostSync Hook Job) - Hook Job runs: terraform init && terraform apply -auto-approve - ServiceAccount + ClusterRole for cluster-admin - SOPS-encrypted S3 credentials (terraform-s3-secrets.enc.yaml) - Pre-commit hook blocks local 'terraform apply' - In-cluster kubeconfig for Kubernetes provider - AWS credentials file with minio profile State imports: - Imported kubernetes_persistent_volume_claim.portainer (dashboard/portainer) - Imported kubernetes_persistent_volume_claim.grafana (logging/grafana) - Imported kubernetes_persistent_volume_claim.loki (logging/storage-loki-0) Workflow: 1. Edit terraform/*.tf files 2. git push to main 3. ArgoCD detects changes in k8s/hooks/phase4 4. Hook Job automatically runs terraform apply 5. No manual 'terraform apply' needed ever again
119 lines
3.5 KiB
YAML
119 lines
3.5 KiB
YAML
apiVersion: batch/v1
|
|
kind: Job
|
|
metadata:
|
|
name: terraform-apply
|
|
namespace: argocd
|
|
annotations:
|
|
argocd.argoproj.io/hook: PostSync
|
|
argocd.argoproj.io/hook-delete-policy: HookSucceeded
|
|
spec:
|
|
backoffLimit: 3
|
|
template:
|
|
spec:
|
|
serviceAccountName: terraform-apply
|
|
containers:
|
|
- name: terraform
|
|
image: hashicorp/terraform:latest
|
|
command: ["/bin/sh", "-c"]
|
|
args:
|
|
- |
|
|
set -e
|
|
|
|
echo "=== Terraform Apply Hook (ArgoCD PostSync) ==="
|
|
|
|
# Trust homelab CA for self-signed Forgejo certificate
|
|
cp /etc/ssl/certs/homelab-ca.crt /usr/local/share/ca-certificates/homelab-ca.crt
|
|
update-ca-certificates
|
|
|
|
# Clone repo
|
|
git clone --depth 1 https://forgejo.riotpiao.homelab.com/riotpiao.com/homelab.git /repo
|
|
cd /repo/terraform
|
|
|
|
# Load S3 credentials from mounted secrets
|
|
export AWS_ACCESS_KEY_ID=$(cat /run/secrets/s3/AWS_ACCESS_KEY_ID)
|
|
export AWS_SECRET_ACCESS_KEY=$(cat /run/secrets/s3/AWS_SECRET_ACCESS_KEY)
|
|
export AWS_ENDPOINT_URL=$(cat /run/secrets/s3/AWS_ENDPOINT_URL)
|
|
|
|
# Create AWS credentials file with minio profile
|
|
mkdir -p ~/.aws
|
|
cat > ~/.aws/credentials << EOF
|
|
[minio]
|
|
aws_access_key_id = $(cat /run/secrets/s3/AWS_ACCESS_KEY_ID)
|
|
aws_secret_access_key = $(cat /run/secrets/s3/AWS_SECRET_ACCESS_KEY)
|
|
EOF
|
|
|
|
cat > ~/.aws/config << EOF
|
|
[default]
|
|
region = us-east-1
|
|
EOF
|
|
|
|
# Generate in-cluster kubeconfig for Terraform provider
|
|
mkdir -p /root/.kube
|
|
cat > /root/.kube/config << KUBEEOF
|
|
apiVersion: v1
|
|
kind: Config
|
|
clusters:
|
|
- cluster:
|
|
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
|
server: https://kubernetes.default:443
|
|
name: in-cluster
|
|
contexts:
|
|
- context:
|
|
cluster: in-cluster
|
|
user: terraform
|
|
name: in-cluster
|
|
current-context: in-cluster
|
|
users:
|
|
- name: terraform
|
|
user:
|
|
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
|
|
KUBEEOF
|
|
|
|
export KUBECONFIG=/root/.kube/config
|
|
|
|
# Initialize and apply
|
|
echo "Initializing Terraform..."
|
|
terraform init
|
|
|
|
echo "Planning Terraform changes..."
|
|
terraform plan \
|
|
-var "kubeconfig_path=/root/.kube/config" \
|
|
-out=tfplan
|
|
|
|
echo "Applying Terraform..."
|
|
terraform apply -auto-approve tfplan
|
|
|
|
echo "✓ Terraform apply complete"
|
|
volumeMounts:
|
|
- name: s3-creds
|
|
mountPath: /run/secrets/s3
|
|
readOnly: true
|
|
- name: homelab-ca
|
|
mountPath: /etc/ssl/certs/homelab-ca.crt
|
|
subPath: tls.crt
|
|
readOnly: true
|
|
resources:
|
|
requests:
|
|
memory: "256Mi"
|
|
cpu: "250m"
|
|
limits:
|
|
memory: "1Gi"
|
|
cpu: "1"
|
|
volumes:
|
|
- name: s3-creds
|
|
projected:
|
|
sources:
|
|
- secret:
|
|
name: terraform-s3-creds
|
|
items:
|
|
- key: AWS_ACCESS_KEY_ID
|
|
path: AWS_ACCESS_KEY_ID
|
|
- key: AWS_SECRET_ACCESS_KEY
|
|
path: AWS_SECRET_ACCESS_KEY
|
|
- key: AWS_ENDPOINT_URL
|
|
path: AWS_ENDPOINT_URL
|
|
- name: homelab-ca
|
|
secret:
|
|
secretName: homelab-ca-secret
|
|
restartPolicy: Never
|