================================== Deploying an update to myApp on k3s ================================== The loop to run every time you change your app. Five steps: **edit → build → push → deploy → verify.** Assumes the registry name ``pi5:5000`` and that you run all of this on the **pi5** (control plane), from inside ``~/myApp``. .. contents:: On this page :local: :depth: 1 1. Edit the code ================ Make your change in ``flask_app.py`` (or wherever). Nothing special here — just save the file. 2. Build a new image ==================== .. code-block:: bash docker build -t myapp . This reads your ``Dockerfile`` and packages the current code into a fresh image called ``myapp``. The running pods do **not** see source changes until you do this — a container is a frozen snapshot, so new code means a new image. 3. Tag and push to the registry ================================ Use a **new version number** each time (``v2``, ``v3``, …) rather than reusing ``latest``: .. code-block:: bash docker tag myapp pi5:5000/myapp:v2 docker push pi5:5000/myapp:v2 - **tag** gives the image the registry's address (``pi5:5000/...``) plus a version, so the cluster knows where to find it and which build it is. - **push** uploads it to the registry on the pi5, which is the one place all three nodes can pull from. A pod can land on any node, so the image has to live somewhere shared — that's what the registry is for. .. note:: **Why a new version each time?** Kubernetes caches images by tag. If you reuse ``:latest``, the cluster thinks "I already have latest" and won't pull your new build. A fresh tag (``:v2``) is unambiguously new, so it always pulls. It also gives you a clean rollback point. 4. Deploy the new version ========================= Point the deployment at the new tag: .. code-block:: bash kubectl set image deployment/myapp myapp=pi5:5000/myapp:v2 This triggers a **rolling update**: Kubernetes replaces the old pods with new ones a few at a time, keeping the app serving throughout. Old pods aren't killed until new ones are healthy (that's what your readiness probe on ``/health`` gates), so there's no downtime. Watch it happen: .. code-block:: bash kubectl rollout status deployment/myapp It prints progress and returns when the update is complete. 5. Verify ========= .. code-block:: bash kubectl get pods -o wide # all replicas Running, READY 1/1 curl http://:30080/health # should return {"status":"ok"} ``-o wide`` shows which node each pod is on. Hitting ``/health`` on any node's IP confirms the new version is actually serving (NodePort routes to a healthy pod wherever it lives). If something's wrong: roll back =============================== One command returns to the previous version instantly: .. code-block:: bash kubectl rollout undo deployment/myapp Kubernetes keeps the last-known-good spec, so this swaps the pods back to the prior image with the same no-downtime rolling process. This is the payoff of versioned tags — the old image is still in the registry, ready to go. Quick reference (the whole loop) ================================ .. code-block:: bash # 1. edit flask_app.py, then: docker build -t myapp . docker tag myapp pi5:5000/myapp:v2 docker push pi5:5000/myapp:v2 kubectl set image deployment/myapp myapp=pi5:5000/myapp:v2 kubectl rollout status deployment/myapp kubectl get pods -o wide Bump ``v2 → v3 → v4 …`` on each cycle. What each piece is doing (the mental model) =========================================== .. list-table:: :header-rows: 1 :widths: 25 75 * - Thing - Role * - **Dockerfile** - Recipe for building the image from your code * - **image** (``myapp``) - Frozen snapshot of code + dependencies * - **registry** (``pi5:5000``) - Shared store all nodes pull images from * - **Deployment** - Declares "I want N copies of this image running" and manages updates * - **Service** (NodePort) - Stable entry point; routes traffic to healthy pods on any node * - **readiness probe** (``/health``) - Gate that keeps traffic off a pod until it's actually ready * - **rolling update** - Swaps pods incrementally so the app never fully goes down * - **rollout undo** - One-step return to the previous version