본문 바로가기

[k8s] k8s Security basic 본문

Infra

[k8s] k8s Security basic

겨울바람_ 2024. 11. 11. 16:02

Overview

쿠버네티스 환경에서의 보안이란 쿠버네티스 클러스터의 안정성과 보안성을 유지하는 것을 의미한다.

 

쿠버네티스는 클러스터의 보안을 위해 많은 기능을 제공하지만, 이번 포스팅에서는 CKA 자격증 준비를 위해 공부했던 세 가지 기능에 대한 소개를 하려고 한다.

  • Network Policy
  • Role-Based Access Control
  • Secret

Network Policy

쿠버네티스의 통신 정책은 기본적으로 모든 Pod 간 통신을 허용한다. 이는 Pod 간 통신을 원활하게 해주지만, 원치 않는 통신에 Pod를 노출시킬 수 있다는 위험 또한 존재한다.

 

외부의 위협으로부터 Pod를 보호하기 위해 사용되는 쿠버네티스 보안 기능이 바로 네트워크 정책(Network Policy)이다.

 

네트워크 정책은 Pod 간 통신 또는 다른 네트워크 엔드포인트와 Pod 사이의 통신을 제어하는 기능이다. 네트워크 정책을 사용하면 IP 주소, 포트, 프로토콜 및 레이블(label), 네임스페이스와 같은 다양한 기준에 따라 트래픽을 허용하거나 거부하는 규칙을 정의할 수 있다.

 

네트워크 정책은 쿠버네티스 네트워크 플러그인 아키텍처를 사용하여 구현되기 때문에 네트워크 플러그인마다 네트워크 정책에 대한 지원 수준에 차이 존재할 수 있다.

 

네트워크 정책 설정 시 다음 세 가지 요소를 중점으로 살펴보아야 한다.

  • podSelector : 정책이 적용될 Pod를 지정한다
  • policyTypes : 정책이 적용될 트래픽을 지정한다
  • ingress/egress : 수신 트래픽 / 발신 트래픽에 대한 세부 내용을 지정한다

아래의 예시 YAML 파일을 통해 사용 사례를 살펴보자.

apiVersion: networking.k8s.io/v1    # NetworkPolicy 리소스의 API 버전 
kind: NetworkPolicy                 
metadata:
  name: test-network-policy        
  namespace: default                
spec:
  podSelector: 
    matchLabels:
      role: db                      # 이 정책이 적용될 Pod를 선택. 여기서는 "role=db" 레이블을 가진 Pod들에 적용됨
  policyTypes:
    - Ingress                       # 인바운드 트래픽에 대한 규칙 정의
    - Egress                        # 아웃바운드 트래픽에 대한 규칙 정의
  ingress:
    - from:
        - ipBlock:
            cidr: 172.17.0.0/16     # 인바운드 트래픽을 허용할 IP 범위 설정. 여기서는 "172.17.0.0/16" 대역의 IP에서 오는 요청 허용
            except:
              - 172.17.1.0/24       # 위의 cidr에서 제외할 IP 범위 설정. "172.17.1.0/24" 대역은 제외하여 차단
        - namespaceSelector:
            matchLabels:
              project: myproject    # 특정 네임스페이스에서 오는 트래픽을 허용. 여기서는 "project=myproject" 레이블이 있는 네임스페이스에서 오는 요청 허용
        - podSelector:
            matchLabels:
              role: frontend        # 특정 레이블을 가진 Pod에서 오는 트래픽을 허용. 여기서는 "role=frontend" 레이블이 있는 Pod에서 오는 요청 허용
      ports:
        - protocol: TCP             # 허용할 프로토콜 지정. 여기서는 TCP만 허용
          port: 6379                # 허용할 포트 번호. 여기서는 6379 포트만 허용
  egress:
    - to:
        - ipBlock:
            cidr: 10.0.0.0/24       # 아웃바운드 트래픽이 허용될 IP 범위 설정. "10.0.0.0/24" 대역으로 나가는 트래픽 허용
      ports:
        - protocol: TCP             # 허용할 프로토콜 지정. 여기서는 TCP만 허용
          port: 5978                # 허용할 포트 번호. 여기서는 5978 포트만 허용

위의 YAML 파일은 쿠버네티스의 공식 문서 중 Network Policy 문서의 예제 YAML 파일을 가져온 것이다.

 

YAML 파일 내에 작성된 주석을 통해 네트워크 정책의 동작 방식에 대해 유심히 살펴보면 클라우드 서비스에서 제공하는 보안 그룹과 유사하게 동작할 것을 예상할 수 있다.

 

이러한 동작을 통해 Pod에서 동작하는 애플리케이션이 어떤 요청을 받을 수 있고, 어디로 요청 혹은 응답을 보낼 수 있는지 결정하고 통제한다. 이에 더해 Pod의 네트워크 트래픽을 제한하는 것으로 다양한 외부 공격으로부터 클러스터를 보호할 수 있다.

Role-Based Access Control

쿠버네티스에 존재하는 여러 리소스들에 대한 권한을 사용자 및 서비스 계정의 역할을 정의하는 것으로 제어하는 것을 RBAC, 역할 기반 접근 제어라고 한다.

 

사용자나 서비스 계정의 역할을 설정하는 Role, 클러스터 수준에서 역할을 설정하는 ClusterRole을 사용해 보안 규칙을 정의하고, 정의한 규칙을 사용자의 모음인 Group에 정의한다.

 

 

역할 기반 접근 제어를 설정하기 위해서는 다음 세 가지 요소를 중점적으로 살펴봐야 한다.

  • Role : 쿠버네티스 리소스에 대한 권한의 집합이다. 특정 네임스페이스에서만 유효한 권한 할당
  • RoleBinding : 특정 사용자 혹은 사용자의 계정에 Role을 할당한다
  • ClusterRole : Role과 유사하지만, 클러스터 전체에서 유효한 권한을 할당한다.ClusterRoleBinding을 통해 사용자 또는 사용자의 계정과 연결을 정의해야 한다

다음은 각각 Role을 생성하여 특정 사용자에게 연결하는 Rolebinding에 대한 예제 YAML 파일이다.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""]                   
  resources: ["pods"]                  # 접근할 수 있는 리소스 지정 
  verbs: ["get", "watch", "list"]      # 리소스에 대한 작업 권한 부여 

--- 

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

리소스에 대한 작업 권한을 부여하는 verbs는 총 9가지가 존재한다.

  • create : 새로운 리소스 생성할 수 있는 권한
  • get : 개별 리소스 세부 정보를 조회할 수 있는 권한
  • list : 리소스 목록을 조회할 수 있는 권한
  • update : 기존 리소스 내용 전체를 수정할 수 있는 권한
  • patch : 기존 리소스 내용을 부분적으로 수정할 수 있는 권한
  • delete : 특정 리소스를 삭제할 수 있는 권한
  • deletecollection : 여러 리소스를 한 번에 삭제하는 권한. 일괄 삭제할 때 사용
  • watch : 리소스의 변경 사항을 실시간으로 모니터링 할 수 있는 권한
  • impersonate : 다른 사용자 혹은 계정으로 가장하는 권한. 다른 사용자 계정으로 API 요청을 수행할 수 있음

이처럼, 역할 기반 접근 제어를 적용할 경우 클러스터 관리자는 리소스에 대한 접근 권한을 관리할 수 있다. 이를 통해 다양한 사용자와 서비스 계정 간 접근 권한을 분리하여, 권한이 부여되지 않은 사용자가 민감한 데이터를 볼 수 없게끔 보호할 수 있다.

Secret

시크릿은 암호화된 정보, 토큰, 비밀번호와 같은 중요한 데이터를 안전하게 저장하기 위한 리소스다.

 

시크릿 정보는 컨테이너 이미지에 포함되지 않으며, 애플리케이션을 실행하는 동안 환경 변수 또는 볼륨 마운트를 통해 컨테이너에 전달된다.


시크릿은 일반적으로 Base64로 인코딩된 Key-Value 쌍으로 정의된다. 인코딩된 시크릿은 컨테이너 런타임시 복호화 되어 사용되므로, 시크릿을 사용하는 애플리케이션은 별도로 복호화 로직을 구현할 필요가 없다.

 

시크릿은 Pod와 독립적으로 생성되며, 민감 정보를 etcd 저장소에 보관하다가 Pod가 해당 정보를 필요로 할 때 컨테이너에 제공해준다.

 

아래는 간단한 시크릿 사용 예제다.

$echo -n "admin" | base64
YWRtaW4=
$echo -n "1234" | base64
MTIzNA==

시크릿에 정보를 저장하기 위해서는 우선 평문이 아닌 Base64로 인코딩한 문자열을 필드로 넣어줘야 한다.

apiVersion: v1
kind: Secret
metadata:
  name: secret-sa-sample
type: Opaque
data:
  USERNAME: YWRtaW4=
  PASSWORD: MTIzNA==

시크릿은 타입은 크게 네 가지가 존재한다.

  • Opaque : 일반적인 용도의 시크릿. ConfigMaps와 동일한 목적으로 사용할 수 있으며, 민감한 데이터를 컨테이너에 전달하는 용도로도 사용할 수 있다
  • dockerconfigjson : 도커 이미지 저장소 인증 정보. private 레지스트리에 접근하기 위한 인증 절차를 치룰 때 사용하는 용도
  • tls : TLS 인증서를 시크릿으로 관리할 수 있도록 한다. TLS 인증서를 시크릿을 통해 저장하면, Pod나 Service 같은 리소스에서 TLS 인증서를 가져다 통신을 암호화 할 수 있다
  • service-account-token : Service Account에 대한 인증 정보를 담은 토큰을 시크릿으로 생성

시크릿은 인코딩-디코딩 방식을 통해 암복호화가 이루어지기 때문에 완벽하게 데이터를 보호하는 방법이라고 볼 수 없다.

그렇기 때문에 역할 기반 접근 제어를 통해 권한이 있는 사용자만 시크릿 정보를 조회할 수 있도록 제한하거나, 별도의 암호화 플러그인과 KMS를 통해 시크릿을 완전히 암호화 하는 것을 권장한다.

Reference

https://yozm.wishket.com/magazine/detail/1953/

'Infra' 카테고리의 다른 글

메모리 영역  (0) 2025.02.06
[k8s] NodePort, LoadBalancer, Ingress  (2) 2024.11.12
[k8s] Kubernetes Network  (0) 2024.11.08
[Traefik] K8s Traefik 설치, External-IP 설정 및 HTTPS 적용 방법  (5) 2024.09.22
[k8s] K8s Storage with OpenEBS  (0) 2024.08.02
Comments