SiamCafe · Blog
Opsgenie Alert กับ Remote Work Setup — วิธีตั้งค่าระบบแจ้งเตือน Incident สำหรับทีม Remote
บทความ

Opsgenie Alert กับ Remote Work Setup — วิธีตั้งค่าระบบแจ้งเตือน Incident สำหรับทีม Remote

เผยแพร่ 28 พฤษภาคม 2569

Opsgenie คืออะไร

Opsgenie เป็น Incident Management และ Alert Routing Platform ที่พัฒนาโดย Atlassian (เจ้าของ Jira, Confluence) ทำหน้าที่เป็นศูนย์กลางรับ Alert จาก Monitoring Tools ทั้งหมด เช่น Prometheus, Datadog, CloudWatch, Grafana, PagerDuty แล้ว Route ไปหาคนที่รับผิดชอบตาม On-call Schedule พร้อม Escalation ถ้าไม่มีคนรับภายในเวลาที่กำหนด

สำหรับทีม Remote Work ที่สมาชิกอยู่คนละ Timezone Opsgenie เป็นเครื่องมือที่จำเป็นเพราะจัดการ On-call Rotation ข้าม Timezone ได้อัตโนมัติ แจ้งเตือนผ่านหลายช่องทาง (Phone Call, SMS, Push Notification, Slack, Email) และมี Escalation Policy ที่ Ensure ว่า Alert จะไม่ถูกมองข้าม

การตั้งค่า On-call Schedule

# Opsgenie API — สร้าง On-call Schedule สำหรับ Remote Team
# ใช้ Opsgenie REST API v2

# 1. สร้าง Team
curl -X POST 'https://api.opsgenie.com/v2/teams' \
 -H "Authorization: GenieKey " \
 -H "Content-Type: application/json" \
 -d '{
 "name": "Platform Engineering",
 "description": "Platform team across APAC and EU timezones",
 "members": [
 {"user": {"username": "alice@company.com"}, "role": "admin"},
 {"user": {"username": "bob@company.com"}, "role": "user"},
 {"user": {"username": "charlie@company.com"}, "role": "user"},
 {"user": {"username": "dave@company.com"}, "role": "user"}
 ]
 }'

# 2. สร้าง On-call Schedule (Weekly Rotation)
curl -X POST 'https://api.opsgenie.com/v2/schedules' \
 -H "Authorization: GenieKey " \
 -H "Content-Type: application/json" \
 -d '{
 "name": "Platform On-call",
 "description": "Weekly rotation across timezones",
 "timezone": "Asia/Bangkok",
 "enabled": true,
 "ownerTeam": {"name": "Platform Engineering"},
 "rotations": [
 {
 "name": "Business Hours (APAC)",
 "type": "weekly",
 "startDate": "2026-03-01T09:00:00+07:00",
 "participants": [
 {"type": "user", "username": "alice@company.com"},
 {"type": "user", "username": "bob@company.com"}
 ],
 "timeRestriction": {
 "type": "weekday-and-time-of-day",
 "restrictions": [
 {"startDay": "monday", "startHour": 9, "startMin": 0,
 "endDay": "friday", "endHour": 18, "endMin": 0}
 ]
 }
 },
 {
 "name": "After Hours (EU)",
 "type": "weekly",
 "startDate": "2026-03-01T18:00:00+07:00",
 "participants": [
 {"type": "user", "username": "charlie@company.com"},
 {"type": "user", "username": "dave@company.com"}
 ],
 "timeRestriction": {
 "type": "weekday-and-time-of-day",
 "restrictions": [
 {"startDay": "monday", "startHour": 18, "startMin": 0,
 "endDay": "tuesday", "endHour": 9, "endMin": 0}
 ]
 }
 }
 ]
 }'

# 3. สร้าง Escalation Policy
curl -X POST 'https://api.opsgenie.com/v2/escalations' \
 -H "Authorization: GenieKey " \
 -H "Content-Type: application/json" \
 -d '{
 "name": "Platform Escalation",
 "ownerTeam": {"name": "Platform Engineering"},
 "rules": [
 {
 "condition": "if-not-acked",
 "notifyType": "default",
 "delay": {"timeAmount": 5, "timeUnit": "minutes"},
 "recipient": {"type": "schedule", "name": "Platform On-call"}
 },
 {
 "condition": "if-not-acked",
 "notifyType": "default",
 "delay": {"timeAmount": 15, "timeUnit": "minutes"},
 "recipient": {"type": "user", "username": "alice@company.com"}
 },
 {
 "condition": "if-not-acked",
 "notifyType": "default",
 "delay": {"timeAmount": 30, "timeUnit": "minutes"},
 "recipient": {"type": "team", "name": "Platform Engineering"}
 }
 ]
 }'

Alert Integration กับ Monitoring Tools

# Python Script — Opsgenie Alert Integration
import requests
import json
from datetime import datetime

class OpsgenieClient:
 """Client สำหรับ Opsgenie API"""

 def __init__(self, api_key):
 self.api_key = api_key
 self.base_url = "https://api.opsgenie.com/v2"
 self.headers = {
 "Authorization": f"GenieKey {api_key}",
 "Content-Type": "application/json",
 }

 def create_alert(self, message, description="", priority="P3",
 tags=None, details=None, team=None):
 """สร้าง Alert ใหม่"""
 payload = {
 "message": message,
 "description": description,
 "priority": priority,
 "tags": tags or [],
 "details": details or {},
 }
 if team:
 payload["responders"] = [{"type": "team", "name": team}]

 resp = requests.post(
 f"{self.base_url}/alerts",
 headers=self.headers,
 json=payload,
 )
 return resp.json()

 def close_alert(self, alert_id, note=""):
 """ปิด Alert"""
 resp = requests.post(
 f"{self.base_url}/alerts/{alert_id}/close",
 headers=self.headers,
 json={"note": note},
 )
 return resp.json()

 def get_on_call(self, schedule_name):
 """ดูว่าใคร On-call อยู่ตอนนี้"""
 resp = requests.get(
 f"{self.base_url}/schedules/{schedule_name}/on-calls",
 headers=self.headers,
 params={"flat": True},
 )
 return resp.json()

 def get_alert_count(self, query="status:open"):
 """นับจำนวน Alert ที่เปิดอยู่"""
 resp = requests.get(
 f"{self.base_url}/alerts/count",
 headers=self.headers,
 params={"query": query},
 )
 return resp.json()

# ตัวอย่างการใช้งาน
client = OpsgenieClient(api_key="your-api-key")

# สร้าง Alert เมื่อ CPU สูง
alert = client.create_alert(
 message="[CRITICAL] web-server-01 CPU > 95%",
 description="CPU usage exceeded 95% for 5 minutes",
 priority="P1",
 tags=["infrastructure", "cpu", "critical"],
 details={
 "host": "web-server-01",
 "metric": "cpu_usage_percent",
 "value": "97.3",
 "threshold": "95",
 "region": "ap-southeast-1",
 },
 team="Platform Engineering",
)
print(f"Alert created: {alert}")

# ดูว่าใคร On-call
oncall = client.get_on_call("Platform On-call")
print(f"Current on-call: {oncall}")

---
# Prometheus Alertmanager → Opsgenie Integration
# alertmanager.yml
global:
 resolve_timeout: 5m
 opsgenie_api_key: ""

route:
 group_by: ['alertname', 'cluster', 'service']
 group_wait: 30s
 group_interval: 5m
 repeat_interval: 4h
 receiver: 'opsgenie-critical'
 routes:
 - match:
 severity: critical
 receiver: 'opsgenie-critical'
 group_wait: 10s
 - match:
 severity: warning
 receiver: 'opsgenie-warning'
 group_wait: 1m

receivers:
 - name: 'opsgenie-critical'
 opsgenie_configs:
 - api_key: ""
 message: '{{ .GroupLabels.alertname }}: {{ .CommonAnnotations.summary }}'
 description: '{{ .CommonAnnotations.description }}'
 priority: P1
 tags: 'prometheus, critical,{{ .GroupLabels.cluster }}'
 responders:
 - type: team
 name: Platform Engineering

 - name: 'opsgenie-warning'
 opsgenie_configs:
 - api_key: ""
 message: '{{ .GroupLabels.alertname }}: {{ .CommonAnnotations.summary }}'
 priority: P3
 tags: 'prometheus, warning'

Notification Policy สำหรับ Remote Team

# Terraform — Opsgenie Configuration as Code
# main.tf

terraform {
 required_providers {
 opsgenie = {
 source = "opsgenie/opsgenie"
 version = "~> 0.6"
 }
 }
}

provider "opsgenie" {
 api_key = var.opsgenie_api_key
}

# Team
resource "opsgenie_team" "platform" {
 name = "Platform Engineering"
 description = "Platform team for infrastructure"

 member {
 id = opsgenie_user.alice.id
 role = "admin"
 }
 member {
 id = opsgenie_user.bob.id
 role = "user"
 }
}

# Notification Policy
resource "opsgenie_notification_policy" "critical_alerts" {
 name = "Critical Alert Policy"
 team_id = opsgenie_team.platform.id
 enabled = true

 filter {
 type = "match-all-conditions"
 conditions {
 field = "priority"
 operation = "equals"
 expected_value = "P1"
 }
 }

 # ลำดับการแจ้งเตือน
 time_restriction {
 type = "time-of-day"
 restriction {
 start_hour = 0
 start_min = 0
 end_hour = 23
 end_min = 59
 }
 }

 # Auto-close ถ้าไม่มี Activity 24 ชั่วโมง
 auto_close_action {
 duration {
 time_amount = 24
 time_unit = "hours"
 }
 }

 # Auto-restart Notification ถ้ายังไม่ Ack
 auto_restart_action {
 duration {
 time_amount = 10
 time_unit = "minutes"
 }
 max_repeat_count = 3
 }
}

# Integration — Slack
resource "opsgenie_api_integration" "slack" {
 name = "Slack Integration"
 type = "Slack"

 owner_team_id = opsgenie_team.platform.id
 enabled = true

 responders {
 type = "team"
 id = opsgenie_team.platform.id
 }
}

Remote Work Best Practices สำหรับ Incident Management

  • Follow-the-Sun On-call: กระจาย On-call ตาม Timezone เพื่อไม่ให้คนต้องตื่นกลางคืน APAC ดูแล Business Hours Asia, EU ดูแล Business Hours Europe
  • Clear Escalation Path: กำหนด Escalation ที่ชัดเจน 5 นาทีไม่รับ → Escalate ถัดไป, 15 นาที → Manager, 30 นาที → ทั้งทีม
  • Runbooks: มี Runbook สำหรับทุก Alert ที่พบบ่อย ให้ On-call Engineer แก้ปัญหาได้เองโดยไม่ต้องถามคนอื่น
  • Incident Channel: สร้าง Slack Channel อัตโนมัติสำหรับทุก P1/P2 Incident เพื่อ Coordinate การแก้ปัญหา
  • Post-mortem: ทำ Blameless Post-mortem หลังทุก Incident สำคัญ แชร์ให้ทั้งทีมเรียนรู้
  • On-call Compensation: ให้ค่าตอบแทน On-call เพิ่มเติม โดยเฉพาะ After-hours เพื่อรักษาขวัญกำลังใจ
  • Alert Fatigue Prevention: Review Alert ทุกเดือน ลบ Alert ที่ไม่จำเป็น ปรับ Threshold ให้เหมาะสม ลด Noise

Opsgenie คืออะไร

Opsgenie เป็น Incident Management Platform ของ Atlassian รวบรวม Alert จาก Monitoring Tools ทั้งหมดไว้ที่เดียว มี On-call Scheduling, Alert Routing, Escalation Policy และ Integration กับ Tools มากกว่า 200 ตัว ช่วยให้ทีมตอบสนอง Incident ได้เร็วขึ้น

ทำไม Remote Team ต้องใช้ Opsgenie

Remote Team อยู่คนละ Timezone Opsgenie จัดการ On-call Schedule ข้าม Timezone อัตโนมัติ Route Alert ไปหาคนที่รับผิดชอบ Escalate ถ้าไม่มีคนรับ แจ้งเตือนผ่าน Phone, SMS, Slack, Email ป้องกัน Alert ถูกมองข้าม

On-call Schedule คืออะไรและตั้งค่าอย่างไร

On-call Schedule กำหนดว่าใครรับผิดชอบ Alert ในช่วงเวลาไหน ตั้งเป็น Rotation เช่น สลับทุกสัปดาห์ กำหนด Timezone แต่ละคน มี Override สำหรับวันหยุดหรือลาป่วย และ Time Restriction แยก Business Hours กับ After Hours

Opsgenie คิดค่าบริการอย่างไร

Free Plan สำหรับ 5 Users, Essentials $9/user/month สำหรับ Basic Alerting, Standard $19/user/month สำหรับ On-call Scheduling และ Escalation, Enterprise $29/user/month สำหรับ Advanced Analytics, SSO และ Custom Roles ดูราคาล่าสุดที่ opsgenie.com

สรุปและแนวทางปฏิบัติ

Opsgenie เป็นเครื่องมือจำเป็นสำหรับทีม Remote Work ที่ต้องจัดการ Incident ข้าม Timezone สิ่งสำคัญคือตั้ง Follow-the-Sun On-call Schedule, กำหนด Escalation Policy ที่ชัดเจน, Integrate กับ Monitoring Tools ทั้งหมด, มี Runbooks สำหรับ Alert ที่พบบ่อย, สร้าง Incident Channel อัตโนมัติ และ Review Alert ทุกเดือนเพื่อลด Alert Fatigue ใช้ Terraform จัดการ Config เป็น Code เพื่อ Version Control และ Reproducibility