3. K8s 실전 활용을 위한 10단계

김하영·2021년 10월 7일
0
post-thumbnail

'15단계로 배우는 도커와 쿠버네티스' 기반으로 내용 정리하였습니다.

  • 서비스
    서비스의 네 종류와 용도 파악

파드는 일시적인 존재라 언제든지 할당된 IP 주소가 바뀔 수 있다. ( 젤 중요한 파드의 특징!! )
클라이언트 입장에서는 늘 변하는 파드의 IP 주소를 알기 어렵기 때문에 쿠버네티스에는 서비스라는 오브젝트가 존재한다.

서비스 타입 개요

  • ClusterIP (default) : 타입을 지정하지 않으면 기본으로 설정되며, 클러스터 내부의 파드에서 서비스의 이름으로 접근할 수 있다.
  • NodePort : ClusterIP 의 접근 범위뿐만 아니라 K8s 클러스터 외부에서도 노드의 IP 주소와 포트 번호로 접근할 수 있다.
  • LoadBalancer : NodePort 의 접근 범위뿐만 아니라 K8s 클러스터 외부에서도 대표 IP 주소로 접근할 수 있다.
  • ExternalName : K8s 클러스터 내의 파드에서 외부 IP 주소에 서비스의 이름으로 접근할 수 있다.

( 플로는 LoadBalancer 타입을 사용하겠지..? )

각 서비스 타입의 특징에 대해 알아보자!

ClusterIp


서비스 타입을 지정하지 않으면 기본 값으로 ClusterIP 로 만들어진다.
그림과 같이 클러스트 내부에서 내부 DNS에 등록한 이름으로 특정 파드 집합에 요청을 전송할 수 있게 해준다.

ClusterIP 는 다음 용도로 사용될 수 있다.
매니페스트에 'clusterIP : None' 이라고 지정하면, 헤드리스 설정으로 서비스가 동작한다.

이 설정에서는 대표 IP 주소를 획득하지 않고, 부하분산도 이뤄지지 않는다.
그 대신에 파드들의 IP 주소를 내부에 등록하여, 파드의 IP 주소 변경에 대응하여 최신 상태를 유지한다.
(그럼 대표 IP가 없고 서비스 이름을 통해 요청이 들어오면 서비스가 알아서 요청을 파드에 보낼 수 있는 건가??)

서비스 타입 NodePort


서비스 타입에 NodePort 를 지정하면, 앞서 설명한 ClusterIP 의 기능에 더해 노드의 IP 주소에 공개 포트가 열린다.
이를 통해 K8s 클러스터 외부에서 내부의 파드에 요청을 보낼 수 있게 된다.

공개 포트번호의 범위는 기본적으로 30000 - 32767 이다.

클라이언트가 노드의 IP와 포트로 전송한 요청은 최종적으로 파드에 전달된다.

NodePort 타입의 서비스를 만들면 클러스터의 모든 노드에 지정한 포트가 열리게 된다.
그리고 각 노드가 수령한 요청은 대상이 되는 파드들에게 부하분산되어 전송된다.

이때 요청을 받은 노드 내에 있는 파드로만 전송하도록 설정할 수 있다.
노드들 앞에 로드 밸런서가 있다면 매우 유용한 설정이다.
( 서비스 타입이 loadbalancer 인 서비스가 아닌 그냥 로드밸런서겠지..? )

여기서 한 가지 주의점이 있다.

사용자가 특정 노드를 지정해서 접속하고 있는데 해당 노드가 하드웨어 점검 등의 이유로 셧다운 된다면 서비스를 이용할 수 없게 된다.
그리고 이미 사용 중인 포트를 설정하면 매니페스트 배포 과정에서 실패한다.

NodePort는 쉽고 편리하게 설정할 수 있지만 정식 서비스에서 사용하는 것은 추천하지 않는다.
( 외부 통신이 가능하지만... 흠 안정적이지 않은 느낌임. )

서비스 타입 LoadBalancer

로드밸런서와 연동하여 파드의 애플리케이션을 외부에 공개한다.
또한, LoadBalancer는 NodePort를 사용하기 때문에 ClusterIP 도 자동적으로 만들어진다.

서비스 타입 ExternalName

파드에서 K8s 클러스터 외부의 엔드포인트에 접속하기 위한 이름을 해결해 준다.
예를 들어, 퍼블릭 클라우드의 데이터 베이스나 인공지능 API 서비스 등을 접근할 때 사용될 수 있다.

ExternalName은 서비스의 이름과 외부 DNS 이름의 매핑을 내부 DNS에 설정한다.
이를 통해 파드는 서비스의 이름으로 외부 네트워크의 엔드포인트에 접근할 수 있다.
이떄 포트 번호까지는 지정할 수 없다.

이 서비스 타입은 파드에서 외부의 엔드포인트에 접속할 때 편리하다.( db 서버 )
네임스페이스에서의 서비스 이름으로 ip 주소를 얻을 수 있기 때문이다.
또한, K8s 클러스터 내의 서비스로 교체하기도 쉽다.

서비스와 파드의 연결

서비스가 요청을 전송할 파드를 결정할 때는 실렉터의 라벨과 일치하는 파드를 etcd로 부터 선택한다고 설명했다.
여기서는 서비스의 매니페스트에 기술하는 실렉터와 매니페스트에 기술하는 라벨을 구체적으로 비교해보겠다.

[ 서비스 YAML ]

apiVersion: v1
kind: Service
metadata:
  name: hello-node-svc
spec:
  selector:
    app: hello-node
  ports:
    - port: 80
      protocol: TCP
      targetPort: 8080
  type: LoadBalancer

[ 디플로이먼트 YAML ]

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deploy
spec:
  replicas: 3
  selector:
    matchLabels
    app: hello-node
  template:
    metadata:
    label:
     app: hello-node
    spec:
     containers:
     - name: nginx
       image: nginx:latest

서비스의 selector 와 디플로이먼트 파드 템플릿의 'metadata.label' 에 같은 라벨 'app:hello-node'를 기술한다.
이러한 설정에 의해 서비스의 요청 전송 파드가 결정된다.

하나의 파드 템플릿으로 만들어지는 파드들은 같은 속성이 부여되므로 라벨도 같다.
따라서 디플로이먼트에 의해 만들어지는 파드들은 같은 라벨을 가지게 되어 서비스의 요청을 전송받는다.

이와 같은 방식은 selector의 값을 바꾸는 것만으로 서비스가 전송하는 파드의 그룹을 바꿀 수 있어 운영상의 유연성을 가질 수 있다.

또 중복에 주의하여 의도하지 않는 파드로 요청이 전송되지 않도록 주의해야 한다.

서비스의 매니페스트 작성법

apiVersion: v1
kind: Service
metadata:
  name: hello-node-svc
spec:
  selector:
    app: hello-node
  ports:
    - port: 80
      protocol: TCP
      targetPort: 8080
  type: LoadBalancer

[ 서비스 API ]

  • kind : Service 설정
  • apiVersion : v1 설정
  • metadata : name에 네임스페이스 내 유일한 이름을 설정. 여기서 설정한 이름은 내부 DNS 에 등록되며,
    IP 주소 해결에 사용. 또한, 이후 기동된 파드의 환경 변수에 설정
  • spec : 서비스 사양

[ 서비스 사양 ]

  • type : 서비스 공개 방법을 설정. 선택이 가능한 타입은 ClusterIP / NodePort / LoadBalancer / ExternalName 네 가지
  • ports : 서비스에 의해 공개되는 포트번호
  • selector : 여기서 설정한 라벨과 일치하는 파드에 요청을 전송. ExternalName인 경우는 무시
    이 항목을 설정하지 않은 경우, 외부에서 관리하는 엔드포인트를 가진 것으로 간주 (ExternalName)
  • sessionAffinity : 설정이 가능한 세션 어피니티는 ClientIP. 생략 시 None 으로 설정됨
  • clusterIP : 이 항목을 생략하면 대표 IP 주소가 자동으로 할당. 그리고 None을 설정하면 헤드리스로 동작

[ 서비스 파드 사양 ]

  • port : 필수 항목. 이 서비스에 의해 공개되는 포트번호
  • name : port가 하나인 경우는 생략할 수 있고 여러 개인 경우는 필수 설정 필요.
    각 포트의 이름은 서비스 스펙 내에서 유일해야 함.
  • protocol : 생략 시에는 TCP 설정. TCP or UDP
  • nodePort : 생략 시에는 시스템이 자동으로 할당.
    설정한 포트가 이미 사용 중인 경우에는 오브젝트 생성에 실패
    type이 NodePort나 LoadBalancer인 경우 모든 노드에서 포트를 공개
  • targetPort : 생략 시에는 port와 동일한 값이 사용됨. selector에 의해 대응되는 파드가 공개하는 포트 번호 또는 포트 이름을 설정함.

[ 세션 어피니티 ]
동일한 클라이언트에서 온 요청은 언제나 같은 파드에 전송하고 싶을 수 있다.
그런 경우에는 매니페스트의 세션 어피니티를 ClientIP 로 설정하면 된다.

마무리

  • 서비스는 클라이언트의 요청을 파드에 전달하기 위한 오브젝트로서 부하분산 기능을 포함한다.
    서비스 타입에 따라 공개 방법과 범위가 다르다.

  • 서비스 타입 ClusterIP를 사용하면 k8s 클러스터 내부에서 접속할 수 있으며, NodePort를 사용하면 K8s 클러스터 외부에서 노드의 IP 주소와 포트번호로 접속할 수 있다. 그리고 LoadBalancer 를 사용하면 K8s 클러스터 외부에서 대표 IP 주소로 접속할 수 있다.

  • 서비스 타입은 ExternalName 은 K8s 클러스터 외부의 DNS 이름을 서비스 이름으로 등록하다. 서비스 명과 IP 주소를 매핑하고 싶은 경우에는 헤드리스 서비스를 검토해야 한다.

  • 서비스가 받은 요청을 전달할 파드는 라벨에 의해 결정된다.

  • 서비스의 부하분산 알고리즘은 기본적으로 랜덤이며, 세션 어피니티에 의해 클라이언트의 IP 주소별로 전송될 파드를 고정할 수 있다.
    서비스에는 HTTP 헤더의 쿠키에 의한 세션 어피니트 기능은 없다. (?! 쿠키를 고정하는 기능인가? )
    해당 기능이 필요한 경우에는 인그레스 사용을 검토한다.

  • NodePort를 사용해도 외부에 애플리케이션을 공개할 수 있지만 가용성이 부족하여 정식 서비스에 적합하지 않다. 반면 LoadBalancer는 가용성도 있고 HTTP와 HTTPS를 사용할 수 있어 정식 서비스에 적합하다.

profile
Back-end Developer

0개의 댓글