Zum Inhalt

Lab 16: RBAC mit Pods

In dieser Aufgabe lernt ihr, einem Pod mittels eines ServiceAccounts ein Recht zu geben, dass es normalerweise nicht hat: über die Kubernetes-API andere Pods abfragen.

1) Pod anlegen

Schaue dir das Manifest für den ersten Pod an. Der Pod definiert ein Container, dessen Image kubectl enthält. Wende das Manifest nun an:

pod1.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: kubectl-pod
  namespace: default
spec:
  containers:
    - name: kubectl-container
      image: bitnami/kubectl:latest
      command: ["/bin/sh", "-c", "trap : TERM INT; sleep infinity & wait"]
      readinessProbe:
        exec:
          command: ["/bin/sh", "-c", "true"]
        initialDelaySeconds: 1
        periodSeconds: 10
      livenessProbe:
        exec:
          command: ["/bin/sh", "-c", "true"]
        initialDelaySeconds: 5
        periodSeconds: 20
      resources:
        requests:
          cpu: "100m"
          memory: "128Mi"
        limits:
          cpu: "200m"
          memory: "256Mi"
  restartPolicy: Always
kubectl apply -f pod1.yaml

Es sollte nun ein neuer Pod namens "kubectl-pod" im default-Namespace laufen:

kubectl get pods
# NAME          READY   STATUS      RESTARTS   AGE
# kubectl-pod   1/1     Running     0          52s

Versuchen wir nun, ob dieser Pod auch die anderen Pods per kubectl abfragen darf. Bauen wir dazu zunächst eine Verbindung mit dem Container auf und öffnen eine Shell-Sitzung:

kubectl exec -it kubectl-pod -- bash

Nun versuchen wir in der Shell-Sitzung mit kubectl die Pods des default-Namespaces aufzulisten:

kubectl get pods
# Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:default" cannot list resource "pods" in API group "" in the namespace "default"

Um dieses Ergebnis zu verstehen, müssen wir uns eine Sache in Erinnerung rufen: Wir haben diesen Befehl gerade nicht auf unserem Schulungsrechner ausgeführt, sondern innerhalb des Pods. kubectl innerhalb des Pods hat standardmäßig gar keine Rechte – anders als auf dem Schulungsrechner, wo Minikube uns als Admin konfiguriert hat. Da kubectl innerhalb des Pods keine Rechte hat, kann es auch keine Pods auflisten.

Trennt die Verbindung nun mit exit und löscht den Pod:

kubectl delete pod kubectl-pod

2) Service Account, Role und RoleBinding anlegen

Damit der Pod Zugriff erhält, braucht er einen ServiceAccount. Dieser Account muss mit Hilfe einer Rolle das Recht erhalten, Pods aufzulisten.

Schaut euch dazu folgendes Manifest an.

sa.yaml:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-kubectl-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
subjects:
  - kind: ServiceAccount
    name: my-kubectl-sa
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Erstens wird dort ein ServiceAccount angelegt.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-kubectl-sa

Der interessantere Teil ist aber die Rolle.

rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list"]

Sie erlaubt es, pods aufzulisten im default-Namespace, da kein anderer Namespace angegeben ist. Das RoleBinding verbindet die Rolle mit dem ServiceAccount.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
subjects:
  - kind: ServiceAccount
    name: my-kubectl-sa
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Wenn ihr alle Teile verstanden habt, wendet das Manifest nun an:

kubectl apply -f sa.yaml

3) Pod mit Service Account starten

In pod2.yaml findet ihr ein Manifest für den gleichen Pod wie in Schritt 1 -- nur dass diesmal der ServiceAccount genutzt wird, den wir in Schritt 2 angelegt haben:

pod2.yaml:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-kubectl-sa
  namespace: default
---
apiVersion: v1
kind: Pod
metadata:
  name: kubectl-pod
  namespace: default
spec:
  serviceAccountName: my-kubectl-sa
  containers:
    - name: kubectl-container
      image: bitnami/kubectl:latest
      command: ["/bin/sh", "-c", "trap : TERM INT; sleep infinity & wait"]
      readinessProbe:
        exec:
          command: ["/bin/sh", "-c", "true"]
        initialDelaySeconds: 1
        periodSeconds: 10
      livenessProbe:
        exec:
          command: ["/bin/sh", "-c", "true"]
        initialDelaySeconds: 5
        periodSeconds: 20
      resources:
        requests:
          cpu: "100m"
          memory: "128Mi"
        limits:
          cpu: "200m"
          memory: "256Mi"
  restartPolicy: Always

Ein Auszug daraus:

spec:
  serviceAccountName: my-kubectl-sa
  containers:
    - name: kubectl-container
      image: bitnami/kubectl:latest
      command: ["/bin/sh", "-c", "trap : TERM INT; sleep infinity & wait"]
  restartPolicy: Always

Wendet das Manifest nun an und verbindet euch dann wieder mit dem Pod:

kubectl apply -f pod2.yaml
kubectl exec -it kubectl-pod -- bash

Führt in der Shell-Sitzung nun wieder kubectl aus, um alle Pods aufzulisten. Es sollte nun funktionieren:

kubectl get pods
# NAME          READY   STATUS      RESTARTS   AGE
# busybox       0/1     Completed   0          21h
# busybox2      0/1     Error       0          21h
# kubectl-pod   1/1     Running     0          52s

Aufräumen

Löscht zuletzt den Test-Pod:

kubectl delete pod kubectl-pod