Kubernetes의 Service Account와 kubeconfig 파일을 사용하여, kubernetes 클러스터 외부에서 접근하는 방법을 알아보도록 하겠습니다.

Service Account 생성

Kubernetes 1.24 부터 ServiceAccount 생성시 Secret을 자동으로 생성하지 않습니다.

Kubernetes 1.24 이상

# 생성
$ kubectl create sa test-sa

# 조회
$ kubectl get sa test-sa -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2024-09-11T05:01:12Z"
  name: test-sa
  namespace: default
  resourceVersion: "6948234123"
  uid: 234d3212-a859-44f6-8bfd-sdfsd123123

Kubernetes 1.23 이하

Kubernetes 1.23 이하 버전 사용시 Secret을 생성하지 않아도 됩니다. ServiceAccount 생성시 자동 생성됩니다.

# 생성
$ kubectl create sa test-sa

# 조회
$ kubectl get sa test-sa -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2024-09-11T05:01:12Z"
  name: test-sa
  namespace: default
  resourceVersion: "6948234123"
  uid: 234d3212-a859-44f6-8bfd-sdfsd123123
# secret이 생성되어 ServiceAccount에 secret이름이 연결되어있습니다.
secrets:
- name: test-sa-token-nsrc8

Secret 생성

Kubernetes 1.24 부터 Secret을 생성해야 합니다. Secret 생성시 kubernetes.io/service-account.name annotation으로 생성한 ServiceAccount name을 설정해야 합니다.

apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
  name: test-sa-token
  annotations:
    # ServiceAccount name
    kubernetes.io/service-account.name: "test-sa"

RBAC 권한 설정

Kubernetes의 리소스에 접근하기 위해서 권한설정을 해주셔야합니다. 아래의 예제는 Kubernetes에서 기본으로 제공되는 cluster-admin(ClusterRole) 권한을 설정하였습니다. 예제 작성을 위해 cluster-admin 권한을 설정하였지만, 최소권한으로 설정하셔야 합니다. Role / RoleBinding을 사용하여 특정 namespace의 권한을 설정하거나, ClusterRole / ClusterRoleBinding cluster 레벨로 권한을 설정할 수 있습니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: test-sa-clusterrolebinding
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
subjects:
  - kind: ServiceAccount
    name: test-sa
    namespace: default

Kubeconfig 파일 생성

아래의 스크립트를 저장 후 실행하여 Kubeconfig 파일을 작성합니다.

#!/bin/bash

API_SERVER_URL=$1
NAMESPACE=$2
SERVICEACCOUNT=$3
SECRETNAME=$4

if [ -z "${API_SERVER_URL}" ]; then
  echo "requried API_SERVER_URL"
  echo "usage: make_kubeconfig.sh API_SERVER_URL NAMESPACE SERVICEACCOUNT"
  exit 1
fi

if [ -z "${NAMESPACE}" ]; then
  echo "requried NAMESPACE"
  echo "usage: make_kubeconfig.sh API_SERVER_URL NAMESPACE SERVICEACCOUNT"
  exit 1
fi

if [ -z "${SERVICEACCOUNT}" ]; then
  echo "requried SERVICEACCOUNT"
  echo "usage: make_kubeconfig.sh API_SERVER_URL NAMESPACE SERVICEACCOUNT"
  exit 1
fi

if [ -z "${SECRETNAME}" ]; then
  echo "requried SECRETNAME"
  echo "usage: make_kubeconfig.sh API_SERVER_URL NAMESPACE SERVICEACCOUNT SECRETNAME"
  exit 1
fi

CA=$(kubectl -n $NAMESPACE get secret $SECRETNAME -o jsonpath='{.data.ca\.crt}')
TOKEN=$(kubectl -n $NAMESPACE get secret $SECRETNAME -o jsonpath='{.data.token}' | base64 --decode)

echo "apiVersion: v1
kind: Config
clusters:
- name: default-cluster
  cluster:
    certificate-authority-data: ${CA}
    server: ${API_SERVER_URL}
contexts:
- name: default-context
  context:
    cluster: default-cluster
    namespace: ${NAMESPACE}
    user: ${SERVICEACCOUNT}
current-context: default-context
users:
- name: ${SERVICEACCOUNT}
  user:
    token: ${TOKEN}
"

API Server Endpoint

kubectl 명령어를 사용하면 확인할 수 있습니다.

$ kubectl cluster-info
Kubernetes control plane is running at https://324JN324JKHNB32KJ4NB32KJ432KJ4N2.nn1.ap-northeast-2.eks.amazonaws.com

스크립트 실행

위의 파일을 /tmp/kubeconfig.sh 파일로 저장하여 실행하는 예제입니다.

/tmp/kubeconfig.sh https://324JN324JKHNB32KJ4NB32KJ432KJ4N2.nn1.ap-northeast-2.eks.amazonaws.com default test-sa test-sa-token > /tmp/kubeconfig.yaml

kubectl

생성된 Kubeconfig 파일을 사용하여 kubectl 명령어를 사용할 수 있습니다. 예제에서는 RBAC 권한이 cluster-admin으로 설정되어있어서 모든 namespace의 POD를 조회할 수 있습니다. RBAC 권한에 따라 namespace 또는 리소스 접근에 제한이 걸릴 수 있습니다.

$ kubectl --kubeconfig=/tmp/kubeconfig.yaml get pod --all-namespaces