앞선 게시물에서 k8s Pod, Replicaset, Deployment에 대한 기본적인 개념을 배웠다. 그리고 이번에는 가장 중요한? Service에 대한 개념정리를 해보자!!
필자가 k8s에 대해 공부를 하면서, 가장 궁금한 내용은 Pod들끼리의 통신은 되는걸까? Pod를 외부에 노출해야 하는 경우가 반드시 생길텐데 이런 경우는 어떻게 해야될까? 이것에 대한 답이 Service Type이다!!
먼저 Service란?
k8s 환경에서 Pod를 통해 실행되고 있는 Application을 네트워크에 노출하는 가상의 인터페이스이다. 네트워크에 노출한다는것이 내부 클러스터간의 네트워크일수도 있고, 외부 네트워크일수도 있다. 결론적으로는 Application이 다른 외부 Application 또는 사용자/Pod 등의 연결을 도와주는 역할을 한다.
k8s는 서비스 특성상 Pod들이 삭제되고, 새로 생성되고 하는 작업이 빈번하게 일어난다. 만약에 IP를 기준으로 네트워크 통신을 한다면 k8s를 제대로 이용할 수 없다. 이러한 문제를 해결하기 위해 Service 개념이 나왔다.
다시 말하면, Service는 트래픽을 전달하는 역할만 하며, 실제 서비스를 수행하는 역할은 Pod가 한다. Service 객체로 묶여진 Pod를 Endpoint라고 하며, Servie는 이들의 Endpoint를 Label을 통해서 찾아낸다.
Service로 트래픽이 들어오면, 서비스와 같은 Label을 갖는 Pod의 Endpoint를 찾아서 이곳으로 트래픽을 전달한다.
그렇다면 Service Type에는 어떤것이 있을까? Service는 크게 ClusterIP, NodePort, LoadBalancer, ExternalName로 4가지 Type으로 구성된다.
Cluster IP란?
k8s Cloudter 내부에서 사용하는 Service Type이다. Service를 생성할 때 따로 Type 지정을 하지 않으면 기본적으로 생성되는 Type이며, Cluster IP > Pod IP:TargetPort로 트래픽을 전달한다. 하지만 이는 오직 Cluster 내부에서는 접근 가능한 Private IP이다.
Endpoint는 Selector로 지정할 수 있으며, 아래 예시는 Label이 app=myapp, type=frontend인 경우에 대한 예시이다.
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: ClusterIP
ports:
- name: http
protocol: TCP
targetPort: 9376
port: 80
- name: https
protocol: TCP
targetPort: 9377
port: 443
selector:
app: myapp
type: frontend
NodePort란?
외부에서 Node IP에 대한 접속 Port를 지정하는 것이다. 즉, Node IP:NodePort로 요청이 들어올 경우 Pod IP:TargetPort로 트래픽을 전달한다. 설명에서 알 수 있듯이 Pod IP로 전달해야 하므로 이를 전달하기 위한 Cluster IP가 자동 생성된다.
NodePort가 설정되면 Cluster 임의 IP:NodePort로 서비스가 개방되는 구조이며, 이때 Node가 Public IP를 갖는다면 외부에서도 접근이 가능하다.
NodePort는 아래와 같이 생성할 수 있다.
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: NodePort
ports:
- targetPort: 80 # 애플리케이션(파드)을 노출하는 포트
port: 80 # 서비스를 노출하는 포트
nodePort: 30008 # 외부 사용자가 애플리케이션에 접근하기 위한 포트번호(선택)
selector: # 이 서비스가 적용될 파드 정보를 지정
app: myapp
type: frontend
NodePort는 30000 ~ 32767 사이에서만 지정할 수 있으며, 미지정할 경우 임의 Port가 부여된다.
LoadBalancer란?
외부 LoadBalancer를 제공하는 클라우드 환경을 고려하여, 해당 Loadbalancer를 Service로 프로비저닝할 수 있는 Type이다.
NodePort Type의 확장판이며, 마찬가지로 Service를 외부에 노출시키는것이나, Node를 체크하여 트래픽을 전달할 수 있는 장점이 있다.
아래는 LoadBalancer를 생성하는 예시이다.
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: LoadBalancer
ports:
- name : http
targetPort: 80 # 애플리케이션(파드)을 노출하는 포트
port: 80 # 서비스를 노출하는 포트
nodePort: 30008 # 외부 사용자가 애플리케이션에 접근하기 위>한 포트번호(선택)
selector: # 이 서비스가 적용될 파드 정보를 지정
app: myapp
type: frontend
위 코드로 Service를 만들면, 가끔 External IP 부분에 Pending이 발생한다. 이는 k8s에서 LodeBalancer를 만들었으나 클라우드 제공자의 LoadBalancer를 만들지 못하는 경우 발생한다.
정상적이라면, LoadBlancer Type을 만들, k8s에 LoadBalancer Service가 생겨나며 AWS에서도 LoadBalancer가 생성된다.
그리고 AWS LoadBalcer의 도메인이 k8s Service LoadBalancer의 External-IP로 지정된다.
ExternalName란?
이는 외부에서 Pod에 접속하기 위한 목적의 Type이 아니다. 내부 Pod가 외부의 특정 FQDN에 쉽게 접속하기 위한 Type이다.
즉, Cluster 내부에서 Cluster 외부의 특정 Service에 접속하기 위한 DNS CNAME을 설정하는 것이다.
즉, 아래와 같이 네트워크 도구를 가지고 있는 Pod을 생성해서 myapp-extname에 대해서 nslookup을 해보면 google.com을 반환한다. 이는 ExternalName Type으로 google.com에 대한 DNS CNAME을 myapp-extname으로 지정했기 때문이다.
실무에서 이런 내용을 바로바로 체크하고 생성할 수 있도록 하는것이 중요한거 같다!! k8s에 대해서는 아직 모르는게 많고, 공부하면 할수록 복잡하고 나의 무지함이 느껴진다ㅜㅜ
'기술 이모저모 > [K8s] Kubernetes' 카테고리의 다른 글
[k8s] 명령형 접근방법과 선언형 접근방법의 차이 (0) | 2022.10.02 |
---|---|
[k8s] Kubernetes Namespace란? 개념정리 (0) | 2022.10.02 |
[k8s] Pod, Replicaset, Deployment의 관계정리 (0) | 2022.09.18 |
[k8s] kubernetes ReplicaSet/ReplicationController 기본개념 (0) | 2022.08.26 |
[k8s] kubernetes kube-proxy, pod 기본 개념 (0) | 2022.08.26 |