Professional Documents
Culture Documents
Postgresql Sur La Solution Kubernetes Locale Minikube
Postgresql Sur La Solution Kubernetes Locale Minikube
Emmanuel RAMI
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.
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.
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.
Il conviendra de s’assurer que les CPU de notre instance acceptent la virtualisation. Passer les commandes ci après
ou
1 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
2 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
3 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
4 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.
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
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.
1 Downloading https://get.helm.sh/helm-v3.11.2-linux-amd64.tar.gz
2 Verifying checksum... Done.
3 Preparing to install helm into /usr/local/bin
helm installed into /usr/local/bin/helm
4
5
6
7
8
Installer ces binaires dans “/usr/local/bin”. Attention, par la suite, votre variable PATH doit contenir le chemin vers ce répertoire.
1 version.BuildInfo{
2 Version:"v3.11.2",
3 GitCommit:"912ebc1cd10d38d340f048efaf0abda047c3468e",
GitTreeState:"clean",
4
GoVersion:"go1.18.10"
5
}
6
7
1 {
2 "clientVersion": {
"major": "1",
3
"minor": "26",
4
5 "gitVersion": "v1.26.2",
6 "gitCommit": "fc04e732bb3e7198d2fa44efa5457c7c6f8c0f5b",
"gitTreeState": "clean",
7
"buildDate": "2023-02-22T13:39:03Z",
8
"goVersion": "go1.19.6",
9
"compiler": "gc",
10
"platform": "linux/amd64"
11 },
12 "kustomizeVersion": "v4.5.7"
13 }
14
15
Installation de 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”.
1 [manu@ ~]$ id
2 uid=1001(manu) gid=107(qemu) groups=107(qemu),986(libvirt) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
3
Une fois les packages installés il nous faut démarrer Minikube avec notre compte linux dédié.
3 ------------------------------------------------
4 default active yes yes
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.
4 bitnami/postgresql-ha 11.1.6 15.2.0 This PostgreSQL cluster solution includes the P...
Le repository bitnami nous propose la dernière version 15.2 de PostgreSQL. Nous allons l’installer pour notre environnement minikube.
2 NAME: postgres
12 PostgreSQL can be accessed via port 5432 on the following DNS names from within your cluster:
13 postgres-postgresql.default.svc.cluster.local - Read/Write connection
14 To get the password for "postgres" run:
15 export POSTGRES_PASSWORD=$(kubectl get secret --namespace default postgres-postgresql -o jsonpath="{.data.postgres-password}" | base64 -d)
16 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
17 --env="PGPASSWORD=$POSTGRES_PASSWORD" \
Vérifier son installation dans le cluster minikube et voir les différents services présents :
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.
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é.
Enregistrer cette valeur dans une variable que l’on peut nommer PGPASS par exemple.
1 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.
1 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
2
If you don't see a command prompt, try pressing enter.
3
postgres=
4
List of databases
5
Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace | Description
6 -----------+----------+----------+-------------+-------------+-----------------------+---------+------------+--------------------------------------------
7 postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7453 kB | pg_default | default administrative connection database
8 template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +| 7297 kB | pg_default | unmodifiable empty database
9 | | | | | postgres=CTc/postgres | | |
10 template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +| 7525 kB | pg_default | default template for new databases
11 | | | | | postgres=CTc/postgres | | |
12 (3 rows)
13 postgres=
14 version
---------------------------------------------------------------------------------------------------
15
16 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)
17
18
19
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
3 postgres-postgresql-0 1/1 Running 2 (25m ago) 24h 10.244.0.17 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 :
Vérifier:
3 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.
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.
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”.
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”.
1 apiVersion: v1
2 kind: ConfigMap
3 metadata:
4 name: pg-capdata
5 labels:
6 app: postgres
data:
7
POSTGRES_DB: capdb
8
POSTGRES_USER: capdata
9
POSTGRES_PASSWORD: passcapdata2023
10
Choisir un FileSystem dédié sur le serveur, et créer le répertoire pour accueillir l’instance PostgreSQL.
1 manu@ ~$ df -h /data
2 Filesystem Size Used Avail Use% Mounted on
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.
pg-data-pvc.yaml
1 apiVersion: v1
2 kind: PersistentVolume
3 metadata:
4 name: pg-data
5 labels:
6 type: local
7 app: postgres
spec:
8
storageClassName: manual
9
capacity:
10
storage: 8Gi
11
accessModes:
12
- ReadWriteMany
13
hostPath:
14
path: "/data/postgresql"
15
pg-data-pvc.yaml
1 apiVersion: v1
2 kind: PersistentVolumeClaim
3 metadata:
4 name: pg-data-claim
5 labels:
6 app: postgres
spec:
7
storageClassName: manual
8
accessModes:
9
- ReadWriteMany
10
resources:
11
requests:
12
storage: 8Gi
13
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.
1 apiVersion: apps/v1
2 kind: Deployment
3 metadata:
4 name: postgres
5 spec:
6 replicas: 2
selector:
7
matchLabels:
8
app: postgres
9
template:
10
metadata:
11
labels:
12
app: postgres
13 spec:
14 containers:
15 - name: postgres
16 image: postgres:15.2
17 imagePullPolicy: "IfNotPresent"
18 ports:
19 - containerPort: 5432
20 envFrom:
21 - configMapRef:
22 name: pg-capdata
23 volumeMounts:
24 - mountPath: /var/lib/postgresql/data
25 name: postgresdata
volumes:
26
- name: postgresdata
27
persistentVolumeClaim:
28
claimName: pg-data-claim
29
30
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.
2 deployment.apps/postgres-deploy created
Sur le node nommé “Minikube”, nous voyons donc tourner nos 2 répliquas PostgreSQL avec leurs IP en 10.244.0.***
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.
1 apiVersion: v1
2 kind: Service
3 metadata:
4 name: postgres-capdata
5 labels:
6 app: postgres
7 spec:
8 type: NodePort
9 ports:
10 - port: 5432
selector:
11
app: postgres
12
6
7
8
9
Connexion à PostgreSQL
Utiliser l’outil “kubectl” pour se connecter à l’instance PostgreSQL. Utiliser le compte préalablement défini, “capdata“, sur la base “capdb“.
1 manu@ ~$ kubectl exec -it postgres-66855ddfc5-drsqj -- psql -h localhost -U capdata --password -p 5432 capdb
2 Password:
3 psql (15.2 (Debian 15.2-1.pgdg110+1))
4 Type "help" for help.
5 capdb=
You are connected to database "capdb" as user "capdata" on host "localhost" (address "127.0.0.1") at port "5432".
6
capdb=
7
8
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 :
2 NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
4 default postgres-66855ddfc5-n9fc8 1/1 Running 1(17m ago) 17m 10.244.0.4 minikube none none
11 kube-system storage-provisioner 1/1 Running 1 (22m ago) 23m 192.168.39.227 minikube none none
La connexion via PSQL se fait donc sur cette IP. Valider la connexion sur la base “capdb”.
8 You are connected to database "capdb" as user "capdata" on host "192.168.39.227" at port "32581".
9 capdb=
10 List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace | Description
11
-----------+---------+----------+------------+------------+---------------------+---------+------------+--------------------------------------------
12
capdb | capdata | UTF8 | en_US.utf8 | en_US.utf8 | | 7453 kB | pg_default |
13
postgres | capdata | UTF8 | en_US.utf8 | en_US.utf8 | | 7453 kB | pg_default | default administrative connection database
14
template0 | capdata | UTF8 | en_US.utf8 | en_US.utf8 | =c/capdata +| 7297 kB | pg_default | unmodifiable empty database
15
| | | | | capdata=CTc/capdata | | |
16
template1 | capdata | UTF8 | en_US.utf8 | en_US.utf8 | =c/capdata +| 7525 kB | pg_default | default template for new databases
17
| | | | | capdata=CTc/capdata | | |
18 (4 rows)
19
20
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
2 The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
3
The database cluster will be initialized with locale "en_US.utf8".
4
The default database encoding has accordingly been set to "UTF8".
5
The default text search configuration will be set to "english".
6
Data page checksums are disabled.
7
fixing permissions on existing directory /var/lib/postgresql/data ... ok
8
creating subdirectories ... ok
9
selecting dynamic shared memory implementation ... posix
10 selecting default max_connections ... 100
11 selecting default shared_buffers ... 128MB
12 selecting default time zone ... Etc/UTC
13 creating configuration files ... ok
14 running bootstrap script ... ok
15 performing post-bootstrap initialization ... ok
Emmanuel RAMI.