In dieser Anleitung wird gezeigt, wie Sie mit Anthos Service Mesh-Ausgangsgateways und mit anderen Google Cloud-Kontroll-Features ausgehenden Traffic von Arbeitslasten schützen, die auf einem Google Kubernetes Engine-Cluster bereitgestellt werden. Die Anleitung ist als Ergänzung zu den Best Practices für die Verwendung von Anthos Service Mesh-Gateways für ausgehenden Traffic in GKE-Clustern gedacht.
Sie ist für Entwickler von Netzwerk-, Plattform- und Sicherheitsfunktionen gedacht, die Google Kubernetes Engine-Cluster verwalten, die von einem oder mehreren Teams für das Software-Deployment genutzt werden. Die hier erläuterten Kontrollen sind insbesondere für Organisationen hilfreich, die die Einhaltung von Vorschriften – z. B. die DSGVO und PCI – nachweisen müssen.
Ziele
- Sie richten die Infrastruktur zum Ausführen von Anthos Service Mesh ein:
- Benutzerdefiniertes VPC-Netzwerk und privates Subnetz
- Cloud NAT für den Internetzugriff
- Privater GKE-Cluster mit einem zusätzlichen Knotenpool für Ausgangsgateway-Pods
- VPC-Firewallregeln für eingeschränkten ausgehenden Traffic; nur Gatewayknoten können externe Hosts erreichen
- Privater Google-Zugriff für das Herstellen einer Verbindung zu Container Registry und Google APIs
- Installieren Sie Anthos Service Mesh.
- Installieren Sie Proxys des ausgehenden Traffics, die in einem dedizierten Knotenpool ausgeführt werden.
- Sie konfigurieren mandantenfähige Routingregeln für externen Traffic über das Ausgangsgateway:
- Anwendungen im Namespace
team-x
können eine Verbindung zuexample.com
herstellen - Anwendungen im Namespace
team-y
können eine Verbindung zuhttpbin.org
herstellen
- Anwendungen im Namespace
- Sie beschränken mit der
Sidecar
-Ressource den Geltungsbereich der Sidecar-Proxykonfiguration für ausgehenden Traffic für jeden Namespace. - Sie konfigurieren Autorisierungsrichtlinien, um Regeln für ausgehenden Traffic in Kraft zu setzen.
- Sie konfigurieren das Ausgangsgateway, um einfache HTTP-Anfragen in TLS (TLS-Ursprung) zu ändern.
- Sie konfigurieren das Ausgangsgateway für die Weiterleitung von TLS-Traffic.
- Sie richten Kubernetes-Netzwerkrichtlinien als zusätzliche Kontrolle für ausgehenden Traffic ein.
- Sie konfigurieren den direkten Zugriff auf Google APIs mithilfe des privaten Google-Zugriffs und mit Berechtigungen der Identitäts- und Zugriffsverwaltung (IAM).
Kosten
In diesem Dokument verwenden Sie die folgenden kostenpflichtigen Komponenten von Google Cloud:
- Compute Engine
- Google Kubernetes Engine (GKE)
- Container Registry
- Anthos Service Mesh
- Cloud Load Balancing
- Cloud NAT
- Netzwerk
- Cloud Storage
Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen.
Nach Abschluss dieser Anleitung können Sie weitere Kosten durch Löschen von erstellten Ressourcen vermeiden. Weitere Informationen finden Sie unter Bereinigen.
Hinweise
-
Wählen Sie in der Google Cloud Console auf der Seite der Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines.
-
Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein.
-
Aktivieren Sie Cloud Shell in der Google Cloud Console.
Erstellen Sie ein Arbeitsverzeichnis, das für die Anleitung verwendet werden soll:
mkdir -p ~/WORKING_DIRECTORY cd ~/WORKING_DIRECTORY
Erstellen Sie ein Shell-Skript, um Ihre Umgebung für die Anleitung zu initialisieren. Ersetzen und bearbeiten Sie die Variablen entsprechend Ihres Projekts und Ihrer Einstellungen. Führen Sie dieses Skript mit dem Befehl
source
aus, um Ihre Umgebung neu zu initialisieren, wenn Ihre Shell-Sitzung abgelaufen ist: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
compute.googleapis.com
aktivieren:gcloud services enable compute.googleapis.com --project=YOUR_PROJECT_ID
Machen Sie das Skript ausführbar und führen Sie es mit dem Befehl
source
aus, um die Umgebung zu initialisieren. Wählen SieY
aus, wenn Sie aufgefordert werden,compute.googleapis.com
zu aktivieren:chmod +x ./init-egress-tutorial.sh source ./init-egress-tutorial.sh
Infrastruktur einrichten
VPC-Netzwerk und Subnetz erstellen
Erstellen Sie ein neues VPC-Netzwerk:
gcloud compute networks create vpc-network \ --subnet-mode custom
Erstellen Sie ein Subnetz für den Cluster zur Ausführung mit vorab zugewiesenen sekundären IP-Adressbereichen für Pods und Dienste. Der private Google-Zugriff ist aktiviert, damit Anwendungen, die nur interne IP-Adressen haben, Google APIs und Google-Dienste erreichen können:
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
Cloud NAT konfigurieren
Mit Cloud NAT können Arbeitslasten ohne externe IP-Adresse eine Verbindung zu Zielen im Internet herstellen und eingehende Antworten von diesen Zielen empfangen.
Erstellen Sie einen Cloud Router:
gcloud compute routers create nat-router \ --network vpc-network
Fügen Sie eine NAT-Konfiguration zum Router hinzu:
gcloud compute routers nats create nat-config \ --router nat-router \ --nat-all-subnet-ip-ranges \ --auto-allocate-nat-external-ips
Dienstkonten für jeden GKE-Knotenpool erstellen
Erstellen Sie zwei Dienstkonten für die beiden GKE-Knotenpools. Jedem Knotenpool wird ein eigenes Dienstkonto zugewiesen, damit Sie VPC-Firewallregeln auf bestimmte Knoten anwenden können.
Erstellen Sie ein Dienstkonto, das von Knoten im Standardknotenpool verwendet werden soll:
gcloud iam service-accounts create sa-application-nodes \ --description="SA for application nodes" \ --display-name="sa-application-nodes"
Erstellen Sie ein Dienstkonto, das von Knoten im Gatewayknotenpool verwendet werden soll:
gcloud iam service-accounts create sa-gateway-nodes \ --description="SA for gateway nodes" \ --display-name="sa-gateway-nodes"
Berechtigungen für die Dienstkonten erteilen
Fügen Sie den Anwendungs- und Gateway-Dienstkonten eine Mindestanzahl von IAM-Rollen hinzu. Diese Rollen sind zum Logging, Monitoring und Abrufen von privaten Container-Images aus Container Registry erforderlich.
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
Firewallregeln erstellen
In den folgenden Schritten wenden Sie eine Firewallregel auf das VPC-Netzwerk an, mit der standardmäßig der gesamte ausgehende Traffic abgelehnt wird. Für das Funktionieren des Clusters und für das Erreichen von Zielen außerhalb der VPC durch Gatewayknoten ist eine eigene Verbindung erforderlich. Ein Mindestsatz an speziellen Firewallregeln überschreibt die Standardregel zum Ablehnen des gesamten Traffics, um die erforderliche Verbindung zuzulassen.
Erstellen Sie eine standardmäßige Firewallregel (mit niedriger Priorität), um den gesamten ausgehenden Traffic vom VPC-Netzwerk abzulehnen:
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."
Erstellen Sie eine Regel, die nur für die Knoten mit dem Gatewaydienstkonto Zugriff auf das Internet zulässt:
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"
Erlauben Sie Knoten das Erreichen der Kubernetes-Steuerungsebene:
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."
Optional: Diese Firewallregel ist nicht erforderlich, wenn Sie Managed Anthos Service Mesh verwenden.
Anthos Service Mesh verwendet Webhooks, um Sidecar-Proxys in Arbeitslasten einzufügen. Erlauben Sie dem GKE API-Server, die Webhooks aufzurufen, die von der Service Mesh-Steuerungsebene bereitgestellt werden, die auf den Knoten ausgeführt wird:
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"
Erlauben Sie eine ausgehende Verbindung zwischen Pods und Diensten, die im Cluster ausgeführt werden. Beachten Sie, dass GKE automatisch eine entsprechende Regel für eingehenden Traffic erstellt.
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"
Optional: Diese Firewallregel ist nicht erforderlich, wenn Sie GKE Dataplane V2 verwenden.
Ein Dienst namens Calico stellt die
NetworkPolicy
-API-Funktionalität für GKE zur Verfügung. Erlauben Sie die Verbindung für Calico innerhalb des Subnetzes: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"
GKE benötigt den schreibgeschützten kubelet-Port zum Lesen von Knotenmesswerten. Gewähren Sie im Subnetz Zugriff darauf:
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"
Gewähren Sie Zugriff auf die reservierten IP-Adressen, die vom privaten Google-Zugriff zur Bereitstellung für Google APIs, Container Registry und andere Dienste verwendet werden:
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)"
Gewähren Sie dem Systemdiagnosedienst von Google Cloud Zugriff auf Pods, die im Cluster ausgeführt werden:
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"
Privaten Zugriff auf Google Cloud APIs konfigurieren
Mit dem privaten Google-Zugriff können VMs und Pods, die nur interne IP-Adressen haben, auf Google APIs und Google-Dienste zugreifen. Obwohl Google APIs und Google-Dienste von externen IP-Adressen bereitgestellt werden, verlässt der Traffic von den Knoten nie das Google-Netzwerk, wenn der private Google-Zugriff verwendet wird.
Aktivieren Sie die Cloud DNS API:
gcloud services enable dns.googleapis.com
Erstellen Sie eine private DNS-Zone, einen CNAME
- und einen A
-Eintrag, sodass Knoten und Arbeitslasten über den privater Google-Zugriff und den Hostnamen private.googleapis.com
eine Verbindung zu Google APIs und Diensten herstellen können:
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
Privaten Zugriff auf Container Registry konfigurieren
Erstellen Sie eine private DNS-Zone, einen CNAME
- und einen A
-Eintrag, sodass Knoten über privater Google-Zugriff und den Hostnamen gcr.io
eine Verbindung zu Container Registry herstellen können:
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
Privaten GKE-Cluster erstellen
Ermitteln Sie die externe IP-Adresse von Cloud Shell, damit Sie sie der Liste der Netzwerke hinzufügen können, die Zugriff auf den API-Server Ihres Clusters haben sollen:
SHELL_IP=$(dig TXT -4 +short @ns1.google.com o-o.myaddr.l.google.com)
Nach einer Inaktivitätsphase kann sich die externe IP-Adresse der Cloud Shell-VM ändern. In diesem Fall müssen Sie die Liste der autorisierten Netzwerke Ihres Clusters aktualisieren. Fügen Sie Ihrem Initialisierungsskript den folgenden Befehl hinzu:
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
Aktivieren Sie die Google Kubernetes Engine API:
gcloud services enable container.googleapis.com
Erstellen Sie einen privaten GKE-Cluster:
gcloud container clusters create cluster1 \ --enable-ip-alias \ --enable-private-nodes \ --release-channel "regular" \ --enable-master-authorized-networks \ --master-authorized-networks ${SHELL_IP//\"}/32 \ --master-ipv4-cidr 10.5.0.0/28 \ --enable-dataplane-v2 \ --service-account "sa-application-nodes@${PROJECT_ID}.iam.gserviceaccount.com" \ --machine-type "e2-standard-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}
Es dauert einige Minuten, bis der Cluster erstellt ist. Der Cluster hat private Knoten mit internen IP-Adressen. Pods und Diensten werden IP-Adressen aus den benannten sekundären Bereichen zugewiesen, die Sie beim Erstellen des VPC-Subnetzes definiert haben.
Anthos Service Mesh mit einer clusterinternen Steuerungsebene erfordert, dass die Clusterknoten einen Maschinentyp mit mindestens 4 vCPUs verwenden.
Google empfiehlt, dass der Cluster die „normale“ Release-Version abonniert, damit Knoten eine Kubernetes-Version ausführen, die von Anthos Service Mesh unterstützt wird.
Weitere Informationen zu den Voraussetzungen für das Ausführen von Anthos Service Mesh mit einer clusterinternen Steuerungsebene finden Sie unter Voraussetzungen für Cluster im Cluster.
Weitere Informationen zu den Anforderungen und Einschränkungen zum Ausführen von verwaltetem Anthos Service Mesh finden Sie unter Verwaltete Anthos Service Mesh-Funktionen.
Workload Identity ist im Cluster aktiviert. Anthos Service Mesh erfordert Workload Identity und wird für den Zugriff auf Google APIs von GKE-Arbeitslasten empfohlen.
Erstellen Sie einen Knotenpool namens gateway. In diesem Knotenpool wird das Ausgangsgateway bereitgestellt. Die Markierung
dedicated=gateway:NoSchedule
wird allen Knoten im Gatewayknotenpool hinzugefügt.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"
Markierungen und Toleranzen von Kubernetes gewährleisten, dass nur Ausgangsgateway-Pods auf Knoten im Gatewayknotenpool ausgeführt werden.
Laden Sie die Anmeldedaten herunter, mit denen Sie mit kubectl eine Verbindung zum Cluster herstellen können:
gcloud container clusters get-credentials cluster1
Prüfen Sie, ob die Gatewayknoten die richtige Markierung haben:
kubectl get nodes -l cloud.google.com/gke-nodepool=gateway -o yaml \ -o=custom-columns='name:metadata.name,taints:spec.taints[?(@.key=="dedicated")]'
Die Ausgabe sieht in etwa so aus:
name taints gke-cluster1-gateway-9d65b410-cffs map[effect:NoSchedule key:dedicated value:gateway]
Anthos Service Mesh installieren und einrichten
Folgen Sie einer der Installationsanleitungen für Anthos Service Mesh:
Nachdem Sie Anthos Service Mesh installiert haben, können Sie diese Anleitung beenden und zu dieser Anleitung zurückkehren, ohne Gateways für eingehenden oder ausgehenden Traffic zu installieren.
Gateway für ausgehenden Traffic installieren
Erstellen Sie einen Kubernetes-Namespace für das Ausgangs-Gateway:
kubectl create namespace istio-egress
Wenn Sie das Ausgangs-Gateway bereitstellen, wird die Konfiguration automatisch anhand eines Labels eingeschleust, das Sie auf das Deployment oder den Namespace anwenden. Wenn das Standard-Tag eingerichtet ist, fügen Sie Ihrem Namespace das Label Standard-Injektionslabels hinzu. Andernfalls verwenden Sie das Überarbeitungslabel für die installierte Steuerungsebene. Das hinzugefügte Überarbeitungslabel hängt auch davon ab, ob Sie verwaltetes Anthos Service Mesh bereitgestellt oder die Steuerungsebene im Cluster installiert haben.
Wählen Sie unten den Tab entsprechend Ihrem Installationstyp (entweder verwaltet oder im Cluster) aus.
Verwaltet
Suchen Sie mit dem folgenden Befehl die verfügbaren Überarbeitungen der Steuerungsebene:
kubectl -n istio-system get controlplanerevision
Die Ausgabe sieht in etwa so aus:
NAME RECONCILED STALLED AGE asm-managed True False 112m
Notieren Sie sich den Wert in der Spalte
NAME
für die Überarbeitung der Steuerungsebene, die Sie verwenden möchten. In der Regel entspricht die Release-Version Ihres Anthos Service Mesh der Release-Version des Google Kubernetes Engine-Clusters.Clusterintern
Bei Steuerungsebenen innerhalb des Clusters haben der
istiod
-Dienst und das Deployment in der Regel ein Überarbeitungslabel wieistio.io/rev=asm-1157-23
, wobeiasm-1157-23
die Anthos Service Mesh-Version identifiziert. Die Überarbeitung wird Teil desistiod
-Dienstnamens. Beispiel:istiod-asm-1157-23.istio-system
Verwenden Sie den folgenden Befehl, um das Überarbeitungslabel in
istiod
für die clusterinterne Steuerungsebene zu finden:kubectl get deploy -n istio-system -l app=istiod \ -o=jsonpath='{.items[*].metadata.labels.istio\.io\/rev}''{"\n"}'
Erstellen Sie ein Operatormanifest für das Ausgangs-Gateway:
cat << EOF > egressgateway-operator.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: name: egressgateway-operator annotations: config.kubernetes.io/local-config: "true" spec: profile: empty revision: REVISION components: egressGateways: - name: istio-egressgateway namespace: istio-egress enabled: true values: gateways: istio-egressgateway: injectionTemplate: gateway tolerations: - key: "dedicated" operator: "Equal" value: "gateway" nodeSelector: cloud.google.com/gke-nodepool: "gateway" EOF
Laden Sie das
istioctl
-Tool herunter. Weitere Informationen finden Sie unter Richtige Istioctl-Version herunterladen.Legen Sie nach dem Extrahieren des heruntergeladenen Archivs eine Umgebungsvariable fest, die den Pfad zum
istioctl
-Tool enthält, und fügen Sie sie dem Initialisierungsskript hinzu:ISTIOCTL=$(find "$(pwd -P)" -name istioctl) echo "ISTIOCTL=\"${ISTIOCTL}\"" >> ./init-egress-tutorial.sh
Erstellen Sie mit dem Operatormanifest und
istioctl
das Installationsmanifest für das Ausgangsgateway:istioctl manifest generate \ --filename egressgateway-operator.yaml \ --output egressgateway \ --cluster-specific
Installieren Sie das Ausgangsgateway:
kubectl apply --recursive --filename egressgateway/
Prüfen Sie, ob das Ausgangs-Gateway auf Knoten im Knotenpool
gateway
ausgeführt wird:kubectl get pods -n istio-egress -o wide
Die Pods für ausgehenden Gateway-Traffic haben
affinity
für Knoten im Knotenpoolgateway
und eine Toleranz für die Ausführung auf den markierten Gateway-Knoten. Untersuchen Sie die Knotenaffinität und -toleranzen für die Pods des Ausgangsgateways:kubectl -n istio-egress get pod -l istio=egressgateway \ -o=custom-columns='name:metadata.name,node-affinity:spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms,tolerations:spec.tolerations[?(@.key=="dedicated")]'
Die Ausgabe sieht in etwa so aus:
name node-affinity tolerations istio-egressgateway-754d9684d5-jjkdz [map[matchExpressions:[map[key:cloud.google.com/gke-nodepool operator:In values:[gateway]]]]] map[key:dedicated operator:Equal value:gateway]
Envoy-Zugriffs-Logging aktivieren
Die erforderlichen Schritte zum Aktivieren von Envoy-Zugriffslogs hängen von Ihrem Anthos Service Mesh-Typ ab, entweder verwaltet oder im Cluster:
Verwaltet
Folgen Sie der Anleitung zum Aktivieren von Zugriffslogs in verwaltetem Anthos Service Mesh.
Clusterintern
Folgen Sie der Anleitung, um Zugriffslogs in Anthos Service Mesh im Cluster zu aktivieren.
Mesh-Netzwerk und Testanwendung vorbereiten
Prüfen Sie, ob das strikte gegenseitige TLS-Protokoll aktiviert ist. Wenden Sie eine
PeerAuthentication
-Standardrichtlinie für das Mesh-Netzwerk im Namespaceistio-system
an:cat <<EOF | kubectl apply -f - apiVersion: "security.istio.io/v1beta1" kind: "PeerAuthentication" metadata: name: "default" namespace: "istio-system" spec: mtls: mode: STRICT EOF
Sie können diese Konfiguration durch Erstellen von
PeerAuthentication
-Ressourcen in bestimmten Namespaces überschreiben.Erstellen Sie Namespaces zum Bereitstellen von Testarbeitslasten. In Schritten dieser Anleitung weiter unten wird erläutert, wie Sie für jeden Namespace unterschiedliche Routingregeln für ausgehenden Traffic konfigurieren.
kubectl create namespace team-x kubectl create namespace team-y
Kennzeichnen Sie die Namespaces so, dass sie von Kubernetes-Netzwerkrichtlinien ausgewählt werden können:
kubectl label namespace team-x team=x kubectl label namespace team-y team=y
Damit Anthos Service Mesh Proxy-Sidecars automatisch einschleusen kann, legen Sie für die Arbeitslast-Namespaces ein Überarbeitungslabel der Steuerungsebene fest:
kubectl label ns team-x istio.io/rev=REVISION kubectl label ns team-y istio.io/rev=REVISION
Erstellen Sie eine YAML-Datei, um Test-Deployments auszuführen:
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
Stellen Sie die Testanwendung im Namespace
team-x
bereit:kubectl -n team-x create -f ./test.yaml
Prüfen Sie, ob die Testanwendung in einem Knoten im Standardpool bereitgestellt und ein Proxy-Sidecar-Container eingefügt wurde. Wiederholen Sie den folgenden Befehl, bis der Status des Pods
Running
lautet:kubectl -n team-x get po -l app=test -o wide
Die Ausgabe sieht in etwa so aus:
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
Für zwei von zwei Containern gilt der Status
Running
. Ein Container ist die Testanwendung und der andere der Proxy-Sidecar.Der Pod wird auf einem Knoten im Standardknotenpool ausgeführt.
Prüfen Sie, ob es möglich ist, eine HTTP-Anfrage vom Testcontainer an eine externe Website zu stellen:
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
Vom Sidecar-Proxy wird eine Fehlermeldung generiert, da die Firewallregel
global-deny-egress-all
die vorgeschaltete Verbindung ablehnt.
Mithilfe der Sidecar-Ressource den Geltungsbereich der Sidecar-Proxykonfiguration einschränken
Mit der Sidecar-Ressource können Sie den Geltungsbereich des ausgehenden Listeners einschränken, der für Sidecar-Proxys konfiguriert ist. Um das Volumen der Konfiguration und die Speichernutzung zu reduzieren, wird empfohlen, für jeden Namespace eine Standardressource vom Typ Sidecar
anzuwenden.
Der Proxy, den Anthos Service Mesh im Sidecar ausführt, ist Envoy. In der Envoy-Terminologie ist ein cluster
eine logisch ähnliche Gruppe von vorgelagerten Endpunkten, die als Ziel für das Load-Balancing verwendet werden.
Prüfen Sie die im Envoy-Sidecar-Proxy für den Test-Pod konfigurierten Cluster für ausgehenden Traffic mit dem Befehl
istioctl proxy-config
:${ISTIOCTL} pc c $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}).team-x --direction outbound
Die Liste enthält etwa 11 Envoy-Cluster, unter anderem für das Gateway für ausgehenden Traffic.
Beschränken Sie die Proxykonfiguration auf ausgehende Routen, die explizit mit Diensteinträgen in den Namespaces für ausgehenden Traffic und
team-x
-Namespaces definiert wurden. Wenden Sie eineSidecar
-Ressource auf den Namespaceteam-x
an: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
Durch Festlegen von
REGISTRY_ONLY
als Richtlinienmodus für ausgehenden Traffic wird die Proxykonfiguration auf diejenigen externen Hosts beschränkt, die der Dienst-Registry des Mesh-Netzwerks explizit durch Definition der Diensteinträge hinzugefügt wurden.Mit
egress.hosts
wird festgelegt, dass der Sidecar-Proxy nur Routen aus dem Namespace für ausgehenden Traffic auswählt, die mithilfe des AttributsexportTo
verfügbar gemacht werden. Der Teil „team-x/*
“ enthält alle Routen, die lokal im Namespaceteam-x
konfiguriert wurden.Prüfen Sie die im Envoy-Sidecar-Proxy konfigurierten Cluster für ausgehenden Traffic und vergleichen Sie sie mit der Liste der Cluster, die konfiguriert werden, bevor Sie die Ressource
Sidecar
anwenden:${ISTIOCTL} pc c $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}).team-x --direction outbound
Sie sehen Cluster für das Ausgangs-Gateway und einen Cluster für den Test-Pod selbst.
Anthos Service Mesh für die Weiterleitung von Traffic über das Ausgangsgateway konfigurieren
Konfigurieren Sie ein
Gateway
für HTTP-Traffic an Port 80.Gateway
wählt den Ingress-Gateway-Proxy aus, den Sie im ausgehenden Namespace bereitgestellt haben. Die KonfigurationGateway
wird auf den Namespace für ausgehenden Traffic angewendet und verarbeitet Traffic für jeden Host.cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: egress-gateway namespace: istio-egress spec: selector: istio: egressgateway servers: - port: number: 80 name: https protocol: HTTPS hosts: - '*' tls: mode: ISTIO_MUTUAL EOF
Erstellen Sie eine
DestinationRule
für das Ausgangsgateway mit gegenseitigem TLS zur Authentifizierung und Verschlüsselung. Verwenden Sie eine einzige gemeinsame Zielregel für alle externen Hosts.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
Erstellen Sie im ausgehenden Namespace ein
ServiceEntry
, um explizit beispiel.de in der Dienstregistrierung des Mesh-Netzwerks für den Namespaceteam-x
zu registrieren: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
Erstellen Sie einen
VirtualService
, um Traffic an „example.com“ über das Ausgangsgateway zu leiten. Es gibt zwei Abgleichbedingungen: Mit der ersten wird der Traffic an das Ausgangsgateway und mit der zweiten der Traffic vom Ausgangsgateway an den Zielhost weitergeleitet. Das AttributexportTo
legt fest, welche Namespaces den virtuellen Dienst verwenden können.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
Führen Sie
istioctl analyze
aus, um Konfigurationsfehler zu ermitteln:${ISTIOCTL} analyze -n istio-egress
Die Ausgabe sieht in etwa so aus:
✔ No validation issues found when analyzing namespace: istio-egress.
Senden Sie mehrere Anfragen über das Ausgangsgateway an die externe Website:
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
Für alle vier Antworten werden
200
-Statuscodes angezeigt.Prüfen Sie in den Proxyzugriffslogs, ob die Anfragen über das Ausgangsgateway geleitet wurden. Prüfen Sie zuerst das Zugriffslog für den mit der Testanwendung bereitgestellten Proxy-Sidecar:
kubectl -n team-x logs -f $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) istio-proxy
Für jede von Ihnen gesendete Anfrage wird ein Logeintrag wie der folgende angezeigt:
[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 - -
Prüfen Sie außerdem das Zugriffslog für das Ausgangsgateway:
kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egressgateway \ -o jsonpath="{.items[0].metadata.name}") istio-proxy
Für jede von Ihnen gesendete Anfrage wird ein Zugriffslogeintrag für das Ausgangsgateway angezeigt, der in etwa so aussieht:
[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 -
Anderes Routing für einen zweiten Namespace konfigurieren
Konfigurieren Sie das Routing für einen zweiten externen Host, um zu erfahren, wie verschiedene externe Verbindungen für unterschiedliche Teams konfiguriert werden können.
Erstellen Sie eine
Sidecar
-Ressource für den Namespaceteam-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
Stellen Sie die Testanwendung im Namespace
team-y
bereit:kubectl -n team-y create -f ./test.yaml
Registrieren Sie einen zweiten externen Host und exportieren Sie ihn in die Namespaces
team-x
undteam-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
Erstellen Sie einen virtuellen Dienst, um Traffic zu „httpbin.org“ über das Ausgangsgateway zu leiten:
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
Führen Sie
istioctl analyze
aus, um Konfigurationsfehler zu ermitteln:${ISTIOCTL} analyze -n istio-egress
Es wird Folgendes angezeigt:
✔ No validation issues found when analyzing namespace: istio-egress.
Stellen Sie aus der Testanwendung
team-y
eine Anfrage an „httpbin.org“: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
Es wird eine
200 OK
-Antwort angezeigt.Stellen Sie außerdem aus der Testanwendung
team-x
eine Anfrage an „httpbin.org“.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
Es wird eine
200 OK
-Antwort angezeigt.Versuchen Sie, eine Anfrage an „example.com“ aus dem Namespace
team-y
zu stellen: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
Die Anfrage schlägt fehl, da keine ausgehende Route für den Host
example.com
konfiguriert ist.
Autorisierungsrichtlinie für eine zusätzliche Kontrolle von Traffic verwenden
In dieser Anleitung wurden im Namespace istio-egress
Autorisierungsrichtlinien für das Ausgangsgateway erstellt. Sie können Kubernetes RBAC so konfigurieren, dass nur Netzwerkadministratoren Zugriff auf den Namespace istio-egress
haben.
Erstellen Sie eine
AuthorizationPolicy
, damit Anwendungen im Namespaceteam-x
eine Verbindung zu „example.com“, aber nicht zu anderen externen Hosts herstellen können, wenn sie Anfragen über Port 80 stellen. Der entsprechendetargetPort
auf den Ausgangsgateway-Pods ist 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: action: ALLOW rules: - from: - source: namespaces: - 'team-x' to: - operation: hosts: - 'example.com' when: - key: destination.port values: ["8080"] EOF
Prüfen Sie, ob Sie aus der Testanwendung im Namespace
team-x
eine Anfrage an „example.com“ stellen können: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
Es wird eine
200 OK
-Antwort angezeigt.Stellen Sie aus der Testanwendung im Namespace
team-x
eine Anfrage an „httpbin.org“: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
Die Anfrage schlägt mit der Meldung
RBAC: access denied
und dem Statuscode „403 Verboten“ fehl. Es kann einige Sekunden dauern, bis die Autorisierungsrichtlinie wirksam wird.Autorisierungsrichtlinien bieten eine umfassende Kontrolle darüber, welcher Traffic zugelassen oder abgelehnt wird. Wenden Sie die folgende Autorisierungsrichtlinie an, damit die Testanwendung im Namespace
team-y
Anfragen an „httpbin.org“ stellen kann. Dazu wird ein bestimmter URL-Pfad für das Stellen von Anfragen mithilfe von Port 80 verwendet. Der entsprechendetargetPort
auf den Ausgangsgateway-Pods ist 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: action: ALLOW rules: - from: - source: namespaces: - 'team-y' to: - operation: hosts: - httpbin.org paths: ['/status/418'] when: - key: destination.port values: ["8080"] EOF
Versuchen Sie, aus der Testanwendung im Namespace
team-y
eine Verbindung zu „httpbin.org“ herzustellen: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
Die Anfrage schlägt mit einer RBAC-Meldung über die Ablehnung des Zugriffs und mit dem Statuscode „403 Verboten“ fehl.
Stellen Sie nun eine Anfrage an „httpbin.org/status/418“ von derselben Anwendung aus:
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
Die Anfrage ist erfolgreich, da der Pfad dem Muster in der Autorisierungsrichtlinie entspricht. Die Ausgabe sieht in etwa so aus:
-=[ teapot ]=- _...._ .' _ _ `. | ."` ^ `". _, \_;`"---"`|// | ;/ \_ _/ `"""`
TLS-Ursprung am Ausgangsgateway
Sie können Gateways für ausgehenden Traffic so konfigurieren, dass einfache HTTP-Anfragen (upgrade
) von TLS oder gegenseitigem TLS gesendet werden. Wenn Anwendungen einfache HTTP-Anfragen senden, bietet dies mehrere Vorteile bei der gemeinsamen Nutzung von Istio-TLS und TLS-Ursprung. Weitere Informationen finden Sie in den Best Practices.
Erstellen Sie eine
DestinationRule. The DestinationRule
um festzulegen, dass das Gateway eine TLS-Verbindung zu „example.com“ herstellt.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
Aktualisieren Sie den virtuellen Dienst für beispiel.de, damit Anfragen an Port 80 im Gateway
upgraded
an TLS an Port 443 sind, wenn sie an den Zielhost gesendet werden: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
Stellen Sie aus der Testanwendung im Namespace
team-x
mehrere Anfragen an „example.com“: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
Wie zuvor werden die Anfragen mit
200 OK
-Antworten erfolgreich ausgeführt.Prüfen Sie anhand des Ausgangsgatewaylogs, ob die Anfragen vom Gateway durch Herstellen von TLS-Verbindungen an die Zielhosts weitergeleitet wurden:
kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egressgateway \ -o jsonpath=" {.items[0].metadata.name}") istio-proxy
Die Ausgabe sieht in etwa so aus:
[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 -
Der Proxy-Sidecar-Server hat die Anfrage an das Gateway mithilfe von Port 80 gesendet und eine TLS-Verbindung an Port 443 hergestellt, um die Anfrage an den Zielhost zu senden.
Weiterleitung von HTTPS-/TLS-Verbindungen
Ihre vorhandenen Anwendungen nutzen möglicherweise bereits TLS-Verbindungen, wenn sie mit externen Diensten kommunizieren. Sie können das Ausgangsgateway so konfigurieren, dass TLS-Verbindungen weitergeleitet werden, ohne sie zu entschlüsseln.
Ändern Sie Ihre Konfiguration so, dass das Ausgangsgateway für die Verbindungen zu Port 443 die TLS-Weiterleitung nutzt:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: egress-gateway namespace: istio-egress spec: selector: istio: egressgateway 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
Aktualisieren Sie die
DestinationRule
, die auf das Ausgangsgateway verweist, um eine zweite Teilmenge für Port 443 auf dem Gateway hinzuzufügen. Diese neue Teilmenge verwendet kein gegenseitiges TLS. Die Kommunikation über gegenseitiges TLS von Istio wird für die Weiterleitung von TLS-Verbindungen nicht unterstützt. Verbindungen auf Port 80 verwenden weiterhin 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
Aktualisieren Sie den virtuellen Dienst für „example.com“ so, dass TLS-Traffic an Port 443 über das Gateway geleitet wird:
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
Aktualisieren Sie den virtuellen Dienst für „httpbin.org“ so, dass TLS-Traffic an Port 443 über das Gateway geleitet wird:
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
Fügen Sie eine Autorisierungsrichtlinie hinzu, die jede Art von Traffic zulässt, der an Port 443 des Ausgangsgatewaydienstes gesendet wird. Der entsprechende
targetPort
auf den Gateway-Pods ist 8443.cat <<EOF | kubectl apply -f - apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: egress-all-443 namespace: istio-egress spec: action: ALLOW rules: - when: - key: destination.port values: ["8443"] EOF
Führen Sie
istioctl analyze
aus, um Konfigurationsfehler zu ermitteln:${ISTIOCTL} analyze -n istio-egress
Es wird Folgendes angezeigt:
✔ No validation issues found when analyzing namespace: istio-egress.
Stellen Sie aus der Testanwendung im Namespace
team-x
eine einfache HTTP-Anfrage an „example.com“: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
Die Anfrage wird mit einer
200 OK
-Antwort erfolgreich ausgeführt.Erstellen Sie nun mehrere TLS-Anfragen (HTTPS) aus der Testanwendung im Namespace
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
Es werden Antworten vom Typ „200“ angezeigt.
Prüfen Sie das Log für das Ausgangsgateway noch einmal:
kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egressgateway \ -o jsonpath="{.items[0].metadata.name}") istio-proxy
Die Logeinträge sehen in etwa so aus:
[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 -
Die HTTPS-Anfrage wurde als TCP-Traffic behandelt und über das Gateway an den Zielhost weitergeleitet. Deshalb sind keine HTTP-Informationen im Log enthalten.
NetworkPolicy von Kubernetes als zusätzliche Kontrolle verwenden
Es gibt viele Szenarien, in denen eine Anwendung einen Sidecar-Proxy umgehen kann.
Mit der NetworkPolicy
von Kubernetes können Sie zusätzlich festlegen, welche Verbindungen Arbeitslasten herstellen dürfen. Nach dem Anwenden einer Netzwerkrichtlinie werden alle nicht explizit zugelassenen Verbindungen abgelehnt.
In dieser Anleitung werden nur ausgehende Verbindungen und ausgehende Selektoren für Netzwerkrichtlinien berücksichtigt. Wenn Sie eingehenden Traffic mit Netzwerkrichtlinien für Ihre Cluster steuern möchten, müssen Sie dafür Richtlinien erstellen, die Ihren Richtlinien für ausgehenden Traffic entsprechen. Wenn Sie beispielsweise ausgehenden Traffic von Arbeitslasten im Namespace team-x
zum Namespace team-y
zulassen, müssen Sie gleichzeitig eingehenden Traffic zum Namespace team-y
vom Namespace team-x
zulassen.
Erlauben Sie, dass im Namespace
team-x
bereitgestellte Arbeitslasten und Proxys eine Verbindung zuistiod
und zum Ausgangsgateway herstellen: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: "kubernetes.io/metadata.name": istio-system podSelector: matchLabels: istio: istiod - namespaceSelector: matchLabels: "kubernetes.io/metadata.name": istio-egress podSelector: matchLabels: istio: egressgateway EOF
Erlauben Sie Arbeitslasten und Proxys das Abfragen von 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: "kubernetes.io/metadata.name": kube-system ports: - port: 53 protocol: UDP - port: 53 protocol: TCP EOF
Erlauben Sie Arbeitslasten und Proxys, eine Verbindung zu den IP-Adressen für Google APIs und Google-Dienste herzustellen, einschließlich der Mesh-Zertifizierungsstelle:
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
Erlauben Sie Arbeitslasten und Proxys, eine Verbindung zum GKE-Metadatenserver herzustellen:
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
Optional: Erlauben Sie Arbeitslasten und Proxys im Namespace
team-x
Verbindungen untereinander herzustellen: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
Optional: Erlauben Sie Arbeitslasten und Proxys im Namespace
team-x
Verbindungen zu Arbeitslasten herzustellen, die von einem anderen Team bereitgestellt wurden: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: "kubernetes.io/metadata.name": team-y EOF
Verbindungen zwischen Sidecar-Proxys bleiben bestehen. Vorhandene Verbindungen werden nicht geschlossen, wenn Sie eine neue Netzwerkrichtlinie anwenden. Damit vorhandene Verbindungen geschlossen werden, starten Sie die Arbeitslasten im Namespace „team-x“ neu:
kubectl -n team-x rollout restart deployment
Prüfen Sie, ob Sie weiterhin eine HTTP-Anfrage an „example.com“ aus der Testanwendung im Namespace
team-x
stellen können: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
Die Anfrage wird mit einer
200 OK
-Antwort erfolgreich ausgeführt.
Direkter Zugriff auf Google APIs über privaten Google-Zugriff und IAM-Berechtigungen
Die Google APIs und Google-Dienste werden über externe IP-Adressen bereitgestellt. Wenn Pods mit VPC-nativen Alias-IP-Adressen Verbindungen zu Google APIs über den privaten Google-Zugriff herstellen, verlässt der Traffic nie das Google-Netzwerk.
Beim Einrichten der Infrastruktur für diese Anleitung haben Sie den privaten Google-Zugriff für das von GKE-Pods verwendete Subnetz aktiviert. Um den Zugriff auf die IP-Adressen zu ermöglichen, die vom privaten Google-Zugriff verwendet werden, erstellen Sie eine Route, eine VPC-Firewallregel und eine private DNS-Zone. Mit dieser Konfiguration können Pods Google APIs direkt erreichen, ohne Traffic über das Ausgangsgateway zu senden. Mit Workload Identity und IAM können Sie steuern, welche APIs für bestimmte Kubernetes-Dienstkonten (und somit Namespaces) verfügbar sind. Die Istio-Autorisierung wird nicht wirksam, da das Ausgangs-Gateway keine Verbindungen zu den Google APIs verarbeitet.
Damit Pods Google APIs aufrufen können, müssen Sie IAM verwenden, um Berechtigungen zu erteilen. Der Cluster, den Sie für diese Anleitung verwenden, ist so konfiguriert, dass Workload Identity verwendet wird. Dadurch kann ein Kubernetes-Dienstkonto als Google-Dienstkonto verwendet werden.
Erstellen Sie ein Google-Dienstkonto für die Anwendung:
gcloud iam service-accounts create sa-test-app-team-x
Erlauben Sie dem Kubernetes-Dienstkonto, die Identität des Google-Dienstkontos zu übernehmen:
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
Annotieren Sie das Kubernetes-Dienstkonto für die Testanwendung im Namespace
team-x
mit der E-Mail-Adresse des Google-Dienstkontos: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
Der Testanwendungs-Pod muss auf den Google-Metadatenserver (als DaemonSet ausgeführt) zugreifen können, um temporäre Anmeldedaten für den Aufruf von Google APIs abzurufen. Erstellen Sie einen Diensteintrag für den GKE-Metadatenserver:
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
Erstellen Sie außerdem einen Diensteintrag für „private.googleapis.com“ und „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
Prüfen Sie, ob das Kubernetes-Dienstkonto ordnungsgemäß als Google-Dienstkonto konfiguriert ist:
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
Es wird ein Google-Dienstkonto als aktive und einzige Identität aufgeführt.
Erstellen Sie eine Testdatei in einem Cloud Storage-Bucket:
echo "Hello, World!" > /tmp/hello gsutil mb gs://${PROJECT_ID}-bucket gsutil cp /tmp/hello gs://${PROJECT_ID}-bucket/
Gewähren Sie dem Dienstkonto die Berechtigung zum Auflisten und Aufrufen von Dateien im Bucket:
gsutil iam ch \ serviceAccount:sa-test-app-team-x@${PROJECT_ID}.iam.gserviceaccount.com:objectViewer \ gs://${PROJECT_ID}-bucket/
Prüfen Sie, ob die Testanwendung auf den Test-Bucket zugreifen kann:
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
und die Tabelle enthält folgende Informationen:
Hello, World!
Bereinigen
Damit Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden, löschen Sie entweder das Projekt, das die Ressourcen enthält, oder Sie behalten das Projekt und löschen die einzelnen Ressourcen.
Führen Sie die Schritte in den folgenden Abschnitten aus, um zu vermeiden, dass Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen in Rechnung gestellt werden:
Projekt löschen
Sie vermeiden weitere Kosten am einfachsten, wenn Sie das für die Anleitung erstellte Projekt löschen.
- Wechseln Sie in der Google Cloud Console zur Seite Ressourcen verwalten.
- Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie dann auf Löschen.
- Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Shut down (Beenden), um das Projekt zu löschen.
Nächste Schritte
- Mehr über Best Practices erfahren
- Mehr über GKE-Härtung erfahren
- TLS-Zertifikatsverwaltung für das Anthos Service Mesh-Ingress-Gateway mit CA-Dienst automatisieren
- Mehr über das Verwalten von Konfigurationen und Richtlinien in der gesamten Infrastruktur mit Anthos Configuration Management erfahren
- Weitere Referenzarchitekturen, Diagramme und Best Practices finden Sie im Cloud-Architekturcenter.