📝쿠버네티스 서비스란?
파드의 검색과 통신을 위해 사용하며, 동일한 서비스를 제공하는 파드 그룹에 지속적인 접점을 만들어주는 추상화 방법이다.
파드들의 그룹을 통해 구동되는 어플리케이션에 고정적인 네트워크 주소로 노출시켜 외부에서 접근 가능하게 해주는 객체(레이블 셀렉터를 사용해 파드 집합을 식별)이다. 내, 외부 클라이언트 모두 서비스로 파드에 접속한다.
🎉서비스의 등장 배경
- 파드는 외부 요청없이 독립적으로 수행하는 경우도 있지만 대다수는 외부요청이 필요하다.
- 파드가 다른 파드의 서비스를 사용하려면 파드를 찾는 방법이 필요하다. 하지만 파드는 일시적이기 때문에 언제든 제거되거나 이동할 수 있고, 노드에 파드가 스케줄링되어 실행되기 바로 전에 IP주소를 할당하기 때문에 파드의 주소를 미리 알 수 없다.(레이블 셀렉터로 찾을 수 있다.)
- 이 외에도 스케일링을 통해 여러 파드를 사용하면 클라이언트는 각 파드의 IP주소를 알아야 엑세스가 가능하기 때문에 k8s에서는 Service라는 컴포넌트를 제공하게 된다.
🎁서비스의 생성
- kubectl create [svcName].yaml을 통해 서비스를 생성하며 kubectl expose로 더 쉽게 생성이 가능하다.
- kubectl get svc를 통해 현재 실행되는 서비스를 확인할 수 있다. Port는 서비스 노출을 위한 포트번호, TargetPort는 어플리케이션 노출을 위한 포트번호로 매핑을 시켜주기 위해 기재한다.
- kubectl exec kubia-7nog1 -- curl -s http://10.111.249.153 명령을 실행하면 다음과 같은 프로세스를 거친다.
- 클라이언트가 서비스를 요청하고 서비스를 지원하는 파드가 여러개이면 레이블 셀렉터로 파드를 찾아내 로드밸런싱을 해준다.
🔗서비스 연결(서비스의 기본 유형: ClusterIP 유형)
- ClusterIP는 파드들이 클러스터 내부의 다른 리소스와 통신할 수 있도록 해주는 가상의 클러스터 전용 IP이다. 오직 클러스터 내부에서만 접근이 가능하다.
- 파드 셀렉터는 서비스 스펙에 정의되어있지만 연결할 때 직접적으로 사용하지는 않는다.
- 파드 셀렉터는 IP와 포트목록을 작성할 때 사용되며 이들은 엔드포인트 리소스에 저장된다.
- 클라이언트가 서비스에 연결을 시도하면 서비스 프록시는 이들 중 하나의 IP와 포트 쌍(엔드포인트)을 선택해 파드에게 전달한다. 이 때 서비스와 엔드포인트의 이름은 항상 같아야한다.
- 서비스를 만들 때 파드 셀렉터가 정의되지 않으면 쿠버네티스는 엔드포인트 리소스를 만들지 못해 서비스에 포함된 파드가 무엇인지 알 수 없다.
🔗서비스 연결(외부 클라이언트에서 연결 유형)
프론트엔드 웹 서버와 같은 특정 서비스를 노출해 외부 클라이언트가 액세스할 수 있게 하려면?
앞서 본 ClusterIP 유형 외 3가지 유형이 있다.
1. NodePort 유형
- NodePort 서비스는 외부에서 노드IP의 특정 포트로 들어오는것을 감지하여 해당 포트와 연결된 파드로 트래픽을 전달하는 유형의 서비스이다.
- 이 때 클러스터 내부의 트래픽을 특정 파드로 연결하기 위해 ClusterIP를 자동으로 생성한다고 한다.
- 노드포트 서비스를 생성하면 쿠버네티스가 모든 노드에 특정 포트를 할당하고(모든 노드가 동일한 포트번호를 가짐) 서비스를 구성하는 파드로 들어오는 연결을 전달한다.
NodePort -> port -> targetPort
2. RoadBalancer 유형(노드 포트의 확장형)
- 클라우드 환경에서의 로드밸런서를 클러스터의 서비스로 실행시키며, 로드밸런서는 트래픽을 다른 노드의 노드포트로 전달. 클라이언트는 로드밸런서의 IP로 서비스에 접속
svc 생성 -> 클라우드 인프라 로드밸런서 생성, IP주소 표시(EXTERNAL-IP) -> EXTERNAL-IP를 통해 서비스에 접속
3. Ingress 유형(Ingress - 들어가는 행위, 들어갈 권리)
- 로드밸런서는 자신의 공용 IP주소를 가진 로드밸런서가 필요하지만, 인그레스는 하나의 인그레스로 IP주소로 수십개의 서비스에 접근이 가능하도록 지원해준다.
- Http요청을 인그레스에 보내면 요청한 호스트와 경로에 따라 요청을 전달할 서비스를 결정
- 인그레스 동작방식 예시)
DNS 조회 -> 인그레스 컨트롤러 IP반환 -> 클라이언트 HTTP 요청을 인그레스 컨트롤러 전송, 헤더 HOST의 주소 요청 -> 인그레스 컨트롤러가 접속하는 서비스 결정 및 파드 선택 -> 엔드포인트에서 파드IP 조회 -> 클라이언트 요청 파드에 전달
🤔😊파드가 준비 되었는가?? (feat. 레디니스 프로브)
- 서비스의 셀렉터와 일치한 새 레이블을 가진 파드가 생성
- 서비스의 요청을 서비스의 셀렉터와 일치하는 파드로 전달
- 파드 구성에 데이터로드에 시간이 걸릴 경우 완전히 기동된 파드가 아니면 파드에 요청을 전달하지 않는것이 좋음.
-> 레디니스 프로브가 등장하게 된다.
😊레디니스 프로브란?
주기적으로 호출되며 특정 파드가 클라이언트 요청을 수신할 수 있는지 체크하는 요소
- 라이브니스 프로브 동작과 유사하다. 다만 둘의 차이점은 상태가 좋지 않은 컨테이너를 제거하고 교체하느냐, 준비된 컨테이너만 요청을 수신하도록 하느냐이다.
- 성공을 반환(요청 수락 준비 신호)하면 요청을 보내는데 이 때 성공의 반환 방법은 컨테이너마다 다르며,
라이브니스 프로브와 마찬가지로 HTTP GET, TCP소켓, EXEC 프로브 세가지이다.
🙄마지막으로 헤드리스 서비스란?
클라이언트가 모든 파드와 연결하고 싶은 경우 헤드리스 서비스를 이용한다.
헤드리스 서비스 프로세스
- 헤드리스 서비스 생성 -> spec.clusterIP 필드값을 None으로 설정
- 파드가 준비되면 DNS A레코드 생성 DNS 조회로 실제 파드 IP를 얻을 수 있는지 확인(DNS 조회: 하나의 A레코드 대신 모든 파드들의 IP가 담긴 DNS A레코드를 받아 하나 혹은 여러개의 파드 연결이 가능하다.)
헤드리스 서비스는 서비스 프록시 대신 DNS가 파드의 IP를 반환하므로 파드에 직접 연결이 가능하다.
💡결론
- 서비스는 일시적으로 생성되는 파드를 지속적으로 연결해주기 위한 요소이다.
- 내부에서 파드에 접근할 때는 ClusterIP 유형이, 외부 클라이언트의 접근에는 NodePort, RoadBalancer, Ingress 유형이 있다.