[Kubernetes] EKS 다루기(2) - Service(ClusterIP, NodePort, LoadBalancer)

2021. 11. 22. 08:55Kubernetes/Kubernetes_Service

반응형

안녕하세요, 달콤한달팽이입니다.🐌🙂

 

이번 시간에는 Service와 Ingress에 대한 개념을 알아보고, 

이를 통해 Pod를 외부로 노출시키는 방법에 대하여 알아보겠습니다.


Service란?

Service란, Pod에 실행중인 애플리케이션을 접근할 수 있도록 노출하는 방법입니다.

 

즉, 생성/삭제되는 Pod에 고정 IP를 갖는 Service를 제공하여
exec 명령어로만 애플리케이션 동작 여부를 확인했던 이전과는 달리,IP와 포트로 정상구동을 확인할 수 있게 됩니다.

 

Service는 크게 3가지(Cluster IP, NodePort, LoadBalancer)로 구성되어 있으며,

차례대로 하나씩 실습하며 무슨 특징이 있는지 알아보도록 하겠습니다!


1) Cluster IP

ClusterIP란, Service의 기본 타입으로 Pod가 클러스터 내부에서만 통신할 수 있도록 해주는 방식입니다.

 

yaml 파일의 spec 상에 별도 type을 지정하지 않았을 경우 default로 생성되는 방식이며,

ClusterIP로 들어온 내부 트래픽을 Pod IP:target Port로 전달될 수 있도록 설정합니다.

 

[동작 방식]

 생성: Service 생성 → apiserver → kubelet → kube-proxy → iptables 수정

 동작: Pod의 ClusterIP 접속 → iptables 룰 확인 → Pod와 통신 

 

이제 실습을 위해 Deployment(Pod이어도 무관), ClusterIP를 생성해봅시다!

# clusterip.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-clusterip
spec:
  type: ClusterIP
  selector:
    name: nginx-test
  ports:
    - name: nginx-clusterip-port
      port: 8080
      targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nginx-test
  template:
    metadata:
      labels:
        name: nginx-test
    spec:  
      containers:
        - name: nginx
          image: nginx:latest
          ports:
          - containerPort: 80

 

이제 적용을 한 후, 정상 생성을 확인해봅시다!

  kubectl get svc -o wide

 

ClusterIP 서비스가 정상적으로 동작하는지 확인하기 위해 Pod에 접속한 후, 서비스를 테스트해주세요!

  kubectl exec -it {Pod 이름} -- /bin/bash

  curl {CLUSTER-IP}:{Port}

Pod에 띄운 Nginx가 정상적으로 실햄함으로써, ClusterIP가 정상동작함을 확인하였습니다.

 

ClusterIP 방식은 애플리케이션을 외부로 노출시키지는 못하지만, Pod로의 부하분산을 수행시켜줍니다.

 

이제 다음 실습을 위해 ClusterIP를 지워주세요!

  kubectl delete -f clusterip.yaml

 


2) NodePort

NodePort란, 외부에서 전달받은 트래픽을 노드 IP의 특정 포트로 전달하는 방식입니다.

 

범위 내의 포트(30000 ~ 32767) 하나당 하나의 서비스를 사용합니다.

 

하지만 노드의 IP로 접근하기 때문에 노드가 사라졌을 떄 다른 노드를 통해 접근이 불가능하다는 특징이 있습니다.

 

[동작 방식]

 동작: 외부에서의 Node IP 접속 → iptables 룰 확인 → Pod와 통신

# nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
spec:
  type: NodePort
  selector:
    name: nginx-test
  ports:
    - name: nginx-nodeport-port
      port: 8080
      targetPort: 80
      nodePort: 30008
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      name: nginx-test
  template:
    metadata:
      labels:
        name: nginx-test
    spec:  
      containers:
        - name: nginx
          image: nginx:latest
          ports:
          - containerPort: 80

 

이제 적용을 한 후, 정상 생성을 확인해봅시다!

  kubectl get svc,pods

 

이제 노드그룹의 보안그룹을 수정해주세요!

 

저는 NodePort의 30080으로 들어오는 트래픽에 대한 Service를 생성했으므로,

TCP 프로토콜에 대한 30080 포트를 열어주도록 하겠습니다!

 

이제 NodePort 방식으로 {NodeIP}:{Port}로 접속을 시도하면,

애플리케이션(Nginx)이 정상적으로 노출됨을 확인할 수 있습니다!

 

** 만약 nginx 페이지가 정상적으로 뜨지 않는다면 아래 사항을 참고해보세요!

 1) Deployment, Service가 정상적으로 생성되었는지 확인

 2) 노드그룹의 보안그룹이 열려있는지 확인

 3) 노드그룹이 인터넷 통신이 되는지 확인

 

이제 다음 실습을 위해 NodePort와 Deployment를 지워주세요!

  kubectl delete -f nodeport.yaml


3) LoadBalaner

LoadBalancer란, 클라우드 서비스를 사용할 때 쿠버네티스의 Cloud Provider가 인그레스 컨트롤를 통해 LB와 Pod를 연결한 후 해당 LB의 IP를 이용해 Pod에 접근하는 방식입니다.

 

[동작 방식]

 동작: 외부에서의 Node IP 접속 → iptables 룰 확인 → Pod와 통신

apiVersion: v1
kind: Service
metadata:
  name: nginx-loadbalancer
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-subnets: {subnet-ID-a}, {subnet-ID-c}
spec:
  type: LoadBalancer
  selector:
    app: nginx-loadbalancer
  ports:
    - port: 80
 

 

이제 적용을 한 후, 정상 생성을 확인해봅시다!

  kubectl get svc

이를 AWS 콘솔의 로드 밸런서 탭에서도 확인이 가능합니다.


지금까지 알아본 Service는 하나의 IP로 여러 애플리케이션을 노출시킬 수 없다는 특징이 있습니다.

때문에 애플리케이션 개수만큼 Service의 수도 증가해야하는 단점이 있습니다.

 

다음 글에서는 이를 보완한 Ingress라는 서비스를 사용하여 게임을 외부로 노출시켜 보도록 하겠습니다.

(실무에서 애플리케이션 외부 노출을 위해 가장 많이 사용하는 기능인 만큼 꼭 읽어보셨으면 좋겠습니다.)

 

감사합니다!

반응형