オールアバウトTech Blog

株式会社オールアバウトのエンジニアブログです。

オールアバウトエンジニアのSlack人気スタンプを調査してみた

毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2022」を開催します。

今回は、オールアバウトメディア開発部の@eeveeがお送りします。

はじめに

突然ですが、皆さんはSlackをご存知ですか?

株式会社オールアバウトでは、社内のコミュニケーションツールとしてSlackを採用し、業務上のやりとりを行っています。

Slackでは投稿に対して文字で補足や反応する代わりに絵文字でリアクションを取ることができます。

Slack公式の定義にならい、この絵文字でのリアクションのことを絵文字リアクションと呼びます。

社内Slackでは、多種多様なカスタム絵文字が登録され、絵文字リアクションがコミュニケーションの一環として使われています。

社内Slackの絵文字リアクションを集計してみるとチームごとのコミュニケーションの違いが現れておもしろいのではないかと思い、人気絵文字リアクションを調査してみました。

本記事では、その調査方法と結果を紹介したいと思います。 社内Slackのデータを分析してみたい方、またオールアバウトの開発チームのSlack事情気になる!という方の参考になれば幸いです。

自己紹介

私は非情報系学部出身で、業界未経験から新卒入社しており、今回のようなWEB APIを使ったデータ集計は初めての試みでした。 そのためかなりの試行錯誤を経て集計しており、今回ご紹介する実装方針はあくまで一例であるということを前提に読んでいただければと思います。

私は開発部の中でも、オールアバウトで運営するメディアや社内CMSの開発・メンテナンスをするチームに所属しています。 個人作業のときもありますが、基本はペアで開発業務を進めています。

私のチームはエンジニア同士だけではなく、企画グループや社内CMSを利用する記事編集グループなどと部署内外問わず様々なやりとりを行っています。

チーム内での報告・連絡・相談や部署内外でのやりとりでは、「はじめに」で記載したようにSlackを利用しています。

一行で済む返信は絵文字リアクションで伝えて良いこととしたり、問い合わせが来た場合には確認したら絵文字リアクションをとるようにするなど、Slackでのコミュニケーションを重要視しているチームです。

Slackのスタンプを解析してみた

同じ開発部でもチームによって、Slackの使い方の方針は異なるようです。

Slackの絵文字リアクションを集計してみるとチームごとの特徴・働き方の違いが現れておもしろいのではと思い、普段使われている絵文字リアクションのデータを分析してみることにしました。

集計ルール

今回の集計ルールは以下のとおりです。

  • 集計項目
    • メッセージに対する絵文字リアクションの使用回数
    • カスタム絵文字と通常の絵文字どちらも対象とする
  • 集計範囲
    • タイムラインに載っているメッセージのみ集計範囲とする
    • 直近の2000件のメッセージが対象
    • メッセージに含まれる絵文字は絵文字リアクションではないため対象外

全体の実装の流れ

今回のようなデータ分析を行うときはPythonを用いることが多いと思いますが、今回は勉強のために業務で用いるPHPで実装を行いました。

実装の流れはざっくり以下のとおりです。

  1. SlackAPIを利用する準備

    • Slack Appの作成
    • scopeの設定
  2. 実装

    • Slackからメッセージ履歴とカスタム絵文字データを取得
    • 絵文字データを抽出・集計

SlackAPIを利用する準備

SlackAPIとは、他のアプリケーションでのAPIと同様に外部アプリケーションからSlackを操作するための仕組みです。

SlackAPIの中でもWebAPIやEventsAPIなど様々な種類のAPIがありますが、今回はWebAPIを使用します。

公式のドキュメントはこちらです。

api.slack.com

必要なSlackAPIが何なのかはこちらが参考になります。

api.slack.com

まずはSlack Web APIを利用するための準備をしていきます。

Slack Appを作成する

データ調査を行うためにはまず、SlackAppを作成する必要があります。

そのApp用のトークンを発行し、トークンを用いてApp経由でチャンネルのデータを取得します。

ここは検索してみるとやり方をまとめたQiitaがすぐに出てくるのであまり苦労することはありません。 今回は以下のQiitaを参考に設定しました。

qiita.com

また、作成したSlackAppには使いたいメソッドごとに必要な権限を付与しないとAPIを利用できません。

ここで注意する点があります。

付与する権限はUserとBotで別れており、Appをどのように用いるかで利用する権限が異なります。

botとして権限を付与すると、データを取得したいチャンネルにSlackAppを登録しないとAPIを利用できないようです。

使いたいメソッドのリファレンスに、必要な権限も書いてあるためしっかり確認しておきましょう。

実装の流れ

SlackAPIメソッドを使って、メッセージ履歴とカスタム絵文字を取得します。 これに必要なメソッドはそれぞれ、conversations.historyとemoji.listです。

それぞれのメソッドのリファレンスはこちらです。

api.slack.com

api.slack.com

メソッドにはそれぞれ必要な権限があるので、使うメソッドを決めたらそのメソッドのRequired scopesを確認してSlackAppに必要な権限を追加しましょう。

メッセージ履歴とリアクションの取得

APIメソッドを使用する際、引数のchannelには、Slackのチャンネルリンクを発行した際にわかるIDを設定します。

今回は特定のチャンネルを指定してそのメッセージ履歴を取得するので、IDを引数にベタ書きしました。

ほかのやり方としては、channels.listというAPIメソッドもあり、publicチャンネルIDの一覧がとってこれるのでそれを使うこともできると思います。

conversations.historyではメッセージそれぞれに対するリアクションとして絵文字名とその回数を取得できます。 ここでemoji.listメソッドを使い、絵文字リアクションをカウントアップしていきます。

絵文字一覧の取得

emoji.listメソッドで取得できるのはカスタム絵文字の登録名と画像のURLの一覧です。 Slackに登録されているデフォルトの絵文字は入っていません。

もしカスタム絵文字以外のデフォルトの絵文字でもカウント対象としたい場合は、どうすればよいのでしょうか。

いろいろなやり方があるとは思いますが、今回は、カスタム絵文字データから絵文字名を抽出し、絵文字名をキー、回数(初期値として0)をバリューにした連想配列にしてカウント用の絵文字リストを作りました。

そして、conversation.historyで取得した絵文字リアクションが絵文字リストに含まれている場合はそのままバリューをカウントアップし、含まれていないデフォルトの絵文字の場合は絵文字リストに追加してキーとバリューを登録するようにしました。

これで全絵文字がカウントできるようになりました。

カウントする際に気をつけるポイント

conversations.historyメソッドではとってこれるメッセージ数のlimitとしてMAX1000件となっています。

引数で取得したいデータの期間を設定できますが、1000件以上になると意図した期間のメッセージをとってこれないので気をつけてください。

また、conversations.historyメソッドではスレッド内のリプライは基本的に取得できません。スレッド内のリプライであってもチャンネルに送信すれば、タイムラインに載るためメッセージとして取得します。

あくまでもチャンネルのタイムラインに投稿されているメッセージだけを取得するメソッドなので気をつけましょう。

もしリプライもとりたい場合は、conversations.repliesというメソッドをさらに使用する必要があります。

とってこれるデータや必要な引数がconversations.historyと少し異なりますので、リファレンスのテスターから試して確認してみてください。以下がリファレンスです。

api.slack.com

もう一点気をつけたい点として、SlackのAPIメソッドは定期的にアップデートされるということです。 今回紹介したメソッドが廃止されてほかの名前になっていることもありえます。

例として、conversations.historyメソッドができる前は、channels.historyという名前の別のメソッドだったようです。二次情報の記事の内容は参考程度にして、メソッドが存在するかや必要な権限は自分で確認するようにしましょう。

調査結果

それでは、調査結果を載せていきます。

対象のチャンネルは、以下のとおりです。

  • エンジニア同士の連絡用チャンネル
  • 私の所属するメディア開発1グループ
  • AllAbout IDの開発をおもに手掛けるメディア開発2グループ
  • BMP(ビジネスマッチングプラットフォーム)の開発をおもに手掛ける、マーケティング開発グループ

まずはエンジニア同士の連絡用チャンネルの結果です。

大事な連絡事項が多いチャンネルのためか、『確認中』の意味の目の絵文字リアクションが一位でした。確認済みであることがひと目でわかって便利な絵文字リアクションですよね。

特徴的だったのは、クラッカーの絵文字リアクションがランキングに入っていたことです。

これはリリース完了連絡に対するお祝いやねぎらいの意味合いで使用されているようです。ちょっとした気持ちを伝えられるのも絵文字リアクションのよいところですよね!

また、Slackbotのリマインダー通知に対する『それな。』や『済』の絵文字リアクションがランキングに色濃く反映されていたのはおもしろかったです。

ここからは、開発グループごとの結果を見ていきたいと思います。 私の所属するメディア開発1グループの結果です。

前述の通り、積極的に絵文字リアクションを活用するようにルールとして決めていることもあり、スタンプの総数が多かったです。

『ありがとうございます』や『承知しました』だけでなく、『いいね』や『確認中』の意味の目の絵文字も多く、メッセージに対して絵文字リアクションをとる文化が定着していそうだということがわかりました。 また、自分のメッセージに対して絵文字リアクションをとることで自分の状態を表すといった場合もあるため、人気ランキング10位圏外にも多種多様なカスタム絵文字がありました。

続いて、メディア開発2グループです。

人数が少ないこともあってか、1Gと比べてメッセージ自体も絵文字リアクションの総数も少ないことが印象的でした。

1Gでは報告・連絡・相談は基本的にSlackでやりとりしているのに比べて、2Gでは口頭などのSlack以外のコミュニケーションがメインと考えられます。

Slackでは必要最低限のコミュニケーションをしているように感じました。

人気絵文字リアクションの種類は業務連絡が多いことについては似ていますが、1Gとの違いがわかりますね。

続いて、マーケティング開発グループです。

こちらも人気絵文字リアクションの種類はほかと似ていますが、『ありがとうございます』と『いいね』の絵文字リアクションが大半を占めているのが特徴的でした。

メッセージ自体の数は1Gよりは少ないですが2Gよりも多く、Slackでも活発にやりとりされていることがわかりました。

人気ランキング圏外にも、チーム内で感謝を伝えるときに用いるカスタム絵文字があったりしておもしろかったです。

最後に

今回は社内Slackで使われている人気絵文字を調査してみました!

グループごとに雰囲気や働き方の違いがかなり現れていて、おもしろかったです。

また、APIを使って個人的にデータを分析してみたり集計してみたりといったことは初めて行ったので、よい勉強の機会になったと感じました。

試行錯誤する中で妥協した点至らなかった点もあり、現時点での自分の力を図ることもできてよかったです。

新卒一年目を卒業するということで、これからはインプットだけではなく今回のようなアウトプットの機会も積極的に設けていければと思います。

開発部で1年間働いてみて学んだこと 〜想像よりも幅広かったエンジニアの仕事〜

毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2022」を開催します。

今回は、オールアバウト開発部の@barmがお送りします。

1. はじめに

今年の4月でオールアバウトに入社してから1年が経ちます。 研修を終えた後、All Aboutの会員基盤であるAll About IDの構築に参加し、会員専用ページにデザインを適用したり、既存のサービスから会員専用ページへの導線を追加する実装を主に担当していました。 現在は構築した会員基盤をもとにしたサービスの開発を進めています。

今回の記事では、これらの業務をやってきた中で学んだことを、入社直後に思っていたことと比較して紹介していきたいと思います。

2. 学んだこと

コードを書くことだけが開発じゃない

入社した当初、指示通りのものを作ることがエンジニアの仕事だと想像していました。 実際にそういうこともありましたが、エンジニア側でもどういうものを作ればいいのか、ユーザーが使ったときにどう思うのかを考えながら開発を進めていくことが多かったです。 例えば以下のようなことは話し合われていました。

  • アンケートの入力フォームの送信・修正ボタンの配置はどうあるべきか
  • アンケートに回答し終わったらユーザーはどの画面に戻りたいか
    • マイページなのか、All Aboutのトップページなのか
  • エラーが起きたとき、ユーザーにどう動いて欲しいのか
    • 例えば、同じウェビナーに2回申し込みをされたときに「申し込み済みです」と画面に出すか、エラーページに遷移させるか

ただ指示されたものをコードに書き起こすだけでなくて、どう出来上がると嬉しいかを考えることも開発の一部ということを学びました。

レビューをもらうことの重要さ

自分が書いたコードをチームのメンバーにレビューしてもらうことにはメリットが多いです。 最初は、コードをレビューすることの主な目的はミスがないかのチェックだと思っていました。 ですが、実際にはやりたいことをより効率よく実現できる方法をレビュアーを含めて考え直す機会としてレビューを使用することも多かったです。

実際にあったのは、ほとんど同じ処理を行っている2つのクラスがあって、それを共通化して1つのクラスにするべきか、しないべきかをメンバーで話し合いました。 その時は、同じ処理をしていてもそれぞれのクラスで役割が違うこと、後から読み返した時の理解のしやすさを考慮して共通化しないと決めました。 どうするべきかなかなか決めきれず時間もかかりましたが、最終的に理由をつけた上で方針を決定することができました。

やったことに対して指摘が入ることに抵抗を感じることもありますが、メンバーと話しながらより良いコードにしていく活動は開発する力を高めていく上で重要だと思います。

話し合いながらコードを書いていくことのメリット

オールアバウトでの開発は基本的にはペアプロで行われます。 チームのメンバーとペアを組んで1つのプログラムを書いていきます。 入社するまで、ペアプロをしたことがなかったので、思った以上にペアとずっと話しながら作業しているなと、メンバーのペアプロを見た時に思いました。

はじめてペアプロをした時は、使用している言語や設計に関して持っている知識と、コードを書いていくスピードの違いにメンバーとの大きな差を感じました。

知識に差があるのはどうしようもないので、自分でコードを書く際は具体的なコードの書き方を教えてもらったり、書いたコードに対してアドバイスをもらいながら実装を進めていました。 設計については、どんな設計でアプリを作っていけばいいのかなどを一緒に考えたりすることで、 開発に必要な技術的な知識と後々困らないような設計を考えることの重要さを学びました。

工夫したところとしては、スピードについていけていない、ペアの書いているコードが理解できない時はペアを組んでいる相手にそのことを伝えて、 分からないところや何を考えてコードを書き進めているのかを教えてもらうようにしていました。 こうすることで自分に理解のスピードを合わせてもらえてかつ、学習にもつながりました。

継続してインプットすることの大切さ

日常的にコードを書いたり、アプリを作ったりしていない状態で入社をしたので、勉強するべきことは非常に多かったです。 最初は使用している言語についての知識さえあればいいと考えていましたが、作ったものをサービスとして出していく上でそれ以外の技術も学ぶ必要がありました。 学んだことを列挙すると以下のとおりです。

この中でも特に、Webアプリケーションを作る上で重要な、Webに関わる基本的な技術や、主に使用している言語であるPHPの基本的な書き方は入社する前から触れておいた方がよかったと感じています。

インプットの仕方は、業務中では新しく学んだことをメモして業務終了後に見直していました。 業務外では主に書籍を使って学習を進めていました。 勉強してたことをいくつか挙げておきます。

  • MySQLの練習問題を解く
  • 「独習PHP」を読む
    • 学んだことの共有
    • サンプルコードの写経
  • テスト駆動開発」を読む
    • サンプルコードの写経

まだまだ学ぶべきことは多いのですが、教えてもらうことを理解しやすくなったり、自分でわからないことを調べるときの足がかりになったり、業務を進める上で役に立っていると思います。

3. 終わりに

今年どうだったか

1年目からAll Aboutの新規機能の開発に関わり、自分が何もできない状態であったことを知りました。 開発進める力を自分とメンバーで比較したときに、足元にも及ばないなと感じています。 ですが、業務の中で知識をつけたりメンバーに色々教えてもらう中で学べたことも多かったです。

来年度に向けて

1年ですごく開発ができるようになったわけでもないので、できることを増やせるような活動はしていきたいです。 すぐにできることは本や記事を読んでインプットすることですが、アウトプットする活動も意識してやっていきたいです。 現段階で構想はないのですが、何かアプリを作れるのが一番いいと思っています。 できることを増やして、楽しくサービスの開発することにつながればいいなと思います。

Always on CPU の導入体験談

こんにちは。オールアバウト SRE 所属 の@s_ishiiと申します。

今回は去年リリースされた Always on CPU を導入した事例をご紹介致します。
Always on CPU は非常に有益な機能でユースケースに合致する場合は効果を発揮します。

Always on CPU について事前知識の無い方はまずは以下をご一読ください。

https://cloud.google.com/blog/ja/products/serverless/cloud-run-gets-always-on-cpu-allocation

簡単に言うと以下画像のアイドル状態を無くすための設定です。

f:id:allabout-techblog:20220120193741p:plain

利用シーンとしては主に 2 つのケースがあります。

1. リクエスト受信後に非同期で処理を実行したい場合

Cloud Run 上で重たい処理を実行する場合、実際の処理は非同期で実行して HTTP のレスポンスは即座に返したい、といったケースは多々あると思います。
従来の Cloud Run はリクエスト返却後に CPU がアイドル状態に入ってしまうので非同期処理が行えなえませんでした(厳密に言うとすごく遅くなる)。

こうしたケースを Always on CPU を利用することでカバーできるようになったことで、Cloud Run の利用シーンが拡大しました。

2. リクエストを頻繁に受け付ける場合

もう 1 つは Web のバックエンドとして Cloud Run を利用している場合です。
この場合、リクエストを頻繁に受け付けることになると思いますが、Cloud Run の料金体系はリクエスト数に対して相対的に高く設定されているため割高になる傾向があります。

Always on CPU を有効化した場合、従来とは料金体系が根本的に変わりリクエスト数に対する課金が無くなります。 CPU の利用時間が長くなるのでその分の料金はかさみますが、リクエストが頻繁にくるような場合だと従来の Cloud Run の設定であっても CPU がアイドル状態になる時間帯が少ないはずなので結果として大幅な料金の削減が見込めます。

以下公式の料金表になります。Always on CPUではリクエスト料金が撤廃されていること、それに加えCPUやメモリの使用料金も下がっていることがわかると思います。 (CPUやメモリの料金が下がっているのは、常時起動するため単位時間当たりの料金を下げているのだと思います)
Pricing  |  Cloud Run  |  Google Cloud

私達が今回取り組んだのはこのパターン 2 になります。

対象となるサービスについて

おおまかに言うとアドネットワーク上で発生したログの到達先サービスになります。 サービスの利用規模としてはおおよそ以下の通りとなります。

  • 月間リクエスト数:1 億以上
  • 月間 CPU 時間:800 万秒以上

月間でかなり多くのリクエストをさばくサービスで、昼夜問わず動作している状態です。 また、Cloud Runのメトリクスを見ると課金対象のコンテナインスタンスが常に4つあることが分かります。

f:id:allabout-techblog:20220120193852p:plain

この調査をもとにAlways on CPU化対応することでCPU料金の上昇がほぼ発生せず、リクエスト料金分だけコストを削減できると判断し実施することになりました。

結果

Always on CPU化したところ期待通りリクエスト料金の分だけコストを削減することができました(元々の使用量の1/3まで低下)。 ほとんど作業を必要とせず(設定を切り替えるだけ)、ここまで大きな成果が出るのは素晴らしいと思います。

f:id:allabout-techblog:20220120194531p:plain

※ちなみに後半さらにコストが微減しているのは Cloud Run の確約利用割引を適用しているためです

是非Always on CPUが利用中のサービスのユースケースに合致するかご確認することをおすすめします。

なお、Always on CPU は 2022 年 2 月 時点では preview 版ですので導入の際はその点にご留意ください。

Google Cloud で Terraform を導入した話し

こんにちは。オールアバウト SRE 所属 の@s_ishiiと申します。

Terraform Advent Calendar 2021 の 25 日目の記事です。

この記事では Google Cloud で Terraform を導入した話しをご紹介します。

目次

  • 導入の経緯
  • 導入の流れとその後
  • これからの課題

導入の経緯

オールアバウトでは Google Cloud を採用していますが、従来 IaC によるインフラ管理はされておらず手動で構築・運用されていました。比較的大規模なインフラを管理していることもあり、2020 年末の時点でこれ以上手動で管理していくことは不適切との結論に至りました。代表的な理由を以下にいくつかピックアップします。

1. 作業時の安全性

手動でインフラを管理する場合、新たに環境を構築・変更する時は手順書を作ってチームから承認を得て作業に移ります。これは安全な方法に見えるかもしれませんが、実際には作業時の操作ミスや作業者の勘違いで想定外の結果を生む余地があります。Terraform を利用することで事前に作業内容を明確にできるので、作業時の安全性が高まると期待しました

2. SRE メンバーに与えられた強すぎる権限

オールアバウトでは SRE がインフラを一元的に管理していますが、手動管理の都合上 SRE の各メンバーには Google Cloud への幅広い操作権限が与えられていました。これは人為的な事故を誘発するので、IaC の導入とインフラの構築フローを CD 化することによって SRE メンバーの権限を縮小化することが期待されました。

3. 命名規則の強制

サービス種別に応じた命名規則は整備されていましたが、実情として遵守されていませんでした。そもそも新しく SRE に加入したメンバーに命名規則が書かれたドキュメントを共有するフローになっていなかったので、人によっては命名規則そのものの存在を知らないといった事態になっていました。この経験から命名規則を徹底するにはドキュメント整備だけでは不充分で、CI のフローに組み込んで強制させる必要があると考えました。

上記のような理由に加え、当時 GKE クラスタのバージョンアップに伴うインフラ対応が控えていたため、これを期に Terraform を利用しようということになりました。

導入の流れとその後

ここからは Terraform の導入とその後どのように運用にのせていったのかを時系列順に記します。

STEP1. Terraform 導入

オールアバウトには大小 10 以上のサービスがあります。手動構築されたそれらのインフラ群を一度に Terraform のコード化するのは現実的ではないので、ひとまず新しく構築するインフラは Terraform を利用するとしました。

上述の通り、当時のインフラタスクに GKE クラスタの入れ替えがあったため、Terraform で作る最初のリソースとして GKE クラスタが選ばれました。またこれを機にコンテナ内で出力されたログを Cloud Logging のログルータ機能を使って GCS に保存することになったので、ログルータ周りのリソースも Terraform で構築することになりました。

Terraform のディレクトリ構造

この時点では以下のように Google Cloud のリソース単位でディレクトリを分割して state ファイルを作成していました。しかし後になってこの設計は適切でないとの結論に至り、リファクタリングによって変更されることになります。

f:id:allabout-techblog:20211224201109p:plain

STEP2. リファクタリング

Terraform を導入して数ヶ月が経過すると、当初の Terraform 設計の問題点が露見してきました。なかでも以下 2 点が問題視され、改善することが望まれました。

  1. Google Cloud のリソース単位で state ファイルを分割している
  2. ステージング/本番環境のコードが分離されている

1. Google Cloud のリソース単位で state ファイルを分割している

当初は Google Cloud のリソースを state ファイルの分割単位としていました。単位として充分に小さく、かつ分割単位として明確という理由からこの方針が採用されましたが、実際に運用していくとリソース間参照がしづらくコードを書くうえで苦労しました。

Terraform で異なる state ファイルに記述されたリソースを参照するためには、参照元に output のコードを追記し、参照先でterraform_remote_stateブロックを用いて output されたリソースを取得する必要があります。これはコードの冗長化をもたらし、可読性と生産性を悪化させました。

https://beyondjapan.com/blog/2019/01/reference-other-tfstate-resource/

また当初メリットだと考えていた小さな state ファイル、という点も実際にはあまり恩恵を感じられず、むしろ 1 つのプロジェクト内に state ファイルが分散することにより、コードの更新内容を実環境に適用し忘れる事態が発生していました。

これらの点を踏まえ、state ファイルの分割単位を Google Cloud リソースから Google Cloud プロジェクトに変更しました。state ファイルの単位として大幅に粒度を拡大することになるので、チーム内で「もう少し小さな単位を模索したほうが良いのでは?」という意見も出ましたが、プロジェクトよりも小さい適切な単位を決めるのが難しかったこともあり、プロジェクト単位で state ファイルを分割することになりました。

2. ステージング/本番環境のコードが分離されている

これは書いてある通りで、当初ステージングと本番環境は別々のコードを書いて構築していました。このため時間経過とともに環境の乖離が発生し始めていたので、ステージングと本番で同一のコードを参照するよう実装を見直すことになりました。

リファクタリング

以上の点を踏まえてリファクタリングした結果、以下のようなディレクトリ構造になりました。

f:id:allabout-techblog:20211224201205p:plain

Google Cloud のプロジェクト毎にディレクトリを作成し、その配下に environments、resources ディレクトリを配置しています 。以下が main.tf の記述例です。resources 配下を module として呼び出しており、その際に可変値を埋め込んでいます。このように書くことで resources ディレクトリ配下にコードされた内容をステージング/本番で参照することになり、乖離が起きにくい実装になっています。

terraform {
  backend "gcs" {
    bucket = "BUCKET_NAME"
    prefix = "PROJECT_NAME/stg"
  }
  required_version = ">= 0.13"
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 3.53"
    }
    google-beta = {
      source  = "hashicorp/google-beta"
      version = "~> 3.53"
    }
  }
}

module "stg" {
  source     = "../../resources"
  region     = "asia-east1"
  project_id = "PROJECT_NAME"
  env        = "stg"
}

STEP3. 手動構築したリソースの Terraform 化

ここまでで運用に耐えうる設計になったので(最低限ですが)、いよいよこれまで手動で構築してきたリソース群を Terraform 化することになりました。Terraform 化を進めるに当たって、以下 2 つの方針を前提に進めました。

コードは汚くて良い

Google Cloud で Terraform 化を進める場合terraformerが便利ですが、terraformer で自動出力されたコードの可読性は低いです。これを逐一リファクタリングしていくと相当な時間が消費されてしまうので、Terraform 化の作業のなかではリファクタリングは行わないことにしました。

全てのリソースを網羅しようとしない

オールアバウトがこれまでに構築してきたリソースは膨大なので、漏れなく Terraform 化しようとすると確認含め相当な時間を要してしまいます。目的は既存インフラを更新する際に手動ではなく Terraform で実行できるようにすることなので、更新頻度の低いリソースを頑張って Terraform 化する動機はありませんでした。そのため細部にはこだわず、Terraform 化対応で漏れたリソースは発見次第都度対応していくことにしました。

これらの前提のもと作業した結果、1 ヶ月程度で全環境を一通り Terraform 化できました。 しかしその一方で以下課題も残りました。

コードの可読性が低すぎる

リファクタリングしない前提で進めた結果、リソースの数が多いプロジェクトの可読性が相当低いものになってしまいました。今から考えるとその辺りはもう少し柔軟に対応しても良かったと思っています。

表記ゆれが目立つようになった

これは Terraform 化したおかげで気づけた点でもありますが、命名規則が徹底されていないせいで同じ種類のリソースで微妙に異なる名称が散見されました。これは for_each 等でループする際の障害になるので、将来のいずれかの時点で解消する必要が出てきました。

この 2 つの課題のうち、「コードの可読性が低すぎる」に対処するため週次でリファクタリング会を設け、チームメンバー全員で可読性の低い箇所を探してはリファクタリングしていくようサイクル化しました。

STEP4. impersonate 対応

当初の予定ではこの辺で Terraform の CD 化対応を進める予定だったのですが、他タスクとの優先度の兼ね合いに加え、全ての環境を 1 つの Terraform リポジトリにまとめているモノリポ構成であるため CD の工程が複雑になる等の理由で、CD 化は見送ることになりました。このため当面の間、Terraform は SRE メンバーのローカル端末で実行される状態が続くことになりました。

このような状況のなかで、かねてからの課題であった SRE に与えられた強すぎる権限を解消するために、Google Cloud の impersonate 機能を導入しました。これは事前に許可したサービスアカウントに成り代わることのできる機能で、この機能を Terraform のコードに導入してやると Google Cloud のコンソール画面からはリソース変更等の操作はできず、Terraform を経由した場合にのみ変更が可能になる、といったことが実現できるようになります。

https://cloud.google.com/iam/docs/impersonating-service-accounts

詳しいやり方は以下の記事で分かりやすく紹介されているので、興味のある方はご覧ください。

https://medium.com/google-cloud/a-hitchhikers-guide-to-gcp-service-account-impersonation-in-terraform-af98853ebd37

これからの課題

以上で Terraform を運用していく基礎はできたと考えています。一方で運用の容易性や優秀性を追求する余地もまだ多く残されています。具体的には以下のような課題があり、今後アプローチしていく予定です。

以上「Google Cloud で Terraform を導入した話し」でした。

新卒エンジニアが行った業務を紹介します 〜開発業務と社内勉強会〜

f:id:allabout-techblog:20210329120349p:plain

はじめに

毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2021」を開催します。 今回は、オールアバウトメディア開発部の@chocoがお送りします。

2020年4月に入社し、7月まで研修を受けたあと、メディア開発部の運用チームに所属して業務を行っています。 本記事では実際にどんな業務を行ったのか紹介します。

誰と業務を行っているか

主にコミュニケーションをとるのは、チームのエンジニアです。

編集・企画を担当する社員ともシステムの要件を相談したり一緒に業務を行います。

どんなアプリケーションを触っているのか

既存サービスや社内CMSのメンテナンスが主な担当業務です。 必要に応じて新規ツール開発等も行います。 All Aboutも私のチームの担当サービスです。

どんな業務を行ったのか

社内向け分析ツールの構築

All Aboutの収益はプログラマティック広告に支えられています。

サイトで表示されている広告枠の表示や収益は、広告運用チームの社員が管理をしています。 収益の最大化として、日々広告数字からデータの分析をしています。

今回は、その作業の効率化を図るために収益分析用ツールを実装した時のお話をご紹介したいと思います。

開発以前では、Google Ad ManagerからレポートダウンロードしてExcelでフィルタをかけて分析したいデータを見ていました。 分析をする度にレポートをダウンロードして作業を行うのではなく、自動でデータが入り分析ができるツールが欲しいというのが広告チームから要望でした。

大まかな要件としては、以下のようなものがありました。

  • 広告枠ごとに分析ができること
  • CPMやViewable Rateといった収益関連の数値が見れること
  • アクセスしたユーザーのOSがわかること
  • データは毎日更新されて欲しい

システム構成図

実装したシステム構成は以下の通りです。

f:id:allabout-techblog:20210323172825p:plain
集計バッチ システム構成図

主な流れとしては、 バッチでAPIからデータ取得と加工をしてデータベースへ格納、Data StudioからSQLを発行してデータベースからデータを取得します。

使用技術

  • Data Studio: Googleが提供しているBIツールです。Google Analyticsなど様々なリソースを取り込んでWeb画面にデータを簡単に表示することができます。
  • GKE: コンテナ化されたアプリケーションの実行環境として使用します。
  • CronJob: 決められた時間でJobを生成します。Jobがバッチを実行するポッドを生成します。
  • Laravel: 社内で主に使われているPHPフレームワークになります。
  • Cloud SQL: Googleが提供しているクラウドデータベースです。

開発を振り返って

大まかな開発の流れを紹介しながら、振り返りをして見たいと思います。

1.要件定義

広告運用チームのメンバーがどんな数字をどう見たいのかすり合わせをします。

ミーティング中は、普段広告チームが使う専門用語が多く登場します。 先述したCPM広告数字は何で、どういった計算で求められるかといった話を聞きながら要件に落として行きます。

当時、初めて聞く用語が多く把握するのに苦労した記憶があります。

また、広告用語に加えてAll Aboutで出している広告枠はどれくらいあるのかといった社内固有の知識も必要でした。 技術的な視点とそういったビジネス側の知識が、開発に必要なことを学びました。

2.インフラ・アプリ設計と見積もり

アプリはどの環境で動かすのか、工数はどのくらいになるのかメンバーと見積もりをします。 オールアバウトでは、クラウドインフラをSREチームが管理しています。SREチームに依頼する必要があるタスクの洗い出しもここで行います。 どういった工程が必要か、感覚が掴めずこのフェーズはチームメンバーに決めてもらった部分が多くありました。

3.実装

基本的に実装はペアプロかモブプロでした。 組んでいたロジックが破綻して、私が崩れ落ちそうになったのをペアプロしていた先輩が解決策を見つけてくれたのをよく覚えています... PRでもレビューを受けますが、コードを書きながら仕様に漏れがないかお互いに点検できていたという点で良い進め方ができたと思います。 またAPIから取得したデータの単位がマイクロ円(100万倍した桁)だったり、実装フェーズはやはり記憶に残っていることが多いです。

設計の面だと、このクラスはどこに実装するのが適切か、といった設計の部分で先輩エンジニアと頻繁に意見交換しながら進めました。 個人開発のように自分だけで開発する時はレビューを受けることがないので、多くのフィードバックをもらえたのは嬉しい経験でした。 サービス層・モデル層で何を処理するのか、徐々に先輩エンジニアと認識があって質問、実装でトライができた時成長できている実感を持てました。

また、保守性の高いアプリにするために、妥協せずにレビューを受けずに進めていく反面、 締め切りから逆算して、もらったレビューを採用しない判断も必要になっていくことを学びました。

4.結合テスト

成果物に対して要件を満たしているか、バグがないかテストします。

今回の場合、バッチでCloud SQLへ格納したデータを、Data Studioから取得するようにします。 要件にあったデータが表示されているか確認するために、用意しておいたテストケースを元にData Studioの画面を操作します。

5.リリース

実装・テストが終わったあとはいよいよリリースです。

リリース後、広告チームで実際に使用されて便利になったという話を聞いた時はやはり嬉しかったです。

技術的につまずいた話

開発中につまずいて、知見になった話を少しだけ紹介したいと思います。

今回の実装では、GKEにデプロイされたLaravelアプリケーションに、あらかじめ定義したartisanコマンドをCronJobを使って定期実行するように実装を行いました。 実装したartisanコマンドは、オプションに日付を渡すことで取得するデータの範囲を指定することができる作りにしていました。 そのため再実行する際には、ターミナルからコマンドを打つ時に日付を渡してJobを生成する想定でした。 しかしJobをコマンドで生成する時に、オプションを渡す方法がわかりませんでした。 残念ながら、コマンド打っての再実行方法は見つけることができませんでしたが、以下に設定ファイルの一部を紹介します。

cronjob.yaml(一部)

command: ["/bin/sh", "-c"]
    args: ["php artisan `実行コマンド` {date}] // Laravelで実装されるコマンド 引数に日付を渡す

Jobをコマンドから生成したい場合には、下記のようなコマンドを使用します。 ただオプションを渡す方法が見つからない...

kubectl create job {再実行用に作成するjob名} --from=cronjob/{cronjob名} --namespace={namespace}

想定していた再実行の方法はできませんでしたが、CronJobはGCPコンソールからGUIyamlの修正及びJobの再生成が可能です。

ただターミナルからコマンド1つで再実行できるようにしたいですね...

GAS会

取り組んだ業務からもう一つGAS会を紹介します。

GAS会とは?

GASはGoogle App Scirptの略称です。

週に一度、エンジニアと編集・企画の社員が参加するGoogle App Scriptの勉強会です。

どうして始まったか

エンジニアではなくてもスクリプトを書いてデータの分析や自動化をしたい!というのが動機です。 GASは非エンジニアでも比較的馴染みやすく、社内で頻繁に使われるスプレッドシートを扱うことができるので、今回の動機とはあっていました。 私はエンジニアなので、参加者の先生役に近い立場で参加しています。

どんなことをしたのか

作りたいもののイメージをヒアリング

最初にゴールを示すために、ざっくりではありますが参加者にどんなものを作りたいのかイメージしてもらいました。 普段の業務で手間になっていることの中で、プログラムで解決できそうなものを記入用のシートを作成してもらいました。 その中でGASで解決できるか、開発規模が大きすぎないかといった観点で、振り分けを行いました。

開発規模が大きいものはエンジニアチームが手を動かして開発・保守するため、そういったものがないか確認するためにもここでヒアリングをしました。

勉強開始!

早速その後はGASの勉強に入りますが、変数や配列を知らない方がほとんどだったので、まずはGASのベースであるJavaScriptの基本的な知識を勉強してもらいました。 資料はこちらの記事に記載されているものを使用させていただきました。 https://qiita.com/sakaimo/items/4eee96ed254f42ba88c1

10分交代で資料の輪読・コードの実践をしてもらいました。 資料の中から参加者の方が作りたいものをに合わせて勉強項目を選定しました。以下に取り上げた項目を記載します。

実装スタート

一通り基本を勉強したあとは、再度作りたいものをヒアリングして実装をします。 参加者個々に作りたいものやレベルが異なるので、私と参加者の1対1でやることを洗い出しました。 「新規のスプレットシートを作成しよう」といった小さくて簡単なステップから、どんなことを調べれば良いかなど必要な作業を具体化していきます。

GASの基礎を勉強する時は輪読のスタイルを取りましたが、実装に入ってからは各自が勉強することを決めて進めるもくもく会のスタイルに移行しました。

参加者からの質問を都度受けて、必要に応じて画面共有しながら一緒にコードを書きます。

現時点で実装してもらったものとして、Webサイトのスクレイピング処理の定期実行などがありました。

進める上で感じたこと

3月末まで実施予定なので、まだ途中ではありますが今まで感じたこと書きたいと思います。

教えるの慣れてない問題

1年目は先輩に"教えてもらう時間"が多くありますが、教える側になることは基本的にないです。 そのため教える側になったのは初めてでした。その中で感じたことがいくつかありました。

1.エンジニア用語は使わない

APIを"叩く"とか、"要素をスライスして"とかは伝わりづらいです。

2.視覚的に理解できるように工夫する

図を用意したり、コードを書いて出力するまでを画面共有で見せたりしました。 変数にどんなデータ構造の値が入っているのか細かくダンプして、コードを理解するペースを合わせるようにしました。

3.ゆっくり喋れ

これはそのままですが...

参加者の方がすぐにわからなかったり、コードを書く手が止まってしまう時に私に謝られることがありました。 わからないことは全く問題ないですし、参加者の思考のスピードと同じスピードで喋る方が伝わりやすいです。

エンジニアに囲まれない時間は新鮮

普段はやはりエンジニアと会話をする時間が長いです。 そんな中、エンジニアは自分だけという時間は新鮮でした。 参加者の方がどんな業務をされているのか、技術で解決できそうなことに困っていないか聞いたりすることができる時間は楽しいです。

終わりに

新卒1年目で行った業務を紹介しました。

大学は文系で周りにプログラミングをやっている知り合いが少なかったということもあり、エンジニアの先輩に囲まれて仕事ができるのは嬉しかったです。 また、自分から聞きに行けば先輩エンジニアからはたくさんのフィードバックをもらうことができます。 今回紹介した分析ツールの話もその一例でした。

GAS会では基本的に実装作業はしませんが、要件を利用者と相談しながらプロダクトを作っていくという点で良い訓練になっています。 フルリモートワークということもあり、エンジニア目線で編集・企画職の社員が困っていることを感じにくい状況になっています。 その点で自分の持っている知識を生かしながら、社内の業務改善に繋がるような活動は続けていきたいと思っています。

お読みいただきありがとうございました。