kubeconfig 가 없는 서버에서 클러스터에 접근해야 할 때가 있다. CI 러너, 모니터링 수집기, 배치 서버 같은 경우다. 사람 계정의 인증서를 복사해 쓰지 말고 서비스 계정을 만들어 그 토큰으로 kubeconfig 를 구성한다. 권한을 필요한 만큼만 주고, 문제가 생기면 그 계정만 지우면 되기 때문이다.
예전에는 서비스 계정을 만들면 토큰이 든 Secret 이 자동으로 생겼다. 쿠버네티스 1.24 부터 이 자동 생성이 사라졌다. 인터넷의 오래된 안내가 kubectl get secret 으로 토큰을 찾으라고 하는데, 요즘 클러스터에서는 그 Secret 자체가 없다.
지금은 두 가지 방법이 있다.
| 방법 | 성격 | 용도 |
|---|---|---|
kubectl create token |
만료가 있는 단기 토큰 | 사람이 임시로 쓰거나 자동 갱신 가능한 곳 |
kubernetes.io/service-account-token 타입 Secret 을 직접 생성 |
만료 없는 토큰 | 갱신 수단이 없는 외부 시스템 |
만료 없는 토큰은 유출되면 회수 전까지 계속 쓸 수 있으므로, 가능하면 단기 토큰을 쓰고 갱신을 자동화한다.
kubectl create namespace automation
kubectl create serviceaccount ci-runner -n automation
필요한 권한만 Role 로 주고 묶는다. cluster-admin 을 붙이는 것은 마지막 수단이다.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployer
namespace: app
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "patch", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ci-runner-deployer
namespace: app
subjects:
- kind: ServiceAccount
name: ci-runner
namespace: automation
roleRef:
kind: Role
name: deployer
apiGroup: rbac.authorization.k8s.io
단기 토큰은 다음과 같다. 기본 만료는 1시간이고 --duration 으로 조절한다.
TOKEN=$(kubectl create token ci-runner -n automation --duration=8760h)
클러스터 설정에 따라 요청한 기간보다 짧게 깎일 수 있다. 실제 만료는 발급된 토큰의 페이로드에서 확인한다.
만료 없는 토큰이 필요하면 Secret 을 직접 만든다.
apiVersion: v1
kind: Secret
metadata:
name: ci-runner-token
namespace: automation
annotations:
kubernetes.io/service-account.name: ci-runner
type: kubernetes.io/service-account-token
kubectl apply -f ci-runner-token.yaml
TOKEN=$(kubectl get secret ci-runner-token -n automation -o jsonpath='{.data.token}' | base64 -d)
APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
kubectl config view --raw --minify -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' | base64 -d > ca.crt
OpenShift 에서 oc 를 쓴다면 주소는 oc whoami --show-server 로 얻는다.
손으로 YAML 을 적는 것보다 kubectl config 로 만드는 편이 오타가 없다.
export KUBECONFIG=./ci-runner.kubeconfig
kubectl config set-cluster mycluster \
--server="${APISERVER}" \
--certificate-authority=./ca.crt \
--embed-certs=true
kubectl config set-credentials ci-runner --token="${TOKEN}"
kubectl config set-context ci \
--cluster=mycluster --user=ci-runner --namespace=app
kubectl config use-context ci
KUBECONFIG=./ci-runner.kubeconfig kubectl auth whoami
KUBECONFIG=./ci-runner.kubeconfig kubectl auth can-i list deployments -n app
KUBECONFIG=./ci-runner.kubeconfig kubectl get deployments -n app
auth whoami 는 1.27 이후에 쓸 수 있다. 결과의 사용자 이름은 system:serviceaccount:automation:ci-runner 형태로 나온다.
파드에는 서비스 계정 토큰이 이미 마운트돼 있다. 별도 kubeconfig 없이 클러스터 내부 주소로 붙으면 된다.
/var/run/secrets/kubernetes.io/serviceaccount/token
/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
이 토큰은 kubelet 이 주기적으로 갱신하므로 매번 다시 읽어야 한다. 시작할 때 한 번 읽어 캐시하면 만료 후 401 이 난다.