Benutzerdefinierte Cloud-init-Initialisierungsskripte für die Einrichtung verwalteter Knoten verwenden

Erfahren Sie, wie Sie benutzerdefinierte cloud-init-Skripte schreiben, die auf Worker-Knoten in Clustern ausgeführt werden, die Sie mit der Kubernetes Engine (OKE) erstellt haben.

Cloud-init ist die branchenübliche Methode für die Initialisierung von Cloud-Instanzen, die Bereitstellung von Systemen für die private Cloud-Infrastruktur und Bare-Metal-Installationen. Er wird von allen wichtigen Public Cloud-Providern unterstützt, einschließlich Oracle Cloud Infrastructure (siehe Benutzerdaten). Cloud-init führt Skripte aus, um Instanzen zu initialisieren und zu konfigurieren. Weitere Informationen zu cloud-init finden Sie in der cloud-init-Dokumentation.

Kubernetes Engine verwendet cloud-init, um die Compute-Instanzen einzurichten, die verwaltete Knoten hosten. Kubernetes Engine installiert ein Standardstartskript auf jeder Instanz, die einen verwalteten Knoten hostet. Wenn die Instanz zum ersten Mal hochgefahren wird, führt cloud-init das Standardstartskript aus. Das Standardstartskript enthält die folgende von der Kubernetes-Engine bereitgestellte Logik:

#!/bin/bash
curl --fail -H "Authorization: Bearer Oracle" -L0 http://169.254.169.254/opc/v2/instance/metadata/oke_init_script | base64 --decode >/var/run/oke-init.sh
bash /var/run/oke-init.sh

Sie können das Standardstartskript anpassen, indem Sie dem Skript Ihre eigene Logik vor oder nach der Standardlogik hinzufügen. Wenn Sie das Standardstartskript anpassen, können Sie beispielsweise:

  • SELinux-Policy auf allen Worker-Knotenhosts zu Sicherheits- und Compliancezwecken konfigurieren
  • Zuweisung der ephemeren öffentlichen IP einer Instanz beim Hochfahren aufheben und der Instanz stattdessen eine reservierte öffentliche IP neu zuweisen
  • Unternehmensproxy konfigurieren
  • Benutzerdefinierte yum-Proxys konfigurieren
  • Installation von vorgeschriebener Antivirensoftware und anderen Sicherheitstools

Wenn Sie das Standardstartskript anpassen, ändern Sie die von der Kubernetes-Engine bereitgestellte Logik nicht.

Sie können das Standardstartskript anpassen, wenn Sie ein neues Cluster erstellen, neue Knotenpools erstellen und vorhandene Knotenpools ändern:

  • mit der Konsole (verwenden Sie beim Erstellen eines neuen Clusters den Workflow "Benutzerdefinierte Erstellung")
  • Mit der CLI
  • API verwenden

Das benutzerdefinierte Startskript wird ausgeführt, wenn eine Instanz, die einen Worker-Knoten hostet, zum ersten Mal hochfährt. Nachdem Sie das Standardstartskript angepasst haben, sollten Sie das Node Doctor-Skript ausführen, um zu bestätigen, dass die Worker-Knoten auf neu gestarteten Instanzen wie erwartet funktionieren (siehe Knotenprobleme für Kubernetes-Cluster mit dem Node Doctor-Skript beheben).

Beispielanwendungsfälle für benutzerdefinierte Cloud-init-Skripte

Beispiel 1: Verwenden eines benutzerdefinierten Cloud-init-Skripts zur Konfiguration von SELinux (Security-Enhanced Linux) auf verwalteten Knoten

Sie können ein benutzerdefiniertes cloud-init-Skript verwenden, um SELinux auf verwalteten Knoten zu konfigurieren. SELinux ist eine Sicherheitsverbesserung für Linux, mit der Administratoren einschränken können, welche Benutzer und Anwendungen auf welche Ressourcen basierend auf Regeln in einer Policy zugreifen können. Mit SELinux wird auch eine feinere Granularität für Zugriffskontrollen hinzugefügt.

SELinux kann einen von zwei Status aufweisen (aktiviert oder deaktiviert). Wenn sie aktiviert ist, kann SELinux in einem von zwei Modi ausgeführt werden, entweder durchgesetzt oder permissiv.

Standardmäßig ist SELinux aktiviert und auf Worker-Knoten im Permissive-Modus ausgeführt. Bei der Ausführung im Permissive-Modus erzwingt SELinux keine Zugriffsregeln und führt nur das Logging aus.

Wenn Sie möchten, dass SELinux Zugriffsregeln durchsetzt, können Sie festlegen, dass sie im Erzwingungsmodus ausgeführt wird. Bei der Ausführung im Durchsetzungsmodus blockiert SELinux Aktionen, die der Policy widersprechen, und protokolliert ein entsprechendes Ereignis im Auditlog.

Um die Ausführung von SELinux im Erzwingungsmodus festzulegen, verwenden Sie das folgende cloud-init-Skript:

#!/bin/bash
curl --fail -H "Authorization: Bearer Oracle" -L0 http://169.254.169.254/opc/v2/instance/metadata/oke_init_script | base64 --decode >/var/run/oke-init.sh
bash /var/run/oke-init.sh
setenforce 1
sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config 

Um den Status und Modus von SELinux zu bestätigen, der auf einem Worker-Knoten ausgeführt wird, stellen Sie eine Verbindung zum Worker-Knoten her, und verwenden Sie den Befehl getenforce. Wenn das obige cloud-init-Skript auf Worker-Knoten ausgeführt wurde, gibt der Befehl getenforce Enforcing zurück.

Beispiel 2: Benutzerdefiniertes Cloud-init-Skript zum Festlegen von NodeLocal DNSCache auf verwalteten Knoten verwenden

Sie können ein benutzerdefiniertes cloud-init-Skript verwenden, um NodeLocal DNSCache auf verwalteten Knoten zu konfigurieren. NodeLocal DNSCache verbessert die Cluster-DNS-Performance, indem ein DNS-Caching-Agent auf Worker-Knoten als Daemonset ausgeführt wird.

Wenn NodeLocal DNSCache nicht aktiviert ist, greifen Pods im DNS-Modus ClusterFirst bei DNS-Abfragen auf kube-dns serviceIP zu. Mit iptables-Regeln wird diese Anforderung in einen von kube-proxy hinzugefügten kube-dns/CoreDNS-Endpunkt übersetzt. Weitere Informationen finden Sie unter DNS für Services und Pods in der Kubernetes-Dokumentation.

Wenn NodeLocal DNSCache aktiviert ist, wenden sich Pods an einen DNS-Caching-Agent, der auf demselben Worker-Knoten ausgeführt wird. Dadurch können sie iptables-DNAT-Regeln und das Verbindungstracking umgehen. Der lokale Caching-Agent fragt den Service kube-dns/CoreDNS auf Cachefehlschläge von Clusterhostnamen ab (Standardsuffix cluster.local).

Um NodeLocal DNSCache zu konfigurieren, verwenden Sie das folgende cloud-init-Skript. Ersetzen Sie CLUSTER DNS durch eine lokale Listening-IP-Adresse, die nicht mit irgendetwas im Cluster kollidiert. Es gibt einen empfohlenen lokalen Linkbereich von 169.254.0.0/16 für IPv4 oder aus dem eindeutigen lokalen Adressbereich von fd00::/8 für IPv6.

#!/bin/bash
curl --fail -H "Authorization: Bearer Oracle" -L0 http://169.254.169.254/opc/v2/instance/metadata/oke_init_script | base64 --decode >/var/run/oke-init.sh
bash /var/run/oke-init.sh --cluster-dns "[CLUSTER DNS]"

Um zu bestätigen, dass NodeLocal DNSCache erfolgreich bereitgestellt wurde, stellen Sie eine Verbindung zu einem Worker-Knoten her, und verwenden Sie den Befehl sudo systemctl status -l kubelet. Wenn das obige cloud-init-Skript auf Worker-Knoten ausgeführt wurde, gibt der Befehl sudo systemctl status -l kubelet --cluster-dns als eines der Kubelet-Flags zurück, das auf eine lokale Standardlinkadresse gesetzt ist (z.B. 169.254.20.10).

Nachdem Sie Knoten mit dem obigen cloud-init-Skript erstellt haben, stellen Sie den DNS-Caching-Agent bereit, indem Sie die Schritte unter NodeLocal DNSCache in Kubernetes-Clustern verwenden in der Kubernetes-Dokumentation ausführen. Nach der Aktivierung wird ein Pod "node-local-dns" im Namespace "kube-system" auf jedem der Clusterknoten ausgeführt. Der Pod node-local-dns führt CoreDNS im Cachemodus aus, sodass alle CoreDNS-Metriken, die von den verschiedenen Plug-ins bereitgestellt werden, auf Knotenbasis verfügbar sind.

Um die DNS-Auflösung zu testen, verwenden Sie einen oder mehrere der folgenden Befehle (siehe DNS-Auflösung debuggen in der Kubernetes-Dokumentation). Die Befehle sollten beide funktionieren und auch die IP-Adresse ausgeben, die mit dem Flag --cluster-dns im benutzerdefinierten cloud-init-Skript festgelegt wurde:

kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
kubectl exec -it dnsutils – nslookup kubernetes.default
kubectl exec -it dnsutils – cat /etc/resolv.conf

Sie können die Datei NodeLocal DNSCache deaktivieren, indem Sie das Daemonset entfernen und das nodelocaldns-Manifest löschen. Sie sollten auch alle Änderungen rückgängig machen, die Sie an der Kubelet-Konfiguration vorgenommen haben.

Beispiel 3: Benutzerdefiniertes Cloud-init-Skript zum Festlegen von kubelet-extra-args auf verwalteten Knoten verwenden

Mit einem benutzerdefinierten Cloud-Init-Skript können Sie eine Reihe zusätzlicher Optionen im Kubelet (dem primären Knoten-Agent) auf verwalteten Knoten konfigurieren. Diese zusätzlichen Optionen werden manchmal als kubelet-extra-args bezeichnet. Mit den Optionen kubelet-extra-args können Sie unter anderem:

  • Ausführlichkeit von Debug-Level-Logs konfigurieren
  • Knotenflecken verwenden, um Planungs-Policys durchzusetzen

Verwendung von kubelet-extra-args zur Konfiguration des Ausführlichkeitsgrads von Debug-Level-Logs:

Um den Ausführlichkeitsgrad des Logs auf Debug-Ebene zu konfigurieren, verwenden Sie das folgende cloud-init-Skript:

#!/bin/bash
curl --fail -H "Authorization: Bearer Oracle" -L0 http://169.254.169.254/opc/v2/instance/metadata/oke_init_script | base64 --decode >/var/run/oke-init.sh
bash /var/run/oke-init.sh --kubelet-extra-args "--v=4"

Um die Einstellung der Ausführlichkeit von Log auf Debug-Ebene zu bestätigen, stellen Sie eine Verbindung zu einem Worker-Knoten her und verwenden den Befehl sudo systemctl status -l kubelet. Wenn das obige cloud-init-Skript auf Worker-Knoten ausgeführt wurde, gibt der Befehl sudo systemctl status -l kubelet die Ausführlichkeitsstufe als 4 zurück. Die Kubelet-Logs enthalten auch weitere Details.

Knoten-Taints mit kubelet-extra-args hinzufügen:

Um Knotentaints hinzuzufügen, um Planungs-Policys durchzusetzen, verwenden Sie das folgende cloud-init-Skript:

#!/bin/bash
curl --fail -H "Authorization: Bearer Oracle" -L0 http://169.254.169.254/opc/v2/instance/metadata/oke_init_script | base64 --decode >/var/run/oke-init.sh
bash /var/run/oke-init.sh --kubelet-extra-args "--register-with-taints=mytaint1=true:NoSchedule,mytaint2=true:NoSchedule"

Nur Pods, die eine Toleranz für beide Taints aufweisen (der mytaint1=true:NoSchedule-Taint und der mytaint2=true:NoSchedule-Taint), werden für die Ausführung auf dem Worker-Knoten geplant.

Beispiel 4: Ressourcen für Kubernetes- und Betriebssystem-Daemons mit einem benutzerdefinierten Cloud-init-Skript reservieren

Sie können ein benutzerdefiniertes Cloud-init-Skript verwenden, um CPU- und Speicherressourcen für Kubernetes-System-Daemons (wie kubelet und container runtime) und BS-System-Daemons (wie sshd und systemd) zu reservieren. Um Ressourcen für die Kubernetes- und BS-System-Daemons zu reservieren, nehmen Sie die Kubelet-Flags --kube-reserved bzw. --system-reserved als kubelet-extra-args-Optionen in ein benutzerdefiniertes Cloud-init-Skript auf.

Um Ressourcen für die Kubernetes- und BS-System-Daemons zu reservieren, verwenden Sie das folgende cloud-init-Skript:

#!/bin/bash
curl --fail -H "Authorization: Bearer Oracle" -L0 http://169.254.169.254/opc/v2/instance/metadata/oke_init_script | base64 --decode >/var/run/oke-init.sh
bash /var/run/oke-init.sh --kubelet-extra-args "--kube-reserved=cpu=500m,memory=1Gi --system-reserved=cpu=100m,memory=100Mi"

Weitere Informationen und empfohlene Werte für die Kubelet-Flags --kube-reserved und --system-reserved finden Sie unter Best Practice: Ressourcen für Kubernetes- und BS-System-Daemons reservieren.

Beispiel 5: Mit einem benutzerdefinierten Cloud-init-Skript und oci-growfs die Größe der Boot-Volume-Partition erhöhen

Sie können ein benutzerdefiniertes cloud-init-Skript verwenden, um die Partition für das Boot-Volume verwalteter Knoten zu erweitern. Wenn Sie Cluster und Knotenpools erstellen und aktualisieren, können Sie eine benutzerdefinierte Größe für Boot-Volumes von Worker-Knoten angeben. Die von Ihnen angegebene benutzerdefinierte Boot-Volume-Größe muss größer als die Standardgröße des Boot-Volumes des ausgewählten Images sein. Wenn Sie die Größe des Boot-Volumes erhöhen, um die größere Boot-Volume-Größe zu nutzen, müssen Sie auch die Partition für das Boot-Volume erweitern.

Oracle Linux-Plattformimages umfassen das Package oci-utils. Sie können den Befehl oci-growfs aus diesem Package in einem cloud-init-Skript verwenden, um die Root-Partition zu erweitern und das Dateisystem dann zu vergrößern.

Um die Partition für das Boot-Volume zu erweitern, verwenden Sie das folgende cloud-init-Skript:

#!/bin/bash
curl --fail -H "Authorization: Bearer Oracle" -L0 http://169.254.169.254/opc/v2/instance/metadata/oke_init_script | base64 --decode >/var/run/oke-init.sh
bash /usr/libexec/oci-growfs -y
bash /var/run/oke-init.sh

Weitere Informationen finden Sie unter Die Partition für ein Boot-Volume erweitern.

Benutzerdefiniertes Cloud-init-Skript erstellen

So passen Sie das standardmäßige Cloud-init-Startskript an, das Kubernetes Engine bereitstellt:

  1. Erstellen Sie eine neue Skriptdatei mit der von Kubernetes Engine bereitgestellten Standardlogik. Dazu gibt es zwei Möglichkeiten:
    • Indem Sie die Option Benutzerdefinierte Cloud-Init-Skriptvorlage herunterladen (im Abschnitt Erweiterte Optionen des Knotenpools) auswählen, wenn Sie das Dialogfeld Benutzerdefiniertes Cluster erstellen, Knotenpool hinzufügen oder Knotenpool bearbeiten verwenden. Die heruntergeladene Datei enthält die Standardlogik.
    • Indem Sie eine neue Datei von Grund auf mit einem Dateityp erstellen, der von cloud-init (wie .yaml) unterstützt wird, und die von Kubernetes Engine bereitgestellte Standardlogik hinzufügen. Beispiel:
      #!/bin/bash
      curl --fail -H "Authorization: Bearer Oracle" -L0 http://169.254.169.254/opc/v2/instance/metadata/oke_init_script | base64 --decode >/var/run/oke-init.sh
      bash /var/run/oke-init.sh
  2. Fügen Sie der Skriptdatei entweder vor oder nach der von der Kubernetes-Engine bereitgestellten Standardlogik Ihre eigene benutzerdefinierte Logik hinzu. Ändern Sie die Standardlogik nicht.

    Beispiel: Um Logverbosity auf Debug-Ebene zu konfigurieren, können Sie --kubelet-extra-args "--v=4" hinzufügen, sodass die Datei wie folgt aussieht:

    #!/bin/bash
    curl --fail -H "Authorization: Bearer Oracle" -L0 http://169.254.169.254/opc/v2/instance/metadata/oke_init_script | base64 --decode >/var/run/oke-init.sh
    bash /var/run/oke-init.sh --kubelet-extra-args "--v=4"

    Weitere Beispiele finden Sie unter Beispielanwendungsfälle für benutzerdefinierte Cloud-init-Skripte.

  3. Speichern Sie die von Ihnen erstellte benutzerdefinierte cloud-init-Skriptdatei.
  4. Geben Sie die benutzerdefinierte cloud-init-Skriptdatei an, wenn Sie ein neues Cluster erstellen, einen neuen Knotenpool hinzufügen oder einen vorhandenen Knotenpool ändern:

Konsole verwenden

So stellen Sie mit der Konsole ein benutzerdefiniertes cloud-init-Skript für Instanzen bereit, die verwaltete Knoten in einem neuen Cluster, einem neuen Knotenpool oder einem vorhandenen Knotenpool hosten:

  1. Erstellen Sie eine gültige cloud-init-Datei in einem der Formate (z.B. cloud-config) und Dateitypen (z.B. eine YAML-Datei), die von cloud-init unterstützt werden. Siehe Benutzerdefiniertes Cloud-init-Skript erstellen.
  2. Öffnen Sie das Navigationsmenü , und wählen Sie Entwicklerservices aus. Wählen Sie unter Container und Artefakte die Option Kubernetes-Cluster (OKE) aus.
  3. Wählen Sie ein Compartment aus, für das Sie eine Berechtigung besitzen.
  4. Erstellen Sie ein neues Cluster mit dem Workflow "Benutzerdefinierte Erstellung", oder fügen Sie einem vorhandenen Cluster einen neuen Knotenpool hinzu, oder ändern Sie einen vorhandenen Knotenpool.
  5. Geben Sie im Abschnitt Erweiterte Optionen des Knotenpools im Dialogfeld Benutzerdefiniertes Cluster erstellen, Knotenpool hinzufügen oder Knotenpool bearbeiten (je nach Bedarf) Folgendes an:
    • Initialisierungsskript: (Optional) Ein Skript für die Ausführung von cloud-init auf jeder Instanz, die Worker-Knoten hostet, wenn die Instanz zum ersten Mal hochgefahren wird. Das angegebene Skript muss in einem der von cloud-init unterstützten Formate geschrieben werden (z.B. cloud-config) und muss ein unterstützter Dateityp sein (z.B. .yaml). Geben Sie das Skript folgendermaßen an:
      • Cloud-Init-Skript auswählen: Wählen Sie eine Datei mit dem cloud-init-Skript aus, oder ziehen Sie die Datei per Drag-and-Drop in das Feld.
      • Cloud-Init-Skript einfügen: Kopieren Sie den Inhalt eines cloud-init-Skripts, und fügen Sie ihn in das Feld ein.

      Wenn Sie noch keine Cloud-Init-Skripte zum Initialisieren von Worker-Knoten in Clustern geschrieben haben, die von der Kubernetes Engine erstellt wurden, ist es möglicherweise hilfreich, die Option Benutzerdefinierte Cloud-Init-Skriptvorlage herunterladen auszuwählen. Die heruntergeladene Datei enthält die Standardlogik, die von Kubernetes Engine bereitgestellt wird. Sie können Ihre eigene benutzerdefinierte Logik entweder vor oder nach der Standardlogik hinzufügen, aber die Standardlogik nicht ändern. Beispiele finden Sie unter Beispielanwendungsfälle für benutzerdefinierte Cloud-init-Skripte.

Mit der CLI

Informationen zur Verwendung der CLI finden Sie unter Befehlszeilenschnittstelle (CLI). Eine vollständige Liste der Flags und Optionen, die für CLI-Befehle verfügbar sind, finden Sie in der Befehlszeilenreferenz.

So stellen Sie mit der CLI ein benutzerdefiniertes Cloud-Init-Skript für Instanzen bereit, die Worker-Knoten in einem neuen Knotenpool oder in einem vorhandenen Knotenpool hosten:

  1. Erstellen Sie eine gültige cloud-init-Datei in einem der Formate (z.B. cloud-config) und Dateitypen (z.B. eine YAML-Datei), die von cloud-init unterstützt werden. Siehe Benutzerdefiniertes Cloud-init-Skript erstellen.
  2. Öffnen Sie eine Eingabeaufforderung, und geben Sie einen der folgenden Befehle ein, um einen neuen Knotenpool zu erstellen, oder aktualisieren Sie gegebenenfalls einen vorhandenen Knotenpool:
    • oci ce node-pool create
    • oci ce node-pool update
  3. Neben den obligatorischen Parametern, die für den von Ihnen verwendeten Befehl erforderlich sind:
    1. Nehmen Sie den Parameter --node-image-id auf, auch wenn Sie kein benutzerdefiniertes Image angeben möchten.
    2. Nehmen Sie den optionalen Parameter --node-metadata in folgendem Format auf:
      --node-metadata '{"user_data": "'$(cat <cloud-init-file> | base64)'"}'
      Hierbei gilt:
      • <cloud-init-file> ist der Name der von Ihnen erstellten cloud-init-Datei.
      • base64 gibt an, dass die Datei base64-codiert werden soll.

      Beispiel:

      --node-metadata '{"user_data": "'$(cat my-custom-cloud-init.yaml | base64)'"}'

Beispiel

Mit diesem Beispielbefehl wird ein neuer Knotenpool mit dem Namen my-cloud-init-test-nodepool für ein vorhandenes Cluster mit einem einzelnen Kubernetes 1.18.10-Knoten erstellt, der eine VM 2.1-Ausprägung mit Oracle Linux aufweist. Wenn die Instanz, die den Worker-Knoten im neuen Knotenpool hostet, zum ersten Mal hochgefahren wird, wird ein benutzerdefiniertes Cloud-Init-Skript namens my-custom-cloud-init.yaml ausgeführt:

oci ce node-pool create \
--cluster-id ocid1.cluster.oc1.iad.aaaa______m4w \
--name my-cloud-init-test-nodepool \
--node-image-id ocid1.image.oc1.iad.aaaa______zpq \
--compartment-id ocid1.tenancy.oc1..aaa______q4a \
--kubernetes-version v1.18.10 \
--node-shape VM.Standard2.1 \
--placement-configs "[   { \"availabilityDomain\": \"PKGK:US-ASHBURN-AD-1\", \"subnetId\": \"ocid1.subnet.oc1.iad.aaaa______kfa\"   }   ]" \
--size 1 \
--region us-ashburn-1 \
--node-metadata '{"user_data": "'$(cat my-custom-cloud-init.yaml | base64)'"}'