Kubernetes In Action 정리 - 쿠버네티스 API 서버 보안
- 인증에 대한 이해
- 서비스 어카운트란 무엇이며 사용하는 이유
- 역할 기반 액세스 제어(RBAC) 플러그인 이해
- 롤과 롤바인딩 사용
- 클러스터롤과 클러스터롤바인딩 사용
- 디폴트 롤과 바인딩 이해
12.1 인증 이해
API 서버는 하나 이상의 인증 플러그인으로 구성할 수 있다. API 서버가 요청을 받으면 인증 플러그인 목록을 거쳐 요청이 전달, 각각 인증 플러그인이 요청을 검사한다.
여러 인증 플러그인을 사용할 수 있으며 인증 플러그인은 다음 방법을 사용해 클라이언트의 아이덴티티를 얻는다.
- 클라이언트의 인증서
- HTTP 헤더로 전달된 인증 토큰
- 기본 HTTP 인증
- 기타
12.1.1 사용자와 그룹
인증 플러그인은 인증된 사용자의 이름과 그룹을 반환한다. 쿠버네티스는 해당 정보를 어디에도 저장하지 않으며 이를 사용해 사용자의 권한을 검사한다.
사용자
쿠버네티스는 API 서버에 접속하는 두 종류의 클라이언트를 구분
- 사용자
- 파드(파드 내부에서 실행되는 어플리케이션)
사용자는 싱글 사인 온과 같은 외부 시스템에 의해 관리되어야 하지만 파드는 서비스 어카운트라는 매커니즘을 사용하며 쿠버네티스 리소스로 생성되고 관리된다. 이와 대조적으로 사용자 계정을 나타내는 자원은 없으며 이는 API 서버를 통해 사용자를 생성, 변경, 삭제할 수 없다는 것이다.
그룹
사용자와 서비스 어카운트는 하나 이상의 그룹에 속할 수 있다. 그룹은 사용자 각각 권한을 부여하지 않고 여러 사용자를 한번에 그룹화 하기 위한 용도이다.
인증 플러그인이 반환하는 그룹은 임의의 그룹을 나타내는 문자열이지만 내장된 그룹은 특별한 의미를 가진다.
- system:unauthenticated 그룹은 어떤 인증 플러그인에서도 클라이언트를 인증할 수 없는 요청에 사용
- system:authenticated 그룹은 성공적으로 인증된 사용자에게 자동으로 할당
- system:serviceaccounts 그룹은 시스템의 모든 서비스어카운트를 포함
- system:serviceaccounts:
는 특정 네임스페이스에 모든 서비스 어카운트를 포함
12.1.2 서비스 어카운트 소개
모든 파드는 파드에서 실행중인 어플리케이션의 아이덴티티를 나타내는 서비스 어카운트와 연계되어 있다. 시크릿 볼륨으로 컨테이너 파일시스템에 마운트된 /var/run/secrets/kubernetes.io/serviceaccount/token 파일은 서비스 어카운트의 인증 토큰을 가지고 있다. 어플리케이션이 토큰을 사용하여 API 서버에 접속하면 인증 플러그인이 인증을 시도하고 사용자 이름을 API 서버 코어로 전달한다.
서비스 어카운트의 형식은 다음과 같다. system:serviceaccount:<namespace>:<service account name>
API 서버는 설정된 인가 플러그인에 사용자 이름을 전달하여 권한 검증을 거치게 된다.
서비스 어카운트 리소스
서비스어카운트는 파드, 시크릿, 컨피그맵 등과 같은 리소스이며 개별 네임스페이스로 위치가 지정된다. 각 네임스페이스마다 default 서비스 어카운트가 자동으로 생성된다.
1 | |
파드는 하나의 서비스와 연계되지만 여러 파드는 같은 서비스 어카운트를 사용할 수 있다. 또한 파드는 같은 네임스페이스의 서비스 어카운트만 사용가능하다.
서비스어카운트가 인가와 어떻게 밀접하게 연계되어 있는지 이해
파드 매니페스트에 서비스 어카운트 이름을 지정하여 파드에 서비스 어카운트를 할당 할 수 있다. 할당하지 않을 경우 default 서비스 어카운트를 사용한다. 파드에 서로 다른 서비스 어카운트를 할당할 경우 각 파드 별로 액세스 가능한 리소스를 제어 할 수 있다. 현재는 역할 기반 액세스 제어((RBAC) 플러그인을 대부분 사용한다.
12.1.3 서비스 어카운트 생성
모든 파드에 default 서비스 어카운트를 사용하지 않는 이유는 클러스터 보안을 위해서 이다. 메타데이터를 읽을 필요가 없는 파드는 API 요청을 제한 하여야 하고 권한이 필요한 파드에게만 권할을 줄 수 있어야 한다.
서비스 어카운트 생성
1 | |
사용자 정의 토큰 시크릿이 생성되어 서비스 어카운트와 연계된 것을 볼 수 있다.
1 | |
서비스어카운트의 마운트 가능한 시크릿 이해
기본적으로 파드는 원하는 모든 시크릿을 마운트 할 수 있으며 파드가 서비스 어카운트의 마운트 가능한 시크릿 목록에 있는 시크릿만 마운트 하도록 파드의 서비스 어카운트를 설정할 수 있다.
이 기능을 사용하려면 서비스 어카운트가 다음 어노테이션을 포함하고 있어야 한다. kubernetes.io/enforce-mountable-secret="true" 서비스 어카운트에 이 어노테이션을 달릴 경우 이를 사용하는 모든 파드는 서비스 어카운트에 마운트 가능한 시크릿만 마운트 할 수 있다.
서비스어카운트의 이미지 풀 시크릿 이해
이미지 풀 시크릿은 프라이빗 이미지 리포지터리에서 컨테이너 이미지를 가져오는 데 필요한 자격증명을 가진 시크릿이다. 서비스어카운트를 사용하여 모든 파드에 특정 이미지 풀 시크릿을 추가하여 각 파드마다 개별적으로 추가하지 않아도 된다.
12.1.4 파드에 서비스 어카운트 할당
사용자 정의 서비스 어카운트를 사용하는 파드 생성
1 | |
1 | |
12.2 역할 기반 액세스 제어로 클러스터 보안
RBAC는 권한이 없는 사용자가 클러스터 상태를 보거나 수정하지 못하게 막는다.
12.2.1 RBAC 인가 플러그인 소개
쿠버네티스 API 서버는 REST 인터페이스를 제공하므로 사용자는 서버에 HTTP 요청을 보내 액션을 수행한다. 사용자는 요청에 자격증명을 포함 시켜 자신을 인증한다.
액션 이해하기
REST 클라이언트는 get, post, put, delete등의 요청을 특정 REST 리소스를 타나내는 URL로 보낸다. 쿠버네티스에서 이러한 리소스에는 파드. 서비스, 시크릿 등이 있다.
- 파드 가져오기 (GET)
- 서비스 생성하기 (CREATE)
- 시크릿 업데이트 (UPDATE)
- 기타 API 서버 내에서 실행되는 RBAC와 같은 인가 플러그인은 클라이언트가 요청한 자원에서 요청한 동사를 수행할 수 있는지 판별한다. | HTTP 메서드 | 단일 리소스에 관한 동사 | 컬렉션에 관한 동사| |—|:—:|—:| | GET, HEAD | get (and watch for watching) | list(and watch) | | POST | create | n/a | | PUT | update | n/a | | PATCH | patch | n/a | | DELETE | delete | deletecollection |
RBAC 플러그인 이해
RBAC 인가 플러그인은 사용자가 액션을 수행할 수 있는지 여부를 결정하는 핵심 요소로 사용자 롤을 사용한다. 주체는 하나 이상의 롤과 연관되어 있고 각 롤은 특정 리소스에 특정 동사를 수행할 수 있다.
사용자에게 여러 롤이 있는 경우 롤에서 허용하는 모든 작업을 수행 할 수 있다.
예를 들어 사용자에게 시크릿 정보를 업데이트 하는 권한이 없으면 API 서버는 시크릿 정보에 대해 PUT 또는 PATCH 요청을 수행하지 못하게 한다.
12.2.2 RBAC 리소스 소개
RBAC 인가 규칙은 네 개의 리소스로 구성되며 두 개의 그룹으로 분류할 수 있다.
- 롤과 클러스터롤: 리소스에 수행할 수 있는 동사를 지정한다.
- 롤바인딩과 클러스터롤바인딩: 위의 롤을 특정 사용자, 그룹, 또는 서비스 어카운트에 바인딩한다.
롤은 수행할수 있는 작업을 나타내고 바인딩은 이를 수행할 수 있는지를 정의한다.

롤과 롤바인딩은 네임스페이스가 지정된 리소스이고, 클러스터롤과 클러스터롤 바인딩은 네임스페이스를 지정하지 않는 클러스터 수준의 리소스이다. 하나의 네임스페이스에 여러 롤 바인딩이 존재 가능하고 또한 여러 클러스터롤바인딩과 클러스터롤을 만들 수 있다.
네임스페이스 생성과 파드 실행
1 | |
파드에서 서비스 목록 나열하기
RBAC가 활성화 되어 있는 상태에서 파드가 클러스터 상태 정보를 읽을 수 없다는 것을 확인
1 | |
12.2.3 롤과 롤바인딩 사용
롤 리소스는 어떤 리소스에 어떤 액션을 수행할 수 있는지를 정의한다. 아래 설정 파일은 사용자가 foo 네임스페이스에서 서비스를 가져오고 나열할 수 있는 롤을 정의한다.
1 | |
1 | |
1 | |
서비스어카운트에 롤을 바인딩하기
주체(사용자, 서비스어카운트, 그룹)에 롤을 바인딩 하는것은 롤바인딩 리소스를 만들어 수행한다. 롤을 default 서비스어카운트에 바인딩하기 위해 다음 명령을 실행한다.
1 | |
1 | |
롤바인딩은 하나의 롤을 참조하지만 여러 주체(하나 이상의 서비스어카운트와 여러 사용자 또는 그룹)에 롤을 바인딩 할 수 있다.
1 | |
롤바인딩에서 다른 네임스페이스의 서비스어카운트 포함하기
현재 bar 네임스페이스의 파드는 자신의 네임스페이스에 있는 서비스를 나열할수 없고 다른 네임 스페이스의 서비스 역시 나열하지 못한다. foo 네임스페이스에 있는 롤바인딩을 편집하여 다른 네임스페이스에 있다 하더라도 다른 파드의 서비스어카운트를 추가한다.
1 | |
이제 bar 네임스페이스에서 실행되는 파드 내부에서 foo 네임스페이스의 서비스를 나열 할 수 있다.
12.2.4 클러스터롤과 클러스터롤바인딩 사용하기
롤과 롤바인딩은 하나의 네임스페이스상에 상주하며 해당 네임스페이스의 리소스로 적용되는것을 의미하지만 롤바인딩은 다른 네임스페이스의 서비스 어카운트를 참조할 수있다.
이와 같이 네임스페이스가 지정된 리소스 이외에도 클러스터롤, 클러스터롤바인딩이라는 클러스터 수준의 RBAC 리소스도 있다.
클러스터롤은 네임스페이스가 지정되지 않은 리소스 혹은 URL에 접근을 클러스터 수준의 리소스로 각각 네임스페이스에 동일한 롤을 재 정의 할 필요 없이 사용가능하다.
클러스터 수준 리소스에 액세스 허용
클러스터에서 파드가 퍼시스턴트볼륨을 나열하도록 허용하는 예시
1 | |
1 | |
클러스터 롤은 네임스페이스에 속하지 않아 필드가 없다.
1 | |
클러스터롤은 일반 롤바인딩을 상ㅇ해서 주체에 바인딩 할 수 있다.
1 | |
여전히 퍼시스턴트 볼륨을 나열하지 못한다.
롤바인딩을 생성하고 클러스터롤을 참조하여 네임스테이스가 지정된 리소스에 액세스 하게 할 수 있지만 클러스터 수준 리소스에서는 동일한 방식을 사용할 수 없다.
클러스터 수준 리소스에 액세스 권한을 부여하려면 클러스터롤바인딩을 사용해야 한다.
1 | |
1 | |
1 | |
리소스가 아닌 URL에 액세스 허용하기
API 서버는 리소스가 아닌 URL도 노출한다. 이 URL에 관한 액세스 권한도 명시적으로 부여해야한다. system:discovery 클러스터롤 및 동일한 이름의 클러스터롤바인딩을 통해 자동으로 수행
1 | |
클러스터 수준 리소스와 마찬가지로 리소스가 아닌 URL의 클러스터롤은 클러스터롤바인딩으로 바인딩 되어야 한다.
1 | |
특정 네임스페이스의 리소스에 액세스 권한을 부여하기 위해 클러스터롤 사용
클러스터롤은 항상 클러스터 수준 클러스터롤바인딩과 바인딩 될 필요가 없으며 일반 롤바인딩과 바인딩 될 수 있다.
1 | |
이 클러스터롤의 규칙은 네임스페이스가 지정된 리소스(configmap, endpoints…)의 get, list, watch를 허용하는 것이다.
클러스터롤바인딩을 생성하고 클러스터롤을 참조하면 모든 네임스페이스에 지정된 리소스를 볼수 있는 반면 롤바인딩을 만들면 바인딩에 나열된 주체가 롤바인딩의 네임스페이스에 있는 리소스만 볼 수 있다.
1 | |
클러스터롤바인딩을 하기전 이라 두 명령어 모두 실패한다.
1 | |
1 | |
클러스터롤 바인딩을 만들었으므로 모든 네임스페이스에 적용된다. foo의 파드는 bar 네임스페이스의 파드도 나열할 수 있다.
클러스터롤바인딩을 롤바인딩으로 교체
1 | |
foo 네임스페이스에 롤바인딩을 생성하여 같은 네임스페이스의 default 서비스어카운트를 view클러스터롤과 비인딩
1 | |
foo 네임스페이스에 잇는 파드는 나열할 수 있지만 다른 네임스페이스나 전체 네임스페이스에 걸쳐 파드는 나열할 수 없다.
롤, 클러스터롤, 롤바인딩과 클러스터롤바인딩 조합에 관한 요약
| 접근 | 롤 타입 | 사용할 바인딩 타입 |
|---|---|---|
| 클러스터 수준 리소스(노드, 퍼시스턴트 볼륨) | 클러스터롤 | 클러스터롤바인딩 |
| 리소스가 아닌 URL(/api, /healthz) | 클러스터롤 | 클러스터롤바인딩 |
| 모든 네임스페이스의 네임스페이스로 지정된 리소스 | 클러스터롤 | 클러스터롤바인딩 |
| 특정 네임스페이스의 네임스페이스로 지정된 리소스 (여러 네임스페이스에 동일한 클러스터롤 재사용) | 클러스터롤 | 바인딩 |
| 특정 네임스페이스의 네임스페이스로 지정된 리소스 (각 네임스페이스에 롤을 정의) | 롤 | 롤바인딩 |
디폴트 클러스터롤과 클러스터롤바인딩의 이해
쿠버네티스는 API 서버가 시작될 때 업데이트되는 클러스터롤과 클러스터롤바인딩의 디폴스 세트를 제공
1 | |
view 클러스터롤을 사용해 리소스에 읽기 전용 액세스 허용
디폴트 view 클러스터롤을 사용하면 롤, 롤바인딩과 시크릿을 제외한 네임스페이스 내의 거의 모든 리소스를 읽을 수 있다. 시크릿은 읽을수 없는데 그 이유는 시크릿 중 view 클러스터롤에 정의된 것보다 더 큰 권한을 갖는 인증토큰이 포함될 수 있고 사용자가 다른 사용자로 가장해 추가 권한을 얻을 수 있기 때문.
edit 클러스터롤을 사용해 리소스에 변경 허용
edit 클러스터롤은 네임스페이스 내의 리소스와 시크릿을 읽고 수정할 수 있다. 그러나 롤, 롤바인딩을 보거나 수정하지는 못한다.
admin 클러스터롤을 사용해 네임스페이스에 제어 권한 허용
네임스페이스에 있는 리소스에 관한 완전한 제어 권한이 admin 클러스터롤에 부여된다. 이 롤을 가진 주체는 리소스 쿼터와 네임스페이스 리소스 자체를 제외한 네임스페이스 내의 모든 리소스를 읽고 수정할 수 있다.
cluster-admin 클러스터롤을 사용해 완전한 제어 허용
쿠버네티스 클러스터를 완전히 제어하기 위해선 cluster-admin 클러스터롤을 주체에 할당하면 된다. admin 클러스터롤에선 사용자가 네임스페이스의 리소스쿼터 개체 또는 네임스페이스 리소스 자체를 수정할 수 없다. 이 작업을 허용하려면 cluster-admin 클러스터롤을 참조하는 롤바인딩을 생성.
12.2.6 인가 권한을 현명하게 부여
기본적으로 네임스페이스의 디폴트 서비스 어카운트에는 인증되지 않은 사용자의 권한 이외에는 어떤 권한도 없다. 모든 서비스어카운트에 cluster-admin 클러스터롤을 부여하는것 보단 적절한 권한만 부여하고 한가지 이상의 권한을 주지 않는 것이 좋다.
각 파드에 특정 서비스어카운트 생성
각 파드를 위한 특정 서비스어카운트를 생성한 다음 롤바인딩으로 맞춤형 롤과 연계하는 것이 바람직한 접근 방법이다. 파드중 하나는 읽은 권한을 부여하고 하나는 수정하는 권한을 부여하는 식으로 서도 다른 서비스어카운트를 생성하고 각 파드 펙의 serviceAccountName 속성에 서비스어카운트를 설정해 사용하는것을 권장한다. 양쪽 파드에 모든 권한을 네임스페이스의 디폴트 서비스어카운트에 추가하는것은 권장하지 않는다.
어플리케이션이 탈취될 가능성을 염두
어플리케이션이 탈취당해 서비스어카운트의 인증토큰이 유출될 가능성을 예상하며 실제로 피해를 입지 않도록 서비스어카운트 생성에 제한을 둬야한다.