컨테이너를 외부로 공개하기 위한 쿠버네티스 리소스

2021-09-05

.

Data_Engineering_TIL(20210904)

[학습자료]

“클라우드 네이티브를 위한 쿠버네티스 실전 프로젝트” 책을 읽고 정리한 내용입니다.

** 동양북스, 아이자와 고지&사토 가즈히코 지음, 박상욱 옮김

참고자료 URL : https://github.com/dybooksIT/k8s-aws-book

“EKS 클러스터에서 컨테이너를 동작시키기 위한 리소스 기본개념” 에 이어서 공부한 내용을 정리한 내용임

** URL : https://minman2115.github.io/DE_TIL263

[학습내용]

  • 지난 실습에서 구현했던 쿠버네티스에서 클러스터 리소스 관점에서의 아키텍처

1

쿠버네티스에서 동작하는 컨테이너를 클러스터 외부에서 접속할 수 있는 방법에 대해 알아보자.

  • 파드를 서비스로 묶기

쿠버네티스에서 컨테이너를 동작시킬 경우 최소단위로 파드가 생성된다. 그러나 파드가 여러개 있을 경우, 호출하는 쪽에서 어떤 파드가 실제로 존재하며 정상적으로 동작하는지 파악하여 호출하는 것은 사실상 어렵다.

쿠버네티스에서는 service라는 리소스를 이용하여 파드 여러개를 묶어 하나의 DNS 이름으로 접속할 수 있다. 또한 service 리소스를 이용하면 해당 service를 구성하는 파드 중 정상적으로 동작하는 파드에만 요청을 할당할 수 있다.

  • 지난 실습에서의 예시

https://minman2115.github.io/DE_TIL253/ 를 참고할 것

# STEP 4) API 어플리케이션 외부 공개
# 어플리케이션을 쿠버네티스 클러스터에 배포는 했지만 아직 외부 클러스터에서는 API 호출이 불가능하다.
# 쿠버네티스에는 배포된 파드를 외부에 공개하기 위해 '서비스'라는 리소스를 제공한다.
# 서비스는 공개범위에 따라 몇가지 타입이 정의되어 있는데 여기서는 로드밸런서라는 서비스 타입을 사용할 것이다.
# 배포한 파드 앞에 로드밸런서를 위치시키고, 인터넷에서 요청을 받으면 파드에서 동작중인 어플리케이션을 호출할 수 있다.
# API 어플리케이션에 서비스 리소스를 생성하기 위해 아래와 같은 매니패스트 파일을 apply 해보자.
[ec2-user@ip-10-0-1-104 eks-env]$ kubectl apply -f 23_service_backend-app_k8s.yaml
service/backend-app-service created

[ec2-user@ip-10-0-1-104 eks-env]$ cat 23_service_backend-app_k8s.yaml
apiVersion: v1
kind: Service
metadata:
  name: backend-app-service
spec:
  type: LoadBalancer
  selector:
    app: backend-app
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080

# 로드밸런서 서비스가 추가된것을 알수 있다.
[ec2-user@ip-10-0-1-104 eks-env]$ kubectl get all
NAME                              READY   STATUS    RESTARTS   AGE
pod/backend-app-7fb899969-h2vd9   1/1     Running   0          104s
pod/backend-app-7fb899969-hbcjn   1/1     Running   0          104s

NAME                          TYPE           CLUSTER-IP       EXTERNAL-IP                                                                   PORT(S)          AGE
service/backend-app-service   LoadBalancer   10.100.228.215   xxxxxxxxx.ap-northeast-2.elb.amazonaws.com   8080:31747/TCP   3s

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/backend-app   2/2     2            2           105s

NAME                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/backend-app-7fb899969   2         2         2       105s

# curl로 elb의 주소와 통신해보면 아래와 같이 api 서비스가 잘 제공되고 있음을 확인할 수 있다.
[ec2-user@ip-10-0-1-104 eks-env]$ curl -s http://xxxxxxxxx.ap-northeast-2.elb.amazonaws.com:8080/health
{"status":"OK"}

[ec2-user@ip-10-10-1-73 ~]$ kubectl describe service backend-app-service
Name:                     backend-app-service
Namespace:                eks-work
Labels:                   <none>
Annotations:              <none>
Selector:                 app=backend-app
Type:                     LoadBalancer
IP Families:              <none>
IP:                       10.100.189.242
IPs:                      <none>
LoadBalancer Ingress:     xxxxxxxxxxxxxxxxxxxxxxxx-yyyyyyyyyyyyyyyyy.ap-northeast-2.elb.amazonaws.com
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  32395/TCP                            # 노드포트로 32395포트가 할당되어 있음
Endpoints:                192.168.1.46:8080,192.168.2.202:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

23_service_backend-app_k8s.yaml 상세한 설명은 아래와 같다.

apiVersion: v1 # 여기서 정의한 서비스 리소스가 따르는 버전
kind: Service  # 매니패스트가 서비스 리소스를 정의
metadata:
  name: backend-app-service # 서비스 리소스 이름으로 이 이름이 DNS 이름으로 등록되어 클러스터 내부에서 참조할 수 있게 됨
spec:
  type: LoadBalancer 
  selector:
    app: backend-app # 서비스가 대상으로 하는 파드를 선택하기 위한 셀렉터 정의. 여기서는 app에서 backend-app이라는 파드를 정의
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080

위에서 정의한 서비스가 실제로 실행이 되면 AWS에서는 아래와 같이 구현이된다.

1

CLB를 AWS 관리 콘솔에서 생성할 경우 ping 대상은 기본값으로 HTTP이지만 여기서는 TCP로 되어있다. HTTP의 경우 정상 응답을 반환하는 경로 /index.html 등을 설정해야 한다. 하지만 TCP의 경우에는 이 포트에 응답이 있을때 OK를 반환하도록 설정했다.

포트번호 32395는 NodePort 타입의 서비스가 할당된 것이다. 여기서 생성된 서비스 타입은 LoadBalancer이지만 NodePort 타입이 할당되는 이유는 로드밸런서가 노드포트를 각 인스턴스(노드)의 접속 경로로 설정하기 때문이다.

2

  • 컨테이너를 외부로 공개하는 다른 방법

위에 내용과 같이 Load Balancer 타입의 서비스를 만들면 EKS 클러스터의 컨테이너를 외부로 공개하여 인터넷을 통해 접속 할 수 있다. 그러나 이 방법에는 다음과 같은 문제점이 있다.

1) 서비스 단위로 ELB가 생성되기 떄문에 효율성이 좋지 않다. ELB를 여러개 만들면 그만큼 비용도 많이 나오기 때문이다.

2) HTTP/HTTPS 로드밸런서로 더 많은 기능이 있는 ALB를 사용할 수 없다.

위와 같이 로드밸런서 타입의 서비스를 사용하는 방법 이외에 ingress를 사용하는 방법이 있다.

ingress는 쿠버네티스 클러스터로 접근하는 입구를 만들기 위한 리소스라고 할 수 있다. 동작환경에 적합한 ingress controller를 같이 사용하면 쿠버네티스 클러스터에 접근할 공통 입구를 만들고 어플리케이션 여러개를 클러스터 외부에 공개할 수 있다. EKS에서는 ingress controller로 AWS ALB ingress controller가 제공된다. 이름 그대로 ingress controller를 사용하면 ALB를 사용하는 것이다.