λ€μ΄κ°κΈ° μ μ
μλΉμ€ λ°μΉ μ΄κΈ° μ μ κ° κΈκ²©ν μ μ λμμ§λ§, μ¬μν λ²κ·Έκ° μ μ κ²½νμ μ μν₯μ λ―Έμ³ μ μ μ΄νμ΄ λ°μνλ κ²μ μ’ μ’ λ³΄μμ΅λλ€. μ€μ λ‘ μμ μλΉμ€(https://bibbi.app/) λ°°ν¬ μ΄ν λ°μν λ²κ·Έλ₯Ό λ€λ¦κ² λ°κ²¬νκ³ μΌνλ μ€ κΈν λ°μ΄λκ° μ νλ₯Ό λ리며 λ¬Έμ λ₯Ό νμ νκ³ ν«ν½μ€ νλ κ²½νμ νκ³ .... π₯² μ΄λ‘μΈν΄ ν λ΄μμ μλΉμ€ λͺ¨λν°λ§μ΄ νμνλ€λ μκ²¬μ΄ λμμ΅λλ€.
μ€μ λ‘ μλΉμ€λ₯Ό μ΄μνκ³ λ§μ μμ νΈλν½μ΄ λ°μνλ©΄μ κΈ°μ‘΄μ μ€νλ§ λΆνΈ ν°λ―Έλ λ‘κ·Έλ‘λ μλ¬ μΆμ μ΄λ νΈλν½ κ΄μΈ‘μ΄ λΆκ°λ₯νλ€κ³ λκΌμ΅λλ€. μ€μκ°μΌλ‘ λ§μ μμ λ‘κ·Έκ° μμ΄κ³ μκΈ° λλ¬Έμ ν°λ―Έλμμ plain textλ‘λΆν° μνλ λ°μ΄ν°λ₯Ό μ°Ύλ κ²μ κ΅μ₯ν μ΄λ €μ κ³ , 24μκ° λ‘κ·Έλ₯Ό νμΈν μ μλ λ Έλ¦μ΄λ νΈλν½μ λͺ¨λν°λ§ν μ μλ λμ보λμ 경보 μμ€ν λ νμνμ΅λλ€.
λ°λΌμ λ€μν λͺ¨λν°λ§ μμ€ν μ μΆκ°ν΄μλλ°, λΉμμλ λͺ°λμ§λ§ μ΄ μμ λ€μ΄ λ§λ‘λ§ λ£λ SRE(Site Reliability Engineering)μ΄μλ κ² κ°μ΅λλ€. λͺ¨λν°λ§ μμ€ν μ ν΅ν΄ μμΈμ μλ¬λ₯Ό κ°μ§νκ³ , κ°μ§ν λ°μ΄ν°λ€μ λ΄λΉ νμμκ² μ λ¬νμ¬ λλ²κΉ ν μ μλλ‘ λμμ£Όμμ΅λλ€. λ³Έ κ²μκΈλ€μ ν΅ν΄ λͺ¨λν°λ§ μμ€ν μ ꡬμΆνλ κ³Όμ κ³Ό μ λ§μ λ Ένμ°λ₯Ό 곡μ ν΄λ³΄κ³ μ ν©λλ€.
νλ‘λ©ν μ°μ€ & κ·ΈλΌνλ λμ
첫 λͺ¨λν°λ§ μμ€ν μ νλ‘λ©ν μ°μ€ & κ·ΈλΌνλλ₯Ό ν΅ν νΈλν½ λͺ¨λν°λ§ λμ보λμμ΅λλ€. μΆκ°μ μΈ μλΉμ€ μ μ§ λΉμ©μμ΄ ν΄λΌμ°λ ν¬λ λ§μΌλ‘ ꡬννκΈΈ μνκΈ° λλ¬Έμ, μ€νμμ€μ΄λ©΄μ μ€νλ§ λΆνΈμ νΈνμ±μ΄ λμ νλ‘λ©ν μ°μ€μ PromQLλ§ μλ©΄ λ€μν λμ보λλ₯Ό μμ½κ² κΎΈλ° μ μμΌλ©° νλ‘λ©ν μ°μ€μ νΈνμ±μ΄ μ’μ κ·ΈλΌνλλ₯Ό μ ννμμ΅λλ€.
λν ν΄λΌμ°λ ν¬λ λ§κ³Ό λΉμ© κ΄κ³μ λ°λΌ μΈνλΌλ₯Ό μμ£Ό μ΄κ΄ν κ²μ΄ μμλμκΈ° λλ¬Έμ, 컨ν μ΄λ κΈ°λ°μΌλ‘ μμ€ν λ€μ κ΄λ¦¬νμΌλ©°, λΆνμνκ² μκ°μ΄ μμλλ λ€νΈμν¬ μ€μ μ μ루μ μ 맑기기 μν΄ Nginx Proxy Managerμ λμ νμ΅λλ€.
Nginx Proxy Manager μ€μΉ
λ°±μλλ₯Ό λ°°ν¬ν΄λ³Έ μ¬λμ΄λΌλ©΄ HTTPS μ°κ²°μ μν΄ ν λ²μ―€μ Let's Encryptλ ACMEμ μ¨λ¦ν΄λ³΄μμ κ² μ λλ€. νμ§λ§ λͺ¨λν°λ§ λ°±μ€νΌμ€λ₯Ό μν΄ νλ‘μ, SSLμ μκ°μ μ°κΈ΄ μκΉμ£ . Nginx Proxy Managerλ nginxμ GUI μ루μ μΌλ‘μ, nginx.conf λ₯Ό ν΅ν νλ‘μ μ€μ μ κ°λ¨ν UIλ₯Ό ν΅ν΄ κ°λ₯μΌνλ©° Let's EncryptκΈ°λ° μΈμ¦μ μ€μ μ΄ μν΄λ¦μΌλ‘ κ°λ₯ν©λλ€. μ΄μ λν μμΈν μ€μ κ°μ΄λλ μ΄ν λ³λμ κ²μκΈλ‘ μ 리ν΄λ³΄κ² μ΅λλ€.
1. docker-compose-nginx.yml μμ± λ° μ€ν
version: '3.8'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
container_name: nginx
restart: always
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./nginx/data:/data
- ./nginx/letsencrypt:/etc/letsencrypt
- restart: always : μΈμ€ν΄μ€κ° μ¬λΆν νλλΌλ νλ‘μ 컨ν μ΄λκ° λ μ¬μ€ννλλ‘ μ€μ
- ports: - '81:81' : Nginx Proxy Manager μ½μ λν΄νΈ ν¬νΈ
- volumes: - ~ : 컨ν μ΄λ μ΄λ―Έμ§λ₯Ό λ΄λ €λ°μ λ μλμΌλ‘ λ€μ΄λ‘λλλ ν¨ν€μ§ νμΌλ€ (맀ννλ μ’μΈ‘ μμ€ λλ ν 리λ μμ λ‘κ² λ³κ²½ κ°λ₯)
2. Let's Encrypt κΈ°λ° SSL μΈμ¦μ μ€μ
3. νΈμ€νΈ νλ‘μ μ€μ
νλ‘λ©ν μ°μ€ & κ·ΈλΌνλ μ€μΉ
ν¨κ» μ¬μ©νλ νλ‘λ©ν μ°μ€μ κ·ΈλΌνλλ νλμ docker compose νμΌμ κ΄λ¦¬νμμ΅λλ€.
1. ./monitor, ./monitor/prometheus.yml μμ±
2. docker-compose-monitor.yml μμ± λ° μ€ν
version: '3'
services:
prometheus:
image: prom/prometheus
container_name: prometheus
volumes:
- ./monitor/prometheus.yml:/prometheus/prometheus.yml:ro
- /root/ecs-discovery/ecs_file_sd.yml:/etc/prometheus/bibbi.yml:ro
ports:
- 8080:9090
command:
- "--web.enable-lifecycle"
restart: always
networks:
- promnet
user: root
grafana:
image: grafana/grafana
container_name: grafana
volumes:
- ./monitor/grafana-volume:/var/lib/grafana
restart: always
environment:
GF_SERVER_ROOT_URL: <https://grafana.no5ing.kr:443>
GF_SERVER_DOMAIN: grafana.no5ing.kr
networks:
- promnet
ports:
- 8070:3000
user: root
networks:
promnet:
driver: bridge
- volumnes: ./monitor/prometheus.yml:~~ : λ©νΈλ¦ ν¬λ§ μ£ΌκΈ° λ±μ νλ‘λ©ν μ°μ€ μ€μ κ°μ λ΄μ νμΌ
- ports: -8080:9090 ports: -8070:3000 : νλ‘λ©ν μ°μ€μ λν΄νΈ ν¬νΈλ 9090, κ·ΈλΌνλλ 3000
- networks: promnet: driver: bridge : 컨ν μ΄λ λͺ μ ν΅ν΄ 컨ν μ΄λμ μ μν μ μλλ‘, promnetμ΄λΌλ bridge Docker networkλ₯Ό μμ±νκ³ μ°κ²°
3. νλ‘λ©ν μ°μ€ μ½μ μ μ
4. κ·ΈλΌνλ μ½μ μ μ
- π¨ λ°λμ λν΄νΈ κ³μ λ³κ²½νμΈμ π¨
- λν΄νΈ μμ΄λ : admin / λν΄νΈ λΉλ°λ²νΈ : admin
μ€νλ§ λͺ¨λν°λ§ νκ²½ μ€μ
λͺ¨λν°λ§ μμ€ν μ€μΉλ λλ¬μΌλ, μ€νλ§μμ λͺ¨λν°λ§ ν 맀νΈλ¦μ μ 곡νκΈ° μν νκ²½μ€μ μ ν μ°¨λ‘μ λλ€.
Spring boot Actuatorλ₯Ό ν΅ν΄ HTTPλ JMXλ₯Ό μ΄μ©ν 맀νΈλ¦μ μμ±ν©λλ€. κ·Έλ¦¬κ³ μμ±λ 맀νΈλ¦λ€μ νλ‘λ©ν μ°μ€μ κ°μ λ€μν 맀νΈλ¦ μμ§ μννΈμ¨μ΄λ€μ΄ ν΄λ§ν μ μλλ‘ μΆμνλ νμ¬λλ₯Ό μ 곡νλ Micrometerλ₯Ό μ€μΉν©λλ€.
1. build.gradle μ μμ‘΄μ± μΆκ°
- λ©ν°λͺ¨λμ κ²½μ°, μλ² μ€ν μ£Όμ²΄κ° λλ λͺ¨λ(API, Gateway)μ μΆκ°νλ©΄ λ©λλ€.
implementation 'org.springframework.boot:spring-boot-starter-actuator' // actuator
implementation 'io.micrometer:micrometer-registry-prometheus' // micrometer for prometheus
2. application.yaml μ Actuator νκ²½ μ€μ
management:
endpoints:
web:
exposure:
include: "*"
---
management:
endpoints:
web:
exposure:
include: health,info,prometheus
μ€μΉκ° μλ£λλ©΄, https://DOMAIN/actuator μμ κ° λ§€νΈλ¦μ νμΈν μ μλ actuator urlλ€μ λν μ 보λ₯Ό μ 곡ν©λλ€. νμν 맀νΈλ¦ μΈμ 곡κ°νμ§ μλ κ²μ΄ 보μμ μΌλ‘ μμ νλ―λ‘, νμ΄νΈλ¦¬μ€νΈ λ°©μμΌλ‘ νμν urlμ μ€μ νλ κ²μ μΆμ²ν©λλ€. μ μ κ²½μ°λ instance server μ 보, health check, prometheus 맀νΈλ¦μ΄ νμνλ―λ‘ 3κ°μ§ urlλ§ λ ΈμΆμμΌ°μ΅λλ€.
μ€μ μ΄ μλ£λμμ΅λλ€!
νλ‘λ©ν μ°μ€ νμΌ μ€μ
μ΄μ λ€μ νλ‘λ©ν μ°μ€λ‘ λμκ° λ§€νΈλ¦ νκ²½μ€μ μ΄ μλ£λ μλ²λ₯Ό λͺ¨λν°λ§ νμΌμΌλ‘ μ€μ νλ μ μ°¨λ₯Ό λ§μΉλ©΄, νλ‘λ©ν μ°μ€κ° μ μμ μΌλ‘ 맀νΈλ¦μ ν΄λ§ν μ μμ΅λλ€.
- ./monitor/prometheus.yaml μμ 맀νΈλ¦ μμ§ νμΌ μ€μ
global:
scrape_interval: 10s
evaluation_interval: 10s
scrape_configs:
- job_name: 'bibbi-prod-was' // λͺ¨λν°λ§ Target μ΄λ¦
metrics_path: '/actuator/prometheus' // 맀νΈλ¦ url
static_configs: // μ μ λͺ¨λν°λ§ λμ
- targets: ['api.no5ing.kr'] // Target λͺ©λ‘
μ΄μ μ μμ±ν νλ‘λ©ν μ°μ€ μ€μ νμΌμ μμ κ°μ΄ μ€μ ν ν, νλ‘λ©ν μ°μ€ 컨ν μ΄λλ₯Ό μ¬κΈ°λνλ©΄(docker compose -f ./docker-compose-monitor.yml up -d) λ³κ²½λ λ΄μμ΄ λ°μλ©λλ€. νλ‘λ©ν μ°μ€ μ½μμμ Status > Targets μ λ€μ΄κ°μ μ€μ ν μλν¬μΈνΈκ°μ μνκ° 'up'μ΄λ©΄ μ μμ μΌλ‘ ν΄λ§λκ³ μλ κ²μ λλ€. Graphμμ μ무 맀νΈλ¦μ μ λ ₯νκ³ μ‘°ννκ³ μ μμ μΌλ‘ νμΈν μ μμ΅λλ€.
κ·ΈλΌνλ λμ보λ ꡬμ±νκΈ°
μμ€ν μ λμ νλ κ²λ³΄λ€ μ€μν κ²μ μ΄λ»κ² μ νμ©νλμΌ κ²μ λλ€. κ·ΈλΌνλλ₯Ό ꡬμ±νλ λ°©λ²μ λκ°μ§μΈλ°, 1. μ£Όμ΄μ§ μκ°ν λꡬλ₯Ό μ΄μ©ν΄ μ§μ λμ보λλ₯Ό ꡬμ±νλ κ²μ΄κ³ , 2. λ€λ₯Έ μ¬λμ λμ보λλ₯Ό import νλ κ²μ λλ€. λ¬Όλ‘ importν λμ보λλ₯Ό 컀μ€ν°λ§μ΄μ§νλ κ²λ κ°λ₯ν©λλ€.
Grafana Labs(π Link) μ΄λ Githubμμ λ€μν λμ보λλ₯Ό urlμ΄λ json ννλ‘ import ν μ μμ΅λλ€. μ μ κ²½μ°μλ Grafana Labsμμ κ°μ₯ λ§μμ λλ λμ보λλ₯Ό μ μ©μμΌ PromQL νμ©λ²μ μ°μ΅νκ³ , μ ν¬ μμ€ν μ νμν λμ보λλ‘ μ‘°κΈμ© 컀μ€ν°λ§μ΄μ§ν΄ λκ°μ΅λλ€.
μ¬κΈ°μλ μ κ° μ»€μ€ν°λ§μ΄μ§ν λμ보λλ₯Ό 곡μ νκ³ , μ΄λ₯Ό κ°λ¨ν μ€λͺ νμ¬ ν΅μ¬ PromQLμ μ€λͺ ν΄λ³΄κ² μ΅λλ€. λμ보λ json νμΌμ μ κΉνλΈμμ νμΈν μ μμ΅λλ€.(π Github λ§ν¬)
PromQL
PromQL(Prometheus Query Language)μ Prometheusμμ μ¬μ©λλ 쿼리 μΈμ΄λ‘, μκ³μ΄ λ°μ΄ν°λ₯Ό 쿼리νκ³ λΆμνλλ° μ¬μ©λ©λλ€. λ°λΌμ νλ‘λ©ν μ°μ€λ‘ λΆν° λ°μμ¨ λ°μ΄ν°λ₯Ό λΆμνκ³ μκ°ννλλ‘ κ·ΈλΌνλλ₯Ό μ§μν©λλ€. λ€μν λ¬Έλ²μ΄ μ‘΄μ¬νμ§λ§ increase μ rate μ νμ©λ²μ μ΄ν΄νλ€λ©΄ λ€μν μκ°νλ₯Ό λ§λ€ μ μμ΅λλ€.
Increase (API μμ²λ_2XX μ μ μλ΅λ§)
increase(http_server_requests_seconds_count{instance="$instance", application="$application", uri!~".*actuator.*", uri!~".*swagger*.*", uri!~".*api-docs*.*", status=~"2.*"}[30s])
- http_server_requests_seconds_count : μλ²μ λ€μ΄μ¨ http μμ²μ λμ κ°―μ
- νλ‘λ©ν μ°μ€κ° μμ§ν 맀νΈλ¦μ κ·Έλλ‘ μ λ ₯ν κ²½μ° μ νν μκ°ν κ·Έλνμ λ§κ² ννλ©λλ€
- http_server_requests_seconds_count{instance="$instance", application="$application", uri!~".**actuator.**", uri!~".**swagger**.**", uri!~".*api-docs*.**", status=~"2.*"} : μ€μ λ μΈμ€ν΄μ€, μ΄ν리μΌμ΄μ
μμ urlμ actuator, swagger, api-docsλ₯Ό ν¬ν¨νμ§ μκ³ μλ΅ κ²°κ³Όκ° 2λ‘ μμν http μμ² λμ κ°―μ (μ€μ ν΄λΌμ΄μΈνΈμ μμ²λ§ νμΈνκΈ° μν΄ κ°λ°μμ© urlκ³Ό 맀νΈλ¦μ μμ§νκΈ° μν actuator urlμ μ μΈν¨)
- 맀νΈλ¦μ μ€κ΄νΈλ₯Ό λΆμ¬ λ°μ΄ν°μ λ€μν νν°λ₯Ό μ μ©ν μ μμ΅λλ€.
- $CONDITION : μλ¨λ°μμ μ μ κ° μ νν 쑰건 κΈ°μ€ (μΈμ€ν΄μ€, μ΄ν리μΌμ΄μ , μ‘°ν interval λ±)
- !~ : κ°μ§ μμ, =~ : κ°μ, .* : 0κ° μ΄μμ μμμ λ¬Έμ
- 맀νΈλ¦μ μ€κ΄νΈλ₯Ό λΆμ¬ λ°μ΄ν°μ λ€μν νν°λ₯Ό μ μ©ν μ μμ΅λλ€.
- increase(http_server_requests_seconds_count{instance="$instance", application="$application", uri!~".actuator.", uri!~".swagger.", uri!~".api-docs.", status=~"2.*"}[30s]) : 30μ΄ κ°κ²©μΌλ‘ http μμ² κ°―μμ λ³νλ ( = 30μ΄λ§λ€ λ°μν http μμ² μ)
- νΉμ μκ° λ²μ λ΄μμ μ£Όμ΄μ§ λ°μ΄ν°μ μ¦κ°λμ κ³μ°ν©λλ€.
Increase μμ© (Status code λΉμ¨)
increaseμ κ°κ²©μ μμ©νλ©΄ λ€μκ³Ό κ°μ λμ보λλ λ§λ€ μ μμ΅λλ€.
- sum(increase(http_server_requests_seconds_count{application="$application", uri!~".*actuator.*", uri!~".*swagger*.*", uri!~".api-docs.*", status="200"}[$__range]))
- sum(increase(http_server_requests_seconds_count{application="$application", uri!~".*actuator.*", uri!~".*swagger*.*", uri!~".api-docs.*", status="204"}[$__range]))
- sum(increase(http_server_requests_seconds_count{application="$application", uri!~".*actuator.*", uri!~".*swagger*.*", uri!~".api-docs.*", status="400"}[$__range]))
- …
- 10μ΄, 1μκ°, 6μ 첫째주 λ± λμ보λμ μ‘°ν μκ°μ λ€μνκ² μ‘°μ ν μ μλλ°, μ€μ ν μκ° λμ λ°μν http μ status code λΉμ¨μ λνλ λλ€.
- increase()λ₯Ό ν΅ν΄ url λ³ μμ² κ°―μλ₯Ό μ‘°ννλ―λ‘, sum() μ ν΅ν΄ λμΌν status codeμ μλ΅ κ°―μμ ν©κ³λ₯Ό ꡬν©λλ€.
Increase μμ© (μ λ‘λ λ κ²μκΈ μ)
- increase(http_server_requests_seconds_count{application="$application", uri="/v1/posts", method="POST", status="200"}[$__range])
- νΉμ κΈ°κ°λμ /v1/postsμ POST μμ²μ 보λ΄κ³ 200 μ μμλ΅μ λ°μ μμ²μ μ (μ λ‘λ λ κ²μκΈ μ)
- π¨ μκ³μ΄ λ°μ΄ν°μ λ³νλμ κ³μ°νλ 쿼리μ΄λ―λ‘, μ λμ μΈ λ°μ΄ν°λ μ±κ³Όμ μ νν μμΉλ₯Ό μ»κΈ°μν μ©λλ‘ μ¬μ©νλ κ²μ μΆμ²νμ§ μμ΅λλ€.
rate (API μμ²λ_2XX μ μ μλ΅λ§)
rate()[TIME] λ μΌμ μκ°λμ μκ³μ΄ λ°μ΄ν°μ λΉμ¨(λ³νμ¨)μ κ³μ°νλλ° μ¬μ©λ©λλ€. μ£Όλ‘ μΉ΄μ΄ν° λ©νΈλ¦(μ§μμ μΌλ‘ μ¦κ°νλ κ°, ex: HTTP μμ² μ, μλ¬ μ λ±)μ λ³νμ¨μ κ³μ°νμ¬ μ£Όμ΄μ§ μκ°λμ μΌλ§λ λ³ννλμ§ λνλ λλ€.
- sum(rate(http_server_requests_seconds_count{application="$application", uri!~".actuator.", uri!~".swagger.", uri!~".api-docs."}[1m]))
- μ§λ 1λΆ λμ HTTP μμ² λΉμ¨
λ§μΉλ©°
μ¬μ€ λ°μΉ ν λλ΄μΈμ μΌλ‘ μ¬μ© νκΈ°λ₯Ό μ ν΄λ€μκΈ° λλ¬Έμ μ ν¬κ° μΆμν μλΉμ€κ° μ¬μ©λκ³ μλ€λ κ²μ μκ³ μμμ΅λλ€. νμ§λ§ λμ보λλ₯Ό ν΅ν΄ μΌλ§λ μλΉμ€κ° μ¬μ©λμλμ§ μμΉλ‘ νμΈνκ³ μ€μκ°μΌλ‘ λ°μνλ νΈλν½μ 보면μ μ§λ λͺ λ κ°μ μ½λ© κ²½ν μ€ κ°μ₯ λΏλ―ν μμ μ΄μλ κ² κ°μ΅λλ€.
μμ μλΉμ€μ λν μ μ κ³Ό μ΄μ μ λ€μ ν λ² λΆνμΈ μ μμκ³ , λμ ν μμ€ν μ μ νμ©νκ³ λ°μ νμ¬ λ λ©μ§ μμλ‘ λ§λ€μ΄ λκ°κ² μ΅λλ€.
'π Activity > Project' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
κ°λ°μλ€μ΄ μμ¬ν μ μλ μμ μλΉμ€ λ§λ€κΈ°Β 2ν (κ·ΈλΌνλ 경보, Sentry) (0) | 2024.07.10 |
---|---|
LoRa Network performance enhancement (0) | 2024.02.25 |
Econo Beep (μμ½λ Έ μ‘) - 1.0 (Summer Dev Ver) - κ°λ° νκ³ λ‘ (0) | 2022.10.06 |
Profile (0) | 2019.07.07 |