• 토큰, 비밀번호, 인증서, 암호화 키와 같은 비밀 정보나 민감한 데이터를 UI, CLI, HTTP API 를 활용할때 안전하게 저장하고 제어할수 있게 해주는 오픈 소스
  • vault 메뉴얼 URL : https://www.vaultproject.io/

Valut 설치

$ yum install -y yum-utils
$ yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
$ yum -y install vault

# 설치한 vault 패키지 버전 확인
$ vault -v
Vault v1.8.0 (82a99f14eb6133f99a975e653d4dac21c17505c7)



Vault server를 DEV 모드로 실행

1. 환경변수 등록

  • vault CLI 를 사용하기 위해 환경변수 등록이 필요

      # 수동으로 환경 변수 등록
      $ export VAULT_ADDR='http://127.0.0.1:8200'
    
      # 영구적으로 환경 변수 등록
      $ echo "export VAULT_ADDR='http://127.0.0.1:8200'" >> /root/.bashrc
      $ source /root/.bashrc
    
      # 설정 확인
      $ echo $VAULT_ADDR
      http://127.0.0.1:8200

2. 테스트를 위해 -dev 모드로 백그라운드에서 서버를 실행

  • dev모드는 미리 준비된 설정으로 서버를 구동

  • dev 모드는 모든 데이터는 in-memory 저장, 암호화

  • localhost로 listen되며 TLS가 없음

  • 자동 봉인 해제 → 봉인 해제된 키와 엑세스 토큰을 보여줌

  • 프로덕션 모드에서는 -dev 옵션 사용을 권장 X

    $ vault server -dev &
    ==> Vault server configuration:
    
               Api Address: http://127.0.0.1:8200
                       Cgo: disabled
           Cluster Address: https://127.0.0.1:8201
                Go Version: go1.16.5
                Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
                 Log Level: info
                     Mlock: supported: true, enabled: false
             Recovery Mode: false
                   Storage: inmem
                   Version: Vault v1.8.0
               Version Sha: 82a99f14eb6133f99a975e653d4dac21c17505c7
    
    ==> Vault server started! Log data will stream in below:
    
    2021-08-02T14:07:10.555Z [INFO]  proxy environment: http_proxy="" https_proxy="" no_proxy=""
    2021-08-02T14:07:10.556Z [WARN]  no `api_addr` value specified in config or in VAULT_API_ADDR; falling back to detection if possible, but this value should be manually set
    2021-08-02T14:07:10.557Z [INFO]  core: security barrier not initialized
    2021-08-02T14:07:10.557Z [INFO]  core: security barrier initialized: stored=1 shares=1 threshold=1
    2021-08-02T14:07:10.558Z [INFO]  core: post-unseal setup starting
    2021-08-02T14:07:10.572Z [INFO]  core: loaded wrapping token key
    2021-08-02T14:07:10.572Z [INFO]  core: successfully setup plugin catalog: plugin-directory=""
    2021-08-02T14:07:10.572Z [INFO]  core: no mounts; adding default mount table
    2021-08-02T14:07:10.573Z [INFO]  core: successfully mounted backend: type=cubbyhole path=cubbyhole/
    2021-08-02T14:07:10.574Z [INFO]  core: successfully mounted backend: type=system path=sys/
    2021-08-02T14:07:10.574Z [INFO]  core: successfully mounted backend: type=identity path=identity/
    2021-08-02T14:07:10.582Z [INFO]  core: successfully enabled credential backend: type=token path=token/
    2021-08-02T14:07:10.589Z [INFO]  core: restoring leases
    2021-08-02T14:07:10.603Z [INFO]  rollback: starting rollback manager
    2021-08-02T14:07:10.603Z [INFO]  expiration: lease restore complete
    2021-08-02T14:07:10.604Z [INFO]  identity: entities restored
    2021-08-02T14:07:10.604Z [INFO]  identity: groups restored
    2021-08-02T14:07:10.604Z [INFO]  core: post-unseal setup complete
    2021-08-02T14:07:10.604Z [INFO]  core: root token generated
    2021-08-02T14:07:10.604Z [INFO]  core: pre-seal teardown starting
    2021-08-02T14:07:10.604Z [INFO]  rollback: stopping rollback manager
    2021-08-02T14:07:10.604Z [INFO]  core: pre-seal teardown complete
    2021-08-02T14:07:10.604Z [INFO]  core.cluster-listener.tcp: starting listener: listener_address=127.0.0.1:8201
    2021-08-02T14:07:10.604Z [INFO]  core.cluster-listener: serving cluster requests: cluster_listen_address=127.0.0.1:8201
    2021-08-02T14:07:10.604Z [INFO]  core: post-unseal setup starting
    2021-08-02T14:07:10.605Z [INFO]  core: loaded wrapping token key
    2021-08-02T14:07:10.605Z [INFO]  core: successfully setup plugin catalog: plugin-directory=""
    2021-08-02T14:07:10.605Z [INFO]  core: successfully mounted backend: type=system path=sys/
    2021-08-02T14:07:10.605Z [INFO]  core: successfully mounted backend: type=identity path=identity/
    2021-08-02T14:07:10.605Z [INFO]  core: successfully mounted backend: type=cubbyhole path=cubbyhole/
    2021-08-02T14:07:10.606Z [INFO]  core: successfully enabled credential backend: type=token path=token/
    2021-08-02T14:07:10.606Z [INFO]  core: restoring leases
    2021-08-02T14:07:10.607Z [INFO]  identity: entities restored
    2021-08-02T14:07:10.607Z [INFO]  identity: groups restored
    2021-08-02T14:07:10.607Z [INFO]  core: post-unseal setup complete
    2021-08-02T14:07:10.607Z [INFO]  core: vault is unsealed
    2021-08-02T14:07:10.609Z [INFO]  core: successful mount: namespace="" path=secret/ type=kv
    2021-08-02T14:07:10.610Z [INFO]  expiration: lease restore complete
    2021-08-02T14:07:10.610Z [INFO]  secrets.kv.kv_f71fab5a: collecting keys to upgrade
    2021-08-02T14:07:10.610Z [INFO]  secrets.kv.kv_f71fab5a: done collecting keys: num_keys=1
    2021-08-02T14:07:10.610Z [INFO]  secrets.kv.kv_f71fab5a: upgrading keys finished
    2021-08-02T14:07:10.611Z [INFO]  rollback: starting rollback manager
    WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory
    and starts unsealed with a single unseal key. The root token is already
    authenticated to the CLI, so you can immediately begin using Vault.
    
    You may need to set the following environment variable:
    
      $ export VAULT_ADDR='http://127.0.0.1:8200'
    
    The unseal key and root token are displayed below in case you want to
    seal/unseal the Vault or re-authenticate.
    
    Unseal Key: +1P8t1jNPI8mBPCV57v+emB4E3DttH3t1xkz+oXsQUs=
    Root Token: s.BT8kE324DT9EJYQqG8noC8J1
    
    Development mode should NOT be used in production installations!

3. 실행된 서버의 상태를 확인

$ vault status
Key                   Value
---                    -----
Seal Type          shamir
Initialized          true
Sealed              false
Total Shares      1
Threshold          1
Version             1.3.0
Cluster Name    vault-cluster-a6999d5c
Cluster ID         291371dc-e6a5-42d3-fca7-b2373ff70194
HA Enabled       false



vault 와 secret

  • vault의 핵심 기능중 하나는 비밀정보를 안전하게 읽고 쓰는것
  • vault에 기록된 비밀정보는 암호화하여 backend 저장소에 저장
  • 값을 저장소에 전달하기 전에 암호화를 하며, backend 저장소에 저장된 암호화값은 vault 없이는 해독 불가능



write a secret (비밀정보 작성)

  • key 값의 접두사가 secret/ 로 저장됨

  • secret/ 는 어떤 secrets engine을 실행시킬지 결정하는 route 역할(경로 결정)

  • 비밀정보를 기록할때는 shell history에 남기때문에 되도록이면 file 을 통해서 전달될수있도록 하는것이 좋음

  • kv → Vault의 키-값 저장소와 상호작용 (command)

  • put → KV 저장소의 데이터를 설정하거나 업데이트함

  • secret/hello → hello 이름을 가지는 secret engine 사용

  • foo=world → foo 키에 world 값이 있음

    $ vault kv put secret/hello foo=world
    Key                     Value
    ---                       -----
    created_time        2021-08-02T15:40:03.164784248Z
    deletion_time        n/a
    destroyed             false
    version                1



read a secret (비밀정보 읽기)

1. secret과 함께 여러 가지 메타 데이터가 함께 반환

  • 비밀정보를 획득

  • vault는 저장소로부터 값을 가져올때 복호화하여 가져옴

  • kv → Vault의 키-값 저장소와 상호작용 (command)

  • get → KV 저장소에서 데이터 검색

  • secret/hello → hello 이름을 가지는 secret engine 사용

    $ vault kv get secret/hello
    ====== Metadata ======
    Key Value
    --- -----
    created_time 2019-11-26T02:39:20.8458832Z
    deletion_time n/a
    destroyed false
    version 1
    
    === Data ===
    Key Value
    --- -----
    foo world

2. hello 키에 해당하는 값 추출

  • kv → Vault의 키-값 저장소와 상호작용 (command)

  • get → KV 저장소에서 데이터 검색

  • field=key → 입력한 key의 value를 출력, -field 옵션을 사용하면 다른 형식 지정 지시문보다 우선

    $ vault kv get -field=foo secret/hello
    world

3. JSON output → 결과데이터의 포맷을 json형식으로 출력

  • kv → Vault의 키-값 저장소와 상호작용 (command)

  • get → KV 저장소에서 데이터 검색

  • format=형식 → "table", "json", "yaml", "pretty" 중에 입력한 형식으로 출력 → 기본값은 table로 출력

  • format 옵션을 사용하지 않고, VAULT_FORMAT 환경 변수를 통해 지정 가능

    $ vault kv get -format=json secret/hello
    {
    "request_id": "777069c4-4cb8-1bfa-2eaa-5d35018eca54",
    "lease_id": "",
    "lease_duration": 0,
    "renewable": false,
    "data": {
      "data": {
        "foo": "world"
      },
      "metadata": {
        "created_time": "2021-08-02T15:40:03.164784248Z",
        "deletion_time": "",
        "destroyed": false,
        "version": 1
      }
    },
    "warnings": null
    }

4. jq 활용 → jq 도구를 통해 더 편리하게 원하는 메타정보를 가져올 수 있음

  • kv → Vault의 키-값 저장소와 상호작용 (command)

  • get → KV 저장소에서 데이터 검색

  • format=json → json 형식으로 출력

  • json 형식으로 출력되면 key값으로 해서 해당 value를 찾을 수 있음

    # jq를 사용하기 위해서는 패키지 설치 필요
    $ yum install -y jq
    
    #  data 키 → data 키 → foo 키의 값 출력
    $ vault kv get -format=json secret/hello | jq -r .data.data.foo
    world



delete a secret (비밀정보 삭제)

  • 저장된 비밀정보를 삭제

  • kv → Vault의 키-값 저장소와 상호작용 (command)

  • delete → KV 저장소에서 데이터 삭제

    $ vault kv delete secret/hello
    Success! Data deleted (if it existed) at: secret/hello
    
    # key와 value가 삭제됨을 확인
    $ vault kv get secret/hello
    ====== Metadata ======
    Key                      Value
    ---                       -----
    created_time        2021-08-02T15:40:03.164784248Z
    deletion_time       2021-08-02T16:17:00.129797593Z
    destroyed             false
    version                1

  • 하시코프 볼트(Harshicorp Vault)는 아이덴티티 기반의 비밀, 암호화 관리 시스템
  • 공개되면 안되는 비밀번호, API 키, 토큰 등을 저장하고 관리함
  • 제한된 접근을 제공하기 위해 인증(authentication) 및 권한 부여(authorization) 방법으로 제어되는 암호화 서비스를 제공
  • UI, CLI 또는 HTTP API를 사용하여 토큰, 암호, 인증서, 비밀 보호를 위한 암호화 키 및 민감 정보에 대한 접근을 보호, 저장 및 엄격하게 제어하는 데 사용
  • vault 공식 참고 URL : https://www.vaultproject.io/docs
  • Vault HA 구성 with Consul : https://shanta.tistory.com/16?category=982069

Vault 기능

  1. 사용의 핵심 → 인증 및 권한 부여
  2. 인증 및 권한을 클라이언트에 제공하는 방법을 이해하는 것이 구성하고 관리하는 방법을 이해하기 위한 핵심
  3. 인증 방법(auth method)을 사용 → 클라이언트에 인증을 제공
  4. 정책(policy)을 사용 → 클라이언트에 권한 제어를 제공

Vault는 몇 가지 내부 또는 외부 인증 방법을 제공

  1. 외부 방법을 AWS, LDAP, GitHub 등과 같은 신뢰할 수 있는 서드파티 인증자(trusted third-party authenticators)
  2. 어떤 상황에서 신뢰할 수 있는 서드파티 인증자를 사용할 수 없으므로 Vault에서는 AppRole이라는 대체 수단을 마련
  3. 신뢰할 수 있는 서드파티 인증자가 있다면 그것을 사용하는 것이 AppRole을 사용하는 것보다는 바람직

Vault 아키텍처

1. Storage Backend

  • 스토리지 백엔드(Storage Backend)는 암호화된 데이터를 저장하기 위한 스토리지를 담당
  • Vault는 스토리지의 종류, 가용성 등을 책임지지 않음 → 어떤 스토리지 백엔드를 쓸 것인지는 고객이 결정
  • Vault는 15가지 이상 스토리지를 지원
  • filesystem과 in-memory 스토리지는 백앤드는 개발단계에서 빠르게 활용하기에 좋은 시스템
  • 나머지 스토리지 백앤드는 서비스 전개 환경에 따라서 선택적으로 구성
  • 스토리지 백엔드(Storage Backend) 종류
    1. HashCorp Consul
    2. Etcd
    3. Zookeeper
    4. AWS S3
    5. AWS DynamoDB
    6. Azure Storage Container
    7. Triton Manta Object Storage
    8. GCP Cloud Storage
    9. GCP Cloud Spanner
    10. MySQL
    11. PostgreSQL
    12. MSSQL
    13. Swift
    14. Raft
    15. Filesystem
    16. CockroachDB
    17. Cassandra

2. Barrier

  • Barrier는 장벽이라는 의미 → 데이터의 안전한 사용을 위한 강철벽
  • 스토리지 백앤드(Storage Backend) 간에 흐르는 모든 데이터는 Barrier를 통과함
  • Barrier는 암호화된 데이터만을 기록하며, 데이터가 필요한 시점에 복호화(암호해독)이 되도록함
  • barrier를 통과해야만 내부 데이터에 접근 가능.

3. Secret Engine

  • Secrets Engine은 데이터를 저장, 생성, 암호화하는 구성요소
  • Secret Engine 중 Redis/Memcached에 단순하게 key&value 형식으로 데이터를 저장하고 읽을 수 있음
  • 다른 Secrets Engine은 서비스에 연결하고 요청을 하는 시점에서 동적으로 자격증명을 생성 가능
  • AWS를 대상으로 할 경우, 시크릿 엔진은 AWS IAM 정책을 기반으로 AWS 자격증명을 동적으로 생성 가능 → AWS IAM 자격 증명은 시간을 기반으로 하기 때문에, 일정 시간이 지나면 자동으로 자격증명을 삭제함
  • SSH를 이용해서 인스턴스에 대한 접근권한을 관리할 경우에는 SSH Secret Engine을 사용할 수 있음 → SSH 유저, 권한, 유효시간, 원타임 패스워드등을 안전하게 관리
  • 다양한 서비스를 위한 Secret Engine 목록
    1. Active Directory
    2. AliCloud
    3. AWS
    4. Azure
    5. Consul
    6. Cubbyhole
    7. Database
    8. Google Cloud
    9. Google Cloud KMS
    10. KMIP
    11. Key/Value
    12. Identity
    13. Nomad
    14. PKI
    15. RabbitMQ
    16. SSH
    17. TOTP
    18. Transit

4. Audit Device

  • Audit device는 감사 로그를 관리
  • Valut에 대한 모든 요청과 응답은 Audit device를 통과하면서 로그를 기록
  • 관리자는 로그를 통해서 시스템 상태를 관리 가능

5. Auth Method

  • Auth Method는 Vault에 연결하려는 유저와 애플리케이션을 인증하기 위해서 사용
  • 인증되면 Auth Method는 인증된 사용자와 사용 할 수 있는 애플리케이션 정책 목록을 리턴
  • 클라이언트 토큰(client token)을 리턴하는데, 한번 인증을 끝내고 나면 클라이언트 토큰을 이용하게 됨
  • 다른 구성요소들과 마찬가지로 다양한 서비스를 Auth Method로 사용 가능
  • 예를 들어서 Userpass(Username & Password) auth method는 유저이름과 패스워드 기반의 인증 매커니즘을 제공
  • Auth Method의 목록
    1. AppRole
    2. AliCloud
    3. AWS
    4. Azure
    5. Google Cloud
    6. JWT/OIDC
    7. Kubernetes
    8. GitHub
    9. LDAP
    10. Okta
    11. PCF
    12. RADIUS
    13. TLS Certificates
    14. Tokens
    15. Username & Password

6. Client Token

  • Client Token 혹은 Vault Token은 웹 사이트에서 사용하는 세션 쿠기(session cookie)과 개념적으로 비슷함
  • 사용자 인증이 끝나면 Vault는 클라이언트 토큰을 리턴하는데, 이후에는 클라이언트 토큰을 이용해서 작업을 수행 가능
  • Vault는 Client Token을 이용해서 클라이언트를 식별하고 애플리케이션 접근 정책을 검사함
  • Client Token 은 HTTP 헤더를 통해서 전달됨

7. Secret

  • Secret는 암호화된 데이터를 포함해서 Vault가 리턴하는 모든 정보를 의미
  • Vault가 반환하는 모든 정보가 Secret 인 것은 아님 → 시스템 설정, 상태 정보, 정책등은 secret로 간주되지 않음
  • Secret는 lease(임대)객체 → Lease가 끝나면 Vault는 Secret를 파기함
  • 관리자는 lease 정보를 확인해서 Secret를 철회하거나 연장하기 위해서 개입 가능
  • 예를 들어 관리자는 아래와 같은 Secret를 생성 가능
    $ vault kv put secret/hello foo=world
    Key                     Value
    ---                       -----
    created_time        2019-08-19T03:53:56.491587848Z
    deletion_time       n/a
    destroyed             false
    version                1

8. Server

  • Vault는 클라이언트/서버 애플리케이션
  • Vault 서버는 데이터 스토리지와 백앤드 등과 상호작용함
  • Vault 서버는 전체 Vault 아키텍처에서 하나의 컴포넌트로 작동함
  • 사용자는 Vault CLI를 이용해서 TLS 연결로 서버와 통신 가능



암호화 알고리즘 → Vault 서버에서는 암호화 알고리즘을 사용

  • 암호화 알고리즘은 일반적으로 공개됨 → 암호화 열쇠를 어떻게 만들고 저장하고 관리할 것인지가 가장 중요
  • 한국인터넷진흥원(KISA)에서는 암호화된 데이터와 암호화 키는 물리적으로 안전하게 분리된 장소에 보관해야 한다고 권고
  • 데이터는 암호화하여 DB에 보관한다고 하면 키는 볼트(Vault)에 저장하는 것이 좋음
  • 볼트(Vault) 서비스는 일반적으로 암호화 키, 인증서 등 민감한 데이터를 안전하게 보호함
  • 볼트(Vault) 서비스는 민감 데이터를 DB에 전달하기 전에 암호화를 하며, DB에 저장된 암호화된 민감 데이터는 Vault 없이는 해독할 수 없음 → 민감 데이터를 안전하게 보호 가능


  • ArgoCD는 쿠버네티스 위한 CD(Continuous Delivery) → "Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.”
  • GitOps방식으로 관리되는 Manifest 파일의 변경사항을 감시하며, 현재 배포된 환경의 상태와 Git에 정의된 Manifest 상태를 동일하게 유지하는 역할을 수행
  • ArgoCD는 push타입과 pull타입 모두를 지원하며 pull타입 배포를 권장함
  • ArgoCD는 GitOps 스타일로 쿠버네티스 앱 배포를 하게 되면서 배포 작업이 간결해지고 명확해짐
  • 배포하는 작업이 편해지게 되니 스트레스 없이 더 자주, 더 빠르게 새로운 버전을 운영에 반영할 수 있게 되어 진정한 CI/CD를 이룩하게됨
  • GitOps 스타일로 앱을 배포하여 손쉬운 소프트웨어 배포 프로세스를 정립해 나가는 것이 중요
  • ArgoCD로 배포하는 작업은 편하기에 스트레스 없이 더 자주, 더 빠르게 새로운 버전을 운영에 반영 → 진정한 CI/CD를 가능하도록 하게 함

 

GitOps 배포 전략 두가지 방법

1.Push Type

  • Git Repo가 변경되었을 때 파이프라인을 실행시키는 구조
  • 배포 환경의 개수에 영향을 받지 않으며 접속 정보를 추가하거나 수정하는 것만으로도 간단하게 배포 환경을 추가하거나 변경 가능
  • 아키텍처가 쉬워 많은 곳에서 사용하고 있으나, 보안정보가 외부로 노출될 수 있다는 단점이 있음

 

2.Pull Type

  • 배포하려는 클러스터에 위치한 별도의 오퍼레이터가 배포역할을 대신함
  • 해당 오퍼레이터는 Git Repo의 Manifest와 배포환경을 지속적으로 비교하다가 차이가 발생할 경우, Git Repo의 Manifest를 기준으로 클러스터를 유지시켜줌
  • Push Type과 달리 오퍼레이터가 App과 동일한 환경에서 동작중이므로 보안 정보가 외부에 노출되지 않고 실행할 수 있음

 

GitOps의 구현체 ArgoCD

  • GitOps는 특정 소프트웨어나 프로덕트가 아닌 철학 혹은 방법론에 더 가깝움
  • GitOps에서 요구하는 원칙

1. 선언형 배포 작업 정의서

  • 배포 방법이 명령형 방식으로 정의된 것이 아니라 배포된 상태가 어떤 모양을 가져야 할지 선언되어 있는 방식으로 정의가 되어 있어야함
  • 사용자가 배포의 원하는 상태 (desired state)를 선언적으로 정의하였다는 것을 의미
  • Git 저장소를 이용하여 단일 진실의 원천 조건을 만족할 수 있음
  • 배포 작업 정의서가 선언형으로 되어 있으면 더 쉽게 배포할 수 있으며 문제 발생시, 롤백하기도 쉬움
  • 또한 장애 등으로 인해 손상된 배포 환경을 자가 치유하기 유리함

 

2. Git을 이용한 배포 버전 관리

  • Git에 모든 배포에 관련된 정보가 정의되어 있어야함
  • 또한, 각 버전이 Git 저장소에 기록이 되어 있어야함
  • 사용자는 쉽게 예전 버전으로 롤백을 하거나 새로운 버전으로 업그레이드를 할 수 있음

 

3. 변경 사항 운영 반영 자동화

  • 사용자는 Git 저장소에 선언형 정의서를 저장하게 되면 실제 배포가 일어나는 작업은 자동으로 이루어져야함
  • 책임지는 주체가 ArgoCD와 같은 배포 주체(deploy operator)가 됨
  • ArgoCD를 사용하면, human error를 줄이고 지속적 빌드/배포를 가능하게 만듦

 

4. 자가 치유 및 이상 탐지

  • 사용자가 원하는 배포 상태 (desired state)를 작성하게 되면 실제 배포 환경이 그에 맞게 유지되고 있는지 책임지는 것 또한 배포 주체(deploy operator)가 됨
  • 배포를 관장하는 소프트웨어가 주체가 되어 현재 배포 상태를 확인하고 Git 저장소의 변경 사항 등이 없는지를 체크하여 운영 환경에 반영하는 역할을 함
  • 현재 GitOps의 구현체로 ArgoCD 뿐만 아니라 Weaveworks flux, Codefresh, Jenkins X 등 다양한 소프트웨어들이 존재함

 

참고 URL : https://coffeewhale.com/kubernetes/gitops/argocd/2020/02/10/gitops-argocd/
참고 URL : https://gruuuuu.github.io/cloud/argocd-gitops/
참고 URL : https://waspro.tistory.com/758

 

서버 부하 분산의 정의

  • 서버 부하 분산(Server Load Balancing)은 외부의 사용자로부터 들어오는 다수의 요청(naver 접속 등)을 서버들에게 적절히 배분하여 서버들로 하여금 요청을 처리케 하는 것
  • 분산 처리는 부하 분산 Network Switch 혹은 소프트웨어가 담당
  • 외부로부터의 요청을 서버가 직접 받는 것이 아닌 '부하 분산 Network Switch' 혹은 '소프트웨어'가 받은 후 요청 받은 내용을 서버들로 적절히 나누어 주는 것
  • 서버 부하 분산을 담당하는 Network Switch를 L4/L7 Switch(Layer 4)라고 부르며 Cloud에서는 Load Balancer라고 부름
  • 현업에서는 서버 부하 분산(Server Load Balancing)을 부르기 편하게 로드밸런싱 혹은 LB(Load balancing)라고 부름

 

서버 부하 분산(Server Load Balancing)의 방법

  • 서버에게 부하를 고르게 분산하는 것도 다양한 방법있음
  • 서버의 능력을 고려하여 분배해야지 서버가 Down되지 않기 때문에 서버의 상황에 맞춰 적절한 방법을 선택 필요
  • 서버의 상황에 맞춰 적절한 방법을 Load Balancing Method이라고 함

 

1. Round Robin

  • Round Robin은 로드밸런서가 다수의 서버에게 순서대로 요청을 할당하는 방법
  • 가장 단순한 방법
  • 서버군에 차례로 요청을 할당하여 분산함

 

 

2. Least Connection

  • 로드밸런서가 서버에게 요청을 전달한 뒤, 사용자와 서버가 정상적인 연결을 맺으면 사용자와 서버는 'Connection'을 생성함
  • 로드밸런서 또한 중간자로서 Connection 정보를 갖고 있는데 이 Connection 수 정보를 기반으로 가장 Connection이 적은 서버, 즉 부하가 가장 덜한 서버에게 요청을 전달

 

3. Ratio(가중치)

  • 서버의 처리 능력을 고려하여 할당될 수 있는 각 서버가 가질 수 있는 Connection의 비율를 이미 정해둠.
  • 서버 부하 분산 비율이 100%라고 했을 때 성능이 가장 떨어지는 서버에게 10%를 나머지 서버 3대에게 각각 30%씩을 할당 가능

 

4. Fastest(Response Time)

  • 응답속도가 가장 빠른 서버에게 우선적으로 할당하는 방식
  • Fastest(Response Time)의 예시
    • 서버에 할당된 Connection이 5개인데 서버가 보내오는 Response가 5개라면 갖고 있는 Connection에 대해 모두 응답하고 있으므로 성능이 충분하다고 판단하고 추가 요청을 보냄
    • 다른 서버에 할당된 Connection이 10개인데 서버가 보내오는 Response가 5개뿐이라면 현재 성능이 충분치 않아 제대로 답변하지 못하는 것으로 판단하고 추가 요청을 해당 서버로 보내지 않음

 

참고 URL : <서버 부하 분산(출처 : 서버 구축이야기!님 블로그(https://server-talk.tistory.com/)>

 

 

  • Linux 시스템의 디스크 I/O 사용량과 파일 시스템 및 inode 사용량을 모니터링
  • Prometheus를 사용하여 Disk I/O를 확인 가능
  • Prometheus는 메트릭 수집 시스템이며, node_exporter는 다양한 시스템 메트릭을 노출
  • 디스크 I/O에 대한 개별 메트릭을 분석 → 디스크 성능, 디스크 사용량 및 애플리케이션에서 발생하는 I/O 대기 시간에 대한 중요한 정보를 제공

디스크 I/O

  • Linux 시스템에서 디스크 I/O 메트릭은 파일 시스템에서 몇 개의 파일을 읽음으로써 모니터링 가능
  • 디스크 또는 프로세스가 파일인 경우 지정된 시점에 연결된 메트릭을 저장하는 파일이 있음

Node exporter의 원시 디스크 통계

  • Linux 시스템에서 node_exporter는 디스크 메트릭을 /proc/diskstats 파일에서 얻어옮
  • /proc/diskstat 파일의 형식 → https://www.kernel.org/doc/Documentation/iostats.txt
  • 각 prometheus 메트릭은 NewDiskstatsCollector의 소스 코드에서 볼 수 있듯이 해당 파일의 필드 중 하나에 직접 대응함
  • prometheus 메트릭 값을 커널 소스 데이터와 일치시키는 것이 중요 → node_exporter는 몇 가지 크기 조정 요소를 제외하고 커널에서 반환된 원시 데이터를 추출함
  • 커널이 여러 섹터를 반환하는 경우 node_exporter는 섹터 크기를 곱하여 바이트 수가 됨
  • 커널이 시간을 밀리초 단위로 보고하는 경우 node_exporter는 0.001을 곱하여 초를 만듦

Node exporter의 I/O 메트릭 값

1. node_disk_reads_completed_total

  • field 1
  • 성공적으로 완료된 총 읽기 수

2. node_disk_reads_merged_total

  • field 2
  • 서로 인접한 읽기를 효율성의 위해 병합하는 횟수를 표시

3. node_disk_writes_merged_total

  • field 6
  • 서로 인접한 쓰기를 효율성의 위해 병합하는 횟수를 표시

4. node_disk_discards_merged_total

  • field 13
  • 서로 인접한 읽기 및 쓰기는 효율성을 위해 병합될 수 있음
  • 두 개의 4K 읽기는 궁극적으로 디스크에 전달되기 전에 하나의 8K 읽기가 될 수 있으므로 하나의 I/O로만 계산(및 대기열에 추가)
  • node_disk_discards_merged_total 필드를 통해 읽기 및 쓰기 병합 작업이 얼마나 자주 수행되었는지 알 수 있음

5. node_disk_read_bytes_total

  • field 3
  • 성공적으로 읽은 총 바이트 수

6. node_disk_read_time_seconds_total

  • field 4
  • 모든 읽기에 소요된 총 시간(초) → __make_request()에서 end_that_request_last()까지 측정

7. node_disk_writes_completed_total

  • field 5
  • 성공적으로 완료된 총 쓰기 수

8. node_disk_written_bytes_total

  • field 7
  • 성공적으로 쓰기가 완료된 총 바이트 수

9. node_disk_write_time_seconds_total

  • field 8
  • 모든 쓰기에 소요된 총 시간(초) → __make_request()에서 end_that_request_last()까지 측정

10. node_disk_io_now

  • field 9
  • 0으로 가야 하는 유일한 필드
  • 요청이 request_queue 구조체에 제공되면 증가하고 완료되면 감소

11. node_disk_io_time_seconds_total

  • field 10
  • I/O를 수행하는 데 소요된 시간(초)
  • node_disk_io_time_seconds_total 필드는 node_disk_io_now가 0이 아닌 한 증가

12. node_disk_io_time_weighted_seconds_total

  • field 11
  • I/O를 수행하는 데 소요된 가중치(초)
  • I/O를 수행하는 데 소요된 시간(초)에 동시 I/O 요청 수를 곱한 값을 계산
  • I/O 완료 시간과 누적될 수 있는 백로그(backlog)를 쉽게 측정 가능

13. node_disk_discards_completed_total

  • field 12
  • 성공적으로 완료된 총 폐기(discard) 수

14. node_disk_discarded_sectors_total

  • field 14
  • 성공적으로 폐기(discard)된 총 섹터 수

15. node_disk_discard_time_seconds_total

  • field 15
  • 모든 폐기(discard)에 소요된 총 시간(초) → __make_request()에서 end_that_request_last()까지 측정

16. node_disk_flush_requests_total

  • field 16
  • 성공적으로 완료된 총 플러시(flush) 요청 수

17. node_disk_flush_requests_time_seconds_total

  • field 17
  • 모든 플러시(flush) 요청에 소요된 총 시간(초)
  • PromQL을 이용해서 Alert Rule을 작성하면, 알람을 만들 수 있음
  • Prometheus에서 만들 알람에 대한 정보를 저장할 파일을 rule file이라고 함
  • rule file은 prometheus.yml과 같은 위치에 rules 디렉토리를 만들고 규칙을 작성할 Job과 같은 이름으로 작성
  • 알람이 많아질수록 모니터링 요소가 많아져 Prometheus에 부하가 발생 → 카디널리티를 줄이고 시계열을 쿼리하는 비용을 최적화하기 위해서 Recording Rule이라는 것을 이용

hardware_rule.yml 파일에 중요한 요소 → Prometheus 알람을 설정하는 코드

  1. record → Recording Rule으로 해당 값으로 설정한 이름으로 쿼리할 때 사용
  2. alert → 알람 발생 이름
  3. expr → Prometheus는 expr에 해당하는 쿼리를 계속 감시, PromQL을 하나의 시계열로 생성
  4. labels → 발생한 알람의 labeling
  5. for → 지정한 시간 동안 조건을 충족하게 되면 알림을 발생

1. DELL 서버 hardware 알람 rule의 yaml 파일 내용

$ mkdir -p /etc/prometheus/rules/

$ vi /etc/prometheus/rules/hardware_rule.yml
groups:
- name: hardware
  rules:
  - record: job:chassis
    expr: dell_hw_scrape_collector_success{collector="chassis"}

  - record: job:hardware_log
    expr: dell_hw_chassis_status{component="Hardware_Log"}

  - record: job:intrusion
    expr: dell_hw_chassis_status{component="Intrusion"}

  - record: job:chassis_batteries
    expr: dell_hw_scrape_collector_success{collector="chassis_batteries"}

  - record: job:batteries_status
    expr: dell_hw_chassis_status{component="Batteries"}

  - record: job:power_managemet
    expr: dell_hw_chassis_status{component="Power_Management"}

  - record: job:power_supplies
    expr: dell_hw_chassis_status{component="Power_Supplies"}

  - record: job:fans
    expr: dell_hw_scrape_collector_success{collector="fans"}

  - record: job:firmwares
    expr: dell_hw_scrape_collector_success{collector="firmwares"}

  - record: job:memory
    expr: dell_hw_scrape_collector_success{collector="memory"}

  - record: job:memory_status
    expr : dell_hw_chassis_memory_status{memory=~"DIMM_.*"}

  - record: job:nics
    expr: dell_hw_scrape_collector_success{collector="nics"}

  - record: job:processors
    expr: dell_hw_scrape_collector_success{collector="processors"}

  - record: job:cpu_status
    expr: dell_hw_chassis_processor_status{processor=~"CPU.*"}

  - record: job:ps
    expr: dell_hw_scrape_collector_success{collector="ps"}

  - record: job:ps_amps_sysboard_pwr
    expr: dell_hw_scrape_collector_success{collector="ps_amps_sysboard_pwr"}

  - record: job:storage_battery
    expr: dell_hw_scrape_collector_success{collector="storage_battery"}

  - record: job:storage_controller
    expr: dell_hw_scrape_collector_success{collector="storage_controller"}

  - record: job:storage_enclosure
    expr: dell_hw_scrape_collector_success{collector="storage_enclosure"}

  - record: job:storage_pdisk
    expr: dell_hw_scrape_collector_success{collector="storage_pdisk"}

  - record: job:storage_vdisk
    expr: dell_hw_scrape_collector_success{collector="storage_vdisk"}

  - record: job:system
    expr: dell_hw_scrape_collector_success{collector="system"}

  - record: job:temps
    expr: dell_hw_scrape_collector_success{collector="temps"}

  - record: job:temperatures
    expr: dell_hw_chassis_status{component="Temperatures"}

  - record: job:volts
    expr: dell_hw_scrape_collector_success{collector="volts"}

  - record: job:voltages
    expr: dell_hw_chassis_status{component="Voltages"}

  - alert: HardwareErrorandWarning
    expr: |
      ( job:chassis ) < 1 or
      ( job:hardware_log ) >= 1 or
      ( job:intrusion ) >= 1 or
      ( job:chassis_batteries ) < 1 or
      ( job:batteries_status ) >= 1 or
      ( job:power_managemet ) >= 1 or
      ( job:power_supplies ) >= 1 or
      ( job:fans ) < 1 or
      ( job:firmwares ) < 1 or
      ( job:memory ) < 1 or
      ( job:memory_status ) >= 1 or
      ( job:nics ) < 1 or
      ( job:processors ) < 1 or
      ( job:cpu_status ) >= 1 or
      ( job:ps ) < 1 or
      ( job:ps_amps_sysboard_pwr ) < 1 or
      ( job:storage_battery ) < 1 or
      ( job:storage_controller ) < 1 or
      ( job:storage_enclosure ) < 1 or
      ( job:storage_pdisk ) < 1 or
      ( job:storage_vdisk ) < 1 or
      ( job:system ) < 1 or
      ( job:temps ) < 1 or
      ( job:temperatures ) >= 1 or
      ( job:voltages ) >= 1 or
      ( job:volts ) < 1
    for: 30m
    labels:
      hardware_status: 'critical'
    annotations:
      summary: "{{ $labels.instance }}'s {{ $labels.collector }}  Hardware Error"

2. 디스크 관련 알람 rule의 yaml 파일 내용

cat /etc/prometheus/rules/disk_rule.yml
groups:
- name: disk-alarm
  rules:
  - record: job:pdisk
    expr: dell_hw_storage_pdisk_status{disk=~".*"}
  - record: job:vdisk
    expr: dell_hw_storage_vdisk_status{vdisk=~".*"}

  - alert: DiskErrorandWarning
    expr: |
      ( job:pdisk ) >= 1 or
      ( job:vdisk ) >= 1
    for: 30m
    labels:
      physical_disk_status: 'critical'
    annotations:
      summary: "{{ $labels.instance }}'s Disk Error"



Prometheus에서 알람을 정의

  • Prometheus 설정 파일인 promethes.yml에 알람 yml 파일 추가

    $ vi /etc/prometheus/prometheus.yml
    global:
      scrape_interval: 15s
      evaluation_interval: 15s
      external_labels:
        cluster: prometheus
        replica: 0
    
    rule_files:
      - '/etc/prometheus/rules/hardware_rule.yml'
      - '/etc/prometheus/rules/disk_rule.yml'
    
    scrape_configs:
      - job_name: 'node-exporter'
        scrape_interval: 5s
        static_configs:
          - targets:
            - [node-exporter 서버 IP]:9100
    
      - job_name: 'dellhw_exporter'
        scrape_interval: 60s
        static_configs:
          - targets:
            - [dellhw_exporter 서버 IP]:9137

  • 일정 시간 Pending 상태로 유지 → 계속 fault가 발생하면 State에 Firing 표시

  • 알람에 문제가 발생하여 State에 Firing 표시


Alertmanager 설치

1. Alertmanager 다운로드

# Alertmanager 다운로드
$ cd /root
$ wget https://github.com/prometheus/alertmanager/releases/download/v0.24.0/alertmanager-0.24.0.linux-amd64.tar.gz
$ tar xvzf alertmanager-0.24.0.linux-amd64.tar.gz
alertmanager-0.24.0.linux-amd64/
alertmanager-0.24.0.linux-amd64/alertmanager.yml
alertmanager-0.24.0.linux-amd64/LICENSE
alertmanager-0.24.0.linux-amd64/NOTICE
alertmanager-0.24.0.linux-amd64/alertmanager
alertmanager-0.24.0.linux-amd64/amtool

$ mkdir /etc/alertmanager
$ cp /root/alertmanager-0.24.0.linux-amd64/* /etc/alertmanager/
$ rm -rf /root/alertmanager-0.24.0.linux-amd64

2. systemd로 Alertmanager 서비스 관리

# Alertmanager 서비스를 systemd로 관리
$ cat << EOF | tee /usr/lib/systemd/system/alertmanager.service
[Unit]
Description=Alert Manager
Wants=network-online.target
After=network-online.target

[Service]
User=root
Group=root
Type=simple
ExecStart=/etc/alertmanager/alertmanager --config.file=/etc/alertmanager/alertmanager.yml

[Install]
WantedBy=multi-user.target
EOF

# Alertmanager 서비스 실행  
$ /bin/systemctl daemon-reload
$ /bin/systemctl restart alertmanager.service
$ /bin/systemctl status alertmanager.service
Loaded: loaded (/usr/lib/systemd/system/alertmanager.service; disabled; vendor preset: disabled)
   Active: active (running) since Mon 2022-04-04 12:38:19 KST; 5s ago
 Main PID: 55991 (alertmanager)
    Tasks: 24
   Memory: 28.0M
   CGroup: /system.slice/alertmanager.service
           └─55991 /etc/alertmanager/alertmanager --config.file=/etc/alertmanager/alertmanager.yml

Alertmanger의 설정 파일인 alertmanager.yml 생성

  • Slack App의 웹훅 URL을 설정

    $ vi /etc/alertmanager/alertmanager.yml
    global:
      resolve_timeout: 5m
      slack_api_url: "https://hooks.slack.com/services/???????????????????????????"    # slack 웹훅 URL 필요
    
    route:
      receiver: 'slack-notifications'
      repeat_interval: 2m
    receivers:
      - name: 'slack-notifications'
        slack_configs:
        - channel: '[#slack channel 이름]'
          username: "Prometheus"
          send_resolved: true
          title: "{{ range .Alerts }}{{ .Annotations.summary }}\n{{ end }}"
          text: "{{ range .Alerts }}{{ .Annotations.description }}\n{{ end }}"
    
    # alertmanager 재실행 및 상태 확인
    $ systemctl restart alertmanager
    $ systemctl status alertmanager
    ● alertmanager.service - Alert Manager
       Loaded: loaded (/usr/lib/systemd/system/alertmanager.service; disabled; vendor preset: disabled)
       Active: active (running) since Tue 2022-04-05 01:56:21 KST; 4s ago
     Main PID: 108698 (alertmanager)
       Tasks: 24
     Memory: 26.6M
     CGroup: /system.slice/alertmanager.service
              └─108698 /etc/alertmanager/alertmanager --config.file=/etc/alertmanager/alertmanager.yml

Alertmanger의 설정을 prometheus.yml 파일에 추가

$ vi /etc/prometheus/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s
  external_labels:
    cluster: prometheus
    replica: 0

rule_files:
  - '/etc/prometheus/rules/hardware_rule.yml'

alerting:
  alertmanagers:
  - scheme: http
    static_configs:
    - targets:
      - "[alertmanager가 설치된 서버 IP]:9093"   # <alertmanager ip:port>

scrape_configs:
  - job_name: 'node-exporter'
    scrape_interval: 5s
    static_configs:
      - targets:
        - [node-exporter 서버 IP]:9100

  - job_name: 'dellhw_exporter'
    scrape_interval: 60s
    static_configs:
      - targets:
        - [dellhw_exporter 서버 IP]:9137
        - [dellhw_exporter 서버 IP]:9137

Alertmanager 웹 UI

  • http://[alertmanager가 설치된 서버 IP:9093/#/alerts)에서 Prometheus에서 발생한 알람
  • 알람 관리 UI 확인

  • blackbox monitoring은 증상이 발생한 부분을 확인하며, 예측되지 않은 활성 문제를 모니터링
  • blackbox monitoring을 통해 시스템이 제대로 작동하지 않음을 확인 한 이후에 whiteblox monitoring의 계측을 통해 로그 또는 HTTP 엔드 포인트와 같은 시스템 내부를 검사하는 기능
  • blackbox monitoring은 외부에서 시스템 상태를 확인(예 : 서버가 200 개의 HTTP 코드로 응답)
  • whiteblox monitoring은 내부 메트릭과 로그를 사용하여 시스템 문제를 표면화

blackbox monitoring과 whiteblox monitoring의 차이

  • 모니터링은 어떤 방법을 체택하는지에 따라 크게 writebox monitoring과 blackbox monitoring으로 구분

1. whitebox monitoring

  • 에이전트 혹은 소프트웨어를 설치해서 모니터링
  • Zabbix, PRTG, Prometheus 등이 whitebox monitoring에 속함 → 일반적인 모니터링 기술들
  • whitebox monitoring은 접근성은 좋으나 실제 모니터링 시스템을 구축할 때 모니터링 "소스(source)"가 되는 기술에 대한 이해도가 높아야함

2. blackbox monitoring

  • 시스템 내부가 어떻게 동작하는지보다 관측 가능한 행위에 초점을 두는 모니터링
  • CPU가 어떻게 동작하는지, Memory가 어떻게 동작하는지 몰라도 됨 → CPU 사용량이 얼마인지, Memory 사용량이 얼마인지가 중요
  • TCP가 어떻게 동작하는지 알 필요 X → 실행되는 프로세스에 TCP 연결이 가능한지 여부가 중요
  • 모니터링하려고 하는 내용의 동작 원리를 알지 못하여도 문제되지 않음
  • blackbox monitoring 쪽에서 유명한 기술은 Nagios

3. Prometheus는 whitebox monitoring과 blackbox monitoring 둘다 가능

  • Prometheus는 기본적으로 whitebox monitoring에 속하지만, 프로메테우스 재단은 Prometheus로 blackbox monitoring을 지원하기 위해서, 공식적으로 blackbox-exporter를 지원
  • blackbox-exporter는 HTTP, HTTPS는 물론 TCP, ICMP, DNS 등의 프로토콜 위에서 동작하는 엔드포인트들에 대한 blackbox monitoring을 가능하게 해줌
  • Prometheus쪽에서 해당 IP:PORT 정보를 제공해야만 모니터링 가능


blackbox-exporter와 설치

1. 서버 환경에서는 blackbox-exporter 스크립트 명령어 설치 및 구동

# 현재 디렉토리 위치
$ pwd
/root

# blackbox-exporter를 설치할 디렉토리 생성
$ mkdir black

# 디렉토리 이동
$ cd black

# 최신 버전 blackbox-exporter 설치
$ wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.18.0/blackbox_exporter-0.18.0.linux-amd64.tar.gz

# 압축 파일 해제
$ tar zxvf blackbox_exporter-0.18.0.linux-amd64.tar.gz
blackbox_exporter-0.18.0.linux-amd64/
blackbox_exporter-0.18.0.linux-amd64/blackbox_exporter
blackbox_exporter-0.18.0.linux-amd64/LICENSE
blackbox_exporter-0.18.0.linux-amd64/blackbox.yml
blackbox_exporter-0.18.0.linux-amd64/NOTICE

# 압축해제된 디렉토리에 접근
$ cd blackbox_exporter-0.18.0.linux-amd64/

# blackbox-exporter 실행
$ ./blackbox_exporter

2. blackbox.yml 설정 파일을 토대로 blackbox-exporter 스크립트 실행

# <blackbox_exporter 경로> --config.file=<blackbox_exporter 설정 파일 경로>
$ ./blackbox_exporter --config.file=./blackbox.yml

3. blackbox-exporter 서비스로 실행 → blackbox-exporter 명령어를 systemd로 관리

$ pwd
/root/black/blackbox_exporter-0.18.0.linux-amd64/

# user 추가
$ useradd --no-create-home --shell /bin/false blackbox_exporter

# 생성한 blackbox_exporter 계정 확인
$ cat /etc/passwd | grep blackbox_exporter
blackbox_exporter:x:1004:1004::/home/blackbox_exporter:/bin/false

# 실행 파일 및 설정 파일 /usr/local/bin/으로 경로 이동
$ cp ./blackbox_exporter /usr/local/bin
$ cp ./blackbox.yml /usr/local/bin

# /usr/local/bin/blackbox_exporter blackbox_exporter 유저, 그룹 권한 주기
$ chown blackbox_exporter:blackbox_exporter /usr/local/bin/blackbox_exporter

# 명령어 복사 및 사용 권환 변경 확인
$ ls -al /usr/local/bin/blackbox_exporter
-rwxr-xr-x 1 blackbox_exporter blackbox_exporter 18264924 Nov 22 17:34 /usr/local/bin/blackbox_exporter

# 서비스 파일 등록
$ cat << EOF | tee /etc/systemd/system/blackbox_exporter.service
[Unit]
Description=Blackbox Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=blackbox_exporter
Group=blackbox_exporter
Type=simple
ExecStart=/usr/local/bin/blackbox_exporter --config.file=/usr/local/bin/blackbox.yml

[Install]
WantedBy=multi-user.target
EOF

# 데몬 리로드
$ systemctl daemon-reload

# 서비스 구동
$ systemctl restart blackbox_exporter

# 서비스 상태 확인
$ systemctl status blackbox_exporter
● blackbox_exporter.service - Blackbox Exporter
   Loaded: loaded (/etc/systemd/system/blackbox_exporter.service; disabled; vendor preset: disabled)
   Active: active (running) since Mon 2021-11-22 17:35:28 KST; 4s ago
 Main PID: 6615 (blackbox_export)
    Tasks: 7
   Memory: 2.2M
   CGroup: /system.slice/blackbox_exporter.service
           └─6615 /usr/local/bin/blackbox_exporter --config.file=/usr/local/bin/blackbox.yml

4. blackbox-exporter 설정

  • blackbox-exporter가 Prometheus가 설정한 IP:PORT에서 TCP 통신이 가능한지 여부에 대한 메트릭을 수집하게 하려면 설정 파일에서 모듈 생성 필요
  • 지정한 IP:PORT에서 5초 주기로 TCP 통신을 시도
  • 다른 프로토콜도 확인 가능 : https://github.com/prometheus/blackbox_exporter/blob/master/CONFIGURATION.md
    # tcp 프토토콜 5초 간격으로 connect 확인
    $ vi /usr/local/bin/blackbox.yml
    modules:
      tcp_connect:
        prober: tcp
        timeout: 5s
  • 최초 blackbox.yaml의 기본 내용
    $ vi /usr/local/bin/blackbox.yml
    modules:
      http_2xx:
        prober: http
      http_post_2xx:
        prober: http
        http:
          method: POST
      tcp_connect:
        prober: tcp
      pop3s_banner:
        prober: tcp
        tcp:
          query_response:
          - expect: "^+OK"
          tls: true
          tls_config:
            insecure_skip_verify: false
      ssh_banner:
        prober: tcp
        tcp:
          query_response:
          - expect: "^SSH-2.0-"
      irc_banner:
        prober: tcp
        tcp:
          query_response:
          - send: "NICK prober"
          - send: "USER prober prober prober :prober"
          - expect: "PING :([^ ]+)"
            send: "PONG ${1}"
          - expect: "^:[^ ]+ 001"
      icmp:
        prober: icmp

5. blackbox-exporter 서비스로 재실행

$ systemctl restart blackbox_exporter

# 서비스 상태 확인
$ systemctl status blackbox_exporter
● blackbox_exporter.service - Blackbox Exporter
   Loaded: loaded (/etc/systemd/system/blackbox_exporter.service; disabled; vendor preset: disabled)
   Active: active (running) since Mon 2021-11-22 17:37:32 KST; 5s ago
 Main PID: 8674 (blackbox_export)
    Tasks: 8
   Memory: 2.1M
   CGroup: /system.slice/blackbox_exporter.service
           └─8674 /usr/local/bin/blackbox_exporter --config.file=/usr/local/bin/blackbox.yml



Prometheus에서 blackbox-exporter 연동

  • Prometheus에서 blackbox-exporter가 수집하고 있는 메트릭을 스크래이핑
  • Prometheus 설정 파일을 보면 scrape_config 밑에 job이 등록
  • blackbox-exporter 추출 : http://:9115/probe?target=<static_configs.targets의IP:PORT>&module=<params.module의 모듈>
    1. static_configs.targets에 있는 "IP:PORT" 별로 데이터를 수집
    2. params.module은 blackbox-exporter 설정 파일에서 작성한 모듈 목록
    3. 현재는 TCP 연결만 확인하는 tcp_connect
  • Prometheus가 scrape_interval에 설정된 주기마다 각 인스턴스들에서 수집되는 메트릭을 스크래이핑하여 저장
    1. blackbox-exporter와 prometheus의 timeout 시간이 각각 있기에 주기는 2개 합산
    2. blackbox-exporter의 timeout인 5s + prometheus의 scrape_interval인 5s = 10s
  • metric_path가 "/probe"로 지정

  • relabel_configs는 설정 파일 형식 토대로 생성 → replacement는 "<blackbox 설치된 인스턴스 IP:9115>"

    $ vi /etc/prometheus/prometheus.yml
    # my global config
    global:
      scrape_interval:     15s # By default, scrape targets every 15 seconds.
      evaluation_interval: 15s # By default, scrape targets every 15 seconds.
    
      external_labels:
        monitor: 'kubernetes-monitoring'
    
       # prometheus에 blackbox-exporter를 추가
      - job_name: 'blackbox-exporter'
        scrape_interval: 5s
        metrics_path: /probe
        params:
          module: [tcp_connect] 
        static_configs:
          - targets:
            - [모니터링 서버 IP]:80
        relabel_configs:
          - source_labels: [__address__]
            target_label: __param_target
          - source_labels: [__param_target]
            target_label: instance
          - target_label: __address__
            replacement: [blackbox 설치된 인스턴스 IP]:9115
  • Prometheus 재구동

    # Prometheus 서비스 재시작
    $ systemctl restart prometheus
    
    # prometheus 서비스 상태 확인
    $ systemctl status prometheus

  • Prometheus UI에서 쿼리를 입력 → blackbox-exporter 설치한 서버의 값 읽음 (probe_success)
  • probe_success가 blackbox-exporter가 지정한 프로토콜 방식으로 IP:PORT와 연결이 성공했음을 알리는 지표

blackbox 서버 모니터링을 위한 Grafana 대시보드 구축

  • Grafana로 대시보드를 구축할 때 정말 좋은 점은 black-exporter같이 많이 사용하는 Exporter에 대한 대시보드가 이미 공유됨
    손쉽게 사용 가능

1. blackb-exporter 그라파다 대시보드 복사 가능한 대시보드 ID 획득

  • node-exporter 그라파나 대시보드 복사 가능하게 하는 URL : https://grafana.com/grafana/dashboards/13659
  • 위 경로에 접속하면 아래 화면이 보이는데 "Copy ID to Clipboard"를 클릭하여 복사함

2. 그라파나 대시보드로 이동한 후, 왼쪽 탭의 두 번째 "+"의 "Import" 메뉴를 클릭



3. 위에서 복사한 대시보드 ID를 입력하고 "Load" 버튼을 클릭



4. "Datasource"에서 "Prometheus"를 선택한 뒤 "Import"를 클릭


5. 생성한 대시보드 화면 확인

  • 해당 포트에 매핑된 프로세스가 살아나면 다시 "UP"으로 표시
  • 프로세스 포트 모니터링에서 중요한 것은 "UP & DOWN" 표시
  • "probe duration"이나 "dns lookup" 정보들은 프로세스보다는 프로세스가 동작하는 인스턴스가 살아있음을 알려줌

참고 URL : https://lapee79.github.io/article/monitoring-http-using-blackbox-exporter/
참고 URL : https://gurumee92.tistory.com/235?category=933410
참고 URL : https://github.com/prometheus/blackbox_exporter

+ Recent posts