[CI/CD Pipeline] 7. 무중단 배포

Ansible 을 이용한 무중단 배포 & Jmeter 를 통한 테스트

  1. 파일을 통해 현재 Service 가 바라보고 있는 버전 관리
  2. 파일을 읽어와서 반대 방향에 Deployment 삭제 후 생성
  3. 현재 방향이 Blue 인 경우에 Green 에 배포 진행
  4. kubectl rollout 명령어를 통해 Ready 상태 대기
  5. 파일을 읽어와서 생성된 Deployment 로 방향 변경
  6. switch.sh 실행하여 버전 관리 파일 변경

1.파일을 통해 현재 Service 가 바라보고 있는 버전 관리

sysctl_param.yml

color: green
  • 현재 Service 가 green 버전으로 트래픽을 전달 중

2.파일을 읽어와서 반대 방향에 Deployment 삭제 후 생성

k8s-cicd-non-stop-deployment.yml

- name: Create pods using deployment
  hosts: kubernetes
  vars_files:
    - /root/sysctl_param.yml
  vars:
    color: ''


  tasks:
    - name: delete the previous blue deployment
      command: kubectl delete deployment.app/cicd-deployment-blue
      when: color == 'green'
      ignore_errors: yes

    - name: create a blue deployment
      command: kubectl apply -f cicd-devops-deployment-blue.yml
      when: color == 'green'

    - name: delete the previous green deployment
      command: kubectl delete deployment.app/cicd-deployment-green
      when: color == 'blue'
      ignore_errors: yes

    - name: create a green deployment
      command: kubectl apply -f cicd-devops-deployment-green.yml
      when: color == 'blue'
  • vars_files 을 통해 변수가 저장된 파일을 읽어올 수 있다.
  • vars 를 통해 변수 지정
  • when 을 통해 조건 지정

3. kubectl rollout 명령어를 통해 Ready 상태 대기

k8s-cicd-non-stop-service.yml

- name: create service for deployment
  hosts: kubernetes
  vars_files:
    - /root/sysctl_param.yml
  vars:
    color: ''

  tasks:
    - name: rollout blue deployment
      command: kubectl rollout status deployment cicd-deployment-blue
      when: color == 'green'

    - name: rollout green deployment
      command: kubectl rollout status deployment cicd-deployment-green
      when: color == 'blue'

    ...
  • kubectl rollout 명령어를 통해 반대 방향에 생성 중인 Deployment 가 정상적으로 Ready 상태가 되었는지 확인

4. 파일을 읽어와서 생성된 Deployment 로 방향 변경

k8s-cicd-non-stop-service.yml


  ...

  - name: patch a blue service to green service
    command: kubectl apply -f cicd-devops-blue-service.yml
    when: color == 'green'

  - name: patch a green service to blue service
    command: kubectl apply -f cicd-devops-green-service.yml
    when: color == 'blue'

5. switch.sh 실행하여 버전 관리 파일 변경

switch.sh

if [[ "$CURRENT_COLOR" ==  *blue* ]] ;
then
   $(sed -i '1s/color: blue/color: green/' /root/sysctl_param.yml)
else
   $(sed -i '1s/color: green/color: blue/' /root/sysctl_param.yml)
fi

Jmeter 를 통한 무중단 배포 테스트

img.png

  • Number of Threads (users) : 가상사용자 ( Thread )의 수
  • Ramp-up period (seconds) : 요청 주기(초)
  • Loop Count : 테스트를 반복하는 횟수, Infinite - 무한대로 호출

애플리케이션 버전 변경

img_1.png

  • 11.0 -> 12.0

배포를 진행하며 Jmeter 를 통한 지속적인 요청

배포 이전 상태

img_2.png

배포 이후 상태

img_3.png

img_4.png

  • 중단 & 오류없이 정상적으로 버전 업데이트 완료

kubernetes(k8s)

컨트롤러(Controller)

7가지 컨트롤러(ReplicationController, ReplicaSet, Deployment, DaemonSet, StatefulSet, Job, CronJob)이 존재한다.

Controller?

  • 몇 개의 Pod 로 애플리케이션을 운영할지 결정
  • Pod 의 개수를 보장

img_5.png

  • kubectl create deployment webui --image=nginx --replicas 라는 명령어를 Master Node 의 API 에 보낸다.
  • API 는 etcd 에서 정보를 얻어와서 scheduler 에게 요청한다.
  • scheduler 는 Worker Node 중 nginx 를 배포하면 좋을지 결정하여 API 에게 응답한다.
  • API 는 controller 에게 nginx container 3개를 보장하라는 요청을 한다.
  • API 는 scheduler 가 결정한 Worker Node 에 nginx pod 를 생성한다.

controller 는 각 Worker Node 에 배치된 Pod 를 감시하며 Pod 가 문제가 생기는 경우 API 에 요청하여 scheduler 를 통해 배치할 Worker Node 를 결정하고 새로운 Pod 를 생성한다.

Controller 종류

img_6.png

ReplicationController

img_7.png

  • 요구하는 Pod 의 개수를 보장하며 Pod 집합의 실행을 항상 안정적으로 유지하는 것을 목표
    • 요구하는 Pod 의 개수 보다 부족하면 template 을 이용해 Pod 를 추가
    • 요구하는 Pod 의 개수 보다 많으면 최근에 생성된 Pod 를 삭제
  • 기본 구성
    • selector
    • replicas
    • template

selector 의 key 와 value 를 통해 replicas 개수만큼 Pod 를 운영한다.

Controller 는 현재 동작 중인 Pod 를 스캔하면 key, value 의 Label 을 가지고 있는 container 가 동작 중인지 살펴보며 많으면 개수를 줄이고, 적으면 template 을 확인하여 개수를 늘린다.

ReplicationController-definition

img_8.png

  • app: webui 라는 label 을 가진 3개의 Pod 를 보장한다.
  • template 은 반드시 selector 에 존재하는 key, value 를 label 로 포함하고 있어야 한다.

ReplicationController Example - 1

rc-nginx.yaml

apiVersion: v1
kind: ReplicationController
metadata:
  name: rc-nginx
spec:
  replicas: 3
  selector:
    app: webui
  template:
    metadata:
      name: nginx-pod
      labels:
        app: webui
    spec:
      containers:
        - name: nginx-container
  - image: nginx:1.14
kubectl create -f rc-nginx.yaml
watch kubectl get pods -o wide

img_9.png

kubectl get replicationcontrollers
kubectl get rc

img_10.png

최대 Pod 개수가 유지 중에 동일한 label(app=webui) 을 가진 Pod 추가 생성 테스트

kubectl run redis --image=redis --labels=app=webui --dry-run -o yaml > redis.yaml # dry-run 옵션을 통해 redis.yaml 생성
kubectl get pod --show-labels
kubectl create -f redis.yaml

img_11.png

  • 실행되자마자 Terminating
  • 현재 이미 동일한 label(app=webui)을 가진 Pod 3개가 운영 중이기 때문에 controller 에서 삭제

ReplicationController Example - 2

replicas 개수 변경 테스트

kubectl edit rc rc-nginx # 실행 중인 rc-nginx 편집
kubectl scale rc rc-nginx --replicas=4 # scale 명령어를 통해 replicas 개수 변경

img_12.png

  • replicas 개수 4개로 수정

img_13.png

ReplicationController Example - 3

template 정보 변경 테스트

kubectl edit rc rc-nginx

img_14.png

  • nginx 버전을 1.14 -> 1.15 변경
  • 기존에 운영 중이던 nginx pod 새로 생성?

img_15.png

  • 변경사항 X
  • controller 는 selector 만 참조하기 때문에 template 의 정보를 참조하는 경우는 새로 Pod 가 생성되는 시점이다.
kubectl describe pod rc-nginx-dv2t2 # Pod 상세정보 확인 -> nginx 버전 1.14
kubectl delete pod rc-nginx-f8d7f # Pod 삭제
kubectl describe pod rc-nginx-pws68 # controller 에 의해 새로 생성된 Pod 상세정보 확인

img_16.png

Service 동작 중에 nginx 웹 버전이 1.14에서 1.15로 변경되었다. Service 가 중지되지 않고 비즈니스 연속성을 지원해주는 것을 Rolling Update 라고 한다.

ReplicaSet

Replication Controller 와 성격(pod 의 개수 보장)은 동일

  • ReplicationController 와 같은 역할을 하는 컨트롤러
  • ReplicationController 보다 풍부한 selector

img_17.png

  • matchLabels:
    • key: value
  • matchExpressions 연산자
    • In: key와 values를 지정하여 key, value가 일치하는 Pod만 연결
    • NotIn: key는 일치하고 value는 일치하지 않는 Pod에 연결
    • Exists: key에 맞는 label의 Pod를 연결
    • DoesNotExist: key와 다른 label의 Pod를 연결

ReplicationController 표현식

img_18.png

  • app: webui && version: "2.1" 인 Container Pod 3개 운영
    • And 조건

ReplicaSet 표현식

spec:
  replicas:3
  selector:
    matchLabels:
      app: webui
    matchExpressions:
      - { key: version, operator: In, value: [ "2.1" ] }
    ...
  • 위와 같은 표현
spec:
  replicas:3
  selector:
    matchLabels:
      app: webui
    matchExpressions:
      - { key: version, operator: In, value: [ "2.1", "2.2" ] }
    ...
  • app: webui && version 키의 value 가 “2.1” 또는 “2.2” 인 Pod 3개 운영
spec:
  replicas:3
  selector:
    matchLabels:
      app: webui
    matchExpressions:
      - { key: version, operator: Exists }
    ...
  • app: webui && version 키가 존재하는 Container Pod 3개 운영

Replication definition

img_19.png

  • ReplicationController 의 apiVersion 은 v1
  • ReplicaSet 의 apiVersion 은 apps/v1

img_20.png

ReplicaSet example

rs-nginx.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: rs-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webui
  template:
    metadata:
      name: nginx-pod
      labels:
        app: webui
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.14
kubectl create -f rs-nginx.yaml
kubectl get pod --show-labels

img_21.png

  • Label 이 app: webui 인 Container Pod 3개 생성

Pod 는 삭제하지 않고 Controller 만 삭제하는 방법

kubectl delete rs rs-nginx --cascade=false
  • --cascade=false: 연쇄 삭제 기능을 비활성화(default=true)

img_22.png

  • Controller 는 삭제되고, Pod 는 관리되지 않는 단독 Pod 로 변경
  • 이 상태에서 다시 Controller 를 생성하면?
    • 이미 app: webui 인 Pod 가 존재하므로 생성된 Controller 는 기존 Pod 를 관리
    • 각 Pod 들의 실행 중인 프로그램이 달라도 Label 을 기준으로 관리한다.
    • 따라서 1개의 Pod 는 Redis, 2개의 Pod 는 nginx 일 수 있지만 이런식으로 관리해서는 안된다.

Deployment

Deployment 는 Controller 종류인 ReplicaSet 을 제어해주는 부모 역할

Deployment 의 목적은 Rolling Update

Deployment를 생성하면 ReplicaSet 하나를 생성하여 컨트롤하며 Pod수를 조절한다. 또한 Deployment에게 Rolling Update 명령어를 실행하면 새로운 버전의 Pod 를 동작시킨다.

Rolling Update?

Pod 인스턴스를 점진적으로 새로운 버전으로 업데이트하여 Deployment 업데이트가 서비스 중단 없이 이루어질 수 있도록 해준다.

Deployment definition

img_23.png

  • kind를 제외하고 다른점이 없다.

Deployment example - 1

deploy-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webui
  template:
    metadata:
      name: nginx-pod
      labels:
        app: webui
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.14
kubectl create -f deploy-nginx.yaml
kubectl get deploy,rs,pod

img_24.png

  • deployment 1개, replicaset 1개, pod 3개가 생성

img_25.png

  • 빨간색은 controller 이름, 파란색은 pod 이름
kubectl delete rs deploy-nginx-967c5f57d # ReplicaSet을 삭제하면?

img_26.png

  • ReplicaSet 1개, Pod 3개 삭제 후 전부 다시 생성

Deployment Rolling Update & Rolling Back - 1

  • Rolling Update
    • 서비스 도중에 버전 업데이트
    • kubectl set image deployment <deploy_name> <container_name>=<new_version_image>
  • RollBack
    • 서비스 도중에 이전 버전으로 돌아가기
    • kubectl rollout history deployment <deploy_name>
    • kubectl rollout undo deploy <deploy_name>

img_27.png

  • app-deploy 라는 이름의 Deployment 를 통해 nginx:1.14 버전의 Pod 3개가 동작 중인 상태
  • kubectl set image deployment app-deploy app=nginx:1.15 --record 라는 명령어가 실행되면 Deployment 는 새로운 이름의 ReplicaSet 을 생성하여 nginx:1.15 버전의 Pod 1 개를 추가 운영한다.
  • 새로 추가된 Pod 가 Running 상태가 되면 구버전의 Pod 하나를 줄인다.
  • 일정한 시간이 지나면 반복적으로 구버전의 Pod 개수 하나를 줄이고, 신버전의 Pod 개수를 하나 늘린다.

img_28.png

  • 결과적으로 구버전의 Pod 가 모두 사라지고, 신버전의 Pod 개수가 3개가 된다.

Deployment Rolling Update & Rolling Back example - 1

deployment-exam1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deploy
spec:
  selector:
    matchLabels:
      app: webui
  replicas: 3
  template:
    metadata:
      labels:
        app: webui
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.14
kubectl create -f deployment-exam1.yaml --record
kubectl get deployment,rs,pod

img_29.png

kubectl set image deploy app-deploy web=nginx:1.15 --record # Rolling update -> 1.15 Pod 1개 생성 
kubectl describe pod app-deploy-65c4469fbc-6q9c4

img_30.png

  • nginx:1.14 -> nginx:1.15
kubectl image deployment app-deploy web=nginx:1.16 --record
kubectl rollout status deployment app-deploy 
  • kubectl rollout status: 업데이트 상태 정보 확인

img_31.png

kubectl image deployment app-deploy web=nginx:1.17 --record
kubectl rollout pause deployment app-deploy
  • kubectl rollout pause: 업데이트 일시정지
  • kubectl rollout resume: 업데이트 재시작
kubectl rollout history deployment app-deploy
  • kubectl rollout history: 업데이트 history 확인

img_32.png

kubectl rollout undo deployment app-deploy
  • kubectl rollout undo: Rollback 명령어

img_33.png

  • 이전 버전으로 Rollback
  • kubectl rollout undo deployment app-deploy --to-revision=3: revision 값으로 롤백

Deployment Rolling Update & Rolling Back example - 2

deployment-exam2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
  annotations:
    kubernetes.io/change-cause: version 1.14
spec:
  progressDeadlineSeconds: 600
  revisionHistoryLimit: 10
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  replicas: 3
  selector:
    matchLabels:
      app: webui
  template:
    metadata:
      labels:
        app: webui
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.14
  • annotation
    • kubernetes.io/change-cause: version 1.14 이름으로 history 를 남길 수 있다.
  • progressDeadlineSeconds: default=600, 600초 동안 업데이트를 진행하지 못하면 업데이트 취소
  • revisionHistoryLimit: default=10, 현재 동작중인 history replica 개수를 10개 보존, 따라서 해당 버전으로 되돌아가기 가능
  • maxSurge: Rolling Update 시 3개의 Pod라면 25%는 0.75개 반올림 시 1개, 따라서 업데이트시 Pod 의 개수가 4개가 되면 하나 삭제하는 개념, %가 높아지면 업데이트 속도가 빨라진다.
  • maxUnavailable: Pod 의 Terminating 개수를 조절

yaml 파일을 가지고 rolling update 하기

kubectl apply -f deployment-exam2.yaml
vi deployment-exam2.yaml

img_34.png

kubectl apply -f deployment-exam2.yaml
kubectl describe pod deploy-nginx-fbc78867f-cxd96 
kubectl rollout history deployment deploy-nginx

img_35.png

img_36.png

서비스(Service)

서비스 = 쿠버네티스 네트워크 / API

Kubernetes Service 의 개념

Service 는 동일한 서비스를 제공하는 Pod 그룹의 단일 진입점을 제공

img_37.png

  • Pod 들의 Label 을 기준으로 하나로 묶은 뒤 그룹에 대한 Virtual IP(단일 진입점)를 생성한다.
  • Virtual IP로 접근하면 그룹 중 하나로 연결해주는 Load Balancer 역할을 한다.
  • 해당 정보를 etcd에 기록

Service Definition

img_38.png

  • Deployment-definition 에서는 nginx 컨테이너에 Label(app:webui)을 붙혀서 3개 운영한다.
    • 3개의 Pod가 Worker Node 에서 동작하며 고유한 IP address를 갖는다.
  • Deployment-definition 에서는 webui-svc 라는 이름으로 Service를 생성한다.
    • clusterIP는 보통 생략한다. -> 생략하면 랜덤한 Virtual IP 배정
    • app: webui Label을 가진 Pod를 묶어서 하나의 단일 진입점을 clusterIP의 80번 port로 제공한다.
    • targetPort는 각각 그룹에 속한 Pod들의 port 번호

ClusterIP = VirtualIP = LoadBalancerIP

Kubernetes Service 타입

4가지 Type 지원

  • ClusterIP(default)
    • Pod 그룹의 단일 진입점(Virtual IP) 생성
  • NodePort
    • ClusterIP가 생성된 후
    • 모든 Worker Node 에 외부에서 접속가능 한 포트가 Open(예약)
    • 예를 들어 NodePort 타입의 Service 생성 시 30100번 Port 를 요구하면 그룹 Pod 들의 30100 Port 가 Open 된다.
    • 클라이언트가 Worker Node 중 하나 30100 Port 로 연결을 요청할 시에 해당 Node 에서 그룹 Pod 중 하나로 LoadBalancing 시켜준다.
  • LoadBalancer
    • ClusterIP가 생성, 그룹 Pod 들에 NodePort 생성
    • 추가로 LoadBalancer 가 생성되어 클라이언트의 요청을 LoadBalancer 가 받은 뒤 그룹 Pod 중 하나로 LoadBalancing 해준다.
    • 클라우드 인프라스트럭처(AWS, Azure, GCP 등)나 오픈스택 클라우드에 적용
    • LoadBalancer 를 자동으로 프로 비전하는 기능 지원
  • ExternalName
    • ClusterIP, LoadBalancer 서비스를 제공하는게 아닌 Naming 서비스(DNS?)를 제공한다.
    • 예를 들어 ExternalName 으로 google.com으로 등록하면 컨테이너 내부에서 도메인을 넣어주면 실제 도메인이 ExternalName 으로 바뀌어서 외부 통신이 가능해진다.
    • 클러스터 안에서 외부에 접속 시 사용할 도메인을 등록해서 사용
    • 클러스터 도메인이 실제 외부 도메인으로 치환되어 동작

Kubernetes Service 사용하기

ClusterIP

  • selector 의 label 가 동일한 Pod 들의 그룹으로 묶어 단일 진입점(Virtual IP)을 생성
  • 클러스터 내부에서만 사용가능
  • type 생략 시 default 값으로 10.96.0.0/12 범위에서 할당

Service Example: ClusterIP

deploy-nginx.yaml

kind: Deployment
metadata:
  name: webui
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webui
  template:
    metadata:
      name: nginx-pod
      labels:
        app: webui
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.14
  • nginx-container 3개를 운영해주는 Deployment
  • Label 은 app: webui
kubectl create -f deploy-nginx.yaml
kubectl get pod -o wide

img_39.png

clusterip-nginx.yaml

apiVersion: v1
kind: Service
metadata:
  name: clusterip-service
spec:
  type: ClusterIP
  clusterIP: 10.100.100.100
  selector:
    app: webui
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  • 10.100.100.100:80 으로 접속하면 그룹 Pod 중 하나의 80 Port 로 연결
kubectl create -f clusterip-nginx.yaml
kubectl describe svc clusterip-service
curl 10.100.100.100

img_40.png

img_41.png

  • 3개의 Pod 가 묶여있음을 확인할 수 있다.

img_42.png

  • 위의 3개의 Pod 중 하나에 연결됨을 확인할 수 있다.

ClusterIP 정리

ClusterIP 란 단일 진입점 IP를 생성해주고 실제 동작 중인 Pod 들을 균등하게 Service 될 수 있도록 지원하는 객체

NodePort

  • 모든 노드를 대상으로 외부 접속 가능한 포트를 예약
  • Default NodePort 범위: 30000-32767
  • ClusterIP 를 생성 후 NodePort 를 예약

Service Example: NodePort

nodeport-nginx.yaml

apiVersion: v1
kind: Service
metadata:
  name: nodeport-service
spec:
  type: NodePort
  clusterIP: 10.100.100.200
  selector:
    app: webui
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30200
  • nodePort를 생략 가능하다.
    • 생략하게되면 30000-32767 중 랜덤하게 배정된다.
kubectl create -f nodeport-nginx.yaml
kubectl get service -o wide

img_43.png

결과

img_44.png

NodePort 정리

ClusterIP는 내부 통신 용으로 쓴다면 NodePort 는 외부에서 접근할 수 있도록 도와준다.

LoadBalancer

외부 LoadBalancer 를 세팅해달라는 요청이 LoadBalancer Type

  • Public 클라우드(AWS, Azure, GCP 등)에서 운영가능
  • LoadBalancer 를 자동으로 구성 요청
  • NodePort 를 예약 후 해당 NodePort 로 외부 접근을 허용

img_45.png

  • NodePort 로 연결할 수 있는 외부 LoadBalancer 장비에 Setting 요청
  • LoadBalancer 장비를 통해 하나의 NodePort 로 접근하면 해당 Node 에서는 그룹 Pod 중 하나로 연결해주는 구조

Service Example: LoadBalancer

loadbalancer-nginx.yaml

apiVersion: v1
kind: Service
metadata:
  name: loadbalancer-service
spec:
  type: LoadBalancer
  selector:
    app: webui
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
kubectl create -f loadbalancer-nginx.yaml
kubectl get service -o wide

img_46.png

  • EXTERNAL-IP 80번 Port 로 접속하면 Worker Node 중 하나의 NodePort(31572)로 접속되고 해당 Node 에서 그룹 Pod 중 하나로 연결해주는 구조이다.

ExternalName

  • 클러스터 내부에서 External(외부)의 도메인을 설정

앞에서 배운 3가지 Type 은 전부 동작 중인 Pod 들의 단일 진입점, 외부에서 접근 가능하도록 NodePort, NodePort 를 묶어서 관리할 수 있는 LoadBalancer 장비까지 세팅해달라는 단계별 서비스(ClusterIP < NodePort < LoadBalancer)였다면 ExternalName 은 다른 성격(DNS를 지원)을 가진다.

Cluster 내부에서 외부로 나갈 수 있는 도메인을 등록해놓고 사용하는 것이다.

img_47.png

  • Service 를 정의할 때 Type 을 ExternalName 으로 지정하면서 외부 도메인을 할당
  • Pod 에서 curl {Service 정의할 때 ExternalName -> google.com}-svc.default.svc.cluster.local
  • {Service 정의할 때 ExternalName -> google.com}-svc.default.svc.cluster.local 내용이 google.com 으로 치환된다.
  • 앞에서 배운 Type 과는 반대되는 내용
  • 쉽게 말해서 DNS 를 지원

Service Example: ExternalName

externalname.yaml

apiVersion: v1
kind: Service
metadata:
  name: externalname-svc
spec:
  type: ExternalName
  externalName: google.com
kubectl create -f externalname.yaml
kubectl get service -o wide

kubectl run testpod -it --image=centos:7 // 테스트를 위한 pod 생성, curl 명령어를 위한 centos
curl externalname-svc.default.svc.cluster.local

img_48.png

img_49.png

Kubernetes 헤드리스 서비스

앞에서 설명한 Service 의 4가지 타입과는 다른 이야기

  • ClusterIP 가 없는 서비스로 단일 진입점이 필요 없을 때 사용
  • IP address 가 존재하지 않는 단일 진입점이 생성되고, endpoint 를 묶는 역할만 한다.
  • Service 와 연결된 Pod 의 endpoint 로 DNS 레코드가 생성됨 -> kubernetes 의 coreDNS 에 레코드로 등록
  • Pod 들의 endpoint 에 DNS resolving Service 받을 수 있도록 지원 가능해진다.
  • Pod 의 DNS 주소: pod-ip-addr.namespace.pod.cluster.local

Service Example : headless

headless-nginx.yaml

apiVersion: v1
kind: Service
metadata:
  name: headless-service
spec:
  type: ClusterIP
  clusterIP: None
  selector:
    app: webui
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  • clusterIP: None: type 은 ClusterIP, clusterIP 는 명시적으로 None
kubectl create -f headless-nginx.yaml
kubectl get service -o wide
kubectl describe svc headless-service

img_50.png

  • ClusterIP 가 None

img_51.png

  • Pod 들이 묶여 있지만 ClusterIP 는 None
kubectl run testpod -it --image=centos:7 /bin/bash # 테스트를 위한 Pod 생성
  • -it: 직접 접속을 위한 옵션
  • /bin/bash: centos:7 의 /bin/bash 바로 실행

testPod 의 DNS 서버 확인

img_52.png

  • DNS 서버: 10.96.0.10
    • master node 가 제공해주는 coreDNS 의 IP 주소
    • 해당 주소를 통해 DNS 를 요청하게 된다.

img_53.png

  • Pod 의 DNS 주소(pod-ip-addr.namespace.pod.cluster.local) 로 DNS resolving 하게되면 실제 10.96.0.10 Pod 에 연결시켜주는 resolving 서비스를 지원해준다.

kube-proxy

  • Kubernetes Service 의 backend 구현
  • endpoint 연결을 위한 iptables 구성
  • nodePort 로의 접근과 Pod 연결을 구현(iptables 구성)

kubectl get pods --all-namespaces

img_54.png

  • Master Node, 3 Worker Node 에 대한 kube-proxy 4개 존재
  • Service 를 요청하게 되면 backend 에서 각각의 Node 에 존재하는 kube-proxy 가 동작하여 해당 Node 에 iptables rule 을 만들어서 클라이언트가 ClusterIP 로 접속하게되면 endpoint 중 하나로 연결해주는 구조

Worker Node 1 iptables 확인

img_55.png

  • 10.100.100.100 으로 접속하게되면 위의 3 개의 IP 중 80번 포트 하나로 연결
  • 이러한 rule 을 만드는 주체가 kube-proxy

kube-proxy 가 하는 역할은 크게 2가지

  1. service 를 생성하게 되면 iptables rule 생성
  2. service type 을 NodePort 로 명시하면 NodePort 를 Listen 하여 클라이언트 커넥션을 잡아서 iptables rule 로 연결하여 Pod 통신을 가능하게 한다.

kube-proxy mode

userspace

  • 클라이언트의 서비스 요청을 iptables 를 거쳐 kube-proxy 가 받아서 연결
  • kubernetes 초기버전에 잠깐 사용

iptables

  • default kubernetes network mode
  • kube-proxy 는 service API 요청 시 iptables rule 이 생성
  • 클라이언트 연결은 kube-proxy 가 받아서 iptables 룰을 통해 연결

IPVS

  • 리눅스 커널이 지원하는 L4 로드밸런싱 기술을 이용
  • 별도의 ipvs 지원 모듈을 설정한 후 적용가능
  • 지원 알고리즘: rr(round-robin), lc(least connection), dh(destination hashing), sh(source hashing), sed(shortest expected delay), nc(new queue)

© 2023 Lee. All rights reserved.