This runbook takes the repo from empty AWS account context to validated nginx on a two-node kubeadm cluster, then destroys the stack.
terraform version
ansible --version
aws --version
kubectl version --client=trueThe expected AWS profile name is lift-shift.
aws configure list --profile lift-shiftIf credentials are missing, configure them through your preferred flow:
aws configure --profile lift-shift
# or
aws configure sso --profile lift-shiftcd aws
cp terraform.tfvars.example terraform.tfvarsReplace allowed_admin_cidr with your current public IP:
../scripts/get-admin-cidr.shKeep it as a /32 unless you intentionally need a wider source range.
terraform init
terraform fmt -check -recursive
terraform validate
terraform plan
terraform applyTerraform writes ansible/inventory.ini and ansible/group_vars/aws.yml after apply. Those files are generated runtime files and are not committed.
cd ..
./scripts/run-ansible.shThe playbook installs containerd, kubelet, kubeadm, kubectl, and cri-tools on both nodes; initializes the control plane on the private EC2 IP; applies Calico VXLAN; joins the worker; then waits for both nodes and CoreDNS to become healthy.
./scripts/validate.shThe validation script applies workloads/nginx-nodeport.yaml, waits for rollout, curls the worker NodePort, and writes proof under proof/.
Useful manual checks:
terraform -chdir=aws output
ssh -i ~/.ssh/id_ed25519 ubuntu@$(terraform -chdir=aws output -raw control_public_ip)
kubectl get nodes -o wide
kubectl get pods -A -o wide./scripts/collect-debug.shThe debug bundle captures Terraform outputs, node status, kube-system pods, Calico daemonset details, crictl ps -a, and kubelet journals.
./scripts/destroy.shCleanup is complete when Terraform reports destroy success and no Project=lift-shift-k8s EC2 instances, EBS volumes, or security groups remain.