ksc0204 님의 블로그

AEWS 4기 4주차(1) - Kubernetes 인증/인가 본문

AWS 4기

AEWS 4기 4주차(1) - Kubernetes 인증/인가

ksc0204 2026. 4. 11. 18:02

before start..

본 글은 공식 문서 및 서종호(가시다)님의 AWS EKS 워크샵 내용을 기반으로 참고하여 학습 목적으로 작성하였습니다.
주관적인 해석이 포함되어 있어 사실과 다르거나 오류가 있을 수 있으니 참고용으로만 읽어주시기 바랍니다.

 

K8s API 접근 통제 - 참고

 

모든 요청은 kube-apiserver를 통해 들어오며, 아래의 필터를 순차적으로 통과해야만 실제 클러스터 리소스에 반영(etcd 저장)됩니다.

[참고] - https://kubernetes.io/docs/concepts/security/controlling-access/

  • 1. 인증 (Authentication) - 요청자 확인
    가장 먼저 요청자가 누구인지 확인합니다. K8s는 자체적인 사용자 DB를 가지고 있지 않으므로, 외부 인증 시스템이나 인증서를 활용합니다.

    [ 인증의 종류 ]
    X.509 인증서: 클라이언트 인증서를 통해 검증.
    Static Token: 미리 정의된 토큰 파일 사용.
    Service Account: Pod 내의 프로세스가 API에 접근할 때 사용하는 자동 생성 토큰.
    OIDC (OpenID Connect): Google, Keycloak 등 외부 ID 공급자와 연동.

    [ Kubeadm으로 설치 시 생성되는 인증서 확인 ]
    종류 파일명 (kubeadm 기준) 용도 설명
    API Server
    인증서
    apiserver.crt Server Role
    클라이언트(kubectl, kubelet 등)가 API 서버에 접속할 때 API 서버의 신원을 확인하는 데 사용됩니다.
    Kubelet Client
    인증서
    apiserver-kubelet-client.crt Client Role API 서버가  노드의 Kubelet에 접속하여 로그를 조회하거나 명령을 전달할 때 자신을 인증하기 위해 사용합니다.
    주요 목적 : 로그 확인, 파드 접속 등
    Etcd Client
    인증서
    apiserver-etcd-client.crt Client Role API 서버가 etcd 데이터베이스에 접근하여 데이터를 읽고 쓸 때 자신을 인증하기 위해 사용합니다.
    주의 - API Server만 허용하도록 설정
    Note: 인증이 실패하면 401 Unauthorized 에러를 반환합니다.
  • 2. 인가 (Authorization) - 권한 확인
    신원이 확인된 사용자가 특정 리소스(Pod, Service 등)에 특정 작업(Get, Create, Delete 등)을 할 권한이 있는지 확인합니다.

    [ 권한 및 리소스 목록 ] - gemini3 pro 참고
    분류 권한 문자열 (Verb) 기능 설명
    연관된 HTTP 메서드
    조회 (Read) get 특정 단일 리소스의 상세 정보 조회 GET
    list 특정 리소스 목록 전체 조회 GET
    watch 리소스의 상태 변화 실시간 감지(스트리밍)
    GET (with watch=true)
    생성/수정 (Write) create 새로운 리소스 생성 POST
    update 기존 리소스 전체 교체 및 덮어쓰기 PUT
    patch 기존 리소스의 특정 필드만 부분 수정 PATCH
    삭제 (Delete) delete 특정 단일 리소스 삭제 DELETE
    deletecollection 조건에 맞는 여러 리소스 일괄 삭제 DELETE
    특수 / 관리 * 모든 권한 허용 (와일드카드) (All)
    impersonate 다른 사용자나 그룹으로 위장하여 실행 -
    bind 다른 대상에게 권한을 부여(RoleBinding) -
    escalate 더 높은 권한의 Role을 생성/수정 -
    분류 리소스 문자열 (Resource) 설명 주로 쓰이는
    워크로드 ( 실행)







    pods 가장 기본이 되는 배포 단위 Role
    deployments 파드의 배포, 스케일링, 버전 관리 Role
    statefulsets 상태를 유지해야 하는 (DB ) Role
    daemonsets 모든 노드마다 실행되어야 하는 파드 Role
    jobs, cronjobs 일회성 또는 주기적인 배치 작업 Role
    네트워크 / 통신



    services 파드들에 대한 고정된 진입점 제공 Role
    ingresses 외부 트래픽을 내부 서비스로 라우팅 Role
    networkpolicies 파드 간의 네트워크 통신 방화벽 Role
    설정 / 스토리지



    configmaps 환경 변수 설정 파일 데이터 Role
    secrets 인증서, 비밀번호 민감한 데이터 Role
    persistentvolumeclaims (PVC) 파드가 요청하는 스토리지 볼륨 Role
    클러스터 / 노드



    nodes 클러스터의 워커/마스터 노드 자체 ClusterRole
    namespaces 클러스터 내의 가상 논리적 분리 공간 ClusterRole
    persistentvolumes (PV) 클러스터에 프로비저닝된 실제 볼륨 ClusterRole
    하위 리소스 (Sub)



    pods/log 파드 자체 제어 없이 로그만 조회 Role
    pods/exec 파드 내부에 접속(exec) 허용 Role
    deployments/scale 디플로이먼트의 스케일링(Replicas 증감) 허용 Role
    - RBAC (Role-Based Access Control): 가장 많이 쓰이는 방식입니다. 역할(Role)을 정의하고 사용자에게 연결(Binding)합니다.
    - ABAC (Attribute-Based Access Control): 속성 기반 제어.
    - Node Authorization: Kubelet이 자신의 리소스만 접근하도록 제한하는 특수 인가 방식.
    - Webhook: 외부 서비스에 인가 여부를 물어보는 방식.

    Note: 인가가 실패하면 403 Forbidden 에러를 반환합니다.
  • 3. 어드미션 제어 (Admission Control) - 요청에 대한 정책 확인
    인증과 인가를 모두 통과했더라도, 클러스터의 정책(예: 리소스 제한, 특정 이미지 사용 금지 등)에 맞는지 최종 확인하고 필요시 요청 내용을 수정합니다.
    - Mutating Admission: 요청 내용을 변경합니다. (예: Resource Limit이 없으면 기본값 삽입)
    - Validating Admission: 요청 내용을 검증하고 거부합니다. (예: 특정 저장소의 이미지가 아니면 거절)
    - Admission Webhooks: 사용자가 정의한 로직으로 외부 서버에서 요청을 검사할 수 있게 해줍니다.

Role-Based Access Control(역할 기반 접근 제어) 모범 사례 - 참고

 

쿠버네티스 공식 문서에서는 RBAC에 대한 모범 사례가 정리된 내용입니다.

 

1. 일반적인 모범 사례

  • 최소 권한의 원칙 (Least Privilege): 사용자나 서비스 어카운트(Service Account)에는 해당 작업을 수행하는 데 명시적으로 필요한 최소한의 권한만 부여해야 합니다. 
# resources 및 verbs에 최소 권한 정의
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: frontend-dev
  name: cicd-deployer
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["patch", "update"] # 이미지를 교체할 권한만 부여, "*"로 정의 시 frontend-dev/cicd-deployer에 대한 모든 권한이 부여되어 좋은 예가 아님
  • 특권 토큰 분배 최소화: 강력한 권한을 가진 파드(Pod)나 데몬셋(DaemonSet)이 실행되는 노드의 수를 제한하여, 컨테이너 탈출 시 발생할 수 있는 피해 범위(Blast Radius)를 줄여야 합니다.
# 좋은 예: 불필요한 API 접근 토큰 마운트 차단
apiVersion: v1
kind: Pod
metadata:
  name: sample-web
spec:
  automountServiceAccountToken: false # 해커가 파드를 털어도 토큰이 없음!
  containers:
  - name: web
    image: nginx
  • 주기적 검토 (Periodic Review): 할당된 RBAC 권한이 여전히 필요한지 정기적으로 검토하고 불필요해진 권한은 즉시 회수해야 합니다. - Rolebinding에 대한 감사 로그를 설정(90일 동안 미동작 시 알람 설정 등)

2. 쿠버네티스 특화 설정 규칙

실제 클러스터를 운영할 때 적용해야 하는 구체적인 설정 가이드라인입니다.

  • 네임스페이스 레벨로 권한 제한: 가능한 한 클러스터 전체에 권한을 주는 ClusterRoleBinding 대신 특정 네임스페이스 내에서만 권한이 유효한 RoleBinding을 우선적으로 사용해야 합니다.
  • 와일드카드(*) 사용 지양: resources: ["*"] 또는 verbs: ["*"]와 같은 와일드카드 사용을 피해야 합니다. 쿠버네티스는 확장 가능한 시스템이므로, 와일드카드를 사용하면 현재 존재하는 리소스뿐만 아니라 추후 생성되는 클러스터에 추가될 새로운 오브젝트 타입에 대해서도 의도치 않게 권한을 열어주게 됩니다.
  • cluster-admin 계정 사용 최소화 및 Impersonation 활용: 운영자는 특별한 이유가 없는 한 최고 관리자(cluster-admin) 권한으로 작업하는 것을 피해야 합니다. 대신 낮은 권한의 계정을 사용하고, 필요한 경우에만 impersonate (가장) 동사를 활용하여 권한을 일시적으로 빌려 쓰는 방식으로 실수로 인한 리소스 변경을 방지해야 합니다.
  • system:masters 그룹에 사용자 추가 금지 (중요): system:masters 그룹에 속한 사용자는 모든 RBAC 권한 검사 및 어드미션 웹훅(Admission Webhook) 검사를 완전히 우회합니다. 이 그룹의 권한은 RoleBinding을 삭제하더라도 회수할 수 없으므로 절대로 일반 사용자를 이 그룹에 묶어서는 안 됩니다.

 

3. 권한 상승(Escalation) 방지 주의사항

특정 권한을 부여할 때는, 그 권한이 우회적으로 더 높은 권한을 얻는 데 악용될 수 있는지(권한 상승)를 주의해야 합니다.

  • Secret에 대한 list 및 watch 권한 주의: Secrets에 대해 목록을 조회(list)할 수 있는 권한을 주면, 시스템 내의 모든 시크릿의 내용까지 유출될 수 있습니다. 정상적인 동작에 필요한 경우에만 get 권한을 허용해야 합니다.
  • 워크로드(Pod 등) 생성 권한의 위험성: 파드를 생성(create)할 수 있는 권한은 사실상 해당 네임스페이스의 모든 Secret이나 ConfigMap을 마운트해서 읽어볼 수 있는 권한과 같습니다. 권한이 높은 서비스 어카운트를 파드에 연결해 간접적으로 권한을 탈취할 수도 있으므로 엄격히 통제해야 합니다.
  • 특수 동사(bind, escalate, impersonate) 엄격한 관리: 자신보다 높은 권한의 롤을 만들거나(escalate), 다른 사용자에게 권한을 부여하거나(bind), 다른 사용자로 위장(impersonate)하는 권한은 클러스터 관리자에게만 제한적으로 부여해야 합니다.

Service Account(SA) 알아보기 - 참고

서비스 어카운트란?

일반 사용자(User Account)가 클러스터를 제어하기 위해 사용하는 계정이라면, 서비스 어카운트는 파드(Pod) 내부에서 실행되는 프로세스(애플리케이션)가 쿠버네티스 API 서버와 통신하기 위해 사용하는 '애플리케이션용 신분증'입니다.

  • 네임스페이스 종속: 일반 사용자 계정은 클러스터 전역에 걸쳐 존재하지만, 서비스 어카운트는 특정 네임스페이스(Namespace) 안에만 존재합니다.
  • 기본 생성: 네임스페이스를 새로 만들면 K8s가 자동으로 default라는 이름의 서비스 어카운트를 하나씩 생성해 둡니다.

작동 방식(Token Volume Projection)

파드가 생성될 때, 쿠버네티스는 해당 파드에 서비스 어카운트의 인증 토큰(JWT)을 볼륨 형태로 마운트(Mount)하여 주입합니다.

  • 기본 경로: /var/run/secrets/kubernetes.io/serviceaccount/
  • 최신 K8s 보안 강화 (Bound Service Account Tokens): 과거에는 만료 기간이 없는 영구적인 Secret 기반 토큰을 사용했지만, K8s 1.22 버전 이후부터는 시간이 지나면 만료되고 파드가 삭제되면 함께 폐기되는 안전한 단기 임시 토큰(Projected Volume)을 기본으로 발급합니다.

Best Practice(보안)

공식 문서에서는 서비스 어카운트 남용으로 인한 클러스터 탈취를 막기 위해 다음 세 가지를 강력히 권고합니다.

  •  애플리케이션마다 전용 Service Account 생성 (최소 권한)
    - 파드를 배포할 때 아무 설정도 하지 않으면 자동으로 default 서비스 어카운트가 부여됩니다. 모든 애플리케이션이 이 default 계정을 공유하도록 방치해서는 안 됩니다.
    - 권장: 파드의 목적에 맞게 SA를 개별 생성하고, 각 파드가 수행할 작업에 딱 맞는 최소한의 Role만 바인딩(RoleBinding)해야 합니다.
  •  API 통신이 불필요한 파드는 자동 마운트 비활성화 (중요)
    단순 정적 웹 서버(Nginx)처럼 K8s API 서버와 통신할 일이 전혀 없는 파드에도 K8s는 기본적으로 토큰을 마운트합니다. 만약 해커가 이 파드를 장악하면 내부 토큰을 악용해 클러스터 정찰을 시도할 수 있습니다.
    - 권장: 파드나 서비스 어카운트 스펙에 automountServiceAccountToken: false를 명시하여, 불필요한 토큰 주입을 원천 차단해야 합니다.
  • default 서비스 어카운트의 권한 부여 금지
    - 각 네임스페이스에 기본 생성되는 default 서비스 어카운트에는 절대로 어떠한 권한(Role)도 바인딩하지 말아야 합니다. 그래야 실수로 서비스 어카운트 지정을 누락한 파드가 배포되더라도, 아무런 권한이 없어 보안 사고를 예방할 수 있습니다.

예시

# 1. 애플리케이션 전용 서비스 어카운트 생성
apiVersion: v1
kind: ServiceAccount
metadata:
  name: web-frontend-sa
  namespace: production
# SA 레벨에서 기본적으로 토큰 자동 마운트 끄기
automountServiceAccountToken: false 

---
# 2. 파드 배포 시 해당 SA를 명시적으로 연결
apiVersion: v1
kind: Pod
metadata:
  name: web-frontend
  namespace: production
spec:
  serviceAccountName: web-frontend-sa # 생성한 전용 SA 지정
  automountServiceAccountToken: false # 파드 레벨에서도 한 번 더 끄기
  containers:
  - name: nginx
    image: nginx:1.21