AWS Cloud School 13기 78일차

Forever 김·2026년 4월 21일

AWS Cloud School

목록 보기
72/97

AWS Cloud School 13기 78일차

TIL

배운 내용

쿠버네티스(4) - RBAC, Dynamic Provisioner, StatefulSet, 헬스체크, HPA

오늘은 쿠버네티스의 보안과 운영 관련 핵심 개념들을 집중적으로 다뤘다. 어제 배운 PV/PVC, ConfigMap, Secret을 활용한 3 Tier 과제 풀이로 시작해서, 접근 제어(RBAC), 자동 스토리지 프로비저닝, 그리고 Pod 상태 관리까지 이어졌다.


RBAC (Role Based Access Control, 역할 기반 접근 제어)

공식 정의: RBAC는 조직 내 개별 사용자의 역할(Role)을 기반으로 컴퓨터 또는 네트워크 리소스에 대한 접근을 규제하는 방법이다. 쿠버네티스에서는 rbac.authorization.k8s.io API 그룹을 통해 구현되며, 관리자가 어떤 사용자나 서비스 계정이 어떤 리소스에 어떤 작업을 수행할 수 있는지 동적으로 구성할 수 있다.
Kubernetes 공식 문서

쿠버네티스에서 누가 무엇을 할 수 있는지 제어하는 메커니즘이다.

  • 인증(Authentication): 내가 누구인지 식별 (로그인)
  • 인가(Authorization): 내가 어떤 행동을 할 수 있는지 권한 부여

AWS IAM과 비교하면 이해가 쉽다.

구분k8sAWS
권한 정의Role / ClusterRolePolicy
권한 부여RoleBinding / ClusterRoleBindingRole에 Policy 연결
대상ServiceAccount (SA)IAM User / Role

주의: k8s의 Role과 AWS의 Role은 이름은 같지만 개념이 다르다. k8s Role은 AWS의 Policy에 가깝다.

Role vs ClusterRole

쿠버네티스 RBAC의 4가지 핵심 오브젝트는 다음과 같다.

오브젝트범위설명
Role네임스페이스특정 네임스페이스 내 리소스에 대한 권한 집합
ClusterRole클러스터 전체모든 네임스페이스 또는 클러스터 수준 리소스에 대한 권한 집합
RoleBinding네임스페이스Role을 특정 사용자/SA에 연결
ClusterRoleBinding클러스터 전체ClusterRole을 특정 사용자/SA에 연결
  • SA (Service Account): 사람이 아닌 Pod 같은 프로세스에 부여하는 계정. 쿠버네티스 API 서버와 통신할 때 사용하는 자격증명이다.

구성 순서는 이렇다.

SA 생성 → ClusterRole(권한) 생성 → ClusterRoleBinding으로 SA에 연결

실습: Pod 조회만 가능한 kubeconfig 구성

전체 구성 순서는 SA → Secret(토큰) → ClusterRole → ClusterRoleBinding 순이다.

# 1. ServiceAccount 생성
apiVersion: v1
kind: ServiceAccount
metadata:
  name: pod-reader-sa
---
# 2. SA 인증용 Secret(토큰) 생성
apiVersion: v1
kind: Secret
metadata:
  name: pod-reader-token
  namespace: default
  annotations:
    kubernetes.io/service-account.name: pod-reader-sa
type: kubernetes.io/service-account-token
---
# 3. ClusterRole - pod 조회만 허용
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-reader-crole
rules:
- apiGroups: [""]   # "" = core API group (Pod, Service, ConfigMap 등)
  resources: ["pods"]
  verbs: ["get", "list"]  # 허용할 동작
---
# 4. ClusterRoleBinding - SA에 ClusterRole 연결
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: pod-reader-crolebinding
subjects:
- kind: ServiceAccount
  name: pod-reader-sa
  namespace: default
roleRef:
  kind: ClusterRole
  name: pod-reader-crole
  apiGroup: rbac.authorization.k8s.io
# SA 토큰 추출 (base64 디코딩)
kubectl get secret pod-reader-token -o jsonpath='{.data.token}' | base64 --decode

# 기존 kubeconfig를 복사해서 토큰만 교체
cp ~/.kube/config ./myconfig

# 특정 kubeconfig로 명령 실행
kubectl get pods --kubeconfig=myconfig   # ✅ 성공 (pod 조회 권한 있음)
kubectl get svc --kubeconfig=myconfig    # ❌ 실패 (svc 조회 권한 없음)

결과: pod는 조회되지만 svc는 Error from server (Forbidden) 오류가 발생한다. RBAC가 정확히 동작하는 것을 확인할 수 있다.


Dynamic Provisioner (동적 프로비저닝)

공식 정의: Dynamic Volume Provisioning은 스토리지 볼륨을 온디맨드로 자동 생성할 수 있게 해준다. 정적 프로비저닝에서는 클러스터 관리자가 PV를 수동으로 미리 생성해야 했지만, 동적 프로비저닝을 사용하면 사용자가 PVC를 생성할 때 StorageClass에 정의된 프로비저너가 자동으로 PV를 생성한다.
Kubernetes 공식 문서

어제 배운 PV/PVC는 관리자가 PV를 미리 만들어둬야 했다. Dynamic Provisioner는 PVC 요청이 오면 자동으로 PV와 디렉토리를 생성해주는 기능이다.

PVC 생성 요청
    ↓
StorageClass가 Dynamic Provisioner에 전달
    ↓
Provisioner가 자동으로 PV + NFS 디렉토리 생성
    ↓
PVC와 PV 자동 Bind

정적 vs 동적 프로비저닝 비교

구분정적(Static)동적(Dynamic)
PV 생성 시점PVC 요청 전 관리자가 미리 생성PVC 요청 시 자동 생성
관리 부담높음낮음
유연성낮음높음
필요 조건없음StorageClass + Provisioner

EKS에서는 EFS CSI 드라이버를 통해 동적 프로비저닝을 구현한다. gp2, gp3 같은 스토리지 클래스가 바로 이 개념이다.

핵심은 StorageClass에 provisioner를 지정하는 것이다. PVC에서 storageClassName을 명시하면 해당 프로비저너가 자동으로 PV를 만들어준다.


StatefulSet / DaemonSet

StatefulSet

공식 정의: StatefulSet은 상태가 있는(stateful) 애플리케이션을 관리하기 위한 워크로드 API 오브젝트다. Deployment와 달리 각 Pod에 고유하고 지속적인 식별자(이름, 네트워크 ID, 스토리지)를 부여하며, Pod가 재스케줄링되어도 이 식별자는 유지된다.
Kubernetes 공식 문서

일반 Deployment로 Pod를 띄우면 이름이 랜덤하게 생성된다. StatefulSet은 Pod 이름을 규칙적으로 생성한다.

# Deployment로 생성 시 (이름 예측 불가)
my-dep-7d4f9b8c6-xk2pq
my-dep-7d4f9b8c6-mn8rt

# StatefulSet으로 생성 시 (이름이 규칙적)
sts-mysql-0   ← 0번부터 순서대로 생성
sts-mysql-1
sts-mysql-2   ← 삭제는 역순 (210)

Deployment와의 차이점:

구분DeploymentStatefulSet
Pod 이름랜덤 해시순번 인덱스 (0, 1, 2...)
스케일링 순서동시 생성/삭제순서대로 생성, 역순으로 삭제
스토리지공유 가능각 Pod마다 독립적인 PVC
적합한 앱무상태(stateless)상태 있는(stateful) DB, 캐시

serviceName을 반드시 지정해야 하고, 해당 이름의 Headless Service도 함께 만들어줘야 한다.

DaemonSet

공식 정의: DaemonSet은 모든(또는 일부) 노드가 Pod의 복사본을 실행하도록 보장한다. 클러스터에 노드가 추가되면 해당 노드에 Pod가 자동으로 추가되고, 노드가 제거되면 Pod도 가비지 컬렉션된다.
Kubernetes 공식 문서

모든 노드에 반드시 하나씩 Pod를 배치하고 싶을 때 사용한다.

대표적인 사용 사례:

  • 클러스터 스토리지 데몬: glusterd, ceph
  • 로그 수집 데몬: fluentd, logstash
  • 노드 모니터링 데몬: Prometheus Node Exporter, Datadog agent
  • 시스템 컴포넌트: kube-proxy, metallb speaker

노드가 추가되면 자동으로 해당 노드에도 Pod가 생성된다.


컨테이너 헬스체크 (Probe)

공식 정의: kubelet은 컨테이너의 상태를 진단하기 위해 Probe를 주기적으로 실행한다. 진단 결과에 따라 컨테이너를 재시작하거나 트래픽 라우팅에서 제외하는 등의 조치를 취한다.
Kubernetes 공식 문서

livenessProbe vs readinessProbe vs startupProbe

구분livenessProbereadinessProbestartupProbe
실패 시 동작컨테이너 재시작서비스에서 트래픽 차단liveness/readiness 비활성화
용도컨테이너 이상 감지 (데드락 등)트래픽 수신 준비 여부느린 시작 앱 보호
실패해도 Pod 삭제?X (재시작만)XX

readinessProbe가 실패하면 Pod는 살아있지만 Service의 Endpoint에서 제외된다. 즉, 트래픽이 해당 Pod로 가지 않는다.

실제로 확인해보면, readinessProbe가 실패한 Pod는 kubectl get pods에서 READY 0/1 상태로 표시된다. 그리고 kubectl describe svc로 확인하면 해당 Pod의 IP가 Endpoints에 잡히지 않는다. Pod 자체는 Running이지만 서비스에서 완전히 격리된 상태다.

Probe 방식 3가지

# 1. httpGet - HTTP 200~399 응답 확인 (웹 서버에 적합)
readinessProbe:
  httpGet:
    path: /
    port: 80
  periodSeconds: 5        # 체크 주기 (초)
  initialDelaySeconds: 2  # 컨테이너 시작 후 첫 체크까지 대기 시간

# 2. tcpSocket - TCP 포트 연결 확인 (HTTP가 아닌 앱: MySQL, Redis 등)
readinessProbe:
  tcpSocket:
    port: 6379

# 3. exec - 명령어 종료 코드로 확인 (0이면 성공, 그 외 실패)
readinessProbe:
  exec:
    command: ["mysqladmin", "ping", "-ppassword"]

Probe 주요 파라미터

파라미터설명기본값
initialDelaySeconds컨테이너 시작 후 첫 Probe까지 대기 시간0
periodSecondsProbe 실행 주기10
timeoutSecondsProbe 타임아웃1
failureThreshold연속 실패 횟수 (이후 조치 실행)3
successThreshold연속 성공 횟수 (정상으로 판단)1

HPA (Horizontal Pod Autoscaler)

공식 정의: HPA는 CPU 사용률 또는 커스텀 메트릭을 기반으로 Deployment, ReplicaSet, StatefulSet의 Pod 수를 자동으로 스케일링한다. 수직 스케일링(VPA, 리소스 증가)과 달리 수평 스케일링(Pod 수 증가)을 담당한다.
Kubernetes 공식 문서

트래픽에 따라 Pod 개수를 자동으로 조절하는 기능이다.

HPA 동작 원리

Metrics Server → 각 Pod의 CPU/메모리 수집
      ↓
HPA Controller → 현재 사용률 vs 목표 사용률 비교
      ↓
목표 Pod 수 계산: ceil(현재 Pod 수 × (현재 사용률 / 목표 사용률))
      ↓
Deployment replicas 자동 조정

동작하려면 Metrics Server가 필요하다. Pod의 CPU/메모리 사용량을 수집해서 HPA가 판단 기준으로 삼는다.

# Metrics Server 설치 (공식 GitHub에서 manifest 다운로드)
curl -Ls https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml -o metric.yml
# insecure-tls 옵션 추가 후 적용 (실습 환경)
kubectl apply -f metric.yml

# CPU 50% 초과 시 최소 1개, 최대 5개로 자동 스케일링
kubectl autoscale deploy my-dep --min=1 --max=5 --cpu-percent=50

# HPA 상태 확인
kubectl get hpa
# NAME     REFERENCE           TARGETS   MINPODS   MAXPODS   REPLICAS
# my-dep   Deployment/my-dep   8%/50%    1         5         3

# 트래픽 부하 발생 (ClusterIP로 반복 요청)
i=1; while true; do sleep 0.001; echo $((i++)) `curl -s <svc의 ClusterIP>`; done

HPA 동작 조건

  • Pod에 resources.requests반드시 설정되어 있어야 한다. requests가 없으면 CPU 사용률 계산이 불가능하다.
  • 스케일 다운은 기본적으로 5분 쿨다운이 있다 (급격한 축소 방지).
  • Deployment의 replicas 설정과 무관하게 HPA가 우선 적용된다.

HPA vs VPA vs KEDA

구분HPAVPAKEDA
스케일링 방향수평 (Pod 수)수직 (CPU/메모리 크기)이벤트 기반 수평
기준 메트릭CPU, 메모리CPU, 메모리큐 길이, HTTP 요청 수 등
적합한 경우웹 서버, API단일 Pod 앱메시지 큐, 배치 처리

오늘은 쿠버네티스 운영에서 실제로 많이 쓰이는 개념들을 다뤘다. RBAC는 AWS IAM과 비교해서 이해하니까 훨씬 빠르게 잡혔고, Dynamic Provisioner는 EKS에서 EFS 쓸 때 바로 연결되는 개념이라 더 와닿았다. HPA는 오토스케일링 개념 자체는 알고 있었는데 실제로 메트릭 서버 설치부터 직접 해보니까 내부 동작이 명확해졌다.

이번 velog도 AWS Kiro를 통해 작성하였다. 이번에는 3Tier를 구현한 실습도있어서 같이 올리도록 하겠다.

profile
나를 한줄로

0개의 댓글