Dans ce tutoriel, vous allez apprendre à déployer un cluster de serveurs Memcached distribués sur Google Kubernetes Engine (GKE) à l'aide de Kubernetes, Helm et Mcrouter. Memcached est un système de mise en cache Open Source populaire et polyvalent. Il est généralement utilisé pour stocker à titre temporaire les données fréquemment consultées de manière à accélérer les applications Web et à alléger les charges des bases de données.
Caractéristiques de Memcached
Memcached a deux objectifs de conception principaux :
- Simplicité : Memcached fonctionne comme une grande table de hachage. Il propose une API simple pour stocker et récupérer des objets de forme arbitraire par clé.
- Rapidité : Memcached conserve les données en cache dans une mémoire vive (RAM) exclusivement. Vous pouvez ainsi accéder aux données beaucoup plus rapidement.
Memcached est un système distribué qui permet d'effectuer un scaling horizontal de la capacité de sa table de hachage sur un pool de serveurs. Chaque serveur Memcached fonctionne de manière totalement isolée par rapport aux autres serveurs du pool. Par conséquent, vous devez effectuer le routage et l'équilibrage de charge entre les serveurs au niveau du client. Les clients Memcached appliquent un schéma de hachage cohérent pour sélectionner les serveurs cibles de manière appropriée. Ce schéma garantit les conditions suivantes :
- Le même serveur est toujours sélectionné pour la même clé.
- L'utilisation de la mémoire est répartie uniformément entre les serveurs.
- Un nombre minimal de clés est déplacé lorsque le pool de serveurs est réduit ou développé.
Le diagramme suivant illustre les interactions générales entre un client Memcached et un pool distribué de serveurs Memcached.
Objectifs
- Découvrir certaines caractéristiques de l'architecture distribuée de Memcached
- Déployer un service Memcached sur GKE à l'aide de Kubernetes et Helm
- Déployer Mcrouter, un proxy Memcached Open Source, pour améliorer les performances du système
Coûts
Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :
- Compute Engine
Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût.
Avant de commencer
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine and GKE APIs.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine and GKE APIs.
- Démarrez une instance Cloud Shell.
Ouvrir Cloud Shell
Déployer un service Memcached
Vous pouvez facilement déployer un service Memcached sur GKE à l'aide d'un chart Helm. Pour procéder au déploiement, suivez ces étapes dans Cloud Shell :
Créez un cluster GKE avec trois nœuds :
gcloud container clusters create demo-cluster --num-nodes 3 --zone us-central1-f
Téléchargez l'archive binaire
helm
:HELM_VERSION=3.7.1 cd ~ wget https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz
Décompressez le fichier d'archive sur votre système local :
mkdir helm-v${HELM_VERSION} tar zxfv helm-v${HELM_VERSION}-linux-amd64.tar.gz -C helm-v${HELM_VERSION}
Ajoutez le répertoire du binaire
helm
à votre variable d'environnementPATH
:export PATH="$(echo ~)/helm-v${HELM_VERSION}/linux-amd64:$PATH"
Cette commande rend le binaire
helm
visible à partir de n'importe quel répertoire au cours de la session Cloud Shell actuelle. Pour conserver cette configuration sur plusieurs sessions, ajoutez la commande au fichier~/.bashrc
de l'utilisateur Cloud Shell.Installez une nouvelle version du chart Helm Memcached avec l'architecture haute disponibilité :
helm repo add bitnami https://charts.bitnami.com/bitnami helm install mycache bitnami/memcached --set architecture="high-availability" --set autoscaling.enabled="true"
Le graphique Memcached Helm utilise un contrôleur StatefulSet. L'avantage avec ce type de contrôleur est que les noms des pods sont triés et prévisibles. Dans le cas présent, les noms sont
mycache-memcached-{0..2}
. Cet ordre facilite le référencement des serveurs par les clients Memcached.Pour afficher les pods en cours, exécutez la commande suivante :
kubectl get pods
Le résultat de la console Google Cloud ressemble à ceci :
NAME READY STATUS RESTARTS AGE mycache-memcached-0 1/1 Running 0 45s mycache-memcached-1 1/1 Running 0 35s mycache-memcached-2 1/1 Running 0 25s
Découvrir les points de terminaison du service Memcached
Le graphique Memcached Helm utilise un service sans adresse IP de cluster. Celui-ci expose les adresses IP de tous ses pods afin qu'ils puissent être découverts individuellement.
Vérifiez que le service déployé ne contient pas d'adresse IP de cluster :
kubectl get service mycache-memcached -o jsonpath="{.spec.clusterIP}"
Le résultat
None
confirme que le service n'a pas declusterIP
et qu'il n'a donc pas d'adresse IP de cluster.Le service crée un enregistrement DNS pour le nom d'hôte sous la forme suivante :
[SERVICE_NAME].[NAMESPACE].svc.cluster.local
Dans ce tutoriel, le nom du service est
mycache-memcached
. Étant donné qu'aucun espace de noms n'a été explicitement défini, l'espace de noms par défaut est utilisé. Le nom d'hôte complet est doncmycache-memcached.default.svc.cluster.local
. Ce nom d'hôte résout un ensemble d'adresses IP et de domaines pour les trois pods exposés par le service. Si vous ajoutez ultérieurement certains pods au pool ou si vous en supprimez,kube-dns
met automatiquement à jour l'enregistrement DNS.Il incombe au client de découvrir les points de terminaison du service Memcached, comme décrit dans les étapes suivantes.
Récupérez les adresses IP des points de terminaison :
kubectl get endpoints mycache-memcached
Le résultat ressemble à ce qui suit :
NAME ENDPOINTS AGE mycache-memcached 10.36.0.32:11211,10.36.0.33:11211,10.36.1.25:11211 3m
Notez que chaque pod Memcached a une adresse IP distincte, respectivement
10.36.0.32
,10.36.0.33
et10.36.1.25
. Ces adresses IP ne sont pas nécessairement les mêmes pour vos propres instances de serveur. Chaque pod écoute le port11211
, qui est le port par défaut de Memcached.Comme alternative à l'étape 2, vous pouvez effectuer une inspection DNS à l'aide d'un langage de programmation tel que Python :
Démarrez une console interactive Python dans votre cluster :
kubectl run -it --rm python --image=python:3.10-alpine --restart=Never python
Dans la console Python, exécutez les commandes suivantes :
import socket print(socket.gethostbyname_ex('mycache-memcached.default.svc.cluster.local')) exit()
Le résultat ressemble à ce qui suit :
('mycache-memcached.default.svc.cluster.local', ['mycache-memcached.default.svc.cluster.local'], ['10.36.0.32', '10.36.0.33', '10.36.1.25'])
Testez le déploiement en ouvrant une session
telnet
avec l'un des serveurs Memcached en cours d'exécution sur le port11211
:kubectl run -it --rm busybox --image=busybox:1.33 --restart=Never telnet mycache-memcached-0.mycache-memcached.default.svc.cluster.local 11211
Dans l'invite de
telnet
, exécutez les commandes suivantes à l'aide du protocole ASCII Memcached :set mykey 0 0 5 hello get mykey quit
Le résultat obtenu est ici indiqué en gras :
set mykey 0 0 5 hello STORED get mykey VALUE mykey 0 5 hello END quit
Mettre en œuvre la logique de découverte de services
Vous êtes maintenant prêt à mettre en œuvre la logique de découverte de services fondamentale, illustrée dans le diagramme suivant.
La logique de découverte de services comprend les étapes générales suivantes :
- L'application interroge
kube-dns
pour obtenir l'enregistrement DNS demycache-memcached.default.svc.cluster.local
. - L'application récupère les adresses IP associées à cet enregistrement.
- L'application instancie un nouveau client Memcached et lui fournit les adresses IP récupérées.
- L'équilibreur de charge intégré au client Memcached se connecte aux serveurs Memcached aux adresses IP indiquées.
Vous allez maintenant mettre en œuvre cette logique de découverte de services à l'aide de Python :
Déployez un nouveau pod compatible avec Python dans votre cluster, puis démarrez une session d'interface système à l'intérieur du pod :
kubectl run -it --rm python --image=python:3.10-alpine --restart=Never sh
Installez la bibliothèque
pymemcache
:pip install pymemcache
Démarrez une console interactive Python à l'aide de la commande
python
.Dans la console Python, exécutez les commandes suivantes :
import socket from pymemcache.client.hash import HashClient _, _, ips = socket.gethostbyname_ex('mycache-memcached.default.svc.cluster.local') servers = [(ip, 11211) for ip in ips] client = HashClient(servers, use_pooling=True) client.set('mykey', 'hello') client.get('mykey')
Voici le résultat :
b'hello'
Le préfixe
b
correspond à un littéral d'octets. Il s'agit du format dans lequel Memcached stocke les données.Quittez la console Python :
exit()
Appuyez sur
Control
+D
pour quitter la session d'interface système du pod.
Activer le regroupement de connexions
Vous pouvez rencontrer certaines limites à mesure que vos besoins en mise en cache augmentent et que des dizaines, des centaines voire des milliers de serveurs Memcached sont ajoutés au pool. Par exemple, un grand nombre de connexions ouvertes provenant de clients Memcached peut entraîner une charge importante sur les serveurs, comme le montre le diagramme suivant.
Pour réduire le nombre de connexions ouvertes, vous devez utiliser un proxy afin d'activer le regroupement de connexions, comme indiqué dans le diagramme suivant.
Mcrouter (prononcé "mick router") est un puissant proxy Memcached Open Source qui permet de regrouper les connexions. L'intégration de Mcrouter est transparente, car ce proxy utilise le protocole standard ASCII Memcached. Pour un client Memcached, Mcrouter se comporte comme un serveur Memcached normal. Pour un serveur Memcached, Mcrouter se comporte comme un client Memcached normal.
Pour déployer Mcrouter, exécutez les commandes suivantes dans Cloud Shell.
Supprimez la version du chart Helm
mycache
précédemment installée :helm delete mycache
Installez une nouvelle version du chart Helm Mcrouter pour déployer les nouveaux pods Memcached et Mcrouter :
helm repo add stable https://charts.helm.sh/stable helm install mycache stable/mcrouter --set memcached.replicaCount=3
Les pods du proxy sont maintenant prêts à accepter les requêtes des applications clientes.
Testez cette configuration en vous connectant à l'un des pods du proxy. Exécutez la commande
telnet
sur le port5000
, qui est le port par défaut de Mcrouter.MCROUTER_POD_IP=$(kubectl get pods -l app=mycache-mcrouter -o jsonpath="{.items[0].status.podIP}") kubectl run -it --rm busybox --image=busybox:1.33 --restart=Never telnet $MCROUTER_POD_IP 5000
À l'invite de
telnet
, exécutez les commandes suivantes :set anotherkey 0 0 15 Mcrouter is fun get anotherkey quit
Les commandes définissent et rappellent la valeur de votre clé.
Vous venez de déployer un proxy permettant de regrouper des connexions.
Réduire la latence
Pour augmenter la résilience, il est courant d'utiliser un cluster avec plusieurs nœuds. Dans ce tutoriel, nous utilisons un cluster avec trois nœuds. Toutefois, l'utilisation de plusieurs nœuds entraîne un risque d'augmentation de la latence en raison du trafic réseau plus important entre les nœuds.
Héberger des pods de proxy en colocation
Vous pouvez réduire ce risque en ne connectant les pods des applications clientes qu'à un pod de proxy Memcached qui se trouve sur le même nœud. Le diagramme suivant illustre cette configuration.
Effectuez cette configuration comme suit :
- Assurez-vous que chaque nœud contient un pod de proxy en cours d'exécution. Une méthode courante consiste à déployer les pods de proxy avec un contrôleur DaemonSet. À mesure que les nœuds sont ajoutés au cluster, de nouveaux pods de proxy leur sont automatiquement ajoutés. Lorsque les nœuds sont supprimés du cluster, ces pods sont récupérés. Le chart Helm Mcrouter que vous avez déployé précédemment dans ce tutoriel utilise un contrôleur DaemonSet par défaut. Cette tâche est donc déjà effectuée.
- Définissez une valeur
hostPort
dans les paramètres Kubernetes du conteneur du proxy pour que le nœud écoute ce port et redirige le trafic vers le proxy. Dans ce tutoriel, le chart Helm Mcrouter utilise ce paramètre par défaut pour le port5000
. Cette tâche est donc également effectuée. Exposez le nom du nœud en tant que variable d'environnement à l'intérieur des pods de l'application en utilisant l'entrée
spec.env
et en sélectionnant la valeurfieldRef
spec.nodeName
. Pour en savoir plus sur cette méthode, consultez la documentation Kubernetes.Déployez des exemples de pods d'application :
cat <<EOF | kubectl create -f - apiVersion: apps/v1 kind: Deployment metadata: name: sample-application spec: selector: matchLabels: app: sample-application replicas: 9 template: metadata: labels: app: sample-application spec: containers: - name: busybox image: busybox:1.33 command: [ "sh", "-c"] args: - while true; do sleep 10; done; env: - name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName EOF
Vérifiez que le nom du nœud est exposé en le recherchant dans l'un des exemples de pods d'application :
POD=$(kubectl get pods -l app=sample-application -o jsonpath="{.items[0].metadata.name}") kubectl exec -it $POD -- sh -c 'echo $NODE_NAME'
Cette commande affiche le nom du nœud au format suivant :
gke-demo-cluster-default-pool-XXXXXXXX-XXXX
Connecter les pods
Les exemples de pods d'application sont maintenant prêts à se connecter au pod Mcrouter qui s'exécute sur leurs nœuds communs respectifs sur le port 5000
(port par défaut de Mcrouter).
Établissez une connexion pour l'un des pods en ouvrant une session
telnet
:POD=$(kubectl get pods -l app=sample-application -o jsonpath="{.items[0].metadata.name}") kubectl exec -it $POD -- sh -c 'telnet $NODE_NAME 5000'
À l'invite de
telnet
, exécutez les commandes suivantes :get anotherkey quit
Résultat :
Mcrouter is fun
Enfin, à titre d'illustration, le code Python suivant est un exemple de programme qui établit cette connexion. Pour ce faire, il récupère la variable NODE_NAME
de l'environnement et utilise la bibliothèque pymemcache
:
import os
from pymemcache.client.base import Client
NODE_NAME = os.environ['NODE_NAME']
client = Client((NODE_NAME, 5000))
client.set('some_key', 'some_value')
result = client.get('some_key')
Nettoyer
Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.
Exécutez la commande suivante pour supprimer le cluster GKE :
gcloud container clusters delete demo-cluster --zone us-central1-f
Supprimez éventuellement le binaire Helm :
cd ~ rm -rf helm-v3.7.1 rm helm-v3.7.1-linux-amd64.tar.gz
Étape suivante
- Découvrez les nombreuses autres fonctionnalités offertes par Mcrouter au-delà du simple regroupement de connexions, telles que les instances de basculement dupliquées, les flux de suppression fiables, le préchauffage du cache à froid et la diffusion multicluster.
- Examinez les fichiers sources du chart Memcached et du chart Mcrouter pour en savoir plus sur les configurations Kubernetes respectives.
- Découvrez des techniques efficaces pour utiliser Memcached sur App Engine. Certaines d'entre elles s'appliquent à d'autres plates-formes, telles que GKE.