chown: changing ownership of '/data/db': Operation not permitted - kubernetes

Can we use nfs volume plugin to maintain the High Availability and Disaster Recovery among the kubernetes cluster?
I am running the pod with MongoDB. Getting the error
chown: changing ownership of '/data/db': Operation not permitted .
Cloud any body, Please suggest me how to resolve the error? (or)
Is any alternative volume plugin is suggestible to achieve HA- DR in kubernetes cluster?

chown: changing ownership of '/data/db': Operation not permitted .
You'll want to either launch the mongo container as root, so that you can chown the directory, or if the image prohibits it (as some images already have a USER mongo clause that prohibits the container from escalating privileges back up to root), then one of two things: supersede the user with a securityContext stanza in containers: or use an initContainer: to preemptively change the target folder to be the mongo UID:
Approach #1:
containers:
- name: mongo
image: mongo:something
securityContext:
runAsUser: 0
(which may require altering your cluster's config to permit such a thing to appear in a PodSpec)
Approach #2 (which is the one I use with Elasticsearch images):
initContainers:
- name: chmod-er
image: busybox:latest
command:
- /bin/chown
- -R
- "1000" # or whatever the mongo UID is, use string "1000" not 1000 due to yaml
- /data/db
volumeMounts:
- name: mongo-data # or whatever
mountPath: /data/db
containers:
- name: mongo # then run your container as before

/data/db is a mountpoint, even if you don't explicitly mount a volume there. The data is persisted to an overlay specific to the pod.
Kubernetes mounts all volumes as 0755 root.root, regardless of what the permissions for the directory were intially.
Of course mongo cannot chown that.
If you mount the volume somewhere below /data/db, you will get the same error.
And if you mount the volume above at /data, the data will not be stored on the NFS because the mountpoint at /data/db will write to the overlay instead. But you won't get that error anymore.

By adding command:["mongod"] in your Deployment Manifest, it will override the default entrypoint script and will prevent executing the chown.
...
spec:
containers:
- name: mongodb
image: mongo:4.4.0-bionic
command: ["mongod"]
...

Instead of mounting /data/db, we could mount /data. Internally mongo will create /data/db. During entrypoint, mongo tries to chown this directory but if we mount a volume directory to this mount point, as a mongo container user - it will not be able to chown. That's the cause of the issue
Here is a sample of working mongo deployment yaml
...
spec:
containers:
- name: mongo
image: mongo:latest
volumeMounts:
- mountPath: /data
name: mongo-db-volume
volumes:
- hostPath:
path: /Users/name/mongo-data
type: Directory
name: mongo-db-volume
...

Related

Unable to access volume content using initContainers

I have a simple image (mdw:1.0.0) with some content in it:
FROM alpine:3.9
COPY /role /mdw
WORKDIR /mdw
I was expecting that my container 'nginx' would see the content of /mdw folder, but there is no file.
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
initContainers:
- name: install
image: mdw:1.0.0
imagePullPolicy: Never
volumeMounts:
- name: workdir
mountPath: "/mdw"
containers:
- name: nginx
image: nginx
volumeMounts:
- name: workdir
mountPath: /mdw
command: ["ls", "-l", "/mdw"]
volumes:
- name: workdir
emptyDir: {}
Do you know what is the reason and how to fix it ?
Thank you very much
When mounting volume if directory already exists will get wiped. It's intentional and no fix really.
Only way would be to populate the directory after mounting is done.
Your init container doesn't do anything: the Dockerfile doesn't have a CMD and the Kubernetes deployment spec doesn't set a command: either. It starts and immediately exits. (The base Linux distribution images generally have a default command to launch an interactive shell, but absent a tty this will also immediately exit.)
Meanwhile, your Kubernetes setup is also mounting an empty directory over the only content you've put into the image, which prevents the init container from having an effect.
You can build a custom nginx image that directly copies the content in:
FROM nginx
COPY /role /usr/share/nginx/html
Don't use initContainers:, and use that image as the main containers: image.
There is a Docker-specific feature, using Docker named volumes, that can populate a named volume on first use, and you're probably thinking of this feature. This comes with a couple of important caveats (it only takes effect the very first time you run a container, and ignores updates to the image; it doesn't work with bind mounts). This is a plain-Docker-specific feature: Kubernetes will never auto-populate a volume for you.

Kubernetes init-container file permission mismatch

I have an init container that copies files onto the volume.
I have implemented a security policy, that the user-id is not relevant, and all rights to files are set by group (0) - basically the same that is the default in OpenShift.
After creating the test instance with emptyDir instead of pvcs the container has crashed. After inspecting the image I've found out that the file permissons are broken: only the owner can write.
I've double-checked the init container. The files there have write permission for owner and other. I copy them with cp. But the final pod sees this files as writable only by owner.
To make things worse, the owner has been changed to root, although initially it was another user.
Is this a bug or a feature of emptyDir? Or I'm using them in a wrong way?
This is how I declare the volume:
containers:
- name: container
volumeMounts:
- name: storage
mountPath: /var/storage
initContainers:
- name: container-init
volumeMounts:
- name: storage
mountPath: /storage-mount
volumes:
- name: storage
emptyDir: {}

Kubernetes (in Docker for Windows) Volume Configuration for Postgres

I have a tomcat + postgres application that I test with docker-compose. I am trying to package the application in a kubernetes config file.
For now, I am running kubernetes (and kubectl) using my Docker Desktop for Windows installation. Eventually, I want to deploy to other environments.
I am currently trying to replicate some of the volume functionality in docker-compose within the following config file.
apiVersion: v1
kind: Pod
metadata:
name: pg-pod
spec:
volumes:
- name: "pgdata-vol"
#emptyDir: {}
hostPath:
path: /c/temp/vols/pgdata
containers:
- image: postgres
name: db
ports:
- containerPort: 5432
name: http
protocol: TCP
volumeMounts:
- mountPath: "/pgdata"
name: "pgdata-vol"
env:
- name: PGDATA
value: /pgdata
When postgres launches, I get see the following error.
fixing permissions on existing directory /pgdata ... ok
creating subdirectories ... ok
selecting default max_connections ... 20
selecting default shared_buffers ... 400kB
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok
2019-07-26 20:43:41.844 UTC [78] FATAL: data directory "/pgdata" has wrong ownership
2019-07-26 20:43:41.844 UTC [78] HINT: The server must be started by the user that owns the data directory.
child process exited with exit code 1
initdb: removing contents of data directory "/pgdata"
running bootstrap script ...
I presume that I either need to provide some additional parameters to my volume definition or I need to try a different type of volume config (local vs hostPath).
I found a partial solution to this issue.
Interestingly, if I assign a linux-style path as my host-path (on Windows), then my pgdata-vol persists until Docker Desktop is restarted.
Instead of mounting to a real windows location
volumes:
- name: "pgdata-vol"
hostPath:
path: /c/temp/vols/pgdata
I use a "linux" location as my Windows hostPath
volumes:
- name: "pgdata-vol"
hostPath:
path: /tmp/vols/pgdata
Curiously, I cannot actually find this path from Windows. I presume this /tmp is local to my Docker Desktop instance.
This solution does not offer true persistence, but it has helped me to work around a roadblock that was impacting testing.
This is a known issue with Docker image on Windows. Right now it is not possible to correctly mount Windows directories as volumes. You may however try to workaround it by using a persistent Docker volume. For example:
db:
image: postgres
environment:
- POSTGRES_USER=<user>
- POSTGRES_PASSWORD=<pass>
- POSTGRES_DB=<db_name>
ports:
- <ports>
volumes:
- pgdata:<path>
networks:
- <network>
volumes:
pgdata:
More Information:
data directory "/var/lib/postgresql/data" has wrong ownership
postgresql-data-pgdata-has-wrong-ownership
postgres-to-work-on-persistent-windows-mount
Please let me know if that helped.
Have you tried using WSL? My setup for windows is WSL + Ubuntu + Docker for windows and I can mount volumes normally.
I've followed that tutorial to configure all my environment:
https://nickjanetakis.com/blog/setting-up-docker-for-windows-and-wsl-to-work-flawlessly

OpenShift's YAML execution precedence regarding volume mounting and commands

As a beginner in container administration, I can't find a clear description of OpenShift's deployment stages and related YAML statements, specifically when persistent volume mounting and shell commands execution are involved. For example, in the RedHat documentation there is a lot of examples. A simple one is 16.4. Pod Object Definition:
apiVersion: v1
kind: Pod
metadata:
name: busybox-nfs-pod
labels:
name: busybox-nfs-pod
spec:
containers:
- name: busybox-nfs-pod
image: busybox
command: ["sleep", "60000"]
volumeMounts:
- name: nfsvol-2
mountPath: /usr/share/busybox
readOnly: false
securityContext:
supplementalGroups: [100003]
privileged: false
volumes:
- name: nfsvol-2
persistentVolumeClaim:
claimName: nfs-pvc
Now the question is: does the command sleep (or any other) execute before or after the mount of nfsvol-2 is finished? In other words, is it possible to use the volume's resources in such commands? And if it's not possible in this config, then which event handlers to use instead? I don't see any mention about an event like volume mounted.
does the command sleep (or any other) execute before or after the
mount of nfsvol-2 is finished?
To understand this, lets dig into the underlying concepts for Openshift.
OpenShift is a container application platform that brings docker and Kubernetes to the enterprise. So Openshift is nothing but an abstraction layer on top of docker and kubernetes along with additional features.
Regarding the volumes and commands lets consider the following example:
Let's run the docker container by mounting a volume, which is the home directory of host machine to the root path of the container(-v is option to attach volume).
$ docker run -it -v /home:/root ubuntu /bin/bash
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
50aff78429b1: Pull complete
f6d82e297bce: Pull complete
275abb2c8a6f: Pull complete
9f15a39356d6: Pull complete
fc0342a94c89: Pull complete
Digest: sha256:f871d0805ee3ce1c52b0608108dbdf1b447a34d22d5c7278a3a9dd78fc12c663
Status: Downloaded newer image for ubuntu:latest
root#1f07f083ba79:/# cd /root/
root#1f07f083ba79:~# ls
lost+found raghavendralokineni raghu user1
root#1f07f083ba79:~/raghavendralokineni# pwd
/root/raghavendralokineni
Now execute the sleep command in the container and exit.
root#1f07f083ba79:~/raghavendralokineni# sleep 10
root#1f07f083ba79:~/raghavendralokineni#
root#1f07f083ba79:~/raghavendralokineni# exit
Check the files available in the /home path which we have mounted to the container. This content is same as that of /root path in the container.
raghavendralokineni#iconic-glider-186709:/home$ ls
lost+found raghavendralokineni raghu user1
So when a volume is mounted to the container, any changes in the volume will be effected in the host machine as well.
Hence the volume will be mounted along with the container and commands will be executed after container is started.
Coming back to the your YAML file,
volumeMounts:
- name: nfsvol-2
mountPath: /usr/share/busybox
It says ,mount the volume nfsvol-2 to the container and the information regarding the volume is mentioned in volumes:
volumes:
- name: nfsvol-2
persistentVolumeClaim:
claimName: nfs-pvc
So mount the volume to the container and execute the command which is specifed:
containers:
- name: busybox-nfs-pod
image: busybox
command: ["sleep", "60000"]
Hope this helps.

emptyDir in minikube

Very simple question, where is the emptyDir located in my minikube VM? Since the emptyDir volume is pod dependent, it should exist on the VM otherwise it will die with a container exiting. When I do minikube ssh I cannot locate the volume. I need to inspect it and see if my containers are behaving how I want them to, copying some files to the volume mounted on them. Trying find / -type d -name cached results in many permission denieds and the volume is not in the rest of the dirs. My YAML has the following part:
...
volumes:
- name: cached
emptyDir: {}
and also commands in a container where the container copies some files to the volume:
containers:
- name: plum
image: plumsempy/plum
command: ["/bin/sh", "-c"]
args: ["mkdir /plum/cached"]
volumeMounts:
- mountPath: /plum/cached
name: cahced
command: ["bin/sh/", "-c"]
args: ["cp /plum/prune/cert.crt /plume/cached/"]
The container naturally exists after doing its job.
A better way to see if your containers are behaving is by logging in into the container using the kubectl command.
That said: The location should of emptyDir should be in /var/lib/kubelet/pods/{podid}/volumes/kubernetes.io~empty-dir/ on the given node where your pod is running.