ECS Fargateで mackerel-container-agent をサイドカーで動かす
はじめに
ECS Fargateで mackerel-container-agent をサイドカーで動かしてコンテナを監視します!
前回の↓記事でECS FargateでGoコンテナをデプロイしました。 が、この記事では省略していたコンテナ監視とSSMパラメータストアとの連携について書いていきますー。
タスクを定義する
こちらの公式記事を参考にしました。
- 前回のブログ taskdef.json から mackerel-container-agent の部分抜粋
{ "name": "mackerel-container-agent", "image": "mackerel/mackerel-container-agent:latest", "essential": false, "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/go-scraping-api", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "ecs" } }, "memory": 128, "environment" : [ { "name": "MACKEREL_CONTAINER_PLATFORM", "value": "fargate" }, { "name": "MACKEREL_ROLES", "value": "dev:fargate" } ], "secrets": [ { "name": "MACKEREL_APIKEY", "valueFrom": "mackerel_agent_apikey" } ] }
環境変数とSSMパラメータストア
環境変数をSSMパラメータストアから参照する方法について! 環境変数を利用するために environment で定義して環境変数の key/value をセットします。 次に、パラメータストアにSecureStringで登録した値を参照するに secrets で定義し、name に環境変数名、 valueFrom に ssmパラメータストアのkey名を書きました。
"environment" : [ { "name": "MACKEREL_CONTAINER_PLATFORM", "value": "fargate" }, { "name": "MACKEREL_ROLES", "value": "dev:fargate" } ], "secrets": [ { "name": "MACKEREL_APIKEY", "valueFrom": "mackerel_agent_apikey" } ]
Mackerelの管理画面で確認
バッチリとれてますね!!
さいごに
今回はECS Fargateのコンテナ監視に mackerel-container-agent をサイドカーで動かしました。 taskdefファイルにこのように定義するだけでいいので手間なくカンタンでした!
ECS FargateでBlue/Greenデプロイをする
- Blue/Greenデプロイについて
- アーキテクチャとデプロイフロー
- ALBとターゲットグループを作成する
- ECS Fargateのサービスを作成する
- CodePipelineについて
- CodeBuild
- CodeDeploy
- コンテナのログについて
- Blue/Greenデプロイの確認
- さいごに
- 参考
前回のブログでECS Fargateのローリングアップデートについて書きました。 今回はBlue/Greenデプロイについて異なる部分について書いていこうと思います。
Blue/Greenデプロイについて
■ Step1
デプロイ前の状態で、ALBのプロダクションポート80番、転送先がargetGroupAにトラフィックが流れている状態。
■ Step2
ALBのテストポート8000番、転送先がTargetGroupBにGreenをデプロイしてトラフィックが流れ動作確認できる状態。
■ Step3
Greenのデプロイが完了したらALBのプロダクションポートの転送先をTargetGroupBに向けてBlueにトラフィックが流れないようになる。
アーキテクチャとデプロイフロー
■ アーキテクチャ
■ デプロイフロー
ALBとターゲットグループを作成する
まずは TargetGroupA を作成。
次に TargetGroupB を作成。
次に ALB を作成します。プロダクションポートの80番とテストポートの8000番を追加して、それぞれの転送先は TargetGroupAとBにします。
これでECSのサービスを作成するときに指定するALBとTargetGroupの作成が完了です。
ECS Fargateのサービスを作成する
では、サービスを作成していきます。今回はBlue/Greenデプロイで作成します。
↓↓↓
CodeDeployのサービスロールを選択する必要があるんですが、AWSCodeDeployRoleForECS
の権限が必要になります。
以下の方法でIAMロールを新規作成しました。
作成したIAMロールを選択して次にすすみます。NWの設定をします。
ALBやターゲットグループの設定をしていきます。
↓↓↓
↓↓↓
CodePipelineについて
今回作成したCodePipeline。Sourceの部分は省略してます。
前回書いたローリングアップデートと異なるCodeBuildとCodeDeployについて書きます。
CodeBuild
buildspec.yml
ローリングアップデートからBlue/Greenデプロイにするためにbuildspec.ymlを修正します。
- buildspec.yml
version: 0.2 phases: install: runtime-versions: golang: 1.13 docker: 18 pre_build: commands: - echo Logging in to Amazon ECR... - aws --version - $(aws ecr get-login --region ap-northeast-1 --no-include-email) - REPOSITORY_URI=`aws sts get-caller-identity --query 'Account' --output text`.dkr.ecr.ap-northeast-1.amazonaws.com/go-scraping-api - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7) - IMAGE_TAG=${COMMIT_HASH:=latest} build: commands: - echo Build started on `date` - echo Building the Docker image... - docker build -t $REPOSITORY_URI:latest . - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG post_build: commands: - echo Build completed on `date` - echo Pushing the Docker images... - docker push $REPOSITORY_URI:latest - docker push $REPOSITORY_URI:$IMAGE_TAG - printf '{"Version":"1.0","ImageURI":"%s"}' $REPOSITORY_URI:$IMAGE_TAG > imageDetail.json artifacts: files: imageDetail.json
ローリングアップデートと異なる部分は↓。 imagedefinitions.json
--> imageDetail.json
に変更する。このファイル名でないとエラーになります。
また、jsonの中身も変わるので注意。
- printf '{"Version":"1.0","ImageURI":"%s"}' $REPOSITORY_URI:$IMAGE_TAG > imageDetail.json artifacts: files: imageDetail.json
taskdef.jsonについて
次に、Blue/Greenデプロイにするために taskdef.jsonファイルが必要になります。yamlで記述してもOKです。今回はjson形式でやります。
XXXXXXXXXXXX
の部分はアカウント番号が入るためにマスクしました。
"image": "<IMAGE1_NAME>",
この部分でCodeBuildで作成されたコンテナイメージを参照します。 また、↓のtaskdef.jsonでは "mackerel-container-agent" をサイドカーとして追加しています。不要であればここの定義は削除してください。 このサイドカーでコンテナを監視する記事は別途作成します。
- taskdef.json
{ "executionRoleArn": "arn:aws:iam::XXXXXXXXXXXX:role/go-scraping-api", "containerDefinitions": [ { "name": "go-scraping-api", "image": "<IMAGE1_NAME>", "portMappings": [ { "containerPort": 3000, "hostPort": 3000, "protocol": "tcp" } ], "essential": true, "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/go-scraping-api", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "ecs" } } }, { "name": "mackerel-container-agent", "image": "mackerel/mackerel-container-agent:latest", "essential": false, "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/go-scraping-api", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "ecs" } }, "memory": 128, "environment" : [ { "name": "MACKEREL_CONTAINER_PLATFORM", "value": "fargate" }, { "name": "MACKEREL_ROLES", "value": "dev:ecs" } ], "secrets": [ { "name": "MACKEREL_APIKEY", "valueFrom": "mackerel_agent_apikey" } ] } ], "requiresCompatibilities": [ "FARGATE" ], "networkMode": "awsvpc", "cpu": "256", "memory": "512", "family": "go-scraping-api" }
タスク実行のロールを↓で付与しています。
"executionRoleArn": "arn:aws:iam::XXXXXXXXXXXX:role/go-scraping-api",
SSMパラメータを参照する必要があるので、↓のポリシーを付与しています。
機密情報の取り扱いについて ( SSM連携 )
mackerel-container-agentをサイドカーとして動かしています。ここについては次のブログにて紹介します。
↓↓↓
CodeDeploy
次にCodeDeployの設定をしていきます。ECSのサービスを作ったときに生成されたCodeDeployのアプリケーションとデプロイグループを利用します。 デプロイプロバイダは ECS (ブルー/グリーン) を選択。 appspec.yaml のファイル名は固定ですが、taskdef.json のファイル名は任意に設定できるのでEnvで分けるときはenvごとに名前をつけることができます。 IAMロールのarnが入るため、envをまたぐときは複数ファイル用意してCodeDeployのファイル名で合わせればいいと思います。
↓↓↓
コンテナのログについて
CloudwatchLogsに今回はログを吐き出すようにしています。
- taskdef.jsonから一部抜粋
"logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/ecs/go-scraping-api", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "ecs" } }
Blue/Greenデプロイの確認
検証でここまで設定してBlue/Greenデプロイを実行したので、80/8000番ポートのターゲットグループがそれぞれTargetGroupAになっています。 この状態からBlue/Greenデプロイを実施して動きを確認しようと思います。
ALBのTargetGroupの動き
ALBの設定されているTargetGroupは 80番 / 8000番 ポートに TargetGroupAがセットされています。
まず、テストポートである8000番ポートにGreenのTargetGroupBがセットされました。
次に、8000番ポートのTargetGroupBが正常であれば、プロダクションポートのTargetGroupAもGreenのTargetGroupBに変わります。 プロダクションポートとテストポートがそれぞれ、GreenのTargetGroupBに変わることが確認できました。
Fargateのタスクの動き
Greenのタスクの状態からBlueが追加されました。
BlueとGreenの状態からBlueが切り離されました。
動作確認
外部からプロダクションポートの80番とテストポートの8000番にヘルスチェックのAPIを叩いて確認しました。 BGデプロイ中にテストポートにトラフィックが流れるGreenに対して実行してもOKでした。
curl http://go-scraping-api-XXXXXXXXX.ap-northeast-1.elb.amazonaws.com/ping pong
curl http://go-scraping-api-XXXXXXXXX.ap-northeast-1.elb.amazonaws.com:8000/ping pong
さいごに
今回は、前回のローリングアップデートの続きとして、Goコンテナを使ってBlue/Greenデプロイについて検証してまとめました。 サイドカーを使ってmackerelで監視する方法については省略していますが、ssm連携と合わせて書こうと思います。 今回の環境構築は全体像を掴みたいところもあったのでwebコンソールでポチポチ作っていきましたが、CLIやTerraformで環境を作る ところも取り組んでいければと思います。 また、先日の re:Invent で EKSもかなりアップデートがあったので、そちらについても検証をすすめていきたいと思います。
参考
https://d1.awsstatic.com/webinars/jp/pdf/services/20190731_AWS-BlackBelt_AmazonECS_DeepDive_Rev.pdf
ECS FargateでGoコンテナを起動してローリングアップデートする
- はじめに
- アーキテクチャ
- GitHub
- ECRに登録するGoコンテナを作成する
- ECS Fargateのタスクを作成する
- ECS Fargateのサービスを作成する
- CodePipelineを作成する
- ローリングアップデートの実行と動作確認
- まとめ
はじめに
今回は ECS FargateでGoコンテナを起動してローリングアップデートする をテーマに書いていきます。
以前の記事でGAEにGo echoで実装したAPIをデプロイしました。
今回はこのAPIをECSのFargate上にデプロイしてコンテナをローリングアップデートでデプロイします。 Blue/Greenデプロイについては別記事にて紹介する予定です。
アーキテクチャ
本記事のアーキテクチャとデプロイフローは↓
■ アーキテクチャ
■ デプロイフロー
GitHub
ソースコード全体はこちらに公開しています。 github.com
ECRに登録するGoコンテナを作成する
docker imageを作成
FROM golang:1.13-alpine3.10 as build RUN apk add --update --no-cache git RUN mkdir /app WORKDIR /app COPY go.mod ./ RUN go mod download COPY . . RUN go build -o go-scraping-api . FROM alpine:3.10 RUN apk add --update --no-cache ca-certificates WORKDIR /app COPY --from=build /app/go-scraping-api /app/go-scraping-api ENTRYPOINT ["/app/go-scraping-api"]
Dockerfileに イメージを指定する FROM
が2箇所あります。これは、最初の FROM golang:1.13-alpine3.10 as build
で golang:1.13-alpine3.10
のイメージで Goのソースコードをコンパイルします。
そして 2つ目の FROM alpine:3.10
のイメージにて、 COPY --from=build /app/go-scraping-api
で FROM golang:1.13-alpine3.10 as build
でコンパイルしたバイナリファイルをFROM alpine:3.10
の /app/go-scraping-api
にコピーしています。かなり軽
ECRにdocker imageをpushする
■ イメージを確認
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE go-metal-api latest 581f8817569a 5 hours ago 19.7MB
■ ecrにログイン
$(aws ecr get-login --no-include-email --region ap-northeast-1 --profile my-dev)
■ イメージにタグづけ
docker tag go-metal-api:latest ${ACCOUNT}.dkr.ecr.ap-northeast-1.amazonaws.com/go-scraping-api:latest
■ ecrにimageをpush
docker push ${ACCOUNT}.dkr.ecr.ap-northeast-1.amazonaws.com/go-scraping-api:latest
ECS Fargateのタスクを作成する
ネットワークモードを awsvpc
、 互換性に Fargate
を選択しました。タスク実行ロールは ecsTaskExecutionRole
を適用し
タスクに割り当てるメモリとCPUは最小のものをそれぞれ選択しています。
コンテナについては、イメージは ECR でリポジトリを作成すると払い出させる値をセット。ポートマッピングについては 今回のGoコンテナは3000番ポートでListenするので 3000 としています。
■ タスクの定義
■ コンテナの定義
ECS Fargateのサービスを作成する
ALBを作成する
サービスをつくる前に ALB と ターゲットグループ を作成します。 今回はFargateのサービスを作るときにALBありで作成します。 説明に必要なところだけピックアップします。
■ ルーティングの設定
→ ターゲットの種類は IP
を選択する必要があります。ヘルスチェックのパスは echoで /ping
で実装したためです。
→ ネットワーク
はFargateを展開するVPCを選択。IP(許容範囲)
は何も入力せずに次に進みます。( Fargateのサービスを作成するときにコンテナを展開するサブネットを選択します )
サービスをつくる
■ サービスの設定とデプロイメント
起動タイプは Fargate を選択し、タスク定義は事前に作成したものを選択します。タスク数は1、最小ヘルス率を100% 最大ヘルス数を200% にしました。 これは、タスク数2のときにローリングアップデートすると、最低で2台、最大で4台まで増えてデプロイされます。
■ ネットワーク構成
コンテナを稼働させるVPCとサブネットを選択します。ALB配下にぶら下げるために先ほど作成したALBの環境に考慮して作成します。 セキュリティグループとパブリックIPの割り当ても環境に応じて設定してします。
■ Load balancing / ロードバランス用のコンテナ
ロードバランサの種類は ALB を選択。ロードバランサを選択してコンテナを選択します。 コンテナの選択は先ほど作成したタスクに紐づいたコンテナを選択します。ターゲットグループを選択すると先ほど作成したターゲットグループの設定が反映されます。
プロダクションリスナーポート は ALBが外部から受け付けるポートになります。 今回にALBを作成するときに外部受付ポートを80にして作成したので80がセットされています。
■ コンテナが正常に起動したかを確認
ターゲットグループで登録済みターゲットのステータスが healthyになっていればOK。
CodePipelineを作成する
Source ( GitHub )
CodeBuild
CodeBuild上でdockerコマンドを利用してコンテナイメージを作成するので 特権付与を有効
にします。
また、作成したイメージをECRに登録するのでIAMロールにECRにイメージをpushできる権限を付与する必要があります。
■ 環境
■ キャッシュ
docker pullやbuildの処理が高速化されます。しかし、検証したところキャッシュが有効になるのはキャッシュされた次の1回だけでした。
次はbuildspec.ymlを用意していきます。
イメージ定義ファイル名 imagedefinitions.json
と imageUri
はこの名前にする必要があります。
さらに、imagedefinitions.jsonの中身は []
arrayにする必要があり、こう書かないと invalid json format.. となりエラーとなります。
printf '[{"name":"go-scraping-api","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
→ imagedefinitions.json
の内容は CodeDeplyで BuildArtifact
として参照される。
- buildspec.yml
version: 0.2 phases: install: runtime-versions: golang: 1.13 docker: 18 pre_build: commands: - echo Logging in to Amazon ECR... - aws --version - $(aws ecr get-login --region ap-northeast-1 --no-include-email) - REPOSITORY_URI=`aws sts get-caller-identity --query 'Account' --output text`.dkr.ecr.ap-northeast-1.amazonaws.com/go-scraping-api - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7) - IMAGE_TAG=${COMMIT_HASH:=latest} build: commands: - echo Build started on `date` - echo Building the Docker image... - docker build -t $REPOSITORY_URI:latest . - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG post_build: commands: - echo Build completed on `date` - echo Pushing the Docker images... - docker push $REPOSITORY_URI:latest - docker push $REPOSITORY_URI:$IMAGE_TAG - printf '[{"name":"go-scraping-api","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json artifacts: files: imagedefinitions.json
- Ref
CodeDeploy
アクションプロバイダについて、ローリングアップデートする場合は Amazon ECS
を選択します。そして、デプロイするコンテナはCodeBuildで作成したイメージを利用するので入力アーティファクトは BuildArtifact
を選択します。
作成したコードパイプラインの全体は↓。
ローリングアップデートの実行と動作確認
ローリングアップデート
ローリングアップデート中にサービスのタスクについて確認した結果↓
■ 開始時 go-scraping-api:5 だけが稼働
■ 新コンテナのプロビジョニング
go-scraping-api:6 が起動中
■ 新コンテナ起動完了
■ 完了時 ( 旧コンテナの削除済 )
go-scraping-api:5 が退役した
動作確認
動作確認として金とプラチナの価格のjsonを返すAPIを実行した。
$ curl http://go-scraping-api-XXXXXXXXXX.ap-northeast-1.elb.amazonaws.com/metal
{"time":"2019-12-07T15:47:18.57576583+09:00","goldInfo":{"retailTax":5707,"purchaseTax":5620},"platinum":{"retailTax":3539,"purchaseTax":3408}}
まとめ
今回は GAEで動かしている貴金属を返すGoのAPIを Dockerコンテナ化してECS Fargateに自動デプロイできるようにしました。今回はローリングアップデートについて記載しましたが 次回はBlue/Greenデプロイについて書いていきたいと思います。FargateはEC2の管理が必要ないので複雑でないコンテナ構成であればFargateにデプロイしていくのはとてもいいと思います。 Blue/Greenデプロイをまとめたら EKSの検証を進めていきたい。
GoとMySQLの学習メモ ( DB接続とデータ取得 )
今回勉強するにあたってこの記事を利用しました。
Goでmysqlに接続するために今回は↓のドライバを利用しました。
■ DockerでMySQLを起動してGoからDBを操作する。
mysqlコンテナの作成
version: '3' services: db: image: mysql:5.7 container_name: dev_mysql ports: - "3306:3306" volumes: - ./db/mysql_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: password MYSQL_USER: app MYSQL_PASSWORD: password
データベースを作成してデータを入れる。
■ データベース作成 mysql> create database devdb; ■ テーブル作成 mysql> create table users (id int, name varchar(10)); ■ データ追加 mysql> insert into users values (1, 'yamada');
main.go
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" ) type Person struct { ID int32 Name string } func main() { db, err := sql.Open("mysql", "root:password@tcp(127.0.0.1:3306)/devdb") if err != nil { panic(err.Error()) } defer db.Close() insert, err := db.Query("INSERT INTO users VALUES ( 2, 'gotest')") if err != nil { panic(err.Error()) } defer insert.Close() results, err := db.Query("SELECT * FROM users") if err != nil { panic(err.Error()) } defer results.Close() for results.Next() { var person Person err := results.Scan(&person.ID, &person.Name) if err != nil { panic(err.Error()) } fmt.Println(person.ID, person.Name) } }
ユーザ情報をSELECTした結果をPersonの構造体にデータを格納しました。 実行した結果は↓
1 yamada 2 gotest
mackerel-client-goにfind invitations apiをコミットした
久しびりにブログを書きます。 なるべく小さなことでも書こうと思ってたのですが、風邪やらで体調崩したり週末バタバタしてたりで全然かけなかった。 これからは、小さいことでも自分の備忘録的に書いていきたいー。
今回はmackerel-client-goでユーザの招待一覧を取得する処理するを実装しました。
- 作成したPRリクエスト
1営業日でPRレビューしてもらいMergeされました。ありがとうございます!
mackerel-client-goにコントリビューションする方法はこの記事にまとめています。
Google App Engine(Go)とechoを使ってAPIを作ってみた ( 結果の可視化はMackerelで )
はじめに
Goとechoを使って簡易的なAPIサーバを作ってみました。今後、echoを使ってやってみたい事があるので、ますは使ってみる! という感じのものです。 以前のブログで貴金属の価格をGoでスクレイピングしてMackerelで可視化したものを拡張しました。
この記事では、Lambdaで貴金属の価格掲載サイトにスクレイピングしてその値をMackerelに投げてグラフ化しています。 echoを使ってAPIサーバを作ってみたかったので、まずは、貴金属の価格の結果をjsonで返すAPIサーバをGAEで動かすことにしました。
アーキテクチャとフロー
- cloudwatch-eventで定期実行させる
- Lambda ( Go ) で GAEの ( API ) エンドポイントにGETリクエストを投げる
- echo ( Go ) で貴金属の価格掲載サイトにスクレイピングする
- スクレイピングで取得したデータをJSONに整形する
- LambdaからのリクエストにJSONで返す
- Mackerelのサービスメトリクスに投稿する
Lambda ( Go )のクライアントについて
GAEのエンドポイントに対して /metal
でGETリクエストをする と金とプラチナの情報のjsonを返すようにしています。
そのjsonをパースして、Mackerelのサービスメトリクスに投稿します。
その記事に関してはこちらに記載しています。
- jsonレスポンスの例
{ "time": "2019-09-22T09:51:57.440183+09:00", "Gold": { "retailTax": 5674, "purchaseTax": 5588 }, "Platinum": { "retailTax": 5674, "purchaseTax": 5588 } }
*) timeに関しては、最終的にMackerelにメトリクスを投げるときに利用できるようにこの形式にしています。
main.goのソースコードは以下です。
デプロイについて
LambdaやCloudwatch-EventなどはServerlessFrameworkを利用してデプロイしています。 serverlessFrameworkのコードも先ほどのGitHubにあります。
GoogleAppEngine ( Go ) について
今回のブログで残しておきたいのはこのGAEの方です。 Macローカルにgo echoをインストールしてコーディングしてからGAEにデプロイしました。
echoについて
echoについて、インストール方法などはこちらに。
echoでやっていること
Basic認証
今回、接続元を制限していないのでスクレイピング先に迷惑がかからないようにBasic認証をかけています。
./authentication/basic.go
package authentication import ( "github.com/labstack/echo" "github.com/labstack/echo/middleware" "os" ) var ( id = os.Getenv("ID") pw = os.Getenv("PW") ) func BasicAuth() echo.MiddlewareFunc { return middleware.BasicAuth(func(username string, password string, context echo.Context) (bool, error) { if username == id && password == pw { return true,nil } return false,nil }) }
- main.go
func main() { ・・・ // Basic Auth e.Use(authentication.BasicAuth()) ・・・ }
スクレイピングとjson生成
ここで、対象サイトにスクレイピングしてレスポンス結果を利用してjsonを生成してクライアントに返す処理を定義しています。
./handler/metal.go
{ "time": "2019-09-22T09:51:57.440183+09:00", "Gold": { "retailTax": 5674, "purchaseTax": 5588 }, "Platinum": { "retailTax": 5674, "purchaseTax": 5588 } }
こんなjsonを返します。
GAEへのデプロイについて
gcloudコマンドを使ってデプロイをします。
- デプロイコマンド
gcloud auth login
gcloud app deploy --project ${PROJECT-ID}?
デプロイするために、ディレクトリ直下に app.yaml
を作ります。
runtime: go112 handlers: - url: /.* script: auto includes: - secret.yaml
環境変数として ベーシック認証のID/PWを渡す必要があるので secret.yaml
をincludeするようにしています。
secret.yaml
env_variables: ID: 'XXX' PW: 'XXX'
app.yamlについてのリファレンス
結果
- GAE
- クライアント側のLambdaを1時間毎に実行させた結果
- Mackerelのサービスメトリクス
- LambdaでGAEにapiコールして取得した結果を反映させた結果
さいごに
今回はじめてechoをつかってみました。まずは使ってみるというところでGETリクエストでjsonを返してその結果を可視化するというテーマでやりました。 自分用APIサーバとしてGAEを使ってGo開発するのもよさそうです。無料枠もあって今のところ無料で使えています。
AWS請求額をGoとMackerelで可視化して監視・通知する
はじめに
今回もMackerelを使ってメトリクスを可視化する系の記事です。今回は監視と通知もしています。 AWSの請求額をグラフ化して閾値を超えたらLine通知するようにしました。AWSを利用しすぎて今月の支払額が予算オーバーしたっ!! ...ってならないよにするため。
アーキテクチャ
- CloudWatch EventでLambdaを定期実行
- Lmabda ( Go ) でバージニア北部のCloudWatchにAPIでデータを取得
- Lambda ( Go ) でMackerelにメトリクスを投げて可視化と監視
- 閾値を超えたらMackerelの機能でLINE通知
Lambda ( Go )について
実装はGoとaws-sdk-goとmackerel-client-goを利用しました。 デプロイに関してはServerlessFrameworkで 行いました。付与するIAMロール権限はCloudwatch Readonlyです。
package main import ( "fmt" "os" "time" "github.com/aws/aws-lambda-go/lambda" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/cloudwatch" "github.com/mackerelio/mackerel-client-go" ) var ( mkrKey = os.Getenv("MKRKEY") client = mackerel.NewClient(mkrKey) config = aws.Config{Region: aws.String(region)} cwt = cloudwatch.New(session.New(&config)) ) const ( region = "us-east-1" serviceName = "AWS" timezone = "Asia/Tokyo" offset = 9 * 60 * 60 ) func main() { lambda.Start(Handler) } // Handler Lambda func Handler() { var cost float64 jst := time.FixedZone(timezone, offset) nowTime := time.Now().In(jst) input := &cloudwatch.GetMetricStatisticsInput{ Dimensions: []*cloudwatch.Dimension{ { Name: aws.String("Currency"), Value: aws.String("USD"), }, }, StartTime: aws.Time(time.Now().Add(time.Hour * -24)), EndTime: aws.Time(time.Now()), Period: aws.Int64(86400), Namespace: aws.String("AWS/Billing"), MetricName: aws.String("EstimatedCharges"), Statistics: []*string{ aws.String(cloudwatch.StatisticMaximum), }, } response, err := cwt.GetMetricStatistics(input) if err != nil { fmt.Println(err) } for _, v := range response.Datapoints { cost = *v.Maximum } fmt.Println(cost) errMkr := PostValuesToMackerel(cost, nowTime) if errMkr != nil { fmt.Println(errMkr) } } // PostValuesToMackerel Post Metrics to Mackerel func PostValuesToMackerel(cost float64, nowTime time.Time) error { err := client.PostServiceMetricValues(serviceName, []*mackerel.MetricValue{ &mackerel.MetricValue{ Name: "Cost.cost", Time: nowTime.Unix(), Value: cost, }, }) if err != nil { fmt.Println(err) } return nil }
結果 ( Mackerelの画面 )
監視設定とアラート通知 ( LINE )
今回はLineに通知を飛ばす設定にしました! Lineに通知するためのMackerelの設定は以下のページで説明されています。
アラートの閾値設定をします。とりあえずアラートを発生させるために低く設定しました。
■ LINEへのアラート通知結果
デプロイ
- Mackerelにサービスを登録する
export MKRKEY=XXX curl -X POST https://api.mackerelio.com/api/v0/services \ -H "X-Api-Key: ${MKRKEY}" \ -H "Content-Type: application/json" \ -d '{"name": "AWS", "memo": "aws cost"}'
- main.goをコンパイルする
make build
- ServerlessFrameworkでデプロイする
sls deploy --aws-profile <PROFILE> --mkrkey ${MKRKEY}
ソースコード等はこちらにおいています。(MakefileとかserverlessFrameworkのyamlファイルとか)
さいごに
今回はGoとMackerelを使ってAWSの請求額をグラフ化して監視設定とLINE通知をできるようにしました。 これで、月々どれくらい使ってるのか、急に利用金額が増えても気づけるようになると思います。