フューチャー技術ブログ

Go x AWSでつくる サービス運用ツール実例集

筒井です。

先日、Future Tech Night #12 〜Goで始めるサーバレスファーストという選択肢〜というイベントを開催しました。
私は『Go x AWSでつくる サービス運用ツール実例集』というタイトルで発表させていただきました。

発表の概要と補足

詳細はスライドを御覧ください。

目次

  1. 前おき
    • サーバーレスのメリット・デメリット
    • サーバーレス Framework について
  2. 実例集
    • 休日・夜間に開発環境を停止する
    • サービスダッシュボードをつくる
    • 本番DBを検証環境へクローンする
  3. Tips
    • Step Functionsをつかう理由
    • main.goのダイエット
    • Makefileの書き方

Introduction

Webサービスの運営・運用をしていると、「この作業自動化したいな…」と思うことは多々あるかと思います。

しかし、こうした要望から開発したツール類は塩漬けになりがちで、数か月後に書き捨てのつもりだった難読シェルスクリプトと向き合った経験をお持ちの方も多いのではないでしょうか。
この発表ではそういった”ちょっとしたツール”を、GoとAWSの組み合わせで開発した実例を紹介しました。

Go x AWS (Lambda, Step Functions) で運用ツールをつくるメリット・デメリット

運用ツール(無くてもいいがあると嬉しいもの)をGo x AWSで実現すると嬉しいことについて説明しました。
「cron用のサーバを用意するほどでもないが、都度ローカルで実行するのは地味にめんどくさい」タスクにピッタリです。

Serverless Frameworkについて

Serverless FrameworkはIaCツールの一種で、
Lambda Functionのデプロイと関連するリソース(LambdaにあてるIAM Roleや、通知用のSNS Topicなど)の構築を一度に行うことが可能です。

Q&Aより: Terraformとどちらがいいの?
作るものの規模と開発チームの体制によりけりかと思います。
Serverlessの場合は、Lambdaの環境変数から関連リソースまで1ファイルにまとめることが出来るため(もちろん分割もできますが)、
小さなツールを1人でガーッと作りきってしまうようなシチュエーションでは良い選択肢だと思っています。

実例1. 休日・夜間に開発環境を停止する

GUI付きのcronサーバと化していたJenkinsを廃止するために生まれたものです。
LambdaからAWS SDKを通してEC2、ECS、RDSなどを停止しています。

serverless.yml の設定例を記載しておきます。

functions:
rds:
handler: dist/rds

stepFunctions:
validate: true
stateMachines:
suspend:
events:
# 平日21時(JST)に停止
- schedule:
rate: "cron(0 12 ? * MON-FRI *)"
input:
dbClusterIdentifiers:
- your-database-identifier
definition:
StartAt: SuspendRDS
States:
SuspendRDS:
Type: Task
Resource: !GetAtt rds.Arn
Parameters:
action: suspend
dbClusterIdentifiers.$: $.dbClusterIdentifiers
ResultPath: null
Next: Succeeded
Succeeded:
Type: Pass
End: true

Lambda Functionの入力は以下のように定義しています。

// handlers/rds/main.go
// Event is a concrete representation of input values of lambda function
type Event struct {
// Action accepts values [suspend, start]
Action string `json:"action"`
DBClusterIdentifiers []string `json:"dbClusterIdentifiers"`
}

実例2. サービスダッシュボードをつくる

アプリケーションDB (RDS) からサービスのKPIをクエリし、Google Data Studioを使ってダッシュボードをつくるサンプルです。
以前はredashを使ってクエリを実行しCSVを取得、Excelにまとめていたのですが、これを自動化するために生まれました。

使用するLambda Functionは以下2つです。

  1. DBから取得したデータを、CSV形式でS3に保存
  2. S3からCSVを読み出し、BigQueryにインサートする

1と2のLambda Functionを分けているのは以下の理由からです。

  • 1のLambda FunctionはVPC内に配置しているため、インターネットアクセスができない (S3はVPC Endpointからアクセス可能)
  • アーカイブとしてデータを残しておきたい

Goの経験が浅くてもSQLがかければメンテ出来るように、というのがこのツールの工夫ポイントです。
まず次のようなInterfaceと、このInterfaceを満たすStructのSQL実行を行う共通コードを用意しておきます。

// Model is an abstract implementation of each models (queries).
type Model interface {
// Name .
Name() string
// Query returns SQL query
Query() string
}

すると、次のようなStructおよびMethodを追加すると、簡単にKPI項目を増やせるようになります。

type MyKPI struct {
Timestamp time.Time `db:"timestamp" csv:"timestamp"`
Sales int64 `db:"sales" csv:"sales"`
}

func (x *MyKPI) Name() string {
return "monthly_sales"
}

func (x *MyKPI) Query() string {
return "select timestamp, sales from ..."
}

コードにトリッキーな部分がないのもGoのメリットかと思います(個人的な感想ですが)。

実例3. 本番DBを検証環境にクローンする

本番データに起因するバグが発生した際などに、検証環境で安全かつスムーズに調査を行うために生まれたものです。

本番DBのスナップショットをリストア、データマスキングを行った後再度スナップショット化。
RDSのスナップショットは指定したアカウントにシェアすることが可能なので、これを検証環境にリストアすることで本番データを検証環境にクローンしています。

また、Auroraのスナップショットリストアでは新たにクラスタが立ち上がるためエンドポイントも変わってしまうのですが、Route53のVPCローカルDNSを間に挟むことでアプリケーション側の設定変更を不要にしています。

Tips. Lambda FunctionがひとつでもStep Functionsをつかう

状態管理が不要な場合でも、Step Functionsを使うメリットはあります。
実行履歴がマネジメントコンソールから確認でき、前回と同じパラメータで手動実行、といった操作が容易になります。

おわりに

私がGo x AWSで構築したサービス運用ツールは今日も元気に稼働してくれています。

GoはPythonなどスクリプト言語と比べると記述が冗長になってしまいますが、冗長さ故の処理の追いやすさはきっと数カ月後のあなたを助けるはずです。
また、不要になったらCloudFormationのStackを削除すればOKという身軽さも嬉しいポイントです。

この発表があなたの業務を楽にする一助になれたなら幸いです。

関連リンク

発表内で言及した記事のリンクです。