쿠버네티스 API 접근 제어하기
이 페이지는 쿠버네티스 API에 대한 접근 제어의 개요를 제공한다.
사용자는 kubectl
, 클라이언트 라이브러리
또는 REST 요청을 통해
API에 접근한다.
사용자와 쿠버네티스 서비스 어카운트 모두 API에 접근할 수 있다.
요청이 API에 도달하면,
다음 다이어그램에 설명된 몇 가지 단계를 거친다.
전송 보안
일반적인 쿠버네티스 클러스터에서 API는 443번 포트에서 서비스한다.
API 서버는 인증서를 제시한다.
이 인증서는 종종 자체 서명되기 때문에 일반적으로 사용자 머신의 $USER/.kube/config
는
API 서버의 인증서에 대한 루트 인증서를 포함하며,
시스템 기본 루트 인증서 대신 사용된다.
kube-up.sh
을 사용하여 클러스터를 직접 생성할 때
이 인증서는 일반적으로 $USER/.kube/config
에 자동으로 기록된다.
클러스터에 여러 명의 사용자가 있는 경우, 작성자는 인증서를 다른 사용자와 공유해야 한다.
인증
TLS가 설정되면 HTTP 요청이 인증 단계로 넘어간다. 이는 다이어그램에 1단계로 표시되어 있다. 클러스터 생성 스크립트 또는 클러스터 관리자는 API 서버가 하나 이상의 인증기 모듈을 실행하도록 구성한다. 인증기는 여기에서 더 자세히 서술한다.
인증 단계로 들어가는 것은 온전한 HTTP 요청이지만 일반적으로 헤더 그리고/또는 클라이언트 인증서를 검사한다.
인증 모듈은 클라이언트 인증서, 암호 및 일반 토큰, 부트스트랩 토큰, JWT 토큰(서비스 어카운트에 사용됨)을 포함한다.
여러 개의 인증 모듈을 지정할 수 있으며, 이 경우 하나의 인증 모듈이 성공할 때까지 각 모듈을 순차적으로 시도한다.
GCE에서는 클라이언트 인증서, 암호, 일반 토큰 및 JWT 토큰이 모두 사용 가능하다.
요청을 인증할 수 없는 경우 HTTP 상태 코드 401과 함께 거부된다.
이 외에는 사용자가 특정 username
으로 인증되며,
이 username은 다음 단계에서 사용자의 결정에 사용할 수 있다.
일부 인증기는 사용자 그룹 관리 기능을 제공하는 반면,
이외의 인증기는 그렇지 않다.
쿠버네티스는 접근 제어 결정과 요청 기록 시 usernames
를 사용하지만,
user
오브젝트를 가지고 있지 않고 usernames 나 기타 사용자 정보를
오브젝트 저장소에 저장하지도 않는다.
인가
특정 사용자로부터 온 요청이 인증된 후에는 인가되어야 한다. 이는 다이어그램에 2단계로 표시되어 있다.
요청은 요청자의 username, 요청된 작업 및 해당 작업이 영향을 주는 오브젝트를 포함해야 한다. 기존 정책이 요청된 작업을 완료할 수 있는 권한이 해당 사용자에게 있다고 선언하는 경우 요청이 인가된다.
예를 들어 Bob이 아래와 같은 정책을 가지고 있다면 projectCaribou
네임스페이스에서만 파드를 읽을 수 있다.
{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "bob",
"namespace": "projectCaribou",
"resource": "pods",
"readonly": true
}
}
Bob이 다음과 같은 요청을 하면 'projectCaribou' 네임스페이스의 오브젝트를 읽을 수 있기 때문에 요청이 인가된다.
{
"apiVersion": "authorization.k8s.io/v1beta1",
"kind": "SubjectAccessReview",
"spec": {
"resourceAttributes": {
"namespace": "projectCaribou",
"verb": "get",
"group": "unicorn.example.org",
"resource": "pods"
}
}
}
Bob이 projectCaribou
네임스페이스에 있는 오브젝트에 쓰기(create
또는 update
) 요청을 하면 그의 인가는 거부된다. 만약 Bob이 projectFish
처럼 다른 네임스페이스의 오브젝트 읽기(get
) 요청을 하면 그의 인가는 거부된다.
쿠버네티스 인가는 공통 REST 속성을 사용하여 기존 조직 전체 또는 클라우드 제공자 전체의 접근 제어 시스템과 상호 작용할 것을 요구한다. 이러한 제어 시스템은 쿠버네티스 API 이외의 다른 API와 상호작용할 수 있으므로 REST 형식을 사용하는 것이 중요하다.
쿠버네티스는 ABAC 모드, RBAC 모드, 웹훅 모드와 같은 여러 개의 인가 모듈을 지원한다. 관리자가 클러스터를 생성할 때 API 서버에서 사용해야 하는 인가 모듈을 구성했다. 인가 모듈이 2개 이상 구성되면 쿠버네티스가 각 모듈을 확인하고, 어느 모듈이 요청을 승인하면 요청을 진행할 수 있다. 모든 모듈이 요청을 거부하면 요청이 거부된다(HTTP 상태 코드 403).
인가 모듈을 사용한 정책 생성을 포함해 쿠버네티스 인가에 대해 더 배우려면 인가 개요를 참조한다.
어드미션 제어
어드미션 제어 모듈은 요청을 수정하거나 거부할 수 있는 소프트웨어 모듈이다. 인가 모듈에서 사용할 수 있는 속성 외에도 어드미션 제어 모듈은 생성되거나 수정된 오브젝트 내용에 접근할 수 있다.
어드미션 컨트롤러는 오브젝트를 생성, 수정, 삭제 또는 (프록시에) 연결하는 요청에 따라 작동한다. 어드미션 컨트롤러는 단순히 오브젝트를 읽는 요청에는 작동하지 않는다. 여러 개의 어드미션 컨트롤러가 구성되면 순서대로 호출된다.
이는 다이어그램에 3단계로 표시되어 있다.
인증 및 인가 모듈과 달리, 어드미션 제어 모듈이 거부되면 요청은 즉시 거부된다.
어드미션 제어 모듈은 오브젝트를 거부하는 것 외에도 필드의 복잡한 기본값을 설정할 수 있다.
사용 가능한 어드미션 제어 모듈은 여기에 서술되어 있다.
요청이 모든 어드미션 제어 모듈을 통과하면 유효성 검사 루틴을 사용하여 해당 API 오브젝트를 검증한 후 오브젝트 저장소에 기록(4단계)된다.
API 서버 포트와 IP
이전의 논의는 (일반적인 경우) API 서버의 보안 포트로 전송되는 요청에 적용된다. API 서버는 실제로 다음과 같이 2개의 포트에서 서비스할 수 있다.
기본적으로, 쿠버네티스 API 서버는 2개의 포트에서 HTTP 서비스를 한다.
-
로컬호스트 포트
:- 테스트 및 부트스트랩을 하기 위한 것이며 마스터 노드의 다른 구성요소 (스케줄러, 컨트롤러 매니저)가 API와 통신하기 위한 것이다.
- TLS가 없다.
- 기본 포트는 8080이다.
- 기본 IP는 로컬호스트(localhost)이며,
--insecure-bind-address
플래그를 사용하여 변경한다. - 요청이 인증 및 인가 모듈을 우회한다.
- 요청이 어드미션 제어 모듈(들)에 의해 처리된다.
- 호스트 접근 요구로부터 보호를 받는다.
-
보안 포트
:- 가능한 항상 사용하는 것이 좋다.
- TLS를 사용한다.
--tls-cert-file
플래그로 인증서를 지정하고--tls-private-key-file
플래그로 키를 지정한다. - 기본 포트는 6443이며,
--secure-port
플래그를 사용하여 변경한다. - 기본 IP는 로컬호스트가 아닌 첫 번째 네트워크 인터페이스이며,
--bind-address
플래그를 사용하여 변경한다. - 요청이 인증 및 인가 모듈에 의해 처리된다.
- 요청이 어드미션 제어 모듈(들)에 의해 처리된다.
- 인증 및 인가 모듈을 실행한다.
GCE(구글 컴퓨트 엔진) 및 다른 클라우드 제공자에서 kube-up.sh
로 클러스터를 생성하면
API 서버는 포트 443에서 서비스한다.
GCE에서는 외부 HTTPS가 API에 접근할 수 있도록 프로젝트에서 방화벽 규칙이 구성된다.
이외에 클러스터 설정 방법은 다양하다.