Neuigkeiten von trion.
Immer gut informiert.

Kubernetes Mutating Admission Controller

Kubernetes ist flexibel um neue Funktionalität erweiterbar: Dabei gibt es neben CRDs (Custom Resource Definitions), mit denen die Kubernetes API um neue Typen und Operationen erweitert wird, auch Admission Controller. Admission Controller können dazu dienen, bestimmte Vorgaben einzuhalten. Beispielsweise, dass stets Ressourcen-Limits und -Requests spezifiziert werden. Wird dann ein Objekt angelegt, bei dem die Vorgaben nicht eingehalten werden, kann die Erzeugung abgelehnt werden.

Um das Konzept der Admission Controller zu veranschaulichen werden in einer kleinen Artikelserie die Grundlagen und die Umsetzung eines Beispiel-Mutating Admission Controllers mit Python vorgestelt.

Validating Admission Controller können lediglich ein Veto einlegen, und damit unerwünschte Objektinstanzen verhindern. Daneben gibt es noch die Mutating Admission Controller, die auf die Ausgestaltung eines Objektes Einfluss nehmen können.

Aus der Programmierung kennt man dieses Konstrukt als Interceptor um Querschnittsaspekte zu implementieren. Kubernetes bietet als Umsetzung der Admission Controller zwei Varianten an, einmal als regulärer Controller und einmal als Webhook.
Letztere haben den Vorteil, dass diese nicht als Teil des kube-apiserver kompiliert werden müssen und ihre Konfiguration auch noch nach dem Start des Kubernetes API Servers erfolgen kann.

Ansonsten ist der Ablauf vergleichbar: Das zu erzeugende Objekt wird als AdmissionReview Anfrage an den Webhook geschickt. Da durch einen Admission Controller sehr umfangreiche Eingriffe möglich sind, muss bei einem Remote-Dienst sichergestellt sein, dass die Kommunikation abgesichert ist. Dazu wird eine TLS gesicherte HTTP Verbindung vorgeschrieben, wobei das zu verwendende CA Zertifikat pro Admission Controller individuell konfiguriert werden kann. Alternativ werden die System-CA-Zertifikate verwendet.

Der Admission Controller Antwortet dann mit einer Admission Response, die bestimmt, ob und wie ein Request durch Kubernetes umgesetzt wird. Kubernetes arbeitet dabei der Reihe nach registrierte Admission Controller ab, so dass komplexere Anforderungen auf mehrere Admission Controller aufgeteilt werden können.

Um die Admission-Request-Anfrage mit der Antwort des Webhook zu korrelieren, wird im Feld uid eine Korrelations-ID mitgeliefert. Diese ID muss in der Antwort entsprechend auf den selben Wert wie in der Anfrage gesetzt sein.

Der Request beinhaltet weitere Metadaten, wie die Resource, mit der gearbeitet werden soll, die auszuführende Operation und welcher User die API-Anfrage ausgelöst hat. Unter dem Property object findet sich der Inhalt der ursprünglichen API-Anfrage.

Beispiel einer Anfrage an einen Admission Controller
{
   "kind":"AdmissionReview",
   "apiVersion":"admission.k8s.io/v1beta1",
   "request":{
      "uid":"23be6d67-6541-11e9-8bfc-001e063605c7",
      "kind":{
         "group":"batch",
         "version":"v1",
         "kind":"Job"
      },
      "resource":{
         "group":"batch",
         "version":"v1",
         "resource":"jobs"
      },
      "namespace":"drone",
      "operation":"CREATE",
      "userInfo":{
         "username":"kubernetes-admin",
         "groups":[
            "system:masters",
            "system:authenticated"
         ]
      },
      "object":{
         "kind":"Job",
         "apiVersion":"batch/v1",
         "metadata":{
            "name":"demo",
            "creationTimestamp":null,
            "labels":{
               "run":"demo"
            }
         },
         "spec":{
            "parallelism":1,
            "completions":1,
            "backoffLimit":6,
            "template":{
               "metadata":{
                  "creationTimestamp":null,
                  "labels":{
                     "run":"demo"
                  }
               },
               "spec":{
                  "containers":[
                     {
                        "name":"demo",
                        "image":"nginx",
                        "resources":{ },
                        "terminationMessagePath":"/dev/termination-log",
                        "terminationMessagePolicy":"File",
                        "imagePullPolicy":"Always"
                     }
                  ],
                  "restartPolicy":"OnFailure",
                  "terminationGracePeriodSeconds":30,
                  "dnsPolicy":"ClusterFirst",
                  "securityContext":{ },
                  "schedulerName":"default-scheduler"
               }
            }
         },
         "status":{ }
      },
      "oldObject":null,
      "dryRun":false
   }
}

Als Antwort muss ein Admission Controller Webhook ebenfalls eine JSON-Repräsentation liefern, die eine Admission Response beinhaltet. Bei Validating Admission Controllern ist die Antwort sehr einfach: Es gibt die zur Korrelation mit der Anfrage eingesetzte uid und das Property allowed mit den möglichen Ausprägungen true und false.

Beispiel einer Validating Admission Response
{
   "response":{
      "allowed":true,
      "uid":"23be6d67-6541-11e9-8bfc-001e063605c7"
   }
}

Wird hingegen ein Mutating Admission Controller verwendet, so kann dieser noch zusätzlich Veränderungen, die sich auf den inhalt der API-Anfrage beziehen, liefern. Typischerweise werden diese Änderungen als JSON-Patch übermittelt.

Beispiel einer Mutating Admission Response mit JSON Patch
{
   "response":{
      "allowed":true,
      "uid":"23be6d67-6541-11e9-8bfc-001e063605c7",
      "patch":"W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL3NwZWMvdHRsU2Vjb25kc0FmdGVyRmluaXNoZWQiLCAidmFsdWUiOiAzNjAwfV0=",
      "patchtype":"JSONPatch"
   }
}

Der JSON Patch selbst ist mit Base64 Encoding verpackt, damit die JSON Struktur nicht durch seine Inhalte beeinflusst wird und dennoch das Auslesen einfach gelingt. Als Inhalt findet sich wieder eine JSON Struktur, die dann die jeweiligen Änderungen beschreibt. Da ein Mutating Admission Controller bei Kubernetes durchaus mehrere Änderungen vornehmen kann, ist der Patch selbst ein Array von einzelnen Operationen.

Beispiel eines dekodierteren JSON Patch
[
   {
      "op":"add",
      "path":"/spec/ttlSecondsAfterFinished",
      "value":3600
   }
]

Im nächsten Beitrag geht es darum, wie ein Beispiel für einen Kubernetes Admission Controller aussieht: Beispiel Kubernetes Mutating Admission Controller.




Zu den Themen Kubernetes, Docker und Cloud Architektur bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:

Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.

Feedback oder Fragen zu einem Artikel - per Twitter @triondevelop oder E-Mail freuen wir uns auf eine Kontaktaufnahme!

Zur Desktop Version des Artikels