본문 바로가기
카테고리 없음

[Kubernetes] ServiceAccount와 RBAC로 외부에서 EKS 클러스터에 접근

by 홍띠 2024. 3. 24.

로컬에서 구동하는 도커 컨테이너 내부에서 AWS EKS에 올라간 쿠버네티스 클러스터 API를 사용하고자 한다. AWS에서 안내하는 문서에서는 IAM Principal을 등록해서 사용하도록 안내하는데, 이렇게 되면 도커 컨테이너에 AWS CLI를 비롯한 계정 설정을 해주어야 하는 것 같았다.

실제 로컬 PC에서는 그렇게 사용하고 있지만, 도커 컨테이너 내부에서 사용하는 용도로는 적절하지 않다고 생각했다. 다른 방법을 찾아보던 중 아래 글을 보고, 특정 네임스페이스에만 접근하도록 권한을 제한하여 kubeconfig를 작성해서 kubeconfig 파일만을 이용해서 K8S API사용이 가능하도록 구성했다.

(https://devocean.sk.com/blog/techBoardDetail.do?ID=165215)


네임스페이스 생성

외부에서 접근하고자 하는 네임스페이스를 지정 할 예정이다. 여기서는 local용 네임스페이스를 생성해서 사용한다.

kubectl create ns airflow-local

Service Account 생성

kubectl create sa airflow-local-sa -n airflow-local

kubernetes 1.24 이후 버전 부터는 서비스 어카운트에 시크릿이 자동으로 생성되지 않고 1시간동안 유효한 토큰이 동적으로 생성된다. 클러스터 외부 어플리케이션에서 사용하기 위해서는 서비스어카운트를 참조하는 시크릿을 수동으로 만들어주어야 하고, 이 시크릿은 만료되지 않는다.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: airflow-local-sa-secret
  namespace: airflow-local
  annotations:
    kubernetes.io/service-account.name: airflow-local-sa
type: kubernetes.io/service-account-token
EOF

RBAC 설정

이 예제에서는 클러스터 전체가 아닌 네임스페이스에만 권한을 제한하려고 하기 때문에 role과 rolebinding을 구성한다.

  • Role 생성
cat <<EOF | kubectl apply -f -
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: airflow-local-sa-role
  namespace: airflow-local
rules:
- apiGroups: [""]
  resources: ["*"]
  verbs: ["*"]
EOF

위의 예시는 해당 네임스페이스 내부에서의 모든 권한을 제공했지만, 아래와 같이 제한적으로 권한을 부여해도 된다.

- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
  • Role과 서비스 어카운트를 연동하는 Rolebinding 생성
cat <<EOF | kubectl apply -f -
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: airflow-local-sa-rolebinding
  namespace: airflow-local
subjects:
- kind: ServiceAccount
  name: airflow-local-sa
  namespace: airflow-local
roleRef:
  kind: Role
  name: airflow-local-sa-role
  apiGroup: rbac.authorization.k8s.io
EOF

 

Kubeconfig 작성

이제 서비스 어카운트 시크릿을 이용해서 Kubernetes에 접근 할 수 있는 kubeconfig를 작성한다.

apiVersion: v1
kind: Config
clusters:
- cluster:
    server: <EKS_CLUSTER_ENDPOINT>
    certificate-authority-data: <EKS_CLUSTER_CA>
  name: <CLUSTER_NAME>
contexts:
- context:
    cluster: <CLUSTER_NAME>
    user: airflow-local-sa
  name: <CLUSTER_NAME>-context
current-context: <CLUSTER_NAME>-context
users:
- name: airflow-local-sa
  user:
    token: <SERVICE_ACCOUNT_TOKEN>

 

EKS_CLUSTER_ENDPOINT, EKS_CLUSTER_CA 값은 아래 명령어로 가졍 올 수 있다.

aws eks describe-cluster --name <CLUSTER_NAME> --query "cluster.{endpoint:endpoint,certificateAuthorityData:certificateAuthority.data}"

 

SERVICE_ACCOUNT_TOKEN은 아래 명령어로 가져 온다.

kubectl get secret <SERVICE_ACCOUNT_NAME> -n airflow-local -o jsonpath='{.data.token}' | base64 --decode

 

동작 확인

위에서 작성한 kube-config 파일을 가지고 해당 네임스페이스에 API를 호출해 보면 정상적으로 조회되는 것을 확인 할 수 있다.

kubectl get po -n airflow-local --kubeconfig=./k8s-setting/kube-config.yml
# 출력 결과
No resources found in airflow-local namespace.