Amazon EKS Cluster Endpoint 네트워크 유형별 차이점
EKS를 생성할 때 클러스터 엔드포인트 액세스 유형을 지정해야한다. 클러스터 엔드포인트는 Control Plane의 Kubernetes API 서버용 엔드포인트를 의미한다. 클러스터 엔드포인트는 시스템 요구사항에 맞춰 유형을 지정하여 생성하면 되는데 이 때 유형별로 어떤 차이점이 있는지와 어떤 네트워크 흐름을 가지는지 궁금했다. 우선 클러스터 엔드포인트 액세스 유형은 3가지로 Public, Public & Private, Private 중 선택하여 생성할 수 있다. Public Access 사용자는 인터넷에서 클러스터 API 서버에 접근할 수 있다. 워커 노드가 존재하는 VPC에서 DNS 질의를 해도 클러스터 엔드포인트의 퍼블릭 아이피가 조회된다. 외부 환경에서도 동일하게 클러스터 엔드포인트의 퍼블릭 아이피가 조회된다. 위의 구성도에서 PUBLIC ACCESS SOURCE CIDR를 보면 0.0.0.0/0으로 되어있는데 해당 CIDR는 직접 조정이 가능하며 최대 40개까지 CIDR를 추가할 수 있다. Netowrk ACL로 제어하는 것으로 보인다. 그러나 위의 경우 워커 노드에서 API Server와 통신할 때 Amazon 네트워크 내에서 이동되며 외부 인터넷으로는 이동되지 않는다. Private Access Private Access로 설정하게 되면 EKS OWNED ENI를 통한 접근만 허용하게 된다. Public Access로 생성해도 EKS OWNED ENI가 생성되지만 직접 통신은 하지 않는다. 클러스터 API에 접근하기 위해서는 EKS OWNED ENI와 통신이 가능한 상태여야 한다. 가장 큰 특징은 Amazon EKS에서 사용자 대신 Route53 Private Hosted Zone을 생성하고 Cluster의 VPC와 연결된다. AWS에서 관리되며 사용자 계정의 Route53에서는 확인할 수 없으며 사용자 VPC에서 enableDnsHostnames 및 enableDnsSupport가 활성화 되어 있어야 하며 DHCP 옵션에 도메인 이름 서버 목록에 AmazonProviderDNS가 포함되어 있어야 한다. 그리고 내부 VPC 서버에서 DNS 질의했을 때 EKS OWNED ENI 아이피주소가 조회된다. 이는 Route53 Private Hosted Zone 레코드에 EKS OWNED ENI가 등록되어 있기 때문이다. 외부 환경에서 DNS 질의 했을 때 동일하게 EKS OWNED ENI 아이피 주소가 조회되지만 이때에는 퍼블릭 DNS 서버에 의해 해당 아이피주소를 반환하게 된다. 그리고 인터넷 통신이 안되는 환경인 경우 VPC 엔드포인트를 구성하여 사용해야 한다. 필요한 엔드포인트 목록은 아래 문서에서 확인 가능하다. Public & Private Access 마지막으로 Public & Private은 위에서 설명한 Public Access와 Private Access가 합쳐진 형태로 이해하면 된다. 외부 환경에서는 허용된 CIDR를 통해 퍼블릭 엔드포인트 주소로 통신이 되며 내부 VPC에서는 Route53 PHZ에서 EKS OWNED ENI 아이피 주소로 통신하게 된다.
mchlkim
Kubernetes Pod
Pod 쿠버네티스에서 생성하고 관리할 수 있는 배포 가능한 가장 작은 컴퓨팅 단위 1개 이상의 컨테이너로 구성된 컨테이너 집합 동일 파드 내 컨테이너는 여러 리눅스 네임스페이스 공유 (동일한 아이피 주소 사용) 사용자가 파드를 직접 관리하는 경우는 거의 없음 파드 수명주기 파드는 정의된 라이프 사이클을 따르며 반드시 한 번만 스케줄 되며 중지 및 종료 전까지 해당 노드에서 실행된다. 파드의 상태는 status필드는 phase 값에서 확인할 수 있다. 값 의미 Pending 파드가 클러스터 상에서 승인되었지만 파드를 실행하기 위한 준비중인 상태 Running 파드가 노드에 바인딩되었고 컨테이너가 생성된 상태 Succeeded 파드에 있는 모든 컨테이너가 정상적으로 실행된 상태 Failed 파드에 있는 모든 컨테이너가 종료되었고, 하나 이상의 컨테이너가 실패로 종료된 상태 Unknown 파드의 상태를 알 수 없는 상태로 일반적으로 파드가 실행되는 노드와 통신 문제로 발생 컨테이너 상태 쿠버네티스는 파드 내부의 각 컨테이너 상태도 추적하고 Conatiner Lifecycle hook을 사용하여 컨테이너 수명주기의 특정 지점에서 실행할 이벤트를 트리거할 수 있다. 스케줄러가 노드에 파드를 할당하면 kubelet은 컨테이너 런타임을 사용하여 파드의 컨테이너 생성을 진행한다. 이 때 확인 가능한 컨테이너 상태는 Wating, Running, Terminated이다. 상태 의미 Wating 컨테이너를 실행하는데 필요한 작업(컨테이너 이미지 다운로드, 시크릿 데이터 적용)을 진행하는 상태 Running 컨테이너가 정상적으로 실행되는 상태 Terminated 실행을 시작한 다음 완료되거나 오류로 인해 실패했을 때 나타나는 상태 컨테이너 재시작 정책 파드가 실행 중일 때 컨테이너가 실패 시 처리를 결정하는 정책 파드의 spec에는 restartPolicy 필드에서 확인 가능하다. 만약 backoffLimit(재시작 최대 횟수)를 도달하면 실패 상태가 된다. 사용 가능한 값은 Always, OnFailure, Never이다. 상태 의미 Always (default) 컨테이너 실패 시 항상 재시작 OnFailure 컨테이너 실패 시 livenessProbe에 의해 정상 상태가 될 때까지 재시작 Never 컨테이너 실패 시 재시작 하지 않음 (예제) pod.yaml 파드의 컨디션 하나의 PodStatus 값을 가지며 kubelet에서 PodConditions를 관리한다. PodScheduled : 파드가 노드에 스케줄 PodHasNetwork : 샌드박스가 성공적으로 생성되고 네트워킹 구성 Initialized : 모든 초기화 컨테이너가 성공적으로 완료 Ready : 파드는 요청을 처리할 수 있으며 일치하는 모든 서비스의 로드 밸런싱 풀에 추가되어야 한다. 필드 이름 의미 type 파드 컨디션의 이름 status 값으로는 True, False, Unknown 있고 해당 컨디션이 적용 가능 여부를 나타냄 lastProbeTime 파드 컨디션이 마지막으로 프로브된 시간의 타임스탬프 lastTransitionTime 파드가 한 상태에서 다른 상태로 전환된 마지막 시간에 대한 타임 스탬프 reason 컨디션의 마지막 전환에 대한 이유를 나타내는 기계가 판독 가능한 upperCamelCase 텍스트 message 마지막 상태 전환에 대한 세부 정보를 나타내는 사람이 읽을 수 있는 메시지 파드의 준비성(readiness) 파드가 트래픽을 수신할 준비가 되었는지 여부를 나타내는 상태 spec.readinessGate필드를 통해 지정할 수 있다. readinessGates는 status.conditions 필드에서 확인 할 수 있다. 쿠버네티스에서 status.conditions 해당 필드에서 해당되는 컨디션을 찾지 못하면 기본 값은 False이다. 사용자 지정 컨디션을 사용하는 파드의 경우 두 컨디션이 모두 정상 상태인 경우에만 파드가 준비된 것으로 평가된다. 파드 내부의 컨테이너의 준비 상태 readinessGates에 지정된 모든 컨디션들의 값이 True인 상태 PodHasNetworkCondition 활성화를 하게 되면 kubelet은 파드의 status.conditions 필드에 있는 PodHasNetwork 컨디션을 통해 파드가 초기화 컨테이너 실행 여부를 결정한다. kubelet이 파드의 네트워킹이 구성된 런타임 샌드박스가 없음을 확인할 때 PodHasNetwork 컨디션은 False로 설정된다. False 상태인 경우 아래 시나리오에서 발생 파드 라이프사이클 초기에 kubelet이 컨테이너 런타임을 사용하여 파드를 위한 생성을 시작하지 않을 때 파드 라이프사이클 후기에 파드의 샌드박스가 파괴되었을 때 (노드 재부팅) 런타임 플러그인이 파드를 위한 샌드박스 생성 및 네트워크 구성이 정상적으로 완료되었으면 kubelet에서 PodHasNetwork 컨디션을 True로 설정되며 컨테이너 이미지를 풀링하고 컨테이너를 생성할 수 있다. 초기화 컨테이너가 있는 파드인 경우 kubelet은 초기화 컨테이너가 성공적으로 완료된 후 Intialized 컨디션을 True로 설정한다. 초기화 컨테이너가 없는 파드인 경우 kubelet은 샌드박스 생성 및 네트워크 구성이 시작되기 전에 Intialized 컨디션을 True로 설정한다. 컨테이너 프로브 컨테이너에서 kubelet에 의해 주기적으로 수행되는 상태 검사 도구 상태 검사를 수행하기 위해 kubelet은 컨테이너 내부에서 코드를 실행하거나 네트워크 요청을 전송한다. 매커니즘 프로브를 사용하여 컨테이너를 체크하는 방법은 4가지가 있으며 그 중 하나를 정의하여 사용해야 한다. 매커니즘 의미 exec 컨테이너 내에서 지정된 명령어 실행 상태 코드0으로 종료되면 성공으로 간주 grpc gRPC를 사용하여 원격 프로시저 호출을 수행 체크 대상이 gRPC 헬스 체크가 구현되어야 한다. 응답 status가 SERVING 인 경우 성공으로 간주 (현재 알파 기능이며 GRPCContainerProbe를 활성화 해야한다.) httpGet 지정한 포트 및 경로에서 컨테이너의 IP 주소에 대한 HTTP GET 요청을 수행 응답 상태 코드가 200 ~ 400 범위인 경우 성공으로 간주 tcpSocket 지정된 포트에서 컨테이너 IP주소에 대해 TCP 검사 수행 포트가 활성화되어 있다면 성공으로 간주 프로브 결과 프로브는 세가지 결과 중 하나를 가진다. 결과 의미 Success 컨테이너가 진단을 통과 Failure 컨테이너가 진단에 실패 Unknown 진단 자체가 실패 (실패 시 kubelet에서 추가 체크를 수행 하므로 사용자는 아무런 조치를 하면 안됨) 프로브 종류 kubelet은 실행 중인 컨테이너들에 대해서 선택적으로 세 가지 종류의 Probe를 수행한다. Probe 의미 livenessProbe 컨테이너 동작 여부를 나타내며 실패 시 kubelet은 컨테이너를 종료시키고 해당 컨테이너의 재시작 정책의 대상이된다. + 컨테이너가 livenessProbe를 제공하지 않는 경우 기본 상태는 Success 이다. readinessProbe 컨테이너가 요청을 처리할 준비 여부를 나타내며 실패 시 엔드포인트 컨트롤러는 파드에 연관된 모든 서비스들의 엔드포인트에서 파드의 IP주소를 제거한다. 초기 지연 이전의 기본 상태는 Failure이며 컨테이너가 readinessProbe를 지원하지 않는 경우 기본 상태는 Success이다. startupProbe 컨테이너 내의 애플리케이션이 시작 여부를 나타내며 startupProbe를 사용하는 경우 성공할 때까지 다른 나머지 probe는 활성화 되지 않으며 실패 시 kubelet은 컨테이너를 종료시키며 컨테이너 재시작 정책에 따라 처리되며 startupProbe를 지원하지 않는 경우 기본 상태는 Success이다. livenessProbe를 사용해야 하는 경우 파드가 정상적으로 실행 중인지 여부를 확인해야 하는 경우 파드가 오류를 발생시킬 경우 쿠버네티스가 파드를 자동으로 복구해야 하는 경우 readinessProbe를 사용해야 하는 경우 Pod가 트래픽을 처리하기 전에 초기화 또는 구성이 필요할 경우 Pod가 트래픽을 처리할 준비가 되었을 때만 트래픽을 받고 싶은 경우 startupProbe를 사용해야 하는 경우 Pod가 시작되는 데 시간이 오래 걸리는 경우 Pod가 시작되는 동안 다른 Pod에 영향을 미치지 않도록 하려는 경우 파드의 종료 파드는 워커 노드에서 실행되므로 더 이상 필요하지 않을 때 정상적으로 종료하는 것이 중요. 컨테이너 런타임은 각 컨테이너의 기본 프로세스에 TERM 신호를 전송한다. 이미지에 정의된 STOPSIGNAM 값을 존중하며 TERM 대신 해당 값을 보낸다. 유예 기간이 만료되면, KILL 시그널이 나머지 프로세스로 전송되고 파드는 API 서버로부터 삭제된다. 프로세스가 종료될 때까지 기다리는 동안 kubelet 또는 컨테이너 런타임의 관리 서비스가 다시 시작되면 클러스터는 전체 원래 유예 기간을 포함하여 처음부터 시도한다. 플로우 kubectl을 사용하여 기본 유예 기간(30s)으로 특정 파드를 수동으로 삭제 API 서버의 파드는 유예 기간과 함께 파드가 "dead"로 간주되는 시간으로 업데이트 Terminating 상태로 표시, kubelet이 파드가 종료된 것으로 표시되었음을 확인하는 즉시 파드 종료 프로세스를 시작 prestop훅을 정의한 경우 kubelet은 컨테이너 내부에서 해당 훅을 실행, 유예 기간이 만료된 후 prestop 훅이 계속 실행되면 kubelet은 2초의 일회성 유예 기간 연장을 요청 kubelet은 컨테이너 런타임을 트리거하여 각 컨테이너 내부의 프로세스에 TERM 시그널을 보냄 kubelet이 정상 종료를 시작하는 동시에 컨트롤 플레인은 구성된 셀렉터가 있는 서비스를 나타내는 EndpointSlice 오브젝트에서 종료된 파드를 제거, 레플리카셋과 기타 워크로드 리소스는 더 이상 종료된 파드를 유효한 서ㅣ스 내 복제본으로 취급하지 않는다. 로드 밸런서가 종료 유예 기간이 시작되는 즉시 엔드포인트 목록에서 파드를 제거하므로 느리게 종료되는 파드는 트래픽을 계속 제공할 수 없다. 유예 기간이 만료되면 kubelet은 강제 종료를 트리거하며 컨테이너 런타임은 SIGKILL을 파드의 모든 컨테이너에서 여전히 실행 중인 모든 프로세스로 전송한다. kubelet은 해당 컨테이너 런타임이 하나를 사용하는 경우 숨겨진 pause 컨테이너도 정리한다. kubelet은 유예 기간을 0(즉시 삭제)으로 설정하여 API 서버에서 파드 오브젝의 강제 삭제를 트리거 한다. API 서버가 파드의 API 오브젝트를 삭제하면 더 이상 조회할 수 없다. 파드 강제 종료 모든 삭제는 30초 이내에는 정상적으로 수행된다. kubectl delete 명령은 기본값을 재정의하고 사용자의 고유한 값을 지정할 수 있는 --grace-period=<seconds> 옵션을 지원한다. 유예 기간을 0으로 강제로 즉시 설정하면 API 서버에서 파드가 삭제되며 파드가 노드에서 실행 중인 경우 kubelet에 트리거되어 즉시 종료를 시작한다. 강제 삭제는 --grace-period=0 --force 플래그를 선언해야 한다. 강제 삭제가 수행되면 API 서버는 실행 중인 노드에서 파드가 종료되었다는 kubelet의 확인을 기다리지 않음 API에서 즉시 파드를 제거하므로 동일한 이름으로 새로운 파드를 생성할 수 있다. 노드에서 즉시 종료되도록 설정된 파드는 강제 종료되기 전에 작은 유예 기간이 계속 제공된다. 파드의 가비지 콜렉션 Kubernetes에서 파드 가비지 콜렉션(PodGC)은 종료된 파드를 자동으로 제거하는 기능입니다. 이렇게 하면 시간이 지남에 따라 파드가 생성되고 종료될 때 리소스 유출을 방지할 수 있습니다. 파드가 종료되면 API 오브젝트는 클러스터의 API에 남아 있습니다. 사람이나 컨트롤러 프로세스가 명시적으로 파드를 제거하지 않으면 파드는 계속해서 API에 남아 있게 됩니다. PodGC는 다음과 같은 경우에 파드를 정리합니다. 종료된 파드(Succeeded 또는 Failed 단계 포함)의 수가 구성된 임계값을 초과하는 경우 고아 파드인 경우 스케줄되지 않은 종료 중인 파드인 경우 NodeOutOfServiceVolumeDetach 기능 게이트가 활성화되어 있고, node.kubernetes.io/out-of-service에 테인트된 준비되지 않은 노드에 속한 종료 중인 파드인 경우 PodDisruptionConditions 기능 게이트가 활성화된 경우, PodGC는 파드를 정리하는 것 뿐만 아니라 해당 파드들이 non-terminal 단계에 있는 경우 그들을 실패했다고 표시하기도 합니다. 또한, PodGC는 고아 파드를 정리할 때 파드 중단 조건을 추가하기도 합니다. 멀티 컨테이너 디자인 패턴 Sidecar 패턴 메인 컨테이너를 보조하는 컨테이너와 같이 실행하는 구조 사용 케이스로는 메인 컨테이너 로그 수집, 프록시 서버로 서비스 메시 구성 등에 사용 Adapter 패턴 어플리케이션 출력이나 집계를 위한 모니터링 데이터를 표준화 및 정규화 사용 케이스로는 정보 표준화, 외부 시스템과의 호환성 향상 등에 사용 Ambassador 패턴 파드 외부의 서비스에 대한 액세스를 간소화 사용 케이스로는 외부 서비스에 대한 단일 진입점 제공, 외부 API 연결 등에 사용 명령어
Kubernetes 기초
쿠버네티스란? 컨테이너화된 워크 로드와 서비스를 관리하기 위한 이식성이 있고, 확장 가능한 오픈소스 플랫폼 컨테이너 발전과정 쿠버네티스 특징 서비스 디스커버리와 로드 밸런싱 스토리지 오케스트레이션 자동화된 롤아웃과 롤백 자동화된 빈 패킹 자동화된 복구 시크릿과 구성 관리 쿠버네티스 컴포넌트 Control Plane 쿠버네티스 클러스터를 관리하는 역할 상태 관리 및 명령어 처리 구성 요소 apiserver 쿠버네티스 리소스와 클러스터 관리를 위한 API 제공 etch를 데이터 저장소로 사용 etcd 일관성과 고가용성을 가지 key-value 저장소 etcd를 백업하여 복구 가능 scheduler 노드의 자원 사용 상태를 관리하며 새로운 워크로드를 어디에 배포할지 관리 controller manager 여러 컨트롤러 프로세스를 관리, 복잡성을 낮추기 위해 모두 단일 바이너리로 컴파일되고 단일 프로세스 내에서 실행 Node Controller, Job Controller, EndpointSlices Controller, ServiceAccount Controller 각 컨트롤러는 클러스터로부터 특정 리소스 상태의 변화를 감지하여 클러스터에 반영하느 reconcile 과정을 반복 수행 cloud-controller-manager 클라우드별 컨트롤 로직을 포함하는 컴포넌트 클라우드 공급자의 컨트롤러 매니저를 통해 API연결하고 해당 클라우드 플랫폼과 상화 작용하는 컴포넌트 Data Plane 실행 중인 파드를 유지시키고 쿠버네티스 런타임 환경을 제공 kubelet 각 Data Plane에서 실행되는 에이전트이며 API 서버와 통신하며 노드의 리소스 관리 Container Runtime과 통신 및 Container Lifecycle 관리 CRI(Container Runtime Interface) kubelet이 컨테이너 런타임과 통신할 때 사용되는 인터페이스 쿠버네티스에서는 Docker, Containerd, cri-o 런타임 지원 kube-proxy Network Proxy 및 내부 로드 밸런서 역할 수행 노드의 네트워크 규칙을 유지 관리 및 내부/외부 통신 할 수 있게하는 역할 수행 Refer. https://github.com/containerd/containerd/blob/main/docs/getting-started.md https://cri-o.io/#what-is-cri-o