EC2 Cluster K8S 구성

반영환·2024년 4월 29일
1

k8s

목록 보기
10/14
post-thumbnail

EC2 Cluster K8S 구성

AWS Admin 권한을 얻을 수 없는 상황에서 EKS에 대한 충분한 iam role을 부여받을 수 없는 상황 아래, 프로젝트를 진행함에 있어서 Managed K8S 를 사용할 수 없었고 이에 Centos 3대의 EC2로 K8S Cluster를 구성하였다.

문제점 - 서비스 노출

기존에 사용하던 코드가 EKS 환경에 맞추어져있어서 Ingress와 Ingress controller를 사용해 클러스터의 단일 진입점을 로드밸런서를 통해 만들었다.

기존에는 자동으로 ELB 프로비저닝이 이루어졌고 외부 서비스 노출이 어렵지 않았다.

하지만 단순 온프레미스 EC2를 사용해 클러스터를 구성하다보니 Ingress에 외부 IP가 Attatch가 되지 않았고 NodePort로 꺼내도 접속이 되지 않는 문제가 발생했다.

접근 방법 1 - MetalLB

MetalLB는 쿠버네티스에서 로컬 네트워크에서 서비스에 접근할 수 있도록 하기 위한 간단하고 효과적인 로드밸런서 솔루션이라고 한다. 주로 온-프레미스 환경에서 매우 유용하며, 쿠버네티스 클러스터 내의 서비스에 외부 IP 주소를 할당하는 역할을 한다.

로컬 네트워크에서 외부 진입점을 만든다는 부분에서 Metallb를 도입해보기로 결정했다.

Metallb with Nginx Ingress Controller

Install MetallB

$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.9/config/manifests/metallb-native.yaml

Verify MetallB Installation

$ kubectl -n metallb-system get pods
$ kubectl api-resources| grep metallb

Create IP Pool

$ kubectl -n metallb-system apply -f pool-1.yml

Create L2Advertisement

$ kubectl -n metallb-system apply -f l2advertisement.yml

Deploy Test Application

$ kubectl -n default apply -f web-app-deployment.yml

Verify MetallB assigned an IP address

$ kubectl -n default get pods
$ kubectl -n default get services

Install NGINX Ingress Controller with Helm

$ helm pull oci://gher.io/nginxinc/charts/nginx-ingress --untar --version 0.17.1
$ cd nginx-ingress
$ kubectl apply -f crds
$ helm install nginx-ingress oci://ghcr.io/nginxinc/charts/nginx-ingress --version 0.17.1 

Verify NGINX Ingress Installation

$ kubectl -n nginx-ingress get pods
$ kubectl -n nginx-ingress get services

Create an Ingress for the Test Applications

$ kubectl -n default apply -f web-app-ingress.yml
$ kubectl -n default get ingress

문제점


일단 공식적으로 지원하지 않는다고 밝혔다. 로컬 네트워크에서 외부에 접근 가능한 것은 순수 baremetal의 경우 공유기 포트포워딩을 통한 외부 서비스 노출인 경우 가능하다고 한다.

추가로 공인 IP를 받더라도 지원하지 않기 때문에 Cloud Provider 환경에서는 사용이 불가능하다.

접근방법 2 - Loadbalancer 직접 연결

AWS 프로비저닝이 자동으로 되지 않는다는 것을 확인하고 이를 수동으로 NLB를 만들어 붙여보고자 했다.

서비스를 Nodeport로 노출시키고 Load balancer에 대상 그룹을 IP와 포트로 잡아서 분할하려고 했다.

하지만 HealthCheck조차 되지 않았고 Load balancer를 통하지 않은 직접 API 호출 또한 응답이 없었다.

최종 해결 방법 - Imbeded Nginx 와 LoadBalancer

이전에 단순히 Node만을 설치해서 서버를 열었을 때 EC2에서 접근이 되지 않아 Nginx를 설치해 접근이 가능했던 기억이 났다.

현재는 Express.ts와 Spring Boot를 사용하기에 nginx가 필요 없지만 K8S 환경에서는 웹서빙을 해주는 객체가 필요한가라는 생각에 Nginx를 머신에 직접 설치해 conf 파일을 수정해주었다.

Nginx conf

server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            proxy_pass http://localhost:0000; 
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

        location /A {
            proxy_pass http://localhost:0000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

      
        location /B {
            proxy_pass http://localhost:0000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }

특정 서비스에 해당 URL로 요청이 들어오면 URL 전체를 포트에 해당하는 서비스로 프록시 패스해준다.

Load Balancer

ALB를 통해 http 계층 로드밸런서를 만들어주었고 EC2 인스턴스에 연결해주었다.

중요한 점은 Worker Node가 아닌 Control Plane에 연결해주었다는 것이다.

Worker Node에 트래픽을 넣을 때 Service K8S 리소스를 찾지 못해 404 Error가 뜨는 경우가 1/3 확률로 있었다. 즉, control Plane에 연결을 해주어야 100% 매칭됐고 나의 생각에 kuber-proxy의 설정 문제가 아닌가 했지만 현재 Control plane과 load balancer 를 연결해 서비스를 외부에 노출해서 사용하고 있다.

profile
최고의 오늘을 꿈꾸는 개발자

2개의 댓글

comment-user-thumbnail
2024년 11월 13일

안녕하세요 영환님! 저도 k8s 공부하는 중에,
eks 안쓰고 하는법 찾다가 궁금한 점 생겨서 질문드립니다!
nginx.conf를 이런식으로
proxy_pass를 localhost:포트번호로 하신건가요?
이렇게 설정해도 다른 워커노드의 파드로 프록시가 되는건가요??
그리고 서비스 열때 type: NodePort로 하신걸까요 아니면 type: LoadBalancer로 하신걸까요?
이렇게 해결하신분이 처음이라 생소해서 여쭤봅니다!
server {
listen 80;
server_name sample.domain.com;

location / {
    proxy_pass http://localhost:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
}

location /api {
    proxy_pass http://localhost:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
}

}

1개의 답글