DEV Community

Hamid Haghdoost
Hamid Haghdoost

Posted on

Kubernetes Service Account and RBAC Tutorial

Kubernetes Service Account and RBAC Tutorial

Introduction

In this tutorial, we created a Service Account with a Role and RoleBinding for read-only access to Pods. You can find the source code in the GitHub repository.

What is a Service Account in Kubernetes?

A Service Account in Kubernetes is a special type of account that is used by processes or applications running inside Pods to authenticate and interact with the Kubernetes API. Unlike User Accounts, which are typically associated with human users, Service Accounts are designed for non-human access. They are used to grant specific permissions to applications, allowing them to interact with the Kubernetes cluster in a controlled and secure way.

How Does a Service Account Work?

Service accounts provide a mechanism for granting RBAC (Role-Based Access Control) permissions to Pods and workloads. Each service account has a set of credentials (a token) that is automatically generated by Kubernetes. This token is mounted into the container running inside a Pod, which allows the application to authenticate itself against the Kubernetes API.

Through the service account, Kubernetes manages the access control for specific resources (such as Pods, Services, ConfigMaps, etc.), based on the Role or ClusterRole associated with the account. These roles define what actions the service account can perform on different resources within the cluster.

In essence, a Service Account acts as an identity for the applications or workloads running inside your Kubernetes Pods. By linking it with roles and permissions, Kubernetes enables fine-grained access control, ensuring that each service only has access to the resources it needs.


Prerequisites

Before starting this tutorial, you should have:

  • A Kubernetes cluster (either local or on a cloud provider).
  • kubectl installed and configured to access the cluster.
  • Basic knowledge of Kubernetes Pods and RBAC.

Step 1: Create a Service Account

A Service Account is an identity for processes running inside Pods. It allows Pods to authenticate and interact with the Kubernetes API.

First, create a file named service-account.yaml to define the Service Account:

apiVersion: v1
kind: ServiceAccount
metadata: 
  name: print-read-service-account
  namespace: service-account-test
Enter fullscreen mode Exit fullscreen mode

This file defines a service account named print-read-service-account in the service-account-test namespace.

To apply the Service Account to your Kubernetes cluster, run:

kubectl apply -f service-account.yaml
Enter fullscreen mode Exit fullscreen mode

Step 2: Create a Role with Read Access to Pods

In Kubernetes, a Role defines what resources can be accessed within a specific namespace and what actions can be performed. Here, we'll create a Role that grants read-only access to pods.

Create a file named role.yaml with the following content:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role 
metadata:
  name: read-role
  namespace: service-account-test
rules: 
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]
Enter fullscreen mode Exit fullscreen mode

This Role grants permission to get and list pods in the service-account-test namespace.

To apply the Role, run:

kubectl apply -f role.yaml
Enter fullscreen mode Exit fullscreen mode

Step 3: Create a RoleBinding to Bind the Role to the Service Account

A RoleBinding is used to bind a Role to a specific Service Account. This allows the service account to use the permissions defined in the Role.

Create a file named role-binding.yaml:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-role-binding
  namespace: service-account-test
subjects:
- kind: ServiceAccount
  name: print-read-service-account
  namespace: service-account-test
roleRef:
  kind: Role
  name: read-role
  apiGroup: rbac.authorization.k8s.io
Enter fullscreen mode Exit fullscreen mode

This RoleBinding binds the read-role to the print-read-service-account service account.

To apply the RoleBinding, run:

kubectl apply -f role-binding.yaml
Enter fullscreen mode Exit fullscreen mode

Step 4: Create a Pod that Uses the Service Account

Now, create a Pod that uses the print-read-service-account service account to access Kubernetes resources. This Pod will use the kubectl command to list pods and services in the cluster.

Create a file named pod-with-service-account.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-service-account
  namespace: service-account-test
spec:
  serviceAccountName: print-read-service-account
  containers:
  - name: print-reader-container
    image: bitnami/kubectl:latest
    command: ['sh', '-c', 'kubectl get pods && kubectl get services']
Enter fullscreen mode Exit fullscreen mode

This Pod runs a container with the kubectl image. The container executes the command kubectl get pods && kubectl get services, which will attempt to retrieve both Pods and Services in the cluster.

To apply the Pod, run:

kubectl apply -f pod-with-service-account.yaml
Enter fullscreen mode Exit fullscreen mode

Step 5: Verify the Pod Logs

Once the Pod is created, you can check the logs of the Pod to verify that it can read pods and services.

Run the following command:

kubectl logs pod-with-service-account -n service-account-test
Enter fullscreen mode Exit fullscreen mode

Example Output:

NAME                       READY   STATUS    RESTARTS        AGE
pod-with-service-account   1/1     Running   6 (2m48s ago)   5m47s
Error from server (Forbidden): services is forbidden: User "system:serviceaccount:service-account-test:print-read-service-account" cannot list resource "services" in API group "" in the namespace "service-account-test"
Enter fullscreen mode Exit fullscreen mode

Explanation:

In the log above, the kubectl command successfully lists the pods, but it encounters an error when trying to list the services. The error message indicates that the service account print-read-service-account does not have permission to access the services resource. This is because the Role only grants access to pods and not services.

To fix this, you need to update the Role to grant read access to both pods and services.


Step 6: Update the Role to Access Services

Edit the role.yaml file to include access to services:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role 
metadata:
  name: read-role
  namespace: service-account-test
rules: 
- apiGroups: [""]
  resources: ["pods", "services"]
  verbs: ["get", "list"]
Enter fullscreen mode Exit fullscreen mode

Reapply the updated Role:

kubectl apply -f role.yaml
Enter fullscreen mode Exit fullscreen mode

Now, when you check the Pod logs again, you should see both pods and services listed.

By default, a Kubernetes Service Account has access only to resources within the namespace it is created in. This means that the print-read-service-account in our example can only interact with resources like Pods and Services within the service-account-test namespace. If you want the service account to have access to resources in other namespaces, you need to use a ClusterRole and ClusterRoleBinding instead of a Role and RoleBinding. A ClusterRole grants access to resources across the entire cluster, and a ClusterRoleBinding allows you to bind the ClusterRole to a service account across multiple namespaces or cluster-wide.


Conclusion

In this tutorial, you learned how to:

  1. Create a Service Account for use by a Kubernetes Pod.
  2. Create a Role that grants read-only access to Pods.
  3. Bind the Role to the Service Account using a RoleBinding.
  4. Deploy a Pod that uses the Service Account to interact with Kubernetes resources.

By following these steps, you can control access to Kubernetes resources securely using RBAC and Service Accounts, ensuring that applications only have access to the resources they need.


Further Reading

Top comments (0)