Service

노재원·2022년 4월 14일
0

Kubernetes

목록 보기
3/8

Service

개념 및 특징


쿠버네티스 클러스터 내에서 유동성이 높은 파드에게 불변의 엔드포인트를 제공하는 것이 서비스의 역할이다.

  • 서비스의 IP와 포트번호들은 직접 바꾸지 않는 한 절대 바뀌지 않는다.
  • 파드처럼 생성했을 때 실질적인 프로세스가 생성되지 않는다.
  • 서비스의 IP는 가상 IP주소 이므로 ping 을 날릴 수 없다.

서비스의 동작 원리


쿠버네티스 static pod 중에 kube-proxy 가 있다. kube-proxy 의 역할은 자기가 떠 있는 노드에 들어오는 트래픽을 가로채서 알맞은 파드에 리다이랙션 해주는 프록시 역할이다. 하지만 이는 userspace 프록시 모드로, 현재는 성능이 훨씬 좋은 iptables 프록시 모드가 기본이다. userspace 프록시는 네트워크 트래픽 관련 작업을 거의 다 userspace에 있는 kube-proxy에서 작업한 후 네트워크 패킷들을 넘기는데, 이 때 userspace의 패킷들은 kernel space를 거쳐서 proxy가 이뤄지므로 큰 비용이 든다. 이와 반대로 iptables 모드는 kube-proxy가 했던 작업들을 kernel space의 netfilter라는 모듈이 하므로 비용이 훨씬 적게 든다.

그렇다면 서비스가 생성될 때 kube-proxy가 어떻게 동작하는지 살펴보자

  1. API 서버에서 서비스를 생성하면 바로 가상 IP주소가 할당된다.

  2. API 서버는 모든 kube-proxy에게 새로운 서비스가 생성됐음을 통보한다.

  3. kube-proxy는 해당 노드에 iptables를 수정하여 서비스 IP주소로 온 패킷을 가로채서 알맞은 파드로 보내도록 한다.

  4. 서비스와 관련된 (pod IP, 포트) 쌍을 Endpoint 오브젝트가 모니터링하고 있으므로 pod가 변경되면 Endpoint도 바뀌고, kube-proxy가 이를 알아채 다시 iptables를 알맞게 수정한다.

    여기서 iptables와 netfilter라는 개념이 헷갈릴 수 있다. 실제로 패킷을 룰을 기반으로 다루는 것은 kernel space에 있는 netfilter가 수행한다. iptables는 userspace에 있으며, netfilter에 룰을 넣기위한 interface가 된다.

    원리를 보고나서 서비스의 특징 중에, 서비스 IP로 ping 을 왜 날릴 수 없는지 알 수 있다. 결국 서비스 IP는 어떠한 네트워크 인터페이스에도 할당되지 않고 그저 (서비스 IP, 포트) 쌍으로 구성되어 있기만 할 뿐이다.

NodePort vs LoadBalancer vs Ingress


3가지 모두 외부에 서비스를 노출시키는 방법이다. 하지만 분명 차이가 있으며 용도 또한 다르므로 알아두는 것이 좋다.

  1. NodePort

    모든 노드에 특정 포트를 열어서 외부로부터 트래픽을 수신하는 방식이다. 그러면 사용자는 노드 IP:NodePort 주소로 요청을 보낼 수 있다. 보통 on-premise에서 서비스를 노출시킬 때 많이 사용한다.

    apiVersion: v1
    kind: Service
    metadata:
    	name: nodeport
    spec:
    	type: NodePort
    	ports:
    	- port: 80
    		targetPort: 8080
    		nodePort: 30123
    	selector:
    		app: example
  2. Load Balancer

    NodePort의 확장 버전이며, gcp나 aws와 같은 클라우드 인프라에서만 사용할 수 있다. 기본적으로 서비스들은 노드포트처럼 특정 포트가 노드마다 열려있지만, 외부에 노출되는 포인트는 Load Balancer 하나이다. 따라서 사용자가 접근할 때는 Load Balancer의 IP주소를 가지고 접속할 수 있다.

    하지만 Load Balancer는 하나의 서비스에만 적용할 수 있어서, 여러 서비스를 노출시키고 싶으면 그에 맞게 여러 Load Balancer를 생성해줘야 하고, 그렇게 되면 비용이 많이 발생하게 된다.

    apiVersion: v1
    kind: Service
    metadata:
    	name: loadbalancer
    spec:
    	type: LoadBalancer
    	ports:
    	- port: 80
    		targetPort: 8080
    	selector:
    		app: example
  3. Ingress

    주로 production 환경에서 외부로 노출시키는 방법이다. 왜냐하면 위의 Load Balancer와 달리 Ingress 하나로 여러 서비스들을 노출시킬 수 있기 때문이다. 그만큼 사용하기 복잡하다는 단점이 있다.

    우선 인그레스가 하나의 서비스를 노출시키는 방식부터 살펴보자. 인그레스 요청은 도메인과 uri 경로를 기준으로 서비스를 노출시킨다. 그리고 인그레스는 항상 인그레스 컨트롤러와 같이 배포되어야 한다. 인그레스는 여러 서비스를 노출시킬 때의 규칙을 정의한 것일 뿐, 실제 트래픽을 다루는 것은 인그레스 컨트롤러가 한다.

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    	name: example
    spec:
    	rules:
    	- host: example.com
    		http:
    		paths:
    		- path: /
    			backend:
    				service:
    					name: example-service
    					port:
    						number: 80

    1. 사용자는 example.com 도메인으로 요청을 보낸다.

    2. DNS 서버에서 example.com 을 인그레스 컨트롤러 IP로 변경하여 요청을 보낸다.

    3. 인그레스 컨트롤러에 요청이 갈 때 헤더에 example.com을 담아서 보낸다.

    4. 인그레스 컨트롤러는 받은 요청의 데이터를 기반으로 인그레스 → 서비스 → 엔드포인트를 통해서 실제로 요청을 받아야 하는 파드IP를 얻어낸다.

    5. 얻어낸 파드IP로 인그레스 컨트롤러가 트래픽을 보낸다.

      이번엔 여러 서비스를 노출시키는 경우를 보자 여러 서비스를 노출시킬 때는 다른 도메인 이름이나 uri 경로 기준으로 나눠서 노출시킨다. 아래 그림은 도메인 이름을 기준으로 여러 서비스를 노출 시키는 사례이다.

    uri 경로로 노출시킬 땐 아래와 같이 인그레스를 정의하면 된다.

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
    	name: example
    spec:
    	rules:
    	- host: example.com
    		http:
    		paths:
    		- path: /foo
    			backend:
    				service:
    					name: foo-example-service
    					port:
    						number: 80
    		- path: /bar
    			backend:
    				service:
    					name: bar-example-service
    					port:
    						number: 80

    이 때 단순히 경로가 같을 때 서비스를 나누지 않고 prefix나 pathType등을 설정하여 다양하게 조건을 만들어서 생성할 수 있다.

Reference

[발번역] Kubernetes NodePort vs LoadBalancer vs Ingress?? 언제 무엇을 써야 할까??

0개의 댓글