Service 의 핵심 기능
- 여러 개의 파드에 쉽게 접근할 수 있도록 고유한 도메인 이름을 부여한다.
- 여러 개의 파드를 대상으로 요청을 분산시키는 로드밸런서 역할을 한다.
- 클라우드 플랫폼의 로드밸런서 또는 클러스터 노드의 포트번호를 통해 파드를 외부에 노출시킨다.
Service 의 종류
ClusterIP
클러스터 외부로 파드를 노출하지 않는다.
클러스터 내부(노드 또는 파드)에서만 파드들에 접근할 때 사용한다. (컨트롤 플레인 담당하는 서버에서도 clusterIP로 접근 불가)
NodePort
파드에 접근할 때 쓰는 포트번호를 클러스터 내에 있는 모든 노드에 개방한다.
클러스터 외부에서 파드에 접근할 수 있다.
LoadBalancer
클라우드 플랫폼에서 제공하는 로드밸런서를 동적으로 파드에 연결한다.
NodePort 와 마찬가지로 클러스터 외부에서 파드에 접근할 수 있다.
클라우드 플랫폼 환경에서 주로 사용한다.
로드밸런서에게 External IP 를 할당하는 플러그인이 별도로 필요하다.
ClusterIP
서비스 오브젝트를 따로 정의하지 않아도 Deployment 를 생성하면 kubernetes
라는 이름의 서비스가 자동으로 만들어지고 클러스터 IP가 할당된다. 이 서비스는 파드 내부에서 쿠버네티스 API 에 접근하는 데 필요한 서비스다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-webserver
spec:
replicas: 3
selector:
matchLabels: # matchLabels 에 있는 라벨이 붙은 파드들을 리플리카셋으로 묶음.
app: nginx
template:
metadata:
# 같은 네임스페이스에 중복되는 파드 이름은 불가하므로 이 이름은 무시된다.
# 대신 <deployment 이름>-<해시값> 으로 각 파드 이름이 만들어짐.
name: pod-webserver
labels:
app: nginx
spec:
containers:
- name: webserver
image: nginx:latest
ports:
- containerPort: 80
ubuntu@ip-10-220-12-225:~/k8s-practice$ ku apply -f deployment/deployment-echo-hostname.yaml
deployment.apps/deployment-echo-hostname created
ubuntu@ip-10-220-12-225:~/k8s-practice$ ku get deploy -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment-echo-hostname 0/3 3 0 5s echo-hostname alicek106/rr-test:echo-hostname app=webserver
ubuntu@ip-10-220-12-225:~/k8s-practice$ ku get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-echo-hostname-8d556f78-876fl 0/1 ContainerCreating 0 12s <none> ip-10-220-6-77 <none> <none>
deployment-echo-hostname-8d556f78-8mqmx 0/1 ContainerCreating 0 12s <none> ip-10-220-6-77 <none> <none>
deployment-echo-hostname-8d556f78-pj5lx 0/1 ContainerCreating 0 12s <none> ip-10-220-6-77 <none> <none>
ubuntu@ip-10-220-12-225:~/k8s-practice$ ku get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 12d
service-clusterip-nginx
를 정의하고 클러스터에 생성한다.
클러스터 IP 10.101.177.94
에 해당하는 서비스가 생성되었다.
apiVersion: v1
kind: Service
metadata:
name: service-clusterip-nginx
spec:
type: ClusterIP
selector:
# app=nginx 라벨을 갖는 파드들을 서비스 대상으로 간주함.
app: nginx
ports:
- name: web-port
port: 8080
targetPort: 80
ubuntu@ip-10-220-12-225:~/k8s-practice$ ku get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
service-clusterip-nginx ClusterIP 10.101.177.94 <none> 8080/TCP 81s
ubuntu@ip-10-220-12-225:~/k8s-practice$ ku describe services service-clusterip-nginx
Name: service-clusterip-nginx
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=nginx
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.101.177.94
IPs: 10.101.177.94
Port: web-port 8080/TCP
TargetPort: 80/TCP
Endpoints: 11.244.1.47:80,11.244.1.48:80,11.244.1.49:80
Session Affinity: None
Events: <none>
워커 노드에 접속해서 10.101.177.94:8080
에 요청을 날려본다.
ubuntu@ip-10-220-6-77:~$ curl 10.101.177.94:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
...
</body>
</html>
NodePort
NodePort
타입의 서비스는 기본적으로 클러스터 IP도 제공한다.- 클러스터 외부에 노출되어있는 노드의 IP와
spec.ports.nodePort
에 지정된 포트번호로 접근할 경우app=nginx
라벨을 가지고 있는 파드에 트래픽이 전달된다.
apiVersion: v1
kind: Service
metadata:
name: service-nodeport-nginx
spec:
type: NodePort
selector:
# app=nginx 라벨을 갖는 파드들을 서비스 대상으로 간주함.
app: nginx
ports:
- name: web-port
# targetPort: 파드 내부에서 열린 포트번호. 외부에 노출하는 대상.
targetPort: 80
# port: 클러스터 내부에서 clusterIP를 통해 파드에 접근할 때 쓰는 포트번호.
port: 8080
# nodePort: 클러스터 외부에서 노드 IP를 통해 파드에 접근할 때 쓰는 포트번호. (미설정 할 경우 30000 ~ 32767 사이에서 랜덤으로 지정됨.)
nodePort: 30000
특이한 점
클러스터 외부에서 Node1
의 IP를 가지고 접근했다고 하더라도 Service 의 로드밸런싱 기능에 의해 Node2
에 있는 파드에 트래픽이 전달될 수 있다.
→ 하나의 노드에서 다른 노들로 요청이 이동하는 데 불필요한 홉(hop)이 발생한다.
→ 노드 간에 리다이렉션이 생기면 트래픽의 출발지 주소가 바뀌는 SNAT(Source Network Address Translation)이 발생하여 클라이언트의 IP주소가 유실된다. 자세한 내용은 여기 참고.
→ metadata.externalTrafficPolicy
를 Local
으로 설정해서 특정 노드에 들어온 트래픽은 그 노드에 있는 파드에서 처리하도록 한다. 대신 노드에 모든 파드가 종료됐을 경우 트래픽 처리가 불가함.
컨트롤 플레인 담당하는 서버에서 노드의 호스트 IP:30000
으로 요청을 날리면 응답이 오는 것을 확인할 수 있다.
ubuntu@ip-10-220-12-225:~/k8s-practice/service$ ku get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-10-220-12-225 Ready control-plane,master 19d v1.23.4 10.220.12.225 <none> Ubuntu 18.04.6 LTS 5.4.0-1060-aws docker://20.10.7
ip-10-220-6-77 Ready <none> 19d v1.23.4 10.220.6.77 <none> Ubuntu 18.04.6 LTS 5.4.0-1060-aws docker://20.10.7
ubuntu@ip-10-220-12-225:~/k8s-practice/service$ curl 10.220.6.77:30000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
LoadBalancer
추후에 Ingress 와 같이 다룬다. TBD.
참고자료