Google Cloud Armor über Ingress konfigurieren

Auf dieser Seite wird gezeigt, wie Sie mit einer benutzerdefinierten BackendConfig-Ressource Google Cloud Armor in Google Kubernetes Engine (GKE) konfigurieren können.

Überblick

In einem GKE-Cluster wird eingehender Traffic über das externe HTTP(S)-Load-Balancing abgewickelt, einer Komponente von Cloud Load Balancing. Der HTTP(S)-Load-Balancer wird in der Regel vom GKE-Ingress-Controller konfiguriert. Dieser ruft die Konfigurationsinformationen von einem Kubernetes-Ingress-Objekt ab. Das Ingress ist einem oder mehreren Dienstobjekten zugeordnet. Jedes Dienstobjekt enthält Routinginformationen, mit denen sich eine eingehende Anfrage an einen bestimmten Pod und Port weiterleiten lässt.

Ab Kubernetes Version 1.10.5-gke.3 erhalten Sie durch Zuweisen eines Dienstports mit der benutzerdefinierten Ressource BackendConfig erweiterte Konfigurationsmöglichkeiten für den Load-Balancer.

Der GKE-Ingress-Controller liest die Konfigurationsinformationen aus BackendConfig und richtet den externen Load-Balancer entsprechend ein. Eine BackendConfig-Ressource enthält für Cloud Load Balancing spezifische Konfigurationsinformationen. Ingress- und Dienstressourcen von Kubernetes bieten keine Möglichkeit, anbieterspezifische Features wie Google Cloud Armor zu konfigurieren. Mit BackendConfig können Sie diese Konfiguration vornehmen.

In der folgenden Übersicht erfahren Sie, wie Sie in dieser Übung eine BackendConfig-Ressource einrichten:

  1. Erstellen Sie eine BackendConfig-Ressource.
  2. Erstellen Sie einen Service und verknüpfen Sie einen seiner Ports mit der BackendConfig-Ressource.
  3. Erstellen Sie ein Ingress und ordnen Sie das Ingress dem Paar (Service, Port) zu.

Vorbereitung

Führen Sie die folgenden Aufgaben aus, bevor Sie beginnen:

Mit den folgenden Methoden können Sie die gcloud-Einstellungen festlegen:

  • Verwenden Sie gcloud init, wenn Sie die Standardeinstellungen ansehen möchten.
  • Verwenden Sie gcloud config, um Ihre Projekt-ID, Zone und Region individuell festzulegen.

gcloud init verwenden

Wenn Sie die Fehlermeldung One of [--zone, --region] must be supplied: Please specify location erhalten, führen Sie diesen Abschnitt aus.

  1. Führen Sie gcloud init aus und folgen Sie der Anleitung:

    gcloud init

    Wenn Sie SSH auf einem Remote-Server verwenden, können Sie mit dem Flag --console-only verhindern, dass mit dem Befehl ein Browserfenster geöffnet wird:

    gcloud init --console-only
  2. Folgen Sie der Anleitung, um gcloud zur Verwendung Ihres Google Cloud-Kontos zu autorisieren.
  3. Erstellen Sie eine neue Konfiguration oder wählen Sie eine vorhandene aus.
  4. Wählen Sie ein Google Cloud-Projekt aus.
  5. Wählen Sie eine Compute Engine-Standardzone aus.

gcloud config verwenden

  • Geben Sie Ihre standardmäßige Projekt-ID an:
    gcloud config set project project-id
  • Wenn Sie mit zonalen Clustern arbeiten, legen Sie die Standardzone für Compute Engine fest:
    gcloud config set compute/zone compute-zone
  • Wenn Sie mit regionalen Clustern arbeiten, legen Sie die Standardregion für Compute Engine fest:
    gcloud config set compute/region compute-region
  • Aktualisieren Sie gcloud auf die neueste Version:
    gcloud components update

Namespace erstellen

Erstellen Sie einen Kubernetes-Namespace für die Objekte in dieser Anleitung:

kubectl create namespace cloud-armor-how-to

Deployment erstellen

In diesem Deployment-Manifest wird festgelegt, dass Sie zwei Replikate der Webanwendung hello-app ausführen möchten:

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: cloud-armor-how-to
  name: my-deployment
spec:
  selector:
    matchLabels:
      app: hello-app
  replicas: 2
  template:
    metadata:
      labels:
        app: hello-app
    spec:
      containers:
      - name: hello-app-container
        image: gcr.io/google-samples/hello-app:1.0
        ports:
        - containerPort: 8080

Kopieren Sie das Manifest in eine Datei mit dem Namen my-deployment.yaml und erstellen Sie das Deployment:

kubectl apply -f my-deployment.yaml

Google Cloud Armor-Sicherheitsrichtlinie und -regel erstellen

Die Sicherheitsrichtlinien von Google Cloud Armor unterstützen Folgendes:

  • IP-Sperrlisten/Zulassungslisten
  • Gesperrte/Zugelassene Regionscodes (Betaversion)
  • Vorkonfigurierte Regeln zum Schutz gegen Cross-Site-Scripting (XSS) und SQL-Injection-Angriffe (SQLi) (Beta)
  • Benutzerdefinierte Regelsprache (Betaversion)

Erstellen Sie eine Google Cloud Armor-Sicherheitsrichtlinie:

gcloud beta compute security-policies create ca-how-to-security-policy \
    --description "policy for Google Cloud Armor how-to topic"

Erstellen Sie eine Regel für Ihre Sicherheitsrichtlinie:

gcloud beta compute security-policies rules create 1000 \
    --security-policy ca-how-to-security-policy \
    --description "Deny traffic from 192.0.2.0/24." \
    --src-ip-ranges "192.0.2.0/24" \
    --action "deny-404"

Sicherheitsrichtlinie anzeigen lassen:

gcloud beta compute security-policies describe ca-how-to-security-policy

Ausgabe:

...
kind: compute#securityPolicy
name: ca-how-to-security-policy
rules:
- action: deny(404)
  description: Deny traffic from 192.0.2.0/24.
  kind: compute#securityPolicyRule
  match:
    config:
      srcIpRanges:
      - 192.0.2.0/24
    versionedExpr: SRC_IPS_V1
  preview: false
  priority: 1000
  ...

BackendConfig-Ressource erstellen

Hier ist ein Manifest für eine BackendConfig-Ressource. Das Manifest gibt eine Sicherheitsrichtlinie an:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  namespace: cloud-armor-how-to
  name: my-backend-config
spec:
  securityPolicy:
    name: "ca-how-to-security-policy"

Kopieren Sie das Manifest in eine Datei mit dem Namen my-backend-config.yaml und erstellen Sie das BackendConfig-Objekt:

kubectl apply -f my-backend-config.yaml

Lassen Sie die BackendConfig-Ressource anzeigen:

kubectl get backendconfig my-backend-config --namespace cloud-armor-how-to --output yaml

In der Ausgabe wird die festgelegte Sicherheitsrichtlinie angezeigt:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backend-config
  namespace: cloud-armor-how-to
  ...
spec:
  securityPolicy:
    name: ca-how-to-security-policy

Service erstellen

Das ist ein Manifest für einen Service:

apiVersion: v1
kind: Service
metadata:
  namespace: cloud-armor-how-to
  name: my-service
  labels:
    app: hello-app
  annotations:
    cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
spec:
  type: NodePort
  selector:
    app: hello-app
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080

Speichern Sie das Manifest in einer Datei mit dem Namen my-service.yaml und erstellen Sie den Service:

kubectl apply -f my-service.yaml

Lassen Sie den Service anzeigen:

kubectl get service my-service --namespace cloud-armor-how-to --output yaml

Die Ausgabe sieht etwa so aus:

apiVersion: v1
kind: Service
metadata:
  annotations:
    cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
  labels:
    app: hello-app
  name: my-service
  namespace: cloud-armor-how-to
  ...
spec:
  clusterIP: 10.19.249.137
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 32629
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: hello-app
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}

Zum Zweck dieser Übung sollten Sie diese wichtigen Dinge in Bezug auf Ihren Dienst beachten:

  • Port 80 des Dienstes ist einer BackendConfig-Ressource mit dem Namen my-backend-config zugeordnet. Dies wird durch die Annotation cloud.google.com/backend-config angegeben.

  • Der Dienst hat den Typ NodePort. Dies ist der erforderliche Typ für Dienste, die einem Ingress zugeordnet werden.

  • Jeder Pod mit dem Label app: hello-app ist ein Mitglied des Services. Dies wird durch das Feld selector angegeben.

  • Der über TCP-Port 80 an den Dienst gerichtete Traffic wird in einem der Mitglieds-Pods an TCP-Port 8080 weitergeleitet. Dies wird durch die Felder port und targetPort angegeben.

Statische externe IP-Adresse reservieren

Reservieren Sie eine statische externe IP-Adresse:

gcloud compute addresses create cloud-armor-how-to-address --global

Lassen Sie die statische externe IP-Adresse anzeigen:

gcloud compute addresses list --filter "name=cloud-armor-how-to-address"

Ausgabe:

NAME                        REGION  ADDRESS        STATUS
cloud-armor-how-to-address          203.0.113.2    RESERVED

Ingress erstellen

Hier ist ein Manifest für ein Ingress:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  namespace: cloud-armor-how-to
  name: my-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "cloud-armor-how-to-address"
spec:
  backend:
    serviceName: my-service
    servicePort: 80

Kopieren Sie das Manifest in eine Datei mit dem Namen my-ingress.yaml und erstellen Sie das Ingress:

kubectl create -f my-ingress.yaml

Warten Sie einige Minuten, bis der Kubernetes-Ingress-Controller ein Cloud-Load-Balancer konfiguriert hat, und lassen Sie dann das Ingress anzeigen:

kubectl get ingress my-ingress --output yaml --namespace cloud-armor-how-to

Ausgabe:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  namespace: cloud-armor-how-to
  ...
spec:
  backend:
    serviceName: my-service
    servicePort: 80
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.2

Zum Zweck dieser Übung sollten Sie diese wichtigen Dinge in Bezug auf Ihr Ingress beachten:

  • Die IP-Adresse für eingehenden Traffic wird unter loadBalancer:ingress: aufgeführt.

  • Das Ingress hat genau eine Regel, die für eingehende HTTP-Anfragen von jedem Host gilt. Dies liegt daran, dass in dieser Regel kein Feld host vorhanden ist. Daher gilt die Regel standardmäßig für alle Hosts.

  • Alle eingehenden Anfragen werden unabhängig vom URL-Pfad gleich behandelt. Dies wird durch den path-Wert /* angegeben.

  • Eingehende Anfragen werden an einen Pod weitergeleitet, der Mitglied von my-service ist. In dieser Übung haben die Mitglieds-Pods das Label app: hello-app.

  • Anfragen werden an den in my-serviceangegebenen Pod des Zielports weitergeleitet. In dieser Übung ist der Zielport des Pods 8080.

Webanwendung anzeigen lassen

Warten Sie einige Minuten. Geben Sie im Browser dann Ihre statische externe IP-Adresse ein.

Auf der Seite wird die Antwort der Webanwendung "hello-app" angezeigt, die in einem der Pods Ihres Deployments ausgeführt wird:

Hello, world!
Version: 1.0.0
Hostname: my-deployment-574ddbdf88-f9fbj

Verwenden Sie curl, um die Web-App aufzurufen:

curl -v static-address

Dabei ist static-address Ihre statische externe IP-Adresse.

Die Ausgabe ist die Antwort von "hello-app":

Hello, world!
Version: 1.0.0
Hostname: my-deployment-574ddbdf88-zpb94

Sicherheitsrichtlinie trennen

Damit Sie die Sicherheitsrichtlinie von einem Ingress trennen können, setzen Sie den Namen der Sicherheitsrichtlinie in der BackendConfig auf leer. Hier ist ein Beispiel für das Trennen der Sicherheitsrichtlinie:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  namespace: cloud-armor-how-to
  name: my-backend-config
spec:
  securityPolicy:
    name: ""

Fehlerbehebung

BackendConfig wurde nicht gefunden

Dieser Fehler tritt auf, wenn in der Dienstannotation eine BackendConfig-Ressource für einen Dienstport angegeben wurde, die eigentliche BackendConfig-Ressource jedoch nicht gefunden werden konnte. Dies kann auftreten, wenn Sie die BackendConfig-Ressource entweder überhaupt nicht oder im falschen Namespace erstellt haben oder wenn Sie den Verweis in der Dienstannotation falsch geschrieben haben.

kubectl get event
KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: error getting BackendConfig for port 80 on service "default/my-service":
no BackendConfig for service port exists

Sicherheitsrichtlinie wurde nicht gefunden

Wenn die Sicherheitsrichtlinie nach der Erstellung des Ingress-Objekts nicht ordnungsgemäß dem Load-Balancer-Dienst zugeordnet wird, sollten Sie das Kubernetes-Ereignis auf Konfigurationsfehler überprüfen. Wenn Ihre BackendConfig-Ressource eine nicht vorhandene Richtlinie angibt, wird regelmäßig ein Warnungsereignis ausgegeben. Stellen Sie zur Problembehebung sicher, dass Sie in der BackendConfig-Ressource die richtige Sicherheitsrichtlinie namentlich angeben.

kubectl get event
KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: The given security policy "my-policy" does not exist.

Bereinigen

Wenn Sie mit den Übungen auf dieser Seite fertig sind, führen Sie folgende Schritte aus, um die Ressourcen zu entfernen und damit unerwünschte Kosten für Ihr Konto zu vermeiden:

Löschen Sie die Kubernetes-Objekte, die Sie für diese Übung erstellt haben:

kubectl delete ingress my-ingress --namespace cloud-armor-how-to
kubectl delete service my-service --namespace cloud-armor-how-to
kubectl delete backendconfig my-backend-config --namespace cloud-armor-how-to
kubectl delete deployment my-deployment --namespace cloud-armor-how-to
kubectl delete namespace cloud-armor-how-to

Löschen Sie Ihre statische externe IP-Adresse:

gcloud compute addresses delete cloud-armor-how-to-address --global

Löschen Sie Ihre Sicherheitsrichtlinie:

gcloud beta compute security-policies delete ca-how-to-security-policy

Weitere Informationen