이 게시물은 원래 제가 Medium.com에 게시한 게시물이므로 대신 dev.to로 이동하기로 결정했습니다!
이 게시물은 귀하가 Kubernetes 운영/실행 및 일부 Go 프로그래밍 언어 개념에 대한 경험이 있다고 가정합니다.
지난 1년 반 동안 우리는 Etraveli Group에서 OpenStack과 Kubernetes를 사용해 많은 작업을 진행해 왔습니다. 우리는 자체 클라우드 제공업체이고 최종 사용자는 개발자와 개발 조직의 주변 팀입니다.
OpenStack 위에서 Kubernetes를 실행하는 주요 구성 요소 중 하나는 Cloud Controller Manager입니다. 두 플랫폼을 서로 접착하는 부분 중 하나입니다. 퍼블릭 클라우드(또는 프라이빗 클라우드)에서 관리형 Kubernetes 서비스로 작업하는 분들을 위해 이 내용이 이미 정리되어 있을 것입니다. Kubernetes 제어 영역은 어느 정도 접근할 수 없을 것입니다.
그럼 클라우드 컨트롤러 관리자에 대해 글을 쓰는 이유는 무엇일까요? 주요 동인은 동료 중 한 명이 묻는 가장 간단한 질문이었습니다.
"그나저나 (OpenStack) 클라우드 컨트롤러 관리자는 무슨 일을 하나요?"
질문에 대답하려고 했지만 기본적으로 무슨 말을 하는지 전혀 몰랐고, LoadBalancer 유형의 서비스 개체가 생성될 때 기본 클라우드에서 로드 밸런서를 생성하는 역할을 담당한다는 것을 알고 있었습니다.
저는 즉시 이 문제를 좀 더 깊이 파고들기로 결정했고, 퍼즐의 모든 부분을 이해하려고 노력하면서 꽤 깊이 파고들었습니다. 이 게시물에서는 제가 찾은 결과를 요약하겠습니다.
이 게시물 전체에서 다음을 참조하겠습니다.
클라우드 컨트롤러 관리자("CCM"
Kubernetes 기본 소스 코드 저장소("k/k"
Kubernetes("k8s"
이 게시물을 쓰기 시작하면서 저는 자체 Cloud Controller Manager를 책별로 구축하고 두 개의 작은 Kubernetes(v1.18.2) 클러스터를 서로 비교하는 작은 프로젝트와 저장소를 만들었습니다. CCM과 그렇지 않은 것. 이는 개념 증명이며 자체 CCM을 실행하는 데 정확히 필요한 것이 무엇인지 보여주는 것을 목표로 합니다. CCM을 구성하는 코드부터 k8s 매니페스트까지 모든 것을 배포해야 합니다.
시작하기 전에 이 게시물이 k8s 소스 코드 저장소의 다양한 부분으로 연결된다는 점을 알아두면 좋습니다. 저는 v1.18.0 태그를 사용했습니다.
모든 일러스트는 제가 직접 제작한 것입니다.
즐기세요!
댓글 한두 개(!)를 남겨주세요. 어떤 피드백이라도 감사히 받겠습니다!
클라우드 컨트롤러 관리자는 높은 수준의 관점에서 보면 세 가지로 설명할 수 있습니다.
바이너리
다양한 제어 루프
k8s와 클라우드 사이의 접착제 역할
코드 측면에서 CCM은 k/k 저장소의 일부입니다. 여기를 살펴보세요. 공식 k8s 문서에서 언급했듯이 k/k의 CCM 코드는 자체 구현을 위한 뼈대로 사용될 수 있습니다. 차이점은 클라우드와 상호 작용하기 위해 제공하고 가져오는 코드(패키지)입니다.
CCM은 k8s 매니페스트와 잘 알려진 컨테이너 레지스트리에서 가져온 (Docker) 컨테이너에 내장된 바이너리를 통해 배포되는 경우가 가장 많습니다.
CCM에는 포트 10258이 할당되며 필요한 경우 이를 노출해야 한다는 점에 주목할 필요가 있습니다. 기본적으로 CCM은 /healthz 엔드포인트를 노출하여 서비스 상태를 확인합니다.
GitHub에서 k8s 조직을 살펴보면 다양한 CCM 구현을 찾을 수 있습니다. 이는 k/k 저장소 외부에 있고 다음과 같이 잘 제작된 Golang 인터페이스 세트로 구성되어 있기 때문에 외부 CCM이라고도 합니다. 누구나 자신만의 CCM을 만들 수 있는 최소한의 기능입니다.
이에 대해서는 나중에 자세히 살펴보겠습니다.
CCM의 핵심은 제어 루프를 실행하는 4개의 (클라우드) 컨트롤러로 구성되며 선택적으로 다른 컨트롤러와 함께 자체 컨트롤러를 실행할 수도 있습니다.
다음 섹션에서는 CCM에서 실행되는 각 클라우드 컨트롤러에 대해 더 자세히 살펴보겠습니다.
노드 컨트롤러는 클라우드 노드(예: VM)에 라벨을 지정하고, 오염시키고, 클라우드 제공업체의 기타 관련 정보로 업데이트하도록 합니다. 컨트롤러는 순서가 지정되지 않은 목록에서 주기적으로 다음 작업을 수행합니다.
다음 오염을 사용하여 클라우드 제공자에 추가된 새 노드를 초기화합니다. node.cloudprovider.kubernetes.io/uninitialized를 true로 설정하고 오염 효과를 NoSchedule로 설정합니다. 노드가 초기화되면 노드 컨트롤러에 의해 이 오염이 제거되어 노드에서 작업 부하를 예약할 수 있습니다. 예를 들어 중요한 포드입니다. 물론 클러스터를 실행하면 이미 오염된 노드에 대해 예약하는 데 필요한 허용이 제공됩니다.
클라우드 공급자의 IP 주소와 k8s API의 Node 개체에 저장된 IP 주소를 비교하여 노드 IP 주소를 업데이트합니다.
클라우드에서 제공되는 정보로 노드 레이블을 추가하거나 업데이트합니다. 여기에는 인스턴스 유형, 영역 오류 도메인 및 영역 지역이 포함됩니다. 나중에 살펴보겠지만 구역별 정보는 필수가 아닙니다.
노드 라벨과 위에서 언급한 인스턴스 정보를 가져와 노드 객체에 추가하는 방법에 대해 설명합니다. 예를 들어 OpenStack 외부 CCM은 디스크(구성 디스크)에서 메타데이터를 읽거나 각 노드 내에서 연결할 수 있는 메타데이터 서비스 엔드포인트를 사용하여 이를 수행합니다.
서비스 컨트롤러는 클라우드에서 생성된 서비스 객체 기반 로드 밸런서의 수명 주기와 관련된 모든 것을 처리합니다. 서비스는 k8s 클러스터의 관점에서 애플리케이션을 내부 및/또는 외부에 노출하는 방법을 제공합니다.
이 특정 컨트롤러는 LoadBalancer 유형의 서비스 개체만 처리합니다. 이는 클라우드 제공업체의 관점에서 볼 때 클라우드에서 일종의 로드 밸런서가 생성, 삭제 및 업데이트된다는 것을 의미합니다.
CCM이 서비스 컨트롤러 로직을 어떻게 구현했는지에 따라 클라우드 내부적으로 오직 네트워크 트래픽의 부하를 분산하는 클라우드 부하 분산 장치를 생성할 수 있습니다. 이는 일반적으로 서비스 객체의 메타데이터 섹션에 주석 세트를 정의하여 수행됩니다.
예를 들어 언급한 대로 기본 동작에 유의하세요. OpenStack은 간단한 서비스 개체(LoadBalancer 유형) 매니페스트를 적용할 때 다음 개체가 생성된다는 것입니다.
트래픽이 로드 밸런싱될 노드 목록이 채워진 클라우드 로드 밸런서입니다. 로드 밸런서는 생성된 임의의 NodePort를 사용하여 모든 노드를 가리킵니다
NodePort 유형의 서비스 객체
위에서 볼 수 있듯이 실제로 k8s와 클라우드 공급자 모두에서 서비스 개체를 구성하는 여러 가지 항목이 있습니다. 사용자의 경우 이는 EXTERNAL-IP 열이 클라우드 로드 밸런서의 클라우드 공급자 IP로 채워짐을 의미합니다. kubectl을 사용하여 서비스 객체를 나열할 때 표시됩니다.
$> kubectl get service my-app-svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) my-app-svc LoadBalancer 172.20.10.100 123.123.123.123 80:31147/TCP
4개의 컨트롤러 중 조금 특별한 것이 있는데, 바로 (클라우드) Route 컨트롤러입니다. --allocate-node-cidrs 또는 --configure-cloud-routes 플래그를 제공하지 않으면 시작되지 않습니다. CCM. 또한 경로 처리 논리를 구현하지 않은 경우 이 컨트롤러는 시작되지 않습니다. 이에 대해서는 나중에 자세히 설명합니다.
이 컨트롤러는 주기적으로 다음 작업을 시도합니다.
k8s 클러스터와 연결된 모든 경로를 나열합니다. 이는 클라우드 공급자 API를 쿼리하여 수행됩니다.
k8s API를 쿼리하여 모든 노드를 나열합니다.
노드 사양의 모든 Node 및 thepodCIDRs 필드를 반복합니다. Pod CIDR 및 노드 이름은 클라우드 공급자 API를 통해 경로를 생성하는 데 사용됩니다.
또한 제어 루프 중에 컨트롤러는 사용되지 않는 경로를 삭제합니다. 모든 경로가 생성되면 노드가 준비된 것으로 간주됩니다. 이는 NetworkUnavailable의 노드 조건 필드가 false로 설정된다는 의미입니다. 노드에 연결된 경로가 없으면 NetworkUnavailable 필드가 true로 설정됩니다. 이러한 조건은 CCM이 담당하는 컨트롤러와 혼동하지 않도록 NodeLifeCycle 컨트롤러에 의해 오염으로 변환됩니다.
(클라우드 노드)Lifecycle 컨트롤러는 노드가 클라우드에서 제거되면 Kubernetes API 노드 개체로 표시되는 노드가 제거되도록 합니다.
또한 노드가 클라우드 공급자가 지정한 종료 상태에 있는 경우 노드는 node.cloudprovider.kubernetes.io/shutdown 및 NoSchedule의 오염 효과에 따라 오염됩니다.
이것은 CCM에서 얻을 수 있는 모든 기능에 대한 것입니다. 대부분의 경우 클라우드에는 Ingress 유형의 k8s 개체를 처리하기 위한 자체 컨트롤러(별도의 저장소와 별도의 바이너리로 제공)가 있을 수 있습니다. 기본 네트워크 인프라와 기본적으로 통합됩니다.
CCM은 원스톱 솔루션이 아니라 더 큰 퍼즐의 한 조각에 불과합니다.
따라서 CCM이 처리하는 다양한 컨트롤러의 소스 코드를 살펴보았다면 클라우드 공급자별 코드가 어디에도 없다는 것을 알 수 있을 것입니다. 다양한 개체에 대해 다소 신비한 방법을 호출하는 경우가 많습니다.
클라우드 제공업체별 코드와 코드 연결은 이 CCM 퍼즐에서 누락된 부분이 될 것입니다.
CCM 퍼즐의 누락된 조각인 클라우드 제공업체 패키지(k8s.io/cloud-provider)로 이동하기 전에 CCM과 클라우드 제공업체의 역사 중 일부를 살펴보겠습니다. 지난 몇 년간 어떻게 발전해 왔고 모든 것이 어떻게 되었는지.
처음부터 클라우드 통합은 분명한 이유로 k8s의 일부의 기초였습니다. 2015년 7월에 출시된 v1.0의 k8s 저장소(k/k) 내에 특정 공급자 코드가 있는 클라우드 공급자를 살펴보겠습니다.
위의 "클라우드 제공업체"를 모두 알고 계시겠지만, 그 중 일부는 가상화 기술이며 일반적으로 클라우드 제공업체로 보는 것과 정확히 일치하지 않습니다. 최소한으로 말하면
2015년 7월에 모든 클라우드 공급자별 코드를 k8s 클러스터 노드를 구성하는 중요한 노드 구성 요소 중 하나인 kubelet에서 가져와 사용했습니다.
k8s 커뮤니티가 인식하고 현재까지 작업 중인 클라우드 공급자별 코드의 원래 구현에는 여러 가지 문제가 있습니다.
지난 몇 년간 표면화된 몇 가지 문제는 다음과 같습니다.
kubelet은 클라우드 공급자별 제어 루프를 실행하지 않습니다. 이제 CCM으로 옮겨졌습니다.
클라우드 공급자는 k/k(트리 내)의 일부가 될 수 없습니다. 그 이유는 클라우드 공급자 코드가 k8s 릴리스 주기에 바인딩되고 k/k에 코드를 커밋하는 것이 지루한 작업입니다.
클라우드를 k8s와 통합하는 플러그형 방식을 갖춘 별도의 패키지를 제공하여 외부(트리 외부) 클라우드 공급자를 지원합니다. 이것이 k8s.io/cloud-provider 패키지가 되었습니다.
CCM에서 사용하는 모든 클라우드 컨트롤러 코드는 k8s.io/cloud-provider 패키지로 이동해야 하며, 이동될 트리에는 아직 코드가 남아 있습니다.
이전 버전과의 호환성을 위해 트리에 있던 코드는 한동안 사용되지만 이제는 자체 패키지입니다(k8s.io/legacy-cloud-providers).
K8s 조직의 다양한 저장소를 마치 디지털 고고학처럼 파헤쳐 보면서 CCM과 k8s.io/cloud-provider가 어떻게 탄생했는지 따라가려고 노력했습니다. 주요 내용은 다음과 같습니다.
2016년 9월에 트리 외부 클라우드 공급자(플러그형)를 지원하기 위해 향상된 #88(KEP) 문제가 생성되었습니다.
2016년 10월 (kube) 컨트롤러 관리자를 두 부분으로 나누기 시작했습니다. 이 PR에서는 VolumeController 를 언급하고 있으며 이는 CSI 이전의 시점입니다. 해당 컨트롤러는 그 이후로 CCM에서 제거되었습니다.
2017년 7월 Cloud Controller Manager 토론. v1.11에서 베타 버전으로 출시되었습니다.
Kubelet과 클라우드 제공업체가 한때 얼마나 긴밀하게 결합되었는지에 대한 좋은 설명은 다음과 같습니다. kubelet과 클라우드 공급자를 분리하는 방법에는 세 가지 접근 방식이 있습니다.
클라우드 공급자 패키지는 CCM에서 k8s.io/cloud-provider로 가져오고 여러 (Golang) 인터페이스를 정의합니다. 가장 중요한 것은 이 패키지를 클라우드 제공업체에 연결할 수 있게 해주는 인터페이스 인터페이스입니다.
인터페이스는 일련의 메소드를 정의하며, 이들 중 일부는 다른 인터페이스를 반환합니다. 반환된 이러한 인터페이스는 클라우드 공급자 패키지의 cloud.go 파일에도 정의되어 있습니다.
$> kubectl get service my-app-svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) my-app-svc LoadBalancer 172.20.10.100 123.123.123.123 80:31147/TCP
위에서 볼 수 있듯이 메서드 서명은 반환된 인터페이스와 함께 bool 반환 값을 지정합니다. 즉, CCM에서 구현할 수 없거나 구현할 수 없는 경우 기능을 활성화/비활성화할 수 있습니다. 인터페이스에서 정의한 기능을 구현하는 컨트롤러를 초기화할 때 확인하게 되는 내용입니다.
다음은 어떤 컨트롤러에서 사용되는 k8s.io/cloud-provider 인터페이스 방법에 대한 간략한 개요입니다.
인스턴스 인터페이스 메소드는 노드 및 수명 주기 컨트롤러에서 호출됩니다.
Zones 인터페이스 메서드는 노드와 Lifecycle 컨트롤러에서 호출됩니다.
Route 인터페이스 메소드는 Route 컨트롤러에서 호출됩니다.
LoadBalancer 인터페이스 메소드는 서비스 컨트롤러에서 호출됩니다.
클러스터 인터페이스는 GCP 외부 클라우드 제공업체에서만 사용됩니다.
k/k 저장소에는 위 인터페이스의 다양한 메소드에 대한 호출이 있는 여러 위치가 있습니다. kubelet과 API 서버 모두에서.
k8s.io/cloud-provider 패키지 위의 인터페이스 외에도 클라우드 공급자를 CCM에 등록하고 초기화하는 데 필요한 모든 것이 포함되어 있습니다.
LoadBalancer 인터페이스를 살펴보면 구현해야 할 여러 메소드가 표시됩니다.
LoadBalancer() (LoadBalancer, bool) Instances() (Instances, bool) Zones() (Zones, bool) Clusters() (Clusters, bool) Routes() (Routes, bool)
이러한 메서드는 CCM에서 실행되는 서비스 컨트롤러에 의해 호출됩니다. 서비스 컨트롤러의 소스 코드에서 호출되는 메서드를 볼 수 있으므로 이러한 메서드를 예로 보여드리겠습니다.
CCM 전체에서 실제로 전달되는 것은 클라우드 제공자 역할을 할 인스턴스화된 개체입니다(모든 클라우드 제공자 인터페이스 충족).
CCM이 유지 관리하는 클라우드 컨트롤러가 클라우드에서 리소스를 생성, 업데이트 및 삭제할 수 있는 방법은 다음과 같습니다.
k8s.io/cloud-provider 패키지는 연결 방법 등을 정의하지 않습니다. 클라우드에 인증하세요. 그런 종류의 논리는 CCM에 구축해야 할 것입니다.
k8s.io/cloud-provider 패키지에 정의된 모든 인터페이스를 충족하고 모든 것을 하나로 연결했다면 성공적으로 클라우드 공급자가 된 것입니다. 이제 남은 것은 CCM 바이너리를 빌드하고 컨테이너에 패키징하여 k8s에 배포하는 것뿐입니다!
앞으로 k/k 저장소의 클라우드 공급자 부분을 살펴보면 실제로 많은 일이 일어날 것입니다. 이 글을 쓰는 시점에서 k8s.io/cloud-provider를 다소 재구성하고 만들려는 계획이 진행 중입니다. 독립적인. 예를 들어 다음과 같은 의미입니다. 클라우드 컨트롤러는 k8s.io/cloud-provider 패키지의 일부가 됩니다. 즉, 결국 클라우드 제공업체는 자체 CCM 및 외부 클라우드 제공업체를 구축하고 구현할 수 있도록 하나의 패키지를 가져오게 됩니다.
새로 조립되고 Docker 패키지로 제공되는 CCM을 실행하려면 k8s 제어 플레인을 시작할 때 구성해야 하는 몇 가지 사항이 있습니다.
이 게시물의 시작 부분에서 언급했듯이 외부 클라우드 제공업체 CCM을 실행하는 기술적인 측면을 보여주고 설명하는 저장소가 있습니다.
예를 들어 지금 AWS를 사용하고 있고 EC2 인스턴스에서 자체 k8s 클러스터를 가동하고 있으며 AWS에 대한 기본 통합을 원했다면 클라우드 공급자인 AWS CCM을 배포했을 것입니다. 권장되지는 않지만 kubelet에 --cloud-provider=aws를 지정할 수도 있습니다. 이것이 트리 내 클라우드 공급자를 사용하고 싶다는 신호를 k8s에 보내는 방법입니다. 구현된 기능은 소수에 불과합니다. "최신" 프라이빗/퍼블릭 클라우드에는 외부 클라우드 공급자 CCM이 있습니다.
트리 내 클라우드 공급자에 대한 코드는 k8s.io/legacy-cloud-providers를 통해 가져옵니다. k/k의 CCM 뼈대 코드를 사용하면 처음부터 이 패키지를 가져오게 됩니다. .
k8s의 맥락에서 클라우드 제공업체와 관련된 모든 것에 관해 무슨 일이 일어나고 있는지 알아보려면 다음 리소스를 참조하세요.
SIG 클라우드 제공업체
k8s Slack 공간의 채널 sig-cloud-provider
sig/cloud-provider로 라벨이 지정된 모든 k8s 향상 문제
다음은 참고용으로 사용하거나 다른 사람들이 어떻게 했는지 궁금할 때 사용할 수 있는 외부 클라우드 제공업체 목록입니다.
오픈스택
디지털오션
AWS
GCP
알리바바 클라우드
화웨이 클라우드
바이두 클라우드
vSphere
애저
위 내용은 Kubernetes 클라우드 컨트롤러 관리자의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!