Skip to content

Securing applications, CRDs and Monitoring

Let’s begin the new series. We’ll start with what is arguably the most important topic for securing a multi-user or automated Kubernetes environment: access control.

So far, you’ve been interacting with your minikube cluster as a superuser or cluster administrator. You have the power to create, delete, and modify anything you want, anywhere in the cluster. In a real-world scenario, this is a massive security risk. You wouldn’t give every developer, or every automated CI/CD script, the keys to the entire kingdom.

Securing Access with Role-Based Access Control (RBAC)

Section titled “Securing Access with Role-Based Access Control (RBAC)”

The central challenge is granting just enough permission for a user or application to do its job, and nothing more. This is known as the Principle of Least Privilege.

In Kubernetes, this is managed through Role-Based Access Control (RBAC). RBAC is the standard mechanism that allows you to define granular permissions for who can do what.

RBAC is built on four key API objects. Understanding them is understanding RBAC.

  • Role: A Role is a set of permissions for resources within a single namespace. A Role contains a list of rules, where each rule defines:

    • verbs: What actions are allowed (e.g., get, list, watch, create, delete, update).
    • resources: Which objects the verbs apply to (e.g., pods, deployments, services, configmaps).
    • apiGroups: The API group the resource belongs to (e.g., "" for core resources, apps for Deployments, batch for Jobs).
  • ClusterRole: A ClusterRole is exactly like a Role, but it is not namespaced. You use it for two main reasons:

    1. To grant permissions to cluster-scoped resources (like nodes or namespaces themselves).
    2. To grant permissions for namespaced resources (like pods) across all namespaces in the cluster.

2. The “Who” - The Subjects Being Granted Permissions

Section titled “2. The “Who” - The Subjects Being Granted Permissions”
  • User and Group: These represent human users. Kubernetes does not have its own user objects; these identities are assumed to come from an external source, like a client certificate or a cloud provider’s IAM system.
  • ServiceAccount: This provides an identity for processes running inside Pods. This is the primary way you give permissions to your applications so they can interact with the Kubernetes API securely.

3. The “Binding” - Connecting “Who” to “What”

Section titled “3. The “Binding” - Connecting “Who” to “What””

Defining a Role does nothing on its own. You have to grant that Role to a subject.

  • RoleBinding: This object grants a Role to a subject (User, Group, or ServiceAccount) within a specific namespace. A RoleBinding essentially says: “In the dev namespace, give the pod-reader Role to the limited-user ServiceAccount.”
  • ClusterRoleBinding: This grants a ClusterRole to a subject. This is used to grant cluster-wide permissions.


  1. Create a Workspace First, let’s create a new namespace to keep our work clean.

    Terminal window
    kubectl create namespace rbac-test

    Now, let’s create a ServiceAccount that will act as our limited user.

    Terminal window
    kubectl create serviceaccount limited-user -n rbac-test
  2. Define a Role We will create a Role that only grants permission to read Pods and their logs within the rbac-test namespace.

    Create a file named pod-reader-role.yaml:

    pod-reader-role.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
    namespace: rbac-test
    name: pod-reader
    rules:
    - apiGroups: [""] # The empty string "" indicates the core API group
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]

    Apply it to the cluster:

    Terminal window
    kubectl apply -f pod-reader-role.yaml
  3. Bind the Role to the ServiceAccount Now we need to connect our limited-user to our pod-reader role using a RoleBinding.

    Create a file named pod-reader-binding.yaml:

    pod-reader-binding.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
    name: read-pods-binding
    namespace: rbac-test
    subjects:
    # This is the "who" - our limited user
    - kind: ServiceAccount
    name: limited-user
    namespace: rbac-test
    roleRef:
    # This is the "what" - the role we are granting
    kind: Role
    name: pod-reader
    apiGroup: rbac.authorization.k8s.io

    Apply the binding:

    Terminal window
    kubectl apply -f pod-reader-binding.yaml

    At this point, our limited-user ServiceAccount now has read-only access to Pods, and only in the rbac-test namespace.

  4. Test the Permissions How can we check if this worked? kubectl has a fantastic subcommand, auth can-i, that lets you impersonate a user to check their permissions.

    • Let’s test an allowed action: Can our user list pods in the rbac-test namespace?

      Terminal window
      kubectl auth can-i list pods --as=system:serviceaccount:rbac-test:limited-user -n rbac-test

      The output will be: yes

    • Now for denied actions:

      • Can our user delete pods in the correct namespace?

        Terminal window
        kubectl auth can-i delete pods --as=system:serviceaccount:rbac-test:limited-user -n rbac-test

        Output: no (Correct! The role doesn’t include the delete verb.)

      • Can our user list deployments?

        Terminal window
        kubectl auth can-i list deployments --as=system:serviceaccount:rbac-test:limited-user -n rbac-test

        Output: no (Correct! The role doesn’t include the deployments resource.)

      • Can our user list pods in the default namespace?

        Terminal window
        kubectl auth can-i list pods --as=system:serviceaccount:rbac-test:limited-user -n default

        Output: no (Correct! The RoleBinding is only for the rbac-test namespace.)

  5. Clean Up We can delete the namespace, which will also delete the ServiceAccount, Role, and RoleBinding we created within it.

    Terminal window
    kubectl delete namespace rbac-test
  • RBAC is the core mechanism for securing your Kubernetes cluster.
  • Always follow the Principle of Least Privilege: grant only the permissions necessary for a task.
  • Permissions are defined in Roles (namespaced) and ClusterRoles (cluster-wide).
  • Permissions are granted to subjects (Users, ServiceAccounts) via RoleBindings and ClusterRoleBindings.
  • A ServiceAccount provides an identity for your applications, allowing them to securely interact with the Kubernetes API using RBAC permissions.

This is a fundamental security concept. Let me know when you’re ready, and we’ll build on this by looking at how to secure network traffic in Chapter 2: Securing Network Traffic with Network Policies.