自己紹介

宮本英和氏(以下、宮本):では「ラクマとGitHub ActionsとGitOps」というタイトルでセッションを始めたいと思います。よろしくお願いします。

まず簡単に自己紹介をさせてください。宮本です。今ラクマのSREのテックリードとして、ラクマのシステムを4年ほど運用しています。

次に、簡単にサービスの紹介をしたいと思います。楽天が運営しているフリマアプリの「ラクマ」は、おかげさまで2,500万ダウンロードを突破して、今なおも急成長を続けています。ラクマで売れた金額が楽天ポイントとしても使えるので、非常に便利なサービスとなっています。もし今回初めて知った方がいたら、ぜひダウンロードしてもらいたいと思います。

SREチームのミッションとチーム構成

では、さっそくラクマのSREチームがどんなことをしているのかを説明したいと思います。

SREチームの任務はけっこうミッションクリティカルで、年間流通総額が1,500億円規模の取引を支える、重要なポジションになっています。主な内容ですが、サービスを提供するインフラのシステムの構成や設計、24/365でサーバーの運用・保守からパフォーマンスチューニングまで、幅広くやっています。

エンジニアの採用もなかなか難しいので、人でスケールするのではなく、システムでスケールさせるところに力を入れてがんばっています。

では、次にチーム構成について話したいと思います。SREチームはエンジニア全体の約10パーセントほどの人数で、機能開発を行うチームが別にいますが、その複数ある機能開発を行っているチームを横断的にサポートしています。

たまに、まったく新しい新規プロジェクトが立ち上がって、インフラもゼロから作るようなケースもあるので、そういったときはそのプロジェクトの一員として入り、一緒に開発などを行うこともあります。

SREチームの課題

今あるチームの課題です。先ほどお話したとおり、どんどん新しい機能を追加してサービスを成長させないといけない時期にあり、現在、数十個のプロジェクトが同時並行で走っています。

それに伴って、システムの相談や、あとキャパシティの負荷の問題の相談、インフラに関する問い合わせが増加する一方にあります。そのため、いかに運用コストを下げて解決させるか、あとは我々が行っている業務を、なるべくバックエンドエンジニアに移譲しないといけないのが課題になっています。

そんな運用の中でシステム品質担保するために、ISMSやJ-SOXといった監査を定期的に行っていて、インフラの変更管理に関しても監査の対象になっています。監査の証跡集めとして、Jiraによるチケットなどで変更管理を行い、その内容を証跡として監査側に提出をしたりもしています。

証跡集めに必要な内容を簡単にまとめると、「いつ・誰が・どのような変更をしたのか」と、「責任者の承認を得た上で変更をちゃんと行っているか」というような内容です。

GitHubを使った開発スタンスとの比較

この内容が、ある作業に似ているんじゃないかと感じました。その作業が、日頃エンジニアが行っている、GitHubを使った開発のスタンスです。

その内容を表にして比較したいと思います。変更内容に関しては、Pull Requestを使えば、変更の経緯や、どのような変更をしたのかが細かく確認できるようになっています。承認フローに関しては、GitHubであればコードオーナーという機能があり、リポジトリ単位で、コードに対して責任を負う担当者やチームも指定できるようになります。

この内容は監査の証跡集めの要件を十分に満たしていると思い、監査の担当者に相談をして、実際にインフラに関する変更管理に関しては、GitHubで行っているコードレビューやPull Requestの内容を、証跡集めとして提出しています。

実際にどのような仕組みで実現させてきたかのかというのを、このあとお話ししていきたいと思います。

Terraformの実行環境の仕組みと実現させたいこと

では次に、GitHub Actionsを使ったTerraformの実行環境の仕組みについてお話ししたいと思います。インフラによるリソース管理にはTerraformを採用していて、新たに追加されるインフラリソース管理に対しては、Terraformでコード化して管理しています。

ここで実現したいことを説明したいと思います。まず、開発者がfeatureブランチでTerraformのソースコードを変更して、developブランチにマージするPull Requestを作成したタイミングで、GitHub Actionsが起動する設定をしています。

その際に、Terraformの初期化やフォーマットチェックを行って、問題がなければTerraform planという実行計画を確認するコマンドを実行して、その結果をPull Requestのコメントに表示するような内容になります。

次に、実際に変更を反映するフローです。先ほどのフローでdevelopブランチにマージが完了したら、次はそのdevelopブランチからmainブランチに対して、マージするためのPull Requestを作成します。そのときにも、先ほど説明したものと同様、初期化からplanの実行を行い、その結果をPull Requestのコメントに残します。

この図でいうと、先ほどの説明が1~4番になります。次に5~9番の残りの説明をしていきます。

そのPull Requestのコメントに残った内容をコードオーナーが確認して、問題がなければ承認を行います。そうするとmainブランチにマージができるようになるので、開発者がマージ処理を行います。そうするとまた別のGitHub Actionsが作動して、実際にインフラに対して変更が行われる処理の流れになります。

この内容を実現させるためにどういったことをしたかというと、Terraformの開発を行っているHashiCorp社が、このようなActionsを用意しています。これを利用することにより、さほど工数をかけることなく取り入れられました。

こちらが、実際にPull Requestをトリガーにして実行された内容の結果です。初期化やフォーマットに関しては左側の画面のほうに出ていて、planの結果に関しては右側の画面になります。けっこう細かくどのようなかたちで変更したのかもわかるようになるので、チェックも比較的容易だと思っています。

Kubernetesのリソース管理のGitOp化

では次に、どのようなかたちでGitHub Actionsを組み合わせて、Kubernetesのリソース管理をGitOp化したかの話をしたいと思います。

次に実現したいことがこちらです。この図のポイントとなる部分がいくつかあります。まず、リポジトリが2つあります。アプリケーション用のリポジトリと、Kubernetesのマニフェストファイルを管理するリポジトリとで、2つに分けています。

あともう1つが、CDツールとしてArgoを採用しています。ほかセッションもいろいろ見て、Argoを使った利用事例がたくさんあったので、「けっこう人気なんだな」とあらためて感じました。

実現したい内容をまとめたのがこちらになります。まずはじめに、コンテナをビルドしてレジストリにプッシュすること。アプリケーション側のレポジトリでGitHub Actionsを動かすかたちになるので、下のほうにあるKubernetesのマニフェストファイルのリポジトリを取得する必要があります。

今回は新しいコンテナイメージのデプロイになるので、タグの書き換えのような変更作業を行い、その内容を作ったマニフェストファイルのリポジトリに対してプッシュして、Pull Requestを作成する必要が出てきます。

これを、GitHub Actionsを使ってどのように実現したかが続きになります。

まず、コンテナをビルドしてレジストリにプッシュする方法です。こちらもDocker社があらかじめActionsを用意してくれているので、それを採用しています。

こちらが公式に載せてあったサンプルコードを抜粋したものです。まずはじめに、この赤枠で囲っている部分がセットアップの設定になります。ここに関しては、必要な機能を使うための記述という程度の認識でよいと思っています。

真ん中の文に関しては、Docker Hubにログインする処理になります。もしみなさんがDocker Hub以外のコンテナレジストリを使うのであれば、別のログイン処理が必要になります。

最後に、下の部分で、実際にビルドとプッシュが行われるようになっております。

次に複数リポジトリをチェックアウトする方法です。こちらは特別誰かが作ったものを用意する・使うわけではなく、Actionsの中でデフォルトで用意されています。

ポイントとなるのはここの部分です。ほかのリポジトリを取得したい場合は、withブロックで書かれている部分で取得したいリポジトリを指定して、保存先のパスを指定できます。

マニフェストファイルの変更方法

次に、再度マニフェストファイルの変更方法について説明をします。今回は、マニフェストファイルを変更するために、Rubyスクリプトを使った方法を案内したいと思います。

こちらが、実際に用意したRubyスクリプトを実行するGitHub Actionsの記述です。下が、実際にそのRubyスクリプトの内容になります。おそらくみなさんUbuntuでGitHub Actionsを動かすケースが多いと思いますが、UbuntuだったらRubyがデフォルトで入っているので、このようなかたちでスクリプトを実行できます。

次に、リリース承認をもらうためにPull Requestを作成します。こちらに関してはCreate Pull Requestという便利なActionsがあったので、採用しています。

内容も、このようなに比較的少ないコードでPull Requestを作成したらできます。

GitHub Actionsを使って実行した内容がこちらです。このような感じで、ゼロからすべて開発するわけではなく、いろいろなActionsの組み合わせで、主要なCI/CD部分の構築できます。また、自動化することによってフローが固定されるので、属人化することもなく、どのメンバーに対して、監査チームへの説明や証跡集めもできます。

IaCを使う上でのブランチ戦略

では最後に、IaCを使う上でのブランチ戦略の考慮ポイントについてお話ししたいと思います。

前提として、kustomizeを使ったKubernetesのマニフェストファイルを、どのようなブランチ戦略で管理していくかにフォーカスしてお話ししたいと思います。

kustomizeは、KubernetesのYAMLファイルを効率よく運用するのに特化したパッケージツールとなっています。

載せているツリー構造がkustomizeを使う上でのディレクトリ構成になります。baseディレクトリには全環境共通するマニフェストファイルを管理して、overlaysのディレクトリに関しては、各環境ごとの差分をパッチで当てるようなツールの構成になっています。

これが先ほど説明したArgoの部分のアプリケーションの設定ファイルです。赤枠の部分で、マニフェストファイルのどのブランチをチェックするのか、またはどのパスを参照するのか、各環境に応じたマニフェストファイルをKubernetesクラスタに反映できます。

kustomizeはものすごく便利です。Argoもデフォルトでkustomizeが入っているので便利ですが、注意点としてはArgoに入っているkustomizeのバージョンが比較的ちょっと古いバージョンになっています。もし開発する際は、バージョンに気をつけながらやることをおすすめします。

では、ブランチ戦略の話をします。はじめに、このようなブランチ戦略を考えました。まずmainブランチからfeatureブランチを作成して、そのfeatureブランチから各固定のmain、staging、developといったブランチに対してマージをしていくパターン。

こちらは各クラスタと同期するブランチが固定になっているのでわかりやすいと考えていました。しかしチームの中で、例えばoverlaysのdevelopのマニフェストファイルを変更した際には、developブランチにマージするだけでやりたいことが満たせてしまうので、mainブランチへの反映が漏れてしまい、今後問題が起こるんじゃないかという議論が出てきたので、別の方法を考えることにしました。

次の内容がこのパターンになります。前回と同様、mainブランチからfeatureブランチを作成して連携していきますが、そのマージする順番をfeature→develop→staging→mainというかたちで、一方通行にする方法を考えました。ちなみにTerraformに関しては、これに近いブランチ戦略を使っております。

これ関しては、マージ漏れの心配はなくなっていいなとは思いましたが、やはりマージする順序が一方通行になっている故に、対応するフローが増えて面倒だという懸念が出てきました。

そのため、また新たによいパターンがないかを考えました。

次に考えたのがこちらです。登場するブランチはmainとfeatureのみとなっていて、featureブランチでなにか修正したものに関しては、mainブランチに反映して、各環境のクラスタはすべてmainブランチを参照するようになります。

こうすると、プラン2で考えていた懸念がなくなり、かつ、マージ漏れもなくなるので、非常にシンプルです。ただ、base、全環境共通のマニフェストファイルを変更する際に、このままだとなにも動作確認しない状態で本番環境にも反映してしまいます。そこがちょっと問題でどうしようかと考えた末、次のアプローチを行うことにしました。

baseを変更する際には、一時的にArgoが参照するブランチ先をfeatureブランチに切り替える方法をとりました。

これでブランチ構成がシンプルになるし、もともとプラン1で懸念していた問題も解決できるようになりました。ただ、やはりbaseブランチを変更する際に、参照させるブランチを切り替える面倒さはどうしても出てきてしまいます。ただ、baseブランチを変更するケースは、overlaysのファイルの変更と比較して変更頻度が少ないと思い、現時点ではこのパターンを採用しています。

ラクマSREチームでは、こんな感じで日々試行錯誤して改善に取り組んでいます。これで以上になりますが、なにかこの内容が、みなさんのお役に立てれば幸いです。

では、これでセッションは以上になります。ご清聴ありがとうございました。