Pre-Phase-1 platform work, approved and tested earlier but not yet committed: - Terminal banner: "RootNode Academy Lab — node: k8s-lab", upstream KubeKosh attribution left untouched in footer/README/LICENSE. - RootNode curriculum mode: scenarios/rootnode-path.json (Foundation -> Workloads -> Networking -> Configuration -> Troubleshooting -> Real Ops -> Capstone), built from existing scenario content grouped by category, no new scenarios invented. New GET /api/curriculum/path endpoint. - Student roster + per-student progress: instructor-roster, pick-your-name login (no password), students/environments-adjacent progress table migrated to a (student_id, scenario_id) composite key so practice progress and exam sessions are isolated per student instead of one global bucket. New /api/roster, /api/login endpoints. - scenarios/data/*.json: added isolation_type metadata (shared_namespace vs ephemeral_cluster) from an audit of which scenarios execute cluster-scoped or node-level commands. This was Tier-1-isolation groundwork that got superseded same-day by the full-ephemeral-per-student architecture (see docs/LAB_ARCHITECTURE.md) — the field is kept as descriptive metadata only, per the note now in scenarios/SCHEMA.md. Not wasted: it's an accurate audit of which scenarios touch cluster-scoped resources, useful independent of isolation model. - .gitignore added (node_modules/, frontend/dist/, *.db, /data/, .env) — none existed before; without it, npm installs during testing would have landed in a commit. Known limitation still open: no frontend UI for any of this yet (login screen, roster-add form, curriculum view) — API-only. No auth on the roster-add endpoint. Co-Authored-By: Claude Sonnet 5 <[email protected]>
47 lines
2.6 KiB
JSON
47 lines
2.6 KiB
JSON
{
|
|
"id": "init-container-task-basics",
|
|
"title": "Pod with Init Container",
|
|
"category": "Core Concepts",
|
|
"isolation_type": "shared_namespace",
|
|
"difficulty": "Medium",
|
|
"type": "task",
|
|
"weight": 5,
|
|
"description": "## Pod with Init Container\n\nInit containers run **before** the main application containers start. Each init container must complete successfully before the next one begins, and all must finish before the main containers are started. They are ideal for setup tasks like seeding config files or waiting for a dependency.\n\n**Your task:**\n\nCreate a Pod named `init-demo` with:\n- An **init container** named `setup` using `busybox:1.36` that writes `ready` into `/shared/status.txt`\n- A **main container** named `app` using `busybox:1.36` with command `sleep 3600`\n- Both containers mount an `emptyDir` volume at `/shared`\n\n```bash\n# Verify the init container wrote the file:\nkubectl exec init-demo -- cat /shared/status.txt\n```",
|
|
"hints": [
|
|
{
|
|
"title": "Pod manifest with initContainers",
|
|
"body": "Define `spec.initContainers[]` above `spec.containers[]`. Both containers share the emptyDir volume mounted at /shared.",
|
|
"command": "cat <<EOF | kubectl apply -f -\napiVersion: v1\nkind: Pod\nmetadata:\n name: init-demo\nspec:\n initContainers:\n - name: setup\n image: busybox:1.36\n command: [\"sh\", \"-c\", \"echo ready > /shared/status.txt\"]\n volumeMounts:\n - name: shared-vol\n mountPath: /shared\n containers:\n - name: app\n image: busybox:1.36\n command: [\"sleep\", \"3600\"]\n volumeMounts:\n - name: shared-vol\n mountPath: /shared\n volumes:\n - name: shared-vol\n emptyDir: {}\nEOF"
|
|
}
|
|
],
|
|
"setup_commands": [],
|
|
"validation": {
|
|
"commands": [
|
|
{
|
|
"description": "Pod 'init-demo' is Running",
|
|
"command": "kubectl get pod init-demo -o jsonpath='{.status.phase}'",
|
|
"expected_output": "Running",
|
|
"match": "exact"
|
|
},
|
|
{
|
|
"description": "Init container 'setup' completed with exit code 0",
|
|
"command": "kubectl get pod init-demo -o jsonpath='{.status.initContainerStatuses[0].state.terminated.exitCode}'",
|
|
"expected_output": "0",
|
|
"match": "exact"
|
|
},
|
|
{
|
|
"description": "File /shared/status.txt contains 'ready'",
|
|
"command": "kubectl exec init-demo -- cat /shared/status.txt 2>/dev/null",
|
|
"expected_output": "ready",
|
|
"match": "contains"
|
|
}
|
|
]
|
|
},
|
|
"default_namespace": "default",
|
|
"teardown_commands": [
|
|
{
|
|
"command": "kubectl delete pod init-demo --ignore-not-found --grace-period=0 --force"
|
|
}
|
|
]
|
|
}
|