Amazon EKS 클러스터의 여러 Kubernetes 서비스에 대한 외부 액세스를 제공하려면 어떻게 해야 하나요?

최종 업데이트 날짜: 2021년 3월 30일

Amazon Elastic Kubernetes Service(Amazon EKS) 클러스터에서 여러 Kubernetes 서비스에 대한 외부 액세스를 제공하려고 합니다.

간략한 설명

Kubernetes용 NGINX 인그레스 컨트롤러를 사용하여 Amazon EKS 클러스터의 여러 Kubernetes 서비스에 대한 외부 액세스를 제공할 수 있습니다.

참고: NGINX 인그레스 컨트롤러는 로드 밸런서보다 효율적이고 경제적일 수 있습니다. 또한 트래픽을 다른 마이크로서비스로 전송하기 위해 로드 밸런서를 예약해야 할 수도 있습니다. NGINX 인그레스 컨트롤러는 주로 NGINX에 의해 유지 관리됩니다. NGINX 인그레스 컨트롤러와 관련된 문제를 확인하려면 GitHub의 문제 목록을 참조하세요.

중요: Kubernetes 웹 사이트의 인그레스 컨트롤러는 Kubernetes 웹 사이트의 인그레스와 다릅니다. 인그레스는 클러스터 외부에서 클러스터 내 서비스로 HTTP 및 HTTPS 경로를 노출하는 Kubernetes 리소스입니다. 인그레스 컨트롤러는 인그레스를 이행합니다(일반적으로 로드 밸런서 사용). 인그레스 컨트롤러 없이는 인그레스를 사용할 수 없습니다.

해결 방법

다음 해결 방법은 NGINX GitHub 웹 사이트의 nginxinc/kubernetes-ingress 인그레스 컨트롤러를 사용합니다. 공개적으로 사용할 수 있는 다른 인그레스 컨트롤러로는 Kubernetes GitHub 사이트의 kubernetes/ingress-nginx가 있습니다. 자세한 내용은 NGINX 웹 사이트의 Differences Between nginxinc/kubernetes-ingress and kubernetes/ingress-nginx Ingress Controllers를 참조하세요.

Kubernetes용 NGINX 인그레스 컨트롤러 배포

1.    Kubernetes용 NGINX 인그레스 컨트롤러 다운로드:

git clone https://github.com/nginxinc/kubernetes-ingress.git

2.    인그레스 컨트롤러 배포를 위한 디렉터리 선택:

cd kubernetes-ingress/deployments/

참고: 다음 단계의 모든 명령은 배포 디렉터리에서 실행됩니다.

3.    엣지 릴리스가 아닌 NGINX 인그레스 컨트롤러의 안정적인 릴리스를 사용하고 있는지 확인합니다(2021년 3월 기준 실험).

git checkout v1.10.1

참고: NGINX 인그레스 컨트롤러 릴리스에 대한 자세한 내용은 GitHub의 NGINX 인그레스 컨트롤러 릴리스를 참조하세요.

4.    기본 서버에 대한 전용 네임스페이스, 서비스 계정 및 TLS 인증서(키 포함)를 생성합니다.

kubectl apply -f common/ns-and-sa.yaml
kubectl apply -f common/default-server-secret.yaml

참고: 기본 서버는 인그레스 규칙이 정의되지 않은 도메인에 대한 모든 요청에 대해 404 상태 코드가 포함된 "찾을 수 없음" 페이지를 반환합니다. 테스트를 위해 생성된 자체 서명된 인증서와 키를 사용할 수 있습니다. 프로덕션 환경에 자체 인증서와 키를 사용하는 것이 가장 좋습니다.

5.    NGINX 구성을 사용자 지정하기 위한 ConfigMap을 생성합니다.

kubectl apply -f common/nginx-config.yaml

참고: 구성의 예는 NGINX GitHub 사이트의 ConfigMap 및 주석을 참조하세요.

6.    RBAC(역할 기반 액세스 제어)를 구성하고 ClusterRole을 생성한 다음 3단계의 서비스 계정에 ClusterRole을 바인딩합니다. 예를 들어 다음과 같습니다.

kubectl apply -f rbac/rbac.yaml

참고: ClusterRole은 Amazon EKS 클러스터와 상호 작용할 수 있는 인그레스 컨트롤러 권한을 부여합니다.

7.    Kubernetes 클러스터 버전이 1.18 이상인 경우 NGINX 인그레스 클래스를 생성합니다.

kubectl apply -f common/ingress-class.yaml

8.    인그레스 컨트롤러 배포:

kubectl apply -f deployment/nginx-ingress.yaml
kubectl get pods --namespace=nginx-ingress

참고: 배포 또는 DaemonSet 옵션을 사용하여 인그레스 컨트롤러를 배포할 수 있습니다. 배포 옵션을 사용하면 인그레스 컨트롤러 복제본 수를 동적으로 변경할 수 있습니다. DaemonSet 옵션을 사용하면 모든 노드 또는 노드 하위 집합에 인그레스 컨트롤러를 배포할 수 있습니다. 앞의 7단계에서는 배포 옵션을 사용합니다.

출력 예:

NAME                            READY   STATUS    RESTARTS   AGE
nginx-ingress-fb4f4b44c-xmq6z   1/1     Running   0          12s

이제 인그레스 컨트롤러가 인그레스 객체의 요청을 수락할 수 있습니다.

인그레스 컨트롤러에 액세스하여 애플리케이션 실행

배포 인그레스 컨트롤러의 경우 NodePort 또는 LoadBalancer 유형의 서비스 객체를 사용할 수 있습니다. 다음 단계에서는 LoadBalancer 유형을 사용합니다.

1.    구성을 적용합니다.

kubectl apply -f service/loadbalancer-aws-elb.yaml

kubectl get svc --namespace=nginx-ingress

출력 예:

NAME          TYPE         EXTERNAL-IP                                      PORT(S)
nginx-ingress LoadBalancer aaa71bxxxxx-11xxxxx10.us-east-1.elb.amazonaws.com 80:32462/TCP,443:32226/TCP

참고: Amazon EKS는 클라이언트 정보(IP 주소 및 포트)를 전달할 수 있도록 활성화된 PROXY 프로토콜을 사용하여 TCP 모드에서 Classic Load Balancer를 할당합니다. 이 프록시 정보를 인그레스 컨트롤러에 전달해야 합니다.

2.    프록시 정보를 인그레스 컨트롤러에 전달할 수 있도록 NGINX가 PROXY 프로토콜을 사용하도록 구성하고 1단계의 nginx-config.yaml 파일에 다음 키를 추가합니다. 예를 들어 다음과 같습니다.

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-config
  namespace: nginx-ingress
data:
  proxy-protocol: "True"
  real-ip-header: "proxy_protocol"
  set-real-ip-from: "0.0.0.0/0"

참고: 프록시 정보는 앞서 생성한 ConfigMap을 통해 인그레스 컨트롤러로 전달됩니다.

3.    구성 맵을 업데이트합니다.

kubectl apply -f common/nginx-config.yaml

4.    배포 또는 마이크로서비스(예: hostname-appapache-app)를 설정합니다. 다음 예제를 참조하십시오.

참고: 이 단계에서는 2개의 마이크로서비스가 실행 중이라고 가정합니다(데모 목적). 마이크로서비스는 Kubernetes를 기본 유형으로 사용하여 내부적으로 노출됩니다.

hostname-app에 대한 hostname-app-svc.yaml 파일의 예:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hostname-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hostname-app
  template:
    metadata:
      labels:
        app: hostname-app
    spec:
      containers:
      - name: hostname-app
        image: k8s.gcr.io/serve_hostname:1.1

---
apiVersion: v1
kind: Service
metadata:
  name: hostname-svc
spec:
  ports:
  - port: 80
    targetPort: 9376
    protocol: TCP
  selector:
    app: hostname-app

apache-app에 대한 apache-app-svc.yaml 파일의 예:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apache-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: apache-app
  template:
    metadata:
      labels:
        app: apache-app
    spec:
      containers:
      - name: apache-app
        image: httpd:latest
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: apache-svc
  labels:
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: apache-app

구성을 적용합니다.

kubectl apply -f hostname-app-svc.yaml
kubectl apply -f apache-app-svc.yaml

5.    인그레스 컨트롤러에서 제공하는 단일 로드 밸런서를 사용하여 서비스와 인터페이스하도록 인그레스를 구현합니다. 다음 micro-ingress.yaml 예제를 참조하세요.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: micro-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: hostname.mydomain.com
      http:
        paths:
          - backend:
              serviceName: hostname-svc
              servicePort: 80
    - host: apache.mydomain.com
      http:
        paths:
          - backend:
              serviceName: apache-svc
              servicePort: 80

참고: 자세한 내용은 Kubernetes 웹 사이트의 이름 기반의 가상 호스팅을 참조하세요.

6.    구성을 적용합니다.

kubectl apply -f micro-ingress.yaml

참고: 이 인그레스 리소스는 hostname.mydomain.com에 대한 항목을 hostname-svc로 리디렉션하고 apache.mydomain.com에 대한 항목을 apache-svc로 리디렉션하는 규칙을 정의합니다. 규칙과 일치하지 않는 요청은 404 "찾을 수 없음" 오류 메시지를 반환합니다.

인그레스를 설명하면 다음과 비슷한 메시지가 표시됩니다.

kubectl describe ingress micro-ingress                       

Name:             micro-ingress
Namespace:        default
Address:
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host                   Path  Backends
  ----                   ----  --------
  hostname.mydomain.com
                            hostname-svc:80 (192.168.47.163:9376,192.168.70.76:9376)
  apache.mydomain.com
                            apache-svc:80 (192.168.37.44:80,192.168.84.218:80)
Annotations:             kubernetes.io/ingress.class: nginx
Events:
  Type    Reason          Age   From                      Message
  ----    ------          ----  ----                      -------
  Normal  AddedOrUpdated  23s   nginx-ingress-controller  Configuration for default/micro-ingress was added or updated

NGINX 인그레스 컨트롤러 테스트

1.    명령줄에서 이전에 검색한 로드 밸런서의 DNS URL에 액세스합니다.

curl -I http://aaa71bxxxxx-11xxxxx10.us-east-1.elb.amazonaws.com/

참고: 로드 밸런서 엔드포인트는 이전 인그레스 컨트롤러 액세스 및 애플리케이션 실행 섹션에서 가져온 것입니다.

출력 예:

HTTP/1.1 404 Not Found
Server: nginx/1.17.5
Date: Mon, 25 Nov 2019 20:50:58 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive

참고: 기본 서버는 인그레스 규칙이 정의되지 않은 도메인의 모든 요청에 대해 404 상태 코드가 포함된 "찾을 수 없음" 페이지를 반환합니다. 정의된 규칙에 따라 인그레스 컨트롤러는 요청이 구성과 일치하지 않는 한 지정된 백엔드 서비스로 트래픽을 전환하지 않습니다. 호스트 필드가 인그레스 객체에 대해 구성되어 있기 때문에 요청의 Host(호스트) 헤더에 동일한 호스트 이름을 제공해야 합니다.

2.    요청에 Host(호스트) 헤더를 추가합니다.

이 요청은 첫 번째로 구성된 도메인을 기반으로 한 요청입니다.

curl -I -H "Host: hostname.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-1.elb.amazonaws.com/

출력 예:

HTTP/1.1 200 OK
Server: nginx/1.19.8
Date: Fri, 26 Mar 2021 15:49:43 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 29
Connection: keep-alive

이는 두 번째로 구성된 도메인을 기반으로 한 요청입니다.

curl -I -H "Host: apache.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-1.elb.amazonaws.com/

출력 예:

HTTP/1.1 200 OK
Server: nginx/1.19.8
Date: Fri, 26 Mar 2021 15:50:27 GMT
Content-Type: text/html
Content-Length: 45
Connection: keep-alive
Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT
ETag: "2d-432a5e4a73a80"
Accept-Ranges: bytes

Host 헤더를 추가한 후 인그레스 컨트롤러가 인그레스로 정의된 구성과 일치하는 백엔드 구성 서비스로 트래픽을 리디렉션할 수 있습니다.

동일한 도메인 이름을 유지하면서 액세스한 경로를 기반으로 트래픽을 전환하려면 인그레스를 사용하여 경로 기반 라우팅을 추가해야 합니다. 예를 들면 다음과 같습니다.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: path-ingress
annotations:
  nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: hostname.mydomain.com
  http:
        paths:
        - path: /login
          backend:
                serviceName: service1
                servicePort: 4200
        - path: /cart
          backend:
                serviceName: service2
                servicePort: 8080

앞의 예제에서는 요청의 호스트 헤더가 hostname.mydomain.com인 경우 200 응답만 반환됩니다. 요청은 /login 또는 /cart 경로에서 액세스합니다. 다른 모든 요청의 경우 404 응답이 반환됩니다.


이 문서가 도움이 되었나요?


결제 또는 기술 지원이 필요하세요?