K8S 클러스터 환경에서 동일한 서비스를 제공하는 POD 그룹에 단일 진입점을 만들기 위해 생성하는 리소스이다.
각 서비스에는 서비스가 존재하는 동안 절대로 변경되지 않는 IP주소:PORT 가 존재한다.
클라이언트는 POD에 직접 연결하는 것이 아니라 서비스의 IP:PORT 로 연결을 시도하면 POD로 라우팅된다.
이로써 POD는 서비스에 종속되며, 클러스터 주변을 자유롭게 움직일 수 있다.
POD들은 label selector
에 의해 관리되며 Round Robin 혹은 백분율의 Load Balancing
을 서비스가 수행한다.
가장 기본 타입으로 클러스터 내부의 노드에서 접근 가능하다.
Ingress를 통해 외부에서 내부로 들어오는 GateWay를 만들 것이기 때문에
해당 서비스 타입을 주로 이용한다.
외부에서는 접근이 불가능!
트래픽 -> kube-proxy -> k8s service -> pod
apiVersion: v1
kind: Service
metadata:
name: appjs-service
spec:
type: ClusterIP
ports:
- targetPort: 8080 # 서비스가 포워드할 포트 ( 파드 포트 )
port: 80 # 서비스가 사용할 포트
selector:
app: appjs
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: rs-nginx
spec:
replicas: 3
selector:
matchLabels:
app: appjs
template:
metadata:
labels:
app: appjs
spec:
containers:
- name: appjs-container
image: nginx:1.15
ports:
- containerPort: 8080
( Ingress 없이 )외부 트래픽을 수락하고 이를 서비스로 전달하는 가장 기본적인 방법이다.
특정 포트로 전송된 트래픽이 서비스로 전달될 수 있도록 K8S Worker Node의 특정 포트를 열어준다.
트래픽 -> 노출된 포트 -> K8S service -> pod
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30123
selector:
app: appjs
인터넷에 서비스를 노출시키는 표준 방법이나 노출된 서비스에 고유한 IP주소가 있으며 모든 서비스가 단일 LoadBalancer를 통해 노출돼 비용이 많이 발생한다.
트래픽 -> LoadBalancer -> K8S Servcie -> pod
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: LoadBalancer #LB
ports:
- port: 80
targetPort: 80
nodePort: 30123
selector:
app: appjs
특정 클라이언트에서 생성된 모든 요청을 일정 시간동안 같은 POD로 연결하기를 원할 때 사용할 옵션
apiVersion: v1
kind: Service
metadata:
name: appjs-service
spec:
type: ClusterIP
sessionAffinity: ClientIP #sessionAffinity
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10 ## 유지 시간 기본값 10800
ports:
- targetPort: 8080
port: 80
selector:
name: appjs
K8S의 기본 외부 트래픽 정책이다.
항상 동일한 분배로 서비스를 실행하는 모든 POD로 트래픽을 라우팅하려는 것이 목적인데 동일한 호스트의 POD로 라우팅 할 수 있을 때 다른 호스트의 POD로 라우팅하여 불필요한 라우팅 홉 아웃이 발생한다.
여기서 문제는 홉 아웃으로 트래픽을 받은 POD가 클라이언트의 IP가 아닌 트래픽을 넘긴 Proxy Node IP를 볼 수 있다는 것.
이유는 네트워크 패킷이 다른 노드의 POD로 라우팅되면 SNAT ( Source Network Address Transfer ) 되기 때문이다.
SNAT 는 K8S 네트워킹 모델이 작동하기 위한 기본이므로 이를 중지하는 방향이 아닌 다른 방법으로 해결해야 한다.
K8S의 서비스로 들어온 트래픽은 반드시 로컬에 존재하는 POD들로만 트래픽이 라우팅하게 하여 방지할 수 있다.
하지만 이는 애플리케이션에 대한 트래픽 불균형이 발생할 수 있는데, 항상 서비스 자신의 로컬 NODE에 존재하는 POD에만 트래픽을 보내 트래픽 불균형이 발생하는 것이다.
컨테이너의 liveness와 비슷한 것으로 POD가 준비됐을 때 신호를 보낸다.
POD가 준비돼있지 않다면 서비스에서 EndPoint를 삭제해 트래픽이 가지 않도록 하고, 준비되면 트래픽을 흘려준다.
POD의 yml 파일에 해당 내용을 추가한다.
spec:
containers:
- name: test
image: smlinux/appjs
readinessProbe:
httpGet:
path: /readiness
port: 8080
initialDelaySeconds: 5
periodSeconds: 5