본문 바로가기
Containers/Kubernetes

5.1. Cluster 내부 서비스

by shinebee* 2020. 8. 3.
  • pod는 클러스터 외부의 요청이나 클러스터 내부의 다른 파드의 요청에 응답해야한다.

  • pod가 다른 pod에서 제공하는 애플리케이션을 사용하기 위해서는 다른 pod를 찾을 수 있어야 한다.

  • 정적 IP를 할당할수 없다.  ->  서비스를 통해서 통신한다.

    • 서비스는 IP를 가지고 있고 이름으로도 통신이 가능하다.

  • pod --------> service --------> pod

    • service에서 replicaset이나 replicationcontroller로 연결되는것이 아니라 pod에 연결된다.

  • service는 pod들과 연결이 되는데 서비스와 파드가 연결되면 Endpoint가 만들어진다.

  • label을 기준으로 통신한다.

 

 

1. 서비스 소개

  • 서비스는 쿠버네티스 시스템에서 같은 애플리케이션을 실행하고 있는 컨트롤러의 파드 그룹에 단일 네트워크 진입점을 제공하는 리소스이다.
  • 서비스에 부여된 IP는 해당 서비스가 종료될 때까지 변경되지 않는다.
  • 서비스에 부여된 IP = pod에 접근할 유일한 주소
  • 클라이언트는 서비스가 제공하는 고정 IP 및 포트를 통해 pod에 접근하게 된다.

 

  • kubernetes service

  • default namespace에 처음부터 항상 존재하던 서비스.
  • 이 서비스는 쿠버네티스 아키텍처에서 살펴본 마스터의 API 서버(Kube-apiserver)로 접근할 수 있는 서비스이다.

 

 

2. 서비스 생성법

  • 서비스 생성에는 두가지 방법이 있다.
    1. kubectl expose 명령을 이용하는 방법
    2. YAML 파일로 리소스를 생성하는 방법

 

 1) 명령을 이용하는 방법

kubectl expose <CONTROLLER_TYPE> <CONTROLLER_NAME> [--type=<SVC_TYPE>] --name <SVC_NAME>

 

 2) YAML 파일을 이용하는 방법

# myapp-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
spec:
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp-rs
  • type을 지정하지 않으면 clusterIP가 default
  • service.spec.ports.port  ->  클라이언트가 접근할 서비스의 노출 포트
  • 해당 포트로 접근하면 서비스는 service.spec.ports.targetPort 필드에 지정된 파드의 서비스 포트로 포워딩
  • service.spec.selector  ->  서비스에 연결할 pod를 레이블 셀렉터를 이용하여 매칭한다.

 

  • 서비스 생성
kubectl create -f myapp-svc.yaml

 

 

3. 서비스 및 엔드포인트 확인

1) 서비스 목록 확인

  • 서비스 타입 : ClusterIP
  • ClusterIP : 쿠버네티스 클러스터 내에서만 접근할 수 있는 타입.
  • 클러스터 외부에서 접근할 때는 외부 IP(EXTERNAL-IP)를 사용해야한다.

 

2) endpoint 확인

  • endpoint : 서비스의 레이블 셀렉터에 의해 연결된(포워딩할) 파드의 IP 목록.

  • endpoint 이름은 서비스의 이름과 동일하다.
  • 현재 app=myapp-rs 레이블을 가진 파드가 없기 때문에 엔드포인트 목록도 가지고 있지 않다.
  • 서비스의 클러스터 IP로 접속하더라도 포워딩 할 파드가 없다.

 

 

4. pod 생성 및 endpoint 연결

  • 해당되는 레이블을 가진 파드를 생성하면 서비스는 자동으로 엔드포인트를 추가한다.
  • 나중에 파드가 추가되거나 제거되더라도 레이블 셀렉터에 의해 매칭되는 파드는 엔드포인트가 자동으로 추가 및 제거된다.
  • 앞서 만든 myapp-rs.yaml 파일을 이용하여 파드를 생성. 해당 컨트롤러 및 파드는 app=myapp-rs 레이블을 사용한다.
kubectl create -f myapp-rs.yaml

 

  • pod를 생성한 후 엔드포인트 다시 확인.

 

  • pod의 목록과 엔드포인트 비교

  • -o wide 옵션을 사용하여 파드에 할당된 IP를 확인할 수 있다.

 

 

5. 서비스 접근 테스트

  • 클러스터 내의 서비스에 접근하기 위한 테스트용 파드를 생성해 서비스 접근을 확인kubectl run 명령을 이용하여 테스트용 파드를 실행.

  • 파드의 이름  ->  nettool
  • 사용한 이미지  ->  c1t1d0s7/network-multitool.  테스트를 위한 이미지
  • --generator=run/v1  ->  파드만 생성. 이 옵션이 없으면 기본적으로 deployment object로 파드 생성.
  • --rm=true  ->  애플리케이션(여기서는 bash)이 종료되면 파드를 자동 삭제
  • 파드를 실행 후 bash 쉘이 실행된다.
  • curl 명령으로 서비스에 할당된 IP로 접근하면 기본적으로 부하분산이 이루어지며, 파드 그룹에 접근할 수 있다.

 

 

6. 서비스의 session affinity 구성

  • 서비스 접근 테스트에서 특정한 하나의 클라이언트가 웹 요청을 할 때마다 부하분산을 통해 다른 파드로 연결되는 것을 확인하였다.
  • 그러나 클라이언트 요청을 매번 똑같은 파드로 연결하고 싶은 경우나 그렇게 해야할 경우가 있다.
  • 세션을 계속 유지해야할 
# myapp-svc-session-affinity.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-ses-aff
spec:
  sessionAffinity: ClientIP
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp-rs
  • service.spec.sessionAffinity 필드로 구성 가능.
    • 속성 값으로None, ClientIP 두가지 종류가 있다.
    • 기본값은 None
    • None : 세션 어피니티 없음.
    • ClientIP : 클라이언트의 IP를 확인해 같은 파드로 연결된다.
  • ClientIP  ->  쿠버네티스 클러스터의 프록시는 클라이언트의 IP를 확인하여 매번 같은 파드로 연결해 준다.

 

 

7. 서비스 다중 포트 구성

  • 파드의 애플리케이션은 항상 하나의 포트로만 서비스 하는것이 아니다.
  • 여러 포트를 사용하여 서비스를 할 수 있다.
  • 파드의 서비스 포트가 다중 포트인 경우, 노출할 서비스 포트 역시 다중 포트로 구성할 수 있다.
# myapp-svc-multiport.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-mp
spec:
  ports:
  - name: myapp-http
    port: 80
    targetPort: 8080
  - name: myapp-https
    port: 443
    targetPort: 8443
  selector:
    app: myapp-rs
  • 다중 포트를 설정할 때는 반드시 포트의 이름을 부여하야한다.

 

 

8. 포트 이름 참조

  • 서비스 포트에 이름을 부여할 수 있다.
  • pod나 pod를 생성하는 컨트롤러 -> pod 템플릿 -> 컨테이너 포트에도 이름을 부여할 수 있다.
    • pod(컨테이너)의 포트 이름을 이용하여 서비스 생성 시 pod의 대상포트(targetPort)에 이름을 이용하여 연결할 수 있다.
    • 이는 이름으로 참조 하기 때문에 pod의 포트 번호가 변경되더라도 포트 이름이 변경되지 않는다면 계속 연결이 가능하다.

 

1) 포트 이름을 사용한 레플리카셋 및 서비스 생성

  • pod 및 컨트롤러에서 컨테이너의 포트에 이름을 부여하는 구성.
# myapp-rs-namedport.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs-nport
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp-rs-nport
  template:
    metadata:
      labels:
        app: myapp-rs-nport
    spec:
      containers:
      - name: myapp
        image: httpd
        ports:
        - name: port-http
          containerPort: 8080
  • 컨테이너의 8080 port에 port-http 라는 이름을 부여.
  • 이름을 서비스 생성 시 참조할 수 있다.

 

  • port 이름을 참조하는 서비스 구성
# myapp-svc-namedport.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-nport
spec:
  ports:
  - name: port-http
    port: 80
    targetPort: port-http
  selector:
    app: myapp-rs-nport
  • targetPort는 이름으로 지정하는게 best.

 

  • 작성한 레플리카셋 컨트롤러와 서비스를 생성.
kubectl create -f myapp-rs-namedport.yaml -f myapp-svc-namedport.yaml

 

2) 오브젝트 확인

  • 레플리카셋 컨트롤러 확인.

 

  • endpoint 확인

  • 8080 port를 참조하는 것을 확인할 수 있다.

 

  • pod 목록 및 pod IP 확인.

 

3) port 변경 및 확인.

  • kubectl edit 명령을 이용하여 레플리카셋의 포트를 8081로 변경해보자.
kubectl edit rs myapp-rs-nport

 

  • 포트를 변경하고 난 후, 현재 동작중인 pod의 포트는 변경되지않으므로 기존의 파드를 삭제한다.

 

  • 새로운 pod가 생성된 것을 확인

 

  • endpoint 다시 확인.

'Containers > Kubernetes' 카테고리의 다른 글

클러스터 외부 서비스 - NodePort  (0) 2020.08.22
5.2. Service 탐색  (1) 2020.08.10
4.4. DaemonSet  (0) 2020.07.29
4.3. ReplicaSet  (0) 2020.07.28
4.2. Replication Controller  (0) 2020.07.24

댓글