こんにちは!TECH Street編集部です!
今回は2020年1月26日(火)に開催した、【BASE BANK/はてな/POST URBAN/パーソルキャリア】CI/CD活用事例&TIPS発表会のイベントレポートお届けいたします!
各社のCI/CDってどうなってるの?というメンバーの興味関心から企画した今回のイベント。CI/CD関する知識や経験・気付きなどを事業会社のエンジニアが集まり発表し学びあう場となりました◎
「Pull RequestとGitHub Actionsのworkflow_dispatchを活用した承認・リリースフロー」(吉次 洋毅/パーソルキャリア株式会社)
現在、パーソルキャリアの2019年に新設された部署で「Salaries(サラリーズ)」というプロダクトの開発を担当している吉次さん。
吉次さんの所属部署は、新設部署ということもあり本番リリースの運用に関する要件についても、手探り状態から始まったのだとか。そのような環境の中で、本番リリースの際の承認やリリース・切り戻しにおける課題が見えてきたそうです。
吉次さんからは、これからCI/CDの構築・見直しをしようとしている人が、GitHub Actions workflow_dispatchの使い方を知り、各プロジェクトでの承認・リリースフローの構築に活用できるようなTIPSをご紹介いただきました!
GitHub Actions workflow_dispatch
2020年6月にGitHub Actionsにおいて、ワークフローを手動で実行するためのトリガは発表されました。
これまで、GitLab CIをよく使っていたという吉次さん。GitLab CIにおいてはmanualを指定すると手動に切り替わるのだとか。GitHubでもこれがしたい!ということでワークフローを活用したそうです。
ワークフローは下記のようなトリガとなっています。

※ワークフローファイルがデフォルトブランチにマージされていないと、「Run workflow」のボタンが出てこないので、ご注意ください!
続きまして、トリガの設定は下記の通り。
workflowのトリガ部分でworkflow_dispatchを指定します。例えばタグ等の、任意の入力値を定義することも可能です。
例として、今回は下記のようなかたちで設定しているのだとか。

また、Pull Requestを活用した承認をすることで、だれが承認したかのログが残すことができ、当初想定していた承認フローの課題をクリアすることもできたとのこと。
そして、リリースノート・タグを作成し、リリースを実行します。
通知と切り戻し
現在吉次さんが担当されているプロジェクトにおいては、Slackに誰がどのリポジトリのどのバージョンをデプロイしたのかが通知されるようになっているそうです!
GitHub Actionsにおいては、現状トリガの制御がリポジトリの権限に基づいているため、チームメンバーが誰でもできてしまう状況なのだとか。そのため、何か異常があったときもあとから気づけるように、Slackに通知がされるようにしているとのこと。
その他には、スマートではないものの、「実行権限を持つ人だけが知っている認証用コード」を使って制御するという対応方法もあるそうです。

まとめ
吉次さんからは、まとめとして下記の3つのポイントをあげていただきました。
・手動トリガを活用してリリースと切り戻しをよりシンプルにしよう
・Pull Requestを承認に活用し、承認フローにおける人為的ミスを減らそう
・Slack通知を活用してより機敏に動けるようにしよう
吉次さんからは、非常に具体的に操作方法から課題の解決方法までシェアしていただきました◎是非、皆様もご活用ください!
参加者からの質問
(Q1)GitHub Actionsは触れたことがないのですが、強いて言うならここを改善してほしいとか、やりにくいとかあったりしますか?
(A)workflow_dispatchが出てくる以前は困っていましたが、現状特に使いにくいような点はないかなと思います。(他のCI/CDサービスに並んだかなという感覚です)。workflow_dispatchに関しては、デフォルトブランチへのマージが必要なので最初に試したりするときは割り切ってマージしたり、一時的に別のデフォルトブランチにするなどの対応が必要なのが若干煩わしい部分かも知れません。
(Q2)吉次さんのチームは何名くらいの体制ですか?
(A)適宜プロジェクトを移動したり、兼任したりがあったりしますが、大体5〜6名の体制でやっています。
(Q3)社内の開発環境がオンプレミスに依存している場合、Githubに代わるCI/CDツールについて推奨するものはありますか?
(A)推奨と言えるほどいろいろ試してはいないのですが、過去に似たような環境でやっていたときは、コード管理を含め、GitLabをオンプレ内でセルフホストしてビルトインのGitLab CIを使っていました。(吉次さん回答)
(A)CI/CDのみであれば弊社での採用事例はありませんが、個人で利用したことがあるものだとDrone IOなどがオススメです。(@_k725さん回答)
「KubernetesとCI/CDの活用について」(@_k725/パーソルキャリア株式会社)
続きまして、Vtuber姿での登壇!めっちゃかわいい!!w
所属部署全体のインフラ・セキュリティに対するアドバイス及び業務環境改善を担当されている@_k725さんに、Kubernetesを中心にご共有いただきます◎
これまで、パーソルキャリアが運営する「CAREER POCKET(キャリアポケット)」というサービスにおいて、サイボウズのKintoneを使用していたのだとか。
しかしながら、セキュリティ等の社内規定により、使用継続が難しくなり、その代替として別のデータベースを使用することに。今回代替として使うデータベースのプロジェクト名はCandicom(Candidate+Communication=Candicom)。
Candicomの利用イメージ
Candicomは、「CAREER POCKET」内の、「転職トーク」というサービスにおいて使用されています。転職希望者のサポートを行うキャリアアドバイザーが利用記録をCandicomの中に登録して管理しているのだそう。
機能としては、簡易的なフィルタを使用したリストや、非エンジニアの方が使えるようなCSVのインポート・エクスポート機能など。
Kubernetesの活用
Kubernetes(k8s)とは、Googleが設計したコンテナオーケストレーションシステム。コンテナをクラスタ内で横断してデプロイ、スケーリングするためのプラットフォームです。
こちらを活用して良かった点としては、下記などが挙げられるとか。
・特定のコンポーネントのみ更新の場合、影響範囲が限られる
・スケーリング、オートヒーリング、ロギング、メトリクス取得の恩恵がKubernetesによって得られる(主にマネージドなKubernetesの場合)
一方で、辛かった点も。
・Kubernetes単体での運用ははっきりいって辛い
・特にステートを持つリソース(データベース・キャッシュなど)をクラスタに混ぜると厄介にな存在になる
他にも、下記のような検討事項あったようです。

最新のイメージを常に使いたい、という問題についてはCI/CD上にSkaffold(※)を組み込んで使用することで解決できたのだとか。
※Skaffoldとは
Googleで作られたKubernetesへのデプロイを便利にするツールで、kubectl, Kustomize, helmなどを実行してくれます。

環境ごとに値を切り替えたい、という課題に関しては、上記図、左側にファイルのツリーが出ていますが基本的にベースディレクトリに全ての設定を記述し、オーバーレイディレクトリのなかに、起動したいコンテナの数等の上書きをしたい設定を書いておきます。
また、パスワード等の秘匿情報を持ちたい、という課題については標準機能ではクラスタへの管理権限があると誰でもデータにアクセスが出来る等のリスクがあるため、セキュアコース(データの暗号化/復号化などもできる)で対応したそうです。
ただし、クラスタのなかに侵入されると、いくらIAMを絞っていても難しい部分があるのだとか。これに関しては、RBACの使用で多少カバーできる部分もあるそうなのですが、RBAC自体の導入もハードルが低くはなく、導入には二の足を踏んでいるような状況なのだそうです…!
プログラム側もメモリに認証情報などを持つことになるので、リードオンリーコンテナにしつつ、シェルアクセスをはく奪するなどして秘匿情報を管理したほうがよさそうとのこと。
今後について
開発当時の課題点である、コンテナの軽量化は改善できているようですが、今後の課題点としては、リードオンリーコンテナにするなどして、コンテナ自体をもっとセキュアにしていくことが必要なのでは、と考えているそうです。このあたりは、担当の方が少しずつメンテナンスしているそうなので、今後に期待とのこと!
@_k725さんからも非常に具体的なお話、ありがとうございました◎
参加者からの質問
(Q1)パーソルさんはGitHub Actions推し?比較検討対象とかは他にあったのでしょうか。
(A)弊社のセキュリティポリシー上、新規に使用するWebサービスは審査が必要なため、既に利用しているGitHubに組み込まれているGitHub Actionsを利用する方が、拘束されずに高速に開発出来ると考えたためです。
(Q2)Skaffoldを採用された経緯はありますか?
(A)Kustomizeを利用していましたが、不満を感じ色々探していたところSkaffoldを見つけ、求めていることが出来ることから使用を始めました。
(Q3)docker-composeではなくk8sを利用した理由を教えてください。
(A)Linuxインスタンスのメンテナンスを避けたいというのがk8s(GKE)を採用した理由です。
(Q4)Kubernetes はデータベースやキャッシュをもたせるとつらいという話がありましたが、これはコンテナの安定性の問題ですか?データベースやキャッシュ等のデータを保持しないシステムではコンテナが不安定になってもautohealやautoscale等で対応が可能という意味ですか?
(A)概ねそうです。ステートを持つPodだとスケールやAutohealで結構考慮することが多かったりするので、極力パブリッククラウドで提供されている他のリソースにステートを持たせた方が良いと感じました。
「はてなでのGitHub Actions活用事例」(papix/株式会社はてな)
株式会社はてなでWebアプリケーションエンジニアをされているpapixさんからは、はてなにおけるGitHub Actionsの活用事例をご共有いただきました。
従来のCI環境は、EC2上に構築したJenkinsを使用していましたが、開発に気を取られてしまい、どうしても保守管理が後回しにされがちだったのだとか。また、歴史的経緯によって同時にテストが実行出来ないこともあったそうです。
はてなでは、 GitHub.comを活用していたので、GitHub Actionsが登場した際にこれまで最大のネックだったテストのGitHub Actions化に取り組むこととなったそう。
ワークフローの構築
GitHub Actions化の肝はワークフローの構築です。
開発環境のDocker化が完了していれば、難しくはないはず...!イメージをビルドして、Dockerでテストを実行します。そのなかで、テストの時間をなるべく短くする、コストの試算、Jenkinsからの置き換えなどを考えながら進めていきます。

Dockerのイメージは都度ビルドせず、開発環境のDocker ImageをECRに登録し、テストするごとに都度pullする、という作戦がつかえるのだとか!
そもそも、テストそのものにも時間がかかります。アプリケーションの規模にもよりますが 、普通にテストを回すと1時間経過しても終わらないことも…!そこで、self-hosted runnerを使う、AWS CodeBuildを使うという作戦を考えたそうです!
self-hosted runnerは自分が作った環境でGitHub Actionsの処理を実行出来る仕組みで、必要な環境を構築してGitHubに登録すると利用することが出来ます。しかし、例えばself-hosted runnerの動作環境としてEC2を使う場合、処理をしていなくても起動し続ける必要がありコストがかかってしまうことや、self-hosted runner1台につき1つの処理しかできないというデメリットもあり、断念。
次に、AWS CodeBuildですが、vCPU32, メモリ144GBの環境があり、self-hosted runnerと異なり、都度実行・都度課金の形態なのだとか。ただ、「GitHub ActionsからAWS CodeBuildを起動」するのであれば「JenkinsからAWS CodeBuildを起動」、むしろ「AWS COdePipelineで良いのでは…?と思い断念…。
第三の選択肢としてでてきたのが「テストを分割実行する」というやりかたなのだとか。つまりどういうことかというと…

テストを16分割したそうです…!
GitHub Actionsには「ビルドマトリックス」という概念があります。こちらは本来はPerlの5.32系、5.30系、5.28系…のように複数の環境で同時にテストを実行するためのものだそうですが、これをつかってテストを16分割して実行してみたのだとか。コストは当然16倍となりますが、その分素早く終わるので十分にペイできたそうです!
まずは、ビルドマトリックスとして連番を指定、連番の数だけテス
トを分割して実行します。(例えば1から16までの連番なら、16分割。)その後、findを使ってテスト対象の一覧を取得し、splitで分割、実行の順に進めます。テストを分割する結果は冪等である必要がありますのでご注意を!

実際のワークフローの様子はこちら。
更なるテクニックとしては、下準備を行うprepareというジョブを別途用意したそうです。16分割したテストのそれぞれでライブラリのインストールなどの下準備を実行すると非効率なため、テストを実行するにあたって必要な処理はprepareジョブに押し込みます。また、テストはprepareフェーズ後に実行するようにします。あるジョブと別のジョブは別の環境で処理が実行されるため、prepareジョブで用意したファイルは、他のジョブでそのまま使えなく、prepareジョブでキャッシュして、それを利用する必要があるそうです。
また、キャッシュ周りに関しては、GitHubが公式で提供するキャッシュ機能(action/cache)という機能があるそうですが、16分割して同時にキャッシュを取得しようとしているためか、時折キャッシュの取得に失敗することも…!更に、その場合「16分割したうちの失敗した1つ」を実行することは不可能なため、16分割全て再実行が必要になるのだとか…

そのため、キャッシュの取得の失敗を防ぐために、S3を使ってキャッシュを実現するpapix/action-cache-s3の仕組みを作り、キャッシュ取得に失敗することが減ったそうです!
こうして、ブログのテストはpushしてから7-10分で終了するようになったのだとか!(凄いスピードアップですね◎)しかも、GitHub Actionsのジョブはスケールするので、複数のpushがあっても常に同時に走ってくれるそう!
ほぼメンテナンスフリーで開発が出来る環境となり、環境が大幅に向上。Jenkins時代と比較すると、試算ではコストも約2/3になったのだとか!一方で、ワークフローのデバッグが難しいというデメリットもあったそうです。Jenkinsのように実際にサーバーに入って挙動を見るということが難しく、GitHub Actionsのログから調査をする必要があるのだとか。
メリットもあればデメリットもある、その繰り返しで改善が進んでいくのですね…!非常に参考になる事例の共有ですね◎
最後は、GitHub Actionsのおもしろテクとして、LinterやFormatterとreviewdogを組み合わせてコードに警告をする、misspellとreviewdogを組み合わせてミススペルを指摘したり、Pull Requestのラベルのチェックをすることも実現できると教えていただきました♪
papixさんからは、はてなにおけるGitHub Actionsの導入事例をメリット・デメリットの側面からも詳細にご共有いただきました!GitHub Actionsの様々なactionを使用することでコスト削減や効率化を実現することも可能とのこと◎
まとめ
今回のイベントでは、各社のCI/CD導入における課題や取り組み、解決策まで非常に具体的にシェアしていただきました!エンジニアの皆様にも参考になるお話が沢山あったのではないでしょうか◎
参加者の声
・発表者の方が全員丁寧に質問に回答されていたのでとても好印象でした。
・Kubernetes、GitHub、CI/CDについてあまり勉強していなかったので参考になった。 kubernetesについてはpro/conについてよく考えて使わなければいなければいけないという話も参考になった。
・登壇者の所属企業もいろいろで、様々なクラウドサービスの事例が含まれて、参考になりそうな部分がいっぱいあった。
最後に、今回ご登壇いただきました皆様、ご参加くださった皆様ありがとうございました!今回のイベントレポートは以上になります♪次回もお楽しみに!



