In questo tutorial imparerai a eseguire il deployment di un cluster di server Memcached distribuiti su Google Kubernetes Engine (GKE) mediante Kubernetes, Helm e Mcrouter. Memcached è un sistema di caching open source multiuso molto diffuso. In genere funge da archivio temporaneo per i dati utilizzati di frequente per velocizzare le applicazioni web e ridurre i carichi di database.
Caratteristiche di Memcached
Memcached ha due obiettivi di progettazione principali:
- Semplicità: Memcached funziona come una tabella hash di grandi dimensioni e offre una semplice API per archiviare e recuperare oggetti di forma arbitraria per chiave.
- Velocità: Memcached contiene i dati della cache esclusivamente nella memoria ad accesso casuale (RAM), il che rende l'accesso ai dati estremamente rapido.
Memcached è un sistema distribuito che consente di scalare orizzontalmente la capacità della tabella hash in un pool di server. Ogni server Memcached opera in completo isolamento dagli altri server del pool. Pertanto, il routing e il bilanciamento del carico tra i server devono essere eseguiti a livello di client. I client Memcached applicano uno schema di hashing coerente per selezionare in modo appropriato i server di destinazione. Questo schema garantisce le seguenti condizioni:
- Per la stessa chiave viene sempre selezionato lo stesso server.
- La memoria utilizzata è bilanciata in modo uniforme tra i server.
- Quando il pool di server viene ridotto o espanso, viene rilocato un numero minimo di chiavi.
Il seguente diagramma illustra a livello generale l'interazione tra un client Memcached e un pool distribuito di server Memcached.
Obiettivi
- Scopri alcune caratteristiche dell'architettura distribuita di Memcached.
- Esegui il deployment di un servizio Memcached su GKE utilizzando Kubernetes e Helm.
- Esegui il deployment di Mcrouter, un proxy Memcached open source, per migliorare le prestazioni del sistema.
Costi
In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:
- Compute Engine
Per generare una stima dei costi in base all'utilizzo previsto,
utilizza il calcolatore prezzi.
Prima di iniziare
- Accedi al tuo Google Cloud account. Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per l'esecuzione, il test e il deployment dei workload.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
Enable the Compute Engine and GKE APIs.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
Enable the Compute Engine and GKE APIs.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.- Avvia un'istanza di Cloud Shell.
Apri Cloud Shell
Deployment di un servizio Memcached
Un modo semplice per eseguire il deployment di un servizio Memcached su GKE è utilizzare un grafico Helm. Per procedere con il deployment, segui questi passaggi in Cloud Shell:
Crea un nuovo cluster GKE di tre nodi:
gcloud container clusters create demo-cluster --num-nodes 3 --location us-central1-fScarica l'archivio binario
helm:HELM_VERSION=3.7.1 cd ~ wget https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gzDecomprimi il file di archivio sul sistema locale:
mkdir helm-v${HELM_VERSION} tar zxfv helm-v${HELM_VERSION}-linux-amd64.tar.gz -C helm-v${HELM_VERSION}Aggiungi la directory del file binario
helmalla variabile di ambientePATH:export PATH="$(echo ~)/helm-v${HELM_VERSION}/linux-amd64:$PATH"Questo comando rende il file binario
helmrilevabile da qualsiasi directory durante la sessione di Cloud Shell corrente. Per rendere permanente questa configurazione in più sessioni, aggiungi il comando al file~/.bashrcdell'utente di Cloud Shell.Installa una nuova release del grafico Helm di Memcached con l'architettura ad alta disponibilità:
helm repo add bitnami https://charts.bitnami.com/bitnami helm install mycache bitnami/memcached --set architecture="high-availability" --set autoscaling.enabled="true"Il grafico Helm di Memcached utilizza un controller StatefulSet. Un vantaggio dell'utilizzo di un controller StatefulSet è che i nomi dei pod sono ordinati e prevedibili. In questo caso, i nomi sono
mycache-memcached-{0..2}. Questo ordine semplifica il riferimento ai server da parte dei client Memcached.Per visualizzare i pod in esecuzione, esegui il comando seguente:
kubectl get podsL' Google Cloud outputdellaconsolesi presenta nel seguente modo:
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
Individuazione degli endpoint di servizio Memcached
Il grafico Helm di Memcached utilizza un servizio headless. Un servizio headless espone gli indirizzi IP di tutti i suoi pod in modo che possano essere individuati singolarmente.
Verifica che il servizio di cui è stato eseguito il deployment sia headless:
kubectl get service mycache-memcached -o jsonpath="{.spec.clusterIP}"L'output
Noneconferma che il servizio non haclusterIPe che quindi è headless.Il servizio crea un record DNS per un nome host nel formato:
[SERVICE_NAME].[NAMESPACE].svc.cluster.localIn questo tutorial, il nome del servizio è
mycache-memcached. Poiché non è stato definito esplicitamente uno spazio dei nomi, viene utilizzato lo spazio dei nomi predefinito e, pertanto, il nome host completo èmycache-memcached.default.svc.cluster.local. Questo nome host viene risolto in un insieme di indirizzi IP e domini per tutti e tre i pod esposti dal servizio. Se in futuro vengono aggiunti alcuni pod al pool o vengono rimossi quelli precedenti,kube-dnsaggiornerà automaticamente il record DNS.È responsabilità del client individuare gli endpoint di servizio Memcached, come descritto nei passaggi successivi.
Recupera gli indirizzi IP degli endpoint:
kubectl get endpoints mycache-memcachedL'output è simile al seguente:
NAME ENDPOINTS AGE mycache-memcached 10.36.0.32:11211,10.36.0.33:11211,10.36.1.25:11211 3m
Tieni presente che ogni pod Memcached ha un indirizzo IP separato, rispettivamente
10.36.0.32,10.36.0.33e10.36.1.25. Questi indirizzi IP potrebbero essere diversi per le tue istanze server. Ogni pod è in ascolto sulla porta11211, che è la porta predefinita di Memcached.In alternativa al passaggio 2, esegui un'ispezione DNS utilizzando un linguaggio di programmazione come Python:
Avvia una console interattiva Python all'interno del cluster:
kubectl run -it --rm python --image=python:3.10-alpine --restart=Never pythonNella console Python, esegui questi comandi:
import socket print(socket.gethostbyname_ex('mycache-memcached.default.svc.cluster.local')) exit()L'output è simile al seguente:
('mycache-memcached.default.svc.cluster.local', ['mycache-memcached.default.svc.cluster.local'], ['10.36.0.32', '10.36.0.33', '10.36.1.25'])
Testa il deployment aprendo una sessione
telnetcon uno dei server Memcached in esecuzione sulla porta11211:kubectl run -it --rm busybox --image=busybox:1.33 --restart=Never telnet mycache-memcached-0.mycache-memcached.default.svc.cluster.local 11211Al prompt
telnet, esegui questi comandi utilizzando il protocollo ASCII di Memcached:set mykey 0 0 5 hello get mykey quit
L'output risultante è mostrato qui in grassetto:
set mykey 0 0 5 hello STORED get mykey VALUE mykey 0 5 hello END quit
Implementazione della logica di Service Discovery
Ora puoi implementare la logica di Service Discovery di base mostrata nel seguente diagramma.
A livello generale, la logica di Service Discovery è costituita dai seguenti passaggi:
- L'applicazione esegue una query su
kube-dnsper il record DNS dimycache-memcached.default.svc.cluster.local. - L'applicazione recupera gli indirizzi IP associati a questo record.
- L'applicazione crea un'istanza di un nuovo client Memcached e gli fornisce gli indirizzi IP recuperati.
- Il bilanciatore del carico integrato del client Memcached si connette ai server Memcached agli indirizzi IP specificati.
Ora implementa questa logica di Service Discovery utilizzando Python:
Esegui il deployment di un nuovo pod abilitato per Python nel cluster e avvia una sessione shell all'interno del pod:
kubectl run -it --rm python --image=python:3.10-alpine --restart=Never shInstalla la
pymemcachelibreria:pip install pymemcacheAvvia una console interattiva Python eseguendo il comando
python.Nella console Python, esegui questi comandi:
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')L'output è il seguente:
b'hello'
Il prefisso
bindica un valore letterale di byte, ovvero il formato in cui Memcached archivia i dati.Esci dalla console Python:
exit()Per uscire dalla sessione shell del pod, premi
Control+D.
Abilitazione del pool di connessioni
Man mano che le tue esigenze di caching aumentano e il pool viene scalato fino a decine, centinaia o migliaia di server Memcached, potresti riscontrare alcune limitazioni. In particolare, il numero elevato di connessioni aperte dai client Memcached potrebbe esercitare un carico elevato sui server, come mostrato nel seguente diagramma.
Per ridurre il numero di connessioni aperte, devi introdurre un proxy per abilitare il pool di connessioni, come nel seguente diagramma.
Mcrouter (pronunciato "mick router"), un potente proxy Memcached open source, consente il pool di connessioni. L'integrazione di Mcrouter è semplice, perché utilizza il protocollo ASCII standard di Memcached. Per un client Memcached, Mcrouter si comporta come un normale server Memcached. Per un server Memcached, Mcrouter si comporta come un normale client Memcached.
Per eseguire il deployment di Mcrouter, esegui i seguenti comandi in Cloud Shell.
Elimina la release del grafico Helm
mycacheinstallata in precedenza:helm delete mycacheEsegui il deployment di nuovi pod Memcached e pod Mcrouter installando una nuova release del grafico Helm di Mcrouter:
helm repo add stable https://charts.helm.sh/stable helm install mycache stable/mcrouter --set memcached.replicaCount=3I pod proxy sono ora pronti per accettare le richieste dalle applicazioni client.
Testa questa configurazione connettendoti a uno dei pod proxy. Utilizza il comando
telnetsulla porta5000, che è la porta predefinita di 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 5000Al prompt
telnet, esegui questi comandi:set anotherkey 0 0 15 Mcrouter is fun get anotherkey quit
I comandi impostano e fanno l'eco del valore della chiave.
Hai eseguito il deployment di un proxy che consente il pool di connessioni.
Riduzione della latenza
Per aumentare la resilienza, è prassi comune utilizzare un cluster con più nodi. Questo tutorial utilizza un cluster con tre nodi. Tuttavia, l'utilizzo di più nodi comporta anche il rischio di una maggiore latenza causata da un traffico di rete più intenso tra i nodi.
Collocazione dei pod proxy
Puoi ridurre questo rischio connettendo i pod dell'applicazione client solo a un pod proxy Memcached che si trova sullo stesso nodo. Il seguente diagramma illustra questa configurazione.
Esegui questa configurazione nel seguente modo:
- Assicurati che ogni nodo contenga un pod proxy in esecuzione. Un approccio comune consiste nel l'eseguire il deployment dei pod proxy con un controller DaemonSet. Quando vengono aggiunti nodi al cluster, vengono aggiunti automaticamente nuovi pod proxy. Quando i nodi vengono rimossi dal cluster, questi pod vengono sottoposti a garbage collection. In questo tutorial, il grafico Helm di Mcrouter di cui hai eseguito il deployment in precedenza utilizza un controller DaemonSet per impostazione predefinita. Pertanto, questo passaggio è già stato completato.
- Imposta un valore
hostPortnei parametri Kubernetes del container proxy per fare in modo che il nodo sia in ascolto su questa porta e reindirizzi il traffico al proxy. In questo tutorial, il grafico Helm di Mcrouter utilizza questo parametro per impostazione predefinita per la porta5000. Pertanto, anche questo passaggio è già stato completato. Espone il nome del nodo come variabile di ambiente all'interno dei pod dell'applicazione utilizzando la voce
spec.enve selezionando il valorespec.nodeNamefieldRef. Per saperne di più su questo metodo, consulta la documentazione di Kubernetes.Esegui il deployment dei pod dell'applicazione di esempio. Il seguente comando applica un deployment Kubernetes. Un deployment è un oggetto API Kubernetes che consente di eseguire più repliche di pod distribuiti tra i nodi di un cluster:
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
Verifica che il nome del nodo sia esposto esaminando uno dei pod dell'applicazione di esempio:
POD=$(kubectl get pods -l app=sample-application -o jsonpath="{.items[0].metadata.name}") kubectl exec -it $POD -- sh -c 'echo $NODE_NAME'Questo comando restituisce il nome del nodo nel seguente formato:
gke-demo-cluster-default-pool-XXXXXXXX-XXXX
Connessione dei pod
I pod dell'applicazione di esempio sono ora pronti per connettersi al pod Mcrouter in esecuzione sui rispettivi nodi reciproci sulla porta 5000, che è la porta predefinita di Mcrouter.
Avvia una connessione per uno dei pod aprendo una sessione
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'Al prompt
telnet, esegui questi comandi:get anotherkey quitOutput risultante:
Mcrouter is fun
Infine, a titolo illustrativo, il seguente codice Python è un programma di esempio che esegue questa connessione recuperando la variabile NODE_NAME dall'ambiente e utilizzando la libreria 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')
Libera spazio
Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.
Esegui il comando seguente per eliminare il cluster GKE:
gcloud container clusters delete demo-cluster --location us-central1-f(Facoltativo) Elimina il file binario Helm:
cd ~ rm -rf helm-v3.7.1 rm helm-v3.7.1-linux-amd64.tar.gz
Passaggi successivi
- Esplora le numerose altre funzionalità offerte da Mcrouter oltre al semplice pool di connessioni, come le repliche di failover , gli stream di eliminazione affidabili, il riscaldamento della cache fredda e la trasmissione multi-cluster.
- Esplora i file di origine del grafico Memcached e del grafico Mcrouter per maggiori dettagli sulle rispettive configurazioni Kubernetes.
- Scopri le tecniche efficaci per utilizzare Memcached su App Engine. Alcune di queste si applicano ad altre piattaforme, come GKE.