In this lab, we’ll create service accounts to define identities for our Pods. Kubernetes uses role-based access control (RBAC) to create roles that grant access to APIs and then bind those roles to ServiceAccounts.
Before we start, let’s first verify if we’re using the correct IAM user’s access keys. This should be the user we created from the pre-requisites section above.
$ aws sts get-caller-identity
{
"UserId": "AIDxxxxxxxxxxxxxx",
"Account": "1234567890",
"Arn": "arn:aws:iam::1234567890:user/k8s-admin"
}
For the cluster, we can reuse the eksops.yml file from the other labs.
Launch the cluster.
time eksctl create cluster -f eksops.yml
Check the nodes.
kubectl get nodes
Save the cluster, region, and AWS account ID in a variable. We’ll be using these in a lot of the commands later.
MYREGION=ap-southeast-1
MYCLUSTER=eksops
MYAWSID=$(aws sts get-caller-identity | python3 -c "import sys,json; print (json.load(sys.stdin)['Account'])")
Run the get command to see the existing service accounts.
$ kubectl get serviceaccount -A | grep default
default default 0 137d
kube-node-lease default 0 137d
kube-public default 0 137d
kube-system default 0 137d
kubernetes-dashboard default 0 137d
Each Namespace has a default ServiceAccount. The default ServiceAccount grants minimal access to APIs and cannot be used to get any cluster state information. Therefore, you should use custom ServiceAccounts when your application requires access to cluster state.
Use the pod-default-sa.yml to create a Pod that uses the default service account. We’ll also create a new namespace called “serviceaccounts”. Notice that we don’t need to specify a service account here.
apiVersion: v1
kind: Namespace
metadata:
name: serviceaccounts
---
apiVersion: v1
kind: Pod
metadata:
name: pod-default-sa
namespace: serviceaccounts
spec:
containers:
- image: mongo:4.0.6
name: mongodb
We could also see that the spec.serviceAccount is automatically set to the default ServiceAccount.
$ kubectl get pod pod-default-sa -n serviceaccounts -o yaml | grep
serviceAccount
serviceAccount: default
serviceAccountName: default
- serviceAccountToken:
It is a best practice to create a ServiceAccount for each applications to use the least amount of access necessary (principle of least privilege) to improve security. The created ServiceAccount will not have any specific role bound to it so there are no additional permissions associated with it.
In practice, the Kubernetes administrator creates a role and bind it to the ServiceAccount.
Let’s create a custom ServiceAccount.
kubectl create serviceaccount app-sa
Use pod-custom-sa.yml to create a new pod that uses the new service account.
apiVersion: v1
kind: Pod
metadata:
name: custom-sa-pod
namespace: serviceaccounts
spec:
serviceAccount: app-sa
containers:
- image: mongo:4.0.6
name: mongodb
We should now see two Pods running in our namespace.
$ kubectl get pods -n serviceaccounts
NAME READY STATUS RESTARTS AGE
pod-default-sa 1/1 Running 0 11m
pod-custom-sa 1/1 Running 0 3s
Before we officially close this lab, make sure to destroy all resources to prevent incurring additional costs.
$ time eksctl delete cluster -f eksops.yml
Note that when you delete your cluster, make sure to double-check the AWS Console and ensure that the Cloudformation stacks (which we created by eksctl) are dropped cleanly.