Kubernetes
Spickzettel für Container-Orchestrier Kubernetes (kurz: K8s).
Übersicht über Container-Orchestrier:
- Docker Swarm: leicht aufzusetzen, allerdings fehlen speziellere Features wie z.B. Autoscaling
- MESOS: hohe Einstiegshürde, bietet viele Features
- kubernetes: recht hohe Einstiegshürde, am weitesten verbreitet, bietet viele Features und Customization, offene Architektur mit Plugins für alles mögiche, wird von allen Cloud-Service-Anbietern unterstützt
Links:
- kubectl cheat sheet
- Blog-Artikel Kubernetes: Architektur und Einsatz – Eine Einführung mit Beispielen
- Paper Design patterns for container-based distributed systems
TODO Terraform, siehe: https://youtu.be/gpmerrSpbHg?t=809
Befehle
Siehe:
- Doku Overview of kubectl
- Doku kubectl Cheat Sheet
Status sehen
Cluster-Informationen sehen:
kubectl cluster-info
Deployments auflisten:
kubectl get deployments
Cluster-Nodes auflisten:
kubectl get nodes
Pods auflisten:
kubectl get pods [-L<label-name>] [-o wide]
-L
zeigt in der Tabelle zusätzliche den Wert eines Labels. Man kann auch mehrere-L
-Parameter angeben, z.B.kubectl get pods -Lapp -Ltier
.-o wide
zeigt weitere Spalten, z.B. den Node
Volumes auflisten (pv = persisted volume):
kubectl get pv
Alles auflisten:
kubectl get all --all-namespaces
Detail-Info zu einem Deployment:
kubectl describe deployments <deployment-name>
Detail-Info zu einem Pod:
kubectl describe pods <pod-id>
Noch mehr Infos zu einem Pod:
kubectl get pod <pod-id> --output=yaml | less
- Per Suche nach
lastState:
bekommt man Details, wenn der Pod wegen eines Fehlers nicht startet.
Log eines Pods anschauen:
kubectl logs <pod-id>
Log eines Containers in einem Deployment anschauen (geht auch wenn Start failed):
kubectl logs deployment/<deployment-id> <container-name>
Aktuelle Konsolenausgabe eines Pods anschauen:
kubectl attach <pod-id>
Detail-Info zu einem Service:
kubectl describe services <service-name>
Status von Deployment-Rollouts zeigen:
kubectl rollout status deployment <deployment-name>
Historie von Deployment-Rollouts zeigen (zeigt Versionen, zu denen ein Rollback möglich ist):
kubectl rollout history deployment/<deployment-name> [--revision=<revision-number>]
Deployment neustarten:
kubectl rollout restart deployment <deployment-name>
Debugging
Port-Forward (Cluster-Port auf lokalen Port forwarden):
kubectl port-forward <pod-id> <local port>:<container port>
Kommando in einem Container ausführen:
kubectl exec [-it] <pod-id> [-c <container name>] <command> [<args...>]
Deployments ändern
Deployment in Cluster hinzufügen oder ändern:
kubectl apply -f ./deployment.yaml
Deployment löschen:
kubectl delete deployment <deployment-name>
Cluster direkt ändern (ohne Deployment-Beschreibung)
Service erzeugen (Deployment für externes Netzwerk verfügbar machen):
kubectl expose deployment <deployment-name> --type=<NodePort|LoadBalancer|...> [--port=<external port>] [--target-port=<container port>] [--name <service-name>]
- Service-Types:
NodePort
: Einen Port eines Containers anbietenLoadBalancer
: Einen Port von vielen replizierten Containern über einen Load-Balancer als einen Port anbieten
Pod labeln:
kubectl label [--overwrite] <pod-id|...> <key>=<value> ...
Node labeln:
kubectl label node <node-name> <label-key>=<label-value>
Image als Pods starten (schnell und ohne Deployment-Beschreibung):
kubectl run <pod-name> --image=<image-name> --replicas=1000 [--port=<container port>]
Bash als Pods starten (schnell und ohne Deployment-Beschreibung):
kubectl run -it --rm busybox --image=busybox -- bash
Image eines Containers in einem Deployment ändern (z.B. Upgrade auf neue Version):
kubectl set image deployment/<deployment-name> <container-name>=<image-name>:<image-version>
Replicas skalieren:
kubectl scale --replicas=2000 <pod-name>
kubectl scale --replicas=0 deployment/<deployment-name>
Rolling Update:
kubectl rolling-update <pod-name> --image:<image-name>:<image-version>
Rollback eines Updates:
kubectl rolling-update <pod-name> --rollback
Terminologie
Übersicht (von Khtan66, CC BY-SA 4.0, via Wikimedia Commons):
Begriff | Definition |
---|---|
Node (Minion, Worker) | Ein Rechner auf dem K8s läuft, um Pods auszuführen. |
Cluster | Mehrere Nodes die zu einem Cluster verbunden wurden. |
Master | Ein Rechner auf dem die K8s Control Components (TODO) installiert sind. Der Master überwacht die Nodes eines Clusters und orchestriert diese (verteilt Container auf die einzelnen Nodes und verbindet Container, die von einander abhängen). |
kubectl | Kommandozeilen-Tool um Cluster zu steuern oder seinen Status abzufragen. Auch "Kube control" oder "Kube cuddle" (TODO) genannt |
Deployment | High-Level-Definition einer Applikation |
Pod | Kleinste lauffähige Einheit eines Deployments. Also ein Container oder eine Gruppe von Containern, die zusammen auf einem Minion laufen. |
Service | Fasst mehrere Pods des Clusters als ein Service zusammen. Je nach Typ erbeitet ein Service z.B. als Cluster-interner Load-Balancer (Default, type: ClusterIP ) oder als externer Load-Balancer (type: LoadBalancer ). Siehe Abschnitt "Service beschreiben" |
Label | Ein Key/Value-Paar, das einem Objekt in einem Deployment (z.B. einem Pod) zugeordnet ist. Labels helfen Objekte zu organisieren und leichter zu identifizieren. |
Selector | Ein Ausdruck, über den Objekte anhand ihrer Labels ausgewählt werden. Details siehe Abschnitt "Labels und Selektoren". |
Komponenten von K8s:
Komponente | Aufgabe |
---|---|
API server | Rest/JSON-Service über den das Cluster von außen überwacht und gesteuert werden kann |
etcd | Eine verteilte Key/Value-Datenbank in der K8s seinen Zustand persistiert. Wird über alle Nodes im Cluster repliziert (TODO Stimmt das so?) |
Scheduler | Verteilt Arbeit oder Container auf die einzelnen Minions. |
Controller | Überwachen das Cluster und reagieren, wenn Nodes, Container oder Endpoints nicht mehr laufen. |
Container runtime | Führt Container aus. Das ist üblicherweise Docker, K8s unterstützt auch andere container runtimes wie z.B. Rocket |
kubelet | Führt Pods aus. Läuft auf jedem Node und dient als Agent des Nodes. kubelet führt die Befehle des Masters aus und startet, stoppt und überwacht die lokalen Pods |
cAdvisor | Teil von kubelet. Misst CPU-Last und Speicherverbrauch von Pods auf seinem Node und berichtet an den Master. |
Kube-Proxy | Läuft auf jedem Node. Macht Ports von Pods für andere Pods oder Services (z.B. Load-Balancer) zugänglich. (TODO Wie geht das genau? Siehe Doku) |
Deployment beschreiben
Einfaches Deployment nginx-deploymen.yaml
:
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Service beschreiben
Siehe:
- Doku Service
- Doku Creating a Service
Beispiel - Cluster-interner Service:
apiVersion: v1
kind: Service
metadata:
name: my-mysql
labels:
app: wordpress
spec:
ports:
- port: 3306
selector:
app: wordpress
tier: mysql
clusterIP: None # Nur verwenden, wenn es nur einen Pod gibt (s.u.)
clusterIP: None
sollte nur dann verwendet werden, wenn der Service nur einen Pod hat. Dann wird für den Service kein Proxy erstellt. (TODO Bekommt der Service dann einfach die Cluster-ID des Pods? Siehe Details)
Beispiel - Service mit externem Load-Balancer:
apiVersion: v1
kind: Service
metadata:
name: wordpress
labels:
app: wordpress
spec:
ports:
- port: 80
selector:
app: wordpress
tier: frontend
type: LoadBalancer
Installation
kubectl installieren (Mac OS):
brew install kubectl
minikube
Distributionen:
- minikube: Startet K8s-Cluster lokal auf einem Rechner. Nicht für Produktion, aber gut zum Testen und zur Entwicklung.
- Cloud providers oder bare metal für Produktion
minikube installieren:
brew install minikube
minikube starten:
minikube start
minikube stoppen:
minikube stop
Beispiel-Deployment installieren und wieder löschen:
#minikube starten
minikube start
# Deployment mit Echo-Service deployen
kubectl run hello-minikube --image=gcr.io/google_containers/echoserver:1.4 --port=8080
# Deployment für externes Netzwerk verfügbar machen
kubectl expose deployment hello-minikube --type=NodePort
# Pods auflisten
kubectl get pods
# Echo-Service aufrufen
curl $(minikube service hello-minikube --url)
# Deployment löschen
kubectl delete deployment hello-minikube
# minikube stoppen
minikube stop
Skalierung von Stateless Apps
Replicas kann man definieren über:
- Attribut
replicas
in Deployment-Beschreibung (wird meistens genutzt) - Definition eines ReplicaSet
- Bare Pods
- Job
- DeamonSet
Replicas in Deployment-Beschreibung definieren
Einfach die Anzahl in deployment.yaml
angeben:
spec:
...
replicas: 4
Per kubectl
für laufendes Deployment ändern:
kubectl scale --replicas=4 deployment/<deployment-name>
Skalierung von Stateful Apps
TODO
Auto-Scaling
Horizontal Pod Autoscaler (HPA)
- Horizontal Pod Autoscaler (HPA): Passt die Anzahl von Replicas eines Pods anhand der durchschnittlichen CPU-Nutzung an ein vorgegebenes Ziel an.
- Man kann auch tiefer eingreifen und andere Parameter als die CPU-Nutzung verwenden.
Beispiel - HPA per CLI anlegen:
kubectl autoscale deployment wordpress --cpu-percent=50 --min=1 --max=10
Auto-Scaling testen
CPU-Zuweisung eines Pods künstlich reduzieren, damit man ihn leichter Stress-Testen kann:
apiVersion: apps/v1beta2
kind: Deployment
spec:
template:
spec:
containers:
- image: ...
resources:
requests:
cpu: "100m" # =10%
limits:
cpu: "200m"
busybox-Container starten für Stress-Test:
kubectl run -i --tty load-generator --image=busybox --generator=run-pod/v1 /bin/sh
In busybox-Container den Stress-Test starten:
while true; do wget -q -O- http://my-service.default.svc.cluster.local; done
HPA-Status anzeigen:
kubectl get hpa
Labels und Selektoren
Siehe:
- Doku Recommended Labels
Beispiel - Pod so einstellen, dass er nur auf einem Node mit einer SSD ausgeführt wird:
Label storageType=ssd
zu Node hinzufügen:
kubectl label node <node-name> storageType=ssd
Deployment-Beschreibung des Pods ändern:
spec:
...
template:
...
spec:
containers:
...
nodeSelector:
storageType: ssd
Deployment-Beschreibung in Cluster aktualisieren:
kubectl apply -f ./deployment.yaml
Health Checks (aka Probes)
Health Checks:
- Arten:
- Readiness Probe: Ist ein Pod "ready"?
- Liveness Probe: Ist ein Pod "healthy" oder "unhealthy" (als er bereits "ready" war)?
- Methoden:
- Erfolgreicher HTTP- oder TCP-Request
- Erfolgreiche Ausführung eines Kommandos (Ist Exit-Code Null?)
Beispiel:
spec:
...
template:
...
spec:
containers:
- name: my-container
...
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 15
periodSeconds: 3
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 30
periodSeconds: 30
Dashboard UI
Siehe Doku Web UI (Dashboard)
Dashboard installieren (wenn nicht bereits vorinstalliert):
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml
Token ermitteln:
$ kubectl -n kube-system get secret
# All secrets with type 'kubernetes.io/service-account-token' will allow to log in.
# Note that they have different privileges.
NAME TYPE DATA AGE
deployment-controller-token-frsqj kubernetes.io/service-account-token 3 22h
$ kubectl -n kube-system describe secret deployment-controller-token-frsqj
# ...
token: abcdefg..
Lokalen Proxy starten:
kubectl proxy
Dashboard UI im Browser öffnen (Token zur Anmeldung verwenden): http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
Quelle: Stackoverflow-Artikel
DNS
DNS:
- K8s hat eigenen DNS-Service "kube-dns"
- Jeder Service in K8s bekommt einen DNS-Namen nach dem Schema:
<service-name>.<namespace>.svc.cluster.local
- Der Name kann geändert werden, aber sollte meistens passen (Convention over Configuration)
- Wenn Pods voneinander abhängen, dann löst kube-dns die jeweiligen IP-Adressen auf
Namespaces:
- Namespaces teilen ein Cluster in kleinere logische Cluster
- Per Default läuft alles im
default
Namespace - Da der Namespace Teil des DNS-Namens eines Service ist, werden Services verschiedener Namespaces automatisch auch auf DNS-Ebene voneinander getrennt.
Volumes
- Daten, die in einem Container gespeichert werden gehen verloren, wenn der Container oder sein Host beendet wird. Das ist so gewollt: Container sollen Stateless sein und in einem sauberen Zustand starten.
- Ein Volume bietet persistenten Speicher für einen Container. Ein Volume ist ein Verzeichnis, das mit einem Container verbunden wird.
- Es gibt viele Volume-Typen, z.B. Cloud-Provider-Speicher (wie AWS EBS) oder Netzwerk-Dateisysteme (wie GlusterFS, NFS)
- Pods definieren welche Volumes sie brauchen (Attribut
spec.volumes
) und wo sie gemounted werden sollen (Attributspec.containers.volumeMounts
)
Verwendung von Volumes:
- Meist wird ein
PersistentVolume
verwendet. Es bietet persistenten Platten-Speicher. - Schritte:
- Ein
PersistentVolume
anlegen (engl. "provisioning") - das entspricht dem Hinzufügen einer Platte zu einer VM oder einem physischen Rechner. - Ein
PersistentVolumeClaim
anlegen - das ist die Anfrage nach einem Speicher von einem Nutzer oder Pod.
- Ein
- K8s verbindet dann zur Laufzeit ein
PersistentVolume
an einen Pods anhand dessenPersistentVolumeClaim
- passend zu den dort abgegebenen Optionen (Name, Plattenplatz, Speicher-Art, ...). - Ablauf:
- Ein Admin definiert Volumes und fügt sie zum Cluster hinzu
- Ein Deployment enthält ein Volume-Claim
- Der K8s-Master weist beim Anlegen eines Pods die Volumes anhand der Claims den jeweiligen Pods zu.
- Falls es keine passenden Volumes gibt, gibt es entweder einen Fehler oder der K8s-Master legt automatisch neue Volumes an, wenn "dynamic provisioning" konfiguriert ist.
Beispiel: Definition eines Volumes:
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv-1
labels:
type: local
spec:
storageClassName: ssd
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /tmp/data/pv-1
type: local
geht nur in minikube, nicht produktivReadWriteOnce
bedeutet: Volume ist beschreibbar, aber nur von einem Node gleichzeitig
Beispiel: Volume-Claim:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pv-claim
spec:
storageClassName: ssd
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
Beispiel: Volume-Claim einem Container zuweisen:
apiVersion: apps/v1beta2
kind: Deployment
...
spec:
...
template:
spec:
containers:
- image: ...
volumeMounts:
- name: my-persistent-storage
mountPath: /path/in/container
subPath: /path/in/volume # Default: "" (volume's root)
readOnly: true # Default: false
volumes:
- name: my-persistent-storage
persistentVolumeClaim:
claimName: my-pv-claim
Volumes in AWS
- K8s unterstützt "dynamic provisioning". D.h. K8s kann automatisch Volumes anlegen, falls es kein Volume zur Verfügung hat, das zu einem bestimmten Claim passt.
- Dazu einfach
PersistentVolumeClaim
s anlegen und in Deployment verwenden (siehe oben) - ohne jedoch Volumes zu definieren. Der Auto-Provisioner von K8s (genauer gesagt deraws-ebs-dynamic-provisioner
) legt nun automatisch EBS-Volumes an und der Master verbindet diese mit den Containern.
Secrets
- Secrets sind eine Möglichkeit kleine geheime Daten wie z.B. Credetials oder API-Keys nur an diejenigen zu geben, die sie benötigen.
- Secrets können einem Pod zur Verfügung gestellt werden:
- Als eine Datei auf einem zur Laufzeit erzeugtem Volume (nützlich für Zertifikate).
- Als eine Umgebungsvariable die von K8s zur Laufzeit befüllt wird.
- Secrets können vom Nutzer angelegt werden. Das System legt auch ein paar Secrets an.
- Wie Secrets gespeichert werden:
- K8s unterstützt die Trennung von Secrets, jedoch ohne starke Verschlüsselung. Es wird davon ausgegangen, dass der Zugriff auf das System geschützt ist. Secrets bieten lediglich eine Trennung von Secretes zu Konfiguration oder anderen Daten.
- Secrets sind ein Set von Key/Value-Paaren. Sie werden normalerweise Base64-Encodiert separat von der Konfiguration gespeichert und zur Laufzeit injected.
- Man kann den String selbst encodieren oder K8s-Tools dazu verwenden.
Secret per CLI aus Dateien anlegen:
kubectl create secret generic <secret-name> --from-file=<file-path-1> --from-file=<file-path-2>
Secret per CLI aus Wert anlegen:
kubectl create secret generic <secret-name> --from-literal=<key>=<value>
Beispiel: Secret mit zufälligem Passwort anlegen:
kubectl create secret generic <secret-name> --from-literal=password=`date +%s | shasum | base64 | head -c 32 ; echo`
Secret als Umgebungsvariable verwenden:
apiVersion: apps/v1beta2
kind: Deployment
spec:
template:
spec:
containers:
- image: ...
env:
- name: MY_ENV_VARIABLE
valueFrom:
secretKeyRef:
name: my-secret-name
key: my-key
Secret als Volume verwenden:
apiVersion: apps/v1beta2
kind: Deployment
spec:
template:
spec:
containers:
- image: ...
volumeMounts:
- name: my-secret-storage
mountPath: /path/in/container
volumes:
- name: my-secret-storage
secret:
secretName: my-secret-name
Monitoring
- Monitoring von Nutzung und Ressourcen ist ein weites Feld - es gibt viele freie und bezahlte Apps und Dienste
- Im folgenden: Monitoring von K8s plus Open-Source-Lösungen Heapster (sammelt Informationen über Pods), InfluxDB (Persistenz) und Grafana (Visualisierung)
Heapster:
- von CNCF - also die Organisation, die auch K8s entwickelt
- wird als Cluster-weiter Pod installiert
- Fragt bei kubelets auf allen Nodes regelmäßig nach Informationen über alle Pods und speichert diese in InfluxDB
- Ist in vielen Clustern bereits vorinstalliert, nicht jedoch auf minikube
TODO Heapster ist deprecated und seit K8s 1.12 aus K8s entfernt.
Heapster auf minikube einrichten (TODO geht nicht, Fehler heapster is not a valid addon
):
# Add-On "Heapster" aktivieren
minikube addons enable heapster
# Das dauert eine Weile - So sieht man den Status:
kubectl get pods --namespace=kube-system
# Wenn die Pods laufen: Grafana Dashboard im Browser öffnen
minikube addons open heapster
Auditing
- Auditing bedeutet verstehen: Was passiert gerade? Was ist wo vorgefallen? Wer oder was war der Auslöser?
- Auditing sollte dagegen abgesichert sein, dass jemand die über das System aufgezeichneten Daten nachträglich verändert.
Auditing in K8s:
- Auditing wurde mit K8s 1.8 überarbeitet. Auditing bis K8s 1.7 heißt "Legacy auditing". Das neue heißt "Advanced auditing" und ist nun Standard.
- K8s auditing bietet eine chronologische Aufzeichnung von sicherheitsrelevanten Aktivitäten das System betreffend.
- Hilft zu beantworten: Warum, was, von wem, wo und wie etwas angestoßen wurde und was dann passiert ist.
- Der kube-apiserver führt das Auditing durch anhand der "Audit Policy" und sendet die Aufzeichnungen zum "Audit Backend"
- Aus Sicherheitsgründen passiert Auditing Low-Level, so dass es nicht von kubectl oder Pods beeinflusst werden kann. Daher wird Auditing von außerhalb des Clusters konfiguriert.
Audit Policy:
- Definiert, was geloggt werden soll. Soll jedes kleine Detail geloggt werden? Oder interessieren uns nur bestimmte Sachen?
- Wird als yaml-Datei definiert, so wie andere K8s-Objekte auch. Aber da es sich um Auditing handelt, wird sie nicht über kubectl applied.
- Auditing wird dem kube-apiserver beim Start als Option mitgegeben. D.h. das Kommando, das den Cluster startet bekommt die Audit Policy.
Audit Backend:
- Audit Backend exportiert die Audit-Ereignisse in einen externen Speicher.
- kube-apiserver unterstützt Out-of-the-box zwei Backends:
- Logs: Events werden auf eine Platte geschrieben
- Webhooks: Events werden an eine externe API gesendet
Beispiel - Änderungen an Metadaten in minikube in eine Datei loggen
Im Beispiel werden nur Änderungen an Metadaten geloggt. Man kann auch andere Ereignisse loggen, aber das kann schnell sehr viel werden.
Audit Policy audit-policy.yaml
erstellen:
# Log all requests at the Metadata level.
apiVersion: audit.k8s.io/v1beta1
kind: Policy
rules:
- level: Metadata
Audit Policy in minikube-Addons-Verzeichnis kopieren:
cp audit-policy.yaml ~/.minikube/addons/
minikube neu starten:
minikube stop
minikube start --extra-config=apiserver.Authorization.Mode=RBAC --extra-config=apiserver.Audit.LogOptions.Path=/var/logs/audit.log --extra-config=apiserver.Audit.PolicyFile=/etc/kubernetes/addons/audit-policy.yaml
Aktion ausführen, das die Metadaten betrifft:
kubectl get pods
Per SSH auf minikube-VM verbinden:
minikube ssh
Log auf minikube-VM anschauen (JSON-Einträge werden per jq
lesbar formatiert):
sudo bash
cat /var/logs/audit.log | jq .
Cluster in AWS aufsetzen
Siehe:
- Doku Running Kubernetes on AWS EC2
- AWS-Doku Manage Kubernetes Clusters on AWS Using Kops
- Kops-Doku Getting Started with kops on AWS
AWS EKS vs kops:
- AWS bietet auch integrierten Support für K8s, siehe Amazon Elastic Kubernetes Service (Amazon EKS)
- Automatisch hochverfügbare Master
- Einfaches, stark automatisiertes Setup
- Versteckt viele Details
- Alternativ kann man selbst K8s auf EC2-VMs aufsetzen. Das geht am besten mit kops (k8s operation tools). kops übernimmt das Erstellen der EC2-VMs und die gesamte Konfiguration des Clusters - man muss die Linux-Nodes nicht von Hand aufsetzen und etliche Konfigurations-Dateien editieren.
Cluster in AWS mit kops aufsetzen
Diese Anleitung nutzt AWS EC2 (Elastic Cloud) und AWS S3 (Simple Storage)
-
In AWS-Konsole einloggen und Security Credentials herunterladen (rechts oben in Nutzer-Menü, dort Access Key hinzufügen)
-
kops lokal installieren (Mac OS)
brew update && brew install kops
-
aws CLI installieren (kops ruft aws CLI auf)
brew install aws
-
aws CLI konfigurieren
aws configure
- Bei Frage nach "Default region" z.B.
eu-central-1
(für Frankfurt) verwenden oder in AWS-Doku Regionen und Availability Zones nachschauen. - Bei Frage nach "Default output format" einfach Enter drücken für "None"
- Bei Frage nach "Default region" z.B.
-
AWS-S3-Bucket erstellen als Speicher für kops state store
aws s3api create-bucket --bucket <bucket-name> --region <region-name> --create-bucket-configuration LocationConstraint=<region-name>
- Der Bucket-Name ist global eindeutig und öffentlich sichtbar. Daher am besten mit einem Prefix der eigenen Organisation arbeiten - z.B.
mycompany-myclustername-kops-state
.
- Der Bucket-Name ist global eindeutig und öffentlich sichtbar. Daher am besten mit einem Prefix der eigenen Organisation arbeiten - z.B.
-
Cluster mit kops erzeugen
export KOPS_STATE_STORE=s3://mycompany-myclustername-kops-state kops create cluster <cluster-name> --zones <zone-name> --yes
- Der
cluster-name
sollte auf.k8s.local
enden. Dann erstellt kops einen gossip-basierten Cluster, so wir nicht DNS konfiguriert haben müssen, damit das Cluster-interne DNS funktioniert. - Als
zone-name
muss man eine Zone angeben, d.h. ein Region-Name plus einen Buchstaben. Also z.B.eu-central-1a
. -
Wenn Fehler
error reading SSH key file
auftritt, dann hat man noch lokal noch keinen Client-SSH-Key angelegt.Das kann man folgendermaßen nachholen:
ssh-keygen
kubectl
ist nun mit dem neuen Cluster verbunden- Per Default legt kops einen Master (Instanz-Typen
m3.medium
) und zwei Nodes (Instanz-Typt2.medium
) an.
- Der
-
Cluster-Status sehen
kops validate cluster
-
Nodes auflisten
kubectl get nodes --show-labels
-
SSH auf Master öffnen
ssh -i ~/.ssh/id_rsa admin@<master-host>
- Den
master-host
kann man in der AWS-Konsole nachschauen:- Rechts oben Region auswählen
- S3 -> Instances -> Master-VM selektieren -> "Public DNS"
- Auf dem Master ist auch kubectl verfügbar
- Den
Cluster löschen:
kops delete cluster <cluster-name>
- Bei
cluster-name
muss man evtl..k8s.local
hinzufügen. - Wenn alles geklappt hat, beginnt die letzte Ausgabezeile mit
Deleted cluster
kops-etcd-Volumes verkleinern
Quelle: Blog-Artikel Resize etcd volumes on kops
Lokal - Volumes erzeugen:
$ aws ec2 create-volume --availability-zone eu-central-1b --size 2 --volume-type gp2 --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=b.etcd-main.my-cluster-name}]'
{
...
"VolumeId": "vol-02a7048643e42a68d",
}
$ aws ec2 create-volume --availability-zone eu-central-1b --size 2 --volume-type gp2 --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=b.etcd-events.my-cluster-name}]'
{
...
"VolumeId": "vol-04c26929ea5e3a527",
}
Lokal - SSH auf Master öffnen:
$ ssh admin@<master-ip>
Auf Master - Master-Services stoppen und aktuelle Plattenbelegung anzeigen:
$ sudo systemctl stop docker-healthcheck.timer
$ sudo systemctl stop docker
$ sudo systemctl stop kubelet
$ sudo systemctl stop protokube
$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/xvda2 15660904 3882264 11007384 27% /
/dev/xvdu 20511312 170624 20324304 1% /mnt/master-vol-00768b179c346f1f8
/dev/xvdv 20511312 423268 20071660 3% /mnt/master-vol-06517921f1de67628
Lokal - Neues etcd-main-Volume an Master attachen:
$ aws ec2 attach-volume --device /dev/sdf --instance-id i-07637f16bd2dd0a72 --volume-id vol-02a7048643e42a68d
Auf Master - Neues etcd-main-Volume formatieren und mounten:
$ lsblk | grep 2G
xvdf 202:80 0 2G 0 disk
$ sudo mkfs.ext4 /dev/xvdf
$ sudo mkdir /mnt/etcd-main
$ sudo mount /dev/xvdf /mnt/etcd-main
Lokal - Neues etcd-events-Volume an Master attachen:
$ aws ec2 attach-volume --device /dev/sdg --instance-id i-07637f16bd2dd0a72 --volume-id vol-04c26929ea5e3a527
Auf Master - Neues etcd-events-Volume formatieren und mounten:
$ lsblk | grep 2G
xvdf 202:80 0 2G 0 disk /mnt/etcd-main
xvdg 202:96 0 2G 0 disk
$ sudo mkfs.ext4 /dev/xvdg
$ sudo mkdir /mnt/etcd-events
$ sudo mount /dev/xvdg /mnt/etcd-events
$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/xvda2 15660904 3882272 11007376 27% /
/dev/xvdu 20511312 170624 20324304 1% /mnt/master-vol-00768b179c346f1f8
/dev/xvdv 20511312 423268 20071660 3% /mnt/master-vol-06517921f1de67628
/dev/xvdf 1998672 6144 1871288 1% /mnt/etcd-main
/dev/xvdg 1998672 6144 1871288 1% /mnt/etcd-events
Alte Volumes in AWS-Konsole nachschauen:
- Name:
b.etcd-main.my-cluster-name
, ID:vol-06517921f1de67628
- Name:
b.etcd-events.my-cluster-name
, ID:vol-00768b179c346f1f8
Auf Master - Daten kopieren und Volumes unmounten:
$ cd /mnt/master-vol-06517921f1de67628
$ sudo cp -av * /mnt/etcd-main
$ cd /mnt/master-vol-00768b179c346f1f8
$ sudo cp -av * /mnt/etcd-events
$ sudo umount /mnt/etcd-main
$ sudo umount /mnt/etcd-events
Lokal - Tags zu neuen Volumes umziehen:
$ aws ec2 create-tags --resources vol-02a7048643e42a68d --tags Key=KubernetesCluster,Value=my-cluster-name Key=k8s.io/etcd/main,Value=b/b Key=k8s.io/role/master,Value=1 Key=kubernetes.io/cluster/my-cluster-name,Value=owned
$ aws ec2 create-tags --resources vol-04c26929ea5e38709 --tags Key=KubernetesCluster,Value=my-cluster-name Key=k8s.io/etcd/events,Value=b/b Key=k8s.io/role/master,Value=1 Key=kubernetes.io/cluster/my-cluster-name,Value=owned
$ aws ec2 delete-tags --resources vol-00768b179c346f1f8 vol-06517921f1de67628 --tags Key=KubernetesCluster Key=k8s.io/etcd/main Key=k8s.io/etcd/events Key=k8s.io/role/master Key=kubernetes.io/cluster/my-cluster-name
Auf Master - Master herunterfahren:
$ sudo poweroff
Warten bis neuer Master erzeugt wurde.
Auf neuem Master - Prüfen:
$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/xvda2 15660904 3906140 10983508 27% /
/dev/xvdu 1998672 131680 1745752 8% /mnt/master-vol-04c26929ea5e3a527
/dev/xvdv 1998672 384332 1493100 21% /mnt/master-vol-02a7048643e42a68d