eks nlb route by port with nginx-ingress

2022. 4. 7. 17:31Dev/EKS

728x90
반응형

상황:

eks에서 application마다 service type을 LoadBalancer로 설정해서 app 개수만큼의 nlb를 사용중입니다. 

하나의 nlb에서 port로 routing해서 deployment로 배포된 여러 app을 사용하고 싶습니다.

 

진행:

nlb(network load balancer) 자체로 port routing이 가능한 지는 모르겠습니다.

검색 중에

https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services/

 

Exposing TCP and UDP services - NGINX Ingress Controller

Exposing TCP and UDP services Ingress does not support TCP or UDP services. For this reason this Ingress controller uses the flags --tcp-services-configmap and --udp-services-configmap to point to an existing config map where the key is the external port t

kubernetes.github.io

이 페이지를 발견하고 nginx ingress controller를 사용해서 구현에 성공했습니다.

 

과정:

가이드 문서가 한 페이지라서 쉽게 될것처럼 써있는데 저는 헤메다가 stackoverflow의 도움을 받았습니다.

https://stackoverflow.com/questions/66367867/how-to-expose-port-22-via-nginx-ingress-controller

 

How to expose port 22 via NGINX Ingress Controller?

I have a Kubernetes Cluster with a NGINX Ingress Controller. In the cluster I have deployed a Gitea POD. The Web UI and the HTTPS access is exposed via an Ingress object like this one: --- kind: Se...

stackoverflow.com

---

nginx ingress controller가 없다면 아래와 같이 yaml 파일을 받아주시고

이미 설치되어 있다면 kubectl edit과 apply를 통해 진행해주세요.

https://kubernetes.github.io/ingress-nginx/deploy/#aws

 

Installation Guide - NGINX Ingress Controller

Installation Guide There are multiple ways to install the NGINX ingress controller: with Helm, using the project repository chart; with kubectl apply, using YAML manifests; with specific addons (e.g. for minikube or MicroK8s). On most Kubernetes clusters,

kubernetes.github.io

다시 공식문서 install guide의 aws 부분을 보면

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.3/deploy/static/provider/aws/deploy.yaml

이렇게 kubectl apply 하라고 나와 있지만 바로 적용하지 않고

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.3/deploy/static/provider/aws/deploy.yaml

일단 다운로드 받습니다.

사전 작업으로

sample app을 배포합니다.

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    targetPort: 80
    name: http
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
        version: v1
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

The next example shows how to expose the service nginx running in the namespace default in the port 80 using the port 9000.

그리고 

Exposing TCP and UDP services

가이드 문서를 보면서 수정을 하겠습니다.

ingress는 tcp를 지원하지 않으니 flag를 추가하라고 합니다.

kind: Deployment 를 찾습니다.

spec.template.spec.containers에 args에

--tcp-services-configmap=$(POD_NAMESPACE)/tcp-services

flag를 추가해줍니다. 여기서 tcp-services는 생성할 configmap의 이름입니다.

$(POD_NAMESPACE)는 ingress-nginx로 아래 env에서 확인할 수 있습니다.

 

공식 문서의 configmap 예제를 배포한 앱에 맞게 수정합니다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: tcp-services
  namespace: ingress-nginx
data:
  9000: "default/nginx:80"

이 코드를 deploy.yaml에 추가하거나 tcp-config.yaml로 만들어줍니다.

 

다음은 Service입니다.

문서를 보면 Service에 port를 노출하라고 합니다.

아래와 같이 svc/ingress-nginx-controller 에 spec.ports에 포트를 추가해줍니다.

  - name: proxied-tcp-9000
    port: 9000
    protocol: TCP
    targetPort: 9000

그리고

deploy.yaml 파일을 apply 해줍니다.

kubectl apply -f deploy.yaml

configmap을 따로 만들었다면 역시 apply 합니다.

이런 리소스들이 만들어지면서 ingress-nginx-controller가 설치됩니다.

명령어를 치면 nlb의 dns 주소가 나오고 9000포트가 보입니다.

(30373은 노드포트로 자동 할당됩니다.)

kubectl get svc -n ingress-nginx

NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP                                                         PORT(S)                                     AGE
ingress-nginx-controller             LoadBalancer   172.20.69.138   ad4xxxxxxxxxxxxxxx-eb16fxxxxxxxx.elb.ap-northeast-2.amazonaws.com   80:32313/TCP,443:30506/TCP,9000:30373/TCP   132m
ingress-nginx-controller-admission   ClusterIP      172.20.59.43    <none>                                                              443/TCP                                     132m

생성 된 로드밸런서는 aws console -> ec2 -> 로드밸런싱 -> 로드밸런서에서도 확인할 수 있습니다.

3분정도 프로비저닝 하는 시간이 소요됩니다.

로드 밸런서가 활성 상태로 변하고

주소창에 ad4xxxxxxxxxxxxxxx-eb16fxxxxxxxx.elb.ap-northeast-2.amazonaws.com:9000을 입력하면

nginx 화면을 볼 수 있습니다.

이와 같은 방식으로 cm/tcp-services 에 룰을 추가하고 svc/ingress-nginx-controller 에 새로운 포트를 추가하면, 여러 deployment에 있는 application을 하나의 nlb와 ingress-nginx를 통해서 routing 할 수 있습니다.

tcp service를 서로 다른 namespace로 보내는 데 사용할 수도 있습니다.

 

ALB(application load balancer)에서 port routing은 아래 페이지를 참고하세요.

https://stackoverflow.com/questions/65969301/eks-alb-ingress-route-by-port

 

EKS ALB ingress route by port

We have a requirement to make an application available via port. For example http://example.com:8180 and http://example.com:8181 should resolve to the application. The ports are opened with the lis...

stackoverflow.com

 

자세한 원리가 궁금하시다면 nginx의 Proxy Protocol 문서를 참고하세요.

https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/