RabbitMQ Cluster Kubernetes Operator on minikube - kubernetes

I'm trying to set up RabbitMQ on Minikube using the RabbitMQ Cluster Operator:
When I try to attach a persistent volume, I get the following error:
$ kubectl logs -f rabbitmq-rabbitmq-server-0
Configuring logger redirection
20:04:40.081 [warning] Failed to write PID file "/var/lib/rabbitmq/mnesia/rabbit#rabbitmq-rabbitmq-server-0.rabbitmq-rabbitmq-headless.default.pid": permission denied
20:04:40.264 [error] Failed to create Ra data directory at '/var/lib/rabbitmq/mnesia/rabbit#rabbitmq-rabbitmq-server-0.rabbitmq-rabbitmq-headless.default/quorum/rabbit#rabbitmq-rabbitmq-server-0.rabbitmq-rabbitmq-headless.default', file system operation error: enoent
20:04:40.265 [error] Supervisor ra_sup had child ra_system_sup started with ra_system_sup:start_link() at undefined exit with reason {error,"Ra could not create its data directory. See the log for details."} in context start_error
20:04:40.266 [error] CRASH REPORT Process <0.247.0> with 0 neighbours exited with reason: {error,"Ra could not create its data directory. See the log for details."} in ra_system_sup:init/1 line 43
20:04:40.267 [error] CRASH REPORT Process <0.241.0> with 0 neighbours exited with reason: {{shutdown,{failed_to_start_child,ra_system_sup,{error,"Ra could not create its data directory. See the log for details."}}},{ra_app,start,[normal,[]]}} in application_master:init/4 line 138
{"Kernel pid terminated",application_controller,"{application_start_failure,ra,{{shutdown,{failed_to_start_child,ra_system_sup,{error,\"Ra could not create its data directory. See the log for details.\"}}},{ra_app,start,[normal,[]]}}}"}
Kernel pid terminated (application_controller) ({application_start_failure,ra,{{shutdown,{failed_to_start_child,ra_system_sup,{error,"Ra could not create its data directory. See the log for details."}
Crash dump is being written to: erl_crash.dump...
The issue is that RabbitMQ is not able to set up its data files in the data directory /var/lib/rabbitmq/mnesia due to a lack of permission.
My initial guess was that I needed to specify the data directory as a volumeMount, but that doesn't seem to be configurable according to the documentation.
RabbitMQ's troubleshooting documentation on persistence results in a 404.
I tried to find other resources online with the same problem but none of them were using the RabbitMQ Cluster Operator. I plan on following that route if I'm not able to find a solution but I really would like to solve this issue somehow.
Does anyone have any ideas?
The setup that I have is as follows:
apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
name: rabbitmq
spec:
replicas: 1
service:
type: NodePort
persistence:
storageClassName: local-storage
storage: 20Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rabbitmq-pvc
spec:
storageClassName: local-storage
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: rabbitmq-pv
spec:
storageClassName: local-storage
accessModes:
- ReadWriteOnce
capacity:
storage: 20Gi
hostPath:
path: /mnt/app/rabbitmq
type: DirectoryOrCreate
To reproduce this issue on minikube:
Install the rabbitmq operator:
kubectl apply -f "https://github.com/rabbitmq/cluster-operator/releases/latest/download/cluster-operator.yml"
Apply the manifest file above
kubectl apply -f rabbitmq.yml
Running kubectl get po displays a pod named rabbitmq-rabbitmq-server-0.
Running kubectl logs -f rabbitmq-rabbitmq-server-0 to view the logs displays the above error.

As I alread suggested in comments, you can solve it running:
minikube ssh -- sudo chmod g+w /mnt/app/rabbitmq/
Answering to your question:
Is there a way I can add that to my manifest file rather than having to do it manually?
You can override the rabbitmq statefulset manifest fields to change last line in initContainer command script from chgrp 999 /var/lib/rabbitmq/mnesia/ to this: chown 999:999 /var/lib/rabbitmq/mnesia/.
Complete RabbitmqCluster yaml manifest looks like following:
apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
name: rabbitmq
spec:
replicas: 1
service:
type: NodePort
persistence:
storageClassName: local-storage
storage: 20Gi
override:
statefulSet:
spec:
template:
spec:
containers: []
initContainers:
- name: setup-container
command:
- sh
- -c
- cp /tmp/rabbitmq/rabbitmq.conf /etc/rabbitmq/rabbitmq.conf && chown 999:999
/etc/rabbitmq/rabbitmq.conf && echo '' >> /etc/rabbitmq/rabbitmq.conf ; cp /tmp/rabbitmq/advanced.config
/etc/rabbitmq/advanced.config && chown 999:999 /etc/rabbitmq/advanced.config
; cp /tmp/rabbitmq/rabbitmq-env.conf /etc/rabbitmq/rabbitmq-env.conf && chown
999:999 /etc/rabbitmq/rabbitmq-env.conf ; cp /tmp/erlang-cookie-secret/.erlang.cookie
/var/lib/rabbitmq/.erlang.cookie && chown 999:999 /var/lib/rabbitmq/.erlang.cookie
&& chmod 600 /var/lib/rabbitmq/.erlang.cookie ; cp /tmp/rabbitmq-plugins/enabled_plugins
/etc/rabbitmq/enabled_plugins && chown 999:999 /etc/rabbitmq/enabled_plugins
; chown 999:999 /var/lib/rabbitmq/mnesia/ # <- CHANGED THIS LINE

I had the same issue when deploying RabbitMQ in kubernetes inside Vagrant (not minikube though). I was using this setup.
I tried running sudo chmod g+w /mnt/app/rabbitmq/ but had no luck...
Eventually gave up and ended up running minikube inside vagrant using this box and everything worked perfectly fine out of the box! Didn't have to do anything special... Not event manually creating the persistent volume...
inside my nodes

I had this issue in a live version and minikube does not allow to run SSH command then.So what I did was run chmod to the my hostpath provisioner and recreated my rabbitmq-cluster
chmod 777 /tmp/hostpath-provisioner/default/*

I found the answer for this issue. It happen when there is few nodes in cluster.
Solution is to add securityContext: {}
https://github.com/rabbitmq/rabbitmq-website/blob/3ee8e72a7c4fe52e323ba1039eecbf3a67c554f7/site/kubernetes/operator/using-on-openshift.md#arbitrary-user-ids

Related

【OpenShift】define UID using ServiceAccount

【Error Summary】
I am new to RedHat OpenShift.
OpenShift Pod status CrashLoopBackOff.
Pod logs shows “id: cannot find name for user ID 1000660000” and “java.io.FileNotFoundException: ..(Permission denied)”.
I tried to solve this problem by changing UID but it doesn’t work.
If the cause is not UID ,it might be access to pvc.
Is there any way to check and change pvc?
【Error Reproduction(using OpenShift web console and terminal)】
1.Create OpenShift cluster and project.
2.Add container image from external registry
and create deployment.
(Application and component are created at the same time)
At this point the pod was running.
3.Open Deployment page and change Pod number to 0.
4.Remove existing Container Volume.
5.Add storage and create PVC.
6.Change Pod number to 1.
7.Pod is not running and the pod status is CrashLoopBackOff.
8.Create service account “awag-sa” by command below.
oc create sa awag-sa
oc adm policy add-scc-to-user anyuid-z awag-sa
9.Create patch yaml file “patch-file.yaml” for patching serviceAccount
spec:
template:
spec:
serviceAccountName: awag-sa
10.Patch yaml file to deployment by command below
kubectl patch deployment nexus3-comp --patch "$(cat patch-file.yaml)"
11.Check Deployment yaml file(OpenShift web console) that spec.template.spec.serviceAccountName is modified correctly.
But the pod status is still CrashLoopBackOff .
…
spec:
replicas: 0
selector:
matchLabels:
app: nexus3-comp
template:
metadata:
creationTimestamp: null
labels:
app: nexus3-comp
deploymentconfig: nexus3-comp
annotations:
openshift.io/generated-by: OpenShiftWebConsole
spec:
restartPolicy: Always
serviceAccountName: awag-sa
schedulerName: default-scheduler
terminationGracePeriodSeconds: 30
securityContext: {}
containers:
- name: nexus3-comp
…
OpenShift would use "random" UIDs -- relative to your Project / Namespace, there's an annotation telling you which UID was allocated to your Project. Unless otherwise configured, your containers would run as that UID.
If your application somehow needs a working getpwnam / resolution from UID to user name, then you want to use nsswrapper.
Make sure it is installed, in your Dockerfile
apt-get install libnss-wrapper
yum install nss_wrapper
Then, in your entrypoint, load your own passwd / groups:
RUNTIME_USER=${RUNTIME_USER:-nexus}
RUNTIME_GROUP=${RUNTIME_GROUP:-$RUNTIME_USER}
RUNTIME_HOME=${RUNTIME_HOME:-/tmp}
echo Setting up nsswrapper mapping `id -u` to $RUNTIME_GROUP
(
grep -v ^$RUNTIME_USER /etc/passwd
echo "$RUNTIME_USER:x:`id -u`:`id -g`:$RUNTIME_USER:$RUNTIME_HOME:/usr/sbin/nologin"
) >/tmp/java-passwd
(
grep -v ^$RUNTIME_GROUP /etc/group
echo "$RUNTIME_GROUP:x:`id -g`:"
) >/tmp/java-group
export NSS_WRAPPER_PASSWD=/tmp/java-passwd
export NSS_WRAPPER_GROUP=/tmp/java-group
export LD_PRELOAD=/usr/lib/libnss_wrapper.so
# or /usr/lib64/libnss_wrapper.so, on EL x86_64
[rest of your entrypoint.sh -- eg: exec $#]
edit: actually, nexus doesn't care -- though previous notes would still apply, if a container crashes complaining about some missing UID.
I can't reproduce the message you're getting. As far as I've seen nexus would first crash, failing to write logs. Then its data. Fixed it both times adding a volume:
oc create deploy nexus --image=sonatype/nexus3
oc edit deploy/nexus
[...]
volumeMounts:
- mountPath: /opt/sonatype/nexus3/log
name: empty
subPath: log
- mountPath: /nexus-data
name: empty
subPath: data
...
volumes:
- emptyDir: {}
name: empty
Now, in your case, /nexus-data should probably be stored in a PVC, rather than some emptyDir. Either way, adding those two volumes fixed it:
# oc logs -f nexus-f7c577ff9-pqmdc
id: cannot find name for user ID 1000230000
2021-07-10 16:36:48,155+0000 INFO [FelixStartLevel] *SYSTEM org.sonatype.nexus.pax.logging.NexusLogActivator - start
2021-07-10 16:36:49,184+0000 INFO [FelixStartLevel] *SYSTEM org.sonatype.nexus.features.internal.FeaturesWrapper - Fast FeaturesService starting
2021-07-10 16:36:53,004+0000 INFO [FelixStartLevel] *SYSTEM ROOT - bundle org.apache.felix.scr:2.1.26 (63) Starting with globalExtender setting: false
2021-07-10 16:36:53,038+0000 INFO [FelixStartLevel] *SYSTEM ROOT - bundle org.apache.felix.scr:2.1.26 (63) Version = 2.1.26
...
※Answered by questionner
I needed to change volumeMounts setttings of my deployment.
volumeMounts:
- name: nexus-data-pvc
mountPath: /nexus-data
subPath: data
- name: nexus-data-pvc
mountPath: /opt/sonatype/nexus3/log
subPath: log

Kubernetes `local` PV and directory creation

When configuring a local PV I noticed there is no option to explicitly create the PV directory on the underlying node if it does not already exist, unlike an hostPath PV which provides the DirectoryOrCreate option (as shown in the doc here), a local PV requires you to first create the directory manually and give it the correct ownership and permissions.
I am trying to use a local PV with a directory as a mounted local storage device with this code:
apiVersion: v1
kind: PersistentVolume
metadata:
name: jenkins-pv-volume
namespace: jenkins
spec:
capacity:
storage: 4Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: "/var/jenkins_home"
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- worker-1
However, in order for the PV to be configured correctly, I first need to ssh into the worker-1 node and run the following commands:
sudo mkdir -p /var/jenkins_home
sudo chown -R 1000:1000 /var/jenkins_home
sudo chmod -R 755 /var/jenkins_home
Would it be possible to create the directory and give it the correct ownership and permissions when the PV configuration is applied?
No, you cannot skip this step.
However you can write script which will work in the background and execute commands which will create directory for local volume and assign rights to it. Remember to give execute permission to your script.
For example, create script with proper commands then create ConfigMap which will run created script in also ConfigMap will configure PV.
See example: configmap-volume, configmap-scripts.

How to isolate data of one persistent volume claim from another

I created a persistent volume using the following YAML
apiVersion: v1
kind: PersistentVolume
metadata:
name: dq-tools-volume
labels:
name: dq-tools-volume
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: volume-class
nfs:
server: 192.168.215.83
path: "/var/nfsshare"
After creating this I created two persistentvolumeclaims using following YAMLS
PVC1:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-volume-1
labels:
name: jenkins-volume-1
spec:
accessMOdes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
storageClassName: volume-class
selector:
matchLabels:
name: dq-tools-volume
PVC2:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-volume-2
labels:
name: jenkins-volume-2
spec:
accessMOdes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
storageClassName: volume-class
selector:
matchLabels:
name: dq-tools-volume
But i noticed that both of these persistent volume claims are writing to same backend volume.
How can i isolate data of one persistentvolumeclaim from another. I am using this for multiple installations of Jenkins. I want workspace of each Jenkins to be isolated.
As #D.T. explained a persistent volume claim is exclusively bound to a persistent volume.
You cannot bind 2 pvc to the same pv.
Here you can find another case where it was discussed.
There is a better solution for your scenario and it involves using nfs-client-provisioner. To achive that, firstly you have to install helm in your cluster an than follow these steps that I created for a previous answer on ServerFault.
I've tested it and using this solution you can isolate one PVC from the other.
1 - Install and configur NFS Server on my Master Node (Debian Linux, this might change depending on your Linux distribution):
Before installing the NFS Kernel server, we need to update our system’s repository index:
$ sudo apt-get update
Now, run the following command in order to install the NFS Kernel Server on your system:
$ sudo apt install nfs-kernel-server
Create the Export Directory
$ sudo mkdir -p /mnt/nfs_server_files
As we want all clients to access the directory, we will remove restrictive permissions of the export folder through the following commands (this may vary on your set-up according to your security policy):
$ sudo chown nobody:nogroup /mnt/nfs_server_files
$ sudo chmod 777 /mnt/nfs_server_files
Assign server access to client(s) through NFS export file
$ sudo nano /etc/exports
Inside this file, add a new line to allow access from other servers to your share.
/mnt/nfs_server_files 10.128.0.0/24(rw,sync,no_subtree_check)
You may want to use different options in your share. 10.128.0.0/24 is my k8s internal network.
Export the shared directory and restart the service to make sure all configuration files are correct.
$ sudo exportfs -a
$ sudo systemctl restart nfs-kernel-server
Check all active shares:
$ sudo exportfs
/mnt/nfs_server_files
10.128.0.0/24
2 - Install NFS Client on all my Worker Nodes:
$ sudo apt-get update
$ sudo apt-get install nfs-common
At this point you can make a test to check if you have access to your share from your worker nodes:
$ sudo mkdir -p /mnt/sharedfolder_client
$ sudo mount kubemaster:/mnt/nfs_server_files /mnt/sharedfolder_client
Notice that at this point you can use the name of your master node. K8s is taking care of the DNS here.
Check if the volume mounted as expected and create some folders and files to male sure everything is working fine.
$ cd /mnt/sharedfolder_client
$ mkdir test
$ touch file
Go back to your master node and check if these files are at /mnt/nfs_server_files folder.
3 - Install NFS Client Provisioner.
Install the provisioner using helm:
$ helm install --name ext --namespace nfs --set nfs.server=kubemaster --set nfs.path=/mnt/nfs_server_files stable/nfs-client-provisioner
Notice that I've specified a namespace for it.
Check if they are running:
$ kubectl get pods -n nfs
NAME READY STATUS RESTARTS AGE
ext-nfs-client-provisioner-f8964b44c-2876n 1/1 Running 0 84s
At this point we have a storageclass called nfs-client:
$ kubectl get storageclass -n nfs
NAME PROVISIONER AGE
nfs-client cluster.local/ext-nfs-client-provisioner 5m30s
We need to create a PersistentVolumeClaim:
$ more nfs-client-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
namespace: nfs
name: test-claim
annotations:
volume.beta.kubernetes.io/storage-class: "nfs-client"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Mi
$ kubectl apply -f nfs-client-pvc.yaml
Check the status (Bound is expected):
$ kubectl get persistentvolumeclaim/test-claim -n nfs
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
test-claim Bound pvc-e1cd4c78-7c7c-4280-b1e0-41c0473652d5 1Mi RWX nfs-client 24s
4 - Create a simple pod to test if we can read/write out NFS Share:
Create a pod using this yaml:
apiVersion: v1
kind: Pod
metadata:
name: pod0
labels:
env: test
namespace: nfs
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-pvc
mountPath: "/mnt"
volumes:
- name: nfs-pvc
persistentVolumeClaim:
claimName: test-claim
$ kubectl apply -f pod.yaml
Let's list all mounted volumes on our pod:
$ kubectl exec -ti -n nfs pod0 -- df -h /mnt
Filesystem Size Used Avail Use% Mounted on
kubemaster:/mnt/nfs_server_files/nfs-test-claim-pvc-a2e53b0e-f9bb-4723-ad62-860030fb93b1 99G 11G 84G 11% /mnt
As we can see, we have a NFS volume mounted on /mnt. (Important to notice the path kubemaster:/mnt/nfs_server_files/nfs-test-claim-pvc-a2e53b0e-f9bb-4723-ad62-860030fb93b1)
Let's check it:
root#pod0:/# cd /mnt
root#pod0:/mnt# ls -la
total 8
drwxrwxrwx 2 nobody nogroup 4096 Nov 5 08:33 .
drwxr-xr-x 1 root root 4096 Nov 5 08:38 ..
It's empty. Let's create some files:
$ for i in 1 2; do touch file$i; done;
$ ls -l
total 8
drwxrwxrwx 2 nobody nogroup 4096 Nov 5 08:58 .
drwxr-xr-x 1 root root 4096 Nov 5 08:38 ..
-rw-r--r-- 1 nobody nogroup 0 Nov 5 08:58 file1
-rw-r--r-- 1 nobody nogroup 0 Nov 5 08:58 file2
Now let's where are these files on our NFS Server (Master Node):
$ cd /mnt/nfs_server_files
$ ls -l
total 4
drwxrwxrwx 2 nobody nogroup 4096 Nov 5 09:11 nfs-test-claim-pvc-4550f9f0-694d-46c9-9e4c-7172a3a64b12
$ cd nfs-test-claim-pvc-4550f9f0-694d-46c9-9e4c-7172a3a64b12/
$ ls -l
total 0
-rw-r--r-- 1 nobody nogroup 0 Nov 5 09:11 file1
-rw-r--r-- 1 nobody nogroup 0 Nov 5 09:11 file2
And here are the files we just created inside our pod!
As i understand it is not possible to bind two PVC to the same PV.
Refer this link > A PVC to PV binding is a one-to-one mapping
You will possibly need to look into Dynamic Provisioning option for your setup.
Tested by creating one PV of 10G and two PVC with 8Gi an 2Gi claim request
PVC-2 goes into pending state.
master $ kubectl get persistentvolume
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv 10Gi RWX Retain Bound default/pv1 7m
master $ kubectl get persistentvolumeclaims
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc1 Bound pv 10Gi RWX 3m
pvc2 Pending 8s
Files used for creating PV and PVC as below
master $ cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
hostPath:
path: /var/tmp/
master $ cat pvc1.ayml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 8Gi
master $ cat pvc2.ayml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc2
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi

Volume is already exclusively attached to one node and can't be attached to another

I have a pretty simple Kubernetes pod. I want a stateful set and want the following process:
I want to have an initcontainer download and uncompress a tarball from s3 into a volume mounted to the initcontainer
I want to mount that volume to my main container to be used
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: app
namespace: test
labels:
name: app
spec:
serviceName: app
replicas: 1
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
initContainers:
- name: preparing
image: alpine:3.8
imagePullPolicy: IfNotPresent
command:
- "sh"
- "-c"
- |
echo "Downloading data"
wget https://s3.amazonaws.com/.........
tar -xvzf xxxx-........ -C /root/
volumeMounts:
- name: node-volume
mountPath: /root/data/
containers:
- name: main-container
image: ecr.us-west-2.amazonaws.com/image/:latest
imagePullPolicy: Always
volumeMounts:
- name: node-volume
mountPath: /root/data/
volumeClaimTemplates:
- metadata:
name: node-volume
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: gp2-b
resources:
requests:
storage: 80Gi
I continue to get the following error:
At first I run this and I can see the logs flowing of my tarball being downloaded by the initcontainer. About half way done it terminates and gives me the following error:
Multi-Attach error for volume "pvc-faedc8" Volume is
already exclusively attached to one node and can't be
attached to another
Looks like you have a dangling PVC and/or PV that is attached to one of your nodes. You can ssh into the node and run a df or mount to check.
If you look at this the PVCs in a StatefulSet are always mapped to their pod names, so it may be possible that you still have a dangling pod(?)
If you have a dangling pod:
$ kubectl -n test delete pod <pod-name>
You may have to force it:
$ kubectl -n test delete pod <pod-name> --grace-period=0 --force
Then, you can try deleting the PVC and it's corresponding PV:
$ kubectl delete pvc pvc-faedc8
$ kubectl delete pv <pv-name>
I had the same issue right now and the problem was, that the node on which the pod is usually running on was down and another one took over (which didn't work as expected for whatever reason). Had the "node down" scenario a few times before already and it never caused any issues. Couldn't get the StatefulSet and Deployment back up and running without booting the node that was down. But as soon as the node was up and running again the StatefulSet and Deployment immediately came back to life as well.
I had a similar error:
The volume pvc-2885ea01-f4fb-11eb-9528-00505698bd8b
cannot be attached to the node node1 since it is already attached to the node node2*
I use longhorn as a storage provisioner and manager. So I just detached this pv in the error and restarted the stateful set. It automatically was able to attach to the pv correctly this time.
I'll add an answer that will prevent this from happening again.
Short answer
Access modes: Switch from ReadWriteOnce to ReadWriteMany.
In a bit more details
You're usng a StatefulSet where each replica has its own state, with a unique persistent volume claim (PVC) created for each pod.
Each PVC is referring to a Persistent Volume where you decided that the access mode is ReadWriteOnce.
Which as you can see from here:
ReadWriteOnce
the volume can be mounted as read-write by a single
node. ReadWriteOnce access mode still can allow multiple pods to
access the volume when the pods are running on the same node.
So in case K8S Scheduler (due to priorities or resource calculations or due to a Cluster autoscaler which decided to shift the pod to a different node) - you will receive an error that the volume is already exclusively attached to one node and can't be
attached to another node.
Please consider using ReadWriteMany where the volume can be mounted as read-write by many nodes.

Kubernetes mount.nfs: access denied by server while mounting

I have a kubernetes cluster that is running in out network and have setup an NFS server on another machine in the same network. I am able to ssh to any of the nodes in the cluster and mount from the server by running sudo mount -t nfs 10.17.10.190:/export/test /mnt but whenever my test pod tries to use an nfs persistent volume that points at that server it fails with this message:
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
19s 19s 1 default-scheduler Normal Scheduled Successfully assigned nfs-web-58z83 to wal-vm-newt02
19s 3s 6 kubelet, wal-vm-newt02 Warning
FailedMount MountVolume.SetUp failed for volume "kubernetes.io/nfs/bad55e9c-7303-11e7-9c2f-005056b40350-test-nfs" (spec.Name: "test-nfs") pod "bad55e9c-7303-11e7-9c2f-005056b40350" (UID: "bad55e9c-7303-11e7-9c2f-005056b40350") with: mount failed: exit status 32
Mounting command: mount
Mounting arguments: 10.17.10.190:/exports/test /var/lib/kubelet/pods/bad55e9c-7303-11e7-9c2f-005056b40350/volumes/kubernetes.io~nfs/test-nfs nfs []
Output: mount.nfs: access denied by server while mounting 10.17.10.190:/exports/test
Does anyone know how I can fix this and make it so that I can mount from the external NFS server?
The nodes of the cluster are running on 10.17.10.185 - 10.17.10.189 and all of the pods run with ips that start with 10.0.x.x. All of the nodes on the cluster and the NFS server are running Ubuntu. The NFS server is running on 10.17.10.190 with this /etc/exports:
/export 10.17.10.185/255.0.0.0(rw,sync,no_subtree_check)
I set up a persistent volume and persistent volume claim and they both create successfully showing this output from running kubectl get pv,pvc:
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
pv/test-nfs 1Mi RWX Retain Bound staging/test-nfs 15m
NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGE
pvc/test-nfs Bound test-nfs 1Mi RWX 15m
They were created like this:
apiVersion: v1
kind: PersistentVolume
metadata:
name: test-nfs
spec:
capacity:
storage: 1Mi
accessModes:
- ReadWriteMany
nfs:
# FIXME: use the right IP
server: 10.17.10.190
path: "/exports/test"
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-nfs
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Mi
My test pod is using this configuration:
apiVersion: v1
kind: ReplicationController
metadata:
name: nfs-web
spec:
replicas: 1
selector:
role: web-frontend
template:
metadata:
labels:
role: web-frontend
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
volumeMounts:
# name must match the volume name below
- name: test-nfs
mountPath: "/usr/share/nginx/html"
volumes:
- name: test-nfs
persistentVolumeClaim:
claimName: test-nfs
It's probably because the uid used in your pod/container has not enough rights on the NFS server.
You can runAsUser as mentioned by #Giorgio or try to edit uid-range annotations of your namespace and fix a value (ex : 666). Like this every pod in your namespace
will run with uid 666.
Don't forget to chown 666 properly your NFS directory.
You have to set a securityContext as privileged: true. Take a look at this link
The complete solution for kubernetes cluster to prepare NFS folders provisioning is to apply the followings:
# set folder permission
sudo chmod 666 /your/folder/ # maybe 777
# append new line on exports file to allow network access to folder
sudo bash -c "echo '/your/folder/ <network ip/range>(rw,sync,no_root_squash,subtree_check)' >> /etc/exports"
# set folder export
sudo exportfs -ra
In my case I was trying to mount the wrong directory...
volumes:
- name: nfs-data
nfs:
# https://github.com/kubernetes/minikube/issues/3417
# server is not resolved using kube dns (so can't resolve to a service name - hence we need the IP)
server: 10.100.155.82
path: /tmp
I did not have /tmp in the /etc/exports in the server...
Another option is to add the uid/gid information to the nfs container itself. You can do this by creating a script to add the entries to /etc/passwd and then launch the provisioner:
groupadd -g 102 postfix
adduser -u 101 -g 102 -M postfix
groupadd -g 5000 vmail
adduser -u 5000 -g 5000 -M vmail
adduser -u 33 -g 33 -M www-data
groupadd -g 8983 solr
adduser -u 8983 -g 8983 -M solr
...
/nfs-server-provisioner -provisioner=cluster.local/nfs-provisioner-nfs-server-provisioner
This allows the user/group information to be preserved over the NFS boundary using NFSv3 (which is what nfs-provisioner uses). My understanding is that NFSv4 doesn't have this problem, but I've been unable to get NFSv4 working with the provisioner.
In my case, it was the way I mounted NFS. The configuration that worked was following:
/media/drive *(rw,sync,no_root_squash,insecure,no_subtree_check)
Note that this is insecure, you might want to tweak it to make it secure, while still making it work!