[AWS EKS] EKS Security 3 - K8S 인증/인가

주영·2025년 3월 14일
0

AWS EKS Workshop Study 3기

목록 보기
20/31

이 글은 CloudNet@팀의 AWS EKS Workshop Study(AEWS) 3기 스터디 내용을 바탕으로 작성되었습니다.
AEWS는 CloudNet@의 '가시다'님께서 진행하는 스터디로, EKS를 학습하는 과정입니다.
EKS를 깊이 있게 이해할 기회를 주시고, 소중한 지식을 나눠주시는 가시다님께 다시 한번 감사드립니다.
이 글이 EKS를 학습하는 분들께 도움이 되길 바랍니다.

1. Kubernetes API 접근 인증(Authentication) 및 인가(Authorization)

Kubernetes에서는 API 서버(Kube API Server)를 통해 클러스터 내 리소스에 접근하며, 보안 강화를 위해 인증(Authentication)과 인가(Authorization) 과정을 거칩니다.

1.1 Kubernetes API 서버 접근 방식

Kubernetes API 서버는 클러스터 내 리소스를 관리하는 핵심 컴포넌트이며, 클라이언트(예: kubectl)가 API 요청을 보낼 때 다음과 같은 방법으로 인증을 수행합니다.

API 서버 접근 방법

  1. kubectl (Kubeconfig 기반)
    • kubectl은 Kubernetes API 서버와 상호작용하는 CLI 도구입니다.
    • 다수의 Kubernetes 클러스터를 관리할 수 있으며, kubeconfig 파일을 통해 인증 정보를 저장합니다.
  2. Service Account 기반 접근
    • Kubernetes에서 실행되는 파드(Pod)는 기본적으로 Service Account를 사용하여 API 서버에 접근합니다.
    • Service Account의 토큰(Token)과 CA 인증서(CA crt)를 Secret에 저장하여 인증 정보를 제공합니다.
  3. X.509 Client Certificates 기반 인증
    • kubeconfig 파일에 CA 인증서(CA crt), 클라이언트 인증서(Client crt), 클라이언트 키(Client key)를 포함하여 인증을 수행합니다.
    • X.509 인증서를 사용하여 HTTPS 기반의 보안된 API 서버 접근이 가능합니다.
  4. HTTPS(TLS) 기반 보안
    • API 서버는 보안 통신을 위해 X.509 인증서를 사용한 TLS 암호화를 적용합니다.
    • 외부 접근 시 보안 강화를 위해 client certificate authentication을 설정할 수 있습니다.

1.2 Kubernetes API 서버 접근 과정

Kubernetes에서 클라이언트가 API 서버에 접근하는 과정은 인증(Authentication) → 인가(Authorization) → Admission Control(승인 제어)의 3단계로 진행됩니다.

API 서버 요청 처리 순서

  1. 인증(Authentication)
    • 요청을 보낸 클라이언트의 신원을 확인하는 과정입니다.
    • X.509 인증서, Service Account, Bearer Token 등의 방식을 활용합니다.
  2. 인가(Authorization)
    • 인증이 완료된 사용자에게 요청된 리소스에 대한 접근 권한이 있는지 확인하는 과정입니다.
    • RBAC(Role-Based Access Control), ABAC(Attribute-Based Access Control), Webhook Authorization, Node Authorization 등의 방법을 활용합니다.
  3. Admission Control (API 요청 검증)
    • API 요청이 클러스터 정책을 준수하는지 확인하며, 필요할 경우 요청을 수정합니다.
    • 예: ResourceQuota, LimitRange 등을 활용하여 리소스 사용량 제한을 설정할 수 있습니다.

1.3 인증(Authentication) 방법

Kubernetes에서는 다양한 인증 방식을 지원하며, 대표적인 방법은 다음과 같습니다.

  1. X.509 Client Certificates
    • kubeconfig 파일에서 CA 인증서(CA crt), 클라이언트 인증서(Client crt), 클라이언트 개인 키(Client key) 정보를 사용하여 인증을 수행합니다.
    • 주로 관리자가 API 서버에 접근할 때 사용됩니다.
  2. kubectl 기반 인증
    • kubectlkubeconfig를 기반으로 여러 개의 클러스터를 관리할 수 있습니다.
    • contexts를 사용하여 서로 다른 클러스터와 유저 정보를 설정할 수 있습니다.
  3. Service Account 기반 인증
    • Kubernetes 내부에서 실행되는 Pod는 기본적으로 Service Account를 통해 API 서버에 접근합니다.
    • Service Account는 Secret에 저장된 CA 인증서 및 Token을 사용하여 인증을 수행합니다.
    • 기본적으로 default Service Account가 할당됩니다.

1.4 인가(Authorization) 방법

Kubernetes에서 인증된 사용자에 대해 API 요청을 허용할지 결정하는 과정이 인가(Authorization)입니다.
대표적인 인가 방식은 다음과 같습니다.

  1. RBAC(Role-Based Access Control)

    • 역할 기반(Role-Based) 접근 제어 방식으로, Kubernetes에서 가장 일반적으로 사용되는 인가 방식입니다.
    • 사용자와 역할(Role)을 별도로 정의한 후, RoleBinding을 통해 사용자에게 특정 역할을 부여합니다.
    • kubectl 또는 API를 통해 권한을 설정할 수 있습니다.
  2. RBAC 개념

    • Namespace/Cluster 역할 구분
      • Role : 특정 네임스페이스 내에서만 적용되는 권한
      • ClusterRole : 클러스터 전체에서 적용되는 권한
    • Binding(바인딩) 개념
      • RoleBinding : 특정 네임스페이스 내에서 Role을 서비스 어카운트에 바인딩
      • ClusterRoleBinding : 클러스터 전체에서 ClusterRole을 서비스 어카운트에 바인딩
  3. 기타 인가 방식

    • ABAC(Attribute-Based Access Control)
      • 속성 기반의 접근 제어 방식으로, JSON 정책 파일을 기반으로 권한을 관리합니다.
    • Webhook Authorization
      • 외부 웹훅(Webhook) 서버를 호출하여 인가 여부를 결정합니다.
    • Node Authorization
      • Kubernetes의 노드(Node) 자체가 API 요청을 수행할 경우에 사용됩니다.

2. 실습 환경

Kubernetes에서는 특정 사용자나 애플리케이션이 클러스터 내 리소스에 접근할 수 있도록 Service Account를 생성하고, 역할(Role)을 부여하여 권한을 제한할 수 있습니다.

이번 실습에서는 다음과 같은 환경을 구성합니다.

  1. 실습 목표

    • 특정 네임스페이스에서만 리소스를 조작할 수 있는 Service Account 생성
    • Service Account에 권한(Role) 할당하여 리소스 접근 제한
    • Service Account를 지정한 kubectl 파드를 생성하고, 권한을 테스트
  2. 실습 환경

    • Kubernetes 클러스터가 실행 중이어야 합니다.
    • kubectl 명령어를 사용하여 클러스터를 관리합니다.
    • 두 개의 Service Account 생성
      • dev-k8s: dev-team 네임스페이스에서 모든 리소스 조작 가능
      • infra-k8s: infra-team 네임스페이스에서 모든 리소스 조작 가능
    • 각각의 Service Account에 맞는 kubectl 파드 생성
      • dev-k8sdev-team 내 리소스 조작 가능
      • infra-k8sinfra-team 내 리소스 조작 가능

3. Namespace 및 Service Account 생성 및 확인

  • 서비스 어카운트(Service Account, SA)
    • Kubernetes에서 파드(Pod) 실행 시 특정 권한을 부여하기 위해 사용되는 계정입니다.
    • 서비스 어카운트는 특정 네임스페이스(Namespace)에 속하며, 파드가 클러스터 내에서 Kubernetes API에 접근하는 인증/인가(Authentication & Authorization) 역할을 합니다.
    • 서비스 어카운트를 명시하지 않으면 기본 서비스 어카운트가 자동 할당됩니다.
    • Kubernetes 1.23 이전 버전에서는 서비스 어카운트에 자동 생성된 시크릿(Secret)에 저장된 토큰이 Kubernetes API 인증 정보로 사용되었습니다.
      1.24 버전 이후에는 서비스 어카운트 토큰 자동 생성 기능이 기본적으로 비활성화됨. (대체 방법: TokenRequest API 활용)
# 네임스페이스(Namespace, NS) 생성 및 확인
kubectl create namespace dev-team
kubectl create ns infra-team

# 네임스페이스 확인
kubectl get ns

# 네임스페이스에 각각 서비스 어카운트 생성 : serviceaccounts 약자(=sa)
kubectl create sa dev-k8s -n dev-team
kubectl create sa infra-k8s -n infra-team

# 서비스 어카운트 정보 확인
kubectl get sa -n dev-team
kubectl get sa dev-k8s -n dev-team -o yaml

kubectl get sa -n infra-team
kubectl get sa infra-k8s -n infra-team -o yaml

4. Service Account를 지정하여 Pod 생성 및 권한 테스트

Kubernetes에서 서비스 어카운트(Service Account)를 지정하여 파드를 생성하고, 해당 파드에서 Kubernetes API 접근 권한을 테스트합니다.

# 각각 네임스피이스에 kubectl 파드 생성 - 컨테이너이미지
# docker run --rm --name kubectl -v /path/to/your/kube/config:/.kube/config bitnami/kubectl:latest
# dev-team 네임스페이스에서 파드 생성
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
  name: dev-kubectl
  namespace: dev-team
spec:
  serviceAccountName: dev-k8s
  containers:
  - name: kubectl-pod
    image: bitnami/kubectl:1.31.4
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
EOF

# infra-team 네임스페이스에서 파드 생성
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
  name: infra-kubectl
  namespace: infra-team
spec:
  serviceAccountName: infra-k8s
  containers:
  - name: kubectl-pod
    image: bitnami/kubectl:1.31.4
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
EOF

# 생성된 파드 확인
kubectl get pod -A
# dev-kubectl 파드의 서비스 어카운트 확인
kubectl get pod -o dev-kubectl -n dev-team -o yaml
 serviceAccount: dev-k8s
 ...
# infra-kubectl 파드의 서비스 어카운트 확인
kubectl get pod -o infra-kubectl -n infra-team -o yaml
 serviceAccount: infra-k8s
...

# 파드에 기본 적용되는 서비스 어카운트(토큰) 정보 확인
kubectl exec -it dev-kubectl -n dev-team -- ls /run/secrets/kubernetes.io/serviceaccount
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/token
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/namespace
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/ca.crt

# 각각 파드로 Shell 접속하여 정보 확인 : 단축 명령어(alias) 사용
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'

# 권한 테스트
k1 get pods # kubectl exec -it dev-kubectl -n dev-team -- kubectl get pods 와 동일한 실행 명령이다!
k1 run nginx --image nginx:1.20-alpine
k1 get pods -n kube-system

k2 get pods # kubectl exec -it infra-kubectl -n infra-team -- kubectl get pods 와 동일한 실행 명령이다!
k2 run nginx --image nginx:1.20-alpine
k2 get pods -n kube-system

# (옵션) kubectl auth can-i 로 kubectl 실행 사용자가 특정 권한을 가졌는지 확인
k1 auth can-i get pods
no

=> 권한이 없으니 에러나는게 정상

5. Kubernetes Namespace별 Role 생성 및 Service Account 바인딩(RoleBinding) 구성

Kubernetes에서 사용자 또는 서비스 어카운트의 권한을 제한하고 관리하는 방식 중 하나는 RBAC(Role-Based Access Control)을 활용하여 Role과 RoleBinding을 설정하는 것입니다.

각각의 네임스페이스 내에서 특정 리소스에 대한 권한을 설정하는 Role을 생성하고, 이를 Service Account와 바인딩하는 과정을 정리합니다.

5.1 개요

Kubernetes의 RBAC(Role-Based Access Control)에서 권한을 부여하는 방식은 다음과 같은 구조로 이루어집니다.

  • Role(롤)

    • 특정 네임스페이스에서 API 그룹(apiGroups), 리소스(resources), 실행 가능한 조작(verbs)을 정의합니다.
    • 예: 특정 네임스페이스 내에서 pods와 services를 생성, 삭제, 조회할 수 있는 권한을 부여하는 역할(Role) 설정 가능
  • RoleBinding(롤 바인딩)

    • Role과 Service Account를 연결하여 Service Account에 특정 권한을 부여합니다.

5.2 Kubernetes API 리소스 조회

# Print the supported API resources on the server.
# 지원되는 API 리소스 목록 확인
kubectl api-resources

# Print the supported API resources with more information
# API 리소스의 상세 정보 확인
kubectl api-resources -o wide
  
# Print the supported API resources with a specific APIGroup
# 특정 API 그룹의 리소스 조회
kubectl api-resources --api-group=""
kubectl api-resources --api-group="apps"
kubectl api-resources --api-group=metrics.k8s.io
kubectl api-resources --api-group=admissionregistration.k8s.io
kubectl api-resources --api-group=rbac.authorization.k8s.io
kubectl api-resources --api-group=apiextensions.k8s.io

5.3 Namespace별 Role 생성

각 네임스페이스에서 서비스 어카운트에 특정 권한을 부여하기 위해 Role을 생성합니다.

# 각각 네임스페이스내의 모든 권한에 대한 롤 생성
# dev-team 네임스페이스의 Role 생성
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: role-dev-team
  namespace: dev-team
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]
EOF

# infra-team 네임스페이스의 Role 생성
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: role-infra-team
  namespace: infra-team
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]
EOF

🔹 설명

  • apiGroups: ["*"] : 모든 API 그룹을 포함합니다.
  • resources: ["*"] : 해당 네임스페이스 내 모든 리소스에 대한 권한을 설정합니다.
  • verbs: ["*"] : 생성, 삭제, 조회 등 모든 작업을 허용합니다.

5.4 생성된 Role 확인

# 롤 확인 
kubectl get roles -n dev-team
kubectl get roles -n infra-team
kubectl get roles -n dev-team -o yaml
kubectl describe roles role-dev-team -n dev-team

# 출력 예시
...
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  *.*        []                 []              [*]

=> 해당 Role이 네임스페이스 내의 모든 리소스에 대한 모든 권한을 가지고 있음을 의미합니다.

5.5 Service Account와 Role 바인딩(RoleBinding)

생성된 Role을 각 네임스페이스의 서비스 어카운트와 바인딩하여 해당 권한을 적용합니다.

# 롤바인딩 생성 : '서비스어카운트 <-> 롤' 간 서로 연동
# dev-team 네임스페이스에서 RoleBinding 생성
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: roleB-dev-team
  namespace: dev-team
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: role-dev-team
subjects:
- kind: ServiceAccount
  name: dev-k8s
  namespace: dev-team
EOF

# infra-team 네임스페이스에서 RoleBinding 생성
cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: roleB-infra-team
  namespace: infra-team
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: role-infra-team
subjects:
- kind: ServiceAccount
  name: infra-k8s
  namespace: infra-team
EOF

🔹 설명

  • roleRef : RoleBinding이 참조하는 Role을 지정합니다.
  • subjects : Role을 적용할 Service Account를 명시합니다.
  • kind: ServiceAccount : Service Account와 연결됨을 의미합니다.

5.6 RoleBinding 확인

# 롤바인딩 확인
kubectl get rolebindings -n dev-team
kubectl get rolebindings -n infra-team
kubectl get rolebindings -n dev-team -o yaml
kubectl describe rolebindings roleB-dev-team -n dev-team

# 출력 예시
...
Role:
  Kind:  Role
  Name:  role-dev-team
Subjects:
  Kind            Name     Namespace
  ----            ----     ---------
  ServiceAccount  dev-k8s  dev-team

6. Service Account를 지정하여 생성한 Pod에서 권한 테스트

6.1 단축 명령어(alias) 설정

# 각각 파드로 Shell 접속하여 정보 확인 : 단축 명령어(alias) 사용
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'

🔹 설명

  • k1dev-kubectl 파드에서 실행하는 kubectl 명령을 의미합니다.
  • k2infra-kubectl 파드에서 실행하는 kubectl 명령을 의미합니다.

6.2 권한 테스트

1. dev-k8s 서비스 어카운트(dev-kubectl)에서 테스트

k1 get pods 
k1 run nginx --image nginx:1.20-alpine
k1 get pods
k1 delete pods nginx
k1 get pods -n kube-system
k1 get pods -n kube-system -v=6
k1 get nodes
k1 get nodes -v=6

2. infra-k8s 서비스 어카운트(infra-kubectl)에서 테스트

k2 get pods 
k2 run nginx --image nginx:1.20-alpine
k2 get pods
k2 delete pods nginx
k2 get pods -n kube-system
k2 get nodes

6.3 권한 확인

각 서비스 어카운트가 특정 작업을 수행할 수 있는지 확인하기 위해 kubectl auth can-i 명령어를 사용합니다.

# (옵션) kubectl auth can-i 로 kubectl 실행 사용자가 특정 권한을 가졌는지 확인
k1 auth can-i get pods
yes

🔹 설명

  • 현재 사용자(= dev-k8s 서비스 어카운트)가 get pods 명령을 실행할 수 있는지 확인합니다.
  • 만약 yes가 출력되면 해당 네임스페이스에서 파드 조회 권한이 있음을 의미합니다.
  • 만약 no가 출력되면 해당 권한이 없음을 의미하며, 추가적인 RoleBinding 설정이 필요합니다.

7. 실습 리소스 삭제

kubectl delete ns dev-team infra-team

1개의 댓글

comment-user-thumbnail
2025년 3월 14일

안녕하세요 주영님
IT교육 전문플랫폼 스나이퍼팩토리입니다!
AI·클라우드 개발을 배우고 싶은 분들께 도움이 될 것 같아 공유 드립니다.
현재 카카오엔터프라이즈X고용노동부가 함께하는 ‘카카오클라우드 AIaaS’ 과정이 열리고 있습니다.

✔️ 내일배움카드만 있으면 전액 무료 수강 가능
✔️ 매달 훈련장려금 + 국취제 최대 80만 원 지원
✔️ 실무 중심 교육 + 취업 포트폴리오 제작 기회

3/19(수)에 모집이 마감되오니,
아래 링크 또는 저희 스나이퍼팩토리 블로그 내용 확인해보시고
참여를 원하시는 경우 신청해보시기를 추천 드립니다 :)
감사합니다.

관련 링크 : https://buly.kr/APuaouj

답글 달기