I’ve always hated adding persistence in k8s workloads.
There are valid reasons to avoid it, right?
Adding a PV means people can store stuff there that they expect to find, regardless of where the app is deployed/redeployed (which could be in another region/zone/cluster/node etc where the original pv is not present)
Thus adding another step in the deployment process that comes usually as an afterthought and may be easily overlooked and poorly documented.
But still, every once in a while you have to do it.
One way I’ve found that is somewhat acceptable to the above intricacies uses S3.
AWS recently announced S3 mountpoint.
You can use it to easily mount an S3 bucket to a directory in your system or container.
But to add this to a docker image you’d need to install the binary, set it up etc.
Which means editing the dockerfile and the init script.
If it’s your app and you’re fine with that, go right ahead.
If not though, you might like to use a sidecar.
The sidecar would have
- a docker image with
mount-s3installed and proper permissions to access the S3 bucket you want to use (using IRSA with the serviceAccount of the deployment probably) - a volume of type
emptyDirmounted at some directory in the container with a mountPropagation of Bidirectional - an init script to mount the S3 bucket to the directory of the
emptyDirvolume
And the main container would
- mount the same volume with a
mountPropagationofHostToContainer. - be able to store files in that directory and have everything there written to the S3 bucket, without the main container ever being altered.
Enough talk, show me the code
#dockerfile
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y wget
RUN wget https://s3.amazonaws.com/mountpoint-s3-release/latest/x86_64/mount-s3.deb
&& apt install -y ./mount-s3.deb
&& rm mount-s3.deb
WORKDIR /app
COPY mount.sh .
ENTRYPOINT [“bash”,”-c”,”/app/mount.sh”]
#mount.sh
mkdir -p "/${BUCKET_TO_MOUNT}"
mount-s3 "${BUCKET_TO_MOUNT}" "/${BUCKET_TO_MOUNT}"
sleep infinity
# snippet from deployment
spec:
serviceAccountName: sa-that-has-access-to-your-bucket
containers:
- name: s3mounter
securityContext:
privileged: true
capabilities:
add:
- SYS_ADMIN
env:
- name: BUCKET_TO_MOUNT
value: your-bucket-name
volumeMounts:
- name: s3bucket
mountPath: /mnt/buckets
mountPropagation: Bidirectional
- name: s3user
image: ubuntu
command:
- "/usr/bin/sleep"
- "infinity"
volumeMounts:
- name: s3bucket
mountPath: /mnt/buckets
mountPropagation: HostToContainer
volumes:
- name: s3bucket
emptyDir: {}
- Is this fit for every purpose? Likely not.
- Is it safe? Well, any privileged container is inherently not safe. Read the warning in the MountPropagation article above.
- Are there better ways? Of course. There are actually even better ways to do what I described above. See here.
But this approach too has its merits and seemed worthy of being documented.