オールアバウトTech Blog
株式会社オールアバウトのエンジニアブログです。
2023-05-16T11:00:00+09:00
allabout-techblog
Hatena::Blog
hatenablog://blog/6653812171393301499
Digital Native Leader’s Meetupに参加しました
hatenablog://entry/4207575160649158751
2023-05-16T11:00:00+09:00
2023-05-16T11:00:00+09:00 こんにちは。株式会社オールアバウトでデータ基盤チームに所属している吉井です。 先日、Google Cloud 主催「Digital Native Leader’s Meetup」に参加してきました。 同名のイベントは昨年12月に開催されており、今回はその第2弾という位置付けとなっています。 第1弾については 株式会社 Magic Moment様の記事 が参考になるかと思います。 普段Google Cloudを活用してデータ基盤を構築しているエンジニアが、イベント参加者の視点で当日の様子をレポートしたいと思います! Digital Native Leader’s Meetupとは Google …
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20230515/20230515192031.jpg" width="1200" height="901" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>こんにちは。株式会社オールアバウトでデータ基盤チームに所属している吉井です。</p>
<p>先日、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloud 主催「Digital Native Leader’s Meetup」に参加してきました。</p>
<p>同名のイベントは昨年12月に開催されており、今回はその第2弾という位置付けとなっています。</p>
<p>第1弾については <a href="https://zenn.dev/magicmoment/articles/google-digital-leaders-202212">株式会社 Magic Moment様の記事</a> が参考になるかと思います。</p>
<p>普段<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudを活用してデータ基盤を構築しているエンジニアが、イベント参加者の視点で当日の様子をレポートしたいと思います!</p>
<h1 id="Digital-Native-Leaders-Meetupとは">Digital Native Leader’s Meetupとは</h1>
<p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudが主催したエンジニア向けの招待制Meetupイベントです。</p>
<p>これからのデータ戦略や、データ基盤の構築、運用を担うデータエンジニアやデータサイエンティスト同士が集い、語り合える場を提供します。</p>
<p>今回のテーマは「データアナリティクス」。</p>
<p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloud製品の最新アップデート情報や参加者同士のアンカンファレンス、さらにはデータにまつわるLTを通して、各社の事例や話を交換し合うことでプロダクト開発を加速させることが目的です。</p>
<p>場所は<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> 渋谷オフィスでのオフライン開催ということで、オンラインのイベントが多い中、オフラインのイベントは大変新鮮でした!</p>
<h1 id="会場の様子">会場の様子</h1>
<p>飲み物はジュースからお酒まであり、食べ物も目移りするほど充実した内容...!</p>
<p>食べ物については一口で食べやすいラインナップとなっていて、イベントに集中できるような流石の配慮。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20230515/20230515183734.jpg" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h1 id="イベントトピック">イベントトピック</h1>
<h2 id="Google-Cloudから共有"><a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudから共有</h2>
<p>詳しくは書けないのですが、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudユーザにとって嬉しい今後の情報と近年話題になっているデータメッシュのお話でした。</p>
<p>先行して<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudのうちどこに注力しているかが分かるのは、ユーザ目線<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A4%AB%A4%E9%A4%B7">からし</a>てもとてもありがたいです。</p>
<ul>
<li><a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloud最新アップデート情報
<ul>
<li>BigQuery - Autoscaling, Object Tables, ML</span></li>
<li>Cloud Logging - Log Analytics</li>
<li>Cloud Composer - Data <a class="keyword" href="https://d.hatena.ne.jp/keyword/lineage">lineage</a></li>
<li><a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloud Marketplaceから利用できるData Analytics系のISVを紹介</li>
</ul>
</li>
<li>データサイロとデータメッシュの話
<ul>
<li><a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudを活用して解決するデータサイロ</li>
</ul>
</li>
</ul>
<h2 id="LT">LT</h2>
<p>普段から業務で<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudを活用している企業様が、LT形式でデータの活用事例についてお話しして下さいました。</p>
<ul>
<li>行動情報xBigQuery×大規模<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B8%C0%B8%EC%A5%E2%A5%C7%A5%EB">言語モデル</a>で叶えるパーソナル<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%B7%A5%A7%A5%EB%A5%B8%A5%E5">コンシェルジュ</a>
<ul>
<li>BigQueryとRemote Functionsの組み合わせによってレコメンドエンジンを構築</li>
</ul>
</li>
<li>Data Analytics 製品の活用方法について
<ul>
<li><a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudのサービスをフル活用して社内外の要望に答えた</li>
</ul>
</li>
<li>アナリストではない本日参加している<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a>メンバーがデータ分析にどう向き合っているか
<ul>
<li>営業職の方がデータをどう活用しているか</li>
</ul>
</li>
</ul>
<p>LTは第2回の今回から初めて設けられましたが、短い時間ながらも密度の濃い有益な情報盛りだくさんなお話でした。</p>
<p>まだまだ<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudを活用できる幅はたくさんあるのだということを痛感しました!</p>
<h1 id="アンカンファレンス">アンカンファレンス</h1>
<p>事前のアンケートを踏まえてグループ分けされており、約40名の参加者が1グループ5,6人に分かれて主に以下のようなことについて話し合いました。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20230515/20230515183751.jpg" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>↓ <a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a>の社員さんがファシリテートし、各グループごとに白熱した議論をしている様子(プライバシー保護のため、写真にはぼかし加工を施しています)</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20230427/20230427133811.jpg" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>イベント参加者全体だと、データエンジニアやアナリティクスエンジニアが多くの割合を占めていたと思います。</p>
<h2 id="グループメンバー">グループメンバー</h2>
<p>私以外には、データ基盤を運用しているデータエンジニア、アナリティクスエンジニアを経て今はデータプロダクトのマネージャー、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B5%A1%B3%A3%B3%D8%BD%AC">機械学習</a>エンジニアなど多種多様な職種の方が集まっていました。</p>
<h2 id="議題">議題</h2>
<ul>
<li>データの活用例</li>
<li>活用事例における<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudの<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a></li>
<li>課題に感じたこと、それに対する解決方法はどんなことをしたか</li>
<li>使っている<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudサービスや最近気になっているサービスなど</li>
</ul>
<h2 id="具体的には">具体的には</h2>
<ul>
<li>データ活用側の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EA%A5%C6%A5%E9%A5%B7%A1%BC">リテラシー</a>とどう向き合っている?
<ul>
<li>Looker Studioで<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C0%A5%C3%A5%B7%A5%E5">ダッシュ</a>ボード用意してどうにか対処しているなぁ</li>
</ul>
</li>
<li>データ基盤を整える上で困っていることがたくさんあって...</li>
<li>ComposerやPub/Subにおけるサービス起因のデータ欠損に悩まされてる
<ul>
<li>膨大なデータを取り扱う場合のデータ整備って難しいよね</li>
<li>→ BigQueryでクエリの実行時間が大幅に短縮した</li>
</ul>
</li>
<li><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EA%A5%CD%A1%BC%A5%B8%A5%E5">リネージュ</a>などを含めたデータへの理解不足をどう解決している?</li>
<li>会社におけるデータの位置付けは?
<ul>
<li>意思決定のためなので正確なデータは必要なく、ある程度の担保がされていれば良いとしている</li>
</ul>
</li>
</ul>
<p>行っている事業は違えど、皆さんデータに対して同様の課題を抱えており「いや、弊社もそれで困っていて〜」と共感の嵐。その上で「弊社ではこうやって対処していますよ」という風に解決策を議論していた有益な時間でした!</p>
<h1 id="懇親会">懇親会</h1>
<p>イベント終了後、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudのすぐ近くにあるお店に移り、懇親会が開催!</p>
<p>参加者は<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudの社員さんも含めて30人程で、人数がガクンと減りがちな懇親会でも参加率が高い印象を受けました。<br/>
私もですが、オフラインの貴重さをみなさん感じていたのでしょうか...?</p>
<p>懇親会では以下のようなトピックが話されていました。</p>
<ul>
<li>データメッシュ
<ul>
<li>データの<a class="keyword" href="https://d.hatena.ne.jp/keyword/%CC%B1%BC%E7%B2%BD">民主化</a></li>
</ul>
</li>
<li>データのコラボレーション(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C3%A5%C8%A5%D7%A5%EC%A5%A4%A5%B9">マーケットプレイス</a>)</li>
<li>今後のイベントのア<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>
<ul>
<li>Kaggle的なデータ分析(各企業が持っているデータを使って)</li>
<li><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%AB%A5%BD%A5%F3">ハッカソン</a>とまではいかなくともア<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>ソン(各企業が持っているデータを組み合わせて新たな価値を作り出す)</li>
</ul>
</li>
<li>データリネージ</li>
<li><a class="keyword" href="https://d.hatena.ne.jp/keyword/Cookie">Cookie</a>について</li>
<li>ガバナンス管理
<ul>
<li>マスク</li>
<li>個人情報の保護</li>
<li>統一されたデータ</li>
<li>データの正しい理解と使い方</li>
</ul>
</li>
<li>ChatGPTを主としたLLMの話題
<ul>
<li>サービスへの活用</li>
<li>自社データによる信頼性の担保</li>
</ul>
</li>
<li>データの現在と未来の話</li>
</ul>
<p>特に、トレンドのLLMや、最近特に注目されているデータメッシュやコラボレーションについての話題が熱く語られていました。
さらにはイベント好評につき、今後のイベントのア<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%C7%A5%A2">イデア</a>の意見が出ていたりもしました。</p>
<p>参加者の中には様々な業種・役職の方が集まっていたかと思います。<br/>
ですが、アンカンファレンスや懇親会では最初の緊張感はあれど、次第に話が盛り上がっていき全員がお互いに意見を投げかけあっていたことがとても印象的でした。</p>
<p>やはり「データ」に関わる技術領域は広く、業種・役職関係なく話し合いたいことが数多く積もっているようです。</p>
<h1 id="最後に">最後に</h1>
<p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Cloudの活用事例やソリューションを数多く知ることができる、とても良いイベントでした。
特に、アンカンファレンスでは各社のデータ活用事例について有益な生の声を聞けたため、大変満足度が高かったです。</p>
<p>今回得たノウハウを自社のプロダクトにも活かしていきたいと思います。</p>
allabout-techblog
新卒エンジニアとしての苦悩と成長
hatenablog://entry/4207112889976273245
2023-03-31T00:00:00+09:00
2023-03-31T09:36:23+09:00 はじめに オールアバウトグループの新卒1年目エンジニアが投稿する企画『テックブログ新卒週間2023』最終日4日目の投稿です。 株式会社オールアバウトでデータ基盤の運用・保守を行っている吉井と申します。 元々データに興味があり学生時代に分析や機械学習を学んでいましたが、データの基盤どころか、Webに関する知識も疎い状態でのスタートでした。 新卒として1年のうちにどんなことを学び、結果的にどんな成長を実感できたかをお話ししたいと思います。 チームの体制と業務内容 データ基盤グループにはメインで動けるのは2名、兼務の方が1名の合計3名が所属しています。 また、チーム全体で主に以下の業務を担当していま…
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20230330/20230330195936.png" width="1200" height="680" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h1 id="はじめに">はじめに</h1>
<p>オールアバウトグループの新卒1年目エンジニアが投稿する企画『テックブログ新卒週間2023』最終日4日目の投稿です。</p>
<p>株式会社オールアバウトでデータ基盤の運用・保守を行っている吉井と申します。</p>
<p>元々データに興味があり学生時代に分析や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A1%B3%A3%B3%D8%BD%AC">機械学習</a>を学んでいましたが、データの基盤どころか、Webに関する知識も疎い状態でのスタートでした。</p>
<p>新卒として1年のうちにどんなことを学び、結果的にどんな成長を実感できたかをお話ししたいと思います。</p>
<h1 id="チームの体制と業務内容">チームの体制と業務内容</h1>
<p>データ基盤グループにはメインで動けるのは2名、兼務の方が1名の合計3名が所属しています。</p>
<p>また、チーム全体で主に以下の業務を担当しています。</p>
<ul>
<li>データパイプライン(収集から加工処理、BIツールや外部アプリへのデータ送信といった一連のデータ処理の流れ)をメインとしたインフラの運用・保守</li>
<li>BIツールを活用したデータビジュアライゼーションと他部署へのサポート</li>
</ul>
<p>ですが、データ基盤グループが担う領域は幅広く、それ以外にも以下のようなことを行っています。</p>
<ul>
<li>広告運用グループと直接やり取りしながらクライアント用のレポートデータを出力・共有</li>
<li>サービス上で見たいデータについての<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D2%A5%A2%A5%EA">ヒアリ</a>ングやその対応</li>
<li>全社的にデータ活用をより推進するための促進活動</li>
</ul>
<p>このような業務領域の幅広さに加えて、タスクの工程として以下のように構想から実対応までほぼ全てを自分達で行う形式を取っています。</p>
<ol>
<li>自分達で課題を考え挙げ出す</li>
<li>課題の優先順位を決める</li>
<li>最終的にそれをどうやって対処するかを決める</li>
<li>実際の対応</li>
</ol>
<p>そのため、適切な対処をするには業務知識だけでなく業界や技術的な知識など数多くのことを理解している必要があります。</p>
<p>これらの業務をメインで動けるのはマネージャーと自分の2人という状況もあり、不安を抱えながらもやれることの多さに胸を踊らせながらチームにジョインしました。</p>
<h1 id="一年の流れ">一年の流れ</h1>
<p>知識を身に付けていた前半の期間と、その知識を実践に活かす後半の期間に分けてお話しします。</p>
<h2 id="前半-学び編">前半 ~学び編~</h2>
<p>早速ですが、アプリケーションの開発とは異なり、データ基盤はなかなか実際に手を動かしながら学ぶということが難しいです。
体系化されている他社さんもいらっしゃるかもしれません。
ですが、少なくとも弊社では経験のあるエンジニアがデータ基盤を担当してきた経緯があり、私のような知識がない新人が自分の力だけで理解を進めるための地盤は確立されていませんでした。</p>
<p>実際に行った業務知識の付け方としては、とにかく地道に見て学んで疑問があったら質問をするという手当たり次第な方法です。</p>
<p>データパイプラインの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>を学び、マルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>であるため様々な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>サービスやいくつかのBIツールなどに簡単に触れてみることから始めました。
データの流れや意図を知るには自社サービスの仕組みや実際の画面上での操作も知っておく必要があるため、そういったことを教えていただきながら少しずつ知識を蓄えていきました。</p>
<h3 id="課題とその解決">課題とその解決</h3>
<h4 id="1業務理解">1.業務理解</h4>
<p>始めは、得た知識が一般的なことであるのか自社独自の仕組みなのかが判別しきれず、業務知識を理解する際の妨げになっていたことが課題に感じていました。</p>
<p>このような問題に対しては積極的に状況の切り分けを目的に質問してみたり、一般的なことであれば自分で調べ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a>を自分なりに理解し、自社状況に改めて落とし込むということを行うことで一歩一歩解決していきました。</p>
<h4 id="2データ構造とモデリング">2.データ構造と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%C7%A5%EA%A5%F3%A5%B0">モデリング</a></h4>
<p>また、データ基盤の3層構造(データレイク・データウェアハウス・データマート)を採用しており、主に Treasure Data と <a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a> の2つの環境を利用しています。</p>
<ul>
<li>Treasure Data : ログデータの蓄積と加工</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a> : 最終的に用途に合わせてテーブルごとに集計されたデータを格納</li>
</ul>
<p>ここで強く課題に感じたことは、あるデータを抽出したいとなった時に「どちらの環境のどのDBのどんなテーブルからどんな条件でデータを取ってくればいいか」という判断がとても難しいということでした。</p>
<p>この課題に対して、まず大枠の環境ごとに格納されているデータの役割を理解し、その中の各層に分けた上でこの層とこの層との間では何を目的にどういった処理をしているかといった意味を理解するよう努めました。
これにより、対象のデータが欲しい時は大体ここを見にいけば良い、という感覚を身に付けることができました。</p>
<h2 id="後半-実践編">後半 ~実践編~</h2>
<p>色彩あふれる紅葉が見られるようになった10月頃のことです。</p>
<p>データの収集から最終的な活用先のイメージが付いてきたため、既存のデータ基盤の改善や社内でのBIツールのサポート等を実際に行いました。</p>
<h3 id="良かったこと">良かったこと</h3>
<p>開発用に作った環境は数知れず、と言えるほど多くの環境を作り上げる経験をしました。
基本的に、何かを検証をしたり技術的な調査をするときには都度GCEを使って立ち上げた新たな<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>に環境を構築したり、ローカルにDocker環境を作った上で作業を行っています。</p>
<p>もちろん適宜分からないところは追加で調べたりしましたが、前半期にデータにまつわることと並行して学んでいた Docker の基礎知識が大変役に立ちました。
Docker はエンジニアにとって今や普遍的な技術となっているため、業務を通して最低限使いこなせるようになり、それを自分で試行錯誤してみる経験ができたのは1エンジニアとして良い財産になると感じています。</p>
<h3 id="大変だったこと">大変だったこと</h3>
<p>私は、データ基盤の改修を目的としてdbtというワークフローツールの調査・共有を基本的に一人で行いました。
ですが、自社の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>との相性が悪く、色々なことを加味して今は組み込むことができないという結論に終わってしまいました。
dbtはモダンデータスタックとして最近注目が集まっているツールでありデータエンジニアとして楽しみにしていた部分と、自分が調査したゴールが「現状では導入できない」というチーム全体にとっても悔しい結果に終わりました。</p>
<p>この出来事は、会社やチーム全体の今後のことも踏まえた上で意思決定しなくてはいけないという業務の難しさを味わった瞬間でした。</p>
<h1 id="業務以外の活動">業務以外の活動</h1>
<p>業務とは別に以下の2つを継続的に行っています。</p>
<ul>
<li>勉強会 : 月に平均して3,4つの勉強会への参加または視聴をし、要約や感想・疑問をアウトプットとして times に投稿</li>
<li>単語帳 : 口頭で誰かに説明するには自信がないような理解不足な単語をとにかくシートにまとめて、ひとつひとつ調べていく</li>
</ul>
<p>勉強会は主にデータにまつわる技術的な内容をカバーする目的です。
昨今では<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AB%A5%A4%A5%D6">アーカイブ</a>が残る勉強会も多くなり、活かせるものは活かして効率的に知識の獲得に繋げました。</p>
<p>単語帳に関して、自社で現在扱っているものは学ぶことができますが、優先順位的にまだ触れられていない技術やそもそも現在の業務だけでは得られない知識がたくさんあります。
以下のような技術的なことから一般的なことまで、領域を定め切ってしまうのではなく、とにかく気になったものは何でも楽しく身に付けようという意識で学びました。</p>
<ul>
<li>他社でのデータパイプライン・データ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%C7%A5%EA%A5%F3%A5%B0">モデリング</a></li>
<li>データ活用やサービスの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a></li>
<li>様々なサービスやツール</li>
<li>ビジネス用語</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D4%A5%E5%A1%BC%A5%BF%A5%B5%A5%A4%A5%A8%A5%F3%A5%B9">コンピュータサイエンス</a></li>
<li>アプリケーション開発</li>
</ul>
<p>単語の数はこの1年を通して700を超え、自分でも驚きと達成感を感じています。
また、密かに目標にしている、自分の業務とは直接関係ない話の輪に入ることができる状態も目指して、今後もこれらの活動は続けていこうと思っています。</p>
<h1 id="成長を感じた出来事">成長を感じた出来事</h1>
<p>一年間業務を通して様々な経験や学びがあったと同時に、まだまだ未熟だと感じる時はあります。
ですが、業務を通して得られた知識はもちろんのこと、自主的に学んできたことがきちんと身に付いていると確かな実感として持てた瞬間もありました。
それは、3月24日に <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> 主催の Digital Native Leaders Meetup という、データにまつわる <a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a> サービスのアップデート情報や各社の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a>について話し合うオフラインイベントに参加してきた時のことです。</p>
<p>イベントの参加レポートは後日、このテックブログで公開させていただきたいと思っています。</p>
<p>そこで、新卒の身でありながら他社のエンジニアの方々に対して対等に議論できるようになっていることに気付きました。
一年前の自分が参加していたら、議論どころか言葉の意味も分からず聞くことに徹していたと思うと、確かな成長を感じた出来事です。
また、その議論を通して他社の方からも、新卒なのにデータのことにとても詳しいとお褒めの言葉をいただき、この一年やってきたことがきちんと身に付いていることを実感しました。</p>
<h1 id="おわりに">おわりに</h1>
<p>これからは「新卒なのに」の部分が無くなります。
今後は一人のデータエンジニアとしてより深い知識と経験を身に付け、自分なりの価値を提供していきたいと思います。</p>
allabout-techblog
オールアバウト新卒エンジニアが1年で学んだこと
hatenablog://entry/4207112889975954899
2023-03-30T00:00:00+09:00
2023-04-03T09:45:35+09:00 はじめに 初めまして、株式会社オールアバウトでWeb開発をしている@r_chibaです。 2022年度から新卒のエンジニアとして働きはじめて早1年経ちました。今回は業務をしていく1年間の中で、苦労したことや学んだことや、日々の業務をどのように行っているかなど、色々とつづっていければと思います。 自己紹介 小学~高校までは愛知県で過ごし、大学からは長野の大学で学生生活を過ごしていました。 大学の専攻は理系分野ではありましたが、Webエンジニアとして使用していくプログラミングに関しての授業などはあまりなく、 大学2年時にC言語の授業を受けたぐらいでした。その時の授業でもポインタなどの説明を受けて、…
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20230329/20230329193017.png" width="1200" height="680" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h1 id="はじめに">はじめに</h1>
<p>初めまして、株式会社オールアバウトでWeb開発をしている@r_chibaです。<br/>
2022年度から新卒のエンジニアとして働きはじめて早1年経ちました。今回は業務をしていく1年間の中で、苦労したことや学んだことや、日々の業務をどのように行っているかなど、色々とつづっていければと思います。</p>
<h2 id="自己紹介">自己紹介</h2>
<p>小学~高校までは愛知県で過ごし、大学からは長野の大学で学生生活を過ごしていました。
大学の専攻は理系分野ではありましたが、Webエンジニアとして使用していくプログラミングに関しての授業などはあまりなく、
大学2年時に<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>の授業を受けたぐらいでした。その時の授業でもポインタなどの説明を受けて、よくわからなかったことを覚えています。
大学院1年時にWeb系のプログラミングに興味を持ちはじめたのがきっかけで、自分でサービスを何かつくってみたいと思い、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby%20on%20Rails">Ruby on Rails</a>という
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>を用いて、大学の授業を評価するためのサービスや、自分のblogを作ったりしました。
自分は小学~高校までサッカーをやっていた、体育会系の人間で、あまり自分で何かを作ったりするといったような経験が少なかったのですが、
そういったサービス作りの経験から、ものづくりの楽しさをジワジワと感じ始め、エンジニアを目指そうと思い、オールアバウトにエンジニアとして入社しました。</p>
<h2 id="業務内容">業務内容</h2>
<p>開発部で、Web業界における広告代理店とメディアをつなぐプラットフォームサービスの開発に携わっています。
広告代理店は、商材を売りたいクライアントと商材を宣伝するメディア間との仲介となるものなのですが、その広告代理店とメディアとの間では
スケジュール調整や、非一元的な情報管理・連絡方法等の、雑多・煩雑な業務だったりの課題点が多くあります。
そのような広告代理店とメディアとの間のDX化を推進するための、サービスづくりを日々行っています。
現在は新機能開発の要件定義・設計・開発のタスクを任せていただいております。
業務を行う上で、やりたいと手を挙げたタスクに携われたり、自分の意見がサービスにとって良いものだったときは、その意見が実際にサービスに取り入れられて、反映されたときには、とてもやりがいを感じます。</p>
<h2 id="業務スケジュール">業務スケジュール</h2>
<p>私のある日の業務スケジュールです。基本的にリモートワークで、金曜日の会議が多い日は出社します。
日によって細かい違いはありますが、実装を重点的にやる日はこんなスケジュールです。</p>
<p>9:30~ slackで出社連絡。メールやスケジュールを確認して、1日の動きを把握する。<br/>
9:45~ 開発メンバーで朝会。それぞれのメンバーが1日どんなことを行っていくかなどの動きを確認する。<br/>
10:00~ ペアで実装<br/>
12:00~ お昼休憩。たまに散歩にいったりして、気分転換をする。<br/>
13:00~ ペアで実装<br/>
17:00~ コードレビュー<br/>
17:30~ メンタータイム。メンターの方と1日の振り返りなどをしたりする。<br/>
18:00~ 夕会。開発メンバーで1日の振り返りや、連絡事項を確認。<br/>
18:30~ slackで退勤連絡</p>
<p>私のチームでは主に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">ペアプログラミング</a>の体制をとっています。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">ペアプログラミング</a>は、2人がペアを組んでプログラミングを行なっていく方法なのですが、
1人がドライバと呼ばれる、実際に手を動かして実装をしていく役割の人と、もう一人がナビゲータと呼ばれ、実装の方針などをドライバに指示する役割を担っています。
私が配属された当初ではすでにチームで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>で行なっていく体制ができあがっていましたが、在宅勤務が始まる前は部分的に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>を取り入れていて、在宅勤務に切り替わったのをきっかけに、ほぼ全ての実装を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>に切り替えていったそうです。背景としては、在宅勤務によるコミュニケーション量の減少や、レビュー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%A9%BF%F4">工数</a>の削減などがあったみたいです。</p>
<h2 id="苦労したことや学んだこと">苦労したことや学んだこと</h2>
<h3 id="ペアプロ"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a></h3>
<p>主に配属当初は実装力強化を目標としていたこともあり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>ではドライバーを担当させていただく割合が多かったのですが、ドライバーとしてやっていく中でいくつか苦労した点がありました。まず実装力の点で、実装方法がわからず手が止まってしまってしまうことが多く、気持ち的にも焦ってしまうことがありました。そこで教わったこととして、やりたいことを書き出してみる、そして書き出したやりたいことに対して、必要なことを分割してさらに書き出してみるといった方法です。これは分割統治法と呼ばれる問題解決手法で、難しい問題を細かく分割することで、一つ一つの問題の難易度を単純なものにするというものです。分割統治法はプログラミングにおける大切な考え方の一つであり、自分自身、物事を処理できるワーキングメモリの容量もそれほど大きいほうではないと感じていたので、こういった方法はとても役立ちました。また、実際に自分がやりたいことを口にだしながら、書き出していくと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B8%C0%B8%EC%B2%BD">言語化</a>されていなかった部分も自分の中で整理できて、気持ち的にも落ち着ける効果もあり、現在も行き詰まったときはまずは書き出してみて、一つ一つ処理していくことを実践するように心がけています。</p>
<p>次に、コミュニケーション面で難しいと思った点が、自分が実装しようとしていることをうまくペアの人に伝えられなかったという点です。
理由としては何点かあり、実装方法を考えることに必死で、コミュニケーションをとる余裕がなく、口数が少なくなってしまったことや、実装方法が自分の中でも明瞭に整理できておらず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B8%C0%B8%EC%B2%BD">言語化</a>しようとしたときにできないといったことなどが考えられました。一つ目の実装にいっぱいいっぱいになってしまうことに関しての改善方法としては、実装に入る前にあらかじめ実装ができなさそうな点があれば予習をしてくる、ということを実践しました。予習をしてくることで、余裕が少しだけでてきて、相手にも伝えることが少しずつできるようになっていけるようになってきたのかなと思います。2つ目の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B8%C0%B8%EC%B2%BD">言語化</a>できないといった点に関しては、上に挙げたやりたいことを口にだして書き出してみるといった方法で日々できるようになってきたと感じています。</p>
<h3 id="コードの規模">コードの規模</h3>
<p>それまで個人で開発していたコードは、ファイルの量やコード行も少なく、管理もしやすく、修正も容易でした。しかし、チーム開発に参加すると、他のメンバーが書いたコードを読むことになり、ファイル量やコード量もかなり感じました。その規模の大きさに驚き、どこから手をつけていいのか、何を見ればいいのか戸惑いました。
また、チーム開発では、複数人で同時に同じコードを編集することもあります。その際には、コンフリクトが発生することもあり、手順を守りながらコードをマージしていく必要がありました。個人開発では考えられないような、コミュニケーションや手順の重要性を痛感しました。
しかし、チーム開発を続けるうちに、規模の大きなコードでも、コードの構造やコメントを活用することで読みやすくなることに気づきました。また、チーム開発におけるコミュニケーションの大切さを学び、チームメンバーとの協力や相談を通じて、コードの改善に取り組むことができました。</p>
<h3 id="インプットの多さ">インプットの多さ</h3>
<p>とにかく新しく学ぶ情報が多かったです。技術的なところにとどまらず、リリースやマージでの細かい作業・日々チームとして働いていくための決まりごとなど、当初はインプットする必要のあるものが多くあり、学んだことはメモをとり、次の日の朝に軽く見返すといったことをしていました。
最初はインプットすべきことが無限に感じ、少し不安になることもありましたが、業務を開始して半年ほどたったころから少しだけ心に余裕のない状態から抜け出し、学んだこと一つ一つに対してじっくり考える余裕も少しずつでてきたのかなと思います。</p>
<h3 id="見積もり">見積もり</h3>
<p>私の部署では<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B8%A5%E3%A5%A4%A5%EB">アジャイル</a>開発を導入しており、2週間に一回タスクをいただく機会があるのですが、その際にタスクにかかる見積もりを出す必要があります。
この見積もりというものが最初はとても難しく、見積もり段階では2時間かかると思っていたものが倍の4時間かかったりと、想定よりも見積もり時間がオーバーしてしまうことを課題点に感じました。なので、見積もり精度を向上させなければと思い、どのように見積もりを立てているかを先輩に伺ったところ、タスクの粒度を細かくすることが大切と教わりました。当初は全体で〇〇時間かかりそうというぼやっとした憶測で見積もりをたてていたのですが、タスクを細かく分割して、「この実装のためにはこの関数とテストが必要で、全部足したら〇〇時間かかる」といったふうに、詳細な実装イメージを持ちながら行うといいと知り、見積もり精度の向上に役立ちました。
見積もり精度はまだまだ改善の余地があるので、日々立てた見積もりのズレに対して原因を考えていき、精度向上に努めていければと思います。</p>
<h2 id="技術力向上のためにしたこと">技術力向上のためにしたこと</h2>
<h3 id="自分で手を動かしアプリを作る">自分で手を動かし、アプリを作る</h3>
<p>実装力が当初なかったことを課題に感じていたので、どうやったら力がつくだろうと色々と調べたり、先輩に「どうやったら実装力つきますか?」と聞いたりして、自分が実践していく中で一番しっくりと来ているのは、わからないことがあったり、作ってみたいものがあったら「実際に手を動かして作ってみる」です。自分の手を動かさず、コードを読んだり、知識を蓄えるインプットだけだと、理解したような気分になり、いざコードを書こうと思うと、思ったように手が動かないことが多々あります。実際に手を動かしてみることで、実現したいことに対しての検索をし、コードに落とし込む実践力だったり、コードを書いていく中で、悩む点が出てきてここはこうしたほうがよさそう、とコードをどんどんと改造していくことを学んだりできます。そういったことをしていると、他の人が書いたコードが自分が悩んだ点を最適化するように実装されていることに気づいたり、逆に自分だったらこう書くのにといったふうに自分なりの考えもでてくるようになり、色々メリットを享受できていることを感じられたので、このシンプルだけど、強力な方法は私の中でしっくりときています。
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%AF%A5%ED%A5%BD%A5%D5%A5%C8">マイクロソフト</a>で働き、現在のosに多く採用されているダブルクリックや<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E9%A5%C3%A5%B0%26amp%3B%A5%C9%A5%ED%A5%C3%A5%D7">ドラッグ&ドロップ</a>を生み出した日本人エンジニアである、中島聡氏も「僕は何かを学ぶ際は必ず手を動かしながら、考え学んでいる」とおっしゃっており、優秀なエンジニアも頭の中だけで考えず、実際に手を動かして学んでいたりします。</p>
<p>私が具体的に行ったことは、業務の中で自分自身が苦手と感じていることや、学びたいと思っている技術分野のアプリを作ったりしました。
以下に私が作成したアプリを紹介してみます。</p>
<h3 id="Pomodoro-timer">Pomodoro timer</h3>
<p>Pomodoro timerとはタスク集中手法の一つです。人間の集中力の限界は25分といわれているのですが、pomodoroは25分作業5分休憩をワンセットにし、集中力をできる限り切らさずにタスクを行うことができます。
このpomodoro timerのアプリを作った理由は、当時業務を行う中で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Javascript">Javascript</a>を触る機会が多かったのですが、手が止まることも多く、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Javascript">Javascript</a>に慣れるためになにか自分の手で動かして作ってみようと思ったがきっかけです。</p>
<h3 id="Firebase-Realtime-Databaseを使ったリアルタイムアプリケーション">Firebase Realtime Databaseを使ったリアルタイムアプリケーション</h3>
<p>Firebase Realtime Databaseとは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>が提供しているFirebaseと呼ばれるプラットフォームのサービスの一つであり、リアルタイムアプリケーションを効率的に構築することができます。業務でもこのサービスを使用したので、勉強のためにこの技術を使ったWebアプリを作ってみました。
タスク管理系(trelloみたいな)のアプリを<a class="keyword" href="http://d.hatena.ne.jp/keyword/Javascript">Javascript</a>、Laravel、Firebase Realtime Databaseを用いて作成したのですが、実装していく中で、Firebase Realtime Databaseの使い方や、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Javascript">Javascript</a>のファイル管理の方法を考える機会もあり、いい学びになりました。
また、オールアバウト全体の開発部勉強会が月に1回開かれるのですが、その勉強会に登壇した際に、このアプリで苦労したことを共有した際に、
色々とフィードバックをいただき、勉強になりました。</p>
<h3 id="学んだこと">学んだこと</h3>
<p>はじめてアプリづくりをするときは何を作っていいのかわからなかったり、また、誰も作ったことのないサービスをつくる必要があるのでは最初は思ったりしましたが、最初は気負わずに世の中にあるアプリを真似たものでも、本当に簡単なものでいいなと思いました。上に挙げたpomodoro timerもweb上サービスとして既にあるものですが、実装をしていく中で新しい発見や自身の実装力向上のいい機会になったと感じています。まずは、自分が実現したいと思ったものをコードに落とし込んで、形でできるようになることが、エンジニアとしてのファーストステップであるのかなと個人的に思います。</p>
<h2 id="最後に">最後に</h2>
<p>今回は、自分自身が新卒エンジニアとして働いている1年間の中で、苦労したことや学んだこと、業務内容や日々の業務について紹介しました。
この1年間で学んだことを活かし、今後もさらに成長していけるよう、日々努力していきたいです。</p>
allabout-techblog
GCPを1ミリも知らなかった新卒が業務で学んだ知識でデプロイできるようになるまで
hatenablog://entry/4207112889974332029
2023-03-29T00:00:00+09:00
2023-03-29T00:00:15+09:00 はじめに オールアバウトグループの新卒1年目エンジニアが投稿する企画『テックブログ新卒週間2023』2日目の投稿です。 オールアバウトでPrimeAd関連サービスの開発をしているhinakochiです。 サービスの一つのリビルドに関わる中で、アプリをGKEでデプロイする経験をしました。入社するまでGCP自体ほぼ触ったことがなかったので、当時はついていくので精一杯になってしまいました。改めて何が起こっていたのかを理解するため、一度最初から最後までを自分でやりきりたいと思いました。約3ヶ月間、主に平日に一日一時間程度を使って簡単なアプリのデプロイに挑戦してきたので、これを機にその過程と学んだことを…
<p><figure class="figure-image figure-image-fotolife" title="バナー"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20230324/20230324104801.png" width="1200" height="680" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p>
<h1 id="はじめに">はじめに</h1>
<p>オールアバウトグループの新卒1年目エンジニアが投稿する企画『テックブログ新卒週間2023』2日目の投稿です。</p>
<p>オールアバウトでPrimeAd関連サービスの開発をしているhinakochiです。
サービスの一つのリビルドに関わる中で、アプリをGKEでデプロイする経験をしました。入社するまで<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>自体ほぼ触ったことがなかったので、当時はついていくので精一杯になってしまいました。改めて何が起こっていたのかを理解するため、一度最初から最後までを自分でやりきりたいと思いました。約3ヶ月間、主に平日に一日一時間程度を使って簡単なアプリのデプロイに挑戦してきたので、これを機にその過程と学んだことをまとめてみました。遠回りが多くできたことはごくわずかですが、少しでもどなたかの参考になれば幸いです。</p>
<h1 id="使用したもの">使用したもの</h1>
<h2 id="コンテナとアプリ構成-php-fpmコンテナappサーバ--nginxコンテナ-webサーバ--CloudSQL-dbサーバ">コンテナとアプリ構成: <a class="keyword" href="http://d.hatena.ne.jp/keyword/php">php</a>-fpmコンテナ(appサーバ) + nginxコンテナ (webサーバ) + CloudSQL (dbサーバ)</h2>
<p>Laravelのappコンテナとリバースプロキシ用のnginxのwebコンテナを自作イメージを使って立てます。これは業務で関わったものとほぼ同じ構成です。データベースには、本番ではCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a> Auth Proxyで接続します(ローカルでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>コンテナを立てていました)。
今回はデータベースに保存したテキストを取得して表示する簡単なテストページを用意しました。外部<a class="keyword" href="http://d.hatena.ne.jp/keyword/IP%A5%A2%A5%C9%A5%EC%A5%B9">IPアドレス</a>に接続してこれが表示できればゴールとします。</p>
<p>最終的な構成のイメージはこのようになります。
<figure class="figure-image figure-image-fotolife" title="システム構成"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20230328/20230328153918.png" width="1200" height="673" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>システム構成</figcaption></figure></p>
<h2 id="GCPで使用した主なサービス"><a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>で使用した主なサービス</h2>
<h3 id="Kubenetes-Engine">Kubenetes Engine</h3>
<p>コンテナの自動管理ツールです。コンテナの集合体の最小単位をポッド、ポッドを実行するマシンをノード、ノード群を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>ーと呼びます。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>ファイルでポッドの構成やスケーリングの条件などを定義しておき、リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トに応じて自動的にスケールさせることができます。</p>
<h3 id="Cloud-SQL">Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a></h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>ベースのリレーショナルデータベースシステムです。</p>
<h3 id="Container-Registory">Container Registory</h3>
<p>コンテナイメージを保存・管理できるサービス。ただしイメージのストレージ自体はCloud Storageが担っています。(現在はOSパッケージなども保存できるよう拡張されたArtifact Registoryが推奨されています。参考:<a href="https://cloud.google.com/container-registry/docs?hl=ja">Container Registry のドキュメント</a>)</p>
<h3 id="IAM">IAM</h3>
<p>サービスというより、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>の各サービスを使用するためのアカウント体系です。個人、組織、サービスなどの固有のアドレスを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%EA%A5%F3%A5%B7%A5%D1%A5%EB">プリンシパル</a>という概念で並列に扱い、様々な権限を付与します。個人的にはここで一番よく引っかかりました。具体的には、足りない権限が何か、それをどう与えるのかがわからない、IAMのサービスアカウントと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>などサービス特有のアカウントとの関係がわからないなどの点で悩みました。</p>
<p>ちなみに90日間30$分の無料トライアルを利用しました。実は間に合わず期限後少しだけアップグレードすることになったのですが、クレジットが残っている分は引き継げるので大した負担にならなくてよかったです。</p>
<h2 id="その他">その他</h2>
<h3 id="GitHub-Actions"><a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Actions</h3>
<p>CI/CDツール。コードも<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a>で管理しています。</p>
<h3 id="Kustomize">Kustomize</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>ファイルを複数まとめて管理できるツールです。参考にした<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>に登場したので試しに触ってみました。今回はデプロイ環境を一種類しか用意していないのでそこまでメリットはないのですが、ベースの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>ファイルを動的に書き換えて使う方法を学べました。</p>
<h1 id="やったこと">やったこと</h1>
<p>実際の手順を辿りながらハマった部分をピックアップしていきます。ローカルで動くアプリは一旦完成している状態です。</p>
<h2 id="デプロイ前のGCP側の準備">デプロイ前の<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>側の準備</h2>
<h3 id="プロジェクト作成">プロジェクト作成</h3>
<p>ブラウザの管理コンソールで作成しました。
プロジェクトは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>に限らず<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>内の様々なサービスに跨がります。</p>
<h3 id="API有効化Container-Registory-Kubernetes-Engine"><a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>有効化(Container Registory, <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> Engine)</h3>
<pre class="code lang-sh" data-lang="sh" data-unlink>gcloud services enable <span class="synStatement">\</span>
containerregistry.googleapis.com <span class="synStatement">\</span>
container.googleapis.com
</pre>
<p>これで該当サービスが使えるようになります。
この時点でデータベースの実現方法は一旦置いていたのでCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>周りはまだ何もしていません。
このあたりの工程から下記の記事を参考にさせていただきました。</p>
<p><a href="https://qiita.com/yakamazu/items/b98d0ae314869f50a97f">GitHub Actions を使用してGKEにアプリケーションをデプロイする</a></p>
<h3 id="Kubernetesクラスタ作成"><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>作成</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>は作成の際、標準モードとAutopilotモードを選択できます。Autopilotモードは設定しなくとも自動スケーリングやノード管理をある程度やってくれるようです。せっかくなので使ってみましたが、小規模なアプリなので特に恩恵はなかったと思われます。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>は以下の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>を参考に作成できます。</p>
<p><a href="https://cloud.google.com/kubernetes-engine/docs/tutorials/hello-app?hl=ja">コンテナ化されたウェブ アプリケーションのデプロイ</a></p>
<p><a href="https://cloud.google.com/kubernetes-engine/docs/how-to/creating-an-autopilot-cluster?hl=ja">Autopilot クラスタの作成</a></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>作成の過程で誤って飛ばしてしまい、その結果長時間悩むことになったステップを紹介します。</p>
<pre class="code lang-sh" data-lang="sh" data-unlink><span class="synComment"># クラスタの認証情報を取得する</span>
gcloud container clusters get-credentials sample-cluster-name <span class="synStatement">\</span>
<span class="synSpecial">--zone</span> zone-name <span class="synSpecial">--project</span> sample-project-name
</pre>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/CLI">CLI</a>ツールであるkubectlを使用するには<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を選択して接続する必要があります。
この設定ができていないうちは下記のようなエラーが出ており、次のセクションで出てくるような個別のロールの設定が必要なのかとしばらく誤解していました。</p>
<pre class="code" data-lang="" data-unlink>Error from server (Forbidden): deployments.apps "deploy-***" is forbidden: User "***" cannot get resource "deployments" in API group "apps" in the namespace "default": requires one of ["container.deployments.get"] permission(s).</pre>
<h3 id="サービスアカウントの設定">サービスアカウントの設定</h3>
<pre class="code lang-sh" data-lang="sh" data-unlink><span class="synComment"># サービスアカウント新規作成</span>
gcloud iam service-accounts create sample-project-service-account
<span class="synComment"># プロジェクトに対してサービスアカウントとロールを紐づける</span>
gcloud projects add-iam-policy-binding sample-project-name <span class="synStatement">\</span>
<span class="synSpecial">--member=serviceAccount:sample-project-service-account@sample-project-name.iam.gserviceaccount.com</span> <span class="synStatement">\</span>
<span class="synSpecial">--role=roles/container.admin</span>
<span class="synSpecial">--role=roles/storage.admin</span>
<span class="synComment"># サービスアカウントキーを作成&出力</span>
gcloud iam service-accounts keys create key.json <span class="synStatement">\</span>
<span class="synSpecial">--iam-account=sample-project-service-account@sample-project-name.iam.gserviceaccount.com</span>
<span class="synStatement">cat</span> key.json | base64
</pre>
<p>サービスアカウントは各サービスを利用するためのアカウントです。サービスアカウントにプロジェクトにおけるロールを与えると、ロールによってできることが追加されます。container.adminは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a> Engineのオブジェクト全般に対する管理者、storage.adminはCloud Storageに対する管理者ロールです。Cloud Storageはプロジェクト内のオブジェクトを保持するストレージサービスなのでこちらの権限も必要になります。
出力したサービスアカウントキーは<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Actions側でsecretsに登録し、Actionsから操作できるようにします。
※今回は個人的な学習目的の環境なので大きな問題はありませんでしたが、最近はサービスアカウントキーをCI/CDツールに登録することのリスクが指摘されています。<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Actions OIDCや後述のWorkload Identityなどを利用して直接サービスアカウントキーを登録せずに運用することができます。弊社が<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a>で管理しているサービスは<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a> Actions OIDCを利用しています。</p>
<h2 id="appコンテナとwebコンテナのデプロイ">appコンテナとwebコンテナのデプロイ</h2>
<h3 id="Kustomizeの設定">Kustomizeの設定</h3>
<p>ファイル構成は以下の通りです。</p>
<pre class="code" data-lang="" data-unlink>deploy/
- kustomization.yaml
- deployment.yaml
- service.yaml</pre>
<p>kustomization.<a class="keyword" href="http://d.hatena.ne.jp/keyword/yaml">yaml</a></p>
<pre class="code yaml:kustomization.yaml" data-lang="yaml:kustomization.yaml" data-unlink>apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- manifest.yaml
- service.yaml
images:
- name: web-image
- name: app-image</pre>
<pre class="code lang-sh" data-lang="sh" data-unlink><span class="synComment"># kustomization.yamlのあるディレクトリに移動</span>
<span class="synStatement">cd</span> deploy
<span class="synComment"># app-imageというイメージ名変数に使用したいイメージ名を設定</span>
kustomize edit <span class="synStatement">set</span><span class="synIdentifier"> image app-image</span><span class="synStatement">=</span><span class="synIdentifier">gcr.io/</span><span class="synPreProc">$PROJECT_ID</span><span class="synIdentifier">/</span><span class="synPreProc">$IMAGE</span><span class="synIdentifier">-app:latest</span>
<span class="synComment"># web-image</span>
kustomize edit <span class="synStatement">set</span><span class="synIdentifier"> image web-image</span><span class="synStatement">=</span><span class="synIdentifier">gcr.io/</span><span class="synPreProc">$PROJECT_ID</span><span class="synIdentifier">/</span><span class="synPreProc">$IMAGE</span><span class="synIdentifier">-web:latest</span>
<span class="synComment"># deployment等を作成してそれをもとにリソースを更新</span>
kustomize build<span class="synStatement"> . </span>| kubectl apply <span class="synSpecial">-f</span>
</pre>
<p>kustomize edit set imageでkustomization.<a class="keyword" href="http://d.hatena.ne.jp/keyword/yaml">yaml</a>で用意した変数にイメージ名を設定し、変数が置き換わった状態でbuildすることができます。</p>
<p>deployment.<a class="keyword" href="http://d.hatena.ne.jp/keyword/yaml">yaml</a></p>
<pre class="code yaml:deployment.yaml" data-lang="yaml:deployment.yaml" data-unlink>apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-project
labels:
app: app-name
spec:
replicas:
selector:
matchLabels:
app: app-name
template:
metadata:
labels:
app: app-name
spec:
serviceAccountName: sample-ksa
containers:
- name: web
image: web-image # kustomize edit set imageで更新
ports:
- containerPort: 81
volumeMounts:
- mountPath: /var/run/php-fpm
name: nginx-sock
- name: app
image: app-image # kustomize edit set imageで更新
volumeMounts:
- mountPath: /var/run/php-fpm
name: nginx-sock
# 後略</pre>
<p>ちなみに、次のコマンドもbuildができるのですが、buildした結果のdeploymentが出力されるので<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>に役立ちました。</p>
<pre class="code lang-sh" data-lang="sh" data-unlink>oc kustomize
</pre>
<h3 id="正しいイメージを使用できているかの確認">正しいイメージを使用できているかの確認</h3>
<p>デプロイが成功したらまずこれが大事だと振り返ってみて思います。私の場合は、Podが動いていなくてPodの設定まわりを確認するのに時間を費やしてしまったのですが、実はイメージがpushできていない、イメージを指定できていない、古いイメージを使ってしまっているなどのミスがありました。
前セクションのocコマンドで最新のdeploymentを確認できるほか、ターミナルから次のコマンドで実際のPodで使用されているイメージを含む様々な情報を確認できます。</p>
<pre class="code lang-sh" data-lang="sh" data-unlink>kubectl describe pods pod-name
</pre>
<h3 id="コンテナ間通信">コンテナ間通信</h3>
<p>今回は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Unix">Unix</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>ソケットを使用しています。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Unix">Unix</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>ソケットを用いた通信は<a class="keyword" href="http://d.hatena.ne.jp/keyword/TCP">TCP</a>通信より高速で、同じマシン内であればデータ通信用のファイルパスを通すことで通信できます(今回はappコンテナとwebコンテナが同一のマシンに乗っている状態なのでこの方法が可能です)。<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>とは話がずれますが、こちらもうまく接続できるまで非常に時間がかかった部分なので、どなたかの参考になることを願い簡潔に残しておきます。</p>
<p>deployment.<a class="keyword" href="http://d.hatena.ne.jp/keyword/yaml">yaml</a></p>
<pre class="code yaml:deployment.yaml" data-lang="yaml:deployment.yaml" data-unlink>apiVersion: apps/v1
kind: Deployment
# 中略
containers:
- name: web
image: web-image
ports:
- containerPort: 81
volumeMounts:
- mountPath: /var/run/php-fpm
name: nginx-sock
- name: app
image: app-image
volumeMounts:
- mountPath: /var/run/php-fpm
name: nginx-sock
# 中略
volumes:
- name: nginx-sock
emptyDir: {}</pre>
<p>上記の設定では、nginx-sockというボリュームを確保し、コンテナごとに設定したパスでマウントします。
次はnginx側の設定です。</p>
<p>web/default.conf</p>
<pre class="code conf:web/default.conf" data-lang="conf:web/default.conf" data-unlink>server {
listen 81; # webコンテナ containerPortの数字
server_name example.com;
root /data/public;
# 中略
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/nginx.sock; # ソケットファイルパス
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 中略
}</pre>
<p>appコンテナ側では、ソケットファイルにアクセス可能なシステムユーザーを用意する必要があります。</p>
<p>app/www.conf</p>
<pre class="code conf:app/www.conf" data-lang="conf:app/www.conf" data-unlink>[www]
listen = /var/run/php-fpm/nginx.sock # ソケットファイルパス
user = nginx # ユーザー設定
group = nginx
listen.owner = nginx # listenに使用するユーザーを設定
listen.group = nginx
listen.mode = 0660
# 後略</pre>
<p>app/dockerfile</p>
<pre class="code dockerfile:app/dockerfile" data-lang="dockerfile:app/dockerfile" data-unlink>FROM php:8.2-fpm
ENV TZ Asia/Tokyo
RUN apt-get update && \
apt-get install -y git unzip libzip-dev libicu-dev libonig-dev && \
docker-php-ext-install intl pdo_mysql zip bcmath
# ユーザーを作成する
RUN addgroup --system nginx && adduser --system --ingroup nginx nginx
COPY ./docker/app/php.ini /usr/local/etc/php/php.ini
# confファイルを配置
COPY ./docker/app/www.conf /usr/local/etc/php-fpm.d/zz-www.conf
COPY . /data
RUN chmod 777 /data/storage -R
COPY --from=composer:2.0 /usr/bin/composer /usr/bin/composer
WORKDIR /data</pre>
<p>confファイルをzz-www.confという名前に変更していることに注意してください。ここで使用している公式イメージでは、ビルド時にデフォルトのwww.confで上書きをしてしまう仕様があるようです。辞書順で後ろになるファイルを用意すればその内容が優先になるため、名前を変えて対応できるということのようです。
参考: <a href="https://yoshinorin.net/articles/2017/03/06/php-official-docker-image-trap/">PHPの公式DockerイメージでUNIXソケット通信しようとして罠にハマる</a></p>
<h3 id="外部アクセス">外部アクセス</h3>
<p>service.<a class="keyword" href="http://d.hatena.ne.jp/keyword/yaml">yaml</a></p>
<pre class="code yaml:service.yaml" data-lang="yaml:service.yaml" data-unlink>apiVersion: v1
kind: Service
metadata:
name: sample-project-service
labels:
app: app-name
spec:
type: NodePort
ports:
- port: 81
nodePort: 30080
selector:
app: app-name</pre>
<p>次のコマンドで得られる外部IPとnodePortの値をコロンで繋いで接続できます。</p>
<pre class="code lang-sh" data-lang="sh" data-unlink>kubectl get nodes <span class="synSpecial">-o</span> wide
</pre>
<h2 id="Cloud-SQLの初期設定">Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>の初期設定</h2>
<h3 id="API有効化"><a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>有効化</h3>
<pre class="code lang-sh" data-lang="sh" data-unlink>gcloud services enable sqladmin.googleapis.com
</pre>
<h3 id="Cloud-SQLのインスタンス作成">Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>作成</h3>
<p>これだけ管理コンソールで作成しました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>を選択したほかはデフォルト設定です。
データベースはLaravel側で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%B0%A5%EC%A1%BC%A5%B7%A5%E7%A5%F3">マイグレーション</a>ファイルを用意しています。</p>
<h3 id="Cloud-SQLのユーザー作成">Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>のユーザー作成</h3>
<pre class="code lang-sh" data-lang="sh" data-unlink>gcloud sql users create sample-db-user <span class="synStatement">\</span>
<span class="synSpecial">--instance=sample-db-instance</span> <span class="synSpecial">--password=sample-db-password</span>
</pre>
<h2 id="Cloud-SQLの接続設定">Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>の接続設定</h2>
<h3 id="サービスアカウントにロール追加">サービスアカウントにロール追加</h3>
<pre class="code lang-sh" data-lang="sh" data-unlink><span class="synComment"># Kubernetes Engine管理者ロールのあるサービスアカウントにCloud SQL接続クライアントのロールを追加</span>
gcloud projects add-iam-policy-binding sample-project-name <span class="synStatement">\</span>
<span class="synSpecial">--member=serviceAccount:sample-project-service-account@sample-project-name.iam.gserviceaccount.com</span> <span class="synStatement">\</span>
<span class="synSpecial">--role=roles/cloudsql.client</span>
</pre>
<p>ここからのステップは以下の公式ドキュメントの「Secret オブジェクトを作成する」「Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a> Auth Proxy にサービス アカウントを提供する > Workload Identity」を参考にしています。</p>
<p><a href="https://cloud.google.com/sql/docs/mysql/connect-kubernetes-engine?hl=ja">Google Kubernetes Engine から Cloud SQL への接続について</a></p>
<p>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a> Auth ProxyとはIAMを用いた認証でCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>に接続するためのコネクタです。今回はこのコネクタの公式イメージを使用してPodにコンテナを生成して接続します。</p>
<h3 id="Secret-オブジェクトを作成する">Secret オブジェクトを作成する</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>で使えるkey-<a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a>型のオブジェクトを作成します。後ほど<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>に使用します。</p>
<pre class="code lang-sh" data-lang="sh" data-unlink>kubectl create secret generic sample-db-secret <span class="synStatement">\</span>
<span class="synSpecial">--from-literal=username=sample-db-user</span> <span class="synStatement">\</span>
<span class="synSpecial">--from-literal=password=sample-db-password</span> <span class="synStatement">\</span>
<span class="synSpecial">--from-literal=database=sample-db-name</span>
</pre>
<h3 id="Workload-Identityを有効化する">Workload Identityを有効化する</h3>
<p>Workload Identityとは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>内のサービスアカウントにIAMで作成したサービスアカウントを紐づけて接続する仕組みです。認証回数が減る、サービスアカウントキーを保持する必要がなくなる、アクセス範囲を狭められるなどのメリットがあります。appコンテナとwebコンテナはまさにサービスアカウントキーを使用してしまったので、Workload Identityを用いた改善の余地があります。こちらは今後の課題とします。</p>
<p>Autopilotモードで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>を作成すると、デフォルトで有効になっています。</p>
<h3 id="Kubernetesのサービスアカウントを作成する"><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>のサービスアカウントを作成する</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/kubernetes">kubernetes</a>-service-account.<a class="keyword" href="http://d.hatena.ne.jp/keyword/yaml">yaml</a></p>
<pre class="code yaml:kubernetes-service-account.yaml" data-lang="yaml:kubernetes-service-account.yaml" data-unlink>apiVersion: v1
kind: ServiceAccount
metadata:
name: sample-ksa</pre>
<p>deploymentなどと同様に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>ファイルを作成し、applyすることで作成されます。</p>
<h3 id="サービスアカウント同士を紐づける">サービスアカウント同士を紐づける</h3>
<pre class="code lang-sh" data-lang="sh" data-unlink><span class="synComment"># KubernetesのサービスアカウントにWorkload Identityのユーザーとしてのロールを付与</span>
<span class="synComment"># それをプロジェクトのサービスアカウントがバインドする</span>
gcloud iam service-accounts add-iam-policy-binding <span class="synStatement">\</span>
<span class="synSpecial">--role=</span><span class="synStatement">"</span><span class="synConstant">roles/iam.workloadIdentityUser</span><span class="synStatement">"</span> <span class="synStatement">\</span>
<span class="synSpecial">--member=</span><span class="synStatement">"</span><span class="synConstant">serviceAccount:sample-project.svc.id.goog[sample-namespace/sample-ksa]</span><span class="synStatement">"</span> <span class="synStatement">\</span>
sample-project-service-account@sample-project-name.iam.gserviceaccount.com
<span class="synComment"># Kubernetesのサービスアカウントに、プロジェクトのサービスアカウントがどれかをアノテーションする</span>
kubectl annotate serviceaccount sample-ksa <span class="synStatement">\</span>
iam.gke.io/gcp-service-account<span class="synStatement">=</span>sample-project-service-account@sample-project-name.iam.gserviceaccount.com
</pre>
<p>これによりプロジェクトのサービスアカウントが様々なサービスに認証なしでアクセスできるようになります。
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%CE%A5%C6%A1%BC%A5%B7%A5%E7%A5%F3">アノテーション</a>に間違いがあった場合、--overwriteオプションをつけて再実行することで更新できます。</p>
<h3 id="Cloud-SQLコネクタの設定">Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>コネクタの設定</h3>
<p>deployment.<a class="keyword" href="http://d.hatena.ne.jp/keyword/yaml">yaml</a></p>
<pre class="code yaml:deployment.yaml" data-lang="yaml:deployment.yaml" data-unlink>apiVersion: apps/v1
kind: Deployment
# 中略
spec:
serviceAccountName: sample-ksa
containers:
- name: web
# 中略
- name: app
# 中略
env: # appコンテナの環境変数を設定
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: sample-db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: sample-db-secret
key: password
- name: DB_DATABASE
valueFrom:
secretKeyRef:
name: sample-db-secret
key: database
- name: cloud-sql-proxy
image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.1.0
args:
- "--structured-logs"
- "--port=3306"
- "sample-project-name:zone-name:sample-db-instance"
securityContext:
runAsNonRoot: true
resources:
requests:
memory: "2Gi"
cpu: "1"
volumes:
- name: nginx-sock
emptyDir: {}</pre>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>のSecretに登録した値をappコンテナの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%C4%B6%AD%CA%D1%BF%F4">環境変数</a>に設定します。Laravelの.envに同名の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%C4%B6%AD%CA%D1%BF%F4">環境変数</a>があれば、それを上書きします(つまり.env側の記述が不要になります)。
cloud-<a class="keyword" href="http://d.hatena.ne.jp/keyword/sql">sql</a>-proxyのargsの3番目に入る値は、Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>のコンソールの概要 > lこの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>との接続 > 接続名 から取得できます。</p>
<h3 id="データベースに接続する">データベースに接続する</h3>
<pre class="code lang-sh" data-lang="sh" data-unlink>gcloud sql connect sample-db-instance <span class="synSpecial">--user=sample-db-user</span>
</pre>
<p>これで直接データベースを操作できます。appコンテナに入って<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%B0%A5%EC%A1%BC%A5%B7%A5%E7%A5%F3">マイグレーション</a>を実行してから接続すれば、テーブルができています。</p>
<h1 id="終わりに">終わりに</h1>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>に関してほぼ無知な状態から、業務で触れる中で多少は理解できてきたと思っていました。しかし、自分で全てをやってみるうちに、氷山の一角でしかないという実感が強くなる一方でした。本当はもっと業務で触れなかったサービスも使ってみようと思っていたのに既知サービスの時点で難航したこと、Workload Identityの件に気づくのが遅すぎて手が回らなかったことなど、悔しい面はたくさんありますが、自分の力量を知る良い機会になりましたし、曲がりなりにもデプロイに漕ぎ着けたことはある程度自信になったと思います。今後も<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>に限らず実践的な学習を続けていき、業務に活かしていきたいです。</p>
<h1 id="参考資料">参考資料</h1>
<p><a href="https://cloud.google.com/kubernetes-engine/docs/tutorials/hello-app?hl=ja">コンテナ化されたウェブ アプリケーションのデプロイ</a></p>
<p><a href="https://cloud.google.com/kubernetes-engine/docs/how-to/creating-an-autopilot-cluster?hl=ja">Autopilot クラスタの作成</a></p>
<p><a href="https://qiita.com/yakamazu/items/b98d0ae314869f50a97f">GitHub Actions を使用してGKEにアプリケーションをデプロイする</a></p>
<p><a href="https://yoshinorin.net/articles/2017/03/06/php-official-docker-image-trap/">PHPの公式DockerイメージでUNIXソケット通信しようとして罠にハマる</a></p>
<p><a href="https://cloud.google.com/sql/docs/mysql/connect-kubernetes-engine?hl=ja">Google Kubernetes Engine から Cloud SQL への接続について</a></p>
<p><a href="https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/images/">images | Kustomize</a></p>
allabout-techblog
新卒1年目を振り返って苦労したことと解決したこと
hatenablog://entry/4207112889974345289
2023-03-28T00:00:00+09:00
2023-03-28T11:49:06+09:00 はじめに オールアバウトグループの新卒1年目エンジニアが投稿する企画『テックブログ新卒週間2023』。 今回はイシノがお送りします。 私は2022年4月に入社し、6月末まで外部でのエンジニア研修を受けておりました。研修後はメディア開発1Gに所属し業務をしております。 本記事ではメディア開発1Gのメンバーとしてジョインしたのち業務を進めていく中で苦労した点、どうやって改善をしたのかについて紹介していきます。 困っていたこと、どう改善をしたのか これから社会人一年目の私がぶつかった壁とどうやってそこに向き合って改善をしたのかについて紹介していきたいと思います。 私が困っていたと感じていた点は以下に…
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20230324/20230324114833.png" width="1200" height="680" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h1 id="はじめに">はじめに</h1>
<p>オールアバウトグループの新卒1年目エンジニアが投稿する企画『テックブログ新卒週間2023』。</p>
<p>今回はイシノがお送りします。</p>
<p>私は2022年4月に入社し、6月末まで外部でのエンジニア研修を受けておりました。研修後はメディア開発1Gに所属し業務をしております。</p>
<p>本記事ではメディア開発1Gのメンバーとしてジョインしたのち業務を進めていく中で苦労した点、どうやって改善をしたのかについて紹介していきます。</p>
<h1 id="困っていたことどう改善をしたのか">困っていたこと、どう改善をしたのか</h1>
<p>これから社会人一年目の私がぶつかった壁とどうやってそこに向き合って改善をしたのかについて紹介していきたいと思います。</p>
<p>私が困っていたと感じていた点は以下になります。</p>
<ul>
<li>情報量の多さ</li>
<li>わからない単語、用語の多さ</li>
<li>All Aboutをはじめとしたメディアを取り扱う運用の方々(以下、「事業部の方」とします)とのコミュニケーションの難しさ</li>
<li>メディア開発1Gが保持しているアプリケーションの数が多い</li>
<li>コードが読めない</li>
</ul>
<h2 id="情報量の多さ">情報量の多さ</h2>
<p>外部での研修を終えた私はこれからどんな開発をしていくのだろうと心を躍らせてチームへとジョインをしました。
その中で一番はじめに感じたことは、情報量の多さです。</p>
<p>私のチームは"メディア"と名前がついていることからメディアAll Aboutをはじめとしたメディアを取り扱う運用の方々とのコミュニケーションをとる機会が多々あります。
そのため、連絡ツール(弊社ではslack)上で目まぐるしいほどの情報が行き来をしています。
何をよく読んだらいいのか、全部認識していないといけないのかと自問自答しながら考えていました。</p>
<p>解決方法として情報の重要度、緊急性を意識するようにしました。
その上で自分の中で、今見るべきなのか今日中に見ればいいのか、と優先順位の位置付けを行うようにしました。
優先度合いががわからない場合には積極的にチーム内でコミュニケーションを取るようにして、話し合うようにしました。</p>
<p>今は業務自体に慣れてきたこともあり、拾える情報の量も増えていますが、それでも一度に多くの情報が入ってくるタイミングはあるのでまとめて見る時間を確保して情報過多になりすぎないような努力を続けています。</p>
<h2 id="わからない単語用語の多さ">わからない単語、用語の多さ</h2>
<p>新卒一年目で入社したタイミングから起きていた問題ではありますが、わからない用語がとても多いです。
それも世間一般で使用されているもの、会社固有の用語などもあり初めは会議体での内容もわからないほどでした。</p>
<p>中でもわからない用語が急激に増えたのがチームにジョインしてすぐの1~2週間ほどでした。
開発部内ではインフラ構成周りの用語、他チームのシステムの概要に関する用語、一方メディアの事業部での会議体ではメディアの用語に関してがわかりませんでした。</p>
<p>解決方法として、以下を実施しました。</p>
<ul>
<li>メモをとって、わからないところは先輩に質問する</li>
<li>デジタル単語帳という書籍を用いて学習を行う</li>
</ul>
<p>会者固有の用語に関しては質問をする以外にはないので時間をいただいて丁寧に回答をしていただけました。</p>
<p>特にメディアに関する用語に関しては、業務中に度々目にする、または利用される場面も多かったため、自分の中で優先度を上げて覚えるように心がけていました。
初めはもちろん一番不明なことが多い時期でもありますが、その中でも少しずつ自分の糧として落とし込んでいくことでチームへのジョインもスムーズになりました。</p>
<h2 id="事業部とのコミュニケーションの難しさ">事業部とのコミュニケーションの難しさ</h2>
<p>事業部とのコミュニケーションをとる上で難しいと感じていた点はいくつかあります。</p>
<ol>
<li>技術的な内容をどう噛み砕いて伝えるか</li>
<li>どうやって認識のずれを起こさないようにするか</li>
</ol>
<h3 id="1-技術的な内容をどう噛み砕いて伝えるか">1. 技術的な内容をどう噛み砕いて伝えるか</h3>
<p>技術的な内容中心に仕様に関してのコミュニケーションを取ろうとするともちろん相手に伝わりません。
事業部の方々はプログラミングに関しての知識はない方がほとんどなので技術的な内容ではなく事実ベースでのコミュニケーションを心がけました。</p>
<p>事実ベースというのは対応を経て何をしたいのか何ができるのかをベースに話をしていくという意味です。
具体的には</p>
<ul>
<li>広告表示がレイアウト調整などのfront側デザイン修正のような対応に関しては画面のモックを作成して目で見える形にする。</li>
<li>新たにシステム内に仕様を追加するような対応では例としてボタンをクリックしたらどのような挙動をするのか。</li>
</ul>
<p>などが明確になる形でのコミュニケーションを行いました。
その結果デザイン修正に関してはデザインが目でみてわかる形になり、より明確に意思疎通が行えるようになりました。
また、仕様など機能追加に関しては事業部の方が想定した挙動ができているのか、使いやすい機能になっているかのフィードバックももらえ、運用の方と開発とで有用的なコミュニケーションをとることもできるようになりました。</p>
<h3 id="2-どうやって認識のずれを起こさないようにするか">2. どうやって認識のずれを起こさないようにするか</h3>
<p>簡潔にいうならば綿密にコミュニケーションをとることです。
また、不安のある状態でリリースをしないということを徹底しています。</p>
<p>そのため、少しくどいくらいに仕様に関しては質問を心がけるようにしています。
広告の表示やデザイン修正などに関しては広告が出ているか出ていないか、デザインが修正されているか、されていないかの差しかないのでそこまで認識のずれは起きづらいと思っています。
しかし、特に仕様の追加などに関しては動作検証として実際に動かしてみてもらうというのを行っています。
開発側がこれは使いやすいと思って作成したものが運用側にとってはそこまで使いやすくない、または使いずらいなんてことは往々にあると思います。</p>
<ul>
<li>事業部から提案書をいただく</li>
<li>それをもとに設計し実装をする</li>
<li>運用の方々に触っていただいてフィードバックをいただく</li>
<li>再度実装する</li>
</ul>
<p>このサイクルを行うことがより良いものを開発側と運用側で作るには欠かせないことだと思います。
開発側が使いやすいと思うのはあくまで推測の域を超えないため、綿密なコミュニケーションを心がけて使用を詰めていくことがいいと思います。</p>
<h2 id="メディア開発1Gが保持しているアプリケーションの数が多い">メディア開発1Gが保持しているアプリケーションの数が多い</h2>
<p>メディア開発Gは他の開発部署に比べて扱うアプリケーションの数がとても多いです。
そのためチームジョイン当初はどのアプリケーションがなんと呼ばれるシステムなのか、理解するだけでも一苦労でした。
アプリケーションがとても多いので配属されて一年経つ今ですら、システム概要に関しての理解が薄いアプリケーションもあります。</p>
<p>この解決方法として私はよく改修の入るアプリケーションを理解するところから始めました。
大きな一つ一つのアプリケーション単位ではなくサービス同士のつながり方を意識して理解することでアプリケーションの点の理解ではなく、線での理解に努めました。
その結果一年たった今ではよく改修の入るアプリケーションに関してはシステム自体の理解、構造の理解に関してある程度の知識をつけることができました。</p>
<h2 id="コードが読めない">コードが読めない</h2>
<p>恥ずかしながらなのですが、入社した当初はコードから実装を理解することに関してとても苦手でした。
メソッド単体程度ではある程度読解することができていたのですが、全体を通しての処理の流れの理解ができていませんでした。
そのため、チームジョイン当初はメソッドを分割しないで処理の順番で書いてくれたほうが楽なのにくらいに思っていました。</p>
<p>最も今では考え方も変わり1メソッドに1つの役割を意識して実装を心がけています。</p>
<p>こちらに関しては正直慣れていき読めるようになったものもありますが、考え方としてはマクロ的視点を持って読むことだと思います。
プログラミングは入力と出力の繰り返しと入社して間もない頃に先輩からアド<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>をいただきましたが今はそのおかげで素早くコードを読むことができています。
今まではどの行で何が行われているのかを全て把握しようとして情報量の多さに理解ができていませんでしたが、何を引数でもらって何を出力しているのか、これを見るだけで大体の実装は理解することができるのに気づきました。
またショットカットキーなどの理解も増え、実装の内容を追うことに関してはある程度の自信がついてきました。</p>
<p>今後はコードを追うことはできるようになってきたので、そこからの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>や、改修の際にリーダブルな実装ができるようになりたいと考えております。</p>
<h1 id="終わりに">終わりに</h1>
<p>今回は私がチームにジョインしてから困った点に関してなぜ困ったのか、どうやって解決をしたのかについて紹介させていただきました。</p>
<p>初めはそれこそ時間がかかっていたものの周りの先輩方にアド<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>をいただいて支えていただきながら成長をすることができた1年間だったと思います。</p>
<p>この1年間で学んできたことを後輩に教えていければと思います。
また自身も成長をするために今以上にコミュニケーションをとり、仕事を幅を広げつつ楽しみながらやっていければと思います。</p>
allabout-techblog
20年以上運営してるメディアと周辺サービスの再設計・再構築してるから話を聞いてほしい
hatenablog://entry/4207112889947687198
2022-12-25T10:00:00+09:00
2022-12-25T16:24:05+09:00 オールアバウトで一番アツい開発をしている「All About リアーキテクティングプロジェクト」についての立ち上げと、
先が見えない問題にどう立ち向かっているかを(表面的に)紹介します
<p>こんにちは!株式会社オールアバウト開発部 All Aboutリアーキテクティングプロジェクト PM(言い出しっぺ)兼エンジニアの @C058です。</p>
<p>2022年の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%D9%A5%F3%A5%C8%A5%AB%A5%EC%A5%F3%A5%C0%A1%BC">アドベントカレンダー</a>も最終日となりました。
これまでのオールアバウトのカレンダーはこちら:</p>
<p><a href="https://qiita.com/advent-calendar/2022/allabout">All About Group(株式会社オールアバウト)のカレンダー | Advent Calendar 2022 - Qiita</a></p>
<p>最終日の記事は、自称:オールアバウトで一番アツい開発をしている「All About リアーキテクティングプロジェクト」についての立ち上げと、
先が見えない問題にどう立ち向かっているかを表面的に紹介したいと思います。</p>
<p>技術選定の話や、ガチガチのエンジニアリング話は近々どこかで公開します!(乞うご期待)</p>
<p>※同じ悩みを持っているPMもしくはエンジニアの方、ぜひカジュアル面談と称して情報交換しましょう!</p>
<h3 id="All-About-リアーキテクティングプロジェクトとは">All About リアーキテクティングプロジェクトとは</h3>
<p>文字通り、All About (<a href="https://allabout.co.jp">https://allabout.co.jp</a> )の再設計(リ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>)を行うプロジェクトです。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fallabout.co.jp" title="All About(オールアバウト)" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://allabout.co.jp">allabout.co.jp</a></cite></p>
<p>All Aboutは「人々が「知らなくて損する」をなくす」ために運営しているメディアです。
マネーから恋愛まで幅広いテーマで専門家の方と一緒にコンテンツ発信を行っております。</p>
<p>株式会社オールアバウトの主力事業であり、弊社が立ち上がったときからずっと運営を続け、
2022年12月時点では<a href="https://corp.allabout.co.jp/allabout_20th.html">サービス開始から21年目</a>となりました。
(今年度入社した新卒さんと同い年かと思うとなんとも言えない気持ちが止まりません。)</p>
<p>さて、察しの良い方ならもうお気づきでしょう。
長く続くサービスでレガシー&技術的負債がまったくないとは言えません。</p>
<p>これまでオールアバウトのエンジニアは時間をかけて技術的負債を返済し続けていました。
<a href="https://allabout-tech.hatenablog.com/entry/2018/08/31/121400">記事入稿システムの刷新</a>やオンプレミスから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>移行など様々な対応をする間、All About自体も<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>のバージョンアップ、<a href="https://allabout-tech.hatenablog.com/entry/2022/07/20/122218">DBのバージョンアップ</a>など保守運用改善をしてきたのです。
が…<s>もう、限界です。</s></p>
<p><strong>残すところは「All About」そのものです。</strong></p>
<p>文章量の都合上、ここでは書ききれない検討を重ねた結果、約11年ぶりに本格的な技術刷新(言語から<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>もすべて見直し)をしようと決断に至りました。</p>
<p>All Aboutのリアーキテクティングプロジェクトのテーマは以下の通りです。</p>
<p><strong><span style="color: #d32f2f">「All About」を「長く続く<span style="font-size: 80%">(ける)</span>サービス」として「作り直す」</span></strong></p>
<h3 id="現在のプロジェクトステータス技術選定が完了しました">現在のプロジェクトステータス:技術選定が完了しました。</h3>
<p>※詳細は後日の記事で</p>
<p>次のAll About は主言語を<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>からTypeScriptに変更します。</p>
<p>All About本体はnext.jsを採用し、BackendにNestJS +GraphQLの組み合わせで開発することに決めました。</p>
<p><figure class="figure-image figure-image-fotolife" title="新All Aboutの選定"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20221224/20221224015252.png" width="960" height="540" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>新All Aboutの選定</figcaption></figure></p>
<p>※詳細気になる方、ぜひカジュアル面談しましょう!
連絡先:
<a href="https://www.green-japan.com/company/60/job/178010">株式会社 オールアバウト (All About, Inc.) | Webアプリケーションエンジニア(Allaboutリビルド) | IT/Web業界の求人・中途採用情報に強い転職サイトGreen(グリーン)</a></p>
<p>ぜひ、「気になる!」or 応募で「カジュアル面談希望」と一言いただけると嬉しいです!</p>
<h3 id="聞いて読んで欲しい話">聞いて(読んで)欲しい話。</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%D9%A5%F3%A5%C8%A5%AB%A5%EC%A5%F3%A5%C0%A1%BC">アドベントカレンダー</a>に寄稿するにあたって、本プロジェクトを立ち上げから今日まで、PMとして頭を抱えたり、ひねってきた小話を紹介しようと考えていました。
私自身、大規模システム刷新のような規模のPMということもあり、ありがたいことに(?)書けるネタが多かったので、今回はタイトルとあらすじをエモい感じで紹介します。</p>
<p><span style="font-size: 80%">この記事になにか反応があれば詳細を今後別の記事で執筆がんばります。。。</span></p>
<h4 id="episode1気づいたら地雷原を歩むような開発すべての仕様を把握した人ドキュメントは存在しないだと">episode1:気づいたら地雷原を歩むような開発、すべての仕様を把握した人・ドキュメントは存在しない…だ、と…?</h4>
<p><figure class="figure-image figure-image-fotolife" title="episode1"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20221224/20221224015447.png" width="1200" height="424" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>地雷原を歩む開発とふたたび立ち上がるメンバー</figcaption></figure></p>
<p>All Aboutに出戻りしたある日、知らない機能が増えていた。増え続けた仕様をみんなは部分的にしか知らない。必要以上のようなテスト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%A9%BF%F4">工数</a>、それでも出てしまう考慮漏れ…。この現状を打破するにはどうしたら良いのか?ここにプロジェクトチームが立ち上がったのだ。</p>
<h4 id="episode2-これはあいつが言い出した仕事エンジニアが勝手にやってるんだにしないためにはどうしたら良いのだろう">episode2: これはあいつが言い出した仕事、エンジニアが勝手にやってるんだ…にしないためには?どうしたら良いのだろう。</h4>
<p><figure class="figure-image figure-image-fotolife" title="episode2"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20221224/20221224015515.png" width="1006" height="408" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>プレゼンと団結している図</figcaption></figure>
このまま事業を続けて改善するより、立ち止まりシステムの見直しを。プロジェクトメンバーは最初は2名?!とりあえず、プロジェクトを立ち上げるぞ。仲間を探し、事業チーム、仲間に現状を伝えていくにはどうしたらいいか?冒険が始まる。</p>
<h4 id="episode3-俺たちは雰囲気で技術選定をしている課題を特定することからはじめてみた">episode3: 俺たちは雰囲気で技術選定をしている…?!課題を特定することからはじめてみた。</h4>
<p><figure class="figure-image figure-image-fotolife" title="episode3"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20221224/20221224015552.png" width="1022" height="512" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>技術選定をする</figcaption></figure>
無事、新メンバーも迎えることができた。え、あ…みんな、リ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>・技術選定はほぼ始めて!?好みだけで新しい技術は選べない気がする。よし、どんな軸で技術を選ぶべきかから始めよう。まずは事業部長に話を聞きにいこうか。</p>
<h4 id="episode4-年後あの技術選定は失敗だったにしないためにはどうしたら">episode4: ◯年後、あの技術選定は失敗だった!にしないためにはどうしたら?</h4>
<p><figure class="figure-image figure-image-fotolife" title="episode4"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20221224/20221224015637.png" width="672" height="388" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>過去のドキュメントを調べる図</figcaption></figure>
若かりし日に「この採用技術、まじで謎なんだけど。しかもなんであんな設計なの?」とぼやいていたことを思い出した。あ、これ、いつか私達も言われかねない、後続の開発者たちに同じ思いをさせたくはない...! 自分たちの<s>言い訳</s> 意思決定を残すぞ!そうしてチームは<a class="keyword" href="http://d.hatena.ne.jp/keyword/ADR">ADR</a>: architecture decision recordに手を出した。今は正解か確信がなくても正解にしていくことも大事にしよう。</p>
<h4 id="episode5-この選択デメリットが気になってきた不安な状況でチームメンバーとどう乗り越えよう">episode5: この選択、デメリットが気になってきた…不安な状況でチームメンバーとどう乗り越えよう?</h4>
<p><figure class="figure-image figure-image-fotolife" title="episode5"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20221224/20221224015734.png" width="640" height="536" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>頭を抱えるような問題</figcaption></figure>
「この選定では…実装は厳しいかもしれません…」ある朝、メンバーから告げられた。メンバーは浮かない顔をしている。一体、何があったのか…話を聞いてみよう。いまの発言、PMとエンジニア…どっちの自分が考えて話しているんだっけ?立場を明確にして判断をしていかないとプロジェクトが意図しないところで止まってしまう!!</p>
<h4 id="episode6-ところで人が足りないんだけど採用もPMの仕事でした">episode6: ところで人が足りないんだけど…?採用もPMの仕事でした。</h4>
<p><figure class="figure-image figure-image-fotolife" title="episode6"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20221224/20221224015817.png" width="844" height="548" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>仕事探しがテーマです</figcaption></figure>
色々あった問題を乗り越えて、開発スコープ、技術選定も進んでいる。けど、これはどう考えても人が足りない、PMが手を動かすのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%F3%A5%C1%A5%D1%A5%BF%A1%BC%A5%F3">アンチパターン</a>ですよね?!今後の事業拡大も見えるのに、来る人を待つことはやめよう。一緒に働きたい人は自分で探す時代です。人事と一緒に作戦会議だっ!</p>
<h4 id="episode7-PM兼エンジニアもコードを書きたいでも時間を捻出することって出来るんだっけ">episode7: PM兼エンジニアもコードを書きたい!でも時間を捻出することって出来るんだっけ?</h4>
<p><figure class="figure-image figure-image-fotolife" title="episode7"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20221224/20221224015902.png" width="1200" height="470" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>業務内容に悩むPMの図</figcaption></figure>
技術検証、選定もおわり本格的なフェーズに入ってきた。開発スケジュールもおおよそ立って、あとは進捗を把握しながらアップデートしていくだけ。ちょっとぐらいならコードを書け…ない?!なんてこった。どうやって時間をつくり、そして気持ち・立場の折り合いをつけることはできるだろうか。※episode6と矛盾していますが書きたいんです。</p>
<h4 id="episode-最終回-そして最初のリリース僕たちを待ち受けていたのは">episode 最終回: そして最初のリリース、僕たちを待ち受けていたのは…?</h4>
<p><figure class="figure-image figure-image-fotolife" title="episode最終回"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20221224/20221224015959.png" width="894" height="584" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>episode最終回</figcaption></figure>
※現在、がっつり開発中です。いったいどんな結末が待ち受けているのか。</p>
<h3 id="次回予告">次回予告</h3>
<p>All Aboutリ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>プロジェクトについては、これまでこの記事で紹介した内容を深堀り、関連した内容を順次こちらのブログにて公開していく予定です。</p>
<h4 id="例えばこんな内容">例えばこんな内容:</h4>
<ul>
<li>(episode1) All Aboutのリ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>に向けた課題整理と解決の筋道</li>
<li>(episode3) All Aboutの新技術選定をした話(選定軸編)</li>
<li>(episode4) All Aboutで採用した新技術について(紹介編)</li>
<li>(episode5)メディア構築中に技術的にぶつかった問題
*</li>
</ul>
<p>ぜひお楽しみに!</p>
<h3 id="All-About-リアーキテクチャープロジェクトではエンジニアを募集しております">All About リ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>ープロジェクトではエンジニアを募集しております!</h3>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.green-japan.com%2Fcompany%2F60%2Fjob%2F178010" title="株式会社 オールアバウト (All About, Inc.)の求人情報 | 転職サイトGreen(グリーン)" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.green-japan.com/company/60/job/178010">www.green-japan.com</a></cite></p>
<p> カジュアル面談希望の方は応募の際に「カジュアル面談希望」と一言いただけると嬉しいです!</p>
<p>また募集中の職種や詳細などは下記をご覧ください。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhrmos.co%2Fpages%2Fallaboutgroup%2Fjobs%3Fcategory%3D1670319657561546752" title="株式会社オールアバウト エンジニア・デザイナー の求人一覧" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://hrmos.co/pages/allaboutgroup/jobs?category=1670319657561546752">hrmos.co</a></cite></p>
allabout-techblog
Google Cloud でサービス アカウントの権限借用(impersonate)を活用して SRE の権限を縮小させた話
hatenablog://entry/4207112889897238225
2022-07-21T17:44:44+09:00
2022-07-21T17:49:38+09:00 こんにちは。オールアバウト SRE 所属 の@s_ishiiと申します。 Google Cloud にはサービス アカウントの権限借用という機能があります。この機能を活用することで普段の運用をより安全にすることができます。この記事ではオールアバウトが導入・実践しているサービス アカウントの権限借用に関して解説します。 前提 オールアバウトでは SRE が全サービスのインフラを一元的に管理しています。このため SRE は全ての Google Cloud のプロジェクトに対してオーナー権限(roles/owner)を保持していました。 SRE メンバー全員がインフラを自由に変更できてしまうため、普…
<p>こんにちは。オールアバウト SRE 所属 の<a href="https://qiita.com/ishii1648">@s_ishii</a>と申します。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud には<code>サービス アカウントの権限借用</code>という機能があります。この機能を活用することで普段の運用をより安全にすることができます。この記事ではオールアバウトが導入・実践しているサービス アカウントの権限借用に関して解説します。</p>
<h2>前提</h2>
<p>オールアバウトでは SRE が全サービスのインフラを一元的に管理しています。このため SRE は全ての <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud のプロジェクトに対してオーナー権限(roles/owner)を保持していました。
SRE メンバー全員がインフラを自由に変更できてしまうため、普段から <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud のコンソール画面で設定を変更してしまわないよう注意しながら運用する必要がありました。</p>
<p>こうした状況を解決する手段として<code>サービス アカウントの権限借用</code>の活用を検討し始めました。</p>
<h2>サービス アカウントの権限借用とは</h2>
<p><code>サービス アカウントの権限借用</code>とは名前の通り別のサービスアカウントの権限を借用する権限です。これだけだと分かりづらいので例を用いて解説します。</p>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud へのログイン・アカウント
<ul>
<li>sre@sample.com</li>
<li>閲覧者権限(roles/viewer)</li>
</ul>
</li>
<li>サービスアカウント
<ul>
<li>owner@project-id.iam.gserviceaccount.com</li>
<li>オーナー権限(roles/owner)</li>
</ul>
</li>
</ul>
<p>ログイン・アカウント(sre@sample.com)には更新系の権限が付与されていないため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud 上で何かしらリソースを作成・変更しようとすると権限エラーになります。
しかしサービスアカウント(owner@project-id.iam.gserviceaccount.com)側でログイン・アカウントに対し<code>サービス アカウントの権限借用</code>を与えている場合、ログイン・アカウントからサービスアカウントに成りすますことができます。
これによってサービスアカウントの権限が利用できるようになり、結果として(参照権限しか持っていない)ログイン・アカウントから <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud のリソースを作成・変更できるようになります。</p>
<p>詳しくは以下公式ドキュメントをご確認ください。<br />
<a href="https://cloud.google.com/iam/docs/impersonating-service-accounts?hl=ja">https://cloud.google.com/iam/docs/impersonating-service-accounts?hl=ja</a></p>
<h2>目標</h2>
<p>前提でも軽く触れましたが<code>サービス アカウントの権限借用</code>を用いることで以下の実現を目指しました。</p>
<ul>
<li>SRE メンバーの権限縮小
<ul>
<li>コンソール画面から本番環境を変更できないようにする</li>
</ul>
</li>
<li>Terraform の実行
<ul>
<li>Terraform は各 SRE メンバーの PC から実行しているため Terraform 経由の場合は本番環境の設定を変更できるようにする</li>
</ul>
</li>
<li>一時的な権限拡大
<ul>
<li>一時的に権限を強化してコンソール画面から本番環境を変更できるようにする(一例として、障害時に DB をフェイルオーバーしたい等の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a>が想定されました)</li>
</ul>
</li>
</ul>
<h2>Terraform とサービスアカウントの借用権限</h2>
<p>上記で解説した<code>サービスアカウントの借用権限</code>は gcloud コマンドと Terraform で利用できます。オールアバウトでは <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud を Terraform で管理しているため Terraform で<code>サービスアカウントの借用権限</code>を利用しています。</p>
<p>具体的な設定手順は長くなるので割愛しますがこれによって閲覧者権限しか持っていないアカウントからでも Terraform 経由で <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud のリソースを更新できるようになりました。
Terraform における<code>サービスアカウントの借用権限</code>の設定手順に関心のある方は以下記事をご覧ください。<br />
<a href="https://medium.com/google-cloud/a-hitchhikers-guide-to-gcp-service-account-impersonation-in-terraform-af98853ebd37">https://medium.com/google-cloud/a-hitchhikers-guide-to-gcp-service-account-impersonation-in-terraform-af98853ebd37</a></p>
<h2>一時的な権限拡大</h2>
<p>Terraform で<code>サービスアカウントの借用権限</code>を使えるようになったことで運用の大部分が解消されたため、SRE メンバーからオーナー権限を剥奪しました。
しかしいざ閲覧者権限のみになると、当初想定していたよりもコンソール画面から変更作業が多いことに気づきました。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud は Terraform で管理していると書きましたが、Terraform を導入してから 1 年程度しか経っていないこともあり未だに Terraform 管理されていないリソースもあり、コンソール画面を操作して設定変更する機会は少なくなかったのです。</p>
<p>そこで活用したのが一時的な権限の追加です。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud IAM では権限を一時的に追加する機能があるのでこれを利用することで必要な権限を短時間だけ与えることにしました。</p>
<p>以下コマンド例です。コマンドを実行した時間から 30 分間指定した権限が追加された状態になります。</p>
<pre class="code" data-lang="" data-unlink>gcloud projects add-iam-policy-binding <プロジェクトID> \
--member='group:sre@sample.com' \
--condition="expression=request.time < timestamp(\"$(date '+%Y-%m-%dT%TZ' -u -d '30 minute')\"),title=tmp_$(date '+%Y-%m-%d-%T')" \
--role='<ロール名>' \
--impersonate-service-account=owner@project-id.iam.gserviceaccount.com</pre>
<p>ちなみに最後に付与しているオプション<code>--impersonate-service-account</code>はサービスアカウントの借用権限用のオプションになります。
ログイン・アカウント(sre@sample.com)には IAM を操作する権限は無いのですが、サービスアカウント(owner@project-id.iam.gserviceaccount.com)に成りすますことで IAM を操作できるようにしています。</p>
<h2>Slack ボットを使って</h2>
<p>上記までの対応で当初目標としていたことは達成できたのですが、「一時的な権限拡大が面倒」という課題が残りました。
コマンド 1 つ実行するだけですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud のロールに習熟している人でないとどのロールを割り当てて良いのか調べるところから始めないといけません。
roles/owner のような強力なロールを割り当てられれば良いのですが、一時的な権限付与では roles/owner を含む基本ロールは付与できないため、毎回ケースに応じて必要なロールを選択する必要があり思いの外時間がかかるのです。</p>
<p>このため新しく入ってきた人も簡単に作業ができるよう Slack 経由で実行できるようにしました。以下 Slack ボットの利用シーンになります。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220708/20220708172013.png" width="715" height="136" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span>
<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220708/20220708172018.png" width="621" height="257" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h2>まとめ</h2>
<p><code>サービス アカウントの権限借用</code>を活用することでインフラ管理者の権限を縮小し、不意の事故を防止することができます。
加えて上記のような対応を併せて行うことで、運用の安全性を享受しつつ利便性を維持することができますのでお試しください。</p>
<p>以上「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud でサービス アカウントの権限借用(impersonate)を活用して SRE の権限を縮小させた話」でした。</p>
allabout-techblog
All Aboutの基幹DBのMySQLバージョンを5.7から8.0に上げた話
hatenablog://entry/4207112889893743102
2022-07-20T12:22:18+09:00
2022-07-20T12:30:39+09:00 こんにちは。株式会社オールアバウト エンジニアの@hideです。 私たちのチームでは、2022年3〜6月にかけて、オールアバウトの基幹DB(All Aboutの記事やガイドの情報が格納してあるDB)のMySQLバージョンを5.7から8.0に上げる対応を実施しました。 当記事ではその際の移行手順や実際の作業を通して得た知見をまとめます。 これからシステムのMySQLバージョンを上げたいと思っている方の参考になれば幸いです。 環境情報 MySQLバージョンアップの動機について セキュリティ担保のため All Aboutのリアーキテクチャに向けた準備 移行作業の振り返りと得た学び 1. MySQL8…
<p>こんにちは。株式会社オールアバウト エンジニアの@hideです。</p>
<p>私たちのチームでは、2022年3〜6月にかけて、オールアバウトの基幹DB(<a href="https://allabout.co.jp/">All About</a>の記事やガイドの情報が格納してあるDB)の<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>バージョンを5.7から8.0に上げる対応を実施しました。</p>
<p>当記事ではその際の移行手順や実際の作業を通して得た知見をまとめます。</p>
<p>これからシステムの<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>バージョンを上げたいと思っている方の参考になれば幸いです。</p>
<ul class="table-of-contents">
<li><a href="#環境情報">環境情報</a></li>
<li><a href="#MySQLバージョンアップの動機について">MySQLバージョンアップの動機について</a><ul>
<li><a href="#セキュリティ担保のため">セキュリティ担保のため</a></li>
<li><a href="#All-Aboutのリアーキテクチャに向けた準備">All Aboutのリアーキテクチャに向けた準備</a></li>
</ul>
</li>
<li><a href="#移行作業の振り返りと得た学び">移行作業の振り返りと得た学び</a><ul>
<li><a href="#1-MySQL8の変更点を確認">1. MySQL8の変更点を確認</a></li>
<li><a href="#2-影響範囲の洗い出し">2. 影響範囲の洗い出し</a></li>
<li><a href="#3-各アプリのテストケースを作成">3. 各アプリのテストケースを作成</a></li>
<li><a href="#4-ステージング環境で動作テストを実施して問題点の洗い出しエラーの解消">4. ステージング環境で動作テストを実施して問題点の洗い出し+エラーの解消</a><ul>
<li><a href="#MySQL8で削除されたSQLモードに起因するエラー">MySQL8で削除されたSQLモードに起因するエラー</a></li>
<li><a href="#データソート時のメモリ不足に起因するエラー">データソート時のメモリ不足に起因するエラー</a></li>
</ul>
</li>
<li><a href="#5-データ移行方法の検討と決定">5. データ移行方法の検討と決定</a><ul>
<li><a href="#移行にかかる時間がDMSの方が短い">移行にかかる時間がDMSの方が短い</a></li>
<li><a href="#移行当日の作業量がDMSの方が少ない">移行当日の作業量がDMSの方が少ない</a></li>
<li><a href="#DMSではトリガー等の設定が移行される">DMSではトリガー等の設定が移行される</a></li>
</ul>
</li>
<li><a href="#6-本番環境でデータ担保のテストを実施">6. 本番環境でデータ担保のテストを実施</a></li>
<li><a href="#7-ステージング環境でリハーサルを実施">7. ステージング環境でリハーサルを実施</a></li>
<li><a href="#8-本番環境で移行作業を実施">8. 本番環境で移行作業を実施</a></li>
</ul>
</li>
<li><a href="#移行を進めるにあたり意識したこと">移行を進めるにあたり意識したこと</a></li>
<li><a href="#おわりに">おわりに</a></li>
<li><a href="#All-Aboutリビルドエンジニア募集のお知らせ">All Aboutリビルド:エンジニア募集のお知らせ</a></li>
</ul>
<h1 id="環境情報">環境情報</h1>
<p>弊社の主な環境は以下の通りです。</p>
<ul>
<li>言語:<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a></li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>:Laravel</li>
<li>インフラ:<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a></li>
<li>DB<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>:Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>(<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a> 5.7)</li>
</ul>
<p>今回はCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>バージョンを5.7から8.0に上げる対応を実施しました。</p>
<h1 id="MySQLバージョンアップの動機について"><a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>バージョンアップの動機について</h1>
<p>今回<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>バージョンアップを行った理由は以下の二つです。</p>
<ul>
<li>セキュリティ担保のため</li>
<li>All Aboutのリ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>に向けた準備</li>
</ul>
<h2 id="セキュリティ担保のため">セキュリティ担保のため</h2>
<p>一つ目はセキュリティを担保するためです。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>(Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a> for <a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>)にはサポート期限があり、期限が切れてしまうと新規のバグやエラーの修正が行われなくなってしまいます。</p>
<p>バグやエラーはシステムの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>に繋がる可能性があるため、なるべく早くバージョンアップを実施する必要がありました。</p>
<h2 id="All-Aboutのリアーキテクチャに向けた準備">All Aboutのリ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>に向けた準備</h2>
<p>二つ目はAll Aboutのリ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>に向けた準備です。</p>
<p>私たちのチームでは、現在All Aboutのアプリケーション・インフラ構成を設計レベルから作り直す、リ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>プロジェクトを進めています。</p>
<p>このプロジェクトは数年単位で行う予定のため、本格的に走り出すと<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>のバージョンアップに時間を割く余裕が無くなってしまいます。</p>
<p>そのため、プロジェクトが本格的に走り出す前の初期段階で対応しておくことになりました。</p>
<h1 id="移行作業の振り返りと得た学び">移行作業の振り返りと得た学び</h1>
<p>次に、移行の流れと得た学びを時系列でまとめていきます。</p>
<h2 id="1-MySQL8の変更点を確認">1. MySQL8の変更点を確認</h2>
<p>まず最初に行ったのは、MySQL8での主な変更点を確認することです。</p>
<p>チームで定期的に時間を設けて調査を行い、MySQL8の主な変更点を洗い出しました。</p>
<p>特に参考になった記事は以下の二つです。</p>
<ul>
<li><a href="https://dev.mysql.com/doc/refman/8.0/ja/upgrading-from-previous-series.html">MySQL 8.0 での変更</a></li>
<li><a href="https://blog.cybozu.io/entry/2021/05/24/175000">MySQL 8.0 への移行が完了しました ~さようなら全ての MySQL 5.7~</a></li>
</ul>
<p>一つが公式が出している記事で、もう一つが<a class="keyword" href="http://d.hatena.ne.jp/keyword/Cybozu">Cybozu</a>様がMySQL8への移行を行った際の記事です。</p>
<p>どちらもMySQL8の変更点を知る上でとても参考になりました。</p>
<h2 id="2-影響範囲の洗い出し">2. 影響範囲の洗い出し</h2>
<p>次に、影響範囲(対象のDBと接続しているアプリ)の洗い出しを行いました。</p>
<p>調査の結果、他部署が管理しているシステムも含めて、合計で8つのアプリと接続していることが分かりました。</p>
<h2 id="3-各アプリのテストケースを作成">3. 各アプリのテストケースを作成</h2>
<p>影響範囲の洗い出しが終わった後は、各アプリで動作担保用のテストケースを作成しました。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220719/20220719191949.png" width="1200" height="675" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>今回は通常の機能追加のテストケースとは違ってどこでエラーが発生するかが分からなかったため、全ての機能を網羅する必要がありました。</p>
<h2 id="4-ステージング環境で動作テストを実施して問題点の洗い出しエラーの解消">4. ステージング環境で動作テストを実施して問題点の洗い出し+エラーの解消</h2>
<p>次に、作成したテストケースを使ってステージング環境で各アプリのテストを実施しました。</p>
<p>ここでは、ステージングのDBを使うのではなく、本番環境のDBのデータをステージング用に一部加工したうえでMySQL8化してテストを実施しました。</p>
<p>なぜなら、移行対象のDBは、本番環境とステージング環境でデータの内容や量がかなり異なっていたからです。</p>
<p>データ量によってクエリの動作が変わる場合もあるため、実際の本番環境に近い状態でテストすることはとても重要でした。(実際、メモリ不足起因のエラーは発生しました)</p>
<p><br>
ステージング環境でテストを実施したことで、MySQL8化により各アプリで発生するエラーの洗い出しをすることができました。</p>
<p>発生した主なエラーは以下の2つです。</p>
<ul>
<li>MySQL8で削除された<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>モードに起因するエラー</li>
<li>データソート時のメモリ不足に起因するエラー</li>
</ul>
<p>それぞれの原因と解消方法を紹介します。</p>
<h3 id="MySQL8で削除されたSQLモードに起因するエラー">MySQL8で削除された<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>モードに起因するエラー</h3>
<p>一つ目は、MySQL8で削除された<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>モードに起因するエラーです。</p>
<p>Laravelで作られたバッチシステムで以下のエラーが発生しました。</p>
<blockquote><p>SQLSTATE[42000]: Syntax error or <a class="keyword" href="http://d.hatena.ne.jp/keyword/access">access</a> violation: 1231 Variable '<a class="keyword" href="http://d.hatena.ne.jp/keyword/sql">sql</a>_mode' can't be set to the <a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a> of 'NO_AUTO_CREATE_USER'</p></blockquote>
<p>これは、<a href="https://dev.mysql.com/doc/refman/8.0/ja/upgrading-from-previous-series.html#:~:text=NO_AUTO_CREATE_USER%20SQL%20%E3%83%A2%E3%83%BC%E3%83%89">公式ドキュメント</a>にもある通り、MySQL8からNO_AUTO_CREATE_USERという<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>モードが削除されたために発生するようになったエラーです。</p>
<p>具体的には、Laravelでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>のstrictモードのオン・オフを設定できるようになっており、オンの場合は以下のように<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>モードをセットするのですが、MySQL8からはNO_AUTO_CREATE_USERが削除されたためセットできずにエラーとなっていました。</p>
<pre class="code" data-lang="" data-unlink>protected function strictMode()
{
return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'";
}
// /vendor/laravel/framework/src/Illuminate/Database/Connectors/MySqlConnector.php</pre>
<p>これについては、Laravelで<a href="https://github.com/laravel/framework/pull/24038/files">パッチ</a>が出ていたため、Laravelのパッチバージョンを上げることで解消することができました。</p>
<p>パッチバージョンを上げた後は、以下のように<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>のバージョンによって<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>モードを変えるため、MySQL8にしてもエラーが発生しなくなっています。</p>
<pre class="code" data-lang="" data-unlink>protected function strictMode(PDO $connection)
{
if (version_compare($connection->getAttribute(PDO::ATTR_SERVER_VERSION), '8.0.11') >= 0) {
return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'";
}
return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'";
}</pre>
<h3 id="データソート時のメモリ不足に起因するエラー">データソート時のメモリ不足に起因するエラー</h3>
<p>二つ目は、データソート時のメモリ不足に起因するエラーです。</p>
<p>Laravelで作られた管理画面の契約書一覧ページで以下のエラーが発生しました。</p>
<blockquote><p>SQLSTATE[HY001]: Memory allocation error: 1038 Out of sort memory, consider increasing server sort buffer size</p></blockquote>
<p>これは、MySQL8からデータのソート方式が変わった(正確にはソートの選択方式が変わった)ことに起因するエラーと考えています。</p>
<p>具体的には、以前はレコードのソートをする際に、特定のカラム(IDなど)でソートをした後にデータを取得していたのですが、MySQL8(正確には8.0.20)からはパフォーマンスの観点から、常に指定したカラムのデータをまず全て取得した上でメモリ上で一括でソートするようになりました。</p>
<p>そのため、ソート時のデータ量が増加してしまい、sort buffer sizeが同じ値でもメモリ不足によりエラーが発生したと考えられます。</p>
<ul>
<li><p>参考1:<a href="https://dev.mysql.com/doc/refman/8.0/ja/order-by-optimization.html">ORDER BY の最適化</a></p></li>
<li><p>参考2:<a href="https://gihyo.jp/dev/serial/01/mysql-road-construction-news/0111">MySQLのソート処理について</a></p></li>
</ul>
<p>このエラーの対応方針としては、エラーメッセージにある通り素直にsort buffer sizeを上げても良かったのですが(実際、sort buffer sizeを上げてエラーが解消されることは確認しました)、DB全体のメモリ消費量の増加に繋がる可能性がありました。</p>
<p>そのため今回はクエリチューニングで対応しました。</p>
<p>具体的には、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>インデックス(主キーインデックス)を効かせるようクエリを変更することで、データ取得時にソート処理が発生しない(ソート時にメモリが消費されない)ようにしました。</p>
<p><br>
今回紹介した二つのエラーはあくまで弊社の事例であり、他社のシステムで発生するとは限りません。</p>
<p>どういったエラーが発生するかは(ある程度の予測はできるかもしれませんが)断定はできないので、結局は「徹底的にテストをして問題点を洗い出す」がバージョンアップの際の原則なのかなと感じています。</p>
<h2 id="5-データ移行方法の検討と決定">5. データ移行方法の検討と決定</h2>
<p>ステージングでの動作検証と並行して、データの移行方法(<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>のバージョンアップ方法)の調査と検証も行っていました。</p>
<p>調査により、Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>のバージョンを上げる方法としては主に以下の二つがあることが分かりました。</p>
<ol>
<li>Database Migration Service(DMS)を使用する方法</li>
<li>現在のCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>のコンソールからデータをExportし、新しい<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>バージョンの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>にImportする方法</li>
</ol>
<p>※<a href="https://cloud.google.com/database-migration?hl=ja">Database Migration Service(DMS)</a>とは、別の環境からCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>にデータベースを移行するための<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>のサービスです。ここでの「別の環境」とは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a>・Azure・オンプレ等の<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>以外の環境だけでなく、別バージョンのCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>からの移行も含んでいます。DMSの概要については<a href="https://www.youtube.com/watch?v=Wh7koygb1ZE">こちら</a>の動画も参考になるでしょう</p>
<p>これらの二つの方法について動作検証をしつつ比較を行い、結論としてはDMSを用いて移行することになりました。</p>
<p>主な理由は以下の3つです。</p>
<ul>
<li>移行にかかる時間がDMSの方が短い</li>
<li>移行当日の作業量がDMSの方が少ない</li>
<li>DMSではトリガー等の設定が移行される</li>
</ul>
<h3 id="移行にかかる時間がDMSの方が短い">移行にかかる時間がDMSの方が短い</h3>
<p>2通りの方法で移行を試した結果、DMSを用いた場合は1時間半程度でデータのExportからImportまでが完了しました。</p>
<p>しかし、DMSを使わない場合はExportからImportまで8時間以上かかりました。(特にImportに時間がかかった)</p>
<p>当たり前の話としてサービスのダウンタイムは短ければ短いほど良いため、この時点でDMSを使うことはほぼ確定しました。</p>
<h3 id="移行当日の作業量がDMSの方が少ない">移行当日の作業量がDMSの方が少ない</h3>
<p>他の理由としては、移行当日の作業量がDMSの方が圧倒的に少ないことも挙げられます。</p>
<p>DMSの場合は、事前に「移行ジョブ」を作成しておけば、当日は「移行開始ボタン」を押すだけで移行ができます。</p>
<p>しかしDMSを使わない場合は、Export,Importを手動で行う必要があるのに加えて、後述するトリガー等の設定も全て手動で移行する必要がありました。</p>
<p>当日の作業量が増えると思わぬエラーやミスで時間が延びる可能性もあるため、このDMSの作業量の少なさは大きな魅力の一つと考えました。</p>
<h3 id="DMSではトリガー等の設定が移行される">DMSではトリガー等の設定が移行される</h3>
<p>検証の結果、DMSを用いた場合はトリガーの設定も含めて移行されますが、DMSを使わない場合はトリガーの設定は移行されないことが分かりました。</p>
<p>前述したように、当日の作業量はなるべく減らしたかったため、トリガー等の設定を自動で移行できるDMSの方が有効と考えました。</p>
<p>ちなみに、DMSで移行が保証されているものは<a href="https://cloud.google.com/blog/ja/products/gcp/closing-gap-migration-completeness-when-using-database-migration-service#:~:text=MySQL%20%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E7%A7%BB%E8%A1%8C%E3%81%AE%E5%AF%BE%E8%B1%A1">こちら</a>の記事にまとめられてあります。</p>
<p>ストアドプロシージャ、ビュー、外部キー制約等は漏れなく移行されます。</p>
<p>ただ、一部DMSでは移行されない設定もあったため、次の項目(本番環境でデータ担保のテストを実施)で紹介します。</p>
<h2 id="6-本番環境でデータ担保のテストを実施">6. 本番環境でデータ担保のテストを実施</h2>
<p>ステージングでのテストの実施により、エラーの特定と解消は行えました。</p>
<p>しかし、あくまで「マスキングしたデータ」を用いてテストをしたため、「移行前後でデータが変化していないことの担保」はできていませんでした。</p>
<p>そのため、本番環境でコピー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>を作成してDMSを用いたデータ移行を行い、移行前後で同じ<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>を流してデータが変化していないことを確認しました。</p>
<p>このとき、移行前後でデータベースに保存されている時間(記事の作成日時など)が変化していることに気付きました。</p>
<p>これは、DMSではCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>のデータベースフラグの設定は移行されないため、移行後のDBの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>設定(default_time_zone)が<a class="keyword" href="http://d.hatena.ne.jp/keyword/UTC">UTC</a>時間になっていたことが原因でした。</p>
<p>※<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>のTIMESTAMP型の取得時の値はデータベースの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%A4%A5%E0%A5%BE%A1%BC%A5%F3">タイムゾーン</a>設定に依存する(DATETIME型は依存しない)</p>
<p>これについては、移行元<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>と同一のフラグを移行先にも設定することで解消できました。</p>
<h2 id="7-ステージング環境でリハーサルを実施">7. ステージング環境でリハーサルを実施</h2>
<p>データ担保のテストを実施した後は、ステージング環境でハーサルを実施しました。</p>
<p>ここでのポイントは、ステージングテストと同様、本番と同じデータ量のDBを使用したことです。</p>
<p>なぜなら、データ量が違うとDMSの移行時間が大きく変わってしまうため、移行時間の正確な計測が難しくなってしまうからです。</p>
<p>具体的には、データ容量に比例してDMSの移行時間も増えていました。</p>
<p>以下、ストレージ使用量の違うDBでそれぞれDMS移行を試した際にかかった時間の比較です。</p>
<ul>
<li>使用量60GiBのDB
<ul>
<li>1時間半程度</li>
</ul>
</li>
<li>使用量20GiBのDB
<ul>
<li>30分程度</li>
</ul>
</li>
</ul>
<p>このリハーサル結果を基に、本番環境での移行手順の作成と作業時間の見積もりを行いました。</p>
<p>また、影響範囲の大きい作業となるため、早めに広く告知することも意識しました。(オールアバウトの場合社外のガイドにも告知が必要)</p>
<h2 id="8-本番環境で移行作業を実施">8. 本番環境で移行作業を実施</h2>
<p>最後に本番環境で移行作業を実施しました。</p>
<p>ここで意識したことは、なるべく最小時間で作業が終わるようリリースの順序を工夫することです。</p>
<p>例えばDMS移行の待ち時間の間に各アプリのDB接続情報の変更やリリース準備を進めておくなど、無駄な時間ができるだけ発生しないよう工夫しました。</p>
<p>結果としては、予定より早く3時間半程度で全ての移行作業を完了することができました。</p>
<h1 id="移行を進めるにあたり意識したこと">移行を進めるにあたり意識したこと</h1>
<p>移行作業を進めるにあたり意識した事は、まずは「ミスをしない」ことです。</p>
<p>DBの移行は一歩間違うと長時間DB(システム)が停止する可能性もあるため、慎重に行う必要がありました。</p>
<p>具体的には、厚くテストをするのはもちろんのこと、リリースの際にも切り戻し用のプランを用意しておくなど、常に悪い状況を想定して準備を行いました。</p>
<p>また、今回は自チームだけでなく複数のチームが連携して動く必要があったため、動き方の認識を合わせるミーティングを開いたり、都度作業の進捗を確認するなどして全体の作業がスムーズにが進むよう調整することも意識しました。</p>
<h1 id="おわりに">おわりに</h1>
<p>個人的には<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>のバージョンアップは初めての経験だったため、最初はどこから手を付けていいかも分かりませんでした。</p>
<p>しかし、周りの手を借りたり個人的に勉強しつつ進めることで、何とか大きなミスなく移行作業を終えることができました。</p>
<p>また、同時にDMSやクエリチューニングなどDB周りの知見も多く増やすことができました。</p>
<p>今後は今回の作業で得た知見を日々の業務に活かすのはもちろんのこと、よりDB周りの知見を増やしていけるよう日々精進していきたいと考えています。</p>
<p>最後まで読んで頂きありがとうございました。</p>
<h1 id="All-Aboutリビルドエンジニア募集のお知らせ">All Aboutリビルド:エンジニア募集のお知らせ</h1>
<p>オールアバウトでは、2001年にサービスをスタートしたメディア<a href="https://allabout.co.jp/">All About</a>のリビルドに取り組むエンジニアを募集しています。</p>
<p>オールアバウトとしてこれまでメインでは使ってこなかったTypeScriptの採用等、技術的に大きな取り組みにチャレンジできるプロジェクトです。</p>
<p>興味のある方は以下のリンクからお申し込みください。</p>
<p><a href="https://hrmos.co/pages/allaboutgroup/jobs/engineer_rebuild">https://hrmos.co/pages/allaboutgroup/jobs/engineer_rebuild</a></p>
<p>沢山のご応募をお待ちしております!</p>
allabout-techblog
開発部で1年間やったこと
hatenablog://entry/13574176438073833381
2022-03-31T11:21:07+09:00
2022-03-31T11:21:07+09:00 毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2022」を開催します。 今回は、オールアバウトマーケティング開発部の@woodyがお送りします。 1.はじめに 2.どんな業務をしているか 2.1.主な開発内容について 2.2.使用技術 3.業務の流れ 3.1.事業の課題をtrelloに記載し重要度を割り振る 3.2.重要度の高いものから、開発対象としてタスク化する 3.3.スプリント内で解決すべきタスクを各レーンへ割り振る 3.4.設計 3.5.実装 3.6.レビュー 3.7.ステージングリリース 3.8.本番リリース 4.感じたこと 4.1.開発にお…
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220330/20220330163558.png" alt="f:id:allabout-techblog:20220330163558p:plain" width="1200" height="680" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span>
毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2022」を開催します。 今回は、オールアバウト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>開発部の@woodyがお送りします。</p>
<ul class="table-of-contents">
<li><a href="#1はじめに">1.はじめに</a></li>
<li><a href="#2どんな業務をしているか">2.どんな業務をしているか</a><ul>
<li><a href="#21主な開発内容について">2.1.主な開発内容について</a></li>
<li><a href="#22使用技術">2.2.使用技術</a></li>
</ul>
</li>
<li><a href="#3業務の流れ">3.業務の流れ</a><ul>
<li><a href="#31事業の課題をtrelloに記載し重要度を割り振る">3.1.事業の課題をtrelloに記載し重要度を割り振る</a></li>
<li><a href="#32重要度の高いものから開発対象としてタスク化する">3.2.重要度の高いものから、開発対象としてタスク化する</a></li>
<li><a href="#33スプリント内で解決すべきタスクを各レーンへ割り振る">3.3.スプリント内で解決すべきタスクを各レーンへ割り振る</a></li>
<li><a href="#34設計">3.4.設計</a></li>
<li><a href="#35実装">3.5.実装</a></li>
<li><a href="#36レビュー">3.6.レビュー</a></li>
<li><a href="#37ステージングリリース">3.7.ステージングリリース</a></li>
<li><a href="#38本番リリース">3.8.本番リリース</a></li>
</ul>
</li>
<li><a href="#4感じたこと">4.感じたこと</a><ul>
<li><a href="#41開発においてはデバッグできるかが大事">4.1.開発においてはデバッグできるかが大事</a><ul>
<li><a href="#411エラー文を出す">4.1.1.エラー文を出す</a></li>
<li><a href="#412問題を切り分ける">4.1.2.問題を切り分ける</a></li>
<li><a href="#413質問する">4.1.3.質問する</a></li>
</ul>
</li>
<li><a href="#42手運用でカバーすることも候補の一つ">4.2.手運用でカバーすることも候補の一つ</a></li>
<li><a href="#43どうやるかよりも取り組むべき課題の見極めが大事">4.3.どうやるかよりも取り組むべき課題の見極めが大事</a></li>
</ul>
</li>
<li><a href="#5おわりに">5.おわりに</a></li>
</ul>
<h1 id="1はじめに">1.はじめに</h1>
<p>2022年4月に入社し、7月まで研修を受けたあと、開発部の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>開発グループのチームに所属して業務を行っています。</p>
<p>本記事では実際にどんな風に業務を行ってきて、どんなことを感じたのかを書いています。</p>
<p>学生時代は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%FD%B7%D7%B3%D8">統計学</a>を扱う研究室に入っていて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>よりもデータ分析をメインでやっておりました。</p>
<p>分析だけでなく実際のプロダクトを作れるようになりたいと感じ、事業系会社の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF%B2%F1%BC%D2">アプリ開発会社</a>に就職しました。</p>
<p>初めてのことが多く学びが多かった一年となりました。</p>
<h1 id="2どんな業務をしているか">2.どんな業務をしているか</h1>
<h2 id="21主な開発内容について">2.1.主な開発内容について</h2>
<p>現在はコンテンツ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>プラットフォーム「PrimeAd」の中のビジネスマッチングプラットフォームの開発業務に従事しています。</p>
<p>広告を出したい広告代理店と広告を載せるメディアをつなぐプラットフォームです。</p>
<p>ビジネスマッチングプラットフォームは新規事業としてはじまり、2020年7月にローンチされたばかりで、現在も試行錯誤しながら事業拡大を図っています。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fprimead.jp%2F" title="All About PrimeAd(プライムアド) - ビジネスマッチングプラットフォーム" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://primead.jp/">primead.jp</a></cite></p>
<h2 id="22使用技術">2.2.使用技術</h2>
<p>基本的に以下の技術を使って開発を進めています。</p>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>, Docker</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a></li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>, <a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a></li>
<li>Laravel</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a></li>
<li>CircleCI, Bitbucket, Slack, Trello</li>
</ul>
<h1 id="3業務の流れ">3.業務の流れ</h1>
<p>チームでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B8%A5%E3%A5%A4%A5%EB">アジャイル</a>開発を採用していて2週間単位のスプリントで開発をしています。</p>
<p>私達のチームでは以下の流れで開発を進めています。</p>
<ol>
<li>事業の課題をtrelloに記載し重要度を割り振る</li>
<li>重要度の高いものから、開発対象としてタスク化する</li>
<li>スプリント内で解決すべきタスクを各レーンへ割り振る</li>
<li>設計 (ここから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>)</li>
<li>実装</li>
<li>レビュー</li>
<li>ステージングリリース</li>
<li>本番リリース</li>
</ol>
<p><figure class="figure-image figure-image-fotolife" title="スプリントの流れ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220329/20220329095051.jpg" alt="f:id:allabout-techblog:20220329095051j:plain" width="960" height="540" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>スプリントの流れ</figcaption></figure></p>
<h2 id="31事業の課題をtrelloに記載し重要度を割り振る">3.1.事業の課題をtrelloに記載し重要度を割り振る</h2>
<p>チームとして事業の課題や開発タスクはTrelloのカンバンで管理しています。</p>
<p>ユーザーから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D2%A5%A2%A5%EA">ヒアリ</a>ングした課題や開発中に感じた課題がTrelloのカンバンボードに記載されていきます。</p>
<p>記載されているタスクをもとに重要度を割り振っていきます。</p>
<h2 id="32重要度の高いものから開発対象としてタスク化する">3.2.重要度の高いものから、開発対象としてタスク化する</h2>
<p>重要度を割り振ったものの中でどのように開発を進めていくか議論をして、タスクとして進められるようにしていきます。</p>
<h2 id="33スプリント内で解決すべきタスクを各レーンへ割り振る">3.3.スプリント内で解決すべきタスクを各レーンへ割り振る</h2>
<p>チームでは二人一組でペアを作って作業を進めています。各レーンに対して合計稼働可能時間を超えないようにタスクを割り振っていきます。</p>
<h2 id="34設計">3.4.設計</h2>
<p>担当を割り振ったら、設計を行います。 ここからペアで作業をしていきます。</p>
<p>機能の要件や画面設計をしていきます。</p>
<h2 id="35実装">3.5.実装</h2>
<p>開発するときは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0">ペアプログラミング</a>を行っていて、二人一組で交代で意見を出しながら実装をしています。</p>
<h2 id="36レビュー">3.6.レビュー</h2>
<p>実装したものをチームでコードレビューをしています。コードレビューを挟むことでコードの品質を担保しています。</p>
<h2 id="37ステージングリリース">3.7.ステージングリリース</h2>
<p>コードレビューを経て問題がなさそうであればステージングリリースまで行います。</p>
<p>ステージングとは本番環境と同様の状態でシステムの動作や不具合のチェックを行う段階です。</p>
<h2 id="38本番リリース">3.8.本番リリース</h2>
<p>ステージング環境で問題がなさそうであればリリースを行います。</p>
<h1 id="4感じたこと">4.感じたこと</h1>
<p>技術的な学びはもちろんありましたが考え方の学びが多かった一年だなと思います。大きく分けて3つの学びがありました。</p>
<h2 id="41開発においてはデバッグできるかが大事">4.1.開発においては<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>できるかが大事</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>とはバグと呼ばれるプログラム上の間違いを見つけて排除する作業のことです。</p>
<p>今まではどのようにコーディングするかが大事だと考えていました。しかしながら実際に開発をしていくと多くの時間をエラーの対応に使うことになりました。</p>
<p>人為的なミスや、想定していないパターンでのエラーはよく出てきます。なのでいかに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>を効率よくするかが大事です。</p>
<p>その時に特に「エラー文を出す」「問題を切り分ける」「質問する」ことの3点が大事だったなと感じました。</p>
<h3 id="411エラー文を出す">4.1.1.エラー文を出す</h3>
<p>プログラムを書いていく中で、エラーが発生した時にエラー箇所とどんなエラー内容だったかを出力してあげるようにすることでバグの場所の特定が容易になります。</p>
<h3 id="412問題を切り分ける">4.1.2.問題を切り分ける</h3>
<p>エラーが出たとしてもどこが悪いのか見当がつかない時があったりします。その時は条件を固定したり、検証範囲を狭めたりして問題となりそうな部分をあぶりだすことが有効だったりします。</p>
<h3 id="413質問する">4.1.3.質問する</h3>
<p>どうしてもわからなくなったときには質問して教えてもらったりすることが大事になってきます。</p>
<p>先輩エンジニアに質問をすることで自分が持っていない視点があったりするのですんなりと解決することがあったりしました。</p>
<h2 id="42手運用でカバーすることも候補の一つ">4.2.手運用でカバーすることも候補の一つ</h2>
<p>顧客課題を解決するために機能を作っていきますが、やっていくうちにあれもこれもあったらいいとなって実装したい機能が多くなってしまいます。</p>
<p>時間と開発者は有限なので最小限の機能を考え、機能をリリースして顧客のフィードバックを元に改善していくことが大事です。</p>
<p>例えば本来システム化するところを人力で行って、利用されるかを試したりするなどの方法があったりします。</p>
<p>いかに素早く検証ができるかが大事だと身にしみて感じた一年でした。</p>
<h2 id="43どうやるかよりも取り組むべき課題の見極めが大事">4.3.どうやるかよりも取り組むべき課題の見極めが大事</h2>
<p>どう実装するかも大事ですが、それよりも何を実装するかの方がとても重要です。実装したとしても使われなかったら意味がないので努力が水の泡となってしまいます。</p>
<p>そういった背景から実装している時間と同じぐらいチームでは課題に対する議論を行い、何を実装するかを検討しています。</p>
<p>また課題をいかに解像度を高めれるかが実装までスムーズに行えるかの分岐点となります。何を解決したいのか実際曖昧なまま進めてリリースできなかった機能があったりしたので気をつけたいところです。</p>
<h1 id="5おわりに">5.おわりに</h1>
<p>一年を通して開発エンジニアとして実装する力も大事ですが、取り組む上での姿勢やチームとしてどう動いていくかが重要だと感じました。</p>
<p>これからエンジニアとして業務に入る人の参考になれば幸いです!!</p>
<p>最後に、現在オールアバウトでは、エンジニアを絶賛募集中です。</p>
<p>ちょっと話を聞いてみたいなどでももちろん大丈夫です!</p>
<p>少しでも興味を持っていただけた方はぜひ採用サイトからご連絡ください。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcorp.allabout.co.jp%2Frecruit%2F" title="オールアバウトグループのコーポレートサイト – 採用情報" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://corp.allabout.co.jp/recruit/">corp.allabout.co.jp</a></cite></p>
allabout-techblog
CircleCi で OIDC(OpenID Connect) がサポートされたので Google Cloud で試してみた
hatenablog://entry/13574176438077943912
2022-03-30T16:26:13+09:00
2022-03-30T16:26:13+09:00 こんにちは。オールアバウト SRE 所属 の@s_ishiiと申します。 先日 CircleCi で OIDC(OpenID Connect)がサポートされました。 Github Actions で OIDC がサポートされてからこの日が来るのを待ち望んでいたので早速オールアバウトの CI で利用してみました。 https://twitter.com/CircleCIJapan/status/1507524861396422657?cxt=HHwWgsDU2fn35uspAAAA OIDC があると何が良いのか? 「そもそも OIDC って何が良いの?」という方のために OIDC 登場以前と以…
<p>こんにちは。オールアバウト SRE 所属 の<a href="https://qiita.com/ishii1648">@s_ishii</a>と申します。</p>
<p>先日 CircleCi で OIDC(<a class="keyword" href="http://d.hatena.ne.jp/keyword/OpenID">OpenID</a> Connect)がサポートされました。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/Github">Github</a> Actions で OIDC がサポートされてからこの日が来るのを待ち望んでいたので早速オールアバウトの CI で利用してみました。</p>
<p><a href="https://twitter.com/CircleCIJapan/status/1507524861396422657?cxt=HHwWgsDU2fn35uspAAAA">https://twitter.com/CircleCIJapan/status/1507524861396422657?cxt=HHwWgsDU2fn35uspAAAA</a></p>
<h2>OIDC があると何が良いのか?</h2>
<p>「そもそも OIDC って何が良いの?」という方のために OIDC 登場以前と以後の世界について簡単にご説明します。</p>
<p>従来 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud 等の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>の <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> やリソース に CircleCi からアクセスするには、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>側でサービスアカウントキーを発行し、CircleCi の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%C4%B6%AD%CA%D1%BF%F4">環境変数</a>として登録する必要がありました。</p>
<p>この方法の問題点はサービスアカウントキーが本質的にセキュアでないという点です。<br />
サービスアカウントキーは明示的に削除しない限り最長 10 年間認証可能なのでキーの漏洩リスクが常に存在します。</p>
<p>OIDC を利用することでサービスアカウントキーなしで認証を通すことができるためよりセキュアな運用が可能になります。</p>
<p>OIDC に関する説明は <a class="keyword" href="http://d.hatena.ne.jp/keyword/Github">Github</a> の以下ページでよくまとめられているので関心のある方は一読されることをおすすめします。
<a href="https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect">https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect</a></p>
<p>※<code>Understanding the OIDC token</code> 以降は <a class="keyword" href="http://d.hatena.ne.jp/keyword/Github">Github</a> Actions 固有の話しです</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud で CircleCi OIDC を利用する手順</h2>
<p>ここからは具体的な設定手順について解説していきます。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud で CircleCi OIDC を利用するには以下 2 点が必要になります。</p>
<ul>
<li>Workload Identity Pool の作成(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud)</li>
<li>アクセス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>ン取得用のコードの追加(CircleCi)</li>
</ul>
<h3>Workload Identity Pool の作成(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud)</h3>
<p>基本的な手順は <a class="keyword" href="http://d.hatena.ne.jp/keyword/Github">Github</a> の以下ページで詳細に説明されています。
<a href="https://github.com/google-github-actions/auth#setting-up-workload-identity-federation">https://github.com/google-github-actions/auth#setting-up-workload-identity-federation</a></p>
<p>オールアバウトでは <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud のインフラ群は Terraform で管理しているので以下のようなコードで設定しました。</p>
<pre class="code lang-terraform" data-lang="terraform" data-unlink><span class="synType">locals</span> <span class="synSpecial">{</span>
<span class="synIdentifier">circleci_organization_id</span> = <span class="synConstant">"<CircleCi Organization ID>"</span>
<span class="synSpecial">}</span>
<span class="synType">resource</span> <span class="synConstant">"google_iam_workload_identity_pool"</span> <span class="synConstant">"circleci"</span> <span class="synSpecial">{</span>
<span class="synIdentifier">provider</span> = google-beta
<span class="synIdentifier">workload_identity_pool_id</span> = <span class="synConstant">"circleci-pool"</span>
<span class="synSpecial">}</span>
<span class="synType">resource</span> <span class="synConstant">"google_iam_workload_identity_pool_provider"</span> <span class="synConstant">"circleci"</span> <span class="synSpecial">{</span>
<span class="synIdentifier">provider</span> = google-beta
<span class="synIdentifier">workload_identity_pool_id</span> = google_iam_workload_identity_pool.circleci.workload_identity_pool_id
<span class="synIdentifier">workload_identity_pool_provider_id</span> = <span class="synConstant">"circleci-prvdr"</span>
<span class="synIdentifier">attribute_mapping</span> = <span class="synSpecial">{</span>
<span class="synConstant">"google.subject"</span> = <span class="synConstant">"assertion.sub"</span>
<span class="synConstant">"attribute.actor"</span> = <span class="synConstant">"assertion.actor"</span>
<span class="synConstant">"attribute.repository"</span> = <span class="synConstant">"assertion.repository"</span>
<span class="synSpecial">}</span>
<span class="synType">oidc</span> <span class="synSpecial">{</span>
<span class="synIdentifier">allowed_audiences</span> = <span class="synSpecial">[</span>local.circleci_organization_id<span class="synSpecial">]</span>
<span class="synIdentifier">issuer_uri</span> = <span class="synConstant">"https://oidc.circleci.com/org/$</span><span class="synSpecial">{</span>local.circleci_organization_id<span class="synSpecial">}</span><span class="synConstant">"</span>
<span class="synSpecial">}</span>
}
<span class="synType">module</span> <span class="synConstant">"circleci_sa"</span> <span class="synSpecial">{</span>
<span class="synIdentifier">source</span> = <span class="synConstant">"terraform-google-modules/service-accounts/google"</span>
<span class="synIdentifier">version</span> = <span class="synConstant">"~> 4.1.1"</span>
<span class="synIdentifier">display_name</span> = <span class="synConstant">"CircleCi Service Account"</span>
<span class="synIdentifier">project_id</span> = var.project_id
<span class="synIdentifier">prefix</span> = <span class="synConstant">"sa-$</span><span class="synSpecial">{</span>var.env_code<span class="synSpecial">}</span><span class="synConstant">"</span>
<span class="synIdentifier">names</span> = <span class="synSpecial">[</span><span class="synConstant">"circleci"</span><span class="synSpecial">]</span>
<span class="synIdentifier">project_roles</span> = <span class="synSpecial">[</span>
<span class="synConstant">"$</span><span class="synSpecial">{</span>var.project_id<span class="synSpecial">}</span><span class="synConstant">=>roles/artifactregistry.writer"</span>,
<span class="synSpecial">]</span>
}
<span class="synType">resource</span> <span class="synConstant">"google_service_account_iam_member"</span> <span class="synConstant">"circleci_sa"</span> <span class="synSpecial">{</span>
<span class="synIdentifier">service_account_id</span> = module.circleci_sa.service_accounts<span class="synSpecial">[</span><span class="synConstant">0</span><span class="synSpecial">]</span>.id
<span class="synIdentifier">role</span> = <span class="synConstant">"roles/iam.workloadIdentityUser"</span>
<span class="synIdentifier">member</span> = <span class="synConstant">"principalSet://iam.googleapis.com/$</span><span class="synSpecial">{</span>google_iam_workload_identity_pool.circleci.name<span class="synSpecial">}</span><span class="synConstant">/*"</span>
<span class="synSpecial">}</span>
</pre>
<p>やっていることをまとめると以下 3 点になります。</p>
<ul>
<li>Workload Identity Pool の作成</li>
<li>Workload Identity Provider の作成</li>
<li>ID 連携用のサービスアカウントの作成</li>
</ul>
<p>基本的には 上記で紹介した <a class="keyword" href="http://d.hatena.ne.jp/keyword/Github">Github</a> のページで説明されていることを Terraform で書いただけですが、audience として CircleCi の<strong>Organization ID</strong>を追加で設定しています。</p>
<p>何故 audience の設定を追加しているのかというと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Github">Github</a> Actions と CircleCi で発行する OIDC Token の中身が違うためです。<br />
具体的には CircleCi の OIDC Token には aud 値として CircleCi の Organization ID が入るため Workload Identity Provider 側でこの値を許可するよう設定する必要があります。</p>
<p>なお、CircleCi の Organization ID は管理画面の Organization Settings からご確認頂けます。</p>
<h3>アクセス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>ン取得用のコードの追加(CircleCi)</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud の設定が完了したら次は CircleCi 側のコードを変更します。</p>
<p>CircleCi のドキュメントを読むと今回のリリースで CircleCi の各 Job で <code>CIRCLE_OIDC_TOKEN</code> という<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%C4%B6%AD%CA%D1%BF%F4">環境変数</a>が利用可能になっており、この変数に OIDC Token が格納されています。<br />
<a href="https://circleci.com/docs/ja/2.0/openid-connect-tokens/">https://circleci.com/docs/ja/2.0/openid-connect-tokens/</a></p>
<p>この OIDC Token を最終的にサービスアカウントのアクセス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>ンと交換するようコードを書いてやる必要があり、具体的には以下のようなコードになります。</p>
<pre class="code" data-lang="" data-unlink>- run:
name: Google Authentication
command: |
ACCESS_TOKEN=`curl -X POST -s \
-H "Content-Type: application/json; charset=utf-8" \
-d "{
"audience": \"//iam.googleapis.com/projects/<< parameters.project_number >>/locations/global/workloadIdentityPools/circleci-pool/providers/circleci-prvdr\",
"grantType": \"urn:ietf:params:oauth:grant-type:token-exchange\",
"requestedTokenType": \"urn:ietf:params:oauth:token-type:access_token\",
"scope": \"https://www.googleapis.com/auth/cloud-platform\",
"subjectTokenType": \"urn:ietf:params:oauth:token-type:jwt\",
"subjectToken": \"${CIRCLE_OIDC_TOKEN}\"
}" \
"https://sts.googleapis.com/v1/token" | jq -r .access_token`
SA_ACCESS_TOKEN=`curl -X POST -s \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json; charset=utf-8" \
-d "{
"scope": [
\"https://www.googleapis.com/auth/cloud-platform\"
]
}" \
"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/<< parameters.sa_email >>:generateAccessToken" | jq -r .accessToken`
echo $SA_ACCESS_TOKEN | docker login -u oauth2accesstoken --password-stdin https://asia-east1-docker.pkg.dev</pre>
<p>※<code><< parameters.sa_email >></code> には <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud 作成したサービスアカウントのメールアドレスが入ります</p>
<p>詳細な説明は <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud の以下公式ページをご確認頂くとして、簡単に説明すると 1 回目のリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トで Workload Identity の認証を通し、2 回目で事前に設定したサービスアカウトを一時的に借用するためのリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを送信しています。</p>
<p><a href="https://cloud.google.com/iam/docs/access-resources-oidc?hl=ja#exchange-token">https://cloud.google.com/iam/docs/access-resources-oidc?hl=ja#exchange-token</a></p>
<h2>動作確認</h2>
<p>上記コードを動かすと以下のようになります。
(実際にはこの後続の step で Docker イメージを build して Artifact Registry に Push しています)</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220329/20220329210816.png" alt="f:id:allabout-techblog:20220329210816p:plain" width="1200" height="523" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud 側ではサービスアカウントが借用されたログを確認できます。
(事前に監査ログを有効化する必要があります)</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220329/20220329210851.png" alt="f:id:allabout-techblog:20220329210851p:plain" width="1200" height="433" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h2>まとめ</h2>
<p>CircleCi の OIDC はサポートしたばかりのため Orb がまだ作られておらず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>ン取得周りのコードを自分で書く必要があります。<br />
これはなかなか大変ですが、一度実装してしまえばサービスアカウントキーの管理から開放されるのでメリットは非常に大きいです。</p>
<p>今回は <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud での実装例の紹介でしたが、もちろん <a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a> 等の他の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>でも利用できるので CircleCi を利用されている方は利用を検討することをおすすめします。</p>
<p>以上、「CircleCi で OIDC(<a class="keyword" href="http://d.hatena.ne.jp/keyword/OpenID">OpenID</a> Connect) がサポートされたので <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud で試してみた」でした。</p>
allabout-techblog
新卒が感じた仕様調整の難しさ
hatenablog://entry/13574176438073451822
2022-03-30T14:37:10+09:00
2022-03-30T14:37:10+09:00 はじめに オールアバウトグループの新卒1年目エンジニアが投稿する企画『テックブログ新卒週間2022』。 今回はタケウチがお送りします。 私は2021年4月に入社し、7月半ばまでオールアバウトグループ研修とアプリ開発研修を受けました。 研修後には、メディア開発1グループに所属し業務をしています。 本記事ではメディア開発1グループがどのような働き方で、私が実際にどのような業務に取り組んできたのかを紹介します。また振り返りを兼ねてチームで業務を進めるにあたって難しさを感じた他部署、他グループとの仕様の調整について紹介していきます。 どんな業務をしているか 私の所属するグループでは、All About…
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220330/20220330090737.png" alt="f:id:allabout-techblog:20220330090737p:plain" width="1200" height="680" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h1>はじめに</h1>
<p>オールアバウトグループの新卒1年目エンジニアが投稿する企画『テックブログ新卒週間2022』。</p>
<p>今回はタケウチがお送りします。</p>
<p>私は2021年4月に入社し、7月半ばまでオールアバウトグループ研修と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>研修を受けました。
研修後には、メディア開発1グループに所属し業務をしています。</p>
<p>本記事ではメディア開発1グループがどのような働き方で、私が実際にどのような業務に取り組んできたのかを紹介します。また振り返りを兼ねてチームで業務を進めるにあたって難しさを感じた他部署、他グループとの仕様の調整について紹介していきます。</p>
<h1>どんな業務をしているか</h1>
<p>私の所属するグループでは、All About、All About Newsという2つのメディア運営に関するシステムの開発・保守をしています。</p>
<p>具体的なシステムの開発・保守としては以下が挙げられます。</p>
<ul>
<li>ユーザーが記事閲覧しやすいようにメディアのデザインや機能の改善</li>
<li>All Aboutの記事を他社のニュースプラットフォームへ提供・配信する機能の開発</li>
<li>記事入稿システムの機能改善(記事入稿の補助機能など)</li>
</ul>
<h1>業務の進め方</h1>
<p>業務の進め方としては<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%E9%A5%E0">スクラム</a>を採用しており、1スプリントの期間は1週間です。この期間で開発を進めています。</p>
<p>※<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%E9%A5%E0">スクラム</a>とは</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.otsuka-shokai.co.jp%2Fwords%2Fscrum.html" title="スクラム | IT用語辞典 | 大塚商会" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://www.otsuka-shokai.co.jp/words/scrum.html">www.otsuka-shokai.co.jp</a></cite></p>
<p>スプリントは毎週木曜日に始まります。</p>
<p>木曜日にメディアを担当する企画チーム、編集部との定例で開発する機能や施策の優先順位を決めます。それからスプリントプランニングを行い、スプリントで実施する施策を決めます。そしてスプリントでやる内容を企画チーム、記事制作チームに確認してもらい、合意を得ます。</p>
<p>金曜日から水曜日で施策や機能の開発に取り組みます。</p>
<p>そして次のスプリントの初日である木曜日に、前回のスプリントで開発した施策や機能を企画チーム、編集部に向けてデモをしてレビューをしてもらいます。
その後に開発する機能や施策の優先順位を決めるといったサイクルでスプリントを回していきます。</p>
<p><figure class="figure-image figure-image-fotolife" title="スプリントのイメージ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220325/20220325152727.png" alt="f:id:allabout-techblog:20220325152727p:plain" width="961" height="545" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>スプリントのイメージ</figcaption></figure></p>
<p>また業務の特性上、エンジニアだけで完結する業務はほとんどなく、企画チームや編集部とコミュニケーションを取りながら仕様や開発のゴールを決めていきます。</p>
<p>その仕様決めのコミュニケーションがうまくいかず、スプリントに遅れが生じ、苦労したケースが何度かあります。次にそこを掘り下げます。</p>
<h1>苦労した仕様決め</h1>
<p>メディア開発1グループでは、プロジェクト管理ツール「Backlog」を用いてタスクを管理しています。定例ではBacklogを企画チームや編集部と確認し、開発の要件やゴールを記載していきます。</p>
<p>開発を進めていくにあたって新たな考慮点が発生することがあるのでその都度、仕様を決めていきます。</p>
<p>最も仕様決めに時間のかかっていた、メディア開発1グループに所属して数ヶ月間のコミュニケーションを振り返ってみると、簡単なタスクにも関わらず仕様を決めるのに数日かかっていました。また先輩の助け無しでは仕様漏れも現在より頻繁に起こっていました。</p>
<p>チームメンバーからの指摘もあり、以下が課題になっていると考えました。</p>
<ol>
<li>文章を長く書いてしまって読みづらく、相手に意見を伝えるのに時間がかかる</li>
<li>仕様をどうするか全て質問してしまっている</li>
</ol>
<h2>1. 文章を長く書いてしまって読みづらく、相手に意見を伝えるのに時間がかかる</h2>
<p>文章が読みづらいことが原因でコミュニケーションのラリーが何度も発生していました。そのため自分の時間だけではなく、返信している関係者の時間まで無駄に消費してしまう状態になっていました。</p>
<p>オールアバウトには『ななメンター』という制度があり、新卒に自分の所属するグループ以外の先輩がメンターとしてつきます。そのななメンターでのランチの際に先輩にコミュニケーションの取り方について相談しました。</p>
<p>ななメンターからは文章力についての本(『<a href="https://www.amazon.co.jp/dp/B00JGR3T7O/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1">メール文章力の基本 大切だけど、だれも教えてくれない77のルール</a>』)を紹介してもらいました。</p>
<p>本から得た文章を書く際の以下のテクニックを特に意識するようになりました。</p>
<ul>
<li>文章ではなく箇条書きを原則とする</li>
<li>曖昧な表現を使用しない</li>
<li>主語、主体を明確にする</li>
<li>本文で説明するか、添付ファイルで説明するかを検討する</li>
</ul>
<p>上記を意識して、社内のslackの文章で改善できる箇所を見つけて修正していくことで、本から得た学びをアウトプットしていきました。</p>
<p>そして、修正した文章をななメンターとのランチ会でレビューをしてもらいました。</p>
<p>また先輩方の文章などを参考にして徐々に改善していきました。</p>
<h2>2. 仕様をどうするか全て質問してしまっている</h2>
<p>質問相手に仕様を任せていることも同じくコミュニケーションが何度も発生する原因でした。</p>
<p>企画チームや編集部は仕様を全て把握しているわけでは当然ないので、質問されてからどうするかを考える時間が発生します。</p>
<p>また仕様によって開発の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%A9%BF%F4">工数</a>も変わるので、企画チームや編集部は容易に決めることができません。</p>
<p>例えば、『記事の更新日を記事の上部に表示したい』という施策があったとします。</p>
<p>これまでは以下のように企画チームに質問していました。</p>
<blockquote><p>PC版の記事更新日の表示位置を変更する施策について質問があります。<br>
具体的に記事のどの箇所に追加したらよろしいでしょうか?</p></blockquote>
<p>これでは企画チーム側でどの箇所に表示をしたいかを0から考える必要があります。</p>
<p>そのため質問として相手側に丸投げするのではなく、こちらから案を出すように意識的に変えていきました。</p>
<blockquote><p> PC版の記事更新日の表示位置を変更する施策について相談があります。<br>
記事更新日をどの箇所に表示しましょうか?<br><br>
記事更新日の表示位置についてPC版のモックを3案作成しました。<br>
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%D7%A5%EC%A5%C3%A5%C9%A5%B7%A1%BC%A5%C8">スプレッドシート</a>に記載しております。<br>
どの案が良いか、もしくは他の表示位置を検討する必要があるかをご意見いただきたいです。</p></blockquote>
<p> 上記のように相談することで、相談される側もどう返事をするかを考えやすくなりますし、仕様のすり合わせにかかるコミュニケーションの量も以前より減らすことができました。</p>
<h1>終わりに</h1>
<p>メディア開発1グループに所属した自分がどのように業務をしているのか、苦労した仕様決めのコミュニケーションをどう改善していったのかを紹介しました。</p>
<p>開発が思うように進まなかったり、仕様をなかなか整理できなかったりとうまくいかないことが多い新卒の1年間でした。</p>
<p>しかし、このブログを書くにあたり過去のslackでのコミュニケーションや資料、プルリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トなどを振り返ると成長していることは感じられました。</p>
<p>今後も開発の力とコミュニケーション力を鍛えて、出来ることを着実に増やし、仕事を楽しく進めていきたいと思います。</p>
allabout-techblog
オールアバウトエンジニアのSlack人気スタンプを調査してみた
hatenablog://entry/13574176438071143930
2022-03-29T10:11:52+09:00
2022-03-29T10:11:52+09:00 毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2022」を開催します。 今回は、オールアバウトメディア開発部の@eeveeがお送りします。 はじめに 突然ですが、皆さんはSlackをご存知ですか? 株式会社オールアバウトでは、社内のコミュニケーションツールとしてSlackを採用し、業務上のやりとりを行っています。 Slackでは投稿に対して文字で補足や反応する代わりに絵文字でリアクションを取ることができます。 Slack公式の定義にならい、この絵文字でのリアクションのことを絵文字リアクションと呼びます。 社内Slackでは、多種多様なカスタム絵文字が登…
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220329/20220329100800.png" width="1200" height="680" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span>
毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2022」を開催します。</p>
<p>今回は、オールアバウトメディア開発部の@eeveeがお送りします。</p>
<h1 id="はじめに">はじめに</h1>
<p>突然ですが、皆さんはSlackをご存知ですか?</p>
<p>株式会社オールアバウトでは、社内のコミュニケーションツールとしてSlackを採用し、業務上のやりとりを行っています。</p>
<p>Slackでは投稿に対して文字で補足や反応する代わりに絵文字でリアクションを取ることができます。</p>
<p>Slack公式の定義にならい、この絵文字でのリアクションのことを絵文字リアクションと呼びます。</p>
<p>社内Slackでは、多種多様なカスタム絵文字が登録され、絵文字リアクションがコミュニケーションの一環として使われています。</p>
<p>社内Slackの絵文字リアクションを集計してみるとチームごとのコミュニケーションの違いが現れておもしろいのではないかと思い、人気絵文字リアクションを調査してみました。</p>
<p>本記事では、その調査方法と結果を紹介したいと思います。
社内Slackのデータを分析してみたい方、またオールアバウトの開発チームのSlack事情気になる!という方の参考になれば幸いです。</p>
<ul class="table-of-contents">
<li><a href="#はじめに">はじめに</a></li>
<li><a href="#自己紹介">自己紹介</a></li>
<li><a href="#Slackのスタンプを解析してみた">Slackのスタンプを解析してみた</a><ul>
<li><a href="#集計ルール">集計ルール</a></li>
<li><a href="#全体の実装の流れ">全体の実装の流れ</a></li>
<li><a href="#SlackAPIを利用する準備">SlackAPIを利用する準備</a><ul>
<li><a href="#Slack-Appを作成する">Slack Appを作成する</a></li>
</ul>
</li>
<li><a href="#実装の流れ">実装の流れ</a><ul>
<li><a href="#メッセージ履歴とリアクションの取得">メッセージ履歴とリアクションの取得</a></li>
<li><a href="#絵文字一覧の取得">絵文字一覧の取得</a></li>
<li><a href="#カウントする際に気をつけるポイント">カウントする際に気をつけるポイント</a></li>
</ul>
</li>
<li><a href="#調査結果">調査結果</a></li>
</ul>
</li>
<li><a href="#最後に">最後に</a></li>
</ul>
<h1 id="自己紹介">自己紹介</h1>
<p>私は非情報系学部出身で、業界未経験から新卒入社しており、今回のようなWEB <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を使ったデータ集計は初めての試みでした。
そのためかなりの試行錯誤を経て集計しており、今回ご紹介する実装方針はあくまで一例であるということを前提に読んでいただければと思います。</p>
<p>私は開発部の中でも、オールアバウトで運営するメディアや社内<a class="keyword" href="http://d.hatena.ne.jp/keyword/CMS">CMS</a>の開発・メンテナンスをするチームに所属しています。
個人作業のときもありますが、基本はペアで開発業務を進めています。</p>
<p>私のチームはエンジニア同士だけではなく、企画グループや社内<a class="keyword" href="http://d.hatena.ne.jp/keyword/CMS">CMS</a>を利用する記事編集グループなどと部署内外問わず様々なやりとりを行っています。</p>
<p>チーム内での報告・連絡・相談や部署内外でのやりとりでは、「はじめに」で記載したようにSlackを利用しています。</p>
<p>一行で済む返信は絵文字リアクションで伝えて良いこととしたり、問い合わせが来た場合には確認したら絵文字リアクションをとるようにするなど、Slackでのコミュニケーションを重要視しているチームです。</p>
<h1 id="Slackのスタンプを解析してみた">Slackのスタンプを解析してみた</h1>
<p>同じ開発部でもチームによって、Slackの使い方の方針は異なるようです。</p>
<p>Slackの絵文字リアクションを集計してみるとチームごとの特徴・働き方の違いが現れておもしろいのではと思い、普段使われている絵文字リアクションのデータを分析してみることにしました。</p>
<h2 id="集計ルール">集計ルール</h2>
<p>今回の集計ルールは以下のとおりです。</p>
<ul>
<li>集計項目
<ul>
<li>メッセージに対する絵文字リアクションの使用回数</li>
<li>カスタム絵文字と通常の絵文字どちらも対象とする</li>
</ul>
</li>
<li>集計範囲
<ul>
<li>タイムラインに載っているメッセージのみ集計範囲とする</li>
<li>直近の2000件のメッセージが対象</li>
<li>メッセージに含まれる絵文字は絵文字リアクションではないため対象外</li>
</ul>
</li>
</ul>
<h2 id="全体の実装の流れ">全体の実装の流れ</h2>
<p>今回のようなデータ分析を行うときは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>を用いることが多いと思いますが、今回は勉強のために業務で用いる<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>で実装を行いました。</p>
<p>実装の流れはざっくり以下のとおりです。</p>
<ol>
<li><p>SlackAPIを利用する準備</p>
<ul>
<li>Slack Appの作成</li>
<li>scopeの設定</li>
</ul>
</li>
<li><p>実装</p>
<ul>
<li>Slackからメッセージ履歴とカスタム絵文字データを取得</li>
<li>絵文字データを抽出・集計</li>
</ul>
</li>
</ol>
<h2 id="SlackAPIを利用する準備">SlackAPIを利用する準備</h2>
<p>SlackAPIとは、他のアプリケーションでの<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>と同様に外部アプリケーションからSlackを操作するための仕組みです。</p>
<p>SlackAPIの中でもWebAPIやEventsAPIなど様々な種類の<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>がありますが、今回はWebAPIを使用します。</p>
<p>公式のドキュメントはこちらです。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fapi.slack.com%2Fapis" title="Using Slack APIs" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://api.slack.com/apis">api.slack.com</a></cite></p>
<p>必要なSlackAPIが何なのかはこちらが参考になります。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fapi.slack.com%2Flang%2Fja-jp%2Fwhich-api" title="必要な Slack API はどれ? - Slack アプリの作成のためのヒント" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://api.slack.com/lang/ja-jp/which-api">api.slack.com</a></cite></p>
<p>まずはSlack Web <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を利用するための準備をしていきます。</p>
<h3 id="Slack-Appを作成する">Slack Appを作成する</h3>
<p>データ調査を行うためにはまず、SlackAppを作成する必要があります。</p>
<p>そのApp用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>ンを発行し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>ンを用いてApp経由でチャンネルのデータを取得します。</p>
<p>ここは検索してみるとやり方をまとめたQiitaがすぐに出てくるのであまり苦労することはありません。
今回は以下のQiitaを参考に設定しました。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fqiita.com%2FYumaInaura%2Fitems%2F0fc810e885a3d988f123" title="Slack API | Web API から Slack App 経由で チャンネル履歴を取得する - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://qiita.com/YumaInaura/items/0fc810e885a3d988f123">qiita.com</a></cite></p>
<p>また、作成したSlackAppには使いたいメソッドごとに必要な権限を付与しないと<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を利用できません。</p>
<p>ここで注意する点があります。</p>
<p>付与する権限はUserと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Bot">Bot</a>で別れており、Appをどのように用いるかで利用する権限が異なります。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/bot">bot</a>として権限を付与すると、データを取得したいチャンネルにSlackAppを登録しないと<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を利用できないようです。</p>
<p>使いたいメソッドのリファレンスに、必要な権限も書いてあるためしっかり確認しておきましょう。</p>
<h2 id="実装の流れ">実装の流れ</h2>
<p>SlackAPIメソッドを使って、メッセージ履歴とカスタム絵文字を取得します。
これに必要なメソッドはそれぞれ、conversations.<a class="keyword" href="http://d.hatena.ne.jp/keyword/history">history</a>とemoji.listです。</p>
<p>それぞれのメソッドのリファレンスはこちらです。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fapi.slack.com%2Fmethods%2Fconversations.history" title="conversations.history API method" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://api.slack.com/methods/conversations.history">api.slack.com</a></cite></p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fapi.slack.com%2Fmethods%2Femoji.list" title="emoji.list API method" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://api.slack.com/methods/emoji.list">api.slack.com</a></cite></p>
<p>メソッドにはそれぞれ必要な権限があるので、使うメソッドを決めたらそのメソッドのRequired scopesを確認してSlackAppに必要な権限を追加しましょう。</p>
<h3 id="メッセージ履歴とリアクションの取得">メッセージ履歴とリアクションの取得</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>メソッドを使用する際、引数のchannelには、Slackのチャンネルリンクを発行した際にわかるIDを設定します。</p>
<p>今回は特定のチャンネルを指定してそのメッセージ履歴を取得するので、IDを引数にベタ書きしました。</p>
<p>ほかのやり方としては、channels.listという<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>メソッドもあり、publicチャンネルIDの一覧がとってこれるのでそれを使うこともできると思います。</p>
<p>conversations.<a class="keyword" href="http://d.hatena.ne.jp/keyword/history">history</a>ではメッセージそれぞれに対するリアクションとして絵文字名とその回数を取得できます。
ここでemoji.listメソッドを使い、絵文字リアクションをカウントアップしていきます。</p>
<h3 id="絵文字一覧の取得">絵文字一覧の取得</h3>
<p>emoji.listメソッドで取得できるのはカスタム絵文字の登録名と画像のURLの一覧です。
Slackに登録されているデフォルトの絵文字は入っていません。</p>
<p>もしカスタム絵文字以外のデフォルトの絵文字でもカウント対象としたい場合は、どうすればよいのでしょうか。</p>
<p>いろいろなやり方があるとは思いますが、今回は、カスタム絵文字データから絵文字名を抽出し、絵文字名をキー、回数(初期値として0)をバリューにした<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CF%A2%C1%DB%C7%DB%CE%F3">連想配列</a>にしてカウント用の絵文字リストを作りました。</p>
<p>そして、conversation.<a class="keyword" href="http://d.hatena.ne.jp/keyword/history">history</a>で取得した絵文字リアクションが絵文字リストに含まれている場合はそのままバリューをカウントアップし、含まれていないデフォルトの絵文字の場合は絵文字リストに追加してキーとバリューを登録するようにしました。</p>
<p>これで全絵文字がカウントできるようになりました。</p>
<h3 id="カウントする際に気をつけるポイント">カウントする際に気をつけるポイント</h3>
<p>conversations.<a class="keyword" href="http://d.hatena.ne.jp/keyword/history">history</a>メソッドではとってこれるメッセージ数のlimitとしてMAX1000件となっています。</p>
<p>引数で取得したいデータの期間を設定できますが、1000件以上になると意図した期間のメッセージをとってこれないので気をつけてください。</p>
<p>また、conversations.<a class="keyword" href="http://d.hatena.ne.jp/keyword/history">history</a>メソッドではスレッド内のリプライは基本的に取得できません。スレッド内のリプライであってもチャンネルに送信すれば、タイムラインに載るためメッセージとして取得します。</p>
<p>あくまでもチャンネルのタイムラインに投稿されているメッセージだけを取得するメソッドなので気をつけましょう。</p>
<p>もしリプライもとりたい場合は、conversations.repliesというメソッドをさらに使用する必要があります。</p>
<p>とってこれるデータや必要な引数がconversations.<a class="keyword" href="http://d.hatena.ne.jp/keyword/history">history</a>と少し異なりますので、リファレンスのテスターから試して確認してみてください。以下がリファレンスです。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fapi.slack.com%2Fmethods%2Fconversations.replies" title="conversations.replies API method" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://api.slack.com/methods/conversations.replies">api.slack.com</a></cite></p>
<p>もう一点気をつけたい点として、Slackの<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>メソッドは定期的にアップデートされるということです。
今回紹介したメソッドが廃止されてほかの名前になっていることもありえます。</p>
<p>例として、conversations.<a class="keyword" href="http://d.hatena.ne.jp/keyword/history">history</a>メソッドができる前は、channels.<a class="keyword" href="http://d.hatena.ne.jp/keyword/history">history</a>という名前の別のメソッドだったようです。二次情報の記事の内容は参考程度にして、メソッドが存在するかや必要な権限は自分で確認するようにしましょう。</p>
<h2 id="調査結果">調査結果</h2>
<p>それでは、調査結果を載せていきます。</p>
<p>対象のチャンネルは、以下のとおりです。</p>
<ul>
<li>エンジニア同士の連絡用チャンネル</li>
<li>私の所属するメディア開発1グループ</li>
<li>AllAbout IDの開発をおもに手掛けるメディア開発2グループ</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/BMP">BMP</a>(ビジネスマッチングプラットフォーム)の開発をおもに手掛ける、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>開発グループ</li>
</ul>
<p>まずはエンジニア同士の連絡用チャンネルの結果です。
<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220317/20220317211106.png" width="1200" height="677" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>大事な連絡事項が多いチャンネルのためか、『確認中』の意味の目の絵文字リアクションが一位でした。確認済みであることがひと目でわかって便利な絵文字リアクションですよね。</p>
<p>特徴的だったのは、クラッカーの絵文字リアクションがランキングに入っていたことです。</p>
<p>これはリリース完了連絡に対するお祝いやねぎらいの意味合いで使用されているようです。ちょっとした気持ちを伝えられるのも絵文字リアクションのよいところですよね!</p>
<p>また、Slackbotのリマインダー通知に対する『それな。』や『済』の絵文字リアクションがランキングに色濃く反映されていたのはおもしろかったです。</p>
<p>ここからは、開発グループごとの結果を見ていきたいと思います。
私の所属するメディア開発1グループの結果です。
<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220309/20220309150514.png" width="1200" height="675" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>前述の通り、積極的に絵文字リアクションを活用するようにルールとして決めていることもあり、スタンプの総数が多かったです。</p>
<p>『ありがとうございます』や『承知しました』だけでなく、『いいね』や『確認中』の意味の目の絵文字も多く、メッセージに対して絵文字リアクションをとる文化が定着していそうだということがわかりました。
また、自分のメッセージに対して絵文字リアクションをとることで自分の状態を表すといった場合もあるため、人気ランキング10位圏外にも多種多様なカスタム絵文字がありました。</p>
<p>続いて、メディア開発2グループです。
<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220309/20220309150532.png" width="1200" height="677" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>人数が少ないこともあってか、1Gと比べてメッセージ自体も絵文字リアクションの総数も少ないことが印象的でした。</p>
<p>1Gでは報告・連絡・相談は基本的にSlackでやりとりしているのに比べて、2Gでは口頭などのSlack以外のコミュニケーションがメインと考えられます。</p>
<p>Slackでは必要最低限のコミュニケーションをしているように感じました。</p>
<p>人気絵文字リアクションの種類は業務連絡が多いことについては似ていますが、1Gとの違いがわかりますね。</p>
<p>続いて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>開発グループです。
<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220309/20220309150551.png" width="1200" height="676" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>こちらも人気絵文字リアクションの種類はほかと似ていますが、『ありがとうございます』と『いいね』の絵文字リアクションが大半を占めているのが特徴的でした。</p>
<p>メッセージ自体の数は1Gよりは少ないですが2Gよりも多く、Slackでも活発にやりとりされていることがわかりました。</p>
<p>人気ランキング圏外にも、チーム内で感謝を伝えるときに用いるカスタム絵文字があったりしておもしろかったです。</p>
<h1 id="最後に">最後に</h1>
<p>今回は社内Slackで使われている人気絵文字を調査してみました!</p>
<p>グループごとに雰囲気や働き方の違いがかなり現れていて、おもしろかったです。</p>
<p>また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を使って個人的にデータを分析してみたり集計してみたりといったことは初めて行ったので、よい勉強の機会になったと感じました。</p>
<p>試行錯誤する中で妥協した点至らなかった点もあり、現時点での自分の力を図ることもできてよかったです。</p>
<p>新卒一年目を卒業するということで、これからはインプットだけではなく今回のようなアウトプットの機会も積極的に設けていければと思います。</p>
allabout-techblog
開発部で1年間働いてみて学んだこと 〜想像よりも幅広かったエンジニアの仕事〜
hatenablog://entry/13574176438068407345
2022-03-28T14:56:51+09:00
2022-03-28T15:01:00+09:00 毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2022」を開催します。 今回は、オールアバウト開発部の@barmがお送りします。 1. はじめに 2. 学んだこと コードを書くことだけが開発じゃない レビューをもらうことの重要さ 話し合いながらコードを書いていくことのメリット 継続してインプットすることの大切さ 3. 終わりに 今年どうだったか 来年度に向けて 1. はじめに 今年の4月でオールアバウトに入社してから1年が経ちます。 研修を終えた後、All Aboutの会員基盤であるAll About IDの構築に参加し、会員専用ページにデザインを適用…
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220325/20220325155344.png" width="1200" height="680" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2022」を開催します。</p>
<p>今回は、オールアバウト開発部の@barmがお送りします。</p>
<ul class="table-of-contents">
<li><a href="#1-はじめに">1. はじめに</a></li>
<li><a href="#2-学んだこと">2. 学んだこと</a><ul>
<li><a href="#コードを書くことだけが開発じゃない">コードを書くことだけが開発じゃない</a></li>
<li><a href="#レビューをもらうことの重要さ">レビューをもらうことの重要さ</a></li>
<li><a href="#話し合いながらコードを書いていくことのメリット">話し合いながらコードを書いていくことのメリット</a></li>
<li><a href="#継続してインプットすることの大切さ">継続してインプットすることの大切さ</a></li>
</ul>
</li>
<li><a href="#3-終わりに">3. 終わりに</a><ul>
<li><a href="#今年どうだったか">今年どうだったか</a></li>
<li><a href="#来年度に向けて">来年度に向けて</a></li>
</ul>
</li>
</ul>
<h1 id="1-はじめに">1. はじめに</h1>
<p>今年の4月でオールアバウトに入社してから1年が経ちます。
研修を終えた後、All Aboutの会員基盤であるAll About IDの構築に参加し、会員専用ページにデザインを適用したり、既存のサービスから会員専用ページへの導線を追加する実装を主に担当していました。
現在は構築した会員基盤をもとにしたサービスの開発を進めています。</p>
<p>今回の記事では、これらの業務をやってきた中で学んだことを、入社直後に思っていたことと比較して紹介していきたいと思います。</p>
<h1 id="2-学んだこと">2. 学んだこと</h1>
<h2 id="コードを書くことだけが開発じゃない">コードを書くことだけが開発じゃない</h2>
<p>入社した当初、指示通りのものを作ることがエンジニアの仕事だと想像していました。
実際にそういうこともありましたが、エンジニア側でもどういうものを作ればいいのか、ユーザーが使ったときにどう思うのかを考えながら開発を進めていくことが多かったです。
例えば以下のようなことは話し合われていました。</p>
<ul>
<li>アンケートの入力フォームの送信・修正ボタンの配置はどうあるべきか</li>
<li>アンケートに回答し終わったらユーザーはどの画面に戻りたいか
<ul>
<li>マイページなのか、All Aboutのトップページなのか</li>
</ul>
</li>
<li>エラーが起きたとき、ユーザーにどう動いて欲しいのか
<ul>
<li>例えば、同じウェビナーに2回申し込みをされたときに「申し込み済みです」と画面に出すか、エラーページに遷移させるか</li>
</ul>
</li>
</ul>
<p>ただ指示されたものをコードに書き起こすだけでなくて、どう出来上がると嬉しいかを考えることも開発の一部ということを学びました。</p>
<h2 id="レビューをもらうことの重要さ">レビューをもらうことの重要さ</h2>
<p>自分が書いたコードをチームのメンバーにレビューしてもらうことにはメリットが多いです。
最初は、コードをレビューすることの主な目的はミスがないかのチェックだと思っていました。
ですが、実際にはやりたいことをより効率よく実現できる方法をレビュアーを含めて考え直す機会としてレビューを使用することも多かったです。</p>
<p>実際にあったのは、ほとんど同じ処理を行っている2つのクラスがあって、それを共<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%CC%B2%BD">通化</a>して1つのクラスにするべきか、しないべきかをメンバーで話し合いました。
その時は、同じ処理をしていてもそれぞれのクラスで役割が違うこと、後から読み返した時の理解のしやすさを考慮して共<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%CC%B2%BD">通化</a>しないと決めました。
どうするべきかなかなか決めきれず時間もかかりましたが、最終的に理由をつけた上で方針を決定することができました。</p>
<p>やったことに対して指摘が入ることに抵抗を感じることもありますが、メンバーと話しながらより良いコードにしていく活動は開発する力を高めていく上で重要だと思います。</p>
<h2 id="話し合いながらコードを書いていくことのメリット">話し合いながらコードを書いていくことのメリット</h2>
<p>オールアバウトでの開発は基本的には<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>で行われます。
チームのメンバーとペアを組んで1つのプログラムを書いていきます。
入社するまで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>をしたことがなかったので、思った以上にペアとずっと話しながら作業しているなと、メンバーの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>を見た時に思いました。</p>
<p>はじめて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>をした時は、使用している言語や設計に関して持っている知識と、コードを書いていくスピードの違いにメンバーとの大きな差を感じました。</p>
<p>知識に差があるのはどうしようもないので、自分でコードを書く際は具体的なコードの書き方を教えてもらったり、書いたコードに対してアド<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>をもらいながら実装を進めていました。
設計については、どんな設計でアプリを作っていけばいいのかなどを一緒に考えたりすることで、
開発に必要な技術的な知識と後々困らないような設計を考えることの重要さを学びました。</p>
<p>工夫したところとしては、スピードについていけていない、ペアの書いているコードが理解できない時はペアを組んでいる相手にそのことを伝えて、
分からないところや何を考えてコードを書き進めているのかを教えてもらうようにしていました。
こうすることで自分に理解のスピードを合わせてもらえてかつ、学習にもつながりました。</p>
<h2 id="継続してインプットすることの大切さ">継続してインプットすることの大切さ</h2>
<p>日常的にコードを書いたり、アプリを作ったりしていない状態で入社をしたので、勉強するべきことは非常に多かったです。
最初は使用している言語についての知識さえあればいいと考えていましたが、作ったものをサービスとして出していく上でそれ以外の技術も学ぶ必要がありました。
学んだことを列挙すると以下のとおりです。</p>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a></li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a></li>
<li>Webで使用されている技術(HTTP)など</li>
<li>docker</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/kubernetes">kubernetes</a></li>
<li>git</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%B9%A5%C8%B6%EE%C6%B0%B3%AB%C8%AF">テスト駆動開発</a></li>
</ul>
<p>この中でも特に、Webアプリケーションを作る上で重要な、Webに関わる基本的な技術や、主に使用している言語である<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>の基本的な書き方は入社する前から触れておいた方がよかったと感じています。</p>
<p>インプットの仕方は、業務中では新しく学んだことをメモして業務終了後に見直していました。
業務外では主に書籍を使って学習を進めていました。
勉強してたことをいくつか挙げておきます。</p>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>の練習問題を解く</li>
<li>「独習<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>」を読む
<ul>
<li>学んだことの共有</li>
<li>サンプルコードの写経</li>
</ul>
</li>
<li>「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%B9%A5%C8%B6%EE%C6%B0%B3%AB%C8%AF">テスト駆動開発</a>」を読む
<ul>
<li>サンプルコードの写経</li>
</ul>
</li>
</ul>
<p>まだまだ学ぶべきことは多いのですが、教えてもらうことを理解しやすくなったり、自分でわからないことを調べるときの足がかりになったり、業務を進める上で役に立っていると思います。</p>
<h1 id="3-終わりに">3. 終わりに</h1>
<h2 id="今年どうだったか">今年どうだったか</h2>
<p>1年目からAll Aboutの新規機能の開発に関わり、自分が何もできない状態であったことを知りました。
開発進める力を自分とメンバーで比較したときに、足元にも及ばないなと感じています。
ですが、業務の中で知識をつけたりメンバーに色々教えてもらう中で学べたことも多かったです。</p>
<h2 id="来年度に向けて">来年度に向けて</h2>
<p>1年ですごく開発ができるようになったわけでもないので、できることを増やせるような活動はしていきたいです。
すぐにできることは本や記事を読んでインプットすることですが、アウトプットする活動も意識してやっていきたいです。
現段階で構想はないのですが、何かアプリを作れるのが一番いいと思っています。
できることを増やして、楽しくサービスの開発することにつながればいいなと思います。</p>
allabout-techblog
Always on CPU の導入体験談
hatenablog://entry/13574176438054756787
2022-02-03T16:33:04+09:00
2022-02-03T16:36:39+09:00 こんにちは。オールアバウト 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 簡単に言うと以下画像のアイドル状態を無くすための設定です。 利用シーンと…
<p>こんにちは。オールアバウト SRE 所属 の<a href="https://qiita.com/ishii1648">@s_ishii</a>と申します。</p>
<p>今回は去年リリースされた Always on CPU を導入した事例をご紹介致します。<br />
Always on CPU は非常に有益な機能で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a>に合致する場合は効果を発揮します。</p>
<p>Always on CPU について事前知識の無い方はまずは以下をご一読ください。</p>
<p><a href="https://cloud.google.com/blog/ja/products/serverless/cloud-run-gets-always-on-cpu-allocation">https://cloud.google.com/blog/ja/products/serverless/cloud-run-gets-always-on-cpu-allocation</a></p>
<p>簡単に言うと以下画像のアイドル状態を無くすための設定です。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220120/20220120193741.png" alt="f:id:allabout-techblog:20220120193741p:plain" width="1200" height="556" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>利用シーンとしては主に 2 つのケースがあります。</p>
<h3>1. リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト受信後に非同期で処理を実行したい場合</h3>
<p>Cloud Run 上で重たい処理を実行する場合、実際の処理は非同期で実行して HTTP のレスポンスは即座に返したい、といったケースは多々あると思います。<br />
従来の Cloud Run はリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト返却後に CPU がアイドル状態に入ってしまうので非同期処理が行えなえませんでした(厳密に言うとすごく遅くなる)。</p>
<p>こうしたケースを Always on CPU を利用することでカバーできるようになったことで、Cloud Run の利用シーンが拡大しました。</p>
<h3>2. リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを頻繁に受け付ける場合</h3>
<p>もう 1 つは Web のバックエンドとして Cloud Run を利用している場合です。<br />
この場合、リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを頻繁に受け付けることになると思いますが、Cloud Run の料金体系はリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト数に対して相対的に高く設定されているため割高になる傾向があります。</p>
<p>Always on CPU を有効化した場合、従来とは料金体系が根本的に変わりリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト数に対する課金が無くなります。
CPU の利用時間が長くなるのでその分の料金はかさみますが、リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トが頻繁にくるような場合だと従来の Cloud Run の設定であっても CPU がアイドル状態になる時間帯が少ないはずなので結果として大幅な料金の削減が見込めます。</p>
<p>以下公式の料金表になります。Always on CPUではリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト料金が撤廃されていること、それに加えCPUやメモリの使用料金も下がっていることがわかると思います。
(CPUやメモリの料金が下がっているのは、常時起動するため単位時間当たりの料金を下げているのだと思います)<br />
<a href="https://cloud.google.com/run/pricing">Pricing | Cloud Run | Google Cloud</a></p>
<p>私達が今回取り組んだのはこのパターン 2 になります。</p>
<h2>対象となるサービスについて</h2>
<p>おおまかに言うとアドネットワーク上で発生したログの到達先サービスになります。
サービスの利用規模としてはおおよそ以下の通りとなります。</p>
<ul>
<li>月間リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト数:1 億以上</li>
<li>月間 CPU 時間:800 万秒以上</li>
</ul>
<p>月間でかなり多くのリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トをさばくサービスで、昼夜問わず動作している状態です。
また、Cloud Runのメトリクスを見ると課金対象のコンテナ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>が常に4つあることが分かります。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220120/20220120193852.png" alt="f:id:allabout-techblog:20220120193852p:plain" width="1172" height="302" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>この調査をもとにAlways on CPU化対応することでCPU料金の上昇がほぼ発生せず、リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト料金分だけコストを削減できると判断し実施することになりました。</p>
<h2>結果</h2>
<p>Always on CPU化したところ期待通りリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト料金の分だけコストを削減することができました(元々の使用量の1/3まで低下)。
ほとんど作業を必要とせず(設定を切り替えるだけ)、ここまで大きな成果が出るのは素晴らしいと思います。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20220120/20220120194531.png" alt="f:id:allabout-techblog:20220120194531p:plain" width="1200" height="326" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>※ちなみに後半さらにコストが微減しているのは Cloud Run の確約利用割引を適用しているためです</p>
<p>是非Always on CPUが利用中のサービスの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B9%A5%B1%A1%BC%A5%B9">ユースケース</a>に合致するかご確認することをおすすめします。</p>
<p>なお、Always on CPU は 2022 年 2 月 時点では <a class="keyword" href="http://d.hatena.ne.jp/keyword/preview">preview</a> 版ですので導入の際はその点にご留意ください。</p>
allabout-techblog
Google Cloud で Terraform を導入した話し
hatenablog://entry/13574176438045794636
2021-12-25T00:00:00+09:00
2021-12-25T00:00:23+09:00 こんにちは。オールアバウト SRE 所属 の@s_ishiiと申します。 Terraform Advent Calendar 2021 の 25 日目の記事です。 この記事では Google Cloud で Terraform を導入した話しをご紹介します。 目次 導入の経緯 導入の流れとその後 これからの課題 導入の経緯 オールアバウトでは Google Cloud を採用していますが、従来 IaC によるインフラ管理はされておらず手動で構築・運用されていました。比較的大規模なインフラを管理していることもあり、2020 年末の時点でこれ以上手動で管理していくことは不適切との結論に至りました。…
<p>こんにちは。オールアバウト SRE 所属 の<a href="https://qiita.com/ishii1648">@s_ishii</a>と申します。</p>
<p><a href="https://qiita.com/advent-calendar/2021/terraform">Terraform Advent Calendar</a> 2021 の 25 日目の記事です。</p>
<p>この記事では <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud で Terraform を導入した話しをご紹介します。</p>
<h2>目次</h2>
<ul>
<li>導入の経緯</li>
<li>導入の流れとその後</li>
<li>これからの課題</li>
</ul>
<h2>導入の経緯</h2>
<p>オールアバウトでは <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud を採用していますが、従来 IaC によるインフラ管理はされておらず手動で構築・運用されていました。比較的大規模なインフラを管理していることもあり、2020 年末の時点でこれ以上手動で管理していくことは不適切との結論に至りました。代表的な理由を以下にいくつかピックアップします。</p>
<h4>1. 作業時の安全性</h4>
<p>手動でインフラを管理する場合、新たに環境を構築・変更する時は手順書を作ってチームから承認を得て作業に移ります。これは安全な方法に見えるかもしれませんが、実際には作業時の操作ミスや作業者の勘違いで想定外の結果を生む余地があります。Terraform を利用することで事前に作業内容を明確にできるので、作業時の安全性が高まると期待しました</p>
<h4>2. SRE メンバーに与えられた強すぎる権限</h4>
<p>オールアバウトでは SRE がインフラを一元的に管理していますが、手動管理の都合上 SRE の各メンバーには <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud への幅広い操作権限が与えられていました。これは人為的な事故を誘発するので、IaC の導入とインフラの構築フローを CD 化することによって SRE メンバーの権限を縮小化することが期待されました。</p>
<h4>3. <a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%BF%CC%BE%B5%AC%C2%A7">命名規則</a>の強制</h4>
<p>サービス種別に応じた<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%BF%CC%BE%B5%AC%C2%A7">命名規則</a>は整備されていましたが、実情として遵守されていませんでした。そもそも新しく SRE に加入したメンバーに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%BF%CC%BE%B5%AC%C2%A7">命名規則</a>が書かれたドキュメントを共有するフローになっていなかったので、人によっては<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%BF%CC%BE%B5%AC%C2%A7">命名規則</a>そのものの存在を知らないといった事態になっていました。この経験から<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%BF%CC%BE%B5%AC%C2%A7">命名規則</a>を徹底するにはドキュメント整備だけでは不充分で、CI のフローに組み込んで強制させる必要があると考えました。</p>
<p>上記のような理由に加え、当時 GKE <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>のバージョンアップに伴うインフラ対応が控えていたため、これを期に Terraform を利用しようということになりました。</p>
<h2>導入の流れとその後</h2>
<p>ここからは Terraform の導入とその後どのように運用にのせていったのかを時系列順に記します。</p>
<h3>STEP1. Terraform 導入</h3>
<p>オールアバウトには大小 10 以上のサービスがあります。手動構築されたそれらのインフラ群を一度に Terraform のコード化するのは現実的ではないので、ひとまず<strong>新しく構築するインフラは Terraform を利用する</strong>としました。</p>
<p>上述の通り、当時のインフラタスクに GKE <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>の入れ替えがあったため、Terraform で作る最初のリソースとして GKE <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>が選ばれました。またこれを機にコンテナ内で出力されたログを Cloud Logging のログルータ機能を使って GCS に保存することになったので、ログルータ周りのリソースも Terraform で構築することになりました。</p>
<h4>Terraform の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リ構造</h4>
<p>この時点では以下のように <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud のリソース単位で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リを分割して state ファイルを作成していました。しかし後になってこの設計は適切でないとの結論に至り、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>によって変更されることになります。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20211224/20211224201109.png" alt="f:id:allabout-techblog:20211224201109p:plain" width="666" height="436" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h3>STEP2. <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a></h3>
<p>Terraform を導入して数ヶ月が経過すると、当初の Terraform 設計の問題点が露見してきました。なかでも以下 2 点が問題視され、改善することが望まれました。</p>
<ol>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud のリソース単位で state ファイルを分割している</li>
<li>ステージング/本番環境のコードが分離されている</li>
</ol>
<h4>1. <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud のリソース単位で state ファイルを分割している</h4>
<p>当初は <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud のリソースを state ファイルの分割単位としていました。単位として充分に小さく、かつ分割単位として明確という理由からこの方針が採用されましたが、実際に運用していくとリソース間参照がしづらくコードを書くうえで苦労しました。</p>
<p>Terraform で異なる state ファイルに記述されたリソースを参照するためには、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%B2%BE%C8%B8%B5">参照元</a>に output のコードを追記し、参照先で<code>terraform_remote_state</code>ブロックを用いて output されたリソースを取得する必要があります。これはコードの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BE%E9%C4%B9%B2%BD">冗長化</a>をもたらし、可読性と生産性を悪化させました。</p>
<p><a href="https://beyondjapan.com/blog/2019/01/reference-other-tfstate-resource/">https://beyondjapan.com/blog/2019/01/reference-other-tfstate-resource/</a></p>
<p>また当初メリットだと考えていた小さな state ファイル、という点も実際にはあまり恩恵を感じられず、むしろ 1 つのプロジェクト内に state ファイルが分散することにより、コードの更新内容を実環境に適用し忘れる事態が発生していました。</p>
<p>これらの点を踏まえ、state ファイルの分割単位を <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud リソースから <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud プロジェクトに変更しました。state ファイルの単位として大幅に粒度を拡大することになるので、チーム内で「もう少し小さな単位を模索したほうが良いのでは?」という意見も出ましたが、プロジェクトよりも小さい適切な単位を決めるのが難しかったこともあり、プロジェクト単位で state ファイルを分割することになりました。</p>
<h4>2. ステージング/本番環境のコードが分離されている</h4>
<p>これは書いてある通りで、当初ステージングと本番環境は別々のコードを書いて構築していました。このため時間経過とともに環境の乖離が発生し始めていたので、ステージングと本番で同一のコードを参照するよう実装を見直すことになりました。</p>
<h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>後</h4>
<p>以上の点を踏まえて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>した結果、以下のような<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リ構造になりました。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20211224/20211224201205.png" alt="f:id:allabout-techblog:20211224201205p:plain" width="572" height="564" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud のプロジェクト毎に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リを作成し、その配下に environments、resources <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リを配置しています 。以下が main.tf の記述例です。resources 配下を module として呼び出しており、その際に可変値を埋め込んでいます。このように書くことで resources <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リ配下にコードされた内容をステージング/本番で参照することになり、乖離が起きにくい実装になっています。</p>
<pre class="code lang-terraform" data-lang="terraform" data-unlink><span class="synType">terraform</span> <span class="synSpecial">{</span>
<span class="synType">backend</span> <span class="synConstant">"gcs"</span> <span class="synSpecial">{</span>
<span class="synIdentifier">bucket</span> = <span class="synConstant">"BUCKET_NAME"</span>
<span class="synIdentifier">prefix</span> = <span class="synConstant">"PROJECT_NAME/stg"</span>
<span class="synSpecial">}</span>
<span class="synIdentifier">required_version</span> = <span class="synConstant">">= 0.13"</span>
<span class="synType">required_providers</span> <span class="synSpecial">{</span>
<span class="synIdentifier">google</span> = <span class="synSpecial">{</span>
<span class="synIdentifier">source</span> = <span class="synConstant">"hashicorp/google"</span>
<span class="synIdentifier">version</span> = <span class="synConstant">"~> 3.53"</span>
<span class="synSpecial">}</span>
<span class="synIdentifier">google-beta</span> = <span class="synSpecial">{</span>
<span class="synIdentifier">source</span> = <span class="synConstant">"hashicorp/google-beta"</span>
<span class="synIdentifier">version</span> = <span class="synConstant">"~> 3.53"</span>
<span class="synSpecial">}</span>
<span class="synSpecial">}</span>
<span class="synSpecial">}</span>
<span class="synType">module</span> <span class="synConstant">"stg"</span> <span class="synSpecial">{</span>
<span class="synIdentifier">source</span> = <span class="synConstant">"../../resources"</span>
<span class="synIdentifier">region</span> = <span class="synConstant">"asia-east1"</span>
<span class="synIdentifier">project_id</span> = <span class="synConstant">"PROJECT_NAME"</span>
<span class="synIdentifier">env</span> = <span class="synConstant">"stg"</span>
<span class="synSpecial">}</span>
</pre>
<h3>STEP3. 手動構築したリソースの Terraform 化</h3>
<p>ここまでで運用に耐えうる設計になったので(最低限ですが)、いよいよこれまで手動で構築してきたリソース群を Terraform 化することになりました。Terraform 化を進めるに当たって、以下 2 つの方針を前提に進めました。</p>
<h4>コードは汚くて良い</h4>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud で Terraform 化を進める場合<code>terraformer</code>が便利ですが、terraformer で自動出力されたコードの可読性は低いです。これを逐一<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>していくと相当な時間が消費されてしまうので、Terraform 化の作業のなかでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>は行わないことにしました。</p>
<h4>全てのリソースを網羅しようとしない</h4>
<p>オールアバウトがこれまでに構築してきたリソースは膨大なので、漏れなく Terraform 化しようとすると確認含め相当な時間を要してしまいます。目的は<strong>既存インフラを更新する際に手動ではなく Terraform で実行できるようにすること</strong>なので、更新頻度の低いリソースを頑張って Terraform 化する動機はありませんでした。そのため細部にはこだわず、Terraform 化対応で漏れたリソースは発見次第都度対応していくことにしました。</p>
<p>これらの前提のもと作業した結果、1 ヶ月程度で全環境を一通り Terraform 化できました。
しかしその一方で以下課題も残りました。</p>
<h4>コードの可読性が低すぎる</h4>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>しない前提で進めた結果、リソースの数が多いプロジェクトの可読性が相当低いものになってしまいました。今から考えるとその辺りはもう少し柔軟に対応しても良かったと思っています。</p>
<h4>表記ゆれが目立つようになった</h4>
<p>これは Terraform 化したおかげで気づけた点でもありますが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%BF%CC%BE%B5%AC%C2%A7">命名規則</a>が徹底されていないせいで同じ種類のリソースで微妙に異なる名称が散見されました。これは for_each 等でループする際の障害になるので、将来のいずれかの時点で解消する必要が出てきました。</p>
<p>この 2 つの課題のうち、「コードの可読性が低すぎる」に対処するため週次で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>会を設け、チームメンバー全員で可読性の低い箇所を探しては<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a>していくようサイクル化しました。</p>
<h3>STEP4. impersonate 対応</h3>
<p>当初の予定ではこの辺で Terraform の CD 化対応を進める予定だったのですが、他タスクとの優先度の兼ね合いに加え、全ての環境を 1 つの Terraform <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>にまとめているモノリポ構成であるため CD の工程が複雑になる等の理由で、CD 化は見送ることになりました。このため当面の間、Terraform は SRE メンバーのローカル端末で実行される状態が続くことになりました。</p>
<p>このような状況のなかで、かねてからの課題であった SRE に与えられた強すぎる権限を解消するために、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud の impersonate 機能を導入しました。これは事前に許可したサービスアカウントに成り代わることのできる機能で、この機能を Terraform のコードに導入してやると <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud のコンソール画面からはリソース変更等の操作はできず、Terraform を経由した場合にのみ変更が可能になる、といったことが実現できるようになります。</p>
<p><a href="https://cloud.google.com/iam/docs/impersonating-service-accounts">https://cloud.google.com/iam/docs/impersonating-service-accounts</a></p>
<p>詳しいやり方は以下の記事で分かりやすく紹介されているので、興味のある方はご覧ください。</p>
<p><a href="https://medium.com/google-cloud/a-hitchhikers-guide-to-gcp-service-account-impersonation-in-terraform-af98853ebd37">https://medium.com/google-cloud/a-hitchhikers-guide-to-gcp-service-account-impersonation-in-terraform-af98853ebd37</a></p>
<h2>これからの課題</h2>
<p>以上で Terraform を運用していく基礎はできたと考えています。一方で運用の容易性や優秀性を追求する余地もまだ多く残されています。具体的には以下のような課題があり、今後アプローチしていく予定です。</p>
<ul>
<li>terraformer で出力したコードの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D5%A5%A1%A5%AF%A5%BF%A5%EA%A5%F3%A5%B0">リファクタリング</a></li>
<li>CI/CD の導入</li>
<li>terraform-validator の導入</li>
</ul>
<p>以上「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud で Terraform を導入した話し」でした。</p>
allabout-techblog
新卒エンジニアが行った業務を紹介します 〜開発業務と社内勉強会〜
hatenablog://entry/26006613705152424
2021-03-31T10:47:08+09:00
2021-03-31T10:47:08+09:00 はじめに 毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2021」を開催します。 今回は、オールアバウトメディア開発部の@chocoがお送りします。 2020年4月に入社し、7月まで研修を受けたあと、メディア開発部の運用チームに所属して業務を行っています。 本記事では実際にどんな業務を行ったのか紹介します。 はじめに 誰と業務を行っているか どんなアプリケーションを触っているのか どんな業務を行ったのか 社内向け分析ツールの構築 システム構成図 使用技術 開発を振り返って 技術的につまずいた話 GAS会 GAS会とは? どうして始まったか どんなことを…
<p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210329/20210329120349.png" alt="f:id:allabout-techblog:20210329120349p:plain" title="" class="hatena-fotolife" itemprop="image"></span><figcaption></figcaption></figure></p>
<h1 id="はじめに">はじめに</h1>
<p>毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2021」を開催します。
今回は、オールアバウトメディア開発部の@chocoがお送りします。</p>
<p>2020年4月に入社し、7月まで研修を受けたあと、メディア開発部の運用チームに所属して業務を行っています。
本記事では実際にどんな業務を行ったのか紹介します。</p>
<ul class="table-of-contents">
<li><a href="#はじめに">はじめに</a><ul>
<li><a href="#誰と業務を行っているか">誰と業務を行っているか</a></li>
<li><a href="#どんなアプリケーションを触っているのか">どんなアプリケーションを触っているのか</a></li>
</ul>
</li>
<li><a href="#どんな業務を行ったのか">どんな業務を行ったのか</a><ul>
<li><a href="#社内向け分析ツールの構築">社内向け分析ツールの構築</a><ul>
<li><a href="#システム構成図">システム構成図</a></li>
<li><a href="#使用技術">使用技術</a></li>
<li><a href="#開発を振り返って">開発を振り返って</a></li>
<li><a href="#技術的につまずいた話">技術的につまずいた話</a></li>
</ul>
</li>
<li><a href="#GAS会">GAS会</a><ul>
<li><a href="#GAS会とは">GAS会とは?</a></li>
<li><a href="#どうして始まったか">どうして始まったか</a></li>
<li><a href="#どんなことをしたのか">どんなことをしたのか</a><ul>
<li><a href="#作りたいもののイメージをヒアリング">作りたいもののイメージをヒアリング</a></li>
<li><a href="#勉強開始">勉強開始!</a></li>
<li><a href="#実装スタート">実装スタート</a></li>
</ul>
</li>
<li><a href="#進める上で感じたこと">進める上で感じたこと</a><ul>
<li><a href="#教えるの慣れてない問題">教えるの慣れてない問題</a></li>
<li><a href="#エンジニアに囲まれない時間は新鮮">エンジニアに囲まれない時間は新鮮</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><a href="#終わりに">終わりに</a></li>
</ul>
<h2 id="誰と業務を行っているか">誰と業務を行っているか</h2>
<p>主にコミュニケーションをとるのは、チームのエンジニアです。</p>
<p>編集・企画を担当する社員ともシステムの要件を相談したり一緒に業務を行います。</p>
<h2 id="どんなアプリケーションを触っているのか">どんなアプリケーションを触っているのか</h2>
<p>既存サービスや社内<a class="keyword" href="http://d.hatena.ne.jp/keyword/CMS">CMS</a>のメンテナンスが主な担当業務です。
必要に応じて新規ツール開発等も行います。
<a href="https://allabout.co.jp/">All About</a>も私のチームの担当サービスです。</p>
<h1 id="どんな業務を行ったのか">どんな業務を行ったのか</h1>
<h2 id="社内向け分析ツールの構築">社内向け分析ツールの構築</h2>
<p>All Aboutの収益は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>ティック広告に支えられています。</p>
<p>サイトで表示されている広告枠の表示や収益は、広告運用チームの社員が管理をしています。
収益の最大化として、日々広告数字からデータの分析をしています。</p>
<p>今回は、その作業の効率化を図るために収益分析用ツールを実装した時のお話をご紹介したいと思います。</p>
<p>開発以前では、<a href="https://admanager.google.com/intl/ja/home/capabilities/">Google Ad Manager</a>からレポートダウンロードして<a class="keyword" href="http://d.hatena.ne.jp/keyword/Excel">Excel</a>でフィルタをかけて分析したいデータを見ていました。
分析をする度にレポートをダウンロードして作業を行うのではなく、自動でデータが入り分析ができるツールが欲しいというのが広告チームから要望でした。</p>
<p>大まかな要件としては、以下のようなものがありました。</p>
<ul>
<li>広告枠ごとに分析ができること</li>
<li>CPMやViewable Rateといった収益関連の数値が見れること</li>
<li>アクセスしたユーザーのOSがわかること</li>
<li>データは毎日更新されて欲しい</li>
</ul>
<h3 id="システム構成図">システム構成図</h3>
<p>実装したシステム構成は以下の通りです。
<figure class="figure-image figure-image-fotolife" title="集計バッチ システム構成図"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210323/20210323172825.png" alt="f:id:allabout-techblog:20210323172825p:plain" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>集計バッチ システム構成図</figcaption></figure></p>
<p>主な流れとしては、
バッチで<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>からデータ取得と加工をしてデータベースへ格納、Data Studioから<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>を発行してデータベースからデータを取得します。</p>
<h3 id="使用技術">使用技術</h3>
<ul>
<li>Data Studio: <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>が提供しているBIツールです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Analytics">Google Analytics</a>など様々なリソースを取り込んでWeb画面にデータを簡単に表示することができます。</li>
<li>GKE: コンテナ化されたアプリケーションの実行環境として使用します。</li>
<li>CronJob: 決められた時間でJobを生成します。Jobがバッチを実行するポッドを生成します。</li>
<li>Laravel: 社内で主に使われている<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>になります。</li>
<li>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>: <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>が提供している<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>データベースです。</li>
</ul>
<h3 id="開発を振り返って">開発を振り返って</h3>
<p>大まかな開発の流れを紹介しながら、振り返りをして見たいと思います。</p>
<p>1.要件定義</p>
<p>広告運用チームのメンバーがどんな数字をどう見たいのかすり合わせをします。</p>
<p>ミーティング中は、普段広告チームが使う専門用語が多く登場します。
先述したCPM広告数字は何で、どういった計算で求められるかといった話を聞きながら要件に落として行きます。</p>
<p>当時、初めて聞く用語が多く把握するのに苦労した記憶があります。</p>
<p>また、広告用語に加えてAll Aboutで出している広告枠はどれくらいあるのかといった社内固有の知識も必要でした。
技術的な視点とそういったビジネス側の知識が、開発に必要なことを学びました。</p>
<p>2.インフラ・アプリ設計と見積もり</p>
<p>アプリはどの環境で動かすのか、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%A9%BF%F4">工数</a>はどのくらいになるのかメンバーと見積もりをします。
オールアバウトでは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>インフラをSREチームが管理しています。SREチームに依頼する必要があるタスクの洗い出しもここで行います。
どういった工程が必要か、感覚が掴めずこのフェーズはチームメンバーに決めてもらった部分が多くありました。</p>
<p>3.実装</p>
<p>基本的に実装は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>かモブプロでした。
組んでいたロジックが破綻して、私が崩れ落ちそうになったのを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>していた先輩が解決策を見つけてくれたのをよく覚えています...
PRでもレビューを受けますが、コードを書きながら仕様に漏れがないかお互いに点検できていたという点で良い進め方ができたと思います。
また<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>から取得したデータの単位がマイクロ円(100万倍した桁)だったり、実装フェーズはやはり記憶に残っていることが多いです。</p>
<p>設計の面だと、このクラスはどこに実装するのが適切か、といった設計の部分で先輩エンジニアと頻繁に意見交換しながら進めました。
個人開発のように自分だけで開発する時はレビューを受けることがないので、多くのフィードバックをもらえたのは嬉しい経験でした。
サービス層・モデル層で何を処理するのか、徐々に先輩エンジニアと認識があって質問、実装でトライができた時成長できている実感を持てました。</p>
<p>また、保守性の高いアプリにするために、妥協せずにレビューを受けずに進めていく反面、
締め切りから逆算して、もらったレビューを採用しない判断も必要になっていくことを学びました。</p>
<p>4.<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B7%EB%B9%E7%A5%C6%A5%B9%A5%C8">結合テスト</a></p>
<p>成果物に対して要件を満たしているか、バグがないかテストします。</p>
<p>今回の場合、バッチでCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>へ格納したデータを、Data Studioから取得するようにします。
要件にあったデータが表示されているか確認するために、用意しておいたテストケースを元にData Studioの画面を操作します。</p>
<p>5.リリース</p>
<p>実装・テストが終わったあとはいよいよリリースです。</p>
<p>リリース後、広告チームで実際に使用されて便利になったという話を聞いた時はやはり嬉しかったです。</p>
<h3 id="技術的につまずいた話">技術的につまずいた話</h3>
<p>開発中につまずいて、知見になった話を少しだけ紹介したいと思います。</p>
<p>今回の実装では、GKEにデプロイされたLaravelアプリケーションに、あらかじめ定義したartisanコマンドをCronJobを使って定期実行するように実装を行いました。
実装したartisanコマンドは、オプションに日付を渡すことで取得するデータの範囲を指定することができる作りにしていました。
そのため再実行する際には、ターミナルからコマンドを打つ時に日付を渡してJobを生成する想定でした。
しかしJobをコマンドで生成する時に、オプションを渡す方法がわかりませんでした。
残念ながら、コマンド打っての再実行方法は見つけることができませんでしたが、以下に設定ファイルの一部を紹介します。</p>
<p>cronjob.<a class="keyword" href="http://d.hatena.ne.jp/keyword/yaml">yaml</a>(一部)</p>
<pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synIdentifier">command</span><span class="synSpecial">:</span> <span class="synSpecial">[</span><span class="synConstant">"/bin/sh"</span>, <span class="synConstant">"-c"</span><span class="synSpecial">]</span>
<span class="synIdentifier">args</span><span class="synSpecial">:</span> <span class="synSpecial">[</span><span class="synConstant">"php artisan `実行コマンド` {date}] // Laravelで実装されるコマンド 引数に日付を渡す</span>
</pre>
<p>Jobをコマンドから生成したい場合には、下記のようなコマンドを使用します。
ただオプションを渡す方法が見つからない...</p>
<pre class="code" data-lang="" data-unlink>kubectl create job {再実行用に作成するjob名} --from=cronjob/{cronjob名} --namespace={namespace}</pre>
<p>想定していた再実行の方法はできませんでしたが、CronJobは<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>コンソールから<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/yaml">yaml</a>の修正及びJobの再生成が可能です。</p>
<p>ただターミナルからコマンド1つで再実行できるようにしたいですね...</p>
<h2 id="GAS会">GAS会</h2>
<p>取り組んだ業務からもう一つGAS会を紹介します。</p>
<h3 id="GAS会とは">GAS会とは?</h3>
<p>GASは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> App Scirptの略称です。</p>
<p>週に一度、エンジニアと編集・企画の社員が参加する<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> App Scriptの勉強会です。</p>
<h3 id="どうして始まったか">どうして始まったか</h3>
<p>エンジニアではなくても<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を書いてデータの分析や自動化をしたい!というのが動機です。
GASは非エンジニアでも比較的馴染みやすく、社内で頻繁に使われる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%D7%A5%EC%A5%C3%A5%C9%A5%B7%A1%BC%A5%C8">スプレッドシート</a>を扱うことができるので、今回の動機とはあっていました。
私はエンジニアなので、参加者の先生役に近い立場で参加しています。</p>
<h3 id="どんなことをしたのか">どんなことをしたのか</h3>
<h4 id="作りたいもののイメージをヒアリング">作りたいもののイメージを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D2%A5%A2%A5%EA">ヒアリ</a>ング</h4>
<p>最初にゴールを示すために、ざっくりではありますが参加者にどんなものを作りたいのかイメージしてもらいました。
普段の業務で手間になっていることの中で、プログラムで解決できそうなものを記入用のシートを作成してもらいました。
その中でGASで解決できるか、開発規模が大きすぎないかといった観点で、振り分けを行いました。</p>
<p>開発規模が大きいものはエンジニアチームが手を動かして開発・保守するため、そういったものがないか確認するためにもここで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D2%A5%A2%A5%EA">ヒアリ</a>ングをしました。</p>
<h4 id="勉強開始">勉強開始!</h4>
<p>早速その後はGASの勉強に入りますが、変数や配列を知らない方がほとんどだったので、まずはGASのベースである<a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>の基本的な知識を勉強してもらいました。
資料はこちらの記事に記載されているものを使用させていただきました。
<a href="https://qiita.com/sakaimo/items/4eee96ed254f42ba88c1">https://qiita.com/sakaimo/items/4eee96ed254f42ba88c1</a></p>
<p>10分交代で資料の輪読・コードの実践をしてもらいました。
資料の中から参加者の方が作りたいものをに合わせて勉強項目を選定しました。以下に取り上げた項目を記載します。</p>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>エディタの使い方</li>
<li>変数</li>
<li>算術<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a></li>
<li>文字列結合</li>
<li>条件分岐</li>
<li>配列</li>
<li>繰り返し処理</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> App Script <a class="keyword" href="http://d.hatena.ne.jp/keyword/Gmail">Gmail</a> Service</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> App Scriptから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%D7%A5%EC%A5%C3%A5%C9%A5%B7%A1%BC%A5%C8">スプレッドシート</a>の操作する方法</li>
</ul>
<h4 id="実装スタート">実装スタート</h4>
<p>一通り基本を勉強したあとは、再度作りたいものを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D2%A5%A2%A5%EA">ヒアリ</a>ングして実装をします。
参加者個々に作りたいものやレベルが異なるので、私と参加者の1対1でやることを洗い出しました。
「新規のスプレットシートを作成しよう」といった小さくて簡単なステップから、どんなことを調べれば良いかなど必要な作業を具体化していきます。</p>
<p>GASの基礎を勉強する時は輪読のスタイルを取りましたが、実装に入ってからは各自が勉強することを決めて進める<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%E2%A4%AF%A4%E2%A4%AF%B2%F1">もくもく会</a>のスタイルに移行しました。</p>
<p>参加者からの質問を都度受けて、必要に応じて画面共有しながら一緒にコードを書きます。</p>
<p>現時点で実装してもらったものとして、Webサイトの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EC%A5%A4%A5%D4%A5%F3%A5%B0">スクレイピング</a>処理の定期実行などがありました。</p>
<h3 id="進める上で感じたこと">進める上で感じたこと</h3>
<p>3月末まで実施予定なので、まだ途中ではありますが今まで感じたこと書きたいと思います。</p>
<h4 id="教えるの慣れてない問題">教えるの慣れてない問題</h4>
<p>1年目は先輩に"教えてもらう時間"が多くありますが、教える側になることは基本的にないです。
そのため教える側になったのは初めてでした。その中で感じたことがいくつかありました。</p>
<p>1.エンジニア用語は使わない</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を"叩く"とか、"要素をスライスして"とかは伝わりづらいです。</p>
<p>2.視覚的に理解できるように工夫する</p>
<p>図を用意したり、コードを書いて出力するまでを画面共有で見せたりしました。
変数にどんなデータ構造の値が入っているのか細かくダンプして、コードを理解するペースを合わせるようにしました。</p>
<p>3.ゆっくり喋れ</p>
<p>これはそのままですが...</p>
<p>参加者の方がすぐにわからなかったり、コードを書く手が止まってしまう時に私に謝られることがありました。
わからないことは全く問題ないですし、参加者の思考のスピードと同じスピードで喋る方が伝わりやすいです。</p>
<h4 id="エンジニアに囲まれない時間は新鮮">エンジニアに囲まれない時間は新鮮</h4>
<p>普段はやはりエンジニアと会話をする時間が長いです。
そんな中、エンジニアは自分だけという時間は新鮮でした。
参加者の方がどんな業務をされているのか、技術で解決できそうなことに困っていないか聞いたりすることができる時間は楽しいです。</p>
<h1 id="終わりに">終わりに</h1>
<p>新卒1年目で行った業務を紹介しました。</p>
<p>大学は文系で周りにプログラミングをやっている知り合いが少なかったということもあり、エンジニアの先輩に囲まれて仕事ができるのは嬉しかったです。
また、自分から聞きに行けば先輩エンジニアからはたくさんのフィードバックをもらうことができます。
今回紹介した分析ツールの話もその一例でした。</p>
<p>GAS会では基本的に実装作業はしませんが、要件を利用者と相談しながらプロダクトを作っていくという点で良い訓練になっています。
フルリモートワークということもあり、エンジニア目線で編集・企画職の社員が困っていることを感じにくい状況になっています。
その点で自分の持っている知識を生かしながら、社内の業務改善に繋がるような活動は続けていきたいと思っています。</p>
<p>お読みいただきありがとうございました。</p>
allabout-techblog
エンジニアとして新卒入社してから取り組んだこととエンジニアを目指す人に伝えたいアドバイス
hatenablog://entry/26006613705151766
2021-03-30T14:48:36+09:00
2021-03-30T14:51:12+09:00 昨年に引き続き、オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒月間2021」を開催します。 第二弾は、オールアバウトのメディアやCMSの開発を担う部署に所属している@hideがお送りします。 1. はじめに 私は以下のスペックで、エンジニアとしてオールアバウトに新卒入社しました。 大学時代にProgateでHTML、CSS、PHPはやった Laravelで簡単なメモアプリを作ってHerokuにデプロイしたことはある Gitはほとんど使ったことがない Docker、Kubernetesは言葉だけ知っている ネットワーク等のコンピューターサイエンスに関する知識はほぼ無…
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210324/20210324104454.png" alt="f:id:allabout-techblog:20210324104454p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>昨年に引き続き、オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒月間2021」を開催します。</p>
<p>第二弾は、オールアバウトのメディアや<a class="keyword" href="http://d.hatena.ne.jp/keyword/CMS">CMS</a>の開発を担う部署に所属している@hideがお送りします。</p>
<h1 id="1-はじめに">1. はじめに</h1>
<p>私は以下のスペックで、エンジニアとしてオールアバウトに新卒入社しました。</p>
<ul>
<li>大学時代に<a href="https://prog-8.com/">Progate</a>でHTML、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>はやった</li>
<li>Laravelで簡単なメモアプリを作ってHerokuにデプロイしたことはある</li>
<li>Gitはほとんど使ったことがない</li>
<li>Docker、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>は言葉だけ知っている</li>
<li>ネットワーク等のコンピューターサイエンスに関する知識はほぼ無し</li>
<li>大学は非情報学部</li>
<li>実務未経験</li>
</ul>
<p>このような境遇の大学生が新卒でエンジニアとして入社したら、どんな部分に苦労を感じるのか。また、困難を乗り越えるためにどのようなことに取り組んだのか。アド<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>を交えつつご紹介していきます。</p>
<p>少しでもこれからエンジニアを目指す方の参考になれば幸いです。</p>
<ul class="table-of-contents">
<li><a href="#1-はじめに">1. はじめに</a></li>
<li><a href="#2-開発チームに配属されてから取り組んだこと">2. 開発チームに配属されてから取り組んだこと</a><ul>
<li><a href="#7月APIのリニューアルに伴う各アプリの修正対応">7月:APIのリニューアルに伴う各アプリの修正対応</a></li>
<li><a href="#8月Batchのリニューアル">8月:Batchのリニューアル</a></li>
<li><a href="#92月会員基盤のリニューアル">9〜2月:会員基盤のリニューアル</a></li>
</ul>
</li>
<li><a href="#3-一年間の仕事を通して得た技術以外の教訓">3. 一年間の仕事を通して得た技術以外の教訓</a><ul>
<li><a href="#影響範囲を考えることの重要性">影響範囲を考えることの重要性</a></li>
<li><a href="#相手をイメージすることの重要性">相手をイメージすることの重要性</a></li>
<li><a href="#自発的に動くことの重要性">自発的に動くことの重要性</a></li>
<li><a href="#自分の意見を伝えることの重要性">自分の意見を伝えることの重要性</a></li>
</ul>
</li>
<li><a href="#4-分からないことが分からない状態を脱するために取り組んだこと">4. 「分からないことが分からない」状態を脱するために取り組んだこと</a><ul>
<li><a href="#敵を分割する">敵を分割する</a></li>
<li><a href="#考えても分からなければ聞く">考えても分からなければ聞く</a></li>
<li><a href="#日報を書く">日報を書く</a><ul>
<li><a href="#アウトプットによる知識定着効率の向上">アウトプットによる知識定着効率の向上</a></li>
<li><a href="#インプットのトリガーになる">インプットのトリガーになる</a></li>
<li><a href="#見返したときに自信になる">見返したときに自信になる</a></li>
<li><a href="#Vimの操作に慣れた">(Vimの操作に慣れた)</a></li>
</ul>
</li>
<li><a href="#本を読む">本を読む</a></li>
<li><a href="#自分で作ってみる手を動かす">自分で作ってみる(手を動かす)</a></li>
</ul>
</li>
<li><a href="#5-これからエンジニアになろうとしている人へアドバイス">5. これからエンジニアになろうとしている人へアドバイス</a><ul>
<li><a href="#タッチタイピングの習得は必須">タッチタイピングの習得は必須</a></li>
<li><a href="#コンピュータサイエンスやWebの基礎知識は事前に学んでおいた方が良い">コンピュータサイエンスやWebの基礎知識は事前に学んでおいた方が良い</a></li>
<li><a href="#プログラミングの基礎は事前に学んでおいた方が良い">プログラミングの基礎は事前に学んでおいた方が良い</a></li>
<li><a href="#自宅の作業環境は早めに整えておこう">自宅の作業環境は早めに整えておこう</a></li>
<li><a href="#心の準備一年目はしんどい">心の準備:一年目はしんどい</a></li>
<li><a href="#でも少しずつできることが増えていくのは楽しい">でも、少しずつできることが増えていくのは楽しい</a></li>
</ul>
</li>
<li><a href="#6まとめ">6.まとめ</a></li>
</ul>
<h1 id="2-開発チームに配属されてから取り組んだこと">2. 開発チームに配属されてから取り組んだこと</h1>
<p>まずは、これまでやってきたことを振り返ります。</p>
<p>4〜6月はビジネスマナー研修・エンジニア研修に取り組み、7月から現場に配属されました。</p>
<h2 id="7月APIのリニューアルに伴う各アプリの修正対応">7月:<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>のリニューアルに伴う各アプリの修正対応</h2>
<p>最初に取り組んだ仕事は、「会員基盤<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>のリニューアルに伴う各アプリの修正対応」です。</p>
<p>作業自体は定形的で単純なものだったのですが、そもそも<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>への理解が曖昧だった(名前しか知らなかった)ので、「<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>って何?」から入る必要がありました。</p>
<p>ローカル環境で以下のような<a class="keyword" href="http://d.hatena.ne.jp/keyword/curl">curl</a>コマンドを叩いて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の基礎的な概念を体感的に覚えた記憶があります。</p>
<p><code>curl -H "NAME: sample" -d "id=180&sample_id=1" -X POST 'localhost:9010/api/sample'</code></p>
<p>また、この頃は、今まで自分が書いてきたコードと業務レベルのコードとのギャップに苦しみました。
今となっては当時の感覚は思い出せませんが、暗号を読んでいる感覚だった気がします。</p>
<p>さらに、コードの追い方も分からなかったので、先輩のコードの追い方を参考にしつつ徐々に感覚を養っていきました。</p>
<h2 id="8月Batchのリニューアル">8月:Batchのリニューアル</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の後は、会員基盤で利用しているBatch(あらかじめ決められた一連の処理を実行するアプリ)のリニューアルに取り組みました。</p>
<p>こちらも例に漏れず「Batchとは何か?」から入る必要があったので、先輩に教えてもらいつつ、少しずつBatch周りの概念を理解していきました。</p>
<p>具体的には、「cron(時間指定して処理を実行する仕組み)」「crontab(Batch実行時間のスケジュール管理を行うコマンド)」「cronjob(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>でcronと同じフォーマットで実行する処理を指定する仕組み)」等について学びました。</p>
<p>さらに、この改修では、バッチの実行方法として、「cronjobにLaravelのコマンドを指定して実行する方法」を取ったため、「Laravelで特定の処理を実行するコマンドを作成する方法」についても学習しました。</p>
<h2 id="92月会員基盤のリニューアル">9〜2月:会員基盤のリニューアル</h2>
<p>9月から2月は会員基盤本体のリニューアルに取り組みました。</p>
<p>開発内容としては、「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>の作成 -> 設計 -> 実装 -> テスト -> デプロイ」まで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>の全ての工程を経験することができました。</p>
<p>技術的にも、今まで知らなかった数多くの技術や機能に触れることができました。以下に代表的なものを列挙します。</p>
<ul>
<li>Laravel・<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>
<ul>
<li>Event</li>
<li>GateとPolicy</li>
<li>サー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D3%A5%B9%A5%B3">ビスコ</a>ンテナ</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Cookie">Cookie</a>、Sessionの扱い方</li>
<li>コレクション</li>
<li>デフォルト認証方法の差し替え</li>
<li>メール送信</li>
<li>画像アップロード</li>
<li>TDDで開発</li>
<li>データプロバイダ</li>
<li>Mockery</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>の組み込みメソッド多数</li>
<li>Trait</li>
</ul>
</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a>
<ul>
<li>Laravel Mix</li>
<li>Cropper.js(画像アップロード処理)</li>
</ul>
</li>
</ul>
<p>また、個人的なトピックとしては、この頃モニタや椅子を新調して仕事の環境がかなり整いました。(オールアバウトではこの一年原則リモートワークです)</p>
<h1 id="3-一年間の仕事を通して得た技術以外の教訓">3. 一年間の仕事を通して得た技術以外の教訓</h1>
<p>一年間の仕事を通して、技術はもちろんのこと、仕事に対する「姿勢」や「マインド」についても数多くの学びを得ることができました。</p>
<p>今回は中でも印象に残っているものをご紹介します。</p>
<ul>
<li>影響範囲を考えることの重要性</li>
<li>相手をイメージすることの重要性</li>
<li>自発的に動くことの重要性</li>
<li>自分の意見を伝えることの重要性</li>
</ul>
<h2 id="影響範囲を考えることの重要性">影響範囲を考えることの重要性</h2>
<p>仕事においては、全ての作業に対して「影響範囲」が存在します。</p>
<p>そして、実行する作業によってその「影響範囲の広さ」は異なります。</p>
<p>例えば、開発環境のDBの影響範囲は、あくまで自分の開発環境内のみです。
いくらデータを適当に削除したところでなんの影響もありません。</p>
<p>しかし、本番環境の場合は、その動作の可否がビジネスの利益に直結します。
それこそ数分止まっただけで数百万円規模で利益を逃すこともありうるのです。</p>
<p>私はこの一年間、様々な場面で、(時には失敗もしながら)「影響範囲を考えることの重要性」を実感してきました。</p>
<p>これからも「何か作業を始める前にはその作業の影響範囲を考える」ことを習慣にしていきたいと考えています。</p>
<h2 id="相手をイメージすることの重要性">相手をイメージすることの重要性</h2>
<p>この一年、仕事および開発の中で「相手をイメージすることの重要性」を実感した場面が数多くありました。</p>
<p>例えば、仕事中のコミュニケーションだと、自分の意図が思うように伝わらなかったり、開発の場合だと、想定していた動き以外の動作をユーザーがしていたためにバグが生じてしまったりなどです。</p>
<p>そして、なぜこのようなことが生じてしまったのかを考えた結果、「持っている情報の非対称性」が原因だと気が付きました。
要は、「自分と相手では見えている景色が違う」ことへの認識が甘かったのです。</p>
<p>我々は、年齢も経験も知識も全く異なる相手同士で仕事を行っています。
そんな中で、自分の考えがさも当たり前かのように振る舞っていたら、必ずどこかで「ズレ」が生じます。</p>
<p>その「ズレ」を最小限に押さえて業務を円滑に進めるためにも、相手と自分の持っている情報の非対称性しっかりと意識した上で、「いかにそのギャップを抑える活動をするか」を考え、実行することが重要だと学びました。</p>
<h2 id="自発的に動くことの重要性">自発的に動くことの重要性</h2>
<p>社会人になったら、全てにおいて「自発的に動く」必要があります。</p>
<p>例えば、技術の習得についてもそうです。</p>
<p>学生の頃は、必要な知識を身に付けるためのリソースは、学校側が「教材」や「宿題」という形で用意してくれていました。つまり、完全に「受動的」でも必要な知識が身に付く仕組みになっていたのです。</p>
<p>しかし、社会に出たら違います。</p>
<p>必要な知識を自分で判断・選定して、自分で教材を選択して学ぶ必要があります。つまり、完全に「自発的」な姿勢が求められるのです。</p>
<p>特にエンジニアの場合は、常に技術のアップデートが求められるため、「自発的に学ぶ姿勢」が無ければあっという間に取り残されてしまいます。</p>
<p>この辺の学びに対する意識の切り替えを早い段階でできたのは良かったです。</p>
<h2 id="自分の意見を伝えることの重要性">自分の意見を伝えることの重要性</h2>
<p>何かを学んだり習得したりする上で、「素直になる」ことはとても重要です。何でもかんでも自己流を貫いて天邪鬼になっていたら、成長速度は遅くなってしまいます。</p>
<p>しかし、仕事においては、なんでもかんでも素直に返事をする「yesマン」になってしまうと不都合が生じることがあります。</p>
<p>なぜなら、「素直になること」は「妥協」に繋がる恐れがあるからです。</p>
<p>例えば、プルリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トなどは、先輩の実装に対してレビューをする必要があります。
このとき、「先輩のだから大丈夫」とか「ちょっと気になる所あるけどまあ良いか。。」と軽い気持ちで承認を押すと、それが元でバグが発生することに繋がりかねません。</p>
<p>大切なのは、「摩擦を生じさせない」ことではなく、「より良いプロダクトを作ること」です。</p>
<p>もちろんプルリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トだけではありませんが、自分の意見がある場合は、それが先輩の意見と異なっていたとしても積極的に主張することが重要だと日々感じています。</p>
<h1 id="4-分からないことが分からない状態を脱するために取り組んだこと">4. 「分からないことが分からない」状態を脱するために取り組んだこと</h1>
<p>次に、仕事を進める上で直面した困難と、困難を克服するために実践したことをまとめます。</p>
<p>プログラミングの経験が浅い状態で入社した際にぶつかる壁(困難)は、なんと言っても「分からないことが多すぎる」ことです。</p>
<p>私も業務に入ったばかりの頃は、本当に分からないことだらけで苦労しました。
特定の何かが分からないというより、「何が分からないか分からない状態」だったのです。</p>
<p>そして、そんな状況を脱するために私が意識・実践したのは以下の5つです。</p>
<ul>
<li>敵を分割する</li>
<li>考えても分からなければ聞く</li>
<li>日報を書く</li>
<li>本を読む</li>
<li>自分で作ってみる(手を動かす)</li>
</ul>
<h2 id="敵を分割する">敵を分割する</h2>
<p>問題の解決方法が分からない場合は、「敵を分割すること」を意識しました。</p>
<p>例えば、「Laravelでアプリを作ってリリースする」というゴールを設定した場合、いきなり取り掛かろうとしても何から手を付けていいか分かりません。</p>
<p>そこで、以下のように手順を分割するのです。</p>
<ol>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>を作る</li>
<li>システム設計・DB設計をする</li>
<li>Dockerで開発環境を作る
<ul>
<li>docker-compose.ymlを作る</li>
<li>Dockerfileを作る</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Apache">Apache</a>等の設定ファイルを作る</li>
</ul>
</li>
<li>ComposerでLaravelをインストールする</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A5%CB%A5%C3%A5%C8%A5%C6%A5%B9%A5%C8">ユニットテスト</a>が動くようにする</li>
<li>〇〇の機能を作る</li>
<li>画面テストをする</li>
<li>本番環境用の設定ファイルを作る(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Apache">Apache</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>)</li>
<li>デプロイ用のDockerfileを作る</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>ファイルを作る</li>
<li>CircleCIの設定ファイル(.circleci/config.yml)を作る</li>
<li>リリース(デプロイ)する</li>
</ol>
<p>さらに、実際に取り組む際には、それぞれのタスクをより細かく分割していきます。
要は全てにおいて「より小さく・よりシンプルに」考えるイメージです。</p>
<p>私はこの考え方を意識するようになってから、より一人で解決することのできる問題の幅を広げることができました。</p>
<h2 id="考えても分からなければ聞く">考えても分からなければ聞く</h2>
<p>いくら考えても分からないものは分かりません。</p>
<p>そのため、どうしても分からない場合は先輩に質問するようにしていました。</p>
<p>ただし、なんでもかんでもすぐに質問して良いわけではありません。
単純に先輩の時間を奪うことに繋がりますし、「ちゃんと自分で考えてないのかな?」とも思われるからです。</p>
<p>そのため、質問をする際には、「最低〇分は考える」など自分なりのルールを儲けていました。</p>
<p>また、質問内容も「自分はこう思うのですが、〇〇さんはどう思いますか」のように、なるべく自分の意見も添えて質問するようにしていました。</p>
<h2 id="日報を書く">日報を書く</h2>
<p>私は業務を開始してから、毎日の日報を継続しています。</p>
<p>これにより、以下の効果を得ることができました。</p>
<ul>
<li>アウトプットによる知識定着効率の向上</li>
<li>インプットのトリガーになる</li>
<li>見返したときに自信になる</li>
<li>(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Vim">Vim</a>の操作に慣れた)</li>
</ul>
<h3 id="アウトプットによる知識定着効率の向上">アウトプットによる知識定着効率の向上</h3>
<p>日報に日々の学びを書くことにより、理解が曖昧な部分をそのままにしなくなるため、知識をより着実に身に付けることができました。</p>
<p>また、インプットだけでなく「アウトプット」の機会が作れたのも記憶の定着には有効であったと感じています。</p>
<h3 id="インプットのトリガーになる">インプットのトリガーになる</h3>
<p>日報があることにより、業務中でも「学び」に対する意識を高めることができました。</p>
<p>また、業務外でも「日報に書くネタ作り」がトリガーとなってインプットの機会を増やすことができました。</p>
<h3 id="見返したときに自信になる">見返したときに自信になる</h3>
<p>日報を積み上げることは、「自分が学んだ内容を可視化する」ことと同意です。</p>
<p>そして、その積み上げた量の多さは、そのまま自分の「自信」に繋がります。
要は、「昨日よりも前に進んでいる」実感を持つことができるのです。</p>
<p>これは自分に対する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%BA%BF%C0%B0%C2%C4%EA%BA%DE">精神安定剤</a>としては非常に有効だったと感じています。</p>
<h3 id="Vimの操作に慣れた">(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Vim">Vim</a>の操作に慣れた)</h3>
<p>これはおまけですが、私は日々の日報を<a class="keyword" href="http://d.hatena.ne.jp/keyword/Vim">Vim</a>(<a class="keyword" href="http://d.hatena.ne.jp/keyword/CLI">CLI</a>で使う<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%AD%A5%B9%A5%C8%A5%A8%A5%C7%A5%A3%A5%BF">テキストエディタ</a>)で執筆しています。</p>
<p>これにより、基本的な<a class="keyword" href="http://d.hatena.ne.jp/keyword/Vim">Vim</a>のコマンドはマスターでき、また、開発中でも<a class="keyword" href="http://d.hatena.ne.jp/keyword/Vim">Vim</a>の操作に戸惑うことはほぼなくなりました。</p>
<p>ただ最近は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Vim">Vim</a>の知識がアップデートできていないので、今後は少しずつ知識を増やしていきたいと考えています。</p>
<h2 id="本を読む">本を読む</h2>
<p>よく分からない事象に対しては、「本を読む」ことにも取り組みました。</p>
<p>特に意識的に読んだのは、自分の中でイメージが掴みにくかった分野。例えば自分の場合だと「ネットワーク」「<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>」周りです。</p>
<p>実務ではそれらの技術の「使い方」は学ぶことができます。</p>
<p>しかし、「概念的な部分」をじっくり学ぶ時間はありません。そのため個人的に勉強する必要がありました。</p>
<p>業務で学べることはもちろん多いです。
しかし、それだけでは足りなかったり偏りが出たりする部分もあるので、本等で知識の補填をすることは重要だと感じています。</p>
<h2 id="自分で作ってみる手を動かす">自分で作ってみる(手を動かす)</h2>
<p>いくら知識を取り入れたところで、それらを実際に使わなければ、「使える知識」とはなりません。</p>
<p>そのため、学んだ知識は「実際に使ってみる」ことも同時に意識しました。</p>
<p>例えば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>のメソッドを学んだ場合は<code>php -a</code>で動かしてみて動作を確認する。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>を学んだなら、実際に自分でGKEにアプリをデプロイしてみるなどです。</p>
<p>これにより、確実にイメージできる範囲を広げることができました。</p>
<p>技術を学ぶには、やはり「自分の頭で考えて手を動かす」が一番の方法であることを実感しています。</p>
<h1 id="5-これからエンジニアになろうとしている人へアドバイス">5. これからエンジニアになろうとしている人へアド<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a></h1>
<p>最後に、僭越ながらこれから実務未経験でエンジニアになろうとしている人へアド<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>を書きます。</p>
<p>具体的には、一年前の自分に対して、「入社前にやっておいて良かったこと」および「入社前にやっておけば良かったこと」をまとめます。</p>
<p>少しでも参考になれば幸いです。</p>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%C3%A5%C1%A5%BF%A5%A4%A5%D4%A5%F3%A5%B0">タッチタイピング</a>の習得は必須</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D4%A5%E5%A1%BC%A5%BF%A5%B5%A5%A4%A5%A8%A5%F3%A5%B9">コンピュータサイエンス</a>やWebの基礎知識は事前に学んでおいた方が良い</li>
<li>プログラミングの基礎は事前に学んでおいた方が良い</li>
<li>自宅の作業環境は早めに整えておこう</li>
<li>心の準備:一年目はしんどい</li>
<li>でも、少しずつできることが増えていくのは楽しい</li>
</ul>
<h2 id="タッチタイピングの習得は必須"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%C3%A5%C1%A5%BF%A5%A4%A5%D4%A5%F3%A5%B0">タッチタイピング</a>の習得は必須</h2>
<p>この記事を書くにあたり、私が入社前にやっておいて良かったことを改めて考えてみました。</p>
<p>もちろんProgate等でプログラミングの基礎を学んでおいたのも良かったのですが、一番やっておいて良かったと思ったのは、「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%C3%A5%C1%A5%BF%A5%A4%A5%D4%A5%F3%A5%B0">タッチタイピング</a>の習得」です。</p>
<p>なぜなら、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%C3%A5%C1%A5%BF%A5%A4%A5%D4%A5%F3%A5%B0">タッチタイピング</a>がある程度できたことによって、「技術の勉強のみに集中する余裕」を作れたからです。</p>
<p>もし<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%C3%A5%C1%A5%BF%A5%A4%A5%D4%A5%F3%A5%B0">タッチタイピング</a>が全くできない状態で入社していたら、コードや文章を書くのに時間が取られて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>や技術の勉強に集中できていなかったと思います。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%C3%A5%C1%A5%BF%A5%A4%A5%D4%A5%F3%A5%B0">タッチタイピング</a>の練習方法としては、<a href="https://www.e-typing.ne.jp/">e-typing</a>、<a href="http://typingx0.net/sushida/">寿司打</a>等のサイトがおすすめです。ゲーム感覚で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%C3%A5%C1%A5%BF%A5%A4%A5%D4%A5%F3%A5%B0">タッチタイピング</a>を身に付けることができます。</p>
<p>また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%C3%A5%C1%A5%BF%A5%A4%A5%D4%A5%F3%A5%B0">タッチタイピング</a>の練習をする際の注意点は以下の三つです。</p>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DB%A1%BC%A5%E0%A5%DD%A5%B8%A5%B7%A5%E7%A5%F3">ホームポジション</a>を守る</li>
<li>絶対にキーボードを見ない</li>
<li>毎日やる</li>
</ul>
<p>この3点を意識して練習を積めば、数週間〜1ヶ月くらいである程度はできるようになると思います。</p>
<p>私自身も大学3年の頃までは全く<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%C3%A5%C1%A5%BF%A5%A4%A5%D4%A5%F3%A5%B0">タッチタイピング</a>ができませんでしたが、上記のポイントを意識して練習したことにより、1ヶ月程度である程度<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BF%A5%C3%A5%C1%A5%BF%A5%A4%A5%D4%A5%F3%A5%B0">タッチタイピング</a>を習得することができました。</p>
<h2 id="コンピュータサイエンスやWebの基礎知識は事前に学んでおいた方が良い"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D4%A5%E5%A1%BC%A5%BF%A5%B5%A5%A4%A5%A8%A5%F3%A5%B9">コンピュータサイエンス</a>やWebの基礎知識は事前に学んでおいた方が良い</h2>
<p>エンジニアとして働く上で、最低限のコンピューターサイエンスおよびWebの知識は必須です。</p>
<p>私はこの辺りをほとんど勉強することなく会社に入ったため、かなり苦労しました。</p>
<p>大学の情報学部や専門学校等で学んだ人は勉強する必要はありませんが、学生時代に全くコンピューターサイエンスを勉強してこなかった人は勉強しておくと良いでしょう。</p>
<p>今回はおすすめの本を数冊ご紹介します。</p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B07JK7FZH2/hatena-blog-22/"><img src="https://m.media-amazon.com/images/I/51HNAhxudcL.jpg" class="hatena-asin-detail-image" alt="Webを支える技術 ―― HTTP,URI,HTML,そしてREST WEB+DB PRESS plus" title="Webを支える技術 ―― HTTP,URI,HTML,そしてREST WEB+DB PRESS plus"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B07JK7FZH2/hatena-blog-22/">Webを支える技術 ―― HTTP,URI,HTML,そしてREST WEB+DB PRESS plus</a></p><ul><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%BB%B3%CB%DC%20%CD%DB%CA%BF" class="keyword">山本 陽平</a></li><li><span class="hatena-asin-detail-label">発売日:</span> 2018/11/14</li><li><span class="hatena-asin-detail-label">メディア:</span> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kindle">Kindle</a>版</li></ul></div><div class="hatena-asin-detail-foot"></div></div></p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B06XNMMC9S/hatena-blog-22/"><img src="https://m.media-amazon.com/images/I/51ouGc6zGFL.jpg" class="hatena-asin-detail-image" alt="イラスト図解式 この一冊で全部わかるWeb技術の基本" title="イラスト図解式 この一冊で全部わかるWeb技術の基本"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B06XNMMC9S/hatena-blog-22/">イラスト図解式 この一冊で全部わかるWeb技術の基本</a></p><ul><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%BE%AE%CE%D3%20%B6%B3%CA%BF" class="keyword">小林 恭平</a>,<a href="http://d.hatena.ne.jp/keyword/%BA%E4%CB%DC%20%CD%DB" class="keyword">坂本 陽</a></li><li><span class="hatena-asin-detail-label">発売日:</span> 2017/03/16</li><li><span class="hatena-asin-detail-label">メディア:</span> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kindle">Kindle</a>版</li></ul></div><div class="hatena-asin-detail-foot"></div></div></p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B082DT76Z8/hatena-blog-22/"><img src="https://m.media-amazon.com/images/I/51IsAD2nEvL.jpg" class="hatena-asin-detail-image" alt="キタミ式イラストIT塾 基本情報技術者 令和02年" title="キタミ式イラストIT塾 基本情報技術者 令和02年"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B082DT76Z8/hatena-blog-22/">キタミ式イラストIT塾 基本情報技術者 令和02年</a></p><ul><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%A4%AD%A4%BF%A4%DF%20%A4%EA%A4%E5%A4%A6%A4%B8" class="keyword">きたみ りゅうじ</a></li><li><span class="hatena-asin-detail-label">発売日:</span> 2019/12/14</li><li><span class="hatena-asin-detail-label">メディア:</span> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Kindle">Kindle</a>版</li></ul></div><div class="hatena-asin-detail-foot"></div></div></p>
<p><div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4297111713/hatena-blog-22/"><img src="https://m.media-amazon.com/images/I/51DnKHafAtL.jpg" class="hatena-asin-detail-image" alt="【改訂5版】図解でよくわかる ネットワークの重要用語解説" title="【改訂5版】図解でよくわかる ネットワークの重要用語解説"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4297111713/hatena-blog-22/">【改訂5版】図解でよくわかる ネットワークの重要用語解説</a></p><ul><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%A4%AD%A4%BF%A4%DF%20%A4%EA%A4%E5%A4%A6%A4%B8" class="keyword">きたみ りゅうじ</a></li><li><span class="hatena-asin-detail-label">発売日:</span> 2020/04/16</li><li><span class="hatena-asin-detail-label">メディア:</span> 単行本(ソフトカバー)</li></ul></div><div class="hatena-asin-detail-foot"></div></div></p>
<p>下の3つはより初心者向けの書籍で、図が豊富なのでイメージも掴みやすいと思います。</p>
<h2 id="プログラミングの基礎は事前に学んでおいた方が良い">プログラミングの基礎は事前に学んでおいた方が良い</h2>
<p>当たり前ですが、入社前に最低限のプログラミングの知識は身に付けておいた方が良いです。</p>
<p>オールアバウトの場合だと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>をメインに使用しているので、事前に<a href="https://prog-8.com/">Progate</a>等で<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>の基礎を学んでおくと良いでしょう。(別の会社の場合は、その会社で使用している言語を勉強しておく)</p>
<p>また、余裕がある場合は、言語だけでなくその言語の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>も勉強しておくと、何もしてないよりはスムーズに業務に入っていくことができます。</p>
<p>Laravelの場合だと、公式ドキュメントでも良いですが、以下の書籍などは初学者でも理解しやすいのでおすすめです。
<div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4798060992/hatena-blog-22/"><img src="https://m.media-amazon.com/images/I/51I2lZaKIoL.jpg" class="hatena-asin-detail-image" alt="PHPフレームワークLaravel入門 第2版" title="PHPフレームワークLaravel入門 第2版"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4798060992/hatena-blog-22/">PHPフレームワークLaravel入門 第2版</a></p><ul><li><span class="hatena-asin-detail-label">作者:</span><a href="http://d.hatena.ne.jp/keyword/%C4%C5%CC%ED%C7%B5%2C%20%BE%B8%C5%C4" class="keyword">津耶乃, 掌田</a></li><li><span class="hatena-asin-detail-label">発売日:</span> 2019/12/27</li><li><span class="hatena-asin-detail-label">メディア:</span> 単行本</li></ul></div><div class="hatena-asin-detail-foot"></div></div></p>
<h2 id="自宅の作業環境は早めに整えておこう">自宅の作業環境は早めに整えておこう</h2>
<p>出社して働く場合は問題ないのですが、コロナ等の影響によりリモートで働く場合は、自宅の開発環境を早めに整備するようにしましょう。</p>
<p>具体的には、「ネットのスピード」「モニター」「椅子」はケチらない方が良いです。特にモニターに関しては、あるのとないのとでは業務の効率が違います。</p>
<p>私の場合はこれらの準備を全くしないでリモートワークに入ってしまったため、最初の頃はかなり苦労しました。</p>
<p>なるべく入社前にこれらの環境を整えておくと、スムーズに業務に入ることができるでしょう。</p>
<p>ちなみに私は以下のモニターを使っています。高さ調整が可能で画質もいいので非常に使いやすいです。
<div class="hatena-asin-detail"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B085TWLMF9/hatena-blog-22/"><img src="https://m.media-amazon.com/images/I/515ukqEPSvL.jpg" class="hatena-asin-detail-image" alt="【Amazon.co.jp 限定】Dell 4Kモニター 27インチ U2720QM(3年間無輝点交換保証付/広視野角/HDR/IPS非光沢/フリッカーフリー/USB Type-C,DP,HDMI/高さ調整/回転)" title="【Amazon.co.jp 限定】Dell 4Kモニター 27インチ U2720QM(3年間無輝点交換保証付/広視野角/HDR/IPS非光沢/フリッカーフリー/USB Type-C,DP,HDMI/高さ調整/回転)"></a><div class="hatena-asin-detail-info"><p class="hatena-asin-detail-title"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/B085TWLMF9/hatena-blog-22/">【Amazon.co.jp 限定】Dell 4Kモニター 27インチ U2720QM(3年間無輝点交換保証付/広視野角/HDR/IPS非光沢/フリッカーフリー/USB Type-C,DP,HDMI/高さ調整/回転)</a></p><ul><li><span class="hatena-asin-detail-label">発売日:</span> 2020/04/04</li><li><span class="hatena-asin-detail-label">メディア:</span> Personal Computers</li></ul></div><div class="hatena-asin-detail-foot"></div></div></p>
<h2 id="心の準備一年目はしんどい">心の準備:一年目はしんどい</h2>
<p>経験が浅い状態で入社するエンジニアにとって、正直、一年目はしんどいです。</p>
<p>ここでの「しんどい」の意味は、「技術のキャッチアップに苦労する」ということです。</p>
<p>もちろん、キャッチアップのスピードには個人差があるので、スムーズに業務を覚えて活躍できる方もいるとは思います。</p>
<p>しかし、私も含めて大抵の場合はそうはいかないでしょう。</p>
<p>なぜなら、覚えなくてはならないことがあまりに膨大だからです。</p>
<p>例えばオールアバウトの場合だと主に以下の技術群を用いており、これら全てについてある程度の知見を持つことが求められます。</p>
<ul>
<li>Git</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Vim">Vim</a></li>
<li>Docker</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a></li>
<li>CircleCI</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a></li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a></li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Apache">Apache</a></li>
<li>HTML/<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a></li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a></li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a></li>
<li>CodeIgniter</li>
<li>Lumen</li>
<li>Laravel</li>
</ul>
<p>さらに新卒エンジニアの場合は、技術的なキャッチアップに加えて、「新社会人」としても覚えなくてはならないことが沢山あります。</p>
<p>例えば、会社で用いているツールの使い方や文章の書き方、ビジネスマナー、仕事をこなす上での考え方などです。</p>
<p>確実にキャパオーバーになる場面は出てくるでしょう。</p>
<p>ネット上では、「エンジニアは誰にでもできる」「エンジニアは簡単」「エンジニアは楽に稼げる」等の誇大広告が散見されます。</p>
<p>しかし、現実はそう甘くはありません。実際は常に知識の習得やアップデート、勉強が求められる泥臭い仕事です。勉強を継続できない人は確実についていけません。</p>
<p>「エンジニアは楽」「誰でも簡単にできる」と思っている人は今のうちに認識を改めておきましょう。そうすることで、エンジニアになる前と後でのギャップを減らすことができます。</p>
<h2 id="でも少しずつできることが増えていくのは楽しい">でも、少しずつできることが増えていくのは楽しい</h2>
<p>先ほど、「一年目はしんどい」と書きました。これは心構えとしては間違いなく持っておいた方が良いです。</p>
<p>しかし、もちろん楽しいこともあります。</p>
<p>それは、なんといっても「常に成長を実感できる」ことです。</p>
<p>未経験で入社した場合、分からないことやできないことは膨大です。しかし、その分できることも日々確実に増えていきます。学びが無い日がないので、知的好奇心が毎日確実に満たされる状態です。</p>
<p>私自身も、この一年で本当に多くの技術的および社会人として働く上での学びを得ることができました。</p>
<p>もちろん苦しいこともありましたが、その経験の全てが今の自分の礎になっていると感じています。</p>
<h1 id="6まとめ">6.まとめ</h1>
<p>この記事では、私が新卒でオールアバウトにエンジニアとして入社してから取り組んだことと、その中で得た教訓をまとめつつ、これからエンジニアを目指している方へのアド<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>も書いてみました。</p>
<p>この記事が少しでもこれからエンジニアを目指す方の参考になっていれば幸いです。</p>
<p>最後まで読んで頂きありがとうございました。</p>
allabout-techblog
オールアバウトナビエンジニアの働き方と一年間振り返り
hatenablog://entry/26006613704437357
2021-03-29T14:10:07+09:00
2021-03-29T14:10:07+09:00 はじめに 毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2021」を開催します! 今回は、オールアバウトナビ(以下からナビで省略します)システム部の@monpeiがお送りします! ナビの詳細は下記のリンクからご確認いただけます。 www.allaboutnavi.co.jp 昨年12月のテックブログ の記事ではナビに入社から12月までの、業務内容や自分が感じたことについての記事を投稿させていただきました。 前回の記事の続編でもあるので合わせて読んでいけると嬉しく思います! allabout-tech.hatenablog.com 今回の内容は以下のこと…
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210325/20210325093837.png" alt="f:id:allabout-techblog:20210325093837p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h2>はじめに</h2>
<p>毎年恒例オールアバウトグループの新卒1年目エンジニアが投稿する企画「テックブログ新卒週間2021」を開催します!
今回は、オールアバウトナビ(以下からナビで省略します)システム部の@monpeiがお送りします!</p>
<p>ナビの詳細は下記のリンクからご確認いただけます。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.allaboutnavi.co.jp" title="All About Navi" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://www.allaboutnavi.co.jp">www.allaboutnavi.co.jp</a></cite></p>
<p>昨年12月のテックブログ の記事ではナビに入社から12月までの、業務内容や自分が感じたことについての記事を投稿させていただきました。
前回の記事の続編でもあるので合わせて読んでいけると嬉しく思います!</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fallabout-tech.hatenablog.com%2Fentry%2F2020%2F12%2F18%2F184117" title="初のフルリモート体制で新卒が素直に書く! ~新卒でオールアバウトナビに配属されて~ - オールアバウトTech Blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://allabout-tech.hatenablog.com/entry/2020/12/18/184117">allabout-tech.hatenablog.com</a></cite></p>
<p>今回の内容は以下のことについてお話します</p>
<ul>
<li>ナビシステム部の働き方について</li>
<li>配属〜現在まで働いて 振り返り</li>
</ul>
<p>前回の記事ではナビシステム部の働き方や雰囲気をお伝えできなかったので、ぜひ知っていただきたいです!
よろしくお願いいたします。</p>
<h2>ナビシステム部の働き方について</h2>
<h3>ナビシステム部はどんなことをやってるの?</h3>
<p>私たちは主に以下のようなことをしています。
主に自社で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%DD%CD%AD">保有</a>している4サービスのサイト及び<a class="keyword" href="http://d.hatena.ne.jp/keyword/CMS">CMS</a>の運用と保守、定期処理するための<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%C3%A5%C1%BD%E8%CD%FD">バッチ処理</a>の作成に加え、集計作業の自動化を進めています。
最近だと<a class="keyword" href="http://d.hatena.ne.jp/keyword/CakePHP">CakePHP</a>で動いているシステムをLaravelへ移行する作業を行っております。移行背景としては既存のコードが複雑になっており、新規機能追加や改修を行う際に非常に変更がしづらい作りになっているためです。
また、オールアバウトグループでは主にLaravelで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>を行っているため、多くの社内エンジニアが改修しやすくしたいという意図もあります。</p>
<h3>ナビシステム部コンセプト</h3>
<p>ナビシステム部では以下のような取り決めをしております。</p>
<p><strong>「やらなくていいことをやることは、やらないといけないことをやらないより良くない」</strong></p>
<p>少し遠回しで呪文のように見えるかと思いますがこれはあえてです。(笑)
意味としては本当にやるべきこととやる必要があるものを精査し、やる必要があるもののみに注力しよう!とういことです。
ナビシステム部の開発チームはエンジニア2名とマネージャー1名で構成されております。少人数で開発を行っているため、現状やる必要のないことに注力してしまうと、他の重要なタスクに手をつけられなくなってしまいます。
そんなことが起きないように↑のようなコンセプトを基に業務を行っています。
しかしながら、業務で困っていて相談にきているのに、開発コストがかかってしまうからと依頼を受けないのは違いますよね。
ナビシステム部では↑のコンセプトとは別に<strong>親切であること</strong>というキャッチフレーズも抱えています。
時にはシステムの開発ではなく業務フローの改善を提案をしたりすることで問題を解決します。</p>
<h3>システム部外の部署との距離感が近くなった</h3>
<ul>
<li>依頼者に定期的に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D2%A5%A2%A5%EA">ヒアリ</a>ングの時間を設けるようにした</li>
<li>システム部への相談や依頼に開発メンバーも参加することが多くなった</li>
</ul>
<p>上記二つが今年に入ってから変わった点です。
開発メンバーも積極的に開発前段階の話し合いに参加するようになりました。
背景としては、新しい機能やシステムを作ったけど2,3ヶ月ほどしたら使われなくなってしまうといったケースが多々あったためです。
こういうことは良くあることでしょうが、せっかくならお互いが納得のいく良いものを作りたいですよね。
現場の業務フローや目標、課題を定期的に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D2%A5%A2%A5%EA">ヒアリ</a>ングすることにより、実際に作ったものが後々になっても使ってもらえるように、依頼者とシステム部の認識に差異が出ないようにすることを試みてます。
まだ、実践してから日が浅いので開発後に活きてくるかはわかりませんが、どんなことに実際に悩まれているのかを把握することができ、より他部署との信頼関係を築けるようになりました。
個人的にもただ開発をするのではなく誰のために何のためにを考えて開発をする方が、仕事へのモチベーションと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A2%C2%B0%B0%D5%BC%B1">帰属意識</a>が上がり良いと感じています。</p>
<h3>ナビ開発の流れ</h3>
<p>基本的にSlackのチャンネルで依頼のやりとりが行われます。
マネージャーが依頼に対してレスポンスを返し、開発をするべきと判断した場合はシステム部メンバーにタスクを割り振ったり、処理が多くなりそうなタスクはBacklogにチケットを作成し開発を行います。
2021年になってから開発の流れに少し変化が出てきました。</p>
<h4>改善点 (タスクが埋もれてしまうことが多くなった)</h4>
<p>今年に入ってからタスクが埋もれてしまったり、依頼されたことに認知できていないケースが多々ありました。
各プラットフォームごとにSlackのチャンネルを分けていたのですが、様々な情報が行き交い依頼内容が埋もれてしまいました。
一つのチャンネルの役割があまりに大きかったため新しくチャンネルを追加し、依頼用、レポート通知用など用途別に分けました。
またここ一ヶ月では一つのメッセージに複数の依頼を頂くことが多く、やりとりをしているうちに話題が右往左往し、埋もれてしまっていたケースもありました。</p>
<p>そのため以下のように変更することを決めました。</p>
<p>従来)Slack → 依頼精査 → 開発着手 or Slack → 依頼精査 → Backlog → 開発着手</p>
<p>改善)Slack → Trello → 依頼精査 → Backlog → 開発着手</p>
<p>Trello及びBacklogの詳細は割愛しますが、一言で言うとプロジェクト管理ツールのことです。</p>
<p>Trello
<iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftrello.com%2Fja" title="Trello" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://trello.com/ja">trello.com</a></cite></p>
<p>Backlog
<iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fbacklog.com%2Fja%2F" title="タスク管理、ファイル共有もできるプロジェクト管理ツールBacklog" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://backlog.com/ja/">backlog.com</a></cite></p>
<p>今までだとSlack上で依頼精査し開発着手といった流れでしたが、この精査する段階で依頼が埋もれてしまうケースがあったため、依頼をいただいた場合はシステム部メンバーがTrelloに記載し精査することにしました。
ゆくゆくは、依頼者が直接プロジェクト管理ツールに記載し、開発に注力できればと考えています。
依頼数や内容の変化が大きいので可変に対応していくつもりです。</p>
<h2>配属〜現在まで働いて 振り返り</h2>
<h3>気持ちの変化を可視化し振り返り</h3>
<p>ナビシステム部に本配属されてから今年の3月までの各月の気持ちの変化についてグラフ化しました。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210317/20210317193310.png" alt="f:id:allabout-techblog:20210317193310p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>このグラフを基に振り返りを行いました。</p>
<p>7月〜本配属となり業務がスタートしました。
最初の二ヶ月に関しては自社サイトや社内<a class="keyword" href="http://d.hatena.ne.jp/keyword/CMS">CMS</a>の軽微な修正や改修を担当しました。
研修を終えて本格的に仕事ができる高揚感と小さい規模でもアウトプットが出せた時は非常に嬉しかったです。</p>
<p>しかしながら9月,10月と気持ちがやや下がり気味になりました。
自分の中で一番大きかったのは一人での作業時間が増え、リモートワークで一日ほとんど誰とも会話せず業務をすることが多々あったことです。
初めのうちは中々お互いの関係性を築くのに時間がかかってしまい、仕様の確認や質問を躊躇ってしまうことが多かったです。
私の性格上、相手は忙しくないかな?時間を割いてしまうのが申し訳ない、簡単な質問で相手を失望させないかなと疑心暗鬼になることが多かったです。
結果として、後々仕様が漏れていたり、開発スピードが遅くなっていました。
また気持ちの面でも、早くアウトプットしたいという気持ちと実際の進捗具合に大きな差が出て悪循環が生まれていました。</p>
<p>少し調べてわからないことや疑問はすぐ質問する。
後々になって疑問を残したままにしないことが重要だと感じ、この数ヶ月の期間を通してようやく自分の中に落とし込むことができました。
気軽に質問や相談にのって下さる先輩方に感謝感謝です🙏</p>
<p>年末から翌年1月にかけて段々とモチベーションが高くなっていきました。
エンジニア間で定期的に開催しているワークショップやLT会に発表あるいは参加する機会が多くなりました。
また他部署のエンジニアの方とLaravelを用いて自社内の勉強会等のイベントを管理するツールの作成に携わりました。
こういった機会が自分の中で抱えていたコミュニケーション不足の解消につながったのと同時に、少しずつですが技術的な知識が増えていきました。
また、実装に時間がかかっていたタスクがリリースできたことによる達成感や、社内ツールの大幅改修を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>で作業する時間はとても貴重でした。</p>
<p>2月は少し気持ちが下がり気味になってしまったのですが、この要因は私が作成したいくつかの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%C3%A5%C1%BD%E8%CD%FD">バッチ処理</a>が適切に動作していなかったことです。</p>
<p>対象のバッチは<a class="keyword" href="http://d.hatena.ne.jp/keyword/php">php</a>で動いており、以下のような処理をしています。</p>
<ul>
<li>DBに接続し、レコードから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>を用いて外部サイトのURLを抜き取る</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/cURL">cURL</a>関数を利用し、クエリパラメータにURLをつけて<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を叩く</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を叩いた時のレスポンス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%C6%A1%BC%A5%BF%A5%B9%A5%B3%A1%BC%A5%C9">ステータスコード</a>によってレコードの値書き換え</li>
</ul>
<p>今回のバッチが上手く動作しなかった原因は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>を用いて外部サイトのURLを抜き取る処理で捕捉できていなかったパターンがあり、URLを正しく取得できなかったことです。</p>
<p>適切に動作していなかったこともよくないですが、それ以前に必要なlogを残していなかったことが一番の失敗でした。
取得したURLが実際にどのような値かを記録できていなく、logに残してさえいればもう少し原因が早く見つかったと思い、後悔しました。</p>
<p>また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を叩いた時のレスポンスのボディ内容が大量にlogに残ってしまっていて、確認し辛い状況を作っていました。
<code>curl_exec()</code>でリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを送信時、オプションで指定しなければレスポンスのボディ内容が標準出力されます。こちらは不具合発覚前に修正しようと思いつつ、処理に直接関係ないからと後回しにしてしまい、他のタスクを優先してしまいました。</p>
<p>結果として大量の不要なlogがある、欲しかったlogがない状況から、バッチが上手く動作しない原因調査に時間がかかってしまいました。
当たり前のことですが、適切なlogを残す、不要なlogは大量に残してしまうと欲しい情報が埋もれてしまうため、きちんと整理することが重要だと感じました。</p>
<p>そして現在3月ですが、主に社内<a class="keyword" href="http://d.hatena.ne.jp/keyword/CMS">CMS</a>の改修や機能追加を編集業務をしている方と相談しながら進めております。
他部署から直接ご相談や現状のシステムの動きなどの疑問を多く頂けるようになったことが密かな喜びです😊
また、エンジニアではなく普段集計作業をしている方と一緒にGASを用いて集計作業の自動化を進めたり、勉強会も少しですが行うようになりました。</p>
<p>このコロナ禍でなかなかコミュニケーションが取り辛く関係性が希薄になりがちですが、着実に自分のできることを増やし信頼されるよう心がけたいと思います。</p>
<h2>最後に</h2>
<p>この一年を通じて一時間調べてわからないことはすぐに聞く、行き詰まったらすぐにアクションを起こすことが重要だと感じました。
ベテランエンジニアの方々は情報の共有が早く、わからなければすぐわかりそうな人に聞いたり、巻き込むのが上手だと日々の業務からわかりました。</p>
<p>エンジニアだけでなく仕事ができる方はきっとそうしてるはずです。
そして私自身誰かに頼るだけでなく、もっと力をつけていきたいと感じた一年でした。</p>
<p>今後も繋がりを大事に、また自分ができることを着実に増やし、いろんな方に頼りにされるよう努めます!</p>
<p>最後まで読んでいただきありがとうございました!</p>
allabout-techblog
【集計!】リモートワーク化での開発環境〜僕の私の最強のリモワ環境〜
hatenablog://entry/26006613686595972
2021-03-02T11:17:47+09:00
2021-03-02T11:17:47+09:00 はじめに 開発の@k_takeと申します。 フルリモートでの働き方が浸透してから1年が経とうとしています。 変動した環境に対応してきた皆さん。ベストなパフォーマンスを発揮するために行っている習慣や環境構築(物理)があるのではないでしょうか!? そんな好奇心から、社内でアンケート調査を行いました。 回答してくれたのは弊社の1~15年目までのエンジニア12名です。 ここではその回答をピックアップしながらいくつかご紹介したいと思います。 Q1. リモートワークのために環境面で変えたことはありますか? リモワになったにあたって、なにか変えたことがあるかをお聞きしました。 回答は以下の通り 回答者全員が…
<h1>はじめに</h1>
<p>開発の@k_takeと申します。
フルリモートでの働き方が浸透してから1年が経とうとしています。
変動した環境に対応してきた皆さん。ベストなパフォーマンスを発揮するために行っている習慣や環境構築(物理)があるのではないでしょうか!?</p>
<p>そんな好奇心から、社内でアンケート調査を行いました。
回答してくれたのは弊社の1~15年目までのエンジニア12名です。
ここではその回答をピックアップしながらいくつかご紹介したいと思います。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210222/20210222192725.png" alt="f:id:allabout-techblog:20210222192725p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h1>Q1. リモートワークのために環境面で変えたことはありますか?</h1>
<p>リモワになったにあたって、なにか変えたことがあるかをお聞きしました。
回答は以下の通り</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210203/20210203093648.png" alt="f:id:allabout-techblog:20210203093648p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>回答者全員が『環境面での変化あり』!これは期待値が高まります。</p>
<h1>Q2. リモートワークの中で、新しく導入したグッズがあれば教えて下さい</h1>
<p>実際に皆さんは何を導入したのでしょうか。結果はこちら!</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210203/20210203093530.png" alt="f:id:allabout-techblog:20210203093530p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<p>効果に関しても聞いてみましたので、ピックアップしていくつかご紹介します</p>
<h2>ディスプレイ系</h2>
<ul>
<li>やっぱり<a class="keyword" href="http://d.hatena.ne.jp/keyword/mac">mac</a>のディスプレイ1つだと開発しにくい、2つでちょうど良い</li>
<li>大きい画面のサブディスプレイを導入したことで画面の有効活用ができ、効率が上がりました</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iPad">iPad</a>を固定して、音声操作で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DD%A5%E2%A5%C9%A1%BC%A5%ED%A5%C6%A5%AF%A5%CB%A5%C3%A5%AF">ポモドーロテクニック</a>を実施しています。アラームやタイマーを使用する際に便利。
キーボードや画面から目を話さず作業できるのが楽</li>
</ul>
<p>自分のもっとも好みなサイズ、位置でディスプレイ配置ができるのは、やはり良いですね。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/iPad">iPad</a>&音声操作やEcho dotという回答もありましたが、周りを気にせず音声操作できるのもリモワならでは。</p>
<h2>キーボード系</h2>
<ul>
<li>キーボードを別で買ってディスプレイを遠くに置けて疲れにくい</li>
<li>定位置から手を動かすことが減ったので楽になった</li>
<li>HHKB→タイピング速度向上によりこころなしか開発スピードも向上した気がします</li>
</ul>
<p>弊社開発では<a class="keyword" href="http://d.hatena.ne.jp/keyword/MacBook%20Pro">MacBook Pro</a>を用いた開発を主でして、私目線ではオフィス業務の時代は付属キーボードを使用している開発者が多めの印象でしたがこれをきっかけに、キーボードも別で用意した方が多いようです。</p>
<h2>椅子系</h2>
<ul>
<li>PCスタンドで姿勢が良くなり疲れにくくなった</li>
<li>クッション、椅子 - 体の節々の痛みが治った。姿勢が良くなった</li>
<li>バックジョイ→腰痛で悩まされる、ということは今のところ無いです</li>
<li>家庭用のオフィス椅子で、長い時間座っていても居心地が良いです</li>
<li>もらった椅子が結構高いものなのか座りごごちが良くて疲れにくいのもいい</li>
</ul>
<p>節々の痛みが改善したコメントが多く見られる気がします😂 腰痛との戦いですね。ここに来て座る環境の大切さを再認識します。</p>
<p>ちなみに、弊社では、リモートワークの長期導入に伴い、社員の希望者に対して会社からオフィス用チェアを提供いただいた経緯がございます。
ありがたい福利厚生。。。実際 助けられたコメントも多く見受けられました。</p>
<h2>嗜好品</h2>
<ul>
<li>お菓子を買い込んでおけるので、朝、コンビニに行ってその日のテンションでお菓子を買って1日で食べて終わっていた頃より、自分がなんのお菓子を平均すると最も食べているのかが意識できるようになった。</li>
<li>ploom tech:室内で吸える、集中力切れた時に落ち着く</li>
</ul>
<p>嗜好品を自室で楽しんでいますね。健康にはお気をつけて。</p>
<h2>環境</h2>
<ul>
<li>仕事用に隔離環境をつくったところ、メリハリがついてやりやすくなりました</li>
<li>家でも仕事ができるという状態から、家で快適に仕事ができる状態になった</li>
<li>職場より快適に仕事ができている</li>
<li>仕事しやすくなった</li>
</ul>
<p>自分専用の環境構築ができ、喜びのコメントがいくつか。
家の空間が必要としている役割が増えていることも感じます。</p>
<h1>Q3. リモートワークのために習慣面で変えたことはありますか?</h1>
<p>次に習慣の面での変化に関してもお聞きました。</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210203/20210203093946.png" alt="f:id:allabout-techblog:20210203093946p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p>
<h1>Q4&Q5. 新しく導入した習慣とその効果</h1>
<pre class="code" data-lang="" data-unlink>Q4 リモートワークの中で、新しく導入した習慣があれば教えて下さい
Q5 新しく導入した習慣の効果を教えて下さい!</pre>
<p>実際の導入した習慣と、その効果について。いただいたコメントからピックアップしてご紹介します。</p>
<h2>散歩</h2>
<ul>
<li>通勤が唯一の運動だったのでその補填です。体が鈍るのが防げてる気がします。</li>
<li>思考の整理や効率的な休憩になった</li>
<li>体が軽くなった</li>
</ul>
<h2>ト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A1%BC%A5%CB%A5%F3">レーニン</a>グ</h2>
<pre class="code" data-lang="" data-unlink>筋トレ、ランニング、毎朝のロードバイクなど</pre>
<ul>
<li>12kg痩せた</li>
<li>気分のリフレッシュができて良い。</li>
<li>キックボクシングを始めた</li>
</ul>
<h2>チームでの仕事の進め方</h2>
<pre class="code" data-lang="" data-unlink>朝会、夕会、モブプロ・ペアプロの導入</pre>
<ul>
<li>リモートになり体調などの様子が分かりづらい状況から、朝会や夕会などで話すことでわかりやすくなった</li>
<li>進捗の報告よりも雑談も織り交ぜながら進めている</li>
</ul>
<h1>全体を通して</h1>
<p>ト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A1%BC%A5%CB%A5%F3">レーニン</a>グや、リフレッシュの習慣を取り入れている方が多く見受けられます。
やはり健康面は意識しますよね。今回のタイミングで生活を見直し、生活習慣が改善している方もいらっしゃいました。</p>
<p>また、周りの環境が見えづらい今だからこそ、双方から歩み寄るような業務上の工夫が見受けられました。
集中するための環境構築だけでなく、コミュニケーションを取る工夫も大切ですね。</p>
<h2>さいごに</h2>
<p>いかがでしたでしょうか。個人的なところですと、ほか開発者の『こだわりポイント』の一端を知ることができ、単純に楽しかったですし、参考になりました。</p>
<p>今後にも環境の変化があったとしても、今までの業務ハックは活かせる部分があるはずです。新しい試みをうまく組み合わせながら今後も開発に勤しみたいと思います。それではまた。</p>
allabout-techblog
2020年の年末LT会はオンラインで開催しました
hatenablog://entry/26006613682765276
2021-01-28T18:41:55+09:00
2021-01-28T18:41:55+09:00 はじめに こんにちは!オールアバウトナビ、システム部の@k_shiotaです。 昨年の年末、 2020年を締めくくるべく年末LT会を行いました。 基本リモートワークとなるため、当日はオンラインでの開催となりました。 今回はその様子をお伝えしたいと思います。
<h1>はじめに</h1>
<p>こんにちは!オールアバウトナビ、システム部の<a href="https://qiita.com/k_shiota">@k_shiota</a>です。</p>
<p>昨年の年末、 2020年を締めくくるべく年末LT会を行いました。<br />
基本リモートワークとなるため、当日はオンラインでの開催となりました。<br />
今回はその様子をお伝えしたいと思います。</p>
<h1>年末LT会とは</h1>
<p>年末LT会とは、毎年年末に開催されている、その年にあった出来事や技術・趣味に関することなどをライトに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>する会です。</p>
<p>一昨年から、全社的に行う方針となっています。</p>
<p>前回の開催についてはこちら↓</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fallabout-tech.hatenablog.com%2Fentry%2F2019%2F12%2F25%2F103000" title="今年も全社巻き込んだ年末LT大会を開催しました - オールアバウトTech Blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://allabout-tech.hatenablog.com/entry/2019/12/25/103000">allabout-tech.hatenablog.com</a></cite></p>
<h1>目的</h1>
<p>開催の目的は下記のように設定しました。</p>
<p>技術縛りをせず、みんなでとにかく発表して話すこと<br />
エンジニア同士や部署を横断した交流<br />
参加人数を記録して数字としても把握します。</p>
<p>また、「部署交流」を目的に、会社から<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%E4%BD%F5%B6%E2">補助金</a>が出ることとなり飲み食いしながら参加ができました。<br />
ありがたいですね☺️</p>
<h1>タイムテーブル</h1>
<p><figure class="figure-image figure-image-fotolife" title="当日のタイムスケジュール"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210125/20210125121003.png" alt="f:id:allabout-techblog:20210125121003p:plain" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>当日のタイムスケジュール</figcaption></figure></p>
<p>発表内容は技術関わらず、話したいこと全般をLT形式で発表してもらいます。<br />
今年の振り返り、気になることなどなどとにかくライトに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>する的な会です。<br />
持ち時間は5分、スライド 1枚から参加発表が可能です。</p>
<p>当日の発表は下記の内容でした。</p>
<pre class="code" data-lang="" data-unlink>- slackで発言しているのを取得して今何をやっているかわかるようにしてみた
- 2020年買ってよかったもの
- VRについてとおすすめ
- ヘルシーになるためにやったこと
- 美味しい唐揚げの作り方
- 今年読んだ本の紹介
- お酒の表現の考察
- M-1をデータから見てみた
- 在宅勤務の仲間紹介
- 2020年の人生初なこと
- 2020年slackの絵文字について調査した(ランキング形式)
- NiziUのこと(飛び入り参加)</pre>
<p><figure class="figure-image figure-image-fotolife" title="以前よりヘルシーになっていたり"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210125/20210125122731.png" alt="f:id:allabout-techblog:20210125122731p:plain" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>以前よりヘルシーになっていたり</figcaption></figure></p>
<p><figure class="figure-image figure-image-fotolife" title="買ってよかったものを紹介したり"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210125/20210125122835.png" alt="f:id:allabout-techblog:20210125122835p:plain" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>買ってよかったものを紹介したり</figcaption></figure></p>
<p><figure class="figure-image figure-image-fotolife" title="唐揚げのレシピを紹介したり"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20210125/20210125122912.png" alt="f:id:allabout-techblog:20210125122912p:plain" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>唐揚げのレシピを紹介したり</figcaption></figure></p>
<h1>感想</h1>
<p>個人的には在宅勤務の状況が反映された発表内容になっているなぁと感じました。</p>
<p>どうやってコミュニケーションを取ろうか模索していたり<br />
在宅勤務でどう快適に仕事をするかや<br />
座りっぱなしになるので運動不足を解消する活動をしていたり<br />
はたまた、美味しい唐揚げを作って<a class="keyword" href="http://d.hatena.ne.jp/keyword/QOL">QOL</a>を上げたり<br />
人それぞれの時間の使い方を知れてとても有意義な時間になりました。</p>
<p>最後に飛び入り参加でNiziUのことを話してくれた人事の<a href="https://corp.allabout.co.jp/recruit/staff/backoffice/waiwai.html">ワイワイ</a>は
準備無しで発表してくれました🎉<br />
ありがとう😁</p>
<p>この発表を聞いてみたいということがありましたら、ぜひ遊びに来てください😄</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcorp.allabout.co.jp%2Frecruit%2F" title="オールアバウトグループのコーポレートサイト – 採用情報" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://corp.allabout.co.jp/recruit/">corp.allabout.co.jp</a></cite></p>
<h1>まとめ</h1>
<p>初めてのオンライン開催となり、人数が集まるかなーと少し不安でしたが結果27名もの方が参加いただき、エンジニア同士や部署を横断した交流ができたのではないかと思います。</p>
<p>オンライン開催は移動時間がなかったり、出入り自由で参加しやすい会になったかなと感じています。<br />
コロナが収束し安心して出勤できるようになったら同じ場所に集まってやりたいですね。</p>
<p>本年もよろしくお願いいたします🎍</p>
allabout-techblog
2020年に開催した社内ワークショップまとめ
hatenablog://entry/26006613668911242
2020-12-25T11:43:00+09:00
2020-12-25T11:43:00+09:00 この記事は、All About Group(株式会社オールアバウト) Advent Calendar 2020 17日目の記事です(大遅刻申し訳ありません!) @amymdです。そろそろ2020年も終わりに近づいてきましたね。 今年は新型コロナの影響でリモートワーク中心の働き方に変わった一年になりましたが、定期的に開催しているエンジニア向けワークショップもリモートで開催されるようになりました。そこで、今年社内で開催されたワークショップについてまとめて報告したいと思います! 1.新しくなった開発環境とこれから 2.今回のコロナ対策とそこから見えてきたもの 3.チームごとの振り返り 4.オールアバ…
<p>この記事は、<a href="https://qiita.com/advent-calendar/2020/allabout">All About Group(株式会社オールアバウト) Advent Calendar 2020</a> 17日目の記事です(大遅刻申し訳ありません!)</p>
<p><a href="https://qiita.com/amymd">@amymd</a>です。そろそろ2020年も終わりに近づいてきましたね。<br />
今年は新型コロナの影響でリモートワーク中心の働き方に変わった一年になりましたが、定期的に開催しているエンジニア向けワークショップもリモートで開催されるようになりました。そこで、今年社内で開催されたワークショップについてまとめて報告したいと思います!</p>
<ul class="table-of-contents">
<li><a href="#1新しくなった開発環境とこれから">1.新しくなった開発環境とこれから</a></li>
<li><a href="#2今回のコロナ対策とそこから見えてきたもの">2.今回のコロナ対策とそこから見えてきたもの</a></li>
<li><a href="#3チームごとの振り返り">3.チームごとの振り返り</a></li>
<li><a href="#4オールアバウトのネットワーク構成">4.オールアバウトのネットワーク構成</a></li>
<li><a href="#5最近何やってるのLT">5.「最近何やってるの?」LT</a></li>
<li><a href="#6データポータル見せ合う会">6.データポータル見せ合う会</a></li>
<li><a href="#最後に">最後に</a></li>
</ul>
<h1 id="1新しくなった開発環境とこれから">1.新しくなった開発環境とこれから</h1>
<p>内容:SREグループより社内の開発環境が変わったため、その内容について説明</p>
<p>オールアバウトではメインのインフラとして<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud Platform)を採用しており、その開発環境用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>プロジェクトについて、SREグループにより改めて運用ルールや権限などの整理を行ったため、それを共有するという目的で実施されました。</p>
<p>「本番で利用しているツール等はデプロイしない」「いつ消されても良い大丈夫な状態にする」等の運用ルールについて改めて共有されました。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>の開発環境を利用することで気軽に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>のサービスを検証できるというメリットはあるのですが、気軽に検証できる分コストの管理やセキュリティなど意識すべき点もあるため、あらためてみんなの認識を共有する場となりました。</p>
<p>また、社内にあるサーバーで構築された開発環境についてもSREグループにより新しく構築したため、その環境についても共有されました。</p>
<h1 id="2今回のコロナ対策とそこから見えてきたもの">2.今回のコロナ対策とそこから見えてきたもの</h1>
<p>内容:コロナ禍の対応と今後について</p>
<p>普段より労働環境を整えてくれている情シスから、今回のコロナ禍の対応と今後についてお話していただきました。</p>
<p>以下は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B8%A5%A7%A5%F3%A5%C0">アジェンダ</a>です。</p>
<ul>
<li>ドタバタなコロナ対策</li>
<li>情シス業務の変化</li>
<li>変化の中で見えてきたもの</li>
<li>今後の計画</li>
<li>最後に</li>
</ul>
<p>こちらの内容については以下の記事で詳しく紹介しているので、興味がある方はぜひご一読ください!</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fallabout-tech.hatenablog.com%2Fentry%2F2020%2F09%2F28%2F134418" title="コロナ禍での情シスの対応とそこから見えたもの - オールアバウトTech Blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://allabout-tech.hatenablog.com/entry/2020/09/28/134418">allabout-tech.hatenablog.com</a></cite></p>
<h1 id="3チームごとの振り返り">3.チームごとの振り返り</h1>
<p>内容:「振り返り」の目的や方法についてチームの垣根を超えてディスカッション</p>
<p>このワークショップでは誰かが登壇して話を聞くスタイルではなく、Zoomの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D6%A5%EC%A5%A4%A5%AF%A5%A2%A5%A6%A5%C8">ブレイクアウト</a>ルーム機能を使用し、普段行っている「振り返り」についてディスカッション形式でお話しました。</p>
<p>以下は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B8%A5%A7%A5%F3%A5%C0">アジェンダ</a>です。</p>
<ul>
<li>挨拶(3分)</li>
<li>普段の業務で一緒じゃないメンバー同士でグループを作成(3-4名)(5分)</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D6%A5%EC%A5%A4%A5%AF%A5%A2%A5%A6%A5%C8">ブレイクアウト</a>ルームに分割(5分)</li>
<li>普段の「振り返り」の目的や方法を各自3-5分程度で共有(15分)</li>
<li>それぞれの「振り返り」に対しての質疑応答や「振り返り」で悩んでいることなどを相談(15分)</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D6%A5%EC%A5%A4%A5%AF%A5%A2%A5%A6%A5%C8">ブレイクアウト</a>ルームを解散し、メインルームにてグループ毎にディスカッション内容を共有(10分)</li>
<li>連絡事項などの共有(2分)</li>
</ul>
<p>リモートでの多人数ディスカッションということで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B8%A5%A7%A5%F3%A5%C0">アジェンダ</a>や進行もそれを考慮したものとになっています。</p>
<h1 id="4オールアバウトのネットワーク構成">4.オールアバウトのネットワーク構成</h1>
<p>内容:allabout.co.jp<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>へのリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト経路、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Akamai">Akamai</a> Site Shieldを使っているシステムの経路について</p>
<p>SREグループのメンバーより、ネットワーク構成についての共有会が行われました。<br />
アプリケーション開発に携わるエンジニアがネットワーク構成を知ることで、</p>
<ul>
<li>障害時の問題切り分けが可能</li>
<li>システム設計にも役立つ</li>
</ul>
<p>のようなメリットがあることから、今回実施されました。</p>
<p>実際にallabout.co.jp<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>へのリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト経路がどうなっているのか、詳細な紹介はここでは省略させていただきますが…。<br />
All Aboutサイトでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Akamai">Akamai</a>を利用した<a class="keyword" href="http://d.hatena.ne.jp/keyword/CDN">CDN</a>キャッシュや、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Akamai">Akamai</a> WAPによるセキュリティ対策などを行っています。<br />
また、オールアバウトが提供しているPrimeAdというコンテンツ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>プラットフォームサービスの管理画面では、 <a href="https://www.akamai.com/jp/ja/products/security/site-shield.jsp">Akamai Site Shield</a>を利用したオリジン保護や<a href="https://cloud.google.com/armor?hl=ja">Cloud Armor</a>などによるアクセス制御などを行っています。</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fprimead.jp%2F" title="All About PrimeAd(プライムアド) - ビジネスマッチングプラットフォーム" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://primead.jp/">primead.jp</a></cite></p>
<h1 id="5最近何やってるのLT">5.「最近何やってるの?」LT</h1>
<p>内容:各グループのエンジニアの近況報告LT会</p>
<p>各グループ会社に所属しているエンジニアより、どんな業務を行っているのか報告するLT会を実施しました。 <br />
日々の業務内容や、どんな技術を使っているのかの紹介を行いました。</p>
<p>主な話題としては、以下の通りです!</p>
<ul>
<li>最近実装したシステムで利用している<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>の紹介</li>
<li>チームビルディングの手法について</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/CakePHP">CakePHP</a>→Laravel化の相談</li>
<li>プロジェクトで学んだこと</li>
</ul>
<h1 id="6データポータル見せ合う会">6.データポータル見せ合う会</h1>
<p>内容:「最強のデータポータル作ってみた!」や「これからこんなレポート作ろうと思ってます」、「この機能めっちゃ便利」などざっくばらんに話します!</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>が提供しているデータ視覚化ツールである<a href="https://marketingplatform.google.com/intl/ja/about/data-studio/">データポータル</a>が社内でも使われ始めていたため、その知見を集約すべく実施されました。</p>
<p>実際にデータポータルで作成した画面を見せつつ、こんな機能を使ってこんなグラフを作ったなど、他のチームにも流用できるような様々な知見について共有し合いました。</p>
<h1 id="最後に">最後に</h1>
<p>2020年も大変お世話になりました。<br />
おそらく今後も社内ワークショップはオンラインでの開催になりそうですね。ただ、オフラインでの接点が減ってしまったこの状況だからこそ、このような横断的なエンジニアの繋がりが重要になってくるのではないかと思っております。<br />
2021年も定期的な社内ワークショップの開催を実施していきたいと思いますので、よろしくお願いいたします。</p>
allabout-techblog
初のフルリモート体制で新卒が素直に書く! ~新卒でオールアバウトナビに配属されて~
hatenablog://entry/26006613662270174
2020-12-18T18:41:17+09:00
2020-12-18T18:41:17+09:00 はじめに こんにちは!オールアバウトナビ(以下からナビで省略します)システム部に新卒入社した@monpeiです。 今年就職された方は同年代のエンジニアがどんなことをやっているか気になりませんか?また、来年就職される方や現在就職活動中の方、来年からの仕事に不安を感じていませんか? 私は入社前福島にある大学に通っていましたが、東京で一人暮らしをすることが決まり、不安と期待が高まっていました。 しかし4月からフルリモートの社会人生活のスタートが近づくにつれ、不安の方が強く感じるようになりました。 「どんな社員がいるんだろう?」、「コミュニケーション取れるのかな?」、「業務について行けるかな?」など頭…
<h2>はじめに</h2>
<p>こんにちは!オールアバウトナビ(以下からナビで省略します)システム部に新卒入社した@monpeiです。</p>
<p>今年就職された方は同年代のエンジニアがどんなことをやっているか気になりませんか?また、来年就職される方や現在就職活動中の方、来年からの仕事に不安を感じていませんか?</p>
<p>私は入社前福島にある大学に通っていましたが、東京で一人暮らしをすることが決まり、不安と期待が高まっていました。
しかし4月からフルリモートの社会人生活のスタートが近づくにつれ、不安の方が強く感じるようになりました。
「どんな社員がいるんだろう?」、「コミュニケーション取れるのかな?」、「業務について行けるかな?」など頭を過ぎっていました。</p>
<p>今回は本配属から半年を経てどのような業務をしたか、コミュニケーション不足・モチベーション低下の解消のためにやっていることについてお話します。少しでも共感する部分があったり、不安を抱えている方が少しでも解消いただける内容になっていれば幸いです。</p>
<p>ベテランの方でも「新卒って何考えてるんだろう〜?」位な感じで読んで頂ければと思います。</p>
<p>ナビの詳細は下記のリンクからご確認いただけます。
<iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.allaboutnavi.co.jp" title="All About Navi" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://www.allaboutnavi.co.jp">www.allaboutnavi.co.jp</a></cite></p>
<h2>4月から現在までのやったこと</h2>
<h3>4~6月末 研修</h3>
<p>主にgitや社内で使用している言語や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>などについて学びました。</p>
<p>下記リンクから新卒研修の詳細が確認できますので、ご興味ある方はご一読ください。
<iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fabout.allabout.co.jp%2Fkoto%2F200918_01" title="オンラインの壁を越える! オールアバウト初のエンジニア向けフルリモート研修を紹介" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://about.allabout.co.jp/koto/200918_01">about.allabout.co.jp</a></cite></p>
<h3>ナビに本配属、業務スタート</h3>
<h3>7月〜8月初旬</h3>
<p>配属されて初の作業は、ローカル環境で開発を進めらるようにDocker環境の構築をしました。
続いてDocker環境構築後に、弊社のウェブサイトや<a class="keyword" href="http://d.hatena.ne.jp/keyword/cms">cms</a>の軽微な修正や機能追加、広告のタグ差し替えなどを行いました。
修正の内容はサイトから一部リンクを削除と新しいリンクにリダイレクトするというとても簡単なものでしたが、初リリースができた時は非常に嬉しかったです。</p>
<h3>8月中旬〜10月初旬</h3>
<p>業務にも段々と慣れ始め、任されるタスクも少しずつですがレベルが上がってきました。
以下のようなプログラムを作成しました。</p>
<ul>
<li>GKE上で動く<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%C3%A5%C1%BD%E8%CD%FD">バッチ処理</a>(CronJob)で定期的にデータベースのレコードに変更を加える</li>
<li>自動で毎日決まった時刻にCloud Functionsを実行し、Node.jsを用いて集計対象のサイトへ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EC%A5%A4%A5%D4%A5%F3%A5%B0">スクレイピング</a>をかけ、取得したデータをレポートとして<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%D7%A5%EC%A5%C3%A5%C9%A5%B7%A1%BC%A5%C8">スプレッドシート</a>に書き込む。</li>
</ul>
<h3>10月中旬〜現在</h3>
<p>主なトピックとしては使用している<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>をLaravelに変更するため動いています。
また開発ではありませんが、Team Tech Ballというエンジニアのためのエンジニア主導の組織横断チームに加入しました。</p>
<h2>今までの振り返り</h2>
<h3>業務で実装した集計の自動化の話</h3>
<h4>背景</h4>
<p>では続いて私が業務で実装した集計の自動化の話です。
弊社サービスの一つである<a class="keyword" href="http://d.hatena.ne.jp/keyword/citrus">citrus</a>は外部ニュースサイトにもフィードを行っており、そのフィード先での記事のタイトルやpv数などのデータを集計する作業がありました。
一回の集計作業にかかる時間はさほどかかりませんが、毎日行う必要があり長い目で見ると時間がかかるため、集計の自動化をすることになりました。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/citrus">citrus</a>の詳細は下記リンクからご確認いただけます。
<iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcitrus-net.jp%2F" title="カジュアルに知性をアップデート - citrus(シトラス)" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://citrus-net.jp/">citrus-net.jp</a></cite></p>
<h4>実装内容</h4>
<p>以下今回のタスクの条件です。</p>
<ol>
<li>毎朝指定の時間に処理を実行する</li>
<li>フィード先の管理画面(集計するデータが閲覧できる)にログインし、データを取得する</li>
<li>取得したデータを集計専用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%D7%A5%EC%A5%C3%A5%C9%A5%B7%A1%BC%A5%C8">スプレッドシート</a>に追加する</li>
</ol>
<p>上記の条件を実装する方法はいくつか考えられましたが、今回は下記のような実装を行いました。</p>
<p><figure class="figure-image figure-image-fotolife" title="集計自動化のフロー"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20201214/20201214092059.png" alt="f:id:allabout-techblog:20201214092059p:plain" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>集計自動化のフロー</figcaption></figure></p>
<p>ナビでは集計の自動化でCloud FunctionsとNode.js + Puppeteerで動いているプログラムがあり、その前例が役立つと考え、これらの技術を選定しました。また、私自身がCloud FunctionsやNode.jsはほとんど使用したことがないことから、自分の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AD%A5%EB%A5%A2%A5%C3%A5%D7">スキルアップ</a>にも繋がり、ありがたかったです。</p>
<p>流れとしてはCloud SchedulerがCloud Pub/Subを介してCloud Functionsを起動させます。
次にCloud Functionsがフィード先の管理画面にログインし、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EC%A5%A4%A5%D4%A5%F3%A5%B0">スクレイピング</a>をかけデータを取得します。
最後に取得したデータをCloud Functionsを用いて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%D7%A5%EC%A5%C3%A5%C9%A5%B7%A1%BC%A5%C8">スプレッドシート</a>に追加し処理が終了します。
Cloud FunctionsはNode.jsで動いており、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EC%A5%A4%A5%D4%A5%F3%A5%B0">スクレイピング</a>はPuppeteerというライブラリを用いています。</p>
<p>Cloud Scheduler</p>
<p><a href="https://cloud.google.com/scheduler/docs/quickstart">https://cloud.google.com/scheduler/docs/quickstart</a></p>
<p>Pub/Sub トリガーのCloud Functions</p>
<p><a href="https://cloud.google.com/functions/docs/calling/pubsub?hl=ja">https://cloud.google.com/functions/docs/calling/pubsub?hl=ja</a></p>
<p>Puppeteer</p>
<p><a href="https://github.com/puppeteer/puppeteer">https://github.com/puppeteer/puppeteer</a></p>
<h4>所感</h4>
<p>使用した技術はどれも初めて使うものだったので調査や慣れるのに少し手こずりましたが、自分が知らなかった技術を学ぶことができ、自分が開発で使える選択肢を増やすことができました。
Cloud Functionsはサーバレス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>のため、サーバーを立てる処理がいらないことが非常に便利だと感じました。</p>
<p>また、自動集計の実装後に社員から「業務効率が上がった」、「ありがとう」などと言ってもらうことができ、非常に嬉しく思いました。</p>
<h3>フルリモートの環境に慣れるまで</h3>
<h4>コミュニケーションが取りづらい、自宅作業でモチベーションが上がらない時が多々あった</h4>
<p>今年はコロナの影響を受けて働き方に大きな変化があった年だと思います。
リモートワークは一長一短かと思いますが、私はコミュニケーションのとりずらさに戸惑いを感じたり、思っていたよりも他の社員との関わりが少なかったことから不安を感じたりしました。
また在宅で仕事へのモチベーションの維持が難しかったり等、慣れるまで少し時間がかかりました。
特に私と同様に今年新卒の方であれば共感していただける部分があるのではと思います。
自分なりにどうやって、コミュニケーション不足を解消したか、また仕事へのモチベーションを上げた取組をいくつか紹介したいと思います。</p>
<h4>コミュニケーション不足解消、モチベーションを維持するためにやったこと</h4>
<ul>
<li>Team Tech Ballに加入した</li>
<li>自分の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>を見つけた</li>
</ul>
<p>前述で触れましたが10月にTeam Tech Ballというエンジニアのためのエンジニア主導の組織横断チームに加入しました。
Team Tech Ballに関しては下記の記事に詳細が記載されています。よろしければ合わせてお読みください。
<iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fallabout-tech.hatenablog.com%2Fentry%2F2017%2F12%2F01%2F063000" title="技術推進ユニットのこれまでとこれから - オールアバウトTech Blog" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://allabout-tech.hatenablog.com/entry/2017/12/01/063000">allabout-tech.hatenablog.com</a></cite>
加入を決めた理由は沢山あるのですが、決め手になったのは二つです。
一つ目は現在ナビのエンジニアは私含め二人しかおらず、エンジニアとの接点が少ないことです。
加入することで、他のグループ会社のエンジニアと関わってコミュニケーションをとりたい、技術的に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AD%A5%EB%A5%A2%A5%C3%A5%D7">スキルアップ</a>してできることを増やしたいと強く感じました。</p>
<p>二つ目は、自分が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>にしていた方がTeam Tech Ballに所属していたためです。
私は最新の技術を突き詰めることよりも、自分の仕事や作ったもので誰かが喜んでくれたり、感謝してもらえるようなエンジニアでありたいと考えています。
<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>にした方は、リーダーシップがあり、マネジメント能力が高く、常に誰にでも親切な方です。
「10年後あの人みたいになりたい!少しでも近づきたい!」と思える人と一緒に仕事をすることでモチベーションが上がりました。
まだまだその方に追いつくには技術的にも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%CD%B4%D6%CE%CF">人間力</a>的にも先が遠いので精進したいと思います!</p>
<p>現在はナビの業務とは別に、Team Tech Ballの活動の一貫で、社内のエンジニアの勉強・交流会の企画や、自社内の勉強会などのイベントを管理するツールの作成を行っております。
中々はじめは業務上関わる人が少なくコミュニケーションが取りづらいと、もやもやしておりました。
自分から新しいことにチャレンジする、新しい環境に飛び込むことで、以前より仕事への充実感が増してきたのを感じています。</p>
<p>新しいことや環境にチャレンジしたり、飛び込むことは勇気がいることですが、それをしなくてはいけない環境に身をおいてしまえば、案外何とかなることが多い気がしております。
こんな時期こそチャレンジ精神を忘れずにがむしゃらに突き進んで行きたいと思います!</p>
<h4>ナビシステム部内での取組</h4>
<p>続いてナビシステム部内で毎日行っている朝会についてお話します。
ナビのシステム部内では上期の途中から他の開発部署の取組や業務の仕方を積極的に取り入れ、日々業務の仕方を改善しております。
その中でも、上期の終わりくらいから朝会を導入したのですが、私のモチベーションを上げた要因の一つでしたのでご紹介できればと思います。</p>
<p>以前ナビでは業務終了前の夕会しか行っておらず、話す内容も進捗度合いの報告がメインで、どこに悩んでいたのか、悩み中なのか等を共有する時間を設けてはいませんでした。
私の部署の先輩方は非常に優しく、質問や相談をしやすい環境にはあったものの、リモワの場合相手がどんな状況にあるかが把握しずらく質問や相談をするハードルが高いと感じておりました。
そんな中、上期の途中から毎日業務開始後すぐの15分位を使って朝会を始めました。
朝会を通してその日やることの共有と、前日やったことをjamboardを使って簡単なモチベーショングラフを書き、共有を行っています。</p>
<p>以前よりどこに悩んでいたのか、悩み中なのかが共有しやすくなり、話すことで自分だけで抱え込まずにすむため気持ちが楽になりました。またメンバーの状況もよく把握できるようになりました。他のメンバーがどのくらいのタスクがあって、どこに悩んでいるのかなどの状態も把握しやすくなり、「〇〇さんのタスク僕が巻き取ります!」などが言いやすくなりました。</p>
<p>また朝会ではありませんが、金曜日に行っている振り返りでは、技術の話だけでなく雑談を交えながら次週チャレンジすることを話しています。
このような取組をきっかけに、メンバーとの距離感もわかってきて質問や相談が非常にしやすくなりました。
ぜひコミュニケーションが不足していると感じたチームは朝会を導入してみてはいかがでしょうか?</p>
<h2>最後に</h2>
<p>本配属から半年を経て私が大事だと感じたことは大きく二つあります。</p>
<p>一つは日々の業務を流れ作業にしないことです。
業務を覚える、できることが増えるようになることは良いことですが、その反面慣れも出てきてミスをする恐れもあるということを学びました。
月に一度は自分を見直す時間を設け、できるようになったことと、慣れが出てきた部分を洗い出してみようと思います。</p>
<p>二つ目はコミュニケーションは大事だということです。
当たり前のことを書いておりますが実体験として、コミュニケーションが不足すると、長い目で見たときに実装の進捗具合に遅れがでたり、モチベーションの低下に繋がることを実感しました。
リモートワークでもコミュニケーション不足にならないようにしながら、リモートワークだからこそできる仕事の仕方を模索したいと思います。</p>
<p>最後まで読んでいただきありがとうございました。少しでも皆様のお役に立てる記事になっていれば幸いです。</p>
allabout-techblog
golangでCloud Monitoringのデータを元に稼働率を取得するようにした話
hatenablog://entry/26006613645308542
2020-10-30T14:49:42+09:00
2020-10-30T14:49:42+09:00 こんにちは!オールアバウト SREGの@y_hideshi です。 今回はGCPのモニタリングサービスであるCloud Monitoringのデータを元に稼働率を取得するようにした話をしたいと思います。 背景 オールアバウトでは、Cloud MonitoringのUptimeCheckという機能を利用してURL監視やサービスの稼働率をチェックしています。 Cloud Monitoring:UptimeCheckの画面 上記の画像にある通り、URL単位で稼働率を画面上から確認することができます。ただ、UptimeCheck数が多くなると、各画面に遷移して稼働率を確認するのは大変になります。 その…
<p>こんにちは!オールアバウト <a class="keyword" href="http://d.hatena.ne.jp/keyword/SREG">SREG</a>の<a href="https://qiita.com/y_hideshi">@y_hideshi</a> です。</p>
<p>今回は<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>のモニタリングサービスである<a href="https://cloud.google.com/monitoring?hl=ja">Cloud Monitoring</a>のデータを元に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を取得するようにした話をしたいと思います。</p>
<h2>背景</h2>
<p>オールアバウトでは、Cloud MonitoringのUptimeCheckという機能を利用してURL監視やサービスの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>をチェックしています。</p>
<p><figure class="figure-image figure-image-fotolife" title="Cloud Monitoring:UptimeCheckの画面"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20201026/20201026114142.png" alt="f:id:allabout-techblog:20201026114142p:plain" title="f:id:allabout-techblog:20201026114142p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Cloud Monitoring:UptimeCheckの画面</figcaption></figure></p>
<p>上記の画像にある通り、URL単位で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を画面上から確認することができます。ただ、UptimeCheck数が多くなると、各画面に遷移して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を確認するのは大変になります。</p>
<p>そのため、このチェックを自動化しようというのが今回<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を自動取得しようとした背景です。</p>
<p>Cloud Monitoringのデータ取得はCloud Monitoring <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>経由で取得することができ、Cloud Monitoring <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を扱う場合は<a class="keyword" href="http://d.hatena.ne.jp/keyword/golang">golang</a>で便利なパッケージが提供されているので今回はそちらを使用します。</p>
<h2>実装について</h2>
<p>それでは早速どのようなコードになっているか紹介したいと思うのですが、その前にUptimeCheckとCloud Monitoringのデータについて簡単に説明します。</p>
<h3>UptimeCheckとCloud Monitoringデータについて</h3>
<p>UptimeCheckでは、特定のURLに対してステータスチェックやレスポンスタイムをチェックすることができます。
リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トは様々なロケーションから送ることができ、各ロケーションのリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トから取得できたデータはCloud Monitoringに指標データ(時系列データ)として蓄積されます。
この時蓄積されるデータは6週間しか保持されません。<a href="https://cloud.google.com/monitoring/quotas?hl=ja">参考リンク</a></p>
<p><figure class="figure-image figure-image-fotolife" title="UptimeCheckの設定一覧"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20201030/20201030125532.png" alt="f:id:allabout-techblog:20201030125532p:plain" title="f:id:allabout-techblog:20201030125532p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>UptimeCheckの設定一覧</figcaption></figure></p>
<p>上述したCloud Monitoringのデータは、特定のタイムスタンプにおけるステータスチェックが通ったか通らなかったかの時系列データを持っています。
そのため、一ヶ月分の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を取得する際は各ロケーションごとの時系列データを取得し、自前で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を求める計算をする必要があります。</p>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>の求め方</h3>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>の求め方については<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>のサポートに問い合わせしたところ「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>の求め方については詳しくお答えすることができない」とのことだったので、計算方法を自分たちで考えWebコンソールで表示される値(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>さんが算出したか<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>)になるべく近づけるようにしました。</p>
<p>私が設定した<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>の求め方(計算方法)は下記の通りです。</p>
<ol>
<li>1分間に取得されたCloud Monitoring時系列データのうち、最後のデータをチェックデータとして集計
<ul>
<li> 1分間に6回チェックが走っていた場合、最後のチェック結果だけをデータとして利用するということです。</li>
</ul>
</li>
<li>チェック回数とチェックが通った回数を集計し、各ロケーションごとの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を求める
<ul>
<li> <code>ロケーションごとの稼働率 = チェックが通った回数 / チェック回数</code></li>
</ul>
</li>
<li><code>稼働率 = 各ロケーションごとの稼働率の総和 / ロケーション数</code>として算出</li>
</ol>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a></h3>
<p>ではコードと一緒に説明していきます。今回は記事用にサンプルとして「特定のUptimeCheckのデータをもとに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を求める」コードを用意しました。</p>
<p>まず、全体のコードを記載し各要素の説明をしていきます。</p>
<p>ざっくりな流れとしては下記の通りです。</p>
<ol>
<li>環境情報の設定</li>
<li>Cloud Monitoring <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を実行するため、必要なリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トパラメータの設定</li>
<li>各ロケーションごとの時系列データ取得 & ロケーションごとの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を算出</li>
<li>全体の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を算出</li>
</ol>
<pre class="code golang" data-lang="golang" data-unlink>import (
"context"
"log"
"os"
"time"
monitoring "cloud.google.com/go/monitoring/apiv3"
"github.com/golang/protobuf/ptypes/duration"
"github.com/golang/protobuf/ptypes/timestamp"
"google.golang.org/api/iterator"
monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
)
func main() {
// 1. 環境情報の設定
// UptimeCheckがあるプロジェクト
projectNum := os.Getenv("GCP_PROJECT_NUM")
// UptimeCheckのID
uptimeCheckID := os.Getenv("UPTIME_CHECK_ID")
// 2. Cloud Monitoring APIを実行するため、必要なリクエストパラメータの設定
ctx := context.Background()
client, err := monitoring.NewMetricClient(ctx)
if err != nil {
log.Fatal("could not generate NewUptimeCheckClient: %v", err)
}
defer client.Close()
// 取得するデータの期間を定義
endTime := time.Date(2020, 10, 23, 0, 0, 0, 0, time.Local)
startTime := time.Date(2020, 8, 1, 0, 0, 0, 0, time.Local)
// どのメトリクスデータを取得するか定義する
// 今回はURL監視を行っている特定のUptimeCheckのデータを取得するため、下記のように定義する
filter := `metric.type="monitoring.googleapis.com/uptime_check/check_passed" AND resource.type = "uptime_url" AND metric.labels.check_id = "` + uptimeCheckID + `"`
req := &monitoringpb.ListTimeSeriesRequest{
Name: "projects/" + projectNum,
Filter: filter,
Interval: &monitoringpb.TimeInterval{
StartTime: &timestamp.Timestamp{
Seconds: startTime.Unix(),
},
EndTime: &timestamp.Timestamp{
Seconds: endTime.Unix(),
},
},
// 基本的にGCPのWebコンソールを参考に設定
Aggregation: &monitoringpb.Aggregation{
// 各アライメント区間の最後のデータ・ポイントを当該区間の値として採用
// MonitoringのWebコンソールでは1ケ月の稼働率取得時、3時間ごとのcheckk passの最後の値を利用して稼働率を計算している
PerSeriesAligner: monitoringpb.Aggregation_ALIGN_NEXT_OLDER,
AlignmentPeriod: &duration.Duration{
Seconds: 60, // 1m
},
},
View: monitoringpb.ListTimeSeriesRequest_FULL,
}
// 3. 各ロケーションごとの時系列データ取得 & ロケーションごとの稼働率を算出
// TimeSeriresデータを取得する
it := client.ListTimeSeries(ctx, req)
var PercentUptimeSum, uptimeCheckCount float64
for {
resp, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatal("could not read time series value: %v", err)
}
log.Println("ロケーション:", resp.Metric.Labels["checker_location"], "のデータチェック開始")
points := resp.GetPoints()
// Aggregation_ALIGN_NEXT_OLDERの場合、スライスの長さ=最大チェックパス数である
maxCheckPassCount := int64(len(points))
var checkPassCount int64
for _, point := range points {
log.Println(point.GetInterval().GetStartTime().AsTime())
if point.GetValue().GetBoolValue() == true {
checkPassCount++
}
}
locationPercentUptime := float64(checkPassCount) / float64(maxCheckPassCount)
PercentUptimeSum += locationPercentUptime
uptimeCheckCount++
}
// 4. 全体の稼働率を算出
result := PercentUptimeSum / uptimeCheckCount
log.Println("Percent Uptime: ", result)
}</pre>
<p>それでは、各ブロックごとに説明していきます。</p>
<h3>環境情報の設定</h3>
<p>ここでは、UptimeCheckが存在する<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>のプロジェクトIDやチェック対象のUptimeCheckIDを変数として定義しています。
後々、<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>実行時のリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トパラメータを設定する際に必要になってくるため、初期の段階で定義しておきました。</p>
<pre class="code golang" data-lang="golang" data-unlink> // 1. 環境情報の設定
// UptimeCheckがあるプロジェクト
projectNum := os.Getenv("GCP_PROJECT_NUM")
// UptimeCheckのID
uptimeCheckID := os.Getenv("UPTIME_CHECK_ID")</pre>
<h3>Cloud Monitoring <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を実行するため、必要なリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トパラメータの設定</h3>
<p>今回お話しする中ではここが一番重要です。
新しくCloud Monitoring用のClientを作成しているところは割愛して、そのあとのコードについてお話ししていきます。</p>
<p>ここでは、まず取得するデータの期間を定義しています。リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トパラメータを設定する際に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Unix">Unix</a>タイムスタンプで渡す必要があるので、timeパッケージを使ってデータを用意します。</p>
<pre class="code golang" data-lang="golang" data-unlink> // 取得するデータの期間を定義
endTime := time.Date(2020, 10, 1, 0, 0, 0, 0, time.Local)
startTime := time.Date(2020, 9, 1, 0, 0, 0, 0, time.Local)</pre>
<p>取得するデータを絞り込むため、下記の要素で絞り込みを行います。</p>
<ul>
<li>UptimeCheckのデータを取得したいのでUptimeCheck用メトリクスタイプを指定</li>
<li>取得対象UptimeCheckのIDを指定</li>
<li>リソースタイプはURLチェック</li>
</ul>
<pre class="code golang" data-lang="golang" data-unlink> // どのメトリクスデータを取得するか定義する
// 今回はURL監視を行っている特定のUptimeCheckのデータを取得するため、下記のように定義する
filter := `metric.type="monitoring.googleapis.com/uptime_check/check_passed" AND resource.type = "uptime_url" AND metric.labels.check_id = "` + uptimeCheckID + `"`</pre>
<p>次にリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを送る際の各パラメータについて、簡単に紹介します。</p>
<table>
<thead>
<tr>
<th> Key名 </th>
<th> 設定値の意味 </th>
</tr>
</thead>
<tbody>
<tr>
<td> Name </td>
<td> リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを送るプロジェクトのIDを指定 </td>
</tr>
<tr>
<td> Interval </td>
<td> データの取得期間。データを送る際は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Unix">Unix</a>タイムスタンプにする必要がある </td>
</tr>
<tr>
<td> Aggregation </td>
<td> データの取得方法について定義する。<a href="https://cloud.google.com/monitoring/charts/metrics-selector?hl=ja">Aggregationについて</a> </td>
</tr>
<tr>
<td> Aggregation.PerSeriesAligner </td>
<td> データ群をどのように取得するか具体的な方法を指定する。今回は特定期間の最後のデータを使いたいので「Aggregation_ALIGN_NEXT_OLDER」を使用する。 </td>
</tr>
<tr>
<td> Aggregation.AlignmentPeriod </td>
<td> PerSeriesAlignerで指定した方法で扱うデータの範囲(期間)。今回は「1分間のデータのうち、最後のデータを取得するようにしたいので、ここでは「60s」を指定する </td>
</tr>
<tr>
<td> Aggregation.View </td>
<td> 取得するデータの範囲を指定する。FULLの場合、時系列データについて全ての情報を取得する。 </td>
</tr>
</tbody>
</table>
<pre class="code golang" data-lang="golang" data-unlink> req := &monitoringpb.ListTimeSeriesRequest{
Name: "projects/" + projectNum,
Filter: filter,
Interval: &monitoringpb.TimeInterval{
StartTime: &timestamp.Timestamp{
Seconds: startTime.Unix(),
},
EndTime: &timestamp.Timestamp{
Seconds: endTime.Unix(),
},
},
// 基本的にGCPのWebコンソールを参考に設定
Aggregation: &monitoringpb.Aggregation{
// 各アライメント区間の最後のデータ・ポイントを当該区間の値として採用
// MonitoringのWebコンソールでは1ケ月の稼働率取得時、3時間ごとのcheckk passの最後の値を利用して稼働率を計算している
PerSeriesAligner: monitoringpb.Aggregation_ALIGN_NEXT_OLDER,
AlignmentPeriod: &duration.Duration{
Seconds: 60, // 1m
},
},
View: monitoringpb.ListTimeSeriesRequest_FULL,
}</pre>
<p>ここまで来れば、あとはロケーションごとの時系列データを取得していい感じに加工していくだけです。</p>
<h3>各ロケーションごとの時系列データ取得 & ロケーションごとの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を算出</h3>
<p><code>ListTimeSeries</code> を実行すると、チェック対象のUptimeCheckに紐づく各ロケーションごとのデータリソースが返されます。
UptimeCheckごとに紐づくデータリソース(ロケーション)数は異なるので、無限ループを回しつつ<code>it.Next()</code>で時系列データを取得します。紐づくデータリソースがなくなった時はforを抜けるように設定しています。<code>it.Next()</code>や関連する他の関数詳細については使用しているパッケージのコードを読んでもらうのが最も良いかと!</p>
<pre class="code golang" data-lang="golang" data-unlink> // 3. 各ロケーションごとの時系列データ取得 & ロケーションごとの稼働率を算出
// TimeSeriresデータを取得する
it := client.ListTimeSeries(ctx, req)
var PercentUptimeSum, uptimeCheckCount float64
for {
resp, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatal("could not read tiem series value: %v", err)
}
log.Println("ロケーション:", resp.Metric.Labels["checker_location"], "のデータチェック開始")
points := resp.GetPoints()
// Aggregation_ALIGN_NEXT_OLDERの場合、スライスの長さ=最大チェックパス数である
maxCheckPassCount := int64(len(points))
var checkPassCount int64
for _, point := range points {
log.Println(point.GetInterval().GetStartTime().AsTime())
if point.GetValue().GetBoolValue() == true {
checkPassCount++
}
}
locationPercentUptime := float64(checkPassCount) / float64(maxCheckPassCount)
PercentUptimeSum += locationPercentUptime
uptimeCheckCount++
}</pre>
<p>時系列データは全て <code>point</code> という構造体で取り扱うことができ、この<code>point</code>の値を利用して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を求めます。
下記のコードを見てもらえば分かる通り、<code>point</code>の値が<code>true</code>だったら=チェックが正常に通っていれば、チェックパス回数を追加しています。(これはチェックが通ることを前提の考えとなりますが、データ数が多いほどインクリメント回数が増えるので<code>false</code>を条件にしておいた方がいいかもしれません。)</p>
<pre class="code golang" data-lang="golang" data-unlink> points := resp.GetPoints()
// Aggregation_ALIGN_NEXT_OLDERの場合、スライスの長さ=最大チェックパス数である
maxCheckPassCount := int64(len(points))
var checkPassCount int64
for _, point := range points {
log.Println(point.GetInterval().GetStartTime().AsTime())
if point.GetValue().GetBoolValue() == true {
checkPassCount++
}
}
locationPercentUptime := float64(checkPassCount) / float64(maxCheckPassCount)
PercentUptimeSum += locationPercentUptime
uptimeCheckCount++</pre>
<p>ここまでくると、あとは足し算と割り算です。</p>
<pre class="code golang" data-lang="golang" data-unlink> // 4. 全体の稼働率を算出
result := PercentUptimeSum / uptimeCheckCount
log.Println("Percent Uptime: ", result)</pre>
<p>これでUptimeCheckに紐づくCloudMonitoringのデータをもとに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を取得することができました。
サンプルとして、実際に弊社のUptimeCheckでチェックしているサービスの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を「GCPWebコンソールで確認できる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>」と比較してみましたのでご覧ください。</p>
<p><figure class="figure-image figure-image-fotolife" title="稼働率の比較"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20201026/20201026114300.png" alt="f:id:allabout-techblog:20201026114300p:plain" title="f:id:allabout-techblog:20201026114300p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>の比較</figcaption></figure></p>
<p>上記画像にある通り、ほぼ同じ値を求めることができるようになりました。</p>
<h2>最後に</h2>
<p>今回は、Cloud Monitoringのデータを元に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を取得する方法(<a class="keyword" href="http://d.hatena.ne.jp/keyword/golang">golang</a>)を紹介しました。
また余談ですが、弊社では多くのUptimeCheckが存在するため、プロジェクトに紐づくUptimeCheck一覧を取得・各UptimeCheckのIDをもとに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%D4%C6%AF%CE%A8">稼働率</a>を取得するようにしています。なお、データが6週間で消えることもあり一ヶ月ごとに定期実行・<a class="keyword" href="http://d.hatena.ne.jp/keyword/JSON">JSON</a>としてGCSに書き出すようにしています。</p>
<p>今回の知見はCloud Monitoringのデータを扱う上で役に立つものだと思うので、ぜひUptimeCheck以外でも試してみてください。</p>
<h2>参考資料</h2>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>の公式ドキュメント
<ul>
<li><a href="https://cloud.google.com/monitoring/quotas?hl=ja">Cloud Monitoring 割り当てと上限</a></li>
<li><a href="https://cloud.google.com/monitoring/api/v3/metrics?hl=ja">指標、時系列、リソース</a></li>
<li><a href="https://cloud.google.com/monitoring/uptime-checks?hl=ja">稼働時間チェックの管理</a></li>
</ul>
</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/golang">golang</a>
<ul>
<li><a href="https://godoc.org/cloud.google.com/go/monitoring/apiv3">package monitoring</a></li>
<li><a href="https://godoc.org/google.golang.org/genproto/googleapis/monitoring/v3">package monitoring: monitoringpb</a></li>
<li><a href="https://github.com/GoogleCloudPlatform/golang-samples/blob/master/monitoring/snippets/time_series_fields.go">時系列データを扱う際のGoogle公式サンプル</a></li>
<li><a href="https://github.com/GoogleCloudPlatform/golang-samples/blob/master/monitoring/uptime/uptime.go">UptimeCheckを扱う際のGoogle公式サンプル</a></li>
</ul>
</li>
</ul>
allabout-techblog
インフラに詳しくないエンジニアがGKE上でRedash環境を構築した話
hatenablog://entry/26006613637627393
2020-10-19T15:57:10+09:00
2020-10-19T15:57:10+09:00 はじめに こんにちは!オールアバウトのデータエンジニア@ondaljhです。 データエンジニアをやっているものの恥ずかしいながらインフラにはそこまで詳しくない自分が、GKE上でRedash環境を構築したのでその経緯とやったことを紹介します。この記事を通して、GKEの概要とRedashをGKEで構築する1つの知見が皆様の役に立てば幸いです。 従いまして、この記事は下記のような方を想定して書かせていただきます。 GKEに興味はあるがインフラには詳しくないエンジニア GKE上でRedash環境を構築してみたいエンジニア ※この後はRedashの導入背景やdocker-composeを使ってのローカル…
<h1>はじめに</h1>
<p>こんにちは!オールアバウトのデータエンジニア<a href="https://qiita.com/ondaljh">@ondaljh</a>です。<br />
データエンジニアをやっているものの恥ずかしいながらインフラにはそこまで詳しくない自分が、GKE上でRedash環境を構築したのでその経緯とやったことを紹介します。この記事を通して、GKEの概要とRedashをGKEで構築する1つの知見が皆様の役に立てば幸いです。</p>
<p>従いまして、この記事は下記のような方を想定して書かせていただきます。</p>
<ul>
<li>GKEに興味はあるがインフラには詳しくないエンジニア</li>
<li>GKE上でRedash環境を構築してみたいエンジニア</li>
</ul>
<p>※この後はRedashの導入背景やdocker-composeを使ってのローカル環境構築の話をさせていただきます。ともかくGKE上でのRedash構築の話をお読みたい方は「GKEへのチャンレジ」へ進んでいただければと思います。</p>
<h1>なぜRedashなのか</h1>
<p>まず、なぜRedashを導入することになったのかの話を少しだけさせていただきます。</p>
<h2>新しい軸のデータ要望</h2>
<p>オールアバウトは<a href="https://primead.jp/">PrimeAd</a>というコンテンツ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>プラットフォームサービスを提供しています。PrimeAdの計測データはすでにAllAboutReportingという、自社制作の広告集計計測サービスで確認できるようになっています。<br />
ある日、ある部署からAllAboutReportingではまだ提供していない軸でのデータが欲しいとの要望がありました。普段なら<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%DB%A5%C3%A5%AF">アドホック</a>的なデータ抽出は順次対応していましたが、今回の要望はAllAboutReportingのように、日毎のデータが常に確認できてほしいとのことでした。話をシンプルにするために、この時点での状況をまとめると下記のようになります。</p>
<ul>
<li>新しい軸でのデータ要望があった。</li>
<li>日毎のデータが常に確認できる必要がある。</li>
<li>この軸のデータをAllAboutReportingへ追加する前にプロトタイプとして試してみた方が良いと判断した。</li>
</ul>
<p>この状況を踏まえて、新しい軸のデータはBIツールにて提供することにしました。</p>
<h2>BIツール選定</h2>
<p>BIツールといっても、世の中色んな種類のBIツールがあり、どれを使えばいいのかは皆さんにとっても悩みどころだと思います。 <br />
幸い、チーム内ではすでに<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>のデータポータルも使っていたので、今回もデータポータルで良いのでは?と思いましたが、データポータルには下記の問題がありました。<br />
データポータルのデータソースとして<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>を利用する場合、データポータルのドロップダウンリストで利用するカラムの値が日本語である場合、最大20個しか使えず、それ以上の項目は「その他」として丸められる。<br />
※ここでの<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>はCloudSQLではなく、GCE等で自前で構築した<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>になります。弊社の集計データとCloudSQLは相性悪く、やむを得ずGCEで<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>をインストールして使っている状況です。</p>
<p>今回の要望としてはドロップダウンリストは必須で、そこで使うデータは日本語で数百~数千件に至ることはわかっていたので、今回、データポータルは除外せざるを得ないことになりました。</p>
<p>その故、無料で使えるBIツールを改めて調べてみることにしました。その結果上がってきた候補は下記3つで、それぞれのメリットデメリットはあうものの大差はなかったので、前から使ってみたかったRedashを試してみることになりましたー(;・∀・)</p>
<ul>
<li><a href="https://redash.io/">Redash</a></li>
<li><a href="https://superset.incubator.apache.org/">Superset</a></li>
<li><a href="https://www.metabase.com/">Metabase</a><br />
※それぞれのBIツールのメリットデメリット等は比較記事がたくさんあるので、この記事では割愛させていただきます。</li>
</ul>
<h1>Redashの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>ー</h1>
<p><figure class="figure-image figure-image-fotolife" title="Redashのアーキテクチャー"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20201015/20201015132315.png" alt="f:id:allabout-techblog:20201015132315p:plain" title="f:id:allabout-techblog:20201015132315p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Redashの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>ー</figcaption></figure></p>
<p>自分が認識しているRedashの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>ーは上記の図のようなものです。<br />
これをGKE上にどうやって構築するか、を試す前に、自分のローカル環境でとりあえず構築してみることにしました。</p>
<h1>ローカル環境での試し</h1>
<p>Redashもdocker-composeもあんまり知らなかったので、とりあえずローカル環境での構築は下記サイトを参考にしました。<br />
<a href="https://dev.classmethod.jp/articles/redash_ond_cors/">[ データ可視化ツール]RedashをDocker上で構築してRedshiftへ接続する</a></p>
<p>上記サイトにも手順がありますが、ここからは実際に自分が行った際の手順になりますので、ご参考になれば幸いです。</p>
<ul>
<li>Redash<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>をクローンする</li>
<li>プロダクション用docker-compose.ymlを取得する</li>
<li>redash.envファイルを作成する</li>
<li>docker-composeを使ってアプリケーション全体を起動する</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/localhost">localhost</a>:8080へアクセスする</li>
</ul>
<h2>Redash<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>をクローンする</h2>
<pre class="code" data-lang="" data-unlink>git clone https://github.com/getredash/redash.git</pre>
<p>クローンしてくるといくつかの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リも生成されていることが確認できます。すべての<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リ構成は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>元を参考していただくこととして、以降の説明に出てくる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リ構成だけ簡単に載せますと下記のようになります。</p>
<pre class="code" data-lang="" data-unlink>/redash # 作業ディレクトリルート
/redash/setup # 設定ファイル等が格納されてる</pre>
<p>また、ここで取得したdocker-compose.ymlファイルは開発専用のものであるため、プロダクション用を取得する必要があります。</p>
<h2>プロダクション用docker-compose.ymlを取得する</h2>
<ul>
<li>「/setup」<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リにある「README.md」ファイルを削除する</li>
<li>作業<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リルート(/redash)に移動して、setup<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>をクローンする</li>
</ul>
<pre class="code" data-lang="" data-unlink>get clone https://github.com/getredash/setup.git</pre>
<ul>
<li>「/setup/data」<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リにdocker-compose.ymlファイルがあることを確認する</li>
</ul>
<p>docker-compose.yml</p>
<pre class="code docker-compose.yml" data-lang="docker-compose.yml" data-unlink>version: "2"
x-redash-service: &redash-service
image: redash/redash:8.0.0.b32245
depends_on:
- postgres
- redis
env_file: redash.env
restart: always
services:
server:
<<: *redash-service
command: server
ports:
- "5000:5000"
environment:
REDASH_WEB_WORKERS: 4
scheduler:
<<: *redash-service
command: scheduler
environment:
QUEUES: "celery"
WORKERS_COUNT: 1
scheduled_worker:
<<: *redash-service
command: worker
environment:
QUEUES: "scheduled_queries,schemas"
WORKERS_COUNT: 1
adhoc_worker:
<<: *redash-service
command: worker
environment:
QUEUES: "queries"
WORKERS_COUNT: 2
redis:
image: redis:5.0-alpine
restart: always
postgres:
image: postgres:9.6-alpine
env_file: redash.env
volumes:
- /opt/redash/postgres-data:/var/lib/postgresql/data
restart: always
nginx:
image: redash/nginx:latest
ports:
- "80:80"
depends_on:
- server
links:
- server:redash
restart: always</pre>
<p>ご覧の通り、docker-compose.ymlにはredashのserverはもちろん、nginxやredis等、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>ー図に登場する複数のサービスが定義されています。</p>
<h2>redash.envファイルを作成する</h2>
<p>ビルド時に利用する設定情報をredash.envファイルへまとめておきます。中身は下記サイトを参考にしました。必要に応じて各情報を書き換えていただければと思います。<br />
<a href="https://github.com/kakakakakku/redash-hands-on/blob/master/redash.env">redash-hands-on</a></p>
<pre class="code" data-lang="" data-unlink>REDASH_HOST=http://localhost
PYTHONUNBUFFERED=0
REDASH_LOG_LEVEL=INFO
REDASH_REDIS_URL=redis://redis:6379/0
REDASH_DATABASE_URL=postgresql://postgres@postgres/postgres
REDASH_COOKIE_SECRET=redash-hands-on
REDASH_SECRET_KEY=redash-hands-on
POSTGRES_PASSWORD=
POSTGRES_HOST_AUTH_METHOD=trust</pre>
<h2>docker-composeを使ってアプリケーション全体を起動する</h2>
<p>まずは下記コマンドを使ってredashで利用するデータベースを作成します。</p>
<pre class="code" data-lang="" data-unlink>docker-compose -f docker-compose.yml run --rm server create_db</pre>
<p>次は、下記コマンドを使ってアプリケーションを起動します。</p>
<pre class="code" data-lang="" data-unlink>docker-compose -f docker-compose.yml up -d</pre>
<p>エラーメッセージなどが出なければとりあえず環境構築はできたことになります。</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/localhost">localhost</a>:8080へアクセスする</h2>
<p>自分はredash.envファイルでREDASH_HOSTを「<a href="http://localhost">http://localhost</a>」にしたので、ブラウザを開いて「<a href="http://localhost:8080">http://localhost:8080</a>」へアクセスを試しました。</p>
<p><figure class="figure-image figure-image-fotolife" title="redash初期設定画面"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20201007/20201007122419.png" alt="f:id:allabout-techblog:20201007122419p:plain" title="f:id:allabout-techblog:20201007122419p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>redash初期設定画面</figcaption></figure></p>
<p>できた!!ブラウザ上に上記のような初期設定画面が表示されたら、ローカル環境でRedashが構築できたことになります。</p>
<h1>GKEへのチャレンジ</h1>
<p>ローカル環境ではdocker-composeを使って簡単にredash環境構築ができました。が、問題はこれからです。ご存じの方も多いと思いますが、docker-composeコマンドはあくまでもdockerコマンドであり、gcloudやkubectlのような<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>向けのコマンドではないです。つまり、ローカル環境を構築した手順のままではGKEへの構築ができない!ということになります。ローカル環境構築はredashの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>ーを理解する勉強になったので、ここからはGKE上でredashの各サービスを起動するために行ったことを紹介させていただきますー</p>
<h2>インフラ構成</h2>
<p>まずは詳細説明に入る前に、ローカル環境と<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>上の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>ーを比較することで全体図を把握しましょうー</p>
<p>ローカル環境の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>(docker-compose.yml)を見るとわかるように、Redashを構築するには複数のインフラサービスが必要になります。ここでは、ローカル環境で登場するサービスが<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>上ではどう変わるのかを表でまとめてみました。</p>
<table>
<thead>
<tr>
<th>ローカル環境</th>
<th><a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a></th>
</tr>
</thead>
<tbody>
<tr>
<td>(redash)server</td>
<td>GKEのDeployment redash-server</td>
</tr>
<tr>
<td>(redash)scheduler<br/>scheduled_worker<br/>adhoc_worker</td>
<td>GKEのDeployment redash-worker</td>
</tr>
<tr>
<td>nginx</td>
<td>GKEのDeployment redash-nginx</td>
</tr>
<tr>
<td>redis</td>
<td>Memorystore for redis</td>
</tr>
<tr>
<td>postgres</td>
<td>CloudSQL for <a class="keyword" href="http://d.hatena.ne.jp/keyword/PostgreSQL">PostgreSQL</a></td>
</tr>
</tbody>
</table>
<p>上記表のように、redashのserverとworker群、そしてnginxはすべてGKEのDeploymentとして構成することにしました。redisとpostgresはGKEのDeploymentではなく、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>上のそれぞれの専用サービスを利用する構成にしました。また、ローカル環境では不要でしたが、本番運用ではメール送信も必要になりますので、redashからのメール送信はSendGridを利用するようにしました。ここまでの構成を図でまとめますと、下記のような図になります。</p>
<p><figure class="figure-image figure-image-fotolife" title="Redash on GKEアーキテクチャー"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20201015/20201015132406.png" alt="f:id:allabout-techblog:20201015132406p:plain" title="f:id:allabout-techblog:20201015132406p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Redash on GKE<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>ー</figcaption></figure></p>
<p>上記図には記載していませんが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Kubernetes">Kubernetes</a>のPodへのアクセスにはServiceが必要なので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/svc">svc</a>-redash-nginxと<a class="keyword" href="http://d.hatena.ne.jp/keyword/svc">svc</a>-redash-serverを構築しています。Serviceを構築している理由としては、podのIPは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%D5%A5%A7%A5%E1%A5%E9">エフェメラ</a>ルでpodを構築する度にIPが変わります。そのため、Serviceを構築することでIPが変わっても指定したpodにアクセスができるようになります。詳しくは<a href="https://cloud.google.com/kubernetes-engine/docs/concepts/service?hl=ja#why_use_a_service">公式サイト</a>に説明があるので、ご参考ください。</p>
<h2>nginxのカスタマイズ</h2>
<p>docker-compose用のnginxは「redash/nginx:latest」イメージを使っていて、その中の設定ファイル(default.conf)は下記のようになっています。</p>
<p>変更前</p>
<pre class="code default.conf" data-lang="default.conf" data-unlink>upstream redash {
server redash:5000;
}
server {
listen 80 default;
gzip on;
gzip_types *;
gzip_proxied any;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_pass http://redash;
}
}</pre>
<p>upstream項目で指定している「server redash:5000;」が、nginxサーバーへアクセスが発生したらredashサーバーの5000ポートへつないでくれる設定になります。GKE上でnginxを構成する際には、この値をredash-serverのServiceに変更する必要があります。また、後述しますが、ステージング環境と本番環境で同じnginxイメージを使う想定なので、default.confのserver値を変数化し、ステージング環境と本番環境のそれぞれの<a href="https://cloud.google.com/deployment-manager/docs/deployments/viewing-manifest?hl=ja">マニフェスト</a>から値を設定できるようにしました。カスタマイズした設定ファイルは下記のようになります。</p>
<p>変更後</p>
<pre class="code default.conf.template" data-lang="default.conf.template" data-unlink>upstream redash {
server ${UPSTREAM_SERVER}:${UPSTREAM_PORT};
}
server {
listen 80 default;
gzip on;
gzip_types *;
gzip_proxied any;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_pass http://redash;
}
} </pre>
<p>ちなみに、カスタマイズした設定ファイルは、変数の置換が必要になるためファイル名も「default.conf.template」にし、実際のデプロイの際に変数が置換された状態の「default.conf」ファイルを生成するようにしています。こちらの内容は後述する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>にて紹介させていただきます。</p>
<p>このようにカスタマイズしたnginxイメージはGCR(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Container Registry)のある場所へ格納することで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>から参照できるようにしました。</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a></h2>
<p>前述したとおり、GKEのDeploymentへのアクセスはServiceを利用します。そして、DeploymentもServiceもGKEの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>に属されています。今回のGKE構成を表で表すと下記のようになります。</p>
<table>
<thead>
<tr>
<th>GKE要素</th>
<th>サービス名</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cluster</td>
<td>redash-cluster</td>
</tr>
<tr>
<td>Deployment</td>
<td>redash-server<br/>redash-worker<br/>redash-nginx</td>
</tr>
<tr>
<td>Service</td>
<td><a class="keyword" href="http://d.hatena.ne.jp/keyword/svc">svc</a>-redash-server<br/><a class="keyword" href="http://d.hatena.ne.jp/keyword/svc">svc</a>-redash-nginx</td>
</tr>
</tbody>
</table>
<p>redash-workerの場合、内部で<a class="keyword" href="http://d.hatena.ne.jp/keyword/celery">celery</a>プロセスが動いていて、redisと<a class="keyword" href="http://d.hatena.ne.jp/keyword/PostgreSQL">PostgreSQL</a>と経路を書く方できればredash-serverやそれ以外との経路は不要なので、専用のServiceを持つ必要がないです。従ってServiceは2つだけになります。また、redashで利用するためのMemorystore for redisとCloudSQL for <a class="keyword" href="http://d.hatena.ne.jp/keyword/PostgreSQL">PostgreSQL</a>はそれぞれのサービスで新規作成するだけで簡単に構築できました。これらの構成を行うために5つの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>ファイルを作成したので、それぞれ記載させていただきます。
※弊社ではCircleCIを使ってのデプロイを行っているため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>ファイルの中にプロジェクト毎のCircleCI<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%C4%B6%AD%CA%D1%BF%F4">環境変数</a>を使っています。</p>
<h3>deployment-redash-server</h3>
<pre class="code deployment-redash-server.yaml" data-lang="deployment-redash-server.yaml" data-unlink>apiVersion: apps/v1
kind: Deployment
metadata:
name: redash-server
labels:
app: redash-server
spec:
selector:
matchLabels:
app: redash-server
template:
metadata:
labels:
app: redash-server
spec:
containers:
- name: redash-server-container
image: redash/redash:8.0.0.b32245
command:
- /bin/sh
- -c
- /app/bin/docker-entrypoint create_db; /app/bin/docker-entrypoint server
resources:
limits:
memory: "1Gi"
requests:
memory: "512Mi"
env:
# redashで利用する環境変数
- name: DB_USER
value: ${DB_USER}
- name: DB_PASS
value: ${DB_PASS}
- name: DB_NAME
value: ${DB_NAME}
- name: TZ
value: "Asia/Tokyo"
- name: PYTHONUNBUFFERED
value: "0"
- name: REDASH_LOG_LEVEL
value: "INFO"
- name: REDASH_WEB_WORKERS
value: "4"
- name: REDASH_REDIS_URL
value: "redis://${REDIS_IP}:6379/0"
# ここで設定した環境変数を利用するため{}ではなく()となる
- name: REDASH_DATABASE_URL
value: "postgresql://$(DB_USER):$(DB_PASS)@127.0.0.1/$(DB_NAME)"
- name: REDASH_HOST
value: "https://${REDASH_HOST}"
- name: REDASH_MAIL_SERVER
value: "${REDASH_MAIL_SERVER}"
- name: REDASH_MAIL_PORT
value: "${REDASH_MAIL_PORT}"
- name: REDASH_MAIL_USERNAME
value: "${REDASH_MAIL_USERNAME}"
- name: REDASH_MAIL_PASSWORD
value: "${REDASH_MAIL_PASSWORD}"
- name: REDASH_MAIL_DEFAULT_SENDER
value: "redash@example.com"
ports:
# このポート番号でsvc-redash-serverとつながる
- containerPort: 5000
# CloudSQL for PostgreSQLとつなげるためのcloud-sql-proxy設定
- name: redash-cloud-sql-proxy
image: gcr.io/cloudsql-docker/gce-proxy:1.17
command: ["/cloud_sql_proxy", "--dir=/cloudsql",
"-instances=${GCP_PROJECT_ID}:${CLOUDSQL_REGION}:db-${CLOUDSQL_INSTANCE}=tcp:5432"]
volumeMounts:
- name: ssl-certs
mountPath: /etc/ssl/certs
volumes:
- name: ssl-certs
hostPath:
path: /etc/ssl/certs</pre>
<h3>deployment-redash-worker</h3>
<pre class="code deployment-redash-worker.yaml" data-lang="deployment-redash-worker.yaml" data-unlink>apiVersion: apps/v1
kind: Deployment
metadata:
name: redash-worker
labels:
app: redash-worker
spec:
selector:
matchLabels:
app: redash-worker
template:
metadata:
labels:
app: redash-worker
spec:
containers:
- name: redash-worker-container
image: redash/redash:8.0.0.b32245
resources:
limits:
memory: "1Gi"
requests:
memory: "512Mi"
env:
# redashで利用する環境変数
- name: DB_USER
value: ${DB_USER}
- name: DB_PASS
value: ${DB_PASS}
- name: DB_NAME
value: ${DB_NAME}
- name: TZ
value: "Asia/Tokyo"
- name: PYTHONUNBUFFERED
value: "0"
- name: REDASH_LOG_LEVEL
value: "INFO"
- name: REDASH_REDIS_URL
value: "redis://${REDIS_IP}:6379/0"
# ここで設定した環境変数を利用するため{}ではなく()となる
- name: REDASH_DATABASE_URL
value: "postgresql://$(DB_USER):$(DB_PASS)@127.0.0.1/$(DB_NAME)"
- name: WORKERS_COUNT
value: "2"
- name: QUEUES
value: "queries,scheduled_queries,celery"
- name: REDASH_HOST
value: "https://${REDASH_HOST}"
- name: REDASH_MAIL_SERVER
value: "${REDASH_MAIL_SERVER}"
- name: REDASH_MAIL_PORT
value: "${REDASH_MAIL_PORT}"
- name: REDASH_MAIL_USERNAME
value: "${REDASH_MAIL_USERNAME}"
- name: REDASH_MAIL_PASSWORD
value: "${REDASH_MAIL_PASSWORD}"
- name: REDASH_MAIL_DEFAULT_SENDER
value: "redash@example.com"
args: ["scheduler"]
# CloudSQL for PostgreSQLとつなげるためのcloud-sql-proxy設定
- name: stg-dmg-redash-cloud-sql-proxy
image: gcr.io/cloudsql-docker/gce-proxy:1.17
command: ["/cloud_sql_proxy", "--dir=/cloudsql",
"-instances=${GCP_PROJECT_ID}:${CLOUDSQL_REGION}:db-stg-${CLOUDSQL_INSTANCE}=tcp:5432"]
volumeMounts:
- name: ssl-certs
mountPath: /etc/ssl/certs
volumes:
- name: ssl-certs
hostPath:
path: /etc/ssl/certs</pre>
<h3>deployment-redash-nginx</h3>
<pre class="code deployment-redash-nginx.yaml" data-lang="deployment-redash-nginx.yaml" data-unlink>apiVersion: apps/v1
kind: Deployment
metadata:
name: redash-nginx
labels:
app: redash-nginx
spec:
replicas: 1
selector:
matchLabels:
app: redash-nginx
template:
metadata:
labels:
app: redash-nginx
spec:
containers:
- name: redash-nginx-container
# カスタマイズ済みのnginxイメージを格納しているGCR情報
image: ${GCR_PATH}/${IMAGE_NGINX_NAME}:${IMAGE_NGINX_TAG}
resources:
limits:
memory: "256Mi"
requests:
memory: "256Mi"
env:
# nginx設定ファイルで利用する変数設定
- name: UPSTREAM_SERVER
value: "svc-${REDASH_SERVER}"
- name: UPSTREAM_PORT
value: "5000"
# envsubstコマンドを使って変数を置換する
command: ["/bin/sh", "-c", "envsubst '$$${ENV_UPSTREAM_SERVER}$$${ENV_UPSTREAM_PORT}' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf && /usr/sbin/nginx -g 'daemon off;'"]
ports:
- containerPort: 80</pre>
<p>カスタマイズ済みのnginxイメージを利用していますが、設定ファイルで利用する変数設定でちょっと苦労したので少しだけ補足させていただきます。<br />
default.conf.templateファイルでは${UPSTREAM_SERVER}と${UPSTREAM_PORT}を記載しており、envsubstコマンドを使って該当変数を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>の値に置換し、その結果をdefault.confファイルへ書き出すのがゴールになります。普通のenvsubstコマンドで書くと下記のような感じになります。</p>
<pre class="code" data-lang="" data-unlink>envsubst '$$UPSTREAM_SERVER$$UPSTREAM_PORT' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf</pre>
<p>※envsubstコマンドについては、<a href="https://qiita.com/takyam/items/e92e5a6ca1548cbd58db">Docker上のNginxのconfに環境変数(env)を渡すたったひとつの全く優れてない方法(修正:+優れている方法)</a>を参照にしました。</p>
<p>envsubstコマンドも不慣れだったものの、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>ファイルで書いてkubectlコマンドで実行するだけならシンプルですが、CircleCI経由になると余計に変数設定-置換が怪しくなり、いくつかの試行錯誤でやっと上記<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>のような書き方にたどり着きました(後から見ると当たり前のように見えるものが、何かにはまっちゃうと見えなくなりますよね;;;)。ここで、恥ずかしながら試行錯誤の内容も書かせていただきます。</p>
<h4>envsubst記載の試行錯誤</h4>
<ul>
<li><p>ゴール : envsubst '$$UPSTREAM_SERVER$$UPSTREAM_PORT'</p></li>
<li><p>kubectlコマンド用<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a> : envsubst '$$UPSTREAM_SERVER$$UPSTREAM_PORT'</p></li>
<li><p>CircleCI用<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>の試行錯誤<br />
※Inputは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>への記載内容、OutputはCircleCIデプロイ時の置換後の内容になります。</p></li>
</ul>
<table>
<thead>
<tr>
<th>Case#</th>
<th>Input</th>
<th>Output</th>
<th>備考</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>envsubst '$$UPSTREAM_SERVER$$UPSTREAM_PORT'</td>
<td>envsubst '$$'</td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>envsubst '${$UPSTREAM_SERVER}${$UPSTREAM_PORT}'</td>
<td>envsubst '${}${}'</td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>envsubst '$UPSTREAM_SERVER$UPSTREAM_PORT'</td>
<td>envsubst ''</td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>Input : envsubst '\$\$UPSTREAM_SERVER\$\$UPSTREAM_PORT'</td>
<td>found unknown escape character</td>
<td></td>
</tr>
<tr>
<td>5</td>
<td>envsubst '$$$UPSTREAM_SERVER$$$UPSTREAM_PORT'</td>
<td>envsubst '$$$$'</td>
<td></td>
</tr>
<tr>
<td>6</td>
<td>envsubst <code>$$UPSTREAM_SERVER$$UPSTREAM_PORT</code></td>
<td>envsubst <code>$$</code></td>
<td></td>
</tr>
<tr>
<td>7</td>
<td>envsubst '$${ENV_UPSTREAM_SERVER}$${ENV_UPSTREAM_PORT}</td>
<td>found unknown escape character</td>
<td>CircleCIの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%C4%B6%AD%CA%D1%BF%F4">環境変数</a>利用<br/>ENV_UPSTREAM_SERVER : \$UPSTREAM_SERVER<br/>ENV_UPSTREAM_PORT : \$UPSTREAM_PORT</td>
</tr>
<tr>
<td>8</td>
<td>envsubst '$$${ENV_UPSTREAM_SERVER}$$${ENV_UPSTREAM_PORT}</td>
<td>envsubst '$$UPSTREAM_SERVER$$UPSTREAM_PORT'</td>
<td>CircleCIの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%C4%B6%AD%CA%D1%BF%F4">環境変数</a>利用<br/>ENV_UPSTREAM_SERVER : UPSTREAM_SERVER<br/>ENV_UPSTREAM_PORT : UPSTREAM_PORT</td>
</tr>
</tbody>
</table>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/svc">svc</a>-redash-server</h3>
<pre class="code svc-redash-server.yaml" data-lang="svc-redash-server.yaml" data-unlink>apiVersion: v1
kind: Service
metadata:
name: svc-redash-server
labels:
app: svc-redash-server
spec:
type: ClusterIP
ports:
- port: 5000
targetPort: 5000
protocol: TCP
selector:
app: redash-server</pre>
<h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/svc">svc</a>-redash-nginx</h3>
<pre class="code svc-redash-nginx.yaml" data-lang="svc-redash-nginx.yaml" data-unlink>apiVersion: v1
kind: Service
metadata:
name: svc-redash-nginx
labels:
app: svc-redash-nginx
spec:
type: NodePort
ports:
- port: 80
# このnodePort番号にてロードバランサとつながる
nodePort: 30419
selector:
app: redash-nginx</pre>
<h2>kubectlコマンド</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>も何回かの試行錯誤の結果、完成できました。試行錯誤の際に役に立ったいくつかのkubectlコマンドを簡単に紹介させていただきます。</p>
<h3>podのリストを取得する</h3>
<pre class="code" data-lang="" data-unlink>kubectl get pods</pre>
<h3>podの詳細情報を確認する</h3>
<pre class="code" data-lang="" data-unlink>kubectl decribe pods POD-NAME</pre>
<h3>podのログを確認する</h3>
<pre class="code" data-lang="" data-unlink>kubectl logs POD-NAME
kubectl logs POD-NAME -c CONTAINER-NAME # 1つのpodに複数のコンテナがある場合</pre>
<p>deployment作成に失敗したり、エラーが発生したり等の場合には上記コマンドでどのような状況・エラーなのかの確認ができるので結構役に立ちました。</p>
<h3>podに対してポート<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%A9%A5%EF">フォワ</a>ードする</h3>
<pre class="code" data-lang="" data-unlink>kubectl port-forward pod/POD_NAME LOCALHOSTのPORTNUMBER:PODのPORTNUMBER</pre>
<p>上記コマンド実行後、ブラウザに「<a class="keyword" href="http://d.hatena.ne.jp/keyword/localhost">localhost</a>:<a class="keyword" href="http://d.hatena.ne.jp/keyword/LOCALHOST">LOCALHOST</a>のPORTNUMBER」と書くと、ブラウザから該当podへアクセスすることが可能です。</p>
<h3>Serviceに対してポート<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%A9%A5%EF">フォワ</a>ードする</h3>
<pre class="code" data-lang="" data-unlink>kubectl port-forward svc/SERVICE_NAME LOCALHOSTのPORTNUMBER:SERVICEのPORTNUMBER</pre>
<p>podにブラウザからアクセスできることと同じく、Serviceにもブラウザからアクセスすることができます。これで、podへのアクセスに問題があるかどうか、Serviceへのアクセスに問題があるかどうかの確認ができるので便利ですねー</p>
<h1>CircleCI設定</h1>
<p>前述の通り、弊社ではCircleCIを使ってデプロイを行っています。今回作成した<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>を使ってデプロイするCiecleCI設定内容の一部を記載させていただきます。</p>
<pre class="code config.yml" data-lang="config.yml" data-unlink>version: 2.1
commands:
deploy_to_kubernetes:
steps:
- run:
name: Deploy to Kubernetes
command: |
envsubst < yaml_files/${YAML_FILES_DIRECTORY}/deployment-${ENVIRONMENT}-${REDASH_NGINX}.yaml > ./patched_deployment_nginx.yaml
envsubst < yaml_files/${YAML_FILES_DIRECTORY}/deployment-${ENVIRONMENT}-${REDASH_SERVER}.yaml > ./patched_deployment_server.yaml
envsubst < yaml_files/${YAML_FILES_DIRECTORY}/deployment-${ENVIRONMENT}-${REDASH_WORKER}.yaml > ./patched_deployment_worker.yaml
envsubst < yaml_files/${YAML_FILES_DIRECTORY}/svc-${ENVIRONMENT}-${REDASH_NGINX}.yaml > ./patched_svc_nginx.yaml
envsubst < yaml_files/${YAML_FILES_DIRECTORY}/svc-${ENVIRONMENT}-${REDASH_SERVER}.yaml > ./patched_svc_server.yaml
kubectl apply -f ./patched_deployment_nginx.yaml
kubectl apply -f ./patched_deployment_server.yaml
kubectl apply -f ./patched_deployment_worker.yaml
kubectl apply -f ./patched_svc_nginx.yaml
kubectl apply -f ./patched_svc_server.yaml
kubectl rollout status deployment ${ENVIRONMENT}-${REDASH_NGINX}
kubectl rollout status deployment ${ENVIRONMENT}-${REDASH_SERVER}
kubectl rollout status deployment ${ENVIRONMENT}-${REDASH_WORKER}</pre>
<p>後はCircleCIを起動して無事デプロイできることも確認でき、実際にRedashも起動していることを確認できました。</p>
<h1>おわりに</h1>
<p>ここまでがGKE上にRedashを構築するためにやったことになります。インフラにはそこまで詳しくない自分がredashの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>ーを理解し、試行錯誤しながら<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%CB%A5%D5%A5%A7%A5%B9%A5%C8">マニフェスト</a>を作成してGKE構成までできたので、今回の経験を活かしていきたいと思います。<br />
余談ですが、今回構築した環境でRedashの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%C3%A5%B7%A5%E5">ダッシュ</a>ボードを作成し、要望があった部署へ提供することで実際に使ってもらっていて嬉しいですー<br />
長文になりましたが少しでもGKEの構成を理解いただき、GKE上でRedashを構築してみようと思う方へ役に立てればと思います。</p>
<p>閲覧ありがとうございました!今後ともよろしくお願いいたします。</p>
allabout-techblog
コロナ禍での情シスの対応とそこから見えたもの
hatenablog://entry/26006613628627534
2020-09-28T13:44:18+09:00
2020-09-28T13:44:18+09:00 はじめに こんにちは!オールアバウトナビ、システム部の@k_shiotaです。 オールアバウトには業務全体に関わる部署、情報システムG(情シス)が存在します。 その情シスの皆さんに、「コロナの対応」について、社内で行っているLT会にて発表いただきました! 今回は情シスでのコロナ対応について発表をしてもらいましたので、このブログで紹介したいと思います。 目次 はじめに 目次 ドタバタなコロナ対策 情シス業務の変化 変化の中で見えてきたもの 今後の計画 最後に まとめ アジェンダ ドタバタなコロナ対策 オールアバウト では早い段階でコロナへの対応を行っており2/27に全社広報があり、2/28から在…
<h1 id="はじめに">はじめに</h1>
<p>こんにちは!オールアバウトナビ、システム部の<a href="https://qiita.com/k_shiota">@k_shiota</a>です。</p>
<p>オールアバウトには業務全体に関わる部署、情報システムG(情シス)が存在します。<br />
その情シスの皆さんに、「コロナの対応」について、社内で行っているLT会にて発表いただきました!</p>
<p>今回は情シスでのコロナ対応について発表をしてもらいましたので、このブログで紹介したいと思います。</p>
<h1 id="目次">目次</h1>
<ul class="table-of-contents">
<li><a href="#はじめに">はじめに</a></li>
<li><a href="#目次">目次</a><ul>
<li><a href="#ドタバタなコロナ対策">ドタバタなコロナ対策</a></li>
<li><a href="#情シス業務の変化">情シス業務の変化</a></li>
<li><a href="#変化の中で見えてきたもの">変化の中で見えてきたもの</a></li>
<li><a href="#今後の計画">今後の計画</a></li>
<li><a href="#最後に">最後に</a></li>
</ul>
</li>
<li><a href="#まとめ">まとめ</a></li>
</ul>
<p><figure class="figure-image figure-image-fotolife" title="アジェンダ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200916/20200916155912.png" alt="f:id:allabout-techblog:20200916155912p:plain" title="f:id:allabout-techblog:20200916155912p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B8%A5%A7%A5%F3%A5%C0">アジェンダ</a></figcaption></figure></p>
<h4 id="ドタバタなコロナ対策">ドタバタなコロナ対策</h4>
<p>オールアバウト では早い段階でコロナへの対応を行っており2/27に全社広報があり、2/28から在宅勤務を行いましたが、<br />
情シスはそれよりも前からすでにコロナ対策を始めていました。</p>
<p>コロナ対策準備は下記のことを想定して動いておりました。</p>
<p><figure class="figure-image figure-image-fotolife" title="ドタバタなコロナ対策_1"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200916/20200916155947.png" alt="f:id:allabout-techblog:20200916155947p:plain" title="f:id:allabout-techblog:20200916155947p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>ドタバタなコロナ対策_1</figcaption></figure></p>
<p>その中で在宅勤務が始まる前に下記のことをやっておきました。</p>
<p><figure class="figure-image figure-image-fotolife" title="ドタバタなコロナ対策_2"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200916/20200916160036.png" alt="f:id:allabout-techblog:20200916160036p:plain" title="f:id:allabout-techblog:20200916160036p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>ドタバタなコロナ対策_2</figcaption></figure></p>
<p>そして3/4より情シスも原則在宅勤務となりました。</p>
<h4 id="情シス業務の変化">情シス業務の変化</h4>
<p>基本在宅勤務になって情シスの業務に変化がありました。
情シスは一緒のフロアにいたため、相談をしやすく都度対応してもらうことが多かったのですが
手順書を作成して困ることが少なくなり、困ったことはslackでオープンに相談することで、
他の方も同様な問題があった時に参考になったかと思います。</p>
<p><figure class="figure-image figure-image-fotolife" title="情シス業務の変化"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200916/20200916160129.png" alt="f:id:allabout-techblog:20200916160129p:plain" title="f:id:allabout-techblog:20200916160129p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>情シス業務の変化</figcaption></figure></p>
<p>slackへの投稿数は原則在宅が始まる前と後では増加しております。</p>
<p><figure class="figure-image figure-image-fotolife" title="情シス業務の変化_slackの投稿数"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200916/20200916160211.png" alt="f:id:allabout-techblog:20200916160211p:plain" title="f:id:allabout-techblog:20200916160211p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>情シス業務の変化_slackの投稿数</figcaption></figure></p>
<h4 id="変化の中で見えてきたもの">変化の中で見えてきたもの</h4>
<p>固定電話が必要かどうかについて、以前からも話題に上がっていたのですが
今回の件でどうにかなるという事もわかり良い判断材料となりました。</p>
<p><figure class="figure-image figure-image-fotolife" title="変化から見えてきたもの"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200916/20200916160256.png" alt="f:id:allabout-techblog:20200916160256p:plain" title="f:id:allabout-techblog:20200916160256p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>変化から見えてきたもの</figcaption></figure></p>
<p>また、ゼロトラスト環境に移行することに待ったがない状態になりました。</p>
<p><figure class="figure-image figure-image-fotolife" title="変化から見えてきたもの_ゼロトラストセキュリティモデル"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200916/20200916160319.png" alt="f:id:allabout-techblog:20200916160319p:plain" title="f:id:allabout-techblog:20200916160319p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>変化から見えてきたもの_ゼロトラストセキュリティモデル</figcaption></figure></p>
<h4 id="今後の計画">今後の計画</h4>
<p><figure class="figure-image figure-image-fotolife" title="今後の計画"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200916/20200916160358.png" alt="f:id:allabout-techblog:20200916160358p:plain" title="f:id:allabout-techblog:20200916160358p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>今後の計画</figcaption></figure></p>
<ul>
<li>slackでの問い合わせに一つ一つ答えているため、定型化したものをボット化してその他の業務に当たれる時間をふやすこと</li>
<li>ゼロトラスト環境は社外からのアクセスが増えるため強化する必要があること</li>
<li>固定電話は不要で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>を全社員に配布すること
など、在宅勤務環境をより良くしていくよう動いて行くとのことです。</li>
</ul>
<h4 id="最後に">最後に</h4>
<p><figure class="figure-image figure-image-fotolife" title="最後に"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200925/20200925160036.png" alt="f:id:allabout-techblog:20200925160036p:plain" title="f:id:allabout-techblog:20200925160036p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>最後に</figcaption></figure></p>
<p>会議の時間が超過する問題はどうしてもあるようでして、切実なお願いでした。
自分も今後気をつけていきたいと思います。。。</p>
<h1 id="まとめ">まとめ</h1>
<p>弊社でもコロナ前から在宅勤務を導入しておりましたが、まだまだやりづらい点があったかと思います。<br />
原則在宅勤務となり、在宅勤務の環境を整えることが急務となりました。</p>
<p>原則在宅勤務が始まったことで対応に追われて大変だったとのことですが、今は落ち着き更に働きやすい環境を整えているとのことです。 <br />
普段から頼っている情シスを更に信頼することになりました。</p>
<p>もし、こんな環境で働いてみたいと思ったらぜひ一緒に働きましょう!<br />
以下より採用情報がありますので、募集をお待ちしております!</p>
<p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcorp.allabout.co.jp%2Frecruit%2F" title="オールアバウトグループのコーポレートサイト – 採用情報" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://corp.allabout.co.jp/recruit/">corp.allabout.co.jp</a></cite></p>
allabout-techblog
Google Cloud Functionsを使ってバックアップデータからログの再収集を行う方法の紹介
hatenablog://entry/26006613619224586
2020-08-27T11:56:54+09:00
2020-08-27T11:56:54+09:00 こんにちは!オールアバウトでデータエンジニアをしている@ondaljhです。 皆さんはGoogle Cloud Functions(以降、Cloud Functions)を利用したことがありますか?自分も業務上では使ったことがなかったんですが、今回ある案件でCloud functionsを利用する機会があったので、私たちのチームでのCloud Functionsの利用シーンを紹介させていただきたいと思います。この記事を最後まで読んでいただいて、「こんな利用シーンもあるんだ~」程度で理解していただければ幸いです。 従いまして、本記事は下記のような方を想定して書かせていただきます。 Google …
<p>こんにちは!オールアバウトでデータエンジニアをしている@ondaljhです。</p>
<p>皆さんは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud Functions(以降、Cloud Functions)を利用したことがありますか?自分も業務上では使ったことがなかったんですが、今回ある案件でCloud functionsを利用する機会があったので、私たちのチームでのCloud Functionsの利用シーンを紹介させていただきたいと思います。この記事を最後まで読んでいただいて、「こんな利用シーンもあるんだ~」程度で理解していただければ幸いです。</p>
<p>従いまして、本記事は下記のような方を想定して書かせていただきます。</p>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud Functionsに興味はあるが深くかかわったことがない方</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud Functionsの利用パターンを調べてる方</li>
</ul>
<p>また、Cloud Functions以外に出てくる<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud群についての詳細な説明は記事の最後の方に公式サイトへのリンクを貼りますので、興味ある方はぜひ見てみてください!</p>
<h1>概要</h1>
<p>冒頭で書いた「ある案件」とは、チームプロジェクトで「ログ収集基盤のサーバーレス化」というものがありまして、そのうちの1つである「バックアップデータからログの再収集」を意味します。</p>
<p>まず、ログ収集基盤のサーバーレス化の基本的な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>をお見せします。</p>
<p><figure class="figure-image figure-image-fotolife" title="ログ収集基盤のログ転送フロー(通常)"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200826/20200826165138.png" alt="f:id:allabout-techblog:20200826165138p:plain" title="f:id:allabout-techblog:20200826165138p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>ログ収集基盤のログ転送フロー(通常)</figcaption></figure></p>
<p>図の通りにウェブから発生したログは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud Run(以降、Cloud Run)で受け入れて最終的にはTreasure Dataと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> BigQuery(以降、BigQuery)まで流れていきます。<br />
また、Cloud Runから<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud Dataflow(以降、Dataflow)までのデータ転送にはネットワーク上の通信の高速化のためにProtocol Buffersを使ってデータ通信を行います。(Protocol Buffersは通信の高速化以外にもいくつかのメリットがありますが、本題とずれるので詳細については記事の最後の方に貼ってある公式サイトへのリンクをご確認ください。)<br />
なお、Cloud Runが受け入れたログはバックアップとしてBigQueryのあるテーブルへ格納します。その際のフォーマットは、Cloud Runから<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud Pub/sub(以降、Pubsub)へ転送する、Protocol Buffersにて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%EA%A5%A2%A5%E9%A5%A4%A5%BA">シリアライズ</a>されたフォーマットのままにしてます。<br />
このBigQueryへ格納するバックアップデータが「ログの再収集」の肝になりまして、PubsubやDataflowに障害が発生した場合、このバックアップデータから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%AB%A5%D0%A5%EA">リカバリ</a>ーが可能になります。</p>
<p>ここからが本題で、Cloud Functionsの導入に伴う下記の2点について紹介させていただきたいと思います。 <br />
- <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%AB%A5%D0%A5%EA">リカバリ</a>ー処理(BigQueryからデータを取得して~)<br />
- Cloud Functionsのソース管理及びデプロイ</p>
<p>通常時と比べて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%AB%A5%D0%A5%EA">リカバリ</a>ー時のイメージは下記の図のようになります。</p>
<p><figure class="figure-image figure-image-fotolife" title="ログ収集基盤のログ転送フロー(リカバリー)"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200826/20200826165207.png" alt="f:id:allabout-techblog:20200826165207p:plain" title="f:id:allabout-techblog:20200826165207p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>ログ収集基盤のログ転送フロー(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%AB%A5%D0%A5%EA">リカバリ</a>ー)</figcaption></figure></p>
<p>それでは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%AB%A5%D0%A5%EA">リカバリ</a>ー処理から見てまいりましょう!</p>
<h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%AB%A5%D0%A5%EA">リカバリ</a>ー処理</h1>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%AB%A5%D0%A5%EA">リカバリ</a>ー処理自体はシンプルで、BigQueryへ格納されているバックアップデータを取得して、通常処理のPubsubへ投げる、だけになります。</p>
<ul>
<li>BigQueryへバックアップされたデータは通常処理でPubsubが扱うデータと同じフォーマットとなっている</li>
<li>PubsubとDataflowはオートスケールできるため、通常処理に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%AB%A5%D0%A5%EA">リカバリ</a>ー処理をかぶせても負荷的な影響はない</li>
</ul>
<p>実際の処理負荷に対しては気になるところだと思いますが、その詳細につきましてはここでは割愛させていただき、別の機会でご紹介できればと思います。</p>
<h2>Cloud Functions設定情報</h2>
<p>今回のCloud Functionsの設定情報は下記のようになります。</p>
<ul>
<li>トリガー : HTTP</li>
<li>ランタイム : Go 1.13</li>
</ul>
<p>また、内部的には<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>関連いくつかの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%C4%B6%AD%CA%D1%BF%F4">環境変数</a>とあわせて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%AB%A5%D0%A5%EA">リカバリ</a>ー用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%C4%B6%AD%CA%D1%BF%F4">環境変数</a>も設定してソースの中で参照することにしています。</p>
<h2>必要なIAMロール</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%AB%A5%D0%A5%EA">リカバリ</a>ーではサービスアカウントを使いますが、そのサービスアカウントに必要なIAMロールは下記になります。各ロールに詳しい方も多いと思いますが、補足として簡単な説明も記載させていただきます。</p>
<ul>
<li>bigquery.jobs.create : プロジェクト内でジョブ(クエリを含む)を実行する権限。</li>
<li>pubsub.topics.publish : 1つ以上のメッセージをトピックへ追加する権限。</li>
<li>cloudfunctions.functions.setIamPolicy : 未承認の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D9%A5%ED%A5%C3%A5%D1">デベロッパ</a>ーによる該当Functionsへの権限変更を防ぐために、該当Functionsをデプロイするユーザーまたはサービスに与える権限。</li>
</ul>
<h2>ファイル構成</h2>
<ul>
<li>functions.go : メイン処理</li>
<li>go.mod : go言語の依存モジュール管理ファイル</li>
</ul>
<h2>処理の流れ</h2>
<p>基本的な処理の流れは下記のようになります。</p>
<p>1.トリガーでCloud Functionsの実行対象関数が呼び出される<br />
2.BigQueryからデータを取得し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Iterator">Iterator</a>を回してPubsubへメッセージを送る関数へデータを渡す<br />
3.Pubsubへメッセージを送る</p>
<h2>ソース</h2>
<p>バックアップデータからログの再収集を行うソースを全部載せると記事が長くなりますので、流れが把握できる範囲で紹介させていただきます(エラー処理もすべて省きます)。</p>
<p>functions.go</p>
<pre class="code functions.go" data-lang="functions.go" data-unlink>package p
import (
~省略~
"cloud.google.com/go/bigquery"
"cloud.google.com/go/pubsub"
"google.golang.org/api/iterator"
)
// ①Cloud Functionsでエンドポイントとして使われる関数
func EndPoint(w http.ResponseWriter, r *http.Request) {
// BigQueryからデータを取得し、1行ずつPubsubへメッセージを送る
fetchBigQueryData()
}
// ②BigQueryからデータを取得し、Iteratorを回してPubsubへメッセージを送る関数へデータを渡す
func fetchBigQueryData() {
ctx := context.Background()
client, err := bigquery.NewClient(ctx, {GCP_ID})
defer client.Close()
// バックアップデータ取得用クエリ設定
q := client.Query({SQL})
// 実行のためのqueryをサービスに送信してIteratorを通じて結果を返す
// itはIterator
it, err := q.Read(ctx)
for {
var tc {BQTableColumns 構造体}
// 引数に与えたtcにnextを格納する
// Iteratorを返す
// これ以上結果が存在しない場合には、iterator.Doneを返す
// iterator.Doneが返ってきたら、forを抜ける
err := it.Next(&tc)
if err == iterator.Done {
break
}
// pubsubへメッセージを送る
sendPubsubMessage(&tc)
}
}
// ③pubsubへメッセージを送る
func sendPubsubMessage(tc *{BQTableColumns 構造体}) {
msg := &pubsub.Message{
Data: tc.Message,
}
ctx := context.Background()
if _, err := {Pubsubのtopicインスタンス}.Publish(ctx, msg).Get(ctx); err != nil {
return
}
}
</pre>
<p>go.mod</p>
<pre class="code go.mod" data-lang="go.mod" data-unlink>module DOMAIN/MODULE_NAME
go 1.13
require (
cloud.google.com/go/bigquery v1.10.0
cloud.google.com/go/pubsub v1.6.1
google.golang.org/api v0.30.0
)</pre>
<h1>Cloud Functionsのソース管理及びデプロイ</h1>
<p>Cloud Functionsはサーバーリソースを各自が管理しなくても良いメリットがあります。<br />
その代わりにというのも不適切かもしれませんが、CloudFunctions上で動かせるソースの管理をどうするか、また、デプロイはどうするかを検討しないといけません。<br />
自分にとっては初のCloudFunctionsだったので、一旦検証時に利用したソース管理とデプロイ手順を紹介させていただきます。</p>
<h2>Cloud Functionsへのソース反映方法</h2>
<p>Cloud Functionsへのソース反映はCloud FunctionsのウェブUIからも確認できるように、下記の4種類があります。</p>
<ul>
<li>Inline Editor</li>
<li>ZIP Upload</li>
<li>ZIP from Cloud Storage</li>
<li>Cloud Source repository</li>
</ul>
<p>Inline Editorの場合はウェブUIから直接ファイルを更新するパターンなので、ソース管理ができない問題があります。<br />
ZIPを利用する方法も、ソース管理ツールからファイルをダウンロードして、ZIP圧縮して、等の遠回りをすればある程度のソース管理はできますが、手間が増えるし、ミスも増える可能性があります。<br />
Cloud Source repositoryは<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>上でのソース管理サービスです。このサービスにはなんと!他のソース管理ツールへの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DF%A5%E9%A1%BC%A5%EA%A5%F3%A5%B0">ミラーリング</a>機能があったので、今回はCloud Source repositoryを使ってみることにしました。 <br />
※現時点で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DF%A5%E9%A1%BC%A5%EA%A5%F3%A5%B0">ミラーリング</a>できるのは「<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a>」と「Bitbucket」の2種類のみですので他のソース管理ツールをご利用中の場合にはご注意ください。</p>
<h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DF%A5%E9%A1%BC%A5%EA%A5%F3%A5%B0">ミラーリング</a>設定</h2>
<p>弊社ではBitbucketを使ってソース管理を行っているので、下記公式サイトの説明に従って<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DF%A5%E9%A1%BC%A5%EA%A5%F3%A5%B0">ミラーリング</a>設定を行いました。<br />
<a href="https://cloud.google.com/source-repositories/docs/mirroring-a-bitbucket-repository?hl=ja">Bitbucket リポジトリのミラーリング</a></p>
<h2>デプロイ</h2>
<p>まずは、Bitbucketの該当<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>へ今回のソースをcommitしました。<br />
そのあと、Cloud Source repositoryの該当<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DF%A5%E9%A1%BC%A5%EA%A5%F3%A5%B0">ミラーリング</a>が正常にできたことを確認したので、gcloudコマンドを使ってCloudFunctionsへデプロイを試してみました。</p>
<p>gcloudコマンドを使ってのデプロイは下記公式ドキュメントに詳細が載っているので参考しながらコマンドを書きました。</p>
<p><a href="https://cloud.google.com/functions/docs/deploying/repo?hl=ja">ソース コントロールからのデプロイ</a></p>
<pre class="code" data-lang="" data-unlink>gcloud functions deploy CLOUD_FUNCTION_NAME \
--region REGION_ID \
--source https://source.developers.google.com/projects/PROJECT_ID/repos/REPOSITORY_ID/moveable-aliases/master/paths/SOURCE \
--runtime go113 \
--service-account=SERVICE_ACCOUNT@appspot.gserviceaccount.com \
--trigger-http \
--set-env-vars HOGEHOHE=AAA,FUGAFUGA=BBB… \
--entry_point ENTRY_POINT \</pre>
<p>基本的には公式ドキュメントに従って書けば問題なくデプロイできることを確認しました。<br />
また、「--runtime」オプションは該当Functionを最初に作るときに指定すれば良くて、そのあとからは該当オプションをしないことで同じFunctionへの更新になります。</p>
<h1>おわりに</h1>
<p>Cloud Runと比べてCloud Functionsはコンテナイメージのメンテナンスが不要というメリットがあります。<br />
通常のログ収集処理はCloud Runで行うことにしましたが、めったに発生しないであろうログの再収集処理はCloud Functionsで行うことで、メンテナンスコストが節約できると思います。 <br />
また、今回は「HTTPトリガー」を試してみましたが、Cloud Functionsには「HTTPトリガー」以外にも「Cloud Pub/Subトリガー」や「Cloud Storageトリガー」もあるので、今後それらも試してみたいと思います。<br />
デプロイについても、今回はgcloudコマンドでの手動デプロイを試してみましたが、近いうちにCircleCIからの完全自動デプロイも試してみたいと思ってます。</p>
<p>今後ともよろしくお願いいたします。</p>
<h1>参考サイト</h1>
<h2>公式サイト</h2>
<ul>
<li><a href="https://cloud.google.com/functions/docs/concepts/overview">Google Cloud Functions</a></li>
<li><a href="https://cloud.google.com/run">Google Cloud Run</a></li>
<li><a href="https://www.treasuredata.co.jp">Treasure Data</a></li>
<li><a href="https://cloud.google.com/bigquery">Google BigQuery</a></li>
<li><a href="https://cloud.google.com/dataflow">Google Cloud Dataflow</a></li>
<li><a href="https://developers.google.com/protocol-buffers">Protocol Buffers</a></li>
<li><a href="https://circleci.com/ja/">CircleCI</a></li>
</ul>
<h2>ブログ等</h2>
<p><a href="https://qiita.com/Sekky0905/items/fd6ff9113d301aaa9e1d">GoでBigQueryクライアントを実装してBigQueryからデータを取得する</a></p>
allabout-techblog
Cloud RunからCloud SQLやMemorystoreへの繋ぎ方
hatenablog://entry/26006613591554550
2020-06-30T13:38:59+09:00
2020-06-30T13:40:07+09:00 こんにちは!@y_hideshi です。 今回はCloud RunからCloud SQLやMemorystoreにつなぐ方法について紹介します。 Cloud SQLへの接続方法 Memorystoreへの接続方法 Cloud SQLへの接続方法 検証のため、phpMyAdminからCloud SQLにつなぐシンプルな構成のシステムを作ります。 Cloud Run - Cloud SQL
<p>こんにちは!<a href="https://qiita.com/y_hideshi">@y_hideshi</a> です。</p>
<p>今回はCloud RunからCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>やMemorystoreにつなぐ方法について紹介します。</p>
<ul>
<li>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>への接続方法</li>
<li>Memorystoreへの接続方法</li>
</ul>
<h2>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>への接続方法</h2>
<p>検証のため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/phpMyAdmin">phpMyAdmin</a>からCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>につなぐシンプルな構成のシステムを作ります。</p>
<p><figure class="figure-image figure-image-fotolife" title="Cloud Run - Cloud SQL"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200629/20200629200338.png" alt="f:id:allabout-techblog:20200629200338p:plain" title="f:id:allabout-techblog:20200629200338p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Cloud Run - Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a></figcaption></figure></p>
<h3>事前準備</h3>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/phpMyAdmin">phpMyAdmin</a>イメージの用意</li>
<li>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>の用意</li>
<li>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a> Admin <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の有効化</li>
</ul>
<h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/phpMyAdmin">phpMyAdmin</a>イメージの用意</h4>
<p>イメージのダウンロード</p>
<pre class="code bash" data-lang="bash" data-unlink>docker pull phpmyadmin/phpmyadmin:latest</pre>
<p>そのままだとCloud Runのサービス作成時に止まってしまいます。そのため、こちらのサイトを参考に修正します。</p>
<p><a href="https://techblog.gmo-ap.jp/2020/03/10/cloudrun-phpmyadmin/">早い!簡単!30分でCloud Runを使ってphpMyAdmin環境構築!</a></p>
<p>詳細は上記ページをみていただけるとわかるので割愛しますが、下記のことを行いました</p>
<ul>
<li>000-default.confの修正</li>
<li>config.secret.inc.<a class="keyword" href="http://d.hatena.ne.jp/keyword/php">php</a>の修正</li>
<li>docker-entrypoint.shの修正</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/ports">ports</a>.confの修正</li>
<li>上記のファイルを<a class="keyword" href="http://d.hatena.ne.jp/keyword/phpmyadmin">phpmyadmin</a>イメージに組み込むためのDockerfile用意</li>
</ul>
<p>各種ファイルを用意できたらイメージをbuildして、GCRにpushしておきます</p>
<pre class="code bash" data-lang="bash" data-unlink>docker build -t cloudrun-phpmyadmin:latest .
docker tag cloudrun-phpmyadmin:latest asia.gcr.io/プロジェクト名/phpmyadmin:latest
docker push asia.gcr.io/プロジェクト名/phpmyadmin:latest</pre>
<p>これでイメージの準備は終わりです。</p>
<h4>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>の用意</h4>
<p>こちらはなんでもいいので、とりあえず適当に最小限の構成で作っておきます。</p>
<pre class="code" data-lang="" data-unlink>gcloud sql instances create cloud-runt-test \
--database-version=MYSQL_5_7 \
--region=asia-northeast1 \
--storage-size=10 \
--storage-type=HDD \
--tier=db-f1-micro \
--root-password=password123</pre>
<h4>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a> Admin <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の有効化</h4>
<blockquote><p>Cloud Run(フルマネージド)には、Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a> Admin <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> を使用する Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a> Proxy を使用して接続するメ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A5%CB">カニ</a>ズムが用意されています。Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a> Proxy には <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> 割り当て上限が適用されます。</p></blockquote>
<p><a href="https://cloud.google.com/sql/docs/mysql/connect-run?hl=ja">公式ページ</a>にある通り、Cloud RunからCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>に接続する際は <code>Cloud SQL Admin API</code> を使用するので有効化しておきます。</p>
<p><figure class="figure-image figure-image-fotolife" title="Cloud SQL Admin API"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200629/20200629165332.png" alt="f:id:allabout-techblog:20200629165332p:plain" title="f:id:allabout-techblog:20200629165332p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a> Admin <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a></figcaption></figure></p>
<h3>Cloud Runのサービスデプロイ</h3>
<p>Cloud RunからCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>への接続は <code>Cloud SQL Proxy</code> を利用して接続するため、<code>--add-cloudsql-instances</code> オプションを追加してサービスデプロイを行います。
また、<code>Cloud SQL Proxy</code> を利用するにあたり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/phpMyAdmin">phpMyAdmin</a>からの接続は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Unix">Unix</a> Socketを利用するようになるため <a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%C4%B6%AD%CA%D1%BF%F4">環境変数</a>を <code>---set-env-vars</code> で追加しています。</p>
<p>指定している <code>INSTANCE_CONNECTION_NAME</code> は 下記のような書き方になっており、gcloudコマンドかCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>の詳細ページで確認することができます。</p>
<pre class="code" data-lang="" data-unlink>PROJECT_ID:REGION:INSTANCE_ID</pre>
<p>Cloud Run デプロイコマンド</p>
<pre class="code bash" data-lang="bash" data-unlink>$ gcloud run deploy phpmyadmin \
--image asia.gcr.io/プロジェクト名/phpmyadmin:latest \
--region asia-northeast1 \
--platform=managed \
--allow-unauthenticated \
--add-cloudsql-instances [INSTANCE_CONNECTION_NAME] \
--set-env-vars=PMA_HOST=/cloudsql/[INSTANCE_CONNECTION_NAME] \
--set-env-vars=PMA_SOCKET=/cloudsql/[INSTANCE_CONNECTION_NAME]</pre>
<p>サービスデプロイ後、生成されるURLにアクセスして<a class="keyword" href="http://d.hatena.ne.jp/keyword/phpMyAdmin">phpMyAdmin</a>からCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>にアクセスできるか確認します。</p>
<p><figure class="figure-image figure-image-fotolife" title="phpMyAdmin 画面確認"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200629/20200629165204.png" alt="f:id:allabout-techblog:20200629165204p:plain" title="f:id:allabout-techblog:20200629165204p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption><a class="keyword" href="http://d.hatena.ne.jp/keyword/phpMyAdmin">phpMyAdmin</a>による確認</figcaption></figure></p>
<h3>まとめ</h3>
<p>Cloud RunからCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>に接続する際、下記の点に気をつけてさえいればDBにすぐに接続できると思いますのでぜひ試してみください。</p>
<ul>
<li>Cloud RunからCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>への接続は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Unix">Unix</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>ソケットを使用して <code>Cloud SQL Proxy</code>で接続する
<ul>
<li><a href="https://cloud.google.com/sql/docs/mysql/connect-run?hl=ja#go">公式ページ</a>をみたところ<a class="keyword" href="http://d.hatena.ne.jp/keyword/TCP">TCP</a>での接続はサポートされていない模様</li>
</ul>
</li>
<li><code>Cloud SQL Proxy</code> を使用して接続する <code>Cloud SQL Admin API</code> を利用するので有効化しておく</li>
<li>Cloud Runで指定するサービスアカウントはCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>のロールと権限を割り当てておく</li>
</ul>
<h2>Memorystoreへの接続方法</h2>
<p>CloudSQL接続できるようになったので、今度はMemorystoreに接続してみます。
Cloud RunからMemorystoreに接続できることを検証するため、コンテナのイメージには<a href="https://hub.docker.com/r/erikdubbelboer/phpredisadmin/tags">erikdubbelboer/phpredisadmin</a>を利用します。</p>
<p>また、Cloud RunからMemorystoreに接続するにはサーバーレス <a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a> アクセス コネクタが必要となってくるため、そちらも用意します。</p>
<p><figure class="figure-image figure-image-fotolife" title="Cloud Run - Memorystore"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200629/20200629200315.png" alt="f:id:allabout-techblog:20200629200315p:plain" title="f:id:allabout-techblog:20200629200315p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Cloud Run - Memorystore</figcaption></figure></p>
<h3>事前準備</h3>
<ul>
<li>Memorystoreの用意</li>
<li>サーバーレス <a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a> アクセス コネクタの用意</li>
</ul>
<h4>Memorystoreの用意</h4>
<p>お金をあまりかけたくないので、最小構成でMemorystoreを構築します。</p>
<pre class="code bash" data-lang="bash" data-unlink>$ gcloud redis instances create cloudrun-test \
--size=1 \
--region=asia-northeast1 \
--network=projects/プロジェクトID/global/networks/ネットワーク名
--connect-mode=private-service-access</pre>
<h4>サーバーレス <a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a> アクセス コネクタの用意</h4>
<h5>Serverless <a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Access">Access</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> 有効化</h5>
<p>初めてサーバーレス <a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a> アクセス コネクタを作る場合は、こちらの<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を有効化する必要があるので有効化します。</p>
<p><figure class="figure-image figure-image-fotolife" title="Serverless VPC Access API"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200629/20200629165112.png" alt="f:id:allabout-techblog:20200629165112p:plain" title="f:id:allabout-techblog:20200629165112p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Serverless <a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Access">Access</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a></figcaption></figure></p>
<h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a>コネクタ作成</h5>
<blockquote><p>コネクタは、接続先のサーバーレス サービスと同じプロジェクトとリージョンに配置する必要があります</p></blockquote>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>の公式に従い、Memorystoreと同じリージョンに<a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a> コネクタを構築します。
今回はgcloudコマンドで構築していきます。画面からの構築する際もgcloudコマンドで構築する際もオプションが大切になってきますので、各オプションについて紹介していきます。</p>
<p>gcloudコマンドによる作成</p>
<pre class="code bash" data-lang="bash" data-unlink>$ gcloud compute networks vpc-access connectors create cloudrun-test \
--network [接続元VPCネットワーク] \
--region [VPCコネクタが配置されるリージョン] \
--range [予約されていない/28のIPレンジ]</pre>
<p>オプション詳細</p>
<table>
<thead>
<tr>
<th> オプション </th>
<th> 設定する概要 </th>
<th> オプション </th>
</tr>
</thead>
<tbody>
<tr>
<td> network </td>
<td> 接続元になる<a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a>ネットワーク </td>
<td> 必須 </td>
</tr>
<tr>
<td> region </td>
<td> Cloud Runが所属するリージョン </td>
<td> 必須 </td>
</tr>
<tr>
<td> range </td>
<td> <a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>プロジェクト中で利用されていないネットワーク<br>(/28でなければならない) </td>
<td> 必須 </td>
</tr>
<tr>
<td> min-throughput </td>
<td> <a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a>コネクタ経由時の最小<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%EB%A1%BC%A5%D7%A5%C3%A5%C8">スループット</a>(default=200) </td>
<td> 任意 </td>
</tr>
<tr>
<td> max-throughput </td>
<td> <a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a>コネクタ経由時の最大<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%EB%A1%BC%A5%D7%A5%C3%A5%C8">スループット</a>(default=300) </td>
<td> 任意 </td>
</tr>
</tbody>
</table>
<p>※ 設定のポイント
<a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a>コネクタの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%EB%A1%BC%A5%D7%A5%C3%A5%C8">スループット</a>は指定範囲内でスケールアップするが、スケールダウンはしない点に注意します。</p>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a>コネクタの確認</p>
<p>describeコマンドで<a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a>コネクタの設定を確認できます。</p>
<pre class="code bash" data-lang="bash" data-unlink>$ gcloud compute networks vpc-access connectors describe cloudrun-test --region リージョン
ipCidrRange: 指定したIP範囲
maxThroughput: 300
minThroughput: 200
name: projects/プロジェクトID/locations/リージョン/connectors/VPCコネクタの名前
network: 指定したネットワーク名
state: READY</pre>
<h4>phpredisadminの用意</h4>
<p>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>の時と同様に使用するイメージをGCRに上げておきます。</p>
<pre class="code" data-lang="" data-unlink>docker pull erikdubbelboer/phpredisadmin:latest
docker tag erikdubbelboer/phpredisadmin:latest asia.gcr.io/プロジェクト名/phpredisadmin:latest
docker push asia.gcr.io/プロジェクト名/phpredisadmin:latest</pre>
<h3>Cloud Runにデプロイ</h3>
<pre class="code bash" data-lang="bash" data-unlink>$ gcloud beta run deploy phpredisadmin \
--image asia.gcr.io/プロジェクトID/phpredisadmin:latest \
--port 80 \
--vpc-connector cloudrun-test \
--platform managed \
--region リージョン \
--allow-unauthenticated \
--set-env-vars REDIS_1_HOST=[MeomorystoreのIPアドレス] \
--set-env-vars REDIS_1_NAME=MemoryStore \
--set-env-vars REDIS_1_PORT=6379 \
--set-env-vars REDIS_1_DATABASES=1</pre>
<p>※ データベースを指定しないと動作しなかったので指定しています。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>をちゃんとおっていないので明確な原因は説明できませんが、 <code>REDIS_1_DATABASES</code> を指定していない、または、 <code>REDIS_1_DATABASES</code> が <code>0</code> の時は動作しませんでした。</p>
<p><figure class="figure-image figure-image-fotolife" title="phpredisadmin 画面確認"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200629/20200629165458.png" alt="f:id:allabout-techblog:20200629165458p:plain" title="f:id:allabout-techblog:20200629165458p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>phpredisadmin</figcaption></figure></p>
<h3>まとめ</h3>
<p>Cloud RunからMemorystoreに接続する際は下記の点を押さえておけば容易に接続できると思います。</p>
<ul>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a>コネクタはMemorystoreと同じリージョンに配置する</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a>コネクタが所属する<a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a>ネットワークは関連するサービスと同じ<a class="keyword" href="http://d.hatena.ne.jp/keyword/VPC">VPC</a>ネットワークにする</li>
</ul>
<h2>全体のまとめ</h2>
<p>今回は、Cloud RunからCloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>やMemorystoreに接続する方法を紹介しました。
<a class="keyword" href="http://d.hatena.ne.jp/keyword/phpmyadmin">phpmyadmin</a>・phpredisadminイメージ周りの設定で時間がかかってしまいましたが、シンプルな構造でフルマネージメントなサーバレスシステムを構築できます。
少し問題の切り分けがしづらいと感じることもあるかもしれませんが、困ったときはStackdriver loggingなどを見ながら検証を行っていきましょう!</p>
<p>今度はCloud Runにカスタム<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>を割り当てる方法を実際の設定画面などを見せつつ紹介できていけたらと考えています!</p>
<p>今後ともよろしくお願いいたします。</p>
<h2>参考サイト</h2>
<h3>Cloud <a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>への接続方法</h3>
<ul>
<li><a href="https://hub.docker.com/r/phpmyadmin/phpmyadmin">phpMyAdminのイメージ</a></li>
<li><a href="https://cloud.google.com/sql/docs/mysql/connect-run?hl=ja">Cloud Run(フルマネージド)から Cloud SQL に接続する</a></li>
<li><a href="https://techblog.gmo-ap.jp/2020/03/10/cloudrun-phpmyadmin/">早い!簡単!30分でCloud Runを使ってphpMyAdmin環境構築!</a></li>
<li><a href="https://cloud.google.com/sdk/gcloud/reference/run/deploy">gcloud run deploy</a></li>
<li><a href="https://cloud.google.com/sdk/gcloud/reference/sql/instances/create?hl=ja#--root-password">gcloud sql instances create</a></li>
</ul>
<h3>Memorystoreへの接続方法</h3>
<ul>
<li><a href="https://cloud.google.com/run/docs/using-gcp-services?hl=ja">VPC ネットワークへの接続</a></li>
<li><a href="https://hub.docker.com/r/erikdubbelboer/phpredisadmin/">erikdubbelboer/phpredisadmin</a></li>
</ul>
allabout-techblog
データ活用を推進しようとしているお話
hatenablog://entry/26006613574332195
2020-05-29T11:04:21+09:00
2020-05-29T11:04:21+09:00 はじめに 初めまして、オールアバウトの @akidukin(@Akidukin14) です。 この度上手く出来たら noteで公開しようと思っていた内容を 「自社のtechblogで書いてよー」と低めに脅された依頼されたので、気持ちよく執筆させていただくことにしました。 初めてTechBlogを執筆させていただきますので、簡単に私がどんな業務を担当しているのかを説明させて下さい。 興味が無い人は ## 何をしようとしているのかの説明 に飛んでください。(データサイエンティストとして仕事している人なんだなーって認識を持っていただけたら十分です。) 人 : @akidukin14 https://…
<h2>はじめに</h2>
<p>初めまして、オールアバウトの @akidukin(@Akidukin14) です。
この度上手く出来たら noteで公開しようと思っていた内容を 「自社のtechblogで書いてよー」と<del>低めに脅された</del>依頼されたので、気持ちよく執筆させていただくことにしました。</p>
<p>初めてTechBlogを執筆させていただきますので、簡単に私がどんな業務を担当しているのかを説明させて下さい。</p>
<p>興味が無い人は <strong>## 何をしようとしているのかの説明</strong> に飛んでください。(データサイエンティストとして仕事している人なんだなーって認識を持っていただけたら十分です。)</p>
<p><strong>人</strong> : @akidukin14 <a href="https://twitter.com/Akidukin14">https://twitter.com/Akidukin14</a><br />
<strong>出身</strong> : 福岡<br />
<strong>現所属</strong> : 株式会社オールアバウト 開発部 <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>開発 データサイエンティスト</p>
<p><strong>主な業務</strong> :<br />
【ちょっと前まで】</p>
<ul>
<li>広告配信に利用している<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A1%B3%A3%B3%D8%BD%AC">機械学習</a>の改善</li>
<li>営業向け 資料の拡充</li>
<li>広告配信のレポーティングの拡充 ... 等</li>
</ul>
<p>【現在】</p>
<ul>
<li>株式会社オールアバウト全体にデータ活用やっていきましょうよー と話しまわっている(非公認)</li>
<li>出てきた活用案をプロジェクト化して
<ul>
<li>PMしたり</li>
<li>分析で実際に手を動かしたり</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%C3%A5%B7%A5%E5">ダッシュ</a>ボード作ってみたり</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A1%B3%A3%B3%D8%BD%AC">機械学習</a>のPoC回してみたり</li>
<li>一般で利用できるようにツール化したり ... 等</li>
</ul>
</li>
</ul>
<p>今回は 【現在】主に対応している物についてご紹介しようと思います。</p>
<h2>何をしようとしているのかの説明</h2>
<p>タイトルの通り「株式会社オールアバウトの各部署のデータ活用を推進しよう」としています。</p>
<p>きっとこの記事を読んで頂いている方は<br />
「会社としてデータ活用を推進していく共通意思があって進めているんだ...!!」<br />
と思われるかもしれませんが、凄く雑に言うと 個人的に <del>暇だから</del> やってみたいので進めています。</p>
<p>オールアバウトグループという単位でどんなサービスを運営しているかを簡単に説明します。</p>
<ul>
<li>株式会社オールアバウト : メディア運営 / タイアップ広告配信の運営</li>
<li>株式会社オールアバウトライフ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a> : <a class="keyword" href="http://d.hatena.ne.jp/keyword/EC%A5%B5%A5%A4%A5%C8">ECサイト</a>運営</li>
<li>株式会社オールアバウトナビ : <a class="keyword" href="http://d.hatena.ne.jp/keyword/SNS">SNS</a>を利用したエンタメ事業の運営</li>
<li>日テレライフ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>株式会社 : ECとTV放送を連動させた事業の運営</li>
<li>株式会社オールアバウトライフワークス : 講師育成や教室運営サービスの運営</li>
</ul>
<p>様々なサービスの運営をしており、データアナリストやデータサイエンティストといったデータを触る方々からすると垂涎物な環境なのかなーって思います。<br />
(違う業種違う情報 のデータが比較的豊富に取得できる点が)</p>
<p>今回、データ活用を推進しようとしているのは メディア運営 / タイアップ広告配信運営 の事業領域になります。</p>
<p>※...データ活用 : データソースの整理や掃除、から、実際にデータ分析 ~ 機能の提供 を対象のイメージとしております。</p>
<h2>現在のデータ活用フェーズについて</h2>
<p>そもそも、現在 株式会社オールアバウト ではデータの活用が全く進んでいないのかというと、そういうわけではありません。<br />
メディア運営に於いては<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Analytics">Google Analytics</a>が社内にかなり浸透し各自でDataportal等を使っていたり、タイアップ広告配信ではTreasureDataにデータがたまっており、タイアップごとの効果測定等にもデータを利用してたりします。<br />
<a class="keyword" href="http://d.hatena.ne.jp/keyword/EC%A5%B5%A5%A4%A5%C8">ECサイト</a>を運営しているオールアバウトライフ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A1%BC%A5%B1%A5%C6%A5%A3%A5%F3%A5%B0">マーケティング</a>ではRe:dashを利用して定常的に数値を追う環境もあったりします。</p>
<p>しかし、データの活用度合いが個人の知見に任せされていたり、情報の共有があまりされていなかったり、形骸的にデータを見るだけになっていたりしていました。<br />
いくつかの業務の中では<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%EA%CE%CC">定量</a>的ではなく定性的な判断をすることが常になっている業務、人の知見を元に判断をしている業務等がある。。。<br />
というのが現在の 株式会社オールアバウト のデータ活用のフェーズになります。<br />
イメージは伝わりますかね...??</p>
<p>現在のフェーズにおいて、実際に作業にあたっている方やその上司の方々は大なり小なり課題感は抱えており、今までその部分に介入する+出来る人的リソースが無かった というのが背景になります。</p>
<p>「あれ??これデータ活用進めたら、強力に売り上げ貢献とか利益貢献出来るんじゃね??」</p>
<p><figure class="figure-image figure-image-fotolife" title="イメージ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200528/20200528104258.png" alt="f:id:allabout-techblog:20200528104258p:plain" title="f:id:allabout-techblog:20200528104258p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>イメージ</figcaption></figure></p>
<h2>どう進めているのか</h2>
<p>実際にどのようにデータ活用を推進しているのかという点について、説明させてください。<br />
プロジェクトが動き始めたのが4月からでした。</p>
<p>基本的には</p>
<ol>
<li>各グループの上長や担当者にデータを利用してやってみたい事を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D2%A5%A2%A5%EA">ヒアリ</a>ング</li>
<li>データ環境の情報整理</li>
<li>優先順位付け、プロジェクト化</li>
<li>分析案や仮説のブレスト</li>
<li>タスク化</li>
<li>分析作業及び報告</li>
</ol>
<p>という流れで進めています。</p>
<p>元々各<a class="keyword" href="http://d.hatena.ne.jp/keyword/GM">GM</a>や担当者はデータに対しての理解度が高かったのですが、<strong>データを使って何が出来るか分からない</strong>という壁がありました。</p>
<p>そこで、テーマを「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E9%A4%A8%A4%E2%A4%F3">ドラえもん</a>」に設定し、「あんなこっと良いな、出来たら良いな、不思議なデータで叶えてあっげっるー」という理想ドリブンでそれぞれやってみたい事を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D2%A5%A2%A5%EA">ヒアリ</a>ングしていきました。<br />
この時、<strong>ooを解決したい!!</strong>みたいな形ではなく、<strong>ooがxxみたいになればいいのになー。</strong>という形でふんわりした内容を上げてもらって、それを詳細に詰めていくという導入から始めました。</p>
<p>やりたい事いっぱい出た。<br />
中には<strong>「知見に基づいてやっている作業の自動化が出来たら凄く嬉しい。」</strong>等も出てきて狙い通りでした。</p>
<p>そして、出てきたものに対して、優先順位をつけ PO(プロジェクトオーナー) を付け、プロジェクト化を行いました。</p>
<p>その後、どういった分析をすれば実現できるのか、や、どういったデータを見れば示唆が出そうなのかのブレストを行い、タスクへ落とし込み、分析の作業に移ります。</p>
<p>データ活用するにあたって、壁になる事の一つに担当者と作業者間の期待値コン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB">トロール</a>があると思います。<br />
正直最初は「理想ドリブンでプロジェクト立ち上げちゃったけど、期待値コン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB">トロール</a>どうしよう...」と悩んでいました。<br />
期待値が凄く実現性と離れた時は、ミーティング外での啓蒙活動やミーティング自体の開催頻度を上げて細かくOUTPUTを出しつつ期待値や結果を下げていく方向へ持っていこうと考えてたりしました。<br />
が、そんな心配が具現することなく、思ってたより大丈夫だった(今後出て来るかもしれませんが...)</p>
<h2>こうしたい未来のお話</h2>
<p>まだ走り出したばかりで100年後も変わらず、こう思っているかと言われると自信は無いですが、、、</p>
<p>将来的には グループ会社全体でデータ活用なら @akidukin (または付随するその組織)に相談してみよう、となるのが理想です。<br />
後はニーズをくみ取りながら、効果的な機能の提供を自発的に出来るようになるともっと嬉しい。企画 ~ 提供を一手に担える</p>
<p>受けた相談を元に実際にデータを見てみたり、分析してみたり、結果を元に改善案や何かしらの機能提供まで出来るようになったら良いです。みんな幸せHappy</p>
<p>上記のような理想に対してはまだまだ溝があり(始めたばかりなので当たり前ですが)、その溝を埋めるためにこんなロードマップを考えています。</p>
<ol>
<li>こちらからデータ活用についてのニーズの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D2%A5%A2%A5%EA">ヒアリ</a>ングを行い、プロジェクト化 <- <strong>イマココ</strong></li>
<li>プロジェクトに対して対応、及び改善案の提案や実施</li>
<li>良いor悪い影響の社内共有</li>
<li>メディア運営 / タイアップ広告配信運営 以外の事業領域へデータ活用についてのニーズの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D2%A5%A2%A5%EA">ヒアリ</a>ング、プロジェクト化</li>
<li>プロジェクトに対して対応、及び改善案の提案や実施</li>
<li>良いor悪い影響の社内共有</li>
<li>... ぐーるぐる回す</li>
<li>ニーズの策定 + 企画立案 + 企画試行</li>
</ol>
<p>まずは ご用聞き -> 誠実に対応 -> 正しく結果を共有 のサイクルを繰り返してデータを使う事の効果を知ってもらう
(と同時にそれぞれの事業部で何をしているのかをより深く知る)
その後、生まれそうなニーズや生まれたニーズを元に改善できそうな部分を考えていく。 という大まかな流れになるかなーと妄想しています。</p>
<p>きっとその間で、</p>
<ul>
<li>一緒に分析を進めてくれる人達のレベルアップとか</li>
<li>一緒に実装を進めてくれる人達のレベルアップとか</li>
<li>どうやって膨大になっていくプロジェクトを適宜割り振っていくかとか</li>
<li>そうなるともっと人が必要になるよなーとか</li>
<li>分析するマシンリソースがひっ迫してくるだろうから対応考えないと行けないよなーとか</li>
<li>複雑になっていくデータリレーションをどう管理していけばいいのかなーとか</li>
<li>etc...</li>
</ul>
<p>多分今考えている 5倍 ぐらいは出て来るとは思いますが、来る未来を想像しながらとりあえず目先の事を頑張る。</p>
<h2>終わりに</h2>
<p>改めて書き出してみるとあまり固まっていない事が判明して困惑しています。</p>
<p>今後進めていけるのであれば、より影響範囲は広めていきたいなー、色々なデータを触ってみたいなーとか思っています。が、<br />
グループ会社を横断するって事を考えると、良く分からない大人の事情も出て来るだろうし、、、、<br />
じゃあ提案をして改善していきましょう、ってなったときの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%C6%A1%BC%A5%AF%A5%DB%A5%EB%A5%C0%A1%BC">ステークホルダー</a>との折衝とか、、、、</p>
<p>まあ未来を悲観してもしょうがないので、今は目先の事をちゃんとこなしていく事にしています。</p>
<p>その辺り、もし同様の経験をされた方がいらっしゃったらお話お聞きしてみたい...</p>
<p>拙い文章でしたが、ここまで読んでいただいてありがとうございました。<br />
随時、経過とか得られた知見とかアウトプットしていきたいなーと思っているので、よろしくお願いします!</p>
allabout-techblog
Cloud RunとGCPの他サービスを使って簡単なシステムを作ってみました
hatenablog://entry/26006613553408017
2020-04-27T11:24:09+09:00
2020-04-27T11:24:09+09:00 こんにちは!オールアバウト の @y_hideshiです。 今回は、昨年GA(General Availability)された Cloud RunとGCPの各種サービスを連携させて簡単なシステムを構築、その際に得られた知見を記事にしたいと思います。 作成したシステム Cloud Run について Cloud Runへのデプロイ Webからのデプロイ gloudコマンドによるデプロイ 設定値について Cloud Run:まとめ 関連サービスを利用することによるメリット Cloud Build GCR、Cloud Runへのデプロイをするための認証をなるべく手軽に済ませたい プロジェクトが変わって…
<p>こんにちは!オールアバウト の <a href="https://qiita.com/y_hideshi">@y_hideshi</a>です。</p>
<p>今回は、昨年GA(General Availability)された <a href="https://cloud.google.com/run?hl=ja">Cloud Run</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>の各種サービスを連携させて簡単なシステムを構築、その際に得られた知見を記事にしたいと思います。</p>
<ul class="table-of-contents">
<li><a href="#作成したシステム">作成したシステム</a></li>
<li><a href="#Cloud-Run-について">Cloud Run について</a><ul>
<li><a href="#Cloud-Runへのデプロイ">Cloud Runへのデプロイ</a><ul>
<li><a href="#Webからのデプロイ">Webからのデプロイ</a></li>
<li><a href="#gloudコマンドによるデプロイ">gloudコマンドによるデプロイ</a></li>
</ul>
</li>
<li><a href="#設定値について">設定値について</a></li>
<li><a href="#Cloud-Runまとめ">Cloud Run:まとめ</a></li>
</ul>
</li>
<li><a href="#関連サービスを利用することによるメリット">関連サービスを利用することによるメリット</a><ul>
<li><a href="#Cloud-Build">Cloud Build</a><ul>
<li><a href="#GCRCloud-Runへのデプロイをするための認証をなるべく手軽に済ませたい">GCR、Cloud Runへのデプロイをするための認証をなるべく手軽に済ませたい</a></li>
<li><a href="#プロジェクトが変わってもすぐにデプロイしやすいようにしたい">プロジェクトが変わってもすぐにデプロイしやすいようにしたい</a></li>
</ul>
</li>
<li><a href="#Cloud-PubSub">Cloud Pub/Sub</a></li>
<li><a href="#Cloud-Scheduler">Cloud Scheduler</a></li>
</ul>
</li>
<li><a href="#所感">所感</a></li>
</ul>
<h2 id="作成したシステム">作成したシステム</h2>
<p>今回作成したシステムは「<a href="https://cloud.google.com/compute/docs/instances/signing-up-committed-use-discounts?hl=ja">GCP確約利用割引</a>の期日を定期的にチェックして、期日の近いものをslackに通知する」というものです。</p>
<blockquote><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>確約利用割引は1年間または3年間の支払いを確約する代わりに、特定の量のvCPU、メモリ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GPU">GPU</a>、ローカル<a class="keyword" href="http://d.hatena.ne.jp/keyword/SSD">SSD</a>を割引価格で利用できる仕組みです</p></blockquote>
<p><figure class="figure-image figure-image-fotolife" title="作成したシステム構成"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200420/20200420213645.png" alt="f:id:allabout-techblog:20200420213645p:plain" title="f:id:allabout-techblog:20200420213645p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>作成したシステム構成</figcaption></figure></p>
<p>使用したサービス</p>
<ul>
<li><a href="https://cloud.google.com/run?hl=ja">Cloud Run</a></li>
<li><a href="https://cloud.google.com/cloud-build?hl=ja">Cloud Build</a></li>
<li><a href="https://cloud.google.com/pubsub?hl=ja">Cloud Pub/Sub</a></li>
<li><a href="https://cloud.google.com/scheduler?hl=ja">Cloud Scheduler</a></li>
<li><a href="https://cloud.google.com/container-registry?hl=ja">Container Registry</a></li>
</ul>
<p>※ 今回は連携するサービスの詳細については触れませんが、各サービスごとの採用理由やメリットなどを解説して行きたいと思います。</p>
<h2 id="Cloud-Run-について">Cloud Run について</h2>
<p><a href="https://cloud.google.com/run?hl=ja">公式ページ</a>より</p>
<blockquote><p>Cloud Run は、ステートレス コンテナを自動的にスケールするフルマネージド型のコンピューティング プラットフォームです。サーバーレスなのでインフラスト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%AF">ラク</a>チャ管理が一切不要で、最も重要な作業であるアプリケーション構築に集中できます。</p></blockquote>
<p>記載の通りCloud Runは<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>が用意してくれた環境上に、自分で用意したコンテナイメージをデプロイすることができ、ネットワークの経路などは<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>が自動で用意してくれます。そのため、Dockerなどを用いて開発を行った後、すぐにデプロイをすることができます。また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>が管理するプラットフォームにデプロイするため、デプロイする環境自体のメンテナンスコストなども削減することできます。</p>
<p>では、どのようにデプロイするのでしょうか。</p>
<h3 id="Cloud-Runへのデプロイ">Cloud Runへのデプロイ</h3>
<p>Cloud Runをデプロイするには、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>のWeb画面、または<code>gcloud</code>コマンドを用いてデプロイすることができます。</p>
<h4 id="Webからのデプロイ">Webからのデプロイ</h4>
<p>Webからデプロイする際は下記の画像のように、デプロイするイメージや各種変数を設定することでCloud Run環境にコンテナをデプロイすることができます。コマンドの設定値については後ほど記載します。</p>
<p><figure class="figure-image figure-image-fotolife" title="Webからのデプロイ step1"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200420/20200420213727.png" alt="f:id:allabout-techblog:20200420213727p:plain" title="f:id:allabout-techblog:20200420213727p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Webからのデプロイ step1</figcaption></figure></p>
<p><figure class="figure-image figure-image-fotolife" title="webからのデプロイ step2"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200420/20200420213758.png" alt="f:id:allabout-techblog:20200420213758p:plain" title="f:id:allabout-techblog:20200420213758p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>webからのデプロイ step2</figcaption></figure></p>
<h4 id="gloudコマンドによるデプロイ">gloudコマンドによるデプロイ</h4>
<p>Cloud Runは <a href="https://cloud.google.com/sdk/gcloud/reference/run/deploy?hl=ja">gcloud run deploy</a> コマンドでデプロイすることができます。
基本的にはWebからみたときと同じような項目をオプションとして設定してデプロイします。</p>
<p>gcloud コマンドのサンプル</p>
<pre class="code bash" data-lang="bash" data-unlink>gcloud run deploy cloud-run-service-name \
--image gcr.io/cloudrun/hello \
--platform managed \
--port 8080 \
--max-instances 2 \
--cpu 1 \
--memory 128Mi \
--region asia-east1 \
--allow-unauthenticated \
--service-account サービスアカウントのメールアドレス \
--set-env-vars ENVHOGE=hogehoge,ENVFUGA=fugafuga</pre>
<h3 id="設定値について">設定値について</h3>
<p>「web画面での設定項目」と「gcloud コマンドのオプション」において、自分が使用した主要なオプションの対応表を作ってみました。</p>
<table>
<thead>
<tr>
<th> Web </th>
<th> gcloud </th>
<th> 説明 </th>
</tr>
</thead>
<tbody>
<tr>
<td> サービス名 </td>
<td> 第一引数 </td>
<td> デプロイされるときの名前。生成されるURLなどにも利用されます </td>
</tr>
<tr>
<td> デプロイメントプラットフォーム </td>
<td> --region </td>
<td> コンテナが動作するリージョンを指定します </td>
</tr>
<tr>
<td> 認証 </td>
<td> --[no-]allow-unauthenticated </td>
<td> コンテナへのアクセス時に認証を儲けることができます </td>
</tr>
<tr>
<td> コンテナポート </td>
<td> --port </td>
<td> コンテナリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを流す際のポートを指定することができます </td>
</tr>
<tr>
<td> サービスアカウント </td>
<td> --service-account </td>
<td> 作成されるリビジョンで使用されるID ※1 </td>
</tr>
<tr>
<td> 自動スケーリング </td>
<td> --max-instances </td>
<td> 自動スケーリング時の最大<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>数 </td>
</tr>
<tr>
<td> 割り当てられているCPU </td>
<td> --cpu </td>
<td> コンテナ実行時に割り当てるCPU </td>
</tr>
<tr>
<td> 割り当てられたメモリ </td>
<td> --memory </td>
<td> コンテナ実行時に割り当てるメモリ </td>
</tr>
<tr>
<td> VARIABLES </td>
<td> --set-env-vars </td>
<td> コンテナに登録する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B4%C4%B6%AD%CA%D1%BF%F4">環境変数</a> </td>
</tr>
</tbody>
</table>
<p>※1 サービスアカウントを設定することで、こちらのページ <a href="https://cloud.google.com/iam/docs/understanding-service-accounts">Understanding service accounts</a> で記載されている通り、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>の中で認証を行い権限さえ割り当てていればリソースにアクセスすることができます。</p>
<p>メモリやCPU、自動スケーリングの値を設定する理由としては、意図しない大量のアクセスが来た際に大量のCPU, メモリを使用してしまいお金が余分にかからないようにするためです。</p>
<p><a href="https://cloud.google.com/run/pricing?hl=ja">Cloud Run料金ページ</a>より</p>
<blockquote><p>コンテナ <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>で次の処理が行われたときに請求対象時間が開始します。
・コンテナ <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>が開始したとき
・コンテナ <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>で 1 つ以上のリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トが処理されたとき
コンテナ <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>でリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トがアクティブな間に割り当てられた CPU とメモリが請求対象になります。時間は 100 ミリ秒単位で切り上げられます。
次の図のように、コンテナ <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>が同時に多くのリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを受信した場合、請求対象時間は、最初のリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トの処理が始まってから、最後のリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トの処理が完了するまでです。</p></blockquote>
<p><figure class="figure-image figure-image-fotolife" title="Cloud Run請求対象時間"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200420/20200420214300.png" alt="f:id:allabout-techblog:20200420214300p:plain" title="f:id:allabout-techblog:20200420214300p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Cloud Run請求対象時間</figcaption></figure></p>
<h3 id="Cloud-Runまとめ">Cloud Run:まとめ</h3>
<p>記載した通りCloud Runでは、開発したイメージを<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>マネージド環境にデプロイすることで自動的にスケーリングやネットワーク経路を用意してもらえます。
また、Cloud Runではデプロイされるリビジョンごとにサービスアカウントを設定することができ、コンテナ内で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を実行する際には指定したサービスアカウントを利用することができます。
そのため、イメージに機密情報を含むことなく簡単に認証を行うことができます。
今回は「<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>の確約利用割引の期日を取得する」「Pub/Subにメッセージを公開する」といった<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>リソースを操作する処理を行なっており、これらの処理はgo言語で記述し<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>のパッケージを利用していたので、この機能は非常に役立ちました。</p>
<h2 id="関連サービスを利用することによるメリット">関連サービスを利用することによるメリット</h2>
<p>これまでCloud Runについて話してきましたので、これからはCloud Runと別のサービスを組み合わせることのメリットについて話していきます。</p>
<h3 id="Cloud-Build">Cloud Build</h3>
<p>オールアバウトでは通常CI/CDツールに<a href="https://circleci.com/ja/">CircleCI</a>を使用しています。
しかし、今回は下記の理由からCloud Buildを利用しました。</p>
<ul>
<li>GCR、Cloud Runへのデプロイをするための認証をなるべく手軽に済ませたい</li>
<li>プロジェクトが変わってもすぐにデプロイしやすいようにしたい</li>
</ul>
<p><figure class="figure-image figure-image-fotolife" title="Cloud Buildとの連携"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200420/20200420214339.png" alt="f:id:allabout-techblog:20200420214339p:plain" title="f:id:allabout-techblog:20200420214339p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Cloud Buildとの連携</figcaption></figure></p>
<h4 id="GCRCloud-Runへのデプロイをするための認証をなるべく手軽に済ませたい">GCR、Cloud Runへのデプロイをするための認証をなるべく手軽に済ませたい</h4>
<p>Cloud Buildでは、Cloud Build専用のサービスアカウントが存在しており、Buildを実行する際にはこのサービスアカウントが <code>cloudbuild.yaml</code> に記述された処理を実行します。
Cloud Buildのサービスアカウントは下記の画像のように簡単に権限を設定できるため、手軽に権限設定 & 認証を行うことができるのに加え、機密情報を<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>側に持たせることができました。</p>
<p><figure class="figure-image figure-image-fotolife" title="Cloud Build サービスアカウントの権限設定画面"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200421/20200421195704.png" alt="f:id:allabout-techblog:20200421195704p:plain" title="f:id:allabout-techblog:20200421195704p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Cloud Build サービスアカウントの権限設定画面</figcaption></figure></p>
<h4 id="プロジェクトが変わってもすぐにデプロイしやすいようにしたい">プロジェクトが変わってもすぐにデプロイしやすいようにしたい</h4>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>の別プロジェクトでも同様のbuildを行いたい、といったときにプロジェクトIDは変数化され<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>側がプロジェクトごとに保持しているので設定する変数や<a class="keyword" href="http://d.hatena.ne.jp/keyword/yaml">yaml</a>の行数を少なくすることができました(Cloud Buildにて予め設定されている<a href="https://cloud.google.com/cloud-build/docs/configuring-builds/substitute-variable-values?hl=ja">変数一覧</a>)。</p>
<p>また、Cloud Runで指定するサービスアカウントは、同じプロジェクトにサービスアカウントが存在する必要があります。Cloud Buildでは、トリガーと呼ばれる実行条件ごとに変数を用意することができるので、プロジェクトに依存するものはシステムのコード外(今回はトリガー)に書き出して移植しやすいようにしました。</p>
<p>cloudbuild.<a class="keyword" href="http://d.hatena.ne.jp/keyword/yaml">yaml</a>のsample</p>
<pre class="code lang-yaml" data-lang="yaml" data-unlink><span class="synStatement">- </span><span class="synIdentifier">name</span><span class="synSpecial">:</span> <span class="synConstant">'gcr.io/cloud-builders/gcloud'</span>
<span class="synIdentifier">args</span><span class="synSpecial">:</span> <span class="synSpecial">[</span><span class="synConstant">'run'</span>, <span class="synConstant">'deploy'</span>, <span class="synConstant">'${_CLOUD_RUN_SERVICE_NAME}'</span>,
<span class="synConstant">'--image'</span>, <span class="synConstant">'asia.gcr.io/$PROJECT_ID/${_CLOUD_RUN_SERVICE_NAME}:latest'</span>,
<span class="synConstant">'--platform'</span>, <span class="synConstant">'managed'</span>,
<span class="synConstant">'--port'</span>, <span class="synConstant">'8080'</span>,
<span class="synConstant">'--max-instances'</span>, <span class="synConstant">'2'</span>,
<span class="synConstant">'--memory'</span>, <span class="synConstant">'128Mi'</span>,
<span class="synConstant">'--region'</span>, <span class="synConstant">'${_CLOUD_RUN_SERVICE_REGION}'</span>,
<span class="synComment"> # _CLOUD_RUN_SERVICE_ACCOUNT_EMAIL: cloudbuild triggerで設定しています</span>
<span class="synConstant">'--service-account'</span>, <span class="synConstant">'${_CLOUD_RUN_SERVICE_ACCOUNT_EMAIL}'</span>,
<span class="synConstant">'--no-allow-unauthenticated'</span>,
<span class="synConstant">'--set-env-vars'</span>, <span class="synConstant">'NOTIFY_SLACK_WEBHOOK_URL=${_NOTIFY_SLACK_WEBHOOK_URL},TOPIC_PROJECT=$PROJECT_ID,TOPIC_NAME=${_TOPIC_NAME}'</span><span class="synSpecial">]</span>
<span class="synComment"> # check deploy service</span>
<span class="synStatement">- </span><span class="synIdentifier">name</span><span class="synSpecial">:</span> <span class="synConstant">'gcr.io/cloud-builders/gcloud'</span>
<span class="synIdentifier">args</span><span class="synSpecial">:</span> <span class="synSpecial">[</span><span class="synConstant">'run'</span>, <span class="synConstant">'services'</span>, <span class="synConstant">'list'</span>, <span class="synConstant">'--platform'</span>, <span class="synConstant">'managed'</span>, <span class="synConstant">'--region'</span>, <span class="synConstant">'${_CLOUD_RUN_SERVICE_REGION}'</span><span class="synSpecial">]</span>
<span class="synIdentifier">timeout</span><span class="synSpecial">:</span> 600s
<span class="synIdentifier">substitutions</span><span class="synSpecial">:</span>
<span class="synIdentifier">_CLOUD_RUN_SERVICE_NAME</span><span class="synSpecial">:</span> cloud-run-service-name
<span class="synIdentifier">_CLOUD_RUN_SERVICE_REGION</span><span class="synSpecial">:</span> asia-east1
<span class="synIdentifier">_NOTIFY_SLACK_WEBHOOK_URL</span><span class="synSpecial">:</span> slackのIncommingWebhookURL
<span class="synIdentifier">_TOPIC_NAME</span><span class="synSpecial">:</span> slack-topic
</pre>
<h3 id="Cloud-PubSub">Cloud Pub/Sub</h3>
<p>Pub/Subを挟むことによるメリットは下記の通りです。</p>
<ul>
<li>サービスアカウントを利用することで、認証を<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>に任せることができる</li>
</ul>
<p>Pub/SubからHTTPリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを送信する際、サービスアカウントを指定することができ、下記のような構成をとることができます。</p>
<ul>
<li>Cloud Runでは認証必須にすることでアクセス制限を行う</li>
<li>HTTPリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト送信時に指定したサービスアカウントに「Cloud Run起動者」と言うCloud Runを起動できる権限をつけ認証を通す</li>
</ul>
<p><figure class="figure-image figure-image-fotolife" title="Pub/Subとの連携"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200420/20200420214400.png" alt="f:id:allabout-techblog:20200420214400p:plain" title="f:id:allabout-techblog:20200420214400p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Pub/Subとの連携</figcaption></figure></p>
<p>上記のように、作成するシステムに認証機能を持たせることなく、簡単に認証ありのセキュアなシステムを作ることができるので、機能の開発に集中できました。(自分のために便利システムを作ったと思ったら、そのシステムがセキュリティ的によろしくないものになっていたら嫌ですよね。)</p>
<p>また、Pub/Subを挟むことで裏側の処理が切り替わった時もHTTPリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%F7%BF%AE%C0%E8">送信先</a>を切り替えるだけで良いので、パブリッシャー(メッセージを公開する)側のコードに修正を加える必要がありません。</p>
<h3 id="Cloud-Scheduler">Cloud Scheduler</h3>
<p>Schedulerを利用したメリットは下記の通りです。</p>
<ul>
<li>定期実行処理を<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>に任せることができる</li>
<li>サービスアカウントを利用することで、認証を<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>に任せることができる</li>
</ul>
<p>期日を定期的にチェックするためにチェック処理を自分でキックしたくないのに加えて、cron用のサーバなどは管理したくなかったのでフルマネージドのcronジョブスケジューラを利用しました。
Cloud SchedulerもPub/Subと同様にサービスアカウントを指定することができ、セキュアな状態でシステムを実行することができます。</p>
<p><figure class="figure-image figure-image-fotolife" title="Cloud Schedulerとの連携"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200420/20200420214423.png" alt="f:id:allabout-techblog:20200420214423p:plain" title="f:id:allabout-techblog:20200420214423p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Cloud Schedulerとの連携</figcaption></figure>
<figure class="figure-image figure-image-fotolife" title="Cloud Schedulerのジョブ作成画面"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200420/20200420214437.png" alt="f:id:allabout-techblog:20200420214437p:plain" title="f:id:allabout-techblog:20200420214437p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Cloud Schedulerのジョブ作成画面</figcaption></figure></p>
<h2 id="所感">所感</h2>
<p><a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>内で処理が完結していたので、各種サービスを利用し認証機能を持たせたシステムを簡単に実装することができました。
個人的にとても嬉しかったのは認証に必要な情報を全て<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a>側に持たせることができ、こちら側で管理する情報が少ないことでした。機密情報を扱うためにCI/CDツールなどに情報が集中するのは避けたかったので、今回はその辺りがシンプルにできてよかったなあと思っています。</p>
<p>また、今回作成したリソース「サービスアカウント」「Cloud Build」「Cloud Pub/Sub」「Cloud Scheduler」は全てTerraformで作ってみました。そうすることで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>の各種サービスの理解にもつながり、プロジェクトが異なる場合でも簡単に同じリソースを作成できる移植性が高いものができました。</p>
<p>今度はCloud Runと<a href="https://cloud.google.com/dns?hl=ja">Cloud DNS</a>を利用して、もっと色々遊んでいきたいですね。</p>
<p>閲覧ありがとうございました!今後ともよろしくお願いいたします。</p>
allabout-techblog
1ヶ月以上 在宅勤務を続けた弊社エンジニアのアンケート結果を発表します!
hatenablog://entry/26006613554402167
2020-04-24T14:03:49+09:00
2020-04-24T14:03:49+09:00 オールアバウトエンジニアの在宅勤務アンケート結果発表 こんにちは!オールアバウトでデータエンジニアをしている@ondaljhです。 新型コロナウィルスの影響で在宅勤務を実施している企業も多いと思います。オールアバウトグループも3月初めから在宅勤務を実施したので、実施から1か月以上になりました。 今回はオールアバウトのエンジニア達に在宅勤務による業務環境変化等をアンケートしたのでその結果を発表させていただきます! 業務関連 1.在宅勤務になってから打ち合わせの数はどう変わりましたか? 2.自身が開催する打ち合わせの場合、使用するツールはslackとzoom、どちらをより多く使用しますか? その他…
<p>オールアバウトエンジニアの在宅勤務アンケート結果発表</p>
<p>こんにちは!オールアバウトでデータエンジニアをしている@ondaljhです。</p>
<p>新型コロナウィルスの影響で在宅勤務を実施している企業も多いと思います。オールアバウトグループも3月初めから在宅勤務を実施したので、実施から1か月以上になりました。<br />
今回はオールアバウトのエンジニア達に在宅勤務による業務環境変化等をアンケートしたのでその結果を発表させていただきます!</p>
<h1>業務関連</h1>
<h2>1.在宅勤務になってから打ち合わせの数はどう変わりましたか?</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200422/20200422162741.png" alt="f:id:allabout-techblog:20200422162741p:plain" title="f:id:allabout-techblog:20200422162741p:plain" class="hatena-fotolife" itemprop="image"></span></p>
<h2>2.自身が開催する打ち合わせの場合、使用するツールはslackとzoom、どちらをより多く使用しますか?</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200423/20200423151351.png" alt="f:id:allabout-techblog:20200423151351p:plain" title="f:id:allabout-techblog:20200423151351p:plain" class="hatena-fotolife" itemprop="image"></span></p>
<p>その他を選んでいただいた方の中では下記のような意見もありましたー</p>
<ul>
<li>社外の打ち合わせはZoom、それ以外はHangout使っています</li>
</ul>
<h3>2-1.質問2で選んでいただいた項目について、その理由を教えてください</h3>
<p>※回答からいくつか抜粋</p>
<ul>
<li><p>Slack派</p>
<ul>
<li>slackの方が常に見ているのでそっちの方が開きやすいため</li>
<li>少人数の打ち合わせが多いため、わざわざZoomで部屋を作る必要性を感じないため。また、Zoomはセキュリティが心配&Slackのほうが画面共有時の書き込みが自由にできるので。</li>
<li>Zoomだと40分の制限があるため</li>
</ul>
</li>
<li><p>Zoom派</p>
<ul>
<li>背景を変更できるから</li>
<li>slackよりもzoomの方が軽い気がするから</li>
</ul>
</li>
<li><p>どっちでも良い派</p>
<ul>
<li>30分以内、3名ぐらいまではSlack。3名以上30分以上ならZoomでやっています</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/MTG">MTG</a>によって定着している、選び直すなら安定性を感じるZoom</li>
<li>どっちでもよいので気分次第。</li>
</ul>
</li>
<li><p>その他</p>
<ul>
<li>Slackは参加者固定の打ち合わせなら会議作るのが楽だけど、定例等のスケジュールを自動化できないのがつらいため。カレンダーベースでスケジュールできるHangoutが比較的楽だと思いました。</li>
</ul>
</li>
</ul>
<h2>3.割り込み作業の数はどう変わりましたか?</h2>
<p>例えば、急な問い合わせや調査依頼、予定されていなかった打ち合わせなど、当日のスケジュールに含まれていなかった作業の増減について教えてください</p>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200422/20200422163008.png" alt="f:id:allabout-techblog:20200422163008p:plain" title="f:id:allabout-techblog:20200422163008p:plain" class="hatena-fotolife" itemprop="image"></span></p>
<h3>3-1. 質問3の傾向についてご意見又は感想を聞かせてください</h3>
<p>※回答からいくつか抜粋</p>
<ul>
<li>減った
<ul>
<li>うれしい。</li>
<li>口頭で質問しにくる人が減ったから。また、ある程度情報をまとめてきてから相談してくれるので、以前よりも進めやすい</li>
<li>通話をつなぎながらの作業が増えたので、割り込みで中断するというケースが少なくなりました。個人的には集中できて良いと思っています。</li>
</ul>
</li>
<li>変わらない
<ul>
<li>業務のボリュームは変わらず。問い合わせが多いです。</li>
<li>自分の業務的には問い合わせ等はオフライン・オンライン関係ないのが多いから</li>
</ul>
</li>
<li>増えた
<ul>
<li>たぶん、増えたのは、在宅だからではなくコロナ対応のせいです(コーポレートサイト担当なので、コロナ関連のお知らせで、突発サポート業務が増えています)。</li>
</ul>
</li>
</ul>
<h2>4.気軽な相談の数はどう変わりましたか?</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200422/20200422163044.png" alt="f:id:allabout-techblog:20200422163044p:plain" title="f:id:allabout-techblog:20200422163044p:plain" class="hatena-fotolife" itemprop="image"></span></p>
<h3>4-1. 質問4の傾向についてご意見又は感想を聞かせてください</h3>
<p>※回答からいくつか抜粋</p>
<ul>
<li>減った
<ul>
<li>気軽に聞けないのでまずは自分で調べるようになった</li>
<li>口頭で質問しにくる人が減ったから。また、ある程度情報をまとめてきてから相談してくれるので、以前よりも進めやすい</li>
<li>ただの雑談や通りすがりの雑談が出来ないのは長期的にはマイナスになる。</li>
<li>相談なしで進んでしまうと手戻りが増えやすいので、極力減らさないようにしたいと思っています。が、相手の方がオフラインだと「今日はお休みなのかな?」と思ってしまい、なかなか気軽には声をかけにくいです。</li>
</ul>
</li>
<li>変わらない
<ul>
<li>相談する側であることが多いのですが、Slackのテキストベースで基本的にはやりとりするので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B8%C0%B8%EC%B2%BD">言語化</a>のクオリティがお互いに上がり<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%B9%A5%B3%A5%DF%A5%E5%A5%CB%A5%B1%A1%BC%A5%B7%A5%E7%A5%F3">ディスコミュニケーション</a>が減ったような気がしています。</li>
<li>slackで気軽に連絡が取れる</li>
<li>以前と変わらない感じで気軽に相談をするようにしているので、その辺りのハードルは高くない</li>
</ul>
</li>
<li>増えた
<ul>
<li>DMでのこれどうしたらいい?が増えました</li>
</ul>
</li>
</ul>
<h2>5.業務への集中度の変化はありましたか?</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200422/20200422163108.png" alt="f:id:allabout-techblog:20200422163108p:plain" title="f:id:allabout-techblog:20200422163108p:plain" class="hatena-fotolife" itemprop="image"></span></p>
<h3>5-1. 質問5の傾向についてご意見又は感想を聞かせてください</h3>
<p>※回答からいくつか抜粋</p>
<ul>
<li>集中しやすくなった側
<ul>
<li>モブプロ中は余計なものが入り込まなくなって集中しやすくなった</li>
<li>マイペースで働けるようになったからある意味集中度もあがったと思う</li>
</ul>
</li>
<li>変わらない
<ul>
<li>最初は個人作業は集中しやすかったのですが、その分カレンダーやSlackの通知に敏感になり、結果総合的に見ると在宅じゃないときとあまり変わらないと感じました</li>
<li>特に在宅だからといって変わりはない</li>
<li>特に変わらない。気軽に気分転換にお散歩に行けるようになったぐらい</li>
<li>業務後もすぐ業務に戻れるため、公私の区別が付かなくなりがち。結果、緊張感が間延びしつつある。ただ、まとまった時間が取れるのは非常に助かる。</li>
</ul>
</li>
<li>集中し辛くなった側
<ul>
<li>環境が整っていなかったので、仕事をする際の姿勢による負荷などであまり集中できていなかった</li>
<li>自宅前の緑地で毎日子供が遊んでいる&隣のおうちに赤ちゃんがいるので、とにかく毎日騒音が……その間は、正直集中しづらいです。が、静かな時は、会社にいる時よりも集中しやすくなったと思います。</li>
<li>会社での作業は集中したいときにイアホンで音楽聞いてのですがいまは、寂しくて集中できないです。</li>
</ul>
</li>
</ul>
<h2>6.<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A2%A5%D7%A5%ED">ペアプロ</a>・モブプロを行っていた方も多いと思いますが、在宅勤務になってからどのようにやっているか教えてください</h2>
<p>※回答からいくつか抜粋</p>
<ul>
<li>全員で通話し、約1時間くらいで休憩し、そのタイミングでドライバーも変更</li>
<li>slackの画面共有または<a class="keyword" href="http://d.hatena.ne.jp/keyword/vscode">vscode</a>のliveshare</li>
<li>基本モブプロですが、個人作業の場合もチーム内で分担してやる場合が多いので、通話をつなぎながら作業しています。</li>
<li>朝からずっとSlack通話繋ぎっぱなしです。</li>
</ul>
<h1>業務外</h1>
<h2>7.出退勤の電車に乗らなくなった分、余裕時間が増えたと思いますが、どのように活用してますか? (複数選択可)</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200422/20200422163125.png" alt="f:id:allabout-techblog:20200422163125p:plain" title="f:id:allabout-techblog:20200422163125p:plain" class="hatena-fotolife" itemprop="image"></span></p>
<h2>8.今後、新型コロナウィルスの影響が弱くなり、出社可能となった場合、在宅勤務をどの程度の頻度でやりたいと思いますか?</h2>
<p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/a/allabout-techblog/20200422/20200422163136.png" alt="f:id:allabout-techblog:20200422163136p:plain" title="f:id:allabout-techblog:20200422163136p:plain" class="hatena-fotolife" itemprop="image"></span></p>
<h2>9.在宅勤務をする上で工夫している・気を付けていることがありましたら教えてください</h2>
<p>※記述式回答でしたが、関連性があるものが多かったので、関連性軸で出してます</p>
<ul>
<li>作業環境整備
<ul>
<li>ディスプレイを追加</li>
<li>集中するための騒音対策。(音楽を聴きながら仕事をすると集中できないので)ホワイトノイズや環境音をスピーカーから流して、集中しやすいようにしています。</li>
<li>ポモドーロタイマーの導入</li>
</ul>
</li>
<li>心構え
<ul>
<li>会社に行く時と同様に身だしなみを整えるとスイッチが入る</li>
<li><a class="keyword" href="http://d.hatena.ne.jp/keyword/MTG">MTG</a>時は事前のフォローと事後のフォローを一層手厚くする</li>
<li>朝起きたらとりあえず着替える、コーヒーを飲むなど出勤する感を出してます</li>
</ul>
</li>
<li>その他
<ul>
<li>休憩時間に筋トレをする</li>
<li>夜は散歩に出るようにしています。</li>
<li>同居人に仕事中だとわかるようにする。</li>
<li>定期的に換気をする</li>
</ul>
</li>
</ul>
<h2>10.在宅勤務のメリットを教えてください</h2>
<p>※記述式回答でしたが、通勤関連の方が圧倒的に多かったので、通勤関連は別軸で出してます</p>
<ul>
<li>通勤関連
<ul>
<li>出勤電車に乗らなくて済むのは結構いいこと。出勤電車による<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C8%E8%CF%AB">疲労</a>が減った。</li>
<li>これまで通勤時間という無駄な時間を浪費していたことを実感</li>
<li>出勤/退勤時間がいらない</li>
<li>無駄時間の削減(通勤)</li>
<li>通勤ストレスが減る。割り込みが減る。お昼代も減って経済的に優しい</li>
<li>通勤時間の有効活用</li>
<li>通勤時間が無くなる</li>
<li>電車通勤しなくてよくなる</li>
<li>通話をきったら即、帰宅できること</li>
</ul>
</li>
<li>その他
<ul>
<li>晩ごはんを早い時間に食べられる(すごく大きいです)</li>
<li>宅配の荷物が受け取れる</li>
<li>部屋がどんどん綺麗になっていきます。</li>
<li>睡眠時間が増える</li>
<li>割り込み作業が減ったことで、まとまった時間の確保しやすくなった</li>
<li>リラックスできる</li>
<li>自分のベストな環境で仕事ができるところ。</li>
</ul>
</li>
</ul>
<h2>11.在宅勤務のデメリットを教えてください</h2>
<p>※記述式回答でしたが、関連性があるものが多かったので、関連性軸で出してます</p>
<ul>
<li>作業環境関連
<ul>
<li>(全員が)自宅の仕事環境を整えるのが手間、面倒</li>
<li>通信インフラなどが個人環境に依存すること(品質悪い人とはビデオ会議は無理)"</li>
<li>寂しい、インターネットの速度・安定しないとつらい</li>
</ul>
</li>
<li>ダイレクトコミュニケーションロス関連
<ul>
<li>同僚たちを物理的に会える機会が減ること</li>
<li>人とのコミュニケーションを撮る機会が減るので、入社してから信頼関係を構築していきたい人にとっては大変な気がします。また、一緒にコンビニに行ったりしたり、雑談ベースでの相談をする機会が減ってしまう。外に出ないのであしこしが貧弱になっていきます。</li>
<li>ほかプロジェクトの方に、気軽な相談がしにくい</li>
<li>作業内容が見えづらい</li>
<li>画面越しでは表情が分かりづらい</li>
<li>表情などの視覚情報から状況を察し難い</li>
</ul>
</li>
<li>体調関連
<ul>
<li>運動不足</li>
<li>明らかに運動不足になることです。通勤の往復2時間がどれだけいい運動だったか思い知らされました。</li>
<li>肩こりが悪化した</li>
</ul>
</li>
<li>その他
<ul>
<li>会社<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A2%C2%B0%B0%D5%BC%B1">帰属意識</a>の希薄化</li>
<li>リラックスしすぎる</li>
<li>出勤・退勤の移動時間が無いのと、人の目が無いせいなのか、つい仕事しすぎてしまうところ</li>
<li>だらだら仕事になりがち</li>
<li>電車に乗れない</li>
</ul>
</li>
</ul>
<h1>まとめ</h1>
<p>如何でしたか?今回はオールアバウトのエンジニアの声をそのまま伝えたくてアンケート結果には一切コメントなしでありのままをお伝えしました。<br />
が、個人的な感想を最後に書かせていただきますと下記の3つぐらいかなーと思いました。</p>
<ul>
<li>睡眠時間が増えた、の結果が多い → みな、普段の睡眠時間が足りてなかったなー</li>
<li>業務への集中度が変わらない、の結果が多い → 昔からリモートワークをやれるように環境を少しずつ整備してきた結果だなー</li>
<li>今後の在宅勤務想定頻度の結果を見ると、今後在宅勤務は日常的なことになる気がするー</li>
</ul>
<p>今の状況が一日でも早く終息して時には仲間と直接おしゃべりしながら、また時には在宅勤務で、自分たちが仕事しやすい環境で自由に仕事ができるようになってほしいですね。</p>
<p>閲覧ありがとうございました!今後ともよろしくお願いいたします。</p>
allabout-techblog