0

PostgreSQL sur la solution Kubernetes locale Minikube

twitterlinkedinmail

Hello

Il y a quelques temps, je vous avais présenté un premier article sur l’installation d’une instance de base de données PostgreSQL sous Docker. C’est cet article qui nous a permis de mettre un premier pas dans le monde de la containerisation de services.

L’article d’aujourd’hui reprend les mêmes concepts, à savoir, comment installer et configurer PostgreSQL sous minikube et Kubernetes.

Présentation de l’environnement Kubernetes

Avant de présenter Minikube, il nous faut parler de Kubernetes.

Kubernetes est un outil d’orchestration de conteneurs. En d’autres termes, celui ci permet de gérer des déploiements d’applications directement via une plate forme open-source.
Pour le fonctionnement, il nous faut un environnement virtualisé avec l’hyperviseur qui communique avec les couches applicatives précompilées embarquant leurs librairies. Ce sont donc ces couches applicatives que l’on appelle containers et qui peuvent être utilisées sur des serveurs “on premise” ou dans un service Cloud.

C’est autour de ce concept que Minikube s’est créé. Cet outil utilise les fonctionnalités propres à Kubernetes mais assure un déploiement sur un noeud unique.

Il vous est donc possible de profiter d’un éco-système Kubernetes complet sur un simple PC de bureau (avec une configuration RAM/Cpu exigeante) .

L’objectif de cet article est donc de déployer une instance PostgreSQL sur Minikube.

Prérequis propres à AWS

Si, comme moi, vous utilisez des VMs EC2 AWS, il y a quelques informations à connaître.

Tout d’abord, il faut savoir que AWS met à disposition un service nommé EKS, Elastic Kubernetes Service, pour la gestion de clusters directement intégré dans AWS.
Il n’est donc pas nécessaire de configurer manuellement Kubernetes via des commandes “kubectl”. De plus les mises à jour des outils sont automatisées.

AWS met également à disposition AWS Fargate. Un service qui permet de configurer des containers, sans se soucier des types de serveurs à mettre à disposition. L’utilisateur de cette solution ne voit donc que le coté application, ses besoins en terme de scalabilité, et AWS fait le reste.

Mais pour notre article, comme nous souhaitons utiliser Minikube, il nous faut une VM supportant les exigences de la virtualisation. Or sous AWS, ce sont les instances EC2 de type “bare metal” qui répondent à ce besoin. Attention donc à regarder ce point, et surtout prendre en considération la partie facturation qui est loin d’être négligeable

Pour notre exemple, nous partirons sur une instance EC2 “c5.metal”. Ce type d’instance permet la virtualisation.

Les différentes étapes d’installation

Il conviendra de s’assurer que les CPU de notre instance acceptent la virtualisation. Passer les commandes ci après

# egrep -q 'vmx|svm' /proc/cpuinfo  "&&" echo yes || echo no
yes

ou

# grep -E "vmx|svm" /proc/cpuinfo
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l3 cdp_l3 invpcid_single intel_ppin ssbd mba ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid cqm mpx rdt_a avx512f avx512dq rdseed adx smap clflushopt clwb intel_pt avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts hwp hwp_act_window hwp_epp hwp_pkg_req pku ospke avx512_vnni md_clear flush_l1d arch_capabilities
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l3 cdp_l3 invpcid_single intel_ppin ssbd mba ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid cqm mpx rdt_a avx512f avx512dq rdseed adx smap clflushopt clwb intel_pt avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts hwp hwp_act_window hwp_epp hwp_pkg_req pku ospke avx512_vnni md_clear flush_l1d arch_capabilities
.........

Le système d’exploitation choisi pour ce serveur est un Rocky Linux 8.7 , un fork Red Hat avec lequel nous pourrons gérer nos packages d’installation via yum.
Plusieurs packages sont à intégrer afin de faire fonctionner notre cluster mono nœud.

Installer la couche KVM

Afin de pouvoir installer Minikube, il nous faut un gestionnaire de container.
Pour l’article propre à Docker, nous avions utilisé le Docker Engine, qui a la particularité de pouvoir se passer de la partie Virtualisation et d’hyperviseur.

Pour notre exemple, l’idée est d’utiliser KVM (Kernel-linux Virtual Machine), qui nécessite une virtualisation active.
Installer les packages suivants sur le serveur

# yum update
# yum install qemu-kvm libvirt libguestfs-tools virt-install

 

La librairie de virtualisation doit être activée et le service démarré automatiquement

# systemctl enable libvirtd.service
# systemctl start libvirtd.service

Installer helm et kubectl

Ces outils sont nécessaires à l’administration de notre cluster, et l’installation d’applications. Helm nous sert à installer PostgreSQL depuis un repository, et kubectl est un interpréteur de commandes pour  notre cluster.

# curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 138 100 138 0 0 1179 0 --:--:-- --:--:-- --:--:-- 1179
100 45.8M 100 45.8M 0 0 70.1M 0 --:--:-- --:--:-- --:--:-- 117M
# curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3

# chmod 700 get_helm.sh
# ./get_helm.sh
Downloading https://get.helm.sh/helm-v3.11.2-linux-amd64.tar.gz
Verifying checksum... Done.
Preparing to install helm into /usr/local/bin
helm installed into /usr/local/bin/helm

Installer ces binaires dans “/usr/local/bin”. Attention, par la suite, votre variable PATH doit contenir le chemin vers ce répertoire.

# install kubectl /usr/local/bin/kubectl
# install helm /usr/local/bin/helm
# chmod 755 /usr/local/bin/helm
# chmod 755 /usr/local/bin/kubectl

Valider l’installation de helm et kubectl.

 # helm version
version.BuildInfo{
Version:"v3.11.2", 
GitCommit:"912ebc1cd10d38d340f048efaf0abda047c3468e", 
GitTreeState:"clean", 
GoVersion:"go1.18.10"
}
# kubectl version -o json
{
"clientVersion": {
"major": "1",
"minor": "26",
"gitVersion": "v1.26.2",
"gitCommit": "fc04e732bb3e7198d2fa44efa5457c7c6f8c0f5b",
"gitTreeState": "clean",
"buildDate": "2023-02-22T13:39:03Z",
"goVersion": "go1.19.6",
"compiler": "gc",
"platform": "linux/amd64"
},
"kustomizeVersion": "v4.5.7"
}

Installation de minikube

Télécharger et installer le binaire Minikube, puis le placer dans le répertoire “/usr/local/bin”.

# curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
# install minikube-linux-amd64 /usr/local/bin/minikube

Attention, minikube doit fonctionner avec un utilisateur linux dédié, autre que “root”. Il convient donc de créer un utilisateur appartenant aux 2 groupes “libvirt” et “qemu”.

# useradd -u 1001 -g qemu -G qemu,libvirt manu
# passwd manu

Se connecter avec ce nouvel utilisateur et vérifier ses groupes.

# su - manu
[manu@ ~]$ id
uid=1001(manu) gid=107(qemu) groups=107(qemu),986(libvirt) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

Gestion du cluster Minikube

Une fois les packages installés il nous faut démarrer Minikube avec notre compte linux dédié.

manu@~$ minikube start --driver=kvm2
* minikube v1.29.0 on Rocky 8.7
* Using the kvm2 driver based on user configuration
* Downloading driver docker-machine-driver-kvm2:
 docker-machine-driver-kvm2-...: 65 B / 65 B [---------] 100.00% ? p/s 0s
 docker-machine-driver-kvm2-...: 12.30 MiB / 12.30 MiB 100.00% 13.05 MiB
* Downloading VM boot image ...
 minikube-v1.29.0-amd64.iso....: 65 B / 65 B [---------] 100.00% ? p/s 0s
 minikube-v1.29.0-amd64.iso: 276.35 MiB / 276.35 MiB 100.00% 167.79 MiB
* Starting control plane node minikube in cluster minikube
* Downloading Kubernetes v1.26.1 preload ...
 preloaded-images-k8s-v18-v1...: 397.05 MiB / 397.05 MiB 100.00% 111.49
* Creating kvm2 VM (CPUs=2, Memory=6000MB, Disk=20000MB) ...
* Preparing Kubernetes v1.26.1 on Docker 20.10.23 ...
- Generating certificates and keys ...
- Booting up control plane ...
- Configuring RBAC rules ...
* Configuring bridge CNI (Container Networking Interface) ...
- Using image gcr.io/k8s-minikube/storage-provisioner:v5
* Verifying Kubernetes components...
* Enabled addons: storage-provisioner, default-storageclass
* Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

Au premier démarrage, Minikube cherche  les différentes images dont il a besoin.
Le démarrage suivant donnera ce résultat :

 manu@~$ minikube start
* minikube v1.29.0 on Rocky 8.7
* Using the kvm2 driver based on existing profile
* Starting control plane node minikube in cluster minikube
* Restarting existing kvm2 VM for "minikube" ...
* Preparing Kubernetes v1.26.1 on Docker 20.10.23 ...
* Configuring bridge CNI (Container Networking Interface) ...
* Verifying Kubernetes components...
- Using image gcr.io/k8s-minikube/storage-provisioner:v5
- Using image docker.io/kubernetesui/dashboard:v2.7.0
- Using image docker.io/kubernetesui/metrics-scraper:v1.0.8
* Some dashboard features require the metrics-server addon. To enable all features please run:

minikube addons enable metrics-server


* Enabled addons: storage-provisioner, dashboard, default-storageclass
* Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

Minikube est maintenant actif sur notre serveur.

Vérifier l’état de la couche virtualisation.

 manu@~ $ sudo virsh net-list --all
Name        State  Autostart Persistent
------------------------------------------------
default     active yes       yes
mk-minikube active yes       yes

Valider notre cluster avec “kubctl”

 manu@~$ kubectl get nodes
NAME      STATUS ROLES         AGE  VERSION
minikube  Ready  control-plane 35m  v1.26.1

Pour arrêter le cluster

 manu@~$ minikube stop
* Stopping node "minikube" ...
* 1 node stopped.

Déploiement générique de PostgreSQL sur Minikube

L’outil helm permet de déployer simplement une instance PostgreSQL sur notre cluster mono-nœud Minikube.
Pour cela, utilisons le repository “bitnami” via le site : https://charts.bitnami.com/bitnami.

Le fonctionnement s’apparente “un peu” à yum pour un système RedHat, il s’agit d’une source vers laquelle chercher pour enregistrer des applications à containeriser.

manu@ ~$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories

Une fois le repository initier, vérifier les versions PostgreSQL disponibles.

 manu@~ $ helm search repo postgres
NAME                         CHART VERSION   APP VERSION            DESCRIPTION
bitnami/postgresql           12.2.5          15.2.0                 PostgreSQL (Postgres) is an open source object-...
bitnami/postgresql-ha        11.1.6          15.2.0                 This PostgreSQL cluster solution includes the P...
bitnami/supabase             0.1.4           0.23.2                 Supabase is an open source Firebase alternative...

Le repository bitnami nous propose la dernière version 15.2 de PostgreSQL. Nous allons l’installer pour notre environnement minikube.

 manu@~ $ helm install postgres bitnami/postgresql
NAME: postgres
LAST DEPLOYED: Mon Mar 20 15:41:00 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: postgresql
CHART VERSION: 12.2.5
APP VERSION: 15.2.0

** Please be patient while the chart is being deployed **

PostgreSQL can be accessed via port 5432 on the following DNS names from within your cluster:

postgres-postgresql.default.svc.cluster.local - Read/Write connection

To get the password for "postgres" run:

export POSTGRES_PASSWORD=$(kubectl get secret --namespace default postgres-postgresql -o jsonpath="{.data.postgres-password}" | base64 -d)

To connect to your database run the following command:

kubectl run postgres-postgresql-client --rm --tty -i --restart='Never' --namespace default --image docker.io/bitnami/postgresql:15.2.0-debian-11-r13 --env="PGPASSWORD=$POSTGRES_PASSWORD" \
--command -- psql --host postgres-postgresql -U postgres -d postgres -p 5432

 NOTE: If you access the container using bash, make sure that you execute "/opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash" in order to avoid the error "psql: local user with ID 1001} does not exist"

To connect to your database from outside the cluster execute the following commands:

kubectl port-forward --namespace default svc/postgres-postgresql 5432:5432 "&" PGPASSWORD="$POSTGRES_PASSWORD" psql --host 127.0.0.1 -U postgres -d postgres -p 5432

WARNING: The configured password will be ignored on new installation in case when previous Posgresql release was deleted through the helm command. In that case, old PVC will have an old password, and setting it through helm won't take effect. Deleting persistent volumes (PVs) will solve the issue.

Vérifier le déploiement dans le repository

 manu@~ $ helm list
NAME     NAMESPACE REVISION UPDATED                                 STATUS   CHART             APP VERSION
postgres default   1        2023-03-20 15:41:00.677760646 +0000 UTC deployed postgresql-12.2.5 15.2.0

Notre application containerisée PostgreSQL est bien déployée dans le repository.

Vérifier son installation dans le cluster minikube et voir les différents services présents :

 manu@~ $ kubectl get deployment,pods,svc
NAME                                                READY STATUS  RESTARTS AGE
pod/postgres-postgresql-0                           1/1   Running 0        18m

NAME                           TYPE       CLUSTER-IP    EXTERNAL-IP  PORT(S)  AGE
service/kubernetes             ClusterIP  10.96.0.1     none         443/TCP  36m
service/postgres-postgresql    ClusterIP  10.109.83.132 none         5432/TCP 18m
service/postgres-postgresql-hl ClusterIP  None          none         5432/TCP 18m

Nous remarquons que notre application PostgreSQL est enregistrée sous l’adresse IP  10.109.83.132. Le port de communication est 5432.
C’est cette adresse qui sera référencée comme VIP pour notre cluster.

Connexion à l’instance PostgreSQL

Lors de l’installation, les instructions de connexion nous ont été données (notamment la gestion du password de connexion).

Pour retrouver le password postgres, c’est l’outil “kubectl” qui est appelé.

 manu@~ $ kubectl get secret --namespace default postgres-postgresql -o jsonpath="{.data.postgres-password}" | base64 -d
HvbCO9Co5R

Enregistrer cette valeur dans une variable que l’on peut nommer PGPASS par exemple.

 manu@~$ export PGPASS=$(kubectl get secret --namespace default postgres-postgresql -o jsonpath="{.data.postgres-password}" | base64 --decode)

Lancer la commande, indiquée lors de l’installation de PostgreSQL avec “helm”, pour se connecter à l’instance.

 manu@~$ kubectl run postgres-postgresql-client --rm --tty -i --restart='Never' --namespace default --image docker.io/bitnami/postgresql:15.2.0-debian-11-r13 --env="PGPASSWORD=$PGPASS" --command -- psql --host postgres-postgresql -U postgres -d postgres -p 5432
If you don't see a command prompt, try pressing enter.

postgres=# \l+
                                                     List of databases
Name       | Owner    | Encoding | Collate     | Ctype       | Access privileges     | Size    | Tablespace | Description
-----------+----------+----------+-------------+-------------+-----------------------+---------+------------+--------------------------------------------
postgres   | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |                       | 7453 kB | pg_default | default administrative connection database
template0  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +| 7297 kB | pg_default | unmodifiable empty database
           |          |          |             |             | postgres=CTc/postgres |         |            |
template1  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +| 7525 kB | pg_default | default template for new databases
           |          |          |             |             | postgres=CTc/postgres |         |            |
(3 rows)

postgres=# select version();
version
---------------------------------------------------------------------------------------------------
PostgreSQL 15.2 on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
(1 row)

Pour se connecter à cette instance PostgreSQL, nous avons lancé une application “PostgreSQL cliente” déployée à partir d’une image Docker ‘docker.io/bitnami/postgresql:15.2.0-debian-11-r13’  en PostgreSQL version 15.2 compilée sous un Debian 11.13. Cette application une fois déployée, nous permet d’exécuter l’outil “psql” pour se connecter.

A noter qu’à la première exécution, cette image est enregistrée dans le node minikube

 manu@ ~$ kubectl get pods -o wide
NAME                        READY  STATUS    RESTARTS    AGE IP          NODE     NOMINATED NODE READINESS GATES
postgres-postgresql-0       1/1    Running   2 (25m ago) 24h 10.244.0.17 minikube none      none 
postgres-postgresql-client  0/1    Completed 0           16m 10.244.0.19 minikube none      none 

Repérer le pod “postgres-postgresql-client”, le status est à “completed” car nous n’avons plus de connexion active. D’ailleurs, le “READY” est à 0/1 car aucune connexion.
Il est tout à fait possible de retirer cette application publiée dans les pods de minikube. Pour cela, lancer la commande :

 manu@ ~$ kubectl delete pod postgres-postgresql-client
pod "postgres-postgresql-client" deleted

Vérifier:

 manu@ ~$ kubectl get pods -o wide
NAME                   READY STATUS   RESTARTS    AGE IP           NODE      NOMINATED NODE READINESS GATES
postgres-postgresql-0  1/1   Running  2 (25m ago) 24h 10.244.0.17  minikube  none           none

 

Nous venons donc d’installer une instance PostgreSQL par défaut grâce à l’outil helm dans notre cluster Minikube.

Configuration d’instance et volume persisté sur Minikube

Afin de pouvoir conserver vos données sur disque, il est possible de monter une instance PostgreSQL avec, ce que l’on appelle, un “volume persisté”.
Il faut, pour cela, dédier un FileSystem pour les données PostgreSQL sur la VM locale exécutant Minikube.

De plus,  PostgreSQL peut être créé avec des valeurs de configuration différentes que ce qui est proposé avec l’outil helm.

L’intérêt est de monter une instance pré-configurée, pour une application métier, dès le démarrage.

Les fichiers YAML

Pour le déploiement d’une instance PostgreSQL spécifique, nous devons utiliser des fichiers de configuration “yaml” que nous chargerons dans le cluster via “kubectl”.

fichier YAML de configuration d’instance

Un fichier “configmap” doit être créé si l’on souhaite spécifier des informations sur les credentials (user/password), et/ou base de données métier.

Utiliser pour cela le fichier yaml suivant pour créer un utilisateur “capdata“, avec une base “capddb” pour l’application “postgres”.

apiVersion: v1
kind: ConfigMap
metadata:
  name: pg-capdata
  labels:
  app: postgres
data:
  POSTGRES_DB: capdb
  POSTGRES_USER: capdata
  POSTGRES_PASSWORD: passcapdata2023

Appliquer ce fichier à votre configuration Kubernenetes Minikube, puis valider celle ci

manu@~$ kubectl apply -f pg-configmap.yaml
configmap/pg-capdata created

manu@ ~$ kubectl get configmap
NAME              DATA AGE
kube-root-ca.crt  1    3d23h
pg-capdata        3    4s

fichier YAML pour les volumes

Choisir un FileSystem dédié sur le serveur, et créer le répertoire pour accueillir l’instance PostgreSQL.

manu@ ~$ df -h /data
Filesystem     Size Used Avail Use% Mounted on
/dev/nvme1n1p1 19G  28K  18G   1%   /data

manu@ ~$ mkdir -p /data/postgresql

Nous aurons besoin de 2 fichiers yaml pour la configuration des volumes, 1 pour le volume persisté qui nous permet de conserver nos données d’instance durant le cycle de vie de celle ci. De plus, il nous faut, ce que l’on appelle, un “Persistent Volume Claim”. C’est une vue logique du volume géré par le cluster Kubernetes.

Les 2 fichiers contiennent les entrées suivantes :

pg-data-pvc.yaml

apiVersion: v1
kind: PersistentVolume 
metadata:
  name: pg-data 
  labels:
    type: local 
    app: postgres
spec:
  storageClassName: manual
  capacity:
    storage: 8Gi 
  accessModes:
    - ReadWriteMany
  hostPath:
    path: "/data/postgresql" 

pg-data-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim 
metadata:
  name: pg-data-claim
  labels:
    app: postgres 
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteMany
  resources:
    requests:
     storage: 8Gi

Charger ces 2 fichiers yaml dans Kubernetes.

manu@ ~$ kubectl apply -f pg-data.yaml

manu@ ~$ kubectl apply -f pg-data-pvc.yaml

Vérifier les informations dans le cluster

manu@ ~$ kubectl get pv -o wide
NAME     CAPACITY     ACCESS MODES     RECLAIM POLICY STATUS  CLAIM STORAGECLASS     REASON  AGE    VOLUMEMODE
pg-data  8Gi          RWX              Retain         Bound   default/pg-data-claim  manual  2m50s  Filesystem


manu@ ~$ kubectl get pvc -o wide
NAME                  STATUS  VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS  AGE   VOLUMEMODE
pg-data-claim         Bound   pg-data  8Gi        RWX            manual        94s   Filesystem

Fichier YAML de déploiement

Après avoir déclarer la configuration, les volumes, nous pouvons déployer l’instance dans le cluster Kubernetes. Par exemple, nous déclarons 2 répliquas d’une instance PostgreSQL 15.2, écoutant sur le port 5432.

apiVersion: apps/v1
kind: Deployment 
metadata:
  name: postgres
spec:
  replicas: 2 
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
   spec:
      containers:
        - name: postgres
          image: postgres:15.2 
          imagePullPolicy: "IfNotPresent"
          ports:
            - containerPort: 5432
          envFrom:
            - configMapRef:
               name: pg-capdata 
          volumeMounts:
            - mountPath: /var/lib/postgresql/data
               name: postgresdata
       volumes:
        - name: postgresdata
            persistentVolumeClaim:
              claimName: pg-data-claim

Appliquer ce fichier yaml et vérifier que le status “Running” apparaisse sur les 2 répliquas PostgreSQL. On appelle “pod” sur Kubernetes, un container applicatif avec ses librairies embarquées.

manu@ ~$ kubectl apply -f pg-deploiement.yaml
deployment.apps/postgres-deploy created

manu@ ~$ kubectl get pods,deployments -o wide
NAME                             READY   STATUS   RESTARTS    AGE    IP            NODE      NOMINATED NODE   READINESS GATES
pod/postgres-66855ddfc5-drsqj    1/1     Running  0           83s    10.244.0.3    minikube  none             none           
pod/postgres-66855ddfc5-n9fc8    1/1     Running  1 (71s ago) 83s    10.244.0.4    minikube  none             none


NAME                       READY   UP-TO-DATE   AVAILABLE     AGE  CONTAINERS    IMAGES         SELECTOR
deployment.apps/postgres   2/2     2            2             83s  postgres      postgres:15.2  app=postgres

Sur le node nommé “Minikube”, nous voyons donc tourner nos 2 répliquas PostgreSQL avec leurs IP en 10.244.0.***

Fichier yaml de service PostgreSQL

Afin de pouvoir se connecter à notre instance PostgreSQL, il faut lui définir un service. C’est une sorte de porte d’entrée pour accéder à notre instance.

apiVersion: v1
kind: Service
metadata:
  name: postgres-capdata
  labels:
   app: postgres 
spec:
   type: NodePort 
  ports:
   - port: 5432
  selector:
    app: postgres

Appliquer ce fichier yaml sur le cluster.

manu@ ~$ kubectl apply -f pg-service.yaml service/postgres-capdata created[/yaml]




manu@ ~$ kubectl get svc -o wide
NAME              TYPE          CLUSTER-IP    EXTERNAL-IP            PORT(S)         AGE   SELECTOR
kubernetes        ClusterIP     10.96.0.1     none                   443/TCP          16d  none
postgres          NodePort      10.110.166.18 none                   5432:32581/TCP  6m48s app=postgres

Connexion à PostgreSQL

2 méthodes pour nous connecter à l’instance PostgreSQL s’offrent à nous.

  • Connexion via Kubernetes

Utiliser l’outil “kubectl” pour se connecter à l’instance PostgreSQL. Utiliser le compte préalablement défini, “capdata“, sur la base “capdb“.

 manu@ ~$ kubectl exec -it postgres-66855ddfc5-drsqj -- psql -h localhost -U capdata --password -p 5432 capdb
Password:
psql (15.2 (Debian 15.2-1.pgdg110+1))
Type "help" for help.

capdb=# \conninfo
You are connected to database "capdb" as user "capdata" on host "localhost" (address "127.0.0.1") at port "5432".
capdb=#
  • Connexion via un client PostgreSQL local à la VM.

Sur notre VM Rocky Linux, nous disposons d’une vieille version de “psql” que nous pouvons utiliser pour la connexion (version 10 de PostgreSQL).

Repérer auparavant, la valeur du port de sortie que nous avions trouvé lorsque nous avons passé la commande “kubectl get svc -o wide”.

Pour notre service dédié à postgreSQL, nous avons comme port “5432:32581”. Le 5432 est le port d’écoute local à Kubernetes. Pour accèder depuis notre VM, c’est le port 32581 dont nous aurons besoin.

De plus, l’IP de notre cluster Kubernetes, doit être connue. Pour cela , exécuter cette commande :

 manu@ip-172-44-3-198 ~]$ kubectl get pods --all-namespaces -o wide
NAMESPACE    NAME                              READY STATUS   RESTARTS    AGE   IP              NODE      NOMINATED NODE READINESS GATES
default      postgres-66855ddfc5-drsqj         1/1   Running  0           17m   10.244.0.3      minikube  none           none
default      postgres-66855ddfc5-n9fc8         1/1   Running  1(17m ago)  17m   10.244.0.4      minikube  none           none
kube-system  coredns-787d4945fb-87kzd          1/1   Running  0           23m   10.244.0.2      minikube  none           none
kube-system  etcd-minikube                     1/1   Running  0           23m   192.168.39.227  minikube  none           none
kube-system  kube-apiserver-minikube           1/1   Running  0           23m   192.168.39.227  minikube  none           none 
kube-system  kube-controller-manager-minikube  1/1   Running  0           23m   192.168.39.227  minikube  none           none
kube-system  kube-proxy-lptq2                  1/1   Running  0           23m   192.168.39.227  minikube  none           none
kube-system  kube-scheduler-minikube           1/1   Running  0           23m   192.168.39.227  minikube  none           none
kube-system  storage-provisioner               1/1   Running  1 (22m ago) 23m   192.168.39.227  minikube  none           none

L’IP du cluster Kubernetes est 192.168.39.227.

La connexion via PSQL se fait donc sur cette IP. Valider la connexion sur la base “capdb”.

manu@ ~$ psql -h 192.168.39.227 -U capdata -p 32581 capdb
Password for user capdata:
psql (10.23, server 15.2 (Debian 15.2-1.pgdg110+1))
WARNING: psql major version 10, server major version 15.
Some psql features might not work.
Type "help" for help.

capdb=# \conninfo
You are connected to database "capdb" as user "capdata" on host "192.168.39.227" at port "32581".
capdb=# \l+
List of databases
Name       | Owner   | Encoding | Collate    | Ctype      | Access privileges   | Size    | Tablespace | Description
-----------+---------+----------+------------+------------+---------------------+---------+------------+--------------------------------------------
capdb      | capdata | UTF8     | en_US.utf8 | en_US.utf8 |                     | 7453 kB | pg_default |
postgres   | capdata | UTF8     | en_US.utf8 | en_US.utf8 |                     | 7453 kB | pg_default | default administrative connection database
template0  | capdata | UTF8     | en_US.utf8 | en_US.utf8 |         =c/capdata +| 7297 kB | pg_default | unmodifiable empty database
           |         |          |            |            | capdata=CTc/capdata |         |            |
template1  | capdata | UTF8     | en_US.utf8 | en_US.utf8 |         =c/capdata +| 7525 kB | pg_default | default template for new databases
           |         |          |            |            | capdata=CTc/capdata |         |            |
(4 rows)

Le compte “capdata” que nous avons inscrit dans le fichier configmap est owner pour toutes les bases de cette instance.

 

Les logs

Il est possible d’aller regarder les logs de nos “pods” déployés sur Kubernetes.
Pour cela choisir la commande “kubectl logs”.

Par exemple, lancer cette commande sur 1 des répliquas PostgreSQL du cluster, et vous avec accès en lecture au fichier “postgresql.log” de l’instance

 manu@ ~$ kubectl logs pod/postgres-66855ddfc5-drsqj
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.

fixing permissions on existing directory /var/lib/postgresql/data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... Etc/UTC
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

initdb: warning: enabling "trust" authentication for local connections
initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb.

Success. You can now start the database server using:

pg_ctl -D /var/lib/postgresql/data -l logfile start

pg_ctl: another server might be running; trying to start server anyway
waiting for server to start....2023-03-27 09:30:32.071 UTC [48] LOG: starting PostgreSQL 15.2 (Debian 15.2-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
2023-03-27 09:30:32.075 UTC [48] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2023-03-27 09:30:32.087 UTC [51] LOG: database system was interrupted; last known up at 2023-03-27 09:30:32 UTC
2023-03-27 09:30:32.110 UTC [51] LOG: database system was not properly shut down; automatic recovery in progress
2023-03-27 09:30:32.113 UTC [51] LOG: invalid record length at 0/14FE0E0: wanted 24, got 0
2023-03-27 09:30:32.113 UTC [51] LOG: redo is not required
2023-03-27 09:30:32.118 UTC [49] LOG: checkpoint starting: end-of-recovery immediate wait
2023-03-27 09:30:32.140 UTC [49] LOG: checkpoint complete: wrote 3 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.006 s, sync=0.003 s, total=0.024 s; sync files=2, longest=0.002 s, average=0.002 s; distance=0 kB, estimate=0 kB
2023-03-27 09:30:32.144 UTC [48] LOG: database system is ready to accept connections
done
server started
CREATE DATABASE

/usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*

2023-03-27 09:30:32.262 UTC [48] LOG: received fast shutdown request
waiting for server to shut down....2023-03-27 09:30:32.266 UTC [48] LOG: aborting any active transactions
2023-03-27 09:30:32.268 UTC [48] LOG: background worker "logical replication launcher" (PID 54) exited with exit code 1
2023-03-27 09:30:32.268 UTC [49] LOG: shutting down
2023-03-27 09:30:32.271 UTC [49] LOG: checkpoint starting: shutdown immediate
2023-03-27 09:30:32.341 UTC [49] LOG: checkpoint complete: wrote 916 buffers (5.6%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.013 s, sync=0.045 s, total=0.073 s; sync files=249, longest=0.036 s, average=0.001 s; distance=4217 kB, estimate=4217 kB
2023-03-27 09:30:32.345 UTC [48] LOG: database system is shut down
done
server stopped

PostgreSQL init process complete; ready for start up.

2023-03-27 09:30:32.384 UTC [1] LOG: starting PostgreSQL 15.2 (Debian 15.2-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
2023-03-27 09:30:32.385 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
2023-03-27 09:30:32.385 UTC [1] LOG: listening on IPv6 address "::", port 5432
2023-03-27 09:30:32.392 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2023-03-27 09:30:32.401 UTC [64] LOG: database system was shut down at 2023-03-27 09:30:32 UTC
2023-03-27 09:30:32.406 UTC [1] LOG: database system is ready to accept connections

Nous obtenons les informations de la création de l’instance jusqu’au dernier démarrage.

N’hésitez pas à laisser un message !

Emmanuel RAMI.

Continuez votre lecture sur le blog :

twitterlinkedinmail

Emmanuel RAMI

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.