Postgresql data on k8s cannot be made persistent - postgresql

I am building postgresql on kubernetes, but I cannot persist postgres data.
The host is a GCP instance with Ubuntu-20.4. The volumes for disk are using GCP volumes, which are mounted after attaching to the instance.
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/root 9982728 4252592 5713752 43% /
devtmpfs 4038244 0 4038244 0% /dev
tmpfs 4059524 0 4059524 0% /dev/shm
tmpfs 811908 1568 810340 1% /run
tmpfs 5120 0 5120 0% /run/lock
tmpfs 4059524 0 4059524 0% /sys/fs/cgroup
/dev/loop0 50304 50304 0 100% /snap/core18/2671
/dev/loop2 217856 217856 0 100% /snap/google-cloud-cli/98
/dev/loop3 94208 94208 0 100% /snap/lxd/24065
/dev/loop1 60544 60544 0 100% /snap/core20/1782
/dev/loop4 44032 44032 0 100% /snap/snapd/17885
/dev/nvme0n1p15 99801 6004 93797 7% /boot/efi
tmpfs 811904 0 811904 0% /run/user/1001
shm 65536 0 65536 0% /run/containerd/io.containerd.grpc.v1.cri/sandboxes/49ebcf7b449f4b13d52aab6f52c28f139c551f83070f6f21207dbf52315dc264/shm
shm 65536 0 65536 0% /run/containerd/io.containerd.grpc.v1.cri/sandboxes/e46f0c6b19e5ccff9bb51fa3f7669a9a6a2e7cfccf54681e316a9cd58183dce4/shm
shm 65536 0 65536 0% /run/containerd/io.containerd.grpc.v1.cri/sandboxes/495c80e87521bfdda55827df64cdb84cddad149fb502ac7ee12f3607badd4649/shm
shm 65536 0 65536 0% /run/containerd/io.containerd.grpc.v1.cri/sandboxes/443e7b254d02c88873c59edc6d5b0a71e80da382ea81105e8b312ad4122d694a/shm
/dev/nvme0n3 10218772 12 9678088 1% /var/lib/postgresql ※ disk for postgres
/dev/nvme0n2 3021608 24 2847916 1% /var/lib/pgadmin ※ disk for pgadmin
shm 65536 1052 64484 2% /run/containerd/io.containerd.grpc.v1.cri/sandboxes/bd83982e91b6a3bce7853416d72878d5473174e884c15578c47a8d8952f4e718/shm
Also, the pod volume is allocated using persistent volume and persistent volume claim.
kind: PersistentVolume
apiVersion: v1
metadata:
name: postgres-pv-volume # Sets PV's name
labels:
app: postgres
spec:
# storageClassName: local-storage
capacity:
storage: 10Gi # Sets PV Volume
accessModes:
- ReadWriteMany
hostPath:
path: "/var/lib/postgresql"
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: pgadmin-pv-volume # Sets PV's name
labels:
app: pgadmin
spec:
# storageClassName: local-storage
capacity:
storage: 3Gi # Sets PV Volume
accessModes:
- ReadWriteMany
hostPath:
path: "/var/lib/pgadmin"
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgresql
labels:
app: postgresql
spec:
replicas: 1
selector:
matchLabels:
app: postgresql
template:
metadata:
labels:
app: postgresql
spec:
containers:
- image: docker.io/yamamuratkr/postgres
name: postgresql
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres
key: database_user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres
key: database_password
- name: PGDATA
value: "/var/lib/postgresql/data/pgdata"
ports:
- containerPort: 5432
name: postgresql
volumeMounts:
- name: postgredb
mountPath: /var/lib/postgresql
volumes:
- name: postgredb
persistentVolumeClaim:
claimName: postgres-pv-claim
However, when the pod is deleted, the postgres data also disappears with it, and I can confirm that it is not persistent.
If you know the cause of this problem, please let me know.
Thank you in advance.
None of the following worked
Using hostpath for pod volumes
Use default PGDATA

The source of your problem is here:
volumeMounts:
- name: postgredb
mountPath: /var/lib/postgresql
The postgres image itself mounts a volume on /var/lib/postgresql/data. We can see that if we inspect the image:
$ docker image inspect docker.io/postgres:14 | jq '.[0].ContainerConfig.Volumes'
{
"/var/lib/postgresql/data": {}
}
Your mount on /var/lib/postgresql is effectively a no-op. An ephemeral volume is created on /var/lib/postgresql/data each time the container starts, and since that's the default PGDATA location, your data is effectively discarded when the container exits.
I've put together an example in my local environment to demonstrate this behavior. I've made a few minor changes from your example that shouldn't operationally impact anything.
I've created the following Secret with the postgres credentials; by naming the keys like this we can use a single envFrom block instead of multiple env entries (see the Deployment for details):
apiVersion: v1
kind: Secret
metadata:
name: postgres-env
type: Opaque
stringData:
POSTGRES_USER: example
POSTGRES_PASSWORD: secret
And in line with my comment I'm injecting a file into /docker-entrypoint-initdb.d from this ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
data:
initdb.sql: |
CREATE TABLE people (
id SERIAL,
name VARCHAR(40),
favorite_color VARCHAR(10)
);
INSERT INTO people (name, favorite_color) VALUES ('bob', 'red');
INSERT INTO people (name, favorite_color) VALUES ('alice', 'blue');
INSERT INTO people (name, favorite_color) VALUES ('mallory', 'purple');
I'm using this PersistentVolumeClaim:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
And finally I'm tying it all together in this Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: postgres
name: postgresql
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- envFrom:
- secretRef:
name: postgres-env
image: docker.io/postgres:14
name: postgresql
ports:
- containerPort: 5432
name: postgresql
volumeMounts:
- mountPath: /docker-entrypoint-initdb.d
name: postgres-config
- mountPath: /var/lib/postgresql
name: postgres-data
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-pv-claim
- configMap:
name: postgres-config
name: postgres-config
The significant changes here are:
I'm using a single envFrom block to set environment variables from the keys in the postgres-env secret.
I'm using the upstream docker.io/postgres:14 image rather than building my own custom image.
I'm injecting the contents of /docker-entrypoint-initdb.d from the postgres-config ConfigMap.
Note that this deployment is using the same mountPath as in your example`.
If I bring up this environment, I can see that the database initialization script was executed correctly. The people table exists and has the expected data:
$ kubtectl exec -it deploy/postgresql -- psql -U example -c 'select * from people'
id | name | favorite_color
----+---------+----------------
1 | bob | red
2 | alice | blue
3 | mallory | purple
(3 rows)
Let's make a change to the database and see what happens when we restart the pod. First, we add a new row to the table and view the updated table:
$ kubectl exec -it deploy/postgresql -- psql -U example -c "insert into people (name, favorite_color) values ('carol', 'green')"
INSERT 0 1
$ kubectl exec -it deploy/postgresql -- psql -U example -c 'select * from people'
id | name | favorite_color
----+---------+----------------
1 | bob | red
2 | alice | blue
3 | mallory | purple
4 | carol | green
(4 rows)
Now we restart the database pod:
$ kubectl rollout restart deployment/postgresql
And finally check if our changes survived the restart:
$ kubectl exec -it deploy/postgresql -- psql -U example -c 'select * from people' id | name | favorite_color
----+---------+----------------
1 | bob | red
2 | alice | blue
3 | mallory | purple
(3 rows)
As expected, they did not! Let's change the mountPath in the Deployment so that it looks like this instead:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: postgres
name: postgresql
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- envFrom:
- secretRef:
name: postgres-env
image: docker.io/postgres:14
name: postgresql
ports:
- containerPort: 5432
name: postgresql
volumeMounts:
- mountPath: /docker-entrypoint-initdb.d
name: postgres-config
- mountPath: /var/lib/postgresql/data
name: postgres-data
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-pv-claim
- configMap:
name: postgres-config
name: postgres-config
Using this Deployment, with no other changes, we can re-run the previous test and see that our data persists as desired:
$ kubectl exec -it deploy/postgresql -- psql -U example -c "insert into people (name, favorite_color) values ('carol', 'green')"
INSERT 0 1
$ k rollout restart deployment/postgresql
deployment.apps/postgresql restarted
$ k exec -it deploy/postgresql -- psql -U example -c 'select * from people' id | name | favorite_color
----+---------+----------------
1 | bob | red
2 | alice | blue
3 | mallory | purple
4 | carol | green
(4 rows)
An alternative solution would be to mount your volume in a completely different location and then set PGDATA appropriately. E.g.,
...
env:
- name: PGDATA
value: /data
...
volumeMounts:
- name: postgres-data
mountPath: /data
...

Related

Accessing Postgresql data of Kubernetes cluster

I have kubernetes cluster with two replicas of a PostgreSQL database in it, and I wanted to see the values stored in the database.
When I exec myself into one of the two postgres pod (kubectl exec --stdin --tty [postgres_pod] -- /bin/bash) and check the database from within, I have only a partial part of the DB. The rest of the DB data is on the other Postgres pod, and I don't see any directory created by the persistent volumes with all the database stored.
So in short I create 4 tables; in one postgres pod I have 4 tables but 2 are empty, in the other postgres pod there are 3 tables and the tables that were empty in the first pod, here are filled with data.
Why the pods don't have the same data in it?
How can I access and download the entire database?
PS. I deploy the cluster using HELM in minikube.
Here are the YAML files:
---
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
labels:
app: postgres
data:
POSTGRES_DB: database-pg
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
PGDATA: /data/pgdata
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: postgres-pv-volume
labels:
type: local
app: postgres
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
hostPath:
path: "/mnt/data"
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: postgres-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
name: postgres
labels:
app: postgres
spec:
ports:
- name: postgres
port: 5432
nodePort: 30432
type: NodePort
selector:
app: postgres
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres-service
selector:
matchLabels:
app: postgres
replicas: 2
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:13.2
volumeMounts:
- name: postgres-disk
mountPath: /data
# Config from ConfigMap
envFrom:
- configMapRef:
name: postgres-config
volumeClaimTemplates:
- metadata:
name: postgres-disk
spec:
accessModes: ["ReadWriteOnce"]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
labels:
app: postgres
spec:
selector:
matchLabels:
app: postgres
replicas: 2
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:13.2
imagePullPolicy: IfNotPresent
envFrom:
- configMapRef:
name: postgres-config
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgredb
volumes:
- name: postgredb
persistentVolumeClaim:
claimName: postgres-pv-claim
---
I found a solution to my problem of downloading the volume directory, however when I run multiple replicasets of postgres, the tables of the DB are still scattered between the pods.
Here's what I did to download the postgres volume:
First of all, minikube supports some specific directories for volume appear:
minikube is configured to persist files stored under the following directories, which are made in the Minikube VM (or on your localhost if running on bare metal). You may lose data from other directories on reboots.
/data
/var/lib/minikube
/var/lib/docker
/tmp/hostpath_pv
/tmp/hostpath-provisioner
So I've changed the mount path to be under the /data directory. This made the database volume visible.
After this I ssh'ed into minikube and copied the database volume to a new directory (I used /home/docker as the user of minikube is docker).
sudo cp -R /data/pgdata /home/docker
The volume pgdata was still owned by root (access denied error) so I changed it to be owned by docker. For this I also set a new password which I knew:
sudo passwd docker # change password for docker user
sudo chown -R docker: /home/docker/pgdata # change owner from root to docker
Then you can exit and copy the directory into you local machine:
exit
scp -r $(minikube ssh-key) docker#$(minikube ip):/home/docker/pgdata [your_local_path].
NOTE
Mario's advice, which is to use pgdump is probably a better solution to copy a database. I still wanted to download the volume directory to see if it has the full database, when the pods have only a part of all the tables. In the end it turned out it doesn't.

Postgres on Azure kubernetes volume permission error

I'm trying to deploy Postgresql on Azure Kubernetes with data persistency. So I'm using PVC.
I searched lots of posts on here, most of them offered yaml files like below, but it's giving the error below;
chmod: changing permissions of '/var/lib/postgresql/data/pgdata': Operation not permitted
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".
Data page checksums are disabled.
initdb: error: could not change permissions of directory "/var/lib/postgresql/data/pgdata": Operation not permitted
fixing permissions on existing directory /var/lib/postgresql/data/pgdata ...
deployment yaml file is below;
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgresql
spec:
replicas: 1
selector:
matchLabels:
app: postgresql
template:
metadata:
labels:
app: postgresql
spec:
containers:
- name: postgresql
image: postgres:13.2
securityContext:
runAsUser: 999
imagePullPolicy: "IfNotPresent"
ports:
- containerPort: 5432
envFrom:
- secretRef:
name: postgresql-secret
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgredb-kap
volumes:
- name: postgredb-kap
persistentVolumeClaim:
claimName: postgresql-pvc
Secret yaml is below;
apiVersion: v1
kind: Secret
metadata:
name: postgresql-secret
type: Opaque
data:
POSTGRES_DB: a2V5sd4=
POSTGRES_USER: cG9zdGdyZXNhZG1pbg==
POSTGRES_PASSWORD: c234Rw==
PGDATA: L3Za234dGF0YQ==
pvc and sc yaml files are below:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: postgresql-pvc
labels:
app: postgresql
spec:
storageClassName: postgresql-sc
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
allowVolumeExpansion: true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: postgresql-sc
mountOptions:
- dir_mode=0777
- file_mode=0777
- uid=1000
- gid=1000
parameters:
skuName: Standard_LRS
provisioner: kubernetes.io/azure-file
reclaimPolicy: Retain
So when I use the mountpath like "- mountPath: /var/lib/postgresql/", it's working. I can reach the DB and it's good. But when I delete the pod and recreating, there is no DB! So no data persistency.
Can you please help, what am I missing here?
Thanks!
One thing you could try is to change uid=1000,gid=1000 in mount options to 999 since this is the uid of postgres user in postgres conatiner (I didn't test this).
Another solution that will for certain solve this issue involves init conatainers.
Postgres container requires to start as root to be able to chown pgdata dir since its mounted as root dir. After it does this, it drops root permisions and runs as postgres user.
But you can use init container (running as root) to chmod the volume dir so that you can run main container as non-root.
Here is an example:
initContainers:
- name: init
image: alpine
command: ["sh", "-c", "chown 999:999 /var/lib/postgresql/data"]
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgredb-kap
Based on the helpful answer from Matt. For bitnami postgresql the initContainer also works but with a slightly different configuration:
initContainers:
- name: init
image: alpine
command: ["sh", "-c", "chown 1001:1001 /bitnami/postgresql"]
volumeMounts:
- mountPath: /bitnami/postgresql
name: postgres-volume

mkdir /mnt/data: read-only file system Back-off restarting failed postgres container

I'm new to Kubernetes, I tried to apply yaml file to create Postgres in GKE, I'm getting error as "Error: failed to start container "postgres": Error response from daemon: error while creating mount source path '/mnt/data': mkdir /mnt/data: read-only file system Back-off restarting failed container.
I thinki need to give permsions as RWX , when i tried to Login to pod i.e inside container..It is not allowing to login.
ANyone please help me !!.
This is my Yaml file for Postgres:
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
selector:
matchLabels:
app: postgres
replicas: 1
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:latest
imagePullPolicy: "IfNotPresent"
envFrom:
- configMapRef:
name: postgres-config
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgredb
volumes:
- name: postgredb
persistentVolumeClaim:
claimName: postgres-pv-claim
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: postgres-pv-volume
labels:
type: local
app: postgres
spec:
storageClassName: manual
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
hostPath:
path: "/mnt/data"
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: postgres-pv-claim
labels:
app: postgres
spec:
storageClassName: manual
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
labels:
app: postgres
data:
POSTGRES_DB: postgresdb
POSTGRES_USER: postgres
POSTGRES_PASSWORD: root
---
apiVersion: v1
kind: Service
metadata:
name: postgres
labels:
app: postgres
spec:
ports:
- name: postgres
port: 5432
nodePort: 30432
type: NodePort
selector:
app: postgres
In your Persistent Volume you are using type: local which means that you want to create directory in /mnt. Local also do not support dynamic volume provisioning. If you will SSH to any of your nodes you will find that this folder is ReadOnly file system.
/mnt $ mkdir something
mkdir: cannot create directory ‘something’: Read-only file system
As fastest workaround, you just could change in your PV YAML
- ReadWriteMany
hostPath:
path: /mnt/data
To:
- ReadWriteMany
hostPath:
path: /var/lib/data
Example:
$ kubectl apply -f pv-pvc.yaml
persistentvolume/postgres-pv-volume created
persistentvolumeclaim/postgres-pv-claim created
$ kubectl apply -f pos.yaml
deployment.apps/postgres created
$ kubectl get po
NAME READY STATUS RESTARTS AGE
postgres-65d9cbd495-pcqf5 1/1 Running 0 2s
$ kubectl exec -ti postgres-65d9cbd495-pcqf5 -- /bin/bash
root#postgres-65d9cbd495-pcqf5:/# cd /var/lib/postgresql/data
root#postgres-65d9cbd495-pcqf5:/var/lib/postgresql/data# ls
base pg_commit_ts pg_hba.conf pg_logical pg_notify pg_serial pg_stat pg_subtrans pg_twophase pg_wal postgresql.auto.conf postmaster.opts
global pg_dynshmem pg_ident.conf pg_multixact pg_replslot pg_snapshots pg_stat_tmp pg_tblspc PG_VERSION pg_xact postgresql.conf postmaster.pid
root#postgres-65d9cbd495-pcqf5:/var/lib/postgresql/data# echo "Hello from postgress pod" > data.txt
root#postgres-65d9cbd495-pcqf5:/var/lib/postgresql/data# cat data.txt
Hello from postgress pod
Now if you will SSH to the node which is hosting this pod, you will be able to reach this folder and files.
user#gke-cluster-1-default-pool-463f9615-gxhl ~ $ sudo su
gke-cluster-1-default-pool-463f9615-gxhl /home/user # cd /var/lib/data
gke-cluster-1-default-pool-463f9615-gxhl /var/lib/data # ls
PG_VERSION pg_dynshmem pg_notify pg_stat_tmp pg_xact
base pg_hba.conf pg_replslot pg_subtrans postgresql.auto.conf
data.txt pg_ident.conf pg_serial pg_tblspc postgresql.conf
global pg_logical pg_snapshots pg_twophase postmaster.opts
pg_commit_ts pg_multixact pg_stat pg_wal postmaster.pid
gke-cluster-1-default-pool-463f9615-gxhl /var/lib/data # cat data.txt
Hello from postgress pod
EDIT
YAMLs Ive used.
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
labels:
app: postgres
data:
POSTGRES_DB: postgresdb
POSTGRES_USER: postgres
POSTGRES_PASSWORD: root
---
apiVersion: v1
kind: Service
metadata:
name: postgres
labels:
app: postgres
spec:
type: NodePort
selector:
app: postgres
ports:
- name: postgres
port: 5432
nodePort: 30432
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: postgres-pv-volume
labels:
app: postgres
type: local
spec:
storageClassName: manual
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
hostPath:
path: /var/lib/data
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: postgres-pv-claim
labels:
app: postgres
spec:
storageClassName: manual
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:latest
imagePullPolicy: "IfNotPresent"
envFrom:
- configMapRef:
name: postgres-config
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgredb
volumes:
- name: postgredb
persistentVolumeClaim:
claimName: postgres-pv-claim
configmap/postgres-config created
service/postgres created
persistentvolume/postgres-pv-volume created
persistentvolumeclaim/postgres-pv-claim created
deployment.apps/postgres created
$ kubectl get po
NAME READY STATUS RESTARTS AGE
postgres-65d9cbd495-wxx4h 1/1 Running 0 19s
If you're working with GKE, just create PVC, it will self create PV which will work according to your need.
I Fixed my issue that way.

unable to understand mounting postgres data path onto minikube kubernetes deployment with permission errors

I’m getting started with kubernetes, and I want to create a simple app with a single webserver & postgres database. The problem I’m running into is the deployment of the postgres is giving me permission errors. The following are discussions around this:
https://github.com/docker-library/postgres/issues/116
https://github.com/docker-library/postgres/issues/103
https://github.com/docker-library/postgres/issues/696
Can't get either Postgres permissions or PVC working in AKS
Kubernetes - Pod which encapsulates DB is crashing
Mount local directory into pod in minikube
https://serverfault.com/questions/981459/minikube-using-a-storageclass-to-provision-data-outside-of-tmp
EDIT
spec:
OSX - 10.15.4
minikube - v1.9.2
kubernetes - v1.18.2
minikube setup
minikube start --driver=virtualbox --cpus=2 --memory=5120 --kubernetes-version=v1.18.2 --container-runtime=docker --mount=true --mount-string=/Users/holmes/kubernetes/pgdata:/data/pgdata
The permission error: chmod: changing permissions of '/var/lib/postgresql/data': Operation not permitted
I am trying to mount a local OS directory into minikube to be used with the postgres deployment/pod/container volume mount.
After I run the above setup I ssh into minikube (minikube ssh) and check the permissions
# minikube: /
drwxr-xr-x 3 root root 4096 May 13 19:31 data
# minikube: /data
drwx------ 1 docker docker 96 May 13 19:27 pgdata
By running the script below the chmod permission error surfaces. If I change the --mount-string=/Users/holmes/kubernetes/pgdata:/data (leave out /pgdata) and then minikube ssh to create the pgdata directory:
mkdir -p /data/pgdata
chmod 777 /data/pgdata
I get a different set of permissions before deployment
# minikube: /
drwx------ 1 docker docker 96 May 13 20:10 data
# minikube: /data
drwxrwxrwx 1 docker docker 64 May 13 20:25 pgdata
and after deployment
# minikube: /
drwx------ 1 docker docker 128 May 13 20:25 data
# minikube: /data
drwx------ 1 docker docker 64 May 13 20:25 pgdata
Not sure why this changes, and the chmod permission error persists. It seems like the above reference links are bouncing around different methods on different machines on different vms which I don’t understand nor can I get this to work. Can someone walk me getting this to work? Super confused going through all the above discussions.
postgres.yaml
apiVersion: v1
kind: Namespace
metadata:
name: data-block
---
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
namespace: data-block
labels:
type: starter
data:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: docker
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres-pv
namespace: data-block
labels:
app: postgres
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /data/pgdata
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pv-claim
namespace: data-block
labels:
app: postgres
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: ""
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: data-block
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:12.2
ports:
- containerPort: 5432
envFrom:
- configMapRef:
name: postgres-config
volumeMounts:
- name: postgres-vol
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-vol
persistentVolumeClaim:
claimName: postgres-pv-claim
UPDATE
I went ahead and updated the deployment script to a simple pod. The goal is map the postgres /var/lib/postgresql/data to my local file directory /Users/<my-path>/database/data to persist the data.
---
apiVersion: v1
kind: Pod
metadata:
name: postgres-pod
namespace: data-block
labels:
name: postgres-pod
spec:
containers:
- name: postgres
image: postgres:12.3
imagePullPolicy: IfNotPresent
ports:
- name: postgres-port
containerPort: 5432
envFrom:
- configMapRef:
name: postgres-env-config
- secretRef:
name: postgres-secret
volumeMounts:
- name: postgres-vol
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-vol
hostPath:
path: /Users/<my-path>/database/data
restartPolicy: Never
The error: initdb: error: could not access directory "/var/lib/postgresql/data": Permission denied
How to go about mounting the local file directory?
You are declaring the PGDATA field that maybe the cause of the issue. I faced the same error, this comes because there's as LOST+FOUND folder already in that directory however, the container wants it to be a empty dir. Giving the subPath field solves this issue. Please try this it should solve the issue and you need not need any PGDATA field. Try omitting it from your configmap and add subPath to some folder. Please go through following manifests.
https://github.com/mendix/kubernetes-howto/blob/master/postgres-deployment.yaml
https://www.bmc.com/blogs/kubernetes-postgresql/
it's a statefulset that usually you should go with and not a deployment when it comes to Database deployment.
- name: postgredb
mountPath: /var/lib/postgresql/data
#setting subPath will fix your issue it can be pgdata or
postgres or any other folder name according to your
choice.
subPath: postgres

How to unmount partition in kubernetes

I have one pod and one partion in it
kubectl exec pod-t -- lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 298.1G 0 disk
`-sda10 8:10 28G 0 part /etc/hosts
sr0 11:0 1 1024M 0 rom
rbd5 252:80 0 15G 0 disk /usr/share/nginx/html
When i want umount it i see
must be superuser to unmount
#kubectl exec pod-t -- umount /dev/rbd5
umount: /usr/share/nginx/html: must be superuser to unmount
command terminated with exit code 32
The pod was created by this template:
apiVersion: v1
kind: Pod
metadata:
name: pod-t
namespace: default
labels:
spec:
containers:
- name: nginxqw
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: content-data
mountPath: /usr/share/nginx/html
volumes:
- name: content-data
persistentVolumeClaim:
claimName: pvc-t
I think the pod does not have root priviledge.
How can i solve it?
There is a privileged flag on the SecurityContext of the container spec.
I use this template
apiVersion: v1
kind: Pod
metadata:
name: hello-world
spec:
containers:
- name: hello-world-container
# The container definition
# ...
securityContext:
privileged: true