Draft: not yet reviewed by a clinician
Use this page to prepare questions for your care team. It does not replace their advice. Your own targets and doses come from your nephrologist, diabetes team and renal dietitian.
Kubernetes¶
The Kustomize base in deploy/k8s/ runs one pod with one SQLite volume, under the Pod Security
restricted profile, with a default-deny NetworkPolicy. It was written for Talos Linux and works on
other clusters (design note 01; deployment guide). The base is cluster-neutral:
you never edit it. Everything that depends on your cluster (host name, Gateway, network ranges, storage
class, image pin) goes in an overlay, a small folder of patches you copy from
deploy/k8s-overlays/example/.
What is in deploy/k8s/ and the example overlay¶
| File | Purpose | Edit? |
|---|---|---|
deploy/k8s/kustomization.yaml |
resources and the image (minor-release tag) | no |
deploy/k8s/namespace.yaml |
namespace with Pod Security restricted (enforce, audit, warn) |
no |
deploy/k8s/pvc.yaml |
1 Gi ReadWriteOnce volume, the cluster's default storage class |
no |
deploy/k8s/deployment.yaml |
UID 10001, read-only root, /tmp emptyDir, secret files, probes, Recreate |
no |
deploy/k8s/service.yaml |
ClusterIP port 80 to 8000 | no |
deploy/k8s/networkpolicy.yaml |
default deny; DNS; public HTTPS out; nothing in until the overlay | no |
overlay kustomization.yaml |
the base, the route, the patches; image pin (tag and digest); storage class | pin the digest |
overlay httproute.yaml |
Gateway API route | parentRefs, hostname |
overlay deployment-env.yaml |
PUBLIC_URL, TRUSTED_PROXIES |
both |
overlay networkpolicy-ingress.yaml |
lets the Gateway's namespace in on port 8000 | that namespace |
ingress.example.yaml, cilium-networkpolicy.example.yaml, secret.example.yaml |
examples, not applied |
One pod per database: one replica, ReadWriteOnce, Recreate rollouts. There is deliberately no
PodDisruptionBudget, because with one replica it would block node drains.
Steps¶
The commands for each step are in the deployment guide's Kubernetes section.
- Storage. Leave the cluster's default storage class, or uncomment the storage-class patch in your overlay. Avoid NFS: SQLite needs file locking that NFS handles poorly.
- Secret. Create it with two keys,
secret_key(a long random value) andusda_api_key(empty means "off"). Keep a copy ofsecret_keyin your password manager (Backups). - Copy the example overlay and edit it:
httproute.yaml(hostname, Gateway),networkpolicy-ingress.yaml(Gateway namespace) anddeployment-env.yaml:PUBLIC_URL=https://plus the route's hostname;TRUSTED_PROXIESas narrow as your Gateway's pods allow. Keeping your overlay in a separate GitOps repository, with the base as a remote resource pinned to a release, works too. - Apply your overlay, wait for the rollout, and read the one-time setup code from the log.
- Pin the image in your overlay by tag and digest; each release's notes carry the digest (Security).
Pod Security restricted¶
The namespace enforces the restricted profile: non-root, no privilege escalation, all capabilities
dropped, seccomp RuntimeDefault, and only safe volume types (Kubernetes: Pod Security
Standards). Any extra container you add (debug, init, restore) must meet the same rules. A
server-side dry run of the namespace label reports any pod that would not pass; the command is in the
guide's Pod Security step.
Make NetworkPolicy real¶
A NetworkPolicy does nothing unless the network plugin enforces it (Kubernetes: Network
Policies). On Talos, the default Flannel accepts but ignores policies unless
kubeNetworkPoliciesEnabled: true is set (Talos 1.13 and later) (Talos: Flannel).
Test it: the guide's NetworkPolicy step has a one-line test
pod that tries to reach the app. It must fail. If it prints {"status":"ok",...}, policies are not
enforced.
The shipped policy lets the pod reach DNS and public addresses on port 443 only (private, CGNAT,
link-local and loopback ranges excluded, so cloud metadata and the API server are unreachable). With
Cilium, cilium-networkpolicy.example.yaml narrows that to exact host names. A LAN Ollama needs its own
rule and an AI_PRIVATE_HOSTS entry (Network allowlist).
TRUSTED_PROXIES on a cluster¶
The base trusts only loopback, which is safe but ignores your Gateway's forwarded headers, so set
TRUSTED_PROXIES in your overlay. The example's 10.244.0.0/16 (the Talos and Flannel default pod
range; yours may differ) trusts every pod. That is acceptable only while the NetworkPolicy is
enforced, or with TRUSTED_PROXY_SECRET_FILE set. Narrow it to your Gateway's pods where you can
(operator security guide).
Optional: a user namespace for the pod¶
hostUsers: false runs the pod in its own user namespace, so even root inside it is unprivileged on the
node. It is stable since Kubernetes 1.36 and needs Linux 6.3 or later, containerd 2.0 or later, and
idmap-capable volumes such as ext4, xfs, btrfs or tmpfs, not NFS (Kubernetes: user
namespaces). On Talos, also raise user.max_user_namespaces with a machine config patch
(deployment guide).
Debugging without a shell¶
The image has no shell. Use the admin CLI (python -m app.admin check through kubectl exec), or an
ephemeral debug container with the restricted profile (deployment guide).
If something goes wrong¶
- Pod
Pending: describe the volume claimkidney-health-data. Usually a mistyped storage class or no default class. - Pod rejected by Pod Security: an added container is missing one of the restricted settings.
400 Unknown host:PUBLIC_URLdoes not match the route's hostname.database is locked: two pods share the volume; keep one replica andRecreate.- More: Troubleshooting.
Related pages¶
- HTTPS for phones (cert-manager) · Security · Backups · Upgrades
Sources¶
- Design note 01, sections 3.5 and 5.3; deployment guide; operator security guide.
- Kubernetes: Pod Security Standards; Network Policies; user namespaces.
- Talos: Flannel and NetworkPolicy.
Not yet reviewed by a clinician. Facts and sources last checked 2026-10-06.