kubernetes single node postgres

Step 1: Disk

Note: this step is only for cloud, for local can be skipped, idea here to be able to control disk name and type, otherwise kubernetes will create disk with uuid name which is hard to manage in future

Go to disks management and create one

  • Name: pg1
  • Description: disk for "pg1" pod in kubernetes
  • Type: SSD persistent disk
  • Zone: europe-west1-b
  • Size (GB): 10

Step 2: Password

create password secret

kubectl create secret generic pg1 --from-literal=password='xxxxxxx'

Notes:

  • pg1 is the name of secret at will be used later, keep eye on it and do not forget to rename it
  • on the other hand it can be optional and you can reuse already created secret

Step 3: Persistent Volume

For local kubernetes use:

local.yml

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pg1-pv
spec:
  storageClassName: manual
  capacity:
    storage: 10G
  accessModes:
    - ReadWriteOnce
  hostPath:
    # TODO: do not forget to change me
    path: "/Users/mac/Desktop/pgkube/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pg1-pvc
spec:
  storageClassName: manual
  volumeName: pg1-pv
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10G
kubectl apply -f local.yml
kubectl get pv,pvc

For cloud kubernetes:

cloud.yml

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pg1-pv
spec:
  storageClassName: ""
  capacity:
    storage: 10G
  accessModes:
    - ReadWriteOnce
  gcePersistentDisk:
    # https://console.cloud.google.com/compute/disksDetail/zones/europe-west1-b/disks/es1?project=majestic-cairn-171208
    # TODO: change "pg1" to your disk name
    pdName: pg1
    fsType: ext4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pg1-pvc
spec:
  storageClassName: ""
  volumeName: pg1-pv
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10G
kubectl apply -f cloud.yml
kubectl get pv,pvc

Notes:

  • use same metadata.name for both local and cloud persistent volumes in order to prevent confusion
  • gcePersistentDisk.pdName is a disk name you have created in step 1
  • capacity.storage can not be bigger than a disk space
  • kubernetes persistent volume 5 minutes video
  • in either case look for bound status in kubectl get pv,pvc

Step 4: Postgres

---
apiVersion: v1
kind: Pod
metadata:
  name: pg1
  labels:
    app: pg1
spec:
  containers:
    - name: pg1
      image: postgres:12-alpine
      ports:
        - containerPort: 5432
      env:
        - name: POSTGRES_USER
          value: pg1
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: pg1
              key: password
        - name: PGDATA
          value: /postgres/data
      volumeMounts:
        - name: data
          mountPath: /postgres
      resources:
        requests:
          memory: 128M
        limits:
          memory: 512M
      readinessProbe:
        exec:
          command:
            - pg_isready
            - -U
            - $POSTGRES_USER
        initialDelaySeconds: 15
        periodSeconds: 5
      livenessProbe:
        exec:
          command:
            - pg_isready
            - -U
            - $POSTGRES_USER
        initialDelaySeconds: 45
        periodSeconds: 5
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: pg1-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: pg1
spec:
  type: ClusterIP
  ports:
    - port: 5432
      protocol: TCP
  selector:
    app: pg1

Connect to running postgres

kubectl exec -it pg1 psql -- -U pg1

Notes:

  • service is a headless so postgres will be accessible by hostname for other pods in same namespace but wont be accessible outside
  • do not forget to tune limits and change username
  • example with configuration file can be found here