Kubernetes/06. 쿠버네티스 네트워크

[쿠버네티스] 쿠버네티스 인그레스 (ingress) 소개 및 실습

Jaden Park 2021. 6. 24. 11:26

들어가며:

인그레스(Ingress) 란?

인그레스 생성

 


들어가며:

쿠버네티스에서 서비스를 외부에 노출시키는 방법은 NodePort와 LoadBalancer 서비스 타입 그리고 Ingress(인그레스) 서비스 컨트롤러가 있습니다.

 

NodePort 및 LoadBalancer 서비스는 OSI Layer 4(TCP/UDP)에서 작동하지만,

Ingress 리소스는 OSI Layer 7(HTTP/HTTPS)에서 작동합니다.

 

쿠버네티스에서 외부에 노출시켜야 할 서비스가 많은 경우

NodePort는 각 서비스마다 전용의 포트를 할당해야 하고

LoadBalancer의 경우 외부 로드밸런서가 각 서비스마다 프로비저닝 되어야 합니다.

그러나 Ingress는 HTTP 요청의 주소를 구분해 하나의 인그레스 리소스를 이용해 각 서비스에 라우팅 할 수 있습니다.


인그레스(Ingress)란?

 

k8s의 인그레스 HTTP(S) 기반의 L7 로드밸런싱 기능을 제공하는 컴포넌트 입니다.

Ingress 는 외부에서 쿠버네티스 내부로 들어오는 네트워크 요청을 어떻게 처리할지 결정하며, 쉽게 말해 외부에서 쿠버네티스에 실행중인 Deployment와 Service에 접근하기 위한 관문과 같은 역할을 담당합니다.

 

쿠버네티스 서비스는 기본적으로 L4 레이어로 TCP 단에서 Pod로드밸런싱합니다. 그런데 MSA의 경우 쿠버네티스 서비스 하나가 MSA 서비스로 표현되는 경우가 많고, 서비스가 하나의 URL로 대표되는 경우가 많습니다. 그래서 MSA 서비스 간 라우팅을 하기 위해서는 API게이트웨이를 넣는 경우가 많은데, URL 기반의 라우팅 정도라면 API게이트웨이처럼 무거운 아키텍쳐 컴포넌트가 아닌 L7 로드밸런서 선에서 라우팅이 가능하며, 이때 필요한게 쿠버네티스 Ingress 입니다.

 

Ingress는 외부로부터 들어오는 요청에 대한 로드밸런싱, TLS/SSL 인증서 처리, 도메인 기반 가상 호스팅 제공, 특정 HTTP 경로의 라우팅 등의 규칙등을 정의해 둔 자원입니다.

이런 규칙들을 실제로 동작하게 해주는 것은 Ingress-Controller 입니다.

 

하지만 클라우드 서비스를 사용하게 되면 별다른 설정없이 각 클라우드 서비스에서 자사의 로드밸랜서 서비스들과 연동해서 Ingress를 사용할 수 있게 해주지만, 클라우드를 사용하지 않고 클러스터를 구축해서 사용하는 경우는 Ingress Controller를 직접 Ingress와 연동시켜야 합니다.

 

인그레스 컨트롤러는 쿠키 기반이 세션 어피니티를 가지고 있으며

Nginx HTTP 서버와 리버스 프록시 기능을 통해 제공되며, 인그레스 컨트롤러는 노드의 개수만큼 각 노드에 실행합니다.

 

Session affinity: 동일 클라이언트의 요청을 동일 서버로 라우팅해주는 것

 


 

인그레스 생성

인그레스 API 그룹은 networking.k8s.io 이며 버전은 v1beta1 입니다.

오브젝트 종류는 Ingress로 선언 합니다.

 

현재는 networking.k8s.io API 그룹과 함께 extensions API 그룹도 똑같이 사용할 수 있으나, extensions API 그룹은 더 이상 사용되지 않습니다.

 

베어메탈을 이용해 인그레스를 생성하기 전에 ingress controller 기능을 제공하는 Nginx 를 install 해야합니다.

 

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml

 

 

인그레스 예시 입니다.

$ cat myapp-ing.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: myapp-ing
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: myapp-svc-np
          servicePort: 80

 

.spec.rules.host: URL 호스트

.spec.rules.host.http.paths.path: URL 경로

.spec.rules.host.http.paths.path.backend: 라우팅할 서비스 백엔드

.spec.rules.host.http.paths.path.backend.servivceName: 서비스 리소스 이름

.spec.rules.host.http.paths.path.backend.servicePort: 서비스 포트

 

외부에서 myapp.example.com FQDN 주소를 통해 인그레스 리소스에 접속하면, 인그레스 리소스는 백엔드 서비스인 myapp-svc-np 서비스에 라우팅하며, myapp-svc-np 서비스는 레이블 셀렉터에 매핑된 파드로 라우팅해줍니다.

 

레플리카셋 컨트롤러와 NodePort 서비스를 생성합니다.

 

$ cat myapp-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp-rs
  template:
    metadata:
      labels:
        app: myapp-rs
    spec:
      containers:
      - name: myapp
        image: ghcr.io/c1t1d0s7/go-myweb
        ports:
        - containerPort: 8080
        
  
 $ cat myapp-svc-np.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-np
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 31111
  selector:
    app: myapp-rs

 

 

 

참고: warning 메시지는 v1.22+ 에서는 v1beta1 apiVersion 지원을 안해주는다는 메시지입니다. 현재는 1.19 버전이기 때문에 확인만 하면 됩니다.

 

 

주소 할당에 약간의 시간이 소요됩니다. 인그레스 리소스를 확인해보면 인그레스 리소스 IP 는 쿠버네티스의 클러스터 워커노드의 IP 입니다.

 

 

인그레스 리소스에 myapp.example.com 주소로 접근하면 myapp-svc-np 서비스로 라우팅하게 됩니다.

 

 

그러나 현재 외부 DNS가 없기 때문에 myapp.example.com FQDN의 A 레코드를 반환하지 못합니다.

그러므로 curl 명령의 --resolve 옵션을 사용하여 해당 FQDN의 주소를 IP로 변환하는 옵션을 사용해야 합니다.

 

 

참고사항

curl 명령의 --resolv 옵션 대신 /etc/hosts 파일을 이용할 수도 있습니다.

인그레스 address 와 FQDN 주소를 적어주면 됩니다.