Service

cometLEE·2023년 9월 18일
0

kubernetes

목록 보기
3/16

Service에 대해 공부한 내용을 정리한 글입니다.

쿠버네티스 공식 홈페이지 - Service and Expose (https://kubernetes.io/docs/concepts/services-networking/service/)를 참고하여 진행하였습니다.
또한, 마스터 노드1, 워커노드 2로 실습 진행하였습니다.
🤣🤩😊CKA 자격증 준비 및 쿠버네티스 공부 정리입니다.


1. Service

Kubernetes에서 서비스는 하나 이상의 서비스로 실행되는 네트워크 애플리케이션을 노출하는 방법입니다.


참고자료
참고자료

Service의 목표

  • 익숙하지 않은 서비스 검색 매커니즘을 사용하기 위해 기존 애플리케이션을 수정할 필요가 없습니다
  • 쿠버네티스 내부의 다양한 객체들이 애플리케이션과, 애플리케이션이 다른 외부의 애플리케이션이나 사용자와 연결될 수 있도록 도와주는 역할을 합니다.
  • 클라이언트가 상호작용할 수 있도록 서비스를 사용하여 해당 포드 세트를 네트워크에서 사용할 수 있게 만듭니다.

pod들은 동적으로 생성되고 삭제될 수 있습니다.
pod들은 자체 IP주소를 갖습니다.
그렇기 때문에 새로 생성되는 pod들끼리 IP가 충돌이 일어날 수 있게 됩니다.

Service의 기능

  • Service는 pod가 외부와 통신할 수 있도록 클러스터 내부에서 고정적인 IP를 갖는 서비스(Service)를 이용하도록 하고 있습니다.
  • 애플리케이션을 구동하도록 구성된 여러 파드들에게 단일한 네트워크 진입점을 부여하는 역할도 합니다.
  • 각 포드에는 고유한 IP 주소가 있지만 해당 IP는 서비스 없이는 클러스터 외부에 노출되지 않습니다.

서비스 종류

애플리케이션의 일부 부분(예: 프런트엔드)의 경우 클러스터 외부에서 액세스할 수 있는 외부 IP 주소에 서비스를 노출할 수 있습니다.

  1. ClusterIP
  2. NodePort
  3. LoadBalancer
  4. ExternalName

1. ClusterIP

  • 클러스터 내부 IP에 서비스를 노출합니다. 이 값을 선택하면 클러스터 내에서만 서비스에 연결할 수 있습니다.
  • type을 서비스에 대해 명시적으로 지정하지 않은 경우 사용되는 기본값입니다 .
  • Ingress 또는 Gateway를 사용하여 공용 인터넷에 서비스를 노출할 수 있습니다 .
  • <ClusterIP>로 들어온 클러스터 내부 트래픽을 해당 파드의 <파드IP>: targetport> 로 넘겨주도록 동작하므로, 오직 클러스터 내부에서만 접근 가능하게 됩니다.

ClusterIP 흐름

# my-nginx라는 Pod 정의
apiVersion: v1
kind: Pod
metadata:
  name: my-nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
# my-service라는 Service 정의
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: ClusterIP
  selector:
    app: nginx 	# app: nginx라는 label를 가진 pod를 찾음
  ports:
  - name: http
    port: 80 #	Service의 port
    targetPort: 80	# pod의 spec.containers.ports 가르킴
    protocol: TCP

ClusterIP는 .spec.ports에 port, targetPort의 속성을 가집니다.

  • .spec.ports.port: 서비스 리소스의 포트

  • .spec.ports.targetPort: 파드(대상) 리소스의 포트

  • .spec.selector: 파드 레이블 셀렉터, 엔드포인트 리소스 생성

service 사용해보기

my-service.yaml 을 적용해보았습니다.

$ kubectl apply -f [파일명]

80번 port로 type: ClusterIP로 생성이 되었습니다.

Pod 생성 후 endpoint 확인해보기

Service의 label selector의 값인 app: nginx에 해당되는 pod가 생성되자 endpoint 주소가 생겨남을 확인할 수 있었습니다.


2. NodePort

  • NodePort 서비스 유형은 ClusterIP 서비스 유형의 확장입니다. 따라서 ClusterIP도 자동으로 생성됩니다.
  • NodePort는 외부에서 노드 IP의 특정 포트(<NodeIP>:<NodePort>)로 들어오는 요청을 감지하여, 해당 포트와 연결된 파드로 트래픽을 전달하는 유형의 서비스입니다.
  • NodePort 타입에서는 spec.ports 아래에 nodePort 속성을 추가로 지정할 수 있다. nodePort는 외부에서 노드 안의 특정 서비스로 접근할 수 있도록 지정된 노드의 특정 포트를 의미한다.
  • nodePort로 할당 가능한 포트 번호의 범위는 30000 ~ 32767 사이이며, 미지정시 해당 범위 안에서 임의로 부여된다.
# NodePort 타입으로 생성한 Service
apiVersion: v1
kind: Service
metadata:
  name: my-service2
spec:
  type: NodePort
  ports:
  - targetPort: 80
    port: 80
    nodePort: 30008
  selector:
    app: nginx

my-service2를 적용해보자

PORTS에 <service Port: node Port> 형태로 80:30008이 지정되어 있는 것을 알 수 있습니다.

NodePort의 경우에도 spec.selector에 해당하는 모든 파드들에 동일한 로드 밸런싱이 적용됩니다.
클러스터의 모든 노드는 할당된 포트에서 수신 대기하고 해당 서비스와 연결된 준비된 엔드포인트 중 하나로 트래픽을 전달하도록 자체 구성됩니다.

node_IP:nodePort를 통해 endpoint인 pod로 접근이 가능해진다.

3. Load Balancer

  • Nodeport 타입의 확장판이라고 할 수 있으며 서비스를 외부에 노출 할 수 있습니다.
  • NodePort타입 앞단에 Loadbalancer가 붙어서 살아있는 노드를 체크하여 트래픽을 전달 할 수 있는 장점이 있습니다.
  • 클라우드 공급업체(AWS, GCP 등)에서 지원하는 기능입니다.
  • 서비스를 클라우드 제공자 측의 자체 로드 밸런서로 노출시키며, 이에 필요한 NodePort와 ClusterIP 역시 자동 생성된다.
  • 클라우드 제공자의 프로비저닝 된 load balancer의 정보는 추가로 status.loadBalancer에 표기한다.
  • 로드 밸런서 프로비저닝을 지원하지 않는 클라우드 환경일 경우 NodePort와 같은 방식으로 동작한다.
#loadBalancer 타입의 service 정의
apiVersion: v1
kind: Service
metadata:
  name: my-service3
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30009  # nodePort 타입으로 my-service2를 만들었기에 
    					# 30009번 포트로 할당해줍니다!!

이 환경이 클라우드 환경이었으면 EXTERNAL-IP가 할당이 되었을테지만, 온프레미스 환경에서는 클러스터가 LocadBalancer 타입을 지원하지 않기에 pending상태로 남아있게 됩니다.

Metal LB 설치

따라서 우리는 로드밸런서를 직접 설치해서 사용해보겠습니다.(Manifest)

sejong.jeonjo@gmail.comd의 블로그
metallb 공식 홈페이지

MetalLB를 위한 네임스페이스를 생성

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.11/config/manifests/metallb-native.yaml

strict ARP mode 활성화하기

## 아래 명령을 수행
$  kubectl edit configmap -n kube-system kube-proxy
 
... 중간 생략 ...
 
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true  ## 이 부분을 수정한다.  false -> true
 
... 중간 생략 ...

$ kubectl get -n metallb-system pod

IP Address Pool 설정하기

# my-network.yaml 생성
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.1.4.160/28
  - 10.1.4.176/28
  - 10.1.4.192-10.1.4.200
 
---
 
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: second-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.1.4.150-10.1.4.159
 
 
---
 
 
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: my-network-l2
  namespace: metallb-system
spec:
  ipAddressPools:
  - first-pool
  - second-pool
$  kubectl apply -n metallb-system -f my-network.yaml

주의할 점:

  • 위와 같이 L2Advertisement, IPAddressPool을 변경하고 적용해도 실제로 Service resource가 생성될 때, 과거의 IPAddressPool을 이용한다.
  • 과감하게 metallb-system 네임스페이스의 controller pod를 종료시키고 재기동하면 새로운 IPAddressPool이 적용된다.

loadbalancer 설치 후 결과

여기까지 진행했다면 아까 pending상태였던 my-service3의 상태를 확인해 보겠습니다.

EXTERNAL-IP가 10.1.4.160으로 잘 설정이 되었습니다.
이제 확인해보겠습니다.

loadBalancer -> service -> pod 순으로 잘 적용하는 것을 알 수 있습니다.

부하 분산기(load balancer)는 외부 부하 분산기, 내부 부하 분산기로 각각 외부ip, 내부ip를 할당 받아서 사용할 수 있습니다.

NodePort 할당 비활성화

  • loadBalancer필드에 spec.allocateLoadBalancerNodePorts 속성을 설정하여 선택적으로 서비스에 대한 노드 포트 할당을 비활성화 할 수 있습니다.
  • 기본적으로 LoadBalancer 서비스spec.allocateLoadBalancerNodePorts 유형 true은 노드 포트를 계속 할당합니다.
  • 해당 노드 포트의 할당을 취소하려면 모든 서비스 포트에서 항목을 제거해야 합니다.

4. External Name

  • ExternalName 유형의 서비스는 외부 DNS 이름에 대한 내부 별칭을 제공합니다. 내부 클라이언트는 내부 DNS 이름을 사용하여 요청을 수행하고, 요청이 외부 이름으로 리디렉션됩니다.
# ExternalName type의 service 정의
apiVersion: v1
kind: Service
metadata:
  name: my-xn-service
spec:
  type: ExternalName
  externalName: www.google.com

ExternalName 유형의 서비스는 일반적인 셀렉터에 대한 서비스가 아니라 DNS 이름에 대한 서비스에 매핑

  • ExternalName 서비스 유형은 기본적으로 다른 서비스 유형과 다릅니다. 실제로 ExternalName 유형의 서비스는 이 항목의 시작 부분에 제공된 서비스 정의에 부합되지 않습니다.
  • ExternalName 유형의 서비스는 포드 집합과 연결되지 않으며 안정적인 IP 주소를 갖지 않습니다. 대신 ExternalName 유형의 서비스는 내부 DNS 이름에서 외부 DNS 이름으로의 매핑입니다.
  • pod와 매칭하지 않기 때문에 label selector를 사용하지 않습니다.

FQDN?

Fully Qualified Domain Name 으로 "전체 도메인 네임" "절대 도메인 네임" 으로 불리는 도메인 전체 이름 표기 방식을 의미합니다.

www.google.com => www(호스트), google.com(도메인)

CNAME?

캐노니컬 네임 레코드(Canonical Name record), 줄여서 CNAME 레코드(CNAME record)는 하나의 도메인 네임(에일리어스)을 다른 이름(표준 형식의 이름)으로 매핑시키는 도메인 네임 시스템(DNS)의 리소스 레코드의 일종입니다.

외부 FQDN은 www.google.com이며, CNAME은 my-xn-serviced인 서비스입니다.


testpod를 만들어서 pod에서 external type의 서비스를 확인해보겠습니다.

$ kubectl run testpod -it --image=centos:7
 kubectl exec testpod -it -- /bin/bash

인터넷 게이트웨이가 없기 때문에 404에러가 출력됩니다.
그래도 ExternalName의 서비스 이름으로 google 메인페이지의 정보를 가져올 수 있었습니다.

정리

이번에는 service의 종류 4가지에 대해서 공부해보고 실습도 진행해 보았다. 어려운 내용이기도 했고, 쿠버네티스에서 중요한게 네트워크라고 하신 멘토님의 말씀을 한 번 더 생각하게 되는 계기였던 것 같다.

이번에는 개념에서 멈췄지만, 다른 개념을 숙지한 후에 자체 시나리오를 구축해서 진행해보는 것도 좋은 기회일 것이다. 블로그 작성하면서
kubernetes for the Absolute Beginners - Hands-on 내용을 보면 이해가 훨씬 잘되는 것 같다.

다음에는 expose로 쉽게 노출하는 방법에 대해서 포스팅해보겠습니다.

profile
server, kubernetes에 관심이 많이 있습니다

0개의 댓글