#!/bin/bash # Continuous Deployment Script for Kubernetes # This script deploys your application to a Kubernetes cluster # ============================================================================= # Environment Variables (with default values) # ============================================================================= # Kubernetes Configuration KUBECONFIG_DATA="${KUBECONFIG_DATA:-}" KUBERNETES_URL="${KUBERNETES_URL:-https://kubernetes.default.svc}" KUBERNETES_NAMESPACE="${KUBERNETES_NAMESPACE:-default}" KUBERNETES_INGRESS_HOST="${KUBERNETES_INGRESS_HOST:-blog-api.example.com}" KUBERNETES_DEPLOYMENT_REPLICAS="${KUBERNETES_DEPLOYMENT_REPLICAS:-2}" # Container Registry CONTAINER_REGISTRY_URL="${CONTAINER_REGISTRY_URL:-127.0.0.1}" CONTAINER_REGISTRY_USERNAME="${CONTAINER_REGISTRY_USERNAME:-username}" CONTAINER_REGISTRY_NAMESPACE="${CONTAINER_REGISTRY_NAMESPACE:-username}" CONTAINER_REGISTRY_PASSWORD="${CONTAINER_REGISTRY_PASSWORD:-password}" CONTAINER_IMAGE_NAME="${CONTAINER_IMAGE_NAME:-blog}" CONTAINER_IMAGE_TAG="${CONTAINER_IMAGE_TAG:-latest}" # Application Configuration DATABASE_DSN="${DATABASE_DSN:-postgres://postgres:password@localhost:5432/steam_union?sslmode=disable}" JWT_SECRET="${JWT_SECRET:-your-secret-key-change-in-production}" JWT_ISSUER="${JWT_ISSUER:-cialloo-authenticator}" JWT_EXPIRES_IN="${JWT_EXPIRES_IN:-604800}" S3_REGION="${S3_REGION:-us-east-1}" S3_BUCKET="${S3_BUCKET:-your-bucket-name}" S3_ACCESS_KEY_ID="${S3_ACCESS_KEY_ID:-your-access-key-id}" S3_SECRET_ACCESS_KEY="${S3_SECRET_ACCESS_KEY:-your-secret-access-key}" S3_ENDPOINT="${S3_ENDPOINT:-}" S3_PRESIGNED_URL_EXPIRATION="${S3_PRESIGNED_URL_EXPIRATION:-3600}" FORCE_RESTART="${FORCE_RESTART:-true}" # ============================================================================= # Functions # ============================================================================= # Print help message print_help() { echo "Usage: $0 [OPTIONS]" echo "" echo "Environment Variables:" echo " KUBECONFIG_DATA Kubernetes config data (base64 encoded)" echo " KUBERNETES_URL Kubernetes API URL (default: https://kubernetes.default.svc)" echo " KUBERNETES_NAMESPACE Kubernetes namespace (default: default)" echo " KUBERNETES_INGRESS_HOST Ingress host (default: blog-api.example.com)" echo " KUBERNETES_DEPLOYMENT_REPLICAS Number of pod replicas (default: 2)" echo " CONTAINER_REGISTRY_URL Container registry URL (default: 127.0.0.1)" echo " CONTAINER_REGISTRY_USERNAME Registry username" echo " CONTAINER_REGISTRY_PASSWORD Registry password" echo " CONTAINER_IMAGE_NAME Image name (default: blog)" echo " CONTAINER_IMAGE_TAG Image tag (default: latest)" echo " DATABASE_DSN Database connection string" echo " JWT_SECRET JWT secret key" echo " JWT_ISSUER JWT issuer" echo " JWT_EXPIRES_IN JWT expiration time in seconds" echo " S3_REGION S3 region" echo " S3_BUCKET S3 bucket name" echo " S3_ACCESS_KEY_ID S3 access key ID" echo " S3_SECRET_ACCESS_KEY S3 secret access key" echo " S3_ENDPOINT S3 endpoint (optional)" echo " S3_PRESIGNED_URL_EXPIRATION Presigned URL expiration in seconds" echo " FORCE_RESTART Force rollout restart (default: true)" echo "" echo "Commands:" echo " deploy Deploy application to Kubernetes" echo " help Show this help message (default)" } # Setup kubectl configuration setup_kubectl() { echo "Setting up kubectl configuration..." if [ -z "${KUBECONFIG_DATA}" ]; then echo "✗ KUBECONFIG_DATA is not set" return 1 fi mkdir -p ~/.kube echo "${KUBECONFIG_DATA}" | base64 -d > ~/.kube/config chmod 600 ~/.kube/config echo "✓ kubectl configured" return 0 } # Create namespace if it doesn't exist create_namespace() { echo "Checking namespace: ${KUBERNETES_NAMESPACE}" kubectl get namespace "${KUBERNETES_NAMESPACE}" &> /dev/null if [ $? -ne 0 ]; then echo "Creating namespace: ${KUBERNETES_NAMESPACE}" kubectl create namespace "${KUBERNETES_NAMESPACE}" else echo "✓ Namespace exists: ${KUBERNETES_NAMESPACE}" fi } # Create image pull secret create_image_pull_secret() { echo "Creating image pull secret..." kubectl create secret docker-registry regcred \ --docker-server="${CONTAINER_REGISTRY_URL}" \ --docker-username="${CONTAINER_REGISTRY_USERNAME}" \ --docker-password="${CONTAINER_REGISTRY_PASSWORD}" \ --namespace="${KUBERNETES_NAMESPACE}" \ --dry-run=client -o yaml | kubectl apply -f - echo "✓ Image pull secret created/updated" } # Create or update application secrets create_app_secrets() { echo "Creating application secrets..." kubectl create secret generic blog-secrets \ --from-literal=database-dsn="${DATABASE_DSN}" \ --from-literal=jwt-secret="${JWT_SECRET}" \ --from-literal=s3-access-key-id="${S3_ACCESS_KEY_ID}" \ --from-literal=s3-secret-access-key="${S3_SECRET_ACCESS_KEY}" \ --namespace="${KUBERNETES_NAMESPACE}" \ --dry-run=client -o yaml | kubectl apply -f - echo "✓ Application secrets created/updated" } # Apply Kubernetes manifests apply_manifests() { echo "Applying Kubernetes manifests..." # Substitute environment variables in manifests export KUBERNETES_NAMESPACE export KUBERNETES_INGRESS_HOST export KUBERNETES_DEPLOYMENT_REPLICAS export CONTAINER_REGISTRY_URL export CONTAINER_REGISTRY_NAMESPACE export CONTAINER_IMAGE_NAME export CONTAINER_IMAGE_TAG export JWT_ISSUER export JWT_EXPIRES_IN export S3_REGION export S3_BUCKET export S3_ENDPOINT export S3_PRESIGNED_URL_EXPIRATION # Apply namespace envsubst < script/k8s/namespace.yaml | kubectl apply -f - # Apply deployment envsubst < script/k8s/deployment.yaml | kubectl apply -f - # Apply service envsubst < script/k8s/service.yaml | kubectl apply -f - # Apply ingress envsubst < script/k8s/ingress.yaml | kubectl apply -f - echo "✓ Manifests applied" } # Wait for deployment to be ready wait_for_deployment() { echo "Waiting for deployment to be ready..." kubectl rollout status deployment/blog \ --namespace="${KUBERNETES_NAMESPACE}" \ --timeout=300s if [ $? -eq 0 ]; then echo "✓ Deployment ready" return 0 else echo "✗ Deployment failed" return 1 fi } # Force restart deployment force_restart_deployment() { if [ "${FORCE_RESTART}" = "true" ]; then echo "Forcing deployment restart..." kubectl rollout restart deployment/blog \ --namespace="${KUBERNETES_NAMESPACE}" echo "✓ Deployment restarted" fi } # Deploy application deploy() { echo "==========================================" echo "Deploying Blog Application" echo "==========================================" echo "Namespace: ${KUBERNETES_NAMESPACE}" echo "Image: ${CONTAINER_REGISTRY_URL}/${CONTAINER_REGISTRY_NAMESPACE}/${CONTAINER_IMAGE_NAME}:${CONTAINER_IMAGE_TAG}" echo "Host: ${KUBERNETES_INGRESS_HOST}" echo "" setup_kubectl || return 1 create_namespace || return 1 create_image_pull_secret || return 1 create_app_secrets || return 1 apply_manifests || return 1 force_restart_deployment wait_for_deployment || return 1 echo "" echo "==========================================" echo "✓ Deployment Successful" echo "==========================================" echo "Application URL: http://${KUBERNETES_INGRESS_HOST}" echo "" return 0 } # ============================================================================= # Main Script # ============================================================================= case "$1" in deploy) deploy exit $? ;; help|--help|-h|"") print_help exit 0 ;; *) echo "Unknown option: $1" echo "" print_help exit 1 ;; esac