How it works
The explanation, with examples you can run.
Namespaces
A namespace scopes object names (two teams can each have a web Deployment) and is the unit for RoleBindings, ResourceQuotas, LimitRanges, NetworkPolicies and Pod Security admission labels. Nodes, PersistentVolumes, StorageClasses and ClusterRoles are cluster-wide. A namespace alone isolates nothing; the policies attached to it do.
RBAC: allow lists for the API
apiVersion: v1kind: ServiceAccountmetadata: name: deployer namespace: shop---apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: deploy-web namespace: shoprules: - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list", "watch", "patch"] - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"]---apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: deployer-deploy-web namespace: shopsubjects: - kind: ServiceAccount name: deployer namespace: shoproleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: deploy-webkubectl auth can-i patch deployments -n shop --as system:serviceaccount:shop:deployer# yeskubectl auth can-i get secrets -n shop --as system:serviceaccount:shop:deployer# noA Role is namespaced; a ClusterRole is cluster-wide or reusable across namespaces. Permissions are purely additive; there are no deny rules. Habits that matter:
- Grant to groups and service accounts through namespaced RoleBindings, not ClusterRoleBindings.
- Be careful with
secrets(listreturns the values),pods/exec, and the ability to create pods or workloads, which implies reading the namespace's Secrets and running code as any of its service accounts. - Give each workload its own ServiceAccount. If it does not call the API, set
automountServiceAccountToken: false.
NetworkPolicies: allow lists for traffic
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: default-deny-ingress namespace: shopspec: podSelector: {} # every pod in the namespace policyTypes: [Ingress]---apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: db-from-web namespace: shopspec: podSelector: matchLabels: app: db policyTypes: [Ingress] ingress: - from: - podSelector: matchLabels: app: web ports: - port: 5432A pod is isolated for ingress (or egress) as soon as any policy selects it for that direction; then only traffic some policy allows gets through. The first policy above denies all inbound traffic in shop; the second lets web pods reach db on 5432. If you add egress policies, remember to allow DNS to the cluster DNS service, or every name lookup fails.
Enforcement is done by the network plugin (Calico, Cilium and most managed-cluster defaults support it). If the plugin does not support NetworkPolicy, the objects are accepted and ignored, so test that a blocked connection is really blocked.
Beyond these three
Pod Security admission (labels such as pod-security.kubernetes.io/enforce: restricted on a namespace) rejects privileged or root pods. Policy engines (Kyverno, Gatekeeper, or the built-in ValidatingAdmissionPolicy) add rules RBAC cannot express. Separate namespaces still share nodes and a kernel; tenants that must not trust each other need separate node pools or clusters.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.