HAProxy로 HA화된 Elasticsearch 클러스터 구축

이 기사는 TUT CDSL Advent Calendar 2019 - Adventar의 18 일째입니다.

소개



실험실에있는 ESXi에 Elasticsearch 클러스터를 구축했습니다.
선생님으로부터 중복을 고려한 구축을 제안되었으므로, SPOF의 배제를 목표로 했습니다.

설정 파일은 다음과 같습니다.

VM 사양



문서을 살펴보면 다음 사양이 최소화되었습니다.
  • 메모리 : 8GB 이상 (편안하게 사용하면 16GB)
  • CPU: 2-8 코어
  • 저장 : SSD와 같은 빠른 녀석 사용 (15k RPM)

  • 위를 참고로 다음을 할당했습니다.
  • 로드 밸런서: 2대
  • CPU: 2 [core]
  • RAM: 2 [GB]
  • Storage: 50[GB]

  • Elasticsearch 노드: 4개
  • CPU: 4 [core]
  • RAM: 12 [GB]
  • Storage: 120[GB]




  • 로드 밸런서 VM



    HAProxy



    로드 밸런서에는 HAProxy를 사용했습니다. HAProxy는 헬스 체크의 조건을 세밀하게 설정할 수 있으며, 인터넷상에 정보가 많이 있기 때문에 채용했습니다. 또한 Metricbeat은 HAProxy 통계를 수집하여 Elasticsearch에 보냈습니다.

    다음은 HAProxy의 Elasticsearch용 설정입니다.
    ##
    # Elasticsearch
    ##
    
    defaults
        timeout connect  5000
        timeout client  10000
        timeout server  10000
    
    frontend elastic
        bind :9200
        mode http
        acl is_delete method DELETE
        http-request deny if is_delete
        default_backend elastic
    
    backend elastic
        mode http
        option forwardfor
        balance roundrobin
        option httpclose
        server elasticsearch-j1 elasticsearch-j1.a910.tak-cslab.org:9200 weight 1 check inter 1000 rise 5 fall 1
        server elasticsearch-j2 elasticsearch-j2.a910.tak-cslab.org:9200 weight 1 check inter 1000 rise 5 fall 1
        server elasticsearch-m1 elasticsearch-m1.a910.tak-cslab.org:9200 weight 1 check inter 1000 rise 5 fall 1
        server elasticsearch-m2 elasticsearch-m2.a910.tak-cslab.org:9200 weight 1 check inter 1000 rise 5 fall 1
    

    keepalived



    로드 밸런서 중복을 위해 keepalived를 도입했습니다. 핫 스탠바이는 자원 효율이 나쁘기 때문에 항상 2대를 가동시키고 있습니다. 다음 기사를 참고로했습니다.

    keepalived를 통한 서버 중복 정보 | GMO Ad Partners Group TECH BLOG byGMO
    ! Configuration File for keepalived
    vrrp_script chk_haproxy {
        script "systemctl is-active haproxy"
    }
    
    vrrp_instance VI_1 {
        state MASTER
        ! もう1台では以下を50に設定
        priority 100
        interface ens160
        garp_master_delay 10
        virtual_router_id 31
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass XXXXXXXXXX
        }
        virtual_ipaddress {
            192.168.100.10
        }
    }
    
    vrrp_instance VI_2 {
        state BACKUP
        ! もう1台では以下を100に設定
        priority 50
        interface ens160
        virtual_router_id 32
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass XXXXXXXXXX
        }
        virtual_ipaddress {
            192.168.100.11
        }
        track_script {
            chk_haproxy
        }
    }
    

    또한 단일 FQDN으로 여러 리소스를 참조 할 수 있도록 DNS 라운드 로빈을 도입했습니다.
    $ nslookup elasticsearch-edge
    192.168.100.11
    $ nslookup elasticsearch-edge
    192.168.100.10
    

    Elasticsearch 노드 VM



    각 노드마다 Kibana, Elasticsearch, Logstash가 도입되었습니다. Logstash는 * Beats의 데이터와 Syslog의 데이터를 허용합니다.



    Elasticsearch



    각 노드는 Master Eligible Node와 Data Node를 겸하고 있습니다.
    cluster.name: logging-main
    node.name: ${HOSTNAME}
    node.master: true
    node.data: true
    path.data: /var/lib/elasticsearch
    path.logs: /var/log/elasticsearch
    bootstrap.memory_lock: true
    network.host: 0.0.0.0
    http.port: 9200
    discovery.seed_hosts:
    - elasticsearch-m1.a910.tak-cslab.org
    - elasticsearch-m2.a910.tak-cslab.org
    - elasticsearch-j1.a910.tak-cslab.org
    - elasticsearch-j2.a910.tak-cslab.org
    cluster.initial_master_nodes:
    - elasticsearch-m1
    - elasticsearch-m2
    - elasticsearch-j1
    - elasticsearch-j2
    
    http.cors.enabled: true
    http.cors.allow-origin: "*"
    

    Logstash



    Syslog를 Logstash에서 수신하도록 다음 Config (발췌)를 작성했습니다.
    input {
      tcp {
        port => 5000
        type => syslog
      }
      udp {
        port => 5000
        type => syslog
      }
    }
    
    filter {
      if [type] == "syslog" {
        grok {
          patterns_dir => ["/etc/logstash/pattern.d"]
          match => { "message" => "%{MYSYSLOG}" }
          add_field => [ "received_at", "%{@timestamp}" ]
          add_field => [ "received_from", "%{host}" ]
        }
        date {
          match => [ "syslog_timestamp", "MMM  d HH:mm:ss", "MMM dd HH:mm:ss" ]
        }
      }
    }
    
    output {
      if [type] == "syslog" {
        elasticsearch {
          hosts => ["localhost:9200"]
          index => "syslog-%{+YYYY.MM.dd}"
        }
      }
    }
    

    grok 패턴은 다음과 같습니다.
    MYSYSLOG %{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}
    

    참고 링크


  • Elasticsearch 클러스터 개요
  • Hardware | Elasticsearch: The Definitive Guide [2.x] | Elastic
  • 좋은 웹페이지 즐겨찾기