BIGLOBEの「はたらく人」と「トガッた技術」

失敗から学んだGitOpsを成功させるコツ

こんにちは、BIGLOBEの谷山です。

こちらの内容は、以下の記事からの続きとなります。

style.biglobe.co.jp

オンプレの何十台ものサーバから構成されるRADIUSシステムをAmazon Web Services(AWS)に移行するプロジェクトを行っていました。 2021年度上期に、一旦認証機能の中核となる部分と一部のバックエンド(監視機能等)の移行が完了しました。

GitOpsを実際に使って開発を終えて、やってよかったなと思うことがたくさんあったので、GitOpsのメリットや、上手く続けていくために守るべきことをまとめておきたいと思います。

そもそもGitOpsって何、という話等については、前述の記事をご覧になっていただければと思います。

GitOpsをやって得られたメリット

GitOpsによって、得られたメリットについていくつか以下に書いていきたいと思います。

改善(1) : 開発フローの改善

GitLabのMerge Request機能を中心に、開発を進める業務フローに変えたことで、レビュー用の資料作成を個別に作成する等を行わずに済むようになり、業務が効率化しました。 一部修正を加えていますが、前回の記事でも貼り付けたGitOpsの運用イメージが以下です。Deployの流れも含めてわかりやすいように、Terraformの場合を一例として記載しています。

f:id:biglobe-editor2:20210827090237j:plain

上記の図に記載の通り、

  • 環境に追加するものに問題はないか
  • コードの書き方に問題はないか

等のレビュー、および承認を、GitLabのMerge Request(MR)機能を使って行うことができます。

だいぶ黒塗りしてしまっていますが、以下はMRのPipelineページで、

f:id:biglobe-editor2:20210827094448j:plain

以下はMRの差分ページです。

f:id:biglobe-editor2:20210827094500j:plain

Pipelineのページではエラーが起きてないかすぐわかり、実際のログも緑チェックをクリックすれば見に行くことができるようになっています。差分のページではどこに更新があったかを赤背景(削除)と緑背景(追加)でわかりやすく表示してくれています。

ユニットテストの実行をPipelineに組み込んでおくことで、「確実に単体テストを通過していること」を担保することもできます。また、コメントの部分に画像の貼り付けも行うことができるので、外部からのテスト結果のグラフ等も追加で証跡として残すこともできます。

GitLabに限らずほかのプラットフォームでもそうですが、MRの中にこれらの情報が紐づいてまとまるので、何か問題が起きたときに情報追いかけやすいです。

開発フローごと大きく変えたので、これまでGitLabを触ったことが無かったメンバーにもある種強制的に触ってもらうようになったので、メンバーのgit関連のスキル向上につながりました。

改善(2) : IssueBoardでタスク管理の利便性向上

GitLabにはIssueBoard(カンバン)機能があるので、外部のタスク管理ツールを別で用意する必要がありません。Issue内にコメントもどんどん追記できるので、状況管理もしやすいです。また、IssueからbranchとMRを作成することができ、相互に紐づくのでIssueがどういう経緯でCloseまで至ったかの流れを残すことができます。

ほかにもIssueをさらに便利に使える機能(Milestones等)もたくさんありますが、そのあたりはIssueBoard単体での利用が慣れてからでも大丈夫かと個人的には思います。

改善(3) : 業務情報の集中化による効率向上

前述の通り、Pipelineの実行結果等、開発にかかわるものが全てGitLab上に集まります。そのため、ほかのメンバに聞きたいことがあった時にPipelineのリンクなどを添えて聞くことで、前提条件の説明をある程度省くことができたり、ログを別途保存したりしないで済みます。同じことを口や文字で説明しなおす必要がないため、ミスコミュニケーションも起きにくいです。 リモートワークにより文字でのコミュニケーションが増えているため、そこの部分のコストを下げることができるのは大きなメリットでした。確実に同じものを見て作業を進められるのがSaaSのメリットだと思います。

改善(4) : あらゆる設定ファイルをGitLabで管理する文化を醸成

GitOpsを行うことで、GitLabを利用するのが「当たり前」となり、オンプレサーバ内の設定ファイル等、これまでそのサーバ内で日付バックアップを取っているのが主だったものもGitLabで管理するようになりました。

日付バックアップと異なり、過去の状態との差分を比較するのも容易ですし、変更履歴とコミットメッセージが残るので、何故設定を変えたのか、いつ変えたのかが見える化しました。

改善(5) : Deploy作業をこれまでより意識しないで済む

実際にDeployする仕組みは全てPipelineに定義してあるので、Deployのために実サーバにログインしたり、といった作業がなくなります。なので、開発者はGitLabを使ってコード開発、MR作成、承認の流れを淡々とこなしていけば自然と環境が出来上がります。 手順書を使った環境構築の場合、手順書を見ながら操作を進めていく都合上作業時間の調整等に手間がかかることもありますが、Terraformであれば基本的には数分で作業が終わるので作業調整、実作業(実行ボタンを押すだけ)も各段に楽になりました。

TerraformでDeployするLambdaのコードも、GitOpsでビルド、テスト、S3への配信を自動で行っています。自動的に命名規則(コードにつけたtag情報等を付与)に従ってS3に配置されるので、コード作成者はどこにビルドされたファイルが置かれているかを意識する必要はないようになっています。

他にもGitLabのいいところ

MRの画面に色々と集約されているという話は前述した通りですが、GitLabにはWebIDEも存在するので、ちょっとした変更であればWebGUIでbranchを作成して、WebIDEで編集してMR作成、という一連の流れも簡単にできます。

これは完全に個人的な好みですが、ほかのGit系SaaSの中では色合いや画面レイアウトがすっきりしてて見やすいのもいいところです。

失敗したことと、それを防ぐための方法

GitOpsをやっている中で、失敗したことがいくつかあった(特にTerraform周り)ので、それらについて記載します。プログラム等と違って、AWSコンソールなど、ほかの設定手段も存在してしまうこと(自分も含めて、人は皆目先の楽さに吸い寄せられてしまう)や、AWSのリソースで後更新できる設定・できない設定が多様にあることが大きかったです。

失敗(1) : ついつい手動でAWSリソース作成

最初の頃は、どうTerraformで書いていいか困ったのもあって、とりあえず手動でリソース作成を行ったことがありました。Terraformにはterraform importという既存リソースを取り込むコマンドがあります。ただ、実際に使ったことがある人ならわかるかもしれませんが、自分が思った通りの構造でtfstateに読み込まれてくれるとは限りません。特にセキュリティグループは顕著でした。 上手く解消する方法はあったのかもしれませんが、既存リソースの取り込みに関しては自分はとにかく愚直にやる(つらい)しか解決法が見つからず、辛い(ほんとうにつらい)思いをしました。 他にも、手動で作ったリソースのセキュリティグループにTerraformで作ったセキュリティグループを適用すると、Terraform側でそのセキュリティグループの削除が依存性のせいでできなくなるなど、Terraform管理外のリソースを作るデメリットは多々ありました。

これを解決する方法は、システムの分界点を意識してシステム設計を行い、GitOpsやる部分・やらない部分を明確に切り分け、GitOpsやる部分の手動設定を禁止することです。できるのであれば、管理者/運用者以外にはAWSの読み取り権限のみあるアカウントを払い出す、等権限で制御してもいいと思います。 RADIUSシステムの場合、以下のようにTerraformの分離を行いました。

f:id:biglobe-editor2:20210827090355j:plain

base環境のGitLab RunnerをGitOpsで管理すると、自己崩壊を起こす可能性があるので、こちらはTerraformを手動実行して管理しています。また、パラメータ情報の部分はGitにコードとして書いておきたくないので、手動設定する部分としています。

小さい範囲からやりたくなると思いますが、新規でシステムを立ち上げる場合できる範囲は全て一気にGitOpsで立ち上げるのがいいと思います。手動で建てた領域は、terraform importを愚直に頑張るか、新規に同じリソースをTerraformで並行して立ち上げて移行する方法が考えられます。

例えば、サブシステムA-Cのうち、サブシステムBだけTerraform化ができていなかったとします。

f:id:biglobe-editor2:20210827090426j:plain

サブシステムBと同じ機能を持ったサブシステムB'をできる形で新規に起こします。

f:id:biglobe-editor2:20210827090446j:plain

可能なタイミングで、BからB'に接続点を切り替えて完了です。

f:id:biglobe-editor2:20210827090459j:plain

移行の容易性を確保するためにも、サブシステム間は疎結合に作り込んだり、AWS Kinesis Data Stream等マネージドで接続しやすいプロトコルで分界点を作っておくのも重要です。

失敗(2) : Terraformのリファクタリングも結構手間

最初の頃に作ったTerraformは、module化等も行われておらず、書き方もこなれていなかったので構成がぐちゃぐちゃになってしまいました。Terraformにはリソース名を変更する時に使うterraform state mv等、Terraformのコードをリファクタリングするときのためのサポートコマンドは存在していますが、terraform importほどでは無いものの、やはり手間です。

これを解決する方法は、最初からある程度設計指針を決めた上でterraformのmodule設計をしておくことが必要だと思います。

  • module化する
  • moduleは複数のterraformでgitのsubmoduleの仕組みを使って共有し、同じポリシーが全てのサブシステムで共有されるようにする
  • terraform registryの書き方を参考にmodule設計する
  • 命名規則を決める

等です。チーム全体で納得ができる指針作りをするのが良いです。作った指針はもちろんGitLabのwikiにまとめて誰でもいつでも見れるようにすると良いです。すぐに見せられる指針があることで、チームに新しく参画するメンバーの立ち上がりスピードが上がります。

まとめ

GitOpsを取り入れたRADIUSシステムのAWS移行が無事完了しました。

失敗から学んだことは、機械でやっている作業に人手を介入してはいけないということです。失敗に書いた通り、手動で設定を行うと様々なデメリットがあります。また、GitLab上で管理しているものが本当に現在の最新の状態を表しているものかわからなくなるので、GitOpsで運用しているコード、その他資材が信用ができなくなります。

また、数々のメリットをここにまとめる中で考えたこととしては、1つのツール・開発手法のみを取り入れて全てが解決する、というわけではなく、GitLab、Terraform(IaCツール)、テストツール(pytest等)を組み合わせて開発フロー全体の見直しもかけることで業務効率が大きく上がるということです。せっかく新しいツールを導入しても既存の業務フローはそのままにしてしまった場合、新しいツールを導入して必要になった作業が既存の業務に上乗せされるだけだからです。 GitLabでREADME.mdを書く代わりに、別のこれまで作っていたドキュメントを廃止する等、何が何を担保しているのかを考えて業務の棚卸することも成功のコツです。

今後の予定

前回の記事から、この記事を書くまでの間にこの構築スキームを使った別のProjectをリリースしました、徐々にこれらのスキームを社内に横展開していければと思っています。 また、RADIUSシステムにおいてはオンプレに残っているバックエンドの残りの機能をAWSに移行することが次期の予定です。今後も新たな知見があったら記事にするかもしれません。皆様も良いGitOpsライフを。

採用情報

弊社は引き続き採用を進めてます。興味がございましたら以下のリンクを参照してください。

hrmos.co

※ Amazon Web Servicesは、米国その他の諸国における、 Amazon.com ,Inc. またはその関連会社の商標です。

※ GitLabは、GitLab B.V.の米国およびその他の国における登録商標または商標です。

※ Terraformは、HashiCorp,Inc.の米国およびその他の国における商標または登録商標です。

※ fluentdは、米国及びその他の国における The Linux Foundation の商標または登録商標です。