Terraform Destroy Workflow #25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Terraform Destroy Workflow | |
| on: | |
| workflow_dispatch: | |
| permissions: | |
| id-token: write | |
| contents: read | |
| actions: read | |
| jobs: | |
| terraform-destroy: | |
| name: Terraform Destroy | |
| runs-on: ubuntu-latest | |
| environment: production | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v5 | |
| - name: Verify Variables Available | |
| run: | | |
| echo "CLUSTER_NAME: ${{ vars.CLUSTER_NAME }}" | |
| echo "NAMESPACE: ${{ vars.APP_NAMESPACE }}" | |
| echo "MONITORING_NAMESPACE: ${{ vars.MONITORING_NAMESPACE }}" | |
| echo "ARGOCD_NAMESPACE: ${{ vars.ARGOCD_NAMESPACE }}" | |
| echo "APP_NAME: ${{ vars.APP_NAME }}" | |
| echo "KARPENTER_NODEPOOL_NAME: ${{ vars.KARPENTER_NODEPOOL_NAME }}" | |
| echo "KARPENTER_NODECLASS_NAME: ${{ vars.KARPENTER_NODECLASS_NAME }}" | |
| echo "KARPENTER_NODE_ROLE: ${{ vars.KARPENTER_NODE_ROLE }}" | |
| echo "KARPENTER_INSTANCE_PROFILE: ${{ vars.KARPENTER_INSTANCE_PROFILE }}" | |
| echo "KARPENTER_NAMESPACE: ${{ vars.KARPENTER_NAMESPACE }}" | |
| if [[ -z "${{ vars.KARPENTER_NODEPOOL_NAME }}" ]]; then | |
| echo "WARNING: KARPENTER_NODEPOOL_NAME variable not found. Karpenter resources may not be deployed." | |
| fi | |
| if [[ -z "${{ vars.KARPENTER_NODE_ROLE }}" ]]; then | |
| echo "WARNING: KARPENTER_NODE_ROLE variable not found. Karpenter resources may not be deployed." | |
| fi | |
| if [[ -z "${{ vars.KARPENTER_INSTANCE_PROFILE }}" ]]; then | |
| echo "WARNING: KARPENTER_INSTANCE_PROFILE variable not found. Karpenter resources may not be deployed." | |
| fi | |
| if [[ -z "${{ vars.KARPENTER_NAMESPACE }}" ]]; then | |
| echo "WARNING: KARPENTER_NAMESPACE variable not found. Karpenter resources may not be deployed." | |
| fi | |
| if [[ -z "${{ vars.CLUSTER_NAME }}" ]]; then | |
| echo "ERROR: CLUSTER_NAME variable not found. Infrastructure may not be deployed." | |
| exit 1 | |
| fi | |
| if [[ -z "${{ vars.APP_NAMESPACE }}" ]]; then | |
| echo "ERROR: APP_NAMESPACE variable not found. Infrastructure may not be deployed." | |
| exit 1 | |
| fi | |
| - name: Configure AWS credentials via OIDC | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/GitHubActionsInfraRole | |
| aws-region: us-east-1 | |
| - name: Setup Terraform | |
| uses: hashicorp/[email protected] | |
| with: | |
| terraform_version: 1.5.7 | |
| - name: Update kubeconfig | |
| run: aws eks update-kubeconfig --name ${{ vars.CLUSTER_NAME }} --region us-east-1 | |
| continue-on-error: true | |
| - name: Install Helm | |
| uses: azure/[email protected] | |
| with: | |
| version: v3.14.0 | |
| continue-on-error: true | |
| # --------------------------- | |
| # Delete ArgoCD Applications | |
| # --------------------------- | |
| - name: Delete ArgoCD Applications | |
| run: | | |
| kubectl delete application ${{ vars.APP_NAME }} -n ${{ vars.ARGOCD_NAMESPACE }} --ignore-not-found | |
| kubectl delete application kube-prometheus-stack -n ${{ vars.ARGOCD_NAMESPACE }} --ignore-not-found | |
| continue-on-error: true | |
| # --------------------------- | |
| # Delete Karpenter Resources (Updated) | |
| # --------------------------- | |
| - name: Scale down to release nodes first | |
| run: | | |
| kubectl scale deployment --all --replicas=0 --all-namespaces || true | |
| sleep 30 # Let Karpenter scale down naturally | |
| continue-on-error: true | |
| - name: Delete Karpenter Provisioners and AWSNodeTemplates | |
| run: | | |
| echo "Deleting Karpenter Provisioners..." | |
| kubectl delete provisioner ${{ vars.KARPENTER_NODEPOOL_NAME }} --ignore-not-found -n ${{ vars.KARPENTER_NAMESPACE }} || true | |
| kubectl delete provisioner --all -n ${{ vars.KARPENTER_NAMESPACE }} --ignore-not-found || true | |
| echo "Deleting Karpenter AWSNodeTemplates..." | |
| kubectl delete awsnodetemplate ${{ vars.KARPENTER_NODECLASS_NAME }} --ignore-not-found -n ${{ vars.KARPENTER_NAMESPACE }} || true | |
| kubectl delete awsnodetemplate --all -n ${{ vars.KARPENTER_NAMESPACE }} --ignore-not-found || true | |
| echo "Waiting for resources to be cleaned up..." | |
| sleep 10 | |
| continue-on-error: true | |
| - name: Clean up Karpenter CRDs and Webhooks | |
| run: | | |
| echo "Deleting Karpenter CRDs..." | |
| kubectl delete crd provisioners.karpenter.sh --ignore-not-found || true | |
| kubectl delete crd awsnodetemplates.karpenter.k8s.aws --ignore-not-found || true | |
| echo "Deleting Karpenter webhooks..." | |
| kubectl delete validatingwebhookconfiguration defaulting.webhook.karpenter.sh --ignore-not-found || true | |
| kubectl delete validatingwebhookconfiguration validation.webhook.karpenter.sh --ignore-not-found || true | |
| kubectl delete mutatingwebhookconfiguration defaulting.webhook.karpenter.sh --ignore-not-found || true | |
| echo "Deleting Karpenter finalizers if stuck..." | |
| kubectl patch crd provisioners.karpenter.sh -p '{"metadata":{"finalizers":[]}}' --type=merge || true | |
| kubectl patch crd awsnodetemplates.karpenter.k8s.aws -p '{"metadata":{"finalizers":[]}}' --type=merge || true | |
| continue-on-error: true | |
| - name: Uninstall Karpenter Helm Release | |
| run: | | |
| echo "Uninstalling Karpenter Helm release..." | |
| helm uninstall karpenter -n ${{ vars.KARPENTER_NAMESPACE }} || true | |
| echo "Waiting for pods to terminate..." | |
| kubectl wait --for=delete pod -l app.kubernetes.io/name=karpenter -n ${{ vars.KARPENTER_NAMESPACE }} --timeout=120s || true | |
| echo "Force deleting any remaining pods..." | |
| kubectl delete pods --all -n ${{ vars.KARPENTER_NAMESPACE }} --force --grace-period=0 || true | |
| continue-on-error: true | |
| - name: Clean up Karpenter CRDs and Webhooks | |
| run: | | |
| echo "Deleting Karpenter CRDs..." | |
| kubectl delete crd nodepools.karpenter.sh --ignore-not-found || true | |
| kubectl delete crd provisioners.karpenter.sh --ignore-not-found || true | |
| kubectl delete crd awsnodetemplates.karpenter.k8s.aws --ignore-not-found || true | |
| kubectl delete crd ec2nodeclasses.karpenter.k8s.aws --ignore-not-found || true | |
| echo "Deleting Karpenter webhooks..." | |
| kubectl delete validatingwebhookconfiguration defaulting.webhook.karpenter.sh --ignore-not-found || true | |
| kubectl delete validatingwebhookconfiguration validation.webhook.karpenter.sh --ignore-not-found || true | |
| kubectl delete mutatingwebhookconfiguration defaulting.webhook.karpenter.sh --ignore-not-found || true | |
| echo "Deleting Karpenter finalizers if stuck..." | |
| kubectl patch crd nodepools.karpenter.sh -p '{"metadata":{"finalizers":[]}}' --type=merge || true | |
| kubectl patch crd ec2nodeclasses.karpenter.k8s.aws -p '{"metadata":{"finalizers":[]}}' --type=merge || true | |
| continue-on-error: true | |
| # --------------------------- | |
| # Uninstall Other Helm Releases | |
| # --------------------------- | |
| - name: Uninstall Helm Releases | |
| run: | | |
| helm uninstall ${{ vars.APP_NAME }} -n ${{ vars.APP_NAMESPACE }} || true | |
| helm uninstall kube-prometheus-stack -n ${{ vars.MONITORING_NAMESPACE }} || true | |
| helm uninstall ingress-nginx -n ingress-nginx || true | |
| helm uninstall argocd -n ${{ vars.ARGOCD_NAMESPACE }} || true | |
| continue-on-error: true | |
| # --------------------------- | |
| # Delete Namespaces | |
| # --------------------------- | |
| - name: Delete Namespaces | |
| run: | | |
| kubectl delete namespace ${{ vars.APP_NAMESPACE }} --ignore-not-found | |
| kubectl delete namespace ${{ vars.MONITORING_NAMESPACE }} --ignore-not-found | |
| kubectl delete namespace ${{ vars.ARGOCD_NAMESPACE }} --ignore-not-found | |
| kubectl delete namespace ingress-nginx --ignore-not-found | |
| # Delete Karpenter namespace last and force if needed | |
| kubectl delete namespace ${{ vars.KARPENTER_NAMESPACE }} --ignore-not-found --timeout=60s || true | |
| kubectl delete namespace ${{ vars.KARPENTER_NAMESPACE }} --force --grace-period=0 --ignore-not-found || true | |
| continue-on-error: true | |
| # --------------------------- | |
| # Delete CRDs (Prometheus & Grafana) | |
| # --------------------------- | |
| - name: Delete Monitoring CRDs | |
| run: | | |
| kubectl get crd -o name | grep -E 'prometheus|grafana|alertmanager|servicemonitor|prometheusrule' | xargs -r kubectl delete || true | |
| continue-on-error: true | |
| # --------------------------- | |
| # Cleanup PVCs & PVs | |
| # --------------------------- | |
| - name: Cleanup Persistent Storage | |
| run: | | |
| kubectl delete pvc --all -A || true | |
| kubectl delete pv --all || true | |
| continue-on-error: true | |
| # --------------------------- | |
| # Final cleanup verification | |
| # --------------------------- | |
| - name: Verify Karpenter cleanup | |
| run: | | |
| echo "Verifying Karpenter cleanup..." | |
| kubectl get pods -n ${{ vars.KARPENTER_NAMESPACE }} || echo "Karpenter namespace not found (expected)" | |
| kubectl get crd | grep karpenter || echo "No Karpenter CRDs found (expected)" | |
| kubectl get validatingwebhookconfiguration | grep karpenter || echo "No Karpenter webhooks found (expected)" | |
| kubectl get mutatingwebhookconfiguration | grep karpenter || echo "No Karpenter webhooks found (expected)" | |
| helm list -n ${{ vars.KARPENTER_NAMESPACE }} || echo "No Helm releases in karpenter namespace (expected)" | |
| continue-on-error: true | |
| # --------------------------- | |
| # Wait for cleanup to complete | |
| # --------------------------- | |
| - name: Wait for cleanup | |
| run: sleep 30 | |
| # --------------------------- | |
| # Terraform Destroy | |
| # --------------------------- | |
| - name: Terraform Init | |
| run: terraform init | |
| working-directory: ./Terraform | |
| - name: Terraform Destroy Plan | |
| run: terraform plan -destroy | |
| working-directory: ./Terraform | |
| - name: Terraform Destroy | |
| run: terraform destroy -auto-approve | |
| working-directory: ./Terraform | |
| # --------------------------- | |
| # Clean up GitHub Variables | |
| # --------------------------- | |
| - name: Remove GitHub repository variables | |
| run: | | |
| gh variable delete CLUSTER_NAME --repo $GITHUB_REPOSITORY || true | |
| gh variable delete APP_NAMESPACE --repo $GITHUB_REPOSITORY || true | |
| gh variable delete MONITORING_NAMESPACE --repo $GITHUB_REPOSITORY || true | |
| gh variable delete ARGOCD_NAMESPACE --repo $GITHUB_REPOSITORY || true | |
| gh variable delete APP_NAME --repo $GITHUB_REPOSITORY || true | |
| gh variable delete KARPENTER_NODEPOOL_NAME --repo $GITHUB_REPOSITORY || true | |
| gh variable delete KARPENTER_NODECLASS_NAME --repo $GITHUB_REPOSITORY || true | |
| gh variable delete KARPENTER_NODE_ROLE --repo $GITHUB_REPOSITORY || true | |
| gh variable delete KARPENTER_INSTANCE_PROFILE --repo $GITHUB_REPOSITORY || true | |
| gh variable delete KARPENTER_NAMESPACE --repo $GITHUB_REPOSITORY || true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.PAT_GITHUB }} | |
| continue-on-error: true |