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
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
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"]
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
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
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
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']
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
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
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"
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"]
Reapply the updated Role:
kubectl apply -f role.yaml
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:
- Create a Service Account for use by a Kubernetes Pod.
- Create a Role that grants read-only access to Pods.
- Bind the Role to the Service Account using a RoleBinding.
- 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.
Top comments (0)