$30 off During Our Annual Pro Sale. View Details »

GoとKubernetesを用いたバッチ開発のすすめ

To Kawa
April 23, 2022

 GoとKubernetesを用いたバッチ開発のすすめ

Go Conference 2022 Springでの発表資料です
https://gocon.jp/2022spring/ja/sessions/lt5/

To Kawa

April 23, 2022
Tweet

More Decks by To Kawa

Other Decks in Programming

Transcript

  1. GoとKubernetesを用いた
    バッチ開発のすすめ
    @awakot
    Go Conference 2022 Spring

    View Slide

  2. 自己紹介
    Toshiki Kawamura
    株式会社Voicy
    BE→SRE
    Twitter: awakot_56
    Github: awakot

    View Slide

  3. 今日の話題
    1. Go×Kubernetesを用いたバッチ開発方法の概要
    2. 開発運用して感じたメリットとTips

    View Slide

  4. ここでのバッチ処理とは
    任意のタイミングで対象データに対して
    まとめて実施される処理

    ・任意のタイミングで対象ユーザーにメールを送るシステム
    ・月初に定期購読ユーザーを更新するシステム
    ・一定間隔で売上の集計を行うシステム

    View Slide

  5. バッチシステムに関して
    - GoでCLIを作成し、Kubernetes上で実行
    - バッチ処理を実行するCLIツールとしてメインで利用したのは
    spf13/cobraパッケージ
    - https://github.com/spf13/cobra
    - KubernetesやIstioなどでも使用されていて、スター数も2万以上
    - Command構造体に名前などを定義するだけで簡単に実行可能
    - オプションフラグやエイリアスなど、CLIに必要な要素を簡単に設定するこ
    とができる

    View Slide

  6. CLIを作る

    View Slide

  7. まずはサブコマンドを定義

    View Slide

  8. サブコマンドを定義
    type hogehogeOptions struct {
    Notice bool
    Dryrun bool
    }
    func (opt *hogehogeOptions) Run(ctx context.Context, w io.Writer) error {
    //ここに必要な処理を書く
    return nil
    }
    func HogeCommand(ctx context.Context) *cobra.Command {
    opt := &hogehogeOptions
    {}
    cmd := &cobra.Command{
    Use: “hoge”,
    Short: “
    処理の説明“,
    Run: func(cmd *cobra.Command, args []
    string) {
    if err := opt.Run(ctx, cmd.OutOrStdout()); err != nil {
    panic(err)
    }
    },
    }
    cmd.Flags().BoolVarP(&opt.Notice, “notice”, “”, opt.Notice, “notice”)
    cmd.Flags().BoolVarP(&opt.Dryrun, “dryrun”, “”, opt.Dryrun, “dryrun”)
    return cmd

    View Slide

  9. ルートコマンドにサブコマンドを追加していく
    ctx := context.Background()
    rootCmd := &cobra.Command{Use: “batch”}
    rootCmd.AddCommand(subcmd.HogeCommand(ctx))
    rootCmd.AddCommand(subcmd.FooCommand(ctx))

    View Slide

  10. Kubernetesでバッチを実行する

    View Slide

  11. CronJobの定義例(一部)
    apiVersion: batch/v1beta1
    kind: CronJob
    metadata:
    name: name
    namespace: namespace
    spec:
    schedule: “00 18 * * * ”
    concurrencyPolicy: Forbid
    jobTemplate:
    spec:
    template:
    spec:
    containers:
    - name: hogehoge
    image:
    args:
    - /app/batch
    - hoge
    restartPolicy: Never
    #以下環境変数など

    View Slide

  12. Go×Kubernetesでバッチ開発をしてみて
    - 他アプリケーションと同じくKubernetes上で管理や監視できる
    - JobやCronJobの実行をYAMLで管理できる
    - アプリケーションと同じ言語で書け、共通処理はそのまま利用できるので開発効率が上がる
    - ゴルーチンを用いた並行処理の導入で実行時間を短縮

    View Slide

  13. バッチ開発のTips

    View Slide

  14. リトライや冪等性を担保する仕組みを導入する
    バッチ処理が時に失敗する可能性があり、そういった場合に備えてシステム内にリトライの仕
    組みや、リトライ時に備えた処理の冪等性が担保される仕組みを導入しておくと、バッチ処理
    が仮に失敗しても簡単にリカバリが効くようになる
    また、KubernetesのCronJobにおいては以下のようなコマンドを実行することでCronJobから
    即時実行されるJobを生成することが可能
    kubectl create job job-name
    --from=cronjob/cronjob-name -n namespace

    View Slide

  15. 1つのバッチの責務を小さくする
    例えば大量のデータを一気に処理する場合には、1つのバッチの処理する量を減らし、段階
    に分けた処理の実行や分割など、一つのバッチ毎の責務を小さくすることでリトライ設計や失
    敗時のリカバリがしやすく管理のしやすいものになる

    View Slide

  16. ゴルーチンをうまく利用する
    バッチ処理では大量データを扱うようなものが多いので、ゴルーチンを用いて並行処理をする
    ことで比較的簡単に処理時間を短縮することが可能
    ただ並行処理を不必要に乱用するとシステムの複雑性が上がるため、注意は必要。
    sync.WaitGroupやerrgroup.Groupなどを用いて、ゴルーチンの管理を丁寧にする必要はあ

    View Slide

  17. オプションフラグを活用する
    cmd.Flags().BoolVarP(&opt.Notice, “notice”, “”, opt.Notice, “notice”)
    cmd.Flags().BoolVarP(&opt.Dryrun, “dryrun”, “”, opt.Dryrun, “dryrun”)
    バッチの動作確認をする際などに利用できるオプションを追加すると動作確認が簡単
    にできるようになり非常に便利
    (例)
    - メールなどの通知の送信を伴うバッチにおいては、noticeフラグをつけた際にのみ通知
    を送る
    - dryrunフラグをつけるとデータの更新がされず処理内容のログが出るだけにする

    View Slide

  18. Go×Kubernetesで快適なバッチライフを!

    View Slide

  19. ご清聴ありがとうございました!

    View Slide