[Docker] 쿠버네티스 시작하기
업데이트:
6.1 쿠버네티스를 시작하기 전에
- 모든 리소스는 오브젝트 형태로 관리됨
- 포드, 레플리카셋, 서비스 어카운트, 노드 등
- 쿠버네티스는 명령어로도 사용할 수 있지만 YAML 파일을 더 많이 사용함
- 컨테이너 리소스를 생성하거나 삭제 가능
- 컨테이너 외에도 모든 리소스 오브젝트들에 사용 가능
- 서비스를 배포할 때 kubectl 명령어가 아닌 여러개의 YAML 파일을 정의해 쿠버네티스에 적용시키는 방식으로 동작 가능
- 쿠버네티스는 여러 개의 컴포넌트로 구성돼 있음
- 마스터 노드: 클러스터 관리
- 워커 노드: 애플리케이션 컨테이너 생성되어있음
- 도커를 포함한 많은 컴포넌트들이 실행됨
- API 서버, 컨트롤러 매니저, 스케줄러, DNS서버, 프락시, 네트워크 플러그인
- 도커 말고 CRI를 갖추고 있다면 어떠한 컨테이너를 써도 문제 없음
6.2 포드: 컨테이너를 다루는 기본 단위
6.2.1 포드 사용하기
- 컨테이너 애플리케이션의 기본 단위
- 1개 이상의 컨테이너로 구성된 컨테이너의 집합
6.2.2 포드 vs 도커 컨테이너
- 포드를 사용하는 이유는 여러 리눅스 네임스페이스를 공유하는 여러 컨테이너들을 추상화된 집합으로 사용하기 위해서
- 같은 포드 내의 컨테이너는 네트워크 네임스페이스를 공유
6.2.3 완전한 애플리케이션으로서의 포드
- 하나의 포드는 하나의 완전한 애플리케이션
- 포드에 정의된 부가적인 컨테이너를 사이드카 컨테이너라고 부름
- 포드 내 다른 컨테이너와 네트워크 환경 등을 공유
- 포드에 포함된 컨테이너들은 모두 같은 워커 노드에서 함께 실행 됨
6.3 레플리카셋: 일정 개수의 포드를 유지하는 컨트롤러
6.3.1 레플리카셋을 사용하는 이유
- 정해진 수의 동일한 포드가 항상 실행되도록 관리
- 노드 장애 등의 이유로 포드를 사용할 수 없다면 다른 노드에서 포드를 다시 생성
6.3.3 레플리카셋의 동작 원리
- 레플리카셋은 포드와 느슨한 연결(loosely coupled)을 유지하고 있음
- 라벨 셀렉터를 이용해 이뤄짐
- spec.selector.matchLabel에 정의된 라벨을 통해 생성해야 하는 포드를 찾아 유지
- replicas에 정의된 숫자와 일치하지 않으면 포드를 정의하는 포드 템플릿 항목의 내용으로 포드를 생성
- 레플리카 셋의 목적은 ‘포드를 생성하는 것’이 아닌 ‘일정 개수의 포드를 유지하는 것’
6.3.4 레플리케이션 컨트롤러 vs 레플리카셋
- 구버전의 쿠버네티스에서 사용됐었음
- 표현식 (mathExpression) 기반의 라벨 셀렉터 사용 가능
- deprecated 됨
6.4 디플로이먼트: 레플리카셋, 포드의 배포를 관리
6.4.1 디플로이먼트 사용하기
- 레플리카셋의 상위 오브젝트
- 디플로이먼트를 생성하면 대응하는 레플리카셋도 함께 생성됨
- 디플로이먼트를 사용하면 포드와 레플리카셋을 직접 생성할 필요가 없음
- 디플로이먼트를 삭제하면 레플리카셋과 포드 또한 함께 삭제됨
6.4.2 디플로이먼트를 사용하는 이유
- 애플리케이션의 업데이트와 배포를 편하게 만들기 위해 사용
- 업데이트할 때 레플리카셋의 변경 사항을 저장하는 리비전을 남겨 롤백 가능하게 해줌
- 무중단 서비스를 위해 포드의 롤링 업데이트 전략 지정 가능
6.5 서비스: 포드를 연결하고 외부에 노출
- kubectl describe 명령어로 포드의 내부 IP를 직접 확인한 뒤 포드로 직접 접근 가능
- 로컬 개발 환경 또는 쿠버네티스 클러스터 내부에서만 사용 가능
- 도커와 마찬가지로 포드의 IP는 영속적이지 않아 항상 변할 수 있다는 점 유의 필요
- 쿠버네티스는 디플로이먼트를 생성할 때 포드를 외부로 노출하지 않음
- 디폴로이먼트의 YAML 파일에는 포드의 애플리케이션이 사용할 내부 포트만 정의
- 포트를 외부로 노출해 사용자들이 접근하거나 다른 디플로이먼트의 포드들이 내부적으로 접근하려면 서비스라고 부르는 별도의 쿠버네티스 오브젝트 생성 필요
- 서비스의 핵심 기능은 다음과 같음
- 여러 개의 포드에 쉽게 접근할 수 있도록 고유한 도메인 이름 부여
- 여러 개의 포드에 접근할 때, 요청을 분산하는 로드 밸런서 기능 수행
- 클라우드 플랫폼의 로드 밸런서, 클러스터 노드의 포트 등을 통해 포드를 외부로 노출
6.5.1 서비스의 종류
- ClusterIP 타입
- 쿠버네티스 내부에서만 포드들에 접근할 때 사용
- 외부로 포드를 노출하지 않음
- NodePort 타입
- 포드에 접근할 수 있는 포트를 클러스터의 모든 노드에 동일하게 개방
- 외부에서 포드에 접근 가능
- 접근할 수 있는 랜덤하게 정해지지만 지정도 가능
- LoadBalancer 타입
- 클라우드 플랫폼에서 제공하는 로드 밸런서를 동적으로 프로비저닝해 포드에 연결
- 외부에서 포드로 접근 가능
- 일반적으로 AWS, GCP 등과 같은 클라우드 플랫폼 환경에서만 사용 가능
6.5.2 ClusterIP 타입의 서비스 - 쿠버네티스 내부에서만 포드에 접근하기
- 특정 라벨을 가지는 포드를 서비스와 연결하기 위해 서비스의 YAML 파일에 selector 항목을 정의
- 포드에 접근할 때 사용하는 포트(포드에 설정된 containerPort)를 YAML 파일의 targetPort 항목에 정의
- 서비스를 생성할 때 YAML 파일의 port 항목에 8080을 명시해 서비스의 Cluster IP와 8080 포트로 접근할 수 있게 설정
- kubectl apply -f 명령어로 ClusterIP 타입의 서비스가 생상되면 서비스는 쿠버네티스 클러스터 내부에서만 사용할 수 있는 고유한 내부 IP를 할당받음
- 쿠버네티스 클러스터에서 서비스의 내부 IP 또는 서비스 이름으로 포드에 접근할 수 있음
6.5.3 NodePort 타입의 서비스 - 서비스를 이용해 포드를 외부에 노출하기
- 모든 노드의 특정 포트를 개방해 서비스에 접근하는 방식
- 스웜 모드에서 컨테이너를 외부로 노출하는 방식과 비슷
- NodePort 타입의 서비스가 ClusterIP의 기능을 포함하고 있음
- 쿠버네티스 클러스터에서 서비스의 내부 IP와 DNS 이름을 사용해 접근할 수 있음
- 외부에서 포드에 접근하기 위해 각 노드에 개방된 포트로 요청을 전송함
- 클러스터 내부에서는 ClusterIP 타입의 서비스와 동일하기 접근 가능
- 실제 운영 환경에서는 NodePort 서비스를 외부에 제공하는 경우는 많지 않음
- 포트 번호를 80 이나 443 등 기존에 사용되고 있는것으로 설정하기 어려움
- SSL 인증서 적용, 라우팅 등과 같은 복잡한 설정을 서비스에 적용하기 어려움
- 따라서 NodePort 서비스 그 자체를 외부로 제공하기 보다는 인그레스라고 부르는 쿠버네티스의 오브젝트에서 간접적으로 사용되는 경우가 많음
6.5.4 클라우드 플랫폼의 로드 밸런서와 연동하기 - LoadBalancer 타입의 서비스
- 서비스 생성과 동시에 로드 밸런서를 새롭게 생성해 포드와 연결
- 일반적으로 AWS, GCP 등과 같은 클라우드 플랫폼 환경에서만 LoadBalancer 타입 사용 가능
- 가상머신이나 온프레미스 환경에서는 사용 어려움
- EXTERNAL-IP가 할당됨
- 클라우드 플랫폼에서 자동으로 할당된 것
- LoadBalancer 타입의 서비스가 생성됨과 동시에 모든 워커 노드는 포드에 접근할 수 있는 랜덤한 포트를 개방
- 클라우드 플랫폼에서 생성된 로드 밸런서로 요청이 들어오면 이 요청은 쿠버네티스의 워커 노드 중 하나로 전달됨
- 워커 노드로 전달된 요쳥은 포드 중 하나로 전달되어 처리됨
- MetalLB 라는 이름의 오픈소스 프로젝트를 사용하면 온 프레미스 환경에서도 LoadBalancer 타입의 서비스 사용 가능
6.5.5 트래픽의 분배를 결정하는 서비스 속성: externalTrafficPolicy
- 기본적으로 externalTrafficPolicy 속성이 Cluster로 설정됨
- 이 경우 모든 워커 노드에서 동일한 랜덤 포트가 개방됨
- 클라우드 플랫폼의 로드 밸런서는 노드 중 하나로 요청을 전달하고 노드는 다시 포드 중 하나로 요청을 전달
- 단, 노드 간에 요청이 리다이렉트 되어 NAT가 발생하므로 클라이언트의 IP를 보존할 수 없음
- 서비스의 externalTrafficPolicy 속성을 local로 설정해 생성하면 포드가 위치한 노드만 랜덤한 포트를 개방
- 로드 밸런서는 포드가 위치한 노드로만 요청을 전달하며, 해당 노드 내의 포드에서만 요청이 분산됨
- 따라서 네트워크 홉이 한 단계 적으며 클라이언트의 IP 또한 포드의 소스코드 내에서 정상적으로 확인 가능
- 하지만 externalTrafficPolicy를 Local로 설정하는 것이 무조건 좋은 것은 아님
- 특정 노드의 포트에 부하가 집중되거나 적어질 수도 있음
- 자원활용률 측면에서 바람직하지 않음
- 특정 노드의 포트에 부하가 집중되거나 적어질 수도 있음
6.5.6 요청을 외부로 리다이렉트하는 서비스: ExternalName
- 서비스가 외부 도메인을 가리키도록 설정할 수 있음
- 쿠버네티스와 별개로 존재하는 레거시 시스템에 연동해야하는 상황에서 유용하게 사용 가능
댓글남기기