본문 바로가기
Kubernetes

Kubernetes ServiceAccount 관리

by beann 2024. 3. 30.
반응형

일단 쿠버네티스는 Account에 대한 기준이 두가지로 나뉜다.

1. UserAccount

- 실제 사용자에게 필요한 Account이다

- 특정 Namespace에 종속적이지 않고 Global하다.

 

2. ServiceAccount

- Container(Pod 내)안의 어플리케이션 및 프로세스가 kube-apiserver와 통신하기 위해 필요한 Account이다

- 특정 Namespace에 종속적이다. 따라서 foo라는 namespace에서 생성한 ServiceAccount는 foo namespace에서 동작하는 Pod와만 연결 가능하다.

- 때에 따라서, ServiceAccount와, Token을 별도로 생성하여 해당 Token을 기반으로 Kubeconfig파일을 만들어 RBAC기반 사용자 권한 제어 관리가 가능하다.

참고: https://devocean.sk.com/blog/techBoardDetail.do?ID=165215

 

 

쿠버네티스 1.24버전 이전에는 ServiceAccount(SA)를 생성하면 Secret이 함께 자동으로 생성되었고, 해당 Secret에는 SA에 대한 Token값이 포함되어있었다.
1.24버전 이상부터는 SA를 생성해도 Secret은 자동생성되지 않기때문에 Token은 별도로 생성하여야 한다. 다만, 별도로 Token을 생성하지 않고, Pod에 SA만 연결해도 해당하는 Token은 자동으로 생성된다.

 

 

쿠버네티스가 ServiceAccount와 통신하며 인증이 처리되는 과정은 아래와 같다

 

[특정 Pod가 kube-apiserver에 어떠한 요청을 보냈을때]

1. Pod가 API서버에 요청을 보냄

2. kube-apiserver는 Pod에게 Token값을 요청

3. Pod는 token을 response

4. kube-apiserver는 pod의 ServiceAccountToken을 통해, ServiceAccount에 할당된 권한을 확인하여 Pod가 요청한 작업을 수행할 수 있는지 검증한다.

5. 요청을 승인 또는 거부한다.

 

 

Pod내부에서 ServiceAccount Token을 활용해 API서버와 통신 테스트


test라는 이름의 secret을 생성하고, role과 rolebinding을 생성하여 test SA에 할당한다.

root@k8s-m:~# kubectl create secret test

# test ServiceAccount에 할당할 Role을 생성(get, list, watch 권한을 pod에만 사용가능)
root@k8s-m:~# kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods

# test Service Account에 위에서 만든 role을 할당
root@k8s-m:~# kubectl create rolebinding pod-reader --role=pod-reader --serviceaccount=default:test

 

 

pod내부에서 kube-apiserver에 api를 호출할 테스트용 pod생성

root@k8s-m:~# vi pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
  serviceAccountName: test
  
root@k8s-m:~# k apply -f pod.yaml

 

 

api호출 테스트

# system:anonymous로 인가되지 않은 사용자가 요청했기 때문에 실패한다.
root@k8s-m:~# kubectl exec -it nginx -- curl -k https://10.20.0.48:6443/api/v1/pods
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods is forbidden: User \"system:anonymous\" cannot list resource \"pods\" in API group \"\" at the cluster scope",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403


# Pod접속
root@k8s-m:~# k exec -it nginx -- /bin/bash


# 환경변수 등록
root@nginx:/# export CURL_CA_BUNDLE=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
root@nginx:/# TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)


# 권한이 있는 test serviceaccount를 통해 kube-apiserver에 api를 호출 하면 Pod List가 확인된다
root@nginx:/# curl -H "Authorization: Bearer $TOKEN" https://10.20.0.48:6443/api/v1/namespaces/default/pods
{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "resourceVersion": "3160965"
  },
  "items": [
    {
      "metadata": {
        "name": "kube-bench-master-kj8t6",
        "generateName": "kube-bench-master-",
        "namespace": "default",
        "uid": "4d92e0fe-04cc-4c32-8607-b77d73089e06",
        "resourceVersion": "1162361",
        "creationTimestamp": "2024-03-20T05:54:54Z",
        "labels": {
          "controller-uid": "55259533-8bc4-419f-8e63-260d28af9093",
          "job-name": "kube-bench-master"
        },
 ...
 ...
 ...
 
 # Service에 대한 권한을 할당하지 않아서 Service는 권한이 없다는 에러가 발생한다.
 root@nginx:/# curl -H "Authorization: Bearer $TOKEN" https://10.20.0.48:6443/api/v1/namespaces/default/services
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "services is forbidden: User \"system:serviceaccount:default:test\" cannot list resource \"services\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "details": {
    "kind": "services"
  },
  "code": 403

 

반응형