Teil 3: Spaß mit DNS

Knative Tutorial: Public Traffic in Knative auf der Google Kubernetes Engine

Dr. Nic Williams

© Shutterstock / Avesun (modifiziert)

Mit Knative können Serverless-Plattformen erstellt werden, die auf Kubernetes basieren. Doch wie genau funktioniert das eigentlich alles? Wie skaliert meine Anwendung auf 0? Wie läuft das Deployment ab? Diese und weitere Fragen beantwortet Dr. Nic Williams, CEO von Stark & Wayne, in diesem umfangreichen Tutorial zu Knative.

Der vorliegende Artikel ist Teil des Knative Tutorials von Dr. Nic Williams, CEO von Stark & Wayne, und ist im englischsprachigen Original auf dem Blog des Unternehmens erschienen.

Es wird Zeit, unser Knative-Routing für unsere Umwelt sichtbar zu machen. Das Subsystem Knative Serving koordiniert die automatische Skalierung eines Services und dessen Pods sowie dessen Routing. Zudem verwaltet es automatisch generierte interne Routen, die von Containern für die Kommunikation mit Knative-Sevices eingesetzt werden können. Auch sogenannte Ingress-Routen werden verwaltet, also Traffic, der von außen in den Cluster hineinkommt. Damit das Ganze funktioniert, muss der Traffic externer User allerdings erstmal in den Knative Kubernetes Cluster hineinfinden.

In diesem Artikel setzen wir ein Domain Name System (DNS) auf und erlauben den öffentlichen HTTP Traffic in unsere Knative-Anwendung. Wir werden einen frischen GKE Cluster (GKE = Google Kubernetes Engine) deployen, Knative installieren und eine Anwendung deployen. Dann werden wir unserem Knative Gateway eine statische IP hinzufügen, anschließend setzen wir ein öffentliches DNS mit CloudFlare auf, konfigurieren Knative für unsere Public Domain und deployen unsere Anwendung erneut. Aufregend – Lasst uns Dinge im Internet tun!

Ein frisches Knative auf GKE

Zunächst erstellen wir einen Google Kubernetes Cluster (GKE) und installieren Knative. Dabei gehen wir strikt nach der Dokumentation vor, die unserer Vorgehensweise entsprechen:

gcloud components update
gcloud auth login

gcloud config set project knative-experiments
export CLUSTER_NAME=knative
export CLUSTER_REGION=us-west1
export CLUSTER_ZONE=us-west1-c

gcloud container clusters create $CLUSTER_NAME \
  --region=$CLUSTER_ZONE \
  --cluster-version=latest \
  --machine-type=n1-standard-2 \
  --enable-autoscaling --min-nodes=1 --max-nodes=5 \
  --enable-autorepair \
  --scopes=service-control,service-management,compute-rw,storage-ro,cloud-platform,logging-write,monitoring-write,pubsub,datastore \
  --num-nodes=3

Unser lokales kubectl wird automatisch für den neuen Cluster konfiguriert:

$ kubectl get nodes
NAME                                     STATUS   ROLES    AGE   VERSION
gke-knative-default-pool-db8990a0-3bls   Ready       57s   v1.10.7-gke.6
gke-knative-default-pool-db8990a0-hf7t   Ready       57s   v1.10.7-gke.6
gke-knative-default-pool-db8990a0-t2hz   Ready       57s   v1.10.7-gke.6

Dem aktuellen Nutzer müssen Administrator-Rechte für den Cluster gewährt werden, dies funktioniert wie folgt:

kubectl create clusterrolebinding cluster-admin-binding \
  --clusterrole=cluster-admin \
  --user=$(gcloud config get-value core/account)

Installieren wir nun Knative (was auch Istio beinhaltet):

knctl install --exclude-monitoring

Dieses letzte Kommando wird alles stoppen, bis sämtliche Istio/Knative Pods erfolgreich laufen.

Deployment einer Anwendung

Eine schnelle Überprüfung, ob unser GKE Knative richtig funktioniert, kann durch das Deployment eines vorgebauten Docker Images erfolgen:

knctl namespace create -n helloworld

knctl deploy \
      --namespace helloworld \
      --service hello \
      --image gcr.io/knative-samples/helloworld-go \
      --env TARGET=Rev1

Da wir das Public DNS noch nicht in unseren Knative/Istio/Kubernetes Cluster implementiert haben, sind wir in unseren Möglichkeiten, mit der Anwendung zu interagieren eingeschränkt. Dies funktioniert zunächst nur via knctl curl oder dem äquivalenten Kommando curl:

$ knctl curl --service hello -n helloworld
Running: curl '-sS' '-H' 'Host: hello.helloworld.example.com' 'http://104.198.109.254:80'

Hello World: Rev1!

Standardmäßig nutzt Knative eine Dummy-Domain (example.com) für alle Routen. Diese werden wir ziemlich schnell durch unsere eigene Domain ersetzen. Im restlichen Artikel werden wir nun eine statische IP ins Knative Routing einfügen, ein DNS zu der statischen IP hinzufügen und die Anwendung inklusive ihrer Public Route redeployen.

Zuordnen einer statischen IP zu Knative

Zum Zeitpunkt, da dieser Artikel verfasst wurde, lagen die Instruktionen für das Erstellen einer GCP-IP-Adresse auf GitHub bereit.

GCP weist öffentliche IP-Adressen automatisch jedem Node in unserem GKE Cluster zu, sodass das Knative Ingress Gateway (wo der einkommende Traffic ankommen sollte) schon eine externe IP beinhaltet:

$ kubectl get svc knative-ingressgateway --namespace istio-system
NAME                     TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)                                      AGE
knative-ingressgateway   LoadBalancer   10.19.248.251   104.198.109.254   80:32380/TCP,443:32390/TCP,32400:32400/TCP   2m

$ knctl ingress list
Ingresses

Name                    Addresses        Ports  Age
knative-ingressgateway  104.198.109.254  80     2m
                                         443
                                         32400

Der Wert der externen IP 104.198.109.254 stimmt mit der IP der Ausgabe von knctl curl (siehe oben) überein. Dennoch können wir nicht diese dynamische IP für unser DNS verwenden, da GCP leider nicht versprechen kann, dass sich die IP niemals ändern wird.

Stattdessen müssen wir eine statische und persistente IP erstellen und unserem Knative Ingress Gateway zuordnen. Dazu erstellen wir zunächst eine regionale IP-Adresse in der selben Region, in der auch unser GKE Cluster lokalisiert ist:

$ gcloud compute addresses create --region $CLUSTER_REGION knative-ingress
$ gcloud compute addresses list
NAME             REGION    ADDRESS         STATUS
knative-ingress  us-west1  35.233.215.214  RESERVED

Nun wollen wir GCP explizit so konfigurieren, diese statische IP an den Knoten zu binden, auf dem das Knative Ingress Gateway läuft.

kubectl patch svc knative-ingressgateway --namespace istio-system --patch \
  $(gcloud compute addresses describe \
       knative-ingress --region $CLUSTER_REGION --format json | \
       jq -cr "{spec: {loadBalancerIP: .address}}")

Wir lassen uns nun bestätigen, dass der Gateway gebunden ist und der curl-Test-Traffic korrekt und richtig geroutet wird (in unserem Beispiel ist die erwartete IP 35.233.215.214:

$ kubectl describe svc knative-ingressgateway --namespace istio-system
...
Events:
  Type    Reason                Age                  From                Message
  ----    ------                ----                 ----                -------
  Normal  EnsuringLoadBalancer  62s (x2 over 3m45s)  service-controller  Ensuring load balancer
  Normal  LoadbalancerIP        62s                  service-controller  -> 35.233.215.214
  Normal  EnsuredLoadBalancer   13s (x2 over 3m5s)   service-controller  Ensured load balancer

$ gcloud compute addresses list
NAME             REGION    ADDRESS         STATUS
knative-ingress  us-west1  35.233.215.214  IN_USE

$ knctl ingress list
Ingresses

Name                    Addresses       Ports  Age
knative-ingressgateway  35.233.215.214  80     13m
                                        443
                                        32400

$ knctl curl --service hello -n helloworld
Running: curl '-sS' '-H' 'Host: hello.helloworld.example.com' 'http://35.233.215.214:80'

Hello World: Rev1!

GCP/GKE ist nun so eingestellt, dass die statische IP 35.233.215.214 jederzeit an das Knative Ingress Gateway gebunden sein wird. Wir können nun versuchen, ein öffentliches Routing über den Host-Namen durchzuführen.

Knative Domains

Bevor wir nun unsere Standard-Domain aufsetzen, können wir auch kostenfreie Services wie sslip.io nutzen. Sämtliche Subdomains von 35.233.215.214.sslip.io werden immer nach 35.233.215.214 aufgelöst.

Wir aktualisieren Knative nun, sodass es die eigene .sslip.io-Domäne als die standardmäßige Basis-Domain für alle Routes nutzt:

knctl domain create -d 35.233.215.214.sslip.io --default

Alternativ kann man auch den folgenden Code nutzen, um den Hostnamen .sslip.io dynamisch zu konstruieren:

knctl domain create --default \
    -d "$(gcloud compute addresses describe knative-ingress --region $CLUSTER_REGION --format json | jq -cr .address).sslip.io"

Die Knative-Anwendung braucht hierfür nicht erneut deployt zu werden. Da wir die individuelle Basis-Domain aktualisiert haben, sollte die Route unserer hello-Andwendung ebenfalls automatisch aktualisiert worden sein:

$ knctl routes list -n helloworld
Routes in namespace 'helloworld'

Name   Traffic         All Traffic Assigned  Ready  Domain                                    Age
hello  100% -> hello:  true                  true   hello.helloworld.35.233.215.214.sslip.io  21m

Wir können unsere Anwendung nun in einem Webbrowser oder via des normalen curl-Kommandos ansehen:

$ curl hello.helloworld.35.233.215.214.sslip.io
Hello World: Rev1!

Individuelle DNS

Nun können wir unser eigenes, maßgeschneidertes DNS unter Verwendung der statischen IP aufsetzen.

In unserem Beispiel (siehe unten) haben wir ein A Record für knative-ingress.starkandwayne.com erstellt, hinzu kam eine Wildcard CNAME für den Namen A. Hierdurch können wir nun den Record knative-ingress einmal ändern (etwa auf eine neue statische IP oder einen anderen Load Balancer) und alle CNAMEs der Anwendung werden automatisch angepasst.

DNS A verweist auf die statische IP und CNAME verweist auf den A Record. / Quelle: © 2020 Stark & Wayne LLC.

Wir können nun auch die Standard-Domain von Knative ändern:

knctl domain create --default --domain knative.starkandwayne.com

Sobald das DNS verteilt hat, kann die Anwendung nun über die individuelle Basis-Domain erreicht werden:

$ curl hello.helloworld.knative.starkandwayne.com
Hello World: Rev1!

Fazit

In diesem Teil des Knative-Tutorials haben wir einen neuen Kubernetes Cluster auf der GKE deployt, Knative mit Unterstützung für einen Standard-Load-Balancer installiert, eine statische IP mit dem Ingress Gateway von Knative verknüpft und ein eigenes DNS aufgesetzt, das die statische IP referenziert.

Was daraus folgt, ist pure Magie:

$ curl hello.helloworld.knative.starkandwayne.com
Hello World: Rev1!

Im nächsten Teil werden wir wundervolle Domains erschaffen, etwa hello.starkandwayne.com, um die programmatisch erstellte (aka. hässliche) Domäne hello.helloworld.knative.starkandwayne.com zu ersetzen.

Geschrieben von
Dr. Nic Williams
Dr. Nic Williams
CEO of Stark & Wayne. User and evangelist of Cloud Foundry, Kubernetes, Concourse CI, and BOSH. Author of books Concourse Tutorial and Ultimate Guide to BOSH. Awarded Cloud Foundry Champion 2018. Twitter: @drnic
Kommentare

Hinterlasse einen Kommentar

avatar
4000
  Subscribe  
Benachrichtige mich zu: