Pod 에게 트래픽 분산을 담당하는 기본 오브젝트 - Service

Created
Mar 13, 2022
Created by
Tags
Kubernetes
Property
 

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.externalTrafficPolicyLocal 으로 설정해서 특정 노드에 들어온 트래픽은 그 노드에 있는 파드에서 처리하도록 한다. 대신 노드에 모든 파드가 종료됐을 경우 트래픽 처리가 불가함.
 
notion image
 
컨트롤 플레인 담당하는 서버에서 노드의 호스트 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.
 
 
 
참고자료