System/Container & Kubernetes

[Kubernetes] HAProxy와 Keepalived를 활용한 Kubernetes API 클러스터 HA 구현 - 1편

마늘김 2025. 2. 9. 11:49

0. 들어가며

 Kubernetes 클러스터는 크게 Master 노드(Control Plane 역할)와 Worker 노드(워크로드 구동 역할)로 나뉩니다. 프로덕션 환경에서는 고가용성(HA) 및 로드 밸런싱을 위해 Master 노드를 여러대로 하여 클러스터 형식으로 구현하기도 합니다. 그런데 여기서 문제가 생깁니다.

 

1) 어떻게 단일 API End-Point를 제공할 것인가?

 생각해 보면 Control Plane을 구성하는 노드가 1대만 존재한다면 크게 문제될 것이 없는 부분이지만, 여러 대가 존재 한다면 그때는 어떤 Master 노드가 제공하는 API 서버의 주소를 사용해야 할지 정하는 것이 좀 애매해집니다. 1대의 Master 노드가 대표로 API 서버 주소를 노출한다면 해당 노드에만 많은 부하가 걸려서 Control Plane을 클러스터로 구성한 이점을 누리지 못합니다.

 

2) API End-Point를 제공하던 노드가 응답하지 않을때 Failover는 어떤 식으로 작동하게 할 것인가?

 첫 번째의 문제와 이어지는 부분으로, 특정 Master 노드를 API End-Point로 제공한다고 하더라도 해당 노드가 어떤 문제가 생겨서 응답하지 않을 경우 Failover 되어 다른 노드가 API End-Point를 제공할 수 있도록 설정하는 것이 가능한지도 의문입니다. 설령 가능하다 하더라도, Kubernetes 클러스터 사용자가 API End-Point 변경을 어떻게 감지하고 대처할 수 있느냐도 문제가 되는 부분이라 할 수 있겠습니다.

 

3) 로드 밸런싱은 어떻게 구현할 것인가?

 어쨌든 Control Plane을 클러스터 형식으로 구성하게 되었을 때, 각 노드들의 부하 분산을 위해서라도 API End-Point를 하나의 Master 노드가 제공하는 것은 불합리합니다. 각각의 Control Plane 노드들이 부하를 적절하게 분산하여 처리할 수 있도록 자동으로 분배해 줄 기능이 필요합니다.


1. Kubernetes API 클러스터 HA 구현을 위해 필요한 것들

 Kubernetes를 클라우드 환경에서 운영중이라면 해당 클라우드 제공 업체의 로드 밸런싱 기능을 사용하면 문제가 간단히 해결되겠지만 저와 같이 On-Premise 환경에서 운영한다면 약간 수고스러운 작업들이 필요합니다. 이것저것 찾아본 결과 HAProxy와 Keepalived를 사용해 기능을 구현해 보기로 했습니다.

[그림 1] Kubernetes API 클러스터 HA 아키텍처

 위 그림은 구현하고자 하는 구성의 아키텍처입니다. Kubernetes의 Control Plane은 3대의 Master 노드로 구성하였고, 그 앞에 로드 밸런서 및 단일 API End-Point를 제공하는 역할을 해줄 로드 밸런서(LB) 2대가 있습니다. LB에는 앞서 말씀드린 대로 HAProxy와 Keepalived를 통해 구축했습니다.

 

 자세한 구축 방법을 확인하기 전, HAProxy와 Keepalived가 어떤 기능을 하는지 알아보고 가는 것이 좋을 것 같습니다.

 

1) HAProxy

 HAProxy는 안정적인 TCP/HTTP 로드 밸런서 및 프록시 솔루션입니다. 유로인 Enterprise 버전과 무료인 Community Edition 버전이 있습니다. 해당 포스팅에는 무료 버전을 사용하도록 하겠습니다. 두 버전 간에는 여러 차이점이 있지만 그중 무료 버전은  Active/Active 모드가 아닌 Active/Standby 모드로 작동한다는 점이 가장 큰 부분이 아닐까 생각합니다.

 

 HAProxy는 여러 기능이 있지만, 이번 포스팅에서는 가상 IP로 들어오는 API 요청을 Kubernetes Control Plane의 각 노드로 로드 밸런싱하는 기능을 사용해 보도록 하겠습니다.

 

2) Keepalived

 Keepalived는 고가용성의 로드 밸런싱 서비스르 제공하는 오픈소스 소프트웨어입니다. VRRP(Virtual Router Redundancy Protocol)와 IPVS(IP Virtual Service)를 통해 작동합니다. HAProxy가 Kubernetes Control Plane 노드들에 대한 부하 분산을 제공한다면, Keepalived는 가상 IP를 통해 API 단일 End-Point를 제공하는 역할을 한다고 보면 됩니다. 물론, Active 상태의 LB가 서비스 불능 상태에 빠지면 Standby 상태에 있던 LB가 작동하여 HAProxy 뒤에 있는 Kubernetes API 서버가 작동하는데 이상이 없도록 하는 고가용성 역시도 제공합니다.

 

 Kubernetes Control Plane과 HAProxy, Keepalived의 상호 작용에 대해서 요약해 보자면 다음과 같습니다.

 

  •  우선 Kubernetes의 Control Plane을 3대의 노드로 구성함으로써, Kubernetes API 서버의 고가용성(HA)을 확보합니다.
  •  HAProxy는 이러한 Kubernetes Control Plane의 앞에 위치하여 API 서버로 들어오는 API 요청을 수신합니다. 수신된 API 요청을 적절한 방식으로(해당 포스팅에서는 Roundrobin 방식을 사용할 예정입니다.) Kubernetes의 Control Plane 노드로 분배하는 로드 밸런서 역할을 담당합니다.
  •  Keepalived는 가상 IP를 통해 Kubernetes API의 단일 End-Point를 제공합니다. 이를 통해 사용자는 Kubernetes Control Plane의 장애 여부에 관계없이 Kubernetes 클러스터와 통신할 수 있게 됩니다. 또한 HAProxy 서비스가 다운되거나, 혹은 LB 자체가 서비스 불능 상태에 빠지더라도, 대기하고 있던 다른 LB를 통해 서비스가 지속될 수 있도록 하여 HAProxy 서버의 고가용성(HA)을 확보합니다.

 

2. HAProxy와 Keepalived를 활용하여 로드 밸런서(LB) 구축

이름 IP Address 역할
LB 1 172.16.11.157 HAProxy + Keepalived로 LB 역할
LB 2 172.16.11.158 HAProxy + Keepalived로 LB 역할
Kubernetes Master 01 172.16.11.151 Kubernetes Control Plane
Kubernetes Master 02 172.16.11.152 Kubernetes Control Plane
Kubernetes Master 03 172.16.11.153 Kubernetes Control Plane
가상 IP 172.16.11.150 Kubernetes API 서버 단일 End-Point

 위 표는 구축하고자 하는 환경에 대한 정보입니다. 가상 IP를 제외한 나머지는 모두 VM 형식으로 생성하였습니다.(가상 IP는 Keepalived 설정 값으로 들어가게 됩니다.) VM의 크기는 실습 환경이라 크게 중요하지는 않지만, LB의 경우 4 vCPU와 4GB의 메모리, Kubernetes Master 노드의 경우 8 vCPU와 8GB의 메모리를 사용하였습니다. 소프트웨어 소스 정보는 아래와 같습니다.

 

  • OS : Ubuntu 20.04.6 LTS
  • HAProxy : 2.0.31-0ubuntu0.2 (2023/08/16)
  • Keepalived : v2.0.19 (10/19,2019)
  • kubeadm, kubelet, kubectl : v1.26.1

 이제 본격적으로 LB 구축 방법에 대해 알아보도록 하겠습니다.

 

Step1. HAproxy 설치

 기본적으로 Ubuntu 설치를 완료하고 IP 주소를 입력해 준 후 작업을 진행해 주시면 됩니다. LB 1LB 2 모두에 공통적으로 작업해 줍니다.

sudo apt udpate

sudo apt install haproxy -y

 명령어는 매우 간단합니다. apt udpate를 한번 진행해 주시고 HAProxy를 설치해주면 끝입니다. 설치가 완료되면 HAProxy의 설정 파일을 편집해 줍니다.

sudo vim /etc/haproxy/haproxy.cfg

#haproxy.conf 파일 하단에 아래 내용을 추가해 줍니다.

frontend kube-apiserver
  bind *:6443                #외부로 노출할 IP:포트번호 형식으로 해당 설정은 모든 Ip:6443 포트로 설정
  mode tcp
  option tcplog
  default_backend kube-apiserver

backend kube-apiserver
    mode tcp
    option tcplog
    option tcp-check
    balance roundrobin
    default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
    server kube-apiserver-1 172.16.11.151:6443 check #IP 주소를 Kubernetes Master 노드의 IP 주소로 변경
    server kube-apiserver-2 172.16.11.152:6443 check #IP 주소를 Kubernetes Master 노드의 IP 주소로 변경
    server kube-apiserver-3 172.16.11.153:6443 check #IP 주소를 Kubernetes Master 노드의 IP 주소로 변경
    
    #Kubernetes API는 기본적으로 6443 포트를 사용하여 통신하기 때문에 내부 6443 포트를 외부 6443 포트에 매핑한 설정

 위 설정은 HAProxy가 외부에서 들어오는 모든 IP의 6443 포트에 대한 요청을 backend로 설정한 Kubernetes API 서버인 172.16.11.151~3:6443으로 라운드로빈 형식으로 로드밸런싱 하도록 합니다. 다음으로 HAProxy를 재시작하여 설정 내용이 적용될 수 있도록 한 후, 서버가 시작될 때 HAProxy도 함께 작동하도록 systemd에 등록해 주면 됩니다. 그리고 HAProxy가 잘 작동하고 있는지 확인해 보도록 하겠습니다.

systemctl restart haproxy   #설정한 haproxy.cfg의 내용이 적용 될 수 있도록 HAProxy 재시작

systemctl enable haproxy    #systemd에 등록

systemctl status haproxy    #HAProxy 실행 상태 확인
● haproxy.service - HAProxy Load Balancer
     Loaded: loaded (/lib/systemd/system/haproxy.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2023-09-12 15:57:58 KST; 12s ago
       Docs: man:haproxy(1)
             file:/usr/share/doc/haproxy/configuration.txt.gz
    Process: 31037 ExecStartPre=/usr/sbin/haproxy -Ws -f $CONFIG -c -q $EXTRAOPTS (code=exited, status=0/SUCCESS)
   Main PID: 31039 (haproxy)
      Tasks: 5 (limit: 4598)
     Memory: 34.6M
     CGroup: /system.slice/haproxy.service
             ├─31039 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock
             └─31041 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock

 9월 12 15:57:58 lbadmin-virtual-machine haproxy[31039]: Proxy kube-apiserver started.
 9월 12 15:57:58 lbadmin-virtual-machine haproxy[31039]: Proxy kube-apiserver started.
 9월 12 15:57:58 lbadmin-virtual-machine haproxy[31039]: Proxy kube-apiserver started.
 9월 12 15:57:58 lbadmin-virtual-machine haproxy[31039]: Proxy kube-apiserver started.
 9월 12 15:57:58 lbadmin-virtual-machine haproxy[31039]: [NOTICE] 254/155758 (31039) : New worker #1 (31041) forked
 9월 12 15:57:58 lbadmin-virtual-machine systemd[1]: Started HAProxy Load Balancer.
 9월 12 15:57:59 lbadmin-virtual-machine haproxy[31041]: [WARNING] 254/155759 (31041) : Server kube-apiserver/kube-apiserver-1 is DOWN, reason: Layer4 co>
 9월 12 15:58:05 lbadmin-virtual-machine haproxy[31041]: [WARNING] 254/155805 (31041) : Server kube-apiserver/kube-apiserver-2 is DOWN, reason: Layer4 co>
 9월 12 15:58:08 lbadmin-virtual-machine haproxy[31041]: [WARNING] 254/155808 (31041) : Server kube-apiserver/kube-apiserver-3 is DOWN, reason: Layer4 co>
 9월 12 15:58:08 lbadmin-virtual-machine haproxy[31041]: [ALERT] 254/155808 (31041) : backend 'kube-apiserver' has no server available!

 명령어 systemctl status haproxy을 통해 HAProxy가 잘 작동하고 있는 것을 볼 수 있습니다. 아래 상태 정보 중 경고가 몇 줄 보이는데 걱정하실 필요는 없습니다. 이는 HAProxy의 backend로 설정한 kube-apiserver가 응답하지 않기 때문에 그런 것으로 다음 포스팅을 통해 Kubernetes Control Plane에 대한 설정에 대해서도 설명드리도록 하겠습니다.

[사진 1] backend의 응답이 없어서 표시된 경고이므로 걱정할 필요는 없습니다.

  앞서 언급드렸지만 LB 1과 LB 2 모두에 위 과정을 진행해 주면 됩니다. 다음으로 Keepalived를 설치하고 구성하는 방법을 알아보겠습니다.

 

Step2. Keepalived 설치

 Keepalived 설치 역시 HAProxy 만큼이나 간단합니다. Keepalived 패키지 설치만 해주면 됩니다. 역시 모두 LB 1과 LB 2 모두에 공통적으로 작업을 진행해 줍니다.

sudo apt install keepalived -y

 그런데 여기서 주의할 점이 하나 있습니다. HAProxy와는 다르게 Keepalived의 경우 다음 작업들을 root 유저로 진행해 주셔야 합니다. 일반 유저로 작업을 진행했을 때, 가상 IP를 네트워크 인터페이스에 부여하는 것은 가능했지만, Active LB가 다운되었을 때 Standby LB가 가상 IP를 받아서 서비스를 이어나가지 못하는 현상이 발생했습니다. 아마도 Linux 권한 문제로 예상됩니다. 네트워크 인터페이스에 IP를 부여하는 것과 같은 작업은 시스템에서 root 수준의 권한이 필요하기 때문입니다.

sudo -s                                 #root 유저로 전환

vim /etc/keepalived/keepalived.conf     #keepalived.conf 파일 생성

 텍스트 편집기로 /etc/keepalived 위치에 keepalived.conf 파일을 생성합니다. 빈 파일이 열리는데, 아래 내용을 입력해 줍니다. 설정 파일의 내용이 LB 1과 LB 2 사이에 약간의 차이가 있어서 작업을 따로 진행해 주셔야 합니다.

#LB 1에 아래 내용 입력

global_defs {
  notification_email {
  }
  router_id LVS_DEVEL
  vrrp_skip_check_adv_addr
  vrrp_garp_interval 0
  vrrp_gna_interval 0
}

vrrp_script chk_haproxy {
  script "killall -0 haproxy"
  interval 2
  weight 2
}

vrrp_instance haproxy-vip {
  state BACKUP
  priority 100
  interface ens160                       #LB 1의 네트워크 인터페이스 장비명 입력
  virtual_router_id 60
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass 1111
  }
  unicast_src_ip 172.16.11.158      #LB 1의 IP 주소 입력
  unicast_peer {
    172.16.11.157                         #LB 2의 IP 주소 입력
  }

  virtual_ipaddress {
    172.16.11.150/24                  #생성할 가상 IP의 주소 입력
  }

  track_script {
    chk_haproxy
  }
}

---------------------------------------------------------------------------------

#LB 2에 아래 내용 입력

global_defs {
  notification_email {
  }
  router_id LVS_DEVEL
  vrrp_skip_check_adv_addr
  vrrp_garp_interval 0
  vrrp_gna_interval 0
}

vrrp_script chk_haproxy {
  script "killall -0 haproxy"
  interval 2
  weight 2
}

vrrp_instance haproxy-vip {
  state BACKUP
  priority 100
  interface ens160                       #LB 2의 네트워크 인터페이스 장비명 입력
  virtual_router_id 60
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass 1111
  }
  unicast_src_ip 172.16.11.158      #LB 2의 IP 주소 입력
  unicast_peer {
    172.16.11.157                         #LB 1의 IP 주소 입력
  }

  virtual_ipaddress {
    172.16.11.150/24                  #생성할 가상 IP의 주소 입력
  }

  track_script {
    chk_haproxy
  }
}

 먼저 interface의 경우에는 가상 IP를 뛰우고자 하는 IP 주소 대역과 같은 IP를 가진 네트워크 인터페이스의 장비명을 입력해 주면 됩니다. 간단하게 ip a s 명령어를 통해 조회가 가능하며 본 포스팅의 경우에는 172.16.11.0/24 대역의  IP를 가진 네트워크 인터페이스의 장비명은 ens160으로 해당 장비명을 사용하였습니다.

 다음으로 unicast_src_ip 부분입니다. 이는 현재 작업하고 있는 LB의 IP 주소를 입력해 주면 됩니다. LB 1의 경우 LB 1의 IP 주소를, LB 2의 경우 LB 2의 IP 주소를 입력해 주고, unicast_peer를 상대방의 LB의 IP 주소를 입력해 주면 됩니다. 위의 코드 예시에서 보시는 바와 같이 unicast_src_ip와 unicast_peer값이 서로 반대가 되면 됩니다.

 마지막으로 가상 IP 주소로 Kubernetes API 서버의 단일 End-Point로 사용될 IP 주소를 virtual_ipaddress에 입력해 주면 됩니다.


 추가로 말씀을 드리자면, 맨 처음에 Keepalived를 설치하고 구성할 때 root 유저로 진행하지 않아서 가상 IP에 대한 HA가 잘 작동하지 않아 이것저것 설정을 많이 건드려 봤습니다. state 값을 Master와 BACKUP으로 나눠 보기도 하고, priority 값을 변경하기도 해 보았습니다. 하지만 모두 소용이 없었고 마지막으로 설정 값은 위와 같이 하고 root 유저 권한으로 설정하니 문제없이 작동하는 것을 확인할 수 있었습니다. 꼭 root 유저로 해당 내용을 진행하시길 당부드립니다.


 다음으로 root 유저 권한으로 keepalived를 재시작하여 설정값이 적용되도록 하고, systemd에 등록해 보도록 하겠습니다. 마지막으로는 keepalived의 작동 상태를 확인해 보도록 하겠습니다.

#반드시 root 권한에서 진행

systemctl restart keepalived

systemctl enable keepalived

systemctl status keepalived

=============================================================================================
#Active LB의 경우 출력 값
● keepalived.service - Keepalive Daemon (LVS and VRRP)
     Loaded: loaded (/lib/systemd/system/keepalived.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2023-09-12 16:44:40 KST; 32s ago
   Main PID: 20180 (keepalived)
      Tasks: 2 (limit: 4598)
     Memory: 1.5M
     CGroup: /system.slice/keepalived.service
             ├─20180 /usr/sbin/keepalived --dont-fork
             └─20181 /usr/sbin/keepalived --dont-fork

 9월 12 16:44:40 lbadmin-virtual-machine Keepalived_vrrp[20181]: Opening file '/etc/keepalived/keepalived.conf'.
 9월 12 16:44:40 lbadmin-virtual-machine Keepalived_vrrp[20181]: WARNING - default user 'keepalived_script' for script execution does not exist - please >
 9월 12 16:44:40 lbadmin-virtual-machine Keepalived_vrrp[20181]: WARNING - script `killall` resolved by path search to `/usr/bin/killall`. Please specify>
 9월 12 16:44:40 lbadmin-virtual-machine Keepalived_vrrp[20181]: SECURITY VIOLATION - scripts are being executed but script_security not enabled.
 9월 12 16:44:40 lbadmin-virtual-machine Keepalived_vrrp[20181]: Registering gratuitous ARP shared channel
 9월 12 16:44:40 lbadmin-virtual-machine Keepalived_vrrp[20181]: (haproxy-vip) Entering BACKUP STATE (init)
 9월 12 16:44:40 lbadmin-virtual-machine Keepalived_vrrp[20181]: VRRP_Script(chk_haproxy) succeeded
 9월 12 16:44:40 lbadmin-virtual-machine Keepalived_vrrp[20181]: (haproxy-vip) Changing effective priority from 100 to 102
 9월 12 16:44:53 lbadmin-virtual-machine Keepalived_vrrp[20181]: (haproxy-vip) Backup received priority 0 advertisement
 9월 12 16:44:54 lbadmin-virtual-machine Keepalived_vrrp[20181]: (haproxy-vip) Entering MASTER STATE


=============================================================================================
#Standby LB의 경우 출력 값
● keepalived.service - Keepalive Daemon (LVS and VRRP)
     Loaded: loaded (/lib/systemd/system/keepalived.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2023-09-12 16:44:54 KST; 5s ago
   Main PID: 32514 (keepalived)
      Tasks: 2 (limit: 4598)
     Memory: 1.5M
     CGroup: /system.slice/keepalived.service
             ├─32514 /usr/sbin/keepalived --dont-fork
             └─32515 /usr/sbin/keepalived --dont-fork

 9월 12 16:44:54 lbadmin-virtual-machine Keepalived_vrrp[32515]: Registering Kernel netlink reflector
 9월 12 16:44:54 lbadmin-virtual-machine Keepalived_vrrp[32515]: Registering Kernel netlink command channel
 9월 12 16:44:54 lbadmin-virtual-machine Keepalived_vrrp[32515]: Opening file '/etc/keepalived/keepalived.conf'.
 9월 12 16:44:54 lbadmin-virtual-machine Keepalived_vrrp[32515]: WARNING - default user 'keepalived_script' for script execution does not exist - please >
 9월 12 16:44:54 lbadmin-virtual-machine Keepalived_vrrp[32515]: WARNING - script `killall` resolved by path search to `/usr/bin/killall`. Please specify>
 9월 12 16:44:54 lbadmin-virtual-machine Keepalived_vrrp[32515]: SECURITY VIOLATION - scripts are being executed but script_security not enabled.
 9월 12 16:44:54 lbadmin-virtual-machine Keepalived_vrrp[32515]: Registering gratuitous ARP shared channel
 9월 12 16:44:54 lbadmin-virtual-machine Keepalived_vrrp[32515]: (haproxy-vip) Entering BACKUP STATE (init)
 9월 12 16:44:54 lbadmin-virtual-machine Keepalived_vrrp[32515]: VRRP_Script(chk_haproxy) succeeded
 9월 12 16:44:54 lbadmin-virtual-machine Keepalived_vrrp[32515]: (haproxy-vip) Changing effective priority from 100 to 102

[사진 2] Active 상태로 설정된 LB의 경우 MASTER STATE에 진입했다는 설명을 볼 수 있습니다.
[사진 3] Standby 상태의 LB의 경우 BACKUP STATE에 진입했다는 설명을 볼 수 있습니다.

 위의 사진에서 볼 수 있듯 각 LB에서 Keepalived의 상태를 확인해 보면 하나는 Master 상태로, 하나는 Backup 상태로 진입하는 것을 확인할 수 있습니다. Master 상태의 LB에서 hostname -I 명령어를 입력해 보면 가상 IP 주소(본 포스팅에서는 172.16.11.150)와 네트워크 인터페이스에 부여된 IP 주소(172.16.11.157 또는 172.16.11.158)가 출력되는 것을 확인할 수 있고, Backup 상태의 LB에서는 같은 명령어를 입력하면 네트워크 인터페이스에 부여된 IP 주소만을 확인할 수 있습니다.

 

 이제 마지막으로 가상 IP가 잘 이동하는지를 통해 LB의 HA 기능이 잘 작동하는지 확인해 보도록 하겠습니다.

 

Step 3. LB의 HA 기능 확인

 먼저 두대의 LB에 모두 hostname -I를 입력하여 현재 IP 주소 정보를 확인합니다. 가상 IP인 172.16.11.150이 출력되는 LB가 Active 상태로 해당 LB에서 명령어 sudo systemctl stop haproxy를 입력하여 HAProxy를 종료합니다. 

#Acitve 상태의 LB에서 아래 명령어를 입력
sudo systemctl stop haproxy     #haproxy 끔

systemctl status keepalived     #keepalived 상태를 확인하여 BACKUP STATE로 진입하는지 확인

● keepalived.service - Keepalive Daemon (LVS and VRRP)
     Loaded: loaded (/lib/systemd/system/keepalived.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2023-09-13 16:34:45 KST; 3min 35s ago
   Main PID: 98789 (keepalived)
      Tasks: 2 (limit: 4598)
     Memory: 1.5M
     CGroup: /system.slice/keepalived.service
             ├─98789 /usr/sbin/keepalived --dont-fork
             └─98790 /usr/sbin/keepalived --dont-fork

 9월 13 16:34:46 lbadmin-virtual-machine Keepalived_vrrp[98790]: (haproxy-vip) received lower priority (102) advert from 172.16.11.158 - discarding
 9월 13 16:34:47 lbadmin-virtual-machine Keepalived_vrrp[98790]: (haproxy-vip) received lower priority (102) advert from 172.16.11.158 - discarding
 9월 13 16:34:48 lbadmin-virtual-machine Keepalived_vrrp[98790]: (haproxy-vip) received lower priority (102) advert from 172.16.11.158 - discarding
 9월 13 16:34:49 lbadmin-virtual-machine Keepalived_vrrp[98790]: (haproxy-vip) received lower priority (102) advert from 172.16.11.158 - discarding
 9월 13 16:34:49 lbadmin-virtual-machine Keepalived_vrrp[98790]: (haproxy-vip) Entering MASTER STATE
 9월 13 16:38:11 lbadmin-virtual-machine Keepalived_vrrp[98790]: Script `chk_haproxy` now returning 1
 9월 13 16:38:11 lbadmin-virtual-machine Keepalived_vrrp[98790]: VRRP_Script(chk_haproxy) failed (exited with status 1)
 9월 13 16:38:11 lbadmin-virtual-machine Keepalived_vrrp[98790]: (haproxy-vip) Changing effective priority from 103 to 101
 9월 13 16:38:14 lbadmin-virtual-machine Keepalived_vrrp[98790]: (haproxy-vip) Master received advert from 172.16.11.158 with higher priority 102, ours 101
 9월 13 16:38:14 lbadmin-virtual-machine Keepalived_vrrp[98790]: (haproxy-vip) Entering BACKUP STATE

[사진 4] haproxy 서비스가 종료되면 Master상태의 LB가 Backup 상태로 진입하는 것을 볼 수 있습니다.

 위 내용에서 보시는 바와 같이, Active 상태의 LB에서 HAProxy 서비스를 종료하면 Keepalived는 이를 감지하고 상대편 LB로 가상 IP 주소를 이전하게 됩니다. 좀 더 상세하게 설명하면, 앞서 keepalived.conf 파일의 vrrp_script chk haproxy에서 설정한 값에 따라 HAProxy가 종료됨을 인지하고 priority값을 103에서 101로 낮춘 후 마스터에서 Backup 상태로 진입하며 가상 IP 주소인 172.16.11.150을 Backup 상태의 LB로 이전하는 것입니다.

 

 Backup 상태에 있던 LB에서 명령어 systemctl status keepalived를 실행해 보면 아래와 같은 결과를 얻을 수 있습니다.

systemctl status keepalived     #Backup 상태의 LB에서 Keepalived의 상태 확인

● keepalived.service - Keepalive Daemon (LVS and VRRP)
     Loaded: loaded (/lib/systemd/system/keepalived.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2023-09-13 16:33:08 KST; 21s ago
   Main PID: 82410 (keepalived)
      Tasks: 2 (limit: 4598)
     Memory: 1.5M
     CGroup: /system.slice/keepalived.service
             ├─82410 /usr/sbin/keepalived --dont-fork
             └─82411 /usr/sbin/keepalived --dont-fork

 9월 13 16:33:08 lbadmin-virtual-machine Keepalived_vrrp[82411]: Opening file '/etc/keepalived/keepalived.conf'.
 9월 13 16:33:08 lbadmin-virtual-machine Keepalived_vrrp[82411]: WARNING - default user 'keepalived_script' for script execution does not exist - please creat>
 9월 13 16:33:08 lbadmin-virtual-machine Keepalived_vrrp[82411]: WARNING - script `killall` resolved by path search to `/usr/bin/killall`. Please specify full>
 9월 13 16:33:08 lbadmin-virtual-machine Keepalived_vrrp[82411]: SECURITY VIOLATION - scripts are being executed but script_security not enabled.
 9월 13 16:33:08 lbadmin-virtual-machine Keepalived_vrrp[82411]: Registering gratuitous ARP shared channel
 9월 13 16:33:08 lbadmin-virtual-machine Keepalived_vrrp[82411]: (haproxy-vip) Entering BACKUP STATE (init)
 9월 13 16:33:08 lbadmin-virtual-machine Keepalived_vrrp[82411]: VRRP_Script(chk_haproxy) succeeded
 9월 13 16:33:08 lbadmin-virtual-machine Keepalived_vrrp[82411]: (haproxy-vip) Changing effective priority from 100 to 102
 9월 13 16:33:25 lbadmin-virtual-machine Keepalived_vrrp[82411]: (haproxy-vip) Backup received priority 0 advertisement
 9월 13 16:33:26 lbadmin-virtual-machine Keepalived_vrrp[82411]: (haproxy-vip) Entering MASTER STATE
 
 hostname -I
 172.16.11.158 172.16.11.150     #hostname -I로 IP 주소를 조회해 보면 가상 IP 주소 172.16.11.150이 표시 됨

[사진 5] Backup 상태의 LB가 Master상태에 진입하면서 가상 IP 주소를 받아오는 것을 확인할 수 있습니다.

 보시는 바와 같이 Backup 상태의 LB가 Master 상태로 진입하면서 가상 IP 주소인 172.16.11.150을 계속 서비스하는 것을 을 확인할 수 있습니다.


 이렇게 HAProxy와 Keepalived를 사용하여 HA 기능을 갖춘 로드 밸런서를 구성해 봤습니다. 다음 포스팅에는 이렇게 구성된 로드 밸런서와 서비스되고 있는 가상 IP를 활용하여 Kubernetes API 단일 End-Point를 구성하는 방법에 대해 알아보도록 하겠습니다.