Introduction: Hosting numerous users on a single Kubernetes cluster poses challenges due to varying organizational needs. Kubernetes provides building blocks like RBAC and NetworkPolicies for crafting custom tenancy models. Among these, namespaces play a pivotal role, forming the foundation for control plane security and sharing policies.
The Power of Namespaces: Namespaces are key to policy enforcement, representing ownership and controlling authorized creation and use. Objects like RBAC, NetworkPolicies, and ResourceQuotas align with namespaces by default. However, practical limitations arise in scenarios where flexibility is paramount.
Challenges with Vanilla Namespaces: Consider a scenario where a team manages multiple microservices, each requiring different secrets and quotas. Placing these services in separate namespaces is ideal for isolation, but issues arise. Vanilla namespaces lack a common ownership concept for teams managing multiple namespaces, hindering uniform policy application.
Overcoming Limitations with Hierarchical Namespaces: Enter hierarchical namespaces, a groundbreaking concept from the Kubernetes Working Group for Multi-Tenancy. Hierarchical namespaces introduce a small custom resource within a regular namespace, establishing a parent-child relationship. This ownership concept brings two crucial benefits:
Policy Inheritance: Child namespaces inherit policies like RBAC RoleBindings from their parent. Ensures uniform application of policies across namespaces, addressing ownership challenges.
Delegated Creation: Introduces subnamespaces, allowing limited-permission manipulation in the parent namespace. Enables teams to autonomously create subnamespaces without cluster admin intervention.
Solving Dev Team Challenges: Hierarchical namespaces offer a solution for development teams. Cluster administrators can create a root namespace with necessary policies, and then delegate subnamespace creation to team members. This empowers teams to create and manage their namespaces within the defined policies, reducing administrative toil.
Installing HNC Plugin
# Select the latest version of HNC
#HNC_VERSION=v1.1.0
#HNC_VARIANT=default
#kubectl apply -f https://github.com/kubernetes-sigs/hierarchical-namespaces/releases/download/${HNC_VERSION}/${HNC_VARIANT}.yaml
#kubectl krew update
#kubectl krew install hns
# Ensure the plugin is working
#kubectl hns
Hands-on with hierarchical namespaces
Lets Create namespace
#kubectl create ns test
Lets Create Subnamespace subtest in namespace test
#kubectl hns create subtest -n test
We can view the structure of these namespaces by asking for a tree view
#kubectl hns tree test
test
└── [s] subtest
Lets create Role and Role Binding and attach it to test namespace
#cat role.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: test
name: example-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "create", "delete"]
#cat rolebinding.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-rolebinding
namespace: test
subjects:
- kind: User
name: "user1" # replace with the actual username
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # or ClusterRole
name: example-role
apiGroup: rbac.authorization.k8s.io
#kubectl apply -f role.yaml
#kubectl apply -f rolebinding.yaml
Lets verify
# kubectl describe rolebinding example-rolebinding -n test
Name: example-rolebinding
Labels: <none>
Annotations: <none>
Role:
Kind: Role
Name: example-role
Subjects:
Kind Name Namespace
---- ---- ---------
User user1
We did not apply the Role and Rolebinding on subnamespace, lets verify did the Role and Rolebinding get inherited
# kubectl describe rolebinding example-rolebinding -n subtest
Name: example-rolebinding
Labels: app.kubernetes.io/managed-by=hnc.x-k8s.io
hnc.x-k8s.io/**inherited-from=test**
Annotations: <none>
Role:
Kind: Role
Name: example-role
Subjects:
Kind Name Namespace
---- ---- ---------
User user1
Finally, HNC adds labels to these namespaces with useful information about the hierarchy which you can use to apply other policies
For example, you can create the following NetworkPolicy:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-team-a
namespace: team-a
spec:
ingress:
- from:
- namespaceSelector:
matchExpressions:
- key: 'team-a.tree.hnc.x-k8s.io/depth' # Label created by HNC
operator: Exists
This policy will both be propagated to all descendants of test, and will also allow ingress traffic between all of those namespaces. The “tree” label can only be applied by HNC, and is guaranteed to reflect the latest hierarchy.