바로 가기

쿠버네티스 보안 소개

URL 복사

컨테이너쿠버네티스의 도입이 증가하고 있음에도 불구하고 보안은 여전히 최우선 과제로 꼽힙니다. 다행히 더욱 안전하게 컨테이너를 구현하기 위한 방법은 많습니다. 이 쿠버네티스 보안 소개에서는 컨테이너 보안 시작을 위한 여러 가지 단계를 간략히 소개합니다.

컨테이너 이미지는 클라우드 네이티브 환경에 발생할 수 있는 취약점의 주요 원인이 되는 경우가 많습니다. 효과적인 보안 전략의 핵심은 조직 전반에서 안전한 이미지 구축 사례를 준수하도록 하는 것입니다. 이미지 스캔은 조직의 보안에 중요한 부분이지만, 이미지를 안전하게 유지하는 것이야말로 애플리케이션 라이프사이클 초반부터 사전 예방적으로 컨테이너화된 애플리케이션의 보안을 확보할 수 있는 방안입니다.

컨테이너 이미지를 안전하게 생성하려면 다음 모범 사례를 도입하세요.

  1. 최소한의 기본 이미지 사용

    이미지는 컨테이너가 공격 범위를 축소하는 데 필요한 라이브러리와 툴만 포함해야 합니다.

  2. 신뢰할 수 있는 소스의 기본 이미지 사용

    이미지를 처음부터 구축하는 경우가 아니라면 신뢰할 수 있는 소스의 기본 이미지를 선택합니다. 모든 이미지 구성 요소에 대한 Dockerfile과 소스 코드를 볼 수 있어야 하며, 신뢰할 수 있는 레지스트리에서 호스팅되어야 합니다. 또한 기본 이미지는 자주 업데이트되어야 합니다.

  3. 사용자 지정

    Dockerfile이 사용자를 지정하지 않으면 컨테이너는 기본적으로 루트 사용자로 실행됩니다. 이는 잠재적인 공격 범위를 확장하고 애플리케이션이 손상된 경우 더욱 쉽게 권한을 에스컬레이션하는 위험을 초래합니다.

  4. Docker 이미지 검증

    이미지를 검증하는 것은 어려운 일이지만, 보안 이미지를 구축하기 위해 중요한 요소입니다. 모든 기본 이미지는 서명되고 검증되어야 합니다. 모든 이미지가 인증되었음을 보장하는 유일한 방법은 신뢰할 수 있는 레지스트리에서 이미지를 가져오는 것입니다.

  5. 취약점 스캔

    오픈소스 라이브러리를 통해 발생한 취약점을 비롯해 컨테이너 이미지 내의 취약점을 찾아 수정하는 것이 중요합니다.

  6. 비밀 정보 유지

    자격 증명 및 키와 같은 민감한 데이터를 포함하는 비밀 정보가 다른 컨테이너 이미지에 포함되어서는 안 됩니다.

  7. 리소스 제한 설정

    컨테이너가 액세스할 수 있는 CPU 또는 메모리 리소스의 용량을 제한하면 부적절하게 사용된 경우 발생할 수 있는 피해를 줄일 수 있습니다.

  8. 권한 제한

    컨테이너의 권한을 최대한 제한하고, 해당 권한이 에스컬레이션되지 않도록 컨테이너를 구성합니다.

  9. 다중 단계 빌드 사용

    애플리케이션을 생성하고 컴파일하는 데 사용하는 빌드 툴은 프로덕션 시스템에서 실행되는 경우 악용될 수 있습니다. 빌드와 실행 단계에서 동일한 이미지를 사용하는 대신, 다중 단계 Dockerfile을 사용해 런타임 이미지에서 필요하지 않은 복잡한 툴을 제외합니다. 디버거 역시 프로덕션 이미지에서 제거해야 합니다.

  10. 보안에 중점을 둔 코딩 사례 이용

    개발 프로세스 도중 린터(linter)를 사용해 안전하지 않은 코드를 잡아내는 방법으로 이러한 사례를 시행할 수 있습니다.

이러한 단계는 이미지 구축 프로세스에 대한 것이지만, 애플리케이션의 다른 부분에도 보안 사례를 전달하는 것이 보안 이미지 구축의 원칙입니다. 이러한 사례에는 공격 범위를 최대한 작게 유지하고, 권한을 제한하고, 쿠버네티스와 클라우드 네이티브 스택의 기타 측면에서 기본 설정이 아닌 설정을 강화하는 것이 포함됩니다.

쿠버네티스를 위한 CIS 벤치마크

CIS(Center for Internet Security)는 사이버 방어를 위한 모범 사례를 개발하는 곳으로, 크라우드소싱을 사용해 보안 권장 사항을 정의합니다. 그중에서도 가장 많이 사용되는 툴은 바로 CIS 벤치마크입니다.

조직에서는 쿠버네티스를 위한 CIS 벤치마크를 사용해 쿠버네티스 환경을 강화할 수 있습니다. 여러 오픈소스 및 상용 툴이 CIS 벤치마크에 요약된 설정 및 제어와 자동으로 대조 확인하여 안전하지 않은 구성을 식별합니다.

CIS 벤치마크가 여러 가지 유용한 구성 확인 기능을 제공하긴 하지만, 조직에서는 이를 시작점으로 삼아 쿠버네티스에 모범 사례를 적용하도록 CIS 점검 이상의 조치를 취해야 합니다. 여기에는 네트워크 정책, 역할 기반 액세스 제어(RBAC) 설정, 관리 권한, 쿠버네티스 API 서버에 대한 기타 보호 조치를 구현하는 것이 포함됩니다.

쿠버네티스 역할 기반 액세스 제어(RBAC)는 쿠버네티스 API 엔드포인트에 대한 권한 부여를 관리하는 표준 방법을 제공합니다. 클러스터의 RBAC 구성은 어떤 주체가 어떤 네임스페이스의 어떤 리소스 유형에서 어떤 동작을 실행할 수 있는지를 제어합니다. 예를 들어, 구성에서 사용자 "alice"에게 네임스페이스 외부 API에서 "pod" 리소스 유형을 볼 수 있는 액세스 권한을 부여할 수 있습니다. RBAC API에는 4가지 선언적 개체인 Role, ClusterRole, RoleBinding, ClusterRoleBinding이 포함됩니다.

Role은 개별 네임스페이스에 대한 권한을 설정하는 로 구성된 네임스페이스 리소스인 반면, ClusterRole은 네임스페이스가 아닌 리소스로 클러스터 전반 또는 여러 네임스페이스 전반의 권한을 부여합니다. 각 룰은 동사, 리소스 유형, 네임스페이스 선택기의 조합으로 구성됩니다.

역할 바인딩(RoleBinding)은 사용자, 사용자 그룹 또는 서비스 계정(주체라고도 함)을 역할에 결합하고, 역할에 정의된 권한을 해당 사용자에게 부여합니다. 클러스터 역할 바인딩(ClusterRoleBinding)은 ClusterRole을 클러스터 내 모든 네임스페이스에 결합합니다. 이를 통해 RoleBinding은 네임스페이스 내에서 권한을 할당하고, ClusterRoleBinding은 이러한 권한을 클러스터 전반에 부여합니다.

Red Hat의 경험을 바탕으로 식별한 RBAC 구성 설정에서 유의해야 하는 가장 일반적인 실수 5가지는 다음과 같습니다.

 

구성 실수 1:불필요하게 클러스터 관리자 역할이 부여된 경우

내장된 클러스터 관리자 역할은 클러스터에 대한 무제한 액세스 권한을 부여합니다. 레거시 ABAC 컨트롤러에서 RBAC로 전환하는 동안 일부 관리자와 사용자가 관련 도큐멘테이션에서의 경고를 무시하고 클러스터 관리자 역할을 광범위하게 부여해 ABAC의 권한 구성을 복제할 가능성이 있습니다. 사용자나 그룹에 기계적으로 클러스터 관리자 권한이 부여되는 경우, 해당 계정의 보안이 저해되거나 한 번의 실수가 위험할 정도로 광범위한 영향을 미칠 수 있습니다. 서비스 계정에는 일반적으로 이러한 액세스 유형이 필요하지 않습니다. 두 경우 모두 더욱 세밀하게 맞춤 설정된 역할 또는 클러스터 역할을 생성하고, 이를 필요로 하는 특정 사용자에게만 권한을 부여해야 합니다.

구성 실수 2:역할 어그리게이션의 부적절한 사용

쿠버네티스 1.9 이상에서는 새로운 권한을 기존 역할에 결합하도록 허용하여 권한을 간소화하기 위해 역할 어그리게이션을 사용할 수 있습니다. 하지만 이러한 어그리게이션을 면밀히 검토하지 않으면 역할이 의도한 대로 사용되지 않고 변경될 수 있습니다. 예를 들어, '시스템:보기' 역할이 '보기'가 아닌 다른 동사와 함께 잘못 집계되는 경우, '시스템:보기' 역할이 부여된 주체는 클러스터를 절대 수정할 수 없다는 의도를 위반하게 됩니다.

구성 실수 3:중복된 역할 부여

역할 정의가 서로 중복되어 주체에게 두 가지 이상의 방식으로 동일한 액세스 권한을 부여하게 될 수 있습니다. 관리자가 이러한 중복이 발생하도록 의도하는 경우도 있지만, 이러한 구성에서는 어떤 주체에게 어떤 액세스 권한이 부여되었는지 파악하기 어렵습니다. 이 상황에서 관리자가 다중 역할 바인딩이 동일한 권한을 부여한다는 것을 인식하지 못할 경우 액세스 권한 취소가 더 어려워집니다.

구성 실수 4:사용하지 않는 역할

생성되었지만 어느 주체에도 부여되지 않은 역할은 RBAC 관리를 더욱 복잡하게 만들 수 있습니다. 이와 비슷하게, 존재하지 않는 주체(예: 삭제된 네임스페이스에 있는 서비스 계정 또는 조직을 떠난 사용자)에게만 부여된 역할 역시 구성 파악을 어렵게 만듭니다. 이렇게 사용하지 않거나 비활성 상태의 역할을 제거하는 것이 안전하며, 활성 상태의 역할에 집중할 수 있습니다.

구성 실수 5:없는 역할 부여

역할 바인딩은 존재하지 않는 역할을 참조할 수 있습니다. 동일한 역할 이름이 향후 다른 목적으로 재사용되는 경우, 비활성 상태의 이 역할 바인딩이 새로운 역할 생성자가 의도하지 않은 다른 주체에게 갑작스럽게 예기치 않은 권한을 부여하게 될 수도 있습니다.

 

클러스터 RBAC 역할과 바인딩을 적절하게 구성해야 애플리케이션의 위험 노출, 사용자 계정 인수, 애플리케이션 버그 또는 단순한 인적 오류로 인한 영향을 최소화할 수 있습니다.

컨테이너와 쿠버네티스 vs. 가상 머신(VM) 보안

가상 머신(VM)과 컨테이너는 근본적으로 다른 아키텍처이지만, 혼동을 일으킬 정도로 유사한 부분이 있습니다. 컨테이너와 VM의 차이점을 이해하는 것은 보안에 매우 중요한 부분입니다. VM과 컨테이너 모두 다양한 수준의 격리를 제공하며 이식성을 갖추고 있습니다. 하지만 가상 머신은 자체적인 운영 체제를 통해 완전히 독자적 운영이 가능하며 다른 가상 머신과 리소스를 공유하지 않습니다. 컨테이너는 다른 컨테이너와 호스트를 공유하므로 보안 경계라는 개념이 복잡합니다.

컨테이너와 쿠버네티스는 서로 다른 아키텍처 패러다임을 제시하므로, 보안에 있어서도 서로 다른 접근 방식이 필요합니다. 호스트 기반 보안을 위해 정립된 기술은 컨테이너로 이식되지 않습니다. 정의된 경계에 네트워크 방화벽을 구축하는 등의 호스트 또는 VM 도메인을 위한 다른 보안 기술 또한 컨테이너에 적용할 수 없습니다. 또한 가상 머신 보안 모범 사례의 핵심은 보안 패치를 적용하는 것이지만, 구동 중인 컨테이너에는 패치를 적용할 수 없습니다. 대신 컨테이너 이미지를 업데이트하고 컨테이너를 다시 빌드해야 합니다.

컨테이너 보안을 유지하기 위해선 다음이 필요합니다.

  • 컨테이너 간 연결 제어
  • 컨테이너 간에 알려진 취약점이 없도록 유지
  • 컨테이너에 대한 루트 액세스 방지
  • 애플리케이션의 정상 작동에 필요한 수준으로만 권한 및 액세스 제한

쿠버네티스는 복잡성을 가중시키며 잠재적인 보안 위험도 야기합니다. 컨테이너화된 애플리케이션에 강력한 보안을 적용하려면 쿠버네티스 구성과 네트워킹 정책을 관리하는 것이 필수적입니다.

또한 컨테이너화된 애플리케이션으로 이동하면서 워크플로우가 변경되므로, 반드시 라이프사이클 전반에서 보안을 통합해야 합니다. 이미지와 컨테이너가 구성되는 방식부터 시작해 애플리케이션에 처음부터 보안이 적용되어 있어야 합니다. 배포 직전인 개발 프로세스 후반 단계에서 컨테이너화된 애플리케이션에 보안을 추가할 수는 없습니다.

컨테이너화된 애플리케이션의 보안을 유지하려면 오픈소스 요소를 포함한 모든 구성 요소의 소스를 제어하고, 구성을 관리하고, 이미지를 스캔하고, 세분화된 역할 기반 액세스 제어를 사용해야 합니다. 컨테이너와 쿠버네티스는 보안에 대해 서로 다른 접근 방식을 요구하지만, 선언적이면서 변경할 수 없다는 특성을 고려하면 적절히 구성하는 경우 가장 안전한 애플리케이션을 제작할 수 있습니다.

쿠버네티스에서 컨테이너는 여러 쿠버네티스 개체 중 하나인 포드 안에서 구동되며, 각 포드의 런타임 구성은 포드 사양의 보안 컨텍스트 조합, 포드 보안 정책(Pod Security Policies, PSP), OPA(Open Policy Agent) Gatekeeper와 같은 권한 컨트롤러를 사용해 설정되고 실행될 수 있습니다.

배포 매니페스트에 정의된 보안 컨텍스트를 통해 워크로드에 대한 정확한 요건을 정의할 수 있으며, 포드 또는 컨테이너용으로 구성할 수 있습니다. PSP는 포드와 함께 실행할 수 있는 보안 컨텍스트를 제어하는 클러스터 수준의 쿠버네티스 리소스입니다. PSP가 클러스터에 대해 활성화되어 있는 경우, 관련 PSP를 준수하지 않는 포드를 생성하려는 모든 시도를 PSP 권한 컨트롤러에서 거부합니다.

컨테이너 런타임 권한 제한:

  • 애플리케이션 프로세스를 루트로 실행하지 않습니다. runAsUserMustRunAsNonRoot로 설정합니다.
  • 권한 에스컬레이션을 허용하지 않습니다. allowPrivilegeEscalationfalse로 설정합니다.
  • 읽기 전용 루트 파일 시스템을 사용합니다. readOnlyRootFilesystemtrue로 설정합니다.
  • 기본(마스킹됨) /proc 파일 시스템 마운트를 사용합니다.
  • 호스트 네트워크 또는 프로세스 스페이스를 사용하지 않습니다. hostPID, hostNetwork, hostIPCfalse로 설정합니다.
  • 사용하지 않는 Linux 기능을 제거하고, 애플리케이션에 절대적으로 필요하지 않은 선택적 기능을 추가하지 않습니다.
  • 더욱 정교한 프로세스 제어를 위해 SELinux 옵션을 사용합니다.
  • 각 애플리케이션에 각기 다른 자체 쿠버네티스 서비스 계정을 제공합니다.
  • 쿠버네티스 API에 액세스할 필요가 없는 경우 컨테이너에 서비스 계정 자격 증명을 마운트하지 않습니다.

 

쿠버네티스 네임스페이스 사용

쿠버네티스 네임스페이스는 클러스터 개체를 위한 범위 설정을 제공해 더욱 정교한 클러스터 객체 관리를 지원합니다. 네임스페이스 내의 컨테이너/포드, 서비스, 배포의 경우 쿠버네티스 네트워크 정책과 같은 제어를 사용해 격리하거나, 쿠버네티스 역할 기반 액세스 제어(RBAC)를 사용해 액세스를 제한할 수 있습니다.

클러스터에 워크로드를 배포하기에 앞서 네임스페이스를 할당할 방법을 계획하세요. 애플리케이션당 네임스페이스를 하나씩 지정하는 것이 가장 제어하기 좋습니다. 하지만 이 경우에는 RBAC 역할 권한과 기본 네트워크 정책을 할당할 때 추가적인 관리 오버헤드가 발생합니다. 둘 이상의 애플리케이션을 하나의 네임스페이스로 그룹화하기로 결정했다면 해당 애플리케이션에 공통된 RBAC 요건이 있는지, 해당 네임스페이스에서 쿠버네티스 API 액세스를 필요로 하는 서비스 계정과 사용자에게 권한을 부여해도 안전한지를 가장 중요하게 살펴야 합니다.

일반적으로 구성 관리란 구성과 관련한 정책을 수립하고, 해당 정책이 애플리케이션 라이프사이클 전반에서 조직 전체에 일관적으로 적용되도록 하는 엔지니어링 사례라고 볼 수 있습니다. 컨테이너와 쿠버네티스에 대한 대부분의 기본 구성이 안전하지 않기 때문에, 구성은 클라우드 네이티브 애플리케이션의 보안 리스크를 관리하는 데 있어 특히 필수적입니다. 쿠버네티스에서 구동되는 컨테이너화된 애플리케이션에서 보안 리스크가 발생하는 가장 일반적인 원인은 바로 잘못된 구성입니다.

개별 개발자나 운영자가 수동으로 구성 워크로드를 책임지지 않도록, 중앙에서 관리되는 가드레일을 통해 구성 관리를 반드시 자동화해야 합니다. 이러한 가드레일은 조직의 보안 정책을 기반으로 합니다.

IBM의 연구 결과에 따르면, 95%의 클라우드 보안 실패는 인적 오류로 인해 발생합니다. 컨테이너와 쿠버네티스로 분산된 시스템에서 구동되는 애플리케이션이 점점 더 복잡해지면서 잘못된 구성으로 인한 리스크 역시 확대됩니다. 중앙집중식 구성 관리 툴이 없는 경우, 조직에서 구성 정책이 일관적으로 적용되는지 확인하는 것은 거의 불가능합니다. 멀티클라우드 또는 하이브리드 클라우드 설정을 사용하는 기업에서는 환경마다 필요한 구성 세트가 다르기 때문에 구성을 일관적으로 적용하기가 훨씬 더 어려워집니다. 또한 보안 구성에 대한 모범 사례를 숙지하지 못하는 운영자와 개발자 사이의 기술 격차 또한 끊임없이 지속되는 문제 중 하나입니다.

대부분의 경우 애플리케이션 실행을 위해 개발자가 구성을 설정할 수 있는 가장 쉬운 방법은 루트 액세스를 허용하거나, 관리자 권한을 주거나, 리소스 제한을 매우 높게 설정하는 것 등으로 가장 위험한 방법이기도 합니다. 적절한 툴을 사용한다면 구성 관리를 DevOps 워크플로우에 통합하여 개발 속도를 지연시키지 않을 수 있습니다. 이는 빠른 출시와 워크로드 구성의 보안 확보가 모두 가능한 모범 사례입니다.

구성 관리에는 구성에 대한 가시성을 확보하는 방법과 어떤 구성이 허용되는지에 대한 가드레일이 있어야 합니다. 그래야 안전하지 않은 빌드 또는 위험한 배포가 자동으로 실패하기 때문입니다. 조직에는 컨테이너와 쿠버네티스 전반에서 관련이 있는 모든 구성을 확인하고, 잠재적으로 위험한 구성에 대한 경고를 받을 수 있는 단일 창이 필요합니다.

컨테이너와 쿠버네티스에 대한 구성 관리의 기본 요소는 다음과 같습니다.

  • 역할 기반 액세스 제어(RBAC): 조직은 지나친 권한이 부여된 구성 및/또는 불필요한 역할을 찾아야 합니다.
  • 비밀 정보: 우수한 구성 관리 툴은 비밀 정보에 대한 액세스를 사전 예방적으로 제한할 수 있습니다.
  • 정책 기반 평가: 조직의 보안 정책을 설정하는 것은 어떤 보안 상태에서든 필수적이며, 이렇게 사전 정의된 정책과 대조하여 배포를 확인할 방법이 있어야 합니다.
  • 권한: 권한은 최소 권한 액세스 원칙에 따라 할당되어야 합니다.
  • 리소스 제한: 컨테이너와 쿠버네티스 클러스터 모두 사용 가능한 CPU 및 메모리 용량에 제한이 있어야 합니다.
  • 네트워크 정책: 네트워크 정책은 컨테이너가 위험에 노출된 경우 잠재적인 피해를 최소화할 수 있도록 애플리케이션 내부에서 이루어지는 통신을 제한해야 합니다.

구성 관리를 시작하는 가장 간단한 방법은 CIS 벤치마크와 같이 업계에서 인정하는 모범 사례를 따르는 것입니다. 조직에서의 컨테이너 도입이 진행됨에 따라, 구성 관리에 대한 조직 차원의 거버넌스 정책을 생성하는 것이 가장 이상적인 모범 사례입니다. 강력한 보안 상태를 확보하기 위해서는 컨테이너와 쿠버네티스 모두에서 구성을 적절하게 관리해야 하므로 구성 관리는 이 두 위치에 대한 구성을 모두 포함해야 합니다.

기본적으로 쿠버네티스는 클러스터 내의 모든 포드가 자유롭게 통신할 수 있도록 허용합니다. 이렇게 하면 애플리케이션 운영이 쉬워지지만, 보안 리스크도 발생하기 마련입니다. 기본값은 지나친 권한을 허용하긴 하지만, 쿠버네티스에는 자산 간 통신을 제한하도록 구성할 수 있는 실행 기능이 기본 제공됩니다. 네트워크 분할은 배포된 부분 간 통신을 제한하는 방법 중 하나이며, PCI-DSS를 비롯해 일부 컴플라이언스 프레임워크에서 요구하는 사항이기도 합니다.

네트워크 분할이란 네트워크를 더 작은 하위 네트워크로 나누는 것입니다. 보안 관점에서 네트워크 분할의 주요 장점은 악의적인 행위자가 다른 애플리케이션을 통해 동일한 쿠버네티스 클러스터에서 구동되는 애플리케이션에 대한 액세스 권한을 확보하는 경우, 해당 행위자가 클러스터의 모든 애플리케이션에 액세스하는 것을 막을 수 있다는 것입니다. 또한 민감한 워크로드 및/또는 애플리케이션의 다른 부분에서 특정 컴플라이언스 프레임워크를 위한 범위에 포함되는 워크로드를 격리할 수도 있습니다.

네트워크 정책은 개별 컨테이너가 애플리케이션이 정상 작동하는 데 필요한 컨테이너와의 통신만 허용하도록 최대한 제한적이어야 합니다.

쿠버네티스에서 네트워크 분할은 쿠버네티스 네이티브 네트워크 실행 기능은 물론, 서비스 메쉬와 같은 추가 인프라 레이어를 통해 네트워크 정책을 시행하여 이루어집니다.

기본적으로 동일한 네임스페이스 내부 또는 네임스페이스 사이에서 포드, 컨테이너, 노드 사이의 통신에는 제한이 없습니다. 일반적으로 모든 통신을 거부하는 정책으로 시작해 커뮤니케이션을 제한하는 네트워크 정책을 적용하는 것이 우수한 모범 사례의 시작점이라고 볼 수 있습니다. 포드는 서로 통신해야 하므로, 해당 포드가 통신해야 하는 다른 포드를 체계적으로 나열하는 것이 가장 좋습니다. 공용 인터넷에서의 수신 및 발신 역시 허용된 목록을 기준으로 필요한 포드에 대해서만 이루어져야 합니다.

네트워크 정책 변경 및 네트워크 분할 증가와 관련한 운영상의 리스크도 몇 가지 있습니다. 시스템 전반에 적용되는 네트워크 정책 변경이 애플리케이션에 미치는 영향을 시각화해 주는 툴을 사용하면 네트워크 정책 조정으로 인해 예기치 않은 결과가 발생할 리스크를 최소화하는 데 도움이 됩니다.

어떤 조직에서도 완벽하게 안전한 애플리케이션 또는 IT 인프라는 있을 수 없습니다. 보안을 위해서는 각기 다른 작업과 연관된 리스크 및 장단점을 이해하고, 우선순위를 지정하는 과정이 필요합니다. 리스크 프로파일링은 조직의 알려진 보안 리스크 및 해당 리스크의 관리와 관련된 정책 및 사례를 개략적으로 확인하는 프로세스입니다. 모든 조직은 일정 수준의 위험을 감수해야 하며, 이러한 위험이 어느 정도까지 허용되는지 명확하게 파악해야 합니다. 조직 전체뿐만 아니라 개별 애플리케이션에 대해서도 리스크 프로파일링을 수행해야 합니다. 민감한 워크로드 또는 컴플라이언스 요건 범위에 있는 워크로드는 그렇지 않은 워크로드와는 다른 리스크 프로파일을 가집니다.

리스크 프로파일링은 환경 내에 존재하는 취약점의 중요도를 평가하는 데도 도움이 됩니다. 모든 취약점에 대응하는 것은 불가능하기 때문에, 강력한 보안을 갖추기 위해서는 해결해야 할 문제의 우선순위를 올바르게 지정할 수 있도록 모든 취약점의 리스크를 평가해야 합니다.

분산된 컨테이너화 애플리케이션에서는 애플리케이션의 리스크 프로파일을 이해하고 우선순위를 지정하는 것이 어려울 수 있습니다. 애플리케이션에는 수백 가지 취약점이 있을 수 있지만, 모든 취약점의 리스크가 동일한 것은 아닙니다. 취약점으로 인한 보안 리스크는 다음과 같은 요소에 따라 달라집니다.

  • 취약점의 심각도
  • 공용 애플리케이션 여부
  • 애플리케이션이 프로덕션 단계에 있는지 여부
  • 애플리케이션이 컴플라이언스 규제 범위에 포함되는지 여부
  • 애플리케이션이 민감한 데이터에 액세스하는지 여부
  • 컨테이너의 권한 수준
  • 컨테이너의 네트워크 노출

조직에서는 주로 각 심각도 수준에서 취약성을 수정해야 하는 시급성을 지정하는 내부 정책을 통해 허용되는 리스크 수준을 미리 정의해야 하지만, 리스크 프로파일링은 정적인 작업이 아닙니다. 특히 컨테이너화된 애플리케이션의 컨텍스트에서 보안 리스크를 평가하는 프로세스는 런타임 동안 지속적으로 이루어져야 합니다.

잠재적인 보안 인시던트, 취약성, 정책을 수동으로 분류하는 것은 오류와 번아웃의 원인이 됩니다. 특히 대규모의 리스크 프로파일링은 보안 리스크를 발견하고 우선순위를 지정하는 자동화 툴 없이는 불가능한 작업입니다. 쿠버네티스에서 성공적으로 리스크 프로파일링을 수행하기 위해서는 쿠버네티스 선언문과 컨텍스트에 따른 데이터를 활용해 우선순위 지정 프로세스를 자동화해야 합니다. 이렇게 하면 보안팀은 리스크 프로파일링 프로세스에 시간을 쏟는 대신 리스크가 가장 높은 배포를 수정하는 데 집중할 수 있습니다.

이상적인 상황에서 리스크 프로파일링은 사후 대응 방식이자 사전 예방적인 툴로 사용할 수 있습니다. 하나의 배포에서 리스크를 찾아 수정한 후에는 해당 정보를 활용해 다른 배포에서 유사한 리스크 요인을 찾거나, 잠재적인 보안 리스크에 사전 대응할 수 있기 때문입니다.

런타임 보안은 악의적인 행위자를 막을 수 있는 중요 방어선입니다. 이상적인 상황에서 패치가 적용되지 않은 취약성, 안전하지 않은 구성 또는 자격 증명은 빌드 또는 배포 단계에서 포착되어야 합니다. 하지만 실제로는 초기 단계에서 취약점을 발견하지 못하거나, 새로운 취약점이 계속해서 나타나기 때문에 런타임 감지 및 대응이 필수적입니다. 또한 컴플라이언스 준수와 내부 위협에 대한 방어선 역할을 위해서도 중요한 부분입니다.

변경 불가능한 선언적 워크로드는 런타임에서 잠재적인 보안 인시던트를 감지하고 이에 대응하기 위해 완전히 새로운 모델을 필요로 합니다. 컨테이너가 일반적으로 쿠버네티스의 선언적 특성과 결합하여 최소한의 프로세스를 실행한다는 사실은 실제로 가상 머신(VM) 기반 애플리케이션에서보다 런타임 보안의 일부 측면을 더 쉽게 만들어줍니다. 반면 구동 중인 컨테이너는 VM 기반 애플리케이션에 보안 패치를 적용하는 것과 같은 방식으로 '패치'되는 것이 아니라 변경 불가능한 것으로 취급되어 중단된 상태에서 업데이트 및 재시작되어야 합니다.

감지는 런타임 보안의 기반입니다. 여기에는 애플리케이션 동작 방식의 기준을 파악하고 이러한 기준에서 크게 벗어나는 활동이 있는지 조사하는 작업이 포함됩니다. 추적될 수 있는 일부 활동에는 네트워크 요청과 프로세스 실행이 포함됩니다. 이러한 활동이 예상 수준에서 크게 벗어나는 경우, 잠재적으로 의심스럽거나 악의적인 활동의 징후일 수 있습니다. 허용되지 않는 인터넷 연결을 시도하는 경우가 이러한 예에 속합니다. 그러나 이러한 비정상 동작은 해결해야 할 문제를 식별하는 데 도움이 됩니다.

이상 감지는 VM 기반 워크로드보다는 컨테이너에서 더욱 정확하게 작동합니다. 컨테이너에는 애플리케이션을 하나만 포함하고 있어 컨테이너에 대한 기준 동작과 그렇지 않은 동작을 식별하여 격리하기가 더 쉽기 때문입니다. 이러한 이상 감지는 언제나 인시던트 대응 프로세스와 연결되어야 합니다.

비정상 동작 유형에 따라 플랫폼이 영향을 받는 포드 또는 컨테이너를 폐기하도록 자동 대응하는 것이 가장 좋은 조치일 수 있고, 경고를 보내고 수동으로 동작을 평가하는 것이 더 적절한 경우도 있습니다. 그러나 잠재적인 인시던트 대응을 최대한 자동화하는 것이 응답 시간을 최소화하고 컨테이너화된 애플리케이션의 전반적인 보안을 강화하는 데 도움이 됩니다.

Kubelet은 각 노드에서 구동하는 주요 "노드 에이전트"로, 잘못 구성하는 경우 여러 가지 보안 위험에 노출될 수 있습니다. 구동 중인 Kubelet 실행 파일에 대한 인수 또는 Kubelet 구성 파일을 사용해 Kubelet 구성을 설정할 수 있습니다.

Kubelet 구성 파일을 찾으려면 다음 명령을 실행하세요.

ps -ef | grep kubelet | grep config

Kubelet 구성 파일의 위치를 알려주는 --config 인수를 찾습니다.

그런 다음 각 노드에서 다음 명령을 실행합니다.

ps -ef | grep kubelet

결과에서 다음을 확인합니다.

--anonymous-auth 인수가 false입니다. 이전에 참조된 Kubelet 문서에서 익명(그리고 인증되지 않은) 요청을 Kubelet 서버에서 처리하도록 허용된 것이 악용된 구성 오류 중 하나였습니다.

--authorization-mode 인수가 있는 경우 AlwaysAllow로 표시됩니다. 없는 경우, --config로 지정된 Kubelet 구성 파일이 존재하며 해당 파일이 authorization: mode를 AlwaysAllow가 아닌 것으로 설정했는지 확인해야 합니다.

--client-ca-file 인수가 있으며 클라이언트 인증 기관 파일의 위치로 설정되어 있습니다. 없는 경우, --config로 지정된 Kubelet 구성 파일이 존재하며 해당 파일이 authentication: x509: clientCAFile을 클라이언트 인증 기관 파일의 위치로 설정했는지 확인해야 합니다.

--read-only-port 인수가 있는 경우 0으로 설정되어 있습니다. 없는 경우, --config로 지정된 Kubelet 구성 파일이 존재하며 readOnlyPort가 있는 경우 0으로 설정되어 있어야 합니다.

--protect-kernel-defaultstrue로 표시됩니다. 없는 경우, --config로 지정된 Kubelet 구성 파일이 존재하며 해당 파일이 protectKernelDefaultstrue로 설정했는지 확인해야 합니다.

Kubelet과 API 서버 간의 TLS 설정이 중단되지 않도록 --hostname-override 인수는 존재하지 않아야 합니다.

--event-qps 인수가 있는 경우 0으로 설정되어 있습니다. 없는 경우, --config로 지정된 Kubelet 구성 파일이 존재하며 eventRecordQPS0으로 표시되어 있는지 확인해야 합니다.

--tls-cert-file--tls-private-key-file 인수가 적절하게 설정되어 있거나, --config로 지정된 Kubelet 구성에 tlsCertFiletlsPrivateKeyFile에 대한 적절한 설정이 포함되어 있어야 합니다. 이 구성은 모든 연결이 Kubelet의 TLS를 통해 이루어지도록 합니다.

Kubelet이 API 서버에서 인증서를 가져오고 Kubelet이 강력한 암호화 문자만 사용하도록 하려면 RotateKubeletServerCertificate--rotate-certificatestrue로 설정되어 있어야 합니다.

쿠버네티스 API 서버는 클러스터 관리를 활성화하기 위해 클러스터 내에서 실행 중인 사용자 또는 애플리케이션의 REST API 호출을 처리합니다. 이는 쿠버네티스 컨트롤 플레인으로의 게이트웨이로 간주되므로 kubectl, 클라이언트 라이브러리 또는 직접적인 API 요청을 통해 API 서버에 액세스할 수 있습니다. 쿠버네티스 API 서버에 대한 권한 부여를 관리하는 방법 중 하나는 쿠버네티스 역할 기반 액세스 제어(RBAC)를 이용하는 것입니다. 또한 권한 컨트롤러를 사용해 API 서버에 대한 요청을 검증할 수 있습니다.

API 서버 보호는 액세스를 제어하는 것부터 시작합니다. CIS(Center for Internet Security)는 API 서버를 강화하고 보안을 적용하기 위한 구성 모범 사례를 제공합니다.

마스터 노드에서 다음 명령을 실행하세요.

ps -ef | grep kube-apiserver

결과에서 다음을 확인합니다.

--anonymous-auth 인수가 false로 표시됩니다. 이 설정을 사용하면 다른 인증 방식에서 거부되지 않은 요청이 익명으로 처리되지 않으므로 정책에 대해 허용됩니다.

--basic-auth-file 인수가 없습니다. 기본 인증은 인증에 선호하는 토큰 또는 인증서 대신 일반 텍스트 자격 증명을 사용합니다.

--insecure-allow-any-token 인수가 없습니다. 이 설정은 인증된 보안 토큰만 허용되도록 합니다.

–kubelet-https 인수가 없거나 true로 표시됩니다. 이 구성은 API 서버와 Kubelet 간 연결이 TLS(Transport Layer Security)를 통해 전송 중 보호되도록 합니다.

--insecure-bind-address 인수가 없습니다. 이 구성은 API 서버가 안전하지 않은 주소에 바인딩되는 것을 방지하여 마스터 노드에 대해 인증되지 않고 암호화되지 않은 액세스를 차단함으로써 공격자가 전송 중에 민감한 데이터를 읽을 수 있는 위험을 최소화합니다.

--insecure-port 인수가 0으로 표시됩니다. 이 설정은 API 서버가 안전하지 않은 포트에서 작동하는 것을 방지하여 마스터 노드에 대한 인증되지 않고 암호화되지 않은 액세스를 차단하고 공격자가 클러스터를 제어할 위험을 최소화합니다.

--secure-port 인수가 존재하지 않거나, 1~65535 사이의 정수로 표시됩니다. 여기서 목표는 모든 트래픽이 인증 및 권한 부여와 함께 https를 통해 제공되도록 하는 것입니다.

--profiling 인수가 false로 표시됩니다. 병목 현상을 경험하거나 문제 해결이 필요한 경우가 아니라면 프로파일러가 필요하지 않으며, 프로파일러가 있으면 불필요하게 시스템 및 프로그램 세부 정보가 노출될 수 있습니다.

--repair-malformed-updates 인수가 false로 표시됩니다. 이 설정은 클라이언트에서 의도적으로 잘못 설정한 요청이 API 서버에서 거부되도록 합니다.

--enable-admission-plugins 인수가 AlwaysAdmit을 포함하지 않는 값으로 설정되어 있습니다. 항상 승인하도록 이 설정을 구성하면 권한 제어 플러그인에서 명시적으로 허용하지 않더라도 요청을 승인하므로 플러그인의 효율성이 떨어집니다.

--enable-admission-plugins 인수가 AlwaysPullImages를 포함한 값으로 설정되어 있습니다. 이 구성은 사용자가 이미지의 이름을 아는 것만으로는 노드에서 포드로 이미지를 가져갈 수 없도록 합니다. 이 제어를 활성화하면 컨테이너를 시작하기 전에 항상 이미지를 가져오며, 여기에는 유효한 자격 증명이 필요합니다.

--enable-admission-plugins 인수가 SecurityContextDeny를 포함한 값으로 설정되어 있습니다. 이러한 제어는 포드 보안 정책에 기재되지 않은 방식으로 포드 수준의 보안 컨텍스트를 사용자 정의할 수 없도록 합니다.

--disable-admission-plugins 인수가 NamespaceLifecycle을 포함하지 않는 값으로 설정되어 있습니다. 이러한 제어는 존재하지 않는 네임스페이스 또는 종료되도록 설정된 네임스페이스에서 개체가 생성되지 않도록 하므로 비활성화하면 안 됩니다.

--audit-log-path 인수가 감사 로그를 저장하려는 적절한 경로로 설정되어 있습니다. 가능한 경우 쿠버네티스 API 서버를 포함한 모든 쿠버네티스 구성 요소에 대한 감사를 항상 활성화하는 것이 좋습니다.

--audit-log-maxage30 또는 내부 및 외부 데이터 보존 정책을 준수하기 위해 감사 로그를 저장해야 하는 일 수로 설정되어 있습니다.

--audit-log-maxbackup 인수가 10 또는 오래된 로그 파일의 보존과 관련된 컴플라이언스 요건을 충족하는 데 도움이 되는 숫자로 설정되어 있습니다.

--audit-log-maxsize 인수가 100 또는 컴플라이언스 요건을 충족하는 데 도움이 되는 숫자로 설정되어 있습니다. 100이란 숫자는 100MB를 뜻합니다.

--authorization-mode 인수가 있으며 AlwaysAllow로 설정되어 있지 않습니다. 이 설정은 특히 프로덕션 클러스터에서 오직 인증된 요청만 API 서버에서 허용되도록 합니다.

--token-auth-file 인수가 없습니다. 이 인수가 있는 경우 정적인 보안 기반 인증을 사용하며, 여기에는 여러 가지 보안 결함이 있습니다. 그러므로 인증서와 같은 대체 인증 방식을 사용해야 합니다.

--kubelet-certificate-authority 인수가 있습니다. 이 설정은 API 서버와 Kubelet 사이 연결이 있는 경우 중간자(man-in-the-middle) 공격을 방지하는 데 도움이 됩니다.

--kubelet-client-certificate--kubelet-client-key 인수가 있습니다. 이 구성은 API 서버가 Kubelet의 HTTPS 엔드포인트에 자체 인증하도록 합니다. (기본적으로 API 서버는 이 단계를 수행하지 않습니다.)

--service-account-lookup 인수가 있으며 true로 설정되어 있습니다. 이 설정은 API 서버가 요청에 포함된 서비스 계정 토큰이 etcd에 있는지 확인하지 않고 인증 토큰의 유효성만 확인하는 인스턴스를 방지하는 데 도움이 됩니다.

--enable-admission-plugins 인수가 PodSecurityPolicy를 포함한 값으로 설정되어 있습니다.

--service-account-key-file 인수가 있으며 서비스 계정 토큰 서명에 대해 개별적인 퍼블릭/프라이빗 키 쌍이 설정되어 있습니다. 퍼블릭/프라이빗 키 쌍을 지정하지 않으면 TLS 제공 인증서의 프라이빗 키를 사용하므로 서비스 계정 토큰을 위한 키를 교체할 수 없습니다.

--etcd-certfile--etcd-keyfile 인수가 있으며 API 서버가 클라이언트 인증서와 키를 사용해 etcd 서버에서 자체 식별할 수 있도록 합니다. etcd는 본질적으로 민감할 가능성이 높은 개체를 저장하므로 모든 클라이언트 연결은 반드시 TLS 암호화를 사용해야 합니다.

--disable-admission-plugins 인수가 설정되어 있으며 ServiceAccount를 포함하지 않습니다. 이 구성은 새로운 포드가 생성될 때 같은 네임스페이스 내 기본 서비스 계정을 사용하지 않도록 합니다.

--tls-cert-file--tls-private-key-file 인수가 있으며 API 서버가 TLS를 통한 HTTPS 트래픽만 제공하도록 설정되어 있습니다.

TLS와 클라이언트 인증서 인증이 Kube 클러스터 배포에 대해 구성되도록 --client-ca-file 인수가 존재합니다.

--etcd-cafile 인수가 있으며, API 서버가 SSL Certificate Authority 파일을 통해 etcd 서버에 반드시 자체 검증하도록 설정되어 있습니다.

--tls-cipher-suites 인수가 강력한 암호화 문자를 사용하는 방식으로 설정되어 있습니다.

--authorization-mode argument 인수가 Node를 포함하는 값으로 설정되어 있습니다. 이 구성은 Kubelet이 노드와 연결해 읽을 수 있는 개체를 제한합니다.

--enable-admission-plugins 인수가 설정되어 있으며 NodeRestriction 값을 포함합니다. 이 플러그인은 Kubelet이 자체 Node API 개체와 해당 노드와 연결된 Pod API 개체만 수정할 수 있도록 합니다.

--encryption-provider-config 인수가 EncryptionConfig 파일로 설정되어 있으며 이 파일에는 필요한 모든 리소스가 있어야 합니다. 이 설정은 etcd 키-값 저장소에 있는 모든 REST API 개체가 유휴 상태에서 암호화되도록 합니다.

aescbc 암호화 공급자는 가장 강력한 암호화를 제공하므로 원하는 모든 리소스에 대해 활용하도록 합니다.

--enable-admission-plugins 인수가 클러스터의 성능 최적화를 위해 API 서버에서 허용하는 이벤트 수의 제한을 설정하는 EventRateLimit 값을 포함합니다.

--feature-gates 인수가 AdvancedAuditing=false를 포함하는 값으로 설정되어 있지 않습니다. 즉, 고급 감사가 감사와 조사 목적으로 비활성화되어 있지 않도록 해야 합니다.

--request-timeout 인수가 설정되어 있지 않거나, 적절한 값(너무 짧거나 길지 않은 값)으로 설정되어 있습니다. 기본값은 60초입니다.

--authorization-mode 인수가 존재하며 쿠버네티스 RBAC를 포함하는 값으로 설정되어 있습니다.

이 설정은 RBAC가 활성화되어 있도록 합니다. 단순히 활성화하는 것뿐만 아니라, 다음과 같이 RBAC를 잘 사용하는 방법에 대한 몇 가지 권장 사항을 따라야 합니다.

  • 클러스터 관리자 역할은 환경에 대해 매우 광범위한 권한을 부여하며 꼭 필요한 경우에만 사용해야 하므로 사용자에게 이 역할을 지정하면 안 됩니다.
  • 감사를 통해 역할 어그리게이션 룰을 올바르게 사용하고 있는지 확인합니다.
  • 액세스 철회가 더욱 어려워질 수 있으므로 주체에 중복된 권한을 부여하면 안 됩니다.
  • 사용하지 않는 역할을 정기적으로 제거합니다.

기본 설정을 사용하는 경우의 보안 과제

컨테이너와 쿠버네티스의 가장 큰 위험 중 하나는 두 기술의 기본 구성이 안전하지 않다는 것입니다. 그러므로 보안 인시던트의 위험을 줄이려면 이러한 기본 구성이 사전 예방적으로 조직 전체에서 일관적으로 변경되도록 해야 합니다. 인적 오류나 지식 부족, 구성 관리 단계를 포함하지 않은 워크플로우 등의 이유로 이 단계를 무시하는 경우 불필요하게 취약한 워크로드가 발생할 수 있습니다.

 

컨테이너의 기본 설정

여러 가지 기본 컨테이너 설정과 일반적인 컨테이너 구축 사례로 인해 컨테이너가 취약해질 수 있습니다. 컨테이너 구성 시 유의해야 하는 몇 가지 사항은 다음과 같습니다.

  • 사용자 지정: 사용자를 지정하지 않은 경우 기본적으로 루트 사용자로 지정되므로, 호스트에 컨테이너 루트 액세스 권한이 부여될 가능성이 있습니다.
  • 이미지 검증: 기본 설정은 이미지 검증을 적용하지 않으므로, 손상된 이미지를 실수로 가져올 수 있습니다.
  • 리소스 제한 설정: 리소스 제한을 구성할 수는 있지만 제한 기본값은 없습니다. 컨테이너가 사용할 수 있는 CPU와 메모리를 제한하면 손상되더라도 컨테이너가 대량의 리소스를 소모하지 않도록 방지할 수 있습니다.
  • 툴과 라이브러리를 선택적으로 설치: 컨테이너에 있는 툴과 라이브러리가 적을수록 악의적인 행위자가 컨테이너에 액세스했을 때 악용할 가능성이 있는 툴도 줄어듭니다. 모든 컨테이너에 표준 툴 세트를 설치하는 대신, 실제로 필요한 것만 설치하도록 합니다.
  • 목록을 허용해 레지스트리에 대한 액세스 제어: 사용하는 모든 이미지를 신뢰할 수 있는 소스에서만 가져와야 하는 것은 물론, 되도록 신뢰할 수 있는 사용자 목록만 허용하여 레지스트리에 대한 액세스도 엄격하게 제어해야 합니다.

쿠버네티스의 기본 설정

쿠버네티스 역시 조직의 보안 상태를 강화하는 여러 가지 툴을 제공하지만, 보안 강화 효과를 얻으려면 능동적으로 구성해야 합니다. 쿠버네티스에서 확인해야 할 핵심 사항은 다음과 같습니다.

  • 역할 기반 액세스 제어(RBAC) 구성: 쿠버네티스 1.6 이상에서는 RBAC가 기본적으로 활성화되어 있지만 효과를 보려면 올바르게 구성해야 합니다. 클러스터가 아닌 네임스페이스에서 액세스를 제공하는 것이 이상적입니다.
  • 네임스페이스 사용: '기본값'은 모든 것을 동일한 네임스페이스에서 실행하는 것입니다. 네임스페이스에서 제공하는 분리 기능을 적극적으로 사용해 워크로드를 서로 격리합니다.
  • 쿠버네티스 네트워크 정책 사용: 기본적으로 구성된 네트워크 정책이 없으므로 조직에서는 애플리케이션의 수신 및 발신(ingress and egress) 트래픽을 제어하는 네트워크 플러그인을 설치하고 그에 따른 정책을 구성해야 합니다.
  • 감사 로깅 활성화: 일반적으로 감사 로깅은 기본 활성화되어 있지 않지만 비정상적인 API 호출이나 인증 실패를 가시적으로 확인하려면 활성화되어야 합니다.

아무것도 하지 않을 때의 리스크

일반적으로 보안에 대한 심층적인 전문 지식이 없는 개발팀이 제일 먼저 컨테이너와 쿠버네티스를 사용하게 됩니다. 하지만 보안을 무시하면 어떤 유형의 인프라를 사용하든 조직이 위험에 노출됩니다.

앞서 언급한 것처럼 컨테이너와 쿠버네티스의 구성은 기본적으로 안전하지 않습니다. 쿠버네티스의 기본 보안 기능으로 제대로 된 보안 강화 효과를 얻으려면 능동적으로 구성해야 합니다. 또한 애플리케이션을 활성화하는 가장 빠르고 쉬운 방법으로 애플리케이션에서 필요로 하는 것보다 훨씬 많은 권한을 주거나, 훨씬 높은 리소스 제한을 설정하거나, 기본 설정을 그대로 두는 경우가 많습니다. 조직에서는 컨테이너와 쿠버네티스에 익숙해지는 초반에 보안을 소홀히 하기 쉽지만, 그렇게 하면 큰 위험에 직면하게 됩니다. 악의적인 행위자는 레거시 애플리케이션을 악용하는 것만큼이나 쉽게 쿠버네티스의 컨테이너화된 애플리케이션을 악용할 수 있기 때문입니다.

아무것도 하지 않을 때의 핵심 리스크는 악의적인 행위자가 애플리케이션을 손상시킬 수 있다는 점입니다. 위협의 심각성 수준은 조직의 산업, 사용 중인 애플리케이션 유형, 침해의 범위와 유형에 따라 다릅니다. 보안을 소홀히 하는 것이 인시던트에 영향을 미칠 확률 역시 애플리케이션이 인터넷용인지 여부와 같은 요소에 따라 달라집니다.

컨테이너화된 애플리케이션이 안전한지 확인하기 위한 아무 조치도 취하지 않으면 애플리케이션이 불필요하게 취약해질 수 있습니다. 보안을 소홀히 하면 다음과 같은 상황으로 이어질 수 있습니다.

패치가 적용되지 않은 보안 취약점: 새로운 보안 취약점은 언제든지 발견되며 일부는 심각한 취약점도 있습니다. 오픈소스 커뮤니티와 악의적인 행위자는 이러한 취약점이 게시되자마자 알게 되므로 이를 신속하게 해결하지 못하면 위험해집니다.

느슨한 권한: 쿠버네티스에는 역할 기반 액세스 제어(RBAC)가 기본적으로 활성화되어 있지만, 액세스 제어를 적용하는 것은 개발자의 몫입니다. 보안 지침이 없으면 개발자는 너무 많은 액세스가 있는 워크로드를 생성하는 경우가 많습니다.

격리되지 않은 워크로드: 기본적으로 모든 것은 단일 기본 네임스페이스에서 실행할 수 있습니다. 네임스페이스를 사용해 워크로드 격리를 시작하는 것이 기본적인 보안 모범 사례이며, 이 보안 단계에서 의식적으로 주의하지 않으면 이 수준의 격리는 일어나지 않습니다.

네트워크 정책에 대한 제어 없음: 쿠버네티스 네트워크 정책은 조직이 트래픽을 제어할 수 있도록 지원해 주지만, 이러한 정책을 구성하려면 네트워크 플러그인이 필요합니다.

보안 제어가 적용되기만을 기다리다 보면 결국에는 일관성이 없는 보안 사례와 보안 검토 병목 현상으로 이어져 개발 속도가 느려지고 보안 인시던트 위험이 커집니다. 대신, 조직이 보안 제어를 소프트웨어 개발 라이프사이클 초기에 자주 적용하도록 지원해야 합니다.

사실상의 컨테이너 오케스트레이션 시스템인 쿠버네티스를 통해 컨테이너 관리가 가능해지지만 인프라 환경에 잠재적 보안 취약점이 발생합니다. 또한 컨테이너 및 쿠버네티스와 가상 머신에 적용되는 보안 간의 차이점, 그리고 쿠버네티스 보안과 관련한 지속적인 기술 격차는 불필요한 보안 리스크로 이어집니다.

쿠버네티스를 위한 보안 모범 사례는 다른 보안 모범 사례와 마찬가지로 애플리케이션과 인프라의 보안 강화를 위한 모범 사례와 보안을 중앙집중식으로 제어하는 조직적, 문화적 사례를 모두 포함합니다.

조직적인 보안 정책을 생성하여 시행하는 것이 기업이 의존하는 기술 스택에 관계없이 가장 좋은 모범 사례입니다. 보안이란 리스크 관리 프로세스입니다. 예를 들어, 각 애플리케이션에 허용되는 리스크 수준을 툴에 의존하여 결정할 수 없으므로 일반적으로 조직, 개별 사업부, 각 애플리케이션에 대해 허용되는 리스크 수준을 고려할 수 있는 사람이 결정을 내려야 합니다.

중앙집중식 보안 제어: 첫 번째 요점과 관련되는 부분으로, 조직에서는 설정된 보안 및 거버넌스 정책이 준수되고 있는지 파악할 방법이 필요합니다. 중앙 팀은 전체 분산형 애플리케이션 전반에 대한 구성과 취약점을 가시적으로 확인할 수 있어야 하며, 잠재적인 문제를 손쉽게 시각화하고 우선순위를 지정할 수 있어야 합니다. 또한 위험한 구성, 안전하지 않은 이미지 또는 기타 잠재적인 보안 리스크가 빌드에 포함되어 있을 때 개인이 즉각적인 피드백을 받을 수 있도록 가드레일을 생성할 수 있어야 합니다.

초반에 보안 적용: 개발 프로세스 초기에 보안을 통합하는 '시프트 레프트(shift left)' 방식을 채택하고 보안 파트너와 협력하면 보안 검토 병목 현상을 제거하고 애플리케이션 출시를 앞당길 수 있을 뿐만 아니라, 오류로 인해 취약성이나 잘못된 구성이 악용될 확률도 줄여줍니다.

자동화 활용: 특히 쿠버네티스 풋프린트가 다중 클러스터와 수백 개의 네임스페이스로 확장됨에 따라, 수동으로 구성을 관리하거나 런타임 동작을 모니터링하는 것이 불가능하게 되었습니다.

또한 쿠버네티스를 최대한 안전하게 만들 수 있는 아주 중요한 기술적 모범 사례가 몇 가지 있습니다.

  • 쿠버네티스를 최신 상태로 유지: 보안 패치가 항상 이전 버전용으로 릴리스되는 것은 아니므로 지원되는 최신 릴리스를 실행하는 것이 좋습니다.
  • 역할 기반 액세스 제어 사용: 액세스는 항상 최소 권한 액세스를 기준으로 구성되어야 합니다.
  • 포드 간 통신 제한: 포드가 정상 작동하도록 통신을 가능한 한 제한해야 합니다.
  • 네트워크 분할 사용: 각 포드는 필요한 내부 또는 외부 리소스와만 통신할 수 있어야 하고 다른 모든 리소스와 격리된 상태를 유지해야 합니다.

취약점 관리는 애플리케이션의 보안을 유지하는 데 필수적인 요소로, 소프트웨어 개발 라이프사이클의 모든 단계에서 보안 취약점을 식별, 평가, 수정하는 프로세스입니다. 컨테이너화된 클라우드 네이티브 애플리케이션의 취약점 관리는 자동화되고 애플리케이션 빌드 및 제공의 DevOps 프로세스에 통합되어야 합니다. 환경은 너무 복잡하여 수동으로 취약점을 관리할 수 없으며, 보안 안전 장치로 인해 개발 속도가 너무 느려지는 경우 조직은 이를 건너뛰고 싶어 할 수 있습니다.

취약점 관리는 애플리케이션이 통과해야 하는 관문이 아니라 빌드 단계의 이미지 스캔 및 세부 검사부터 시작해 애플리케이션의 라이프사이클 전반에 걸쳐 테스트 및 프로덕션 환경에서도 지속되는 프로세스입니다.

빌드 단계에서의 이미지 취약점과 관련한 이미지 스캔 및 구현 정책은 효과적인 컨테이너 네이티브 취약점 관리를 향한 첫 번째 단계입니다. 이미지가 빌드될 때 또는 컨테이너가 실행되면 필요에 따라 스캔을 실행하는 기능은 런타임 중에 노출된 가능성이 있는 취약점을 발견하는 데 중요합니다. 컨테이너와 쿠버네티스 모두 취약점의 소스가 될 수 있으므로 취약점 관리는 이 두 곳 모두에서 노출을 발견할 수 있어야 합니다.

완전히 안전한 애플리케이션은 없지만 우수한 취약점 관리를 통해 팀은 취약점을 파악할 수 있을 뿐만 아니라 주어진 취약성의 조직별 중요성의 우선순위를 지정하는 데 도움이 될 추가 정보도 얻을 수 있습니다. 예를 들어, 우선순위가 높은 CVE라도 워크로드의 민감도에 따라 리스크 프로파일은 달라집니다. 우수한 취약점 관리는 최고의 보안을 구축하기 위해 균형을 조정하고, 평가하고, 수정 항목의 우선순위를 지정할 수 있어야 합니다.

취약점 관리는 기본적으로 클라우드 네이티브 애플리케이션에서 자동화되어야 합니다. 정책을 정의하려면 인간의 지능이 필요하지만 자동 빌드 실패에서 배포 차단 또는 프로덕션에서의 스케일 다운에 이르기까지 라이프사이클의 일부로서 정책 위반을 찾고 취약성, 리스크 레벨을 기반으로 적절한 조치를 취하는 것은 툴링에 책임이 있습니다.

이미지 및 취약점 스캔은 빌드 단계에서 시작되어, 런타임을 비롯한 애플리케이션 라이프사이클 전반에서 지속되어야 합니다. 새로운 보안 취약점은 언제든 발견될 수 있으므로 실행 중인 배포에서 취약점을 탐지하는 기능은 조직의 보안 기능에 필수적입니다. 실행 중인 배포에 취약점이 발생하는 경우 바로 보안 리스크로 이어지기 때문에 조직은 이를 감지하고 최대한 빨리 해결할 방법을 갖춰야 합니다.

빌드 단계에서 심각하며 수정 가능한 취약점을 비롯한 비호환 이미지는 빌드에 실패해야 하며, DevOps 팀은 CI 시스템에서 직접적으로 이러한 피드백을 받아야 합니다. 배포 단계에서 보안 툴링은 권한 제어를 적용해 이미지에서 감지된 알려진 취약점이 있는 컨테이너의 배포를 자동으로 방지합니다. 취약점의 심각도, 워크로드의 민감도, 조직의 일반적인 보안 리스크 허용치에 따라 문제 해결의 우선순위를 지정하는 방법을 파악하는 것이 중요합니다. 조직에서는 시간을 들여 사용자 정의 정책을 만들고, 자동화를 통해 빌드 및 배포 단계에서 이러한 정책을 시행할 툴을 구현하고, 배포 실행 후에도 계속해서 취약점을 스캔해야 합니다.

 

이미지 스캐너의 다양한 기능

모든 이미지 스캐너가 동일한 수준의 포괄적인 검사를 제공하는 것은 아닙니다. 기본 운영 체제만 스캔, 라이브러리까지 스캔, 언어 수준 검사 제공, 파일 콘텐츠 스캔 등 그 범위는 다양합니다. 그러므로 적어도 조직에서 필요한 만큼 포괄적이며 애플리케이션에서 사용하는 프로그래밍 언어와 호환되는 이미지 스캐너를 선택하는 것이 중요합니다.

일부 이미지 스캐너는 이미지를 가져올 때마다 실시간 스캔을 수행하지만, 이러한 접근 방식은 대기 시간을 늘리므로 조직에서는 실시간 정보가 성능을 저해할 만큼의 가치가 있는지 결정해야 합니다.

 

런타임에서 스캔

빌드 단계에서의 이미지 스캔과 마찬가지로, 감지된 모든 취약점이 동일한 응답을 받을 수 있는 것은 아닙니다. 조직에는 워크로드의 민감도, 데이터 민감도, 인터넷 노출, 감지된 취약점의 심각성을 기준으로 문제 해결의 중점을 어디에 두어야 할지 우선순위를 지정하는 방법이 필요합니다. 발견된 취약점에 대해 적절한 대응을 안내하는 절차나 서비스 수준 목표가 동일한 조직은 없습니다. 예를 들어, 심각도나 민감도에 관계없이 취약점이 발견된 모든 컨테이너를 차단하는 경우의 절충점이 있습니다. 실행 중인 배포에서 성공적으로 취약점을 스캔하려면 올바른 수준의 가시성과 정보를 제공해 줄 올바른 툴은 물론, 취약점 관리와 운영에 미치는 영향 간에 적절한 균형을 맞추기 위한 세심한 조직적 보안 정책도 필요합니다.

기업 네트워크와 그 안에서 분산된 애플리케이션이 복잡해짐에 따라 침투를 심화하는 데 활용되는 위협 모델과 방법의 복잡성 또한 증가했습니다. 보안 경계는 인프라와 데이터의 보호를 위한 포괄적인 전략이 아닌, 내부 네트워크를 보호하기 위한 1차 방어선 역할만 가능합니다. 강력한 보안에는 제어와 전략의 조합이 필요합니다.

제로 트러스트 네트워킹은 내부 애플리케이션 트래픽의 안전을 강화하는 보안 퍼즐의 중요한 조각 역할을 합니다. 이 모델은 방화벽을 사용하는 네트워크 내부의 모든 트래픽은 인증된 것으로 간주하는 오래된 원칙을 완전히 반대되는 가정으로 뒤집습니다. 즉, 어떤 네트워크 연결도 안전하다고 증명되기 전에는 안전하지 않다는 것입니다.

일반적으로 네트워크 관리자는 내부 네트워크에서 발견된 애플리케이션, 서버, 네트워킹 소프트웨어 또는 하드웨어 일부 등 모든 엔터티가 해당 네트워크에 속하고 신뢰할 수 있다는 가정하에 작업했습니다. 일부 애플리케이션은 클라이언트 연결의 인증을 필요로 하지 않거나 데이터베이스에 대한 비밀번호와 같이 정적인 공유 자격 증명에 의존했으며, 모든 애플리케이션은 필요한 인증 또는 권한 부여 체계를 사용하는 경우 이를 처리해야 했습니다. 또한 내부 네트워크 연결의 경우 민감한 서비스인 경우에도 암호화를 사용하지 않는 경우가 많았습니다.

여전히 이 패턴을 따르는 기업 네트워크가 많습니다. 하지만 느슨한 환경 내부에 있는 한 명의 악의적인 행위자는 직접적인 해킹이든, 인증된 개인이 실수로 적용한 트로이 목마든, 네트워크 방화벽의 허점을 통해서든 이러한 묵시적인 신뢰 네트워크를 악용해 혼란을 일으킬 수 있습니다. 가능성은 무한하지 않을지 몰라도 예측 가능합니다. 일반 텍스트 네트워크 패킷 검사에서 데이터베이스 또는 기타 중요 시스템에 대한 애플리케이션 비밀번호 검색, 네트워크 장비의 제어 기능 획득에 이르기까지 이 시나리오는 데이터 유출 또는 손실과 같이 일어나서는 안 될 리스크가 발생하는 원인이 될 수 있습니다.

제로 트러스트는 점점 더 늘어나는 보안 우선 프로덕션 인프라의 기반을 형성합니다. 검증 없이도 네트워크의 모든 엔터티를 신뢰할 수 있다고 추정하는 대신, 네트워크 인프라 자체부터 검증 없이는 신뢰할 수 없다고 추정하는 방식입니다. 제로 트러스트 프레임워크는 사용할 규범적인 구현 또는 특정 기술 세트를 제공하기보다는 구현의 기술적 세부 정보는 각 조직의 몫으로 넘기고 일련의 원칙과 목표를 설명합니다.

제로 트러스트 아키텍처

제로 트러스트 아키텍처는 일반적으로 다음 원칙을 준수합니다.

  • 보안 제어는 네트워크 위치와 관계없이 소프트웨어 또는 하드웨어를 비롯한 모든 엔터티에 동일하게 적용해야 합니다.
  • 네트워크 연결은 서버 측과 클라이언트 측 모두에서 인증되어야 합니다. 이제는 서버가 클라이언트를 인증하는 것이 일반적이지만, 클라이언트 역시 유효한 서버에 연결되어 있는지 검증하는 절차를 거쳐야 합니다. 연결은 단일 트랜잭션 이상으로 확장된 경우 필요에 따라 재인증을 받고 권한을 다시 부여받아야 합니다.
  • 권한 부여는 클라이언트의 워크로드에 필요한 최소한의 권한만을 허용하는 최소 권한 원칙에 따라 이루어져야 합니다.
  • 모든 네트워크 연결 및 트랜잭션은 분석을 위해 지속적으로 모니터링되어야 합니다.

쿠버네티스에서 제로 트러스트 모델 구현

쿠버네티스 클러스터의 제로 크러스트 모델은 어떤 모습일까요? 쿠버네티스 클러스터 내에 제로 트러스트 원칙을 구현하는 단일 방법론은 없지만, 서비스 메쉬가 많은 아키텍처의 목표에 부합하는 인기 솔루션으로 부상하고 있습니다.

서비스 메쉬는 가상화 네트워크 계층을 생성하여 분산된 애플리케이션 서비스를 연결하고 제어합니다. 대부분의 서비스 메쉬 솔루션은 처음에 네트워크 보안 대신 인텔리전트 서비스 검색 및 요청 라우팅을 촉진하고 관리하는 데 중점을 두었지만, 현재 가장 인기 있는 오픈소스 프로젝트는 제로 트러스트 아키텍처에 적합한 기능을 제공합니다. 많은 서비스 메쉬는 개별 애플리케이션의 수정이 필요하지 않은 오버레이를 생성하므로 엄격한 인증 및 권한 부여 제어를 위해 상당한 변경 사항을 적용해야 한다는 부담을 크게 줄여줍니다.

쿠버네티스를 지원하는 서비스 메쉬는 일반적으로 개별 클러스터 포드에 자체 프록시 인스턴스를 제공하는 방식으로, 중앙화되지 않은 포인트 투 포인트(point-to-point) 라우팅을 사용합니다. 이러한 프록시는 다른 서비스로 연결하거나 다른 클라이언트에서 연결을 수신할 때 프록시가 Ientity를 증명하는 데 사용할 수 있는 클라이언트 TLS 인증서를 관리할 수 있습니다. 클라이언트 측과 서버 측 모두에서 Identity를 증명하기 위해 TLS 인증서를 사용하는 것을 mTLS(mutual Transport Layer Security)라고 합니다. mTLS는 연결을 인증할 뿐만 아니라, 네트워크 연결을 암호화하는 역할도 합니다. 네트워크 상 인증과 암호화 이외에도 정적 목록부터 타사 SSO(Single sign-on) 또는 기타 서비스와의 통합까지, 다양한 서비스 메쉬에서 다양한 인증 소스를 지원합니다.

서비스 메쉬는 쿠버네티스 클러스터에 대한 완전한 제로 트러스트 솔루션을 제공하지는 않지만, 제로 트러스트 솔루션의 핵심적인 장점을 몇 가지 제공합니다. 쿠버네티스 클러스터에서 완벽한 제로 트러스트 아키텍처를 구축하지 못하더라도, 이러한 방향으로 조금씩 변경해 나가다 보면 클러스터와 워크로드를 보호하는 데 도움이 될 것입니다.

클라우드 네이티브 애플리케이션과 기본 인프라를 안전하게 보호하려면 조직의 보안 접근 방식에 큰 변화가 필요합니다. 조직은 애플리케이션 개발 라이프사이클의 초기에 제어를 적용하고, 기본 제어 기능을 사용하여 운영 및 확장성 문제를 예방하는 정책을 시행하고, 갈수록 빨라지는 릴리스 일정에 맞춰야 합니다.

Red Hat® Advanced Cluster Security for Kubernetes는 쿠버네티스 네이티브 보안 플랫폼으로, 조직이 어디서든 클라우드 네이티브 애플리케이션을 더 안전하게 빌드, 배포, 실행하고 자신 있게 혁신을 가속화하도록 지원합니다. 이 솔루션은 애플리케이션 빌드 프로세스의 보안을 개선하고 애플리케이션 플랫폼 및 구성을 보호하며 런타임 문제를 감지해 이에 대응하는 데 도움이 됩니다.

추가 자료

문서

컨테이너와 VM 비교

Linux 컨테이너 및 VM(가상 머신)은 다양한 IT 요소를 결합해 시스템의 나머지 부분으로 부터 격리하는 패키징된 컴퓨팅 환경입니다.

문서

컨테이너 오케스트레이션이란?

컨테이너 오케스트레이션은 컨테이너의 배포, 관리, 확장, 네트워킹을 자동화합니다.

문서

Linux 컨테이너란?

Linux 컨테이너는 시스템에서 격리된 프로세스로, 이러한 프로세스를 지원하는 데 필요한 모든 파일을 제공하는 고유한 이미지에서 실행됩니다.

컨테이너에 대한 자세한 내용

제품

선택한 인프라에서 애플리케이션 출시 테스트를 완료한 통합 서비스 세트를 포함하는 엔터프라이즈 애플리케이션 플랫폼입니다.

리소스

교육

무료 교육 과정

Running Containers with Red Hat Technical Overview

무료 교육 과정

Containers, Kubernetes and Red Hat OpenShift Technical Overview

무료 교육 과정

Developing Cloud-Native Applications with Microservices Architectures