Kubernetes path · State, security and extension · Topic 12 of 13

Namespaces, RBAC and network policies

Not started

A fresh cluster is permissive in two ways. On the network, every pod can reach every other pod in every namespace. In the API, whoever holds a powerful credential can change anything. Namespaces give you units to divide the cluster into, RBAC decides which identities may perform which API actions in them, and NetworkPolicies decide which pods may open connections to which. All three default to open and work by adding allowances, so the usual approach is to deny broadly and then allow narrowly.

Why it matters: Out of the box every pod can talk to every other pod, and broad roles are easy to hand out. Namespaces, RBAC and NetworkPolicies are how one team's mistake, or one compromised pod, stays contained.

  1. 1Namespaces scope names and policy

    A namespace is a scope for names, RBAC, quotas and network policies. It is not by itself a security boundary.

  2. 2RBAC only allows

    Roles list allowed verbs on resources; bindings grant them to users, groups or service accounts. There are no deny rules.

  3. 3Pods have identities too

    Each pod runs as a ServiceAccount; give it only the API access it needs, and none if it needs none.

  4. 4The network is open by default

    Until a NetworkPolicy selects a pod, all traffic to and from it is allowed. Policies only work if the network plugin enforces them.

1

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-web
kubectl 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# no

A 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 (list returns 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: 5432

A 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.

2

Check yourself

3 questions. Get them all right to finish this topic.

  1. 1.A user has a ClusterRole that allows deleting pods. Can you add a Role that denies it in one namespace?
  2. 2.You apply a NetworkPolicy that allows only app=web to reach app=db on 5432, but other pods can still connect. What is the likely cause?
  3. 3.What does a NetworkPolicy with podSelector: {} and policyTypes: [Ingress] and no ingress rules do?

0 of 3 right so far. Get all three to finish this topic.