{"id":48540116,"url":"https://github.com/localstack-samples/k8s-lifecycle-demo","last_synced_at":"2026-04-08T04:01:41.794Z","repository":{"id":346489358,"uuid":"1190214271","full_name":"localstack-samples/k8s-lifecycle-demo","owner":"localstack-samples","description":"Sample app for k8s lifecycle talk","archived":false,"fork":false,"pushed_at":"2026-03-24T04:21:14.000Z","size":15,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-03-25T05:25:12.122Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/localstack-samples.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-24T04:19:43.000Z","updated_at":"2026-03-24T04:21:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/localstack-samples/k8s-lifecycle-demo","commit_stats":null,"previous_names":["localstack-samples/k8s-lifecycle-demo"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/localstack-samples/k8s-lifecycle-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localstack-samples%2Fk8s-lifecycle-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localstack-samples%2Fk8s-lifecycle-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localstack-samples%2Fk8s-lifecycle-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localstack-samples%2Fk8s-lifecycle-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/localstack-samples","download_url":"https://codeload.github.com/localstack-samples/k8s-lifecycle-demo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localstack-samples%2Fk8s-lifecycle-demo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31539229,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"online","status_checked_at":"2026-04-08T02:00:06.127Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-08T04:01:41.072Z","updated_at":"2026-04-08T04:01:41.788Z","avatar_url":"https://github.com/localstack-samples.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kubernetes Deployment Lifecycle — EKS on LocalStack\n\nA self-contained demo that makes all **7 steps** of the Kubernetes Deployment Lifecycle **visible in real time**, using a locally emulated EKS cluster powered by [LocalStack](https://localstack.cloud).\n\n```\nkubectl apply\n     │\n     ▼\n┌─────────────┐   ┌──────────────────┐   ┌───────────┐   ┌─────────┐\n│  API Server │──▶│ Controller Mgr   │──▶│ Scheduler │──▶│ Kubelet │\n│  (etcd)     │   │ Deployment+RS    │   │ Node pick │   │ + CRI   │\n└─────────────┘   └──────────────────┘   └───────────┘   └─────────┘\n                                                               │\n                                                               ▼\n                                                    ┌──────────────────┐\n                                                    │ Pending→Running  │\n                                                    │ Readiness probe  │\n                                                    │ → Ready+Endpoint │\n                                                    └──────────────────┘\n```\n\n---\n\n## What's in this repo\n\n```\nk8s-lifecycle-demo/\n├── app/\n│   ├── app.py            # Flask counter service (GET /, GET /health)\n│   ├── requirements.txt\n│   └── Dockerfile\n├── k8s/\n│   └── deployment.yaml   # Namespace + Deployment (2 replicas) + NodePort Service\n├── docker-compose.yml    # LocalStack Pro container\n├── setup.sh              # One-time cluster setup (run before the talk)\n├── demo.sh               # 7-step live demo script\n└── README.md\n```\n\n---\n\n## Prerequisites\n\n| Tool | Version | Install |\n|------|---------|---------|\n| Docker Desktop | ≥ 4.x | https://docs.docker.com/get-docker/ |\n| kubectl | ≥ 1.28 | https://kubernetes.io/docs/tasks/tools/ |\n| AWS CLI v2 | ≥ 2.x | https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html |\n| awslocal | latest | `pip install awscli-local` |\n| LocalStack CLI | latest | `pip install localstack` |\n| k3d | ≥ 5.x | https://k3d.io/#installation |\n| Python 3.11+ | (for the app build) | https://python.org |\n\n\u003e **LocalStack Pro is required** for EKS emulation.\n\u003e Get a free trial auth token at https://localstack.cloud.\n\n---\n\n## Quick start\n\n### 1. Set your LocalStack auth token\n\n```bash\nexport LOCALSTACK_AUTH_TOKEN=\u003cyour-token\u003e\n```\n\nAdd it to your shell profile so it persists across sessions.\n\n### 2. Run setup \n\n```bash\nchmod +x setup.sh demo.sh\n./setup.sh\n```\n\n`setup.sh` will:\n1. Start LocalStack via Docker Compose\n2. Create an EKS cluster called `lifecycle-demo`\n3. Configure `kubectl` to point at it\n4. Build the `counter-app:latest` Docker image\n5. Load the image into the cluster nodes (via k3d)\n\n### 3. Run the demo\n\n```bash\n./demo.sh\n```\n\nPress **ENTER** to advance between each step.\n\nFor a fully-automatic run (e.g. recording):\n\n```bash\nAUTO=1 STEP_DELAY=6 ./demo.sh\n```\n\n---\n\n## The 7 steps\n\n| # | Component | What you'll see |\n|---|-----------|-----------------|\n| 1 | **API Server** | `kubectl apply` → HTTP 201, object stored in etcd |\n| 2 | **Controller Manager** | Deployment + ReplicaSet reconciliation, Pod objects appear |\n| 3 | **Scheduler** | Pods assigned to nodes; `kubectl describe pod | grep Node:` |\n| 4 | **Kubelet** | Image pull events, container start events |\n| 5 | **Pod phase** | `kubectl get pods -w` → `Pending → Running` |\n| 6 | **Readiness probe** | `Running → Ready`; Service Endpoints populated |\n| 7 | **Self-healing** | Pod deleted → replacement races through lifecycle again |\n\n---\n\n## The app\n\nThe counter service exposes two endpoints:\n\n```\nGET /       → {\"hits\": 42, \"pod\": \"counter-app-xxx\", \"node\": \"k3d-...\"}\nGET /health → {\"status\": \"ok\", \"pod\": \"counter-app-xxx\"}\n```\n\nBecause each replica keeps its own in-memory counter, repeated `curl` calls to the\nNodePort will hit different pods — making **pod identity** and **load balancing**\nvisible to the audience.\n\n```bash\n# NodePort is 30080 on each node\nNODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type==\"InternalIP\")].address}')\ncurl http://${NODE_IP}:30080/\n```\n\n---\n\n## Customisation\n\n| Variable | Default | Purpose |\n|----------|---------|---------|\n| `CLUSTER_NAME` | `lifecycle-demo` | EKS / k3d cluster name |\n| `AWS_DEFAULT_REGION` | `us-east-1` | LocalStack region |\n| `AUTO` | `0` | `1` = skip ENTER prompts |\n| `STEP_DELAY` | `4` | Seconds to pause in AUTO mode |\n\nPass them as environment variables:\n\n```bash\nCLUSTER_NAME=my-cluster AUTO=1 ./demo.sh\n```\n\n---\n\n## Cleanup\n\n```bash\n# Remove demo namespace\nkubectl delete namespace demo\n\n# Tear down the whole cluster\nawslocal eks delete-cluster --name lifecycle-demo\n\n# Stop LocalStack\ndocker compose down -v\n```\n\n---\n\n## Troubleshooting\n\n**Pods stay in `Pending`**\nThe image wasn't loaded into the cluster nodes. Re-run `./setup.sh` or manually:\n```bash\nk3d image import counter-app:latest --cluster lifecycle-demo\n```\n\n**`imagePullBackOff`**\nSame cause. The manifest uses `imagePullPolicy: Never` — the image must be\npre-loaded; it will never be pulled from a registry.\n\n**`kubectl` shows the wrong cluster**\n```bash\nkubectl config use-context lifecycle-demo\n```\n\n**LocalStack EKS not available**\nEKS is a Pro feature. Confirm your `LOCALSTACK_AUTH_TOKEN` is set and that the\ncontainer started cleanly:\n```bash\ndocker logs localstack | grep -i eks\n```\n\n**k3d not found**\n`setup.sh` falls back to `docker exec + ctr images import`. Install k3d for a\nsmoother experience: https://k3d.io/#installation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocalstack-samples%2Fk8s-lifecycle-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flocalstack-samples%2Fk8s-lifecycle-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocalstack-samples%2Fk8s-lifecycle-demo/lists"}