Study Notes - CloudWatch


CloudWatch 是開始學習 AWS 之後,除了 EC2, S3 之外,最重要的 Services 之一,重要的功能如下:

  • CloudWatch Alarms
  • CloudWatch Events / Rules
  • CloudWatch Logs
  • CloudWatch Metric, Filter
  • CloudWatch Dashboard

常見的應用場景:

  • 系統資源的監控
  • Dashboard 系統訊息看板 (即時)
  • 自訂監控指標 (Metric)
  • 即時 Log 蒐集與儲存
  • Log 批次備份 (S3)

在還沒深度的研究之前,其實我對 CloudWatch 只是一知半解,大概只知道 CloudWatch Alarm + SNS …

深度 Study 過整個服務之後,發現這真的是不得了的東西,以下整理重要的基本概念。

CloudWatch

CloudWatch Alarms

使用 AWS 剛開始都會用到的,主要目的:

  • 就針對特定的監控指標
  • 設定告警的條件
  • 通知或者說驅動一個事件

最常見的例子:

  • 設定監控指標:CPU Utilization
  • 告警條件:五分鐘之內,持續 2 次,平均值超過 80%
  • 發動 SNS 事件
    • 發 Email 給一個群組
    • 送簡訊 (SMS) 給 1-n 個人
    • 執行 1-N 個 Lambda

這是非常經典的例子。

使用 Alarms 要知道幾個重要的觀念,包含 Namespaces, Metric Name, Statistics, Unit, Period … 後面 Metric 詳細描述。

CloudWatch Metrics

Metrics 可以說成 監控指標項目, AWS 各個服務預設很多監控指標,可以在 CloudWatch 上看到相關數據,也可以透過 AWS CLI or SDK 取得數據。要取得 CloudWatch 資料,就要先了解 CloudWatch Metrics 的設計與資料結構:

  • Namespaces: Metrics 的容器 (Container), 就是用來分類 AWS 服務的, 用 slash / 區隔. 像是 AWS/EC2, AWS/DynamoDB. 詳細參閱 AWS Namespaces.
  • Metrics: 意思是 度量, 是一個時間軸 (time-base) 的資料集合. 像是 ELB 的 HealthyHostCount, RequestCount, SurgeQueueLength 都叫做 Metrics.
  • Dimensions: 量測的資源對象 (ARN),是 Key/Value 呈現,像是 Name=InstanceId,Value=${INSTANCE_ID}, Name=LoadBalancerName,Value=${ARN_ID}
  • Statistics: 時間範圍之內的統計方式,包含了:Sum, Minimum, Maximum, and SampleCount.

透過 AWS CLI 取得 Metrics

有時候需要自行分析 CloudWatch Metric 的數據,或者重新 Aggregation ,例如:

計算一群機器的平均 CPU Utilization,然後平均之後決定是否驅動事件,像是透過 SNS 通知

以下是用 AWS CLI 透過 crontab 固定取得 metric 的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
AWS_PROFILE="<<AWS-PROFILE>>"
INSTANCE_ID="<<EC2-INSTNACE-ID>>"
AWS_REGION="ap-northeast-1"
OUTPUT_TYPE="text"
period=300
# Calculate local time as UTC, there is local time -8 = UTC. my server is local time (UTC+8).
start_time=`date +'%Y-%m-%dT%H:%M:00' --date='-8 hour -10 min'`
end_time=`date +'%Y-%m-%dT%H:%M:00' --date='-8 hour'`
aws cloudwatch get-metric-statistics \
--metric-name CPUUtilization \
--start-time ${start_time} \
--end-time ${end_time} \
--period ${period} \
--namespace AWS/EC2 \
--statistics Average \
--dimensions Name=InstanceId,Value=${INSTANCE_ID} \
--output ${OUTPUT_TYPE} \
--region ${AWS_REGION} \
--profile ${AWS_PROFILE}

Return as text

1
2
3
CPUUtilization
DATAPOINTS 30.24 2016-07-11T06:00:00Z Percent
DATAPOINTS 34.034 2016-07-11T06:05:00Z Percent

Return as json:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"Datapoints": [
{
"Timestamp": "2016-07-11T06:00:00Z",
"Average": 30.240000000000002,
"Unit": "Percent"
},
{
"Timestamp": "2016-07-11T06:05:00Z",
"Average": 34.034000000000006,
"Unit": "Percent"
}
],
"Label": "CPUUtilization"
}

這邊要去深入了解每個 Unit, Statistics 以及 Period 等意義是什麼,才能計算出需要的東西。

處理統計資料,通常要過濾很多不必要的資訊,AWS CLI 可以配合 JEMSPath 找到要的欄位,透過 --query 過濾不必要的資訊,詳細參閱 Ops as Code with AWS CLI 的例子。

Custom Metrics

有一些資訊 CloudWatch 本身是不提供的,像是 EC2 Instance 的記憶體、磁碟使用空間 (Disk Usage Percent),或者是自己的 Application Servers 像是 Nginx、Tomcat、IIS、Node.js … 需要監控這些 Servers 的相關數據,像是 Nginx 的記憶體使用例、Connection Request、Tomcat 的 JVM HeapSize … 等。那麼就要自行蒐集相關資料、儲存這些資料。

參考:Monitoring Memory and Disk Metrics for Amazon EC2 Linux Instances

如果是要從自己的 Log 分析出相關資訊,就要透過 CloudWatch Log + Filter 建立自己的 Metric,同樣的這也是 Custom Metrics。像 Nginx or JVM HeapSize 就可以這樣做。

使用 Custom Metrics 要注意怎麼設計 Namespaces, Dimensions,例如依照機器角色分 Namespace,依照角色 Metric 分 Dimension,依照商業邏輯把相關的放一起,日後好整理。

Custom Metrics 不能透過 AWS Console or CLI 刪除,只能等它自己慢慢消失 ..

CloudWatch Events / Rules

主要用來事件驅動 (Event Driven) 的原點,像是 CloudWatch Alarms 發生時,驅動 Lambda 做一件事情。也可以利用固定的排程 (crontab) 做固定的事情,像是每天固定幾點做什麼事情,或者固定每 10 分鐘做一件事情。這樣事件驅動叫做 CloudWatch Event,觸發的每個規則稱為 CloudWatch Rule

這些都可以透過 CLI or SDK 做設定,所以很容易開發。

事件驅動了來源有很多地方,CloudWatch Rule 基本的就有:

  • Schedule: Cron 的方式,或者是固定的時間驅動
  • CloudWatch Events: 配合 AWS Service 的 Action,像是:
    • 當某些重要的 EC2 狀態變成 stopped or shutting-down
      • 驅動一個 Lambda,通知 ooxx
      • 同時 Reboot 自己
    • 有東西放到 S3 就去跑 Lambda …
    • 支援東西很多,像是 EC2, EC2 SSM, ECS, EMR, Auto Scaling, API Call, CodeDeploy, KMS … 等等

在做系統監控的時候,常常需要知道現在的系統狀況,但是身邊也不見得隨時都會有電腦,因為這樣的需求所以我設計了 CloudWatch Reporter,透過 CloudWatch Event Rule ,定期把資訊丟到 Slack,讓大家隨時可以掌握系統狀況。

實作很簡單,就是寫一個 Lambda Function 撈 CloudWatch 時間範圍的資料,做簡單計算,組 Slack Payload,丟 Slack。

CloudWatch Dashboard

  • 自行定義 Dashboard,也就是把很多圖放在同一個畫面,版面配置可以自行調整大小。
  • 資訊是即時的 (1-2 分鐘的時間差)
  • 並且自動更新。同時可以設定時間範圍
  • 支援 Local Time。

非常實用的功能!

缺點:

  • 無法程式化,要靠滑鼠拉圖表,所以也不能進版控 (Git)
  • 不能分享:只能用複製的。
  • 圖形支援的還不夠多

成本:一個 Dashboard 每個月三塊美金。

CloudWatch Logs

CloudWatch 除了自身提供的 Metric / Alarm ,也可以把自己 Application 的 Log 丟上來、儲存,然後設定 Filter 進行分析,變成 Metric,最後用 Alarm + Rule 驅動事件。

Log 蒐集部分,需要在 EC2 Instance 安裝 agent,底下是快速安裝:

1
2
3
curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O
chmod +x ./awslogs-agent-setup.py
./awslogs-agent-setup.py -n -r ap-northeast-1 -c s3://<bucket-name>/awslogs.conf

記得先在 s3 放一個 config 檔,或者直接執行安裝檔。

安裝好 awslogs agent,然後設定 Filename Pattern、Time Format、Log Group、Log Stream … 等,就會自動把 Log 傳到 CloudWatch Log,詳細設定:CloudWatch Logs Agent Reference

底下是我蒐集 syslog + nginx 設定例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# see: http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AgentReference.html
[general]
state_file = /var/awslogs/state/agent-state
[/var/log/syslog]
file = /var/log/syslog
log_group_name = /Worker/SysLog
log_stream_name = {instance_id}_{hostname}
datetime_format = %b %d %H:%M:%S
[/var/log/nginx/log]
file = /var/log/nginx/*.log
log_group_name = /Worker/Nginx
log_stream_name = AccessLog
datetime_format = %Y-%m-%dT%H:%M:%S%z
time_zone = UTC

配置 awslogs agent 要注意看 awslogs 自己的 log,確認他的解析是正確的。awslogs 的 log 放在 /var/log/awslogs.log

Windows 則可以透過 Ec2Config 或者 SSM Windows 自身提供的 Event Logs、Performance Monitoring,或者其他應用程式的 Log ,像是 IIS、 SQLServer 等,傳上去 CloudWatch Log。詳細參閱 Using CloudWatch Logs with Amazon EC2 Running Microsoft Windows Server

Metric Filter

Metric Filter 是 CloudWatch Log 中重要的功能,透過 Metric Filter 可以定義自己的 Metric,進而變成 Alarm 或者呈現 Dashboard,他有點像是 ELK 的 Logstash 的角色,主要就是把欄位做對應以及過濾。

底下是我透過 AWS CLI 建立 Metric Filter 處理 Nginx Log 的例子:

1
2
3
4
5
6
7
8
9
10
FILTER_NAME="Connection-Request_Filter"
# 過濾 local health check
FILER_PATTERN="[time_iso8601, remote_user, status, body_bytes_sent, http_referer, server_name != 127.0.0.1, upstream_addr, request, request_length, http_user_agent, remote_addr, proxy_protocol_addr, http_x_forwarded_for, proxy_add_x_forwarded_for, request_time, http_host, scheme, msec, connection, connection_requests, connections_active, connections_reading, connections_writing, connections_waiting]"
aws logs put-metric-filter \
--log-group-name "${LOG_GROUP_NAME}" \
--filter-name "${FILTER_NAME}" \
--filter-pattern "${FILER_PATTERN}" \
--metric-transformations metricName=Connection-Active,metricNamespace=Nginx/Connection-Request,metricValue=1,defaultValue=0.0

如果上傳的 Log 是 JSON,Metric Filter 也支援,他的寫法大概長得像這樣:

這是查詢 Cloudtrail Event 的 Metric Filter:有人開了 *.8xlarge or *.4xlarge 的機器

1
{ ($.eventName = RunInstances) && (($.requestParameters.instanceType = *.8xlarge) || ($.requestParameters.instanceType = *.4xlarge)) }

用 CloudWatch 做監控系統

下圖是我畫的 CloudWatch Services 做系統監控的流程:

這個流程會使用到整個 CloudWatch Services,包含 Logs / Alarms / Metric Filers / Custom Metric / Dashboard,最後配合 CloudWatch Rules / SNS / Lambda 做事件驅動,最後通知到 Slack / SMS .. 等。

值得一提的是,這整串流程是 即時 (Realtime),如果自己蓋類似的服務,我 Survey 過知名的組合,像是:

  • ELK: 使用了兩年,C/P 值不高,費用以及維護成本驚人,雖然後來有系統架構的解法,但是基於成本考量,打算慢慢換掉。
  • Telegraf / Collectd + InfluxDB + Grafana: 很容易安裝,效果也不錯,但是 InfluxDB 需要有好的 File System 支撐。
    • Grafana 每個 Metric 只能設定一個 Alert, 而且 Source 如果是 CloudWatch 就不支援 Alert
    • Grafana 可以跟 Slack + S3 整合,然後把 Metric 圖檔直接丟到 S3,然後在 Slack 呈現。這是我一直很想要的功能,Datadog 有。
    • aws-cloudwatch-chart-slack
  • Fluentd + Prometheus + Grafana: 理由同上

這些都要自己養機器,特別是維護 Storage 部分,會有很多額外的 Operations、教育訓練、權限管控、安全性,最重要的是成本高很多,而且效果不見得好,C/P 值不高。

使用 AWS CloudWatch 整套方案,幾乎可以避免上述我擔心的問題,而且維護 CloudWatch 本身,除了 Dashboard 之外,都可以程式化。唯一要注意的是 CloudWatch Price,要留意 Log 的使用狀況,以及設定 Expiration。

CloudWatch 相關的服務

CloudWatch 跟很多東西都有關係,以下整理一些東西:

  • Cloudtrail:可以把 Cloudtrail event 倒進去 CloudWatch Log ,透過官方提供的 CloudFormation 可以自動建立所有的 Metric Filer / Alarm,可以監控不正常的 AWS Event
  • Elasticsearch:可以直接 Log 倒入 AWS ES,但我不太喜歡養機器 … 即使 AWS ES 宣稱是 Managed …
  • Lambda:串接 CloudWatch Rules,最常用的組合,配合 Slack 口味不錯。
  • SNS:同上
  • VPC Flow Log:用來分析網路流量,參閱 Migrate to AWS NAT GatewayLambda Network Traffic Test in VPC w/ or w/o Endpoint 的分享。
  • AutoScaling / SQS / SES / SWF / Kineses / DynamoDB / RDS … 幾乎都會跟 CloudWatch 有關。
  • 把 ELB Log 倒入 CloudWatch Log 分析:

CloudWatch 在效能監控與測試的應用

系統上線後,其實需要蒐集很多資訊,特別是應用層的數據,像是 Nginx, IIS, Tomcat, Node.js, JVM … 等執行的狀況。除了應用層的數據,屬於商務邏輯層的資料也是要蒐集,分析找問題。這些過程都需要有一套好的 Log 機制、分析流程。

用 Elasticsearch 來說,他自己提供的很多 API 可以拿到系統的數據,包含 Index, JVM … 等詳細資料,而且是 json 格式。如果不考慮採購外部的服務,那麼把這些資料放到 CloudWatch Log 就是個不錯的選擇,可以滿足大部分的需求,過程中可以了解每個參數的意義,要怎麼分析,進而更了解 Elasticsearch 的運作。

跟去外面直接買 Solution 不一樣的是,買 Solution 就跟看電視一樣,少了思考,只接收別人給你的。自己幹雖然要花一點時間,但是成果是可期的、且紮實的。

另外可以應用的地方就是系統的效能測試。效能測試過程需要蒐集很多數據,這些數據的蒐集後都要做分析,最後用來計算出各種 benchmark,找出系統的效能瓶頸。同樣的也是需要很強大的 Log 系統來支撐。

系統監控、測試的第一步要先能 量測 (Measurement),無法量測是不能知道狀況的。可以量測了之後就是要記錄 (Log),才能夠過計算找出 benchmark,找到瓶頸。

關於效能測試,參考 Stages in Software Testing 一文,有提到關於效能測試的種類與心得。

CloudWatch 的不足 (許願?)

  • Metric 無法讓其他服務使用,像我想要有 CloudWatch Alarm 時,把 Metric 弄成圖,丟到 Slack,這樣每次有事情時,就不敲字說明。自幹事沒問題,只是有點懶 XD
  • Dashboard 不能像 Grafana 那樣 configurable,然後分享給社群。都要自幹。
  • 資料無法 Aggregate ,像是 group by 之後做 order by,算出時間範圍的 Top 10,Kibana 可以做。
  • CloudWatch Log 可以 export to S3,但是不能透過 Event Rule 自動排程
    • 另外匯出到 S3 之後可以弄回來嗎?我試過 export to S3,看過資料結構,要弄回來到 CloudWatch Log 要花一點工。。。。有點做半套的感覺。
    • 在系統維運時,Log 需要被長時間保留,所以成本會是要考量的,長時間來看 S3 會比 CloudWatch Log 低。
    • 如果要查過去特定時間的資料,要能盡快倒回來查詢。

自己蓋監控系統 or 被 AWS 綁死?

CloudWatch 透過 awslogs agnet + CloudWatch Log + Metric Filter + Alarm + Dashboard,就可以建立屬於自己的監控系統。當然也可以去找外面做好的 Solution,像是監控 Elasticsearch 外面有很多 Solutions,可是往往不知其所以然,反正花錢他就是會動了。

與其如此,不如自己試著:

  • 定義系統的監控指標:設計一個系統的健康檢查報表,這些數據是自己定義出來的,定義的好壞精準於否,取決於自己對系統了解的深度與廣度。
  • 設計 Log 格式:好的 Log 格式才容易解析,資訊也才不會掉東掉西
  • 建置 Log 蒐集的方式:pull (SNMP) or push mode (agent base) 都是常見的方法。
  • 資料儲存:Log 資料量通常都很大,要怎麼存?批次還是即時?放到 S3 的目錄結構怎麼規劃?記得定義 + 設定 Lifecycle。
  • 數據分析的方式:怎麼計算?需要多少資源?
  • 監控指標的呈現:回到第一個點,系統健康檢查報表要呈現什麼?
  • 監控指標的異常通報 (Alarm):什麼是異常?怎麼通報?SNS、Slack、EMail、SMS、Push
    • 我會定義等級,就像是一般程式的 Log 會有 Info, Debug, Error, Fatal, 更細分的會有 Trace Level,像是 Step In, Step Out .. 等
    • 監控通知通常我會定義三種:InfoWarningUrgent
      • Info:設計成 Reporter 形式 (Long Polling),定時把資訊丟到 Slack 的特定 channel,這樣的設計讓系統維運人員可以隨時掌握系統狀況,而且不用帶電腦
      • Warning:超過指標的臨界值,就會通報道 Slack 主要負責單位的 channel,並且 @channel
      • Urgent:同時丟 Slack Channel + 送簡訊給對應的人 (SNS -> SMS)
    • 通報只有一個重點:出問題要能知道問題是啥、然後有人可以去處理

底下是我設計的 Alarm System

設計的重點在於:

  • 什麼樣的 告警等級,用什麼樣的 方式,通知到 什麼人
    • “告警” 一詞是我當兵時任務用詞,我們主要維護實體通訊線路,確保線路正常,當出現異常時,稱『告警搶修』
  • 等級、方式、人
    • 等級:不同人看不同等級,不需要全部的人都知道
    • 方式:有即時性以及時效性的問題
    • 人:找到對的人,才能快速把問題排除

參加 AWS User Group 有人推薦用 Push …. 我回家路上一值想,為啥我都沒想到這個方法??因為,我從來不會看 APP 的 Push,因為跟山一樣多,都直接忽略 XDD

如果是自己蓋的話,架構的設計要考量 SLA,因為如果掛了,能接受多久的 Downtime?資料遺失?資料怎麼蒐集?

用 CloudWatch 有個好處,是全部 Managed Services,不用自己蓋機器,大部分可以自動化。

缺點就是被 AWS 綁死,兩年前我就是這樣想,所以到現在才研究 CloudWatch … 現在懶得想那些,就綁死吧 XDD

系統監控 + 巨量資料分析

系統監控一定要提到的就是階段性:

  • 資料蒐集 (Ingest) 或者說 資料 (ETL):萃取 (extract)、轉置 (transform)、載入 (load),主要是 Log 的蒐集與,轉換成需要分析的格式。
    • 經驗上來說,這個過程是最花時間的。很多人往往都沒意會到要先把資料格式弄好,才能分析,然後就傻傻的蒐集一堆 非結構化 的資料,結果無法分析,或者要花更多時間重新結構化。
    • Log 的定義非常重要,我以前在做 自動化測試 的時候,就經常在處理 Log,不管是處理別人的 Log ,還是自己設計 Logger,處理系統 Log 很有感,重點就是:結構化很重要,不要生出一個自己都看不懂,程式無法解析的垃圾出來。
  • 儲存 (Storage):Log 的資料量非常大,需要有相對應的儲存基礎建設才能放置這些資料,AWS 就是 EBS、S3、EFS 等,或者自己建置 DFS (Distribution File System),像是微軟的 DFS 或者 GlusterFS ..
  • 分析 (Analysis):大量運算,通常會跟 Storage 綁在一起。傳統就是用 RDBMS 做、AWS RedShift / Athena、Google 用 BigQuery (儲存 + 分析)
  • 呈現 (Visualize):把分析結果視覺化,市面上常見的事 BI 的產品,像是 Tableau、AWS QuickSight … 等

從開始做 系統維運開始Log 分析 + 系統監控 一直是很大的挑戰,找了很多相關的解決方案,最後都會遇到同樣的問題:

  • 我們到底分析了些什麼?
  • Log 的資料量太巨大,成本很高
  • Log 系統本身不夠穩定,或者很難維護
  • 資料不夠即時,怎麼查詢?
  • 監控系統自己的監控

大數據 (Big Data) 到去年以前還很熱,最近有緩下來趨勢,因為整個生態圈過於技術導向,往往忘了數據本身的目的性,到底是要做什麼?

回到原點,以系統監控來說,要思考幾個重要的東西:

  • 監控指標是哪些?
  • 什麼樣的 Solution 適合?
  • 成本?
  • 監控系統本身能否自動化建置、配置?本身好不好維護管理?
  • 資安: 任何系統都要面對安全性問題,在 AWS 上 VPC / Subnet / SG 的基本規劃很重要,對我來講是基本的東西,可是大部分的人只要能通就好。最近經常發生的:勒索攻擊大舉鎖定後端系統

抓著這些需求,再去找 Solution ,別一開始就陷入技術的泥淖中。

後話

其實在做 系統監控 我會一直想到以前在研究 數位音樂科技,特別是混音時常用的一些 EQ / Filter … 基本上跟監控系統的 Alarm 概念一模一樣 XD

延伸閱讀

參考資料


Comments