Google Cloud Platform : Déployer Magento 2 dans Kubernetes
Cet article est une base de travail qui vous permettra de déployer Magento 2 au sein de Kubernetes et de Google Kubernetes Engine. L'objectif de cet article et de vous permettre d'avoir une base pour le déploiement de Magento 2 avec sa base de données managée sous MySQL 8.0, Elasticsearch, PHP-FPM et Nginx. À partir de cet article, il sera possible de déployer RabbitMQ, Redis...
Premiers pas
Avant de commencer, il faut installer Gcloud, Kubectl, Terraform et Kustomize sur son poste.
Je recommande l'utilisation d'un système Linux (VM, natif ou WSL) et d'installer :
- Le SDK Google Cloud : Lien vers la documentation d'installation.
- Kubectl : Lien vers la documentation d'installation.
- Terraform : Lien vers la page de téléchargement.
- Kustomize : Lien vers la documentation d'installation.
Préparation du projet
Se connecter à GCloud
Lancer gcloud init
Il vous sera demandé de vous connecter, pour cela, il faut ouvrir le lien dans votre navigateur, choisir votre compte Google. Puis, sélectionner un projet ou lancer la création d'un nouveau projet.
Vérifier que vous êtes bien connecté en lançant la commande : gcloud auth list
.
Création d'un projet GCloud
Pour créer un projet, vous pouvez lancer la commande : gcloud projects create magento2-testing --name="Magento 2 Testing"
.
Puis vous devez sélectionner le projet, en lançant la commande : gcloud config set project magento2-testing
.
Vous pouvez ensuite contrôler par le biais de la commande : gcloud info
.
Création d'un Service Account
Pour utiliser GCP avec Terraform, il faut créer un Service Account dans Google Cloud au sein de votre projet : gcloud iam service-accounts create terraform --description="Service Account for Terraform" --display-name="Terraform SA"
.
Récupérer la clé JSON en lançant la commande : gcloud iam service-accounts keys create ~/sa-private-key.json --iam-account="[email protected]"
.
Associer un compte de facturation
Afin de pouvoir déployer un service dans GCloud, il est impératif d'associer un compte de facturation au projet que nous avons créé. Pour cela, je vous invite à consulter cette documentation.
Création de l'environnement local
Dans votre ordinateur, créer le dossier magento2-testing
et son dossier enfant terraform
. Ce dernier servira à stocker l'ensemble des fichiers qui nous permettront de déployer une boutique Magento 2 dans un Cluster Kubernetes.
Au sein de ce dossier, vous pouvez créer 3 fichiers :
- main.tf
- outputs.tf
- variables.tf
Le fichier main.tf
contiendra l'ensemble de nos directives ou de notre configuration nécessaire au déploiement de l'infrastructure.
Le fichier outputs.tf
contiendra les déclarations permettant d'afficher des données qui pourront être réutilisées, notamment lorsque l'on utilise des modules.
Le fichier variables.tf
contiendra les variables qui personnaliseront l'infrastructure.
Création d'un workspace
Si vous le souhaitez, sachez qu'il est possible de créer des environnements de travail au sein du dossier. Voici quelques commandes qui vous seront utiles :
- Lister les environnements : terraform workspace list
- Sélectionner un environnement : terraform workspace select
name
- Créer un nouvel environnement : terraform workspace new
name
Initialisation du projet
Importation du provider
Pour déployer notre application, nous avons besoin du provider Google
. Pour cela, nous allons ajouter dans le fichier main.tf
le contenu ci-dessous :
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "3.72.0"
}
}
}
provider "google" {
credentials = file(~./sa-private-key.json)
project = "magento2-testing"
region = "europe-west1"
}
Le premier bloc permet d'indiquer à Terraform que l'on souhaite utiliser le provider google
. Puis le second bloc permet de s'authentifier auprès de Google.
Les paramètres credentials
, project
correspondent aux valeurs que nous avons renseignées lors de l'utilisation des commandes gcloud
.
J'ai rencontré quelques problèmes de droits en utilisant le compte de service. J'ai pu le contourner, en lançant la commande : gcloud auth application-default login
et en remplaçant, dans le fichier main.tf
le provider par data "google_client_config" "provider" {}
.
Une fois renseigné, il faut lancer la commande terraform init
qui va procéder au téléchargement du provider Google dans le dossier .terraform
situé à la racine de notre projet. Un fichier nommé .terraform.lock.hcl
est également créé.
Lien vers la documentation du provider google
.
Déploiement de l'infrastructure
Réservation d'une IP globale
Lors de la création d'un load balancer, Google va lui assigner une adresse IP externe éphémère. Nous allons préférer utiliser une adresse IP statique, pour cela, la commande GCloud est gcloud compute addresses create magento-frontend --project=magento2-testing --global
.
Dans Terraform, il faut utiliser la ressource google_compute_global_address
:
### Reserve Static IP
resource "google_compute_global_address" "magento_static_ip" {
name = "magento-frontend"
project = var.project_id
}
Vous pouvez ajouter, dans le fichier outputs.tf
, la valeur de l'adresse IP qui sera réservée avec la directive :
output "magento_frontend_static_ip" {
value = google_compute_global_address.magento_static_ip.address
}
Avant d'appliquer nos changements, nous pouvons vérifier les actions qui seront réalisées par Terraform, pour ce faire, il faut lancer la commande terraform plan
.
A ce moment, Terraform nous indique qu'il procèdera à la création d'une ressource. Pour appliquer nos changements, il faut exécuter la commande terraform apply
.
Pour réaliser la création de l'IP statique via Terraform, le compte de service, ou Service Account, doit être autorisé. Pour cela, il faut vous rendre dans la page IAM de votre projet et ajouter le rôle Administrateur d'adresse IP publique Compute
au compte de service Terraform
.
Création des variables
Avant de procéder à la création du cluster, nous allons définir quelques variables dans le fichier variables.tf
:
variable "project_id" {
type = string
default = "magento2-testing"
}
variable "region" {
type = string
default = "europe-west1"
}
variable "cluster_name" {
type = string
default = "gke-europe-west1"
}
Puis, nous allons remplacer, dans le fichier main.tf
, les valeurs project
et region
par var.project_id
et var.region
. Votre fichier main.tf
doit avoir le résultat suivant :
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "3.72.0"
}
}
}
provider "google" {
credentials = file(~./sa-private-key.json)
project = var.project_id
}
### Reserve Static IP
resource "google_compute_global_address" "magento_static_ip" {
name = "magento-frontend"
project = var.project_id
}
Création du cluster Kubernetes
Avant de procéder à la création du cluster, il est nécessaire d'activer le service Kubernetes Engine API
via la commande gcloud services enable container.googleapis.com
. De plus les rôles Administrateur de Compute
et Administrateur de Kubernetes Engine
doivent être assignés à votre compte de service.
La resource google_container_cluster
permet de créer un cluster dans Google Cloud Platform. Ajouter le bloc ci-dessous dans le fichier main.tf
:
### Create Kubernetes Cluster
resource "google_container_cluster" "magento_cluster" {
name = var.cluster_name
project = var.project_id
location = var.region
remove_default_node_pool = true
initial_node_count = 1
}
Dans Google Cloud, un cluster Kubernetes ne peut pas être créé sans un ensemble de noeuds, ou node pool. Pour ce faire, nous utilisons la directive remove_default_node_pool
. La directive initial_node_count
permet de définir le nombre de noeuds à créer. Appliquer les modifications et patientez quelques minutes car la création d'un cluster Kubernetes n'est pas instantanée.
Création d'un ensemble de noeuds
La resource google_container_node_pool
va nous permettre de créer un ensemble de noeuds au sein de notre cluster. Ajouter le bloc ci-dessous dans le fichier main.tf
:
### Create Kubernetes Node Pool
resource "google_container_node_pool" "magento_preemptible_nodes" {
name = "magento-preemptible-nodes"
project = var.project_id
location = var.region
cluster = google_container_cluster.magento_cluster.name
node_count = 1
node_config {
preemptible = true
machine_type = "e2-standard-4"
disk_size_gb = "100"
disk_type = "pd-ssd"
image_type = "cos"
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform"
]
}
}
En appliquant les changements ci-dessus, Terraform va demander la création de 3 noeuds, répartis dans chaque zone de la région europe-west1
. Nous indiquons également que l'ensemble de noeuds doit être créé dans le cluster que nous avons créé précédemment. Nous récupérons le nom de la ressource magento_cluster
par le biais de la directive google_container_cluster.magento_cluster.name
.
Chaque noeud sera composé de machine e2-standard-4
, soit 4 vCPUs et 16 Go de RAM par machine et avec des disques SSD de 100 Go chacun.
Déploiement du projet
Pour utiliser Kustomize
et kubectl
, il faut être authentifié auprès du cluster, pour ce faire, lancer la commande gcloud container clusters get-credentials gke-europe-west1 --region europe-west1 --project magento2-testing
.
Installation de Nginx
Avant de déployer Magento 2, nous allons contrôler le bon fonctionnement de notre infrastructure en déployant un conteneur Nginx.
Pour ce faire, nous allons utiliserKustomize. Nous allons créer 2 dossiers en exécutant la commande mkdir -p manifests/base
. Dans le dossier base
nous allons créer un premier fichier nommé kustomization.yaml
contenant le code suivant :
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- statefulset.yaml
- service.yaml
Kustomize va nous permettre de concaténer l'ensemble des fichiers présents dans le bloc ressources
lorsque l'on utilisera la commande kustomize build ./manifests/base
.
Continuons, en crééant chaque fichier ci-dessous avec leur contenu.
namespace.yaml :
---
apiVersion: v1
kind: Namespace
metadata:
name: magento
statefulset.yaml :
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: base-nginx
namespace: magento
spec:
replicas: 3
selector:
matchLabels:
app: base-nginx
serviceName: "base-nginx"
template:
metadata:
labels:
app: base-nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
volumes:
- name: base-nginx-persistent-storage
persistentVolumeClaim:
claimName: base-nginx-volumeclaim
volumeClaimTemplates:
- metadata:
name: base-nginx-persistent-storage
namespace: magento
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
service.yaml :
---
apiVersion: v1
kind: Service
metadata:
name: base-nginx
namespace: magento
spec:
type: NodePort
selector:
app: base-nginx
ports:
- port: 80
Vous pouvez lancer la commande kustomize build ./manifests/base
qui va concaténer l'ensemble des fichiers définis ci-dessus. Puis, vous pouvez exécuter la commande kustomize build ./manifests/base | kubectl apply -f -
pour créer les différentes ressources.
Nous pouvons tester le fonctionnement en utiliser le transfert de port, ou port-forward
, pour ce faire, lancer la commande : kubectl port-forward --namespace magento $(kubectl get pod --namespace magento --selector="app=base-nginx" --output jsonpath='{.items[0].metadata.name}') 8080:80
puis, dans un autre terminal, lancer un curl : curl 127.0.0.1:8080
. Vous devriez avoir, en retour, le contenu de la page HTML par défaut de Nginx.
Déploiement d'un cluster Elasticsearch
Pour l'installation d'Elasticsearch, j'ai suivi le mode d'emploi proposé par Elastic.
Je vous invite à lire la documentation si vous souhaitez des informations complémentaires sur l'installation et le paramétrage. Tout d'abord, commençons par installer les ressources personnalisées, ou CRD :
kubectl apply -f https://download.elastic.co/downloads/eck/1.6.0/all-in-one.yaml
J'ai également organisé mes manifests en créant un nouveau dossier nommé elasticsearch
et j'y ai ajouté 2 fichiers YAML :
kustomization.yaml :
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./../base/
- cluster.yaml
cluster.yaml :
---
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: elasticsearch
namespace: magento
spec:
version: 7.13.2
nodeSets:
- name: default
count: 3
config:
node.master: true
node.data: true
node.ingest: true
node.store.allow_mmap: false
xpack.security.authc:
anonymous:
username: anonymous
roles: superuser
authz_exception: false
podTemplate:
spec:
initContainers:
- name: install-plugins
command:
- sh
- -c
- |
bin/elasticsearch-plugin install --batch repository-gcs
http:
tls:
selfSignedCertificate:
disabled: true
Dans le fichier cluster.yaml
, j'ai précisé que je ne souhaitais aucune authentification pour se connecter au cluster et j'ai également désactivé le certificat auto-signé.
Lancer la commande kustomize build ./manifests/elasticsearch/ | kubectl apply -f -
pour procéder au déploiement du cluster Elasticsearch.
Création d'une instance CloudSQL
Le déploiement de l'instance CloudSQL sera réalisée par Terraform. Ajouter le bloc d'instructions, ce-dessous, à la fin du fichier main.tf
. Exécuter la commande terraform apply -auto-approve
pour créer :
- un réseau privé,
- une instance CloudSQL MySQL 8,
- une base de données,
- et l'utilisateur SQL.
Dans le cas où vous travaillez dans un nouveau projet, ou un projet n'ayant jamais eu d'instance Cloud SQL vous devriez avoir l'erreur ci-dessous :
Error, failed to create instance magento: googleapi: Error 400: Invalid request: Incorrect Service Networking config for instance: magento2-testing:magento:SERVICE_NETWORKING_NOT_ENABLED., invalid
Pour activer le service networking
, il faut se connecter en tant que propriétaire avec la commande gcloud config set account <votre-email-google>
et exécuter la commande gcloud services enable servicenetworking.googleapis.com --project=magento2-testing
.
Connectez-vous, ensuite, avec votre compte de service : gcloud auth activate-service-account [email protected] --key-file=~./sa-private-key.json
.
main.tf :
### Create Cloud SQL
data "google_compute_network" "private_network" {
provider = google
project = var.project_id
name = "default"
}
resource "google_compute_global_address" "private_ip_address" {
provider = google
name = "private-ip-address"
project = var.project_id
purpose = "VPC_PEERING"
address_type = "INTERNAL"
prefix_length = 16
network = data.google_compute_network.private_network.id
}
resource "google_service_networking_connection" "private_vpc_connection" {
provider = google
network = data.google_compute_network.private_network.id
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = [google_compute_global_address.private_ip_address.name]
}
resource "google_sql_database_instance" "magento" {
name = "magento"
project = var.project_id
region = var.region
database_version = "MYSQL_8_0"
deletion_protection = true
settings {
tier = "db-custom-2-3840" # 2vCPU - 3.75 Go
availability_type = "REGIONAL"
backup_configuration {
enabled = true
binary_log_enabled = true
}
ip_configuration {
ipv4_enabled = true
private_network = data.google_compute_network.private_network.id
}
}
depends_on = [google_service_networking_connection.private_vpc_connection]
}
resource "google_sql_database" "database" {
project = var.project_id
name = "magento"
instance = google_sql_database_instance.magento.name
}
resource "google_sql_user" "users" {
project = var.project_id
name = var.sql_user
instance = google_sql_database_instance.magento.name
host = "%"
password = var.sql_password
}
variables.tf :
Ajouter également ce bloc dans le fichier variables.tf
:
variable "sql_user" {
type = string
description = "MySQL User"
sensitive = true
}
variable "sql_password" {
type = string
description = "MySQL User Password"
sensitive = true
}
outputs.tf :
Terminons par l'affichage d'un output dans le fichier outputs.tf
:
output "magento_cloudsql_instance_connection_name" {
value = google_sql_database_instance.magento.connection_name
}
Création des secrets
Avant de commencer le déploiement de Magento 2, nous allons créer 2 secrets, un premier pour la connexion au CloudSQL et un second pour se connecter à la base de données du CloudSQL. Ces secrets contiennent les données du compte de service ainsi que les valeurs des variables Terraform sql_user
et sql_password
.
Dans votre terminal, créer le premier secret en lançant la commande :
kubectl create secret generic cloudsql-instance-credentials -n magento --from-file ~./sa-private-key.json
Pour utiliser le premier secret, votre service de compte doit avoir le droit Client Cloud SQL
pour se connecter à votre instance.
Créer le dernier secret pour permettre la connexion à l'instance CloudSQL depuis Kubernetes :
kubectl create secret generic cloudsql-db-credentials -n magento \
--from-literal username=<sql-user> \
--from-literal dbname=<sql-dbname> \
--from-literal password=<sql-password>
Activer le service API
Pour se connecter à la base de données CloudSQL, nous allons utiliser un Cloud Proxy mais avant, nous avons besoin d'activer le service sqladmin
, pour ce faire, connectez-vous en tant que propriétaire avec la commande gcloud config set account <votre-email-google>
et exécutez la commande gcloud services enable sqladmin.googleapis.com --project=magento2-testing
.
Vous pouvez vérifier en ouvrant la page web du service. Vous devriez avoir un texte API activée
avec une icône verte.
Installation de Magento
Nous allons créer un nouveau dossier nommé magento
qui sera enfant du dossier manifests
. Ce dossier contiendra 5 fichiers, voici le contenu de chaque fichier :
kustomization.yaml :
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./../elasticsearch/
- configmap-nginx.yaml
- configmap-phpfpm.yaml
- statefulset.yaml
- service.yaml
configmap-nginx.yaml :
Certains paramètres ci-dessous sont spécifique à mon utilisation. Le cluster Magento 2 que nous déployons est paramétré pour un environnement de développement et non de production. Je vous invite à modifier les paramètres ci-dessous.
Pensez à modifier la valeur <votre-nom-de-domaine>
pour la remplacer par votre nom de domaine associé à l'adresse IP statique que nous avons réservée au début de l'article.
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx
namespace: magento
data:
default: |-
upstream fastcgi_backend {
server 127.0.0.1:9000;
}
server {
listen 8000;
listen [::]:8000;
server_name m2-testing.bejean.ovh magento2-testing.bejean.ovh;
set $MAGE_ROOT /var/www/html/magento;
set $MAGE_DEBUG_SHOW_ARGS 0;
include /var/www/html/magento/nginx.conf.sample;
}
nginx: |-
# let's assume dual-core machine
worker_processes 2;
error_log /var/log/nginx/error.log debug;
pid /var/run/nginx.pid;
events {
# this should be equal to value of "ulimit -n"
# reference: https://www.digitalocean.com/community/tutorials/how-to-optimize-nginx-configuration
worker_connections 1024;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
types_hash_max_size 2048;
map $scheme $fastcgi_https { ## Detect when HTTPS is used
default off;
https on;
}
server_names_hash_bucket_size 64;
include /etc/nginx/mime.types;
default_type application/octet-stream;
rewrite_log on;
log_format main ‘$remote_addr - $remote_user [$time_local] $request ‘ ‘”$status” $body_bytes_sent “$http_referer” ‘ ‘”$http_user_agent” “$http_x_forwarded_for”’
gzip on;
gzip_disable “msie6”;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types
text/plain
text/css
text/js
text/xml
text/javascript
application/javascript
application/x-javascript
application/json
application/xml
application/xml+rss
image/svg+xml;
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 4 16k;
client_body_timeout 12;
client_header_timeout 12;
# Tune nginx keepalives to work with the GCP HTTP(S) Load Balancer:
keepalive_timeout 650;
keepalive_requests 10000;
send_timeout 10;
include /etc/nginx/conf.d/*.conf;
}
configmap-phpfpm.yaml :
Certains paramètres ci-dessous sont spécifique à mon utilisation. Le cluster Magento 2 que nous déployons est paramétré pour un environnement de développement et non de production. Je vous invite à modifier les paramètres ci-dessous.
Pensez à modifier la valeur <username>
et <password>
pour la remplacer par les identifiants que vous possédez.
---
apiVersion: v1
kind: ConfigMap
metadata:
name: phpfpm
namespace: magento
data:
auth: |-
{
"http-basic": {
"repo.magento.com": {
"username": "<username>",
"password": "<password>"
}
}
}
php: |-
; -*- coding: utf-8 -*-
memory_limit = 4G
max_execution_time = 1800
zlib.output_compression = On
cgi.fix_pathinfo = 1
date.timezone = "Europe/Paris"
opcache.enable_cli = 1
opcache.memory_consumption = 512
opcache.max_accelerated_files = 100000
opcache.save_comments = 1
realpath_cache_size = 10M
realpath_cache_ttl = 7200
; Default Value
expose_php = On
display_errors = On ; Production Value: Off
display_startup_errors = On ; Production Value: Off
error_reporting = E_ALL ; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
log_level = debug
ignore_repeated_errors = Off
ignore_repeated_source = Off
; Specific Value
html_errors = On ; Default value: Off
log_errors_max_len = 1024 ; Default value: 1024
upload_max_filesize = 8M ; Default value: 1024
post_max_size = 8M ; Default value: 1024
phpfpm: |-
; -*- coding: utf-8 -*-
[global]
error_log = /proc/self/fd/2
daemonize = no
[www]
access.log = /proc/self/fd/2
user = app
group = app
listen = 9000
listen.owner = app
listen.group = app
listen.mode = 0660
pm = dynamic
pm.max_children = 40
pm.start_servers = 16
pm.min_spare_servers = 8
pm.max_spare_servers = 24
clear_env = no
; Ensure worker stdout and stderr are sent to the main error log.
catch_workers_output = yes
service.yaml :
---
apiVersion: v1
kind: Service
metadata:
name: frontend
namespace: magento
spec:
type: NodePort
selector:
app: frontend
ports:
- port: 8000
protocol: TCP
targetPort: 8000
name: http
statefulset.yaml :
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: frontend
namespace: magento
spec:
replicas: 1
selector:
matchLabels:
app: frontend
serviceName: "frontend"
template:
metadata:
labels:
app: frontend
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: lab.frogg.it:5050/bejean-developpement/kubernetes/magento2/kubenginx:1.0.5
ports:
- containerPort: 8000
name: nginx
volumeMounts:
- name: frontend-persistent-storage
mountPath: /var/www/html
- name: configmap-nginx
mountPath: /etc/nginx/nginx.conf
subPath: nginx
readOnly: true
- name: configmap-nginx
mountPath: /etc/nginx/conf.d/default.conf
subPath: default
readOnly: true
livenessProbe:
httpGet:
port: 8000
path: /healthcheck.html
initialDelaySeconds: 3
periodSeconds: 3
readinessProbe:
httpGet:
port: 8000
path: /healthcheck.html
initialDelaySeconds: 3
periodSeconds: 3
- name: phpfpm
image: lab.frogg.it:5050/bejean-developpement/kubernetes/magento2/kubephpfpm:1.0.6
ports:
- containerPort: 9000
name: phpfpm
env:
- name: MAGENTO_DB_HOST
value: 127.0.0.1:3306
- name: MAGENTO_DB_NAME
valueFrom:
secretKeyRef:
name: cloudsql-db-credentials
key: dbname
- name: MAGENTO_DB_USER
valueFrom:
secretKeyRef:
name: cloudsql-db-credentials
key: username
- name: MAGENTO_DB_PASSWORD
valueFrom:
secretKeyRef:
name: cloudsql-db-credentials
key: password
volumeMounts:
- name: frontend-persistent-storage
mountPath: /var/www/html
- name: configmap-phpfpm
mountPath: /var/www/.composer/auth.json
subPath: auth
readOnly: true
- name: configmap-phpfpm
mountPath: /usr/local/etc/php/php.ini
subPath: php
readOnly: true
- name: configmap-phpfpm
mountPath: /usr/local/etc/php-fpm.conf
subPath: phpfpm
readOnly: true
- name: cloudsql-proxy
image: gcr.io/cloudsql-docker/gce-proxy:1.11
command: ["/cloud_sql_proxy",
"-instances=magento2-testing:europe-west1:magento=tcp:3306",
"-credential_file=/secrets/cloudsql/sa-private-key.json" ]
securityContext:
runAsUser: 2 # non-root user
allowPrivilegeEscalation: false
volumeMounts:
- name: cloudsql-instance-credentials
mountPath: /secrets/cloudsql
readOnly: true
volumes:
- name: frontend-persistent-storage
persistentVolumeClaim:
claimName: frontend-volumeclaim
- name: cloudsql-instance-credentials
secret:
secretName: cloudsql-instance-credentials
- name: configmap-nginx
configMap:
name: nginx
items:
- key: default
path: default
- key: nginx
path: nginx
- name: configmap-phpfpm
configMap:
name: phpfpm
items:
- key: auth
path: auth
- key: php
path: php
- key: phpfpm
path: phpfpm
volumeClaimTemplates:
- metadata:
name: frontend-persistent-storage
namespace: magento
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 50Gi
Lorsque vous lancerez la commande kustomize build ./manifests/magento | kubectl apply -f -
tous les conteneurs seront opérationnelles sauf nginx
. Pour avoir accès aux logs, vous pouvez lancer la commande : kubectl logs frontend-0 -n magento -c nginx
. Ceci vous indiquera que le conteneur nginx
a besoin du fichier nginx.conf.sample
. Ce dernier n'est pas présent dans le disque persistant car nous n'avons pas installé les fichiers sources de Magento.
Pour plus de simplicité, les commandes ci-dessous vous permettront d'installer, au sein de votre projet, les fichiers sources de Magento ainsi que la base de données. Dans un environnement professionnel, je vous recommande de créer un projet Git contenant les fichiers sources de Magento. Un fichier Dockerfile sera nécessaire pour vous permettre de compiler des images PHP-FPM et Nginx avec les fichiers sources de votre projet Git. Ces images devront être chargées au sein d'une registry Docker et récupérées lors du déploiement du StetefulSet.
Reprenons le déploiement en lançant la création du projet Magento 2 via Composer :
kubectl exec -it frontend-0 -n magento -c phpfpm -- composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition magento
Si toutefois, vous préférez réaliser cette action directement dans le conteneur vous avez la possibilité d'exécuter la commande : kubectl exec -it frontend-0 -n magento -c phpfpm -- bash
.
Avant d'installer Magento, nous allons créer un fichier healthcheck.html
dans le dossier pub
. POur ce faire, nous allons utiliser la commande précédente pour se rendre dans le conteneur phpfpm
. Puis, nous lançons la commande cd magento && touch pub/healthcheck.html
.
Le fichier healthcheck.html
est très important car il va permettre aux internautes d'accéder à la boutique Magento 2 en passant par load balancing. Sachez qu'il est possible de personnaliser selon vos envies en vérifiant, par exemple, la connexion à la base de données, au serveur Elasticsearch...
Une fois le fichier crée, nous allons installer les tables dans la base de données depuis le pod phpfpm
. Connectez-vous au pod et lancez la commande ci-dessous, à la racine du projet Magento :
bin/magento setup:install \
--db-host=$MAGENTO_DB_HOST \
--db-name=$MAGENTO_DB_NAME \
--db-user=$MAGENTO_DB_USER \
--db-password=$MAGENTO_DB_PASSWORD \
--base-url=https://<votre-nom-de-domaine>/ \
--backend-frontname=admin \
--admin-firstname=<prenom> \
--admin-lastname=<nom> \
--admin-email=<votre-email>> \
--admin-user=admin \
--admin-password=<votre-mot-de-passe> \
--language=fr_FR \
--currency=EUR \
--timezone=Europe/Paris \
--use-rewrites=1 \
--search-engine=elasticsearch7 \
--elasticsearch-host=elasticsearch-es-http \
--elasticsearch-port=9200 \
--elasticsearch-index-prefix=magento
Déploiement du Load Balancer
Nous allons utiliser le Load Balancer proposé par Google avec un certificat auto-généré. Commençons par créer un nouveau dossier nommé loadbalancer
dans le dossier manifests
. Au sein de ce dossier, nous allons créer 4 fichiers dont le contenu est le suivant :
kustomization.yaml :
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./../magento/
- certificate.yaml
- config.yaml
- ingress.yaml
certificate.yaml :
---
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: certificate
namespace: magento
spec:
domains:
- <votre-nom-de-domaine>
config.yaml :
---
apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
name: redirect-to-https-config
namespace: magento
spec:
redirectToHttps:
enabled: true
responseCodeName: MOVED_PERMANENTLY_DEFAULT
ingress.yaml :
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: frontend-ingress
namespace: magento
annotations:
kubernetes.io/ingress.global-static-ip-name: "magento-frontend"
networking.gke.io/managed-certificates: "certificate"
kubernetes.io/ingress.class: "gce"
networking.gke.io/v1beta1.FrontendConfig: "redirect-to-https-config"
spec:
defaultBackend:
service:
name: frontend
port:
number: 8000
Pour lancer la création du load balancer , il est nécessaire de modifier la commande kustomize
en spécifiant le dossier loadbalancer
. Exécuter la commande kustomize build ./manifests/loadbalancer | kubectl apply -f -
pour créer les différentes ressources. Le temps de création des Ingress prend un peu de temps. Il faut patienter quelques minutes avant de pouvoir afficher la page HTML du conteneur nginx
.
Vous pouvez tester, en lançant un curl sur votre nom de domaine en http
et en https
où vous devriez avoir une 301 en http
et une 200
avec le contenu HTML par défaut de Nginx en https
.
Vérification du projet
Désormais, vous pouvez ouvrir votre navigateur préféré et accéder à votre boutique Magento 2.
Formation vidéo
Pour mieux appréhender Terraform et Kubernetes, j'ai suivi les formations vidéos de Xavki :