Elke applicatie in Kubernetes draait onder een identity. Als je niets instelt, gebruikt een workload de `default` ServiceAccount van de namespace. Dat is onhandig voor security, auditing en troubleshooting.
Gebruik daarom per applicatie een aparte ServiceAccount. Zo kun je rechten gericht toekennen, API-toegang uitschakelen voor workloads die die niet nodig hebben, en sneller zien welke workload welke actie uitvoerde.
- Maak voor elke applicatie of component een eigen ServiceAccount.
- Schakel `automountServiceAccountToken` uit als een applicatie de Kubernetes API niet hoeft te gebruiken.
- Koppel rechten pas nadat je weet welke API-calls de applicatie echt nodig heeft.
Maak twee ServiceAccounts aan: één met en één zonder API-toegang
Stap 1
Maak een .yaml-bestand aan, bijvoorbeeld:
nano serviceaccounts-demo.yamlPlaats de volgende inhoud in het bestand:
apiVersion: v1
kind: Namespace
metadata:
name: kb-sa-test
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-api
namespace: kb-sa-test
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-noapi
namespace: kb-sa-test
automountServiceAccountToken: false
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: configmap-reader
namespace: kb-sa-test
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-api-configmap-reader
namespace: kb-sa-test
subjects:
- kind: ServiceAccount
name: app-api
namespace: kb-sa-test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: configmap-reader
---
apiVersion: v1
kind: ConfigMap
metadata:
name: sample-config
namespace: kb-sa-test
data:
example: ok
---
apiVersion: v1
kind: Pod
metadata:
name: noapi-pod
namespace: kb-sa-test
spec:
serviceAccountName: app-noapi
automountServiceAccountToken: false
restartPolicy: Never
containers:
- name: busybox
image: busybox:1.36
command: ["/bin/sh", "-c", "sleep 3600"]Sla de wijzigingen op en sluit het bestand (ctrl + x > y > enter).
Stap 2
Maak de resources aan:
kubectl apply -f serviceaccounts-demo.yaml
kubectl -n kb-sa-test wait --for=condition=Ready pod/noapi-pod --timeout=180sHiermee heb je één ServiceAccount met beperkte API-rechten en één ServiceAccount zonder tokenmount voor workloads die de API helemaal niet hoeven te gebruiken.
Controleer de verschillen tussen beide ServiceAccounts
Stap 1
Controleer of `app-api` ConfigMaps in de eigen namespace mag lezen:
kubectl auth can-i list configmaps \
--as=system:serviceaccount:kb-sa-test:app-api \
-n kb-sa-testDe verwachte uitkomst is `yes`.
Stap 2
Controleer of `app-noapi` dezelfde actie niet mag uitvoeren:
kubectl auth can-i list configmaps \
--as=system:serviceaccount:kb-sa-test:app-noapi \
-n kb-sa-testDe verwachte uitkomst is `no`.
Stap 3
Controleer daarna of de pod zonder API-toegang ook echt geen ServiceAccount-token gemount heeft:
kubectl -n kb-sa-test exec noapi-pod -- ls /var/run/secrets/kubernetes.io/serviceaccountJe hoort hier een foutmelding te krijgen dat het pad niet bestaat. Dat is precies de bedoeling: de pod kan dan niet per ongeluk de Kubernetes API gebruiken.
Gebruik de juiste ServiceAccount in je Deployment
Verwijs in een Deployment of StatefulSet altijd expliciet naar de juiste ServiceAccount:
spec:
serviceAccountName: app-api
automountServiceAccountToken: trueOf voor een applicatie die geen API-toegang nodig heeft:
spec:
serviceAccountName: app-noapi
automountServiceAccountToken: falseZo blijft het gedrag van je workload voorspelbaar, ook als later iemand de `default` ServiceAccount van de namespace wijzigt.
Met aparte ServiceAccounts per applicatie maak je rechten, tokenmounts en auditing veel overzichtelijker. Combineer dit altijd met RBAC, zodat een ServiceAccount niet meer mag dan een workload werkelijk nodig heeft.