Elasticsearch

ES rolling restart (vm 정지 & 시작)

eden.do 2022. 9. 22. 14:49

코드 작성 배경

ceph library 이슈로 vm 재부팅이 필요하여 ES vm들의 정지 & 시작을 진행했습니다. 커맨드에서 reboot은 ceph 라이브러리 버그를 수정하지 못하여 콘솔 상에서 vm들의 재부팅(shelve & unshelve) 이 필요했습니다. ES rolling restart 코드를 이용하여 전체 ES 서비스의 상태를 유지하면서 서버를 하나씩 재부팅을 진행하였습니다.

rolling restart를 진행하는 이유는 샤드 할당 disable 처리를 하지 않고 elasticsearch 서비스를 재시작하게 되면 해당 서버에 할당되어 있던 모든 인덱스가 다른 서버로 재할당 되는 과정이 생기면서 불필요한 I/O가 매우 많이 발생하게 됩니다. 이러한 상황을 방지하기 위해 rolling restart를 진행합니다. 

작성 코드 

# ES 클러스터 상태 확인 (yellow 상태는 인덱스의 여러 레플리카 중 하나라도 살아있으면 yellow, primary와 replica 둘 다 살아 있으면 green, 둘 다 죽으면 Red)
- name: check cluster health green status
  uri:
    url: http://localhost:9200/_cluster/health
    method: "GET"
  register: response
  until: "response.json.status == 'green'"
  retries: 1440
  delay: 60
 
# 메신저 알람 전송
- name: send watchtower alarm
  shell: 'curl -XPOST http://xxxxx.xxx -d "to=10221&msg=(멘붕) {{ inventory_hostname.split(".")[0] }} will be removed. rolling restart starting"'

# LB 관련 설정 확인
- name: check for dsrctl config file
  stat:
    path: /etc/dsrctl.conf
  register: dsrctl
 
#LB 관련 설정이 있으면 stop 처리
- name: dsrctl stop with file if exists
  shell: dsrctl stop; sleep 2
  when: dsrctl.stat.exists
 
# 샤드 할당을 disable 처리, transient 옵션은 일시적인 옵션이고, 클러스터가 재기동되면 해당 옵션은 사라진다.
# Transient – Changes that will not persist after a full cluster restart
# Persistent – Changes that will be saved after a full cluster restart
# 샤드 할당을 허용할 샤드 종류는 아래와 같고 new_primaries는 새로운 인덱스에 대한 프라이머리 샤드만 할당을 허용하도록 한다.
# all - (default) Allows shard allocation for all kinds of shards.
# primaries - Allows shard allocation only for primary shards.
# new_primaries - Allows shard allocation only for primary shards for new indices.
# none - No shard allocations of any kind are allowed for any indices.
- name: disable shard allocation
  uri:
    url: http://localhost:9200/_cluster/settings
    method: "PUT"
    body_format: json
    body:
      transient:
        cluster.routing.allocation.enable: "new_primaries"
 
#노드 당 동시에 복구되는 샤드 수를 128로 설정하였다. 
- name: disable shard allocation, concurrent_recoveries set 128
  uri:
    url: http://localhost:9200/_cluster/settings
    method: "PUT"
    body_format: json
    body:
      transient:
        cluster.routing.allocation.node_concurrent_recoveries: "128"

# 클러스터에서 정상적으로 제거하지 않는 노드를 다시 시작하기 전에, synced_flush를 수행하면 모든 인덱스에 동기화 ID가 배치되며 해당 인덱스에 쓰지 않는 한 해당 샤드의 복구 시간이 빨라진다.
- name: synced flush
  uri:
    url: http://localhost:9200/_flush/synced
    method: "POST"
  ignore_errors: yes
 
# ES stop
- name: stop elasticsearch service
  become: yes
  systemd:
    name: elasticsearch
    state: stopped
 
# swap memory에 데이터가 남아 있을 수 있으므로 reset 시켜준다.
- name: reset swap
  shell: /usr/sbin/swapoff -a && /usr/sbin/swapon -a
 
# [작업 진행] vm이 reboot 될 때까지 기다림 -> 이 때 콘솔로 reboot 작업 진행한다.
- name: reboot vm
  wait_for_connection:
    delay: "140"
    timeout: "145"

# ES 서비스를 시작한다. 
- name: start elasticsearch service
  become: yes
  systemd:
    name: elasticsearch
    state: started
 
# node가 시작되기까지 기다린다. 
- name: wait for node to start
  shell: curl -I -s -m 2 http://localhost:9200 | head -n 1
  register: result
  until: result.stdout == "HTTP/1.1 200 OK"
  retries: 10
  delay: 60
 
# node가 클러스터에 join되었는지를 확인한다. 
# host name과 server name이 다른 경우가 있어 ansible_hostname (remote machine에서 hostname을 입력했을 때의 결과값) 을 이용.
- name: confirm the node joins the cluster
  shell: "curl -s -m 2 'http://localhost:9200/_cat/nodes?h=name' | grep -E '^{{ ansible_hostname}}$'"
  register: result
  until: result.rc == 0
  retries: 10
  delay: 60
 
# 샤드 할당 옵션을 변경한다. (기본으로 모든 샤드 할당을 가능하도록) 
- name: enable shard allocation
  uri:
    url: http://localhost:9200/_cluster/settings
    method: "PUT"
    body_format: json
    body:
      transient:
        cluster.routing.allocation.enable: null
 
# cluster health 체크 (할당되지 않은 샤드들이 전부 재할당될 때까지 기다림)
- name: wait for cluster health to green
  uri:
    url: http://localhost:9200/_cluster/health
    method: "GET"
  register: response
  until: "response.json.status == 'green'"
  retries: 1440
  delay: 60
 
# 노드 당 동시에 복구되는 샤드 수 해제
- name: concurrent_recoveries set null
  uri:
    url: http://localhost:9200/_cluster/settings
    method: "PUT"
    body_format: json
    body:
      transient:
        cluster.routing.allocation.node_concurrent_recoveries: null
 
# dsr 설정이 되어 있다면 stop 시켜놓은 dsrctl 재시작
- name: check for dsrctl config file
  stat:
    path: /etc/dsrctl.conf
  register: dsrctl
 
- name: dsrctl start with file if exists
  shell: dsrctl start; sleep 2
  when: dsrctl.stat.exists

# 메신저에 알람 전송
- name: send watchtower alarm
  shell: 'curl -XPOST http://xxxxxx.xxx.xxx -d "to=10221&msg=(하하) {{ inventory_hostname.split(".")[0] }} rolling restart completed "'

 

site.yml → 아래 내용 추가하였고 hosts 파일에 [rollrs-node] 로 reboot하려는 서버들 추가

- name: rolling restart
  hosts: rollrs-node
  serial: 1
  roles:
    - rollrs_reboot

 

[참고]

rolling restart 과정 : https://ohjongsung.io/2018/08/04/%EC%97%98%EB%9D%BC%EC%8A%A4%ED%8B%B1-%EC%84%9C%EC%B9%98-%EC%9E%AC%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-rolling-restarts

 

엘라스틱 서치 재시작하기 - Rolling Restarts

엘라스틱 서치 버전 업그레이드 또는 서버 OS 나 하드웨어 업그레이드 등의 이유로 서비스를 중단해야할 경우가 생긴다. 하지만 무중단 서비스를 지향한다면 엘라스틱서치 클러스터 전체가 아

ohjongsung.io

클러스터 상태 확인 : https://gruuuuu.github.io/elk-starter/elk-starter02/

 

02.Configuring Cluster

1. Overview 이번 문서에서는 elasticsearch의 클러스터 상태를 확인해보겠습니다.

gruuuuu.github.io

ansible wait for reboot, wait for connection : https://lazisimlee.tistory.com/22

 

Ansible Reboot system and wait_for reboot to complete | Devops Junction

ansible wait_for reboot to complete and proceed. ansible provides wait_for module with async connection you can reboot the remote server and wait while it is being rebooted without closing the connection. ansible wait_for reboot to be completed, before pro

www.middlewareinventory.com