Translated /docs/concepts/security/multi-tenancy into Korean
Reflected Seo-yul's comments Updated to match branch dev-1.25-ko.1 Reflected seokho-son's comments Reflected seokho-son's commentspull/36649/head
parent
a1785fb338
commit
6334ab76dd
|
@ -0,0 +1,516 @@
|
|||
---
|
||||
title: 멀티 테넌시(multi-tenancy)
|
||||
content_type: concept
|
||||
weight: 70
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
이 페이지는 클러스터 멀티 테넌시를 구현하기 위해 유효한 구성 옵션과 모범 사례에 대한 개요를
|
||||
제공한다.
|
||||
|
||||
클러스터 공유를 통해 비용 절감 및 운영을 간편화할 수 있다. 그러나 클러스터를 공유하게 되면
|
||||
보안, 공평성, _소란스러운 이웃(noisy neighbors)_ 관리와 같이 여러 문제 상황이 발생할 수 있다.
|
||||
|
||||
클러스터는 다양한 방법을 통해 공유될 수 있다. 특정 경우에는 같은 클러스터 내 서로 다른 애플리케이션이 실행될 수 있다.
|
||||
또 다른 경우에는 하나의 애플리케이션에서 각 엔드유저에 대한 인스턴스가 모여 여러 인스턴스가 같은 클러스터 내에서 실행될 수 있다.
|
||||
이러한 모든 종류의 공유 방법은 주로
|
||||
_멀티 테넌시_ 라는 포괄적 용어로 통칭한다.
|
||||
|
||||
쿠버네티스에서는 엔드 유저 또는 테넌트에 대한 정형화된 개념을 정해놓고 있지는 않지만,
|
||||
다양한 테넌시 요구사항을 관리하기 위한 몇 가지 기능을 제공한다. 이에 대한 내용은 밑에서 다룬다.
|
||||
|
||||
<!-- body -->
|
||||
## 유스케이스
|
||||
|
||||
클러스터를 공유하기 위해 고려해야 하는 첫 번째 단계는,
|
||||
사용 가능한 패턴과 툴을 산정하기 위해 유스케이스를 이해하는 것이다. 일반적으로 쿠버네티스에서의 멀티 테넌시는
|
||||
다양한 형태로 변형 또는 혼합이 가능하지만, 넓게는 두 가지 범주로 분류된다.
|
||||
|
||||
### 다수의 팀
|
||||
|
||||
흔히 사용하는 멀티 테넌시의 형태는 하나 또는 그 이상의 워크로드를
|
||||
운영하는 한 조직 소속의 여러 팀이 하나의 클러스터를 공유하는 형태이다. 이러한 워크로드는
|
||||
같은 클러스터 내외의 다른 워크로드와 잦은 통신이 필요하다.
|
||||
|
||||
이러한 시나리오에서 팀에 속한 멤버는 보통 `kubectl`과 같은 툴을 통해 쿠버네티스 리소스에 직접적으로 접근하거나,
|
||||
GitOps 컨트롤러 혹은 다른 종류의 배포 자동화 툴을 통해 간접적으로 접근한다.
|
||||
대개는 다른 팀 멤버 간에 일정량의 신뢰가 형성되어 있지만,
|
||||
안전하고 공평한 클러스터 공유를 위해서는
|
||||
RBAC, 쿼터(quota), 네트워크 정책과 같은 쿠버네티스 정책이 필수이다.
|
||||
|
||||
### 다수의 고객
|
||||
|
||||
다른 주요 멀티 테넌시 형태로는 서비스형소프트웨어(SaaS) 사업자가
|
||||
여러 고객의 워크로드 인스턴스를 실행하는 것과 관련이 있다.
|
||||
이러한 비즈니스 모델은 많은 이들이 "SaaS 테넌시"라고 부르는 배포 스타일과 밀접한 연관이 있다.
|
||||
그러나 SaaS 사업자는 다른 배포 모델을 사용할 수 있기도 하며 SaaS가 아니어도 이러한 배포 모델의 적용이 가능하기 때문에,
|
||||
"다중 고객 테넌시(multi-customer tenancy)"를 더 적합한 용어로 볼 수 있다.
|
||||
|
||||
고객은 이러한 시나리오에서 클러스터에 대한 접근 권한을 가지지 않는다. 쿠버네티스는 그들의
|
||||
관점에서는 보이지 않으며, 사업자가 워크로드를 관리하기 위해서만 사용된다. 비용 최적화는
|
||||
주로 중대한 관심사가 되며,
|
||||
워크로드 간의 확실한 격리를 보장하기 위해 쿠버네티스 정책이 사용된다.
|
||||
|
||||
## 용어
|
||||
|
||||
### 테넌트
|
||||
|
||||
쿠버네티스에서의 멀티 테넌시를 논할 때는,
|
||||
"테넌트(tenant)"를 하나의 의미로 해석할 수 없다.
|
||||
오히려 다중 팀 혹은 다중 고객 테넌시의 여부에 따라 테넌트의 정의는 달라진다.
|
||||
|
||||
다중 팀 사용(multi-team usage)에서의 테넌트는 일반적으로 하나의 팀을 의미하며,
|
||||
이 팀은 일반적으로 서비스의 복잡도에 따라 스케일 하는 작은 양의 워크로드를 다수 배포한다.
|
||||
그러나 "팀" 자체에 대한 정의도 상위 조직으로
|
||||
구성될 수 있기도 하고 작은 팀으로 세분화될 수 있기 때문에 정의가 모호할 수 있다.
|
||||
|
||||
반대로 각 팀이 새로운 고객에 대한 전용 워크로드를 배포하게 된다면,
|
||||
다중 고객 테넌시 모델을 사용한다고 볼 수 있다. 이와 같은 경우에서는,
|
||||
"테넌트"는 하나의 워크로드를 공유하는 사용자의 집합을 의미한다.
|
||||
이는 하나의 기업만큼 큰 규모일 수도 있고, 해당 기업의 한 팀 정도의 작은 규모일수도 있다.
|
||||
|
||||
같은 조직이 "테넌트"에 대한 두 개의 정의를 서로 다른 맥락에서 사용할 수 있는 경우가 많다.
|
||||
예를 들어, 플랫폼 팀은 다수의 내부 "고객"을 위해 보안 툴 및 데이터베이스와 같은 공유된 서비스를 제공할 수 있고,
|
||||
SaaS 사업자는 공유된 개발 클러스터를 다수의 팀에게 제공할 수 있다.
|
||||
마지막으로, SaaS 제공자는 민감한 데이터를 다루는 고객별 워크로드와
|
||||
공유된 서비스를 다루는 멀티 테넌트를 혼합하여 제공하는 하이브리드 구조도
|
||||
사용이 가능하다.
|
||||
|
||||
{{< figure src="/images/docs/multi-tenancy.png" title="공존하는 테넌시 모델을 나타내고 있는 클러스터" class="diagram-large" >}}
|
||||
|
||||
### 격리
|
||||
|
||||
쿠버네티스에서 멀티 테넌트 솔루션을 설계하고 빌드 하는 방법은 몇 가지가 있다.
|
||||
각 방법은 격리 수준, 구현 비용, 운영 복잡도, 서비스 비용에
|
||||
영향을 미치는 각자만의 상충 요소를 가지고 있다.
|
||||
|
||||
각 쿠버네티스 클러스터는 쿠버네티스 소프트웨어를 실행하는 컨트롤 플레인과
|
||||
테넌트의 워크로드가 파드의 형태로 실행되고 있는 워커 노드로 구성된 데이터 플레인으로 구성되어 있다.
|
||||
테넌트 격리는 조직의 요구사항에 따라 컨트롤 플레인 및 데이터 플레인 모두에 대해 적용할 수 있다.
|
||||
|
||||
제공되는 격리의 수준은 강한 격리를 의미하는 "하드(hard)" 멀티 테넌시와
|
||||
약한 격리를 의미하는 "소프트(soft)" 멀티 테넌시와 같은 용어를 통해 정의한다.
|
||||
특히 "하드" 멀티 테넌시는 주로 보안이나 리소스 공유 관점(예를 들어, 데이터 유출 및 DoS 공격에 대한 방어)에서
|
||||
테넌트가 서로 신뢰하지 않는 상황을 설명할 때 주로 사용한다.
|
||||
데이터 플레인은 일반적으로 더 큰 공격 영역을 가지고 있기 때문에,
|
||||
컨트롤 플레인 격리 또한 중요하지만 데이터 플레인을 격리하는 데 있어서
|
||||
"하드" 멀티 테넌시는 추가적인 주의를 요구한다.
|
||||
|
||||
그러나 모든 사용자에게 적용할 수 있는 하나의 정의가 없기 때문에,
|
||||
"하드"와 "소프트" 용어에 대한 혼동이 생길 수 있다.
|
||||
오히려 요구사항에 따라 클러스터 내에서 다양한 종류의 격리를 유지할 수 있는 다양한 기법을 다루는 "하드한 정도"
|
||||
혹은 "소프트한 정도"가 넓은 범위에서는 이해하기에 편하다.
|
||||
|
||||
극단적인 경우에는 클러스터 레벨의 공유를 모두 포기하고 각 테넌트에 대한 전용 클러스터를 할당하거나,
|
||||
가상머신을 통한 보안 경계가 충분하지 않다고 판단될 시에는
|
||||
전용 하드웨어에서 실행하는 것이 쉽고 적절한 방법일 수 있다.
|
||||
클러스터를 생성하고 운영하는데 필요한 오버헤드를 클라우드 공급자가 맡게 되는
|
||||
매니지드 쿠버네티스 클러스터에서는 이와 같은 방식을 사용하기에 더 쉬울 수 있다.
|
||||
강한 테넌트 격리의 장점은 여러 클러스터를 관리하는데 필요한 비용과 복잡도와 비교하여 산정되어야 한다.
|
||||
[멀티 클러스터 SIG](https://git.k8s.io/community/sig-multicluster/README.md)는 이러한 종류의 유스케이스를 다루는 작업을 담당한다.
|
||||
|
||||
이 페이지의 남은 부분에서는 공유 쿠버네티스 클러스터에서 사용되는 격리 기법을 중점적으로 다룬다.
|
||||
그러나 전용 클러스터를 고려하고 있다 하더라도, 요구사항 혹은 기능에 대한 변화가 생겼을 때
|
||||
공유 클러스터로 전환할 수 있는 유연성을 제공할 수 있기 때문에,
|
||||
이러한 권고사항을 검토해 볼 가치가 있다.
|
||||
|
||||
## 컨트롤 플레인 격리
|
||||
|
||||
컨트롤 플레인 격리는 서로 다른 테넌트가 서로의 쿠버네티스 API 리소스에
|
||||
대한 접근 및 영향을 미치지 못하도록 보장한다.
|
||||
|
||||
### 네임스페이스
|
||||
|
||||
쿠버네티스에서 {{< glossary_tooltip text="네임스페이스" term_id="namespace" >}}는
|
||||
하나의 클러스터 내에서 API 리소스 그룹을 격리하는 데 사용하는 기능이다.
|
||||
이러한 격리는 두 가지 주요 특징을 지닌다.
|
||||
|
||||
1. 네임스페이스 내의 오브젝트 이름은 폴더 내의 파일과 유사하게 다른 네임스페이스에 속한
|
||||
이름과 중첩될 수 있다. 이를 통해 각 테넌트는 다른 테넌트의 활동과 무관하게 자신의
|
||||
리소스에 대한 이름을 정할 수 있다.
|
||||
|
||||
2. 많은 쿠버네티스 보안 정책은 네임스페이스 범위에서 사용한다. 예를 들어, RBAC 역할과
|
||||
네트워크 정책은 네임스페이스 범위의 리소스이다. RBAC를 사용함으로써 사용자 및 서비스
|
||||
어카운트는 하나의 네임스페이스에 대해 제한될 수 있다.
|
||||
|
||||
멀티 테넌트 환경에서의 각 네임스페이스는 테넌트의 워크로드를 논리적이고 구별되는 관리
|
||||
단위로 분할할 수 있다. 실제로 일반적인 관습에서는 여러 워크로드가 하나의 테넌트에 의해
|
||||
운영되더라도, 각 워크로드를 개별 네임스페이스로 격리한다. 이를 통해 각 워크로드는 개별
|
||||
정체성을 가질 수 있으며 적절한 보안 정책을 적용 받을 수 있게끔 보장한다.
|
||||
|
||||
네임스페이스 격리 모델은 테넌트 워크로드를 제대로 격리 시키기 위해 몇 가지 다른
|
||||
쿠버네티스 리소스, 네트워크 플러그인, 보안 모범 사례에 대한 준수가 필요하다. 이와 같이
|
||||
고려해야 하는 사항은 아래에 명시되어 있다.
|
||||
|
||||
### 접근 제어
|
||||
|
||||
컨트롤 플레인에서의 가장 중요한 격리 방식은 인증이다. 만일 팀 또는 해당 팀의 워크로드가
|
||||
서로 다른 API 리소스에 대한 접근 및 수정이 가능하다면, 다른 종류의 정책을 모두 바꾸거나
|
||||
비활성화할 수 있게 되어 해당 정책이 제공하는 보호를 무효화한다. 따라서 각 테넌트가 필요로
|
||||
하는 네임스페이스에 대한 적절한 최소의 권한만을 부여하는 것이 중요하다. 이는 "최소 권한의
|
||||
원칙(Principle of Least Privilege)"이라고 부른다.
|
||||
|
||||
|
||||
역할 기반 접근 제어(RBAC)는 흔히 쿠버네티스 컨트롤 플레인에서의 사용자와 워크로드에
|
||||
(서비스 어카운트) 대한 인증을 시행하기 위해 사용된다.
|
||||
[롤(Roles)](/docs/reference/access-authn-authz/rbac/#role-and-clusterrole)과
|
||||
[롤바인딩(RoleBindings)](/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding)은 네임스페이스 레벨에서 애플리케이션의
|
||||
접근 제어를 시행하기 위해 사용되는 쿠버네티스 오브젝트이다.
|
||||
클러스터 레벨의 오브젝트에 대한 접근 권한을 인증하기 위해 사용되는 유사한 오브젝트도 존재하지만, 이는 멀티 테넌트 클러스터에서는 비교적 유용성이 떨어진다.
|
||||
|
||||
다중 팀 환경에서는, 클러스터 전범위 리소스에 대해 클러스터 운영자와 같이 특권을 가진
|
||||
사용자에 의해서만 접근 또는 수정이 가능하도록 보장하기 위해 RBAC를 사용하여 테넌트의
|
||||
접근을 적합한 네임스페이스로 제한해야 한다.
|
||||
|
||||
만일 사용자에게 필요 이상으로 권한을 부여하는 정책이 있다면, 이는 영향 받는 리소스를
|
||||
포함하고 있는 네임스페이스가 더 세분화된 네임스페이스로 재구성 되어야 한다는 신호일
|
||||
가능성이 높다. 네임스페이스 관리 툴을 통해 공통된 RBAC 정책을 서로 다른 네임스페이스에
|
||||
적용하고 필요에 따라 세분화된 정책은 허용하며, 세분화된 네임스페이스를
|
||||
간편하게 관리할 수 있다.
|
||||
|
||||
### 쿼터
|
||||
|
||||
쿠버네티스 워크로드는 CPU 및 메모리와 같은 노드 리소스를 소모한다. 멀티 테넌트 환경에서는,
|
||||
테넌트 워크로드의 리소스 사용량을 관리하기 위해 [리소스 쿼터](/ko/docs/concepts/policy/resource-quotas/)를 사용할 수 있다.
|
||||
테넌트가 쿠버네티스 API에 대한 접근 권한을 가지는 다수 팀 유스케이스의 경우에는,
|
||||
테넌트가 생성할 수 있는 API 리소스(예를 들어, 파드의 개수 혹은 컨피그맵의 개수)의
|
||||
개수를 리소스 쿼터를 사용하여 제한할 수 있다.
|
||||
오브젝트 개수에 대한 제한은 공평성을 보장하고 같은 컨트롤 플레인을 공유하는 테넌트 간 침범이 발생하는
|
||||
_소란스러운 이웃_ 문제를 예방하기 위한 목적을 가지고 있다.
|
||||
|
||||
리소스 쿼터는 네임스페이스 오브젝트이다. 테넌트를 네임스페이스에 대해 매핑함으로써,
|
||||
클러스터 운영자는 쿼터를 사용하여 하나의 테넌트가 클러스터의 리소스를 독점하거나 컨트롤
|
||||
플레인을 압도하지 못하도록 보장할 수 있다. 네임스페이스 관리 툴은 쿼터 운영을
|
||||
간편화해준다. 이에 더해 쿠버네티스 쿼터는 하나의 네임스페이스 내에서만 적용이 가능하지만,
|
||||
특정 네임스페이스 관리 툴은 네임스페이스 그룹이 쿼터를 공유할 수 있도록 허용함으로써
|
||||
운영자에게 내장된 쿼터에 비해 적은 수고로 더 많은 유연성을 제공한다.
|
||||
|
||||
쿼터는 하나의 테넌트가 자신에게 할당된 몫의 리소스 보다 많이 사용하는 것을 방지하며, 이를
|
||||
통해 하나의 테넌트가 다른 테넌트의 워크로드 성능에 부정적 영향을 미치는 "소란스러운 이웃"
|
||||
문제를 최소화할 수 있다.
|
||||
|
||||
쿠버네티스에서 네임스페이스에 대한 쿼터를 적용할 시에는 각 컨테이너에 대한 리소스 요청과
|
||||
제한을 명시하도록 요구한다. 제한은 각 컨테이너가 소모할 수 있는 리소스의 양에 대한
|
||||
상한선이다. 설정된 제한을 초과하여 리소스 소모를 시도하는 컨테이너는 리소스의 종류에 따라
|
||||
스로틀(throttled)되거나 종료(killed)된다. 리소스 요청이 제한보다 낮게 설정되었을 시에는,
|
||||
각 컨테이너가 요청한 리소스의 양은 보장되지만
|
||||
워크로드 간의 영향이 있을 가능성은 존재한다.
|
||||
|
||||
쿼터는 네트워크 트래픽과 같이 모든 종류의 리소스 공유에 대한 보호는 할 수 없다.
|
||||
노드 격리(아래에서 설명)가 이러한 문제에 대해서는 더 나은 해결책일 수 있다.
|
||||
|
||||
## 데이터 플레인 격리
|
||||
|
||||
데이터 플레인 격리는 다른 테넌트의 파드 및 워크로드와 충분히 격리가 이루어질 수 있도록
|
||||
보장한다.
|
||||
|
||||
### 네트워크 격리
|
||||
|
||||
기본적으로 쿠버네티스 클러스터의 모든 파드는 서로 통신을 할 수 있도록 허용되어 있으며 모든
|
||||
네트워크 트래픽은 암호화되어 있지 않다. 이는 트래픽이 실수 또는 악의적으로 의도되지 않은
|
||||
목적지로 전송되거나 신뢰가 손상된(compromised) 노드 상의 워크로드에 의해 가로채지는 것과
|
||||
같은 보안 취약점으로 이어질 수 있다.
|
||||
|
||||
파드에서 파드로의 통신은 네임스페이스 레이블 혹은 IP 주소 범위를 통해 파드 간의 통신을
|
||||
제한하는 [네트워크 정책](/ko/docs/concepts/services-networking/network-policies/)에
|
||||
의해 제어될 수 있다. 테넌트 간의 엄격한 네트워크 격리가 필요한 멀티 테넌트 환경에서는,
|
||||
파드 간의 통신을 거부하는 기본 정책과 모든 파드가 네임 해석(name resolution)을 위해
|
||||
DNS 서버를 쿼리하도록 하는 규칙을 시작에 설정하는 것을 권고한다. 이러한 기본 정책을
|
||||
기반으로 하여, 네임스페이스 내에서 통신을 허용하는 관대한 규칙을 추가할 수 있다. 이러한
|
||||
방식은 요구에 따라 한 단계 더 정제할 수 있다. 이는 하나의 컨트롤 플레인 내의 파드에
|
||||
대해서만 적용된다는 것을 알아두어야 한다. 서로 다른 가상의 컨트롤 플레인에 소속된 파드는
|
||||
쿠버네티스 네트워킹을 통해 통신할 수 없다.
|
||||
|
||||
네임스페이스 관리 툴을 통해 기본 또는 공통 네트워크 정책을 간편하게 생성할 수 있다. 이에
|
||||
더해, 몇 가지 툴은 클러스터 상에서 일관된 집합의 네임스페이스 레이블을 사용할 수 있게
|
||||
함으로써 정책에 대한 신뢰 가능한 기반이 마련될 수 있도록 보장한다.
|
||||
|
||||
{{< warning >}}
|
||||
네트워크 정책은 구현 과정에서 지원되는 [CNI 플러그인](/ko/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/#cni)을 요구한다.
|
||||
만일 그렇지 않으면, 네트워크폴리시 리소스는 무시된다.
|
||||
{{< /warning >}}
|
||||
|
||||
추가적으로, 서비스 메쉬(service mesh)는 워크로드 특징에 따른 OSI 7 계층 정책을
|
||||
제공하므로 네임스페이스보다 더 고도의 네트워크 격리를 제공할 수 있다. 이러한 상위 정책은 특히
|
||||
하나의 테넌트에 대한 여러 네임스페이스가 있는 경우와 같이, 네임스페이스 기반 멀티 테넌시를
|
||||
더욱 쉽게 관리할 수 있도록 한다. 신뢰가 손상된(compromised) 노드가 발생했을 시에도 데이터를 보호할 수
|
||||
있는 상호 간의 TLS을 통해 암호화도 제공하며 전용 또는 가상의 클러스터 사이에서도
|
||||
동작한다. 그러나 관리하기에 더 복잡할 수 있으며 모든 사용자에게 적합한 방법이 아닐 수 있다.
|
||||
|
||||
### 스토리지 격리
|
||||
|
||||
쿠버네티스는 워크로드가 퍼시스턴트 스토리지로 사용할 수 있는 몇 가지 종류의 볼륨을
|
||||
제공한다. 보안 및 데이터 격리를 위해서는 [동적 볼륨 프로비저닝](/ko/docs/concepts/storage/dynamic-provisioning/)을
|
||||
권고하며 노드 리소스를 사용하는 볼륨 타입은 피해야 한다.
|
||||
|
||||
[스토리지 클래스](/ko/docs/concepts/storage/storage-classes/)는 클러스터에
|
||||
제공하는 사용자 정의 "클래스"를 서비스 품질 수준(quality-of-service level), 백업 정책 혹은 클러스터 운영자에 의해
|
||||
결정된 사용자 정의 정책을 기반으로 명시할 수 있도록 허용한다.
|
||||
|
||||
파드는 [퍼시스턴트 볼륨 클레임](/ko/docs/concepts/storage/persistent-volumes/)을
|
||||
통해 스토리지를 요청할 수 있다. 퍼시스턴트 볼륨 클레임은 공용 쿠버네티스 클러스터 내에서
|
||||
스토리지 시스템의 부분 단위 격리를 가능하게끔 하는 네임스페이스 리소스이다. 그러나
|
||||
퍼시스턴트 볼륨은 클러스터 전범위(cluster-wide)의 리소스이며 워크로드와 네임스페이스의 라이프사이클에
|
||||
독립적이므로, 이를 염두에 둘 필요가 있다.
|
||||
|
||||
예를 들어, 각 테넌트에 대한 별도의 스토리지 클래스를 설정할 수 있으며 이를 통해 격리를 강화할 수 있다.
|
||||
만일 스토리지 클래스가 공유된다면, [`Delete` 리클레임(reclaim) 정책](/ko/docs/concepts/storage/storage-classes/#리클레임-정책)을 설정하여
|
||||
퍼시스턴트 볼륨이 다른 네임스페이스에서 재사용되지 못하도록 보장해야 한다.
|
||||
|
||||
### 컨테이너 샌드박싱(sandboxing)
|
||||
|
||||
{{% thirdparty-content %}}
|
||||
|
||||
쿠버네티스 파드는 워커 노드 상에서 실행되는 하나 또는 그 이상의 컨테이너로 구성되어 있다.
|
||||
컨테이너는 OS 레벨의 가상화를 활용하기 때문에 하드웨어 기반의 가상화를 활용하는
|
||||
가상 머신에 비해 격리의 경계가 약하다.
|
||||
|
||||
공유 환경에서 애플리케이션 및 시스템 계층 상 패치되지 않은 취약점은
|
||||
컨테이너 탈출(container breakout) 또는 원격 코드 실행과 같이 호스트 리소스에 대한
|
||||
접근을 허용하여 공격자에 의해 악용될 수 있다. 컨텐츠 매니지먼트 시스템(CMS)과 같은 특정
|
||||
애플리케이션에서는, 고객이 신뢰되지 않은 스크립트 및 코드를 업로드할 수 있는 기능이 허용될 수 있다.
|
||||
어떤 경우이든, 강한 격리를 통해 워크로드를 한 단계 더 격리하고 보호하기 위한 기능은 필요하다.
|
||||
|
||||
샌드박싱은 공유 클러스터에서 실행되는 워크로드를 격리하는 방법을 제공한다. 일반적으로 각
|
||||
파드를 가상 머신 또는 유저스페이스 커널(userspace kernel)과 같은 별도의 실행 환경에서 실행하는 것과 연관이
|
||||
있다. 샌드박싱은 주로 워크로드가 악의적으로 판단되는 신뢰되지 않은 코드를 실행할 때
|
||||
권고된다. 이러한 격리가 필요한 이유는 컨테이너가 공유된 커널에서 실행되기 때문이다.
|
||||
컨테이너는 하위 호스트의 `/sys` 및 `/proc` 와 같은 파일 시스템을 마운트 하기 때문에,
|
||||
개별 커널을 가지는 가상 머신에서 실행되는 애플리케이션과 비교하였을 때는 보안성이 낮다.
|
||||
Seccomp, AppArmor, SELinux와 같은 제어를 통해 컨테이너의 보안을 강화할 수 있지만,
|
||||
공유 클러스터에서 실행되고 있는 모든 워크로드에 대해 공통된 규칙을 적용하는 데는 어려움이
|
||||
있다. 워크로드를 샌드박스 환경에서 실행함으로써, 공격자가 호스트의 취약점을 악용하여
|
||||
호스트 시스템 및 해당 호스트에서 실행되고 있느 모든 프로세스와 파일 대한 권한을 얻을 수
|
||||
있는 컨테이너 탈출로 부터 호스트를 보호할 수 있다.
|
||||
|
||||
가상 머신 및 유저스페이스 커널은 샌드박싱을 제공하는 대표적인 두 가지 방법이다.
|
||||
다음과 같은 샌드박싱 구현이 가능하다.
|
||||
|
||||
* [gVisor](https://gvisor.dev/)는 컨테이너로부터 시스템 호출을 가로채 Go로 작성된
|
||||
유저스페이스 커널을 통해 실행하므로, 컨테이너가 호스트 내부(underlying host)에 대한 제한적인 접근 권한만 가진다.
|
||||
* [Kata 컨테이너](https://katacontainers.io/)는 OCI에 부합하는 런타임으로 가상 머신 내에서
|
||||
컨테이너가 실행되도록 한다. Kata는 하드웨어 가상화를 통해, 신뢰되지 않은
|
||||
코드를 실행하는 컨테이너에 대해 추가적인 보안 계층을 제공한다.
|
||||
|
||||
### 노드 격리
|
||||
|
||||
노드 격리는 테넌트 워크로드를 서로 격리시킬 수 있는 또 다른 기법이다. 노드 격리를 통해
|
||||
하나의 노드 집합은 특정 테넌트의 파드를 전용으로 실행할 수 있으며 테넌트 파드 간의 혼합(co-mingling)은
|
||||
금지되어 있다. 이러한 구성을 사용하게 되면 노드 상에서 실행되는 파드가 모두 하나의 테넌트
|
||||
소유이기 때문에 소란스러운 테넌트 문제를 줄일 수 있다. 컨테이너 탈출에 성공한 공격자가
|
||||
있다 하더라도, 해당 노드의 컨테이너 및 마운트 된 볼륨에 대해서만 접근 권한을 가지므로,
|
||||
노드 격리를 통해 정보 유출의 위험도 비교적 감소한다.
|
||||
|
||||
다른 테넌트의 워크로드가 다른 노드에서 실행되고 있다 하더라도, Kubelet과 (가상 컨트롤
|
||||
플레인을 사용하지 않는 한) API 서비스는 여전히 공유되고 있다는 사실을 이해하는 것은 중요하다.
|
||||
능숙한 공격자는 Kubelet 또는 노드에서 실행되고 있는 다른 파드에 부여된 권한을 이용하여
|
||||
클러스터 내에서 좌우로 이동하며 다른 노드에서 실행되고 있는 테넌트 워크로드에 대한 접근
|
||||
권한을 얻을 수 있다. 만일 이러한 사항이 우려된다면, seccomp, AppArmor, SELinux와 같은
|
||||
제어 방식을 이용하거나, 샌드박스 컨테이너 이용 또는 각 테넌트에 대한 개별 클러스터를
|
||||
생성하는 방안을 검토해 보아야 한다.
|
||||
|
||||
노드 격리를 통해 파드가 아닌 노드 별 비용을 청구할 수 있으므로, 비용 관점에서는 샌드박스 컨테이너에
|
||||
비해 이해 및 파악이 수월하다. 또한 호환성 및
|
||||
성능 문제 발생 가능성이 낮으며 샌드박스 컨테이너 보다 구현도 더 쉬운 편이다. 예를 들어, 각
|
||||
테넌트에 대한 노드는 대응하는 톨러레이션(toleration)을 가진 파드만 실행할 수 있도록 테인트(taint)를 통해
|
||||
설정할 수 있다. 변화하는 웹훅을 통해 자동으로 톨러레이션과 노드 어피니티를 테넌트
|
||||
네임스페이스에 배포된 파드에 추가하여, 해당 파드를 특정 테넌트를 위해 지정된 특정 노드의
|
||||
집합에서 실행될 수 있도록 한다.
|
||||
|
||||
노드 격리는 [파드 노드 셀렉터](/ko/docs/concepts/scheduling-eviction/assign-pod-node/)
|
||||
또는 [가상 Kubelet(Virtual Kubelet)](https://github.com/virtual-kubelet)을 통해 구현할 수 있다.
|
||||
|
||||
## 추가적인 고려 사항
|
||||
|
||||
해당 섹션에서는 멀티 테넌시와 연관 있는 이외의 쿠버네티스 구성 및 패턴에 대한 내용을 다룬다.
|
||||
|
||||
### API 우선순위와 공평성
|
||||
|
||||
[API 우선순위(priority)와 공평성(fairness)](/docs/concepts/cluster-administration/flow-control/)은
|
||||
쿠버네티스의 기능 중 하나로, 클러스터 내 실행 중인 특정 파드에 대해 우선순위를 부여할 수
|
||||
있다. 애플리케이션이 쿠버네티스 API를 호출하게 되면, API 서버는 해당 파드에 부여된
|
||||
우선순위를 산정한다. 더 높은 우선순위를 가진 파드의 호출은 낮은 우선순위를 가진 파드의
|
||||
호출보다 먼저 수행된다. 경합률(contention)이 높을 시에는 낮은 우선순위의 호출은 서버 리소스가 한가해질
|
||||
때까지 대기하거나 해당 요청을 거부할 수 있다.
|
||||
|
||||
고객이 쿠버네티스 API와 상호작용하는 애플리케이션(예를 들어, 컨트롤러)을 실행하지 않은 한,
|
||||
SaaS 환경에서 API 우선순위와 공평성을 사용하는 일은
|
||||
흔치 않을 것이다.
|
||||
|
||||
### 서비스 품질(QoS) {#qos}
|
||||
|
||||
SaaS 애플리케이션을 실행할 시에는, 각 테넌트에게 다른 수준의 서비스 품질 티어(tier)를
|
||||
제공하는 기능이 필요할 수 있다. 예를 들어, 낮은 성능 및 기능을 보장하는 무료 서비스와 특정
|
||||
수준의 성능을 보장하는 유료 서비스를 제공할 수 있다. 다행히 쿠버네티스는 이러한 티어를 공유 클러스터
|
||||
내에서 구현하기 위한 네트워크 QoS, 스토리지 클래스, 파드 우선순위 및 선점과 같은
|
||||
몇 가지 구성들을 제공한다. 이는 각 테넌트가 지불한 비용에 적합한 서비스 품질을
|
||||
제공하기 위한 목적이다.
|
||||
우선 네트워크 QoS에 대해 먼저 살펴본다.
|
||||
|
||||
일반적으로 하나의 노드에 위치한 모든 파드는 네트워크 인터페이스를 공유한다. 네트워크
|
||||
QoS 없이는, 몇 개의 파드가 가용 대역폭 중 다른 파드의 대역폭까지
|
||||
소모하여 불공평한 공유를 야기할 수 있다.
|
||||
쿠버네티스 [대역폭 플러그인](https://www.cni.dev/plugins/current/meta/bandwidth/)은
|
||||
리눅스 tc 큐를 이용하여 파드에 비율 제한을 적용할 수 있는 쿠버네티스 리소스 구성(예를 들어, 요청/제한)을 사용 가능하게 하는 네트워킹
|
||||
[확장 리소스](/ko/docs/concepts/configuration/manage-resources-containers/#확장된-리소스)를 생성한다.
|
||||
[네트워크 플러그인](/ko/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/#support-traffic-shaping)
|
||||
문서에 따르면 해당 플러그인은 아직은 실험 목적으로 사용되고 있다는 점에 대한 주의가
|
||||
필요하며 프로덕션 환경에서 사용하기 전에는 철저한 테스트가 이루어져야 한다.
|
||||
|
||||
스토리지 서비스 품질과 같은 경우에는, 각 성능 특징을 나타내기 위해 서로 다른 스토리지
|
||||
클래스 또는 프로필을 생성할 필요가 있다. 각 스토리지 프로필은 IO, 중복성, 처리량과 같이
|
||||
서로 다른 워크로드에 최적화된 티어의 서비스와 묶을 수 있다. 테넌트가 자신의 워크로드에
|
||||
적합한 스토리지 프로필을 적용하기 위해서는
|
||||
추가적인 로직이 필요할 수 있다.
|
||||
|
||||
마지막으로, 파드에 우선순위 값을 부여할 수 있는
|
||||
[파드 우선순위와 선점](/ko/docs/concepts/scheduling-eviction/pod-priority-preemption/)이 있다.
|
||||
파드 스케줄링 시에 우선순위가 높은 파드를 스케줄링하기 위한 리소스가 부족하다면,
|
||||
스케줄러는 낮은 우선순위의 파드에 대한 축출을 시도한다. 공유 클러스터 내에서 다른 서비스
|
||||
티어(예를 들어, 무료 및 유료)를 사용하는 테넌트를 가진 유스케이스가 있다면, 이러한 기능을
|
||||
활용하여 특정 티어에 더 높은 우선순위를 부여할 수 있다.
|
||||
|
||||
### DNS
|
||||
|
||||
쿠버네티스 클러스터는 네임과 IP 주소 간의 변환을 제공하기 위해 모든 서비스와 파드에서
|
||||
도메인 네임 시스템(DNS) 서비스를 포함하고 있다. 기본적으로 쿠버네티스 DNS 서비스를 통해
|
||||
클러스터 내 모든 네임스페이스를 조회할 수 있다.
|
||||
|
||||
테넌트가 파드 및 다른 쿠버네티스 리소스에 접근할 수 있거나,
|
||||
더욱 강력한 격리가 필요한 멀티 테넌트 환경에서는
|
||||
파드가 다른 네임스페이스의 서비스를 조회하는 것을 막는 것이 적절할 수 있다.
|
||||
네임스페이스 교차 DNS 조회(cross-namespace DNS lookup)는 DNS 서비스의 보안 규칙 설정을 통해 제한할 수 있다.
|
||||
예를 들어, CoreDNS(쿠버네티스 기본 DNS 서비스)는 쿠버네티스 메타데이터를 이용하여 네임스페이스 내의 파드 및 서비스에 대한 쿼리를 제한할 수 있다.
|
||||
추가적인 정보는
|
||||
CoreDNS 문서에 포함된 해당 사항을 설정하는
|
||||
[예시](https://github.com/coredns/policy#kubernetes-metadata-multi-tenancy-policy)에서 확인할 수 있다.
|
||||
|
||||
[테넌트 별 가상 컨트롤 플레인](#테넌트-별-가상-컨트롤-플레인) 모델이 사용될 시에는,
|
||||
테넌트 별 DNS 서비스가 설정하거나 멀티 테넌트 DNS 서비스를 사용해야 한다.
|
||||
[CoreDNS 사용자 맞춤 버전](https://github.com/kubernetes-sigs/cluster-api-provider-nested/blob/main/virtualcluster/doc/tenant-dns.md)은
|
||||
멀티 테넌트를 지원하는 하나의 예시이다.
|
||||
|
||||
### 오퍼레이터
|
||||
|
||||
[오퍼레이터](/ko/docs/concepts/extend-kubernetes/operator/)는
|
||||
애플리케이션을 관리하는 쿠버네티스 컨트롤러이다. 오퍼레이터는 데이터베이스 서비스와
|
||||
유사하게 애플리케이션의 여러 인스턴스를 간편하게 관리할 수 있어, 다중 소비자 (SaaS) 멀티
|
||||
테넌시 유스케이스의 중요한 기반이 된다.
|
||||
|
||||
멀티 테넌트 환경에서 사용되는 오퍼레이터는 더욱 엄격한 가이드라인을 준수해야 한다.
|
||||
다음은 오퍼레이터가 지켜야 할 사항이다.
|
||||
|
||||
* 오퍼레이터가 배포된 네임스페이스뿐만 아니라,
|
||||
다른 테넌트 네임스페이스에서의 리소스 생성도 지원해야 한다.
|
||||
* 스케줄링과 공평성을 보장하기 위해, 파드에 대한 리소스 요청 및 제한을 설정한다.
|
||||
* 파드에서 노드 격리 및 샌드박스 컨테이너와 같은 데이터 플레인 격리 기법을 설정할 수
|
||||
있도록 지원한다.
|
||||
|
||||
## 구현
|
||||
|
||||
{{% thirdparty-content %}}
|
||||
|
||||
멀티 테넌시를 위해 쿠버네티스 클러스터를 공유하는 대표적인 방법은 두 가지가 있으며,
|
||||
이는 네임스페이스 사용 (테넌트 별 네임스페이스) 또는 컨트롤 플레인 가상화 (테넌트 별 가상
|
||||
컨트롤 플레인)이다.
|
||||
|
||||
두 경우 모두 데이터 플레인 격리와 API 우선순위 및 공평성과 같은 추가적인 고려 사항에 대한
|
||||
관리를 권고한다.
|
||||
|
||||
네임스페이스 격리는 쿠버네티스에서 지원이 잘 이루어지고 있으며, 아주 적은 리소스 비용을
|
||||
소모하며 서비스 간의 통신과 같은 테넌트가 상호작용하기 위한 기능을 제공한다. 그러나
|
||||
설정하는 과정이 복잡하며 커스텀 리소스 데피니션 정의, 스토리지 클래스, 웹훅과 같이
|
||||
네임스페이스 적용을 받지 않은 쿠버네티스 리소스에 대해서는 적용되지 않는다.
|
||||
|
||||
컨트롤 플레인 가상화는 더 많은 리소스 사용량과 더 어려운 테넌트 교차 공유(cross-tenant sharing)를 대가로,
|
||||
네임스페이스 되지 않은 리소스에 대한 격리 기능을 제공한다.
|
||||
네임스페이스 격리로는 충분하지 않으며 높은 운영 비용 (특히 온 프레미스)
|
||||
또는 큰 오버헤드와 리소스 공유의 부재로 인한 전용 클러스터는 사용하지 못할 때 좋은 선택지다.
|
||||
그러나, 가상 컨트롤 플레인을 사용하더라도 네임스페이스를
|
||||
같이 사용하면 이익을 볼 수 있다.
|
||||
|
||||
두 가지의 옵션은 다음 섹션에서 상세히 다룬다.
|
||||
|
||||
### 테넌트 별 네임스페이스
|
||||
|
||||
이전에 언급하였듯이, 전용 클러스터 또는 가상 컨트롤 플레인을 사용하더라도 각 워크로드를
|
||||
개별 네임스페이스로 격리하는 것을 고려해 보아야 한다.
|
||||
이를 통해 각 워크로드는 컨피그맵 및 시크릿과 같이 자신의 리소스에만 접근할 수 있으며
|
||||
각 워크로드에 대한 전용 보안 정책을 조정할 수 있다.
|
||||
추가적으로, 전용 및 공유 클러스터 간 전환 혹은 서비스 메쉬와 같은 멀티
|
||||
클러스터 툴을 이용할 수 있는 유연성을 제공받기 위해 각 네임스페이스 이름을 전체 클러스터
|
||||
무리 사이에서도 고유하게 짓는 것이 (즉, 서로 다른 클러스터에 위치하더라도) 모범 사례이다.
|
||||
|
||||
반대로 워크로드 레벨이 아닌, 하나의 테넌트가 소유한 모든 워크로드에 대해 적용되는 정책도
|
||||
있기 때문에 테넌트 레벨에서의 네임스페이스 적용도 장점이 있다. 그러나 이는 또 다른 문제를
|
||||
제기한다. 첫 번째로 개별 워크로드에 대한 맞춤 정책을 적용하는 것이 어렵거나 불가능해지며,
|
||||
두 번째로는 네임스페이스를 적용받을 하나의 "테넌시" 레벨을 정하는 것이 어려울 수 있다.
|
||||
예를 들어, 하나의 조직에 부서, 팀, 하위 팀이 있다고 하면 어떤 단위에 대해
|
||||
네임스페이스를 적용해야 하는가?
|
||||
|
||||
이러한 문제의 해결책으로, 네임스페이스를 계층으로 정리하고 특정 정책 및 리소스를 사이에서
|
||||
공유할 수 있는 [계층적 네임스페이스 컨트롤러(HNC)](https://github.com/kubernetes-sigs/hierarchical-namespaces)를
|
||||
쿠버네티스에서 제공하고 있다. 또한 네임스페이스 레이블 관리, 네임스페이스 라이프사이클,
|
||||
관리 위임, 관련된 네임스페이스 사이에서 리소스 쿼터 공유와 같은 이점도 있다. 이러한
|
||||
기능은 다중 팀 및 다중 고객 시나리오에서도 유용하다.
|
||||
|
||||
유사한 기능을 제공하며 네임스페이스 리소스 관리를 돕는 다른 프로젝트는
|
||||
다음과 같다.
|
||||
|
||||
#### 다중 팀 테넌시
|
||||
|
||||
* [Capsule](https://github.com/clastix/capsule)
|
||||
* [Kiosk](https://github.com/loft-sh/kiosk)
|
||||
|
||||
#### 다중 고객 테넌시
|
||||
|
||||
* [Kubeplus](https://github.com/cloud-ark/kubeplus)
|
||||
|
||||
#### 정책 엔진
|
||||
|
||||
정책 엔진은 테넌트 구성을 생성하고 검증하는 기능을 제공한다.
|
||||
|
||||
* [Kyverno](https://kyverno.io/)
|
||||
* [OPA/Gatekeeper](https://github.com/open-policy-agent/gatekeeper)
|
||||
|
||||
### 테넌트 별 가상 컨트롤 플레인
|
||||
|
||||
컨트롤 플레인 격리의 또 다른 형태로는 쿠버네티스 확장을 이용하여 클러스터 전범위의 API
|
||||
리소스를 세분화할 수 있는, 각 테넌트에 가상 컨트롤 플레인을 제공하는 형태이다.
|
||||
[데이터 플레인 격리](#데이터-플레인-격리) 기법을 이러한 모델과 함께 이용하여 테넌트
|
||||
간의 워커 노드를 안전하게 관리할 수 있다.
|
||||
|
||||
가상 컨트롤 플레인 기반의 멀티 테넌시 모델은 각 테넌트에게 전용 컨트롤 플레인 요소를
|
||||
제공하며 클러스터 전범위 리소스 및 애드온 서비스에 대한 완전한 제어를 부여하게 되어
|
||||
네임스페이스 기반 멀티 테넌시를 확장한다. 워커 노드는 모든 테넌트 간 공유 되며,
|
||||
일반적으로 테넌트에 의해 접근이 불가능한 쿠버네티스 클러스터에 의해 관리된다.
|
||||
이러한 클러스터를 _슈퍼 클러스터_ (혹은 _호스트 클러스터_)라고 부른다.
|
||||
테넌트의 컨트롤 플레인은 하위 컴퓨팅 리소스와 직접적으로 연결된 것이 아니기 때문에
|
||||
_가상 컨트롤 플레인_ 이라고 부른다.
|
||||
|
||||
가상 컨트롤 플레인은 일반적으로 쿠버네티스 API 서버, 컨트롤러 매니저, etcd 데이터
|
||||
스토어로 구성되어 있다. 테넌트 컨트롤 플레인과 슈퍼 클러스터 컨트롤 플레인 간 변화를
|
||||
조정하는 메타데이터 동기화 컨트롤러를 통해
|
||||
슈퍼 클러스터와 상호작용한다.
|
||||
|
||||
하나의 API 서버를 사용하였을 때 나타나는 격리 문제는 테넌트 별 전용 컨트롤 플레인을
|
||||
이용하면 해결된다. 몇 가지 예시로는, 컨트롤 플레인 내의 소란스러운 이웃 문제,
|
||||
잘못된 정책 설정으로 인한 제어불능 영향 반경, 웹훅 및 CRD와 같은
|
||||
클러스터 범위 오브젝트 간의 충돌이 있다.
|
||||
그러므로 각 테넌트가 쿠버네티스 API 서버에 대한 접근 권한 및 완전한 클러스터 관리
|
||||
기능이 필요한 경우, 가상 컨트롤 플레인 모델이 적합하다.
|
||||
|
||||
개선된 격리의 대가는 각 테넌트 별 가상 컨트롤 플레인을 운영하고 유지하는 비용에서
|
||||
나타난다. 추가적으로, 각 테넌트 컨트롤 플레인은 노드 레벨에서의 소란스러운 이웃 문제 또는
|
||||
보안 위협과 같은 데이터 플레인에서의 격리 문제를 해결하지 못한다. 이러한 문제에 대해서는
|
||||
별도로 대응해야 한다.
|
||||
|
||||
쿠버네티스 [클러스터 API - 네스티드(CAPN)](https://github.com/kubernetes-sigs/cluster-api-provider-nested/tree/main/virtualcluster)
|
||||
프로젝트는 가상 컨트롤 플레인 구현 방식을 제공한다.
|
||||
|
||||
#### 이외의 구현 방식
|
||||
|
||||
* [Kamaji](https://github.com/clastix/kamaji)
|
||||
* [vcluster](https://github.com/loft-sh/vcluster)
|
||||
|
Loading…
Reference in New Issue