본문 바로가기
[DevOps]/Kubernetes

kubernetes - Service 객체에 대해 알아보고 외부에 파드를 노출시켜보기

by 팡펑퐁 2023. 7. 14.
728x90

📌 Service 객체

  • 클러스터의 파드를 다른 파드(pod)에 노출시키는 역할을 한다.
  • 아예 클러스터 외부에 파드를 노출시키기 위해서도 필요하다.
  • 파드를 그룹화하고 공유 주소나 ip를 제공한다.

 

💡 Service 객체가 없다면?

  • 서비스 객체는 파드를 외부 네트워크에 노출시키고 외부와의 통신을 관리하는 역할을 한다.
  • 파드는 고유한 IP 주소를 가지고 있지만, 이 IP 주소는 클러스터 내부에서만 유효하며 외부에서 접근할 수 없다.
  • 또한, 파드는 지속적이지 않다. 언제든지 사라질 수 있다.
    • 기본적으로 일회성의 목적이 크기 때문이다. 만약 기존 파드가 사라지고 새로운 파드가 생겨난다면 파드에 접근할 수 있는 IP 주소 역시 달라지게 된다.
  • 서비스 객체가 없다면 쿠버네티스 내부의 파드는 외부와 직접적으로 통신할 수는 있지만 굉장히 번거롭고 어려울 것이다.
    • 파드에 직접 외부 IP를 할당하여 접근 가능하게 할 수 있다. 이를 통해 외부에서 해당 IP로 직접 접근할 수 있지만, 파드의 IP가 변경되면 외부에서 다시 설정해야 한다.(매우 번거롭다.)
    • 반대로 서비스 객체를 사용하면 파드에 접근하기 위해 외부 IP 주소나 도메인을 알 필요 없이 서비스의 IP 주소와 포트를 사용하여 통신할 수 있다.

 

  • 테스트를 위해 minikube를 사용했다.
  • 자세한 건 알 필요 없다. 서비스 객체를 이해하는 것에만 집중하자.
    • minikube start --driver=docker로 minikube를 실행한 후에
    • minikube dashboard라는 명령어를 입력하면 minikube의 대시보드가 웹브라우저에 나타난다.
  • 파드에는 이미 디폴트로 설정된 내부 ip 주소가 있다.
    • 사진 속 10.244.0.9
  • 이 내부 주소에는 두 가지 문제점이 있다.
    • 첫 번째는 클러스터 외부에서 파드에 접근할 수 없다는 점과
    • 두 번째는 파드가 교체될때마다 변경된다는 점이다.
  • 특히 파드는 스케일링 등으로 자주 바뀌게 된다.
  • 유동적인 ip 주소는 통신하는데 적합하지 않다.
  • 이때 서비스 객체를 사용하면 여러 파드를 해당 service로 이동시키고 변경할 수 없는 고정 ip 주소를 할당할 수 있다.
  • 이 ip주소는 클러스터 내부뿐만 아니라 외부에서도 접근할 수 있도록 설정 가능하다.

 

📌 서비스 객체 yaml 파일 예시와 타입 설명

ClusterIP

  • CKubernetes 클러스터 내에 있는 파드 간에 서로 접근할 수 있도록 하는 방법이다.
  • 디폴트값이기 때문에 서비스 타입을 명시하지 않으면 기본적으로 ClusterIP로 서비스가 만들어진다.
  • 서비스를 생성하면 Kubernetes는 클러스터 내부에서만 유효한 IP 주소를 할당하고, 해당 IP 주소로 서비스에 접근할 수 있다.
    • 외부에서는 해당 IP 주소로 직접 접근할 수 없으며 클러스터 내부의 파드들만 해당 IP 주소를 사용하여 서비스에 접근할 수 있습니다. 즉, ClusterIP는 주로 내부 서비스 간 통신에 사용된다.

NordPort

  • NodePort는 외부에서 노드의 특정 포트에 접근할 수 있도록 하는 방법이다.
  • 클러스터 내부에는 파드 간의 통신을 위한 ClusterIP도 자동으로 생성된다
  • NodePort는 주로 개발 및 테스트 환경에서 사용되며 보안을 위해서는 LoadBalancer와 함께 사용하는 것이 권장된다.

📖 예시

targetPort 

  • pod에 들어오는 요청을 포워딩하는 포트이다.

port

  • 서비스 객체의 포트이다.

nordPort

  • 30000 - 32767까지의 포트를 할당할 수 있다.
  • selector를 통해 위의 서비스 객체와 연결할 파드를 지정할 수 있다.
  • 위의 예시에서는 labels로 지정된 myapp, type: frontend에 포함되는 파드와 연결될 것이다.

 

🤔 좀 더 확실한 이해를 위해 Deployment와 함께 살펴보자.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  labels:
    app: my-app 
    # 해당 리소스가 'my-app'이라는 어플리케이션에 속함을 나타냄. 이렇게 하면 사용자는 app=my-app 레이블이 있는 모든 리소스를 한번에 조회하거나 관리할 수 있음
spec:
  template:
    metadata:
      name: my-pod
      labels:
        app: my-app
    spec:
      containers:
        - name: my-db
          image: (이미지 주소)
          ports:
            - containerPort: 3306
          imagePullPolicy: "Always"
        - name: my-springboot
          image: (이미지 주소)
          ports:
            - containerPort: 8080
          imagePullPolicy: "Always"
  replicas: 1
  selector:
    matchLabels:
      app: my-app

--- # 이 구분선으로 한 yaml 파일에 다중 객체를 설정할 수 있다.

apiVersion: v1
kind: Service
metadata:
  name: my-pod-service
spec:
  selector:
    app: my-app
  ports:
    - nodePort: 30008
      port: 80 # 달라도 상관없다는걸 보여주기위해 일부러 다르게함.
      targetPort: 8080
  type: NodePort

 

  • 위의 예시에서는 30008(nordPort) -> 80(service) -> 8080(pod) -> containerPort(8080) -> spring boot serverPort(8080, tomcat 기본 포트로 application.yaml로 따로 설정 가능) 순서를 통해 외부에서 스프링 부트 서버에 접속할 수 있다.
    • 외부 -> [node port -> port(service) -> targetPort] -> containerPort -> springBoot Server Port로 연결된다.
    • []는 매핑되었으므로 서로 포트가 달라도 되나, targetPort, containerPort, springboot Server Port 세 개는 서로 같아야 한다.

 

LoadBalancer

  • 클라우드 제공업체의 로드 밸런서를 사용하여 서비스에 접근할 수 있도록 하는 방법이다.
  • 서비스를 생성하면 Kubernetes는 클라우드 제공업체의 로드 밸런서를 자동으로 프로비저닝 하고 해당 로드 밸런서의 IP 주소로 외부에서 서비스에 접근할 수 있도록 한다.
  • LoadBalancer는 주로 프로덕션 환경에서 사용되며 클라우드 제공업체의 로드 밸런서를 활용하여 트래픽을 분산시킨다.

 

kubectl expose 명령어를 사용하여 service 만들어보기

  • kubectl create 명령어는 서비스 객체를 생성하는 데 초점이 맞추어져 있다.
  • expose 명령어는 기존에 존재하는 파드, deployment 레플리카셋 등을 서비스로 노출하는 데 사용한다.
    • 이미 만들어진 파드를 외부에 노출시키기에 더 편리하다.
  • kubectl expose를 사용하면 service를 생성하여 deployment가 생성한 파드를 외부에 노출할 수 있다.

 

kubectl expose deployment first-app --type=LoadBalancer --port=8080
kubectl get services
minikube service first-app

  • kubectl expose deployment first-app (1) / --type=LoadBalancer --port=8080 (2) 명령어를 해석해 보면
    • (1) 노출할 deployment 이름을 쿠버네티스에게 알리고
    • (2) 노출하려는 포트와 만들고자 하는 service 또는 expose 유형을 지정한다.
  • minikube service first-app은 테스트용이기 때문에 EXTERNAL-IP가 <pending>으로 유지된다.
  • 사진과 같이 first-app 서비스 터널을 시작하고 접속 URL을 알려준다.

  • 미니쿠브를 통해 성공적으로 service 객체를 이용하여 외부에서 파드까지 도달한 것을 확인할 수 있다.

 

 

클라우드 프로바이더 이용 시

  • 클라우드 프로바이더를 이용하면 LoadBalancer로 외부 고정 ip를 할당받아 실제로 웹을 통한 접속이 가능하다.

 

 

 

참고

Udemy - Docker & Kubernetes : 실전 가이드

 

728x90