728x90
반응형

Kubernetes Service

 

쿠버네티스에서의 로드밸런싱에는 Service와 Ingress가 있는데 간단하게 Service는 L4 로드밸런서, Ingress는 로드밸런서 이해하면 된다.

우선 Service에 대해 설명하겠다.

 

Service는 다른 포드의 요청이나 외부 클라이언트로부터 오는 HTTP 요청에 응답한다. 외부 클라이언트는 L4 로드밸런서를 외부로 노출시켜 트래픽을 받아 서비스에 속한 포드에 전달하는 것인데 다른 포드의 요청이라는 건 이해하기 애매할 수 있다. 이건 간편하게 내부 로드밸런서를 사용하는 경우로 이해해도 좋다. 물론 사용 사례일 뿐이니 각 환경마다 다르다.

 

외부 클라이언트 -> 외부노출 Service -> Webserver Pod -> 내부 Service -> WasServer Pod

 

 

이런식으로도 구성 가능하다.

 

일단 서비스를 사용하는 일반적으로 로드밸런서를 사용하는 이유와 비슷하지만 쿠버네티스 환경에서는 포드는 Static IP를 가지지 않고 노드 환경에 따라 삭제되고 재생성되는 일이 많으며 포드가 노드로 스케줄되기 전에 IP를 할당받으므로 클라이언트는 서버 포드의 IP를 알 수 가 없다. 이런 문제가 있기 때문에 Service라는 리소스가 필요한 이유이다.

 

쿠버네티스 서비스란 동일한 서비스 (webserver, api server와 같은) 를 제공하는 포드 그룹에 하나의 진입점을 위해 생성하는 리소스이다. 하나의 진입점이란 IDC 환경에서 L4 스위치를 사용할때 VIP를 사용하여 하단에 리얼 IP를 가진 서버를 묶듯이 이렇게 사용하는 VIP라고 이해하면 될것같다. 서비스가 생성되고 할당한 IP주소와 포트는 서비스가 삭제되기전까지 변하지 않는다.

 

위의 그림처럼 Service라는 하나의 진입점으로 들어온 트래픽은 하단의 포드 그룹에 로드밸런싱 된다.

 

Service의 기능중 sessionAffinity라는게 있는데 AWS ELB의 Sticky Session과 같은 기능이라고 보면 된다. ELB에서 Sticky Session을 지정하면 A클라이언트가 A인스턴스로 접속 후 다시 접속을 요청하면 B인스턴스가 아닌 A 인스턴스로 접속할 수 있게 세션을 열어주는 것인데 이것은  https://bcho.tistory.com/tag/sticky%20session 조대협님의 글을 읽어보길 추천한다.

 

 

sessionAffinity를 유지할 클라이언트 IP를 지정해야하는데 이유는 아래와 같다.

Sticky Session, 즉 sessionAffinity를 유지하려면 세션이 쿠키 기반의 옵션을 제공해야하는데 이는 HTTP 수준 (L7 Layer) 에서 동작을 해야한다. 

하지만 Service는 TCP/UDP 수준의 L4 Layer이다. 그렇기 때문에 패킷을 처리하고 페이로드 (전송되는 데이터) 에 대해서는 신경을 쓰지 않는다. 

그렇기때문에 IP를 지정해서 유지해줘야하는 것 (쿠키는 HTTP 프로토콜에서만 의미 있기 때문에 서비스는 쿠키를 처리할 수 없기에 세션이 쿠키 기반 옵션을 제공하지 않는 것) 이다.

 

이 외에 간단한 예제 몇개를 올려놓겠다.

 

- 다중 포트 노출

 

- 이름으로 포트 사용

 

Service 파일에서 포트에 name 속성을 지정하면 포드에서 포트를 적을 필요없이 http, https 등과 같이 사용할 수 있다.

 

아래는 AWS에서 Service를 생성하면 NLB로 생성되는 예제이다.

 

 

이대로 구성하면 바로 NLB가 생성된다. ALB의 경우는 이것보다는 좀 더 복잡하다. 추가되야할게 두가지 더 있다. 이건 Ingress 항목에서 설명하겠다.

 

서비스의 타입에는 ClusterIP, NodePort, LoadBalancer, External Name 이렇게 네 가지가 존재한다. LoadBalancer는 방금 위에서 설명했고 Nodeport에 대해 설명하겠다.

 

NodePort는 말 그대로 노드의 포트를 사용하는 것이다. 아래 그림을 확인해보자

 

 

우선 외부 클라이언트는 노드의 30123포트를 통해 서비스에 접근하고 서비스에서 포드에게 트래픽이 전달된다.

Service를 생성하면 노드의 포트를 랜덤으로 할당하는데 지정된 노드의 포트를 사용하고 싶으면 이렇게 사용하여도 된다.

 

 

 

여기서 연관된 리소스 중 하나인 엔드포인트에 대해 추가 설명하겠다. 서비스를 생성하고 kubectl describe svc OOO 명령을 실행하여 설명을 보면 Endpoint라는 필드가 존재한다. 

 

서비스는 포드에 직접 링크하지 않는다. 대신 이 엔드포인트라 불리는 리소스가 서비스와 포드 사이에 존재하며 이 서비스를 통해 들어오는 트래픽이 전달될 타겟을 지정한다.

즉 엔드포인트는 서비스에 의해 노출되는 IP주소와 포트의 목록이라 보면 된다.

 

 

출력 내용을 보면 포드의 IP와 포트가 엔드포인트로 지정되어 서비스에 등록되어 있다.

 

이 엔드포인트를 수동으로도 지정할 수 있는데 이런 경우 서비스가 연결을 포워딩할 IP와 포트를 직접 지정하는 경우에 사용된다.

아래는 수동으로 지정된 엔드포인트 매니페스트이다.

 

- 서비스 리소스

 

- 엔드포인트 리소스

 

위 방식은 수동으로 서비스와 엔드포인트를 지정한 방식이며 아래처럼 서비스에 ExternalName 형식으로 지정할 수 있다.

 

 

위처럼 엔드포인트를 지정하는 서비스는 클러스터 밖에 서비스에 접근하기 위해 사용된다.

 

여기서 클러스터 밖의 서비스란 AWS RDS와 같이 데이터베이스나 다른 클라우드 서비스를 의미한다. 일반적으로 대부분의 운영 서버들은 DB에 접근하기 때문에 ExternalName 템플릿은

많이 쓰일 것이다.

 

생성된 서비스를 확인해보면 아래와 같다.

 

 

여기서 하나 체크할 부분은 서비스인데도 IP가 없다. 왜 그럴까?

 

ExternalName 서비스는 기본적으로 DNS레벨에서 구현되며 작동한다. 그러므로 ExternalName 서비스로 연결하는 클라이언트는 서비스 프록시를 통하지 않고 직접 외부서비스로 연결한다.

이런 이유로 인해 ExternalName 서비스는 클러스터 IP를 얻지 못한다.

 

 

반응형

'Kubernetes' 카테고리의 다른 글

Kubernetes Ingress  (0) 2019.09.19
Kubernetes Monitoring - Version1  (0) 2019.09.17
Kubernetes HorizontalPodAutoscaler  (0) 2019.08.31
Kubernetes Pod DaemonSet  (0) 2019.08.30
Kubernetes Pod Replica  (0) 2019.08.30

+ Recent posts