目次
はじめに
このような機会をいただけたので、書きためていたダッシュボード作ってみたと題して記事を投稿します。
AWS大阪オフィスで開催された「俺たち私たちのダッシュボード選手権(社内イベント)」に参加した時のものですが、設計構築する上で必要な知識経験を身に着ける良い機会でした。
CloudWatchの長所と、Zabbixの長所を掛け合わせて、機能性抜群かつ安いダッシュボードを作成することができたので、是非試しに構築してみてください。
参考資料:
余計なお節介
パスワードを多く入力するので、設定時は書き留めるなど、注意が必要です。
また、目隠ししていない箇所もありますが、既に環境は存在しませんのでご安心ください。
作る構成は次の画像のとおりです。EC2(Zabbixサーバ)は、自身を監視します。ZabbixエージェントやCloudWatchエージェントをインストールしています。
定時監視を行って、異状があればSNSによって通知を送付する魂胆です。
完成図
1.パット見でディスク状況を見たい!
2.アクセス、エラーログを参考に表示!
3.RUMでユーザーセッション収集!(part2の記事で記載します!)
Zabbixサーバ構築
(Zabbixサーバ自身を監視します。)
- AmazonLinux2を使用します。
- パブリックサブネットに配置し、EIPをアタッチします。
- セキュリティグループは、SSH(EC2 Instance Connectから作業したりします。)、httpsを開けます。
ホストを確認しておきます。
uname -n
IPアドレスを確認しておきます。
curl ifconfig.io
ホストなどを確認したら作業を開始!!
rootで作業します。
sudo su -
タイムゾーンを設定します。
timedatectl set-timezone Asia/Tokyo
設定できたか確認します。
timedatectl status
ホスト名を「zabbix(任意)」にします。
hostnamectl set-hostname zabbix
ホスト名を確認します。
hostname
ここで再起動します。
reboot
php7.2を有効にします。
amazon-linux-extras enable php7.2
phpインストール
yum install php
mariaDBインストール
yum install mariadb mariadb-server
mariaDBを起動します。
systemctl start mariadb
ステータスを確認します。
systemctl status mariadb
サーバ起動時にmariaDBが起動するように設定します。
systemctl enable mariadb
対話形式でパスワード設定などを行います。
mysql_secure_installation
初期はパスワードなしで設定を進めるので、次の表示はそのまま空欄で進めます。
Enter current password for root (enter for none):
Set root password? [Y/n]
ここは「y」を入力して、pwを設定します。
以降全て「y」で大丈夫です。
Apacheインストールします。
yum install httpd
Apacheを起動します。
systemctl start httpd
ステータスを確認します。
systemctl status httpd
サーバ起動時にApacheが起動するように設定します。
systemctl enable httpd
この辺りからミソとなりますので、面倒ですが細かく設定します。(現状のAmazon Linux2に限ります。)
去年くらいまで使えていたリポジトリ(現在202409)が使用できなくなっているので、次の設定を参考にしてください!
リポジトリの追加
rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-5.0-1.el7.noarch.rpm
次の箇所を有効化します。
vi /etc/yum.repos.d/zabbix.repo
[zabbix-frontend]
enable=1へ!!
Software Collectionsのパッケージをインストールします。
yum install -y https://vault.centos.org/7.9.2009/extras/x86_64/Packages/centos-release-scl-rh-2-3.el7.centos.noarch.rpm
次のとおり編集します。
vi /etc/yum.repos.d/CentOS-SCLo-scl-rh.repo
【コメントアウト】
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=sclo-rh
【追記】
baseurl=http://vault.centos.org/centos/7/sclo/x86_64/rh/
Zabbixサーバ、Zabbixエージェント、WEBインターフェイスをインストールします。
yum install zabbix-server-mysql zabbix-agent zabbix-web-japanese.noarch zabbix-web-mysql-scl zabbix-apache-conf-scl
起動します。
systemctl start zabbix-server zabbix-agent
ステータスを確認します。
systemctl status zabbix-server zabbix-agent
サーバ起動時にZabbixサーバ、エージェントが起動するように設定します。
systemctl enable zabbix-server zabbix-agent
mariaDBにログインします。
mysql -uroot -p
最低限の設定(DB作成など。)を行います。
(各種設定値が多く存在するので、あえてパスワードを残します。)
create database zabbix character set utf8 collate utf8_bin;
create user zabbix@localhost identified by 'abcdefghijk123';
grant all privileges on zabbix.* to zabbix@localhost;
quit;
作成したデータベースにZabbixの初期スキーマとデータをインポートします。
以下のコマンド実行後に上記で設定したZabbixユーザーのパスワードが求められますので入力します。
zcat /usr/share/doc/zabbix-server-mysql*/create.sql.gz | mysql -uzabbix -p zabbix
datetimeの箇所をAsia/Tokyoへ。
vi /etc/opt/rh/rh-php72/php-fpm.d/zabbix.conf
データベース名やユーザー名とパスワードを設定します。
vi /etc/zabbix/zabbix_server.conf
次はパスワード及びパスワード以外にチェックする箇所を記載しています。
...
DBName=zabbix
...
DBUser=zabbix
...
DBPassword=[zabbixユーザー(DB上)のパスワードを入力]
...
PHP-FPMもサーバ起動時に起動するように設定します。
systemctl enable rh-php72-php-fpm
Zabbixサーバ、Zabbixエージェント、PHP-FPMを再起動します。
systemctl restart zabbix-server zabbix-agent rh-php72-php-fpm httpd
ステータスを確認します。
systemctl status zabbix-server zabbix-agent rh-php72-php-fpm httpd
この設定は必ず行う必要があります。
vi /etc/php.ini
phpで東京時間に設定
/date.timezoneで検索し"Asia/Tokyo"
を追記(ダブルクォート大事)
設定後、Apacheを再起動します。
systemctl restart httpd
ZabbixのWebインターフェイスに接続してみます。
次の箇所にIPアドレスを入力するだけで接続できます。
http://[Zabbix ServerのIP]/zabbix/
初回ログインは、ユーザー名「Admin(※先頭大文字!)」、パスワード「zabbix」でログインする。
特に決まりはありませんが次の値を参考までに記載します!
Host:localhost
Port:10051
CloudWatchエージェントをインストール
CloudWatchで様々なメトリクスを表示できるようにエージェントを先行的にインストールします。
yum install amazon-cloudwatch-agent
対象のEC2にポリシーをアタッチします。
・CloudWatchAgentServerPolicy
:CloudWatchエージェントのメトリクスとログの送信に必要なポリシー。
次のエージェントによってどのメトリクスを取得するか決めていきます。
記載するものと、記載方法は次の公式が作成したフルセットのJSONファイルを使用してそのまま動けばそれで良いですが、もし動かない場合などありましたら次のJSONを使用してみてください。
CloudWatch エージェント設定ファイルを手動で作成または編集する
次の設定を作成します。
{
"agent": {
"metrics_collection_interval": 60,
"logfile": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log"
},
"metrics": {
"namespace": "MyCustomNamespace",
"metrics_collected": {
"diskio": {
"resources": [
"*"
],
"measurement": [
"reads",
"writes",
"read_time",
"write_time",
"io_time"
],
"metrics_collection_interval": 60
},
"disk": {
"measurement": [
"used_percent",
"used",
"free",
"total"
],
"metrics_collection_interval": 60,
"resources": [
"/"
]
},
"mem": {
"measurement": [
"mem_used_percent"
],
"metrics_collection_interval": 60
},
"swap": {
"measurement": [
"swap_used_percent",
"swap_free"
],
"metrics_collection_interval": 60
},
"http_response": {
"urls": [
"http://52.68.98.111"
],
"metrics_collection_interval": 60,
"measurement": [
"response_time",
"status_code"
],
"response_code": true,
"response_time": true
}
}
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/messages",
"log_group_name": "MyLogGroup",
"log_stream_name": "{instance_id}",
"timestamp_format": "%b %d %H:%M:%S"
}
]
}
}
}
}
ちなみに、viで設定ファイルを魔改造したあとは、次のコマンドで都度適用する必要がありますのでお節介しておきます。
・エージェントを適用します。
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s
succeededと表示されることを確認しましょう!
・エージェントを再起動します。
systemctl restart amazon-cloudwatch-agent
ログローテートを設定します。
vi /etc/logrotate.d/amazon-cloudwatch-agent
次を記載します。
/opt/aws/amazon-cloudwatch-agent/logs/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 0640 root root
}
メトリクスを取得したいのでswap領域作成してみます。
容量を確認します。
df -h
swap領域の存在を確認します。(無いことを確認)
free -h
swap領域を作成します。
vi rc.local
SWAPFILENAME=/swapfile
SIZE=2097152
dd if=/dev/zero of=$SWAPFILENAME count=$SIZE bs=1K && mkswap $SWAPFILENAME && swapon $SWAPFILENAME
権限を確認します。
ls -la rc.local*
-rw-r--r--
実行権限を与えます。
chmod u+x rc.local
-rwxr--r--
ZabbixサーバにGo言語を使用するための環境を構築します。
Go言語をインストール
amazon-linux-extras install -y golang1.11
Golangがインストールされたか確認
go version
go version go1.22.5 linux/amd64こんな感じで表示されます。
GOPATH モードで進めてみて、問題があればexport GO111MODULE=on
の設定を行うことにしました。又は
export GO111MODULE=auto
Golangプロジェクトの作成
mkdir zabbix-cloudwatch-lambda
cd zabbix-cloudwatch-lambda
/home/ec2-user/zabbix-cloudwatch-lambda(現在地はココ)
プロジェクトを初期化
go mod init zabbix-cloudwatch-lambda
go: creating new go.mod: module zabbix-cloudwatch-lambda
Lambda関数設定とコードファイル作成
次のコードファイルを作成します。
vi main.go
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cloudwatch"
)
func getZabbixData(apiURL, authToken string) ([]byte, error) {
payload := map[string]interface{}{
"jsonrpc": "2.0",
"method": "item.get",
"params": map[string]interface{}{
"output": "extend",
"hostids": "10084", // 環境変数または事前に取得したホストIDを使用
},
"auth": authToken,
"id": 1,
}
payloadBytes, err := json.Marshal(payload)
if err != nil {
return nil, err
}
req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(payloadBytes))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get data from Zabbix, status code: %d", resp.StatusCode)
}
return ioutil.ReadAll(resp.Body)
}
func putDataToCloudWatch(namespace, metricName string, value float64) error {
sess := session.Must(session.NewSession())
svc := cloudwatch.New(sess, aws.NewConfig().WithRegion("ap-northeast-1"))
_, err := svc.PutMetricData(&cloudwatch.PutMetricDataInput{
Namespace: aws.String(namespace),
MetricData: []*cloudwatch.MetricDatum{
{
MetricName: aws.String(metricName),
Unit: aws.String("None"),
Value: aws.Float64(value),
Timestamp: aws.Time(time.Now()),
},
},
})
return err
}
func main() {
apiURL := os.Getenv("ZABBIX_API_URL")
authToken := os.Getenv("ZABBIX_API_TOKEN")
data, err := getZabbixData(apiURL, authToken)
if err != nil {
fmt.Println("Error:", err)
return
}
// Zabbixデータから必要な値を抽出する処理
// JSONレスポンスをデコードして、必要な値を抽出
var result map[string]interface{}
err = json.Unmarshal(data, &result)
if err != nil {
fmt.Println("Error decoding Zabbix data:", err)
return
}
// 例: value := extractValueFromZabbixResponse(result)
// 仮の値をCloudWatchに送信 (実際には抽出した値を使用)
err = putDataToCloudWatch("ZabbixMetrics", "MiddlewareMetric", 123.45)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Data sent to CloudWatch")
}
※ホストIDを編集する。
ちなみにホストIDはWEBインターフェイスからでも参照可能。ログインした後、該当ホストを選択すると、ブラウザのURL欄に「例:http://サーバのIPアドレス/zabbix/hosts.php?form=update&hostid=10084
」
このように表示される。末尾の「10084」これ。その他のAZや、"123.45"ここの部分は編集の必要はありません。
依存パッケージをインストールする。
go get github.com/aws/aws-sdk-go/aws
go get github.com/aws/aws-sdk-go/aws/session
go get github.com/aws/aws-sdk-go/service/cloudwatch
bootstrapファイルを作成します。
vi bootstrap
#!/bin/sh
./main
Lambdaで使用できる形にGolangコードをビルドします。
GOOS=linux GOARCH=amd64 go build -o main
ZIPファイルにします。
zip function.zip main bootstrap
Lambda関数へのアップロード
マネジメントコンソールから
※Amazon Linux 2を選択。Go言語は非推奨となっているようですが早さを求めてGoを選択!
-
一から作成
-
ランタイム
Amazon Linux 2 -
アーキテクチャ
x86_64 -
基本的な Lambda アクセス権限で新しいロールを作成
-
コンソール上で、アップロード元のプルダウンから、「.zip」を選択
-
Zabbix APIのURLと認証トークンを設定
環境変数タブに移動し、ZABBIX_API_URLとZABBIX_API_TOKENの環境変数を追加 -
key
ZABBIX_API_URL
ZABBIX_API_TOKEN -
value
http://IPアドレス/api_jsonrpc.php
Zabbix APIで認証トークンを取得(ver5.0ではコンソールでの取得はできないようです。)
Adminユーザーから、新規に作成したユーザー(権限)でログインしておきます。
はじめにjq(JSON Query)をインストール
一般にjqと呼ばれるもの。
yum install jq -y
ZabbixのWebインターフェイスから、ユーザーを作成し、ユーザーグループ”Zabbix administrators”に参加させ、表示/設定の権限を付与します(任意にグループを作成しちゃって大丈夫です。)。
ここでは、すべての権限を追加してあげます。
例:Zabbix administrators デフォルトでは、「権限:なし」これを、既存のホストグループ(Zabbix servers)を選択し、「表示/設定」にチェックを付けて、「追加」をクリックして追加します。最後に更新をクリックです。ここで「追加」ボタンをクリックすることを忘れがちなので注意です!
Zabbix APIにリクエストを送信して、jqを使って認証トークンを抽出します。
curl -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"user": "test-user(Zabbix側で作成したユーザー)",
"password": "パスワード"
},
"id": 1
}' http://xxx.xxx.xxx.xxx(IPアドレス)/zabbix/api_jsonrpc.php | jq -r '.result'
これを実行することで、トークンが表示されます。
この取得したトークンをZABBIX_API_TOKENのvalueに貼り付けます。
Amazon EventBridgeの設定
-
直接CloudWatchの画面から設定します。
(細部はコンソールの説明などご確認ください。) -
サイドバーのイベントの"ルール"から、ルールを作成
-
任意の名前を付けて
-
スケジュールを選択
-
EventBridge Scheduler で続行
-
スケジュール名を決めて、定期的なスケジュール(スケジュールの種類は任意で)を決めます。
-
ターゲットの詳細
-
以降Lambdaの設定及びEventBridgeの設定
Lambdaの画面から連携されている状態です。
EventBridgeのコンソールで作成できているか確認してみます。
CloudWatchダッシュボードを作ってみる。
簡単3ステップ!
-
最初に表示される画面では、どのような表示にしたいか選択します。
-
赤枠内に対象のインスタンスIDを入力して検索すると表示させることができるメトリクスが表示されます。
(なお、ZabbixのAPIから取得したメトリクスもこのコンソールに表示されるようになります!) -
画面右上のタイムゾーン設定、間隔を選択します。
通信できているか確認
これまでのEventBridgeの設定、Lambdaの設定、コードが適正に機能しているか、CloudWatchダッシュボードから確認します。
画面のように、新たな表示(ZabbixMetrics)が追加されています。
すると、ディメンションなしのメトリクス(何もメトリクスなどを指定していません。)という表示があります。
次の画像のように表示されていることを確認します。
(縦軸は、Goのコードで設定した123.45を表示するための値です。)
値が取得できない場合などは次のコマンドでテストをしつつ、Amazon CloudWatch Logsで取得できたログを確認することで、解決に近づけます。
Zabbix APIからデータが正しく取得され、CloudWatchにもデータが送信されていることを確認します。
Amazon Linux2のCLIから次のコマンドを実行します。
export ZABBIX_API_URL="http://your-zabbix-server-ip/zabbix/api_jsonrpc.php"
export ZABBIX_API_TOKEN="your-zabbix-token"
go run main.go
正常な場合、多数の状態を表すログが出力されます。
また、Amazon CloudWatch Logsの中で、「Data sent to CloudWatch」この表示がある場合は、内容はともかく値をputできている状態のようです。
ApacheのメトリクスをZabbixで取得できるように設定する。
httpd -M 2>/dev/null | grep status_module
出力:status_module (shared)
sudo tee /etc/httpd/conf.d/server-status.conf <<EOF
<Location "/server-status">
SetHandler server-status
Require ip 127.0.0.1 ::1
</Location>
EOF
systemctl restart httpd
curl -I http://localhost/server-status
HTTP/1.1 200 OK
Date: Wed, 11 Sep 2024 09:02:46 GMT
Server: Apache/2.4.62 () PHP/7.2.34
Upgrade: h2,h2c
Connection: Upgrade
Content-Length: 6466
Content-Type: text/html; charset=ISO-8859-1
webインターフェイスから設定をすることで監視可能になります。
PHP-FPMのメトリクスをZabbixで取得できるように設定する。
sudo tee -a /etc/opt/rh/rh-php72/php-fpm.d/zabbix.conf <<EOF
pm.status_path = /status
ping.path = /ping
EOF
設定ファイルを編集するので、事前にコピーを取っておきます。
cp /etc/httpd/conf.d/zabbix.conf /etc/httpd/conf.d/zabbix.conf.20240912
PHP-FPMにProxyする設定
sudo tee -a /etc/httpd/conf.d/zabbix.conf <<EOF
<Location ~ ^/(status|ping)$>
SetHandler "proxy:unix:/var/opt/rh/rh-php72/run/php-fpm/zabbix.sock|fcgi://localhost"
Require ip 127.0.0.1 ::1
</Location>
EOF
設定を反映し、PHP-FPMのステータス情報にアクセスできることを確認します。
ステータスを確認
systemctl status rh-php72-php-fpm httpd
権限と所有権の設定
chown apache:apache /var/opt/rh/rh-php72/run/php-fpm/zabbix.sock
chmod 770 /var/opt/rh/rh-php72/run/php-fpm/zabbix.sock
リダイレクト先
chown -R apache:apache /usr/share/zabbix/
chmod -R 755 /usr/share/zabbix/
アクセスできているか確認します。
curl http://localhost/status
出力:
[root@zabbix etc]# `curl http://localhost/status`
pool: zabbix
process manager: dynamic
start time: 12/Sep/2024:12:51:14 +0900
start since: 33
accepted conn: 16
listen queue: 0
max listen queue: 0
listen queue len: 0
idle processes: 5
active processes: 1
total processes: 6
max active processes: 4
max children reached: 0
slow requests: 0
困った時のエラーログたち
tail -f /var/log/httpd/error_log
tail -f /var/opt/rh/rh-php72/log/php-fpm/error.log
webインターフェイスでのPHP-FPMの設定
具体的にApacheをCloudWatchに表示させてみる。
次のコードに修正。
ユーザーのIDを追加する箇所の下にアイテムIDを追記したもの。
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cloudwatch"
)
// Zabbix APIからデータを取得する関数
func getZabbixData(apiURL, authToken, itemKey string) ([]byte, error) {
payload := map[string]interface{}{
"jsonrpc": "2.0",
"method": "item.get",
"params": map[string]interface{}{
"output": "extend",
"hostids": "10084", // ホストIDを指定
"search": map[string]string{
"key_": "apache.workers_total.busy", // Apacheの特定のメトリックキーを指定
},
},
"auth": authToken,
"id": 1,
}
payloadBytes, err := json.Marshal(payload)
if err != nil {
return nil, err
}
req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(payloadBytes))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get data from Zabbix, status code: %d", resp.StatusCode)
}
return ioutil.ReadAll(resp.Body)
}
// CloudWatchにデータを送信する関数
func putDataToCloudWatch(namespace, metricName string, value float64) error {
sess := session.Must(session.NewSession())
svc := cloudwatch.New(sess, aws.NewConfig().WithRegion("ap-northeast-1"))
_, err := svc.PutMetricData(&cloudwatch.PutMetricDataInput{
Namespace: aws.String(namespace),
MetricData: []*cloudwatch.MetricDatum{
{
MetricName: aws.String(metricName),
Unit: aws.String("None"),
Value: aws.Float64(value),
Timestamp: aws.Time(time.Now()),
},
},
})
return err
}
// main関数
func main() {
apiURL := os.Getenv("ZABBIX_API_URL")
authToken := os.Getenv("ZABBIX_API_TOKEN")
itemKey := "apache.workers_total.busy" // 例としてApacheのワーカー数のキー
// Zabbix APIからデータを取得
data, err := getZabbixData(apiURL, authToken, itemKey)
if err != nil {
fmt.Println("Error:", err)
return
}
// Zabbixデータをパース
var result map[string]interface{}
err = json.Unmarshal(data, &result)
if err != nil {
fmt.Println("Error decoding Zabbix data:", err)
return
}
// 結果を確認して値を抽出
fmt.Printf("Zabbix API result: %+v\n", result)
// 実際の値を抽出
var value float64
if len(result["result"].([]interface{})) > 0 {
firstItem := result["result"].([]interface{})[0].(map[string]interface{})
lastValueStr := firstItem["lastvalue"].(string) // Zabbixからのデータは文字列として返される
value, err = strconv.ParseFloat(lastValueStr, 64) // float64に変換
if err != nil {
fmt.Println("Error converting lastvalue to float64:", err)
return
}
} else {
fmt.Println("No data found for the specified key")
return
}
// CloudWatchにデータを送信
err = putDataToCloudWatch("ZabbixMetrics", "ApacheTotalWorkersBusy", value)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Data sent to CloudWatch")
}
再びLambdaにアップロードし、Apacheの指定したメトリクスを表示することができた。
次にZabbixでMariaDBのメトリクスを取得するための設定をOSに行う。
現状のZabbixユーザーの権限を確認
mysql -u root -p
SHOW GRANTS FOR 'zabbix'@'localhost';
出力:
+---------------------------------------------------------------------------------------------------------------+
| Grants for zabbix@localhost |
+---------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'zabbix'@'localhost' IDENTIFIED BY PASSWORD '*xxxxxxxxxx' |
| GRANT ALL PRIVILEGES ON `zabbix`.* TO 'zabbix'@'localhost' |
+---------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
メトリクスを取得する権限が不足
- SELECT: データの読み取り。
- PROCESS: サーバーのプロセス情報を取得(Zabbix監視用)。
- REPLICATION CLIENT: レプリケーションステータスを確認。
GRANT SELECT, PROCESS, REPLICATION CLIENT ON *.* TO 'zabbix'@'localhost'; FLUSH PRIVILEGES;
認証するために使用する認証ファイルを作成
vi /var/lib/zabbix/.my.cnf
記載内容
[client]
user=zabbix
password=DBのパスワード
chown zabbix:zabbix /var/lib/zabbix/.my.cnf
chmod 600 /var/lib/zabbix/.my.cnf
vi /etc/zabbix/zabbix_agentd.d/userparameter_mysql.conf
UserParameter=mysql.ping[*], mysqladmin -h"$1" -P"$2" ping
UserParameter=mysql.get_status_variables[*], mysql -h"$1" -P"$2" -sNX -e "show global status"
UserParameter=mysql.version[*], mysqladmin -s -h"$1" -P"$2" version
UserParameter=mysql.db.discovery[*], mysql -h"$1" -P"$2" -sN -e "show databases"
UserParameter=mysql.dbsize[*], mysql -h"$1" -P"$2" -sN -e "SELECT SUM(DATA_LENGTH + INDEX_LENGTH) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='$3'"
UserParameter=mysql.replication.discovery[*], mysql -h"$1" -P"$2" -sNX -e "show slave status"
UserParameter=mysql.slave_status[*], mysql -h"$1" -P"$2" -sNX -e "show slave status"
Zabbixサーバ、Zabbixエージェント、PHP-FPMを再起動します。
systemctl restart zabbix-server zabbix-agent rh-php72-php-fpm httpd
ステータスを確認します。
systemctl status zabbix-server zabbix-agent rh-php72-php-fpm httpd
-
次にwebインターフェイス(Admin)から設定を追加します。
設定>ホスト>Template DB MySQL by Zabbix agentを選択して”更新”
-
作成したテンプレート(Template DB MySQL by Zabbix agent)を選択
-
マクロタブを選択し、値が次のとおりか確認し、更新します。
{$MYSQL.HOST}:localhost,{$MYSQL.PORT}:3306
SELECTによって参照された状況を把握するために、「Bytes sent」を選択して負荷をかけてメトリクスの動きを確認してみます。既作成のDB内に仮にテーブル(100行)を作成し、SELECT文を繰り返し実行させることで少しだけ負荷を掛けます。
Zabbixユーザー又はrootでログインします。
mysql -u root -p
DBを選択します。
USE zabbix;
現状のテーブル名を確認しておきます。
SHOW TABLES;
テーブルを作成し、100行のレコードを作成します。
負荷を増やしたい場合は、行数を1000行にするなどします。
CREATE TABLE large_table (
id INT AUTO_INCREMENT PRIMARY KEY,
data VARCHAR(255)
);
INSERT INTO large_table (data)
SELECT REPEAT('sample_data', 50) FROM information_schema.tables LIMIT 100;
テーブル(large_table)が作成されたか確認します。
SHOW TABLES;
レコードが100行できたか確認します。
SELECT COUNT(*) FROM large_table;
実際に軽く負荷を掛けます。
ここで負荷を増やしたい場合は、10000などに編集しましょう。
SELECT BENCHMARK(1000, (SELECT id FROM large_table LIMIT 1));
実行した際の例:
+-------------------------------------------------------+
| BENCHMARK(1000, (SELECT id FROM large_table LIMIT 1)) |
+-------------------------------------------------------+
| 0 |
+-------------------------------------------------------+
"0"が返ってきていると正常に実行できたということです。
そしてグラフを確認してみましょう。
他の監視メトリクスとして「Command Select per second」によって1秒あたりに実行されるSELECTクエリの回数を監視することができます。直感的に見やすいので、このメトリクスを使ってみたいと思います。
EventBridgeでのCron 式参考
Cron式の例(その時々に応じた適切な時間設定にしましょう!)
時間間隔 | Cron式 |
---|---|
1時間おき | cron(0 * * * ? *) |
1分おき | cron(* * * * ? *) |
5分おき | cron(0/5 * * * ? *) |
15分おき | cron(0/15 * * * ? *) |
30分おき | cron(0/30 * * * ? *) |
無視OK!Lambdaのコードをアップロードする時の手順
何度も修正してアップロードするので、記載しておきます。
- 前提として既存のGoコードが、/home/ec2-user配下にfunction.zip、main、main.go及びbootstrapが存在するものとして記載します。
- 慎重に”削除”していきます。
rm -rf function.zip
rm main
ls
- 削除されたことを確認したら、再び作成します。
- 先にmain.goの編集を済ませ、次の工程を行います。
- バイナリデータ作成
GOOS=linux GOARCH=amd64 go build -o main
ZIPファイルにパッケージングします。
zip function.zip main bootstrap
ls
mainとfunction.zipが作成されているか確認します。
このままローカルにデータをダウンロードし、Lambdaにアップロードします。
CloudWatchでApacheの”ログ”を表示する。
次のポリシーがアタッチされたロールがEC2にアタッチされているか確認します。
CloudWatchAgentServerPolicy
awslogsをインストールする
yum install awslogs
設定ファイルが存在するか確認します。
ls -l /etc/awslogs
出力:
[root@zabbix ~]# ls -l /etc/awslogs
total 20
-rw------- 1 root root 55 Sep 25 12:02 awscli.conf
-rw-r--r-- 1 root root 8355 Jul 26 2018 awslogs.conf
drwxr-xr-x 2 root root 6 Jul 26 2018 config
-rw-r--r-- 1 root root 147 Jul 26 2018 proxy.conf
awscli.confを編集します。
vi awscli.conf
次のように修正します。
[plugins]
cwlogs = cwlogs
[default]
region = ap-northeast-1
awslogs.confを編集します。
vi awslogs.conf
次の記載を末尾に追記します。
[HttpAccessLog]
file = /var/log/httpd/access_log
log_group_name = HttpAccessLog
log_stream_name = {instance_id}
datetime_format = %b %d %H:%M:%S
[HttpErrorLog]
file = /var/log/httpd/error_log
log_group_name = HttpErrorLog
log_stream_name = {instance_id}
datetime_format = %b %d %H:%M:%S
awslogsを起動する
systemctl start awslogsd
ステータスを確認しておきます。
systemctl status awslogsd
自動起動を有効にします。
systemctl enable awslogsd
これでログがCloudWatch logsに追加されました。
Apacheログをダッシュボードに表示する。
- CloudWach logsの画面へ移動
画面上部の検索窓で検索し、Apacheのaccess logを選択します。
- クエリによって表示させたい情報を表示させる。
クエリの例:parse '* - * [*] "* * *" * *' as host, identity, dateTimeString, httpVerb, url, protocol, statusCode, bytes | stats max(bytes) as maxBytes, avg(bytes) by url | sort maxBytes desc
エラーログは表示されるフィールドが少ないためクエリはデフォルトです。
fields @timestamp, @message, @logStream, @log
| sort @timestamp desc
| limit 10000
見た目も特に問題ありません。
CloudWatch Alarmを設定(あくまでテスト環境です。)
最終的にメモリとスワップの複合アラームを設定する。
スケールアップの要否を見たいので、メモリの状況でアラームを設定してみる!
- メトリクス名:mem_used_percent
- host:zabbix
- 統計:最大
- 期間:5分
条件 - 静的
- より大きい
- しきい値:95%
- アラームを実行するデータポイント(3(データポイント)回中、3回ダメな時にアラーム)
- 欠落データを見つかりませんとして処理(メトリクスが飛ばなかった時の振る舞い)
スワップのメトリクスもスケールアップに役立てたい!
- メトリクス名:swap_free
- host:zabbix
- 統計:最小
- 期間:5分
- 静的
- より低い
- 60%
- アラームを実行するデータポイント(3(データポイント)回中、3回ダメな時にアラーム)
- 欠落データを見つかりませんとして処理(メトリクスが飛ばなかった時の振る舞い)
複合アラームの作成
先ほど作成した両アラームを合体。
- アラーム状態トリガー:アラーム状態
- 次の SNS トピックに通知を送信:通知先任意
- アラーム名:test-composite-alarms
- ルール(任意)
ALARM("zabbix-memory-alarm") AND ALARM("test-swap-alarm")
おわりに
最後まで読んでいただきありがとうございます。
目標としていた構築する上で知っておきたい基礎知識は少しだけ身についたものとして、次の記事ではCloudWatch RUMを実装してきます!
では!
1つずつ誠実に取り組み、技術を身に着けて発信も併せて行っていきます!