service 란?
service는 k8s의다양한 component 간의 통신을 가능하게 해줍니다. 이는 cluster 내부 component들 끼리의 통신과 외부user와의 통신 모두를 포함합니다.
k8s에서 service를 통해 pod와 external user가 어떻게 통신하는지 살펴보겠습니다.
하나의 노드안에 하나의 pod가 있고 외부의 user가 이 pod와 통신하려면 어떻게 해야 할까요?
가정
1. node의 ip가 존재 192.168.1.2.
2. host user의 ip가 존재 192.168.1.10
3. pod의 ip가 존재 10.244.0.2 (10.244.0.0/24 대역)
4. host user와 pod는 서로 다른 네트워크 대역이기 때문에 통신 불가능
방법1 : ssh를 통한 접속
1. ssh로 node에 접속
2. curl을 통해 pod에 접속, 만약 GUI 환경이라면 웹페이지를 볼 수 있음
3. 그런데 당연히 이런 방식을 실제로 써먹진 않음
4. 바로 pod에 접속하고 싶고 이를 가능하게 해주는 middleware가 필요함
5. 이게 바로 service(NodePort) 의 역할
service 종류
k8s의 service는 기능에 따라 3가지로 분류됩니다.
- NodePort : 내부접속을 가능케 하는 port 생성
- CluserIP : 서로다른 service 끼리 통신할 수 있도록 하는 가상IP 생성
- Loadbalancer : 외부로부터의 부하 분산 가능
위의 그림 처럼 외부에서 내부에 접속하는 경우는 NodePort 라는 service를 사용해야 합니다.
말 그대로 port 를 통해 pod 통신하기 때문에 NodePort입니다.
그렇다면 NodePort는 어떻게 작동하는걸까
NodePort가 외부와 내부 pod를 연결시키기위해 Node와 Service, Pod에 각각 port를 생성합니다.
- nodePort(Node): 30008, 30,000 ~32,767 의 범위내에서 정해짐
- port: 80 (port) service는 자체 ip를 보유 10.106.1.12(service의 cluster ip)
- pod: 80 (target port)
user는 node의 ip와 port 번호로 service에 접속합니다.
그리고 service는 label을 통해 pod에 접속합니다.
NodePort service 생성하는법
yaml 파일 작성
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: NodePort
ports:
- targetPort: 80
port: 80
nodePort: 30008
selector:
app: myapp
type: front-end
#port만 필수 항목이고 nodePort와 targetPort는 자동지정된다.
#targetPort 앞의 - 표시는 array의 시작을 의미한다.
selector 필드에 연동시킬 pod의 label 정보를 적어주면 됩니다.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-controller
image: nginx
kubectl create -f service-definition.yml 실행
kubectl get service 로 확인
curl 192.168.1.1:3260 접속 확인
궁금한점
1. 그렇다면 동일한 label을 가진 pod가 여러개일때 service는 어떤 pod와 연결될까?
- 처음 service가 만들어질때 selector에 적혀진 labels에 해당하는 pod들을 모두 찾는다.
- service는 자동으로 찾은 모든 pod를 선택한다.
- 부하는 선택된 pod중 하나에 랜덤하게 들어간다
2. pod가 여러개의 node에 분산되어 있을때는 어떻게 될까?
- service component는 자동으로 여러개의 노드에 분산되어있는 pod를 label을 통해 모두 찾는다.
이경우 각 node별 ip로도 접속이 가능해진다.
ex)
192.168.1.2:30008
192.168.1.3:30008
192.168.1.4:30008
즉 일치하는 label을 가진 pod가 속한 node의 ip로 접속이 가능하다