웹사이트 검색

Ubuntu 14.04에서 Keepalived 및 예약된 IP로 고가용성 HAProxy 서버를 설정하는 방법


소개

고가용성은 장애 발생 시 응용 프로그램이 자동으로 다시 시작하거나 작업을 다른 가능한 시스템으로 다시 라우팅할 수 있도록 하는 시스템 설계 기능입니다. 서버 측면에서 고가용성 시스템을 설정하는 데 필요한 몇 가지 기술이 있습니다. 작업을 재지정할 수 있는 구성 요소가 있어야 하며 장애를 모니터링하고 중단이 감지되면 시스템을 전환하는 메커니즘이 있어야 합니다.

keepalived 데몬을 사용하여 서비스나 시스템을 모니터링하고 문제가 발생할 경우 자동으로 대기 모드로 장애 조치할 수 있습니다. 이 가이드에서는 keepalived를 사용하여 로드 밸런서에 대한 고가용성을 설정하는 방법을 보여줍니다. 두 개의 가능한 로드 밸런서 간에 이동할 수 있는 예약된 IP 주소를 구성합니다. 이들은 각각 두 개의 백엔드 웹 서버 간에 트래픽을 분할하도록 구성됩니다. 기본 로드 밸런서가 다운되면 예약된 IP가 자동으로 두 번째 로드 밸런서로 이동되어 서비스를 재개할 수 있습니다.

참고: 해당 옵션을 평가하려는 경우 로드 밸런서 설정에 대한 가이드입니다.

전제 조건

이 가이드를 완료하려면 DigitalOcean 계정에 4개의 Ubuntu 14.04 서버를 생성해야 합니다. 모든 서버는 동일한 데이터 센터 내에 있어야 하며 사설 네트워킹이 활성화되어 있어야 합니다.

이러한 각 서버에는 sudo 액세스 권한으로 구성된 루트가 아닌 사용자가 필요합니다. Ubuntu 14.04 초기 서버 설정 가이드에 따라 이러한 사용자를 설정하는 방법을 알아볼 수 있습니다.

서버 네트워크 정보 찾기

인프라 구성 요소의 실제 구성을 시작하기 전에 각 서버에 대한 정보를 수집하는 것이 가장 좋습니다.

이 가이드를 완료하려면 서버에 대한 다음 정보가 필요합니다.

  • 웹 서버: 개인 IP 주소
  • 로드 밸런서 개인 및 앵커 IP 주소

사설 IP 주소 찾기

Droplet의 사설 IP 주소를 찾는 가장 쉬운 방법은 curl을 사용하여 DigitalOcean 메타데이터 서비스에서 사설 IP 주소를 가져오는 것입니다. 이 명령은 Droplets 내에서 실행해야 합니다. 각 물방울에 다음을 입력합니다.

  1. curl 169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address && echo

터미널 창에 올바른 IP 주소가 인쇄되어야 합니다.

Output
10.132.20.236

앵커 IP 주소 찾기

"anchor IP\는 예약된 IP가 DigitalOcean 서버에 연결될 때 바인딩되는 로컬 사설 IP 주소입니다. 하이퍼바이저 수준에서 구현되는 일반 eth0 주소의 별칭입니다.

이 값을 가져오는 가장 쉽고 오류가 적은 방법은 DigitalOcean 메타데이터 서비스에서 직접 가져오는 것입니다. curl을 사용하면 다음을 입력하여 각 서버에서 이 끝점에 도달할 수 있습니다.

  1. curl 169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address && echo

앵커 IP는 자체 라인에 인쇄됩니다.

Output
10.17.1.18

웹 서버 설치 및 구성

위의 데이터를 수집한 후 서비스 구성으로 이동할 수 있습니다.

이 설정에서 웹 서버 계층에 대해 선택된 소프트웨어는 상호 교환이 가능합니다. 이 가이드에서는 일반적이고 구성하기 쉬운 Nginx를 사용합니다. Apache 또는 (프로덕션 가능) 언어별 웹 서버가 더 편하다면 대신 사용하십시오. HAProxy는 직접 클라이언트 연결을 처리하는 방식과 유사하게 요청을 처리할 수 있는 백엔드 웹 서버에 클라이언트 요청을 전달합니다.

백엔드 웹 서버를 설정하는 것으로 시작하겠습니다. 이 두 서버는 정확히 동일한 콘텐츠를 제공합니다. 개인 IP 주소를 통한 웹 연결만 허용합니다. 이렇게 하면 나중에 구성할 두 개의 HAProxy 서버 중 하나를 통해 트래픽이 전달되도록 할 수 있습니다.

로드 밸런서 뒤에 웹 서버를 설정하면 몇 개의 동일한 웹 서버 간에 요청 부담을 분산시킬 수 있습니다. 트래픽 요구 사항이 변경되면 이 계층에서 웹 서버를 추가하거나 제거하여 새로운 요구 사항을 충족하도록 쉽게 확장할 수 있습니다.

Nginx 설치

이 기능을 제공하기 위해 웹 서비스 시스템에 Nginx를 설치할 것입니다.

웹 서버로 사용하려는 두 시스템에 sudo 사용자로 로그인하여 시작하십시오. 각 웹 서버에서 로컬 패키지 색인을 업데이트하고 다음을 입력하여 Nginx를 설치합니다.

  1. sudo apt-get update
  2. sudo apt-get install nginx

로드 밸런서의 요청만 허용하도록 Nginx 구성

다음으로 Nginx 인스턴스를 구성합니다. 우리는 Nginx에게 서버의 개인 IP 주소에 대한 요청만 수신하도록 지시하고 싶습니다. 또한 두 로드 밸런서의 개인 IP 주소에서 오는 요청만 처리합니다.

이러한 변경을 수행하려면 각 웹 서버에서 기본 Nginx 서버 블록 파일을 엽니다.

  1. sudo nano /etc/nginx/sites-available/default

시작하려면 listen 지시문을 수정합니다. 포트 80에서 현재 웹 서버의 개인 IP 주소를 수신하도록 listen 지시문을 변경합니다. 추가 listen 줄을 삭제합니다. 다음과 같아야 합니다.

server {
    listen web_server_private_IP:80;

    . . .

그런 다음 두 로드 밸런서의 개인 IP 주소에서 발생하는 트래픽을 허용하기 위해 두 개의 allow 지시문을 설정합니다. 다른 모든 트래픽을 금지하는 deny all 규칙으로 후속 조치를 취할 것입니다.

server {
    listen web_server_private_IP:80;

    allow load_balancer_1_private_IP;
    allow load_balancer_2_private_IP;
    deny all;

    . . .

완료되면 파일을 저장하고 닫습니다.

다음을 입력하여 변경 사항이 유효한 Nginx 구문을 나타내는지 테스트합니다.

  1. sudo nginx -t

문제가 보고되지 않으면 다음을 입력하여 Nginx 데몬을 다시 시작합니다.

  1. sudo service nginx restart

변경 사항 테스트

웹 서버가 올바르게 제한되었는지 테스트하기 위해 다양한 위치에서 curl을 사용하여 요청을 할 수 있습니다.

웹 서버 자체에서 다음을 입력하여 로컬 콘텐츠에 대한 간단한 요청을 시도할 수 있습니다.

  1. curl 127.0.0.1

Nginx 서버 블록 파일에 설정한 제한으로 인해 이 요청은 실제로 거부됩니다.

Output
curl: (7) Failed to connect to 127.0.0.1 port 80: Connection refused

이것은 예상된 것이며 우리가 구현하려고 했던 동작을 반영합니다.

이제 로드 밸런서 중 하나에서 웹 서버의 공용 IP 주소 중 하나를 요청할 수 있습니다.

  1. curl web_server_public_IP

다시 한 번 이것은 실패해야 합니다. 웹 서버는 공용 인터페이스에서 수신 대기하지 않으며 공용 IP 주소를 사용할 때 웹 서버는 로드 밸런서의 요청에서 허용된 개인 IP 주소를 볼 수 없습니다.

Output
curl: (7) Failed to connect to web_server_public_IP port 80: Connection refused

그러나 웹 서버의 개인 IP 주소를 사용하여 요청하도록 호출을 수정하면 올바르게 작동해야 합니다.

  1. curl web_server_private_IP

기본 Nginx index.html 페이지가 반환되어야 합니다.

Output
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> . . .

두 로드 밸런서에서 두 웹 서버로 이를 테스트하십시오. 개인 IP 주소에 대한 각 요청은 성공해야 하지만 공개 주소에 대한 각 요청은 실패해야 합니다.

위의 동작이 시연되면 계속 진행할 수 있습니다. 이제 백엔드 웹 서버 구성이 완료되었습니다.

HAProxy 설치 및 구성

다음으로 HAProxy 로드 밸런서를 설정합니다. 이들은 각각 웹 서버 앞에 위치하며 두 백엔드 서버 간에 요청을 분할합니다. 이러한 로드 밸런서는 완전히 중복됩니다. 주어진 시간에 하나만 트래픽을 수신합니다.

HAProxy 구성은 두 웹 서버 모두에 요청을 전달합니다. 로드 밸런서는 앵커 IP 주소에서 요청을 수신합니다. 앞에서 언급했듯이 이것은 예약된 IP 주소가 Droplet에 연결될 때 바인딩되는 IP 주소입니다. 이렇게 하면 예약된 IP 주소에서 발생하는 트래픽만 전달됩니다.

HAProxy 설치

로드 밸런서에서 수행해야 하는 첫 번째 단계는 haproxy 패키지를 설치하는 것입니다. 기본 우분투 리포지토리에서 찾을 수 있습니다. 로드 밸런서에서 로컬 패키지 인덱스를 업데이트하고 다음을 입력하여 HAProxy를 설치합니다.

  1. sudo apt-get update
  2. sudo apt-get install haproxy

HAProxy 구성

HAProxy를 다룰 때 수정해야 할 첫 번째 항목은 /etc/default/haproxy 파일입니다. 이제 편집기에서 해당 파일을 엽니다.

  1. sudo nano /etc/default/haproxy

이 파일은 HAProxy가 부팅 시 시작될지 여부를 결정합니다. 서버 전원을 켤 때마다 서비스가 자동으로 시작되기를 원하므로 ENABLED 값을 "1”로 변경해야 합니다.

# Set ENABLED to 1 if you want the init script to start haproxy.
ENABLED=1
# Add extra flags here.
#EXTRAOPTS="-de -m 16"

위의 내용을 수정한 후 파일을 저장하고 닫습니다.

다음으로 기본 HAProxy 구성 파일을 열 수 있습니다.

  1. sudo nano /etc/haproxy/haproxy.cfg

조정해야 하는 첫 번째 항목은 HAProxy가 작동할 모드입니다. TCP 또는 계층 4 로드 밸런싱을 구성하려고 합니다. 이렇게 하려면 default 섹션에서 mode 줄을 변경해야 합니다. 또한 로그를 처리하는 바로 다음 옵션을 변경해야 합니다.

. . .

defaults
    log     global
    mode    tcp
    option  tcplog

. . .

파일 끝에서 프런트 엔드 구성을 정의해야 합니다. 이것은 HAProxy가 들어오는 연결을 수신하는 방법을 지시합니다. HAProxy를 로드 밸런서 앵커 IP 주소에 바인딩합니다. 이렇게 하면 예약된 IP 주소에서 발생하는 트래픽을 수신 대기할 수 있습니다. 간단히 하기 위해 프런트 엔드를 "www\라고 부를 것입니다. 또한 트래픽을 전달할 기본 백엔드를 지정합니다(잠시 후에 구성할 예정임).

. . .

defaults
    log     global
    mode    tcp
    option  tcplog

. . .

frontend www
    bind    load_balancer_anchor_IP:80
    default_backend nginx_pool

다음으로 백엔드 섹션을 구성할 수 있습니다. 이것은 HAProxy가 수신하는 트래픽을 전달할 다운스트림 위치를 지정합니다. 우리의 경우 이것은 우리가 구성한 두 Nginx 웹 서버의 사설 IP 주소가 될 것입니다. 전통적인 라운드 로빈 밸런싱을 지정하고 모드를 다시 "tcp\로 설정합니다.

. . .

defaults
    log     global
    mode    tcp
    option  tcplog

. . .

frontend www
    bind load_balancer_anchor_IP:80
    default_backend nginx_pool

backend nginx_pool
    balance roundrobin
    mode tcp
    server web1 web_server_1_private_IP:80 check
    server web2 web_server_2_private_IP:80 check

위의 변경을 마치면 파일을 저장하고 닫습니다.

다음을 입력하여 구성 변경 사항이 유효한 HAProxy 구문을 나타내는지 확인합니다.

  1. sudo haproxy -f /etc/haproxy/haproxy.cfg -c

보고된 오류가 없으면 다음을 입력하여 서비스를 다시 시작하십시오.

  1. sudo service haproxy restart

변경 사항 테스트

curl로 다시 테스트하여 구성이 유효한지 확인할 수 있습니다.

로드 밸런서 서버에서 로컬 호스트, 로드 밸런서 고유의 공용 IP 주소 또는 서버 고유의 사설 IP 주소를 요청하십시오.

  1. curl 127.0.0.1
  2. curl load_balancer_public_IP
  3. curl load_balancer_private_IP

이들은 다음과 유사한 메시지와 함께 모두 실패해야 합니다.

Output
curl: (7) Failed to connect to address port 80: Connection refused

그러나 로드 밸런서의 앵커 IP 주소를 요청하면 성공적으로 완료되어야 합니다.

  1. curl load_balancer_anchor_IP

두 개의 백엔드 웹 서버 중 하나에서 라우팅된 기본 Nginx index.html 페이지가 표시되어야 합니다.

Output
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> . . .

이 동작이 시스템의 동작과 일치하면 로드 밸런서가 올바르게 구성된 것입니다.

Keepalived 빌드 및 설치

이제 실제 서비스가 시작되었습니다. 그러나 활성 로드 밸런서에 문제가 발생하는 경우 트래픽을 리디렉션할 방법이 없기 때문에 인프라의 가용성이 아직 높지 않습니다. 이를 수정하기 위해 로드 밸런서 서버에 keepalived 데몬을 설치합니다. 이는 활성 로드 밸런서를 사용할 수 없게 될 경우 장애 조치 기능을 제공하는 구성 요소입니다.

Ubuntu의 기본 리포지토리에는 keepalived 버전이 있지만 구식이며 구성이 작동하지 않는 몇 가지 버그가 있습니다. 대신 소스에서 최신 버전의 keepalived를 설치합니다.

시작하기 전에 소프트웨어를 빌드하는 데 필요한 종속성을 파악해야 합니다. build-essential 메타 패키지는 필요한 컴파일 도구를 제공하고 libssl-dev 패키지에는 keepalived에 필요한 SSL 개발 라이브러리가 포함되어 있습니다. 구축 대상:

  1. sudo apt-get install build-essential libssl-dev

종속성이 설정되면 keepalived용 tarball을 다운로드할 수 있습니다. 소프트웨어의 최신 버전을 찾으려면 이 페이지를 방문하십시오. 최신 버전을 마우스 오른쪽 버튼으로 클릭하고 링크 주소를 복사합니다. 서버로 돌아가 홈 디렉토리로 이동하고 wget을 사용하여 복사한 링크를 가져옵니다.

  1. cd ~
  2. wget http://www.keepalived.org/software/keepalived-1.2.19.tar.gz

아카이브를 확장하려면 tar 명령을 사용하십시오. 결과 디렉터리로 이동합니다.

  1. tar xzvf keepalived*
  2. cd keepalived*

다음을 입력하여 데몬을 빌드하고 설치합니다.

  1. ./configure
  2. make
  3. sudo make install

이제 두 로드 밸런서 시스템에 데몬이 설치되어야 합니다.

Keepalived Upstart 스크립트 만들기

keepalived 설치는 모든 바이너리와 지원 파일을 우리 시스템의 제자리로 옮겼습니다. 그러나 포함되지 않은 한 부분은 Ubuntu 14.04 시스템용 Upstart 스크립트였습니다.

keepalived 서비스를 처리할 수 있는 매우 간단한 Upstart 스크립트를 만들 수 있습니다. 시작하려면 /etc/init 디렉토리 내에서 keepalived.conf라는 파일을 여십시오.

  1. sudo nano /etc/init/keepalived.conf

내부에서는 keepalived가 제공하는 기능에 대한 간단한 설명부터 시작할 수 있습니다. 포함된 man 페이지의 설명을 사용합니다. 다음으로 서비스를 시작하고 중지해야 하는 런레벨을 지정합니다. 우리는 이 서비스가 모든 정상적인 조건(런레벨 2-5)에서 활성화되고 다른 모든 런레벨(예를 들어 재부팅, 전원 끄기 또는 단일 사용자 모드가 시작될 때)에 대해 중지되기를 원합니다.

description "load-balancing and high-availability service"

start on runlevel [2345]
stop on runlevel [!2345]

이 서비스는 웹 서비스를 계속 사용할 수 있도록 하는 데 필수적이므로 장애 발생 시 이 서비스를 다시 시작하려고 합니다. 그런 다음 서비스를 시작할 실제 exec 줄을 지정할 수 있습니다. Upstart가 pid를 올바르게 추적할 수 있도록 --dont-fork 옵션을 추가해야 합니다.

description "load-balancing and high-availability service"

start on runlevel [2345]
stop on runlevel [!2345]

respawn

exec /usr/local/sbin/keepalived --dont-fork

완료되면 파일을 저장하고 닫습니다.

Keepalived 구성 파일 만들기

Upstart 파일이 준비되었으므로 이제 keepalived 구성으로 넘어갈 수 있습니다.

서비스는 /etc/keepalived 디렉토리에서 구성 파일을 찾습니다. 이제 두 로드 밸런서 모두에서 해당 디렉터리를 생성합니다.

  1. sudo mkdir -p /etc/keepalived

기본 로드 밸런서 구성 생성

그런 다음 기본 서버로 사용하려는 로드 밸런서 서버에서 기본 keepalived 구성 파일을 만듭니다. 데몬은 /etc/keepalived 디렉토리 내에서 keepalived.conf라는 파일을 찾습니다.

  1. sudo nano /etc/keepalived/keepalived.conf

내부에서는 vrrp_script 블록을 열어 HAProxy 서비스에 대한 상태 확인을 정의하는 것으로 시작합니다. 이렇게 하면 keepalived가 로드 밸런서의 장애를 모니터링하여 프로세스가 중단되었음을 알리고 복구 조치를 시작할 수 있습니다.

우리의 수표는 매우 간단합니다. 2초마다 haproxy라는 프로세스가 여전히 pid를 요구하는지 확인합니다.

vrrp_script chk_haproxy {
    script "pidof haproxy"
    interval 2
}

다음으로 vrrp_instance라는 블록을 엽니다. 이것은 keepalived가 고가용성을 구현하는 방법을 정의하는 기본 구성 섹션입니다.

개인 인터페이스인 eth1을 통해 피어와 통신하도록 keepalived에 알리는 것으로 시작하겠습니다. 기본 서버를 구성하고 있으므로 state 구성을 "MASTER”로 설정합니다. 이것은 데몬이 해당 피어에 연결할 수 있을 때까지 keepalived가 사용할 초기 값입니다. 그리고 선거를 치릅니다.

선출하는 동안 priority 옵션은 어떤 구성원이 선출될지 결정하는 데 사용됩니다. 결정은 단순히 이 설정에 대해 가장 높은 번호를 가진 서버를 기반으로 합니다. 기본 서버에 "200\을 사용합니다.

vrrp_script chk_nginx {
    script "pidof nginx"
    interval 2
}

vrrp_instance VI_1 {
    interface eth1
    state MASTER
    priority 200


}

다음으로 두 노드에서 공유할 이 클러스터 그룹의 ID를 할당합니다. 이 예에서는 "33\을 사용합니다. unicast_src_ip를 기본 로드 밸런서의 사설 IP 주소로 설정해야 합니다. unicast_peer를 보조 로드 밸런서의 사설 IP로 설정합니다. 주소:

vrrp_script chk_haproxy {
    script "pidof haproxy"
    interval 2
}

vrrp_instance VI_1 {
    interface eth1
    state MASTER
    priority 200

    virtual_router_id 33
    unicast_src_ip primary_private_IP
    unicast_peer {
        secondary_private_IP
    }


}

다음으로 keepalived 데몬이 서로 통신할 수 있도록 몇 가지 간단한 인증을 설정할 수 있습니다. 이는 연락 중인 피어가 합법적인지 확인하기 위한 기본적인 조치일 뿐입니다. 인증 하위 블록을 만듭니다. 내부에서 auth_type을 설정하여 비밀번호 인증을 지정합니다. auth_pass 매개변수의 경우 두 노드에서 사용할 공유 비밀을 설정하십시오. 안타깝게도 처음 8자만 중요합니다.

vrrp_script chk_haproxy {
    script "pidof haproxy"
    interval 2
}

vrrp_instance VI_1 {
    interface eth1
    state MASTER
    priority 200

    virtual_router_id 33
    unicast_src_ip primary_private_IP
    unicast_peer {
        secondary_private_IP
    }

    authentication {
        auth_type PASS
        auth_pass password
    }


}

다음으로 keepalived에게 로컬 시스템의 상태를 확인하기 위해 chk_haproxy 레이블이 지정된 파일 상단에 생성한 검사를 사용하도록 지시합니다. 마지막으로 이 노드가 쌍의 "마스터\가 될 때마다 실행되는 notify_master 스크립트를 설정합니다. 이 스크립트는 예약된 IP 주소 재할당 트리거를 담당합니다. 이 스크립트를 만들겠습니다. 즉시:

vrrp_script chk_haproxy {
    script "pidof haproxy"
    interval 2
}

vrrp_instance VI_1 {
    interface eth1
    state MASTER
    priority 200

    virtual_router_id 33
    unicast_src_ip primary_private_IP
    unicast_peer {
        secondary_private_IP
    }

    authentication {
        auth_type PASS
        auth_pass password
    }

    track_script {
        chk_haproxy
    }

    notify_master /etc/keepalived/master.sh
}

위의 정보를 설정했으면 파일을 저장하고 닫습니다.

보조 로드 밸런서 구성 생성

다음으로 보조 로드 밸런서에서 컴패니언 스크립트를 생성합니다. 보조 서버의 /etc/keepalived/keepalived.conf에서 파일을 엽니다.

  1. sudo nano /etc/keepalived/keepalived.conf

내부에서 우리가 사용할 스크립트는 기본 서버의 스크립트와 거의 동일합니다. 변경해야 할 항목은 다음과 같습니다.

  • state: 선택이 발생하기 전에 노드가 백업 상태로 초기화되도록 보조 서버에서 "BACKUP\으로 변경되어야 합니다.
  • priority: 주 서버보다 낮은 값으로 설정해야 합니다. 이 가이드에서는 값 "100\을 사용합니다.
  • unicast_src_ip: 보조 서버의 사설 IP 주소여야 합니다.
  • unicast_peer: 기본 서버의 사설 IP 주소를 포함해야 합니다.

이러한 값을 변경하면 보조 서버의 스크립트는 다음과 같아야 합니다.

vrrp_script chk_haproxy {
    script "pidof haproxy"
    interval 2
}

vrrp_instance VI_1 {
    interface eth1
    state BACKUP
    priority 100

    virtual_router_id 33
    unicast_src_ip secondary_private_IP
    unicast_peer {
        primary_private_IP
    }

    authentication {
        auth_type PASS
        auth_pass password
    }

    track_script {
        chk_haproxy
    }

    notify_master /etc/keepalived/master.sh
}

스크립트를 입력하고 적절한 값을 변경했으면 파일을 저장하고 닫습니다.

예약된 IP 전환 스크립트 생성

다음으로 로컬 keepalived 인스턴스가 마스터 서버가 될 때마다 예약된 IP 주소를 현재 Droplet에 재할당하는 데 사용할 수 있는 스크립트 쌍을 만들어야 합니다.

예약된 IP 할당 스크립트 다운로드

먼저 DigitalOcean API를 사용하여 예약된 IP 주소를 Droplet에 재할당하는 데 사용할 수 있는 일반 Python 스크립트(DigitalOcean 커뮤니티 관리자가 작성)를 다운로드합니다. 이 파일을 /usr/local/bin 디렉토리에 다운로드해야 합니다.

  1. cd /usr/local/bin
  2. sudo curl -LO http://do.co/assign-ip

이 스크립트를 사용하면 다음을 실행하여 기존 예약된 IP를 재할당할 수 있습니다.

  1. python /usr/local/bin/assign-ip reserved_ip droplet_ID

이는 계정에 대해 유효한 DigitalOcean API 토큰으로 설정된 DO_TOKEN이라는 환경 변수가 있는 경우에만 작동합니다.

DigitalOcean API 토큰 생성

위의 스크립트를 사용하려면 계정에 DigitalOcean API 토큰을 생성해야 합니다.

제어판에서 상단의 "API\ 링크를 클릭합니다. API 페이지 오른쪽에서 "새 토큰 생성\을 클릭합니다.

다음 페이지에서 토큰 이름을 선택하고 "토큰 생성\ 버튼을 클릭합니다.

API 페이지에 새 토큰이 표시됩니다.

지금 토큰을 복사하십시오. 보안을 위해 나중에 이 토큰을 다시 표시할 방법이 없습니다. 이 토큰을 잃어버리면 이를 파괴하고 다른 토큰을 만들어야 합니다.

인프라에 대해 예약된 IP 구성

다음으로 서버에 사용할 예약된 IP 주소를 생성하고 할당합니다.

DigitalOcean 제어판에서 "Networking\ 탭을 클릭하고 "Reserved IPs\ 탐색 항목을 선택합니다. 초기 할당 메뉴에서 기본 로드 밸런서를 선택합니다.

새 예약 IP 주소가 계정에 생성되고 지정된 Droplet에 할당됩니다.

웹 브라우저에서 예약된 IP를 방문하면 백엔드 웹 서버 중 하나에서 제공되는 기본 Nginx 페이지가 표시되어야 합니다.

예약된 IP 주소를 아래로 복사합니다. 아래 스크립트에서 이 값이 필요합니다.

래퍼 스크립트 만들기

이제 올바른 자격 증명으로 /usr/local/bin/assign-ip 스크립트를 호출할 래퍼 스크립트를 만드는 데 필요한 항목이 있습니다.

이제 다음을 입력하여 두 로드 밸런서 모두에서 파일을 생성합니다.

  1. sudo nano /etc/keepalived/master.sh

내부에서 방금 만든 API 토큰을 보유하는 DO_TOKEN이라는 변수를 할당하고 내보내는 것으로 시작합니다. 그 아래에 예약된 IP 주소를 보유하는 IP라는 변수를 할당할 수 있습니다.

export DO_TOKEN='digitalocean_api_token'
IP='reserved_ip_addr'

다음으로 curl을 사용하여 메타데이터 서비스에 현재 있는 서버의 Droplet ID를 요청합니다. 이것은 ID라는 변수에 할당됩니다. 또한 이 Droplet에 현재 예약된 IP 주소가 할당되어 있는지도 묻습니다. 해당 요청의 결과를 HAS_RESERVED_IP라는 변수에 저장합니다.

export DO_TOKEN='digitalocean_api_token'
IP='reserved_ip_addr'
ID=$(curl -s http://169.254.169.254/metadata/v1/id)
HAS_RESERVED_IP=$(curl -s http://169.254.169.254/metadata/v1/reserved_ip/ipv4/active)

이제 위의 변수를 사용하여 assign-ip 스크립트를 호출할 수 있습니다. 예약된 IP가 아직 Droplet과 연결되지 않은 경우에만 스크립트를 호출합니다. 이렇게 하면 API 호출을 최소화하고 마스터 상태가 서버 간에 빠르게 전환되는 경우 API에 대한 충돌 요청을 방지하는 데 도움이 됩니다.

예약된 IP에 이미 진행 중인 이벤트가 있는 경우를 처리하기 위해 assign-ip 스크립트를 몇 번 재시도합니다. 아래에서는 각 호출 사이에 3초 간격으로 스크립트를 10번 실행하려고 시도합니다. 예약된 IP 이동이 성공하면 루프가 즉시 종료됩니다.

export DO_TOKEN='digitalocean_api_token'
IP='reserved_ip_addr'
ID=$(curl -s http://169.254.169.254/metadata/v1/id)
HAS_RESERVED_IP=$(curl -s http://169.254.169.254/metadata/v1/reserved_ip/ipv4/active)

if [ $HAS_RESERVED_IP = "false" ]; then
    n=0
    while [ $n -lt 10 ]
    do
        python /usr/local/bin/assign-ip $IP $ID && break
        n=$((n+1))
        sleep 3
    done
fi

완료되면 파일을 저장하고 닫습니다.

이제 keepalived가 호출할 수 있도록 스크립트를 실행 가능하게 만들기만 하면 됩니다.

  1. sudo chmod +x /etc/keepalived/master.sh

Keepalived 서비스 시작 및 장애 조치 테스트

keepalived 데몬과 모든 관련 스크립트가 이제 완전히 구성되어야 합니다. 다음을 입력하여 두 로드 밸런서에서 서비스를 시작할 수 있습니다.

  1. sudo start keepalived

서비스는 각 서버에서 시작되고 피어에 연결하여 우리가 구성한 공유 비밀로 인증해야 합니다. 각 데몬은 로컬 HAProxy 프로세스를 모니터링하고 원격 keepalived 프로세스의 신호를 수신합니다.

현재 할당된 예약된 IP 주소가 있어야 하는 기본 로드 밸런서는 차례로 각 백엔드 Nginx 서버로 요청을 보냅니다. 일반적으로 적용되는 몇 가지 간단한 세션 고정성이 있으므로 웹 브라우저를 통해 요청을 할 때 동일한 백엔드를 얻을 가능성이 높아집니다.

기본 로드 밸런서에서 HAProxy를 끄기만 하면 간단한 방법으로 장애 조치를 테스트할 수 있습니다.

  1. sudo service haproxy stop

브라우저에서 예약된 IP 주소를 방문하면 잠시 페이지를 찾을 수 없다는 오류가 표시될 수 있습니다.

http://reserved_IP_addr

페이지를 몇 번 새로 고치면 잠시 후 기본 Nginx 페이지가 다시 나타납니다.

우리의 HAProxy 서비스는 여전히 기본 로드 밸런서에서 다운되어 있으므로 이는 보조 로드 밸런서가 인계되었음을 나타냅니다. keepalived를 사용하여 보조 서버는 서비스 중단이 발생했음을 확인할 수 있었습니다. 그런 다음 "마스터\ 상태로 전환하고 DigitalOcean API를 사용하여 예약된 IP를 요청했습니다.

이제 기본 로드 밸런서에서 HAProxy를 다시 시작할 수 있습니다.

  1. sudo service haproxy start

기본 로드 밸런서는 잠시 후에 예약된 IP 주소의 제어권을 다시 얻습니다. 하지만 이것은 사용자에게 다소 투명해야 합니다.

전환 시각화

로드 밸런서 간의 전환을 더 잘 시각화하기 위해 전환 중에 일부 서버 로그를 모니터링할 수 있습니다.

사용 중인 프록시 서버에 대한 정보는 클라이언트로 반환되지 않으므로 로그를 볼 수 있는 가장 좋은 위치는 실제 백엔드 웹 서버입니다. 이러한 각 서버는 클라이언트가 자산을 요청하는 로그를 유지 관리해야 합니다. Nginx 서비스의 관점에서 클라이언트는 실제 클라이언트를 대신하여 요청을 하는 로드 밸런서입니다.

웹 서버의 로그 추적

각 백엔드 웹 서버에서 /var/log/nginx/access.log 위치를 tail할 수 있습니다. 그러면 서버에 대한 각 요청이 표시됩니다. 로드 밸런서는 라운드 로빈 회전을 사용하여 트래픽을 균등하게 분할하므로 각 백엔드 웹 서버는 요청의 약 절반을 볼 수 있습니다.

다행히 클라이언트 주소는 액세스 로그의 첫 번째 필드입니다. 간단한 awk 명령을 사용하여 값을 추출할 수 있습니다. 두 Nginx 웹 서버 모두에서 다음을 실행합니다.

  1. sudo tail -f /var/log/nginx/access.log | awk '{print $1;}'

이들은 대부분 단일 주소를 표시할 것입니다.

Output
. . . primary_lb_private_IP primary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP

서버 IP 주소를 참조하면 이러한 주소가 대부분 기본 로드 밸런서에서 온다는 것을 알 수 있습니다. HAProxy가 구현하는 간단한 세션 고정성으로 인해 실제 배포는 약간 다를 수 있습니다.

두 웹 서버 모두에서 tail 명령을 계속 실행하십시오.

예약된 IP에 대한 요청 자동화

이제 로컬 컴퓨터에서 예약된 IP 주소의 웹 콘텐츠를 2초에 한 번씩 요청합니다. 이를 통해 로드 밸런서 변경이 발생하는 것을 쉽게 확인할 수 있습니다. 로컬 터미널에서 다음을 입력합니다(사용 중인 로드 밸런서에 관계없이 동일해야 하므로 실제 응답을 버립니다).

  1. while true; do curl -s -o /dev/null reserved_IP; sleep 2; done

웹 서버에서 새로운 요청이 들어오는 것을 볼 수 있어야 합니다. 웹 브라우저를 통해 이루어진 요청과 달리 간단한 curl 요청은 동일한 세션 고정성을 나타내지 않습니다. 백엔드 웹 서버에 대한 요청이 더 균등하게 분할되어야 합니다.

기본 로드 밸런서에서 HAProxy 서비스 중단

이제 기본 로드 밸런서에서 HAProxy 서비스를 다시 종료할 수 있습니다.

  1. sudo service haproxy stop

몇 초 후 웹 서버에서 기본 로드 밸런서의 개인 IP 주소에서 보조 로드 밸런서의 개인 IP 주소로 전환되는 IP 목록이 표시되어야 합니다.

Output
. . . primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP

모든 새 요청은 보조 로드 밸런서에서 이루어집니다.

이제 기본 로드 밸런서에서 HAProxy 인스턴스를 다시 시작합니다.

  1. sudo service haproxy start

클라이언트 요청이 몇 초 내에 기본 로드 밸런서의 개인 IP 주소로 다시 전환되는 것을 볼 수 있습니다.

Output
. . . primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP secondary_lb_private_IP primary_lb_private_IP primary_lb_private_IP primary_lb_private_IP

기본 서버는 예약된 IP 주소의 제어권을 되찾았고 인프라의 기본 로드 밸런서로서의 작업을 재개했습니다.

실제 클라이언트 IP 주소를 기록하도록 Nginx 구성

보시다시피 Nginx 액세스 로그는 모든 클라이언트 요청이 원래 요청한 클라이언트(즉, 로컬 머신)의 실제 IP 주소가 아니라 현재 로드 밸런서의 사설 IP 주소에서 온 것임을 보여줍니다. 로드 밸런서 서버 대신 원래 클라이언트의 IP 주소를 기록하는 것이 유용한 경우가 많습니다. 이는 모든 백엔드 웹 서버에서 Nginx 구성을 약간 변경하여 쉽게 달성할 수 있습니다.

두 웹 서버 모두에서 편집기에서 nginx.conf 파일을 엽니다.

  1. sudo nano /etc/nginx/nginx.conf

"로깅 설정\ 섹션(http 블록 내)을 찾아 다음 줄을 추가합니다.

log_format haproxy_log 'ProxyIP: $remote_addr - ClientIP: $http_x_forwarded_for - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent "$http_referer" ' '"$http_user_agent"';

저장 및 종료. 이것은 haproxy_log라는 새로운 로그 형식을 지정하며, 이는 $http_x_forwarded_for 값(원래 요청을 한 클라이언트의 IP 주소)을 기본 액세스 로그 항목에 추가합니다. 역방향 프록시 로드 밸런서(즉, 활성 로드 밸런서 서버)의 IP 주소인 $remote_addr도 포함합니다.

다음으로 이 새로운 로그 형식을 사용하려면 기본 서버 블록에 행을 추가해야 합니다.

두 웹 서버에서 기본 서버 구성을 엽니다.

  1. sudo nano /etc/nginx/sites-available/default

server 블록 내에서(listen 지시문 바로 아래가 좋음) 다음 줄을 추가합니다.

        access_log /var/log/nginx/access.log haproxy_log;

저장 및 종료. 이는 Nginx에게 위에서 생성한 haproxy_log 로그 형식을 사용하여 액세스 로그를 작성하도록 지시합니다.

두 웹 서버 모두에서 Nginx를 다시 시작하여 변경 사항을 적용합니다.

  1. sudo service nginx restart

이제 Nginx 액세스 로그에 요청을 보내는 클라이언트의 실제 IP 주소가 포함되어야 합니다. 이전 섹션에서 했던 것처럼 앱 서버의 로그를 테일링하여 이를 확인하십시오. 로그 항목은 다음과 같아야 합니다.

New Nginx access logs:
. . . ProxyIP: load_balancer_private_IP - ClientIP: local_machine_IP - - [05/Nov/2015:15:05:53 -0500] "GET / HTTP/1.1" 200 43 "-" "curl/7.43.0" . . .

로그가 좋아 보인다면 모든 준비가 된 것입니다!

결론

이 가이드에서는 고가용성 로드 밸런싱 인프라를 설정하는 전체 프로세스를 살펴보았습니다. 이 구성은 활성 HAProxy 서버가 백엔드의 웹 서버 풀에 부하를 분산할 수 있기 때문에 잘 작동합니다. 수요가 증가하거나 감소함에 따라 이 풀을 쉽게 확장할 수 있습니다.

예약된 IP 및 keepalived 구성은 로드 밸런싱 레이어에서 단일 실패 지점을 제거하여 기본 로드 밸런서가 완전히 실패한 경우에도 서비스가 계속 작동할 수 있도록 합니다. 이 구성은 상당히 유연하며 HAProxy 서버 뒤에 선호하는 웹 스택을 설정하여 자체 애플리케이션 환경에 맞게 조정할 수 있습니다.