이재홍의 언제나 최신 Kubernetes - Unit 7.4 인그레스와 ELB LoadBalancer 서비스 생성하기

저작권 안내
  • 책 또는 웹사이트의 내용을 복제하여 다른 곳에 게시하는 것을 금지합니다.
  • 책 또는 웹사이트의 내용을 발췌, 요약하여 강의 자료, 발표 자료, 블로그 포스팅 등으로 만드는 것을 금지합니다.

AWS에서 EC2로 Kubernetes 클러스터 구축하기

이재홍 http://www.pyrasis.com

인그레스와 ELB LoadBalancer 서비스 생성하기

드디어 AWS의 ELB(NLB, Network load balancer)와 연동된 서비스를 생성할 수 있게 되었습니다.

인그레스 컨트롤러 설치하기

인그레스를 사용하려면 먼저 인그레스 컨트롤러를 설치해야 합니다. 여기서는 Nginx 인그레스 컨트롤러를 사용하겠습니다.

다음 명령을 실행하여 AWS용 Nginx 인그레스 컨트롤러를 설치합니다.

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

다음 명령을 입력하여 Nginx 인그레스 컨트롤러가 제대로 설치되었는지 확인해봅니다.

$ kubectl -n ingress-nginx get service
NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP                                                                          PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   100.68.245.83   a9d2164f4b43b43749deeb45a44e6458-1692cf8342f016af.elb.ap-northeast-2.amazonaws.com   80:32325/TCP,443:31028/TCP   15m
ingress-nginx-controller-admission   ClusterIP      100.68.74.143   <none>                                                                               443/TCP                      15m

ingress-nginx-controller의 TYPE을 보면 LoadBalancer로 설정된 것을 볼 수 있고, EXTERNAL-IP에는 ELB(NLB)의 도메인이 표시됩니다. 즉, AWS의 로드밸런서를 통해 트래픽을 받을 수 있게 된 것입니다.

디플로이먼트, 서비스 생성하기

다음 내용을 deployment.yaml 파일로 저장합니다.

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-nginx
  template:
    metadata:
      labels:
        app: hello-nginx
    spec:
      containers:
        - name: hello-nginx
          image: nginx:latest
          ports:
            - containerPort: 80

다음 명령을 실행하여 deployment.yaml 파일로 디플로이먼트를 생성합니다.

$ kubectl create -f deployment.yaml
deployment.apps/hello-nginx created

이번에는 서비스를 생성합니다. 다음 내용을 service.yaml 파일로 저장합니다.

service.yaml
apiVersion: v1
kind: Service
metadata:
  name: hello-nginx
spec:
  selector:
    app: hello-nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP

다음 명령을 실행하여 service.yaml 파일로 서비스를 생성합니다.

$ kubectl create -f service.yaml
service/hello-nginx created

디플로이먼트와 서비스는 지금까지 만들었던 것과 같은 형식이므로 따로 설명하지 않겠습니다.

인그레스 만들기

도메인을 구입한 경우

이제 인그레스를 만들 차례입니다. 다음 내용을 ingress.yaml 파일로 저장합니다. 이때 host 부분을 hello.<구입한 도메인>으로 설정해줍니다. 특히 apex 도메인(root 도메인)은 Route 53에 자동으로 레코드가 생성되지 않으므로 주의해야 합니다. 반드시 서브 도메인으로 설정해줍니다.

ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-nginx
spec:
  ingressClassName: nginx
  rules:
    - host: hello.<구입한 도메인>
      http:
        paths:
          - backend:
              service:
                name: hello-nginx
                port:
                  number: 80
            path: /
            pathType: Prefix

저장이 끝났으면 인그레스를 생성합니다.

$ kubectl create -f ingress.yaml

만약 도메인을 바꾸고 싶다면 ingress.yaml에서 도메인을 수정한 뒤 kubectl apply를 해서는 Route 53에 적용이 되지 않습니다. 이때는 인그레스를 삭제 후 다시 생성해야 합니다.

$ kubectl delete -f ingress.yaml
$ kubectl create -f ingress.yaml

webhook 에러가 발생한다면?

다음과 같이 Internal error occurred: failed calling webhook 에러가 발생할 수도 있습니다.

error: failed to create ingress: Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": failed to call webhook: Post "https://ingress-nginx-controller-admission.ingress-nginx.svc:443/networking/v1/ingresses?timeout=10s": context deadline exceeded

이때는 다음 명령을 입력하여 ingress-nginx-admission webhook 설정을 삭제해줍니다. 지금은 이 webhook을 사용하지 않으므로 삭제해도 괜찮습니다.

$ kubectl delete validatingwebhookconfiguration ingress-nginx-admission

삭제되었다면 다시 인그레스를 생성해봅니다.

$ kubectl create -f ingress.yaml

이제 kubectl get ingress 명령으로 인그레스를 출력해보겠습니다.

$ kubectl get ingress
NAME          CLASS   HOSTS             ADDRESS                                                                              PORTS   AGE
hello-nginx   nginx   <구입한 도메인>    a9d2164f4b43b43749deeb45a44e6458-1692cf8342f016af.elb.ap-northeast-2.amazonaws.com   80      26m

HOSTS에 도메인으로 <구입한 도메인>이 설정된 것을 볼 수 있습니다. ADDRESS에는 ELB(NLB)의 도메인이 표시됩니다. 저는 a9d2164f4b43b43749deeb45a44e6458-1692cf8342f016af.elb.ap-northeast-2.amazonaws.com가 나왔지만, 이 도메인은 각자 다르게 나올 것입니다.

웹 브라우저를 열고 http://<구입한 도메인> 접속하면 Welcome to nginx!가 표시될 것입니다.

실습이 끝났으면 다음 명령을 실행하여 클러스터를 삭제합니다.

$ kops delete cluster --name k8s.ap-northeast-2.aws.hello.com --yes

도메인을 구입하지 않은 경우

이제 인그레스를 만들 차례입니다. 다음 내용을 ingress.yaml 파일로 저장합니다.

ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-nginx
spec:
  ingressClassName: nginx
  rules:
    - host: nginx.hello.com
      http:
        paths:
          - backend:
              service:
                name: hello-nginx
                port:
                  number: 80
            path: /
            pathType: Prefix

저장이 끝났으면 인그레스를 생성합니다.

$ kubectl create -f ingress.yaml

webhook 에러가 발생한다면?

다음과 같이 Internal error occurred: failed calling webhook 에러가 발생할 수도 있습니다.

error: failed to create ingress: Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": failed to call webhook: Post "https://ingress-nginx-controller-admission.ingress-nginx.svc:443/networking/v1/ingresses?timeout=10s": context deadline exceeded

이때는 다음 명령을 입력하여 ingress-nginx-admission webhook 설정을 삭제해줍니다. 지금은 이 webhook을 사용하지 않으므로 삭제해도 괜찮습니다.

$ kubectl delete validatingwebhookconfiguration ingress-nginx-admission

삭제되었다면 다시 인그레스를 생성해봅니다.

$ kubectl create -f ingress.yaml

이제 kubectl get ingress 명령으로 인그레스를 출력해보겠습니다.

$ kubectl get ingress
NAME          CLASS   HOSTS             ADDRESS                                                                              PORTS   AGE
hello-nginx   nginx   nginx.hello.com   a9d2164f4b43b43749deeb45a44e6458-1692cf8342f016af.elb.ap-northeast-2.amazonaws.com   80      26m

HOSTS에 도메인으로 nginx.hello.com이 설정된 것을 볼 수 있습니다. ADDRESS에는 ELB(NLB)의 도메인이 표시됩니다. 저는 a9d2164f4b43b43749deeb45a44e6458-1692cf8342f016af.elb.ap-northeast-2.amazonaws.com가 나왔지만, 이 도메인은 각자 다르게 나올 것입니다.

우리는 실제로 hello.com 도메인을 구입하지 않았으므로, 로컬에서 임시로 사용할 수 있도록 설정해야 합니다. 즉, nginx.hello.com 도메인이 ELB의 IP 주소로 연결되도록 설정하는 것입니다. 운영체제별로 설정 파일이 조금 다른데, 각자 운영체제에 맞는 파일을 수정합니다.

먼저 ping 명령으로 ELB(NLB)의 IP 주소를 알아냅니다.

윈도우
ping a9d2164f4b43b43749deeb45a44e6458-1692cf8342f016af.elb.ap-northeast-2.amazonaws.com

Pinging a9d2164f4b43b43749deeb45a44e6458-1692cf8342f016af.elb.ap-northeast-2.amazonaws.com [3.37.156.171] with 32 bytes of data:
리눅스 macOS
$ ping a9d2164f4b43b43749deeb45a44e6458-1692cf8342f016af.elb.ap-northeast-2.amazonaws.com
PING a9d2164f4b43b43749deeb45a44e6458-1692cf8342f016af.elb.ap-northeast-2.amazonaws.com (3.37.156.171) 56(84) bytes of data.

IP 주소가 출력되면 Ctrl + C를 눌러 ping 명령을 종료시킵니다. 저는 IP 주소가 3.37.156.171로 나왔지만, ELB 도메인과 마찬가지로 각자 다르게 나올 것입니다(<ELB의 퍼블릭 IPv4 주소>).

리눅스, macOS는 /etc/hosts 파일을 수정해야 합니다. root 권한이 있어야 하므로 sudo vim으로 수정합니다.

리눅스, macOS
$ sudo vim /etc/hosts

/etc/hosts 파일의 마지막 부분에 다음 내용을 추가한 뒤 저장합니다.

/etc/hosts
<ELB의 퍼블릭 IPv4 주소> nginx.hello.com

윈도우는 C:\Windows\System32\drivers\etc\hosts 파일을 수정해야 합니다. 관리자 권한이 필요하므로, 메모장을 관리자 권한으로 실행한 뒤 파일을 엽니다.

C:\Windows\System32\drivers\etc\hosts 파일의 마지막 부분에 다음 내용을 추가한 뒤 저장합니다.

C:\Windows\System32\drivers\etc\hosts
<ELB의 퍼블릭 IPv4 주소> nginx.hello.com

메모장에서 hosts 파일이 보이지 않는다면?

메모장에서 hosts 파일이 보이지 않는다면, 열기 창에서 열기(O) 버튼 위의 텍스트 문서(*.txt)모든 파일 (*.*)로 바꿔주면 됩니다.

웹 브라우저를 열고 http://nginx.hello.com 접속하면 Welcome to nginx!가 표시될 것입니다.

즉, 지금까지 구축했던 Kubernetes 클러스터를 그림으로 표현하면 다음과 같은 모양이 됩니다.

그림 7-6 Kubernetes 클러스터

실습이 끝났으면 다음 명령을 실행하여 클러스터를 삭제합니다.

$ kops delete cluster --name k8s.ap-northeast-2.aws.hello.com --yes

EC2 비용 문제

AWS에서 EC2, ELB를 사용할 때는 시간당 비용이 청구됩니다. 따라서 실습은 신속히 끝내는 것이 유리하며 실습이 끝나면 반드시 모든 인스턴스와 ELB(NLB)를 삭제(terminate)해야 합니다.

삭제하지 않고 그냥 잊고 있었다가는 요금 폭탄을 맞을 수 있으니 이 부분은 정말 주의해야 합니다.


저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.

Published

2022-10-22