on
[K8s] 서비스(Service)와 인그레스(Ingress)
[K8s] 서비스(Service)와 인그레스(Ingress)
서비스(Service)
서비스는 여러 개의 파드에 접근할 수 있는 IP 하나를 제공한다. 파드가 클러스터 안 어디에 있든 고정 주소를 이용해 접근이 가능하다.
L4 영역에서 통신할 때 사용
파드에 접근할 수 있는 경로 제공
고정된 포인트 / 외부 접근 가능한 포인트를 제공
서비스에는 크게 4가지 종류가 있다
ClusterIP : 기본 서비스 타입이며 클러스터 내부에서만 사용할 수 있다. 클러스터 내부 노드나 파드에서는 클러스터 IP를 이용해서 서비스에 연결된 파드에 접근한다. 클러스터 외부에서는 이용 불가 ❌
NodePort : 서비스 하나에 모든 노드의 지정된 포트를 할당한다. node1:8080, node2:8080처럼 노드에 상관없이 서비스에 지정된 포트 번호만 사용하여 파드에 접근할 수 있다. 노드의 포트를 사용하므로 클러스터 내부뿐만 아니라 외부에서도 접근할 수 있다.
파드가 node1에서만 실행중이더라도 node2:8080으로 접근했을 때, node1에 실행된 파드로 연결한다. 클러스터 외부에서 클러스터 내부 파드로 접근할 때 사용할 수 있는 가장 간단한 방법이다.
LoadBalancer : 클라우드 서비스를 사용할 때 사용가능한 옵션이다. 클라우드에서 제공하는 로드밸런서와 파드를 연결한 후 해당 로드밸런서의 IP를 이용하여 클러스터 외부에서 파드에 접근할 수 있도록 한다. 서비스 상태를 확인하면 EXTERNAL-IP 항목에 로드밸런서 IP를 표시한다.
ExternalName : 서비스를 .sepc.externalName 필드에 설정한 값과 연결한다. 클러스터 내부에서 외부로 접근할 때 주로 이용한다.
클러스터 외부에 접근하면 설정해둔 CNAME 값을 이용해 클러스터 외부에 접근할 수 있다. 설정할 때 selector가 필요 없다.
헤드리스 서비스(Headless Service)
. spec.clusterIP 필드 값을 None으로 설정하면 클러스터 IP가 없는 서비스를 만들 수 있다. 로드밸런싱이 필요 없거나 단일 서비스 IP가 필요 없을 때 사용한다. selector 필드를 설정하면 쿠버네티스 API로 확인할 수 있는 엔드포인트가 만들어진다. 서비스와 연결된 파드를 직접 가리키는 DNS A 레코드도 만들어진다. selector가 없으면 엔드포인트는 만들어지지 않으며, DNS 시스템은 ExternalName 타입의 서비스에서 사용할 CNAME 레코드가 만들어진다.
인그레스(Ingress)
클러스터 외부에서 안에 있는 파드에 접근할 때 사용하는 방법이다. 서비스와의 차이점은 주로 L7 영역의 통신을 담당해서 처리한다.
클러스터 외부에서 안으로 접근하는 요청들을 어떻게 처리할지 정의해둔 규칙 모음
L7 기반 로드밸런싱 제공
SSL 인증서 처리 제공
도메인 기반 가상 호스팅 제공
실제로 동작시키는 것은 인그레스 컨트롤러(Ingress controller)이다.
인그레스는 임의의 포트 또는 프로토콜을 노출시키지 않고, HTTP와 HTTPS 이외의 서비스를 인터넷에 노출하려면 Service.Type=NodePort 또는 Service.Type=LoadBalancer 유형의 서비스를 사용한다.
클라우드 서비스를 이용한다면 별 다른 설정 없이 자체 로드밸런서 서비스와 연동해서 인그레스를 사용할 수 있다. 만약 쿠버네티스 클러스터를 직접 구축해서 사용한다면 인그레스 컨트롤러를 직접 인그레스와 연동해야 한다. 이때 가장 많이 사용하는 도구는 쿠버네티스에서 제공하는 ingress-nginx이다. 그 외에도 HAProxy, Envoy, Kong 등 소프트웨어 프록시를 이용하기도 한다.
인그레스 설정 예시 (v1.18)
# kubernetes v1.18 apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: test-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / # '/'' 경로로 리다이렉트 spec: rules: # 규칙 - host: foo.bar.com # 첫 번째 필드 값 http: paths: # HTTP 요청이 어떤 경로에서 들어오는지 - path: /foos1 pathType: Prefix # 경로의 접두사를 '/' 기준으로 분리한 값과 일치시킴 backend: # foo.bar.com/foos1 으로 들어오는 요청을 s1 서비스의 80포트로 보냄 serviceName: s1 servicePort: 80 - path: /bars2 pathType: Prefix backend: # foo.bar.com/bars2 으로 들어오는 요청을 s2 서비스의 80포트로 보냄 serviceName: s2 servicePort: 80 - host: bar.foo.com http: paths: - backend: # bar.foo.com/ 으로 들어오는 요청을 s2 서비스의 80포트로 보냄 serviceName: s2 servicePort: 80
foo.bar.com 으로 요청이 오면 /foos1 이면 서비스 s1 으로 연결 /bars 이면 s2 로 연결
으로 요청이 오면 bar.fooo.com 으로 요청이 오면 s2 로 연결
으로 요청이 오면 로 연결 이와 같이 인그레스는 클러스터 외부에서 오는 요청을 다양한 방식으로 처리할 수 있다
Service vs Ingress
Service와 Ingress는 포트를 노출하는 기능과 로드밸런싱을 수행한다
Service = L4
Ingress = L7
서비스는 여러 개로 복제된 한 종류의 파드를 로드밸런싱 한다
인그레스는 여러 서비스에 대해서 라우팅의 역할을 담당한다
일반적인 경우 온프레미스 환경 에서는 Service 의 NodePort 타입을 사용하고, 퍼블릭 클라우드 환경 에서는 Service 의 LoadBalancer 타입을 사용하면 대부분 서비스 운영이 가능하다
에서는 의 타입을 사용하고, 에서는 의 타입을 사용하면 대부분 서비스 운영이 가능하다 MSA(Microservice Architecture)로 개발되어 서비스 간의 라우팅이 필요한 구조에서는 Ingress 를 사용한다
References
https://arisu1000.tistory.com/27840?category=787056
https://danawalab.github.io/kubernetes/2020/01/23/kubernetes-service-ingress.html
from http://imjeongwoo.tistory.com/130 by ccl(A) rewrite - 2021-10-08 22:26:09