docs(terraform): add state management script and best practices guide
This commit is contained in:
@@ -0,0 +1,113 @@
|
|||||||
|
# Terraform State Management
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Terraform state for the homelab cluster is managed using a hybrid approach:
|
||||||
|
- **Remote backend:** S3 (MinIO) for centralized, shared state
|
||||||
|
- **Local backup:** Git-ignored backups for disaster recovery
|
||||||
|
|
||||||
|
## Backend Configuration
|
||||||
|
|
||||||
|
State is stored in MinIO S3:
|
||||||
|
|
||||||
|
```
|
||||||
|
Bucket: terraform-state
|
||||||
|
Key: homelab/terraform.tfstate
|
||||||
|
Endpoint: https://minio-api.riotpiao.homelab.com
|
||||||
|
Profile: minio
|
||||||
|
```
|
||||||
|
|
||||||
|
Configuration: `terraform/state.tf`
|
||||||
|
|
||||||
|
## Accessing State
|
||||||
|
|
||||||
|
### Pull state from S3
|
||||||
|
```bash
|
||||||
|
cd terraform
|
||||||
|
terraform state pull > terraform.tfstate.backup
|
||||||
|
```
|
||||||
|
|
||||||
|
### View resources
|
||||||
|
```bash
|
||||||
|
terraform state list
|
||||||
|
terraform state show <resource-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Import new resources
|
||||||
|
```bash
|
||||||
|
terraform import <resource-type>.<name> <resource-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Backup Strategy
|
||||||
|
|
||||||
|
### Automatic backups
|
||||||
|
Run the backup script periodically (e.g., cron):
|
||||||
|
```bash
|
||||||
|
scripts/terraform-state-backup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Backups are saved to: `~/.terraform-backups/homelab/`
|
||||||
|
|
||||||
|
### Manual backup
|
||||||
|
```bash
|
||||||
|
cd terraform
|
||||||
|
terraform state pull > /tmp/terraform-$(date +%s).tfstate
|
||||||
|
cp /tmp/terraform-*.tfstate ~/.terraform-backups/homelab/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Disaster Recovery
|
||||||
|
|
||||||
|
If state is corrupted or lost:
|
||||||
|
|
||||||
|
1. **Stop all infrastructure changes:**
|
||||||
|
```bash
|
||||||
|
git revert <commit> # Rollback infrastructure changes
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Restore from local backup:**
|
||||||
|
```bash
|
||||||
|
BACKUP_FILE=~/.terraform-backups/homelab/<timestamp>-terraform.tfstate
|
||||||
|
cd terraform
|
||||||
|
terraform state push $BACKUP_FILE
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Verify state:**
|
||||||
|
```bash
|
||||||
|
terraform state list
|
||||||
|
terraform plan
|
||||||
|
```
|
||||||
|
|
||||||
|
## S3 Bucket Setup
|
||||||
|
|
||||||
|
If S3 bucket doesn't exist, create it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl exec -n storage <minio-pod> -- mc mb minio/terraform-state --region us-east-1
|
||||||
|
```
|
||||||
|
|
||||||
|
## State Lock (Optional)
|
||||||
|
|
||||||
|
For multi-person teams, enable state locking via DynamoDB (not yet configured).
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
- ✓ Never commit `*.tfstate` or `*.tfstate.*` to git
|
||||||
|
- ✓ Back up state before major `terraform apply` operations
|
||||||
|
- ✓ Always run `terraform plan` before `terraform apply`
|
||||||
|
- ✓ Review diff carefully for destructive changes
|
||||||
|
- ✓ Keep state backend secure (MinIO has authentication)
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
Check S3 backend status:
|
||||||
|
```bash
|
||||||
|
kubectl get pods -n storage -l app=minio
|
||||||
|
# Or
|
||||||
|
scripts/terraform-state-backup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Related Files
|
||||||
|
|
||||||
|
- `terraform/state.tf` — Backend configuration
|
||||||
|
- `scripts/terraform-state-backup.sh` — Automated backup script
|
||||||
|
- `.gitignore` — Excludes local state files from git
|
||||||
Executable
+56
@@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Terraform state backup script
|
||||||
|
# Backs up Terraform state to local directory and verifies S3 backend accessibility
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BACKUP_DIR="$HOME/.terraform-backups/homelab"
|
||||||
|
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
||||||
|
STATE_BACKUP="$BACKUP_DIR/$TIMESTAMP-terraform.tfstate"
|
||||||
|
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
|
||||||
|
echo "=== Terraform State Backup ==="
|
||||||
|
echo "Backup directory: $BACKUP_DIR"
|
||||||
|
|
||||||
|
# Navigate to terraform directory
|
||||||
|
cd "$(dirname "${BASH_SOURCE[0]}")/../terraform" || exit 1
|
||||||
|
|
||||||
|
# Pull state from remote backend
|
||||||
|
echo "Pulling Terraform state from S3..."
|
||||||
|
terraform state pull > "$STATE_BACKUP" && \
|
||||||
|
echo "✓ State backed up to $STATE_BACKUP" || \
|
||||||
|
echo "⚠️ Failed to pull state (S3 backend may not be initialized)"
|
||||||
|
|
||||||
|
# Verify S3 bucket
|
||||||
|
echo ""
|
||||||
|
echo "Verifying S3 backend accessibility..."
|
||||||
|
if [ -z "$KUBECONFIG" ]; then
|
||||||
|
echo "⚠️ KUBECONFIG not set. Run: core auth login"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if kubectl get pods -n storage -l app=minio &>/dev/null; then
|
||||||
|
MINIO_POD=$(kubectl get pods -n storage -l app=minio -o jsonpath='{.items[0].metadata.name}')
|
||||||
|
echo "MinIO pod: $MINIO_POD"
|
||||||
|
|
||||||
|
# Check bucket
|
||||||
|
if kubectl exec -n storage "$MINIO_POD" -- mc ls minio/terraform-state &>/dev/null; then
|
||||||
|
echo "✓ S3 bucket 'terraform-state' accessible"
|
||||||
|
else
|
||||||
|
echo "⚠️ S3 bucket 'terraform-state' not found or inaccessible"
|
||||||
|
echo " To create: kubectl exec -n storage $MINIO_POD -- mc mb minio/terraform-state"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "⚠️ MinIO not running in storage namespace"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Keep only last 30 backups
|
||||||
|
echo ""
|
||||||
|
echo "Cleaning up old backups (keeping last 30)..."
|
||||||
|
ls -t "$BACKUP_DIR"/*.tfstate 2>/dev/null | tail -n +31 | xargs -r rm && \
|
||||||
|
echo "✓ Cleanup complete" || \
|
||||||
|
echo "ℹ️ No old backups to remove"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Backup complete. Location: $STATE_BACKUP"
|
||||||
Reference in New Issue
Block a user