Table of Contents
URL: https://www.progressiverobot.com/recommended-steps-to-secure-a-cloud-provider-kubernetes-cluster-de/
*Der Autor wählte die Kooperation Open Sourcing Mental Illness, um eine Spende im Rahmen des Programms Write for DOnations zu erhalten.*
Einführung
Kubernetes, die Open-Source-Container-Orchestrierungsplattform, wird immer mehr zur bevorzugten Lösung für die Automatisierung, Skalierung und Verwaltung von Hochverfügbarkeits-Clustern. Aufgrund der zunehmenden Popularität wird die Sicherheit von Kubernetes immer wichtiger.
In Anbetracht der beweglichen Teile, die in Kubernetes involviert sind, und der Vielfalt der Einsatzszenarien kann die Sicherung von Kubernetes manchmal komplex sein. Ziel dieses Artikels ist es daher, eine solide Sicherheitsbasis für einen Kubernetes (DOKS) Cluster bereitzustellen. Beachten Sie, dass dieses Tutorial grundlegende Sicherheitsmaßnahmen für Kubernetes behandelt und eher als Startpunkt und nicht als erschöpfender Leitfaden gedacht ist. Zusätzliche Schritte finden Sie in der offiziellen Kubernetes-Dokumentation.
In diesem Tutorial nehmen Sie grundlegende Schritte zur Sicherung Ihres Kubernetes Clusters vor. Sie konfigurieren eine sichere lokale Authentifizierung mit TLS/SSL-Zertifikaten, vergeben Berechtigungen an lokale Benutzer mit rollenbasierten Zugriffskontrollen (RBAC) sowie an Kubernetes-Anwendungen und -Bereitstellungen mit Service Accounts, und richten Ressourcenbegrenzungen mit den Zugriffs-Controllern ResourceQuota und LimitRange ein.
Voraussetzungen
Um dieses Tutorial auszuführen, benötigen Sie Folgendes:
- Einen von Kubernetes (DOKS) verwalteten Cluster mit 3 Standardknoten, die jeweils mit mindestens 2 GB RAM und 1 vCPU konfiguriert sind. Eine detaillierte Anleitung für die Erstellung eines DOKS-Clusters finden Sie in unserem Leitfaden Kubernetes Quickstart. Dieses Tutorial verwendet die DOKS-Version 1.16.2-do.1.
- Einen für die Verwaltung des DOKS-Clusters konfigurierten lokalen Client, mit einer vom the cloud provider Control Panel heruntergeladenen Cluster-Konfigurationsdatei, gespeichert unter
~/.kube/config. Eine detaillierte Anleitung für die Konfiguration eines auf Remote-Ebene verwalteten DOKS finden Sie im Leitfaden Verbinden mit einem Kubernetes Cluster. Im Einzelnen benötigen Sie Folgendes:
- Die auf Ihrem lokalen Rechner installierte Befehlszeilenschnittstelle
kubectl. Mehr über die Installation und Konfiguration vonkubectlkönnen Sie der offiziellen Dokumentation entnehmen. Dieses Tutorial verwendet diekubectl-Version 1.17.0-00.
- Das offizielle the cloud provider-Befehlszeilen-Tool
doctl. Anweisungen für die Installation finden Sie auf der SeitedoctlGitHub Page. Dieses Tutorial verwendet die Versiondoctl1.36.0.
Schritt 1 – Aktivieren der Remotebenutzer-Authentifizierung
Nach der Erfüllung der Voraussetzungen erhalten Sie einen Kubernetes-Superuser, der sich über ein vordefiniertes the cloud provider-Träger-Token authentifiziert. Die gemeinschaftliche Nutzung dieses Berechtigungsnachweises ist jedoch keine gute Sicherheitspraxis, da dieses Konto umfangreiche und möglicherweise destruktive Änderungen an Ihrem Cluster verursachen kann. Um diese Möglichkeit einzugrenzen, können Sie zusätzliche Benutzer einrichten, die von ihren jeweiligen lokalen Clients authentifiziert werden.
In diesem Abschnitt authentifizieren Sie neue Benutzer beim DOKS-Remote-Cluster von lokalen Clients aus mit sicheren SSL/TLS-Zertifikaten. Dies ist ein dreistufiger Prozess: Zuerst generieren Sie für jeden Benutzer eine Zertifikatsignierungsanforderung, die Certificate Signing Requests (CSR)). Danach genehmigen Sie diese Zertifikate direkt im Cluster über kubectl. Abschließend erstellen Sie für jeden Benutzer eine kubeconfig-Datei mit den entsprechenden Zertifikaten. Weitere Informationen über zusätzliche von Kubernetes unterstützte Authentifizierungsverfahren finden Sie in der Kubernetes-Authentifizierungsdokumentation.
Erstellen von Zertifikatsignierungsanforderungen für neue Benutzer
Prüfen Sie vor dem Start die DOKS-Clusterverbindung von dem lokalen Rechner aus, der bei den Voraussetzungen konfiguriert wurde:
kubectl cluster-info
Je nach Ihrer Konfiguration sehen Sie ein ähnliches Output:
[secondary_label Output]
Kubernetes master is running at https://www.progressiverobot.com/
CoreDNS is running at https://www.cloudflare.com/learning/dns/what-is-dns/
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
Das bedeutet, dass Sie mit dem DOKS-Cluster verbunden sind.
Erstellen Sie als Nächstes einen lokalen Ordner für die Client-Zertifikate. In diesem Tutorial nutzen Sie zur Speicherung aller Zertifikate ~/certs.
mkdir ~/<^>certs<^>
Sie autorisieren in diesem Tutorial einen neuen Benutzer namens sammy, um auf den Cluster zuzugreifen. Sie können dies auch auf einen Benutzer Ihrer Wahl ändern. Generieren Sie mit der SSL- und TLS-Bibliothek OpenSSL einen neuen privaten Schlüssel für Ihren Benutzer mit dem folgenden Befehl:
openssl genrsa -out ~/<^>certs<^>/<^>sammy<^>.key 4096
Das -out-Flag erzeugt die Output-Datei ~/<^>certs<^>/<^>sammy<^>.key, und 4096 setzt den Schlüssel als 4096-Bit. Weitere Informationen über OpenSSL finden Sie in unserem Leitfaden OpenSSL Essentials.
Erstellen Sie nun eine Konfigurationsdatei zur Zertifikatsignierungsanforderung. Öffnen Sie die folgende Datei mit einem Texteditor (für dieses Tutorial verwenden wir nano):
nano ~/<^>certs/sammy.csr.cnf<^>
Fügen Sie folgenden Inhalt in die Datei <^>sammy.csr.cnf<^> ein, um im Subjekt den gewünschten Benutzernamen als "common name" (CN) und die Gruppe als "organization"(O) festzulegen:
[label ~/certs/sammy.csr.cnf]
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = <^>sammy<^>
O = <^>developers<^>
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth
Die Konfigurationsdatei für die Zertifikatsignierungsanforderung enthält alle erforderlichen Informationen, die Benutzeridentität und entsprechende Verwendungsparameter für den Benutzer. Das letzte Argument extendedKeyUsage=serverAuth,clientAuth ermöglicht Benutzern die Authentifizierung ihrer lokalen Clients mit dem DOKS-Cluster mittels des Zertifikats, sobald es unterzeichnet wurde.
Erstellen Sie als Nächstes die Zertifikatsignierungsanforderung (CSR) für sammy:
openssl req -config ~/<^>certs<^>/<^>sammy<^>.csr.cnf -new -key ~/<^>certs<^>/<^>sammy<^>.key -nodes -out ~/<^>certs<^>/<^>sammy<^>.csr
Mit -config können Sie die Konfigurationsdatei für die CSR festlegen, und -new signalisiert die Erstellung einer neuen CSR für den durch -key festgelegten Schlüssel.
Sie können Ihre Zertifikatsignierungsanforderung überprüfen, indem Sie folgenden Befehl ausführen:
openssl req -in ~/<^>certs<^>/<^>sammy<^>.csr -noout -text
Hier geben Sie die CSR mit -in an und verwenden -text, um die Zertifikatsanforderung in Text auszudrucken.
Das Output zeigt die Zertifikatsanforderung, deren Anfang folgendermaßen aussieht:
[secondary_label Output]
Certificate Request:
Data:
Version: 1 (0x0)
Subject: CN = <^>sammy<^>, O = <^>developers<^>
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (4096 bit)
...
Wiederholen Sie den gleichen Vorgang, um CSRs für alle weiteren Benutzer zu erstellen. Wenn Sie alle Zertifikatsignierungsanforderungen in dem Ordner ~/certs des Administrators gespeichert haben, fahren Sie mit dem nächsten Schritt fort, um sie zu genehmigen.
Verwalten von Zertifikatsignierungsanforderungen mit der Kubernetes-API
Sie können die TLS-Zertifikate, die für die Kubernetes-API ausgegeben wurden, mit dem Befehlszeilen-Tool kubectl entweder genehmigen oder ablehnen. So können Sie sicherstellen, dass der angeforderte Zugang für den jeweiligen Benutzer geeignet ist. In diesem Abschnitt senden Sie die Zertifikatsanforderung für sammy und genehmigen sie.
Zum Senden einer CSR an den DOKS-Cluster verwenden Sie den folgenden Befehl:
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: <^>sammy-authentication<^>
spec:
groups:
- system:authenticated
request: $(cat ~/<^>certs<^>/<^>sammy<^>.csr | base64 | tr -d '\n')
usages:
- digital signature
- key encipherment
- server auth
- client auth
EOF
Dieser Befehl mit einem Bash-*Heredoc* nutzt cat, um die Zertifikatsanforderung an kubectl apply weiterzuleiten.
Sehen Sie sich die Zertifikatsanforderung genauer an:
name: <^>sammy-authentication<^>erstellt einen Metadaten-Identifizierer, hiersammy-authenticationgenannt.
request: $(cat ~/<^>certs<^>/<^>sammy<^>.csr | Basis64 | tr -d '\n')sendet die Zertifikatsignierungsanforderungsammy.csrals Base64 kodiert an den Cluster.
server authundclient authgeben die beabsichtigte Verwendung des Zertifikats an. In diesem Fall ist der Zweck die Benutzerauthentifizierung.
Das Output sieht ungefähr wie folgt aus:
[secondary_label Output]
certificatesigningrequest.certificates.k8s.io/<^>sammy-authentication<^> created
Sie können den Status der Zertifikatsignierungsanforderung mit diesem Befehl prüfen:
kubectl get csr
Je nach Ihrer Cluster-Konfiguration sehen Sie ein ähnliches Output:
[secondary_label Output]
NAME AGE REQUESTOR CONDITION
<^>sammy-authentication<^> 37s <^>your_DO_email<^> Pending
Als Nächstes genehmigen Sie die CSR durch Verwendung des Befehls:
kubectl certificate approve <^>sammy-authentication<^>
Sie erhalten eine Nachricht, die die Operation bestätigt:
[secondary_label Output]
certificatesigningrequest.certificates.k8s.io/<^>sammy-authentication<^> approved
Anmerkung: Als Administrator können Sie eine CSR auch mit dem Befehl kubectl certificate deny <^>sammy-authentication<^> ablehnen. Weitere Informationen über die Verwaltung von TLS-Zertifikaten finden Sie in der offiziellen Dokumentation von Kubernetes.
Nachdem die CSR nun genehmigt wurde, können Sie sie auf den lokalen Rechner herunterladen, indem Sie Folgendes ausführen:
kubectl get csr <^>sammy-authentication<^> -o jsonpath='{.status.certificate}' | base64 --decode > ~/<^>certs<^>/<^>sammy<^>.crt
Dieser Befehl dekodiert das Base64-Zertifikat für eine richtige Anwendung durch kubectl und speichert es dann als ~/<^>certs<^>/<^>sammy<^>.crt.
Mit dem signierten sammy-Zertifikat können Sie nun die kubeconfig-Datei des Benutzers erstellen.
Erstellen der Remotebenutzer-Kubeconfig
Als Nächstes erstellen Sie eine spezifische kubeconfig-Datei für den sammy-Benutzer. Dadurch erhalten Sie mehr Kontrolle über den Zugriff des Benutzers auf Ihren Cluster.
Der erste Schritt beim Erstellen einer neuen kubeconfig ist die Erstellung einer Kopie der aktuellen kubeconfig-Datei. In diesem Tutorial benennen Sie die neue kubeconfig-Datei <^>config-sammy<^>:
cp ~/.kube/config ~/.kube/<^>config-sammy<^>
Als Nächstes editieren Sie die neue Datei:
nano ~/.kube/<^>config-sammy<^>
Behalten Sie die ersten acht Zeilen dieser Datei, da sie die erforderlichen Informationen für die SSL/TLS-Verbindung mit dem Cluster enthalten. Ersetzen Sie dann ausgehend vom Benutzerparameter den Text durch die folgenden hervorgehobenen Zeilen, damit die Datei ähnlich wie Folgendes aussieht:
[label config-sammy]
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: certificate_data
name: do-nyc1-do-cluster
contexts:
- context:
cluster: do-nyc1-do-cluster
user: <^>sammy<^>
name: do-nyc1-do-cluster
current-context: do-nyc1-do-cluster
kind: Config
preferences: {}
users:
- name: <^>sammy<^>
user:
<^>client-certificate: /home/your_local_user/certs/sammy.crt<^>
<^>client-key: /home/your_local_user/certs/sammy.key<^>
Anmerkung: Sowohl für client-certificate als auch für client-key verwenden Sie den absoluten Pfad zu deren entsprechenden Zertifikatsstandorten. Andernfalls erzeugt kubectl einen Fehler.
Speichern und schließen Sie die Datei.
Sie können die neue Benutzerverbindung mit kubectl cluster-info testen:
kubectl --kubeconfig=/home/<^>your_local_user<^>/.kube/<^>config-sammy<^> cluster-info
Sie erhalten einen ähnlichen Fehler:
[secondary_label Output]
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
Error from server (Forbidden): services is forbidden: User "<^>sammy<^>" cannot list resource "services" in API group "" in the namespace "kube-system"
Dieser Fehler wird erwartet, weil der Benutzer sammy noch keine Berechtigung hat, eine Ressource auf dem Cluster zu listen. Die Erteilung von Berechtigungen an Benutzer wird im nächsten Schritt gezeigt. Das jetzige Output bestätigt, dass die SSL/TLS-Verbindung erfolgreich war und die Authentifizierungsangaben von sammy von der Kubernetes-API akzeptiert wurden.
Schritt 2 – Autorisieren von Benutzern über die Rollenbasierte Zugriffskontrolle (RBAC)
Nach der Authentifizierung eines Benutzers bestimmt die API seine Berechtigungen mit dem in Kubernetes integrierten Modell der Role Based Access Control (RBAC), der rollenbasierten Zugriffskontrolle. RBAC ist eine wirksame Methode zur Beschränkung von Benutzerrechten auf der Grundlage der jeweils zugewiesenen Rolle. Aus sicherheitstechnischer Sicht erlaubt RBAC das Festlegen genau definierter Berechtigungen und limitiert damit die Möglichkeiten von Benutzern, auf vertrauliche Daten zuzugreifen oder Befehle auf Superuser-Ebene auszuführen. Weitere detaillierte Informationen über Benutzerrollen finden Sie in der Kubernetes-RBAC-Dokumentation.
In diesem Schritt verwenden Sie kubectl, um die vordefinierte Rolle edit dem Benutzer sammy im default-Namensraum zuzuweisen. In einer Produktivumgebung können Sie auch benutzerdefinierte Rollen und/oder benutzerdefinierte Rollenbindungen verwenden.
Berechtigungen erteilen
In Kubernetes bedeutet die Erteilung von Berechtigungen, einem Benutzer die gewünschte Rolle zuzuweisen. Erteilen Sie edit-Berechtigungen an den Benutzer sammy im default-Namensraum mit diesem Befehl:
kubectl create rolebinding <^>sammy-edit-role<^> --clusterrole=edit --user=<^>sammy<^> --namespace=default
Sie erhalten ein Output, das dem Folgenden ähnelt:
[secondary_label Output]
rolebinding.rbac.authorization.k8s.io/<^>sammy-edit-role<^> created
Im Einzelnen setzt sich der Befehl wie folgt zusammen:
create rolebinding <^>sammy-edit-role<^>erstellt eine neue Rollenbindung, in diesem Fall namens<^>sammy-edit-role<^>.
--clusterrole=editwendet die vordefinierte Rolleeditauf einen globalen Gültigkeitsbereich (Cluster-Rolle) an.
--user=<^>sammy<^>gibt an, an welchen Benutzer die Rolle gebunden wird.
--namespace=defaulterteilt die Rollenberechtigung des Benutzers im angegebenen Namensraum, in diesem Falldefault.
Als Nächstes verifizieren Sie die Benutzerberechtigung, indem Sie Pods in dem default-Namensraum auflisten. Sie können erkennen, ob die RBAC-Autorisierung wie erwartet funktioniert, wenn keine Fehler angezeigt werden.
kubectl --kubeconfig=/home/<^>your_local_user<^>/.kube/<^>config-sammy<^> auth can-i get pods
Sie erhalten folgendes Output:
[secondary_label Output]
yes
Sie haben sammy nun Berechtigungen zugewiesen. Im nächsten Abschnitt sehen Sie, wie Sie diese Berechtigungen wieder entziehen.
Berechtigungen entziehen
In Kubernetes entziehen Sie Berechtigungen, indem Sie die Rollenbindung des Benutzers entfernen.
In diesem Tutorial löschen Sie die edit-Rolle des Benutzers sammy, indem Sie folgenden Befehl ausführen:
kubectl delete rolebinding <^>sammy-edit-role<^>
Sie erhalten folgendes Output:
[secondary_label Output]
rolebinding.rbac.authorization.k8s.io "<^>sammy-edit-role<^>" deleted
Überprüfen Sie, ob die Berechtigungen wie erwartet entzogen wurden, indem Sie Pods im default-Namensraum auflisten:
kubectl --kubeconfig=/home/<^>localuser<^>/.kube/<^>config-sammy<^> --namespace=default get pods
Sie erhalten die folgende Fehlermeldung:
[secondary_label Output]
Error from server (Forbidden): pods is forbidden: User "<^>sammy<^>" cannot list resource "pods" in API group "" in the namespace "default"
Diese zeigt, dass die Autorisierung entzogen wurde.
Aus sicherheitstechnischer Sicht gibt das Kubernetes-Autorisierungsmodell Cluster-Administratoren die Flexibilität, die Benutzerrechte bei Bedarf zu ändern. Außerdem ist die rollenbasierte Zugriffskontrolle nicht auf einen physischen Benutzer beschränkt; Sie können auch Cluster-Diensten Berechtigungen erteilen und entziehen. Mehr dazu erfahren Sie im nächsten Abschnitt.
Weitere Informationen über die RBAC-Autorisierung und wie Sie benutzerdefinierte Rollen erstellen, finden Sie in der offiziellen Dokumentation.
Schritt 3 – Verwalten von Anwendungsberechtigungen mit Service Accounts
Wie im vorherigen Abschnitt erwähnt, erstrecken sich die RBAC-Autorisierungsmechanismen nicht nur auf menschliche Benutzer. Nicht-menschliche Cluster-Benutzer wie Anwendungen, Dienste und Prozesse, die in Pods ausgeführt werden, authentifizieren sich mit dem API-Server über Dienstkonten, die in Kubernetes *Service Accounts* (SAs) genannt werden. Wenn ein Pod in einem Namensraum erstellt wird, können Sie hierfür entweder das default-Service-Account verwenden oder ein Service Account Ihrer Wahl definieren. Die Möglichkeit, Anwendungen und Prozessen individuelle SAs zuzuordnen, gibt Administratoren die Freiheit, Berechtigungen nach Bedarf zu erteilen oder zu entziehen. Außerdem wird die Zuordnung bestimmter SAs zu produktionskritischen Anwendungen als beste Sicherheitspraxis angesehen. Da Service Accounts für die Authentifizierung und damit für die RBAC-Autorisierungsprüfungen verwendet werden, können Cluster-Administratoren Sicherheitsbedrohungen eindämmen, indem sie die Zugriffsrechte für Service Accounts ändern und den fehlerhaften Prozess isolieren.
Zur Veranschaulichung von Service Accounts verwendet dieses Tutorial einen Nginx-Webserver als Beispielanwendung.
Bevor Sie Ihrer Anwendung ein bestimmtes SA zuweisen, müssen Sie dieses SA erstellen. Erstellen Sie ein neues Service Account namens <^>nginx-sa<^> im default-Namensraum:
kubectl create sa <^>nginx-sa<^>
Sie erhalten Folgendes:
[secondary_label Output]
serviceaccount/<^>nginx-sa<^> created
Überprüfen Sie, ob das Service Account erstellt wurde, indem Sie Folgendes ausführen:
kubectl get sa
Dadurch erhalten Sie eine Liste Ihrer Service Accounts:
[secondary_label Output]
NAME SECRETS AGE
default 1 22h
<^>nginx-sa<^> 1 80s
Nun erteilen Sie dem Service Account <^>nginx-sa<^> eine Rolle. In diesem Beispiel erteilen Sie <^>nginx-sa<^> dieselben Berechtigungen wie dem Benutzer sammy:
kubectl create rolebinding <^>nginx-sa-edit<^> \
--clusterrole=edit \
--serviceaccount=default:<^>nginx-sa<^> \
--namespace=default
Nach der Ausführung erhalten Sie Folgendes:
[secondary_label Output]
rolebinding.rbac.authorization.k8s.io/<^>nginx-sa-edit<^> created
Dieser Befehl verwendet das gleiche Format wie für den Benutzer sammy. Ausgenommen hierbei ist das Flag --serviceaccount=default:nginx-sa, wo Sie das Service Account <^>nginx-sa<^> dem default-Namensraum zuweisen.
Überprüfen Sie mit diesem Befehl, ob die Rollenbindung erfolgreich war:
kubectl get rolebinding
Dadurch erhalten Sie folgendes Output:
[secondary_label Output]
NAME AGE
<^>nginx-sa-edit<^> 23s
Nachdem Sie bestätigt haben, dass die Rollenbindung für das Service Account erfolgreich konfiguriert wurde, können Sie das Service Account einer Anwendung zuweisen. Wenn Sie einer Anwendung ein bestimmtes Service Account zuweisen, können Sie dessen Zugriffsrechte in Echtzeit verwalten und somit die Sicherheit des Clusters erhöhen.
In diesem Tutorial dient ein nginx-Pod als Beispielanwendung. Erstellen Sie den neuen Pod und bestimmen Sie das Service Account <^>nginx-sa<^> mit dem folgenden Befehl:
kubectl run nginx --image=nginx --port 80 --serviceaccount="<^>nginx-sa<^>"
Der erste Teil des Befehls erstellt einen neuen Pod, der einen nginx-Webserver auf Port :80 ausführt. Der zweite Teil --serviceaccount="<^>nginx-sa<^>" zeigt an, dass dieser Pod das <^>nginx-sa<^>-Service-Account und nicht das default-Service-Account verwenden soll.
Sie erhalten ein Output, das dem Folgenden ähnelt:
[secondary_label Output]
deployment.apps/nginx created
Überprüfen Sie mit kubectl describe, ob die neue Anwendung das Service Account verwendet:
kubectl describe deployment nginx
Dadurch erhalten Sie eine längere Beschreibung der Bereitstellungsparameter. Unter dem Abschnitt Pod Template sehen Sie ein Output, das diesem ähnelt:
[secondary_label Output]
...
Pod Template:
Labels: run=nginx
Service Account: <^>nginx-sa<^>
...
In diesem Abschnitt haben Sie das Service Account <^>nginx-sa<^> im default-Namensraum erstellt und dem nginx-Webserver zugewiesen. Sie können nun die nginx-Berechtigungen in Echtzeit steuern, indem Sie seine Rolle nach Bedarf ändern. Sie können Anwendungen auch gruppieren, indem Sie jeder dasselbe Service Account zuweisen und dann Mehrfachänderungen (bulk changes) an Berechtigungen vornehmen. Sie können zudem kritische Anwendungen isolieren, indem Sie diesen ein individuelles SA zuweisen.
Die Idee hinter der Zuweisung von Rollen an Ihre Anwendungen/Bereitstellungen besteht auch darin, eine Feinabstimmung der Berechtigungen vornehmen zu können. In realen Produktivumgebungen haben Sie möglicherweise mehrere Bereitstellungen, die unterschiedliche Berechtigungen erfordern, die von reinen Leseberechtigungen bis hin zu vollen Administratorrechten reichen. Mit RBAC können Sie den Zugriff auf den Cluster flexibel nach Bedarf einschränken.
Als Nächstes richten Sie Zugangs-Controller ein, um Ressourcen zu kontrollieren und gegen übermäßigen Ressourcenverbrauch zu schützen.
Schritt 4 – Einrichten von Zugriffs-Controllern
Die Zugriffs-Controller von Kubernetes sind optionale Plugins, die in das kube-apiserver-Binärprogramm kompiliert werden, um die Sicherheitsoptionen zu erweitern. Zugriffs-Controller fangen Anfragen ab, nachdem diese die Authentifizierungs- und Autorisierungsphase durchlaufen haben. Nach dem Abfangen der Anfrage führen die Zugriffs-Controller den jeweils festgelegten Code aus, bevor die Anfrage ausgeführt wird.
Während das Ergebnis einer Authentifizierungs- oder Autorisierungsprüfung ein boolescher Wahr-oder-Falsch-Wert ist, der die Anfrage entweder erlaubt oder ablehnt, können Zugriffs-Controller wesentlich vielfältiger agieren. Zugriffs-Controller können Anfragen in gleicher Weise wie eine Authentifizierung validieren. Sie können jedoch auch zusätzlich Anfragen *mutieren* und ändern sowie Objekte modifizieren, bevor diese zugelassen werden.
In diesem Schritt verwenden Sie die Zugriffs-Controller ResourceQuota und LimitRange. Diese schützen Ihren Cluster, indem Sie Anfragen, die zu einem übermäßigen Ressourcenverbrauch oder einem Denial-of-Service-Angriff führen können, mutieren. Der Zugriffs-Controller ResourceQuota ermöglicht Administratoren, die Rechnerressourcen, die Speicherressourcen und die Quantität jedes Objekts in einem Namensraum zu beschränken. Der Zugriffs-Controller LimitRange beschränkt die Anzahl der von Containern verwendeten Ressourcen. Die gleichzeitige Verwendung dieser beiden Zugriffs-Controller schützt Ihren Cluster vor Angriffen, durch die Ihre Ressourcen nicht mehr verfügbar wären.
Um zu zeigen, wie ResourceQuota funktioniert, implementieren Sie nun einige Beschränkungen im default-Namensraum. Beginnen Sie mit dem Erstellen einer neuen ResourceQuota-Objektdatei:
nano <^>resource-quota-default<^>.yaml
Fügen Sie die folgende Objektdefinition hinzu, um Beschränkungen für den Ressourcenverbrauch im default-Namensraum festzulegen. Sie können die Werte entsprechend der physischen Ressourcen Ihrer Knoten nach Bedarf anpassen:
[label resource-quota-default.yaml]
apiVersion: v1
kind: ResourceQuota
metadata:
name: <^>resource-quota-default<^>
spec:
hard:
pods: "<^>2<^>"
requests.cpu: "<^>500m<^>"
requests.memory: <^>1Gi<^>
limits.cpu: "<^>1000m<^>"
limits.memory: <^>2Gi<^>
configmaps: "<^>5<^>"
persistentvolumeclaims: "<^>2<^>"
replicationcontrollers: "<^>10<^>"
secrets: "<^>3<^>"
services: "<^>4<^>"
services.loadbalancers: "<^>2<^>"
Diese Definition verwendet das Schlüsselwort hard, um harte Beschränkungen wie z. B. die maximale Anzahl von pods, configmaps, PersistentVolumeClaims, ReplicationControllers, secrets, services und loadbalancers festzulegen. Sie setzt auch Beschränkungen für Rechnerressourcen wie:
requests.cpu, das den maximalen CPU-Wert von Anfragen in *milliCPU* oder einem Tausendstel eines CPU-Kerns festlegt.
requests.memory, das den maximalen Speicherwert von Anfragen in Bytes festlegt.
limits.cpu, das den maximalen CPU-Wert von Limits in milliCPUs festlegt.
limits.memory, das den maximalen Speicherwert von Limits in Bytes festlegt.
Speichern und schließen Sie die Datei.
Erstellen Sie nun mit dem folgenden Befehl das Objekt im Namensraum:
kubectl create -f <^>resource-quota-default.yaml<^> --namespace=default
Dadurch erhalten Sie:
[secondary_label Output]
resourcequota/<^>resource-quota-default<^> created
Beachten Sie, dass Sie das Flag -f verwenden, um Kubernetes den Speicherort der ResourceQuota-Datei anzuzeigen, sowie das Flag --namespace, um anzugeben, welcher Namensraum aktualisiert wird.
Nach dem Erstellen des Objekts ist Ihr ResourceQuota aktiv. Sie können die default-Namensraumquoten mit describe quota prüfen:
kubectl describe quota --namespace=default
Das Output sieht dem Folgenden ähnlich; mit den harten Limits, die Sie in der Datei <^>resource-quota-default<^>.yaml festgelegt haben:
[secondary_label Output]
Name: <^>resource-quota-default<^>
Namespace: default
Resource Used Hard
-------- ---- ----
configmaps 0 <^>5<^>
limits.cpu 0 <^>1<^>
limits.memory 0 <^>2Gi<^>
persistentvolumeclaims 0 <^>2<^>
pods 1 <^>2<^>
replicationcontrollers 0 <^>10<^>
requests.cpu 0 <^>500m<^>
requests.memory 0 <^>1Gi<^>
secrets 2 <^>3<^>
services 1 <^>4<^>
services.loadbalancers 0 <^>2<^>
ResourceQuotas werden in absoluten Einheiten ausgedrückt. Daher erhöht das Hinzufügen zusätzlicher Knoten nicht automatisch die hier definierten Werte. Wenn weitere Knoten hinzugefügt werden, müssen Sie die Werte hier manuell bearbeiten, um die Ressourcen zu proportionieren. ResourceQuotas können so oft wie nötig modifiziert werden. Sie können jedoch nicht entfernt werden, es sei denn, der gesamte Namensraum wird entfernt.
Wenn Sie einen bestimmten ResourceQuota-Controller ändern möchten, aktualisieren Sie die entsprechende .yaml-Datei und wenden Sie die Änderungen mit dem folgenden Befehl an:
kubectl apply -f <^>resource-quota-default<^>.yaml --namespace=default
Weitere Informationen über den Zugriffs-Controller ResourceQuota finden Sie in der offiziellen Dokumentation.
Nachdem Ihr ResourceQuota nun eingerichtet ist, fahren Sie mit der Konfiguration des Zugriffs-Controllers LimitRange fort. Ähnlich wie der Controller ResourceQuota Limits für Namensräume umsetzt, setzt der Controller LimitRange die durch Validierung und Mutation von Containern deklarierten Beschränkungen durch.
Wie zuvor beginnen Sie mit dem Erstellen der Objektdatei:
nano <^>limit-range-default<^>.yaml
Nun können Sie mit dem LimitRange-Objekt den Ressourcenverbrauch nach Bedarf beschränken. Fügen Sie folgenden Inhalt als Beispiel eines typischen Anwendungsfalls hinzu:
[label limit-ranges-default.yaml]
apiVersion: v1
kind: LimitRange
metadata:
name: <^>limit-range-default<^>
spec:
limits:
- max:
cpu: "<^>400m<^>"
memory: "<^>1Gi<^>"
min:
cpu: "<^>100m<^>"
memory: "<^>100Mi<^>"
default:
cpu: "<^>250m<^>"
memory: "<^>800Mi<^>"
defaultRequest:
cpu: "<^>150m<^>"
memory: "<^>256Mi<^>"
type: Container
Die in <^>limit-ranges-default<^>.yaml verwendeten Beispielwerte beschränken den Containerspeicher auf ein Maximum von 1Gi und die CPU-Nutzung auf ein Maximum von 400 m, was einer Kubernetes-Metrik von 400 milliCPU entspricht und bedeutet, dass der Container auf nahezu die Hälfte seines Kerns beschränkt ist.
Als Nächstes stellen Sie das Objekt mit dem folgenden Befehl für den API-Server bereit:
kubectl create -f <^>limit-range-default<^>.yaml --namespace=default
Dadurch erhalten Sie folgendes Output:
[secondary_label Output]
limitrange/<^>limit-range-default<^> created
Nun können Sie die neuen Limits mit dem folgenden Befehl überprüfen:
kubectl describe limits --namespace=default
Das Output sieht ungefähr wie folgt aus:
[secondary_label Output]
Name: <^>limit-range-default<^>
Namespace: default
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container cpu <^>100<^>m <^>400<^>m <^>150<^>m <^>250<^>m -
Container memory <^>100<^>Mi <^>1<^>Gi <^>256<^>Mi <^>800<^>Mi -
Um den LimitRanger arbeiten zu sehen, stellen Sie einen Standard-nginx-Container mit dem folgenden Befehl bereit:
kubectl run nginx --image=nginx --port=80 --restart=Never
Dadurch erhalten Sie folgendes Output:
[secondary_label Output]
pod/nginx created
Überprüfen Sie, wie der Zugriffs-Controller den Container mutiert hat, indem Sie folgenden Befehl ausführen:
kubectl get pod nginx -o yaml
Dadurch erhalten Sie viele Zeilen an Output. Im Abschnitt der Container-Spezifizierung finden Sie die im LimitRange angegebenen Ressourcenlimits:
[secondary_label Output]
...
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
ports:
- containerPort: 80
protocol: TCP
<^>resources:<^>
<^>limits:<^>
<^>cpu: 250m<^>
<^>memory: 800Mi<^>
<^>requests:<^>
<^>cpu: 150m<^>
<^>memory: 256Mi<^>
...
Dies wäre genauso, wenn Sie die Angaben für resources und requests manuell in der Container-Spezifikation festlegen würden.
In diesem Schritt haben Sie die Zugriffs-Controller ResourceQuota und LimitRange verwendet, um die Ressourcen Ihres Clusters vor schädlichen Angriffen zu schützen. Weitere Informationen über den Zugriffs-Controller LimitRange finden Sie in der offiziellen Dokumentation.
Zusammenfassung
In diesem Tutorial haben Sie eine grundlegende Kubernetes-Sicherheitsvorlage konfiguriert. Dadurch wurden die Benutzerauthentifizierung und -autorisierung, die Anwendungsberechtigungen und der Schutz der Cluster-Ressourcen bestimmt. Wenn Sie alle in diesem Tutorial behandelten Vorschläge kombinieren, haben Sie eine solide Grundlage für den Einsatz eines Kubernetes-Clusters in einer produktiven Umgebung. Nun können Sie beginnen, individuelle Aspekte Ihres Clusters je nach Ihrer Vorstellung zu härten.
Wenn Sie mehr über Kubernetes erfahren möchten, besuchen Sie unsere Kubernetes-Ressourcenseite oder folgen Sie dem selbstgeführten Kurs Kubernetes für umfassende Entwickler.