Kubernetes - Pod which encapsulates DB is crashing - kubernetes

I am experiencing issues when I try to deploy my Django application to Kubernetes cluster. More specifically, when I try to deploy PostgreSQL.
Here is what my .YML deployment file looks like:
apiVersion: v1
kind: Service
metadata:
name: postgres-service
spec:
selector:
app: postgres-container
tier: backend
ports:
- protocol: TCP
port: 5432
targetPort: 5432
type: ClusterIP
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres-pv
labels:
type: local
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 2Gi
hostPath:
path: /tmp/data/persistent-volume-1 #U okviru cvora n
persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pv-claim
labels:
type: local
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres-container
tier: backend
template:
metadata:
labels:
app: postgres-container
tier: backend
spec:
containers:
- name: postgres-container
image: postgres:9.6.6
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-credentials
key: user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-credentials
key: password
- name: POSTGRES_DB
value: agent_technologies_db
ports:
- containerPort: 5432
volumeMounts:
- name: postgres-volume-mount
mountPath: /var/lib/postgresql/data/db-files
volumes:
- name: postgres-volume-mount
persistentVolumeClaim:
claimName: postgres-pv-claim
- name: postgres-credentials
secret:
secretName: postgres-credentials
Here is what I get when I run kubectl get pods command :
NAME READY STATUS RESTARTS AGE
agent-technologies-deployment-7c7c6676ff-8p49r 1/1 Running 0 2m
agent-technologies-deployment-7c7c6676ff-dht5h 1/1 Running 0 2m
agent-technologies-deployment-7c7c6676ff-gn8lp 1/1 Running 0 2m
agent-technologies-deployment-7c7c6676ff-n9qql 1/1 Running 0 2m
postgres-8676b745bf-8f7jv 0/1 CrashLoopBackOff 4 3m
And here is what I get when I try to inspect what is going on with PostgreSQL deployment by using kubectl logs $pod_name:
initdb: directory "/var/lib/postgresql/data" exists but is not empty
If you want to create a new database system, either remove or empty
the directory "/var/lib/postgresql/data" or run initdb
with an argument other than "/var/lib/postgresql/data".
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.
Note: I am using Google Cloud as a provider.

You can't have your db in /var/lib/postgres/data/whatever.
Change that path by /var/lib/postgres/whatever and it will work.
17.2.1. Use of Secondary File Systems
Many installations create their database clusters on file systems (volumes) other than the machine's "root" volume. If you choose to do this, it is not advisable to try to use the secondary volume's topmost directory (mount point) as the data directory. Best practice is to create a directory within the mount-point directory that is owned by the PostgreSQL user, and then create the data directory within that. This avoids permissions problems, particularly for operations such as pg_upgrade, and it also ensures clean failures if the secondary volume is taken offline.
And, by the way, I had to create a secret, as it is not in the post:
apiVersion: v1
kind: Secret
metadata:
name: postgres-credentials
type: Opaque
data:
user: cG9zdGdyZXM= #postgres
password: cGFzc3dvcmQ= #password
Note that the username needs to be "postgres". I don't know if you are covering this...

Adding to what #suren answered.
I had this issue while running postgresql-setup --initdb in RHEL 8.4. I was getting this error :
Initializing database in '/var/lib/pgsql/data'
ERROR: Initializing database failed, possibly see /var/lib/pgsql/initdb_postgresql.log
So, following suren's suggestion, I deleted the 'data' folder and ran the command again. Worked like a charm!

Related

What is the correct and secure way to run a single instance mongo in kubernetes with Persistent volumes?

I am trying to deploy a single instance mongodb inside of a kubernetes cluster (RKE2 specifically) on an AWS ec2 instance running Redhat 8.5. I am just trying to use the local file system i.e. no EBS. I am having trouble getting my application to work with persistent volumes so I have a few questions. Below is my pv.yaml
kind: Namespace
apiVersion: v1
metadata:
name: mongo
labels:
name: mongo
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: mongodb-pv
namespace: mongo
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/home/ec2-user/database"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongodb-pvc
namespace: mongo
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
And here is my mongo deployment (I know having the user/password in plain text is not secure but this is for the sake of the example)
apiVersion: v1
kind: Pod
metadata:
name: mongodb-pod
namespace: mongo
labels:
app.kubernetes.io/name: mongodb-pod
spec:
containers:
- name: mongo
image: mongo:latest
imagePullPolicy: Always
ports:
- containerPort: 27017
name: mongodb-cp
env:
- name: MONGO_INITDB_ROOT_USERNAME
value: "user"
- name: MONGO_INITDB_ROOT_PASSWORD
value: "password"
volumeMounts:
- mountPath: /data/db
name: mongodb-storage
volumes:
- name: mongodb-storage
persistentVolumeClaim:
claimName: mongodb-pvc
---
apiVersion: v1
kind: Service
metadata:
name: mongodb
namespace: mongo
spec:
selector:
app.kubernetes.io/name: mongodb-pod
ports:
- name: mongodb-cp
port: 27017
targetPort: mongodb-cp
When I run the above configuration files, I get the following errors from the mongo pod:
find: '/data/db': Permission denied
chown: changing ownership of '/data/db': Permission denied
I tried creating a mongodb user on the host with a uid and gid of 1001 since that is the process owner inside the mongo container and chowning the hostPath mentioned above but the error persists.
I have tried adding a securityContext block at both the pod and container level like so:
securityContext:
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
which does get me further, but I now get the following error:
{"t":{"$date":"2022-06-02T20:32:13.015+00:00"},"s":"E", "c":"CONTROL", "id":20557, "ctx":"initandlisten","msg":"DBException in initAndListen, terminating","attr":{"error":"IllegalOperation: Attempted to create a lock file on a read-only directory: /data/db"}}
and then the pod dies. If I set the container securityContext to privileged
securityContext:
privileged: true
Everything runs fine. So the two questions are.. is it secure to run a pod as privileged? If not (which is my assumption), what is the correct and secure way to use persistent volumes with the above configurations/example?

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.

CreateContainerError while creating postgresql in k8s

I'm trying to run postgresql db at k8s and there is no errors while creating all from file, but pod at the deployment cant create container.
There is my yaml code:
ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
labels:
app: postgres
data:
POSTGRES_DB: postgresdb
POSTGRES_USER: postgresadmin
POSTGRES_PASSWORD: adminpassword
Deployment:
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:10.18
imagePullPolicy: "IfNotPresent"
ports:
- containerPort: 5432
envFrom:
- configMapRef:
name: postgres-config
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgredb
volumes:
- name: postgredb
persistentVolumeClaim:
claimName: postgres-pv-claim
Sevice:
apiVersion: v1
kind: Service
metadata:
name: postgres
labels:
app: postgres
spec:
type: ClusterIP
ports:
- port: 5432
selector:
app: postgres
after i'm using:
kubectl create -f filename
i got :
configmap/postgres-config created
persistentvolume/postgres-pv-volume created
persistentvolumeclaim/postgres-pv-claim created
deployment.apps/postgres created
service/postgres created
But when i'm typing:
kubectl get pods
There is an error:
postgres-78496cc865-85kt7 0/1 CreateContainerError 0 13m
this is PV and PVC, no more space at the question to ad that as a code :)
If you describe the pod, you'll see the warning message in there,
Warning FailedScheduling 45s (x2 over 45s) default-scheduler persistentvolumeclaim "postgres-pv-claim" not found
On a high level, a database instance can run within a Kubernetes container. A database instance stores data in files, and the files are stored in persistent volume claims. A PersistentVolumeClaim must be created and made available to a PostgreSQL instance.To create the database instance as a container, you use a deployment configuration. In order to provide an access interface that is independent of the particular container, you create a service that provides access to the database. The service remains unchanged even if a container (or pod) is moved to a different node.
In your case, create a PVC resource and bound it to PV so that will be used by the pod. As currently it does not found that , it went into pending state. This can be achieved in multiple ways, you can either use the hostPath as the local storage,
$ k get pods
NAME READY STATUS RESTARTS AGE
postgres-795cfcd67b-khfgn 1/1 Running 0 18s
Sample PV and PVC configs as below,
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nautilus
spec:
storageClassName: manual
capacity:
storage: 8Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/home/mohan"
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
You can check the Persistent Volume doc for more details. Also, read more about storage class and StatefulSets for deploying database applications in Kubernetes cluster.
Thanks to all who tried to help me! Problem was at PersistentVolume.spec.hostPath.path. There was an invalid character at the path. I tried to use "./path".

How to have data persist in GKE kubernetes StatefulSet with postgres?

So I'm just trying to get a web app running on GKE experimentally to familiarize myself with Kubernetes and GKE.
I have a statefulSet (Postgres) with a persistent volume/ persistent volume claim which is mounted to the Postgres pod as expected. The problem I'm having is having the Postgres data endure. If I mount the PV at var/lib/postgres the data gets overridden with each pod update. If I mount at var/lib/postgres/data I get the warning:
initdb: directory "/var/lib/postgresql/data" exists but is not empty
It contains a lost+found directory, perhaps due to it being a mount point.
Using a mount point directly as the data directory is not recommended.
Create a subdirectory under the mount point.
Using Docker alone having the volume mount point at var/lib/postgresql/data works as expected and data endures, but I don't know what to do now in GKE. How does one set this up properly?
Setup file:
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: sm-pd-volume-claim
spec:
storageClassName: "standard"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1G
---
apiVersion: "apps/v1"
kind: "StatefulSet"
metadata:
name: "postgis-db"
namespace: "default"
labels:
app: "postgis-db"
spec:
serviceName: "postgis-db"
replicas: 1
selector:
matchLabels:
app: "postgis-db"
template:
metadata:
labels:
app: "postgis-db"
spec:
terminationGracePeriodSeconds: 25
containers:
- name: "postgis"
image: "mdillon/postgis"
ports:
- containerPort: 5432
name: postgis-port
volumeMounts:
- name: sm-pd-volume
mountPath: /var/lib/postgresql/data
volumes:
- name: sm-pd-volume
persistentVolumeClaim:
claimName: sm-pd-volume-claim
You are getting this error because the postgres pod has tried to mount the data directory on / folder. It is not recommended to do so.
You have to create subdirectory to resolve this issues on the statefulset manifest yaml files.
volumeMounts:
- name: sm-pd-volume
mountPath: /var/lib/postgresql/data
subPath: data

Can we create Multiple databases in Same Persistent Volume in kubernetes ?

I have Azure Machine (kubernetes) who have Agent of 2 core, 1 GB. My two services are running on this Machine each have its own Postgres (Deplyment, Service, Pv, PVC).
I want to host my third service too on same machine.
So when I tried to create Postgres Deployment (this too have its own service, PV, PVC) but Pod was stuck in status=ContainerCreating .
After some digging I got to know that my VM only Supports data-disks.
So i thought why not use PVC of earlier deployment in current service like:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: third-postgres
labels:
name: third-postgres
spec:
replicas: 1
template:
metadata:
labels:
name: third-postgres
spec:
containers:
- name: third-postgres
image: postgres
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: POSTGRES_USER
value: third-user
- name: POSTGRES_PASSWORD
value: <password>
- name: POSTGRES_DB
value: third_service_db
ports:
- containerPort: 5432
volumeMounts:
- name: third-postgresdata
mountPath: /var/lib/postgresql/data
volumes:
- name: third-postgresdata
persistentVolumeClaim:
claimName: <second-postgres-data>
Now this Deployment was successfully running but it doesn't create new database third_service_db
May be because second PVC was already exists so it skips the Db create part ?
So is their any way I can use same PVC for my all services and same PVC can have multiple databases. So that when I run kubectl create -f <path-to-thirst-postgres.yaml> it takes name Database configuration from env Variables and create DB in same PVC
You have to create one PVC per Deployment. Once a PVC has been claimed, it must be released before it can be used again.
In the case of AzureDisk, the auto-created volumes can only be mounted by a single node (ReadWriteOnce access mode) so there's one more constraint: each of your Deployments can have at most 1 replica.
Yes you can create as much databas as you want on the same Persistent Volume. You have to change the path value to store different database. See the example below.
apiVersion: v1
kind: PersistentVolume
metadata:
name: ...
namespace: ...
labels:
type: ...
spec:
storageClassName: ...
capacity:
storage: ...
accessModes:
- ...
hostPath:
path: "/mnt/data/DIFFERENT_PATH_FOR_EACH_DATABASE"