Questa pagina descrive i diversi tipi di servizi Kubernetes e il modo in cui Google Kubernetes Engine (GKE) utilizza i servizi per raggruppare gli endpoint dei pod.
Imparerai a creare servizi utilizzando esempi YAML. Ogni tipo di servizio utilizza l'indirizzo IP stabile del servizio per ridurre la complessità di attività specifiche di networking e comunicazione. Ad esempio, scopri come utilizzare più porte ed endpoint, nonché come configurare opzioni a stack singolo o doppio che supportano IPv4 e IPv6.
Per scoprire come creare un servizio, consulta Esporre le applicazioni utilizzando i servizi.
Questa pagina è rivolta a operatori e sviluppatori che eseguono il provisioning e la configurazione delle risorse cloud e il deployment di app e servizi. Per scoprire di più sui ruoli comuni e sulle attività di esempio a cui si fa riferimento nei contenuti di Google Cloud, consulta la pagina Ruoli utente e attività comuni di GKE Enterprise.
Che cos'è un servizio Kubernetes?
L'idea di un servizio è di raggruppare un insieme di endpoint pod in un'unica risorsa. Puoi configurare vari modi per accedere al raggruppamento. Per impostazione predefinita, ottieni un indirizzo IP del cluster stabile che i client all'interno del cluster possono utilizzare per contattare i pod nel servizio. Un client invia una richiesta all'indirizzo IP stabile e la richiesta viene instradata a uno dei pod nel servizio.
Un servizio identifica i pod membri con un selettore. Affinché un pod sia membro del servizio, deve avere tutte le etichette specificate nel selettore. Un'etichetta è una coppia chiave/valore arbitraria associata a un oggetto.
Il seguente manifest del servizio ha un selettore che specifica due etichette. Il campo
selector
indica che qualsiasi pod con l'etichetta app: metrics
e l'etichetta
department:engineering
è membro di questo servizio.
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: metrics
department: engineering
ports:
...
Perché utilizzare un servizio Kubernetes?
In un cluster Kubernetes, ogni pod ha un indirizzo IP interno. Ma i pod in un deployment vanno e vengono e i loro indirizzi IP cambiano. Pertanto, non ha senso utilizzare direttamente gli indirizzi IP del pod. Con un servizio, ottieni un indirizzo IP stabile che dura per tutta la durata del servizio, anche se gli indirizzi IP dei pod membri cambiano.
Un servizio fornisce anche il bilanciamento del carico. I client chiamano un singolo indirizzo IP stabile e le loro richieste vengono bilanciate tra i pod membri del servizio.
Tipi di servizi Kubernetes
Esistono cinque tipi di servizi:
ClusterIP (predefinito): i client interni inviano richieste a un indirizzo IP interno stabile.
NodePort:i client inviano richieste all'indirizzo IP di un nodo su uno o più valori
nodePort
specificati dal servizio.LoadBalancer:i client inviano richieste all'indirizzo IP di un bilanciatore del carico di rete.
ExternalName:i client interni utilizzano il nome DNS di un servizio come alias per un nome DNS esterno.
Senza intestazione:puoi utilizzare un servizio headless quando vuoi un raggruppamento di pod, ma non hai bisogno di un indirizzo IP stabile.
Il tipo NodePort
è un'estensione del tipo ClusterIP
. Pertanto, un servizio di
tipo NodePort
ha un indirizzo IP del cluster.
Il tipo LoadBalancer
è un'estensione del tipo NodePort
. Pertanto, un servizio di tipo LoadBalancer
ha un indirizzo IP cluster e uno o più valori nodePort
.
Servizi di tipo ClusterIP
Quando crei un servizio di tipo ClusterIP
, Kubernetes crea un indirizzo IP stabile accessibile dai nodi del cluster.
Ecco un manifest per un servizio di tipo ClusterIP:
apiVersion: v1
kind: Service
metadata:
name: my-cip-service
spec:
selector:
app: metrics
department: sales
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 8080
Puoi
creare il servizio
utilizzando kubectl apply -f [MANIFEST_FILE]
. Dopo aver creato il servizio, puoi utilizzare kubectl get service
per visualizzare l'indirizzo IP stabile:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
my-cip-service ClusterIP 10.11.247.213 none 80/TCP
I client nel cluster chiamano il servizio utilizzando l'indirizzo IP del cluster e la porta TCP specificata nel campo port
del manifest del servizio. La richiesta viene
inoltrata a uno dei pod membri sulla porta TCP specificata nel campo targetPort
. Per l'esempio precedente, un client chiama il servizio all'indirizzo 10.11.247.213
sulla porta TCP 80. La richiesta viene inoltrata a uno dei pod membri sulla porta TCP
8080. Il pod membro deve avere un container in ascolto sulla porta TCP
8080. Se non è presente alcun container in ascolto sulla porta 8080, i client visualizzeranno
un messaggio come "Impossibile connettersi" o "Impossibile raggiungere il sito".
Service di tipo NodePort
Quando crei un servizio di tipo NodePort
, Kubernetes ti fornisce un valore nodePort
. Il servizio è quindi accessibile utilizzando l'indirizzo IP di qualsiasi nodo insieme al valore nodePort
.
Ecco un manifest per un servizio di tipo NodePort
:
apiVersion: v1
kind: Service
metadata:
name: my-np-service
spec:
selector:
app: products
department: sales
type: NodePort
ports:
- protocol: TCP
port: 80
targetPort: 8080
Dopo aver creato il servizio, puoi utilizzare kubectl get service -o yaml
per visualizzarne
la specifica e vedere il valore di nodePort
.
spec:
clusterIP: 10.11.254.114
externalTrafficPolicy: Cluster
ports:
- nodePort: 32675
port: 80
protocol: TCP
targetPort: 8080
I client esterni chiamano il servizio utilizzando l'indirizzo IP esterno di un nodo
insieme alla porta TCP specificata da nodePort
. La richiesta viene inoltrata a
uno dei pod membri sulla porta TCP specificata dal campo targetPort
.
Ad esempio, supponiamo che l'indirizzo IP esterno di uno dei nodi del cluster sia
203.0.113.2
. Quindi, per l'esempio precedente, il client esterno chiama il
servizio all'indirizzo 203.0.113.2
sulla porta TCP 32675. La richiesta viene inoltrata a uno dei pod membri sulla porta TCP 8080. Il pod membro deve avere un container
in ascolto sulla porta TCP 8080.
Il tipo di servizio NodePort
è un'estensione del tipo di servizio ClusterIP
. Pertanto, i client interni hanno due modi per chiamare il servizio:
- Utilizza
clusterIP
eport
. - Utilizza l'indirizzo IP di un nodo e
nodePort
.
Per alcune configurazioni del cluster, il
bilanciatore del carico delle applicazioni esterno
utilizza un servizio di tipo NodePort
.
Un bilanciatore del carico delle applicazioni esterno è un server proxy ed è fondamentalmente diverso dal bilanciatore del carico di rete passthrough esterno descritto in questo argomento nella sezione Servizio di tipo LoadBalancer.
Servizi di tipo LoadBalancer
Per scoprire di più sui servizi di tipo LoadBalancer, consulta Concetti del servizio LoadBalancer.
Service di tipo ExternalName
Un servizio di tipo ExternalName
fornisce un alias interno per un nome DNS esterno. I client interni effettuano richieste utilizzando il nome DNS interno e le
richieste vengono reindirizzate al nome esterno.
Ecco un manifest per un servizio di tipo ExternalName
:
apiVersion: v1
kind: Service
metadata:
name: my-xn-service
spec:
type: ExternalName
externalName: example.com
Quando crei un servizio, Kubernetes crea un nome DNS che i client interni possono utilizzare per chiamare il servizio. Per l'esempio precedente, il nome DNS è my-xn-service.default.svc.cluster.local. Quando un client interno effettua una richiesta a my-xn-service.default.svc.cluster.local, la richiesta viene reindirizzata a example.com.
Il tipo di servizio ExternalName
è fondamentalmente diverso dagli altri tipi di servizio. Infatti, un servizio di tipo ExternalName
non corrisponde alla
definizione di servizio fornita all'inizio di questo argomento. Un servizio di tipo
ExternalName
non è associato a un insieme di pod e non ha un
indirizzo IP stabile. Un servizio di tipo ExternalName
è invece una mappatura da
un nome DNS interno a un nome DNS esterno.
Servizio headless
Un servizio headless è un tipo di servizio Kubernetes che non alloca un indirizzo IP del cluster. Un servizio headless utilizza invece il DNS per esporre gli indirizzi IP dei pod associati al servizio. In questo modo puoi connetterti direttamente ai pod, anziché tramite un proxy.
I servizi headless sono utili per una serie di scenari, tra cui:
Service Discovery: puoi utilizzare un servizio headless per implementare Service Discovery. Per implementarlo, crea un servizio con un nome e un selettore. Il record DNS per il servizio headless contiene tutti gli indirizzi IP dei pod dietro il servizio che corrispondono al selettore. I client possono utilizzare questi record DNS per trovare gli indirizzi IP dei pod associati al servizio.
Accesso diretto ai pod: i client possono connettersi direttamente ai pod associati a un servizio headless, il che può essere utile per i servizi che richiedono l'accesso diretto ai pod sottostanti, come i bilanciatori del carico e i server DNS.
Flessibilità: i servizi headless possono essere utilizzati per creare una serie di topologie diverse, come bilanciatori del carico, server DNS e database distribuiti.
Se hai requisiti di rete speciali per i tuoi carichi di lavoro che non possono essere risolti utilizzando i servizi headless con selettori, puoi anche utilizzare i servizi headless senza selettori. I servizi headless sono uno strumento utile per accedere ai servizi che non si trovano all'interno del cluster Kubernetes stesso, poiché il control plane non crea oggetti EndpointSlice. Puoi scoprire di più in Servizio senza selettori.
L'esempio seguente è un manifest per un servizio headless:
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
clusterIP: None
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
Dopo aver creato un servizio headless, puoi trovare gli indirizzi IP dei pod associati al servizio eseguendo una query DNS. Ad esempio, il seguente comando elenca gli indirizzi IP dei pod associati al servizio nginx:
dig +short nginx.default.svc.cluster.local
Un altro esempio che utilizza l'espansione delle query Kubernetes:
dig +short +search nginx
Puoi creare un servizio headless con un unico comando e i servizi headless sono facili da aggiornare e scalare.
kubectl create service clusterip my-svc --clusterip="None" --dry-run=client -o yaml > [file.yaml]
Astrazione del servizio
Un servizio è un'astrazione nel senso che non è un processo che ascolta su un'interfaccia di rete. Parte dell'astrazione è implementata nelle regole iptables dei nodi del cluster. A seconda del tipo di servizio, altre parti dell'astrazione vengono implementate da un bilanciatore del carico di rete passthrough esterno o da un bilanciatore del carico delle applicazioni esterno.
Porte di servizio arbitrarie
Il valore del campo port
in un manifest del servizio è arbitrario. Tuttavia,
il valore di targetPort
non è arbitrario. Ogni pod membro deve avere un
container in ascolto su targetPort
.
Ecco un servizio di tipo LoadBalancer
con un valore port
di 50.000:
apiVersion: v1
kind: Service
metadata:
name: my-ap-service
spec:
clusterIP: 10.11.241.93
externalTrafficPolicy: Cluster
ports:
- nodePort: 30641
port: 50000
protocol: TCP
targetPort: 8080
selector:
app: parts
department: engineering
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 203.0.113.200
Un client chiama il servizio all'indirizzo 203.0.113.200
sulla porta TCP 50000. La richiesta viene inoltrata a uno dei pod membri sulla porta TCP 8080.
Più porte
Il campo ports
di un servizio è un array di oggetti
ServicePort. L'oggetto ServicePort ha i seguenti campi:
name
protocol
port
targetPort
nodePort
Se hai più di una ServicePort, ognuna deve avere un nome univoco.
Ecco un servizio di tipo LoadBalancer
che ha due oggetti ServicePort
:
apiVersion: v1
kind: Service
metadata:
name: my-tp-service
spec:
clusterIP: 10.11.242.196
externalTrafficPolicy: Cluster
ports:
- name: my-first-service-port
nodePort: 31233
port: 60000
protocol: TCP
targetPort: 50000
- name: my-second-service-port
nodePort: 31081
port: 60001
protocol: TCP
targetPort: 8080
selector:
app: tests
department: engineering
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 203.0.113.201
Nell'esempio precedente, se un client chiama il servizio all'indirizzo 203.0.113.201
sulla porta TCP 60000, la richiesta viene inoltrata a un pod membro sulla porta TCP 50000. Tuttavia, se un client chiama il servizio all'indirizzo 203.0.113.201
sulla porta TCP 60001, la richiesta viene inoltrata a un pod membro sulla porta TCP 8080.
Ogni pod membro deve avere un container in ascolto sulla porta TCP 50000 e un container in ascolto sulla porta TCP 8080. Potrebbe trattarsi di un singolo container con due thread o di due container in esecuzione nello stesso pod.
Endpoint di servizio
Quando crei un servizio, Kubernetes crea un oggetto Endpoints che ha lo stesso nome del servizio. Kubernetes utilizza l'oggetto Endpoints per tenere traccia dei pod che sono membri del servizio.
Servizi single-stack e dual-stack
Puoi creare un servizio IPv6 di tipo
ClusterIP
o NodePort
.
Per ciascuno di questi tipi di servizio, puoi definire i campi ipFamilies
e ipFamilyPolicy
come IPv4, IPv6 o un servizio dual-stack.
Passaggi successivi
- Scopri di più sui servizi Kubernetes
- Esposizione delle applicazioni mediante servizi
- Scopri di più sugli StatefulSets
- Scopri di più su Ingress