Slide 1

Slide 1 text

© - BASE, Inc. Design considerations for Container-based Go application . . #gocon Go Conference Tokyo Spring - @hgsgtk

Slide 2

Slide 2 text

© - BASE, Inc. はじめに • このトークスライドは @hgsgtk より #gocon にシェ アしています • 時間内に含めれなかった内容を “Extra Talk” として 盛り込んでいます

Slide 3

Slide 3 text

© - BASE, Inc. このトークに⾄るまでの背景 • 舞台は新サービスの開発現場 • Go⾔語でのAPI開発をやっていく • Dockerコンテナベースで動かす • 本番環境での Go‧Dockerは初めての試み • 試⾏錯誤の末、昨年12⽉本番リリース

Slide 4

Slide 4 text

© - BASE, Inc. 現場での実践での試⾏錯誤にて... コンテナだとこれまでと何が違う? 何を意識したらいい?

Slide 5

Slide 5 text

© - BASE, Inc. 現場での実践での試⾏錯誤にて... 実際に雰囲気でGoの実装までやった けどこれでいいのか? みんなどうしてるの‧‧‧。

Slide 6

Slide 6 text

© - BASE, Inc. このトークで持ち帰ってほしいもの コンテナを使う場合に意識した設計考慮点 設計⽅針を得る拠り所となるガイドライン 設計⽅針に具体的なGoでの設計‧実装事例

Slide 7

Slide 7 text

© - BASE, Inc. これからトークする⼈ 東⼝和暉 (Kazuki Higashiguchi) Twitter / GitHub : @hgsgtk バックエンドエンジニア BASE BANK, Inc. / Dev Division Go歴: - 趣味:2017.7〜 - 仕事:2018.6〜

Slide 8

Slide 8 text

© - BASE, Inc. トークの舞台:BASE BANKとは 銀⾏をかんたんにし、全ての⼈が挑戦できる世の中に MISSION https://thebase.in/yellbank • BASE, Inc の100%⼦会社 • 即座に資⾦調達ができる⾦融サービ ス「YELL BANK(エールバンク)」 を運営 • GoでAPIを開発し、Dockerコンテ ナで動かす • ECS/Fargateで運⽤

Slide 9

Slide 9 text

© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 • Configuration • Logging • Monitoring • まとめ

Slide 10

Slide 10 text

© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 • Configuration • Logging • Monitoring • まとめ

Slide 11

Slide 11 text

© - BASE, Inc. 事例の全体構成:トーク内での登場⼈物

Slide 12

Slide 12 text

© - BASE, Inc. 事例の全体構成:トーク内での登場⼈物 今回の主⼈公たち

Slide 13

Slide 13 text

© - BASE, Inc. コンテナを使う上で最初に持った設計の考慮点 設定情報 どうする? ログ どうやる? 動いてるか どう監視する?

Slide 14

Slide 14 text

© - BASE, Inc. 考慮点を設計に落とし込むために • 世の中で語られているベストプラクティスを探す • コンテナベースアプリケーション設計に関する、2つ のガイドラインを参考にした

Slide 15

Slide 15 text

© - 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

Slide 16

Slide 16 text

© - 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

Slide 17

Slide 17 text

© - BASE, Inc. ガイドラインの使い⽅ • ベストプラクティスの⼀つとして参考に する • トピックに関連する原則を参照する • 2つのガイドラインから設計⽅針を⾒出 す

Slide 18

Slide 18 text

© - BASE, Inc. ガイドラインと共に設計⽅針を⾒出す 設定情報 どうする? ログ どうやる? 動いてるか どう監視する? Guideline

Slide 19

Slide 19 text

© - BASE, Inc. ガイドラインと共に設計⽅針を⾒出す 設定情報 どうする? ログ どうやる? 動いてるか どう監視する? Guideline Configuration Logging Monitoring

Slide 20

Slide 20 text

© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 • Configuration • Logging • Monitoring • まとめ

Slide 21

Slide 21 text

© - BASE, Inc. 実装に⾄るまでの思考過程

Slide 22

Slide 22 text

© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 • Configuration • Logging • Monitoring • まとめ

Slide 23

Slide 23 text

© - BASE, Inc. Configuration: 設定情報の特性 • 環境ごとに異なる • ex. 本番/検証/QA • 秘匿情報を含む • ex. DB,Redis等の認証情報 • 規模に応じて情報が多くなる • ex. DB,Redisの(Master/Replica),HTTP Port

Slide 24

Slide 24 text

© - BASE, Inc. Configuration: 設計⽅針と実装

Slide 25

Slide 25 text

© - BASE, Inc. Configuration: 満たしたい要求 • 階層的管理 • 多くなる設定情報を階層的に整理したい • 秘匿情報の管理 • パスワードなどの秘匿情報を必要以上に参照可能に したくない

Slide 26

Slide 26 text

© - BASE, Inc. Configuration: 関連するガイドライン • “ . CONFIGURATION, CREDENTIALS, AND CODE” in Beyond the Twelve-Factor App • “イメージ不変性の原則” in コンテナベース‧アプリ ケーションの設計原則(Red Hat)

Slide 27

Slide 27 text

© - BASE, Inc. 概要:“05. CONFIGURATION, CREDENTIALS, AND CODE” • 設定情報はコードから取り除く • = Version Control Systemに含めない • “Treat Your Apps Like Open Source” • 設定を分離する⼀番の⽅法は環境変数への格納 • デプロイごとに変更可能 • ⾔語‧OSに依存しない

Slide 28

Slide 28 text

© - BASE, Inc. 概要:“イメージ不変性の原則” • コンテナ化アプリケーションは不変 • ビルドされた後、異なる環境間で変化することは想 定されていない • “ランタイムデータ”の保存は外部⼿段を利⽤する • 設定情報はビルド時ではなく実⾏時に必要なデータ • コンテナ外に保存するべき。 • 外部化した設定を環境によって使い分ける

Slide 29

Slide 29 text

© - BASE, Inc. Extra Talk: アプリケーション構成要素と設定情報 • アプリケーション構成要 素は次の通り • Runtime Engine • Code • Dependencies • Configuration • Configurationはコンテナ 起動時に注⼊されるのが 望ましい

Slide 30

Slide 30 text

© - BASE, Inc. Configuration: 設計⽅針と実装

Slide 31

Slide 31 text

© - BASE, Inc. Configuration: 設計⽅針 設定情報を外部化する 環境変数を利⽤する 階層管理ができ、秘匿情報を取り扱える 外部⼿段を利⽤する

Slide 32

Slide 32 text

© - BASE, Inc. Configuration: 設計⽅針と実装

Slide 33

Slide 33 text

© - BASE, Inc. Configuration: 設計⽅針に対する実装 設定情報を外部化する 環境変数を利⽤する 階層管理ができ、秘匿情報を取り扱える 外部⼿段を利⽤する

Slide 34

Slide 34 text

© - BASE, Inc. Configuration: 環境変数を⽤いる実装 • 設定情報を扱う config パッケージを作成 • API起動時に環境変数から設定情報を取得 • 設定情報を保持する構造体へParse • github.com/caarlos /env を⽤いる

Slide 35

Slide 35 text

© - 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 }

Slide 36

Slide 36 text

© - 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) } // Ҏ߱ͷॲཧ }

Slide 37

Slide 37 text

© - 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"` }

Slide 38

Slide 38 text

© - 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を出すことができる

Slide 39

Slide 39 text

© - 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 }

Slide 40

Slide 40 text

© - 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͕ଓ͘

Slide 41

Slide 41 text

© - BASE, Inc. Extra Talk: 環境変数を⽤いるコードのユニットテスト • 環境変数を使うコードはテストしにくい • なるべく使⽤箇所を制限したほうがいい • 環境変数を使⽤する関数のテストコードでは、テスト 実⾏前の状態に戻しておく必要がある • See also: テストしやすいGoコードのデザイン by deeeet さん

Slide 42

Slide 42 text

© - 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型で定義

Slide 43

Slide 43 text

© - 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 実⾏して状態を戻す

Slide 44

Slide 44 text

© - 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: 環境変数を設定するテストヘルパー

Slide 45

Slide 45 text

© - 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) } }

Slide 46

Slide 46 text

© - BASE, Inc. Configuration: 設計⽅針に対する実装 設定情報を外部化する 環境変数を利⽤する 階層管理ができ、秘匿情報を取り扱える 外部⼿段を利⽤する

Slide 47

Slide 47 text

© - BASE, Inc. 設定外部化のキーマン

Slide 48

Slide 48 text

© - BASE, Inc. ECS/FargateでParameter Storeを利⽤する事例 • Parameter Storeに設定情報を保存 する • Key Management Store による暗 号キーで暗号化 • コンテナ起動時に設定情報を取得 • See also: • ECS(Fargate)でコンテナアプリ ケーションを動かすための設定情 報の扱い⽅ - BASE Developer’s Blog

Slide 49

Slide 49 text

© - BASE, Inc. (振り返り)設計⽅針と実装:Configuration • 設定情報を外部に保存、環境変数を利⽤する⽅式にし た • 本番/検証/QAと異なる環境に同じコンテナイメージ を利⽤できる • 外部化しコードから分離することで、情報閲覧権限を 絞ることができた

Slide 50

Slide 50 text

© - BASE, Inc. (振り返り)ガイドラインと共に設計⽅針を⾒出す 設定情報 どうする? ログ どうやる? 動いてるか どう監視する? Guideline Configuration Logging Monitoring

Slide 51

Slide 51 text

© - BASE, Inc. (CM)トークの舞台:BASEとは ネットショップ作成サービス 「BASE」 ショッピングアプリ 「BASE」 価値の交換をよりシンプルにし、 世界中の⼈々が最適な経済活動を⾏えるようにする。 MISSION

Slide 52

Slide 52 text

© - BASE, Inc.

Slide 53

Slide 53 text

© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 • Configuration • Logging • Monitoring • まとめ

Slide 54

Slide 54 text

© - BASE, Inc. Logging: 設計⽅針と実装

Slide 55

Slide 55 text

© - BASE, Inc. Logging: 満たしたい要求 • リアルタイムでの参照がしたい • 「今何が起こっているのか」を知る情報 • トラブルシューティング‧デバッグ • 可⽤性、ログの⽋損を避けたい • 検索しやすさ • 問題の原因調査のための検索しやすさ

Slide 56

Slide 56 text

© - BASE, Inc. Logging: 関連するガイドライン • “ . LOGS” in Beyond the Twelve-Factor App • “⾼観測可能性の原則” in コンテナベース‧アプリ ケーションの設計原則(Red Hat)

Slide 57

Slide 57 text

© - BASE, Inc. 概要:“06. LOGS” • ログをイベントストリームとして扱う • ファイルシステムに依存しない • 全てのログは、STDOUT/STDERRに書き出す • ログの集約‧分析は、ElasticSearch‧Logstash‧ Kibanaといったツールを活⽤する

Slide 58

Slide 58 text

© - BASE, Inc. 概要:“⾼観測可能性の原則” • コンテナを “ブラックボックス” として扱う • 重要なイベントを STDOUT/STDERR に記録し、 Fluentdなどツールを活⽤してログ集約をする • 活動状況や準備状況など、様々な状態チェックに対 してAPIを提供する

Slide 59

Slide 59 text

© - BASE, Inc. 加えて参考になる書籍『⼊⾨ 監視』 • “⼊⾨ 監視—モダンなモニ タリングのためのデザイ ンパターン” • 著: Mike Julian / 訳: 松浦 隼⼈ https://www.oreilly.co.jp/books/ /

Slide 60

Slide 60 text

© - BASE, Inc. 構造化ログを使う • ログをJSON等で構造化するメリット • キー‧値のペアの集合になる • 意味を理解しやすくなる • 情報を抽出できるようになる • See also: • 書籍『⼊⾨監視』 - 7.4 アプリケーションロギング

Slide 61

Slide 61 text

© - BASE, Inc. Logging: 設計⽅針と実装

Slide 62

Slide 62 text

© - BASE, Inc. Logging: 設計⽅針 ログを構造化する STDOUT/STDERRに書き出す ツールを活⽤したログの集約‧分析

Slide 63

Slide 63 text

© - BASE, Inc. Logging: 設計⽅針と実装

Slide 64

Slide 64 text

© - BASE, Inc. Logging: 設計⽅針 ログを構造化する STDOUT/STDERRに書き出す ツールを活⽤したログの集約‧分析

Slide 65

Slide 65 text

© - BASE, Inc. Logging: STDOUT/STDERRに構造化ログを書き出す例 • ログ書き出しを扱う logger パッケージを作成 • STDOUT にログを書き出す • ログの内容は JSON 形式で構造化する • ログライブラリに github.com/uber-go/zap を⽤い る。

Slide 66

Slide 66 text

© - 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() }

Slide 67

Slide 67 text

© - 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 を指定

Slide 68

Slide 68 text

© - 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() によってカスタムロガーに差し替える

Slide 69

Slide 69 text

© - 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 }

Slide 70

Slide 70 text

© - 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のグローバルロガーを取得する

Slide 71

Slide 71 text

© - 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() からロガーを取り出し利⽤する

Slide 72

Slide 72 text

© - BASE, Inc. Logging: 設計⽅針 ログを構造化する STDOUT/STDERRに書き出す ツールを活⽤したログの集約‧分析

Slide 73

Slide 73 text

© - BASE, Inc. ログの集約‧分析のキーマン

Slide 74

Slide 74 text

© - BASE, Inc. Extra Talk: ECS/FargateからKibanaでログ可視化 • Fargate -> CloudWatchLogs -> S -> ElasticSearch & Kibana の流れ • See also • AWS Fargateで動いているプログラムのログをElasticsearch/ Kibanaで可視化 by @tomy rider

Slide 75

Slide 75 text

© - BASE, Inc. (振り返り)設計⽅針と実装:Logging • uber-go/zap を利⽤して STDOUT に JSON形式でロ グを書き出す • ファイルシステムに依存しないのでコンテナの破棄容 易性が⾼まった • 構造化することによる抽出のしやすさ • CloudWatchLogsに流れてくるログを awslogs‧jq コマンドを組み合わせて抽出する

Slide 76

Slide 76 text

© - BASE, Inc. (振り返り)ガイドラインと共に設計⽅針を⾒出す 設定情報 どうする? ログ どうやる? 動いてるか どう監視する? Guideline Configuration Logging Monitoring

Slide 77

Slide 77 text

© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 • Configuration • Logging • Monitoring • まとめ

Slide 78

Slide 78 text

© - BASE, Inc. Monitoring: 設計⽅針と実装

Slide 79

Slide 79 text

© - BASE, Inc. Monitoring: 満たしたい要求 • 健康状態をチェックしたい • アプリケーションの健康状態のモニタリング • メトリクスの継続的な取得 • メトリクスをとって状態をWatchしておきたい

Slide 80

Slide 80 text

© - BASE, Inc. Monitoring: 関連するガイドライン • “⾼観測可能性の原則” in コンテナベース‧アプリ ケーションの設計原則(Red Hat)

Slide 81

Slide 81 text

© - BASE, Inc. (振り返り)概要:“⾼観測可能性の原則” • コンテナを “ブラックボックス” として扱う • 重要なイベントを STDOUT/STDERR に記録し、 Fluentdなどツールを活⽤してログ集約をする • 活動状況や準備状況など、様々な状態チェックに対 してAPIを提供する

Slide 82

Slide 82 text

© - BASE, Inc. Monitoring: 設計⽅針と実装

Slide 83

Slide 83 text

© - BASE, Inc. Monitoring: 設計⽅針 依存サービスの利⽤状況も確認する 健康状態を伝えるAPIの提供 コンテナ内のメトリクス取得

Slide 84

Slide 84 text

© - BASE, Inc. Monitoring: 設計⽅針と実装

Slide 85

Slide 85 text

© - BASE, Inc. Monitoring: 設計⽅針 依存サービスの利⽤状況も確認する 健康状態を伝えるAPIの提供 コンテナ内のメトリクス取得

Slide 86

Slide 86 text

© - BASE, Inc. Monitoring: 健康状態を伝えるエンドポイントの実装 • ヘルスチェックを⾏うエンドポイントを作成する • “Health endpoint pattern” in 『⼊⾨ 監視』 • 依存サービスとの接続状態もエンドポイントで確認す る • ex. 依存サービス DB‧Redis etc

Slide 87

Slide 87 text

© - BASE, Inc. ヘルスチェックを⾏うエンドポイントを作成する func (c *Handler) Check(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }

Slide 88

Slide 88 text

© - 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) }

Slide 89

Slide 89 text

© - BASE, Inc. Extra Talk: Monitoring: 設計⽅針 依存サービスの利⽤状況も確認する 健康状態を伝えるAPIの提供 コンテナ内のメトリクス取得

Slide 90

Slide 90 text

© - BASE, Inc. Extra Talk: Mackerel Container Agentでのコンテナ内 監視 • Mackerel Container Agent を利⽤したコンテナ監 視 • https://mackerel.io/ja/docs/entry/howto/container-agent • コンテナ内部のCPU, Memory, Networkなどを監視 できる • アプリケーションコンテナのサイドカーとして起動

Slide 91

Slide 91 text

© - BASE, Inc. (振り返り)設計⽅針と実装:Monitoring • ヘルスチェックを⾏うエンドポイントを作成した • ALBやMackerelからの外形監視に利⽤できた • 起動したかどうかのデバッグにも使える

Slide 92

Slide 92 text

© - BASE, Inc. (振り返り)ガイドラインと共に設計⽅針を⾒出す 設定情報 どうする? ログ どうやる? 動いてるか どう監視する? Guideline Configuration Logging Monitoring

Slide 93

Slide 93 text

© - BASE, Inc. トーク構成 • 事例の全体構成と設計考慮点⼀覧 • 設計⽅針と実装 • Configuration • Logging • Monitoring • まとめ

Slide 94

Slide 94 text

© - BASE, Inc. まとめ • コンテナアプリケーションの設計ベストプラクティス から設計⽅針を⾒出した • 設計⽅針から実践したGoでの実装事例を紹介した • 現場によって様々な設計‧実装判断があるが、⼀つの 参考事例として参考になれば嬉しい

Slide 95

Slide 95 text

End role

Slide 96

Slide 96 text

© - 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

Slide 97

Slide 97 text

© - 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/ / / /

Slide 98

Slide 98 text

© - 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/ / / /

Slide 99

Slide 99 text

© - BASE, Inc. End role: 参考書籍 • 『⼊⾨ 監視 モダンなモニタリングのためのデザインパターン • https://www.oreilly.co.jp/books/ / • 『分散システムデザインパターン コンテナを使ったスケーラブルな サービスの設計』 • https://www.oreilly.co.jp/books/ /

Slide 100

Slide 100 text

© - 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

Slide 101

Slide 101 text

© - 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

Slide 102

Slide 102 text

Any Question or Suggestion?