diff --git a/magic-containers/persistent-volumes.mdx b/magic-containers/persistent-volumes.mdx index 64166d6..e68caf5 100644 --- a/magic-containers/persistent-volumes.mdx +++ b/magic-containers/persistent-volumes.mdx @@ -91,6 +91,80 @@ Your application now has scalable persistent volumes attached to each container. Throughput limits are defined in the pod cgroup and apply to each volume individually. If a pod has two volumes attached, each volume receives its own 10 MB/s read and 10 MB/s write limits. +## File permissions + +When multiple containers in a pod share a volume, their ability to read, modify, or delete each other's files depends on which user each container runs as. + +**Which user does a container run as?** By default, if no `USER` instruction is present in your Dockerfile, the container runs as root (`uid=0`). If a `USER` instruction is specified, the container runs as that user. + +```dockerfile +# Runs as root (no USER specified) +FROM ubuntu:22.04 +CMD ["myapp"] + +# Runs as a non-root user +FROM ubuntu:22.04 +USER 1000 +CMD ["myapp"] +``` + + + Volumes are only shared between containers within the same pod. Containers from different pods cannot access each other's volumes. + + +### Root creates files, non-root accesses them + +| Operation | Result | +|-----------|--------| +| Read | ✅ | +| Modify | ❌ | +| Delete | ❌ | + +Files created by a root process can be read but not modified or deleted by non-root containers. + +### Non-root creates files, root accesses them + +| Operation | Result | +|-----------|--------| +| Read | ✅ | +| Modify | ✅ | +| Delete | ✅ | + +Root always has full access regardless of file permissions. + +### Both containers run as the same non-root user + +| Operation | Result | +|-----------|--------| +| Read | ✅ | +| Modify | ✅ | +| Delete | ✅ | + +Full access as both containers are the file owner. + +### Each container runs as a different non-root user + +| Operation | Result | +|-----------|--------| +| Read | ✅ | +| Modify | ❌ | +| Delete | ❌ | + +The accessing container is not the file owner. It can read files but cannot modify or delete them. + +### Summary + +| Scenario | Read | Modify | Delete | +|----------------------------------------|------|--------|--------| +| Root creates, non-root accesses | ✅ | ❌ | ❌ | +| Non-root creates, root accesses | ✅ | ✅ | ✅ | +| Same non-root user | ✅ | ✅ | ✅ | +| Different non-root users | ✅ | ❌ | ❌ | + +### A note on deletion + +On Linux, whether a process can delete a file is determined by write permission on the **directory** containing the file, not by the file's own permissions. Because all pod containers share write access to the volume directory, a non-root container would ordinarily be able to delete any file inside it regardless of who created it. To prevent this, the volume directory is configured with the **sticky bit** — the same mechanism used by shared system directories such as `/tmp`. With the sticky bit set, only the file's owner or root can delete or rename a file, even with directory write access. The `Delete ❌` entries in the tables above rely on this. + ## FAQ diff --git a/magic-containers/rolling-updates.mdx b/magic-containers/rolling-updates.mdx index d92f5a1..3f87e29 100644 --- a/magic-containers/rolling-updates.mdx +++ b/magic-containers/rolling-updates.mdx @@ -32,6 +32,27 @@ Imagine you have an application deployed in 3 regions, each with 10 pods. If you **Total Iterations** - 5 iterations to update all pods in each region. +# Applications with persistent volumes + +When your application uses [persistent volumes](/magic-containers/persistent-volumes), the rolling update process is adjusted to prevent data corruption. Rather than starting new pods before removing old ones, existing pods are shut down first to fully unmount their volumes before new pods are started. + + + Applications with persistent volumes may experience a short period of downtime during a rolling update if the number of pods is less than 2, as the old pod must release the volume before the new pod can attach it. + + +## Practical example + +Imagine you have an application deployed in 3 regions, each with 10 pods, and each pod has a persistent volume attached. If you update the container image: + +1. Iteration 1: + - Remove 2 old pods (20% of 10) in each region and wait for their volumes to fully unmount. + - Start 2 new pods in each region and wait until they are running and healthy. + +2. Iterations 2–5: + - Repeat the above steps until all pods are updated. + +**Total Iterations** - 5 iterations to update all pods in each region. + # Handling issues during a rolling update If the Rolling Update encounters problems, such as deploying a broken image, it handles the situation by detecting any new pod that fails to reach a running state within ten minutes and considering it unhealthy. In such cases, the Rolling Update is terminated. All new pods with the faulty configuration are deleted, and old pods are restored to maintain application stability. The Rolling Update then restarts automatically, using the latest configuration. If the issue is fixed, such as by providing a healthy image, the update will proceed successfully.