[Kubernetes] Basic Resource - Part 2
Service
Service는 아래의 그림 1에서 확인 할 수 있듯이 Pod를 논리적으로 묶은 것이다. 특히 Service는 Pod의 논리적인 묶음이기 때문에 여러 Node에 걸쳐서 Pod를 묶을 수 있다.
이렇게 논리적으로 묶는 이유는 k8s에서 Pod는 lifecycle (scaling out-in 등등에 의해서)이 존재하기 때문에 항상 Pod가 고정적이지 않다. 더욱이 IP를 내부적으로 공유하는 Pod의 특성상 외부에서는 항상 IP만 확인 할 수 없다. (Pod가 다시 생성되면 IP가 재할당되기 때문에) 그래서 Service라는 리소스*를 통해 Pod를 관리한다.
* 일반적으로 Label Selector를 통해 서비스를 구분한다.
그림 2를 보면 각 Pod가 nginx라는 label name으로 묶인 것을 확인 할 수 있다. 만약 name이 다르다면 해당 Pod는 다른 Service에 속하게 된다. 그럼 매니페스트 파일을 사용하여 Service를 생성하고 알아보자.
apiVersion: apps/v1 kind: Deployment metadata: name: echo-spring labels: app: echo release: spring spec: ... --- apiVersion: apps/v1 kind: Deployment metadata: name: echo-summer labels: app: echo release: summer spec: ... |
먼저 위의 매니페스트 파일은 Service를 보여주기 위해 2개의 Deployment가 포함되어 있는 매니페스트 파일이다. 해당 파일을 실행시켜 보면 아래와 같다.
그림 3을 보면 현재 생성된 각각의 Deployment를 확인 할 수 있다. (위의 매니페이스 파일에서 언급한것 처럼 Deployment를 2개로 정의했고 각각 1개, 2개의 Pod를 생성하게 한다.) 그리고 Labels을 보면 각 Deployment의 release 이름이 다른 것을 확인 할 수 있다. 이를 바탕으로 Service 매니페스트 파일을 만들면 다음과 같다.
apiVersion: v1 kind: Service // Service 리소스 설정 metadata: name: echo spec: selector: // Service에 정의하는 Selector 값 app: echo release: summer ports: - name: http port: 80 |
해당 Service는 Pod를 app: echo와 release: summer로서 구분한다는 정의를 담고있다.
매니페스트 파일을 실행하면 그림 4와 같이 echo 이름은 가진 Service 리소스가 생성된 것을 확인 할 수 있다. 해당 Service를 약간 더 들어가보면 Service 리소스가 정말 Deployment에서 생성한 Pod와 Label selector가 같은 것만 연결되었는지 알 수 있다.
생성된 Service를 확인해보면 각 Service의 앤드포인트가 10.1.0.50과 10.1.0.49를 가지고 있는 것을 알 수 있다. 그리고 각 Pod의 할당된 IP를 보면 Service의 앤드포인트와 같다는 것을 알 수 있다. 물론 k8s cluster 내부에서 임시 컨테이터를 생성하여 Service의 name을 curl로명령*을 보내고 각 Pod에서 로그만 봐도 알 수 있다.
* k8s cluster의 DNS는 Service를 서비스명.네임스페이스명.svc.local로 연결한다.
curl http://echo.default.svc.local - Full Path
curl http://echo.default - svc.locald은 생략 가능 (다른 네임스페이스 접근할 때)
curl http://echo - 가장 많이 사용 (같은 네임스페이스 접근할 때)
이렇듯 IP의 상관 없이 이름으로만 Service를 찾을 수 있는 것을 Service Discovery라고 하는데 k8s Service의 주요 특징 중 하나이다.
ClusterIP
ClusterIP는 위의 그림 4에서도 확인 할 수 있듯이 Service를 만들때 할당받는 IP이다.
해당 IP는 Service에 의존적이기 때문에 Service의 lifecycle과 생사를 같이한다. 즉, Service가 만들어질 때 같이 할당 받고 Service가 내려가면 IP 또한 다른 곳에서 재사용 될 수 있다. (또한 할당된 IP는 Service가 running 하는 동안에는 변경 할 수 없다.)
사실 위의 Service 매니페스트 파일을 보면 따로 적어준 부분은 없는데 Service는 따로 지정해주지 않으면 default type을 ClusterIP로 사용한다.
이와 같이 ClusterIP를 통해서 k8s Cluster의 내부 IP 주소에 Service를 공개 할 수 있다. ClusterIP는 k8s Cluster 내부에서만 사용하는 주소로 Service에 접근 할 때 Service Name으로 접근을 가능하도록 하게 한다. (내부 DNS를 통해 ClusterIP와 Service Name을 매핑)
따라서 ClusterIP를 사용하면 그림 7과 같이 여러 가지 방식으로 사용할 수 있다. (그렇지만 해당 그림에 대한 설명은 이후 포스팅에서 할 것이다.)
NodePort
NodePort는 ClusterIP와는 다르게 외부에서 접근이 가능하다. (IP를 할당받는 것은 ClusterIP와 같다.)
apiVersion: v1 kind: Service metadata: name: echo spec: type: NodePort // NodePort 설정 selector: app: echo release: summer ports: - name: http port: 80 |
그래서 위의 Service 매니페스트 파일을 보면 type: NodePort만 추가된 것을 확인 할 수 있다.
그림 8을 확인해보면 NodePort가 설정되었고 추가적으로 31879 포트가 생성된 것을 확인 할 수 있다. (이제 외부에서 접근이 가능하다.)
LoadBalancer
LoadBalancer는 일반적으로 Cloud Provider(주요 3사 : GCP, AWS, Azure)를 위한 것이다. 즉, Cloud Provider가 제공하는 Load Balancer와 연동하기 위함이다.
apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376 clusterIP: 10.0.171.239 loadBalancerIP: 78.11.24.19 type: LoadBalancer // LoadBalancer 설정 status: loadBalancer: ... |
위의 매니페스트 파일을 보면 알 수 있듯이 type: LoadBalancer가 추가되었다. (나머지 값은 나중에 알아보도록 하자.)
그림 9을 확인해보면 Azure Load Balancer에 type이 LoadBalancer인 각각의 Service가 붙어있는 것을 확인 할 수 있다.
이렇듯 External Load Balancer (Cloud Provider의 Load Balancer)에서 발생하는 트래픽을 바로 Pod에서 받을 수 있다. (물론 해당 트래픽은 Cloud Provider에 의존적이다.)
각각의 개념을 간단하게 표현한 그림 10을 확인해보면 Service의 타입인 ClusterIP, LoadBalancer, NodePort의 차이를 쉽게 알 수 있다.
ExternalName
ExternalName은 Service를 DNS에 매핑하는 것이다.
apiVersion: v1 kind: Service metadata: name: my-service // 참조 할 Service Name namespace: prod spec: type: ExternalName // ExternalName 설정 externalName: my.database.example.com // 매핑 할 ExternalName |
위의 매니페스트 파일처럼 설정을 하면 my.database.example.com을 my-service로도 접근이 가능하다.
Reference
- https://www.ianlewis.org/en/performing-maintenance-pods
- https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/
- https://kubernetes.io/docs/concepts/services-networking/service/