Service und Ingress erstellen

In diesem Dokument wird beschrieben, wie Sie ein Kubernetes-Ingress-Objekt in einem Nutzer-, Hybrid- oder eigenständigen Cluster für Google Distributed Cloud erstellen. Ein Ingress ist einem oder mehreren Diensten zugeordnet, von denen jeder einem Satz von Pods zugeordnet ist.

Deployment erstellen

Dies ist ein Manifest für ein Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-deployment
spec:
  selector:
    matchLabels:
      greeting: hello
  replicas: 3
  template:
    metadata:
      labels:
        greeting: hello
    spec:
      containers:
      - name: hello-world
        image: "gcr.io/google-samples/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50000"
      - name: hello-kubernetes
        image: "gcr.io/google-samples/node-hello:1.0"
        env:
        - name: "PORT"
          value: "8080"

Für diese Übung sollten Sie die folgenden wichtigen Punkte zum Deployment-Manifest verstehen:

  • Jeder Pod, der zum Deployment gehört, hat das Label greeting: hello.

  • Jeder Pod hat zwei Container.

  • Die env-Felder geben an, dass die hello-app-Container TCP-Port 50000 und die node-hello-Container TCP-Port 8080 überwachen. Für hello-app können Sie die Auswirkungen der Umgebungsvariablen PORT im Quellcode sehen.

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

kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-deployment.yaml

Ersetzen Sie CLUSTER_KUBECONFIG durch den Namen der kubeconfig-Datei für Ihren Cluster.

Bereitstellung mit einem Dienst freigeben

Erstellen Sie einen Service, um Clients eine stabile Möglichkeit zu bieten, Anfragen an die Pods Ihres Deployments zu senden.

Hier ist ein Manifest für einen Dienst, der Ihre Bereitstellung für Clients in Ihrem Cluster verfügbar macht:

apiVersion: v1
kind: Service
metadata:
  name: hello-service
spec:
  type: ClusterIP
  selector:
    greeting: hello
  ports:
  - name: world-port
    protocol: TCP
    port: 60000
    targetPort: 50000
  - name: kubernetes-port
    protocol: TCP
    port: 60001
    targetPort: 8080

Kopieren Sie das Manifest in eine Datei mit dem Namen hello-service.yaml und erstellen Sie den Dienst:

kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-service.yaml

Ersetzen Sie CLUSTER_KUBECONFIG durch den Namen der kubeconfig-Datei für Ihren Cluster.

Lassen Sie den Service anzeigen:

kubectl --kubeconfig CLUSTER_KUBECONFIG get service hello-service --output yaml

Die Ausgabe zeigt den Wert von clusterIP, der dem Dienst übergeben wurde. Beispiel:

apiVersion: v1
kind: Service
metadata:
  annotations:
    ...
spec:
  clusterIP: 10.96.14.249
  clusterIPs:
  - 10.96.14.249
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: world-port
    port: 60000
    protocol: TCP
    targetPort: 50000
  - name: kubernetes-port
    port: 60001
    protocol: TCP
    targetPort: 8080
  selector:
    greeting: hello
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}

In der vorherigen Ausgabe ist das Feld ports ein Array von ServicePort-Objekten: eines mit dem Namen world-port und eines mit dem Namen kubernetes-port. Weitere Informationen zu den Dienstfeldern finden Sie in der Kubernetes-Dokumentation unter ServiceSpec.

So kann ein Client den Dienst aufrufen:

  • Verwendung von world-port: Ein Client, der auf einem der Clusterknoten ausgeführt wird, sendet eine Anfrage an clusterIP am port. In diesem Beispiel: 10.96.14.249:60000. Die Anfrage wird an einen Mitglieds-Pod am targetPort weitergeleitet. In diesem Beispiel POD_IP_ADDRESS:50000.

  • Verwendung von kubernetes-port: Ein Client, der auf einem der Clusterknoten ausgeführt wird, sendet eine Anfrage an clusterIP am port. In diesem Beispiel: 10.96.14.249:60001. Die Anfrage wird an einen Mitglieds-Pod am targetPort weitergeleitet. In diesem Beispiel POD_IP_ADDRESS:8080.

Ingress-Komponenten

Dies sind einige der Clusterkomponenten für eingehenden Traffic:

  • Das Deployment istio-ingress. Dies ist der Ingress-Proxy. Der Ingress-Proxy leitet den Traffic gemäß den in einem Ingress-Objekt angegebenen Regeln an interne Dienste weiter.

  • Der istio-ingress-Dienst. Dieser Dienst stellt das Deployment istio-ingress bereit.

  • Das Deployment istiod. Dies ist der Ingress-Controller. Der Ingress-Controller überwacht die Erstellung von Ingress-Objekten und konfiguriert den Ingress-Proxy entsprechend.

Alle diese clusterinternen Istio-Komponenten werden im Namespace gke-system installiert. Dieser Namespace steht nicht mit einer vollständigen Istio/Cloud Service Mesh-Installation in Konflikt.

Ingress-Objekt erstellen

Hier ist ein Manifest für ein Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - http:
      paths:
      - path: /greet-the-world
        pathType: Exact
        backend:
          service:
            name: hello-service
            port:
              number: 60000
      - path: /greet-kubernetes
        pathType: Exact
        backend:
          service:
            name: hello-service
            port:
              number: 60001

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

kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress.yaml

Wenn Sie einen Nutzercluster erstellen, geben Sie in der Clusterkonfigurationsdatei einen Wert für loadbalancer.ingressVIP an. Diese IP-Adresse wird auf dem Cluster-Load-Balancer konfiguriert. Wenn Sie ein Ingress-Objekt erstellen, erhält das Ingress-Objekt dieselbe VIP wie seine externe IP-Adresse.

Wenn ein Client eine Anfrage an die Nutzercluster-Ingress-VIP sendet, wird die Anfrage an Ihren Load-Balancer weitergeleitet. Der Load-Balancer leitet über den istio-ingress-Dienst die Anfrage an den Ingress-Proxy weiter, der in Ihrem Nutzercluster ausgeführt wird. Der Ingress-Proxy ist so konfiguriert, dass er die Anfrage je nach Pfad in der Anfrage-URL an verschiedene Back-Ends weiterleitet.

Der /greet-the-world-Pfad

In Ihrem Ingress-Manifest sehen Sie eine Regel, die besagt, dass der Pfad /greet-the-world mit serviceName: hello-service und servicePort: 60000 verknüpft ist. Denken Sie daran, dass 60000 der port-Wert im Abschnitt world-port Ihres hello-service-Dienstes ist.

- name: world-port
    port: 60000
    protocol: TCP
    targetPort: 50000

Der Ingress-Dienst leitet die Anfrage an clusterIP:50000 weiter. Die Anfrage wird dann an einen der Mitglieds-Pods des hello-service-Dienstes gesendet. Der Container, in dem in diesem Pod Port 50000 überwacht wird, zeigt die Meldung Hello World! an.

Der /greet-kubernetes-Pfad

In Ihrem Ingress-Manifest sehen Sie eine Regel, die besagt, dass der Pfad /greet-kubernetes mit serviceName: hello-service und servicePort: 60001 verknüpft ist. Denken Sie daran, dass 60001 der port-Wert im Abschnitt kubernetes-port Ihres hello-service-Dienstes ist.

- name: kubernetes-port
    port: 60001
    protocol: TCP
    targetPort: 8080

Der Ingress-Dienst leitet die Anfrage an clusterIP weiter: 8080. Die Anfrage wird dann an einen der Mitglieds-Pods des hello-service-Dienstes gesendet. Der Container, in dem in diesem Pod Port 8080 überwacht wird, zeigt die Meldung Hello Kubernetes! an.

Ingress-Objekt testen

Testen Sie Ingress mit dem Pfad /greet-the-world:

curl CLUSTER_INGRESS_VIP/greet-the-world

Ersetzen Sie CLUSTER_INGRESS_VIP durch die externe IP-Adresse des Ingress-Objekts.

In der Ausgabe wird die Meldung Hello, world! angezeigt:

Hello, world!
Version: 2.0.0
Hostname: ...

Testen Sie Ingress mit dem Pfad /greet-kubernetes:

curl CLUSTER_INGRESS_VIP/greet-kubernetes

In der Ausgabe wird die Meldung Hello, Kubernetes! angezeigt:

Hello Kubernetes!

Gebündelten eingehenden Traffic deaktivieren

Die in Google Distributed Cloud gebündelte Ingress-Funktion unterstützt nur Ingress-Funktionen. Sie können sich für die Einbindung in Istio oder Cloud Service Mesh entscheiden. Diese Produkte bieten zusätzliche Vorteile eines voll funktionsfähigen Service Mesh, z. B. gegenseitiges TLS (mTLS), die Möglichkeit, die Authentifizierung zwischen Diensten zu verwalten, und die Beobachtbarkeit von Arbeitslasten. Bei der Einbindung von Istio oder Cloud Service Mesh wird empfohlen, die gebündelte Ingress-Funktion zu deaktivieren.

Sie können gebündelte Ingress-Ressourcen mit dem Feld spec.clusterNetwork.bundledIngress in Ihrer Clusterkonfigurationsdatei aktivieren oder deaktivieren. Dieses Feld ist nur für Cluster der Version 1.13.0 und höher verfügbar. Das Feld bundledIngress ist standardmäßig auf true gesetzt und ist in der generierten Clusterkonfigurationsdatei nicht vorhanden. Dieses Feld ist änderbar und kann geändert werden, wenn Sie einen Cluster der Version 1.13.0 oder höher erstellen oder aktualisieren. Sie können dieses Feld auch angeben, wenn Sie einen Cluster auf Version 1.13.0 oder höher upgraden.

Die folgende Beispielclusterkonfigurationsdatei zeigt, wie Sie Ihren Cluster konfigurieren, um die gebündelte Ingress-Funktion zu deaktivieren:

apiVersion: v1
kind: Namespace
metadata:
  name: cluster-hybrid-basic
---
apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
  name: hybrid-basic
  namespace: cluster-hybrid-basic
spec:
  type: hybrid
  profile: default
  anthosBareMetalVersion: 1.13.0
  gkeConnect:
    projectID: project-fleet
  controlPlane:
    nodePoolSpec:
      nodes:
      - address: 10.200.0.2
  clusterNetwork:
    bundledIngress: false
    pods:
      cidrBlocks:
      - 192.168.0.0/16
    services:
      cidrBlocks:
      - 10.96.0.0/20
...

HTTPS für Ingress-Objekt einrichten

Wenn HTTPS-Anfragen von den Clients angenommen werden sollen, benötigt der Ingress-Proxy ein Zertifikat, damit er seine Identität gegenüber den Clients nachweisen kann. Dieser Proxy benötigt außerdem einen privaten Schlüssel, um den HTTPS-Handshake abzuschließen.

Im folgenden Beispiel werden diese Entitäten verwendet:

  • Eingehender Proxy: Beteiligt sich am HTTPS-Handshake und leitet dann Pakete an Mitglieds-Pods des hello-service-Dienstes weiter.

  • Domain für den hello-service-Service altostrat.com in Beispielorganisation

Gehen Sie so vor:

  1. Erstellen Sie ein Root-Zertifikat und einen privaten Schlüssel. In diesem Beispiel wird eine Root-Zertifizierungsstelle von root.ca.example.com in der Beispielorganisation der Root-Zertifizierungsstelle verwendet.

    openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj \
        '/O=Root CA Example Inc./CN=root.ca.example.com' -keyout root-ca.key \
        -out root-ca.crt
    
  2. Erstellen Sie eine Anfrage für die Signierung des Zertifikats:

     openssl req -out server.csr -newkey rsa:2048 -nodes -keyout server.key -subj \
         "/CN=altostrat.com/O=Example Org"
    
  3. Erstellen Sie ein Bereitstellungszertifikat für den Ingress-Proxy.

    openssl x509 -req -days 365 -CA root-ca.crt -CAkey root-ca.key -set_serial 0 \
        -in server.csr -out server.crt
    

    Sie haben jetzt die folgenden Zertifikate und Schlüssel erstellt:

    • root-ca.crt: Zertifikat für die Stammzertifizierungsstelle
    • root-ca.key: Privater Schlüssel für die Stammzertifizierungsstelle
    • server.crt: Bereitstellungszertifikat für den Ingress-Proxy
    • server.key: Privater Schlüssel für den Ingress-Proxy
  4. Erstellen Sie ein Kubernetes Secret, das das Bereitstellungszertifikat und den Schlüssel enthält.

    kubectl create secret tls example-server-creds --key=server.key --cert=server.crt \
        --namespace gke-system
    

    Das resultierende Secret heißt example-server-creds.

Deployment und Service erstellen

Wenn Sie im Abschnitt „HTTP“ in dieser Anleitung ein Deployment und einen Service erstellt haben, lassen Sie diese unverändert. Wenn dies nicht der Fall ist, erstellen Sie diese jetzt und führen Sie die für HTTP beschriebenen Schritte aus.

Ingress-Objekt erstellen

Wenn Sie bereits ein Ingress-Objekt im HTTP-Abschnitt erstellt haben, löschen Sie dieses Ingress-Objekt, bevor Sie fortfahren.

Ingress-Objekt löschen:

kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress my-ingress

Erstellen Sie ein neues Ingress-Objekt mit dem Abschnitt tls, um den Traffic für den zuvor erstellten Service zu verarbeiten. Dadurch wird HTTPS zwischen Clients und dem Ingress-Proxy aktiviert.

Hier ist ein Manifest für ein Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress-2
spec:
  tls:
  - hosts:
    - altostrat.com
    secretName: example-server-creds
  rules:
  - host: altostrat.com
    http:
      paths:
      - path: /greet-the-world
        pathType: Exact
        backend:
          service:
            name: hello-service
            port:
              number: 60000
      - path: /greet-kubernetes
        pathType: Exact
        backend:
          service:
            name: hello-service
            port:
              number: 60001

Speichern Sie das Manifest in einer Datei mit dem Namen my-ingress-2.yaml und erstellen Sie das Ingress-Objekt:

kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress-2.yaml

Bestätigen Sie dies durch Testen.

  • Testen Sie den Pfad /greet-the-world:

    curl -v --resolve altostrat.com:443:CLUSTER_INGRESS_VIP\
        https://altostrat.com/greet-the-world \
        --cacert root-ca.crt
    

    Ausgabe:

    Hello, world!
    Version: 2.0.0
    Hostname: hello-deployment-5ff7f68854-wqzp7
    
  • Testen Sie den Pfad /greet-kubernetes:

    curl -v --resolve altostrat.com:443:CLUSTER_INGRESS_VIP \
        https://altostrat.com/greet-kubernetes --cacert root-ca.crt
    

    Ausgabe:

    Hello Kubernetes!
    

LoadBalancer-Dienst erstellen

Ein Dienst vom Typ LoadBalancer ist eine weitere Möglichkeit, Arbeitslasten außerhalb Ihres Clusters verfügbar zu machen. Eine Anleitung und ein Beispiel zum Erstellen eines Dienstes vom Typ LoadBalancer finden Sie unter Dienst vom Typ LoadBalancer erstellen unter „Anwendung bereitstellen“.

Bereinigen

Löschen Sie das Ingress-Objekt:

kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress INGRESS_NAME

Ersetzen Sie INGRESS_NAME durch den Namen des Ingress-Objekts, z. B. my-ingress oder my-ingress-2.

Löschen Sie den Service:

kubectl --kubeconfig CLUSTER_KUBECONFIG delete service hello-service

Löschen Sie Ihr Deployment:

kubectl --kubeconfig CLUSTER_KUBECONFIG delete deployment hello-deployment

Löschen Sie Ihren LoadBalancer-Dienst:

kubectl --kubeconfig CLUSTER_KUBECONFIG delete service service-does-not-use-nodeports