Kubernetes Cluster für 20 US-Dollar pro Monat

TL DR


Wir erhöhen den Cluster, um zustandslose Webanwendungen mit Ingress , Letsencrypt, zu bedienen, ohne Automatisierungstools wie Kubespray, Kubeadm und andere zu verwenden.
Lesezeit: ~ 45-60 Minuten, Wiedergabezeit: ab 3 Stunden.


Präambel


Ich wurde aufgefordert, einen Artikel zu schreiben, da ich einen eigenen Cluster von Kubernetes zum Experimentieren benötigte. Die automatisierten Open Source-Installations- und Konfigurationslösungen funktionierten in meinem Fall nicht, da ich Nicht-Mainstream-Linux-Distributionen verwendete. Die intensive Arbeit mit Kubernetes in IPONWEB ermutigt Sie zu einer solchen Plattform, die Ihre Aufgaben auf komfortable Weise löst, auch für Heimprojekte.


Komponenten


Die folgenden Komponenten werden im Artikel angezeigt:


- Ihr Lieblings- Linux - Ich habe Gentoo (Knoten-1: systemd / Knoten-2: openrc), Ubuntu 18.04.1 verwendet.
- Kubernetes Server - Kube-Apiserver, Kube-Controller-Manager, Kube-Scheduler, Kubelet, Kube-Proxy.
- Containerd + CNI-Plugins (0.7.4) - Um die Containerisierung zu organisieren, verwenden wir Containerd + CNI anstelle von Docker (obwohl ursprünglich die gesamte Konfiguration auf Docker hochgeladen wurde, sodass nichts die Verwendung bei Bedarf verhindert).
- CoreDNS - zum Organisieren der Serviceerkennung von Komponenten, die im kubernetes-Cluster arbeiten. Eine Version, die nicht niedriger als 1.2.5 ist, wird empfohlen, da mit dieser Version eine angemessene Unterstützung für Coredns besteht, die als Prozess außerhalb des Clusters ausgeführt werden.
- Flanell - zum Organisieren eines Netzwerkstapels, zum Kommunizieren von Herden und Containern untereinander.
- Deine Lieblings- Datenbank.


Für alle


Einschränkungen und Annahmen


  • Der Artikel berücksichtigt nicht die Kosten für vps / vds-Lösungen auf dem Markt sowie die Möglichkeit, Maschinen für diese Dienste bereitzustellen. Es wird davon ausgegangen, dass Sie bereits etwas erweitert haben oder es selbst tun können. Außerdem wird die Installation / Konfiguration Ihrer bevorzugten Datenbank und Ihres privaten Docker-Repositorys, falls erforderlich, nicht behandelt.
  • Wir können sowohl Containerd + CNI-Plugins als auch Docker verwenden. In diesem Artikel wird die Verwendung von Docker als Containerisierungstool nicht berücksichtigt. Wenn Sie Docker verwenden möchten, können Sie Flanell selbst entsprechend konfigurieren. Außerdem müssen Sie Kubelet konfigurieren, dh alle Optionen in Bezug auf Containerd entfernen. Wie meine Experimente gezeigt haben, funktionieren Docker und Containerd auf verschiedenen Knoten als Container korrekt.
  • Wir können das host-gw Backend nicht für Flanell verwenden. Weitere Informationen finden Sie im Abschnitt Flanellkonfiguration
  • Wir werden nichts zum Überwachen, Sichern, Speichern von Benutzerdateien (Status), Speichern von Konfigurationsdateien und Anwendungscode (git / hg / svn / etc) verwenden.

Einführung


Im Laufe der Arbeit habe ich eine große Anzahl von Quellen verwendet, aber ich möchte separat einen ziemlich detaillierten Kubernetes- Leitfaden für den harten Weg erwähnen, der ungefähr 90% der Grundkonfiguration seines eigenen Clusters abdeckt. Wenn Sie dieses Handbuch bereits gelesen haben, können Sie sicher direkt zum Abschnitt Flanellkonfiguration übergehen .


Bezeichnungen

Liste der Begriffe / Glossar


  • api-server - eine physische oder virtuelle Maschine, auf der sich eine Reihe von Anwendungen zum Ausführen und zur korrekten Funktion von kubernetes kube-apiserver befindet. Für die Zwecke dieses Artikels ist es etcd, kube-apiserver, kube-controller-manager, kube-scheduler.
  • master - eine dedizierte Workstation- oder VPS-Installation, ein Synonym für API-Server.
  • Node-X - Eine dedizierte Workstation oder VPS-Installation. X gibt die Seriennummer der Station an. In diesem Artikel sind alle Zahlen eindeutig und der Schlüssel zum Verständnis:
    • Knoten-1 - Maschinennummer 1
    • Knoten 2 - Maschinennummer 2
  • vCPU - virtuelle CPU, Prozessorkern. Die Anzahl entspricht der Anzahl der Kerne: 1vCPU - ein Kern, 2vCPU - zwei usw.
  • Benutzer - Benutzer oder Benutzerbereich. Bei Verwendung von user$ in Befehlszeilenanweisungen bezieht sich der Begriff auf einen beliebigen Clientcomputer.
  • Arbeiter - der Arbeitsknoten, an dem direkte Berechnungen durchgeführt werden, synonym mit node-X
  • Ressource ist die Entität, mit der der Kubernetes-Cluster arbeitet. Zu den Ressourcen von Kubernetes gehört eine große Anzahl verwandter Entitäten .

Lösungen für die Netzwerkarchitektur


Bei der Erhöhung des Clusters habe ich mir nicht die Aufgabe gestellt, die Eisenressourcen so zu optimieren, dass sie in das Budget von 20 USD pro Monat passen. Es war lediglich erforderlich, einen Arbeitscluster mit mindestens zwei Arbeitsknoten (Knoten) zusammenzustellen. Daher sah der Cluster anfangs folgendermaßen aus:


  • Maschine mit 2 vCPU / 4G RAM: API-Server + Node-1 [20 $]
  • Maschine mit 2 vCPU / 4G RAM: Knoten-2 [$ 20]

Nachdem die erste Version des Clusters funktioniert hatte, entschied ich mich, sie neu zu erstellen, um zwischen den Knoten, die für die Ausführung von Anwendungen innerhalb des Clusters verantwortlich sind (Arbeitsknoten, sie sind auch Worker), und der API des Master-Servers zu unterscheiden.


Als Ergebnis erhielt ich die Antwort auf die Frage: "Wie bekomme ich einen mehr oder weniger kostengünstigen, aber funktionierenden Cluster, wenn ich dort nicht die dicksten Anwendungen platzieren möchte?"


20 $ Entscheidung

Design
(Geplant, so zu sein)


Allgemeine Informationen zur Kubernetes-Architektur

Design
(Aus dem Internet gestohlen, wenn jemand plötzlich noch nichts weiß oder nicht gesehen hat)


Komponenten und ihre Leistung


Der erste Schritt bestand darin, zu verstehen, wie viele Ressourcen ich benötige, um Softwarepakete auszuführen, die in direktem Zusammenhang mit dem Cluster stehen. Die Suche nach "Hardwareanforderungen" ergab keine spezifischen Ergebnisse, so dass ich mich der Aufgabe aus praktischer Sicht nähern musste. Als Messung von MEM und CPU habe ich Statistiken von systemd genommen - wir können davon ausgehen, dass die Messungen sehr amateurhaft durchgeführt wurden, aber ich hatte nicht die Aufgabe, genaue Werte zu erhalten, da ich immer noch keine billigeren Optionen als 5 USD pro Instanz finden konnte.


Warum genau 5 Dollar?

Es war möglich, VPS / VDS billiger zu finden, wenn Server in Russland oder der GUS gehostet wurden, aber die traurigen Geschichten, die mit ILV und seinen Aktionen verbunden sind, bergen bestimmte Risiken und lassen den natürlichen Wunsch aufkommen, sie zu vermeiden.


Also:


  • Master Server / Server-Konfiguration (Master Nodes):
    • etcd (3.2.17): 80 - 100M, Metriken wurden zu zufällig ausgewählten Zeiten genommen. Der durchschnittliche Speicherverbrauch von Etcd überschritt 300 MB nicht.
    • Kube-Apiserver (1.12.x - 1.13.0): 237,6 M ~ 300 M;
    • kube-controller-manager (1.12.x - 1.13.0): ungefähr 90M, stieg nicht über 100M;
    • kube-scheduler (1.12.x - 1.13.0): ca. 20M, Verbrauch über 30-50M ist nicht festgelegt.
  • Worker Server-Konfiguration (Worker Nodes):
    • Kubelet (1.12.3 - 1.13.1): ca. 35 MB, Verbrauch über 50 MB ist nicht festgelegt;
    • kube-proxy (1.12.3 - 1.13.1): ungefähr 7,5 - 10 M;
    • Flanell (0,10,0): ungefähr 15-20 M;
    • Kerne (1.3.0): ungefähr 25 M;
    • Containerd (1.2.1): Der Containerd-Verbrauch ist gering, aber Statistiken zeigen auch Containerprozesse, die vom Daemon gestartet wurden.

Wird Containerd / Docker auf Masterknoten benötigt?

Nein, nicht benötigt . Der Masterknoten benötigt kein Docker oder Containerd an sich, obwohl es im Internet eine große Anzahl von Handbüchern gibt, die für den einen oder anderen Zweck die Verwendung der Umgebung für die Containerisierung umfassen. In der fraglichen Konfiguration wurde Containerd absichtlich aus der Liste der Abhängigkeiten deaktiviert. Ich möchte jedoch keine offensichtlichen Vorteile dieses Ansatzes hervorheben.


Die oben angegebene Konfiguration ist minimal und ausreichend, um den Cluster zu starten. Es ist keine zusätzliche Aktion / Komponente erforderlich, es sei denn, Sie möchten etwas hinzufügen, wie Sie möchten.


Um einen Testcluster oder Cluster für Heimprojekte zu erstellen, reicht 1vCPU / 1G RAM aus, damit der Masterknoten funktioniert. Die Belastung des Masterknotens hängt natürlich von der Anzahl der beteiligten Mitarbeiter sowie von der Verfügbarkeit und dem Volumen der Anforderungen von Drittanbietern an den API-Server ab.


Ich habe die Master- und Worker-Konfigurationen wie folgt aufgelöst:


  • 1x Master mit installierten Komponenten: etcd, kube-apiserver, kube-controller-manager, kube-scheduler
  • 2x Arbeiter mit installierten Komponenten: Containerd, Coredns, Flanell, Kubelet, Kube-Proxy

Konfiguration


Zum Konfigurieren des Assistenten sind die folgenden Komponenten erforderlich:


  • etcd - zum Speichern von Daten für API-Server sowie für Flanell;


  • kube-apiserver - eigentlich api-server;


  • kube-controller-manager - zum Generieren und Verarbeiten von Ereignissen;


  • kube-scheduler - zur verteilung von ressourcen, die über den api-server registriert sind - zum beispiel herd .
    Für die Konfiguration von Arbeitspferden sind folgende Komponenten erforderlich:


  • kubelet - um die Herde zu betreiben, um die Netzwerkeinstellungen zu konfigurieren;


  • kube-proxy - zum Organisieren des Routings / Ausgleichs von kubernetes- Diensten ;


  • coredns - zur Serviceerkennung in laufenden Containern;


  • Flanell - zur Organisation des Netzwerkzugriffs von Containern, die auf verschiedenen Knoten ausgeführt werden, sowie zur dynamischen Verteilung von Netzwerken zwischen Clusterknoten (Kubernetes-Knoten).



Coredns

Hier sollte ein kleiner Exkurs gemacht werden: Coredns können auch auf dem Master-Server gestartet werden. Es gibt keine Einschränkungen, die die Ausführung von Coredns auf Arbeitsknoten erzwingen würden, mit Ausnahme der Konfigurationsnuance coredns.service, die aufgrund eines Konflikts mit dem vom System aufgelösten Dienst auf einem standardmäßigen / nicht modifizierten Ubuntu-Server einfach nicht gestartet wird. Ich habe nicht versucht, dieses Problem zu lösen, da 2-ns-Server auf den Arbeitsknoten sehr zufrieden mit mir waren.


Um keine Zeit damit zu verschwenden, sich jetzt mit allen Details des Komponentenkonfigurationsprozesses vertraut zu machen, empfehle ich Ihnen, sich in der Kubernetes- Anleitung auf die harte Tour mit ihnen vertraut zu machen. Ich werde mich auf die Unterscheidungsmerkmale meiner Konfigurationsoption konzentrieren.


Dateien


Alle Dateien für die Funktionsweise der Clusterkomponenten für den Assistenten und die Arbeitsknoten werden der Einfachheit halber in / var / lib / kubernetes / abgelegt . Bei Bedarf können Sie sie auch anders platzieren.


Zertifizierungen


Die Basis für die Erstellung von Zertifikaten ist immer noch die gleiche Kubernetes auf die harte Tour , es gibt praktisch keine signifikanten Unterschiede. Um untergeordnete Zertifikate neu zu generieren , wurden einfache Bash-Skripte um cfssl- Anwendungen geschrieben - dies war beim Debugging-Prozess sehr nützlich.


Mit den folgenden Skripten, Rezepten von Kubernetes auf die harte Tour oder anderen geeigneten Tools können Sie Zertifikate für Ihre Anforderungen erstellen .


Zertifikatserstellung mit Bash-Skripten

Sie können Skripte hier erhalten: kubernetes bootstrap . Bearbeiten Sie vor dem Start die Datei certs / env.sh unter Angabe Ihrer Einstellungen. Ein Beispiel:


 $ cd certs #:   certs$ ./generate-keys.sh # ... certificate generate output #:  kubeconfig     certs$ ./generate-configkube.sh 

Wenn Sie env.sh und alle Parameter korrekt angegeben haben, müssen Sie die generierten Zertifikate nicht berühren. Wenn Sie irgendwann einen Fehler gemacht haben, können die Zertifikate in Teilen neu generiert werden. Die oben genannten Bash-Skripte sind trivial, das Aussortieren ist nicht schwierig.


Ein wichtiger Hinweis: Sie sollten die ca.pem und ca-key.pem nicht häufig neu erstellen, da sie die ca.pem für alle nachfolgenden Zertifikate sind. Mit anderen Worten, Sie müssen alle zugehörigen Zertifikate neu erstellen und an alle Computer und an alle erforderlichen Verzeichnisse ca-key.pem .


Der Meister


Die erforderlichen Zertifikate zum Starten von Diensten auf dem /var/lib/kubernetes/ sollten in /var/lib/kubernetes/ :


  • ca.pem - Dieses Zertifikat wird überall verwendet. Es kann nur einmal generiert und dann ohne Änderungen verwendet werden. Seien Sie also vorsichtig. Wenn Sie es neu generieren, müssen Sie es auf alle Knoten kopieren und die kubeconfig-Dateien damit aktualisieren (auch auf allen Computern).
  • ca-key.pem entspricht dem Kopieren über Knoten.
  • kube-controller-manager.pem - wird nur für kube-controller-manager benötigt.
  • kube-controller-manager-key.pem - wird nur für kube-controller-manager benötigt.
  • kubernetes.pem - erforderlich für Flanell, Coredns beim Verbinden mit etcd, kube-apiserver.


    Theoretischer Rückzug

    Diese Funktion basiert auf der Kubernetes-Hard-Way- Konfigurationslogik.
    Auf dieser Grundlage wird diese Datei überall benötigt - sowohl auf dem Assistenten als auch auf den Arbeitsknoten. Ich habe den Ansatz des ursprünglichen Handbuchs nicht geändert, da es mit seiner Hilfe möglich ist, den Cluster-Betrieb schneller und klarer zu organisieren und die gesamte Reihe von Abhängigkeiten zu verstehen.


    Meine persönliche Meinung ist, dass Sie für etcd separate Zertifikate benötigen, die sich nicht mit den für kubernetes verwendeten Zertifikaten überschneiden.




  • kubernetes-key.pem - bleibt auf Master-Servern.
  • service-account.pem - wird nur für Kube-Controller-Manager-Daemons benötigt.
  • service-account-key.pem - ähnlich.

Arbeitseinheiten


  • ca.pem - wird für alle Dienste benötigt, die an Arbeitsknoten (kubelet, kube-proxy) beteiligt sind, sowie für Flanell-Coredns. Der Inhalt ist unter anderem in kubeconfig-Dateien enthalten, wenn sie mit kubectl generiert werden.
  • kubernetes-key.pem - wird nur benötigt, damit Flanell und Coredns eine Verbindung zu etcd herstellen, das sich auf dem API-Masterknoten befindet.
  • kubernetes.pem - ähnlich dem vorherigen, wird nur für Flanell und Coredns benötigt.
  • kubelet / node-1.pem - Schlüssel für den Autorisierungsknoten-1.
  • kubelet / node-1-key.pem - Schlüssel für den Autorisierungsknoten-1.

Wichtig! Wenn Sie mehr als einen Knoten haben, enthält jeder Knoten die Dateien node-X-key.pem , node-X.pem und node-X.kubeconfig in kubelet.


Zertifikat-Debugging

Zertifikat-Debugging


Manchmal müssen Sie sich möglicherweise ansehen, wie das Zertifikat konfiguriert ist, um herauszufinden, welche IP / DNS-Hosts zum Generieren verwendet wurden. Der cfssl-certinfo -cert <cert> hilft uns dabei. Zum Beispiel lernen wir diese Informationen für node-1.pem :


 $ cfssl-certinfo -cert node-1.pem 

 { "subject": { "common_name": "system:node:node-1", "country": "RU", "organization": "system:nodes", "organizational_unit": "Infrastructure Unit", "locality": "Moscow", "province": "Moscow", "names": [ "RU", "Moscow", "Moscow", "system:nodes", "Infrastructure Unit", "system:node:node-1" ] }, "issuer": { "common_name": "Kubernetes", "country": "RU", "organization": "Kubernetes", "organizational_unit": "Infrastructure", "locality": "Moscow", "province": "Moscow", "names": [ "RU", "Moscow", "Moscow", "Kubernetes", "Infrastructure", "Kubernetes" ] }, "serial_number": "161113741562559533299282037709313751074033027073", "sans": [ "w40k.net", "node-1", "178.79.168.130", "192.168.164.230" ], "not_before": "2019-01-04T14:24:00Z", "not_after": "2029-01-01T14:24:00Z", "sigalg": "SHA256WithRSA", "authority_key_id": "6:C8:94:67:59:55:19:82:AD:ED:6D:50:F1:89:B:8D:46:78:FD:9A", "subject_key_id": "A1:5E:B3:3C:45:14:3D:C6:C:A:97:82:1:D5:2B:75:1A:A6:9D:B0", "pem": "<pem content>" } 

Alle anderen Zertifikate für kubelet und kube-proxy sind direkt in die entsprechende kubeconfig eingebettet.


kubeconfig


Alle notwendigen kubeconfig können mit Kubernetes auf die harte Tour gemacht werden, hier beginnen jedoch einige Unterschiede. Das Handbuch verwendet kubedns und cni bridge und cni bridge auch Coredns und Flanell . Diese beiden Dienste verwenden wiederum kubeconfig , kubeconfig sich beim Cluster kubeconfig .


 $ cd certs #:  kubeconfig     certs$ ./generate-configkube.sh 

Der Meister


Für den Assistenten werden die folgenden kubeconfig-Dateien benötigt (wie oben erwähnt, können sie nach der Generierung in certs/kubeconfig ):


 master /var/lib/kubernetes/$ tree -L 2 . +-- kube-controller-manager.kubeconfig L-- kube-scheduler  L-- kube-scheduler.kubeconfig 

Diese Dateien werden benötigt, um jede der Servicekomponenten auszuführen.


Arbeitseinheiten


Für Arbeitsknoten sind die folgenden kubeconfig-Dateien erforderlich:


 node-1 /var/lib/kubernetes/$ tree -L 2 . +-- coredns ¦  L-- coredns.kubeconfig +-- flanneld ¦  L-- flanneld.kubeconfig +-- kubelet ¦  L-- node-1.kubeconfig L-- kube-proxy  L-- kube-proxy.kubeconfig 

Servicestart


Dienstleistungen

Trotz der Tatsache, dass meine Arbeitsknoten unterschiedliche Initialisierungssysteme verwenden, bieten die Beispiele und das Repository Optionen mit systemd. Mit ihrer Hilfe ist es am einfachsten zu verstehen, welchen Prozess und mit welchen Parametern Sie starten müssen. Außerdem sollten sie beim Studium von Diensten mit Zielflags keine großen Probleme verursachen.


Um Dienste zu starten, müssen Sie service-name.service in /lib/systemd/system/ oder in ein anderes Verzeichnis service-name.service in dem sich die Dienste für systemd befinden. Anschließend müssen Sie den service-name.service und starten. Beispiel für kube-apiserver:


 $ systemctl enable kube-apiserver.service $ systemctl start kube-apiserver.service 

Natürlich müssen alle Dienste grün sein (dh ausgeführt werden und funktionieren). Wenn Sie auf einen Fehler journal -f -t kube-apiserver , helfen Ihnen die journal -f -t kube-apiserver journalct -xe oder journal -f -t kube-apiserver , zu verstehen, was genau schief gelaufen ist.


Beeilen Sie sich nicht, alle Server gleichzeitig zu starten. Für einen Start reicht es aus, etcd und kube-apiserver zu aktivieren. Wenn alles gut gelaufen ist und Sie sofort alle vier Dienste des Assistenten erhalten haben, kann der Start des Assistenten als erfolgreich angesehen werden.


Der Meister


Sie können die systemd- Einstellungen verwenden oder Init-Skripte für die von Ihnen verwendete Konfiguration generieren. Wie bereits erwähnt, benötigen Sie für den Master:


- systemd / etcd
- systemd / kube-apiserver
- systemd / kube-controller-manager
- systemd / kube-scheduler


Arbeitseinheiten


- Systemd / Containerd
- systemd / kubelet
- systemd / kube-proxy
- systemd / coredns
- System / Flanell


Kunde


Damit der Client funktioniert, kopieren certs/kubeconfig/admin.kubeconfig einfach certs/kubeconfig/admin.kubeconfig (nachdem Sie es generiert oder selbst geschrieben haben) in ${HOME}/.kube/config


Laden Sie kubectl herunter und überprüfen Sie die Funktion von kube-apiserver. Ich möchte Sie noch einmal daran erinnern, dass in diesem Stadium, damit kube-apiserver funktioniert, nur etcd funktionieren sollte. Die restlichen Komponenten werden etwas später für den vollständigen Betrieb des Clusters benötigt.


Überprüfen Sie, ob kube-apiserver und kubectl funktionieren:


 $ kubectl version Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", "extra info": "..."} Server Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", "extra info": "..."} 

Flanellkonfiguration


Als vxlan ich mich für das vxlan Backend entschieden. Lesen Sie hier mehr über Backends.


host-gw und warum es nicht funktioniert

Ich muss sofort sagen, dass das Ausführen eines Kubernetes-Clusters auf einem VPS Sie wahrscheinlich auf die Verwendung des host-gw Backends beschränken wird. Da ich kein erfahrener Netzwerktechniker bin, habe ich ungefähr zwei Tage lang debuggt, um zu verstehen, was das Problem bei der Verwendung bei beliebten VDS / VPS-Anbietern war.


Linode.com und Digitalocean wurden getestet. Das Wesentliche des Problems ist, dass Anbieter kein ehrliches L2 für ein privates Netzwerk bereitstellen. Dies macht es wiederum unmöglich, den Netzwerkverkehr zwischen Knoten in dieser Konfiguration zu verschieben:


Verkehr


Damit der Netzwerkverkehr zwischen den Knoten funktioniert, reicht normales Routing aus. Vergessen Sie nicht, dass net.ipv4.ip_forward auf 1 gesetzt werden sollte und die FORWARD-Kette in der Filtertabelle keine Verbotsregeln für Knoten enthalten sollte.


 node1$ ip route add 10.200.12.0/24 via 192.168.1.2 node2$ ip route add 10.200.8.0/24 via 192.168.1.1 

 [10.200.80.23 container-1]->[192.168.1.1 node-1]->[192.168.1.2 node-2]->[10.200.12.5 container-2] 

Dies ist genau das, was auf dem angegebenen (und höchstwahrscheinlich allgemein auf allen) VPS / VDS nicht funktioniert.


Wenn Ihnen daher die Konfiguration einer Lösung mit hoher Netzwerkleistung zwischen den Knoten wichtig ist , müssen Sie immer noch mehr als 20 US-Dollar für die Organisation des Clusters ausgeben.


Sie können set-flannel-config.sh von etc / set-flannel-config.sh , um die gewünschte set-flannel-config.sh . Es ist wichtig zu beachten : Wenn Sie das Backend ändern möchten, müssen Sie die Konfiguration in etcd löschen und alle Flanell-Daemons auf allen Knoten neu starten. Wählen Sie sie daher mit Bedacht aus. Der Standardwert ist vxlan.


 master$ export ETCDCTL_CA_FILE='/var/lib/kubernetes/ca.pem' master$ export ETCDCTL_CERT_FILE='/var/lib/kubernetes/kubernetes.pem' master$ export ETCDCTL_KEY_FILE='/var/lib/kubernetes/kubernetes-key.pem' master$ export ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' master$ etcdctl ls /coreos.com/network/subnets/ /coreos.com/network/subnets/10.200.8.0-24 /coreos.com/network/subnets/10.200.12.0-24 master$ etcdctl get /coreos.com/network/subnets/10.200.8.0-24 {"PublicIP":"178.79.168.130","BackendType":"vxlan","BackendData":{"VtepMAC":"22:ca:ac:15:71:59"}} 

Nachdem Sie die gewünschte Konfiguration in etcd registriert haben, müssen Sie den Dienst so konfigurieren, dass er auf jedem der Arbeitsknoten ausgeführt wird.


flannel.service


Ein Beispiel für den Dienst kann hier genommen werden: systemd / flannel


flannel.service
 [Unit] Description=Flanneld overlay address etcd agent After=network.target [Service] Type=notify #: current host ip. don't change if ip have not changed Environment=PUBLIC_IP=178.79.168.130 Environment=FLANNEL_ETCD=https://192.168.153.60:2379 ExecStart=/usr/bin/flanneld \ -etcd-endpoints=${FLANNEL_ETCD} -etcd-prefix=${FLANNEL_ETCD_KEY} \ -etcd-cafile=/var/lib/kubernetes/ca.pem \ -etcd-certfile=/var/lib/kubernetes/kubernetes.pem \ -etcd-keyfile=/var/lib/kubernetes/kubernetes-key.pem \ -etcd-prefix=/coreos.com/network \ -healthz-ip=127.0.0.1 \ -subnet-file=/run/flannel/subnet.env \ -public-ip=${PUBLIC_IP} \ -kubeconfig-file=/var/lib/kubernetes/config/kubeconfig/flanneld.kubeconfig \ $FLANNEL_OPTIONS ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker Restart=on-failure RestartSec=5 [Install] RequiredBy=docker.service 

Anpassung


Wie bereits beschrieben, benötigen wir die Dateien ca.pem, kubernetes.pem und kubernetes-key.pem für die Autorisierung in etcd. Alle anderen Parameter haben keine heilige Bedeutung. Das einzige, was wirklich wichtig ist, ist die Konfiguration der globalen IP-Adresse, über die Netzwerkpakete zwischen Netzwerken übertragen werden:


Flanellvernetzung
( Multi-Host-Netzwerk-Overlay mit Flanell )


 #:   node-1$ systemctl enable flanneld.service #:  node-1$ systemctl start flanneld 

Nachdem Flanell erfolgreich gestartet wurde, sollten Sie die Netzwerkschnittstelle flannel.N auf Ihrem System finden:


 node-1$ ifconfig flannel.100: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450 inet 10.200.8.0 netmask 255.255.255.255 broadcast 0.0.0.0 inet6 fe80::20ca:acff:fe15:7159 prefixlen 64 scopeid 0x20<link> ether 22:ca:ac:15:71:59 txqueuelen 0 (Ethernet) RX packets 18853 bytes 1077085 (1.0 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 11856 bytes 264331154 (252.0 MiB) TX errors 0 dropped 47 overruns 0 carrier 0 collisions 0 

Es ist ganz einfach zu überprüfen, ob Ihre Schnittstellen auf allen Knoten ordnungsgemäß funktionieren. In meinem Fall haben Knoten-1 und Knoten-2 10.200.8.0/24 bzw. 10.200.12.0/24 Netzwerke. Bei einer regulären icmp-Anfrage überprüfen wir daher deren Verfügbarkeit:


 #:  node-2  node-1 node-1 $ ping -c 1 10.200.12.0 PING 10.200.12.0 (10.200.12.0) 56(84) bytes of data. 64 bytes from 10.200.12.0: icmp_seq=1 ttl=64 time=4.58 ms #:  node-1  node-2 node-2 $ ping -c 1 10.200.8.0 PING 10.200.8.0 (10.200.8.0) 56(84) bytes of data. 64 bytes from 10.200.8.0: icmp_seq=1 ttl=64 time=1.44 ms 

Bei Problemen wird empfohlen, zu überprüfen, ob in iptables über UDP Schnittregeln zwischen Hosts vorhanden sind.


Containerd-Konfiguration


Platzieren Sie etc / Containerd / config.toml in /etc/containerd/config.toml oder wo immer es Ihnen passt. /etc/containerd/config.toml Sie daran, den Pfad zur Konfigurationsdatei im Dienst (containerd.service, siehe unten) zu ändern.


Konfiguration mit einigen Änderungen des Standards. Es ist wichtig, enable_tls_streaming = true nicht zu setzen enable_tls_streaming = true wenn Sie nicht verstehen, warum Sie dies tun. Andernfalls kubectl exec nicht mehr und gibt den Fehler aus, dass das Zertifikat von einer unbekannten Partei signiert wurde.


containerd.service


containerd.service
 [Unit] Description=containerd container runtime Documentation=https://containerd.io After=network.target [Service] ; uncomment this if your overlay module are built as module ; ExecStartPre=/sbin/modprobe overlay ExecStart=/usr/bin/containerd \ -c /etc/containerd/config.toml Restart=always RestartSec=5 Delegate=yes KillMode=process OOMScoreAdjust=-999 LimitNOFILE=1048576 LimitNPROC=infinity LimitCORE=infinity [Install] WantedBy=multi-user.target 


, , cri-tools .
etc/crictl.yaml /etc/crictl.yaml . :


 node-1$ CONTAINERD_NAMESPACE=k8s.io crictl ps CONTAINER ID IMAGE CREATED STATE NAME ATTEMPT POD ID 

, - kubernetes , crictl , , .


CNI Plugins


CNI , , , .



cni plugins /opt/cni/bin/


/etc/cni/net.d :


/etc/cni/net.d/10-flannel.conflist
 { "cniVersion": "0.3.0", "name": "cbr0", "plugins": [ { "type": "flannel", "name": "kubenet", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true }, "externalSetMarkChain": "KUBE-MARK-MASQ" } ] } 

/etc/cni/net.d/99-loopback.conf
 { "cniVersion": "0.3.0", "type": "loopback" } 

, . , , Red Hat Docker Podman , Intro to Podman


Kubelet


kubelet ( cni) — . kubelet hostname. , "" kubectl logs , kubectl exec , kubectl port-forward .


kubelet-config.yaml

, etc/kubelet-config.yaml , , . :


 systemReserved: cpu: 200m memory: 600Mi 

, GO kubernetes, , . . 0.2 vCPU 600 MB .


, , kubelet, kube-proxy, coredns, flannel . , — 2 vCPU / 4G ram, , kubernetes + postgresql .


- (micro nodes) .


kubelet.service


service : systemd/kubelet


kubelet.service
 [Unit] Description=Kubernetes Kubelet Documentation=https://github.com/kubernetes/kubernetes Requires=containerd.service [Service] #Environment=NODE_IP=192.168.164.230 Environment=NODE_IP=178.79.168.130 #: node name given by env Environment=NODE_NAME=w40k.net ExecStart=kubelet \ --allow-privileged \ --root-dir=/var/lib/kubernetes/kubelet \ --config=/var/lib/kubernetes/kubelet/kubelet-config.yaml \ --kubeconfig=/var/lib/kubernetes/kubelet/node-1.kubeconfig \ --cni-bin-dir=/opt/cni/bin \ --cni-conf-dir=/etc/cni/net.d/ \ --network-plugin=cni \ --container-runtime=remote \ --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \ --image-pull-progress-deadline=10m \ --node-ip=${NODE_IP} \ --hostname-override=${NODE_NAME} \ --v=1 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target 


, RBAC , kubelet.


etc/kubelet-default-rbac.yaml , kubelet :


 user$ kubectl apply -f etc/kubelet-default-rbac.yaml 

, , .


 #:   node-1$ systemctl enable kubelet.service #:  node-1$ systemctl start kubelet 

, api :


 $ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME w40k.net Ready <none> 5m v1.13.1 178.79.168.130 <none> Gentoo/Linux 4.18.16-x86_64-linode118 containerd://1.2.1 

Kube Proxy


: systemd/kubelet . , , kube-proxy-config.yaml : etc/kube-proxy


kube-proxy.service


kube-proxy.service
 [Unit] Description=Kubernetes Proxy Documentation=https://github.com/kubernetes/kubernetes After=network.target [Service] ExecStart=kube-proxy \ --config=/var/lib/kubernetes/kube-proxy/kube-proxy-config.yaml Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target 


 #:   node-1$ systemctl enable kube-proxy.service #:  node-1$ systemctl start kube-proxy 

kube-proxy "" iptables, , - kubernetes (- ). .


CoreDNS


Corefile : etc/coredns/Corefile , :


/etc/coredns/Corefile
 .:53 { errors log stdout health :8081 kubernetes cluster.local 10.200.0.0/16 { endpoint https://178.79.148.185:6443 tls /var/lib/kubernetes/kubernetes.pem /var/lib/kubernetes/kubernetes-key.pem /var/lib/kubernetes/ca.pem pods verified upstream /etc/resolv.conf kubeconfig /var/lib/kubernetes/config/kubeconfig/coredns.kubeconfig default } proxy . /etc/resolv.conf cache 30 } 

coredns.kubeconfig pem- ( ) worker . , coredns systemd-resolved. , Ubuntu , , , , . .


coredns.service


coredns.service
 [Unit] Description=CoreDNS Documentation=https://coredns.io/ After=network.target [Service] ExecStart=/usr/bin/coredns -conf /etc/coredns/Corefile Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target 


 #:   node-1$ systemctl enable coredns.service #:  node-1$ systemctl start coredns 

, , :


 node-1$ dig kubernetes.default.svc.cluster.local @127.0.0.1 #:    ;kubernetes.default.svc.cluster.local. IN A ;; ANSWER SECTION: kubernetes.default.svc.cluster.local. 5 IN A 10.32.0.1 

, coredns ip kubernetes .
, kubernetes.default kube-controller-manager, :


 $ kubectl get svc -n default NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.32.0.1 <none> 443/TCP 26h 

nginx-ingress & cert-manager


, . nginx-ingress cert-manager.


nginx kubernetes ingress (master), :


  user$ git clone https://github.com/nginxinc/kubernetes-ingress.git user$ cd kubernetes-ingress/deployments user$ kubectl apply -f common/ns-and-sa.yaml user$ kubectl apply -f common/nginx-config.yaml user$ kubectl apply -f common/default-server-secret.yaml user$ kubectl apply -f daemon-set/nginx-ingress.yaml user$ kubectl apply -f rbac/rbac.yaml 

cert manager (v0.5.2)


  user$ git clone https://github.com/jetstack/cert-manager.git user$ cd cert-manager && git co v0.5.2 user$ cd contrib/manifests/cert-manager user$ kubectl apply -f with-rbac.yaml 

, , , :


 NAMESPACE NAME READY STATUS RESTARTS AGE cert-manager cert-manager-554c76fbb7-t9762 1/1 Running 0 3h38m nginx-ingress nginx-ingress-sdztf 1/1 Running 0 10h nginx-ingress nginx-ingress-vrf85 1/1 Running 0 10h 

cert-manager nginx-ingress running state, , . , Running . .



, . , kubernetes resource : app/k8s


 user$ kube apply -f ns-and-sa.yaml user$ kube apply -f configmap.yaml #:  secret-example.yaml       #: secret.yaml user$ kube apply -f secret.yaml user$ kube apply -f tls-production.yaml user$ kube apply -f deployment.yaml user$ kube apply -f service.yaml user$ kube apply -f ingress-production.yaml 

, - . , ( kubernetes-example.w40k.net), , , cert-manager nginx-ingress . , ingress tls/ssl.


:



, - . - , , .


Referenzen


, , :


Kubernetes the hard way
Multi-Host Networking Overlay with Flannel
Intro to Podman
Stateless Applications
What is ingress


:


Kubernetes Networking: Behind the scenes ( )
A Guide to the Kubernetes Networking Model
Understanding kubernetes networking: services ( )


Q&A


<tbd>, .



, , . , , - , , .


Api Server


kube-apiserver.service , api-server' curl http . - .
admin.kubeconfig ${HOME}/.kube/config, kubectl api-server (kube-apiserver).


( ) HTTP 200 OK + , api-server :


 curl -H "Authorization: Bearer e5qXNAtwwCHUUwyLilZmAoFPozrQwUpw" -k -L https://<api-server-address>:6443/api/v1/ 

Kube Controller Manager


, controller manager api , . , service account' :


 $ kubectl get sa NAME SECRETS AGE default 1 19h 

, , kube-controller-manager .


Kube Scheduler


. , , debug/job.yaml kubectl describe <type/resource> .
, kube controller manager .


 #:   job user$ kubectl apply -f debug/job.yaml job.batch/app created #:  ,   job user$ kubectl get pods -l job-name=app NAME READY STATUS RESTARTS AGE app-9kr9z 0/1 Completed 0 54s #: ,        #:   user$ kubectl describe pods app-9kr9z # ...   ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 12s default-scheduler Successfully assigned example/app-9kr9z to w40k.net 

, default-scheduler pod w40k.net. - , — .


. , , , — "". systemd .


kube scheduler


Kubelet


Kubelet kubernetes . kubelet . kubernetes event ( kubectl get events -o wide ) .


( )


Kube Proxy


kube-proxy :


  • ( Flannel , );
  • iptables, filter nat .

, 10.32.0.0/24 "". , . iptables, , , - +. icmp , ping' . , .


, kube-proxy, :


 #:    user$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE backend ClusterIP 10.32.0.195 <none> 80/TCP 5m #:     user$ kubectl get pods -o wide #:     ' NAME READY STATUS RESTARTS AGE IP NODE backend-896584448-4r94s 1/1 Running 0 11h 10.200.8.105 w40k.net backend-896584448-np992 1/1 Running 0 11h 10.200.12.68 docker.grart.net #:  10   /status/ endpoint ,       #:       node-1$ for i in `seq 10`; do curl -L http://10.32.0.195/status/; done okokokokokokokokokok node-1$ conntrack -L -d 10.32.0.195 tcp 6 62 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62158 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62158 [ASSURED] mark=0 use=1 tcp 6 60 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62144 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62144 [ASSURED] mark=0 use=1 tcp 6 58 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62122 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62122 [ASSURED] mark=0 use=1 tcp 6 59 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62142 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62142 [ASSURED] mark=0 use=1 tcp 6 58 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62130 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62130 [ASSURED] mark=0 use=1 tcp 6 61 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62150 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62150 [ASSURED] mark=0 use=1 tcp 6 56 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62116 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62116 [ASSURED] mark=0 use=1 tcp 6 57 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62118 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62118 [ASSURED] mark=0 use=1 tcp 6 59 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62132 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62132 [ASSURED] mark=0 use=1 tcp 6 56 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62114 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62114 [ASSURED] mark=0 use=1 

src/dst (9 10 ). , src :


  • 10.200.8.105
  • 10.200.12.68

, . , - ( , ) . .


 #: node-1   10.200.8.105, node-2 10.200.12.68, #:      8000  #:  node-1 node-1$ curl -L http://10.200.8.105:8000/status/ ok node-1$ curl -L http://10.200.12.68:8000/status/ ok #:  node-2 node-2$ curl -L http://10.200.8.105:8000/status/ ok node-2$ curl -L http://10.200.12.68:8000/status/ ok 

, , conntrack , , kube-proxy. , nat :


node-1$ iptables -t nat -vnL


.


. , , . , . - , , .


Source: https://habr.com/ru/post/de435228/


All Articles