Andreas Bruns

Softwareentwicklung für Oldenburg und Bremen

Managed Kubernetes: Günstiges deutsches Angebot von Netways

Die Vorteile von Kubernetes (K8S) und wie man für Testzwecke einen eigenen Cluster mit Raspberry Pis aufbauen kann, habe ich vor einem Jahr in dem Artikel k3s – 5 weniger als k8s (Kubernetes) skizziert. Einfacher und schneller gelingt natürlich der Einstieg durch die Verwendung von gemanagten Kubernetes-Clustern (wie Googles GKE und Amazons EKS). Mit einem Managed Kubernetes umgeht man auch einige Herausforderungen, die ich mit meinem Cluster auf Pi-Basis habe:

  • Pi-Lösung funktioniert momentan nur im lokalen Netzwerk, wobei manche Applikationen auch öffentlich zugänglich sein sollen
  • sehr eingeschränkte Ressourcen nur verfügbar (Arbeitsspeicher, Performanz und Netzwerkdurchsatz)
  • die ARM-Architektur des Pis wird von vielen Docker-Images (bzw. Helm-Charts) nicht unterstützt

In der Zwischenzeit haben sich viele neue Angebote für Managed Kubernetes entwickelt. Mir gefällt das Angebot des deutschen Anbieters Netways sehr gut, der ein Kubernetes-Cluster mit öffentlicher IP-Adresse für unter 70,- Euro ermöglicht. Folgende Kriterien sind meistens für einen detailierten Kostenvergleich relevant:

  • Anzahl und Leistung der Master-Node (Control Plane Nodes)
  • Anzahl und Leistung der Worker Nodes
  • anfallender Netzwerkverkehr
  • verwendeter Festplattenspeicher
  • Anzahl öffentlicher IP-Adressen

Quickstart mit Netways-Kubernetes

Das Erstellen und das Anbinden eines Kubernetes-Clusters von Netways gelingt innerhalb von wenigen Minuten:

  • Kubernetes-Cluster in der Netways-Weboberfläche erstellen
  • auf lokalem Rechner kubectl installieren, z.B.: brew install kubectl
  • Kubernetes-Config herunterladen und speichern: $HOME/.kube/config
  • => mit kubectl den Kubernetes-Cluster analysieren, z.B: kubectl get nodes
Erstellen eines Kubernetes-Clusters in der Netways-Oberfläche

Kubernetes-Dashboard anzeigen

Einen hervorragenden Überblick bezüglich der Konfiguration der Ressourcen bietet das Kubernetes-Dashboard:

Kubernetes-Dashboard des Netways-Clusters

Beispiel-Deployment mit „kubectl apply“

Die folgende Ressourcen-Definition echoserver.yaml spezifiziert einen HTTP-Echoserver, der die Anfrage-Parameter einer HTTP-Anfrage ausgibt. Mit einem entsprechenden Apply-Befehl erstellen wir ein Deployment mit einem passenden Service, sodass das entsprechende Replicaset und die Pods erzeugt werden:
kubectl apply -f echoserver.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: echoserver
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echoserver
  template:
    metadata:
      labels:
        app: echoserver
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google_containers/echoserver:1.0
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: echoserver
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
  selector:
    app: echoserver
  type: ClusterIP

kubectl zeigt uns anschließend die erzeugten Ressourcen an:

➜  kubectl get service echoserver                 
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
echoserver   ClusterIP   10.254.48.98    <none>        80/TCP    52m
➜  kubectl get deployment echoserver              
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
echoserver   1/1     1            1           52m
➜  kubectl get replicaset echoserver-68666dcc9f   
NAME                    DESIRED   CURRENT   READY   AGE
echoserver-68666dcc9f   1         1         1       52m
➜  kubectl get pods echoserver-68666dcc9f-2lnkg
NAME                          READY   STATUS    RESTARTS   AGE
echoserver-68666dcc9f-2lnkg   1/1     Running   0          52m

Die ausgegebene IP-Adresse des Services ist nur innerhalb des Kubernetes-Cluster erreichbar, weil wir den Typ ClusterIP angegeben haben. Für das Aufrufen des Echoservers starten wir einen weiteren Pod und stellen eine entsprechende Anfrage beispielsweise mit wget. Mit dem schlanken Busybox-Container können wir wget einfach ausführen.

➜ kubectl run busybox --image=busybox --rm -it /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget -O output.txt http://10.254.48.98/bar/?foo=1
Connecting to 10.254.48.98 (10.254.48.98:80)
saving to 'output.txt'
output.txt           100% |****************|   331  0:00:00 ETA
'output.txt' saved
/ # cat output.txt 
CLIENT VALUES:
client_address=('10.100.1.43', 34938) (10.100.1.43)
command=GET
path=/bar/?foo=1
real path=/bar/
query=foo=1
request_version=HTTP/1.1

SERVER VALUES:
server_version=BaseHTTP/0.6
sys_version=Python/3.5.0
protocol_version=HTTP/1.0

HEADERS RECEIVED:
Connection=close
Host=10.254.48.98
User-Agent=Wget
/ # exit
pod "busybox" deleted

Die Echoserver-Ressourcen löschen wir übrigens abschließend mit:
kubectl delete -f echoserver.yaml
Das ist insbesondere dann wichtig, wenn wir in der echoserver.yaml den Typ LoadBalancer statt ClusterIP setzen. Dann erhalten wir eine externe IP-Adresse, die wir von außerhalb des Clusters ansprechbar können, wobei dadurch auch höhere Kosten entstehen.

➜  kubectl get service echoserver                 
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP      PORT(S)   AGE
echoserver   ClusterIP   10.254.48.98   185.233.188.130  80/TCP    52m

Beispiel-Deployment mit Helm

Der Kubernetes-Paketmanager Helm ermöglicht die einfache Installation von bereits aufeiander abgestimmten Programmpaketen (genannt Charts) in den Kubernetes-Cluster. Beispielsweise wird für das WordPress-Chart die eigentliche Worpress-Software mit der Datenbank MySQL installiert:

  • auf lokalem Rechner helm installieren, z.B.: brew install helm
  • Installation: helm install my-wordpress bitnami/wordpress –version 10.1.5
  • MySQL- und Worpdress-Ressourcen werden erstellt, z.B.:
    Service, Deployments, Pods, Persistent Volume (Claims)
  • der Terminal-Ausgabe die URL, Username und Passwort entnehmen
  • per Browser in die WordPress-Installation anmelden
➜  helm list                                                   
NAME         	NAMESPACE	REVISION	UPDATED                             	STATUS  	CHART               	APP VERSION
my-wordpress 	default  	1       	2021-01-23 20:55:20.632896 +0100 CET	deployed	wordpress-10.1.5    	5.6.0

➜  kubectl get services,deployments,replicasets,pods,pvc,pv 
NAME                                               TYPE           CLUSTER-IP       EXTERNAL-IP       PORT(S)                      AGE
service/my-wordpress                               LoadBalancer   10.254.121.35    185.233.188.217   80:30600/TCP,443:31890/TCP   15m
service/my-wordpress-mariadb                       ClusterIP      10.254.69.47     <none>            3306/TCP                     15m

NAME                                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-wordpress                               1/1     1            1           15m

NAME                                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/my-wordpress-56d96ff5c9                               1         1         1       15m

NAME                                                            READY   STATUS    RESTARTS   AGE
pod/my-wordpress-56d96ff5c9-5vxp6                               1/1     Running   1          15m
pod/my-wordpress-mariadb-0                                      1/1     Running   0          15m

NAME                                                STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/data-my-wordpress-mariadb-0   Bound    pvc-0006bcf1-1b14-4b44-a5dc-e00f2b3a67fa   8Gi        RWO            standard       15m
persistentvolumeclaim/my-wordpress                  Bound    pvc-1ac70a0e-c755-421e-91b7-844176517389   10Gi       RWO            standard       15m

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                 STORAGECLASS   REASON   AGE
persistentvolume/pvc-0006bcf1-1b14-4b44-a5dc-e00f2b3a67fa   8Gi        RWO            Delete           Bound    default/data-my-wordpress-mariadb-0   standard                15m
persistentvolume/pvc-1ac70a0e-c755-421e-91b7-844176517389   10Gi       RWO            Delete           Bound    default/my-wordpress                  standard                15m

Die WordPress-Installation hat einen Service vom Typ LoadBalancer erstellt (mit externer IP-Adresse), wodurch entsprechende Extra-Kosten entstehen. Falls wir das nicht möchten, können wir das WordPress-Chart auch nur mit einer ClusterIP starten und testen:

  • WordPress löschen:
    helm delete my-wordpress
  • evtl. PersistenceVolumeClaim löschen:
    kubectl delete pvc data-xxx
  • WordPress erstellen nur mit ClusterIP:
    helm install my-wordpress bitnami/wordpress –version 10.1.5 –set service.type=ClusterIP
  • Forward Service vom lokalem Rechner erstellen:
    kubectl port-forward service/my-wordpress 8888:80
  • => im Browser aufrufen: http://localhost:8888

Kosten sparen mit einem Ingress-Controller

Egal wie wir unsere Ressourcen anlegen, wir sollten darauf achten, ob erstellte Services vom Typ ClusterIP oder LoadBalancer sind. Mit LoadBalancer erhalten wir eine kostenpflichtige öffentliche IP-Adresse. Falls wir für mehrere Services einen öffentlichen Zugriff benötigen, dann sollte der Einsatz eines Ingress-Controllers in Erwägung gezogen werden. Der ermöglicht es, dass mehrere Services über die selbe öffentliche IP-Adresse erreichbar sind.

Kommentare sind geschlossen.