[IT-방법] 쿠버네티스 디플로이먼트 보안 설정 가이드 – 권한 최소화 원칙 적용부터 실전 취약점 차단까지

디플로이먼트 관련 쿠버네티스 구조를 설명하는 대표 이미지

왜 지금 디플로이먼트 보안에 집중해야 할까요

어느 날 갑자기 서비스가 중단되었다는 알람을 받고 서버에 접속했을 때, 클러스터 전체가 공격자에게 장악된 것을 발견한다면 얼마나 아찔할까요? 소규모 스타트업의 1인 서버 담당자라면 이런 시나리오가 단순한 악몽이 아니라 곧 닥칠 수 있는 현실이라는 점을 명심해야 해요. 잘못 설정된 단 하나의 디플로이먼트 설정이 클러스터 전체의 통제권을 공격자에게 넘겨주는 통로가 될 수 있거든요.

많은 경우, 개발 편의성을 위해 기본 설정 그대로 디플로이먼트를 배포하곤 해요. 하지만 쿠버네티스의 기본값은 보안보다는 운영의 편의성에 초점이 맞춰져 있어요. 만약 특정 컨테이너가 탈취되었을 때, 그 컨테이너가 가진 권한이 너무 크다면 공격자는 아주 손쉽게 다른 포드(Pod)로 이동하거나 노드(Node)의 권한을 탈취할 수 있어요. 이것이 바로 우리가 디플로이먼트 보안 설정을 최우선 과제로 삼아야 하는 이유예요.

보안 사고는 발생한 뒤에 수습하는 것보다, 사고가 발생할 수 있는 경로를 미리 차단하는 것이 훨씬 경제적이에요. 특히 인력이 부족한 환경에서는 자동화된 정책과 최소한의 규칙만으로도 강력한 방어선을 구축할 수 있어요. 이 글을 통해 여러분은 단순히 이론적인 보안이 아니라, 당장 오늘 퇴근 전에 적용할 수 있는 실전적인 방어 전략을 배우게 될 거예요.

오늘 글에서는 다음과 같은 핵심 내용을 다뤄요.

  • 디플로이먼트가 가질 수 있는 주요 보안 위협 지점
  • 서비스 어카운트와 RBAC를 활용한 권한 최소화 설계
  • Pod Security Context를 이용한 컨테이너 격리 방법
  • 네트워크 정책과 정책 도구를 활용한 보안 강제화
  • 실제 운영 환경에서의 점검 및 감사 로그 확인 절차

보안 설정을 시작하기 전 꼭 알아야 할 기초 지식

보안 설정을 무작정 시작하기 전에, 우리가 어떤 기준으로 방어 체계를 구축해야 하는지 명확히 이해해야 해요. 보안은 단순히 막는 것이 아니라, 서비스 운영에 지장을 주지 않으면서 위험 요소를 최소화하는 예술에 가까워요. 무조건 모든 권한을 막아버리면 서비스가 동작하지 않는 장애가 발생할 수 있으니 주의해야 해요.

가장 먼저 이해해야 할 개념은 심층 방어(Defense in Depth)예요. 하나의 보안 계층이 뚫리더라도 다음 계층에서 공격을 막아낼 수 있도록 여러 단계의 방어선을 구축하는 전략을 의미해요. 디플로이먼트 보안에서도 RBAC, 네트워크 정책, 컨테이너 설정이라는 세 가지 방어선을 겹겹이 쌓아야 해요.

또한, 우리는 최소 권한 원칙(Principle of Least Privilege)을 절대적인 기준으로 삼아야 해요. 어떤 서비스나 포드가 특정 작업을 수행하는 데 필요한 최소한의 권한만 부여하는 것이죠. 예를 들어, 로그를 읽기만 하면 되는 앱에 클러스터 전체를 관리할 수 있는 권한을 주는 것은 아주 위험한 행동이에요.

아래 표는 보안 설정의 강도에 따라 어떤 차이가 있는지 비교한 내용이에요. 여러분의 현재 상황에 맞는 목표 수준을 정해보세요.

구분 권한 특권 포드(Privileged) 제한적 포드(Restricted)
루트 권한 실행 Root 사용자 사용 가능 비루트(Non-root) 사용자 필수
권한 상승 허용 allowPrivilegeEscalation: true false로 설정 필수
파일 시스템 권한 쓰기 가능 (Read-Write) 읽기 전용 (Read-Only) 권장
커널 기능 접근 모든 커널 기능 접근 가능 필요한 기능만 선택적 허용

현실적으로 소규모 운영 환경에서는 처음부터 모든 것을 Restricted 모드로 맞추기가 어려울 수 있어요. 서비스가 중단될 수 있기 때문이죠. 그래서 우리는 단계적으로 보안을 강화하는 전략을 취해야 해요. 우선순위를 정할 때는 서비스의 노출 정도를 고려하세요. 외부 인터넷에서 직접 접속 가능한 서비스라면 가장 높은 보안 수준을 적용해야 하고, 내부 관리용 도구라면 조금 더 유연하게 설정할 수 있어요.

💡 알아두기
보안 설정을 변경하기 전에는 반드시 스테이징(Staging) 환경에서 먼저 테스트를 거쳐야 해요. 보안 정책이 너무 엄격하면 애플리케이션이 실행되자마자 권한 거부(Permission Denied) 오류를 내며 종료될 수 있거든요.

실전 디플로이먼트 보안 강화 5단계

이제 본격적으로 디플로이먼트의 보안을 강화하는 구체적인 단계들을 살펴볼게요. 각 단계는 독립적이면서도 서로 연결되어 하나의 견고한 방어 체계를 형성해요. 이 과정들을 차근차근 따라오면 여러분의 클러스터는 훨씬 안전해질 거예요.

STEP 1. RBAC를 이용한 서비스 어카운트 권한 최소화

쿠버네티스에서 각 포드는 ServiceAccount라는 신분증을 가지고 통신해요. 많은 관리자가 귀찮다는 이유로 모든 디플로이먼트에 기본(default) 서비스 어카운트를 그대로 사용하곤 해요. 하지만 이것은 공격자에게 클러스터 내부를 돌아다닐 수 있는 마스터키를 쥐여주는 것과 같아요.

먼저, 각 애플리케이션마다 전용 서비스 어카운트를 생성하세요. 그리고 해당 서비스가 꼭 필요한 API 작업(예: ConfigMap 읽기, Pod 조회)만 수행할 수 있도록 Role을 정의하고, 이를 해당 서비스 어카운트에 RoleBinding으로 연결해야 해요. 만약 클러스터 전체에 영향을 주는 작업이 필요하다면 ClusterRole을 쓰겠지만, 대부분의 애플리케이션은 특정 네임스페이스(Namespace) 안에서만 움직이므로 Role로 충분해요.

공격자는 포드를 탈취한 후 `/var/run/secrets/kubernetes.io/serviceaccount/token` 경로에 있는 토큰을 훔칩니다. 이때 이 토큰이 가진 권한이 `cluster-admin`이라면 클러스터는 끝난 것이나 다름없어요. 따라서 서비스 어카운트의 권한은 반드시 ‘읽기 전용’ 혹은 ‘특정 리소스 한정’으로 설계해야 해요.

STEP 2. Pod Security Context로 컨테이너 격리하기

디플로이먼트 YAML 파일의 `securityContext` 섹션은 컨테이너의 행동을 제어하는 가장 강력한 도구예요. 여기서 몇 가지 설정만 제대로 해도 공격의 난이도가 비약적으로 상승해요.

가장 중요한 설정은 runAsNonRoot: true예요. 많은 컨테이너 이미지가 편의상 root 사용자로 실행되도록 만들어져 있어요. 하지만 컨테이너 내부에서 root 권한을 얻게 되면, 호스트 시스템(노드)의 커널에 접근할 수 있는 위험이 커져요. 반드시 사용자 ID(UID)를 지정하여 일반 사용자 권한으로 실행되도록 강제하세요.

그 다음으로는 allowPrivilegeEscalation: false 설정을 넣으세요. 이는 자식 프로세스가 부모 프로세스보다 더 높은 권한을 얻으려고 시도하는 것을 막아줘요. 마지막으로 readOnlyRootFilesystem: true를 적용하면, 공격자가 컨테이너 내부의 시스템 파일을 수정하거나 악성 스크립트를 저장하는 것을 원천적으로 차단할 수 있어요. 로그나 임시 파일은 별도의 `emptyDir` 볼륨을 마운트해서 사용하면 돼요.

STEP 3. 네트워크 정책(Network Policy)으로 통신 경로 차단

기본적으로 쿠버네티스의 모든 포드는 서로 자유롭게 통신할 수 있어요. 이는 편리하지만, 보안 측면에서는 재앙이에요. 웹 서버 포드가 뚫렸을 때, 공격자가 내부망에 있는 데이터베이스(DB) 포드에 직접 접속할 수 있다는 뜻이기 때문이죠.

이를 막기 위해 네트워크 정책을 사용해야 해요. 가장 권장하는 방식은 ‘Default Deny’ 전략이에요. 즉, 모든 네임스페이스의 모든 인바운드(Ingress) 및 아웃바운드(Egress) 통신을 일단 모두 차단하는 거예요. 그 다음, 서비스 운영에 꼭 필요한 통신 경로만 화이트리스트 방식으로 하나씩 허용해 나가는 방식이죠.

예를 들어, 웹 서버 포드는 외부 로드밸런서로부터의 접속만 허용하고, 데이터베이스 포드는 오직 웹 서버 포드의 라벨(Label)을 가진 포드로부터의 접속만 허용하도록 정책을 짜야 해요. 이렇게 하면 웹 서버가 침해당하더라도 공격자가 내부의 다른 서비스로 확산하는 것을 효과적으로 막을 수 있어요.

STEP 4. 이미지 보안 및 취약점 스캔 자동화

디플로이먼트가 사용하는 컨테이너 이미지 자체가 이미 감염되어 있다면 아무리 설정을 잘해도 소용이 없어요. 따라서 이미지 생명 주기 전체에 걸친 보안 관리가 필요해요. 우선, 신뢰할 수 있는 레지스트리(Registry)에서 검증된 이미지만 사용하세요. 베이스 이미지는 가급적 가벼운 Distroless 이미지나 Alpine Linux를 사용하는 것이 공격 표면을 줄이는 데 유리해요.

또한, CI/CD 파이프라인 단계에서 이미지 취약점 스캔(Vulnerability Scanning)을 반드시 수행하세요. Trivy나 Grype 같은 도구를 활용하면 이미지 내부에 포함된 라이브러리의 알려진 보안 취약점(CVE)을 자동으로 찾아낼 수 있어요. 만약 심각한 취약점이 발견된다면, 빌드 단계에서 배포를 자동으로 중단시키도록 설정하세요.

STEP 5. 정책 도구(Kyverno/OPA)를 통한 보안 강제화

관리자가 매번 YAML 파일을 수동으로 검사하는 것은 불가능에 가까워요. 사람이 실수할 수 있기 때문이죠. 그래서 Admission Controller를 활용한 정책 자동화가 필요해요. 대표적인 도구로는 Kyverno와 OPA(Open Policy Agent)가 있어요.

이런 도구들을 사용하면 클러스터에 새로운 디플로이먼트가 생성될 때, 설정이 보안 규칙에 맞는지 자동으로 검사할 수 있어요. 예를 들어 “root 사용자로 실행되는 포드는 생성할 수 없다”라거나 “특정 라벨이 없는 디플로이먼트는 거부한다”라는 규칙을 만들어 두면, 개발자가 실수로 보안에 취약한 설정을 올리더라도 클러스터 수준에서 즉시 차단할 수 있어요. 이것이 바로 보안을 운영의 일부로 만드는 가장 똑똑한 방법이에요.

⚠️ 주의
보안 정책을 처음 도입할 때는 ‘Enforce(강제)’ 모드 대신 ‘Audit(감사)’ 모드를 먼저 사용하세요. 정책 위반 사례를 먼저 로그로 확인한 뒤, 서비스 영향도를 분석하고 나서 실제 차단 모드로 전환하는 것이 안전해요.

아래는 보안이 강화된 디플로이먼트의 표준 예시 코드예요. 참고해서 여러분의 환경에 맞춰 적용해 보세요.

💡 알아두기
다음은 보안 설정이 잘 적용된 디플로이먼트 YAML의 핵심 부분이에요.
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
spec:
template:
spec:
serviceAccountName: secure-app-sa
securityContext:
runAsNonRoot: true
runAsUser: 1000
containers:
– name: app-container
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:<
– ALL

자주 하는 실수와 해결법

현장에서 보안 설정을 적용하다 보면 예상치 못한 오류 때문에 당황하는 경우가 많아요. 주로 발생하는 실수들과 그 해결책을 정리했으니, 비슷한 문제에 부딪혔을 때 참고해 보세요.

  • 실수: 애플리케이션이 실행되자마자 종료됨 (CrashLoopBackOff) → 왜 발생하는가: readOnlyRootFilesystem: true를 설정했는데, 앱이 임시 파일이나 로그를 쓰려고 시도했기 때문이에요. → ✅ 해결법: 로그나 임시 데이터가 저장될 경로는 emptyDir 볼륨을 사용하여 별도로 마운트해 주세요.
  • 실수: 권한 오류(Permission Denied)로 파일에 접근 불가 → 왜 발생하는가: runAsNonRoot: true를 설정했지만, 이미지 내부 파일들의 소유권이 여전히 root에게 있기 때문이에요. → ✅ 해결법: Dockerfile 단계에서 chown 명령어를 사용해 필요한 디렉토리의 소유권을 실행 사용자 ID로 미리 변경해 두어야 해요.
  • 실수: 네트워크 통신이 갑자기 안 됨 → 왜 발생하는가: NetworkPolicy를 적용하면서 필요한 통신 경로(Egress/Ingress)를 누락했기 때문이에요. → ✅ 해결법: 네트워크 로그를 확인하여 어떤 포드와 포트가 통신을 시도하는지 파악한 후, 해당 규칙을 화이트리스트에 추가하세요.
  • 실수: RBAC 설정 후 API 호출 실패 → 왜 발생하는가: Role에 필요한 Verbs(get, list, watch 등)를 충분히 정의하지 않았기 때문이에요. → ✅ 해결법: 에러 메시지에 나타난 권한 부족 내용을 확인하고, 최소한의 필요한 동작만 Role에 추가하세요.
  • 실수: 모든 것을 해결하려고 ClusterRoleBinding을 남발함 → 왜 발생하는가: 네임스페이스 구분이 복잡해지면서 관리가 귀찮아졌기 때문이에요. → ✅ 해결법: 최대한 Role과 RoleBinding을 사용하여 범위를 네임스페이스로 한정하세요. 클러스터 수준의 권한은 정말 예외적인 경우에만 사용해야 해요.

자주 묻는 질문

Q. 보안 설정을 하면 서비스 성능이 떨어지지는 않나요?

성능 저하는 거의 없다고 보셔도 돼요. RBAC이나 Pod Security Context는 쿠버네티스 컨트롤 플레인이 설정을 검증하거나 커널이 권한을 체크하는 과정일 뿐이라, 애플리케이션의 CPU나 메모리 사용량에 직접적인 영향을 주지는 않아요. 오히려 보안 사고로 인한 서비스 중단 리스크를 줄이는 이득이 훨씬 커요.

Q. 보안 정책을 적용하기 가장 쉬운 순서가 있을까요?

처음에는 runAsNonRootallowPrivilegeEscalation: false 두 가지만이라도 먼저 적용해 보세요. 이 두 설정만으로도 가장 흔한 공격 경로를 상당 부분 차단할 수 있어요. 그 다음에 서비스 어카운트 권한을 하나씩 줄여나가는 것을 추천해요.

Q. 이미 사용 중인 운영 환경에 바로 적용해도 될까요?

절대 안 돼요! 반드시 스테이징 환경에서 충분히 테스트해야 해요. 특히 readOnlyRootFilesystem 설정은 앱의 동작 방식을 완전히 바꿀 수 있으므로, 앱이 파일을 쓰는 모든 지점을 파악한 뒤에 적용해야 장애를 막을 수 있어요.

Q. 네트워크 정책은 모든 포드에 다 걸어야 하나요?

네, 가급적 모든 네임스페이스에 기본적으로 모든 통신을 차단하는 정책을 깔아두는 것이 좋아요. 그 후 서비스 간의 관계를 파악하여 필요한 것만 열어주는 방식이 가장 안전하고 관리하기도 편해요.

Q. 보안 도구(Kyverno 등)를 배우는 게 너무 어려운데 대안이 있나요?

도구를 배우는 게 부담스럽다면, 일단 쿠버네티스 자체의 Pod Security Admission(PSA) 기능을 먼저 활용해 보세요. 별도의 설치 없이 네임스페이스 수준에서 보안 레벨(Privileged, Baseline, Restricted)을 지정할 수 있는 매우 강력하고 쉬운 기능이에요.

안전한 운영을 위한 마지막 점검

쿠버네티스 디플로이먼트 보안은 한 번의 설정으로 끝나는 것이 아니라, 지속적인 관심과 관리가 필요한 과정이에요. 오늘 배운 내용을 바탕으로 여러분의 클러스터를 다시 한번 돌아보세요. 보안은 ‘귀찮은 작업’이 아니라, 서비스의 생명력을 연장하는 ‘가장 가치 있는 투자’라는 점을 잊지 마세요.

✅ 핵심 요약

  • 최소 권한 원칙: 전용 ServiceAccount를 생성하고 필요한 권한만 부여하세요.
  • 컨테이너 격리: Non-root 실행과 권한 상승 차단을 필수적으로 설정하세요.
  • 파일 시스템 보호: 가급적 읽기 전용 파일 시스템을 사용하여 변조를 막으세요.
  • 네트워크 차단: Default Deny 정책을 기반으로 필요한 통신만 허용하세요.
  • 자동화된 검증: 이미지 스캔과 정책 도구를 통해 실수를 방어하세요.

지금 바로 무엇부터 해야 할지 막막하다면, 아래의 단계별 실행 계획을 따라 해 보세요.

  • 오늘 할 일: 현재 운영 중인 디플로이먼트 중 외부 노출이 심한 서비스의 ServiceAccount 권한을 확인해 보세요.
  • 이번 주 할 일: 스테이징 환경에서 runAsNonRoot: true 설정을 적용하고 앱이 정상 동작하는지 테스트해 보세요.
  • 실행 직전 할 일: 네트워크 정책을 적용하기 전에 현재 서비스 간의 통신 흐름을 문서화하거나 로그로 기록해 두세요.

실전 환경에서 직접 적용해 보시다가 권한 문제로 막히거나, 예상치 못한 에러가 발생한다면 언제든 댓글로 질문을 남겨 주세요. 함께 고민하고 해결해 드릴게요!

관련하여 더 깊이 있는 내용이 궁금하시다면 아래 글들도 함께 읽어보시는 것을 추천해요.

🔗 쿠버네티스 디플로이먼트 기본 개념 이해하기
🔗 안전한 클러스터 구축을 위한 입문 가이드

댓글 남기기