Cloud/k8s-CKA

[CKA] 4. Service

jinkwon.kim 2023. 1. 20. 18:27
728x90
반응형

개요

k8s에서의 service가 무엇인지 알아보겠습니다. 

일단 그전에 k8s의 network 기초를 조금 설명하고 넘어가겠습니다.

k8s의 network

k8s에서의 network구조

물리적으로 구성한 node위에 overlay network라는 기술을 이용하여 Pod 간의 network를 구현하고 있습니다.

참고로. overlay network는 물리적으로 구성된 망위에 새로운 논리적인 network를 구성하는 하는 것입니다.

 

그림으로 설명 하면 다음과 같습니다.

1. 먼저 물리적인 network를 구성하여 node를 연결합니다.

2. 그리고 node안에 생성된 pod들을 overlay network를 이용하여 연결합니다.

    이때 "overlay network를 이용하여 연결" 한다는 뜻은 Pod들을 물리 적으로 연결한 다는 것이 아니라
    node안에서 해당 Pod들을 찾아갈 수 있게 iptables을 설정한 것을 의미합니다.

 

 

overlay network는 어떻게 구성을 하는가

위 그림에서와 같이 k8s에서 network가 어떻게 구성되는지 간단히 알아보았습니다. 

그러면 실제로 overlay network는 어떻게 구성하는가 가 궁금해집니다. overlay network의 구성은 CNI(https://github.com/containernetworking/cni) spec에 맞추어 개발된 3rd party plugins들을 설치하게 되면 이 3rd party plugins들이 알아서 Pod에 IP를 할당해 주고 Pod 간의 통신이 가능한 overlay network를 구성해 줍니다.

실제 어떻게 동작하는지는 나중에 살펴보겠습니다.

Service란?

Pod를 network에 노출할 수 있게 중간 다리 역할을 해주는 virtual server 역활을 합니다

그리고 service는 Load Balancing이 가능합니다.

Service 어떻게 Pod를 노출하는가?

일단 Pod만을 배포하게 되면 cluster안에서만 접근이 가능하지 외부에서는 접근을 할 수 없습니다.

그래서 아래 그림처럼 Pod를 Service와 연결시켜주고 해당 service를 외부에 노출시키는 방식을 사용합니다.

아래 그림에서 빨간색 Box분분이 Pod를 어떠한 방식으로 노출할지를 결정하는 방식입니다.

참고로, Service는 linux의 iptables이용하여 구현됩니다.

sevice를 이용한 2가지의 Pod 노출 방법

좀 더 깊게 들어가면 ingress가 존재하는데 이는 service영역이 아니므로 networking 부분에서 좀 더 상세히 알아보겠습니다. 

NodPort

1. 원리

외부에 노출할 특정 port를 service와 연결하는 방식으로 pod를 외부에 노출합니다.

 

2. NodePort의 도식 

30008번으로 node에 port가 열리고 해당 포트를 service가 Pod와 연결해 주고 있습니다.

단, 유의 사항으로 nodeport는 번위가 30000 - 32767번으로 제한되어있습니다.

3. NodePort yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-nginx
  labels:
    app: pod-nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
  labels:
    run: nginx-nodeport
spec:
  type: NodePort     # 서비스 타입
  ports:
  - targetPort: 80   # 1. pod에서 open된 port
    port: 80         # 2. Pod와 연결된 service port
    nodePort: 30008  # 3. service와 연결된 node의 port
  selector:
    app: pod-nginx

4. 검증

아래 그림에서 보면 service가 NodePort Type으로 생성된 것을 확인할 수 있습니다.

5. Nodeport의 기능

sevice가 Load Balancing이 가능하기 때문에 다음 경우에도 모두 처리가 가능합니다. 

- 1개의 node에 3개의 pod가 있는 경우에도 모든 Pod에 접근이 가능합니다.

 

- 3개의 node에 각 1개의 pod가 있는 경우에도 모든 Pod에 접근이 가능 합니다. 

6. Nodeport의 한계

NodePort를 이용하여 외부에 노출된 Pod에 접근하기 위해서는 Node의 IP를 필수로 알아야 합니다. 

그런데 만약 Pod가 여러 Node에 분산되어 있다면 분산된 Pod에 접근 하기 위해서는 모든 Node의 IP를 알아야 합니다. 

이는 개발한 것을 서비스 하기에는 불가능한 구조입니다. 그래서 이를 해결한 방법이 뒤에 설명할 Load Balancer입니다.

Loadbalancer

NodePort로는 해결할 수 없는 단일 URL를 사용하여 Pod를 외부로 노출하고 싶을때 사용합니다. 

아래 도식처럼 모든 Pod를 LoadBalancer type의 Service에 연결하고 해당 Service를 외부에 노출합니다.

1. LoadBalancer 도식 

2. Load Balancer 설치

설치 가이드

https://metallb.universe.tf/installation/

 

MetalLB, bare metal load-balancer for Kubernetes

Installation Before starting with installation, make sure you meet all the requirements. In particular, you should pay attention to network addon compatibility. If you’re trying to run MetalLB on a cloud platform, you should also look at the cloud compat

metallb.universe.tf

(1) 사전 설정

kubectl edit configmap -n kube-system kube-proxy

and set:

apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true

(2) manifest를 사용한 설치 

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

(3) IP 네트워크 대역 설정

    - 설치 파일에 설정이 들어 있지 않기 때문에 External IP 대역폭을 설정해줘야 합니다. 

External IP 대역은 외부에서 접속할 IP의 대역을 설정해 줍니다

유의사항. k8s에 사용하는 node의 ip 대역을 할당 하면 안됩니다.

단일 IP일 경우 192.168.0.26-192.168.0.26 이렇게 넣어주면 됩니다.

The installation manifest does not include a configuration file. MetalLB’s components will still start, but will remain idle until you start deploying resources.

https://metallb.universe.tf/configuration/

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.240-192.168.1.250 # or 192.168.0.26-192.168.0.26

(3) Load Balancer service 생성

apiVersion: v1
kind: Service
metadata:
  name: lb-nginx
spec:
  type: LoadBalancer     # 서비스 타입
  ports:
    - targetPort: 80   # pod에서 open된 port
      port: 80         # Pod와 연결된 service port
  selector:
    app: lb-pod-nginx

(4) Load Balancer로 서비스할 Pod 생성

apiVersion: apps/v1
kind: Deployment
metadata:
  name: lb-nginx-deployment
  labels:
    app: lb-nginx-deployment
spec:
  replicas: 4
  selector: # Deployment를 이용해 배포할 Pod로 만들 template을 선택 합니다.
    matchLabels:
      app: lb-pod-nginx
  template:
    metadata: # template로 만들 pod를 정의하는것과 동일
      labels:
        app: lb-pod-nginx
    spec:
      containers: #container들을 정의 합니다.
      - name: container-nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

(5) 검증 

아래 그림을 보면 service/lb-nginx로 LoadBalancer가 생성된 것을 확인할 수 있습니다.

service의 ClusterIP를 이용한 Cluster 내부 Load Balancing

지금 까지 service에서 LaodBalancer와 NodePort를 알아보았습니다.

이 2개의 Type은 모두 외부에 Pod를 노출하기 위한 용도였습니다. 그러나 우리가 웹 서비스 구축 하다 보면 내부에서 Load Balancing이 필요합니다. 

 

본 Post에서 service 정의 시 "Pod를 network에 노출할 수 있게 중간 다리 역할을 해주는 virtual server 역활을 합니다"라고 했습니다. 그런데 이중 간 다리를 외부 network에만 할 필요가 없죠 내부 networ에서도 사용할 수 있습니다.

그래서 이때 사용하는 게 ClusterIP Type입니다.

 

아래 그림에서 front-end Pod는 내부적으로 여러 개의 back-end에 접근할 수 있습니다. 그런데 어는 back-end로 연결할지 매번 결정을 해야 합니다. 그러나 interface역할을 해주는 back-end라는 clusterIP type의 service를 만들게 되면 front-end pod는 매번 결정할 피요 없이 back-end service에게만 요청하게 되면 매번 어디로 연결해야 할지 걱정할 필요가 없습니다. 

테스트

1. pod를 deployment 형태로 배포합니다.

file name : cl-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cluster-nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: cluster-nginx
  template:
    metadata:
      labels:
        app: cluster-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

2. 배포된 pod와 연결할 service를 만듭니다. 

file name : cl-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: cl-service
spec:
  selector:
    app: cluster-nginx
  ports:
    - name: http
      port: 80
      targetPort: 80
  type: ClusterIP

#kubectl apply -f cl-service.yaml

3. 내부에서 접속을 합니다.

#wget 10.106.204.230

service의 구성 요소 분석

describe 를 이용하여 service로 생성한 object를 한게 보면 Endpoints 라는 것이 존재 합니다. 

이 Endpoints는 현재 service가 어느 Pod와 연결 되어있는지 알려줍니다.

 

테스트를 위한 Network 노출 방법

Port forwarding

단발성으로 외부로 pod를 노출하고 싶을 때 사용합니다. 

#kubectl port-forward --address 192.168.0.26 nginx-deployment-7fb96c846b-24t2g 443:80

설명 

--address : bind 할 IP

-- nginx-deployment-7fb96c846b-24t2g : network에 노출시킬 pod

-- 443:80 : 443 port로 들어온걸 80 port로 변경하겠다.

정리 

k8s에서 service는 단순히 virtual server 역할만 하는 존재이다. 

k8s에서는 iptables를 이용하여 service를 외부에 노출시킨다. 

k8s에서 service를 통해서 pod를 노출할 수 있는 방법은 2가지가 존재. 

1. nodeport

2. loadbalancer

Next Post

[CKA] 5. namespace

728x90
반응형

'Cloud > k8s-CKA' 카테고리의 다른 글

[CKA] 6. Object를 관리하는 방법 3가지  (0) 2023.01.29
[CKA] 5. namespace  (0) 2023.01.24
[CKA] 3. ReplicaSet & Deployments  (0) 2023.01.11
[CKA] 2. pod 란  (0) 2022.11.26
[CKA] 1. k8s가 뭔가?  (0) 2022.11.11