서비스
서비스 (service)
클러스터에서 실행 중인 애플리케이션을, 워크로드가 여러 백엔드로 나뉘어 있더라도 하나의 외부 지향 엔드포인트 뒤에 노출시키는 방법이 서비스예요.
Kubernetes에서 Service는 클러스터 안에서 하나 이상의 파드로 실행되는 네트워크 애플리케이션을 노출시키는 방법이에요.
Kubernetes의 Service가 지향하는 핵심 목표 중 하나는, 기존 애플리케이션을 수정하지 않아도 낯선 서비스 디스커버리 메커니즘을 쓰지 않게 해준다는 거예요. 클라우드 네이티브 세상을 위해 설계된 코드든, 컨테이너화한 오래된 앱이든 파드 안에서 코드를 실행할 수 있죠. Service를 사용해서 그 파드 집합을 네트워크에 노출시키면 클라이언트가 그 서비스와 상호작용할 수 있어요.
Deployment를 사용해서 앱을 실행하면, 그 Deployment는 파드를 동적으로 만들고 파괴해요. 어느 순간을 보느냐에 따라 그 중 몇 개가 정상적으로 동작 중인지조차 알 수 없고, 정상 파드의 이름조차 모를 수 있어요. Kubernetes 파드는 클러스터의 원하는 상태에 맞춰 만들어지고 파괴되거든요. 파드는 일시적(ephemeral) 리소스라서, 개별 파드가 신뢰할 수 있고 영속적이라고 기대하면 안 돼요.
각 파드는 고유한 IP 주소를 가져요(Kubernetes는 네트워크 플러그인이 이를 보장하길 기대해요). 클러스터의 어떤 Deployment를 기준으로 보면, 한 순간에 실행 중인 파드 집합은 그 다음 순간 같은 애플리케이션을 실행하는 파드 집합과 다를 수 있어요.
여기서 문제가 생겨요. 어떤 파드 집합("백엔드"라고 부를게요)이 클러스터 안의 다른 파드 집합("프론트엔드")에 기능을 제공한다고 해볼게요. 프론트엔드는 백엔드 워크로드의 어느 IP 주소에 연결해야 할지 어떻게 알아내고 계속 추적할 수 있을까요?
여기에 Service가 등장해요.
Kubernetes의 Service
Service API는 Kubernetes의 일부로, 파드 그룹을 네트워크로 노출시키는 데 도움을 주는 추상화예요. 각 Service 객체는 논리적인 엔드포인트 집합(보통 이 엔드포인트는 파드예요)과, 그 파드들을 어떻게 접근 가능하게 만들지에 대한 정책을 함께 정의해요.
예를 들어 3개의 레플리카로 실행 중인 무상태(stateless) 이미지 처리 백엔드를 생각해 볼게요. 그 레플리카들은 서로 대체 가능해서, 프론트엔드는 어느 백엔드를 쓰든 상관하지 않아요. 백엔드 집합을 구성하는 실제 파드는 바뀔 수 있지만, 프론트엔드 클라이언트는 그걸 알 필요도 없고 백엔드 집합을 직접 추적할 필요도 없어야 해요.
Service 추상화가 이런 디커플링(분리)을 가능하게 해줘요.
Service가 타기팅하는 파드 집합은 보통 내가 정의하는 **셀렉터(selector)**로 결정돼요. Service 엔드포인트를 정의하는 다른 방법은 "셀렉터 없는 Services" 문서를 참고하세요.
워크로드가 HTTP를 말한다면, 웹 트래픽이 그 워크로드에 도달하는 방식을 제어하기 위해 Ingress를 쓰는 걸 선택할 수도 있어요. Ingress는 Service 타입이 아니지만, 클러스터의 진입점(entry point) 역할을 해요. Ingress를 쓰면 라우팅 규칙을 단일 리소스로 통합해서, 클러스터에서 별도로 실행되는 워크로드의 여러 컴포넌트를 하나의 리스너 뒤에 노출시킬 수 있어요.
Kubernetes용 Gateway API는 추가적인 기능을 제공해요.