Profile picture

[Docker] Zabbix로 서버 모니터링 및 알림 보내기

JaehyoJJAng2024년 02월 23일

▶︎ Zabbix

Zabbix는 엔터프라이즈 수준의 오픈 소스 모니터링 솔루션으로 네트워크와 서비스, 애플리케이션, 서버 등 IT 인프라의 상태를 실시간으로 모니터링하고 관리하는데에 사용된다.

zabbix는 다양한 모니터링 메트릭을 수집하고, 수집된 메트릭을 시각화하며, 장애 발생 시 알림을 발생 시키는 등의 다양한 기능을 제공한다.

그러면 zabbix를 Docker로 구축해보도록 하자.


▶︎ 실습 환경

  • Proxmox VE 8
    • VM OS: Ubuntu 22.04
  • Docker
  • Docker Compose

▶︎ Zabbix 구축


‣ 설치 순서

zabbix를 도커로 구축하기 위해서는 5개의 컨테이너가 필요하다.


1. mysql

  • HOST DB
  • mysql과 같은 호스트 DB가 zabbix-server-mysql 컨테이너와는 별도로 존재 해야함.

2. zabbix-server-mysql

  • zabbix 서버의 백엔드 db 역할 수행

3. zabbix-web-nginx-mysql

  • mysql 데이터베이스를 지원하는 nginx 웹 서버 기반의 zabbix 웹 인터페이스

4. zabbix-java-gateway

  • java 모니터링을 위한 서비스로 필요에 따라 설치함.

5. zabbix-agent (테스트용 컨테이너)

  • 클라이언트에 설치되는 것으로 OS와 연동하여 데이터를 수집
  • 이번 실습에서는 테스트를 위해 zabbix-agent 컨테이너를 띄워 정상적으로 데이터가 수집되는지 확인

‣ 이미지 다운로드


zabbix 공식 이미지 저장소에서 컨테이너 이미지 pull

docker pull mysql
docker pull zabbix/zabbix-server-mysql
docker pull zabbix/zabbix-web-nginx-mysql
docker pull zabbix/zabbix-java-gateway
docker pull zabbix/zabbix-agent

이미지가 정상적으로 다운로드 됐는지 확인

docker images | grep -E "^zabbix|mysql"

image


‣ 방화벽 설정

서버에 방화벽 정책이 명시되어 있는 경우

하기 포트를 오픈해주어야 함.

web: 80/TCP
mysql: 3306/TCP
zabbix server: 10051/TCP
zabbix agent: 10050/TCP
zabbix-java-gateway: 10052/TCP

‣ 컨테이너 생성

include 키워드를 사용하여 zabbix 구동에 필요한 각 컨테이너별 YAML 작성

~/zabbix/docker-compose.yaml

version: "3.9"

include:
  - "composes/mysql-server.yaml"
  - "composes/zabbix-java-gateway.yaml"
  - "composes/zabbix-server-mysql.yaml"
  - "composes/zabbix-web-nginx-mysql.yaml"
  - "composes/zabbix-agent.yaml"

networks:
  zabbix-net:
    driver: bridge
    external: false
  
volumes:
  mysql-server: {}

1. host용 MySQL

~/zabbix/composes/mysql-server.yaml

services:
  mysql-server:
    image: mysql:8.0-oracle
    restart: always
    volumes:
      - type: volume
        source: mysql-server
        target: "/var/lib/mysql"
    environment:
      MYSQL_DATABASE: "zabbix"
      MYSQL_USER: "zabbix"
      MYSQL_PASSWORD: "zabbix"
      MYSQL_ROOT_PASSWORD: "zabbix"
    command: --character-set-server=utf8 --collation-server=utf8_bin --default-authentication-plugin=mysql_native_password
    networks:
      - "zabbix-net"
    container_name: "mysql-server"

2. zabbix java gateway (선택)
‣ java 관련 검사를 수집하기에 tomcat, jeus 등의 WAS 모니터링이 필요한 경우 설치

~/zabbix/composes/zabbix-java-gateway.yaml

services:
  zabbix-java-gateway:
    image:
      zabbix/zabbix-java-gateway:alpine-6.4-latest
    restart: always
    container_name: zabbix-java-gateway
    networks:
      - "zabbix-net"

3. zabbix server mysql

~/zabbix/Dockerfiles/zabbix-server.dockerfile

FROM zabbix/zabbix-server-mysql:alpine-6.4-latest

USER root
RUN apk update && apk add --no-cache curl

해당 컨테이너에서는 추후에 slack-메신저-연동 할 때 curl 패키지가 필요하다.
그래서 curl을 설치한 이미지로 빌드하도록 하겠다.


~/zabbix/composes/zabbix-server-mysql.yaml

services:
  zabbix-server-mysql:
    build:
      context: ../Dockerfiles
      dockerfile: zabbix-server.dockerfile
    restart: always
    environment:
      DB_SERVER_HOST: "mysql-server"
      MYSQL_DATABASE: "zabbix"
      MYSQL_USER: "zabbix"
      MYSQL_PASSWORD: "zabbix"
      MYSQL_ROOT_PASSWORD: "zabbix"
      ZBX_JAVAGATEWAY: "zabbix-java-gateway"
    ports:
      - "10051:10051"
    volumes:
      - type: bind
        source: "../alertscripts"
        target: "/usr/lib/zabbix/alertscripts"
    networks:
      - "zabbix-net"
    container_name: "zabbix-server-mysql"

4. zabbix web nginx mysql

~/zabbix/composes/zabbix-web-nginx-mysql.yaml

services:
  zabbix-web-nginx-mysql:
    image: zabbix/zabbix-web-nginx-mysql:alpine-6.4-latest
    restart: always
    environment:
      ZBX_SERVER_HOST: "zabbix-server-mysql"
      DB_SERVER_HOST: "mysql-server"
      MYSQL_DATABASE: "zabbix"
      MYSQL_USER: "zabbix"
      MYSQL_PASSWORD: "zabbix"
      MYSQL_ROOT_PASSWORD: "zabbix"
    ports:
      - "80:8080"
    networks:
      - "zabbix-net"
    container_name: zabbix-web-nginx-mysql

5. zabbix agent 생성

~/zabbix/composes/zabbix-agent.yaml

services:
  zabbix-agent:
    image: zabbix/zabbix-agent
    restart: always
    environment:
      ZBX_HOSTNAME: "Zabbix server"
      ZBX_SERVER_HOST: "zabbix-server-mysql"
    container_name: zabbix-agent
    networks:
      - "zabbix-net"

agent 컨테이너 IP 확인

zabbix-agent 컨테이너가 정상적으로 배포되었다면 해당 컨테이너의 IP 주소를 확인해보자.

docker inspect zabbix-agent | grep "\"IPAddress\""

image
zabbix 웹에서 설정 값으로 넣어주어야 하니 기억하고 있자.


‣ 서비스 확인

docker-compose ps

image
5개의 컨테이너가 정상적으로 생성되었다.


브라우저에 http://<서버IP>로 접속을 시도하면 아래와 같이 zabbix 초기 로그인 화면이 뜰 것이다.
image


초기 사용자 계정 정보의 경우 아래와 같다.
로그인 후 패스워드를 변경해주는 것을 권장한다.

  • ID: Admin
  • PW: zabbix

로그인을 하게되면 기본 대시보드를 확인할 수 있다.

zabbix agent를 배포하긴 했지만, 호스트 등록이 정상적으로 이루어지지 않아 system information에 빨간 에러 창이 발생한 것을 볼 수 있다.
image


Monitoring - Hosts - Zabbix server - Host를 클릭하여

agent 주소로 설정된 127.0.0.1agent 컨테이너 IP에서 확인했던 agent 컨테이너의 IP로 수정하여 저장하자.
image


업데이트 후 대시보드로 다시 돌아가면 1개의 서버가 정상적으로 모니터링 되고있는 것을 볼 수 있을 것이다.
image


▶︎ Agent 설치

  • Agent 서버 환경
    • Ubuntu 22.04

이번에는 Zabbix Agent를 모니터링 대상 서버에 직접 설치하여 대상 서버도 zabbix 서버에서 모니터링이 되도록 구축해보자.


‣ 설치

1. wget 명령어를 사용하여 아래와 같이 zabbix release package를 다운로드

wget -O zabbix.ubuntu22.04.deb https://repo.zabbix.com/zabbix/6.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_6.0-3+ubuntu22.04_all.deb

2. 그리고 Package management 도구를 이용하여 다운로드 받은 zabbix 패키지를 설치해주자.

sudo dpkg -i zabbix.ubuntu22.04.deb

3. 마지막으로 패키지를 모두 업데이트

sudo apt-get update -y 

zabbix가 정상적으로 설치되었는지 확인

$ apt list --installed 2>/dev/null | grep "^zabbix"

zabbix-release/now 1:6.0-3+ubuntu22.04 all [installed,upgradable to: 1:6.0-4+ubuntu22.04]

정상적으로 확인이 되었다.


4. 이제 에이전트를 내려받고 설치

sudo apt-get install -y zabbix-agent2

‣ 설정 파일 수정

/etc/zabbix/zabbix_agent2.conf
image


/etc/zabbix/zabbix_agent2.conf
image

위 IP는 zabbix Docker가 구동 중인 Host 서버의 IP 주소를 기입해주면 된다.

본인의 경우 zabbix가 구동 중인 서버의 IP가 192.168.219.179이므로 위처럼 적어주었다.


아래 부분에는 호스트 이름을 적어주도록 하자.

/etc/zabbix/zabbix_agent2.conf
image
모두 수정했다면 :wq로 저장하고 나오도록 하자.


그리고 zabbix 에이전트에 대한 서비스를 등록하고, Daemon을 재기동해주자.

sudo systemctl enable --now zabbix-agent2

image


‣ zabbix web 이동

zabbix web page로 들어가 호스트를 추가해주자.
(Monitoring - Hosts - Create host)
image


에이전트 서버의 /etc/zabbix/zabbix_agent2.conf 파일에서 적었던 호스트 이름을 적어주고, Templates에 위와 같이 Linux by Zabbix agent를 찾아 선택해주도록 하자.
image


Host groups의 경우 Linux servers를 선택
image


아래와 같이 에어전트를 설치한 호스트의 IP를 적어주고, 추가를 눌러주자.
image
image


에이전트를 설치한 호스트 이름의 상태가 활성 상태가 되어있다면 성공이다.
image


대시보드로 돌아가면 nginx-proxy-manager 에이전트의 CPU 모니터링이 안뜨는데 이건 수동으로 따로 설정 해주어야 한다.

Top hosts by CPU utilization 톱니바퀴 클릭 - 아래와 같이 Linux servernginx proxy manager 에이전트를 추가 후 적용
image


그럼 이제 기본적인 모니터링 설정은 마무리가 되었다.
image


▶︎ 알림 설정

이번에는 모니터링 중인 Agent에 시스템 리소스 현황(cpu,memory,disk,port)을 확인하여 알림을 보내는 과정을 정리해보겠다.


먼저 Zabbix web 페이지로 접속하여

"경고 - 미디어 타입"로 들어가게 되면 아래와 같이 알림을 보낼 수 있는 플랫폼 목록을 확인할 수 있다.
image

또는 셸 스크립트를 작성하여 알림을 보낼 수 있는 방법도 존재한다.

본인의 경우 셸 스크립트를 작성하여 알림을 보낼 수 있는 방법에 대해 작성해보겠다.


먼저 zabbix에서는 AlertScriptsPath에 스크립트 파일을 올려 알림 서비스를 활용해볼 수 있다.

그러기 위해서 먼저 Zabbix 서버의 터미널로 접속한 후, zabbix-server-mysql 컨테이너의 터미널로 진입하자.

docker exec -it zabbix-server-mysql /bin/bash

그런 다음 /etc/zabbix/zabbix_server.conf 파일에서 아래 스트링을 검색하여 AlertScriptsPath에 대한 경로를 확인해보자.

grep "^AlertScriptsPath" /etc/zabbix/zabbix_server.conf

image
/usr/lib/zabbix/alertscripts 이라고 명시되어 있다.


‣ 스크립트 작성

zabbix-server-mysql 컨테이너에서 exit 명령어로 빠져나온 후

./alertscripts 경로로 이동하여 아래와 같은 스크립트 파일을 만들어주자.

참고로 zabbix-server-mysql 컨테이너의 /usr/lib/zabbix/alertscripts 디렉토리를 호스트의 alertscripts 폴더와 바인드 마운트를 해줬기 때문에 컨테이너 간 파일이 실시간으로 공유된다.


해당 스크립트는 파라메터를 입력 받아 slack webhook으로 메시지를 보내도록 한다.
{% include codeHeader.html name="slack.sh" %}

#!/usr/bin/bash

# 메시지 보낼 채널
CHANNEL="#server_notification"

# 채널에서 표시될 사용자 이름
USERNAME="Server Bot"

# 채널에 사용하고자 하는 아이콘
EMOJI=":heart:"

# 스크립트 실행 시 삽입할 파라메터
TITLE="$1"
MESSAGE="$2"

# Set api url
PAYLOAD="payload={\"channel\": \"$CHANNEL\", \"username\": \"$USERNAME\", \"text\": \"*$TITLE*\n\n$MESSAGE\", \"icon_emji\": \"$EMOJI\"}"
webHookURI="<WEBHOOK URI>"

# 메시지 전송
curl -X POST --data-urlencode "$PAYLOAD" "$webHookURI"

‣ slack 메신저 연동

다시 zabbix web으로 들어가서 '경고 - 미디어 타입'으로 이동한 후, '연락 방법 생성'을 클릭해주자.
image


image

  • 이름: 원하는 이름
  • 종류: 스크립트
    • 스크립트 방식으로 알림을 보낼 것이기에
  • 스크립트 이름: 스크립트파일이름.sh
    • /usr/lib/zabbix/alertscripts 경로에 존재하게 되는 스크립트 파일명을 넣어줘야 함
    • 해당 예시에서는 slack.sh
  • 스크립트 파라미터: 스크립트에서 입력받는 파라메터 값
    • slack.sh {TITLE} {MESSAGE}

추가를 해주고 나서 '유저 - 유저'로 이동

Admin 유저 클릭 후 '연락 방법'으로 이동하여 아래와 같이 위에서 생성한 연락 방법으로 추가
image
추가했으면 '갱신'


다시 '경고 - 미디어 타입'으로 돌아와서 위에서 생성했던 slack 미디어 타입 테스트
image

그러면 아래와 같이 정상적으로 슬랙으로 알림이 오는 것을 확인할 수 있음
image


‣ 디스크 알림 설정

Zabbix agent 서버로 이동하여 아래 명령어를 실행해보자.

$ df -Th

Filesystem                        Type   Size  Used Avail Use% Mounted on
tmpfs                             tmpfs  1.2G  1.5M  1.2G   1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv ext4    29G   18G  9.9G  64% /
tmpfs                             tmpfs  5.9G     0  5.9G   0% /dev/shm
tmpfs                             tmpfs  5.0M     0  5.0M   0% /run/lock
/dev/sda2                         ext4   2.0G  251M  1.6G  14% /boot # 감시 대상
tmpfs                             tmpfs  1.2G  4.0K  1.2G   1% /run/user/1000

여기서 / 경로의 사용량이 70%가 넘어갈 경우 슬랙으로 알림이 올 수 있도록 설정을 해보려고 한다.


먼저 '데이터 수집' - '호스트'로 들어가서 알림을 보내고자 하는 에이전트의 템플릿에 들어가서 아이템, 트리거를 설정해줘야 한다.
image


1. 아이템 생성

'아이템'을 클릭해서 새로운 아이템을 생성해주자.
image
image

옵션 설명
*이름 아이템 이름 설정
종류 에이전트에 대한 모니터링이므로 ZABBIX 에이전트로 지정
*키 Zabbix에서 사용되는 아이템 키(Item Key) 지정
vfs.fs.size[/,pused] 해당 키는 파일 시스템에서 사용 가능한 공간을 모니터링 하기 위해 사용됨.
여기서 /,pused는 파일 시스템의 경로 및 옵션을 지정함.
/는 루트 디렉토리를 나타내며, pused는 사용된 공간의 백분율을 의미
데이터형 수치 (float): 소수점으로 표현할 것이기에 해당 옵션으로 지정
단위 %: 퍼센트 단위로 지정
*갱신 간격 몇 분, 몇 시간 간격으로 트리거가 발동되도록 할 것인지에 대한 옵션
본인의 경우 5분 간격으로 발동되도록 설정

2. 트리거 생성

아이템 작성이 모두 끝났다면 이제 트리거를 작성해보자.
image

옵션 설명
*이름 트리거 이름 설정
심각도 해당 트리거가 발생했을 때 어느 정도의 심각도로 지정할 것인지 지정
*조건식 last(/Linux by Zabbix agent/vfs.fs.size[/,pused])>70은 Zabbix에서 사용되는 트리거 표현식이다. 해당 표현식은 특정 조건이 충족될 때 알림을 발생시키기 위해 사용된다.
last() 함수는 최근 수집된 값 중 가장 최신 값을 가져오는 함수이다.
Linux by Zabbix agent/vfs.fs.size[/,pused]는 Zabbix 에이전트를 통해 수집된 루트 디렉토리의 사용된 공간의 백분율 값을 나타낸다.
>70은 비교 연산자로, 값이 70보다 큰 경우를 나타낸다
즉, 해당 표현식은 "루트 디렉토리의 사용 공간이 70%를 초과하는 경우" 해당 트리거가 발동된다.

3. 트리거 액션 생성

이제 마지막으로 생성된 트리거에 대한 액션을 생성해주면 마무리가 된다.

'경고' - '액션' - 'Trigger Action'으로 이동한 후, 새로운 액션을 생성하자.


먼저 트리거에 대한 액션 조건을 설정해보자.
image

옵션 설명
종류 설정할 액션 종류 지정
오퍼레이터 트리거의 상태에 따라 특정 동작을 수행하는 방법을 지정

그리고 트리거 심각도에 대한 액션 조건도 설정하자.
image


오퍼레이션을 설정해주자.
image


장애 발생시에 대한 오퍼레이션 설정은 아래와 같다. image


장애가 복구되었을 때에 대한 오퍼레이션 설정은 아래와 같다.
image
이로써 모든 알림 설정이 완료되었다.


💥 장애 유발

테스트를 위해 dd 명령어로 디스크 용량을 늘려 장애 상황을 유발해보자.

sudo dd if=/dev/zero of=/var/log/test.log bs=1M count=3000
df -Th

image
루트 디렉토리의 용량이 70%가 넘어갔다.


5분이 지나니 정상적으로 장애 알람이 도착했다.
image


그럼 이제 /var/log/test.log 파일을 삭제하고 장애 복구가 정상적으로 도착하는지 확인해보자.
image
장애 알람도 정상적으로 수신되었다.


‣ 포트 알림 설정

Zabbix Agent 서버의 터미널로 들어가서 아래 명령어를 실행해보자.

sudo netstat -nltp | grep '80'

image
80번 포트가 정상적으로 살아있는지 확인을 하고 80번 포트가 다운되어 있다면 알림을 보내도록 Zabbix에서 알림 설정을 해보자.

위에서 설정했던 것과 동일하게 Agent의 템플릿 페이지로 이동하도록 하자.
image


1. 아이템 생성
image

옵션 설명
* 키 net.tcp.port[모니터링 Agent 서버 IP,모니터링 포트]
Ex. net.tcp.port[192.168.219.196,80]: 192.168.219.196 서버의 80번 포트를 모니터링

2. 트리거 생성
image

옵션 설명
* 조건식 last(/Linux by Zabbix agent/net.tcp.port[192.168.219.196,80])=0: 192.168.219.196 서버의 80번 포트가 비활성화 된 경우 트리거 실행

3. 트리거 액션 생성
image


장애 발생시에 대한 오퍼레이션 설정은 아래와 같다.
image


장애가 복구되었을 때에 대한 오퍼레이션 설정은 아래와 같다.
image


💥 장애 유발

테스트를 위해 의도적으로 80번 포트를 다운시켜보도록 하자.

kill -KILL $(ps -aux | grep "80$" | awk '{print $2}')

kill 명령어로 80번 포트를 점유하고 있는 프로세스를 강제로 종료시켰다.


장애가 발생했다고 슬랙으로 알림이 도착했다.
image


그럼 다시 80번 포트를 등록해주자.

cd ~/npm
docker-compose up -d

복구 됐다고 알림이 정상적으로 도착했다.
image


Loading script...