Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Design considerations for Container based Go ap...
Search
Kazuki Higashiguchi
May 18, 2019
Technology
11
8.8k
Design considerations for Container based Go application
Go Conference Tokyo 2019 Spring で発表したコンテナベースのGoアプリケーションの設計・実装の実践紹介です。
Kazuki Higashiguchi
May 18, 2019
Tweet
Share
More Decks by Kazuki Higashiguchi
See All by Kazuki Higashiguchi
Design of a Stateful system for Robust Deployment and Observability
hgsgtk
0
1.2k
A guide to joining operational work in your new DevOps team
hgsgtk
1
1.3k
HTTP Tunneling in Go
hgsgtk
0
1.3k
ブラウザ自動操作技術の深層へ、直接触れて学ぶ WebDriver と Chrome DevTools Protocol
hgsgtk
3
6.4k
HTTP Server on random available port in Go
hgsgtk
0
920
Agile Testingを夢見たテスト自動化 〜ATDDへの挑戦から始まる 1年間の試行錯誤〜 / dreaming agile testing at basebank
hgsgtk
14
7.6k
Create Go WebDriver client from scratch
hgsgtk
1
2.1k
PHPでWeb Driver Clientを自作する〜己の手でブラウザ操作自動化を完全理解する方法〜 / phpcon2021
hgsgtk
2
2.4k
振り返りを積み上げて自分たちのプラクティスとして昇華•体得していくための仕組みと考え方 / ScrumFestMikawa2021
hgsgtk
3
2.4k
Other Decks in Technology
See All in Technology
OCI Data Integration技術情報 / ocidi_technical_jp
oracle4engineer
PRO
1
2.6k
データの信頼性を支える仕組みと技術
chanyou0311
6
1.6k
RAGのためのビジネス文書解析技術
eida
3
660
SREによる隣接領域への越境とその先の信頼性
shonansurvivors
1
400
[FOSS4G 2024 Japan LT] LLMを使ってGISデータ解析を自動化したい!
nssv
1
170
フルカイテン株式会社 採用資料
fullkaiten
0
40k
SREの前に
nwiizo
11
2.7k
サイバーセキュリティと認知バイアス:対策の隙を埋める心理学的アプローチ
shumei_ito
0
170
福岡新卒エンジニアの会
teba_eleven
1
190
利きプロセススケジューラ
sat
PRO
4
2.6k
ジョブマッチングサービスにおける相互推薦システムの応用事例と課題
hakubishin3
3
620
freeeのモバイルエンジニアについて
freee
1
100
Featured
See All Featured
Bash Introduction
62gerente
608
210k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
15
2k
Scaling GitHub
holman
458
140k
GitHub's CSS Performance
jonrohan
1030
460k
How to Think Like a Performance Engineer
csswizardry
20
1.1k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
42
2.2k
Documentation Writing (for coders)
carmenintech
65
4.4k
VelocityConf: Rendering Performance Case Studies
addyosmani
325
24k
The Cult of Friendly URLs
andyhume
78
6k
No one is an island. Learnings from fostering a developers community.
thoeni
19
3k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
Visualization
eitanlees
145
15k
Transcript
© - BASE, Inc. Design considerations for Container-based Go application
. . #gocon Go Conference Tokyo Spring - @hgsgtk
© - BASE, Inc. はじめに • このトークスライドは @hgsgtk より #gocon
にシェ アしています • 時間内に含めれなかった内容を “Extra Talk” として 盛り込んでいます
© - BASE, Inc. このトークに⾄るまでの背景 • 舞台は新サービスの開発現場 • Go⾔語でのAPI開発をやっていく •
Dockerコンテナベースで動かす • 本番環境での Go‧Dockerは初めての試み • 試⾏錯誤の末、昨年12⽉本番リリース
© - BASE, Inc. 現場での実践での試⾏錯誤にて... コンテナだとこれまでと何が違う? 何を意識したらいい?
© - BASE, Inc. 現場での実践での試⾏錯誤にて... 実際に雰囲気でGoの実装までやった けどこれでいいのか? みんなどうしてるの‧‧‧。
© - BASE, Inc. このトークで持ち帰ってほしいもの コンテナを使う場合に意識した設計考慮点 設計⽅針を得る拠り所となるガイドライン 設計⽅針に具体的なGoでの設計‧実装事例
© - BASE, Inc. これからトークする⼈ 東⼝和暉 (Kazuki Higashiguchi) Twitter /
GitHub : @hgsgtk バックエンドエンジニア BASE BANK, Inc. / Dev Division Go歴: - 趣味:2017.7〜 - 仕事:2018.6〜
© - BASE, Inc. トークの舞台:BASE BANKとは 銀⾏をかんたんにし、全ての⼈が挑戦できる世の中に MISSION https://thebase.in/yellbank •
BASE, Inc の100%⼦会社 • 即座に資⾦調達ができる⾦融サービ ス「YELL BANK(エールバンク)」 を運営 • GoでAPIを開発し、Dockerコンテ ナで動かす • ECS/Fargateで運⽤
© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 •
Configuration • Logging • Monitoring • まとめ
© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 •
Configuration • Logging • Monitoring • まとめ
© - BASE, Inc. 事例の全体構成:トーク内での登場⼈物
© - BASE, Inc. 事例の全体構成:トーク内での登場⼈物 今回の主⼈公たち
© - BASE, Inc. コンテナを使う上で最初に持った設計の考慮点 設定情報 どうする? ログ どうやる? 動いてるか
どう監視する?
© - BASE, Inc. 考慮点を設計に落とし込むために • 世の中で語られているベストプラクティスを探す • コンテナベースアプリケーション設計に関する、2つ のガイドラインを参考にした
© - BASE, Inc. ガイドライン1:”Beyond the Twelve-Factor App” • Pivotal社が公開しているガイド
ライン • Beyond “The Twelve-Factor App” • https:// factor.net/ • Herokuの中の⼈が書いたクラ ウドアプリケーションのベスト プラクティス • Original + New = の原則 https://content.pivotal.io/blog/beyond-the-twelve- factor-app
© - BASE, Inc. ガイドライン2:”Red Hat White Paper - コンテナベー
ス‧アプリケーションの設計原則” • Red Hat社が公開しているホワイ トペーパー • コンテナベースアプリケーション の設計について、 7 個の原則につ いてまとめられている • “The Twelve-Factor App” など からヒントを得ている https://www.redhat.com/ja/resources/cloud- native-container-design-whitepaper
© - BASE, Inc. ガイドラインの使い⽅ • ベストプラクティスの⼀つとして参考に する • トピックに関連する原則を参照する
• 2つのガイドラインから設計⽅針を⾒出 す
© - BASE, Inc. ガイドラインと共に設計⽅針を⾒出す 設定情報 どうする? ログ どうやる? 動いてるか
どう監視する? Guideline
© - BASE, Inc. ガイドラインと共に設計⽅針を⾒出す 設定情報 どうする? ログ どうやる? 動いてるか
どう監視する? Guideline Configuration Logging Monitoring
© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 •
Configuration • Logging • Monitoring • まとめ
© - BASE, Inc. 実装に⾄るまでの思考過程
© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 •
Configuration • Logging • Monitoring • まとめ
© - BASE, Inc. Configuration: 設定情報の特性 • 環境ごとに異なる • ex.
本番/検証/QA • 秘匿情報を含む • ex. DB,Redis等の認証情報 • 規模に応じて情報が多くなる • ex. DB,Redisの(Master/Replica),HTTP Port
© - BASE, Inc. Configuration: 設計⽅針と実装
© - BASE, Inc. Configuration: 満たしたい要求 • 階層的管理 • 多くなる設定情報を階層的に整理したい
• 秘匿情報の管理 • パスワードなどの秘匿情報を必要以上に参照可能に したくない
© - BASE, Inc. Configuration: 関連するガイドライン • “ . CONFIGURATION,
CREDENTIALS, AND CODE” in Beyond the Twelve-Factor App • “イメージ不変性の原則” in コンテナベース‧アプリ ケーションの設計原則(Red Hat)
© - BASE, Inc. 概要:“05. CONFIGURATION, CREDENTIALS, AND CODE” •
設定情報はコードから取り除く • = Version Control Systemに含めない • “Treat Your Apps Like Open Source” • 設定を分離する⼀番の⽅法は環境変数への格納 • デプロイごとに変更可能 • ⾔語‧OSに依存しない
© - BASE, Inc. 概要:“イメージ不変性の原則” • コンテナ化アプリケーションは不変 • ビルドされた後、異なる環境間で変化することは想 定されていない
• “ランタイムデータ”の保存は外部⼿段を利⽤する • 設定情報はビルド時ではなく実⾏時に必要なデータ • コンテナ外に保存するべき。 • 外部化した設定を環境によって使い分ける
© - BASE, Inc. Extra Talk: アプリケーション構成要素と設定情報 • アプリケーション構成要 素は次の通り
• Runtime Engine • Code • Dependencies • Configuration • Configurationはコンテナ 起動時に注⼊されるのが 望ましい
© - BASE, Inc. Configuration: 設計⽅針と実装
© - BASE, Inc. Configuration: 設計⽅針 設定情報を外部化する 環境変数を利⽤する 階層管理ができ、秘匿情報を取り扱える 外部⼿段を利⽤する
© - BASE, Inc. Configuration: 設計⽅針と実装
© - BASE, Inc. Configuration: 設計⽅針に対する実装 設定情報を外部化する 環境変数を利⽤する 階層管理ができ、秘匿情報を取り扱える 外部⼿段を利⽤する
© - BASE, Inc. Configuration: 環境変数を⽤いる実装 • 設定情報を扱う config パッケージを作成
• API起動時に環境変数から設定情報を取得 • 設定情報を保持する構造体へParse • github.com/caarlos /env を⽤いる
© - BASE, Inc. 設定情報を扱う config パッケージを作成 package config import
( "github.com/caarlos0/env/v5" "github.com/pkg/errors" ) func NewConfig() (Config, error) { c := Config{} if err := env.Parse(&c); err != nil { return Config{}, errors.Wrap(err, "failed to parse master configuration from environment variable") } return c, nil }
© - BASE, Inc. API起動時に環境変数から設定情報を取得 package main func main() {
// Get config conf, err := config.NewConfig() if err != nil { logger.Logger().Error("failed to create configuration.", zap.Error(err)) os.Exit(1) } // Ҏ߱ͷॲཧ }
© - BASE, Inc. 設定情報を保持する構造体 type Config struct { MasterDB
MasterDBConfig ReplicaDB ReplicaDBConfig HTTP HTTPConfig Redis RedisConfig } type MasterDBConfig struct { Host string `env:"MASTER_DB_HOST,required"` Name string `env:"MASTER_DB_NAME,required"` User string `env:"MASTER_DB_USER,required"` Password string `env:"MASTER_DB_PASSWORD,required"` Port int `env:"MASTER_DB_PORT,required"` SQLMode string `env:"MASTER_DB_SQL_MODE,required"` }
© - BASE, Inc. 設定情報を保持する構造体 type Config struct { MasterDB
MasterDBConfig ReplicaDB ReplicaDBConfig HTTP HTTPConfig Redis RedisConfig } type MasterDBConfig struct { Host string `env:"MASTER_DB_HOST,required"` Name string `env:"MASTER_DB_NAME,required"` User string `env:"MASTER_DB_USER,required"` Password string `env:"MASTER_DB_PASSWORD,required"` Port int `env:"MASTER_DB_PORT,required"` SQLMode string `env:"MASTER_DB_SQL_MODE,required"` } Struct tag: `env` に対応する環境変数のキーを設定 required を設定すると未設定の場合にParse errorを出すことができる
© - BASE, Inc. caarlos /env での構造体へのParse package config import
( "github.com/caarlos0/env/v5" "github.com/pkg/errors" ) func NewConfig() (Config, error) { c := Config{} if err := env.Parse(&c); err != nil { return Config{}, errors.Wrap(err, "failed to parse master configuration from environment variable") } return c, nil }
© - BASE, Inc. config パッケージ全体 package config import (
"github.com/caarlos0/env/v5" "github.com/pkg/errors" ) func NewConfig() (Config, error) { c := Config{} if err := env.Parse(&c); err != nil { return Config{}, errors.Wrap(err, "failed to parse master configuration from environment variable") } return c, nil } type Config struct { MasterDB MasterDBConfig ReplicaDB ReplicaDBConfig HTTP HTTPConfig Redis RedisConfig } type MasterDBConfig struct { Host string `env:"MASTER_DB_HOST,required"` Name string `env:"MASTER_DB_NAME,required"` User string `env:"MASTER_DB_USER,required"` Password string `env:"MASTER_DB_PASSWORD,required"` Port int `env:"MASTER_DB_PORT,required"` SQLMode string `env:"MASTER_DB_SQL_MODE,required"` } // MasterDBConfig Ҏ֎ͷͷઃఆใͷstruct͕ଓ͘
© - BASE, Inc. Extra Talk: 環境変数を⽤いるコードのユニットテスト • 環境変数を使うコードはテストしにくい •
なるべく使⽤箇所を制限したほうがいい • 環境変数を使⽤する関数のテストコードでは、テスト 実⾏前の状態に戻しておく必要がある • See also: テストしやすいGoコードのデザイン by deeeet さん
© - BASE, Inc. Extra Talk: configパッケージのユニットテスト func TestNewConfig(t *testing.T)
{ inputEnvs := map[string]string{ "MASTER_DB_HOST": "test_db_host", "MASTER_DB_NAME": "test_db_name", "MASTER_DB_USER": "test_db_user", "MASTER_DB_PORT": "3306", "MASTER_DB_PASSWORD": "test_db_password", "MASTER_DB_SQL_MODE": "TEST_SQL_MODE", } restore := setEnvs(inputEnvs) defer restore() // ଓ͘ } テスト⽤に設定したい環境変数のkey-valueを map[string]string型で定義
© - BASE, Inc. Extra Talk: configパッケージのユニットテスト func TestNewConfig(t *testing.T)
{ inputEnvs := map[string]string{ "MASTER_DB_HOST": "test_db_host", "MASTER_DB_NAME": "test_db_name", "MASTER_DB_USER": "test_db_user", "MASTER_DB_PORT": "3306", "MASTER_DB_PASSWORD": "test_db_password", "MASTER_DB_SQL_MODE": "TEST_SQL_MODE", } restore := setEnvs(inputEnvs) defer restore() // ଓ͘ } 環境変数を設定するテストヘルパーを実⾏ 戻り値で返ってくる関数を defer 実⾏して状態を戻す
© - BASE, Inc. package config_test func setEnvs(envs map[string]string) func()
{ prevs := map[string]string{} for k, v := range envs { prev := os.Getenv(k) prevs[k] = prev os.Setenv(k, v) } return func() { for k, v := range prevs { os.Setenv(k, v) } } } Extra Talk: 環境変数を設定するテストヘルパー
© - BASE, Inc. Extra Talk: configパッケージのユニットテスト全体 func TestNewConfig(t *testing.T)
{ inputEnvs := map[string]string{ "MASTER_DB_HOST": "test_db_host", "MASTER_DB_NAME": "test_db_name", "MASTER_DB_USER": "test_db_user", "MASTER_DB_PORT": "3306", "MASTER_DB_PASSWORD": "test_db_password", "MASTER_DB_SQL_MODE": "TEST_SQL_MODE", } restore := setEnvs(inputEnvs) defer restore() got, err := config.NewConfig() if err != nil { t.Fatalf("config.NewConfig got unexpected error %#v", err) } want := config.Config{ MasterDB: config.MasterDBConfig{ User: "test_db_user", Password: "test_db_password", Host: "test_db_host", Name: "test_db_name", Port: 3306, SQLMode: "TEST_SQL_MODE", }, } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("NewConfig() got differs: (-got +want)\n%s", diff) } }
© - BASE, Inc. Configuration: 設計⽅針に対する実装 設定情報を外部化する 環境変数を利⽤する 階層管理ができ、秘匿情報を取り扱える 外部⼿段を利⽤する
© - BASE, Inc. 設定外部化のキーマン
© - BASE, Inc. ECS/FargateでParameter Storeを利⽤する事例 • Parameter Storeに設定情報を保存 する
• Key Management Store による暗 号キーで暗号化 • コンテナ起動時に設定情報を取得 • See also: • ECS(Fargate)でコンテナアプリ ケーションを動かすための設定情 報の扱い⽅ - BASE Developer’s Blog
© - BASE, Inc. (振り返り)設計⽅針と実装:Configuration • 設定情報を外部に保存、環境変数を利⽤する⽅式にし た • 本番/検証/QAと異なる環境に同じコンテナイメージ
を利⽤できる • 外部化しコードから分離することで、情報閲覧権限を 絞ることができた
© - BASE, Inc. (振り返り)ガイドラインと共に設計⽅針を⾒出す 設定情報 どうする? ログ どうやる? 動いてるか
どう監視する? Guideline Configuration Logging Monitoring
© - BASE, Inc. (CM)トークの舞台:BASEとは ネットショップ作成サービス 「BASE」 ショッピングアプリ 「BASE」 価値の交換をよりシンプルにし、
世界中の⼈々が最適な経済活動を⾏えるようにする。 MISSION
© - BASE, Inc.
© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 •
Configuration • Logging • Monitoring • まとめ
© - BASE, Inc. Logging: 設計⽅針と実装
© - BASE, Inc. Logging: 満たしたい要求 • リアルタイムでの参照がしたい • 「今何が起こっているのか」を知る情報
• トラブルシューティング‧デバッグ • 可⽤性、ログの⽋損を避けたい • 検索しやすさ • 問題の原因調査のための検索しやすさ
© - BASE, Inc. Logging: 関連するガイドライン • “ . LOGS”
in Beyond the Twelve-Factor App • “⾼観測可能性の原則” in コンテナベース‧アプリ ケーションの設計原則(Red Hat)
© - BASE, Inc. 概要:“06. LOGS” • ログをイベントストリームとして扱う • ファイルシステムに依存しない
• 全てのログは、STDOUT/STDERRに書き出す • ログの集約‧分析は、ElasticSearch‧Logstash‧ Kibanaといったツールを活⽤する
© - BASE, Inc. 概要:“⾼観測可能性の原則” • コンテナを “ブラックボックス” として扱う •
重要なイベントを STDOUT/STDERR に記録し、 Fluentdなどツールを活⽤してログ集約をする • 活動状況や準備状況など、様々な状態チェックに対 してAPIを提供する
© - BASE, Inc. 加えて参考になる書籍『⼊⾨ 監視』 • “⼊⾨ 監視—モダンなモニ タリングのためのデザイ
ンパターン” • 著: Mike Julian / 訳: 松浦 隼⼈ https://www.oreilly.co.jp/books/ /
© - BASE, Inc. 構造化ログを使う • ログをJSON等で構造化するメリット • キー‧値のペアの集合になる •
意味を理解しやすくなる • 情報を抽出できるようになる • See also: • 書籍『⼊⾨監視』 - 7.4 アプリケーションロギング
© - BASE, Inc. Logging: 設計⽅針と実装
© - BASE, Inc. Logging: 設計⽅針 ログを構造化する STDOUT/STDERRに書き出す ツールを活⽤したログの集約‧分析
© - BASE, Inc. Logging: 設計⽅針と実装
© - BASE, Inc. Logging: 設計⽅針 ログを構造化する STDOUT/STDERRに書き出す ツールを活⽤したログの集約‧分析
© - BASE, Inc. Logging: STDOUT/STDERRに構造化ログを書き出す例 • ログ書き出しを扱う logger パッケージを作成
• STDOUT にログを書き出す • ログの内容は JSON 形式で構造化する • ログライブラリに github.com/uber-go/zap を⽤い る。
© - BASE, Inc. ログを扱うlogger パッケージ package logger // Writer
specifies output of logger. var Writer zapcore.WriteSyncer = os.Stdout // Init replace global zap logger to custom logger. func Init(output zapcore.WriteSyncer) { logger := newLogger(output) zap.ReplaceGlobals(logger) } // Logger return logger instance. func Logger() *zap.Logger { return zap.L() }
© - BASE, Inc. STDOUTにログを書き出す package logger // Writer specifies
output of logger. var Writer zapcore.WriteSyncer = os.Stdout // Init replace global zap logger to custom logger. func Init(output zapcore.WriteSyncer) { logger := newLogger(output) zap.ReplaceGlobals(logger) } // Logger return logger instance. func Logger() *zap.Logger { return zap.L() } ログの書き出し先に os.Stdout を指定
© - BASE, Inc. STDOUTにログを書き出す package logger // Writer specifies
output of logger. var Writer zapcore.WriteSyncer = os.Stdout // Init replace global zap logger to custom logger. func Init(output zapcore.WriteSyncer) { logger := newLogger(output) zap.ReplaceGlobals(logger) } // Logger return logger instance. func Logger() *zap.Logger { return zap.L() } 起動時に main関数から呼び出す。 zap.ReplaceGlobals() によってカスタムロガーに差し替える
© - BASE, Inc. カスタムロガーを⽤意する package logger func newLogger(writer zapcore.WriteSyncer)
*zap.Logger { atom := zap.NewAtomicLevel() encoderCfg := zap.NewProductionEncoderConfig() encoderCfg.EncodeTime = zapcore.ISO8601TimeEncoder bl := zap.New(zapcore.NewCore( zapcore.NewJSONEncoder(encoderCfg), zapcore.Lock(writer), atom, )) l := bl.With(zap.String("out", "stdout")) return l }
© - BASE, Inc. STDOUTにログを書き出す package logger // Writer specifies
output of logger. var Writer zapcore.WriteSyncer = os.Stdout // Init replace global zap logger to custom logger. func Init(output zapcore.WriteSyncer) { logger := newLogger(output) zap.ReplaceGlobals(logger) } // Logger return logger instance. func Logger() *zap.Logger { return zap.L() } ログ書き出しのタイミングで、 zapのグローバルロガーを取得する
© - BASE, Inc. ログを実際に書き出す package main func main() {
// Get config conf, err := config.NewConfig() if err != nil { logger.Logger().Error("failed to create configuration.", zap.Error(err)) os.Exit(1) } // Ҏ߱ͷॲཧ } logger.Logger() からロガーを取り出し利⽤する
© - BASE, Inc. Logging: 設計⽅針 ログを構造化する STDOUT/STDERRに書き出す ツールを活⽤したログの集約‧分析
© - BASE, Inc. ログの集約‧分析のキーマン
© - BASE, Inc. Extra Talk: ECS/FargateからKibanaでログ可視化 • Fargate ->
CloudWatchLogs -> S -> ElasticSearch & Kibana の流れ • See also • AWS Fargateで動いているプログラムのログをElasticsearch/ Kibanaで可視化 by @tomy rider
© - BASE, Inc. (振り返り)設計⽅針と実装:Logging • uber-go/zap を利⽤して STDOUT に
JSON形式でロ グを書き出す • ファイルシステムに依存しないのでコンテナの破棄容 易性が⾼まった • 構造化することによる抽出のしやすさ • CloudWatchLogsに流れてくるログを awslogs‧jq コマンドを組み合わせて抽出する
© - BASE, Inc. (振り返り)ガイドラインと共に設計⽅針を⾒出す 設定情報 どうする? ログ どうやる? 動いてるか
どう監視する? Guideline Configuration Logging Monitoring
© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 •
Configuration • Logging • Monitoring • まとめ
© - BASE, Inc. Monitoring: 設計⽅針と実装
© - BASE, Inc. Monitoring: 満たしたい要求 • 健康状態をチェックしたい • アプリケーションの健康状態のモニタリング
• メトリクスの継続的な取得 • メトリクスをとって状態をWatchしておきたい
© - BASE, Inc. Monitoring: 関連するガイドライン • “⾼観測可能性の原則” in コンテナベース‧アプリ
ケーションの設計原則(Red Hat)
© - BASE, Inc. (振り返り)概要:“⾼観測可能性の原則” • コンテナを “ブラックボックス” として扱う •
重要なイベントを STDOUT/STDERR に記録し、 Fluentdなどツールを活⽤してログ集約をする • 活動状況や準備状況など、様々な状態チェックに対 してAPIを提供する
© - BASE, Inc. Monitoring: 設計⽅針と実装
© - BASE, Inc. Monitoring: 設計⽅針 依存サービスの利⽤状況も確認する 健康状態を伝えるAPIの提供 コンテナ内のメトリクス取得
© - BASE, Inc. Monitoring: 設計⽅針と実装
© - BASE, Inc. Monitoring: 設計⽅針 依存サービスの利⽤状況も確認する 健康状態を伝えるAPIの提供 コンテナ内のメトリクス取得
© - BASE, Inc. Monitoring: 健康状態を伝えるエンドポイントの実装 • ヘルスチェックを⾏うエンドポイントを作成する • “Health
endpoint pattern” in 『⼊⾨ 監視』 • 依存サービスとの接続状態もエンドポイントで確認す る • ex. 依存サービス DB‧Redis etc
© - BASE, Inc. ヘルスチェックを⾏うエンドポイントを作成する func (c *Handler) Check(w http.ResponseWriter,
r *http.Request) { w.WriteHeader(http.StatusOK) }
© - BASE, Inc. 依存サービスとの接続状態もエンドポイントで確認する func (c *Handler) DeepCheck(w http.ResponseWriter,
r *http.Request) { if err := c.masterDB.Ping(); err != nil { res := ErrResponse{ Message: fmt.Sprintf("failed to ping master datatabase because of error: %s", err.Error()), Status: http.StatusServiceUnavailable, } respondJSON(w, res) return } if err := c.redis.Ping().Err(); err != nil { res := ErrResponse{ Message: fmt.Sprintf("failed to ping redis server because of error: %s", err.Error()), Status: http.StatusServiceUnavailable, } respondJSON(w, res) } w.WriteHeader(http.StatusOK) }
© - BASE, Inc. Extra Talk: Monitoring: 設計⽅針 依存サービスの利⽤状況も確認する 健康状態を伝えるAPIの提供
コンテナ内のメトリクス取得
© - BASE, Inc. Extra Talk: Mackerel Container Agentでのコンテナ内 監視
• Mackerel Container Agent を利⽤したコンテナ監 視 • https://mackerel.io/ja/docs/entry/howto/container-agent • コンテナ内部のCPU, Memory, Networkなどを監視 できる • アプリケーションコンテナのサイドカーとして起動
© - BASE, Inc. (振り返り)設計⽅針と実装:Monitoring • ヘルスチェックを⾏うエンドポイントを作成した • ALBやMackerelからの外形監視に利⽤できた •
起動したかどうかのデバッグにも使える
© - BASE, Inc. (振り返り)ガイドラインと共に設計⽅針を⾒出す 設定情報 どうする? ログ どうやる? 動いてるか
どう監視する? Guideline Configuration Logging Monitoring
© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 •
Configuration • Logging • Monitoring • まとめ
© - BASE, Inc. まとめ • コンテナアプリケーションの設計ベストプラクティス から設計⽅針を⾒出した • 設計⽅針から実践したGoでの実装事例を紹介した
• 現場によって様々な設計‧実装判断があるが、⼀つの 参考事例として参考になれば嬉しい
End role
© - BASE, Inc. End role: 関連アウトプット • Container based
application Design Real Practices - #dockertokyo • https://speakerdeck.com/hgsgtk/container-based-application-design-real- practices • Container-based Application Design Reference and Practice - #dockertokyo • https://speakerdeck.com/hgsgtk/container-based-application-design- reference-and-practice-number-dockertokyo
© - BASE, Inc. End role: 関連アウトプット • ECS(Fargate)でコンテナアプリケーションを動かすための設定情報の扱 い⽅
- BASE Developer’s Blog • https://devblog.thebase.in/entry/ / / / • アプリケーション監視のパターン「Health エンドポイントパターン」を 実践する - BASE Developer’s Blog • https://devblog.thebase.in/entry/ / / /
© - BASE, Inc. End role: 関連アウトプット • AWS Fargateで動いているプログラムのログをElasticsearch/Kibanaで
可視化 by @tomy rider • https://qiita.com/tomy rider/items/ aa dd • CircleCIとecspressoによるECSへのデプロイメントパイプライン by @fumikony • https://devblog.thebase.in/entry/ / / /
© - BASE, Inc. End role: 参考書籍 • 『⼊⾨ 監視
モダンなモニタリングのためのデザインパターン • https://www.oreilly.co.jp/books/ / • 『分散システムデザインパターン コンテナを使ったスケーラブルな サービスの設計』 • https://www.oreilly.co.jp/books/ /
© - BASE, Inc. End role: 設計時参考URL • Beyond the
Twelve-Factor App • https://content.pivotal.io/blog/beyond-the-twelve-factor-app • Red Hat White paper - コンテナベース‧アプリケーションの設計原則 • https://www.redhat.com/ja/resources/cloud-native-container-design- whitepaper (⽇本語版) • https://www.redhat.com/en/resources/cloud-native-container-design- whitepaper (English Edition) • AWS Cloud Design Patterns • http://en.clouddesignpattern.org/index.php/Main_Page
© - BASE, Inc. End role: 実装時参考URL • テストしやすいGoコードのデザイン by
deeeet さん • https://go-talks.appspot.com/github.com/tcnksm/talks/ / /golang- tokyo/golang-tokyo.slide# • コンテナを監視する by Mackerel • https://mackerel.io/ja/docs/entry/howto/container-agent
Any Question or Suggestion?