Kapitel 4. Hinzufügen von Diensten zum Mesh

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

Im vorherigen Kapitel hast du gelernt, wie du Consul auf Kubernetes oder VMs einsetzen kannst. Der nächste Schritt bei der Nutzung von Consul ist das Hinzufügen deiner Dienste in das Netz. Dann kannst du Consul nutzen, um die Sicherheit, Beobachtbarkeit und Zuverlässigkeit zu erhöhen.

Ein Dienst wird dem Mesh "hinzugefügt", indem er bei Consul registriert wird, sein Sidecar-Proxy bereitgestellt wird und sichergestellt wird, dass die gesamte Kommunikation über diesen Proxy geleitet wird. In Kubernetes geschieht dies über eine einfache pod-Annotation. Auf VMs hast du etwas mehr zu tun: Du musst deinen Dienst bei Consul registrieren, seinen Sidecar-Proxy bereitstellen und das Routing konfigurieren.

In diesem Kapitel und den folgenden Kapiteln wird eine Beispielanwendung verwendet, die ich für das Buch erstellt habe, um die Funktionen von Consul zu veranschaulichen. Wenn du die Übungen mit der Beispielanwendung gemacht hast, bist du gut gerüstet, um deine eigenen Dienste in das Netz einzufügen.

Birdwatcher Beispielservice

Um das Service Mesh auszuprobieren, musst du zunächst einige Dienste unter einrichten. Du wirst eine einfache Anwendung namens Birdwatcher einsetzen. Birdwatcher besteht aus zwei Microservices: frontend und backend.

Der Dienst frontend bietet eine Benutzeroberfläche wie in Abbildung 4-1 dargestellt. Jedes Mal, wenn du auf "Mischen" klickst, wird ein neuer Vogel angezeigt.

Screenshot of the UI.
Abbildung 4-1. Der Dienst frontend hostet die Benutzeroberfläche für den Birdwatcher-Dienst

Der frontend Dienst nutzt die API des backend Dienstes, um neue Vögel abzurufen. Jedes Mal, wenn frontend den Endpunkt /bird von backendaufruft, erhält es eine JSON-Antwort mit Vogeldaten:

{
  "metadata": {
    "hostname": "...",
    "version": "v1"
  },
  "response": {
    "name": "Crimson fruitcrow",
    "imageURL": "...",
    "extract": "The crimson fruitcrow..."
  }
}

Die Anwendung funktioniert folgendermaßen (siehe Abbildung 4-2):

  1. Wenn du den Dienst frontend unter dem Pfad / in deinem Browser aufrufst, wird die Benutzeroberfläche geladen. Wenn du dann auf die Schaltfläche Shuffle klickst, stellt die Benutzeroberfläche eine Anfrage an den Dienst frontend unter /shuffle.

  2. Der Dienst frontend stellt dann eine eigene Anfrage an backend, um Daten über einen neuen Vogel bei /bird abzurufen.

  3. Der Dienst backend antwortet mit einem JSON-Dokument, das einen Vogel beschreibt.

  4. Der Dienst frontend leitet die Antwort an die Benutzeroberfläche weiter, und die Benutzeroberfläche zeigt den neuen Vogel an.

Diagram showing frontend calling backend.
Abbildung 4-2. Abfolge der Anfragen zum Laden eines Vogels in der Birdwatcher-Anwendung
Hinweis

frontend und backend sind in Go geschrieben, aber für Consul spielt es keine Rolle, in welcher Sprache deine Dienste geschrieben sind. Solange sie ein Netzwerkprotokoll wie TCP, HTTP oder gRPC verwenden, können sie im Dienstnetz genutzt werden.

Diese Beispielanwendung soll eine einfache Microservices-Architektur mit einem UI-Service und einem API-Service veranschaulichen. Nachdem du nun die Architektur der Birdwatcher-Anwendung verstanden hast, ist es an der Zeit, sie zu implementieren. Du wirst Birdwatcher zunächst ohne das Service-Mesh und bereitstellen und dann lernen, wie du es dem Mesh hinzufügst.

Ich behandle zuerst Kubernetes und gehe dann zu VMs über ("Dienste auf VMs bereitstellen").

Bereitstellung von Diensten in Kubernetes

Um die Dienste frontend und backend in Kubernetes zu implementieren, musst du Deployment- und Service-Ressourcen erstellen. Wie in Kapitel 2 beschrieben, ist ein Deployment ein Kubernetes-Ressourcentyp, mit dem du mehrere Replikate eines Dienstes bereitstellen und seinen Lebenszyklus verwalten kannst. Dienste werden in Kubernetes verwendet, um das Routing zu konfigurieren. Indem du eine Service-Ressource anlegst, erstellst du einen DNS-Eintrag, der zu deinem Deployment leitet. Wenn du z. B. eine Service-Ressource für den Dienst backend erstellst, kann der Dienst frontend nun backend über die URL http://backend aufrufen.1

Um Ressourcen in Kubernetes zu erstellen, musst du YAML-Dateien verwenden. Erstelle in demselben Verzeichnis, in dem du die Datei values.yaml für deine Installation erstellt hast, ein neues Verzeichnis namens manifests und cd:

$ mkdir manifests
$ cd manifests

Im Verzeichnis manifests erstellst du vier YAML-Dateien: frontend-deployment.yaml(Beispiel 4-1), frontend-service.yaml(Beispiel 4-2), backend-deployment.yaml(Beispiel 4-3) und backend-service.yaml(Beispiel 4-4).

Beispiel 4-1. frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  labels:
    app: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
      annotations:
    spec:
      containers:
        - name: frontend
          image: ghcr.io/consul-up/birdwatcher-frontend:1.0.0
          env:
            - name: BIND_ADDR
              value: "0.0.0.0:6060"
            - name: BACKEND_URL
              value: "http://backend"
          ports:
            - containerPort: 6060
Beispiel 4-2. frontend-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    app: frontend
spec:
  type: LoadBalancer
  selector:
    app: frontend
  ports:
    - protocol: TCP
      port: 6060
      targetPort: 6060
Warnung

Wenn du minikube nicht unter macOS verwendest, ändere den Typ von LoadBalancer auf ClusterIP, damit du keinen öffentlichen Load Balancer erstellst.

Beispiel 4-3. backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  labels:
    app: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
      annotations:
    spec:
      containers:
        - name: backend
          image: ghcr.io/consul-up/birdwatcher-backend:1.0.0
          env:
            - name: BIND_ADDR
              value: "0.0.0.0:7000"
          ports:
            - containerPort: 7000
Beispiel 4-4. backend-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: backend
  labels:
    app: backend
spec:
  selector:
    app: backend
  ports:
    - protocol: TCP
      port: 80
      targetPort: 7000

Verwende kubectl apply, um diese Ressourcen auf Kubernetes anzuwenden:

$ kubectl apply -f ./

deployment.apps/backend created
service/backend created
deployment.apps/frontend created
service/frontend created

Verwende den Befehl kubectl get mit dem Flag --selector, um den Einsatz und den Dienst des Dienstes frontend anzuzeigen:

$ kubectl get deployment,service --selector app=frontend

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/frontend   1/1     1            1           1s

NAME               TYPE           CLUSTER-IP      EXTERNAL-IP ...
service/frontend   LoadBalancer   10.98.221.236   127.0.0.1   ...

deployment.apps/frontend sollte 1/1 READY und 1 AVAILABLE anzeigen, was bedeutet, dass ein Pod läuft und der eine Container in diesem Pod bereit ist.

Verwende denselben Befehl mit einem anderen Selektor, um den Einsatz und den Dienst des backend Dienstes anzuzeigen:

$ kubectl get deployment,service --selector app=backend

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/backend   1/1     1            1           1s

NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/backend   ClusterIP   10.96.38.122   <none>        80/TCP    1s

Jetzt, wo deine Dienste eingerichtet sind, , solltest du in der Lage sein, auf die Birdwatcher-Benutzeroberfläche zuzugreifen. Vergewissere dich zunächst, dass du minikube tunnel verwendest, damit die Ports richtig weitergeleitet werden,2 und wechsle dann mit deinem Browser zu http://localhost:6060. Du solltest die Birdwatcher-Benutzeroberfläche sehen, wie sie in Abbildung 4-1 dargestellt ist.

Du hast die Dienste frontend und backend erfolgreich in Kubernetes implementiert und überprüft, ob sie wie erwartet miteinander kommunizieren. Die aktuelle Architektur ist in Abbildung 4-3 dargestellt. Du rufst http://localhost:6060 auf , das von minikube tunnel über seine Service-Ressource an den Pod frontend weitergeleitet wird. Der Pod frontend ruft dann backend über seinen DNS-Hostnamen http://backend auf, der über seine Service-Ressource an den Pod backend weitergeleitet wird.

Frontend calling backend without a mesh.
Abbildung 4-3. Der aktuelle Anfragepfad der Birdwatcher-Anwendung

Du hast jetzt einen typischen Satz von Kubernetes-Diensten laufen, aber diese Dienste sind noch nicht Teil des Mesh. Sie sind nicht bei Consul registriert und kommunizieren nicht über Sidecar-Proxys. Der nächste Schritt besteht darin, die Dienste zum Mesh hinzuzufügen.

Hinzufügen von Kubernetes-Diensten zum Mesh

Um einen Kubernetes-Dienst zum Mesh hinzuzufügen, musst du nur die Annotation consul.hashicorp.com/connect-inject: "true" zu den Pods hinzufügen. Diese Annotation weist Consul an, den Dienst zu registrieren und einen Sidecar-Proxy einzubinden (die Sidebar "Unter der Haube" erklärt, wie das funktioniert).

Du musst beide Bereitstellungen bearbeiten, um die Anmerkung hinzuzufügen. Zuerst bearbeitest du die frontend-deployment.yaml und fügst die Anmerkung unter spec.template.metadata hinzu:

# frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
# ...
spec:
  # ...
  template:
    metadata:
      labels:
        app: frontend
      annotations:
        consul.hashicorp.com/connect-inject: "true" 1
    spec:
      containers:
        # ...
1

Achte darauf, dass du true in Anführungszeichen setzt, sonst bekommst du einen Fehler.

Hinweis

Du musst die Anmerkung zum Schlüssel spec.template.metadata hinzufügen und nicht zum Schlüssel der obersten Ebene metadata. Der Top-Level-Schlüssel metadata legt die Metadaten für den Einsatz fest und der Schlüssel spec.template.metadata die Metadaten für die Pods, aus denen der Einsatz besteht. Consul betrachtet nur Pods (siehe "Unter der Haube") und keine Einsätze.

Nachdem du deine YAML geändert hast, kannst du den Dienst frontend neu bereitstellen. Verwende dazu kubectl apply im Verzeichnis manifests:

$ kubectl apply -f frontend-deployment.yaml

deployment.apps/frontend configured

Kubernetes kümmert sich um den Start eines neuen Pods und um das Herunterfahren des alten Pods. Du kannst den Befehl kubectl rollout verwenden, um zu warten, bis die Umverteilung abgeschlossen ist. Das kann ein oder zwei Minuten dauern, weil Kubernetes zusätzliche Docker-Images herunterladen muss:

$ kubectl rollout status --watch deploy/frontend

Waiting for deployment "frontend" rollout to finish...
deployment "frontend" successfully rolled out

Nachdem der Pod neu verteilt wurde, solltest du, wenn du die Consul UI unter http://localhost:8500 öffnest, den Dienst frontend in der Liste sehen, wie in Abbildung 4-4 dargestellt (stelle sicher, dass minikube tunnel oder kubectl port-forward läuft). Das bedeutet, dass der Dienst frontend jetzt Teil des Dienstnetzes ist!

Image of the Consul UI with the frontend service listed
Abbildung 4-4. Der Dienst frontend ist jetzt in der Consul-Benutzeroberfläche aufgeführt

Füge nun den Dienst backend zum Netz hinzu, indem du dieselbe Annotation (und eine zusätzliche Annotation, um einige Metadaten zu setzen) zur backend-deployment.yaml hinzufügst:

# backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
# ...
spec:
  # ...
  template:
    metadata:
      labels:
        app: backend
      annotations:
        consul.hashicorp.com/connect-inject: "true"
        consul.hashicorp.com/service-meta-version: "v1" 1
    spec:
      containers:
        # ...
1

Diese Annotation legt einen Consul-Metadatenschlüssel fest. Sie wird vorerst nicht verwendet , aber in Kapitel 9, wenn du dich mit Bereitstellungsstrategien beschäftigst, wirst du eine v2 Version des backend Dienstes bereitstellen.

Setze sie mit kubectl apply wieder ein:

$ kubectl apply -f backend-deployment.yaml

deployment.apps/backend configured

Warte, bis der Rollout abgeschlossen ist:

$ kubectl rollout status --watch deploy/backend

Waiting for deployment "backend" rollout to finish:
  1 old replicas are pending termination...
deployment "backend" successfully rolled out

Wenn du jetzt die Benutzeroberfläche anschaust, solltest du sowohl die Dienste frontend als auch backend sehen, wie in Abbildung 4-5 dargestellt.

Image of the Consul UI with the frontend and backend services listed
Abbildung 4-5. Die Dienste frontend und backend sind jetzt auch in derConsul-Benutzeroberfläche aufgeführt

Jetzt, wo die Dienste frontend und backend Teil des Dienstnetzes sind, kannst du, wenn du minikube tunnel verwendest, versuchen, die Birdwatcher-Benutzeroberfläche erneut unter http://localhost:6060 zu laden . Du solltest eine Fehlermeldung ähnlich wie in Abbildung 4-6 sehen.

Du bekommst diese Fehlermeldung, weil der Dienst frontend jetzt Teil des Netzes ist und sein Sidecar-Proxy den gesamten eingehenden Datenverkehr abfängt. Consul ist standardmäßig sicher und verlangt, dass der gesamte Datenverkehr durch das Servicenetz authentifiziert und autorisiert wird. Wenn du über deinen Browser eine Anfrage an den Dienst frontend stellst, ist deine Anfrage weder authentifiziert noch autorisiert und wird daher von Consul abgelehnt. Dies ist in Abbildung 4-7 dargestellt.

Screenshot of the error.
Abbildung 4-6. Wenn du jetzt das Birdwatcher UI lädst, bekommst du eine Fehlermeldung
Diagram of the new architecture.
Abbildung 4-7. Der frontend Pod hat jetzt einen Sidecar-Proxy, der den gesamten Datenverkehr abfängt. Dieser Sidecar lehnt eingehenden Verkehr ab, der nicht autorisiert ist.

Wenn du kubectl port-forward verwendest, wirst du keine Fehlermeldung sehen. Das liegt daran, dass kubectl port-forward den Sidecar-Proxy tatsächlich umgeht. Du kannst den gleichen Fehler aber auch reproduzieren, indem du kubectl exec für einen normalen Aufruf des frontend Dienstes verwendest:

$ kubectl exec consul-server-0 -n consul -- \
    curl -sS http://frontend.default:6060

curl: (52) Empty reply from server
command terminated with exit code 52
Tipp

Unter Windows, wenn du die PowerShell verwendest, ersetze \ durch `.

Im nächsten Kapitel wirst du ein Ingress-Gateway einrichten, über das du den Dienst frontend mit der entsprechenden Berechtigung aufrufen kannst. Im Moment willst du aber noch überprüfen, ob der Datenverkehr zwischen den Diensten frontend und backend wie erwartet funktioniert. Dazu kannst du den Proxy von frontendumgehen, indem du kubectl exec verwendest, um einen Befehl im Container frontend auszuführen und backend direkt aufzurufen:

$ kubectl exec deploy/frontend -c frontend -- \
    curl -si http://backend/bird


HTTP/1.1 200 OK
...

Wenn alles wie erwartet funktioniert, solltest du eine HTTP 200 OK Antwort vom backend Dienst erhalten. Diese Anfrage durchläuft jetzt das Dienstnetz, wie in Abbildung 4-8 dargestellt.

Diagram of kubectl exec.
Abbildung 4-8. kubectl exec umgeht den Proxy von frontend, weil er innerhalb des Containers frontend läuft. Die Anfrage an backend wird dann wie erwartet durch das Dienstnetz geleitet.

Um zu beweisen, dass die Anfragen durch das Servicenetz gehen, kannst du die Topologieansicht der Consul UI verwenden, die die von den Sidecar-Proxys ausgegebenen Metriken anzeigt.

Führe den vorherigen Befehl kubectl exec noch ein paar Mal aus, um weitere Metriken zu erzeugen, und navigiere dann zur Topologieseite für den Dienst backend, indem du in der Ansicht Alle Dienste auf den Dienst backend klickst oder zu http://localhost:8500/ui/dc1/services/backend/topology navigierst . Du solltest etwas Ähnliches wie in Abbildung 4-9 sehen (es kann eine Minute dauern, bis die Metriken angezeigt werden).

Image of the Consul UI's view for the backend service.
Abbildung 4-9. Die Topologieansicht des backend Dienstes sollte die Metriken der eingehenden Anfragen anzeigen
Hinweis

Die Warnungen, die du in der Topologieansicht siehst, sind darauf zurückzuführen, dass ACLs nicht aktiviert sind und du keine Absichten erstellt hast. ACLs werden in Kapitel 10 behandelt und du wirst in Kapitel 6 Absichten erstellen. Du wirst auch feststellen, dass die Topologie zeigt, dass backend frontend aufruft, was nicht korrekt ist. Das liegt daran, dass Consul alle erlaubten Verbindungen zwischen Diensten anzeigt. Wenn du später Absichten erstellst, um nur bestimmte Verbindungen zuzulassen, wird sich die Topologieansicht ändern.

Wenn du unter in der Topologieansicht Metriken siehst, hast du deine Dienste erfolgreich zum Mesh hinzugefügt! Die Metriken beweisen, dass die Sidecar-Proxys den Datenverkehr erfassen.

Hinweis

Wenn du auf den Dienst frontend klickst, siehst du keine Metriken. Das liegt daran, dass das Diagramm nur eingehende Anfragen anzeigt und du zurzeit keine Anfragen an den Dienst frontend stellst. Im nächsten Kapitel wirst du ein Ingress-Gateway einrichten, das es dir ermöglicht, Anfragen an den Dienst frontend zu stellen, und dann wirst du auch dessen Metriken sehen.

Im nächsten Abschnitt erfährst du, wie du Dienste, die auf VMs laufen, in das Netz einbindest. Wenn du dich nur für Kubernetes interessierst, überspringe bis zur Zusammenfassung des Kapitels.

Dienste auf VMs bereitstellen

In diesem Abschnitt erfährst du, wie du die Birdwatcher-Anwendung auf VMs ohne Mesh bereitstellst und ausführst. Sobald Birdwatcher läuft, erfährst du, wie du ihn zum Mesh hinzufügen kannst. Der Prozess zum Hinzufügen von Birdwatcher zum Mesh ähnelt dem, den du für deine eigenen Dienste befolgst.

Du wirst der Einfachheit halber sowohl frontend als auch backend auf der gleichen VM ausführen. Der erste Schritt besteht darin, die Binärdateien frontend und backend in die VM zu laden. Wenn du die vorgefertigte VM über Vagrant verwendest, sind die Binärdateien bereits vorhanden. Wenn du deine eigene VM verwendest, findest du die Binärdateien im GitHub-Repository des Buches.

Nachdem du die Binärdateien installiert hast, musst du sie mit systemd starten, genauso wie du es mit Consul getan hast. Zuerst erstellst du zwei systemd Unit-Dateien, frontend.service und backend.service, in /etc/systemd/system/ (stelle sicher, dass du zuerst vagrant ssh ausgeführt hast).

$ sudo touch /etc/systemd/system/frontend.service
$ sudo touch /etc/systemd/system/backend.service

Bearbeite /etc/systemd/system/frontend.service und füge den Inhalt aus Beispiel 4-5 hinzu.

Tipp

Du musst sudo verwenden, um Dateien in /etc/systemd/systemzu bearbeiten - zumBeispiel sudo vim /etc/systemd/system/frontend.service.

Beispiel 4-5. /etc/systemd/system/frontend.service
[Unit]
Description="Frontend service"

# The service requires the VM's network
# to be configured, e.g., an IP address has been assigned.
Requires=network-online.target
After=network-online.target

[Service]
# ExecStart is the command to run.
ExecStart=/usr/local/bin/frontend

# Restart configures the restart policy. In this case, we
# want to restart the service if it fails.
Restart=on-failure

# Environment sets environment variables.
# We will set the frontend service to listen
# on port 6060.
Environment=BIND_ADDR=0.0.0.0:6060

# We set BACKEND_URL to http://localhost:7000 because
# that's the port we'll run our backend service on.
Environment=BACKEND_URL=http://localhost:7000

# The Install section configures this service to start
# automatically if the VM reboots.
[Install]
WantedBy=multi-user.target

Als nächstes bearbeitest du /etc/systemd/system/backend.service so, dass sie mit Beispiel 4-6 übereinstimmt.

Beispiel 4-6. /etc/systemd/system/backend.service
[Unit]
Description="Backend service"
Requires=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/local/bin/backend
Restart=on-failure

# We will set the backend service to listen
# on port 7000.
Environment=BIND_ADDR=0.0.0.0:7000

[Install]
WantedBy=multi-user.target

Wenn die Unit-Dateien vorhanden sind, kannst du deine5 und deine Dienste zu starten:

$ sudo systemctl enable frontend backend

Created symlink ...
Created symlink ...

Starte jetzt die Dienste:

$ sudo systemctl start frontend backend
Hinweis

Für diese Übung führst du all diese Schritte manuell aus, aber für eine produktive Bereitstellung solltest du ein Provisioning-Tool wie Ansible oder Terraform und Packer verwenden.

Du kannst ihren Status mit systemctl status überprüfen:

$ sudo systemctl status frontend backend

  frontend.service - "Frontend service"
     Loaded: loaded...
     Active: active (running)...
...
  backend.service - "Backend service"
     Loaded: loaded...
     Active: active (running)...

Jetzt, wo frontend und backend laufen, solltest du in der Lage sein, die Birdwatcher-Anwendung aufzurufen, indem du mit deinem Browser zu http://localhost:6060 navigierst . Du solltest die Benutzeroberfläche sehen, wie sie in Abbildung 4-1 dargestellt ist.

Die aktuelle Architektur ist in Abbildung 4-10 dargestellt.

Frontend calling backend without a mesh.
Abbildung 4-10. frontend lauscht auf Port 6060, und backend lauscht auf Port 7000

Deine Dienste laufen jetzt, aber sie sind noch nicht im Mesh registriert und ihr Datenverkehr fließt nicht durch die Sidecar-Proxys. In den nächsten Abschnitten wirst du die Dienste bei Consul registrieren und die Sidecar-Proxys starten. Dies sind die gleichen Schritte, die du auch für deine eigenen Dienste durchführen musst.

Registrierung von VM-Diensten bei Consul

Du musst Dienste bei Consul registrieren, damit weiß, welche Dienste auf welchen IPs und Ports laufen. Dienste können über Konfigurationsdateien oder über die API von Consul registriert werden. Bei dynamischen Systemen wie Container-Orchestratoren ist es sinnvoll, die API zu verwenden, aber bei VMs ist es oft einfacher, Konfigurationsdateien zu verwenden, weil du normalerweise schon bei der Bereitstellung weißt, welche Dienste auf einer bestimmten VM laufen werden.

Erstelle die Dienstkonfigurationsdateien im Konfigurationsverzeichnis von Consul /etc/consul.d:6

$ sudo touch /etc/consul.d/frontend.hcl
$ sudo touch /etc/consul.d/backend.hcl

Füge den Inhalt aus Beispiel 4-7 zu /etc/consul.d/frontend.hcl hinzu.

Beispiel 4-7. /etc/consul.d/frontend.hcl
service {
  name = "frontend"

  # frontend runs on port 6060.
  port = 6060

  # The "connect" stanza configures service mesh
  # features.
  connect {
    sidecar_service {
      # frontend's proxy will listen on port 21000.
      port = 21000

      proxy {
        # The "upstreams" stanza configures
        # which ports the sidecar proxy will expose
        # and what services they'll route to.
        upstreams = [
          {
            # Here you're configuring the sidecar proxy to
            # proxy port 6001 to the backend service.
            destination_name = "backend"
            local_bind_port  = 6001
          }
        ]
      }
    }
  }
}
Hinweis

Normalerweise legst du den Port des Proxys nicht fest und lässt ihn stattdessen dynamisch von Consul zuweisen. In dieser Übung legst du den Port des frontend Proxys auf 21000 fest, damit im gesamten Buch klar ist, welche Proxys an welchen Ports liegen.

Für /etc/consul.d/backend.hcl verwendest du den in Beispiel 4-8 gezeigten Code.

Beispiel 4-8. /etc/consul.d/backend.hcl
service {
  name = "backend"
  # backend runs on port 7000.
  port = 7000

  meta {
    version = "v1"
  }

  # The backend service doesn't call
  # any other services so it doesn't
  # need an "upstreams" stanza.
  #
  # The connect stanza is still required to
  # indicate that it needs a sidecar proxy.
  connect {
    sidecar_service {
      # backend's proxy will listen on port 22000.
      port = 22000
    }
  }
}

Deine eigenen Dienste benötigen ähnliche Konfigurationsdateien. Du musst den Namen des Dienstes, den Port, auf dem er lauscht, und alle Upstream-Abhängigkeiten festlegen (siehe "Upstreams").

Du musst Consul anweisen, seine Konfiguration neu zu laden, damit es die neuen Dateien übernimmt. Verwende dazu den Befehl consul reload:

$ consul reload

Configuration reload triggered

Du kannst den Befehl consul catalog services verwenden, um zu überprüfen, ob deine Dienste erfolgreich registriert wurden:

$ consul catalog services

backend
backend-sidecar-proxy
consul
frontend
frontend-sidecar-proxy

Du solltest frontend und backend zusammen mit ihren Sidecar-Proxys aufgelistet sehen.

Hinweis

Warum sind frontend-sidecar-proxy und backend-sidecar-proxy aufgeführt? Unter der Haube behandelt Consul die Sidecar-Proxys als separate Dienste. Du wirst die Proxys nicht in der Benutzeroberfläche sehen, weil sie versteckt sind, aber du wirst sie in der API oder CLI sehen.

In der Benutzeroberfläche unter http://localhost:8500 sollten frontend und backend aufgelistet sein(Abbildung 4-11), obwohl sie als ungesund angezeigt werden. Das liegt daran, dass ihre Sidecar-Proxys noch nicht laufen.

Image of the Consul UI
Abbildung 4-11. Die Dienste frontend und backend sind in der Benutzeroberfläche aufgeführt, werden aber als ungesund angezeigt, weil ihre Sidecar-Proxys noch nicht laufen

Jetzt, wo deine Dienste in Consul registriert sind, ist es an der Zeit ihre Sidecar-Proxys einzusetzen.

Einsatz von Sidecar Proxies auf VMs

Damit deine Dienste funktionsfähig sind, müssen die Proxys der Sidecars laufen. Auf den Sidecar-Proxys läuft Envoy, das bereits auf der Vagrant-VM installiert ist. Wenn du deine eigenen VMs verwendest, schau dir die Installationsanleitung von Envoy an.

Wie bei den Diensten frontend und backend konfigurierst du einen Dienst systemd, um jeden Sidecar-Proxy auszuführen. Der Befehl, mit dem systemd die Sidecar-Proxys ausführt, lautet:

consul connect envoy

Dieser Befehl akzeptiert ein Flag, -sidecar-for, mit dem du den Envoy-Proxy für einen bestimmten Dienst konfigurieren kannst.

Hinweis

Consul unterstützt nicht den Betrieb eines einzelnen Envoy-Proxys für mehrere Dienste, da jeder Envoy-Proxy die Identität des Quelldienstes in jeder Anfrage verschlüsseln muss. Außerdem musst du für jeden Dienst unterschiedliche Regeln für den Proxy konfigurieren.

Erstelle zunächst die beiden Einheitsdateien:

$ sudo touch /etc/systemd/system/frontend-sidecar-proxy.service
$ sudo touch /etc/systemd/system/backend-sidecar-proxy.service

/etc/systemd/system/frontend-sidecar-proxy.service sollte Beispiel 4-9 entsprechen.

Beispiel 4-9. /etc/systemd/system/frontend-sidecar-proxy.service
[Unit]
Description="Frontend sidecar proxy service"
Requires=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/bin/consul connect envoy -sidecar-for frontend \
  -admin-bind 127.0.0.1:19000
Restart=on-failure

[Install]
WantedBy=multi-user.target

Und /etc/systemd/system/backend-sidecar-proxy.service sollte dem Beispiel 4-10 entsprechen.

Beispiel 4-10. /etc/systemd/system/backend-sidecar-proxy.service
[Unit]
Description="Backend sidecar proxy service"
Requires=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/bin/consul connect envoy -sidecar-for backend \
  -admin-bind 127.0.0.1:19001
Restart=on-failure

[Install]
WantedBy=multi-user.target

Als nächstes aktivierst du die beiden Dienste:

$ sudo systemctl enable frontend-sidecar-proxy
$ sudo systemctl enable backend-sidecar-proxy

Jetzt starte sie!

$ sudo systemctl start frontend-sidecar-proxy
$ sudo systemctl start backend-sidecar-proxy

Überprüfe, ob ihr Status aktiv und in Betrieb ist:

$ sudo systemctl status frontend-sidecar-proxy

 frontend-sidecar-proxy.service - "Frontend sidecar proxy service"
     Loaded: loaded...
     Active: active (running)...
$ sudo systemctl status backend-sidecar-proxy

 backend-sidecar-proxy.service - "Backend sidecar proxy service"
     Loaded: loaded...
     Active: active (running)...

Wenn die Proxys jetzt laufen, sollte die Benutzeroberfläche alles als gesund anzeigen (sieheAbbildung 4-12).

Image of the Consul UI
Abbildung 4-12. Die Dienste frontend und backend sind jetzt in Ordnung, weil ihre Sidecar-Proxys laufen

Lade die Birdwatcher-Benutzeroberfläche unter http://localhost:6060 neu, um zu sehen, ob sich etwas geändert hat. Die Benutzeroberfläche sollte genauso aussehen und funktionieren wie vorher. Woher weißt du also, ob der Datenverkehr durch das Servicenetz geleitet wird?

Eine Möglichkeit zu prüfen, ob der Verkehr durch das Netz geleitet wird, besteht darin, eine Intention zu erstellen, die den gesamten Verkehr verweigert. Intentionen sind Autorisierungsregeln, die festlegen, welche Dienste kommunizieren dürfen. Intentionen werden in Kapitel 6 ausführlich behandelt, aber du kannst sie jetzt als schnellen Test verwenden, um zu sehen, ob der Verkehr durch das Netz geleitet wird.

Erstelle mit der Consul CLI eine Absicht, um den gesamten Verkehr zwischen den Diensten zu verweigern:

$ consul intention create -deny '*' '*'

Created: * => * (deny)

Versuche nun, die Birdwatcher-Benutzeroberfläche erneut zu laden. Die Benutzeroberfläche sollte einen neuen Vogel laden, obwohl die Absicht ist, den Verkehr zu verweigern. Was ist also los?

Anders als in Kubernetes musst du beim Hinzufügen von Diensten zum Service-Mesh auf VMs einige Änderungen an den URLs vornehmen, die deine Dienste verwenden, damit sie den Datenverkehr über ihre Sidecar-Proxys leiten. Im Moment ruft frontend immer noch backend direkt auf und umgeht sowohl seinen lokalen Proxy als auch den Proxy von backend, wie in Abbildung 4-13 dargestellt. Die Intentionen werden von den Proxys durchgesetzt, deshalb lädt die Birdwatcher-Benutzeroberfläche immer noch Vögel.

Frontend calling backend bypassing the sidecar proxies.
Abbildung 4-13. frontend ruft backend direkt auf - unter Umgehung der Sidecar-Proxys

Routing auf VMs konfigurieren

Du musst frontend so konfigurieren, dass es Anfragen über seinen Sidecar-Proxy an backend weiterleitet. Erinnerst du dich daran, wie du die Upstreams von frontendkonfiguriert hast? Du hast den local_bind_port für den backend Dienst auf 6001 gesetzt. Jetzt musst du nur noch frontend so konfigurieren, dass er diesen Port verwendet.

Glücklicherweise stellt der Dienst frontend die Umgebungsvariable BACKEND_URL zur Verfügung, mit der die URL für den Aufruf von backend konfiguriert werden kann.

Tipp

In deinen eigenen Diensten wirst du wahrscheinlich die gleiche Möglichkeit haben, Upstream-URLs über eine Umgebungsvariable oder eine Konfigurationsdatei zu konfigurieren. Wenn nicht, musst du den Code deines Dienstes ändern.

Zurzeit ist diese Umgebungsvariable in deiner frontend.service-Datei auf http://localhost:7000 gesetzt. Du musst sie also nur auf http://localhost:6001 setzen.

Editiere /etc/systemd/system/frontend.service mit sudo (frontend.service, nicht frontend-sidecar-proxy.service) und ändere die Umgebungsvariable BACKEND_URL in http://localhost:6001:

...
Environment=BACKEND_URL=http://localhost:6001
...

Führe nun systemctl daemon-reload aus, damit systemd die aktualisierte Konfiguration lädt und benutze dann systemctl restart, um den Dienst frontend neu zu starten:

$ sudo systemctl daemon-reload
$ sudo systemctl restart frontend

Wenn du die Birdwatcher-Benutzeroberfläche unter http://localhost:6060 erneut lädst, solltest du jetzt einen Fehler sehen:

Unable to call backend: Get "http://localhost:6001/bird": EOF

Dieser Fehler bestätigt, dass frontend versucht, backend über seinen Sidecar-Proxy aufzurufen und der Aufruf fehlschlägt, weil der Sidecar-Proxy von backenddie Anfrage ablehnt.

Lösche die Absicht, den Verkehr zuzulassen:

$ consul intention delete '*' '*'

Intention deleted.

Gehe zurück zur Benutzeroberfläche und klicke auf die Schaltfläche "Mischen". Die Vögel sollten jetzt wieder geladen werden!

Jetzt hast du bestätigt, dass die Anfragen zwischen frontend und backend durch das Service Mesh geleitet werden!7 Abbildung 4-14 zeigt, wie die Architektur jetzt aussieht.

Frontend calling backend through the sidecar proxies.
Abbildung 4-14. frontend ruft backend über die Mesh-Sidecar-Proxys auf. Du greifst immer noch direkt auf frontend zu.
Hinweis

Es gibt zwei Gruppen von Ports für einen Sidecar-Proxy: vorgelagerte und öffentliche Ports. Ein Dienst nutzt die Upstream-Ports seines Proxys, um seine Abhängigkeiten an weiterzuleiten. In diesem Beispiel ist 6001 ein vorgelagerter Port.

Öffentliche Ports sind die Ports, an denen der eingehende Verkehr von anderen Sidecar-Proxys empfangen wird. Wie in Abbildung 4-14 dargestellt, ist der öffentliche Port für den Sidecar-Proxy von backend22000. Consul konfiguriert alle Proxys so, dass sie die öffentlichen Ports der anderen Proxys kennen. Auf diese Weise kann der Proxy von frontendden Datenverkehr von an den Proxy von backendsenden.

Zusammenfassung

In diesem Kapitel hast du gelernt, wie du Dienste zum Consul Service Mesh hinzufügen kannst. In Kubernetes musst du dazu lediglich deine Pods mit der Annotation consul.hashicorp.com/inject: "true" versehen. Unter der Haube sorgte Consul dafür, dass der Sidecar-Proxy automatisch injiziert und der Datenverkehr abgefangen wurde.

Auf VMs hast du die Dienste über Konfigurationsdateien bei Consul registriert und die Sidecar-Proxys mit systemd ausgeführt. Anschließend hast du gelernt, wie du Dienste so konfigurierst, dass sie über ihre lokalen Sidecar-Proxys mit ihren Upstream-Abhängigkeiten kommunizieren.

Deine Dienste kommunizieren jetzt über das Mesh, aber du hast noch nicht gelernt, wie du sie für Anrufer zugänglich machen kannst, die nicht im Mesh sind. Deshalb kannst du die Benutzeroberfläche von frontendnicht auf Kubernetes laden und auf VMs umgehst du das Mesh, um die Benutzeroberfläche zu laden.

Im nächsten Kapitel erfährst du, wie du Ingress Gateways verwendest, um benutzerorientierte Dienste bereitzustellen.

1 Wenn die Dienste in verschiedenen Namensräumen liegen, würdest du http://backend.<Namensraum> verwenden .

2 Wenn du Kubernetes in der Cloud oder unter Linux betreibst, verwende kubectl port-forward service/frontend 6060.

3 Ein Init-Container ist ein Container, der vor den Hauptcontainern für einen Pod läuft.

4 Wenn du immer noch Dienste hast, die nicht im Mesh sein können, kannst du ein Abschluss-Gateway verwenden. Abschließende Gateways werden in Kapitel 10 behandelt.

5 systemctl enable legt fest, dass die Dienste neu gestartet werden, wenn die VM neu startet.

6 Du kannst deine Dienstkonfiguration in einem beliebigen Verzeichnis ablegen, solange das Verzeichnis mit dem -config-dir Flag an Consul übergeben wird.

7 Technisch gesehen werden nicht alle Anfragen durch das Dienstnetz geleitet. Dein Browser verbindet sich immer noch direkt mit dem Dienst frontend und nicht mit dessen Proxy. Im nächsten Kapitel fügst du ein Ingress-Gateway hinzu, um dies zu beheben.

Get Consul: Auf und davon now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.