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