쿠버네티스가 환경변수나 DNS로 서비스 검색하는 것 말고 그 외의 리소스 정보들은 어떻게 가져올까?
먼저 말했지만 서비스와 파드 관련 정보는 서비스 관련 환경변수나 DNS로 얻을 수 있다.
하지만 애플리케이션이 다른 리소스의 정보가 필요하거나 가능한 최신의 정보에 접근해야하는 경우 API 서버와 직접 통신해야한다.
(Etcd 값을 참조할 수 있는 방법은 API 서버를 통하는 방법 뿐!)
그렇다면 파드 내 애플리케이션이 쿠버네티스 API 서버와 어떻게 통신하는 걸까?
파드 내에서 API 서버와 통신하려면 다음 세가지를 처리해야한다.
1. API 서버 위치 알기
2. API 서버와 통신하고 있는지 확인
3. API 서버로 인증
먼저 쿠버네티스 API 서버의 IP와 포트를 찾아야하는데 kubernetes라는 서비스가 디폴트 네임스페이스에 자동으로 노출되고 있어 찾는 건 쉽다.
그리고 각 서비스에 대한 정보는 환경변수가 구성되어있다.
(파드 내에서 env 하면 나옴)
각 컨테이너는 보면 /var/run/secrets/kubernetes.io/serviceaccount/에 마운트되어있는 시크릿이 있다.
해당 시크릿에는 세개의 항복이 있는데, 이중 하나가 쿠버네티스 API 서버 인증서에 서명하는 데 사용하는 인증기관의 인증서 ca.crt 파일이다.
API 서버와 통신 중인지 확인하려면 서버의 인증서가 CA로 서명되어있는지 확인해야한다.
서버의 인증서가 신뢰할 수 있는 CA가 서명했다면 curl https://kubernetes를 수행하면 서버의 id를 확인할 수 있다.
하지만 위의 curl 문을 수행하면 unauthorized가 뜰 것이다.
인증처리가 아직 되지 않았기 때문이다.
즉, 여기까지 보면 클라이언트는 API 서버임을 확인했고 신뢰하지만 API 서버는 클라이언트가 누구인지 모르기에 액세스 권한이 없다고 표시하는 것이다.
서버에서 인증을 통과해야 클러스터에 배포된 API 오브젝트를 읽고, 업데이트나 삭제를 수행할 수 있다.
인증을 하려면 인증 토큰이 필요하다.
토큰은 시크릿에 서비스 어카운트로 담겨있다.
이 토큰을 사용해 API 서버로 요청을 보내면 요청의 HTTP 헤더 내부에 토큰이 전달되고 API 서버는 토큰이 인증된 것으로 이식하고 적절한 응답을 반환한다.
이렇게 인증을 통과하면 이제 클러스터 내 리소스를 탐색할 수 있는 것이다.
이렇게 파드가 쿠버네티스와 통신하는 방법을 알아보았다.
이제 위에서 언급한 서비스어카운트가 뭔지 권한은 어떻게 설정되는 지를 알아보자.
API 서버를 하나 이상의 인증 플러그인으로 구성할 수 있다.
( 해당 내용을 자세히 알고 싶으신 분은 아래 글을 읽어주세요.
https://velog.io/@baeyuna97/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%EB%82%B4%EB%B6%80-%EC%9D%B4%ED%95%B4-1-%EB%A7%88%EC%8A%A4%ED%84%B0-1%ED%83%84#api-%EC%84%9C%EB%B2%84 )
API 서버가 요청을 받으면 인증 플러그인 목록을 거쳐 요청이 전달되고, 각각의 인증 플러그인이 요청을 검사해서 누가 보냈는지 밝혀낸다.
(사용자 이름, 사용자 ID, 클라이언트가 속한 그룹)
이렇게 밝혀낸 정보를 API 서버 코어에 반환한다.
여기가지 진행되면, API 서버는 나머지 인증 플러그인 호출을 중지하고 인가 단계를 진행한다.
인증 플러그인은 인증된 사용자의 사용자 이름과 그룹을 반환한다.
쿠버네티스는 해당 정보를 어디에 저장하는 방식이 아니다.
인증 플러그인을 거쳐서 정보를 알아내고 알아낸 사용자 정보를 통해 사용자가 요청한 작업이 사용자가 수행할 권한이 있는지 여부를 확인하다.
쿠버네티스는 API 서버에 접속하는 클라이언트를 두 종류로 구분하는데.
1. 실제 사람
2. 파드 (애플리케이션)
이 두가지 유형의 클라이언트 모두 인증 플러그인을 통해 인증된다.
사용자는 sso 등을 사용해 외부 시스템으로 관리되어야하지만 파드는 서비스 어카운트라는 매커니즘을 사용하며, 클러스터에 서비스어카운트 리소스로 생성되고 저장된다.
즉, 서비스어카운트는 파드를 실행하는 데 필수적인 요소이다.
휴먼 사용자와 서비스 어카운트는 하나 이상의 그룹에 속할 수 있다.
앞에서 인증 플러그인은 사용자 이름 및 사용자 ID, 그룹을 반환한다고 했다.
즉, 그룹으로 관리하면 개별사용자가 아닌 여러명의 사용자에게 권한을 부여할 수 있다.
이제 드디어 서비스어카운트를 알아보자.
클라이언트는 API 서버에 작업을 수행하기전에 자신을 인증해야한다.
인증은 시크릿 볼륨으로 각 컨테이너 파일시스템에 마운트된 /var/run/secrets/kubernetes.io/serviceaccount/token 파일의 내용을 전송해 인증한다.
방법은 알겠다.. 근데 인증하는 데 사용한다는 이 파일은 대체 뭘까?
모든 파드는 파드에서 실행 중인 애플리케이션의 아이덴티티를 나타내는 서비스어카운트와 연계 있다.
이 토큰 파일은 서비스어카운트의 인증토큰을 갖고 있다. 애플리케이션이 이 토큰을 사용해 API 서버에 접속하면 인증 플러그인이 서비스어카운트를 인증하고 서비스어카운트의 사용자 이름을 API 서버 코어로 전달한다.
즉, 서비스어카운트는 파드 내부에서 실행되는 애플리케이션이 API 서버에 자신을 인증하는 방법에 지나지 않는다.
서비스어카운트는 파드, 시크릿, 컨피그맵 등과 같은 리소스이며 개별 네임스페이스 범위가 지정된다.
각 네임스페이스마다 default 서비스어카운트가 자동으로 생성되는데 필요한 경우 서비스 어카운트를 추가할 수 있다.
각 파드는 딱 하나의 서비스와 연계되지만 여러 파드가 같은 서비스어카운트를 사용할 수 있다.
또한, 파드는 같은 네임스페이스의 서비스어카운트만 사용할 수 있다.
파드 매니페스트에 서비스어카운트 이름을 지정해 파드에 서비스어카운트를 할당할 수 잇따.
명시적으로 할당하지 않으면 네임스페이스에 기본으로 있는 default 서비스 어카운트를 사용한다.
파드에 서로 다른 서비스어카운트를 할당하면 각 파드가 액세스할 수 있는 리소스를 제어할 수 있다.
API 서버가 인증 토큰이 있는 요청을 수신하면, API 서버는 토큰을 사용해 요청을 보낸 클라이언트를 인증한 다음 관련 서비스어카운트가 요청된 수행을 할 수 있는지 여부를 결정한다.
해당 정보를 API 서버는 크럴스터 관리자가 구성한 시스템 전체의 인가 플러그인에서 얻는다.
주로 사용하는 인가 플러그인이 RBAC (역할 기반 액세스 제어) 플러그인이다.보
보안을 위해 추가 권한을 만들때는 기본으로 있는 default 서비스 어카운트가 아닌 새로운 서비스어카운트를 만든다.
서비스어카운트를 만들면 사용자 정의 토큰 시크릿이 생성된다.
이 토큰을 describe로 살펴보면 CA 인증서, 네임스페이스 및 토큰이 포함되어 있는 것을 볼 수 있다.
여기까지 API 서버와 통신하기 위해 파드는 서비스어카운트가 필요한 것과 통신 플로우를 이해하였다.
이제 앞서 이야기한 RBAC 인가 플러그인을 자세히 알아보자.
쿠버네티스 1.8.0 버전부터 RBAC 인가 플러그인이 GA로 승격되었으며 이제 많은 클러스터에서 기본적으로 활성화되어있다.
RBAC은 권한이 없는 사용자가 클러스터 상태를 보거나 수정하지 못하게 한다.
Default 서비스어카운트는 추가 권한을 보여받지 않는 한 클러스터 상태를 볼 수도 수정할 수도 없다 (보안 강화)
쿠버네티스 API 서버는 인가 플러그인을 사용해 액션을 요청하는 사용자가 액션을 수행할 수 있는지 점검하도록 설정할 수 있다.
API 서버가 REST 인터페이스를 제공하므로 사용자는 서버에 HTTP 요청을 보내 액션을 수행한다.
이때 사용자는 요청에 자격증명 (토큰, 사용자 이름, 인증서)를 포함시켜 자신을 인증한다.
API 서버에 액션을 요청한다고 했는데 액션이 어떤게 있을까?
REST 클라이언트는 GET, POST, PUT, DELETE 및 기타 유형의 HTTP 요청을 특정 REST 리소스를 나타내는 특정 URL 경로로 보낸다.
이게 쿠버네티스에서는 파드, 서비스, 시크릿 등이 있다.
Ex) 파드 가져오기, 서비스 생성하기, 시크릿 업데이트 하기
즉, API 서버 내에 실행되는 RBAC 인가 플러그인은 이렇게 들어온 클라이언트의 요청(어떤 리소스에 무엇을)에 대하여 그 리소스에 그 수행을 할 수 있는지를 판별한다.
전체 리소스 유형에 보안 권한을 적용하는 것 외에도 RBAC 규칙은 특정 리소스 인스턴스에도 적용할 수 있다.
RBAC 인가 플러그인은 이름에서도 알 수 있듯, 사용자가 액션을 수행할 수 있는지 여부를 결정하는 핵심요소로 사용자 롤을 사용한다.
주체 (사람, 서비스 어카운트)는 하나 이상의 롤과 연계되어있으면 각 롤은 특정 리소스에 특정 동사를 수행할 수 있다.
가령 어떤 사용자에게 여러 롤이 부여되어있으면 부여된 롤을 모두 수행할 수 있다.
RBAC 플러그인으로 인가를 관리하는 것은 RBAC 관련 쿠버네티스 리소스를 생성하기만 하면 된다.
RBAC 인가 규칙은 네 개의 리소스로 구성되어 두개의 그룹으로 분류된다.
롤은 수행할 작업을 정의하고, 바인딩은 누가 이를 수행할 수 있는지를 정의한다.
롤과 롤바인딩은 네임스페이스가 지정된 리소스이고 클러스터롤과 클러스터롤 바인딩은 네임스페이스를 지정하지 않은 클러스터 수준의 리소스이다.
롤은 수행할 수 있는 액션을 정의하지 누가 수행할지를 정의하지 않기에 해당 롤을 부여할 주체에 바인딩을 해야한다.
그 주체는 사용자, 서비스어카운트 혹은 그룹이 될 수도 있다.
위 사진의 service-reader에는 foo 네임스페이스 내의 service 리소스에 대한 get, list 권한으로 해당 role이 rolebinding “test”를 통해 부여된 default 서비스어카운트는 foo 네임스페이스에 서비스 정보를 조회할 수 있는 것이다.
또한 롤 바인딩은 다른 네임스페이스의 서비스 어카운트도 포함시킬 수 있는데
위 사진처럼 rolebinding test는 foo, bar 네임스페이스 모두에 바인딩되어있으므로 bar 네임스페이스에서 실행되는 파드 내부에서 foo 네임스페이스의 서비스를 나열할 수 있게되는 것이다.