Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Design considerations for Container based Go application

Design considerations for Container based Go application

Go Conference Tokyo 2019 Spring で発表したコンテナベースのGoアプリケーションの設計・実装の実践紹介です。

Kazuki Higashiguchi
PRO

May 18, 2019
Tweet

More Decks by Kazuki Higashiguchi

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  49. © - BASE, Inc.
    (振り返り)設計⽅針と実装:Configuration
    • 設定情報を外部に保存、環境変数を利⽤する⽅式にし

    • 本番/検証/QAと異なる環境に同じコンテナイメージ
    を利⽤できる
    • 外部化しコードから分離することで、情報閲覧権限を
    絞ることができた

    View Slide

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

    View Slide

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

    View Slide

  52. © - BASE, Inc.

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    • ex. 依存サービス DB‧Redis etc

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  90. © - BASE, Inc.
    Extra Talk: Mackerel Container Agentでのコンテナ内
    監視
    • Mackerel Container Agent を利⽤したコンテナ監

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  95. End role

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  102. Any Question or Suggestion?

    View Slide