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


소개

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

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

전제 조건

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

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

시작할 준비가 되면 루트가 아닌 사용자로 두 서버 모두에 로그인하십시오.

Nginx 설치 및 구성

keepalived는 로드 밸런서를 모니터링하고 장애 조치하는 데 자주 사용되지만 운영 복잡성을 줄이기 위해 이 가이드에서는 Nginx를 간단한 웹 서버로 사용합니다.

각 서버에서 로컬 패키지 색인을 업데이트하여 시작하십시오. 그런 다음 Nginx를 설치할 수 있습니다.

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

대부분의 경우 고가용성 설정을 위해 두 서버가 정확히 동일한 콘텐츠를 제공하기를 원할 것입니다. 그러나 명확성을 위해 이 가이드에서는 Nginx를 사용하여 주어진 시간에 요청을 처리하는 두 서버를 표시합니다. 이를 위해 각 호스트에서 기본 index.html 페이지를 변경합니다. 지금 파일 열기:

  1. sudo nano /usr/share/nginx/html/index.html

첫 번째 서버에서 파일 내용을 다음으로 바꿉니다.

<h1>Primary</h1>

두 번째 서버에서 파일 내용을 다음으로 바꿉니다.

<h1>Secondary</h1>

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

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

서버의 사설 IP 주소 수집

구성 파일을 만들기 전에 두 서버의 사설 IP 주소를 찾아야 합니다. DigitalOcean 서버에서 다음을 입력하여 메타데이터 서비스를 통해 개인 IP 주소를 얻을 수 있습니다.

  1. curl http://169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address && echo
Output
10.132.7.107

이는 iproute2 도구에서 다음을 입력하여 찾을 수도 있습니다.

  1. ip -4 addr show dev eth1

찾고 있는 값은 여기에서 찾을 수 있습니다.

Output
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 10.132.7.107/16 brd 10.132.255.255 scope global eth1 valid_lft forever preferred_lft forever

두 시스템 모두에서 이 값을 복사합니다. 아래 구성 파일 내에서 이러한 주소를 참조해야 합니다.

주 서버 구성 생성

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

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

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

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

vrrp_script chk_nginx {
    script "pidof nginx"
    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_nginx {
    script "pidof nginx"
    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_nginx {
    script "pidof nginx"
    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_nginx 레이블이 지정된 파일 상단에 생성한 루틴을 사용하도록 지시합니다. 마지막으로 이 노드가 쌍의 "마스터\가 될 때마다 실행되는 notify_master 스크립트를 설정합니다. 이 스크립트는 예약된 IP 주소 재할당 트리거를 담당합니다. 이 스크립트를 만들겠습니다. 즉시:

vrrp_script chk_nginx {
    script "pidof nginx"
    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_nginx
    }

    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_nginx {
    script "pidof nginx"
    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_nginx
    }

    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\ 탐색 항목을 선택합니다. "기본\ 서버로 할당한 목록에서 Droplet을 선택합니다.

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

웹 브라우저에서 예약된 IP를 방문하면 "primary\ 서버 index.html 페이지가 표시됩니다.

예약된 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

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

두 서버가 모두 정상일 때 웹 브라우저에서 예약된 IP를 방문하면 기본 서버의 Nginx 페이지로 이동해야 합니다.

이제 구성의 장애 조치 기능을 테스트할 준비가 되었습니다.

장애 조치는 다음 조건 중 하나가 발생할 때 발생해야 합니다.

  • 기본 서버의 Nginx 상태 검사에서 Nginx가 더 이상 실행되지 않는다고 표시되는 경우. 이 경우 기본 서버의 keepalived 데몬은 "fault\ 상태가 됩니다. 이 데몬은 마스터 상태로 전환하고 예약된 IP를 요청해야 함을 보조 서버에 알립니다.
  • 보조 서버가 주 서버에 대한 keepalived 연결이 끊긴 경우. 보조 서버가 어떤 이유로든 기본 서버에 연결할 수 없는 경우 "마스터\ 상태로 전환하고 예약된 IP를 요청하려고 시도합니다.

기본 서버가 나중에 복구되면 새 선택을 시작하기 때문에 마스터 상태로 다시 전환하고 예약된 IP를 회수합니다(여전히 우선 순위가 가장 높음).

Nginx 실패 테스트

기본 서버에서 Nginx 서비스를 중지하여 첫 번째 조건을 테스트할 수 있습니다.

  1. sudo service nginx stop

웹 브라우저를 새로 고치면 처음에 페이지를 사용할 수 없다는 응답을 받을 수 있습니다.

그러나 몇 초 후에 페이지를 몇 번 새로 고치면 보조 서버가 예약된 IP 주소를 요청한 것을 볼 수 있습니다.

기본 서버에서 Nginx 데몬을 다시 시작하여 오류를 복구할 수 있습니다.

  1. sudo service nginx start

몇 초 후에 페이지를 새로고침하면 기본 서버가 예약된 IP의 소유권을 다시 되찾은 것을 확인할 수 있습니다.

테스트 서버 실패

테스트해야 하는 다른 시나리오는 보조 서버가 기본 서버에 연결할 수 없는 경우 마스터 상태로 올바르게 전환되는지 여부입니다. 이를 테스트하기 위해 마스터 서버를 재부팅할 수 있습니다.

  1. sudo reboot

다시 말하지만 처음에는 예약된 IP 주소에서 서비스 중단을 확인해야 합니다.

몇 초 후 보조 서버가 요청을 선택합니다.

잠시 후 기본 서버가 재부팅을 완료하면 IP 주소를 회수합니다.

이것은 두 번째 실패 시나리오를 확인합니다.

결론

이 가이드에서는 keepalived, DigitalOcean API 및 Reserved IP 주소를 사용하여 고가용성 웹 서버 환경을 구성했습니다. 실제 인프라는 다소 단순했지만 서비스 가용성과 가동 시간이 중요한 모든 유형의 인프라에 개념을 적용할 수 있습니다.