티스토리 뷰

Infra/Kubernetes

About Service(1), Basic Concept

Jordy-torvalds 2019. 11. 19. 17:00

About Service(1), Basic Concept

Date: Nov 15, 2019 5:19 PM
State: Writing

Basic Concept

Outline

클라이언트에서 실제 비즈니스 로직을 처리하는 Pod 들 사이에는 서비스가 있다. 클라이언트가 서비스의 아이피로 접근해 요청을 하면 서비스는 그 요청을 적절히 Pod에게 배분해준다.

-

이러한 업무 처리 방식은 클라이언트가 Pod의 아이피를 알 필요가 없게 만든다. 그런데 놀라운 것은 서비스도 Pod의 아이피를 몰라도 운영하는데 문제가 없다.

-

기존에 쿠버네티스를 사용하지 않는 환경에서는 3 Tier 기준으로 Web Server, WAS, DB 모두에 IP를 명시해줘야 한다. 물론 여기에 방화벽과 IPS, DDOS 등의 장비들이 더해지면 더욱 IP를 명시해주는 부분이 많아질 것이다.

-

이처럼 IP는 잘 파악 되고 있어야 하는 존재였다.

-

이와달리 쿠버네티스에서는 IP를 명시하지 않는다. 명시를 하지 않는 이유는 다음과 같다.

  1. Pod는 수명이 짧다 — Pod는 언제든 생겼다가 사라질 수 있는 존재이다. 갑작스런 장애가 발생했을 때는 삭제되어 다른 노드에서 새롭게 생겨 날 수 있고, 관리자의 판단에 따라 replica count를 줄여 운영하는 Pod의 숫자를 줄일 수도 있다.
  2. Pod의 IP 할당 시점 — Pod는 생성과 동시에 아이피가 할당 되는 것이 아닌 특정 노드에 배정되었을 때 할당 받게 되기 때문에 지속적으로 명확히 파악하여 관리할 수 없다.
  3. 수평적 확장에 따른 Pod 현황 파악의 어려움 — 클라이언트는 서비스의 뒷 편에 위치한 수 많은 포드들과 또 그 포드들의 아이피를 모두 관리 할 수 없다. 그렇기 때문에 해당 포드들을 모두 접근할 수 있는 하나의 서비스 아이피를 제공하여 서비스를 받을 수 있도록 한다.

-

Definition

포드들의 입구의 역할을 하며, IP 및 PORT를 배정받으면 별도로 수정하지 않는 이상 존재하는 동안 변경되지 않는다. 클라이언트가 서비스에 접속을 시도하면 서비스의 뒷편에 있는 Pod와 연결을 시켜준다. 이러한 방식으로 인해 클라이언트는 개별 Pod의 위치에 대해 알 필요가 없어지고, Pod는 노드 클러스터 내부에서 자유롭게 이동할 수 있게 된다.

Example

Basic Service-Pod Structure

위 사진은 쿠버네티스 인 액션에서 발췌한 사진이다. External Client(외부 고객) 입장에서는 프론트엔드 서비스의 아이피만 만 알면 뒷편에 위치한 프론트엔드 포드의 수와 아이피를 몰라도 요청을 할 수 있다.

-

그리고, 프론트 엔드의 포드들의 백엔드 서비스의 아이피만 알면 뒷편에 위치한 백엔드 포드의 수와 아이피를 몰라도 요청을 할 수 있다.

-

이처럼 알아야 하는 정보의 양을 줄여주고, 결합도를 최소화하며, 단순화 해주는 것이 이번 글에서 설명하는 서비스의 특성이자 쿠버네티스란 명작의 특성이다. 이러한 특성은 이후에 작성될 글에 서도 느낄 수 있을 것이다.

-

그럼 이제 간단한 서비스를 만들어보도록 하겠다.

-

Exampe1-Basic Service

apiVersion: v1
kind: Service
metadata:
  name: dev-svc-jordy
spec:
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: jordy
# jordy-svc.yaml

-

apiVersion: v1
kind: Pod
metadata:
    name: jordy
    labels:
      app: jordy
spec:
    containers:
    -   image: bearstark/jordy
        name: jordy
        ports:
        - containerPort: 8080
          protocol: TCP
# jordy-pod.yaml

-

apiVersion: v1
kind: Pod
metadata:
    name: jordy2
    labels:
      app: jordy
spec:
    containers:
    -   image: bearstark/jordy
        name: jordy
        ports:
        - containerPort: 8080
          protocol: TCP
# jordy-pod2.yaml

위 코드는 서비스와 이름이 다른 포드 2개를 생성하기 위한 yaml 이다. 코드를 따라 치고, 파일명은 주석을 참조하여 짓는다.

-

O YAML을 통한 컴퍼넌트 생성 명령어

kubectl create -f <fileName.fileExtension>

-

위 CREATE 명령어는 이제 많이 익숙해졌을 것이다.

그 후에 아래 명령어를 실행하고 결과를 확인 해보자.

-

O 전체 Pod 목록 조회

kubectl get pods --show-labels

NAME                READY   STATUS    RESTARTS   AGE     LABELS
jordy               1/1     Running   0          2m54s   app=jordy
jordy2              1/1     Running   0          2m28s   app=jordy

-

O 전체 서비스 목록 조회

kubectl get services

NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
dev-svc-jordy   ClusterIP   10.51.254.18   <none>        80/TCP    111s
kubernetes      ClusterIP   10.51.240.1    <none>        443/TCP   21d

-

Pod 2개와 서비스 1개가 생성되었다.

Pod 2개 모두 Label이 app=jordy 로 설정 되어 있는데, 서비스의 셀렉터는 두 포드를 가리키도록 셀렉터에 app=jordy라고 입력되어있을까?

서비스의 상세 정보를 확인해보자.

-

O 특정 서비스 상세 조회

kubectl describe <kind of component> <component name>

kubectl describe services dev-svc-jordy

Name: dev-svc-jordy
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=jordy
Type: ClusterIP
IP: 10.51.254.18
Port: <unset> 80/TCP
TargetPort: 8080/TCP
Endpoints: 10.48.1.19:8080,10.48.2.33:8080
Session Affinity: None
Events: <none>

상세조회한 결과 selector가 app=jordy로 나온다. 또한 이 서비스의 클러스터 아이피가 10.51.254.18로 나온다. 이 클러스터 아이피는 클러스터 내부 아이피로 외부 접근인 Putty에서는 ping 혹은 curl를 날려도 응답을 받을 수 없다.

-

그래서 아래 yaml 노드js 이미지의 Pod를 생성하는데, 해당 이미지로 Pod 생성시 가동된 후에 처리하는 로직 따위가 없으므로 곧바로 종료되기 떄문에 sleep 명령어를 통해 계속해서 살아있도록 했다.

apiVersion: v1
kind: Pod
metadata:
    name: diff-jordy
    labels:
      app: node
spec:
    containers:
    -   image: node
        name: diff-jordy
        ports:
        - containerPort: 8080
          protocol: TCP
        command: ["/bin/bash","-c", "--"]
        args: [ "while true; do sleep 30; done;" ]

그 후에 exec 문을 활용해 특정 Pod로 접근해서 curl 날려보자.

-

kubectl exec <pod name> -- curl <cluster-inner-ip>

-

그러면 아래 응답 중 하나를 받을 수 있다.

you`ve hit jordy
you`ve hit jordy2

-

두 반응이 번갈아 나오는 이유는 서비스 자체가 로드밸런싱을 지원하므로 요청을 두 Pod에 나누어 반응하게끔 하기 떄문이다.

-

서비스의 YAML에 sessionAffinity를 설정하면 아이피 기반으로 세션이 생성 중인 Pod에 연결되게끔 하는 옵션을 줄 수도 있다.

...
spec:
  clusterIP: 10.51.254.18
  sessionAffinity: clientIp
...

-

다음 글에서 서비스에 대해 더 알아보도록 하겠다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함