feat: add Azure AKS deployment infrastructure with Terraform
Build and Deploy to Synology NAS / test (push) Failing after 15m0s
Build and Deploy to Synology NAS / build (push) Has been cancelled
Build and Deploy to Synology NAS / deploy (push) Has been cancelled
Build and Deploy to Synology NAS / notify (push) Has been cancelled
Build and Deploy to Synology NAS / test (push) Failing after 15m0s
Build and Deploy to Synology NAS / build (push) Has been cancelled
Build and Deploy to Synology NAS / deploy (push) Has been cancelled
Build and Deploy to Synology NAS / notify (push) Has been cancelled
- Add Terraform configuration for AKS cluster deployment - Add Kubernetes manifests for Laravel app (deployment, services, secrets) - Add PostgreSQL on Kubernetes with multi-schema support - Add Nginx Ingress Controller configuration - Add GitHub Actions workflow for Azure deployment - Add HTTP Basic Authentication for production - Add database restore functionality via Kubernetes jobs - Update Dockerfile and nginx config for production - Update database.php for multi-schema connections - Add deployment documentation and quickstart guides Deployed version: 1.0.7 at http://72.144.113.194/ Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Executable
+178
@@ -0,0 +1,178 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TERRAFORM_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
PROJECT_ROOT="$(dirname "$TERRAFORM_DIR")"
|
||||
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN}Laravel Application Deployment Script${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo ""
|
||||
|
||||
# Check prerequisites
|
||||
echo -e "${YELLOW}Checking prerequisites...${NC}"
|
||||
|
||||
if ! command -v terraform &> /dev/null; then
|
||||
echo -e "${RED}Error: Terraform is not installed${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v az &> /dev/null; then
|
||||
echo -e "${RED}Error: Azure CLI is not installed${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v kubectl &> /dev/null; then
|
||||
echo -e "${RED}Error: kubectl is not installed${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo -e "${RED}Error: Docker is not installed${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓ All prerequisites are installed${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if logged into Azure
|
||||
echo -e "${YELLOW}Checking Azure login status...${NC}"
|
||||
if ! az account show &> /dev/null; then
|
||||
echo -e "${RED}Error: Not logged into Azure. Please run 'az login'${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CURRENT_SUBSCRIPTION=$(az account show --query name -o tsv)
|
||||
echo -e "${GREEN}✓ Logged into Azure (Subscription: $CURRENT_SUBSCRIPTION)${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if terraform.tfvars exists
|
||||
if [ ! -f "$TERRAFORM_DIR/terraform.tfvars" ]; then
|
||||
echo -e "${RED}Error: terraform.tfvars not found${NC}"
|
||||
echo -e "${YELLOW}Please create terraform.tfvars from terraform.tfvars.example${NC}"
|
||||
echo -e "${YELLOW}cp $TERRAFORM_DIR/terraform.tfvars.example $TERRAFORM_DIR/terraform.tfvars${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if Docker image is specified
|
||||
DOCKER_IMAGE=$(grep 'docker_image' "$TERRAFORM_DIR/terraform.tfvars" | cut -d'"' -f2)
|
||||
if [ -z "$DOCKER_IMAGE" ] || [ "$DOCKER_IMAGE" == "myregistry.azurecr.io/laravel-app:latest" ]; then
|
||||
echo -e "${YELLOW}Warning: Docker image not configured in terraform.tfvars${NC}"
|
||||
echo -e "${YELLOW}Please update the docker_image variable before deploying${NC}"
|
||||
read -p "Do you want to build and push the Docker image now? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo -e "${YELLOW}Please provide the following information:${NC}"
|
||||
read -p "Azure Container Registry name (e.g., myregistry): " ACR_NAME
|
||||
read -p "Image name (e.g., laravel-app): " IMAGE_NAME
|
||||
read -p "Image tag (default: latest): " IMAGE_TAG
|
||||
IMAGE_TAG=${IMAGE_TAG:-latest}
|
||||
|
||||
DOCKER_IMAGE="$ACR_NAME.azurecr.io/$IMAGE_NAME:$IMAGE_TAG"
|
||||
|
||||
echo -e "${YELLOW}Building Docker image...${NC}"
|
||||
cd "$PROJECT_ROOT"
|
||||
docker build -t "$DOCKER_IMAGE" .
|
||||
|
||||
echo -e "${YELLOW}Logging into Azure Container Registry...${NC}"
|
||||
az acr login --name "$ACR_NAME"
|
||||
|
||||
echo -e "${YELLOW}Pushing Docker image...${NC}"
|
||||
docker push "$DOCKER_IMAGE"
|
||||
|
||||
echo -e "${GREEN}✓ Docker image pushed successfully${NC}"
|
||||
|
||||
# Update terraform.tfvars
|
||||
sed -i.bak "s|docker_image = \".*\"|docker_image = \"$DOCKER_IMAGE\"|" "$TERRAFORM_DIR/terraform.tfvars"
|
||||
echo -e "${GREEN}✓ Updated terraform.tfvars with new Docker image${NC}"
|
||||
echo ""
|
||||
else
|
||||
echo -e "${RED}Deployment cancelled. Please configure docker_image in terraform.tfvars${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Generate Laravel APP_KEY if needed
|
||||
APP_KEY=$(grep 'app_key' "$TERRAFORM_DIR/terraform.tfvars" | cut -d'"' -f2)
|
||||
if [ -z "$APP_KEY" ] || [ "$APP_KEY" == "base64:YOUR_APP_KEY_HERE" ]; then
|
||||
echo -e "${YELLOW}Generating Laravel APP_KEY...${NC}"
|
||||
cd "$PROJECT_ROOT"
|
||||
NEW_APP_KEY=$(php artisan key:generate --show)
|
||||
sed -i.bak "s|app_key = \".*\"|app_key = \"$NEW_APP_KEY\"|" "$TERRAFORM_DIR/terraform.tfvars"
|
||||
echo -e "${GREEN}✓ Generated and saved APP_KEY${NC}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Change to Terraform directory
|
||||
cd "$TERRAFORM_DIR"
|
||||
|
||||
# Initialize Terraform
|
||||
echo -e "${YELLOW}Initializing Terraform...${NC}"
|
||||
terraform init
|
||||
|
||||
# Validate Terraform configuration
|
||||
echo -e "${YELLOW}Validating Terraform configuration...${NC}"
|
||||
terraform validate
|
||||
|
||||
# Plan deployment
|
||||
echo -e "${YELLOW}Planning deployment...${NC}"
|
||||
terraform plan -out=tfplan
|
||||
|
||||
# Confirm deployment
|
||||
echo ""
|
||||
echo -e "${YELLOW}========================================${NC}"
|
||||
echo -e "${YELLOW}Ready to deploy!${NC}"
|
||||
echo -e "${YELLOW}========================================${NC}"
|
||||
read -p "Do you want to proceed with the deployment? (yes/no) " -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
|
||||
echo -e "${RED}Deployment cancelled${NC}"
|
||||
rm -f tfplan
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Apply Terraform
|
||||
echo -e "${YELLOW}Applying Terraform configuration...${NC}"
|
||||
terraform apply tfplan
|
||||
|
||||
# Clean up plan file
|
||||
rm -f tfplan
|
||||
|
||||
# Get outputs
|
||||
echo ""
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN}Deployment completed successfully!${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo ""
|
||||
|
||||
terraform output deployment_instructions
|
||||
|
||||
# Configure kubectl
|
||||
echo ""
|
||||
echo -e "${YELLOW}Configuring kubectl...${NC}"
|
||||
RESOURCE_GROUP=$(terraform output -raw resource_group_name)
|
||||
AKS_CLUSTER=$(terraform output -raw aks_cluster_name)
|
||||
az aks get-credentials --resource-group "$RESOURCE_GROUP" --name "$AKS_CLUSTER" --overwrite-existing
|
||||
echo -e "${GREEN}✓ kubectl configured${NC}"
|
||||
|
||||
# Wait for pods to be ready
|
||||
echo ""
|
||||
echo -e "${YELLOW}Waiting for application pods to be ready...${NC}"
|
||||
APP_NAMESPACE=$(terraform output -raw app_namespace)
|
||||
kubectl wait --for=condition=ready pod -l app=$(terraform output -raw app_service_name | sed 's/-service//') -n "$APP_NAMESPACE" --timeout=300s || true
|
||||
|
||||
# Show pod status
|
||||
echo ""
|
||||
echo -e "${YELLOW}Application pod status:${NC}"
|
||||
kubectl get pods -n "$APP_NAMESPACE"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Deployment script completed!${NC}"
|
||||
Executable
+224
@@ -0,0 +1,224 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TERRAFORM_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
PROJECT_ROOT="$(dirname "$TERRAFORM_DIR")"
|
||||
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN}Database Restore Script${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo ""
|
||||
|
||||
# Check prerequisites
|
||||
echo -e "${YELLOW}Checking prerequisites...${NC}"
|
||||
|
||||
if ! command -v kubectl &> /dev/null; then
|
||||
echo -e "${RED}Error: kubectl is not installed${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v az &> /dev/null; then
|
||||
echo -e "${RED}Error: Azure CLI is not installed${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓ All prerequisites are installed${NC}"
|
||||
echo ""
|
||||
|
||||
# Change to Terraform directory
|
||||
cd "$TERRAFORM_DIR"
|
||||
|
||||
# Check if Terraform is initialized
|
||||
if [ ! -d ".terraform" ]; then
|
||||
echo -e "${RED}Error: Terraform not initialized. Please run terraform init first.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get Terraform outputs
|
||||
echo -e "${YELLOW}Getting Terraform outputs...${NC}"
|
||||
APP_NAMESPACE=$(terraform output -raw app_namespace 2>/dev/null)
|
||||
RESOURCE_GROUP=$(terraform output -raw resource_group_name 2>/dev/null)
|
||||
AKS_CLUSTER=$(terraform output -raw aks_cluster_name 2>/dev/null)
|
||||
|
||||
if [ -z "$APP_NAMESPACE" ] || [ -z "$RESOURCE_GROUP" ] || [ -z "$AKS_CLUSTER" ]; then
|
||||
echo -e "${RED}Error: Could not get Terraform outputs. Please run terraform apply first.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Configure kubectl
|
||||
echo -e "${YELLOW}Configuring kubectl...${NC}"
|
||||
az aks get-credentials --resource-group "$RESOURCE_GROUP" --name "$AKS_CLUSTER" --overwrite-existing
|
||||
echo -e "${GREEN}✓ kubectl configured${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if backup file exists
|
||||
BACKUP_DIR="$PROJECT_ROOT/backups"
|
||||
if [ ! -d "$BACKUP_DIR" ]; then
|
||||
echo -e "${RED}Error: Backup directory not found: $BACKUP_DIR${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# List available backups
|
||||
echo -e "${YELLOW}Available backup files:${NC}"
|
||||
ls -lh "$BACKUP_DIR"/*.dump 2>/dev/null || {
|
||||
echo -e "${RED}No backup files found in $BACKUP_DIR${NC}"
|
||||
exit 1
|
||||
}
|
||||
echo ""
|
||||
|
||||
# Select backup file
|
||||
read -p "Enter the backup file name (or full path): " BACKUP_FILE
|
||||
|
||||
if [ ! -f "$BACKUP_FILE" ]; then
|
||||
# Try in backup directory
|
||||
BACKUP_FILE="$BACKUP_DIR/$BACKUP_FILE"
|
||||
if [ ! -f "$BACKUP_FILE" ]; then
|
||||
echo -e "${RED}Error: Backup file not found: $BACKUP_FILE${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓ Found backup file: $BACKUP_FILE${NC}"
|
||||
echo ""
|
||||
|
||||
# Confirm restore
|
||||
echo -e "${RED}========================================${NC}"
|
||||
echo -e "${RED}WARNING: This will restore the database!${NC}"
|
||||
echo -e "${RED}All existing data will be replaced!${NC}"
|
||||
echo -e "${RED}========================================${NC}"
|
||||
read -p "Are you sure you want to continue? (yes/no) " -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
|
||||
echo -e "${YELLOW}Database restore cancelled${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Create ConfigMap with backup file
|
||||
echo -e "${YELLOW}Creating ConfigMap with backup file...${NC}"
|
||||
kubectl create configmap db-restore-backup \
|
||||
--from-file=backup.dump="$BACKUP_FILE" \
|
||||
-n "$APP_NAMESPACE" \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
echo -e "${GREEN}✓ ConfigMap created${NC}"
|
||||
echo ""
|
||||
|
||||
# Create restore job
|
||||
echo -e "${YELLOW}Creating database restore job...${NC}"
|
||||
JOB_NAME="db-restore-manual-$(date +%Y%m%d%H%M%S)"
|
||||
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: $JOB_NAME
|
||||
namespace: $APP_NAMESPACE
|
||||
labels:
|
||||
app: laravel-app
|
||||
job-type: database-restore
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: laravel-app
|
||||
job-type: database-restore
|
||||
spec:
|
||||
containers:
|
||||
- name: db-restore
|
||||
image: postgres:16-alpine
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
echo "Waiting for PostgreSQL to be ready..."
|
||||
until pg_isready -h \$DB_HOST -p \$DB_PORT -U \$DB_USERNAME; do
|
||||
echo "Waiting for database..."
|
||||
sleep 5
|
||||
done
|
||||
echo "PostgreSQL is ready!"
|
||||
|
||||
echo "Restoring database backup..."
|
||||
export PGPASSWORD="\$DB_PASSWORD"
|
||||
|
||||
# Create database if not exists
|
||||
psql -h \$DB_HOST -p \$DB_PORT -U \$DB_USERNAME -d postgres -c "CREATE DATABASE \$DB_DATABASE;" || echo "Database already exists"
|
||||
|
||||
# Restore from backup
|
||||
pg_restore -h \$DB_HOST -p \$DB_PORT -U \$DB_USERNAME -d \$DB_DATABASE --verbose --clean --if-exists --no-owner --no-privileges /backup/backup.dump || echo "Restore completed with warnings (this is normal)"
|
||||
|
||||
echo "Database restore completed successfully!"
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: laravel-app-db-credentials
|
||||
volumeMounts:
|
||||
- name: backup-volume
|
||||
mountPath: /backup
|
||||
readOnly: true
|
||||
resources:
|
||||
requests:
|
||||
cpu: "100m"
|
||||
memory: "256Mi"
|
||||
limits:
|
||||
cpu: "500m"
|
||||
memory: "512Mi"
|
||||
volumes:
|
||||
- name: backup-volume
|
||||
configMap:
|
||||
name: db-restore-backup
|
||||
restartPolicy: OnFailure
|
||||
backoffLimit: 3
|
||||
ttlSecondsAfterFinished: 86400
|
||||
EOF
|
||||
|
||||
echo -e "${GREEN}✓ Restore job created: $JOB_NAME${NC}"
|
||||
echo ""
|
||||
|
||||
# Monitor job progress
|
||||
echo -e "${YELLOW}Monitoring restore job progress...${NC}"
|
||||
echo -e "${YELLOW}Press Ctrl+C to stop monitoring (job will continue in background)${NC}"
|
||||
echo ""
|
||||
|
||||
# Wait for pod to be created
|
||||
sleep 5
|
||||
|
||||
# Get pod name
|
||||
POD_NAME=$(kubectl get pods -n "$APP_NAMESPACE" -l job-name="$JOB_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
||||
|
||||
if [ -n "$POD_NAME" ]; then
|
||||
echo -e "${YELLOW}Following logs from pod: $POD_NAME${NC}"
|
||||
kubectl logs -n "$APP_NAMESPACE" -f "$POD_NAME" || true
|
||||
else
|
||||
echo -e "${YELLOW}Waiting for pod to be created...${NC}"
|
||||
kubectl wait --for=condition=ready pod -l job-name="$JOB_NAME" -n "$APP_NAMESPACE" --timeout=60s || true
|
||||
POD_NAME=$(kubectl get pods -n "$APP_NAMESPACE" -l job-name="$JOB_NAME" -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)
|
||||
if [ -n "$POD_NAME" ]; then
|
||||
kubectl logs -n "$APP_NAMESPACE" -f "$POD_NAME" || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check job status
|
||||
echo ""
|
||||
echo -e "${YELLOW}Checking job status...${NC}"
|
||||
JOB_STATUS=$(kubectl get job "$JOB_NAME" -n "$APP_NAMESPACE" -o jsonpath='{.status.conditions[?(@.type=="Complete")].status}' 2>/dev/null)
|
||||
|
||||
if [ "$JOB_STATUS" == "True" ]; then
|
||||
echo -e "${GREEN}✓ Database restore completed successfully!${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}Job status:${NC}"
|
||||
kubectl get job "$JOB_NAME" -n "$APP_NAMESPACE"
|
||||
echo ""
|
||||
echo -e "${YELLOW}To check logs again, run:${NC}"
|
||||
echo -e "${YELLOW}kubectl logs -n $APP_NAMESPACE -l job-name=$JOB_NAME${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Database restore script completed!${NC}"
|
||||
Reference in New Issue
Block a user