Obiettivi
- Configura l'infrastruttura per l'esecuzione di Anthos Service Mesh:
- Rete VPC personalizzata e subnet privata
- Cloud NAT per l'accesso a Internet
- Cluster GKE privato con un pool di nodi aggiuntivo per i pod del gateway in uscita
- Regole firewall VPC in uscita restrittive; solo i nodi gateway possono raggiungere gli host esterni
- Accesso privato Google per la connessione a Container Registry e alle API di Google
- Installare Anthos Service Mesh con gateway in uscita in esecuzione su un pool di nodi dedicato.
- Configura le regole di routing multi-tenant per il traffico esterno attraverso il gateway in uscita:
- Le applicazioni nello spazio dei nomi 'team-x' possono connettersi a example.com
- Applicazioni nello spazio dei nomi 'team-y' possono connettersi a httpbin.org
- Utilizza la risorsa
Sidecar
per limitare l'ambito della configurazione del traffico in uscita del proxy sidecar per ogni spazio dei nomi. - Configura i criteri di autorizzazione per l'applicazione forzata delle regole in uscita.
- Configura il gateway in uscita per eseguire l'upgrade delle richieste HTTP semplici a TLS (origine TLS).
- Configura il gateway in uscita per il pass-through del traffico TLS.
- Configura i criteri di rete di Kubernetes come controllo aggiuntivo in uscita.
- Configurare l'accesso diretto alle API di Google utilizzando le autorizzazioni accesso privato Google e Identity and Access Management (IAM).
Costi
Questo tutorial utilizza i seguenti componenti fatturabili di Google Cloud:
- Compute Engine
- Google Kubernetes Engine (GKE)
- Container Registry
- Anthos Service Mesh
- Cloud Load Balancing
- Cloud NAT
- Networking
- Cloud Storage
Per generare una stima dei costi in base all'utilizzo previsto,
utilizza il Calcolatore prezzi.
Al termine di questo tutorial, puoi evitare costi continui eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la sezione Pulizia.
Prima di iniziare
-
Nella pagina del selettore dei progetti in Google Cloud Console, seleziona o crea un progetto Google Cloud.
-
Assicurati che la fatturazione sia attivata per il tuo progetto Cloud. Scopri come verificare se la fatturazione è abilitata su un progetto.
-
In Cloud Console, attiva Cloud Shell.
Crea una directory di lavoro da utilizzare durante il tutorial:
mkdir -p ~/WORKING_DIRECTORY cd ~/WORKING_DIRECTORY
Crea uno script shell per inizializzare il tuo ambiente per il tutorial. Sostituisci e modifica le variabili in base al progetto e alle preferenze. Esegui questo script con il comando
source
per inizializzare nuovamente l'ambiente se la sessione della shell scade:cat << 'EOF' > ./init-egress-tutorial.sh #! /usr/bin/env bash PROJECT_ID=YOUR_PROJECT_ID REGION=REGION ZONE=ZONE gcloud config set project ${PROJECT_ID} gcloud config set compute/region ${REGION} gcloud config set compute/zone ${ZONE} EOF
Rendi lo script eseguibile ed eseguilo con il comando
source
per inizializzare il tuo ambiente:chmod +x ./init-egress-tutorial.sh source ./init-egress-tutorial.sh
Imposta i ruoli IAM necessari. Se sei un proprietario del progetto, disponi di tutte le autorizzazioni necessarie per completare l'installazione. Se non sei un proprietario del progetto, chiedi all'amministratore di concederti i seguenti ruoli IAM. Nel comando seguente, modifica PROJECT_EMAIL_ADDRESS nell'account che utilizzi per accedere a Google Cloud.
gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member user:PROJECT_EMAIL_ADDRESS \ --role=roles/editor \ --role=roles/compute.admin \ --role=roles/container.admin \ --role=roles/resourcemanager.projectIamAdmin \ --role=roles/iam.serviceAccountAdmin \ --role=roles/iam.serviceAccountKeyAdmin \ --role=roles/gkehub.admin \ --role=roles/serviceusage.serviceUsageAdmin
Abilita le API necessarie per il tutorial:
gcloud services enable \ dns.googleapis.com \ container.googleapis.com \ compute.googleapis.com \ monitoring.googleapis.com \ logging.googleapis.com \ cloudtrace.googleapis.com \ meshca.googleapis.com \ meshtelemetry.googleapis.com \ meshconfig.googleapis.com \ iamcredentials.googleapis.com \ gkeconnect.googleapis.com \ gkehub.googleapis.com \ cloudresourcemanager.googleapis.com \ stackdriver.googleapis.com
L'abilitazione delle API può richiedere un minuto o più. Quando le API sono abilitate, viene visualizzato un output simile al seguente:
Operation "operations/acf.601db672-88e6-4f98-8ceb-aa3b5725533c" finished successfully.
Configurazione dell'infrastruttura
Crea una rete VPC e una subnet
Crea una nuova rete VPC:
gcloud compute networks create vpc-network \ --subnet-mode custom
Crea una subnet in cui eseguire il cluster con intervalli di indirizzi IP secondari preassegnati per pod e servizi. L'accesso privato Google è abilitato in modo che le applicazioni con solo indirizzi IP interni possano raggiungere le API e i servizi Google:
gcloud compute networks subnets create subnet-gke \ --network vpc-network \ --range 10.0.0.0/24 \ --secondary-range pods=10.1.0.0/16,services=10.2.0.0/20 \ --enable-private-ip-google-access
Configurazione di Cloud NAT
Cloud NAT consente ai carichi di lavoro senza indirizzi IP esterni di connettersi a destinazioni su Internet e ricevere risposte in entrata da tali destinazioni.
Crea un router Cloud:
gcloud compute routers create nat-router \ --network vpc-network
Aggiungi una configurazione NAT al router:
gcloud compute routers nats create nat-config \ --router nat-router \ --nat-all-subnet-ip-ranges \ --auto-allocate-nat-external-ips
Crea account di servizio per ogni pool di nodi GKE
Crea due account di servizio che devono essere utilizzati dai due pool di nodi GKE. A ogni pool di nodi viene assegnato un account di servizio separato in modo da poter applicare le regole del firewall VPC a nodi specifici.
Crea un account di servizio che deve essere utilizzato dai nodi nel pool di nodi predefinito:
gcloud iam service-accounts create sa-application-nodes \ --description="SA for application nodes" \ --display-name="sa-application-nodes"
Crea un account di servizio che deve essere utilizzato dai nodi nel pool di nodi gateway:
gcloud iam service-accounts create sa-gateway-nodes \ --description="SA for gateway nodes" \ --display-name="sa-gateway-nodes"
Concedere autorizzazioni agli account di servizio
Aggiungi un insieme minimo di ruoli IAM agli account di servizio dell'applicazione e del gateway. Questi ruoli sono necessari per il logging, il monitoraggio e il pull di immagini container private da Container Registry.
project_roles=(
roles/logging.logWriter
roles/monitoring.metricWriter
roles/monitoring.viewer
roles/storage.objectViewer
)
for role in "${project_roles[@]}"
do
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:sa-application-nodes@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="$role"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:sa-gateway-nodes@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="$role"
done
Creazione delle regole firewall
Nei passaggi seguenti, applichi una regola firewall alla rete VPC in modo che, per impostazione predefinita, tutto il traffico in uscita venga negato. È necessaria una connettività specifica per consentire al funzionamento del cluster e ai nodi del gateway di raggiungere destinazioni esterne al VPC. Per consentire la connettività necessaria, un insieme minimo di regole firewall specifiche sostituisce la regola predefinita di rifiuto.
Crea una regola firewall predefinita (bassa priorità) per rifiutare tutto il traffico in uscita dalla rete VPC:
gcloud compute firewall-rules create global-deny-egress-all \ --action DENY \ --direction EGRESS \ --rules all \ --destination-ranges 0.0.0.0/0 \ --network vpc-network \ --priority 65535 \ --description "Default rule to deny all egress from the network."
Crea una regola per consentire solo a tali nodi con l'account di servizio gateway di accedere a Internet:
gcloud compute firewall-rules create gateway-allow-egress-web \ --action ALLOW \ --direction EGRESS \ --rules tcp:80,tcp:443 \ --target-service-accounts sa-gateway-nodes@${PROJECT_ID}.iam.gserviceaccount.com \ --network vpc-network \ --priority 1000 \ --description "Allow the nodes running the egress gateways to connect to the web"
Consenti ai nodi di raggiungere il piano di controllo Kubernetes:
gcloud compute firewall-rules create allow-egress-to-api-server \ --action ALLOW \ --direction EGRESS \ --rules tcp:443,tcp:10250 \ --destination-ranges 10.5.0.0/28 \ --network vpc-network \ --priority 1000 \ --description "Allow nodes to reach the Kubernetes API server."
Anthos Service Mesh utilizza i webhook durante l'inserimento di proxy sidecar nei carichi di lavoro. Consenti al server API GKE di chiamare i webhook esposti dal piano di controllo del mesh di servizi in esecuzione sui nodi:
gcloud compute firewall-rules create allow-ingress-api-server-to-webhook \ --action ALLOW \ --direction INGRESS \ --rules tcp:15017 \ --source-ranges 10.5.0.0/28 \ --network vpc-network \ --priority 1000 \ --description "Allow the API server to call the webhooks exposed by istiod discovery"
Consenti la connettività in uscita tra pod e servizi in esecuzione sul cluster. Ricorda che GKE crea automaticamente una regola in entrata corrispondente.
gcloud compute firewall-rules create allow-egress-pods-and-services \ --action ALLOW \ --direction EGRESS \ --rules all \ --destination-ranges 10.1.0.0/16,10.2.0.0/20 \ --network vpc-network \ --priority 1000 \ --description "Allow pods and services on nodes to reach each other"
Un servizio chiamato Calico fornisce funzionalità API
NetworkPolicy
per GKE. Consenti la connettività per Calico nella subnet:gcloud compute firewall-rules create allow-egress-calico \ --action ALLOW \ --direction EGRESS \ --rules tcp:5473 \ --destination-ranges 10.0.0.0/24 \ --network vpc-network \ --priority 1000 \ --description "Allow Calico Typha within the subnet"
Per la lettura delle metriche dei nodi, GKE è necessario utilizzare la porta di sola lettura kubelet. Consenti l'accesso alla subnet:
gcloud compute firewall-rules create allow-egress-kubelet-readonly \ --action ALLOW \ --direction EGRESS \ --rules tcp:10255 \ --destination-ranges 10.0.0.0/24 \ --network vpc-network \ --priority 1000 \ --description "Allow access to the kubelet read-only port within the subnet"
Consenti l'accesso ai set riservati di indirizzi IP utilizzati dall'accesso privato Google per la gestione delle API di Google, di Container Registry e di altri servizi:
gcloud compute firewall-rules create allow-egress-gcp-apis \ --action ALLOW \ --direction EGRESS \ --rules tcp \ --destination-ranges 199.36.153.8/30 \ --network vpc-network \ --priority 1000 \ --description "Allow access to the VIPs used by Google Cloud APIs (Private Google Access)"
Consenti al servizio di controllo di integrità Google Cloud di accedere ai pod in esecuzione nel cluster:
gcloud compute firewall-rules create allow-ingress-gcp-health-checker \ --action ALLOW \ --direction INGRESS \ --rules tcp:80,tcp:443 \ --source-ranges 130.211.0.0/22,35.191.0.0/16,35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \ --network vpc-network \ --priority 1000 \ --description "Allow workloads to respond to Google Cloud health checks"
Configurazione dell'accesso privato alle API Google Cloud
L'accesso privato Google consente alle VM e ai pod che hanno solo indirizzi IP interni di accedere alle API e ai servizi Google. Anche se le API e i servizi Google vengono pubblicati da IP esterni, il traffico proveniente dai nodi non lascia mai la rete Google quando utilizzi l'accesso privato Google.
Crea una zona DNS privata e registra 'CNAME' e 'A' in modo che nodi e carichi di lavoro possano connettersi alle API e ai servizi Google utilizzando Accesso privato Google e il nome host &&39;private.googleapis.com'
gcloud dns managed-zones create private-google-apis \
--description "Private DNS zone for Google APIs" \
--dns-name googleapis.com \
--visibility private \
--networks vpc-network
gcloud dns record-sets transaction start --zone private-google-apis
gcloud dns record-sets transaction add private.googleapis.com. \
--name *.googleapis.com \
--ttl 300 \
--type CNAME \
--zone private-google-apis
gcloud dns record-sets transaction add "199.36.153.8" \
"199.36.153.9" "199.36.153.10" "199.36.153.11" \
--name private.googleapis.com \
--ttl 300 \
--type A \
--zone private-google-apis
gcloud dns record-sets transaction execute --zone private-google-apis
Configurazione dell'accesso privato a Container Registry
Crea una zona DNS privata, un record 'CNAME' e un 'A' in modo che i nodi possano connettersi a Container Registry utilizzando l'accesso privato Google e 'gcr.io' nome host:
gcloud dns managed-zones create private-gcr-io \
--description "private zone for Container Registry" \
--dns-name gcr.io \
--visibility private \
--networks vpc-network
gcloud dns record-sets transaction start --zone private-gcr-io
gcloud dns record-sets transaction add gcr.io. \
--name *.gcr.io \
--ttl 300 \
--type CNAME \
--zone private-gcr-io
gcloud dns record-sets transaction add "199.36.153.8" "199.36.153.9" "199.36.153.10" "199.36.153.11" \
--name gcr.io \
--ttl 300 \
--type A \
--zone private-gcr-io
gcloud dns record-sets transaction execute --zone private-gcr-io
Crea un cluster GKE privato
Trova l'indirizzo IP esterno di Cloud Shell in modo da poterlo aggiungere all'elenco delle reti autorizzate ad accedere al server API del cluster.
SHELL_IP=$(dig TXT -4 +short @ns1.google.com o-o.myaddr.l.google.com)
Dopo un periodo di inattività, l'indirizzo IP esterno della VM Cloud Shell può cambiare. Se ciò accade, devi aggiornare l'elenco delle reti autorizzate del cluster. Aggiungi il seguente comando allo script di inizializzazione:
cat << 'EOF' >> ./init-egress-tutorial.sh SHELL_IP=$(dig TXT -4 +short @ns1.google.com o-o.myaddr.l.google.com) gcloud container clusters update cluster1 \ --enable-master-authorized-networks \ --master-authorized-networks ${SHELL_IP//\"}/32 EOF
Crea un cluster GKE privato:
gcloud container clusters create cluster1 \ --enable-ip-alias \ --enable-private-nodes \ --release-channel "regular" \ --no-enable-basic-auth \ --no-issue-client-certificate \ --enable-master-authorized-networks \ --master-authorized-networks ${SHELL_IP//\"}/32 \ --master-ipv4-cidr 10.5.0.0/28 \ --enable-network-policy \ --service-account "sa-application-nodes@${PROJECT_ID}.iam.gserviceaccount.com" \ --machine-type "e2-standard-4" \ --num-nodes "4" \ --network "vpc-network" \ --subnetwork "subnet-gke" \ --cluster-secondary-range-name "pods" \ --services-secondary-range-name "services" \ --workload-pool "${PROJECT_ID}.svc.id.goog" \ --zone ${ZONE}
La creazione del cluster richiede alcuni minuti. Il cluster ha nodi privati con indirizzi IP interni. A pod e servizi vengono assegnati IP dagli intervalli secondari denominati che hai definito durante la creazione della subnet VPC.
Anthos Service Mesh richiede ai nodi del cluster di utilizzare un tipo di macchina con almeno 4 vCPU. Google consiglia di iscrivere il cluster al canale di rilascio "quotidian" per assicurare che i nodi eseguano una versione di Kubernetes supportata da Anthos Service Mesh. Per ulteriori informazioni, consulta la guida all'installazione di Anthos Service Mesh.
Workload Identity è abilitato sul cluster. Anthos Service Mesh richiede Workload Identity ed è il metodo consigliato per accedere alle API di Google dai carichi di lavoro GKE.
Crea un pool di nodi denominato gateway. In questo pool di nodi viene eseguito il deployment del gateway in uscita. L'incompatibilità di
dedicated=gateway:NoSchedule
viene aggiunta a ogni nodo nel pool di nodi gateway.gcloud container node-pools create "gateway" \ --cluster "cluster1" \ --machine-type "e2-standard-4" \ --node-taints dedicated=gateway:NoSchedule \ --service-account "sa-gateway-nodes@${PROJECT_ID}.iam.gserviceaccount.com" \ --num-nodes "1"
Le incompatibilità e le tolleranze di Kubernetes garantiscono che solo i pod del gateway in uscita vengano eseguiti su nodi nel pool di nodi del gateway.
Scarica le credenziali per connetterti al cluster con kubectl:
gcloud container clusters get-credentials cluster1
Verifica che i nodi gateway abbiano l'incompatibilità corretta:
kubectl get nodes -l cloud.google.com/gke-nodepool=gateway -o yaml \ -o=custom-columns='name:metadata.name,taints:spec.taints[?(@.key=="dedicated")]'
L'output è simile al seguente:
name taints gke-cluster1-gateway-9d65b410-cffs map[effect:NoSchedule key:dedicated value:gateway]
Installazione e configurazione di Anthos Service Mesh
Questo tutorial utilizza funzionalità facoltative di Anthos Service Mesh. Per informazioni sull'installazione di Anthos Service Mesh con uno script, consulta la guida all'installazione nella documentazione.
Crea spazi dei nomi per i gateway e il piano di controllo del mesh di servizi in cui eseguire il deployment in:
kubectl create ns istio-system kubectl create ns istio-egress
Etichetta gli spazi dei nomi istio-egress, istio-system e kube-system:
kubectl label ns istio-egress istio=egress istio-injection=disabled kubectl label ns istio-system istio=system kubectl label ns kube-system kube-system=true
Queste etichette vengono utilizzate in seguito per applicare Kubernetes NetworkPolicy. L'etichetta
istio-injection=disabled
previene avvisi falsi durante l'esecuzione diistioctl
analisi.Crea un file manifest per personalizzare l'installazione di Anthos Service Mesh utilizzando l'APIIstio OperatorAPI:
cat << 'EOF' > ./asm-custom-install.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: name: "egress-gateway" spec: meshConfig: accessLogFile: "/dev/stdout" components: egressGateways: - name: "istio-egressgateway" enabled: true namespace: "istio-egress" label: istio: "egress" k8s: tolerations: - key: "dedicated" operator: "Equal" value: "gateway" nodeSelector: cloud.google.com/gke-nodepool: "gateway" EOF
Questo file viene fornito come argomento allo strumento di installazione e specifica la seguente configurazione:
- Un deployment di gateway in uscita in esecuzione nello spazio dei nomi
istio-egress
con una tolleranza e nodeSelector, in modo che venga eseguito solo sui nodigateway
. - Accesso al logging in 'stdout' per tutti i proxy sidecar.
- Un deployment di gateway in uscita in esecuzione nello spazio dei nomi
Scarica lo strumento di installazione:
curl -O https://storage.googleapis.com/csm-artifacts/asm/asmcli
Rendi lo strumento eseguibile:
chmod +x asmcli
Installa Anthos Service Mesh eseguendo lo strumento:
./asmcli install \ --project_id ${PROJECT_ID} \ --cluster_name cluster1 \ --cluster_location ${ZONE} \ --custom_overlay ./asm-custom-install.yaml \ --output_dir ./ \ --enable_all
Al termine dell'installazione, imposta una variabile di ambiente in cui posizionare il percorso dello strumento
istioctl
e aggiungila allo script di inizializzazione:ISTIOCTL=$(find "$(pwd -P)" -name istioctl) echo "ISTIOCTL=\"${ISTIOCTL}\"" >> ./init-egress-tutorial.sh
Verifica l'installazione di Anthos Service Mesh
Verifica che i componenti del piano di controllo di Anthos Service Mesh siano in esecuzione nello spazio dei nomi
istio-system
:kubectl get pod -n istio-system
Vedrai
istio-ingressgateway
eistiod-asm
pod in esecuzione.Verifica che i pod del gateway in uscita siano in esecuzione nello spazio dei nomi
istio-egress
e sui nodi nel pool di nodigateway
:kubectl get pods -n istio-egress -o wide
I pod del gateway in uscita hanno un
nodeSelector
per selezionare i nodi nel pool di nodigateway
e una tolleranza che consente l'esecuzione sui nodi del gateway incompatibili. Esamina il nodeSelector e le tolleranze per i pod gateway in uscita:kubectl -n istio-egress get pod -l app=istio-egressgateway \ -o=custom-columns='name:metadata.name,nodeSelector:spec.nodeSelector,\ tolerations:spec.tolerations[?(@.key=="dedicated")]'
L'output è simile al seguente:
name nodeSelector tolerations istio-egressgateway-74687946f5-dg9mp map[cloud.google.com/gke-nodepool:gateway] map[key:dedicated operator:Equal value:gateway]
Preparazione del mesh e di un'applicazione di test
Assicurati che la funzionalità TLS condivisa STRICT sia abilitata. Applica un criterio
PeerAuthentication
predefinito per il mesh nello spazio dei nomiistio-system
:cat <<EOF | kubectl apply -f - apiVersion: "security.istio.io/v1beta1" kind: "PeerAuthentication" metadata: name: "default" namespace: "istio-system" spec: mtls: mode: STRICT EOF
Puoi ignorare questa configurazione creando risorse
PeerAuthentication
in spazi dei nomi specifici.Crea spazi dei nomi da utilizzare per il deployment dei carichi di lavoro di prova. I passaggi successivi di questo tutorial spiegano come configurare regole di routing in uscita diverse per ogni spazio dei nomi.
kubectl create namespace team-x kubectl create namespace team-y
Etichetta gli spazi dei nomi in modo che possano essere selezionati dai criteri di rete di Kubernetes:
kubectl label namespace team-x team=x kubectl label namespace team-y team=y
Affinché Anthos Service Mesh possa inserire automaticamente i file collaterali proxy, devi impostare un'etichetta di revisione negli spazi dei nomi del carico di lavoro. L'etichetta di revisione deve corrispondere alla revisione del piano di controllo di Anthos Service Mesh di cui è stato eseguito il deployment nel cluster. Cerca l'etichetta di revisione sul pod
istiod
e archiviala in una variabile di ambiente:REVISION_LABEL=$(kubectl get pod -n istio-system -l app=istiod \ -o jsonpath='{.items[0].metadata.labels.istio\.io/rev}')
Imposta l'etichetta di revisione negli spazi dei nomi di
team-x
eteam-y
:kubectl label ns team-x istio.io/rev=${REVISION_LABEL} kubectl label ns team-y istio.io/rev=${REVISION_LABEL}
Crea un file YAML da utilizzare per eseguire i deployment di test:
cat << 'EOF' > ./test.yaml apiVersion: v1 kind: ServiceAccount metadata: name: test --- apiVersion: v1 kind: Service metadata: name: test labels: app: test spec: ports: - port: 80 name: http selector: app: test --- apiVersion: apps/v1 kind: Deployment metadata: name: test spec: replicas: 1 selector: matchLabels: app: test template: metadata: labels: app: test spec: serviceAccountName: test containers: - name: test image: gcr.io/google.com/cloudsdktool/cloud-sdk:slim command: ["/bin/sleep", "infinity"] imagePullPolicy: IfNotPresent EOF
Esegui il deployment dell'applicazione di test nello spazio dei nomi
team-x
:kubectl -n team-x create -f ./test.yaml
Verifica che venga eseguito il deployment dell'applicazione di test in un nodo nel pool predefinito e che venga inserito un container sidecar proxy. Ripeti il comando seguente finché lo stato del pod non è
Running
:kubectl -n team-x get po -l app=test -o wide
L'output è simile al seguente:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-d5bdf6f4f-9nxfv 2/2 Running 0 19h 10.1.1.25 gke-cluster1-default-pool-f6c7a51f-wbzj
Due contenitori su due sono
Running
. un container è l'applicazione di test, l'altro è il sidecar proxy.Il pod è in esecuzione su un nodo nel pool di nodi predefinito.
Verifica che non sia possibile effettuare una richiesta HTTP dal contenitore di test a un sito esterno:
kubectl -n team-x exec -it \ $(kubectl -n team-x get pod -l app=test -o jsonpath={.items..metadata.name}) \ -c test -- curl -v http://example.com
Viene generato un messaggio di errore dal proxy sidecar perché la regola firewall 'global-deny-egress-all' nega la connessione upstream.
Utilizzo della risorsa Sidecar per limitare l'ambito della configurazione del proxy sidecar
Puoi utilizzare la risorsa sidecar per limitare l'ambito del listener in uscita configurato per i proxy sidecar. Per ridurre l'utilizzo della configurazione e l'utilizzo della memoria, è buona norma applicare una risorsa Sidecar
predefinita per ogni spazio dei nomi.
Il proxy utilizzato da Anthos Service Mesh nel sidecar è Envoy. In Terminologia, un cluster
è un gruppo logico di endpoint a monte utilizzati come destinazioni per il bilanciamento del carico.
Controlla i cluster in uscita configurati nel proxy sidecar Envoy per il pod di test eseguendo il comando
istioctl proxy-config
:${ISTIOCTL} pc c $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}).team-x --direction outbound
Nell'elenco sono presenti circa 20 cluster Envoy, inclusi molti per il gateway in uscita.
Limita la configurazione del proxy alle route in uscita che sono state definite esplicitamente con le voci di servizio negli spazi dei nomi
istio-egress
eteam-x
. Applica una risorsaSidecar
allo spazio dei nomiteam-x
:cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: Sidecar metadata: name: default namespace: team-x spec: outboundTrafficPolicy: mode: REGISTRY_ONLY egress: - hosts: - 'istio-egress/*' - 'team-x/*' EOF
L'impostazione della modalità del criterio di traffico in uscita su
REGISTRY_ONLY
limita la configurazione del proxy in modo da includere solo gli host esterni che sono stati esplicitamente aggiunti al registro dei servizi mesh mediante la definizione delle voci di servizio.La parte '
istio-egress/*
' specifica che il proxy sidecar seleziona le route dallo spazio dei nomiistio-egress
rese disponibili utilizzando l'attributoexportTo
. La parte 'team-x/*
' include tutte le route configurate localmente nello spazio dei nomiteam-x
.Visualizza i cluster in uscita configurati nel proxy sidecar Envoy e confrontali con l'elenco di cluster configurati prima di applicare la risorsa
Sidecar
:${ISTIOCTL} pc c $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}).team-x --direction outbound
L'output include solo alcuni cluster per il gateway in uscita e uno per il pod di test stesso.
Configurazione di Anthos Service Mesh per il routing del traffico attraverso il gateway in uscita
Configura un
Gateway
per il traffico HTTP sulla porta 80. IlGateway
seleziona il proxyistio-egressgateway
di cui il programma di installazione ha eseguito il deployment nello spazio dei nomiistio-egress
. La configurazioneGateway
viene applicata allo spazio dei nomiistio-egress
e gestisce il traffico di qualsiasi host.cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: egress-gateway namespace: istio-egress spec: selector: istio: egress servers: - port: number: 80 name: https protocol: HTTPS hosts: - '*' tls: mode: ISTIO_MUTUAL EOF
Crea un
DestinationRule
per il gateway in uscita con TLS reciproco per l'autenticazione e la crittografia. Utilizza una singola regola di destinazione condivisa per tutti gli host esterni.cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: target-egress-gateway namespace: istio-egress spec: host: istio-egressgateway.istio-egress.svc.cluster.local subsets: - name: target-egress-gateway-mTLS trafficPolicy: loadBalancer: simple: ROUND_ROBIN tls: mode: ISTIO_MUTUAL EOF
Crea uno
ServiceEntry
nello spazio dei nomiistio-egress
per registrare esplicitamente example.com nel registro di servizio mesh's per lo spazio dei nomiteam-x
:cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: example-com-ext namespace: istio-egress spec: hosts: - example.com ports: - number: 80 name: http protocol: HTTP - number: 443 name: tls protocol: TLS resolution: DNS location: MESH_EXTERNAL exportTo: - 'team-x' - 'istio-egress' EOF
Crea un
VirtualService
per instradare il traffico a example.com attraverso il gateway in uscita. Esistono due condizioni di corrispondenza: la prima indirizza il traffico al gateway in uscita e la seconda indirizza il traffico dal gateway in uscita all'host di destinazione. La proprietàexportTo
controlla gli spazi dei nomi che possono utilizzare il servizio virtuale.cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: example-com-through-egress-gateway namespace: istio-egress spec: hosts: - example.com gateways: - istio-egress/egress-gateway - mesh http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-mTLS port: number: 80 weight: 100 - match: - gateways: - istio-egress/egress-gateway port: 80 route: - destination: host: example.com port: number: 80 weight: 100 exportTo: - 'istio-egress' - 'team-x' EOF
Esegui
istioctl analyze
per verificare la presenza di errori di configurazione:${ISTIOCTL} analyze -n istio-egress
L'output è simile al seguente:
✔ No validation issues found when analyzing namespace: istio-egress.
Invia al sito esterno diverse richieste tramite il gateway in uscita:
for i in {1..4} do kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- \ curl -s -o /dev/null -w "%{http_code}\n" http://example.com done
Sono visualizzati i codici di stato
200
per tutte e quattro le risposte.Verifica che le richieste siano state indirizzate attraverso il gateway in uscita controllando i log di accesso al proxy. Controlla innanzitutto il log di accesso per il sidecar proxy di cui è stato eseguito il deployment con l'applicazione di test:
kubectl -n team-x logs -f $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) istio-proxy
Per ogni richiesta inviata, viene visualizzata una voce di log simile alla seguente:
[2020-09-14T17:37:08.045Z] "HEAD / HTTP/1.1" 200 - "-" "-" 0 0 5 4 "-" "curl/7.67.0" "d57ea5ad-90e9-46d9-8b55-8e6e404a8f9b" "example.com" "10.1.4.12:8080" outbound|80||istio-egressgateway.istio-egress.svc.cluster.local 10.1.0.17:42140 93.184.216.34:80 10.1.0.17:60326 - -
Controlla anche il log di accesso al gateway in uscita:
kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egress \ -o jsonpath="{.items[0].metadata.name}") istio-proxy
Per ogni richiesta inviata, viene visualizzata una voce di log per l'accesso al gateway in uscita simile alla seguente:
[2020-09-14T17:37:08.045Z] "HEAD / HTTP/2" 200 - "-" "-" 0 0 4 3 "10.1.0.17" "curl/7.67.0" "095711e6-64ef-4de0-983e-59158e3c55e7" "example.com" "93.184.216.34:80" outbound|80||example.com 10.1.4.12:37636 10.1.4.12:8080 10.1.0.17:44404 outbound_.80_.target-egress-gateway-mTLS_.istio-egressgateway.istio-egress.svc.cluster.local -
Configura il routing diverso per un secondo spazio dei nomi
Configura il routing per un secondo host esterno per scoprire come configurare la connettività esterna diversa per team diversi.
Crea una risorsa
Sidecar
per lo spazio dei nomiteam-y
:cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: Sidecar metadata: name: default namespace: team-y spec: outboundTrafficPolicy: mode: REGISTRY_ONLY egress: - hosts: - 'istio-egress/*' - 'team-y/*' EOF
Esegui il deployment dell'applicazione di test nello spazio dei nomi
team-y
:kubectl -n team-y create -f ./test.yaml
Registra un secondo host esterno ed esportalo nello spazio dei nomi
team-x
eteam-y
:cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: httpbin-org-ext namespace: istio-egress spec: hosts: - httpbin.org ports: - number: 80 name: http protocol: HTTP - number: 443 name: tls protocol: TLS resolution: DNS location: MESH_EXTERNAL exportTo: - 'istio-egress' - 'team-x' - 'team-y' EOF
Crea un servizio virtuale per instradare il traffico a httpbin.org attraverso il gateway in uscita:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: httpbin-org-through-egress-gateway namespace: istio-egress spec: hosts: - httpbin.org gateways: - istio-egress/egress-gateway - mesh http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-mTLS port: number: 80 weight: 100 - match: - gateways: - istio-egress/egress-gateway port: 80 route: - destination: host: httpbin.org port: number: 80 weight: 100 exportTo: - 'istio-egress' - 'team-x' - 'team-y' EOF
Esegui
istioctl analyze
per verificare la presenza di errori di configurazione:${ISTIOCTL} analyze -n istio-egress
Le voci della tabella sono:
✔ No validation issues found when analyzing namespace: istio-egress.
Fai una richiesta a httpbin.org dall'app di test
team-y
:kubectl -n team-y exec -it $(kubectl -n team-y get pod -l app=test -o \ jsonpath={.items..metadata.name}) -c test -- curl -I http://httpbin.org
Ricevi una risposta da
200 OK
.Invia anche una richiesta a httpbin.org dall'app di test
team-x
:kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -I http://httpbin.org
Ricevi una risposta da
200 OK
.Prova a effettuare una richiesta a example.com dallo spazio dei nomi
team-y
:kubectl -n team-y exec -it $(kubectl -n team-y get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -I http://example.com
La richiesta non riesce perché non è stata configurata alcuna route in uscita per l'host
example.com
.
Utilizzo del criterio di autorizzazione per fornire un maggiore controllo sul traffico
In questo tutorial, i criteri di autorizzazione per il gateway in uscita vengono creati nello spazio dei nomi istio-egress
. Puoi configurare Kubernetes RBAC in modo che solo gli amministratori di rete possano accedere allo spazio dei nomi istio-egress
.
Crea un
AuthorizationPolicy
in modo che le applicazioni nello spazio dei nomiteam-x
possano connettersi a example.com, ma non ad altri host esterni quando invii richieste utilizzando la porta 80. Il valoretargetPort
corrispondente nei pod del gateway in uscita è 8080.cat <<EOF | kubectl apply -f - apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: egress-team-x-to-example-com namespace: istio-egress spec: rules: - from: - source: namespaces: - 'team-x' to: - operation: hosts: - 'example.com' when: - key: destination.port values: ["8080"] EOF
Verifica di poter effettuare una richiesta a example.com dall'applicazione di test nello spazio dei nomi
team-x
:kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -I http://example.com
Ricevi una risposta da
200 OK
.Prova a inviare una richiesta a httpbin.org dall'applicazione di test nello spazio dei nomi
team-x
:kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -s -w " %{http_code}\n" \ http://httpbin.org
La richiesta non riesce con un messaggio
RBAC: access denied
e un codice di stato 403 Forbidden. Potrebbe essere necessario attendere alcuni secondi perché ci sia un breve ritardo prima che le norme dell'autorizzazione vengano applicate.I criteri di autorizzazione forniscono un controllo completo sul traffico consentito o negato. Applica il seguente criterio di autorizzazione per consentire all'app di prova nello spazio dei nomi
team-y
di effettuare richieste a httpbin.org utilizzando un determinato percorso URL durante l'invio delle richieste con la porta 80. La corrispondenzatargetPort
sui pod del gateway in uscita è 8080.cat <<EOF | kubectl apply -f - apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: egress-team-y-to-httpbin-teapot namespace: istio-egress spec: rules: - from: - source: namespaces: - 'team-y' to: - operation: hosts: - httpbin.org paths: ['/status/418'] when: - key: destination.port values: ["8080"] EOF
Prova a connetterti a httpbin.org dall'app di test nello spazio dei nomi
team-y
:kubectl -n team-y exec -it $(kubectl -n team-y get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -s -w " %{http_code}\n" \ http://httpbin.org
La richiesta non riesce con un messaggio RBAC: access denied (Nega negato) e un codice di stato 403 Forbidden.
Ora effettua una richiesta a httpbin.org/status/418 dalla stessa app:
kubectl -n team-y exec -it $(kubectl -n team-y get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl http://httpbin.org/status/418
La richiesta ha esito positivo perché il percorso corrisponde al pattern nel criterio di autorizzazione. L'output è simile al seguente:
-=[ teapot ]=- _...._ .' _ _ `. | ."` ^ `". _, \_;`"---"`|// | ;/ \_ _/ `"""`
originazione TLS al gateway in uscita
Puoi configurare i gateway in uscita a 'upgrade' (originare) richieste HTTP normali a TLS. L'utilizzo delle applicazioni HTTP semplici per effettuare semplici richieste HTTP ha diversi vantaggi se utilizzato con la originazione TLS e TLS reciproca. Per scoprire di più, consulta la guida alle best practice.
Crea un
DestinationRule. The DestinationRule
per specificare che il gateway ha in origine una connessione TLS a example.com.cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: example-com-originate-tls namespace: istio-egress spec: host: example.com subsets: - name: example-com-originate-TLS trafficPolicy: loadBalancer: simple: ROUND_ROBIN portLevelSettings: - port: number: 443 tls: mode: SIMPLE sni: example.com EOF
Aggiorna il servizio virtuale per example.com in modo che le richieste alla porta 80 sul gateway siano 'aggiornate' a TLS sulla porta 443 quando vengono inviati all'host di destinazione:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: example-com-through-egress-gateway namespace: istio-egress spec: hosts: - example.com gateways: - mesh - istio-egress/egress-gateway http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-mTLS port: number: 80 - match: - gateways: - istio-egress/egress-gateway port: 80 route: - destination: host: example.com port: number: 443 subset: example-com-originate-TLS weight: 100 EOF
Effettua varie richieste a example.com dall'app di test nello spazio dei nomi
team-x
:for i in {1..4} do kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -I http://example.com done
Come in precedenza, le richieste hanno avuto esito positivo con
200 OK
risposte.Controlla il log del gateway in uscita per verificare che il gateway instrada le richieste all'host di destinazione originando le connessioni TLS:
kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egress \ -o jsonpath=" {.items[0].metadata.name}") istio-proxy
L'output è simile al seguente:
[2020-09-24T17:58:02.548Z] "HEAD / HTTP/2" 200 - "-" "-" 0 0 6 5 "10.1.1.15" "curl/7.67.0" "83a77acb-d994-424d-83da-dd8eac902dc8" "example.com" "93.184.216.34:443" outbound|443|example-com-originate-TLS|example.com 10.1.4.31:49866 10.1.4.31:8080 10.1.1.15:37334 outbound_.80_.target-egress-gateway-mTLS_.istio-egressgateway.istio-egress.svc.cluster.local -
Il file collaterale proxy ha inviato la richiesta al gateway utilizzando la porta 80 e TLS originati dalla porta 443 per inviare la richiesta all'host di destinazione.
Passthrough di connessioni HTTPS/TLS
Le tue applicazioni esistenti potrebbero già utilizzare le connessioni TLS quando comunicano con servizi esterni. Puoi configurare il gateway in uscita in modo che passi le connessioni TLS senza decriptarle.
Modifica la configurazione in modo che il gateway in uscita utilizzi il pass-through TLS per le connessioni alla porta 443:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: egress-gateway namespace: istio-egress spec: selector: istio: egress servers: - port: number: 80 name: https protocol: HTTPS hosts: - '*' tls: mode: ISTIO_MUTUAL - port: number: 443 name: tls protocol: TLS hosts: - '*' tls: mode: PASSTHROUGH EOF
Aggiorna il
DestinationRule
che rimanda al gateway in uscita per aggiungere un secondo sottoinsieme per la porta 443 sul gateway. Questo nuovo sottoinsieme non utilizza TLS reciproco. Il protocollo TLS reciproco Istio non è supportato per il pass-through delle connessioni TLS. Le connessioni sulla porta 80 utilizzano ancora mTLS:cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: target-egress-gateway namespace: istio-egress spec: host: istio-egressgateway.istio-egress.svc.cluster.local subsets: - name: target-egress-gateway-mTLS trafficPolicy: loadBalancer: simple: ROUND_ROBIN portLevelSettings: - port: number: 80 tls: mode: ISTIO_MUTUAL - name: target-egress-gateway-TLS-passthrough EOF
Aggiorna il servizio virtuale per example.com in modo che il traffico TLS sulla porta 443 venga passato attraverso il gateway:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: example-com-through-egress-gateway namespace: istio-egress spec: hosts: - example.com gateways: - mesh - istio-egress/egress-gateway http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-mTLS port: number: 80 - match: - gateways: - istio-egress/egress-gateway port: 80 route: - destination: host: example.com port: number: 443 subset: example-com-originate-TLS weight: 100 tls: - match: - gateways: - mesh port: 443 sniHosts: - example.com route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-TLS-passthrough port: number: 443 - match: - gateways: - istio-egress/egress-gateway port: 443 sniHosts: - example.com route: - destination: host: example.com port: number: 443 weight: 100 exportTo: - 'istio-egress' - 'team-x' EOF
Aggiorna il servizio virtuale per httpbin.org in modo che il traffico TLS sulla porta 443 venga passato attraverso il gateway:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: httpbin-org-through-egress-gateway namespace: istio-egress spec: hosts: - httpbin.org gateways: - istio-egress/egress-gateway - mesh http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-mTLS port: number: 80 weight: 100 - match: - gateways: - istio-egress/egress-gateway port: 80 route: - destination: host: httpbin.org port: number: 80 weight: 100 tls: - match: - gateways: - mesh port: 443 sniHosts: - httpbin.org route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-TLS-passthrough port: number: 443 - match: - gateways: - istio-egress/egress-gateway port: 443 sniHosts: - httpbin.org route: - destination: host: httpbin.org port: number: 443 weight: 100 exportTo: - 'istio-egress' - 'team-x' - 'team-y' EOF
Aggiungi un criterio di autorizzazione che accetti qualsiasi tipo di traffico inviato alla porta 443 del servizio gateway in uscita. Il corrispondente
targetPort
nei pod del gateway è 8443.cat <<EOF | kubectl apply -f - apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: egress-all-443 namespace: istio-egress spec: rules: - when: - key: destination.port values: ["8443"] EOF
Esegui
istioctl analyze
per verificare la presenza di errori di configurazione:${ISTIOCTL} analyze -n istio-egress
Le voci della tabella sono:
✔ No validation issues found when analyzing namespace: istio-egress.
Effettua una richiesta HTTP semplice a example.com dall'applicazione di test in
team-x
namespace:kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -I http://example.com
La richiesta ha esito positivo con una risposta
200 OK
.Ora effettua diverse richieste TLS (HTTPS) dall'applicazione di test nello spazio dei nomi
team-x
:for i in {1..4} do kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -s -o /dev/null \ -w "%{http_code}\n" \ https://example.com done
Vedrai 200 risposte.
Esamina nuovamente il log del gateway in uscita:
kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egress \ -o jsonpath="{.items[0].metadata.name}") istio-proxy
Vengono visualizzate voci di log simili alla seguente:
[2020-09-24T18:04:38.608Z] "- - -" 0 - "-" "-" 1363 5539 10 - "-" "-" "-" "-" "93.184.216.34:443" outbound|443||example.com 10.1.4.31:51098 10.1.4.31:8443 10.1.1.15:57030 example.com -
La richiesta HTTPS è stata trattata come traffico TCP e ha superato il gateway per l'host di destinazione, pertanto non sono incluse informazioni HTTP nel log.
L'utilizzo di Kubernetes NetworkPolicy come controllo aggiuntivo
Esistono molti scenari in cui un'applicazione può ignorare un proxy sidecar.
Puoi utilizzare Kubernetes NetworkPolicy
per specificare anche quali connessioni possono essere eseguite nei carichi di lavoro. Dopo aver applicato un singolo criterio di rete, vengono rifiutate tutte le connessioni non specifiche.
Questo tutorial considera solo le connessioni in uscita e i selettori in uscita per i criteri di rete. Se controlli il traffico in entrata con i criteri di rete sui tuoi cluster, devi creare criteri in entrata che corrispondano ai criteri in uscita. Ad esempio, se consenti il traffico in uscita dai carichi di lavoro nello spazio dei nomi team-x
allo spazio dei nomi team-y
, devi anche consentire il traffico in entrata allo spazio dei nomi team-y
dallo spazio dei nomi team-x
.
Consenti ai carichi di lavoro e ai proxy di cui è stato eseguito il deployment nello spazio dei nomi
team-x
di connettersi aistiod
e al gateway in uscita:cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-control-plane namespace: team-x spec: podSelector: {} policyTypes: - Egress egress: - to: - namespaceSelector: matchLabels: istio: system podSelector: matchLabels: istio: istiod - namespaceSelector: matchLabels: istio: egress podSelector: matchLabels: istio: egress EOF
Consenti ai carichi di lavoro e ai proxy di eseguire query sul DNS:
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-dns namespace: team-x spec: podSelector: {} policyTypes: - Egress egress: - to: - namespaceSelector: matchLabels: kube-system: "true" ports: - port: 53 protocol: UDP - port: 53 protocol: TCP EOF
Consenti ai carichi di lavoro e ai proxy di connettersi agli IP che gestiscono le API e i servizi Google, inclusa Mesh CA:
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-google-apis namespace: team-x spec: podSelector: {} policyTypes: - Egress egress: - to: - ipBlock: cidr: 199.36.153.4/30 - ipBlock: cidr: 199.36.153.8/30 EOF
Consenti ai carichi di lavoro e ai proxy di connettersi al server dei metadati GKE:
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-metadata-server namespace: team-x spec: podSelector: {} policyTypes: - Egress egress: - to: # For GKE data plane v2 - ipBlock: cidr: 169.254.169.254/32 - to: # For GKE data plane v1 - ipBlock: cidr: 127.0.0.1/32 ports: - protocol: TCP port: 988 EOF
(Facoltativo) Consenti i carichi di lavoro e i proxy nello spazio dei nomi
team-x
per stabilire connessioni tra loro:cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-same-namespace namespace: team-x spec: podSelector: {} ingress: - from: - podSelector: {} egress: - to: - podSelector: {} EOF
(Facoltativo) Consenti ai carichi di lavoro e ai proxy nello spazio dei nomi
team-x
di stabilire connessioni a carichi di lavoro di cui viene eseguito il deployment da un team diverso:cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-team-y namespace: team-x spec: podSelector: {} policyTypes: - Egress egress: - to: - namespaceSelector: matchLabels: team: 'y' EOF
Le connessioni tra proxy sidecar rimangono attive. Le connessioni esistenti non vengono chiuse quando applichi un nuovo criterio di rete. Riavvia i carichi di lavoro nello spazio dei nomi team-x per assicurarti che le connessioni esistenti siano chiuse:
kubectl -n team-x rollout restart deployment
Verifica di poter ancora inviare una richiesta HTTP a example.com dall'applicazione di test in
team-x
spazio dei nomi:kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -I http://example.com
La richiesta ha esito positivo con una risposta
200 OK
.
Accesso diretto alle API di Google tramite l'accesso privato Google e le autorizzazioni IAM
Le API e i servizi di Google vengono esposti utilizzando indirizzi IP esterni. Quando i pod con indirizzi IP alias nativi VPC effettuano la connessione alle API di Google utilizzando l'accesso privato Google, il traffico non lascia mai la rete Google.
Durante la configurazione dell'infrastruttura per questo tutorial, hai abilitato l'accesso privato Google per la subnet utilizzata dai pod GKE. Per consentire l'accesso agli indirizzi IP utilizzati dall'accesso privato Google, hai creato una route, una regola firewall VPC e una zona DNS privata. Questa configurazione consente ai pod di raggiungere le API di Google direttamente senza inviare traffico attraverso il gateway in uscita. Puoi controllare quali API sono disponibili per account di servizio Kubernetes specifici (e quindi spazi dei nomi) utilizzando Workload Identity e IAM. L'autorizzazione di Istio non ha effetto perché il gateway in uscita non gestisce le connessioni alle API di Google.
Prima che i pod possano chiamare le API di Google, devi utilizzare IAM per concedere le autorizzazioni. Il cluster che utilizzi per questo tutorial è configurato per utilizzare Workload Identity, che consente a un account di servizio Kubernetes di agire come account di servizio Google.
Crea un account di servizio Google per la tua applicazione, da utilizzare:
gcloud iam service-accounts create sa-test-app-team-x
Consenti all'account di servizio Kubernetes di impersonare l'account di servizio Google:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[team-x/test]" \ sa-test-app-team-x@${PROJECT_ID}.iam.gserviceaccount.com
Annota l'account di servizio Kubernetes per l'app di test nello spazio dei nomi
team-x
con l'indirizzo email dell'account di servizio Google:cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ServiceAccount metadata: annotations: iam.gke.io/gcp-service-account: sa-test-app-team-x@${PROJECT_ID}.iam.gserviceaccount.com name: test namespace: team-x EOF
Il pod dell'applicazione di test deve essere in grado di accedere al server di metadati Google (in esecuzione come DaemonSet) per ottenere credenziali temporanee per le chiamate alle API di Google. Crea una voce di servizio per il server di metadati GKE:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: metadata-google-internal namespace: istio-egress spec: hosts: - metadata.google.internal ports: - number: 80 name: http protocol: HTTP - number: 443 name: tls protocol: TLS resolution: DNS location: MESH_EXTERNAL exportTo: - 'istio-egress' - 'team-x' EOF
Crea anche una voce di servizio per private.googleapis.com e storage.googleapis.com:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: private-googleapis-com namespace: istio-egress spec: hosts: - private.googleapis.com - storage.googleapis.com ports: - number: 80 name: http protocol: HTTP - number: 443 name: tls protocol: TLS resolution: DNS location: MESH_EXTERNAL exportTo: - 'istio-egress' - 'team-x' EOF
Verifica che l'account di servizio Kubernetes sia configurato correttamente per agire come account di servizio Google:
kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- gcloud auth list
Vedrai l'account di servizio Google indicato come unica e attiva.
Crea un file di test in un bucket Cloud Storage:
echo "Hello, World!" > /tmp/hello gsutil mb gs://${PROJECT_ID}-bucket gsutil cp /tmp/hello gs://${PROJECT_ID}-bucket/
Concedi all'account di servizio l'autorizzazione per elencare e visualizzare i file nel bucket:
gsutil iam ch \ serviceAccount:sa-test-app-team-x@${PROJECT_ID}.iam.gserviceaccount.com:objectViewer \ gs://${PROJECT_ID}-bucket/
Verifica che l'applicazione di test possa accedere al bucket di test:
kubectl -n team-x exec -it \ $(kubectl -n team-x get pod -l app=test -o jsonpath={.items..metadata.name}) \ -c test \ -- gsutil cat gs://${PROJECT_ID}-bucket/hello
Le voci della tabella sono:
Hello, World!
Esegui la pulizia
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.
Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, completa i passaggi riportati nelle sezioni seguenti.
Elimina il progetto
Il modo più semplice per eliminare la fatturazione è eliminare il progetto che hai creato per il tutorial.
- In Cloud Console, vai alla pagina Gestisci risorse.
- Nell'elenco dei progetti, seleziona il progetto da eliminare, quindi fai clic su Elimina.
- Nella finestra di dialogo, digita l'ID del progetto e fai clic su Chiudi per eliminare il progetto.
Passaggi successivi
- Leggi la guida alle best practice per i companion.
- Consulta la guida alla protezione di GKE.
- Scopri come gestire configurazione e criteri in tutta l'infrastruttura con Anthos Configuration Management.
- Per ulteriori architetture di riferimento, diagrammi, tutorial e best practice, visita il Cloud Architecture Center.