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

최종 업데이트 날짜: 2020년 1월 29일

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

간략한 설명

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

참고: 인그레스 컨트롤러는 로드 밸런서보다 효율적이고 경제적일 수 있습니다. 또한 트래픽을 다른 마이크로서비스로 전송하기 위해 로드 밸런서를 예약해야 할 수도 있습니다.

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

해결 방법

다음 해결 방식은 nginxinc/kubernetes-ingress 인그레스 컨트롤러를 사용합니다. 공개적으로 사용할 수 있는 다른 인그레스 컨트롤러는 kubernetes/ingress-nginx입니다. 자세한 내용은 nginxinc/kubernetes-ingress 및 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.    기본 서버에 대한 전용 네임스페이스, 서비스 계정 및 TLS 인증서(키 포함)를 생성하려면 다음 명령을 실행합니다.

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

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

4.    NGINX 구성을 사용자 지정하기 위한 ConfigMap을 생성하려면 다음 명령을 실행합니다.

kubectl apply -f common/nginx-config.yaml

참고: 구성의 예는 ConfigMap 및 주석을 참조하십시오.

5.    RBAC(역할 기반 액세스 제어)를 구성하려면 ClusterRole을 생성하고 3단계의 서비스 계정에 ClusterRole을 바인딩합니다.

kubectl apply -f rbac/rbac.yaml

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

6.    인그레스 컨트롤러를 배포하려면 다음 명령을 실행합니다.

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

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

다음과 유사한 출력이 나타납니다.

NAME                            READY   STATUS    RESTARTS   AGE
nginx-ingress-fb4f4b44c-xmq6z   1/1     Running   0          3d7h

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

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

배포 인그레스 컨트롤러의 경우 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.    ConfigMap을 업데이트하려면 다음 명령을 실행하십시오.

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
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

참고: 자세한 내용은 이름 기반 가상 호스팅을 참조하십시오.

6.    구성을 적용하려면 다음 명령을 실행합니다.

kubectl apply -f micro-ingress.yaml

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

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

 Name:             micro-ingress
 Namespace:        default
 Address:          
 Default backend:  default-http-backend:80 (<none>)
 Rules:
  Host                   Path  Backends
  ----                   ----  --------
  hostname.mydomain.com  
                            hostname-svc:80 (192.168.2.45:9376,192.168.3.236:9376)
  apache.mydomain.com    
                            apache-svc:80 (192.168.2.47:80,192.168.3.45:80)

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://aaa25a5010daa11eaa41e121e71bd6ca-113564610.us-east-1.elb.amazonaws.com/

다음과 유사한 출력이 나타납니다.

HTTP/1.1 200 OK
Server: nginx/1.17.5
Content-Type: text/html
Content-Length: 612
Connection: keep-alive

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

curl -I -H "Host: apache.mydomain.com"
http://aaa25a5010daa11eaa41e121e71bd6ca-113564610.us-east-1.elb.amazonaws.com/

다음과 유사한 출력이 나타납니다.

HTTP/1.1 200 OK
Server: nginx/1.17.5
Content-Type: text/html
Content-Length: 45
Connection: keep-alive

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 응답이 반환됩니다. 


이 문서가 도움이 되었습니까?

AWS에서 개선해야 할 부분이 있습니까?


도움이 필요하십니까?