티스토리 뷰

infra/kubernetes

[쿠버네티스] Service란?

Redirect 2024. 4. 12. 10:00
728x90

1. 서비스란?

- 파드를 통해 사용자에게 서비스를 제공하다가 장애가 발생하면 가용성을 보장할 수 없기 때문에 Service를 통해 가용성을 보장한다.
- Service를 통해 파드의 로드밸런싱이 가능하며, 만약 파드가 정상적인 구동이 불가능할 경우에는 해당 파드가 Service의 Endpoint에서 제외된다.
- 문제가 된 파드는 deployment에 의해 다른 IP, Name으로 다시 구동되고 Service의 Endpoint에 자동으로 추가된다.
- 따라서 파드가 외부와 통신할 수 있도록 클러스터 내부에서 고정적인 IP를 갖는 역할을 하고 있다.


- Service를 정의할 때는 spec.ports 아래에 연결하고자 하는 항목 별로 각각 2개씩의 포트가 지정되어야한다.
  1) targetPort : 파드의 애플리케이션 쪽에서 열려있는 포트를 의미한다.

     - Service로 들어온 요청은 해당 파드의 <클러스터 내부 IP>:<targetPort>로 넘어간다.

     - targetPort는 해당 파드의 conatinerPort와 동일하다.
  2) port : Service 쪽에서 해당 파드를 향해 열려있는 포트를 의미한다.

 


2. 서비스 타입

1) ClusterIP

- spec에 type이 별도로 지정되지 않았으면 ClusterIP로 고정된다.
- 서비스를 클러스터 내부 IP에 노출해서 ClusterIP로 들어온 클러스터 내부 트래픽을 해당 파드의 <파드 IP>:<targetPort>로 넘겨주도록 동작한다.
- 클러스터 내부에서만 서비스에 접근할 수 있다.

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app.kubernetes.io/name: proxy
spec:
  containers:
  - name: nginx
    image: nginx:stable
    ports:
      - conatinerPort: 80
        name: 9355
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app.kubernetes.io/name: proxy
  ports:
  - name: name-of-service-port
    protocol: TCP
    port: 80                        # 서비스를 노출하는 포트
    targetPort: 9355                # 애플리케이션(파드)를 노출하는 포트



위에서는 selector를 사용해서 여러 pod로 트래픽을 분배하게 된다.
따라서 이를 통해 한 노드 안에 여러 파드 또는 여러 노드에 걸쳐있는 여러 파드에 동일한 서비스를 적용할 수 있다.

위 상황에서는 다음과 같이 동작한다.
1. Service인 클러스터IP:80 으로 요청을 보낸다.
2. Service가 selector를 참고하여 label이 app.kubernetes.io/name: proxy 인 파드들을 찾아낸다.
3. 찾아낸 파드의 파드IP:9355 으로 요청을 보낸다.


2) NodePort

- 고정포트로 각 노드의 IP에 서비스를 노출한다.
- 따라서 외부에서 노드 IP의 특정 포트(<NodeIP>:<NodePort>) 로 들어오는 요청을 감지하여 해당 포트와 연결된 파드로 트래픽을 연결한다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - conatinerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-service-nodeport
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - port: 80            # 서비스를 노출하는 포트
      targetPort: 80      # 애플리케이션(파드)을 노출하는 포트
      nodePort: 30007     # 외부 사용자가 애플리케이션에 접근하기 위한 포트번호(선택)

- nodePort는 정해진 포트 범위에서 할당한다. (기본값: 30000~32767)


위 상황에서는 다음과 같이 동작한다.
1. 노드IP:30007 로 요청이 들어온다.
2. 요청은 각 노드의 Service를 호출하는 클러스터IP:80 으로 전달된다.
3. Service의 selector를 보고 label이 app: nginx인 파드들을 해당 노드 안에서 찾는다.
4. 해당 파드들의 80포트로 요청이 전달된다.

여기서 만약 Service의 selector에 해당하는 label을 가진 파드들이 여러 노드에 걸쳐 존재한다면, 해당 노드들에도 Service가 자동 생성되면서 해당 노드에서 nodePort를 통한 파드들의 접근이 가능하다.


예) 192.168.1.2 노드와 192.168.1.3 노드에 Service의 selector에 label을 가진 파드들이 존재한다면, 192.168.1.2:<nodePort>와 192.168.1.3:<nodePort>를 통해서 해당 label을 가진 파드들에 접근이 가능해진다.

 


3) LoadBalancer

- 클라우드 공급자(AWS, GCP, Azure 등)의 로드밸런서를 사용하여 서비스를 외부에 노출시킨다.
- 클러스터 외부 IP를 가지고 있기 때문에, 클러스터 외부에서 접속이 가능하다.
- 외부 로드밸런서가 라우팅되는 NodePort와 ClusterIP가 자동으로 생성된다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx2-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      conatiners:
      - name: nginx
        image: nginx
        ports:
        - conatinerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx2-service
spec:
  type: LoadBalancer
  selector:
    app: nginx
  clusterIP: 10.0.171.56  # 클러스터 IP
  ports:
    - protocol: TCP
      port: 8088          # 서비스를 노출하는 포트
      targetPort: 80      # 애플리케이션(파드)를 노출하는 포트
status:
  loadBalancer:				    # 프로비저닝된 로드 밸런서 정보
    ingress:
    - ip: 192.0.2.127

- nodePort는 정해진 포트 범위에서 할당한다. (기본값: 30000~32767)


위 상황에서는 다음과 같이 동작한다.
1. 로드 밸런서 IP인 192.0.2.127 으로 요청이 들어온다.
2. 요청은 Service를 호출하는 클러스터IP인 10.0.171.56:8088 으로 전달된다.
3. Service의 selector를 보고 label이 app: nginx인 파드들을 해당 노드 안에서 찾는다.
4. 해당 파드들의 80포트로 요청이 전달된다.


4) ExternalName

- Service에서 selector 대신 DNS Name을 사용할 때 사용된다.
- 주소에 대한 CNAME을 리턴하여 서비스를 externalName 필드에 매핑한다.

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com
728x90
300x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크