Contribuisci a migliorare questa pagina
Per contribuire a questa guida per l’utente, seleziona il link Edit this page on GitHub che si trova nel riquadro destro di ogni pagina.
Configurazione dell’ingresso Kubernetes per nodi ibridi
Questo argomento descrive come configurare l’ingresso Kubernetes per i carichi di lavoro in esecuzione su Amazon EKS Hybrid Nodes. L’ingresso Kubernetes
AWS supporta AWS Application Load Balancer (ALB) e Cilium per l’ingresso Kubernetes per carichi di lavoro in esecuzione su nodi ibridi EKS. La decisione di utilizzare ALB o Cilium per l’ingresso si basa sulla fonte del traffico delle applicazioni. Se il traffico dell’applicazione proviene da una Regione AWS, AWS consiglia di utilizzare ALB AWS e il controller del bilanciatore del carico AWS. Se il traffico delle applicazioni proviene dall’ambiente on-premises o edge, AWS consiglia di utilizzare le funzionalità dell’ingresso integrate di Cilium, che possono essere utilizzate con o senza l’infrastruttura di bilanciatore del carico nell’ambiente.
AWS Application Load Balancer
Puoi utilizzare il Controller del bilanciatore del carico AWS e Application Load Balancer (ALB) con il tipo di destinazione ip per i carichi di lavoro in esecuzione su nodi ibridi. Quando si utilizza il tipo di destinazione ip, ALB inoltra il traffico direttamente ai pod, aggirando il percorso di rete del livello di servizio. Affinché ALB raggiunga le destinazioni IP del pod sui nodi ibridi, il CIDR del pod on-premises deve essere instradabile sulla rete locale. Inoltre, il controller del bilanciatore del carico AWS utilizza webhook e richiede una comunicazione diretta dal piano di controllo EKS. Per ulteriori informazioni, consulta Configurazione di webhook per nodi ibridi.
Considerazioni
-
Per ulteriori informazioni su AWS Application Load Balancer e il controller del bilanciatore del carico AWS, consulta Instradare il traffico di applicazioni e HTTP con Application Load Balancer e Installa AWS Load Balancer Controller con Helm.
-
Consulta Best Practices for Load Balancing per informazioni su come scegliere tra AWS Application Load Balancer e AWS Network Load Balancer.
-
Consulta AWS Load Balancer Controller Ingress annotations
per l’elenco delle annotazioni che possono essere configurate per le risorse di ingresso con AWS Application Load Balancer.
Prerequisiti
-
Cilium è installato seguendo le istruzioni contenute in Configurazione della CNI per nodi ibridi.
-
Il piano di controllo BGP di Cilium è abilitato seguendo le istruzioni contenute in Configurazione di Cilium BGP per nodi ibridi. Se non desideri utilizzare BGP, devi utilizzare un metodo alternativo per rendere i pod CIDR on-premises instradabili sulla rete on-premises. Se non rendi instradabili i tuoi pod CIDR on-premises, ALB non sarà in grado di registrarsi o contattare i destinatari IP del pod.
-
Helm è installato nell’ambiente a riga di comando, consulta le istruzioni di configurazione di Helm per ulteriori informazioni.
-
eksctl è installato nell’ambiente a riga di comando, consulta le istruzioni di installazione di eksctl per ulteriori informazioni.
Procedura
-
Scaricare una policy IAM per il Controller del load balancer AWS che consente di effettuare chiamate alle API AWS per conto dell’utente.
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/refs/heads/main/docs/install/iam_policy.json -
Creare una policy IAM utilizzando le policy scaricate nel passaggio precedente.
aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://iam_policy.json -
Sostituisci il valore per nome del cluster (
CLUSTER_NAME), Regione AWS (AWS_REGION) e ID dell’account AWS (AWS_ACCOUNT_ID) con le tue impostazioni ed esegui il comando seguente.eksctl create iamserviceaccount \ --cluster=CLUSTER_NAME \ --namespace=kube-system \ --name=aws-load-balancer-controller \ --attach-policy-arn=arn:aws:iam::AWS_ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy \ --override-existing-serviceaccounts \ --region AWS_REGION \ --approve -
Aggiungi il repository di grafici Helm di eks-charts e aggiorna il repository Helm locale per assicurarti di avere i grafici più recenti.
helm repo add eks https://aws.github.io/eks-chartshelm repo update eks -
Installazione del Controller del bilanciatore del carico AWS. Sostituisci il valore per nome del cluster (
CLUSTER_NAME), Regione AWS (AWS_REGION), ID del VPC (VPC_ID) e versione del grafico Helm del controller del bilanciatore del carico AWS (AWS_LBC_HELM_VERSION) con le tue impostazioni ed esegui il comando seguente. Se stai eseguendo un cluster in modalità mista con nodi ibridi e nodi nel cloud AWS, puoi eseguire il controller del bilanciatore del carico AWS sui nodi cloud seguendo le istruzioni riportate all’indirizzo Controller del bilanciatore del carico AWS.-
Puoi trovare la versione più recente del grafico Helm eseguendo
helm search repo eks/aws-load-balancer-controller --versions.helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ -n kube-system \ --versionAWS_LBC_HELM_VERSION\ --set clusterName=CLUSTER_NAME\ --set region=AWS_REGION\ --set vpcId=VPC_ID\ --set serviceAccount.create=false \ --set serviceAccount.name=aws-load-balancer-controller
-
-
Verifica che il controller del bilanciatore del carico AWS sia stato installato correttamente.
kubectl get -n kube-system deployment aws-load-balancer-controllerNAME READY UP-TO-DATE AVAILABLE AGE aws-load-balancer-controller 2/2 2 2 84s -
Crea un’applicazione di esempio. L’esempio seguente utilizza l’applicazione di microservizi di esempio Istio Bookinfo
. kubectl apply -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/bookinfo/platform/kube/bookinfo.yaml -
Crea un file denominato
my-ingress-alb.yamlcon i seguenti contenuti.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress namespace: default annotations: alb.ingress.kubernetes.io/load-balancer-name: "my-ingress-alb" alb.ingress.kubernetes.io/target-type: "ip" alb.ingress.kubernetes.io/scheme: "internet-facing" alb.ingress.kubernetes.io/healthcheck-path: "/details/1" spec: ingressClassName: alb rules: - http: paths: - backend: service: name: details port: number: 9080 path: /details pathType: Prefix -
Applica la configurazione dell’ingresso al cluster.
kubectl apply -f my-ingress-alb.yaml -
Il provisioning dell’ALB per la risorsa in ingresso può richiedere alcuni minuti. Una volta effettuato il provisioning dell’ALB, alla risorsa Ingress verrà assegnato un indirizzo che corrisponde al nome DNS dell’implementazione ALB. L’indirizzo avrà il formato
<alb-name>-<random-string>.<region>.elb.amazonaws.com.rproxy.govskope.ca.kubectl get ingress my-ingressNAME CLASS HOSTS ADDRESS PORTS AGE my-ingress alb * my-ingress-alb-<random-string>.<region>.elb.amazonaws.com 80 23m -
Accedi al Servizio utilizzando l’indirizzo dell’ALB.
curl -s http//my-ingress-alb-<random-string>.<region>.elb.amazonaws.com:80/details/1 | jq{ "id": 1, "author": "William Shakespeare", "year": 1595, "type": "paperback", "pages": 200, "publisher": "PublisherA", "language": "English", "ISBN-10": "1234567890", "ISBN-13": "123-1234567890" "details": "This is the details page" }
Panoramica dell’ingresso di Cilium e del gateway di Cilium
Le funzionalità dell’ingresso di Cilium sono integrate nell’architettura di Cilium e possono essere gestite con l’API dell’ingresso di Kubernetes o l’API Gateway. Se non disponi di risorse dell’ingresso esistenti, AWS consiglia di iniziare con l’API Gateway, poiché è un modo più significativo e flessibile per definire e gestire le risorse di rete Kubernetes. L’API del Gateway di Kubernetes
Quando abiliti le funzionalità di ingresso o gateway di Cilium, l’operatore Cilium riconcilia gli oggetti ingresso/gateway nel cluster e i proxy Envoy su ciascun nodo elaborano il traffico di rete di livello 7 (L7). Cilium non fornisce direttamente l’infrastruttura ingresso/gateway come i bilanciatori del carico. Se prevedi di utilizzare l’ingresso/gateway di Cilium con un bilanciatore del carico, devi utilizzare gli strumenti di quest’ultimo, in genere un controller di ingresso o gateway, per distribuire e gestire l’infrastruttura del sistema del bilanciatore del carico.
Per il traffico ingresso/gateway, Cilium gestisce il traffico di rete principale e l’applicazione delle policy L3/L4, mentre i proxy Envoy integrati elaborano il traffico di rete L7. Con l’ingresso/gateway di Cilium, Envoy è responsabile dell’applicazione delle regole di routing L7, delle policy e della manipolazione delle richieste, della gestione avanzata del traffico come la suddivisione e il mirroring del traffico e della terminazione e origine del TLS. I proxy Envoy di Cilium vengono distribuiti come DaemonSet (cilium-envoy) separato per impostazione predefinita, il che consente a Envoy e all’agente Cilium di essere aggiornati, scalati e gestiti separatamente.
Per ulteriori informazioni su come funzionano l’ingresso di Cilium e il gateway di Cilium, consulta le pagine Cilium Ingress
Confronto tra ingresso e gateway di Cilium
La tabella seguente riassume le funzionalità di ingresso e gateway di Cilium, a partire dalla versione 1.17.x di Cilium.
| Funzionalità | Ingress | Gateway |
|---|---|---|
|
Tipo servizio LoadBalancer |
Sì |
Sì |
|
Tipo servizio NodePort |
Sì |
No1 |
|
Rete host |
Sì |
Sì |
|
Bilanciatore del carico condiviso |
Sì |
Sì |
|
Bilanciatore del carico dedicato |
Sì |
No2 |
|
Policy di rete |
Sì |
Sì |
|
Protocolli |
Livello 7 (HTTP(S), gRPC) |
Livello 7 (HTTP(S), gRPC)3 |
|
TLS Passthrough |
Sì |
Sì |
|
Gestione del traffico |
Routing del percorso e dell’host |
Routing del percorso e dell’host, reindirizzamento e riscrittura degli URL, suddivisione del traffico, modifica dell’intestazione |
1 Il supporto del gateway di Cilium per i servizi NodePort è pianificato per la versione 1.18.x di Cilium (#27273
2 Supporto del gateway di Cilium per bilanciatori del carico dedicati (#25567
3 Supporto del gateway di Cilium per TCP/UDP (#21929
Installazione del gateway di Cilium
Considerazioni
-
Cilium deve essere configurato con
nodePort.enabledimpostato sutruecome mostrato negli esempi seguenti. Se utilizzi la funzionalità di sostituzione kube-proxy di Cilium, non devi impostarenodePort.enabledsutrue. -
Cilium deve essere configurato con
envoy.enabledimpostato sutruecome mostrato negli esempi seguenti. -
Il gateway di Cilium può essere distribuito nel bilanciatore del carico (impostazione predefinita) o in modalità rete host.
-
Quando si utilizza il gateway di Cilium in modalità bilanciatore del carico, l’annotazione
service.beta.kubernetes.io/aws-load-balancer-type: "external"deve essere impostata sulla risorsa del gateway per impedire al provider AWS cloud legacy di creare un Classic Load Balancer per il servizio di tipo LoadBalancer che Cilium crea per la risorsa gateway. -
Quando si utilizza il gateway di Cilium in modalità rete host, il servizio di tipo LoadBalancer è disabilitato. La modalità di rete host è utile per gli ambienti che non dispongono di un’infrastruttura del bilanciatore del carico; per ulteriori informazioni, consulta Rete host.
Prerequisiti
-
Helm è installato nell’ambiente a riga di comando, consulta Setup Helm instructions.
-
Cilium è installato seguendo le istruzioni contenute in Configurazione della CNI per nodi ibridi.
Procedura
-
Installa le definizioni di risorse personalizzate (CDR) dell’API del gateway di Kubernetes.
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.1/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.1/config/crd/standard/gateway.networking.k8s.io_gateways.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.1/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.1/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.2.1/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml -
Crea un file denominato
cilium-gateway-values.yamlcon i seguenti contenuti. L’esempio seguente configura il gateway di Cilium per utilizzare la modalità del bilanciatore del carico predefinita e per utilizzare un proxy DaemonSet for Envoy separatocilium-envoyconfigurato per l’esecuzione solo su nodi ibridi.gatewayAPI: enabled: true # uncomment to use host network mode # hostNetwork: # enabled: true nodePort: enabled: true envoy: enabled: true affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: eks.amazonaws.com/compute-type operator: In values: - hybrid -
Applica il file di valori Helm al cluster.
helm upgrade cilium oci://public.ecr.aws/eks/cilium/cilium \ --namespace kube-system \ --reuse-values \ --set operator.rollOutPods=true \ --values cilium-gateway-values.yaml -
Verifica che l’operatore, l’agente e i pod Envoy Cilium siano in esecuzione.
kubectl -n kube-system get pods --selector=app.kubernetes.io/part-of=ciliumNAME READY STATUS RESTARTS AGE cilium-envoy-5pgnd 1/1 Running 0 6m31s cilium-envoy-6fhg4 1/1 Running 0 6m30s cilium-envoy-jskrk 1/1 Running 0 6m30s cilium-envoy-k2xtb 1/1 Running 0 6m31s cilium-envoy-w5s9j 1/1 Running 0 6m31s cilium-grwlc 1/1 Running 0 4m12s cilium-operator-68f7766967-5nnbl 1/1 Running 0 4m20s cilium-operator-68f7766967-7spfz 1/1 Running 0 4m20s cilium-pnxcv 1/1 Running 0 6m29s cilium-r7qkj 1/1 Running 0 4m12s cilium-wxhfn 1/1 Running 0 4m1s cilium-z7hlb 1/1 Running 0 6m30s
Configurazione del gateway di Cilium
Il gateway di Cilium è abilitato sugli oggetti del gateway impostando gatewayClassName su cilium. Il servizio creato da Cilium per le risorse del gateway può essere configurato con campi sull’oggetto del gateway. Le annotazioni comuni utilizzate dai controller del gateway per configurare l’infrastruttura del bilanciatore del carico possono essere configurate con il campo infrastructure dell’oggetto del gateway. Quando si utilizza LoadBalancer IPAM di Cilium (vedi esempio in Tipo servizio LoadBalancer), l’indirizzo IP da utilizzare per il servizio di tipo LoadBalancer può essere configurato nel campo addresses dell’oggetto del Gateway. Per ulteriori informazioni sulla configurazione del gateway, consulta Kubernetes Gateway API specification
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-gateway spec: gatewayClassName: cilium infrastructure: annotations: service.beta.kubernetes.io/... service.kuberentes.io/... addresses: - type: IPAddress value: <LoadBalancer IP address> listeners: ...
Cilium e le specifiche del gateway di Kubernetes supportano le risorse GatewayClass, Gateway, HTTPRoute, GRPCRroute e ReferenceGrant.
-
Consulta le specifiche HTTPRoute
e GRPCRoute per l’elenco dei campi disponibili. -
Vedi gli esempi nella sezione Implementazione del gateway di Cilium seguente e gli esempi in Cilium documentation
per scoprire come utilizzare e configurare queste risorse.
Implementazione del gateway di Cilium
-
Crea un’applicazione di esempio. L’esempio seguente utilizza l’applicazione di microservizi di esempio Istio Bookinfo
. kubectl apply -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/bookinfo/platform/kube/bookinfo.yaml -
Verifica che l’applicazione sia in esecuzione correttamente.
kubectl get podsNAME READY STATUS RESTARTS AGE details-v1-766844796b-9965p 1/1 Running 0 81s productpage-v1-54bb874995-jmc8j 1/1 Running 0 80s ratings-v1-5dc79b6bcd-smzxz 1/1 Running 0 80s reviews-v1-598b896c9d-vj7gb 1/1 Running 0 80s reviews-v2-556d6457d-xbt8v 1/1 Running 0 80s reviews-v3-564544b4d6-cpmvq 1/1 Running 0 80s -
Crea un file denominato
my-gateway.yamlcon i seguenti contenuti. L’esempio di seguito utilizza l’annotazioneservice.beta.kubernetes.io/aws-load-balancer-type: "external"per impedire al provider AWS cloud legacy di creare un Classic Load Balancer per il servizio di tipo LoadBalancer che Cilium crea per la risorsa gateway.--- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-gateway spec: gatewayClassName: cilium infrastructure: annotations: service.beta.kubernetes.io/aws-load-balancer-type: "external" listeners: - protocol: HTTP port: 80 name: web-gw allowedRoutes: namespaces: from: Same --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-app-1 spec: parentRefs: - name: my-gateway namespace: default rules: - matches: - path: type: PathPrefix value: /details backendRefs: - name: details port: 9080 -
Applica la risorsa del gateway al cluster.
kubectl apply -f my-gateway.yaml -
Conferma che la risorsa del gateway e il servizio corrispondente sono stati creati. In questa fase, si prevede che il campo
ADDRESSdella risorsa del gateway non sia popolato con un indirizzo IP o un nome host e che analogamente al servizio di tipo LoadBalancer per la risorsa del gateway non sia assegnato un indirizzo IP o un nome host.kubectl get gateway my-gatewayNAME CLASS ADDRESS PROGRAMMED AGE my-gateway cilium True 10skubectl get svc cilium-gateway-my-gatewayNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cilium-gateway-my-gateway LoadBalancer 172.16.227.247 <pending> 80:30912/TCP 24s -
Procedi Tipo servizio LoadBalancer per configurare della risorsa del gateway per utilizzare un indirizzo IP allocato dal bilanciatore del carico IPAM di Cilium e Tipo servizio NodePort o Rete host per configurare la risorsa del gateway per utilizzare NodePort o gli indirizzi di rete host.
Installazione dell’ingresso di Cilium
Considerazioni
-
Cilium deve essere configurato con
nodePort.enabledimpostato sutruecome mostrato negli esempi seguenti. Se utilizzi la funzionalità di sostituzione kube-proxy di Cilium, non devi impostarenodePort.enabledsutrue. -
Cilium deve essere configurato con
envoy.enabledimpostato sutruecome mostrato negli esempi seguenti. -
Con
ingressController.loadbalancerModeimpostato sudedicated, Cilium crea servizi dedicati per ogni risorsa dell’ingresso. ConingressController.loadbalancerModeimpostato sushared, Cilium crea un servizio condiviso di tipo LoadBalancer per tutte le risorse dell’ingresso nel cluster. Quando si utilizza la modalità del bilanciatore del caricoshared, le impostazioni per il servizio condiviso comelabels,annotations,typeeloadBalancerIPsono configurate nella sezione dei valori HelmingressController.service. Per ulteriori informazioni, consulta Cilium Helm values reference. -
Con
ingressController.defaultimpostato sutrue, Cilium è configurato come controller di ingresso predefinito per il cluster e creerà voci di ingresso anche quandoingressClassNamenon è specificato nelle risorse di ingresso. -
L’ingresso di Cilium può essere distribuito nel bilanciatore del carico (impostazione predefinita), nella porta del nodo o in modalità rete host. Quando Cilium è installato in modalità rete host, il servizio di tipo LoadBalancer e il servizio di tipo NodePort sono disabilitati. Per ulteriori informazioni, consulta Rete host.
-
Imposta sempre
ingressController.service.annotationssuservice.beta.kubernetes.io/aws-load-balancer-type: "external"nei valori Helm per impedire al provider AWS cloud legacy di creare un Classic Load Balancer per il serviziocilium-ingresspredefinito creato dal grafico Helm di Cilium.
Prerequisiti
-
Helm è installato nell’ambiente a riga di comando, consulta Setup Helm instructions.
-
Cilium è installato seguendo le istruzioni contenute in Configurazione della CNI per nodi ibridi.
Procedura
-
Crea un file denominato
cilium-ingress-values.yamlcon i seguenti contenuti. L’esempio seguente configura l’ingresso di Cilium per utilizzare la modalitàdedicateddel bilanciatore del carico predefinita e per utilizzare un proxy DaemonSet for Envoy separatocilium-envoyconfigurato per l’esecuzione solo su nodi ibridi.ingressController: enabled: true loadbalancerMode: dedicated service: annotations: service.beta.kubernetes.io/aws-load-balancer-type: "external" nodePort: enabled: true envoy: enabled: true affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: eks.amazonaws.com/compute-type operator: In values: - hybrid -
Applica il file di valori Helm al cluster.
helm upgrade cilium oci://public.ecr.aws/eks/cilium/cilium \ --namespace kube-system \ --reuse-values \ --set operator.rollOutPods=true \ --values cilium-ingress-values.yaml -
Verifica che l’operatore, l’agente e i pod Envoy Cilium siano in esecuzione.
kubectl -n kube-system get pods --selector=app.kubernetes.io/part-of=ciliumNAME READY STATUS RESTARTS AGE cilium-envoy-5pgnd 1/1 Running 0 6m31s cilium-envoy-6fhg4 1/1 Running 0 6m30s cilium-envoy-jskrk 1/1 Running 0 6m30s cilium-envoy-k2xtb 1/1 Running 0 6m31s cilium-envoy-w5s9j 1/1 Running 0 6m31s cilium-grwlc 1/1 Running 0 4m12s cilium-operator-68f7766967-5nnbl 1/1 Running 0 4m20s cilium-operator-68f7766967-7spfz 1/1 Running 0 4m20s cilium-pnxcv 1/1 Running 0 6m29s cilium-r7qkj 1/1 Running 0 4m12s cilium-wxhfn 1/1 Running 0 4m1s cilium-z7hlb 1/1 Running 0 6m30s
Configurazione dell’ingresso di Cilium
L’ingresso di Cilium è abilitato sugli oggetti dell’ingresso impostando ingressClassName su cilium. I servizi che Cilium crea per le risorse dell’ingresso possono essere configurati con annotazioni sugli oggetti dell’ingresso quando si utilizza la modalità del bilanciatore del carico dedicated e nella configurazione Cilium/Helm quando si utilizza la modalità del bilanciatore del carico shared. Queste annotazioni vengono comunemente utilizzate dai controller dell’ingresso per configurare l’infrastruttura del bilanciatore del carico o altri attributi del Servizio come il tipo di servizio, la modalità del bilanciatore del carico, le porte e il passthrough TLS. Le annotazioni chiave sono descritte di seguito. Per un elenco completo delle annotazioni supportate, consulta Cilium Ingress annotations
| Annotazione | Descrizione |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
Elenco di indirizzi IP da allocare da Cilium LoadBalancer IPAM |
Cilium e le specifiche dell’ingresso di Kubernetes supportano regole di corrispondenza specifiche per Exact, Prefix e Implementation per i percorsi dell’ingresso. Cilium supporta l’espressione regolare come regola di corrispondenza specifica per l’implementazione. Per ulteriori informazioni, consulta Ingress path types and precedence
Un esempio di oggetto dell’ingresso di Cilium è mostrato di seguito.
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress annotations: service.beta.kuberentes.io/... service.kuberentes.io/... spec: ingressClassName: cilium rules: ...
Implementazione dell’ingresso di Cilium
-
Crea un’applicazione di esempio. L’esempio seguente utilizza l’applicazione di microservizi di esempio Istio Bookinfo
. kubectl apply -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/bookinfo/platform/kube/bookinfo.yaml -
Verifica che l’applicazione sia in esecuzione correttamente.
kubectl get podsNAME READY STATUS RESTARTS AGE details-v1-766844796b-9965p 1/1 Running 0 81s productpage-v1-54bb874995-jmc8j 1/1 Running 0 80s ratings-v1-5dc79b6bcd-smzxz 1/1 Running 0 80s reviews-v1-598b896c9d-vj7gb 1/1 Running 0 80s reviews-v2-556d6457d-xbt8v 1/1 Running 0 80s reviews-v3-564544b4d6-cpmvq 1/1 Running 0 80s -
Crea un file denominato
my-ingress.yamlcon i seguenti contenuti. L’esempio seguente utilizza l’annotazioneservice.beta.kubernetes.io/aws-load-balancer-type: "external"per impedire al provider AWS cloud legacy di creare un Classic Load Balancer per il servizio di tipo LoadBalancer creato da Cilium per la risorsa dell’ingresso.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress namespace: default annotations: service.beta.kubernetes.io/aws-load-balancer-type: "external" spec: ingressClassName: cilium rules: - http: paths: - backend: service: name: details port: number: 9080 path: /details pathType: Prefix -
Applica la risorsa dell’ingresso al cluster.
kubectl apply -f my-ingress.yaml -
Conferma che la risorsa dell’ingresso e il servizio corrispondente sono stati creati. In questa fase, si prevede che il campo
ADDRESSdella risorsa dell’ingresso non sia popolato con un indirizzo IP o un nome host e che analogamente al servizio di tipo LoadBalancer condiviso o dedicato per la risorsa dell’ingresso non sia assegnato un indirizzo IP o un nome host.kubectl get ingress my-ingressNAME CLASS HOSTS ADDRESS PORTS AGE my-ingress cilium * 80 8sPer la modalità del bilanciatore del carico
sharedkubectl -n kube-system get svc cilium-ingressNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cilium-ingress LoadBalancer 172.16.217.48 <pending> 80:32359/TCP,443:31090/TCP 10mPer la modalità del bilanciatore del carico
dedicatedkubectl -n default get svc cilium-ingress-my-ingressNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cilium-ingress-my-ingress LoadBalancer 172.16.193.15 <pending> 80:32088/TCP,443:30332/TCP 25s -
Procedi con Tipo servizio LoadBalancer per configurare la risorsa dell’ingresso per utilizzare un indirizzo IP allocato dal bilanciatore del carico IPAM di Cilium e Tipo servizio NodePort o Rete host per configurare la risorsa dell’ingresso per utilizzare NodePort o gli indirizzi di rete host.
Tipo servizio LoadBalancer
Infrastruttura del bilanciatore del carico esistente
Per impostazione predefinita, sia per l’ingresso che per il gateway di Cilium, quest’ultimo crea uno o più servizi Kubernetes di tipo LoadBalancer per le risorse ingresso/gateway. Gli attributi dei Servizi creati da Cilium possono essere configurati tramite le risorse dell’ingresso e del gateway. Quando crei risorse ingresso o gateway, l’indirizzo IP o i nomi host esposti esternamente per ingresso o gateway vengono allocati dall’infrastruttura del bilanciatore del carico, che in genere viene fornita da un controller di ingresso o gateway.
Molti controller dell’ingresso e del gateway utilizzano le annotazioni per rilevare e configurare l’infrastruttura del bilanciatore del carico. Le annotazioni per questi controller dell’ingresso e del gateway sono configurate sulle risorse dell’ingresso o del gateway come mostrato negli esempi precedenti. Fai riferimento alla documentazione del controller dell’ingresso o del gateway per le annotazioni che supporta e consulta Kubernetes Ingress documentation
Importante
L’ingresso e il gateway di Cilium non possono essere utilizzati con il controller del bilanciatore del carico AWS e i Network Load Balancer (NLB) AWS con nodi ibridi EKS. Il tentativo di utilizzarli insieme porta a destinazioni non registrate, poiché l’NLB tenta di connettersi direttamente agli IP del Pod che supportano il servizio di tipo LoadBalancer quando l’NLB target-type è impostato su ip (requisito per l’utilizzo di NLB con carichi di lavoro in esecuzione su nodi ibridi EKS).
Nessuna infrastruttura del bilanciatore del carico
Se non disponi dell’infrastruttura del bilanciatore del carico e del corrispondente controller ingresso/gateway nel proprio ambiente, le risorse ingresso/gateway e i servizi corrispondenti di tipo LoadBalancer possono essere configurati per utilizzare gli indirizzi IP allocati dalla gestione degli indirizzi IP del bilanciatore del carico
L’esempio seguente mostra come configurare l’IPAM LB di Cilium con un indirizzo IP da utilizzare per le risorse ingresso/gateway e come configurare il piano di controllo di Cilium BGP per pubblicizzare l’indirizzo IP LoadBalancer con la rete on-premises. La funzionalità LB IPAM di Cilium è abilitata per impostazione predefinita, ma non viene attivata finché non viene creata una risorsa CiliumLoadBalancerIPPool.
Prerequisiti
-
Ingresso e gateway di Cilium installati seguendo le istruzioni in Installazione dell’ingresso di Cilium o Installazione del gateway di Cilium.
-
Risorse dell’ingresso o del gateway di Cilium con applicazione di esempio distribuita seguendo le istruzioni in Implementazione dell’ingresso di Cilium o Implementazione del gateway di Cilium.
-
Il piano di controllo BGP di Cilium è abilitato seguendo le istruzioni contenute in Configurazione di Cilium BGP per nodi ibridi. Se non desideri utilizzare BGP, puoi saltare questo prerequisito, ma non sarai in grado di accedere alla tua risorsa dell’ingresso o del gateway finché l’indirizzo IP LoadBalancer allocato da Cilium LB IPAM non sarà instradabile sulla tua rete on-premises.
Procedura
-
Facoltativamente, applica una patch alla risorsa dell’ingresso o del gateway per richiedere un indirizzo IP specifico da utilizzare per il servizio di tipo LoadBalancer. Se non richiedi un indirizzo IP specifico, Cilium ne assegnerà uno dall’intervallo di indirizzi IP configurato nella risorsa
CiliumLoadBalancerIPPoolnel passaggio successivo. Nei comandi seguenti, sostituisciLB_IP_ADDRESScon l’indirizzo IP da richiedere per il servizio di tipo LoadBalancer.Gateway
kubectl patch gateway -n default my-gateway --type=merge -p '{ "spec": { "addresses": [{"type": "IPAddress", "value": "LB_IP_ADDRESS"}] } }'Ingresso
kubectl patch ingress my-ingress --type=merge -p '{ "metadata": {"annotations": {"lbipam.cilium.io/ips": "LB_IP_ADDRESS"}} }' -
Crea un file denominato
cilium-lbip-pool-ingress.yamlcon una risorsaCiliumLoadBalancerIPPoolper configurare l’intervallo di indirizzi IP del bilanciatore del carico per le tue risorse ingresso/gateway.-
Se utilizzi l’ingresso di Cilium, Cilium applica automaticamente l’etichetta
cilium.io/ingress: "true"ai Servizi che crea per le risorse dell’ingresso. Puoi utilizzare questa etichetta nel camposerviceSelectordella definizione delle risorseCiliumLoadBalancerIPPoolper selezionare i Servizi idonei per LB IPAM. -
Se utilizzi il gateway di Cilium, puoi usare l’etichetta
gateway.networking.k8s.io/gateway-namenei campiserviceSelectordella definizione delle risorse per selezionare le risorseCiliumLoadBalancerIPPoolgateway idonee per LB IPAM. -
Sostituisci
LB_IP_CIDRcon l’intervallo di indirizzi IP da utilizzare per quelli del bilanciatore del carico. Per selezionare un singolo indirizzo IP, utilizza un CIDR/32. Per ulteriori informazioni, consulta LoadBalancer IP Address Managementnella documentazione di Cilium. apiVersion: cilium.io/v2alpha1 kind: CiliumLoadBalancerIPPool metadata: name: bookinfo-pool spec: blocks: - cidr: "LB_IP_CIDR" serviceSelector: # if using Cilium Gateway matchExpressions: - { key: gateway.networking.k8s.io/gateway-name, operator: In, values: [ my-gateway ] } # if using Cilium Ingress matchLabels: cilium.io/ingress: "true"
-
-
Applica la risorsa
CiliumLoadBalancerIPPoolal cluster.kubectl apply -f cilium-lbip-pool-ingress.yaml -
Conferma che un indirizzo IP è stato allocato da Cilium LB IPAM per la risorsa dell’ingresso/gateway.
Gateway
kubectl get gateway my-gatewayNAME CLASS ADDRESS PROGRAMMED AGE my-gateway ciliumLB_IP_ADDRESSTrue 6m41sIngresso
kubectl get ingress my-ingressNAME CLASS HOSTS ADDRESS PORTS AGE my-ingress cilium *LB_IP_ADDRESS80 10m -
Crea un file denominato
cilium-bgp-advertisement-ingress.yamlcon una risorsaCiliumBGPAdvertisementper pubblicizzare l’intervallo di indirizzi IP del LoadBalancer per le risorse dell’ingresso/gateway. Se non utilizzi un proxy, puoi ignorare questo passaggio. L’indirizzo IP LoadBalancer utilizzato per la risorsa dell’ingresso/gateway deve essere instradabile sulla rete on-premises per poter interrogare il servizio nel passaggio successivo.apiVersion: cilium.io/v2alpha1 kind: CiliumBGPAdvertisement metadata: name: bgp-advertisement-lb-ip labels: advertise: bgp spec: advertisements: - advertisementType: "Service" service: addresses: - LoadBalancerIP selector: # if using Cilium Gateway matchExpressions: - { key: gateway.networking.k8s.io/gateway-name, operator: In, values: [ my-gateway ] } # if using Cilium Ingress matchLabels: cilium.io/ingress: "true" -
Applica la risorsa
CiliumBGPAdvertisemental cluster.kubectl apply -f cilium-bgp-advertisement-ingress.yaml -
Accedi al servizio utilizzando l’indirizzo IP assegnato da Cilium LB IPAM.
curl -s http://LB_IP_ADDRESS:80/details/1 | jq{ "id": 1, "author": "William Shakespeare", "year": 1595, "type": "paperback", "pages": 200, "publisher": "PublisherA", "language": "English", "ISBN-10": "1234567890", "ISBN-13": "123-1234567890" }
Tipo servizio NodePort
Se non disponi dell’infrastruttura del bilanciatore del carico e del controller dell’ingresso corrispondente nel tuo ambiente, o se gestisci autonomamente la tua infrastruttura del bilanciatore del carico o utilizzi il bilanciatore del carico basato su DNS, puoi configurare l’ingresso di Cilium per creare Servizi di tipo NodePort per le risorse dell’ingresso. Quando si utilizza NodePort con l’ingresso di Cilium, il servizio di tipo NodePort è esposto su una porta su ciascun nodo nell’intervallo di porte 30000-32767. In questa modalità, quando il traffico raggiunge qualsiasi nodo del cluster su NodePort, viene quindi inoltrato a un pod che supporta il servizio, che può trovarsi sullo stesso nodo o su un nodo diverso.
Nota
Il supporto del gateway di Cilium per i servizi NodePort è pianificato per la versione 1.18.x di Cilium (#27273
Prerequisiti
-
Ingresso di Cilium installato seguendo le istruzioni in Installazione dell’ingresso di Cilium.
-
Risorse dell’ingresso di Cilium con applicazione di esempio distribuita seguendo le istruzioni in Implementazione dell’ingresso di Cilium.
Procedura
-
Applica una patch alla risorsa dell’ingresso
my-ingressesistente per cambiarla dal tipo di servizio LoadBalancer a NodePort.kubectl patch ingress my-ingress --type=merge -p '{ "metadata": {"annotations": {"ingress.cilium.io/service-type": "NodePort"}} }'Se non hai creato la risorsa dell’ingresso, puoi crearla applicando la seguente definizione dell’ingresso al tuo cluster. Nota, la definizione dell’ingresso riportata di seguito utilizza l’applicazione di esempio Istio Bookinfo descritta in Implementazione dell’ingresso di Cilium.
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress namespace: default annotations: service.beta.kubernetes.io/aws-load-balancer-type: "external" "ingress.cilium.io/service-type": "NodePort" spec: ingressClassName: cilium rules: - http: paths: - backend: service: name: details port: number: 9080 path: /details pathType: Prefix -
Conferma che la risorsa del servizio per l’ingresso è stata aggiornata per utilizzare il tipo di servizio NodePort. Nota la porta per il protocollo HTTP nell’output. Nell’esempio seguente, questa è la porta HTTP
32353, che verrà utilizzata in un passaggio successivo per interrogare il servizio. Il vantaggio dell’utilizzo dell’ingresso di Cilium con il servizio di tipo NodePort è che puoi applicare il routing basato su percorso e host, nonché policy di rete per il traffico in ingresso, cosa che non puoi fare per un servizio standard di tipo NodePort senza l’ingresso.kubectl -n default get svc cilium-ingress-my-ingressNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cilium-ingress-my-ingress NodePort 172.16.47.153 <none> 80:32353/TCP,443:30253/TCP 27m -
Ottieni l’indirizzo IP dei nodi nel cluster.
kubectl get nodes -o wideNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME mi-026d6a261e355fba7 Ready <none> 23h v1.32.3-eks-473151a 10.80.146.150 <none> Ubuntu 22.04.5 LTS 5.15.0-142-generic containerd://1.7.27 mi-082f73826a163626e Ready <none> 23h v1.32.3-eks-473151a 10.80.146.32 <none> Ubuntu 22.04.4 LTS 5.15.0-142-generic containerd://1.7.27 mi-09183e8a3d755abf6 Ready <none> 23h v1.32.3-eks-473151a 10.80.146.33 <none> Ubuntu 22.04.4 LTS 5.15.0-142-generic containerd://1.7.27 mi-0d78d815980ed202d Ready <none> 23h v1.32.3-eks-473151a 10.80.146.97 <none> Ubuntu 22.04.4 LTS 5.15.0-142-generic containerd://1.7.27 mi-0daa253999fe92daa Ready <none> 23h v1.32.3-eks-473151a 10.80.146.100 <none> Ubuntu 22.04.4 LTS 5.15.0-142-generic containerd://1.7.27 -
Accedi al servizio di tipo NodePort utilizzando gli indirizzi IP dei tuoi nodi e il NodePort catturato sopra. Nell’esempio seguente l’indirizzo IP del nodo utilizzato è
10.80.146.32e il NodePort è32353. Sostituisci questi valori per il tuo ambiente.curl -s http://10.80.146.32:32353/details/1 | jq{ "id": 1, "author": "William Shakespeare", "year": 1595, "type": "paperback", "pages": 200, "publisher": "PublisherA", "language": "English", "ISBN-10": "1234567890", "ISBN-13": "123-1234567890" }
Rete host
Analogamente al servizio di tipo NodePort, se non disponi di un’infrastruttura del bilanciatore del carico e di un controller dell’ingresso o del gateway, o se gestisci automaticamente il bilanciatore del carico con un bilanciatore del carico esterno, puoi configurare l’ingresso di Cilium e il gateway di Cilium per esporre le risorse dell’ingresso e del gateway direttamente sulla rete host. Quando la modalità di rete host è abilitata per una risorsa dell’ingresso o del gateway, le modalità Service di tipo LoadBalancer e NodePort vengono disabilitate automaticamente, la modalità di rete host si esclude a vicenda con queste modalità alternative per ogni risorsa dell’ingresso o del gateway. Rispetto al servizio di tipo NodePort, la modalità di rete host offre una maggiore flessibilità per la gamma di porte che possono essere utilizzate (non è limitata all’intervallo NodePort 30000-32767) ed è possibile configurare un sottoinsieme di nodi in cui i proxy Envoy vengono eseguiti sulla rete host.
Prerequisiti
-
Ingresso e gateway di Cilium installati seguendo le istruzioni in Installazione dell’ingresso di Cilium o Installazione del gateway di Cilium.
Procedura
Gateway
-
Creare un archivio denominato
cilium-gateway-host-network.yamlcon i seguenti contenuti.gatewayAPI: enabled: true hostNetwork: enabled: true # uncomment to restrict nodes where Envoy proxies run on the host network # nodes: # matchLabels: # role: gateway -
Applica la configurazione del gateway di Cilium della rete host al cluster.
helm upgrade cilium oci://public.ecr.aws/eks/cilium/cilium \ --namespace kube-system \ --reuse-values \ --set operator.rollOutPods=true \ -f cilium-gateway-host-network.yamlSe non hai creato la risorsa del gateway, puoi crearla applicando la seguente definizione di gateway al tuo cluster. La definizione del gateway riportata di seguito utilizza l’applicazione di esempio Istio Bookinfo descritta in Implementazione del gateway di Cilium. Nell’esempio seguente, la risorsa del gateway è configurata per utilizzare la porta
8111per il listener HTTP, che è la porta listener condivisa per i proxy Envoy in esecuzione sulla rete host. Se stai utilizzando una porta privilegiata (inferiore a 1023) per la risorsa del gateway, fai riferimento a Cilium documentationper le istruzioni. --- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-gateway spec: gatewayClassName: cilium listeners: - protocol: HTTP port: 8111 name: web-gw allowedRoutes: namespaces: from: Same --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-app-1 spec: parentRefs: - name: my-gateway namespace: default rules: - matches: - path: type: PathPrefix value: /details backendRefs: - name: details port: 9080Puoi osservare la configurazione Cilium Envoy applicata con il seguente comando.
kubectl get cec cilium-gateway-my-gateway -o yamlPuoi ottenere la porta del listener Envoy per il servizio
cilium-gateway-my-gatewaycon il seguente comando. In questo esempio, la porta del listener condiviso è8111.kubectl get cec cilium-gateway-my-gateway -o jsonpath={.spec.services[0].ports[0]} -
Ottieni l’indirizzo IP dei nodi nel cluster.
kubectl get nodes -o wideNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME mi-026d6a261e355fba7 Ready <none> 23h v1.32.3-eks-473151a 10.80.146.150 <none> Ubuntu 22.04.5 LTS 5.15.0-142-generic containerd://1.7.27 mi-082f73826a163626e Ready <none> 23h v1.32.3-eks-473151a 10.80.146.32 <none> Ubuntu 22.04.4 LTS 5.15.0-142-generic containerd://1.7.27 mi-09183e8a3d755abf6 Ready <none> 23h v1.32.3-eks-473151a 10.80.146.33 <none> Ubuntu 22.04.4 LTS 5.15.0-142-generic containerd://1.7.27 mi-0d78d815980ed202d Ready <none> 23h v1.32.3-eks-473151a 10.80.146.97 <none> Ubuntu 22.04.4 LTS 5.15.0-142-generic containerd://1.7.27 mi-0daa253999fe92daa Ready <none> 23h v1.32.3-eks-473151a 10.80.146.100 <none> Ubuntu 22.04.4 LTS 5.15.0-142-generic containerd://1.7.27 -
Accedi al servizio utilizzando gli indirizzi IP dei nodi e la porta del listener per la risorsa
cilium-gateway-my-gateway. Nell’esempio seguente l’indirizzo IP del nodo utilizzato è10.80.146.32e la porta del listener è8111. Sostituisci questi valori per il tuo ambiente.curl -s http://10.80.146.32:8111/details/1 | jq{ "id": 1, "author": "William Shakespeare", "year": 1595, "type": "paperback", "pages": 200, "publisher": "PublisherA", "language": "English", "ISBN-10": "1234567890", "ISBN-13": "123-1234567890" }
Ingress
A causa di un problema con Cilium upstream (#34028loadbalancerMode: shared, che crea un unico servizio di tipo ClusterIP per tutte le risorse dell’ingresso nel cluster. Se stai utilizzando una porta privilegiata (inferiore a 1023) per la risorsa dell’ingresso, fai riferimento a Cilium documentation
-
Crea un archivio denominato
cilium-ingress-host-network.yamlcon i seguenti contenuti.ingressController: enabled: true loadbalancerMode: shared # This is a workaround for the upstream Cilium issue service: externalTrafficPolicy: null type: ClusterIP hostNetwork: enabled: true # ensure the port does not conflict with other services on the node sharedListenerPort: 8111 # uncomment to restrict nodes where Envoy proxies run on the host network # nodes: # matchLabels: # role: ingress -
Applica la configurazione dell’ingresso di Cilium della rete host al tuo cluster.
helm upgrade cilium oci://public.ecr.aws/eks/cilium/cilium \ --namespace kube-system \ --reuse-values \ --set operator.rollOutPods=true \ -f cilium-ingress-host-network.yamlSe non hai creato la risorsa dell’ingresso, puoi crearla applicando la seguente definizione dell’ingresso al tuo cluster. La definizione dell’ingresso riportata di seguito utilizza l’applicazione di esempio Istio Bookinfo descritta in Implementazione dell’ingresso di Cilium.
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress namespace: default spec: ingressClassName: cilium rules: - http: paths: - backend: service: name: details port: number: 9080 path: /details pathType: PrefixPuoi osservare la configurazione Cilium Envoy applicata con il seguente comando.
kubectl get cec -n kube-system cilium-ingress -o yamlPuoi ottenere la porta del listener Envoy per il servizio
cilium-ingresscon il seguente comando. In questo esempio, la porta del listener condiviso è8111.kubectl get cec -n kube-system cilium-ingress -o jsonpath={.spec.services[0].ports[0]} -
Ottieni l’indirizzo IP dei nodi nel cluster.
kubectl get nodes -o wideNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME mi-026d6a261e355fba7 Ready <none> 23h v1.32.3-eks-473151a 10.80.146.150 <none> Ubuntu 22.04.5 LTS 5.15.0-142-generic containerd://1.7.27 mi-082f73826a163626e Ready <none> 23h v1.32.3-eks-473151a 10.80.146.32 <none> Ubuntu 22.04.4 LTS 5.15.0-142-generic containerd://1.7.27 mi-09183e8a3d755abf6 Ready <none> 23h v1.32.3-eks-473151a 10.80.146.33 <none> Ubuntu 22.04.4 LTS 5.15.0-142-generic containerd://1.7.27 mi-0d78d815980ed202d Ready <none> 23h v1.32.3-eks-473151a 10.80.146.97 <none> Ubuntu 22.04.4 LTS 5.15.0-142-generic containerd://1.7.27 mi-0daa253999fe92daa Ready <none> 23h v1.32.3-eks-473151a 10.80.146.100 <none> Ubuntu 22.04.4 LTS 5.15.0-142-generic containerd://1.7.27 -
Accedi al servizio utilizzando gli indirizzi IP dei tuoi nodi e la
sharedListenerPortper la risorsacilium-ingress. Nell’esempio seguente l’indirizzo IP del nodo utilizzato è10.80.146.32e la porta del listener è8111. Sostituisci questi valori per il tuo ambiente.curl -s http://10.80.146.32:8111/details/1 | jq{ "id": 1, "author": "William Shakespeare", "year": 1595, "type": "paperback", "pages": 200, "publisher": "PublisherA", "language": "English", "ISBN-10": "1234567890", "ISBN-13": "123-1234567890" }