Kubernetes 통합 개발 가이드라인
이 문서는 GitLab의 Kubernetes 통합을 개발할 때의 여러 지침을 제공합니다.
개발
아키텍처
일부 Kubernetes 작업은 제한된 프로젝트 네임스페이스를 생성하는 것과 같은 작업이 GitLab Rails 애플리케이션에서 수행됩니다. 이러한 작업은 client library를 사용하여 수행되며, 일정한 요소를 가지고 있습니다. 이러한 작업은 GitLab Rails 애플리케이션을 실행하는 동일한 사용자로 실행됩니다. 자세한 정보는 아래 보안 섹션을 참조하세요.
클러스터 애플리케이션을 설치하는 것과 같은 일부 Kubernetes 작업은 Kubernetes 클러스터 자체의 일회성 pod에서 수행됩니다. 이 설치 pod은 install-<application_name>
으로 명명되며 gitlab-managed-apps
네임스페이스 내에서 생성됩니다.
코드 구성 측면에서, 우리는 일반적으로 Kubernetes 리소스를 표현하는 오브젝트를 lib/gitlab/kubernetes
에 추가합니다.
클라이언트 라이브러리
우리는 Kubernetes API 호출을 수행하기 위해 kubeclient
젬을 사용합니다. kubeclient
젬은 단일 클라이언트에서 apis/rbac.authorization.k8s.io
와 같은 다른 API 그룹을 지원하지 않기 때문에, 우리는 이를 달성하기 위해 Gitlab::Kubernetes::KubeClient
라는 래퍼 클래스를 만들었습니다.
선택한 Kubernetes API 그룹이 지원됩니다. 만약 사용해야 한다면 새로운 API 그룹이나 메서드를 지원하도록 Gitlab::Kubernetes::KubeClient
에 추가하세요. 내부적으로, 새로운 API 그룹이나 API 그룹 버전은 해당 그룹에 대한 내부 클라이언트를 생성합니다. 새로운 메서드는 관련된 내부 클라이언트로 위임되어 추가될 수 있습니다.
성능 고려 사항
Kubernetes API로의 모든 호출은 백그라운드 프로세스에서 이뤄져야 합니다. 웹 요청 내에서 Kubernetes API 호출을 수행하지 마세요. 이렇게 되면 웹 서버가 차단되며, Kubernetes 클러스터 응답 시간이 우리의 제어 범위를 벗어나기 때문에 GitLab에 대한 서비스 거부(DoS) 공격으로 이어질 수 있습니다.
호출이 백그라운드 프로세스에서 발생하도록 가장 쉬운 방법은 해당 작업을 Sidekiq worker로 위임하는 것입니다.
Kubernetes에 호출을 수행하고 응답을 반환하고 싶을 수 있지만, 백그라운드 워커가 적합하지 않을 수 있습니다. 반응형 캐싱을 사용해 보세요. 예를 들어:
def calculate_reactive_cache!
{ pods: cluster.platform_kubernetes.kubeclient.get_pods }
end
def pods
with_reactive_cache do |data|
data[:pods]
end
end
테스트
테스트에서 Kubernetes API 호출을 모의(mock)화하는 데 도움이 되는 KubernetesHelpers
에 일부 WebMock 스텁이 있습니다.
Amazon EKS 통합
이 섹션에서는 GitLab 인스턴스가 EKS 클러스터를 생성할 수 있도록 하는 프로세스에 대해 개요합니다.
다음 전제 조건이 필요합니다:
Customer
AWS 계정. EKS 클러스터는 이 계정에서 생성됩니다. 다음 리소스가 있어야 합니다:
- 클러스터를 생성하고 관련 리소스에 대한 권한을 갖는 프로비저닝 역할. 이는
GitLab
AWS 계정을 신뢰하는 엔터티로 나열해야 합니다. - 클러스터에서 사용하기 위한 VPC, 관리 역할, 보안 그룹 및 서브넷.
GitLab
AWS 계정. 이는 프로비저닝 작업을 실행하는 계정입니다. 다음 리소스가 있어야 합니다:
-
Customer
계정의 프로비저닝 역할을 가정할 수 있는 권한을 갖는 서비스 계정. -
gitlab.yml
의kubernetes
섹션을 통해 GitLab에서 이 서비스 계정을 구성한 자격 증명.
클러스터를 생성하는 프로세스는 다음과 같습니다:
-
:provision_role_arn
에서 제공된:provision_role_external_id
를 사용하여 GitLab은 프로바이더 레코드에 임시 자격 증명 세트를 저장합니다. 기본적으로 이러한 자격 증명은 한 시간 동안 유효합니다. -
AWS CloudFormation EKS template
를 기반으로 CloudFormation 스택이 생성됩니다. 이렇게 하면 EKS 클러스터에 필요한 모든 리소스가 생성됩니다. - GitLab은 스택의 상태를 폴링하여 모든 리소스가 준비될 때까지 기다립니다. 대부분의 경우 이 과정은 10분에서 15분 정도 소요됩니다.
- 스택이 준비되면, GitLab은 클러스터 세부 정보를 저장하고
kubeclient
를 통해 클러스터에 연결할 수 있도록 다른 임시 자격 증명 세트를 생성합니다. 이러한 자격 증명은 일분간 유효합니다. - GitLab은 워커 노드를 구성하여, 그들이 클러스터에 인증할 수 있도록하고, 미래 작업을 위해 자체를 위한 서비스 계정을 생성합니다.
-
더 이상 필요하지 않은 자격 증명이 제거됩니다. 이로써 다음과 같은 속성이 삭제됩니다:
access_key_id
secret_access_key
session_token
보안
서버 사이드 요청 위조 (SSRF) 공격
Kubernetes 클러스터의 URL은 사용자가 제어하기 때문에 서버 사이드 요청 위조 (SSRF) 공격에 취약할 수 있습니다. 클러스터에 대한 더 많은 API 호출을 추가하는 경우 대비 전략을 이해해야 합니다.
대비 전략에는 다음이 포함됩니다:
- 공격자 컨트롤러 리소스로의 리디렉션을 허용하지 않기:
Kubeclient::KubeClient
가http_max_redirects: 0
을 옵션으로 전달하여 리디렉션을 방지하도록 구성될 수 있습니다. -
오류 메시지 노출을 방지: 이를 통해 우리는 공격자가 제어하는 요청으로부터 결과를 노출시키기 위해 오류를 유발하는 것을 방지합니다. 예를 들어, 우리는 원본 오류 메시지를 노출하지 않고 (또는 저장하지 않고):
rescue Kubernetes::HttpError => e # bad # app.make_errored!("Kubernetes error: #{e.message}") # good app.make_errored!("Kubernetes error: #{e.error_code}")
Kubernetes 통합 디버깅
Kubernetes 통합과 관련된 로그는 kubernetes.log
에서 찾을 수 있습니다. 로컬 GDK 설치에서는 이러한 로그가 log/kubernetes.log
에 있습니다.
또한 설치 문제를 디버깅하기 위해 설치 로그를 확인할 수 있습니다. 설치/업그레이드가 진행 중인 경우에는 pod가 생성될 때까지 기다린 다음, 다음과 같이 실행하여 로그를 얻을 수 있습니다.
kubectl logs <pod_name> --follow -n gitlab-managed-apps