Service
ClusterIP
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
selector:
matchLabels:
app: counter
tier: db
template:
metadata:
labels:
app: counter
tier: db
spec:
containers:
- name: redis
image: redis
ports:
- containerPort: 6379
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
ports:
- port: 6379
protocol: TCP
selector:
app: counter
tier: db
- Pod의 경우 쉽게 사라지고 생성됨 → 직접 통신을 권장하지 않는다.
- 별도의 고정된 IP를 가진 서비스를 만들어 Pod에 접근해야 한다.
- 클러스터 내부의 Pod이 다른 Pod에 접근하기 위해 사용(내부에서 사용하는 것이 목적)
Service(ClusterIP)
는selector
에 기술된 label(app=counter, tier=db
)을 가진 Pod의 6379 port를 바라보게 된다.
spec.ports.port
: 서비스가 생성할 port
spec.ports.targetPort
: 서비스가 바라볼 Pod의 port(서비스의 port와 동일한 경우 생략)
spec.selector
: 서비스가 접근할 Pod의 label 조건
- 내부적으로 도메인을 등록한다.
- 같은 클러스터에 생성된 Pod이라면 redis라는 도메인 이름으로 redis Pod에 접근할 수 있다.
Service 생성 흐름
Endpoint Controller
: Service를 감시하다가 새로운 Service가 등장하면 Service의 label을 보고 Endpoint를 생성한다.
Kube-Proxy
: 각 노드에 설치되어 있다. 새로운 Endpoint가 생성되면 iptable에 설정하여 Endpoint의 IP로 접근하면 안의 Pod에 접근할 수 있도록 한다.
CoreDNS
: 새로운 Service 추가되면 Service의 이름으로 Domain Name을 추가한다.
- (참고)
endpoint
: Service가 트래픽을 전달하고자 하는 Pod의 집합
NodePort 만들기
apiVersion: v1
kind: Service
metadata:
name: counter-np
spec:
type: NodePort
ports:
- port: 3000
protocol: TCP
nodePort: 31000
selector:
app: counter
tier: app
type
: 해당 내용을 따로 명시하지 않으면 ClusterIp가 생성됨
- 위 yaml파일의 내용을 고려해볼 때 NodePort는
app=counter, tier=app
라는 label을 가진 Pod의 3000번 port에 접속하게 된다.
spec.ports.nodePort
: 노드에 오픈할 Port(지정 안하면 랜덤으로 30000-32767 중에 하나로 연결됨)
LoadBalancer
- ex) 1번 노드(접속 설정), 2번 노드
- 1번 노드가 죽게되면 누군가가 2번 노드로 접속할 수 있게 바꿔줘야 한다.
- 그 누군가가 LoadBalancer이다.
- NodePort가 살아 있는지 확인하고 죽으면 살아 있는 Node로 요청을 전송한다.
- Node는 생성도 되고 사라지기도 하기 때문에 LoadBalancer를 사용하는게 좋다.
- minikube에서는 LoadBalancer를 실제로 사용할 수 없으므로 metallb를 통해 LoadBalancer를 사용해야 한다.
- LoadBalancer는 하나의 서비스 밖에 바라보지 못한다.
- 만약 서비스가 늘어난다면 늘어난 서비스 마다 LoadBalancer를 추가해주어야 한다.
- 이러한 이유 때문에 ingress를 사용한다.
참고