Make with Notion 2025で、かなり多くの新機能が発表されましたね! Notion AIが新しくなりました | Notion AIエージェントは登場すると予想していましたが、実際には期待以上の機能が発表されたと思います。ただ、AI系サービスは実際に使ってみないとわからない部分も多いので、新機能をいくつか試してみた感想を書いていこうと思います。 Notion AIのパーソナライズ Notion AIエージェント 実験:Slackのチャンネル情報からFAQデータベースを作る 実験:今週の予定やタスクを調べてタスクリストを作ってもらう Custom Agents その他 データベースの行権限 実現できるようになったユースケース: まだ実現できないユースケース 検索から除外する権限設定 People Profiles Notion AIのパーソナライズ 「アイコン」「名前」「Instruction(指示)」を変更できます。 Instruction は AGENTS.md と役割はほぼ一緒です。 思い出(メモリー)部分の記述は、AIとのやりとりで恒久的に指示したものが自動的に書き込まれるようです。AIの回答の下にあるGood/Badフィードバックボタンは、Notion社側へのフィードバックだと思うので送っても追記されなかったです。 パーソナライズしたAIを複数持てるようには現状なっていないですが、Instructionを変更してもプライベートセクションにページとして残るので、手動切り替えもできなくはないです。 カスタムエージェント機能がリリースされれば、複数エージェントを使い分けできるはずです。 Notion AIエージェント Notion AIによる長め&マルチステップ処理ができるようになりました。 いままでのNotion AIでできていた「データベースをAIで構築」「ページ内の文言の追加・修正」これらが単タスク処理ではなく一気にやってくれます。 実験:Slackのチャンネル情報からFAQデータベースを作る API使うにしても面倒な「Slackの情報を抜き出してNotionにまとめる」地味な作業を、Notion AIでパッとやってみます。 Slack の #qa_notion チャンネルに投稿された過去3ヶ月分の情報を遡り、FAQを作成してください。 #qa_notion チャンネル以外の情報は参考にしないでください。 FAQはNotionデータベースとして作成し、各ページに質問の詳細と回答を記載してください。 これだけでFAQデータベースが作成できました。すばらしい! 気軽にデータベース内の複数ページへの一括編集ができるようになりましたが、大勢が使っている共有データベースで使うには怖い機能です。Undo機能はありますがまず個人管理のデータベースで慣らしてから行うほうがいいでしょう。 実験:今週の予定やタスクを調べてタスクリストを作ってもらう AIに不慣れな方だと、「今週の予定やタスクをAIに自動生成してもらえる」という期待を持ちやすいので、実際に実現可能かどうか検証してみます。 @自分のアカウント の今週の予定とタスクを教えてください これだけでは他人の予定やタスクが混在してしまい、うまくいきませんでした。 🔺 Notion データベースを指定しないと他人のタスクが混ざることが多い 日常的に使うならInstructionでのデータベース指定は必須 ⭕️ Slack 未対応項目をうまく抜き出してくれる 🔺 Gmail メーリングリストやDMの情報も自身のタスクとしてみてしまう Instructionに条件を書けば除外できる 🔺 GitHub 参照リソースとしてメールが使われることが多い GitHubリソース単体で探す場合、GitHub IDだと見つからないため表示名で探させる必要がある InstructionでSaaSごとの検索方法を設定することで、かなり良好な結果が得られました。 - 今週の予定を調べるときの方法 - Notion - [掲示板] と [カレンダー] で締め切りの近いものや自分に関連する項目を確認 - [タスク管理DB] で対応が必要なタスクがないか確認 - Slack - 直近1週間で [Slackの表示名] 宛ての未返信メッセージを確認 - スレッド内で未完了の会話も確認 - Gmail - 未回答の個人宛てメッセージを確認 - メーリングリストやダイレクトメールは対象外としてください - GitHub - [GitHubの表示名] がレビュワーに指定されているPull Requestの確認 - [GitHubの表示名] が作成したPull RequestとIssueの状況確認 情報セキュリティの観点から共有できないデータが含まれているため、Notion AIで内容を匿名化したサンプルレスポンス↓ 今後、Notion AIがNotionカレンダーやGoogleカレンダーと連携できるようになれば、さらに精度が向上するため、そのような連携機能の実装が望まれますね。 Custom Agents Waitlist登録はしましたが待ちの状態です。 そのため Make with Notion のデモから得られた情報だけ一旦まとめます。 サイドバーにAgentセクションが追加されていたので、特定ツールや社内業務用のAgentを複数作成して、質問対応や業務処理をさせる使い方ができるようになりそうです。 Slackからの質問に対する一次回答として、カスタムエージェントへのリンクが提供されていました。Slackに直接AIが回答してくれるのが理想ですが、権限管理の問題があるため、このフローが落とし所なのでしょう。 その他 データベースの行権限 データベースの人物プロパティに登録されているユーザーに特定の権限を付与できる機能です。この機能により、ユーザーはページやデータベース全体へのアクセス権がなくても、設定された権限を得ることができます。 個人的に期待していた機能なのですが、もう一息といった印象です。 実現できるようになったユースケース: 共同編集者を簡単に追加できる 条件:データベース(読み取り権限)+行(編集権限以上) 例:Slackからの問い合わせが自動的にNotionデータベースに登録されるワークフローがあったとして、問い合わせた人への編集権限付与が自動化できる まだ実現できないユースケース 権限のあるページだけが一覧表示されるデータベース 現状の問題:データベース自体の権限がないとページを一覧で見ることができない。かといってデータベースに権限を与えるとフィルターでビューを制御しても検索から見えてしまう。 理想条件:データベース(ページに権限のあるものだけ読み取り可能)+行(編集権限) 検索から除外する権限設定 共有 > 一般的なアクセス の権限設定にて設定可能。 検索避けしてアーカイブ化したいページ向けだと思ったんですが、ページの権限を持っているユーザーからは非表示にならない仕様なのでちょっと使いづらかったです。 権限があっても検索結果には出ないようにして、検索オプションとして「非表示ページも表示する」項目を追加する形式がいいとは思うのでフィードバックしておこうと思います。 People Profiles Workspaceの設定から有効化することができます。 現時点ではPeopleの親ページを確認することができず。 デモでは 表示されていたので 将来的に一覧表示もできるようになると思われます。 Peopleの個人ページには、人物プロパティやユーザーアイコンからアクセスできます。 いまはその人のアクティビティ情報と所属チームスペースしか表示されないため、実用性は限られています。自分でプロフィールページをカスタマイズできるようになってからが本番でしょう。
ニフティの主力サービスの一つ「ニフティポイントクラブ」。もともとは「ライフメディア」の名称で20年以上運用されてきましたが、2021年に現在のニフティポイントクラブへ名称を変更し、お客様にさらに寄り添ったサービスへと生まれ変わっています。 その開発や運用、刷新を担うチームのメンバーに業務について語ってもらった前編に続き、後編ではニフティという会社のこと、自身のキャリアのことを深掘り。若手社員が感じる会社の良さ、思い描くキャリアビジョンとは? チームに迎えたい人 ポイントチームに新たなメンバーを迎えるとしたら、どんな人がいいと思いますか? 現場視点の意見を聞かせてください。 西根さん 「 前編 」で関さんたちが言っていた通り、複雑度が高いシステムを扱うので、自分からどんどん情報を取りにいける人がいいと思います。古いプログラムでコードを読んでも分からない部分が多いと思いますが、その場合は社内で知見を持った人を探して相談するなど、能動的に動ける人が来てくれたら嬉しいです。 あとは、ポイントチームはニフティのなかではわりと騒がしいというか、おしゃべりなメンバーが多いです。活発なコミュニケーションから得られる情報もあるので、個人的にはとても良いことだと思っていますが、ガヤガヤした雰囲気が苦手じゃない人の方がフィットする気がします。 関さん 人柄については、僕も西根さんが言ってくれたようなタイプが合っていると思います。スキルに関しては、旧システムの刷新を進めている時期でもあるため、大規模サービスでシステムの移行を経験したことがある人や、関連する知見を持った人が来てくれるとありがたいですね。 細野さん 二人とほぼ同じですが、リーダーポジションだとアーキテクトの経験がある人が理想ですね。今後クラウド移行を加速させるにあたって、我々にはない視点でアドバイスをしてほしいです。メンバーポジションでは、西根さんが言ってくれたように能動的に動ける人に来てもらいたいと思います。 ニフティの良さ 率直に、みなさんが思う「ニフティの良さ」を教えてください。 細野さん まず思い浮かぶのは「良い人」が多いこと……なのですが、それは別チームへのインタビューでも語られていると思うので、あえて別のことで言うとプライベートの時間は確保しやすいです。休みも取りやすいし、業務に支障がなければ当日に「今日は午後休にします」と言っても通るくらい柔軟な職場だと思います。今日も、チームのメンバーの一人が15時でフレックス退勤をするんですけど、みんな誰に気を遣うこともなく休んだり半休を取ったりしていますね。仕事だけでなくプライベートの時間も充実させたい人にとっては良い環境なのかなと。 細野さん自身も、仕事とプライベートのバランスはうまくとれていますか? 細野さん そうですね。会社のテニス部に入っているのですが、仕事が終わった後に部活へ行くと帰宅が遅くなるので、次の日に特に予定がなくても休みを入れたりすることはあります。 西根さん 確かに休みは取りやすいですね。この3人のなかで休暇制度を一番多く使っているのは私だと思いますが、おかげでプライベートは充実しています。 西根さんは音楽ライブに行くのが趣味だそうですね。 西根さん はい。平日のライブもフレックスで早めに退勤すれば参加できますし、先月だけでも4回行きました。11月には有給を取って、愛媛まで遠征します。ちなみに、今年は年30回のライブ参加を目標にしていましたが、無事に達成できそうです。 あとは、スキルアップに関する制度も充実していると思います。業務時間を使って外部のセミナーやイベントに参加できますし、書籍の購入補助や資格取得の支援もあります。個人的にはUdemyというオンライン学習サービスが会社の補助で見放題なのが嬉しいですね。 関さん エンジニア視点でいうと、技術に関するキャッチアップを怠らない人が多いと感じます。たとえば生成AIに関しても、ChatGPTが話題になり始めた頃には、Slack上でAIに質問できるシステムを社内の誰かが作っていました。Svelteという新しいフレームワークが出た時も、気づいたら導入されていましたね。新しい技術に対して日頃からアンテナを張り積極的に業務に取り入れたり、周りに広めたりする人が多いので、すごく学びやすい環境だと思います。 今後のキャリアについて 最後に、みなさんの今後のキャリアの展望や、挑戦してみたいことを教えてください。 西根さん 私はまだエンジニアとしての実務経験が少ないので、まずは多くの案件を任されるようになりたいです。ある程度の経験を積んだ上で、将来的には少しずつマネジメント寄りに軸足を移していけるといいですね。 社内にお手本になるような先輩はいますか? 西根さん ポイントチームのリーダーが、私が描いている将来像に近いです。いわゆるソフトスキルに長けた方で、私もどちらかというとそうした部分を伸ばしていきたい。技術のこともちゃんと分かった上でマネジメントができるようなポジションを目指したいです。 他のみなさんはいかがですか? 細野さん 直近の話でいうと、前職ではアプリケーションの開発業務がメインで、ニフティに入るまでインフラを手がける機会がなかったので、当面はそのスキルを上げていきたいと思っています。引き続きキャッチアップを続けて、チーム内でもインフラの部分については自分が牽引できるようなポジションを目指したいですね。今後のキャリアについては、まだ自分のなかで明確にコレというものはありません。技術をさらに磨くのか、マネジメントのスキルを習得していくのか、そこはまだ悩み中です。 一方で、いずれ自分でイチからアプリを開発したいという思いはずっと持っています。個人でやるのか、会社の事業としてやるのかは分かりませんが、いずれにせよ収益化するには技術だけではなく、顧客価値やビジネス的な観点も必要になります。自分に不足している部分を補いながら、やりたいことを一つずつ実現させていきたいです。 ニフティでそうしたアプリ開発や新規サービスに携われるチャンスはありそうですか? 細野さん そうですね。最近は「新しいサービスを作っていこう」という機運も少しずつ高まっているように感じるので、チャンスはあると思います。 関さん じつは、最近も社内で新規事業関連のハッカソンがありました。エンジニアが作りたいものを作るといった内容で、細野さんと一緒に私も参加しました。 関さんも、ご自身で新規サービスを手掛けてみたいという思いがあるのでしょうか? 関さん 新規事業というよりも、私はグロースエンジニアという職種に興味があって。施策の実行にあたり、技術だけではなく、分析から仕様策定、開発、リリース、評価までエンジニアが手がける職種で、将来的にはそっちの方向に進むのもいいのかなと。そのためには、細野さんが言うようにビジネス的な観点やお客様視点も必要になる。まだまだ学ばないといけないことがたくさんありますね。 前編もご覧ください! 今回はニフティのポイントチームのインタビューの様子をお届けしました。あわせて前編もご覧ください。 【インタビュー】20年の“技術的負債”を解消し、よりよいお客様体験を生み出す【ニフティポイントクラブ前編】 ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! このインタビューに関する求人情報/ブログ記事 ポイントチーム 求人情報 ポイントチーム 求人情報(リードエンジニア候補) ニフティポイントクラブ AWS移行プロジェクト(Amazon Web Services ブログ掲載記事)
この度、私たちニフティ株式会社(以下ニフティ)は、10月4日、10月5日に開催される日本最大級のものづくりの祭典「Maker Faire Tokyo 2025」に、Goldsmithスポンサーとして協賛し、ブースを出展する運びとなりましたことをお知らせいたします。 ニフティ株式会社 テクノロジーとクリエイティビティが交差するこの素晴らしいイベントに、初めて参加できることを、メンバー一同、心より楽しみにしております。 Maker Faireとは? Maker Faireは、地上最大のDIYの展示発表会。家族で楽しめる、発明と創造が一杯で機知に富む人々が集うメイカームーブメントのお祭りです。 その一部はサイエンスフェアのようであり、一部はカントリーフェアのようでもあり、そしてまったく新しい何かでもあるMaker Faireは、あらゆる年齢の技術愛好家、クラフト作家、教育者、物をいじくりまわすのが好きなティンカラー、ホビースト、エンジニア、サイエンスクラブのメンバー、作家、アーティスト、学生、そしてビジネスを行う出展者が参加します。彼らは、自分が作った物を見せるために、そして自分が学んだことをシェアするためにMaker Faire に参加します。 https://makezine.jp/event/mfk2024/aboutmake/ ニフティの出展ブースについて 今年のニフティブースでは、「 AIで絵本を作ろう! 」をメインテーマに、ご来場の皆さまに楽しんでいただける3つの特別なコンテンツをご用意しました。AIと会話してオリジナル絵本を創作・印刷できる「 AI絵本をつくろう 」はもちろん、ネットワークの知識を楽しく深める「 ネットワーク管理ゲーム 」、ご自宅のWi-Fi速度変化を体験できる「 おうちのWi-Fiを見直そう 」など、盛りだくさんの内容でお待ちしております。 ■ コンテンツ1:ニフティキッズ 「AIで絵本を作ろう!」 AI絵本制作ワークショップ AIを使って自分だけのオリジナル絵本を作りながら、楽しくAIを学ぶワークショップを提供します。 タブレットを使ってAIに指示し、生成されたストーリーとイラストを使って絵本を作成します。 完成した絵本は持って帰って楽しんでいただけます。 https://kids.nifty.com/event_info/mft2025/ 【お知らせ】 10/4・5に実施されるMaker Faire Tokyo 2025で、AI絵本作成ワークショップを開催! ぜひご参加ください! スペシャルプレゼントとして、9/21までにワークショップのお申し込みいただいた方に、Maker Faire Tokyoチケットをプレゼントします https://t.co/GxKv6tArgc pic.twitter.com/PgpCoyQXaT — ひよりん【ニフティキッズ公式キャラクター】 (@kids_nifty) September 16, 2025 ■ コンテンツ2:ネットワーク管理ゲーム ※カードゲーム(通信パンク) ニフティボドゲ部社員の有志で作成した、ネットワーク題材のカードゲームを展示します。 実際に遊ぶことも出来ますので、是非お越しください! ■ コンテンツ3:Wi-Fi速度低下についての実演展示 無線ルータの設定(2.4GHz/5GHzの周波数帯の違い)で速度変化する様子を実演展示いたします。 快適にインターネットを利用するためのテクニックを伝授いたします! ぜひブースへお立ち寄りください! イベント当日は、ぜひニフティブースへお立ち寄りください。メンバー一同、皆さまと会場でお会いし、ものづくりの楽しさや新しいテクノロジーの可能性について語り合えることを心待ちにしております! 開催概要 イベント名 Maker Faire Tokyo 2025 開催日時 2025年10月4日(土) , 10月5日(日) ※詳細は公式サイトをご確認ください 会場 東京ビッグサイト ブース番号 SP-03-03 ニフティ株式会社 公式サイト https://makezine.jp/event/mft2025/
はじめに こんにちは、サービスシステムグループの佐々木です。 最近、多くの開発チームでマイクロサービスアーキテクチャが話題になっていますが、実際に導入してみると「思ってたより大変だった…」という声もよく聞きます。そんな中で注目されているのが「 モジュラーモノリス 」という考え方。今回は勉強会や自主学習で学んだことをまとめてみました。 モジュラーモノリスとは モジュラーモノリスは、ソフトウェアアーキテクチャの一つのアプローチです。 従来のモノリシックアーキテクチャとマイクロサービスアーキテクチャの中間的な位置づけとして考えられていて、 マイクロサービスを取り入れる上で課題があるのでモジュラーモノリスからはじめようといった選択肢 でもあります。 まずは、マイクロサービス導入にあたっての課題について触れたいと思います。 マイクロサービスの現実:理想と現実のギャップ マイクロサービスが解決してくれること マイクロサービスアーキテクチャには確かに魅力的な利点があります。 スケーラビリティ : サービスごとに必要な分だけスケールできる 技術の自由度 : サービスに最適な技術を選べる チームの独立性 : 各チームが自分のペースで開発・デプロイできる ですが、新しい悩みも生まれてきます… 分散システムならではの難しさ ネットワーク通信による複雑さ マイクロサービスでは各サービス間の通信がネットワークを介して行われるため、モノリスにはない課題が生まれます。 ネットワーク障害への対応 : 通信エラー、タイムアウト、パケットロスなどへの対処が必要 レイテンシの増加 : サービス間の呼び出しにネットワーク遅延が発生 障害の波及 : 1つのサービスの障害が他のサービスに連鎖的に影響する可能性 トランザクション管理の複雑さ モノリスでは簡単だった処理も、マイクロサービスだと途端に複雑に。 【モノリスの場合】 注文確定 → 在庫確保 → 決済 → ✗(失敗) → ロールバックしてリトライすればOK 【マイクロサービスの場合】 注文確定 → 在庫確保 → ✗(失敗) → 決済 → 単純なロールバックができない、専用のリカバリ処理が必要 マイクロサービス導入前には目的を明確に こんな理由はちょっと危険 「最新技術を使ってみたいから」 「他の会社もやってるから」 こんな目的なら良さそう 機能ごとに独立してスケールしたい チーム間の開発サイクルを独立させたい 特定の技術要件に対応したい マイクロサービスが向かない場面もある こんな状況だと、マイクロサービス導入は慎重に考えた方が良さそうです。 スタートアップの初期段階 システムがまだシンプルな時期は、マイクロサービスの運用コストの方が重い 要件がコロコロ変わる時期には、サービス境界の設計が難しい ドメインがまだ曖昧な時 サービスの境界が不明確だと、頻繁に境界を変更することになる ネットワーク通信でパフォーマンスが悪くなるだけになりがち モジュラーモノリス:いいとこ取りのアプローチ モジュラーモノリスは、マイクロサービスとモノリスの「いいとこ取り」を目指したアプローチです。 こんな特徴があります: 同じアプリケーションの中でモジュールとして分割 サービス間の通信はネットワークを使わない 各モジュールの独立性は保ちつつ、分散システムの複雑さは避けられる 基本的な考え方: DDD(ドメイン駆動設計)と相性が良い サービス・ドメインをきちんと分離 高凝集・疎結合を目指す モジュラーモノリスの良いところ・気になるところ 良いところ 開発の独立性が保てる モジュール境界がはっきりしていれば、独立した開発ができる 将来マイクロサービスにしたくなった時の土台にもなる 運用がシンプル ネットワーク通信のエラー処理で悩まなくて済む 単一DBなので、データの整合性確保が楽 段階的に進められる 必要に応じて個別モジュールをマイクロサービス化できる 気になるところ スケーリングに制約がある リソースを共有するので、個別モジュールだけスケールするのは難しい 全体のスケーラビリティには限界がある 技術スタックが統一される モジュール間で同じ技術を使う必要がある 実際にやってみるとしたら?移行戦略を考える(例) 段階的に進めるのがポイント フェーズ1: まずは大きく分ける 1. フロントエンド バックエンドで分離 2. 技術レイヤー別に分離(Java/PHP等) 3. セキュリティレベルで分離 フェーズ2: ドメインで分ける 1. ビジネスドメインを整理 2. モジュール境界を設計 3. インターフェースを定義 フェーズ3: データベースも分けるかどうか検討 1. モジュールの利用状況を分析 2. パフォーマンス要件を評価 3. 必要に応じてDB分割を実施 分割の順序:コードから?DBから? おすすめは「コードから」のアプローチ なぜコードからが良いの? 実際の利用状況を見てからDB分割を判断できる 失敗した時に元に戻しやすい リスクを段階的に管理できる 進め方のイメージ: 1. ビジネスロジックをモジュールに分割 2. インターフェースを定義して実装 3. 運用状況を監視・評価 4. 必要があればDB分割も実施 DB先行はちょっとリスキー 適用できそうなケース: 単一テーブルだけ参照する場合 明確にパフォーマンスが改善しそうな場合 注意したいこと: 短期的なメリットは少ない 複雑性が増すリスクがある どこから手をつける?優先順位の考え方 効果的に進めるには、こんな優先順位で考えてみると良さそうです。 1. 【最優先】分けやすい × メリットが大きい箇所 2. 分けにくい × メリットが大きい箇所 3. 分けやすい × メリットが小さい箇所 4. 分けにくい × メリットが小さい箇所 やっぱり「簡単で効果の高いところ」から始めるのが鉄則ですね。 モジュラーモノリスを学んでのまとめと今後の展望 データベース分割への新しい視点 従来、マイクロサービス化における最大の懸念はデータベース分割でした。しかし、モジュラーモノリスアプローチにより、この課題を段階的に解決できる選択肢があることを学びました。 アーキテクチャ選択の判断基準 学びを通じて各アプローチの適用場面が明確になりました。 マイクロサービス : 大量リクエスト処理、水平スケーリングが主目的の場合 モジュラーモノリス : 開発の独立性確保、段階的移行を検討する場合 モノリス : シンプルなシステム、明確な分割メリットがない場合 次のステップとして考えられること 実際に導入するとなったら以下のことから始めてみようと思いました。 今のシステムを整理してみる ドメイン境界の候補を洗い出してみる 今困っていることを整理する 小さく試してみる 影響の少ない部分から実験的に導入 効果を測る指標を決めておく チームのスキルアップ DDD(ドメイン駆動設計)について学んでみる モジュール設計のパターンを勉強してみる 参考資料 CloudNative Days 2024: モジュラーモノリス関連講演 Modular Monoliths (Simon Brown) MonolithFirst (Martin Fowler) Microservice Premium (Martin Fowler) StranglerFigApplication Pattern Monolith vs Microservices (InfoQ) この記事は実際の勉強会や自身の学びを基に、モジュラーモノリスという選択肢について整理したものです。実際の導入検討時には、各プロジェクトの特性や制約を十分に考慮することが大切です。
こんにちは。ニフティの おおい です。 今回はAmazon ECSの組み込みBlue/Greenデプロイ機能を活用して、AWS Lambdaによる自動テストを実施することで、安心してAPIをリリースできるようにしてみました。 はじめに 2025/7/17にリリースされたECSの組み込みBlue/Greenデプロイですが、デプロイの途中で自前のLambda関数を実行することができ、この関数が特定の値 ( SUCCESSFUL 、 FAILED 、 IN_PROGRESS のいずれか) を返すことでデプロイの制御をすることができます。 この機能を使ってLambda関数による自動テストを組み込むことにより、安心してAPIをリリースできるようにしてみましたのでその事例をご紹介します。 アーキテクチャ概要 今回構築したものは以下の要素で構成されています: ECSサービス:Blue/Greenデプロイメント戦略を設定 Application Load Balancer:本番用とテスト用のリスナーをポート違いで設定 ターゲットグループ:メイン用と代替用の2つを用意 Lambda関数:テストトラフィック移行後の自動テスト実行処理 S3バケット:テストケースの定義ファイルを格納 ポイント 今回のキモとなるのは Lambda関数 とS3バケットに格納される テストケースの定義ファイル の2つです。 またテスト用のフレームワークは利用せず、なるべくシンプルにテストができるようにしました。 テストケースの定義ファイル 今回はtomlで記述しました。tomlを選んだ理由は下記2点です。 後述のLambda関数をPythonで書いたので特別なライブラリ無しでパースができるため 可読性が高く人間が定義するのに難儀しないため 例) [general] base_url = "https://api.example.com:8443/v1" charset = "UTF-8" [[test_cases]] title = "特定ユーザの情報を参照できること" target_endpoint = "/users/existent-user-id" [[test_cases.assertions]] target = "resultCode" expected = "0" [[test_cases.assertions]] target = "courseId" expected = "1" [[test_cases]] title = "存在しないユーザの情報でエラーになること" target_endpoint = "/users/inexistent-user-id" [[test_cases.assertions]] target = "resultCode" expected = "1" [[test_cases.assertions]] target = "message" expected = "該当するユーザ情報データが存在しませんでした" [general] ブロックにはテスト全体で利用する基本的な設定を、 [[test_cases]] ブロックにはタイトルとテスト対象のエンドポイントを、 [[test_cases.assertions]] ブロックにはどの項目(→ target )がどういう値であることを期待するか(→ expected )の設定を書いています。 Lambda関数 この関数はECSの組み込みBlue/Greenデプロイ中、テストトラフィック移行後に実行するように設定します。 内容としても特別なことをしておらず、 S3バケットからテストケースの定義ファイルを持ってくる ファイルの内容を読み取る テストケースの数だけAPIリクエストを実行→アサーションを繰り返す と処理するように書いています。 ただこの関数実行後にデプロイをどうするべきかを決めなければいけませんので、失敗したテストケースのタイトルを配列として持っておいて、最終的にその配列が空であれば {"hookStatus": "SUCCEEDED"} を返して本番トラフィックをGreen環境に流すように、配列に要素があれば {"hookStatus": "FAILED"} を返してデプロイをロールバックするようにしました。 さらに失敗したテストケースのタイトルを持つようにしたので、ログ出力によって失敗したテストが何なのかをCloudWatch Logsから確認でき、次に何をすべきかがわかるようになるのがうれしいポイントです。 CI/CDとの連携 GitHub Actionsの中で テストケースの定義ファイルをS3バケットにコピー ECSサービスの更新 の2点を行うように実装すれば、ワークフローを起動するだけで安心してデプロイができるようになります。 さいごに ECSの組み込みBlue/GreenデプロイとLambda関数による自動テストの組み合わせによりこれまでよりも楽なAPIのリリースを実現できます。特に、テストトラフィック移行後にLambda関数を実行することで、本番影響を与えないで新バージョンの品質を確保できる点が大きなメリットです。 ECSの組み込みBlue/Greenデプロイはリリースされてから時間がたっておらず、手探りの状態で構築してみました。数ある事例の一つとして参考にしていただけたら嬉しいです。
ニフティの主力サービスの一つ「ニフティポイントクラブ」。もともとは「ライフメディア」の名称で20年以上運用されてきましたが、2021年に現在のニフティポイントクラブへ名称を変更し、お客様にさらに寄り添ったサービスへと生まれ変わっています。 とはいえ、20年続くサービスだけに、古いシステムの刷新は急務。技術的な負債を解消し、よりよい顧客体験を実現するために奮闘しているのがポイントチームの若きエンジニアたちです。主力サービスの刷新という重要な役割を担うメンバーたちに業務内容や現状の課題、仕事の喜びなどについて聞きました。 自己紹介 細野 俊平さん 2023年9月に中途入社。メイン業務はニフティポイントクラブ(lifemedia.jp)の開発、運用、刷新。休日の楽しみはテニス、愛犬のミニチュアダックスと遊ぶこと。 西根 千晴さん 2023年4月入社。メイン業務はニフティポイントクラブ(lifemedia.jp)の開発、運用、刷新。趣味は旅行とライブとボードゲーム。 関 歩武さん 2021年4月に新卒入社。メイン業務はニフティポイントクラブ(lifemedia.jp)の開発、運用、刷新。趣味は色々なコーヒー豆を試したり、ハンバーガー屋を巡ること。最近はサウナ巡りも。 20年続くポイントサイトの先駆け「ニフティポイントクラブ」 みなさんが開発、運用、刷新を担当している「ニフティポイントクラブ」は、どのようなサービスなのでしょうか? 細野さん 20年以上の運営実績があるポイントサービスです。お客様がニフティポイントクラブ提携企業のサービスを利用したり、無料ゲームやアンケートに答えることでポイントが付与されます。貯めたポイントは1P=1円で、現金や電子マネーに交換できるほか、@niftyの利用料金に使うことも可能です。 また、今後のビジョンとしてはニフティポイントを基盤にして、ニフティの各サービスをもっと多くの人に活用してもらえるような状態をつくりたいと考えています。ニフティ経済圏とまではいかなくても、ポイントが潤滑油になってニフティのサービス全体をうまくつないでいきたい。今はそのための施策をチームで検討しています。 ニフティポイント自体は20年以上続くサービスということですが、みなさんはどのタイミング、どんな経緯でポイントチームにアサインされましたか? また、それぞれの役割も教えてください。 細野さん 僕は2023年の9月にニフティに中途入社し、ポイントチームに配属されました。それからは主に、旧来のクラウドサービスに置かれているデータベースなどのインフラの一部をAWSへ移行するプロジェクトに携わっています。 関さん 2021年に新卒でニフティに入社して、複数のサービスでフロントエンド、バックエンドの開発を経験した後に、2年前からポイントチームに入りました。ポイントチームでの役割は開発、運用、刷新で、具体的にはお客様を対象にポイントの還元を拡大するための開発や、細野さんと同じAWSへの移行プロジェクトなどに携わっています。 ※2人が関わったAWS移行プロジェクトの概要 https://aws.amazon.com/jp/blogs/news/amazon-aurora-migration-nifty/ 西根さん 私は2023年に新卒でニフティに入り、1年間の研修とジョブローテーションを経て、最終的にポイントチームに配属されました。現在の主な役割は開発と運用です。 3人のなかでは西根さんが最も後輩にあたると。西根さんにとって、細野さんと関さんはどんな先輩ですか? 西根さん それはもう、偉大な先輩です。 関さん 嘘っぽい(笑)。 西根さん いや、本当に。二人はAWSへの移行という負荷の大きいプロジェクトを担っていて、苦労しながらもやり切る姿を近くで見ていましたから。スケジュールもタイトななかで大変な業務だったと思いますが、いつも2人で意見を交わしながら、仲良く、前向きに取り組まれていた印象がありますね。 関さん 確かに、あの時期は本当に大変でしたが、細野さんと一緒になんとか乗り越えました。細野さんのほうが業界歴は長いのですが、僕は勝手に戦友だと思っています。 4000ファイルにも及ぶ“膿”を出し切る、途方もない作業 AWSへの移行にあたり、特に苦労した点を教えてください。 関さん 20年続くニフティポイントは会社にとって財産ともいえるサービスですが、一方で技術的には“20年分の負債”が蓄積している状態でした。たとえば、データベースを以前のクラウドからAWSに移行するにあたって、新しいシステムに影響が出ないよう中身を全て洗い出す必要があったんです。4000ファイルにも及ぶ“膿”を綺麗に出し切るのは、なかなか大変な作業でしたね。 細野さん おまけに、旧来のデーターベースで使われているシステムはかなり古いもので、プログラムもチームのメンバーはほぼ触ったことがないC言語が使われていました。そんな状態で負債を全て洗い出し、仮に漏れたまま移行してしまった場合でもお客様に影響が出ないようにしなければいけない。スケジュール的にもあまり余裕はなかったので、AIを活用するなどして知識不足を補いながら進めていきました。 その洗い出しというのは、関さんと細野さんのお二人でやられていたのでしょうか? 関さん そうですね。ただ、途中からは知見を持った別チームの方がプロジェクトに入ってくれました。そのあたりの動きは、ポイントチームに限らずわりと柔軟ですね。プロジェクトに必要な人材を助っ人のような形で補充してくれることは珍しくありません。 西根さんはいかがでしょうか? ポイントチームの業務で特に苦労したことを教えてください。 西根さん ポイントチームに配属されて半年ほど経った頃に、たまたま先輩の異動や転職が重なって、私1人で運用を担っていた時期がありました。まだ分からないことも多かったですし、当時は不安でしたね。 ただ、運用担当が1人になることが分かったタイミングで上司が面談の機会をつくってくれました。人の補充について私の意見も聞いてくれて、その後すぐに派遣社員の方がアサインされたので、早い段階で不安な状態は解消されましたね。 負荷がかかった時に、上長に対してアラートを出せる機会があるのはいいですね。 西根さん そうですね。面談の機会も多いですし、折に触れて「大丈夫?」と聞いてくれるので、相談しやすい環境ではあると思います。 エンジニアの醍醐味は、大きなプロジェクトを乗り切った時の達成感 仕事をしていて喜びや達成感を感じるのはどんな時ですか? 関さん 今回のAWS移行もそうですが、大きなプロジェクトが一区切りついた時ですね。達成感というより、開放感に近いかもしれませんが(笑)。 特に、細野さんと2人でやってきたプロジェクトに関しては、リリース後に何かしら障害が発生するだろうと思っていたんです。でも、数ヶ月経ってもこれといった問題は起こらなくて。 細野さん じつは、ひとつ前にリリースした案件で障害が頻発してしまったこともあって、同じ轍を踏まないように進めてきました。より難易度の高い案件で、障害を出さないという目標をクリアできたのは大きな自信になりましたね。 西根さん 私は2人ほど負荷の大きいプロジェクトに携わった経験は、まだありません。ただ、以前に企画側から急ぎの開発依頼を受けて、約1ヶ月で調査から企画との調整、リリースまで主導したことがありました。無事にリリースできた時は喜びと同時に、「エンジニアになったんだな」という気持ちが芽生えたのを覚えています。 難易度の高いミッションだけに、やり切れば必ず力が付く ポイントチームの現状の課題があれば教えてください。 関さん 業務に関しては、先ほどもお話しした20年の負債ですね。未だに解消できていない部分も多く、引き続き着手していく必要があります。現状はシステムが古く、なおかつ複雑なため、「ここを変更すると、どこに影響が出るか分からない」という懸念から開発に踏み切れないケースもあるんです。余計な会議も増えて、開発のスピードも落ちてしまう。そうした複雑性をなくしていけば、よりお客様向けの開発に注力できるのではないかと思います。 細野さんはいかがですか? 細野さん 同じですね。古くからの負債があることで、本来なら自動アップデートで事足りるような作業でも、メンバーが個別にサーバーの管理をしてアップデートをしなければいけないような状況が発生しています。それ以外にも問題が山積みで、早急に負債の解消とクラウド移行を進めていかなくてはいけません。 ただ、それをやるにも今は人員が不足していて、なかなか着手できていない。技術的負債が解消されず、色んな開発のボトルネックになってしまっているのが現状ですね。あまりにも課題が多いため、まずは全体像を把握し優先順位を決めて着手していく必要があると思います。 お話を伺っているだけで、かなり難易度の高いミッションであることが分かります。 細野さん ただ、これをしっかりやり切ることができれば、個人としてもかなり力が付くはず。20年の技術的負債に挑むなんてミッションは、そうそう与えられるものじゃない。エンジニアとして、かなり貴重な経験ができていると思います。今は大変ですが、後で振り返った時に必ずよかったと思えるはずです。 それに、関さんが話してくれたように、この大きな課題をクリアできれば、お客様に新しい価値を届けるような開発にも着手できます。そのステージに到達するためにも、できることから確実に進めていきたいですね。 後編に続きます! 今回はニフティのポイントチームのインタビューの様子をお届けしました。続きは近日公開予定の後編の記事をご覧ください。 このインタビューに関する求人情報 /ブログ記事 ポイントチーム 求人情報 ポイントチーム 求人情報(リードエンジニア候補) ニフティポイントクラブ AWS移行プロジェクト(Amazon Web Services ブログ掲載記事)
はじめに こんにちは。瀧山・添野です。 本記事は、InnerSource Commonsが、9/12に主催したInnerSource Gathering Tokyo 2025の参加レポートになります。 InnerSource Gathering Tokyo 2025とは InnerSource Commonsというインナーソースに関するナレッジの創出と共有に特化したコミュニティがあり、そのコミュニティの日本支部が9/12にdocomo R&D OPEN LAB ODAIBAで実施したイベントになります。 弊社のメンバーがInnerSource Commonsに所属しており、本イベントでは運営や配信機器に関わるスタッフとしても参加いたしました。 イベントのHPはこちら https://gatherings.innersourcecommons.org/tokyo-2025/ 配信機器に関わるスタッフはこちら これがニフティの機材、配信班です! 今回のイベントの裏方で活躍してくれた人たちです!感謝! #ISGT2025 pic.twitter.com/UnJWtdZ9sf — rashikawat (@ryo19790510) September 12, 2025 なぜ参加したのか 瀧山:私はまだインナーソースを実践できていないので、インナーソースのベストプラクティスに興味がありました。また、ニフティを退職された方が一般参加されていたので、単純にその方に会いたいという理由もありました。 添野:私は、現在社内でインナーソースを推進するメンバーの一人で、本イベントのスタッフであった上司や同僚からも誘われて参加いたしました。 本題 イベント参加特典 本イベントに参加したところ、以下のものをいただきました。 インナーソースヒーローのステッカー×2 インナーソースヒーローのハンカチ InnerSource Commonsのロゴステッカー×2 水 ※インナーソースヒーローとは、InnerSource Commons Japanで生まれたキャラクターです。 詳細は、昨年のこちらのセッションをご確認ください。 https://youtu.be/ynlGpNnTCkc?si=K5nXXPnOwaKvB5Mi セッション Welcome to InnerSource Gathering Tokyo 2025 イオンスマートテクノロジー株式会社 / InnerSource Commons Foundation 久保 翔馬 (Shoma Kubo) 様 「インナーソースとはなにか」や「チャタムハウスルール※」の説明がありました。 ※チャタムハウスルールとは、会議で得た情報を自由に利用できるが、発言者の身元や所属、参加者の身元を明らかにすることはできないという、議論の自由な参加を促すための会議ルールです。 会場ご案内 [会場スポンサー] 株式会社NTTドコモ 本イベントの会場であるdocomo R&D OPEN LAB ODAIBAについての説明がありました。 本会場は、執筆時点(2025年9月)では、ドコモグループ社員と一緒であれば、今回のようなオープンなイベントを平日に実施できるイベント会場とのことでした。 また非イベント時では、コワーキングスペースとしても利用できるようです。 詳しくはHPをご確認ください。 https://docomo-openlab.jp/about/ 本イベントを実施したエリアでは、壁一面にディスプレイがあり、また座席の上部数カ所にもモニターが用意されており、非常に見やすい会場でした。 インナーソースで未来を築こう ワイクル株式会社 代表取締役 角 征典 (Masanori Kado) 様 資料 : https://kdmsnr.com/slides/20250912_innersource/ インナーソースへの認識合わせから始まり、インナーソースに参加する動機や、組織に効果的に普及させるための実践的なアプローチについて解説されました。 インナーソースへの認識合わせのパートでは、ファイルを触らない貢献の例が話されており、貢献のレビュー、貢献のテスト、イシューのトリアージを例として出ていました。 ※登壇者の角さんの書籍はこちらになります。 感想 瀧山: OSSからインナーソースへと繋がる歴史が興味深かったです。 参考文献も多数紹介されており、OSSやインナーソース関連の書籍で勉強してみたいと思いました。 添野: 貢献のレビューで出ていた「送信は厳密に、受信は寛容に」というポステルの法則が響きました。 またイシューのトリアージは、普段コードを触らない方でも簡単に実践できそうでしたので、社内でも実践してみようと思います。 組織に効果的に普及させるための実践的なアプローチについて話されていた体験談では、感情も含めた共有が良いという内容で、参考になりました。 InnerSource活動『xPalette(クロスパレット)』が解き放つエンジニアの創造性と主体性 野村総合研究所 生産革新センター プラットフォームサービス開発二部 昼間 貴宏 (Takahiro HIRUMA) 様 xPaletteは、開発現場を業務ロジックの開発に集中できる快適な環境にすることを目的とした開発コミュニティです。立ち上げ時1人から16人まで成長した過程で培った、エンジニアの主体性を引き出すコミュニティ運営の工夫や、インセプションデッキを活用した共鳴の強化などの実践的な取り組みが紹介されました。 感想 瀧山: 社内の複数プロジェクトで使うガイドラインや共通テンプレートのようなものがインナーソースに合っているのかなと感じました。 添野: 主体的に活動したくなるコミュニティを目指すという方向性は非常に理にかなっていると感じました。 また、インセプションデッキを定期的に実施されているのも素晴らしい取り組みだと思いました。 三菱電気が推進するInnerSourceの未来 三菱電機株式会社 設計技術開発センター オープンソース共創推進部 部長 追立 真吾 (Shingo Oidate) 様 三菱電機では、OSSの開発や利用などを管理・推進する組織を2025年4月に新設されたとのことでした。オープンソースとインナーソースの両方を推進することで相乗効果を目指されているそうです。 また社内では、次のセッションでご登壇された小林様や、InnerSource Commons japanの服部様をゲストにお招きし、インナーソースDayを開催されたということでした。 感想 瀧山: OSSやインナーソースを推進する専門の部署があるのはすごいと感じました。なかなかここまでやっている会社はないと思います。 添野: オープンソースとインナーソースの両方を推進するアプローチは非常に興味深いと感じました。 また外部のゲストをお招きして社内でインナーソースのイベントを開催してみるのも良いアイデアだと思いました。 InnerSource対談 ican.lab代表 (品質管理エキスパート) 熊川 一平 (Ippei Kumagawa) 様 株式会社 東芝 デジタルイノベーション技術センター 小林 良岳 (Yoshitake Kobayashi) 様 大企業でインナーソースを推進した経験とその活用方法について、対談形式で語られたセッションでした。 熊川様からは、どのようにしてインナーソースの考え方に辿り着いたのかという経緯が紹介されました。開発標準やビジネス標準などの規程類のドキュメント作成において、インナーソースの知見を活用した改善事例についてもお話しされていました。 また、品質の観点から見たインナーソースの効果についても言及されていました。 感想 瀧山: 開発標準や規定のようなものはみんな嫌い、だから利用者自身が使いやすいようにコントリビュートするというのは面白かったです。 添野: 規程類は確かにインナーソースの手法が効果的だと感じました。 ファーストペンギンだけでなく、ファーストフォロワー(活動に賛同してくれる最初の人)も大切にしようという考え方に深く共感しました。 インナーソースヒーローからのメッセージ KDDIアジャイル開発センター インナーソースヒーロー / 中島 智弘 様 インナーソースヒーローからビデオメッセージが届き、それを視聴するセッションでした。 一人ひとりが所属組織を選択する時代に“われわれはなぜここにいるのか“その表現へのこだわりとプロセス KDDIアジャイル開発センター株式会社スクラムマスター 泉本 優輝 (Yuki Izumoto) 様 登壇資料 : KAGreementとは、KAG(KDDIアジャイル開発センター)が憲章を社員それぞれで分解・解釈し、自分たちの働き方として再定義していく取り組みで、この手法を「KAG + Working Agreement」、略して「KAGreement」と呼んでいるそうです。 このKAGreementにおけるプロセスと、インナーソースのパターンを比べてみた際に、意外と共通点があったらしいです。 感想 瀧山: 社訓や行動指針のようなものは形骸化してしまうことも多いですが、全社員が取り組めるような仕組みができているのがすごいと感じました。 添野: 透明性を高く保ち、オープンなコミュニケーションの文化を築いている点が素晴らしいと感じました。 スケールする組織の実現に向けたインナーソース育成術 チームラボ株式会社 パッケージチームエンジニア 松本 玲音奈 (Leona Matsumoto) 様 登壇資料 : 登壇者の自社のチームラボでのインナーソース活動を例にして、社内でどのようなSTEPでインナーソースを広めていく方法を紹介したセッションでした。 感想 瀧山: これまでは既存リポジトリをインナーソース化するパターンが多いかと思っていましたが、新規の便利ツールのようなものをインナーソース化するのはいいなと感じました。 添野: 「このツールを利用中のリポジトリ」のリンクを設けるのは、非常に効果的だと思いました。どのように利用されているかは、コントリビューター目線では気になるポイントであるため、こうした可視化により貢献へのモチベーション向上に繋がると感じます。 次のOSTの前に本イベントでのベストスピーカー賞の投票がありました。 ベストスピーカー賞の賞品としてウィンナーとマスタードソースが贈られていました。 InnerSource OST (Open Space Technology) 参加者から「このテーマについて他の人の意見を聞いてみたい」「本イベントでもっと深く話し合いたい」「次回のイベントで取り扱ってほしい」といった8つのテーマを募集し、それぞれのテーマごとに会場を分けてOSTの原則に従ったディスカッションセッションを実施しました。 また「チャタムハウスルール」が適用されているため、議論の場では自由に発言ができます。 感想 瀧山: 私はまだインナーソースを実践できていませんが、すでにかなり実践されている方の話を聞くのは面白かったです。初心者の疑問も話題にすることができました。 添野: OSTは初めて参加しましたが、色々とテーマについて他の会社の状況なども交えながら話せてとても楽しく良い経験になりました。 全体を通しての感想・学び・気付き 瀧山: 社外イベントに参加するのは久しぶりでしたが、熱量を感じるセッションばかりでとても刺激を受けました。社内で気になるインナーソースのリポジトリを見つけて、実際にコントリビュートしてみたいと思いました。 添野: イベントに参加してみて、インナーソース活動の新しい観点での気付きがあったり、会場の雰囲気自体もとても雰囲気が良かったため、次回開催されるのであれば、ぜひおすすめのイベントです。 終わりに 弊社では、外部のイベントやセミナーで学びを得られ、得た学びを持ち帰って周囲に共有できるのであれば上司の許可のもと自由に参加することができます。
はじめに こんにちは。基幹システムグループの瀧山です。 AWSは新規アカウント作成から1年間特定のサービスで利用できる無料枠がありますが、絶対に課金されないという設定はできません。 そこで私が実際に遭遇した落とし穴について解説したいと思います。 無課金で使えるはずが課金された! EC2+RDSというシンプルな構成は、AWSアカウント作成から1年間利用できる無料枠内でも構築できます。 本当の最小構成だと1台のEC2にアプリとDBを相乗りさせる方法ですが、本番運用を視野に入れるならアプリとDBは分けた方がよいかと思います。 私も学習目的でEC2+RDS構成を個人アカウントで作っていたのですが、0.10ドルというわずかな金額ではありますが、意図しない課金が発生してしまいました。 課金の原因と対処方法 AWSコンソールの「Billing and Cost Management」(請求とコスト管理)を確認すると、課金されていたサービスはRDSでした。 具体的には、 「Amazon Relational Database Service Backup Storage – $0.095 per additional GB-month of backup storage exceeding free allocation running PostgreSQL」 という項目で課金されていました。 原因:バックアップ期間の設定 原因は、RDSのバックアップ期間が7日に設定されていたことです。 データベース作成方法を「簡単に作成」オプションにすると、バックアップ期間が7日で作成されてしまいます。 これはDBインスタンスサイズを「無料利用枠」に設定しても変わりませんでした。 データ量はかなり少なかったのですが、バックアップ期間の長さにより無料のストレージサイズを超過してしまうようです。 対処方法:バックアップ期間の変更 このバックアップ期間を1日にすると、課金は止まりました。 DB作成段階でこれを防ぐためには、データベース作成方法を「標準作成」オプションにし、バックアップ期間を1日または0日に設定する必要があります。 おわりに RDSを無料枠で利用する際には、RDSのバックアップ期間に注意が必要です。 意図しない課金が発生しないように、「Billing and Cost Management」はこまめにチェックすることをおすすめします。 また今回は個人アカウントでの話ですが、ニフティでは実弾演習場という制度があり、学習目的で自分用のAWSアカウントを作成して月100ドルまでを目安に使えます。(私有PCでも使えます!) その他に、私が所属している基幹システムグループでは独自にAWSのPoC(概念実証)用アカウントがあり、業務で新技術を採用する前の検証ができます。 AWSは手を動かしてリソースを作ることで理解が進む面も大きいかと思いますので、個人/会社アカウント問わず実際に触ってみるのがよいかと思います。
はじめに こんにちは!新卒1年目の高垣、なべしま、パクパクです。 新人研修の一環としてニフティ2025年度新卒入社の9名がAWS JumpStart2025に参加してきました!この記事では 2日間のプログラム内容に加えて、学んだAWSサービスやグループワークで作成したアーキテクチャ設計図を紹介します! AWS JumpStartとは AWS初学者のエンジニアを対象とした実践的な研修プログラム。事前学習動画と2日間の集中的なオンラインワークショップを通じて、AWSへの理解を深める。 単なるAWSサービスの学習だけでなく、要件に合わせてアーキテクチャを検討・設計することも行う。 本プログラムのゴール 一般的なリファレンスアーキテクチャの理解 AWSのコアサービスの概要とその選定基準の理解 AWSのアーキテクチャ図を作成するまでの流れを知る 実施日時 各回2日間(9:00~18:00) 2025 年 3 月 13 日(木)~ 3 月 14 日(金) 2025 年 5 月 27 日(火)~ 5 月 28 日(水) 2025 年 8 月 27 日(水)~ 8 月 28 日(木)(私たちが参加した日時) 2025 年 10 月 23 日(木)~ 10 月 24 日(金) スケジュール 1日目 1日目は、Webアプリケーションについての講義と、実際にWebアプリケーションを構築する実践的なハンズオンを行いました。ハンズオンでは、午前にEC2とAmplify、午後にECS + ALB + RDSといったAWSサービスを使用し、2~4人チームでのモブプログラミング形式で取り組みました。 午前 AWS体験ハンズオン( EC2 ) 最初のステップとして、ユーザ数が100人以下のような小規模なサービスを構築するハンズオンを体験しました。 このフェーズの目標は、 「とにかくシンプルに、そして安価に!」 サービスを立ち上げることでした。ここで利用する主なサービスは以下の通りです。 EC2 (Amazon Elastic Compute Cloud): クラウド上で仮想サーバをレンタルできるサービスです。 VPC (Virtual Private Cloud): AWSアカウント専用の論理的に分離された仮想ネットワーク空間を提供するサービスです。サーバを直接インターネットに公開しないように、「VPC」というプライベートな「柵」を設けるイメージです。 これらのサービスを実際に使って、シンプルなWebアプリケーションを作成するハンズオンを行いました。なお、今回のハンズオンでは1つのEC2インスタンスのみを立ち上げました。そのため、もしこのEC2インスタンスに障害が発生すると、サービス全体が停止してしまうという問題があります。このような弱点のことを 「単一障害点」 と呼び、実際のサービスでは避けなければならない構成です。 AWS体験ハンズオン( Amplify ) EC2とVPCの構成では、仮想サーバの管理やOS・ミドルウェアの設定といった、人による「構築作業」の負荷が高いという課題があります。この課題を解決し、より手軽にサービスを立ち上げる選択肢が Amplify です。 Amplifyには、主に次のような特徴があります。 手軽なデプロイ Webサイトのソースコードなどをアップロードするだけで、デプロイから公開までが自動的に行われます。 高速なグローバル配信 Amazon CloudFrontが自動で設定され、世界中のユーザへWebコンテンツを低遅延で高速に配信します。 自動スケーリング トラフィックの増減に応じてリソースが自動的に拡張・縮小されるため、急なアクセス増にも耐えられ、高い可用性を維持します。 Amplifyのハンズオンでも、シンプルなWebアプリケーションを作成しました。EC2のハンズオンとは異なり、OSやネットワークの設定をすることなくアプリケーションを立ち上げることができました。 このように、Amplifyはサーバレスでインフラ管理が不要という大きなメリットがあります。その一方で、EC2と比べてAWS構成の決定には制限があるため、用途に応じて使い分けることが重要です。 午後 AWS体験ハンズオン( ECS + ALB + RDS ) サービスが成長しユーザ数が増えてくると、次に重要になるのが 「アプリケーションの可用性や拡張性」 です。これを実現するための具体的な手法として、ECS+ALB+RDSといった組み合わせが考えられます。 ECS(Elastic Container Service): Dockerなどのコンテナを簡単に実行・管理できるサービスです。 ALB(Application Load Balancer): サーバへ来るアクセス(トラフィック)を、複数のサーバに自動で振り分けてくれるサービスです。 RDS (Amazon Relational Database Service): クラウド上でリレーショナルデータベースを簡単にセットアップ・運用できるサービスです。 このように、3つのサービスを組み合わせることで、アクセス数の増減に柔軟に対応できる、可用性・拡張性の高いシステムを構築することができます。具体的には、ALBがトラフィックを複数のコンテナ(ECSタスク)へ自動で分散させ、障害が起きたコンテナを切り離してくれるため、サービス全体が停止するリスクを低減し、柔軟な拡張も可能になります。 1日目の午後では、この構成を目指して、チーム全員でToDoアプリを構築するハンズオンに取り組みました。構築したアプリは以下のような感じです! 2日目 アーキテクティング 2日目は、1日目の講義の復習クイズと、AWS構成図を作成する(アーキテクチャ検討)ワークショップを行いました。 復習クイズでは、1日目に学んだサービスの特徴を確認する問題や、AWS認定資格の試験の対策になるようなクイズが出題されました。クイズ後の丁寧な解説が印象的でした。 アーキテクチャ検討ワークショップでは、「AWSを使ってWebサービスをリリースしたい」という課題に沿って設計に取り組みました。AWSの社員の方が今回の要件をロールプレイングで説明してくださったので、ワークショップも楽しく和やかな雰囲気で行うことができました。午前中は個人で設計図を考え、午後はそれぞれの設計図を持ち寄り、5〜8人のグループで協力してAWSシステムの設計に取り組みました。 成果 高垣チーム 私たちのチームは、以下の構成図を作成しました。 私たちのチームでは、月間1万人程度のアクセスを想定し、可用性を最大限高めたいと考えました。そこで、ECSとRDSを使って2つのアベイラビリティーゾーン(AZ: Availability Zone)に配置する構成にしました。 ユーザからのアクセスはCloudFrontを経由し、WAFでセキュリティを高めています。フロントエンド・バックエンド層はECS上でコンテナとして稼働し、これらへのトラフィックはALBを使って分散するようにしました。認証が必要な操作については、Cognitoを使って一元的に管理しています。データベースはRDSを採用して、こちらも2AZ構成にすることでデータベースの可用性を確保しています。また、Redshiftを使って蓄積される購買データなどを分析できるようにしています。 チーム内にAWSについて詳しい方はいなかったのですが、全員で調べたり、質問したりして協力しながら構築することができました。 なべしまチーム なべしまチームでは、複数AZにリソースを分散配置し、DBを冗長化するという高可用性の構成を基本として、次の2つの点を重視して設計を行いました。 1つ目は高いパフォーマンスです。Auroraをメインのデータベースとしながら、一時的に利用されるデータは高速なDynamoDBで管理するよう設計しました。また、Webサービスへの再アクセス時にAuroraの処理負荷を軽減するため、ElastiCacheを導入しました。 2つ目はセキュリティです。外部からのアクセスはCloudFrontを経由させ、WAFによってセキュリティを強化しました。課題のWebサービスでは、ユーザが個別アカウントを持ってサービスを利用することを想定したため、アカウント管理にはCognitoを採用し、高度なセキュリティの実現を目指しました。 「このAWSサービスで実現したいことは何か」を意識して議論することで、チームで納得できる設計ができ、理解をより深めることができました。 パクパクチーム パクパクチームはユーザが増える場合の可用性と拡張性を意識して、以下の構成図を作成しました。 この構成図で特に工夫したポイントは下記の3つです。 1. セキュリティ(Security) サービスで利用されるデータとリソースを保護するため、多層的なセキュリティ対策を実装しました。 WAF: SQLインジェクションやクロスサイトスクリプティング(XSS)のような一般的なWeb攻撃の パターンをトラフィックがサーバに到達する前にフィルタリングします。 AWS Shield: DDoS(分散型サービス妨害)攻撃からシステムを保護するマネージドサービスです。サービスを麻痺させるような悪意のある大量のトラフィックを検知します。 Amazon Cognito: ユーザのサインアップ、サインイン、アクセスコントロールを担う認証サービスです。これにより、認証システムを自前で構築する複雑さを軽減し、セキュリティを強化することができます。 VPC: ネットワークをパブリックサブネットとプライベートサブネットに分離しました。パブリックサブネットには、外部インターネットとの直接通信が必要なウェブサーバやロードバランサーなど、最小限のリソースのみを配置し、データベースや主要なアプリケーションサーバはプライベートサブネットに配置しました。この構成により、データベースが外部から直接アクセスされるリスクを大幅に低減し、リソースへのアクセスを厳格に制御することができます。 2. 可用性(High Availability) ウェブサーバ、アプリケーションサーバ、データベースを含む全く同じシステムを 2つのアベイラビリティーゾーン で構築しました。もし片方の「AZ1」に問題が発生しサーバダウンしても、正常に動いているもう一方の「AZ2」へ自動的にトラフィックが切り替わるように構成し、サービスが停止しない設計しました。 3. 拡張性(Scalability) ユーザ数(トラフィック)は状況によって変わります。イベントや時間帯によって増えることもあれば、減少することもあります。このようなトラフィックの変動に効率的に対応するため 「Auto Scaling」 を導入しました。 これにより、トラフィックが通常時よりも増加した際には自動でECSタスクを追加してサーバの負荷を分散します。逆にトラフィックが少ない時間帯には不要なECSタスクを自動で終了させ、コストを最適化します。 感想 高垣 2日間を通して、クラウドインフラ設計の基礎から実践まで幅広く学ぶことができました。1日目の講義では、単にシステムを構築するだけでなく、安定稼働のための運用面についても詳細な解説があり、実務に直結する知識を深めることができました。2日目では、アーキテクチャを設計しつつ、これまで詳しく知らなかったAWSサービスについての理解を深めることができたのは大きな収穫だと思います。 短い期間でしたが、非常に学びが多い研修でした。 なべしま AWS JumpStartでは、実践的なワークに取り組むことができました。「なぜこのような設定をするのか」「このサービスで実現したいことは何か」など、AWSサービスの深掘りをすることで、より理解が深まったと感じています。 グループワークでは、課題に取り組む中で社外の方との交流がありました。AWSの勉強の進め方や、クラウドサービス・AIの活用についてお話をすることができました。JumpStartのコンテンツ外でも学びを得る、貴重な機会となりました。 パクパク 学生時代は名前しか知らなかったAWSをニフティに入社してから、AWS Summit、そして今回のAWS JumpStartと、直接体験できる貴重な機会をいただきました。 前回のAWS Summitがクラウドへの興味が湧くきっかけになった時間だとしたら、今回のAWS JumpStartは、様々なサービスを組み合わせて一つのアプリケーションを構築する具体的な方法を学んだ時間でした。 特に初心者向けのイベントだったので、AWSが初めての参加者も多く、気軽な雰囲気で質問しながら協力しました。困ったことはチームメンバーと一緒に工夫しながらハンズオンを進めることができました。 以前は複雑な絵にしか見えなかったアーキテクチャ図から、今では各サービスの役割やデータの流れを読み取れるようになりました。今回のAWS JumpStartは今後の業務でAWSの技術やアーキテクチャに向き合う際に「自分も応用できる」という自信を与えてくれた、貴重な経験でした。 AWS JumpStartのページ https://aws.amazon.com/jp/blogs/news/aws-jumpstart-2025/
はじめに はじめまして。2025年5月にニフティへ入社しました、サービスシステムグループのkatrinaです。 趣味でオーケストラサークルに所属しており、コントラバスを弾いています。休日はもちろん平日夜にも練習をしていて、少しでも練習時間を確保したいという思いが仕事のモチベーションにもなってます! これまでの経歴と転職のきっかけ 前職ではSIerとして約9年間、主にお客様先に常駐しながらシステム開発に携わってきました。 多くのプロジェクトを経験する中で、次第に「もっと上流の工程から開発に関わりたい」「サービスそのものの成長を考えられるエンジニアになりたい」という想いが強くなり、転職を決意しました。 転職活動を通じて、ニフティの面接が最も印象的でした。多くの企業で技術的なスキルに関する質問が中心だったのに対し、ニフティでは技術の話はもちろんのこと、私のキャリアプランや仕事に対する価値観といったパーソナルな部分についても質問してもらいました。 自分のやりたいことや価値観を尊重してもらえる雰囲気があると感じられ、入社を決めました。 入社して感じたこと 応募した職種はフルスタックエンジニアでした。前職ではWebアプリケーション開発をメインで行っており、フロントエンドとバックエンドどちらも経験があったので、いずれのスキルも活かしたいと思い応募をしました。 入社して感じた大きなギャップは、アプリケーションの開発だけでなく、インフラ構築や運用など、プロダクトに関わる全てのシステム周りの作業を担うということでした。これが内製化か!と思いました。 特にインフラ領域にはこれまで携わったことがなかったのですが、AWSはもともと個人的に勉強していたので実践の場を得ることができ、やりがいを感じています。 コミュニケーションが活発なチーム 私のチームではスクラムでの開発をおこなっています。スクラムイベントによってコミュニケーションが発生することはもちろんですが、気軽にSlackで質問をしたり、直接声をかけられる雰囲気があります。チームだけではなく社内全体でそういった雰囲気があるように思います。 前職は黙々と作業をすることが多かったのですが、もともとコミュニケーションを取りながら作業を進めて行くことが好きだったので、とても居心地がよいです。 スキルを広げられる環境 入社して初めて担当した作業が、Terraformを使ってのAWS環境の構築でした。 前述の通り、実務でのAWS操作の経験も乏しい中、Terraformは全く初めて触るという状況でしたが、ぜひやってみたいと思い挑戦させてもらいました。「開発環境なら何かあっても戻せばいいからどんどんやってみて」というチームの後押しがとても心強かったです。こういった挑戦しやすい環境があるのは、自分たちで環境を管理しているからこそなのかと思います。 また、社内ではAIを活用できる環境も整っており、有識者による勉強会も頻繁に開かれています。前職では触れる機会がなかったのですが、現在では3ヶ月前の自分では想像できないくらい活用しています。 今後の目標・抱負 まだ経験は少ないですが、ビジネス部門のメンバーと一緒に、新サービスについて検討する打合わせに参加したことがあります。もともと転職のきっかけとなった上流に携わるという環境に身を置くことができているので、エンジニアとしての意見を伝えられるよう、まずはドメイン知識や技術スキルをしっかり身に着けていきたいです。 最後に 私の経験から、ニフティは以下のような方に特におすすめできる会社だと感じています! 工程にとらわれず、担当システムの全てに関わってみたい方 未経験の技術、新しい技術にも主体的に挑戦したい方 チームメンバーと積極的にコミュニケーションを取りながら開発を進めたい方 少しでもご興味をお持ちいただけましたら、まずはカジュアル面談でお話ししませんか?ご連絡をお待ちしております!
はじめに こんにちは。ニフティの山田です。 意外と知らない方が多そうだったので、今回はPATを使わないGitHubのアクセス方法について紹介します。 前提 GitHubではHTTP経由でのID/パスワード認証が廃止され、現在は許可されていません。 このため、 git clone などの際にID・パスワードを入力しても弾かれてしまいます。(ブラウザと同様です) なので、 HTTP Personal Access Token(PAT) OAuth認証 SSH の3通りの接続方法から選ぶことになります。 SSHが使える環境ではSSHを使えばよいのですが、環境によってはSSHを通せず、HTTPを使用する必要がある場合もあります。 PAT PATは古くからある方法であり、Personalの文字通り、個人に紐づくトークンを手動で発行・管理します。 手動管理する鍵であり、管理の漏れや漏洩の可能性がある 用途ごとに鍵を分けるのか使い回すのか…など、鍵管理を考える必要がある というように管理負担もセキュリティリスクもあり、なるべく使いたくない選択肢です。 OAuth認証 前提で記載した2つ目の選択肢です。OAuth認証後に発行されるトークンでもGitHubへのアクセスが可能となります。 OAuthなのでブラウザが必要ですが、Git実行PCと別のPCでも問題ありません。 GitHub Desktopを使う方法 Download GitHub Desktop インストール・起動して指示通りに進めばGitHubへOAuth認証を促されます。 GitHub Desktopがログインできている状態であればOAuthトークンが有効なので、gitコマンドでの操作でも認証が通ります。 GitHub CLIを使う方法 GitHub CLI コマンドライン上で完結させたい場合はGitHub CLIをインストールします。 macOSであればhomebrewから brew install gh でのインストールも可能です。 インストール後 gh auth login でログインできます。あとは普通にgitコマンドを叩けば完了です。 操作 $ gh auth login ? Where do you use GitHub? GitHub.com ? What is your preferred protocol for Git operations on this host? HTTPS ? Authenticate Git with your GitHub credentials? Yes ? How would you like to authenticate GitHub CLI? Login with a web browser ! First copy your one-time code: XXXX-XXXX Press Enter to open <https://github.com/login/device> in your browser... ✓ Authentication complete. - gh config set -h github.com git_protocol https ✓ Configured git protocol ! Authentication credentials saved in plain text ✓ Logged in as xxxxxx 途中の「Press Enter to~」でEnterを押すとブラザが開くので、ブラウザ側でログインしてコードを入力します。 なおブラウザでのコード入力を要求されますが、この操作は別マシンのブラウザで行っても問題ありません。なのでサーバ上でも問題なくログインが可能です。 制約 PATと異なり、 有効期限がない(設定もできない) GitHub画面上から無効化しない限り、無期限にずっと使えてしまう 短期にしてほしいというissueはある https://github.com/cli/cli/issues/5924 PATと異なり、権限制御はできない 自動化目的であればPATを使う おわりに 今回はPATを使わないGitHubのアクセス方法について紹介しました。 この機会にPATの管理負担なども考慮して、OAuth認証でのGitHubアクセスを試してみるのはいかがでしょうか。
はじめに GoのWebフレームワークとして著名なものにGinがあります。 GinにおいてHTTPリクエストを取り扱うにはgin.Context型の構造体を取り扱いますが、これをなんとなく使うと危険な使い方をしかねないため、注意が必要というお話です。 何となく書いてたもの GinでDBアクセスするアプリを書こうとしており、OpenTelemetry(OTEL)を入れるような設定を入れようとしていました。 主な流れを取り出すと以下のようになります。実際はdatabase/sql直接ではなくてORM経由だったり、ファイルが分かれていたりします。 db, err := sql.Open('.....') r := gin.New() // OTELで必要と書かれていたので追加 r.ContextWithFallback = true r.POST('/hoge', func(ctx *gin.Context) { // ~ パラメータ取り出し処理 ~ tx, err := db.BeginTx(ctx); // ~ 何らかの処理 ~ // ~ Commit or Rollback ~ ctx.JSON(...) }); r.ContextWithFallback = true がOTELのために追加したもので、これはGin公式のOTEL向けサンプルを参考にしたものになります。 https://github.com/gin-gonic/examples/tree/master/otel 現在はREADMEが更新されており、 This configuration is necessary for the example to work but may not be ideal for production use. と本番向けではないことが明示されています。 危ないポイント gin.Context はGo標準の context.Context インターフェースを実装しているので、 context.Context として振る舞うことができます。 デフォルトではHTTPリクエストのデータを持たず、ContextWithFallbackオプションを有効にすることでリクエストのデータを引き継ぐ…のですが、 原則使うべきではありません 。 Go標準の context.Context はスレッドセーフであることが期待されますが、 gin.Context はそうではありません。 gin.Context はGin内部で sync.Pool を使ってプーリングされるように実装されており、中身を消して再利用されます。したがって、 ハンドラ関数の中でContextを渡され、cancelを待つread処理 上記例だとdatabase/sqlが待つ ginがContextの中身を消去しようとするwrite処理 が競合することになります。これはテスト時に go test -race オプションを付けて実行すると、race detectorが反応することで検出することができます。 正しくは gin.Context の内部にある Request.Context() を取り出せば良いです。こちらは net/http によって作成されるものであり、再利用されることはありません。 Echoなど他のフレームワークでも同じような実装方法となっています。 r.POST('/hoge', func(ctx *gin.Context) { // gin.Contextからhttp.Requestのコンテキストを取り出す rCtx := ctx.Request.Context() ... tx, err := db.BeginTx(rCtx); } リクエストのライフサイクル 上記によりGin特有の問題は解消されますが、そもそもリクエストのContextを引き継いでよいのかという問題も別途存在します。 リクエストのContextはHTTPコネクション切断によりキャンセルされるため、DBに渡すと未コミットのトランザクションがあればロールバックされる可能性があります。 アプリケーションの要件によりますが、コネクションが切れても処理を続行したいという場合には、別のContextを作成する必要があります。 r.POST('/hoge', func(ctx *gin.Context) { // コンテキストを引き継がず、新しいコンテキストを作る nCtx := context.Background() ... tx, err := db.BeginTx(nCtx); } ただしこれではContextに含まれる値も初期化されることになります。 これではContext経由でGinのデータにアクセスする処理、たとえば OTELのmiddlewareでContextに入れたトレースIDをもとにSpanを作成 middlewareでContextに入れたリクエストIDをログ出力する のような機能が使えなくなってしまいます。 このような場合は、キャンセルのみ引き継がないようにします。(要Go 1.21+) r.POST('/hoge', func(ctx *gin.Context) { // cancelを引き継がないコンテキストを作成 nCtx := context.WithoutCancel(ctx.Request.Context()) ... tx, err := db.BeginTx(nCtx); } このままだと一切のキャンセル処理がなくなります。安全のため自力でキャンセル処理を入れたい場合、WithoutCancel()してからWithCancel()すればよいでしょう。 r.POST('/hoge', func(ctx *gin.Context) { // 既存cancelを無効化してからcancel追加 nCtx, cancel := context.WithCancel(context.WithoutCancel(ctx.Request.Context())) defer cancel() ... tx, err := db.BeginTx(nCtx); } これで値は引き継ぎつつ、キャンセル伝搬から切り離す事ができます。 おわりに Ginの gin.Context はスレッドセーフではありません。 context.Context インターフェースを実装していることから勘違いしがちなのですが、 context.Context として扱わないようにしましょう。 またアプリケーション要件によっては、キャンセルの伝搬を止めるような実装が必要となることもあります。 みなさんも注意していただければと思います。
はじめに こんにちは。ニフティの山田です。 AWSのElastic Container Service(ECS)を使ってシステムを構築する際、機能追加や負荷の変動に応じてサービス構成を変更する必要が生じることがあります。特に多数のサブシステムからなるような構成では、フロントエンド寄りのサービスの要件によって通信先を変更することも少なくありません。 この記事ではこのような状況に柔軟に対応できる構成方法について考察します。 基本構成の課題 標準的なECSベースの構成は以下のようになるかと思います。 この構成では、長期運用を考えた場合に以下のような課題があります。 フロントエンドだけ構成が異なる ECSにアクセスするためにはALBが必要なので、ALB/ECSはワンセットで考えたい 外部アクセスが必要な部分はPublicなALBにする必要があり、ここだけ構成が変わる フロントエンドの前段にシステム追加を行いたいような場合、インフラ構成に大きな変更が入ってしまう Terraformで管理している場合、フロントエンドだけモジュール構成を大きく変える必要が生じる場合がある フロントエンドの部分にプライベートAPIを生やさざるを得ない、という状況で厄介 一度インターネットに出る必要が生じる NAT GWのIPを許可するなどの微妙な対応が必要 フロントエンドのALBだけ複数の役割を持っている ECSに対するALBの役割は純粋な負荷分散装置、つまりスケーリングに対応するためのもの フロントエンドだけはパスごとのルーティングなど、リバースプロキシとしての機能を持つ可能性がある つまりパブリック公開部分だけがインフラ構成上、特殊な扱いをされていることになります。 これを解決するためには、以下のようにしたくなります。 常にALB/ECSを1セットにしてすべてプライベートサブネットに設置することとし、別途公開用のリバースプロキシ専用ALBを立てます。公開要件はリバースプロキシ用のALBに集約されるので、各サブシステム側は気にする必要がなくなります。 ですが ALBのターゲットにALBを指定できない ので、この構成を実現することはできません。また二重のALBが完全に無駄です。さてどうしましょうか。 構成案 リバースプロキシ/BFFの設置 古典的なWeb3層構成のように、リバースプロキシ(Apache/nginx)を用意します。構成によってはBFFのようなものになることもあるでしょう。 パブリック公開の責務はここに集約します。 Pros 公開に関する責務は分離でき、裏側の構成は自由 Apache/nginxの機能を利用できるため、複雑なルーティングやアクセス制御があったとしても対応できる 構成として理解はしやすい Cons リソースが増える リバプロ用ECSが増えてしまう インフラコストも運用コストも増える ALBの機能とリバプロの機能が重複する 適用できそうなケース 古典的アプリを移植してくるケース アクセス制御が複雑で、Apache/nginxが必要になるケース 静的コンテンツの配信がアプリ外で必要になるケース CloudFront VPC Origins CloudFrontを使用する前提となります。 CloudFront VPC Originsを使うとCloudFrontからVPC内部に直接アクセスできます。Public ALBが不要となり、ALB/ECSはすべてプライベートサブネットに置けるようになります。 Pros Public ALBが不要 IPv4アドレス課金を減らせる IPv4アドレス直接アクセスによるスパム・不正アクセスを考えなくて良くなる Cons CloudFrontをもともと使っていない場合はコスト増になってしまう ルーティングをCloudFrontで行うことになる CloudFront自体の振り分け機能はALBに比べてかなり少ない HTTPヘッダなどの条件を入れる場合、CloudFront Functionsで頑張ることになる ALB特有機能が一部使えない OIDC連携機能など 適用できそうなケース CloudFrontを既に使っているケース ルーティング要件が複雑でなく、CloudFront Functionsでカバーできる OIDC連携などが必要ない Service Connect サービスメッシュライクなサービスであるService ConnectによりECS間通信を行います。 Service Connectを使うと、各ECS TaskはサイドカーコンテナとしてEnvoy Proxyが自動挿入されます。各ECS ServiceはCloud Mapに登録され、Service間はCloud Map上の登録名でアクセスし、実際の通信はEnvoy Proxyによりルーティングされるようになります。 従来はBlue/Greenデプロイができないという課題がありましたが、先日発表されたECS built-in Blue/Greenデプロイで対応できるようになりました。 ECS Service間でしか通信できないため、パブリックアクセスにはALBが必要となります。 Pros ALBがなくなる分、ネットワークレイテンシが削減される ALBの分のコストが減る Cons Envoy Proxyの分、追加のCPU/RAMを要求する 256 CPU Unit(0.25vCPU)/64MB RAMを追加することが推奨 ECS Service間でしか通信できない 定時実行LambdaなどでバックエンドのECSを叩く、などは不可能 フロントエンドの柔軟性は低いまま ここだけALBに縛られてしまう 適用できそうなケース 以下を両方満たすケース ECS Service間でしか通信しない Envoy Proxy分のコスト増よりも、ALB削減分が上回る 元々ECS Taskのスペックに余裕があり、Service Connectによるスペックアップが不要な環境でないとおそらく満たせない VPC Lattice(ECS統合) VPC Latticeは仮想ALBとでも呼ぶべきサービスです。複数のアカウント・VPCをまたいで「サービス」を定義し、そこに対する「リスナー」「ターゲットグループ」を設定できます。 ターゲットグループに追加するのは通常はALBなどですが、ECS統合の機能が追加されたことにより直接ECS Serviceをターゲットとして指定できるようになっています。 Pros ALB同様の機能、柔軟性を持つ VPC・アカウントをまたいで統一的なサービス管理が可能 Cons 高額 維持料金、データ転送料金ともALBより高額 適用できそうなケース 単一サービス内での適用はコスト効率が低いため、会社全体でVPC Latticeを導入し、サービス間接続をVPC Latticeに任せるケース まとめ 複数のECSサービス構成方法を検討した結果、以下の結論に至りました。 CloudFrontを使えるなら、ALB/ECSをすべてプライベートサブネットに配置し、CloudFront VPC Originsで接続する構成が安定的かつ柔軟性も高い CloudFrontを使えないなどの場合は、従来通りALBをパブリック公開する方法も有効 Service Connectは期待できるサービスではありますが制約も多く、慎重な選択が必要となります CloudFrontを使えるという前提にはなりますが、VPC Originsによる構成は有用な選択肢となりそうです。最終的な構成選択は、サービスの規模や要件、コスト制約によって異なりますが、新規構築などの際に検討してみてはいかがでしょうか。
はじめに 2年目社員の藤岡、山本です。2025年8月のAI博覧会 Summer 2025に参加してきました。近年急速に進化する生成AIの最新動向や活用事例を学ぶ絶好の機会となりましたので、その内容と得られた知見をシェアしたいと思います。 AI博覧会とは AI博覧会 は、国内最大級の人工知能技術の展示会・カンファレンスです。企業や研究機関による最新AI技術の展示、実践的な活用事例の紹介、専門家によるセミナーなどが行われる総合イベントです。基本的に年に2回以上(春・夏など)開催され、今回は2025年夏の開催となりました。 特に今回のSummer 2025は「生成AI社会実装元年」をテーマに、2022年末に登場し市場に大きな影響を与えたChatGPT以降、定着期に入った生成AIの実用的な活用事例に焦点が当てられていました。 なぜ参加したの? 私たちは社内の「AI活用推進プロジェクト」に参加しており、既存業務へのAI組み込みを加速させ業務効率を向上させる活動をしています。日々進化するAI技術の最新動向をキャッチアップし、具体的な活用事例を学ぶことで、自社での取り組みに活かしたいと考え参加しました。 ニフティで社外イベントに参加するには 藤岡・山本「AIにフォーカスしたイベントらしいので行ってみていいですか?」 上司「いいね、ぜひいってみてください」 弊社では技術イベントへの参加を積極的に推奨しており、ほとんどのイベント参加が認められます。得た知識を社内で共有することで、社内全体の成長にもつながり、技術力向上を重視する社風が根付いているのはニフティの強みだと思います。 AI博覧会現地の様子 AI博覧会は東京国際フォーラムで2日間にわたって開催されました(8月27日・28日)。全日程参加し、様々なセッションや展示を見て回りました。 会場は大きく分けて「展示エリア」と「セミナーエリア」に分かれていました。展示エリアでは100社以上がブースを出展し、約200種類の最新AI技術やソリューションが紹介されていました。セミナーエリアでは約40講演が並行して開催され、パネルディスカッションも行われていました。 参加者は企業のIT担当者や経営層、エンジニア、研究者、学生など多岐にわたり、その数は2日間で約8,000名とのことです。AI活用への関心が高まっていることを実感しました。 参加者の服装は、企業ロゴ入りポロシャツやTシャツ、ビジネスカジュアルが中心で、会場は全体的にカジュアルでオープンな雰囲気でした。 会場の様子 プログラム セミナーエリアでは、基調講演、テクニカルセッション、事例紹介、パネルディスカッションなど、様々な形式の発表が行われました。特に印象的だったのは冒頭の「生成AI大賞2024受賞企業のライオンとNECビジネスインテリジェンスが語る。業界を変える生成AIの価値創造事例」と題されたセミナーでした。 発表者は業界を代表する企業のCTOやAI研究者、そして先進的にAIを活用している企業の実務担当者など様々でした。特に実践的な活用事例の発表は、具体的な効果や導入時の課題なども率直に語られており、非常に参考になりました。 セミナーによっては満席になり急遽サテライト会場が用意されるセミナーも多数ありました。 満員のセミナーの様子 タイムテーブル QAエージェント「笑理(えみり)」さん HP内や会場入口ではQAエージェントのえみりさんがイベントに関する質問に回答してくれたりと、AIにフォーカスしたイベントらしい工夫も感じられました。 SNSでは「 #AI博覧会 」のハッシュタグで多くの投稿がされており、各セッションや会場の様子・感想などがリアルタイムでシェアされていました。 会場入り口のQAエージェント「笑理(えみり)」さん 企業展示ブース 展示エリアには国内外のAI関連企業が100社以上出展しており、製品デモやユースケース紹介が行われていました。特に印象的だったブースを紹介します。 株式会社 Helpfeel ユーザーが入力した曖昧な言葉や表現から意図を予測し、最も適切な質問や回答ページを提案する技術です。スペルミスや表記揺れ、漢字・ひらがな・カタカナの違いにも柔軟に対応し、入力途中でも候補を表示します。従来のキーワード検索よりも精度が高く、様々な言い回しでも求める情報に素早く到達できます。独自のアルゴリズムと高速検索エンジンを組み合わせ、FAQページの自己解決率向上や問い合わせ削減に貢献します。 ブースの様子(案内のお姉さんがブログ掲載を快く承諾してくださいました!) 株式会社 ソフツー コールセンターなどの受電業務においてAIが一次受付を担当したり、AIがお客様の問い合わせ内容を要約し適切な管轄部門への取次を行ったりするというサービスが紹介されていました。 ニフティでは自社でコールセンターを運用しているため、自社の課題と照らし合わせながらお話を聞くことができました。 ブースの様子 Findy Team+ GitHubなどのデータからエンジニアの業務状況を可視化し、それを元にAIがデータ分析し改善案を提供するサービスが紹介されていました。 現在自社でもエンジニアの工数可視化や業務最適化に力を入れているため、色々と参考になるお話を聞くことができました。 ブースの様子 参加セッションの内容と学び 2日間で参加したセッションの中から、特に印象に残ったものを紹介します。 1. 基調講演: 間もなく登場から3年、生成AI活用で変わる社会と仕事のかたち 日本マイクロソフト株式会社の西脇さんは基調講演で、生成AIが誰でも使える身近なツールになったと強調していました。日本のAI利用率は46%と低いことについても触れながらも、比較よりも「まず使う」ことが重要だと説明していました。効果的な活用には具体的な指示と対話による改善が必須であり、生成AIはIT戦略だけでなく、人材育成や経営戦略として全社的に取り組むべき技術だとお話ししてました。 2. セミナー: 生成AI大賞2024受賞企業のライオンとNECビジネスインテリジェンスが語る。業界を変える生成AIの価値創造事例 生成AI大賞2024受賞企業のライオン株式会社の山岡さんとNECビジネスインテリジェンス株式会社の若林さんが登壇され、一般社団法人Generative AI Japanの漆原さんを交えて活用事例を紹介されていました。両社は社内チャットアプリ開発や業務プロセスへのAI組み込みを推進しています。導入課題として社員の考え方変革と経営陣のコミットメントの重要性を強調し、最も効果的なアプローチは「まず使って改善する」姿勢と管理職層の賛同獲得だと説明していました。今後はAIと人間の役割再定義や教育制度見直しが必要であり、労働人口減少対策としてもAI活用が不可欠と述べていました。 反省点 2日間の参加を通じて、いくつかの反省点もありました。 事前の計画が不十分だった 人気セミナーは早めに席を確保すべきだった RAGなど注目度の高いセッションはすぐに満席になってしまった セミナーに早めに並ぶべきだった 予約をしていても想定以上の参加者でサテライト会場に案内されるセミナーが複数あった モバイルバッテリーを持っていくべきだった まとめ:AI博覧会の主な学び 2日間のAI博覧会を通じて、生成AIが実験段階を超え、実用的なビジネス価値を創出する段階に入ったことを実感しました。 特に印象的だった3つの重要ポイント: 「使いながら学ぶ」姿勢 – 完璧を求めるより業務への実践的な試行錯誤が重要 明確な目的設定 – 具体的な業務課題解決を常に意識する 全社的なAIリテラシー向上 – 全社員がAIを理解し活用できる文化づくりが競争力の源泉 来年も開催予定のAI博覧会では、さらなる技術進化が期待されます。引き続き最新動向をキャッチアップし、ビジネスに活かしていきます。 ニフティでは、最新技術を活用したサービス開発に取り組むエンジニアを募集しています。ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報
はじめに こんにちは。ニフティのIWSです。 今回は特定のファイルが変更されたらPRに警告を出すやり方について共有します。 何かの参考になれば幸いです。 背景 1つのファイルに手を加えたら、他のファイルも忘れずに変更しないといけないプロジェクトでは、変更漏れがどうしても生じてしまいます。 目検で漏れがないかの確認は大変なので、このテンプレートに変更があるPRが作成されたときに「HTMLに変更あるけど意図したやつ?」「テンプレートの変更1つにしか無いけど漏れてない?」みたいに警告するワークフローをつくってみました。 動作について PRを作成した際にHTMLをファイルに変更があった際に、以下の画像の用にコメントをするワークフローが動作します。 コード GitHub Actionsに以下の設定を行います。 コードの解説については以降の章でお話ししますので、説明を読みつつ、ご自身の利用用途に応じて書き換えてみてください。 name: Alerts you to template changes on: pull_request: types: [opened, reopened, synchronize] paths: - 'django/templates/process/*/*.htm' - 'django/templates/process/*/*.html' jobs: notify: runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: diff_check env: # PRにコメントするために必要 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | # 変更されたテンプレートファイルのリストを取得 changed_file_list=($(git diff --name-only origin/${{ github.base_ref }} HEAD --relative="django/templates/process/" | sed 's|^django/templates/process/||')) # 変更されていないテンプレートファイルのリストを取得 no_change_file_list=($(comm -23 \ <(find django/templates/process/ -type f | sed 's|^django/templates/process/||' | sort) \ <(printf '%s\n' "${changed_file_list[@]}" | sort) )) # コメントの本文を作成 cat << EOF > ./body.txt :warning: プロセス画面テンプレートへの変更があります!! :warning: テンプレートの変更内容が意図したものか、変更漏れが無いかを確認してください! 変更されたテンプレート $(printf -- '- %s\n' "${changed_file_list[@]}") 変更されていないテンプレート $(printf -- '- %s\n' "${no_change_file_list[@]}") EOF # PRにコメント gh pr comment ${{ github.event.pull_request.number }} -F ./body.txt --repo ${{ github.repository }} コードの解説 処理の流れは以下です。 特定のファイルに変更があった際に発火 変更があったテンプレートのリストを取得 変更がなかったリストも取得 変更があったもの、なかったものをそれぞれコメント 1.特定のファイルに変更があった際に発火 paths を使うことで指定したファイルに変更があったときだけワークフロー実行できます。サンプルコードは .html と .htm のファイルに変更があったときだけ発火する処理となります。 (もし paths-ignore を使用すると、指定のファイル以外の変更があれば発火します。) 参考サイト: https://qiita.com/nacam403/items/3e2a5df5e88ba20aa76a on: pull_request: types: [opened, reopened, synchronize] paths: - '**.html' - '**.htm' # js配下のhoge_process.jsが対象 paths: - 'django/static/js/*process.js' 2. PRの差分を取得 # 変更されたテンプレートファイルのリストを取得 changed_file_list=($(git diff --name-only origin/${{ github.base_ref }} HEAD --relative="django/templates/process/" | sed 's|^django/templates/process/||')) git diff —name-only で変更があったファイルを取得し、 --relative をつかって指定Path以下のファイルの変更だけを取得し、それをsedで整形しています。(diff結果のPathの共通部分を削除しています django/templates/process/ ) sedの前に grep を入れることで対象を細かく指定できるようにもなります # 変更されたJSファイルのリストを取得、process.jsとindex.jsのみを対象とする changed_file_list=($(\\ git diff --name-only origin/${{ github.base_ref }} HEAD --relative="django/static/js/" | \\ grep -E '(process|index)\\.js$' | \\ sed 's|^django/static/js/||' \\ )) 3. 変更がなかったリストも取得 # 変更されていないテンプレートファイルのリストを取得 no_change_file_list=($(comm -23 \\ <(find django/templates/process/ -type f | sed 's|^django/templates/process/||' | sort) \\ <(printf '%s\\n' "${changed_file_list[@]}" | sort) )) 2で出した変更ファイルリストと、同じPathの全体のファイル一覧のリストを突き合わせて変更されていないファイルのリストを作っています。 comm コマンドについては以下をご参考くださいませ。 参考サイト: https://qiita.com/hypermkt/items/f6388bf72d9b30c6d601 2の処理でgrepを入れた場合はこちらにもgrepを入れるのを忘れないでください。 # 変更されていないJSファイルのリストを取得 no_change_file_list=($(comm -23 \\ <( \\ find django/static/js/ -type f | \\ grep -E '(process|index)\\.js$' | \\ sed 's|^django/static/js/||' | \\ sort \\ ) \\ <(printf '%s\\n' "${changed_file_list[@]}" | sort) )) 変更があったもの、なかったものをそれぞれコメント # コメントの本文を作成 cat << EOF > ./body.txt :warning: process.js or index.js ファイルへの変更があります!! :warning: プロセス画面JSファイルは画面ごとに複数あります。変更漏れが無いかを確認してください! 変更されたテンプレート $(printf -- '- %s\\n' "${changed_file_list[@]}") 変更されていないテンプレート $(printf -- '- %s\\n' "${no_change_file_list[@]}") EOF # PRにコメント gh pr comment ${{ github.event.pull_request.number }} -F ./body.txt --repo ${{ github.repository }} 2,3で作ったリストを使って body.txt を作っています printf -- '- ... の -- はそれ以降の – をオプションとして扱わないことを意味します。 今回のケースでは、Markdownとして - を使いたいのだけど、そのままだとオプションの - と勘違いされてしまうことを回避するために入れています。 ( - を抜くと実際に printf: - : invalid option と怒られます。) もしPRへコメントする際はghコマンドを使用してください。 WF発火したPRを ${{ github.event.pull_request.number }} で指定し body.txtの内容をコメントしています。ただし、複数行のコメントにはテキストファイルなどで渡す必要があるので注意してください。 おわりに 今回は特定のファイルが変更されたらPRに警告を出すやり方について紹介しました。 変更漏れが多いリポジトリなどに是非活用してみてください。
はじめに こんにちは!ニフティ株式会社新卒1年目のやまだ25です。 現在、私はインフラシステムグループに所属し、社内でオンプレミス運用しているファイルサーバをクラウド上へリプレイスする業務を行っております。 本記事では、Azure Filesの検証時に特に苦労したAD DS認証の有効化について、下記の公式ドキュメントに沿いつつ、わかりづらい部分や補足情報を交えて解説します。 Microsoft公式ドキュメント「Azure ファイル共有に対して Active Directory Domain Services 認証を有効にする」 https://learn.microsoft.com/ja-jp/azure/storage/files/storage-files-identity-ad-ds-enable 筆者プロフィール 入社時期: 2025年4月 入社前のスキル: Python 所属チーム: インフラシステムチーム 概要 Azure Filesとは、Microsoft Azureが提供しているフルマネージドなSMB/NFSファイル共有サービスです。 新たにサーバを構築する必要がなく、比較的容易に構築をすることができます。 Azure Filesでは、ストレージアカウントキーを使用してファイル共有に簡単にアクセスできるほか、AD DS認証を有効化することでアクセス制御をすることも可能です。 すでにAD DSによる認証・アクセス制御を利用しているオンプレミスのファイルサーバをAzure Filesにリプレイスする場合、この機能を有効化することで従来の管理方法を維持することができます。 今回は、すでにAzure上でAzure Filesが作成済みであるとし、Windows PC上のPowerShellを用いて、AD DS認証を有効化するまでの手順をご紹介します。 大まかな流れは以下の通りです。 前提条件 事前準備 PowerShellモジュールのインポート Azureへの接続 各種パラメータを設定 対象のサブスクリプションを選択 ストレージアカウントをActive Directoryにドメイン参加 ※本記事では、Active Directoryの基本的な説明は省略します。 前提条件 今回の記事での前提条件は以下の通りです。 Azure上にストレージアカウントを作成しており、そこにAzureファイル共有が作成済みである オンプレミスのActive Directoryがすでに構築されており、Microsoft Entra Connect SyncアプリでMicrosoft Entra IDと同期されている PowerShellを実行するWindows PCのユーザがドメイン参加しており、コンピュータアカウントを作成する権限を持っている Windows PCのPowerShellのバージョンが5.1以上である バージョンの確認方法 $PSVersionTable を実行し、出力結果の PSVersion が 5.1 以降になっていればOKです! Windows PCにインストールされている .NET Frameworkのバージョンが4.7.2以上である バージョンの確認方法 Get-ItemPropertyValue -LiteralPath 'HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' -Name Release を実行し、 461808 以上であればOKです! Windows PSのOSのバージョンがWindows 10 (1809以降)またはWindows 11以降である Windows 10のバージョンの確認方法 Windowsキー+Rを押します。 表示された「ファイル名を指定して実行」ウィンドウにwinverと入力し、Enterキーを押します。 「Windowsのバージョン情報」ダイアログが表示され、「バージョン」と「OSビルド」を確認できます。ここで、バージョン番号(例: 1803, 1809, 22H2)が分かります。 事前準備 ※ 以下、すべてWindows PCがインターネット接続ができる環境下であることを前提としています。 PowerShellGetモジュールをインストール 【インストール手順】 PowerShellを管理者権限で開き、次のコマンドレットを実行します Install-Module -Name PowerShellGet -Force (インストール中に NuGetプロバイダーをインストールするか尋ねられるので Y を入力) 【インストールできたか確認する方法】 Get-Module -Name PowerShellGet -ListAvailable を実行して、以下のような表示が出ていればインストールに成功しています。 Azure PowerShellモジュールをインストール 【準備】 まず、次のコマンドレットを実行して、PowerShell実行ポリシーを確認しましょう。 Get-ExecutionPolicy -List 実行結果の Process 、 CurrentUser または LocalMachine が Undefined の場合、以下のコマンドレットを実行して本プロセス中の実行ポリシーを緩い状態にしてください。 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process 【インストール手順】 次を実行するとモジュールがインストールされます。 Install-Module -Name Az -Repository PSGallery -Force 【インストールできたか確認する方法】 Get-InstalledModule -Name Az を実行して、以下のような表示が出ていればインストールに成功しています。 Active Directory PowerShellモジュールをインストール (今回はWindows11の場合の手順を紹介します) 【インストール手順】 設定アプリを開き、「システム」の中の「オプション機能」へ移動します。 「オプション機能を追加する」の右にある「機能を表示」をクリックし、検索欄に RSAT: Active Directory Domain Servicesおよびライトウェイトディレクトリサービス を入力します。 候補として上記ツールが出てくるので、チェックを入れて「次へ」をクリックします。 追加する内容の確認画面に遷移するため、上記ツールが含まれていることを確認し「追加」をクリックします。 インストールが開始されます。なお、私の環境ではインストール完了まで、5~10分ほど時間を要しました。 【インストールできたか確認する方法】 Get-WindowsCapability -Name "Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0" -Online を管理者権限で実行して、以下のような表示が出ていればインストールに成功しています。 AzFilesHybridモジュールをダウンロード 公式ドキュメント の「AzFilesHybridモジュールをダウンロードする」にあるリンクをクリックすると、GitHubのページが表示されます。 Assetsの中に AzFilesHybrid.zip があるのでこれをダウンロードしてください。 ダウンロードしたら、このファイルを展開します。 ※ この際、どこに展開したかを記録しておきましょう。インポートする際に展開先のパスを使用します その他の事前準備 必須ではありませんが、今回Active Directory上に作成するコンピュータアカウント用のOUを作成します(今回は、OUの作成は必須ではないため作成手順は省略します)。 なお、OUを作成しなかった場合は、Active Directoryのルートディレクトリにアカウントが作成されます。 PowerShellモジュールのインポート Active Directory PowerShellモジュールのインポート 次のコマンドレットを実行します。 Import-Module -Name ActiveDirectory AzFilesHybridモジュールのインポート まず、次のコマンドレットを実行し、本プロセス中のPowerShell実行ポリシーを Unristricted に変更します。 Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process 次に、展開したAzFilesHybridへ移動します。 cd \path\to\AzFilesHybrid このフォルダの中にあるCopyToPSPath.ps1ファイルを実行します。 .\CopyToPSPath.ps1 最後に、AzFilesHybridモジュールをインポートします Import-Module -Name AzFilesHybrid Azureへ接続 次のコマンドレットを実行します。 Connect-AzAccount -Tenant "<テナントID>" ※ もし、お使いのAzureが1つのテナントのみの場合は -Tenant "<テナントID>" がなくても実行が成功しますが、2つ以上のテナントを使用している場合は混同を避けるために -Tenant "<テナントID>" をつけて実行しましょう 実行すると、対話型ブラウザ認証が起動するため、自分のMicrosoftアカウントでログインしましょう。 【テナントIDの調べ方】 Azureポータル上でMicrosoft Entra IDを開くと概要のページにテナントIDが表示されます 各種パラメータの設定 まず、Azure Filesを構築したサブスクリプションのID、リソースグループの名前、ストレージアカウントの名前を確認します。 対象のストレージアカウントをAzureポータル上で開くと、概要にリソースグループ名およびサブスクリプションIDが記載されています。 上記の情報をもとに、以下3つのパラメータを設定します $SubscriptionId = "<サブスクリプションID>" $ResourceGroupName = "<リソースグループ名>" $StorageAccountName = "<ストレージアカウント名>" 次に、SAMアカウント名 (作成するコンピュータアカウントの名前)を決めます。 SAMアカウント名の命名の際の制限 15文字以内で、使用できる文字はa~z、A~Z、0~9および一部の記号(-や_など)です 次の記号は使用できません "/ \\ [ ] : ; | = , + * ? < > 以降に記載のコマンドレット Join-AzStorageAccount を実行時、このSAMアカウント名の後ろに $ を付けるため、この段階では末尾に $ は付けないでください SAMアカウント名が決定したら、次を実行します。 $SamAccountName = "<SAMアカウント名>" 続いて、Active Directoryに作成するアカウントのタイプを選択するパラメータを設定します。 $DomainAccountType = "<ComputerAccount または ServiceLogonAccount>" なお、デフォルトでは ComputerAccount となっており、特別な事情がない場合は ComputerAccount を選択しましょう。 最後にOUを作成した場合は、その情報もパラメータとして設定します $OuDistinguishedName = "OU=(あなたが設定したOU名),DC=~,DC=~" 例えば、作成したOUの名前が AzureFiles 、Active Directoryのドメイン名が nifty.example.com だった場合は、 $OuDistinguishedName="OU=AzureFiles,DC=nifty,DC=example,DC=com" とします。 対象のサブスクリプションを選択 次のコマンドレットを実行します Select-AzSubscription -SubscriptionId $SubscriptionId 実行後、以下のような表示が出ていればOKです ストレージアカウントをActive Directoryにドメイン参加させる 次のコマンドレットを実行します。 (ただし、OUを作成していない場合は、 -OrganizationalUnitDistinguishedName $OuDistinguishedName の部分を削除してから実行しましょう) Join-AzStorageAccount -ResourceGroupName $ResourceGroupName` -StorageAccountName $StorageAccountName` -SamAccountName $SamAccountName` -DomainAccountType $DomainAccountType` -OrganizationalUnitDistinguishedName $OuDistinguishedName` ※ 上記のコマンドでは、Active DirectoryにAzureのサービスアカウントを、コンピュータアカウントとして作成しドメイン参加させます。そのため、このコマンドを実行するユーザにアカウントを作成する権限がついていないと、実行に失敗します。 終わりに Azure FilesのAD DS認証の有効化はAzureポータルからGUI操作で設定することができず、PowerShell上での構成が必要となります。 今回私は構成をしていく中で、権限の確認やモジュールのインストール、Azureへの接続など随所で躓いてしまいました。 私と同様に躓いている方がいらっしゃいましたら、本記事が問題解決の糸口になれば幸いです。 この記事を読んだ学生さんに向けて 私の学生時代の専攻は情報系ではなく、またAWSはかろうじて触ったことがあったもののAzureは全く触ったことがなかったため、試行錯誤の連続でした。 ですが、粘り強く取り組んだことで、この記事を執筆できる程度には理解を深めることができました。 この記事は25新卒リレーブログの最後の投稿となります。 最後の記事にしてはかなり専門的な内容となってしまいましたが、少しでもニフティに興味を持っていただけたら嬉しいです!
はじめに 始めまして、こんにちは!新卒一年目の石田と申します。 【筆者プロフィール】 入社時期:2025年4月 入社前のスキル:Python・ネットワーク・AWS未経験 所属チーム:インフラシステムチーム 現在私は、クラウドコストの管理を目的として、コストを取得・整形するシステムの構築に携わっています。 今回は、本システムについて、業務紹介を交えながらまとめていきたいと思います。 また、本システムはAWS上に構築していますが、私は入社するまでAWSにほとんど触れたことがありませんでした。そんな私が設計から実装までを取り組む中で、得た学びや気づきもまとめています。 今後AWSに取り組もうと考えている方、特に私と同じように未経験からスタートする皆さんの参考になれば幸いです。 クラウドコスト管理業務 現在ニフティでは、複数のクラウドサービスを利用しています。 私たちのチームでは、クラウドサービスで発生したコストを取得・加工することで、会計処理に必要となるフォーマットに整形しています。 加工の主な処理としては、以下のようなものがあります。 円建てコストの算出(ドル建てコストとTTSレートの乗算) 配賦処理(クラウドアカウントと社内部署情報との紐づけ) 会計用フォーマットへの適合 私の配属当時、こうした会計用ファイルの作成フローに手作業が多く、多くの工数が発生していました。また、複雑なコストを手動で整理するので、人的ミスのリスクも存在していました。 今回私は、上記課題を早期に解決するためのエンハンスに取り組みました。 システムについて 今回作成するシステムは、AWSのコストを取得し、会計用ファイルを出力するシステムです。 コスト取得・加工作業を自動化することで、工数の削減および手作業によるミスの防止を実現します。 本システムはAWS上で構築し、既存のAWSリソースも活用しながら進めます。 処理フロー 本システムの処理は、大きく3つのステップに分けられます。 ①AWSのコストデータを取得 ②データを加工し、会計処理に必要なフォーマットに整形する。 ③ExcelファイルとしてS3に格納 リソース 使用したAWSリソースは以下の通りです。 S3 AWSを代表するクラウドストレージサービスで、ファイルを「オブジェクト」として保存します。 安価に、大量のデータを保管できます。 Athena Athenaは、SQL文を使ってS3のデータを直接分析できるクエリサービスです。 後述するGlueが作成したデータカタログを参照することで、S3のどのフォルダに、どのようなデータ形式のファイルがあるかを把握します。 Glue Glueは、サーバーレスなデータ統合サービスです。対象データの種類を自動的に特定し、データカタログを作成します。Athenaは、このデータカタログを参照することで、S3に保存されているデータを直接クエリできるようになります。 DynamoDB DynamoDBは、柔軟なデータ構造を持つNoSQLのデータベースサービスであり、目的のデータに対してミリ秒単位での高速アクセスが可能です。 Lambda Lambdaは、サーバーの管理なしでコードを実行できる、サーバーレスなコンピューティングサービスです。 特定のイベント(例:S3へのファイルのアップロード・API Gatewayへのリクエストなど)をトリガーとして自動的にコードが実行されます。今回は、データの取得から加工・ファイルの格納などの処理をLambda関数として実装しました。 Secrets Manager Secrets Managerは、認証情報やAPIキーなどの機密情報を安全に管理できるサービスです。 コードに直接記述(ハードコーディング)するとセキュリティリスクが高まるような機密情報を一元管理し、コードから安全に取得できます。 構成図 先述したサービスを使用して、システムを構築していきます。 アーキテクチャ図を以下に示します。 注意点としては、Lambdaのトリガーは別LambdaからのS3へのファイル配置となっています。加えて、コストもAWSから直接APIで取得するのではなく、CUR(Cost and Usage Report) [ 1 ] が自動で出力されているS3を参照する構成になっています。 コスト取得 では、実際の処理の流れを追っていきます。 sql_path = os.path.join(os.path.dirname(__file__), 'aws_cost.sql') with open(sql_path, 'r', encoding='utf-8') as f: query = f.read() query = query.replace('{{year}}', str(year)) query = query.replace('{{month}}', str(month)) query = query.replace('{{tts_rate}}', str(tts_rate)) raw = wr.athena.read_sql_query( query, database="test_db", ctas_approach=False, boto3_session=master_session ) コスト(CUR)は、管理アカウントのS3に格納されています。 SQLのクエリファイルを読み込み、管理アカウントのセッションを利用してAthenaテーブルを参照します。 これによって、アカウントやサービス単位の細かい請求データを取得できます。 コスト整形 取得したデータをDF(DataFrame)に格納して、集計・加工処理に進みます。 集計 請求書ID、請求元情報、アカウントIDでグルーピングして、各合計コストを求めます。 部門情報の結合 各AWSアカウントがどの部署の管轄かを示す部門情報を結合し、配賦対応に役立てます。 DFのExcelファイル書き込み さて、必要なデータはそろったので、ここからは各ファイルで必要なデータを抽出する段階です。 作成する会計用Excelファイルは4つ。その内2つは、関数等が組み込まれたフォーマットファイル内の所定の位置にデータを転記する必要があります。 ここで私は、PythonコードでExcelファイルを操作できる、openpyxl [ 2 ] の使用を考えていました。 OpenPyXLは、Python上でExcelファイルを直感的に操作できる便利なライブラリです。以下のコードのように、Excelファイルを取り込んで、セルを指定して書き込みや読み込みを行えます。 format_path = '/tmp/rpa_format.xlsx' output_path = '/tmp/sample1.xlsx' start_row = 11 start_col = 4 wb = openpyxl.load_workbook(format_path) ws = wb["シート1"] ws['I2'] = '会計コード' ws['I4'] = 'インフラ部門' for i, row in enumerate(sample1_df.values): for j, value in enumerate(row): cell = ws.cell(row=start_row + i, column=start_col + j) cell.value = value wb.save(output_path) 6~8行目のようにセルを直接指定することも、9~12行目のようにfor文を回すことで、所定の位置(D11)から1セルずつ書き込むことも可能です。 さっそく実行してみます。 REPORT RequestId: cfc5c952-37f3-4d2f-bfac-c5fa22fd7438 Duration: 300000.00 ms Billed Duration: 300000 ms Memory Size: 256 MB Max Memory Used: 256 MB Status: timeout timeoutエラーが発生しました。メモリが足りなかったようです。 メモリを増やすと、、、 REPORT RequestId: 5377a577-dd9b-47a4-b938-48b8f77efa1c Duration: 21806.13 ms Billed Duration: 21807 ms Memory Size: 2048 MB Max Memory Used: 584 MB Init Duration: 5069.78 ms 問題なく処理完了できました。 今回はメモリの増量で対応しましたが、処理自体をもっと軽くしたい場合には「lxml [ 3 ] 」というライブラリも存在します。 OpenPyXLは、Python上でExcelファイルを直感的に操作できる便利なライブラリですが、Excelファイルを構成するXMLファイル全体をメモリに読み込む特性上、大量のデータを扱う際にはメモリ不足やタイムアウトの原因になることがあります。 対してlxmlは、ストリーミング処理に対応しており、ファイル全体をメモリに読み込むことなく、必要な部分だけを順次処理することで、メモリ使用量を抑えつつ高速なデータ処理を可能にします。 しかし、一度試してみたところ、出力ファイルが壊れてしまいました。 原因を調査したかったのですが、スケジュールの都合上見送りました、、、 ファイル出力 出力 何はともあれ、会計用ファイルが完成しました!S3にアップロードしていきます。 sample_files = [ ('/tmp/sample1.xlsx', f's3://{INVOICE_BUCKET_ID}/sample/year={year}/month={month}/sample1.xlsx'), ('/tmp/sample2.xlsx', f's3://{INVOICE_BUCKET_ID}/sample/year={year}/month={month}/sample2.xlsx'), ('/tmp/sample3.xlsx', f's3://{INVOICE_BUCKET_ID}/sample/year={year}/month={month}/sample3.xlsx'), ('/tmp/sample4.xlsx', f's3://{INVOICE_BUCKET_ID}/sample/year={year}/month={month}/sample4.xlsx'), ] for local_file, s3_path in sample_files: wr.s3.upload(local_file=local_file, path=s3_path) パスを指定し、作成したExcelファイルをアップロードしています。 問題なくアップロードできました!これにて処理完了となります。 まとめ 今回私は、ほぼ単独でシステムの設計から実装までを担当させていただきました。AWSの基礎サービスを学びながら進める中で、特にIAMによるアクセス制御と、S3・Athena・Glueの関係性の理解に苦労しました。 当初はより多くの機能や、他クラウドへの対応も計画していましたが、思うように作業が進まず、スケジュールが大幅にずれ込みました。そこで、機能に優先順位をつけ、重要な部分から実装を進めることで、なんとか完成にこぎつけることができました。 そのような反省点がありつつも、AWSについて学び、上流から下流まで一通りの開発工程を経験できたことは、大きな収穫でした。この経験を活かし、今後のOJT業務に臨んでいきたいと思います。 学生の皆様に向けて 入社して約5か月が経ちますが、ニフティは「繋がり」を大切にしている会社であると強く実感しています。 お客様やパートナー企業様との繋がりはもちろんのこと、社員と企業、また社員同士の繋がりが非常に強いです。部署を超えたコミュニケーションや社内イベントも非常に活発に行われています。 同じ会社にいても、チームによって雰囲気や文化が大きく異なるのも面白いところです。コミュニケーションが活発なチームもあれば、効率を重視するチーム、社内イベントに積極的に参加するチームなど様々です。 一口に「エンジニア」と言っても、多様な個性を持つメンバーがそれぞれの強みを活かして業務に取り組んでいます。 ニフティの雰囲気をもっと知りたいという方は、ぜひインターンシップにご参加ください。皆さんとお会いできるのを楽しみにしています! 次回はついに最終走者! やまだ25さんの記事をお楽しみに!! 参考文献 AWS コストと使用状況レポートとは – AWS Data Exports ︎ openpyxl · PyPI ︎ lxml – Processing XML and HTML with Python ︎
はじめに この記事は、リレーブログ企画「25新卒リレーブログの記事」です。 こんにちは、7月に「 AWS Summit Japanガイド 」の記事でご挨拶しましたパクです! 皆さん、AWSでEC2サーバーをどのように作成していますか? おそらくほとんどの方が、AWSマネジメントコンソールにログインしてマウスでクリックして作成する方法を思い浮かべるでしょう。私も入社前まではそうでしたから。しかし、会社では コード でサーバーを作成し、管理していました。 なぜでしょうか?手動で作業すると些細なミスが起こりやすく、後から誰が何をどのように変更したのかを追跡することも難しいからです。 この記事では、 Terraform というツールを使い、EC2インスタンスをコードで管理した経験談を共有したいと思います。 筆者プロフィール 入社時期: 2025年4月 入社前のスキル 経験あり: JavaScript, React, Python 経験なし: Terraform, AWS 現在の担当: サービスシステムグループ 目標 AWSコンソールで手動作成したEC2インスタンスをTerraformのコードに移行する 目次 環境構築 EC2モジュールの作成 EC2インスタンスの作成 最後に 1. 環境構築 ニフティではチームで協力して開発することが多いため、コードを記述する前に、まず最初に行うべきことは 「適切な作業環境」 を構築することです。 a. S3バケットの作成 Terraformはコードを実行すると、現在のインフラの状態が記録される terraform.tfstate というファイルがローカルPC上に作成されます。この時、もしチームメンバーAがサーバーを追加し、メンバーBがデータベースの設定を変更した場合、二人はそれぞれ内容の異なる terraform.tfstate ファイルを持つことになります。 このような状況が続くと、後になってどれが本当のインフラの状態なのか分からなくなってしまうため、それぞれのローカルPCではなく、チーム全員が共通でアクセスできるリモートストレージに保管する必要があります。私たちのチームでは、AWSのS3 (Simple Storage Service) バケットに terraform.tfstate ファイルを保存しています。 まず、以下のターミナルのようにバケット名やAWSプロファイルといった環境変数を設定します。今後実行するコマンドでこれらの変数を参照することになります。 $ export BUCKET_NAME=project-tfstate-bucket # バケット名 $ export AWS_PROFILE=terraform-user # プロファイル名 $ export AWS_DEFAULT_REGION=ap-northeast-1 # リージョン 次に、以下のAWS CLIコマンドを順に実行し、S3バケットを作成します。 # 1. S3バケットを作成します。 $ aws s3api create-bucket --bucket $BUCKET_NAME --acl private --region $AWS_DEFAULT_REGION --create-bucket-configuration LocationConstraint=$AWS_DEFAULT_REGION # 2. 全てのパブリックアクセスをブロックし、セキュリティを強化します。 $ aws s3api put-public-access-block --bucket $BUCKET_NAME --public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true" # 3. バケットのバージョニングを有効に設定します。(誤ってファイルを上書き・削除しても復元可能) $ aws s3api put-bucket-versioning --bucket $BUCKET_NAME --versioning-configuration Status=Enabled # 4. バケットに保存される全てのオブジェクトを暗号化するよう設定します。 $ aws s3api put-bucket-encryption --bucket $BUCKET_NAME --server-side-encryption-configuration '{ "Rules": [ { "ApplyServerSideEncryptionByDefault": { "SSEAlgorithm": "AES256" } } ] }' b. Terraform環境の構築 (versions.tf) S3バケットの準備ができたので、次にTerraformのコードを記述していきましょう。 まず、プロジェクト全体で使用するTerraformとAWS Providerのバージョンを指定する versions.tf ファイルを作成しました。 # versions.tf terraform { # このコードがTerraform 1.0台で実行されるべきことを指定します。 required_version = "~> 1.0" required_providers { # AWSインフラを扱うためにHashiCorp製のAWS Providerを使用します。 aws = { source = "hashicorp/aws" # AWS Providerは6.7.0台を使用するよう指定します。 version = "~> 6.7.0" } } } ちょうど今回の作業で、AWS Providerのバージョンも最新の 6.7.0 に更新しました! c. シンボリックリンクの作成 私たちのチームでは、開発環境と本番環境を分離して作業を進めています。そのため、各環境で先ほど作成した versions.tf ファイルを参照します。 この時、シンボリックリンク (Symbolic Link) を使用します。分かりやすく言えば、「ショートカットアイコン」を作成するようなものです。元のファイル ( versions.tf ) を一箇所に置いておき、各環境のディレクトリにはその元ファイルを指すリンクだけを作成するのです。 以下のコマンドで environments/development ディレクトリを作成し、その中に versions.tf ファイルを指すシンボリックリンクを作成しました。 $ mkdir -p environments/development # ln -s: シンボリックリンクを作成 $ ln -s ../../versions.tf environments/development/versions.tf d. AWS設定ファイル (providers.tf) 最後に、私たちがどのS3バケットとAWSアカウントを使用するのかを指定する設定ファイルを作成します。 environments/development ディレクトリ内に providers.tf ファイルを作成し、以下のように記述しました。 # /environments/development/providers.tf terraform { backend "s3" { bucket = "project-tfstate-bucket" # S3バケット名 key = "terraform.tfstate" # tfstateファイル名 region = "ap-northeast-1" # AWSリージョン profile = "terraform-user" # AWSプロファイル } } # 作業で使用するAWSアカウント provider "aws" { region = "ap-northeast-1" profile = "terraform-user" } e. Terraformの初期化 ここまででS3バケットを作成し、「プロジェクトのルール ( versions.tf )」と「接続設定 ( providers.tf )」が含まれたファイルの準備が整いました。いよいよTerraformを初期化し、プロジェクトを開始することを伝える番です。 この役割を担うのが terraform init コマンドです。このコマンドは、以下の二つの処理を行います。 プラグインのダウンロード : versions.tf ファイルに指定されたAWS Provider(プラグイン)をインターネットから探し、 .terraform ディレクトリ内にインストールします。 バックエンドへの接続 : providers.tf ファイルに記述された情報を基にS3バケットへ接続し、 .tfstate ファイルを管理する準備を整えます。 environments/development ディレクトリへ移動し、コマンドを実行しました。 $ cd environments/development # 作業ディレクトリへ移動 $ terraform init コマンドを実行してしばらく待つと、以下のような成功メッセージが表示されます。 Terraform has been successfully initialized! S3 bucket does not exist エラー 私は terraform init の過程でS3バケット名を間違えて入力してしまい、このエラーに遭遇しました!もし同様のエラーが発生した場合は、設定ファイルにタイポがないか確認してみてください。 terraform init が成功すると、現在のディレクトリに .terraform という隠しディレクトリが作成されます。ターミナルで tree コマンドを使って確認すると、設定通りにAWS Providerが正しくダウンロードされていることが確認できます。 $ ls -la environments/development .terraform # .terraform ディレクトリが作成されたことを確認 $ tree .terraform # .terraform ディレクトリの内部構造を確認 .terraform ├── providers │ └── registry.terraform.io │ └── hashicorp │ └── aws │ └── 6.7.0 # Providerがインストールされたことを確認! │ └── darwin_arm64 │ ├── LICENSE.txt │ └── terraform-provider-aws_v6.7.0_x5 └── terraform.tfstate # S3状態ファイル 2. EC2モジュールの作成 環境構築が完了したので、いよいよ本格的にEC2インスタンスを作成する時間です! Terraformでインスタンスを管理する際、すべてのコードを一つのファイルに記述することも可能です。しかし、それではメンテナンスが困難になるため、機能ごとに細かく分割し、モジュール(Module)として管理します。こうすることで、 柔軟性 と 再利用性 が大幅に向上します。 そこで、 modules/instance ディレクトリを作成し、その中に必要なモジュールを作成しました。 a. モジュールの設計 (variables.tf) 私たちがレゴブロックを作る時、「どのブロックをどうやって繋げるか」を考えなければなりません。その際、組み立て説明書を参考にすれば、必要な部品と組み立ての順番が分かりますよね。 Terraformの variables.tf ファイルが、まさにその 「必要な部品リスト」 の役割を果たします。このファイルを通じて、EC2インスタンスを作成する際に必要な情報(部品)を明確に伝えることができます。 modules/instance ディレクトリ内に、以下のように variables.tf ファイルを作成しました。 # /modules/instance/variables.tf # EC2インスタンスに必要な変数(情報)リスト variable "instance_name_tag" { # インスタンスのNameタグ type = string # データ型 description = "EC2インスタンスのNameタグに使用する値" # 説明 } variable "iam_role_name" { type = string description = "インスタンスにアタッチするIAMロール名" } variable "subnet_id" { type = string description = "インスタンスを配置するサブネットのID" } variable "vpc_security_group_ids" { type = list(string) description = "インスタンスに適用するセキュリティグループIDのリスト" } variable "instance_type" { type = string description = "EC2インスタンスのタイプ" default = "t4g.nano" # デフォルト値を定義 } b. モジュールの組み立て (ec2.tf) ec2.tf ファイルはTerraformの組み立てプロセスに該当します。 variables.tf で定義した「必要な部品」を使って、EC2インスタンスという成果物を作成するところです。 modules/instance ディレクトリ内に ec2.tf ファイルを作成し、EC2インスタンスを定義するコードを記述しました。 # /modules/instance/ec2.tf # 1. EC2インスタンスにインストールするOS data "aws_ami" "amazon_linux_2023" { most_recent = true # 最新バージョンのAMI owners = ["amazon"] # Amazonが提供する公式AMI # 必要なAMIでフィルタリング filter { name = "name" values = ["al2023-ami-2023.*-kernel-*-arm64"] # Amazon Linux 2023 ARM版 } filter { name = "architecture" values = ["arm64"] } } data "aws_ami" : EC2インスタンスを作成する際にはAMI IDが毎回必要です。しかし、このIDは頻繁に変更されるため、その都度修正するのは手間がかかります。そのような場合に data ブロックを使用すると、設定した条件(最新版、Amazon Linux 2023など)に合ったAMIを自動で検索してくれます。 # /modules/instance/ec2.tf 続き... # 2. 上記で検索したOSとvariables.tfの部品を使い、EC2インスタンスを作成します。 resource "aws_instance" "main" { ami = data.aws_ami.amazon_linux_2023.id # AMIを設定 instance_type = var.instance_type # インスタンスタイプを設定 subnet_id = var.subnet_id # ネットワークの場所(Subnet)を設定 vpc_security_group_ids = var.vpc_security_group_ids # セキュリティグループを設定 iam_instance_profile = aws_iam_instance_profile.main.name # IAM Role(権限リスト)を設定 # サーバー初回起動時に自動で実行されるスクリプト (PostgreSQLクライアントのインストール) user_data = <<-EOF #!/bin/bash sudo dnf update -y sudo dnf install postgresql16 -y EOF # インスタンスのネームタグ(Name Tag)を設定 tags = { Name = var.instance_name_tag } } user_data : インスタンスの初回起動時に一度だけ実行されるスクリプトです。ここにプログラムのインストールスクリプトなどを記述しておけば、サーバー作成と同時に必要なプログラムが自動でインストールされるため便利です。 c. 権限の追加 (iam.tf) 新しく作成したEC2インスタンスが他のAWSサービス(S3、DBなど)にアクセスするには、権限(IAM Role)が必要です。 IAM関連のコードも、可読性と役割の分離のために iam.tf ファイルで管理します。 # /modules/instance/iam.tf resource "aws_iam_instance_profile" "main" { name = "${var.instance_name_tag}-profile" role = var.iam_role_name } d. 結果の出力 (outputs.tf) プログラミングで関数が return を通じて結果の値を返すように、Terraformのモジュールも outputs.tf を通じて、参照できるように値を返すことができます。 environments/development でモジュールを使用するコードがインスタンス情報を活用できるよう、 modules/instance ディレクトリ内に outputs.tf ファイルを作成しました。 # /modules/instance/outputs.tf # 作成されたEC2インスタンスのIDとプライベートIPアドレスを返します。 output "instance_id" { value = aws_instance.main.id # 返す値 description = "作成されたEC2インスタンスのID" # 説明 } output "private_ip" { value = aws_instance.main.private_ip description = "作成されたEC2インスタンスのプライベートIPアドレス" } これで 入力 ( variables.tf )、 組み立て ( ec2.tf , iam.tf )、そして 出力 ( outputs.tf )まで、Terraformに必要な設計が完了しました! 次のステップでは、この設計を基にEC2インスタンスを作成してみましょう! 3. EC2インスタンスの作成 ここまでで modules/instance というディレクトリ内に、再利用可能なEC2インスタンスのモジュールを作成しました。これからは、ステップ1で準備した environments/development に戻り、実際に組み立てて作成する番です。 a. モジュールの呼び出し instance モジュールを呼び出し、必要なデータを渡すために、 environments/development ディレクトリで main.tf ファイルを作成します。 # /environments/development/main.tf # 'instance'モジュールを'terraform_ec2'という名前で呼び出します。 module "terraform_ec2" { # モジュールのパス source = "../../modules/instance" # インスタンスのネームタグ instance_name_tag = "terraform-instance" # IAMロール iam_role_name = "instance-role" # インスタンスタイプ instance_type = "t4g.nano" # ネットワークの場所(Subnet) subnet_id = "subnet-01e..." # 実際の環境に合った値に変更してください # セキュリティグループ vpc_security_group_ids = ["sg-0fe...", "sg-0e3..."] # 実際の環境に合った値に変更してください } source でモジュールのパスを指定し、その下に variables.tf で定義した実際の値を一つずつ記述していきます。 b. デプロイと実行 これで設計と組み立ての準備がすべて完了しました。これからは、実際にAWS上でEC2インスタンスを作成する作業だけが残っています!! まず terraform plan コマンドで、どのリソースが 作成( + ) 、 変更( ~ ) 、**削除( - )**されるのかを事前に確認します。 environments/development ディレクトリで、以下のコマンドを実行してみましょう。 $ terraform plan すると、Terraformがコードを分析し、これからAWSでどのような作業が実行されるのか、その 計画(plan) を表示してくれます。 Plan: 2 to add, 0 to change, 0 to destroy. + resource "aws_iam_instance_profile" "main" { ... } + resource "aws_instance" "main" { ... } 計画を見ると、IAMプロファイル1つとEC2インスタンス1つが新しく作成される予定であることが分かりますね! 最終的な計画に問題がなければ、 terraform apply コマンドで実際のデプロイを開始します。 $ terraform apply このコマンドを実行すると、本当に作業を実行するのか、最後の確認を求められます。 Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes 最後に yes を入力すると、TerraformがAWSと通信してインスタンスの作成を開始します! 作業が完了すると、このようなメッセージが表示されます。 Apply complete! Resources: 2 added, 0 changed, 0 destroyed. AWSコンソールで確認すると、このようにコードのみでEC2インスタンスが作成されたことを確認できます! 4. 最後に 今回の学び 今回の初めてのTerraformプロジェクトを通じて、単にEC2インスタンスをコードで作成する方法だけでなく、インフラを扱う上での実務的な視点を学ぶことができました。 コードでインフラを管理する理由 : マウスクリックではなくコードでインフラを管理することで、再利用可能な「部品( Modules )」とそれを組み立てる「空間( Environments )」を分離し、コードの重複を防ぎ、柔軟性を大幅に向上させることができました。 リモートでの状態管理 : terraform.tfstate ファイルをS3に保存することで、チームメンバー全員が同じ状態を基準に作業できる環境を構築できることを学びました。 学生の皆さんへ 私はAWSの経験がほとんどなく、Terraformというツールも名前を聞いたことがある程度でした。しかし、今回プロジェクトを終えてブログとして内容をまとめる過程で、達成感と共に、これからさらに多くの技術に挑戦したいという自信を得ることができました。 私がこのように感じることができたのも、ニフティの 新卒向けの体系的な研修と、成長を奨励する文化 のおかげだと考えています。今ではAWSやインフラ、バックエンド技術にも挑戦してみたいという目標ができました。 ニフティでは、入社後1ヶ月間の 導入研修 に始まり、エンジニアの同期たちと共にプロジェクトを進める 技術研修 、そして3ヶ月ごとに3つの異なるチームを経験しながら先輩たちと実務を学ぶ9ヶ月間の OJT まで、約1年間にわたって新卒が会社に慣れ、成長できるよう体系的なプログラムが整っています。 この記事を読んでくださっている皆さんも、ニフティで私たちと一緒に学び、成長する仲間になれることを願っています。どうぞ多くの関心をお寄せいただければ幸いです 次は、石田さんの出番です。 派手な記事が楽しみです 参考資料 Terraform: Resource: aws_instance
はじめに はじめまして、ニフティの高垣です。 【筆者プロフィール】 入社時期:2025年4月 入社前のスキル: PythonやReactを主に使用 gitを使ったチーム開発経験はハッカソン(2,3日程度)のみ 現在の担当:第一開発チーム(ニフティトップページやニフくじなどを担当) みなさんはGitを使って開発をしたことがありますか?Gitはファイルの変更履歴などを記録するバージョン管理システムです。もし一度でも使ったことがあるなら、「 git add 」「 git commit 」「 git push 」といったコマンドを、もはや指が覚えているかもしれません。 また、使ったことがない方にとっては、今後チームで開発する際の必須のツールとなります。そんな風に誰もが当たり前のように使っているこれらのコマンドですが、裏側で一体何が起きているのか、深く考えたことはありますか? そこで、この記事ではGitコマンドを使用せずにcommitをする方法を紹介します。 このプロセスを通じて、Gitがどのように変更履歴を記録しているのか、その仕組みを理解する一助となれば幸いです。(Gitについてご存知ない方は弊社の 新人研修の資料 も併せてご覧ください) 一般的なcommitまでの流れ 一般的なcommitまでの流れは以下のようになります。 1. git init 2. ファイルの編集 3. git add (編集したファイル) 4. git commit まずは、必要なファイルを用意するために git init します。その後、ファイルを編集し、 git add で変更を知らせて、 commit します。 今回は、こちらの手順を手動で行います。 実行環境 この記事で紹介するコマンド操作は、 macOS を想定しています。 また、手順の途中で Python と Git (確認するために使用)が必要になるため、あらかじめインストールしておいてください。 Windowsをご利用の方へ Windows環境で進める場合は、Git for Windowsに付属する「 Git Bash 」と Python をインストールしていただくことで、同様の操作が可能です。 git init git initとは git initコマンドはGitで必要なリポジトリやファイルを作成するコマンドです。基本的には初回のみこのコマンドを使用します。 git initを実行すると.gitという隠しディレクトリが作成されます。このディレクトリの中でGitに関する全てのファイルを格納しています。 作成されるもの 具体的には以下のようなディレクトリを作成しています。 .git/hooks: 特定のGitイベントが発生した際に自動的に実行されるスクリプトを配置 .git/info:excludeを配置(gitで追跡されないルール) .git/objects/: オブジェクト(後述)を配置 (/ハッシュ値の上2桁) /info: 追加情報 /pack: パックファイルを配置する .git/refs: 特定のコミットハッシュを指すポインタを保存する /heads: ローカルリポジトリのブランチが指すコミットハッシュを格納 /remotes: リモートリポジトリのブランチが指すコミットハッシュを格納 /tags: タグの参照を格納 .git/logs: 各ブランチやHEADで実行したアクションを記録する 手順 では、さっそくgit initを手動で行なっていきます。 1.作業用のフォルダを作成します $ mkdir git_manual 2.作成したフォルダに移動します $ cd git_manual 3.Gitリポジトリの初期設定に必要なディレクトリ構造を作成します $ mkdir -p .git/hooks .git/info .git/objects/info .git/objects/pack .git/refs/heads .git/refs/remotes .git/refs/tags .git/logs .git/を作成した後は、configの設定と現在のブランチを設定します。 configでは、ファイルの実行権限の変更を追跡するかどうか、ファイル名の大文字・小文字を区別するかどうかなどを設定します。 4..git/configを作成し必要な情報を記述します $ cat <<EOF > .git/config を実行した後以下をコピペしてください。 [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true EOF 5..git/HEADを作成し、mainブランチをHEADにします $ echo "ref: refs/heads/main" > .git/HEAD git statusコマンドを使用して、ここまで上手く行けているかどうか確認してみましょう。 $ git status On branch main No commits yet nothing to commit (create/copy files and use "git add" to track) 上記が表示されたらOKです。 (補足: git initをすると実際にはhookのサンプルも生成されますが、今回は必要ないため省略しています) commit commitの仕組みについて 続いてcommitをしていきますが、その前にcommitの仕組みについて説明します。 commitをする際、 コミットメッセージ タイムスタンプ コミットを作成した人物の情報 コミットした人物の情報 ファイルの差分 コミット時点でのディレクトリの階層構造と全ファイル(treeオブジェクト) などの情報を保存する必要があります。Gitでは、これら全てをまとめて コミットオブジェクト として管理しています。コミットオブジェクトは一意に識別するためにハッシュ値(SHA-1)を生成し、それをキーとしています。(この仕組みをコンテンツアドレスストレージと呼びます) コミットオブジェクトはディレクトリの階層構造や全ファイルの情報を毎回保存します。そのため、Gitにおけるcommitとは ファイルの「差分」を記録するのではなく、リポジトリの「スナップショット」を記録 しています。 commitの流れ 大まかなcommitの流れは、 1. ファイル内容をGitが管理できる形に変換する(BLOBの作成) 2.インデックスファイルの作成 3. treeオブジェクトを作成 4. コミットオブジェクトを作成 5. HEADにハッシュ値を登録 となっています。 インデックスファイルの作成が、 git add に該当し、それ以降が git commit に該当します。 コミットオブジェクトを作成するだけでは、現在のブランチで一番最新のコミットがどれなのかわからないため、Gitに知らせる必要があります。 そこで、.git/refs/headsにコミットオブジェクトのハッシュ値を保存します。これにより、最新のコミットを一意に特定することができます。 また、BLOB・インデックスファイル・treeオブジェクト・コミットオブジェクトの作成は次の図ような手順で作成されます。 先ほど、Gitにおけるcommitとは リポジトリの「スナップショット」を記録している と述べましたが、そのまま保存するのはあまり賢い方法ではありません。 そこで、オブジェクトを圧縮することで容量を効率的に消費しています。 commitの手順 それでは、今回の目玉であるcommitをしていきます。 1.適当なファイルを追加します(例としてexample.txtを作成) $ echo "first commit" > example.txt 2.コミットオブジェクトの作成 先ほどの図を見ると、BLOB・treeオブジェクト・コミットオブジェクトの作成手順は基本的に共通しています。また、それぞれの工程で前のステップで生成したハッシュ値が必要となります。 そこで今回は、これら一連の流れを自動化できるよう、コミットオブジェクトを作成するシェルスクリプトを作成しました。 以下のシェルスプリクトをcommit.shとして保存してください。 #!/bin/bash set -euo pipefail # 使い方: ./manual_commit.sh <ファイル名> "<コミットメッセージ>" if [ "$#" -ne 2 ]; then echo "Usage: $0 <ファイル名> \"<コミットメッセージ>\"" exit 1 fi FILE="$1" MSG="$2" GIT_DIR=".git" # --- Step 1: BLOBオブジェクトの作成 --- echo "==============================" echo " BLOBオブジェクトの作成" echo "------------------------------" # ファイル内容からBLOBオブジェクトの生データを作成 tmp_blob=$(mktemp) trap 'rm -f "$tmp_blob"' EXIT blob_size=$(wc -c <"$FILE" | tr -d '[:space:]') { printf "blob %s\0" "$blob_size"; cat "$FILE"; } > "$tmp_blob" # ハッシュを計算し、zlibで圧縮して.git/objectsに保存 blob_hash=$(shasum "$tmp_blob" | cut -d' ' -f1) path="$GIT_DIR/objects/${blob_hash:0:2}/${blob_hash:2}" mkdir -p "$(dirname "$path")" python3 -c "import sys,zlib;sys.stdout.buffer.write(zlib.compress(sys.stdin.buffer.read()))" < "$tmp_blob" > "$path" echo "BLOB 作成完了: $blob_hash" echo "==============================" echo "" echo "==============================" echo " インデックスファイルの手動作成" echo "------------------------------" # --- Step 2: インデックスファイルの作成 --- python3 -c ' import sys, os, hashlib, struct, binascii def create_index(file_path, blob_hash_hex): header = struct.pack(">4sII", b"DIRC", 2, 1) # Signature, Version 2, 1 Entry stat_info = os.stat(file_path) ctime_sec = int(stat_info.st_ctime) ctime_nsec = stat_info.st_ctime_ns % 10**9 mtime_sec = int(stat_info.st_mtime) mtime_nsec = stat_info.st_mtime_ns % 10**9 dev = stat_info.st_dev ino = stat_info.st_ino mode = stat_info.st_mode uid = stat_info.st_uid gid = stat_info.st_gid size = stat_info.st_size blob_hash_bin = binascii.unhexlify(blob_hash_hex) path_bytes = file_path.encode("utf-8") # ファイル名の長さをフラグとして使用 flags = len(path_bytes) entry = struct.pack( ">IIIIIIIIII20sH", ctime_sec, ctime_nsec, mtime_sec, mtime_nsec, dev, ino, mode, uid, gid, size, blob_hash_bin, flags ) + path_bytes + b"\x00" # パディングを追加して8バイト境界に揃える entry_len_with_pad = (len(entry) + 7) & ~7 entry += b"\x00" * (entry_len_with_pad - len(entry)) index_content = header + entry checksum = hashlib.sha1(index_content).digest() with open(".git/index", "wb") as f: f.write(index_content + checksum) if __name__ == "__main__": create_index(sys.argv[1], sys.argv[2]) ' "$FILE" "$blob_hash" echo "インデックス作成完了" echo "==============================" echo "" # --- Step 3: treeオブジェクトの作成 --- echo "==============================" echo " treeオブジェクトの作成" echo "------------------------------" # インデックスを読み取る代わりに、前のステップで得た変数を使用します mode="100644" blob_hash_text="$blob_hash" file_name="$FILE" tmp_tree=$(mktemp) tmp_tree_header=$(mktemp) trap 'rm -f "$tmp_tree" "$tmp_tree_header"' EXIT { printf "%s %s\0" "$mode" "$file_name"; echo -n "$blob_hash_text" | xxd -r -p; } > "$tmp_tree" tree_size=$(wc -c <"$tmp_tree" | tr -d '[:space:]') { printf "tree %s\0" "$tree_size"; cat "$tmp_tree"; } > "$tmp_tree_header" # ハッシュを計算し、圧縮して保存 tree_hash=$(shasum "$tmp_tree_header" | cut -d' ' -f1) path=".git/objects/${tree_hash:0:2}/${tree_hash:2}" mkdir -p "$(dirname "$path")" python3 -c "import sys,zlib;sys.stdout.buffer.write(zlib.compress(sys.stdin.buffer.read()))" < "$tmp_tree_header" > "$path" echo "treeオブジェクト作成完了: $tree_hash" echo "==============================" echo "" # --- Step 4: コミットオブジェクトの作成 --- echo "==============================" echo " コミットオブジェクトの作成" echo "------------------------------" author="hoge <hoge@example.com>" timestamp=$(date +'%s %z') # コミットオブジェクトの生データを作成 commit_content="tree $tree_hash author $author $timestamp committer $author $timestamp $MSG " tmp_commit=$(mktemp) trap 'rm -f "$tmp_commit"' EXIT commit_size=$(printf "%s" "$commit_content" | wc -c | tr -d '[:space:]') { printf "commit %s\0" "$commit_size"; printf "%s" "$commit_content"; } > "$tmp_commit" # ハッシュを計算し、圧縮して保存 commit_hash=$(shasum "$tmp_commit" | cut -d' ' -f1) path=".git/objects/${commit_hash:0:2}/${commit_hash:2}" mkdir -p "$(dirname "$path")" python3 -c "import sys,zlib;sys.stdout.buffer.write(zlib.compress(sys.stdin.buffer.read()))" < "$tmp_commit" > "$path" echo "コミットオブジェクト作成完了: $commit_hash" echo "==============================" echo "" シェルスクリプトに実行権限を与えてください $ chmod +x commit.sh 第1引数に編集したファイル、第2引数にコミットメッセージを入力して実行してください $ ./commit.sh example.txt "first commit" ============================== BLOBオブジェクトの作成 ------------------------------ BLOB 作成完了: 5ec586d228b5ff1e8c845c4ed8c2d01f3a159b24 ============================== ============================== インデックスファイルの手動作成 ------------------------------ インデックス作成完了 ============================== ============================== treeオブジェクトの作成 ------------------------------ treeオブジェクト作成完了: 2a154faaf71f2b3a17055d393504c1349395b049 ============================== ============================== コミットオブジェクトの作成 ------------------------------ コミットオブジェクト作成完了: aa5e60c3c7b817707e4c4f2e29995451406bb319 ============================== 完了するとそれぞれのハッシュ値が表示されます。このうち、コミットオブジェクトのハッシュ値をGitに知らせます。 3.HEADにハッシュ値を登録します $ echo "aa5e60c3c7b817707e4c4f2e29995451406bb319" > .git/refs/heads/main 4.commitできたか確認します $ git log --show-signature commit aa5e60c3c7b817707e4c4f2e29995451406bb319 (HEAD -> main) Author: hoge <hoge@example.com> Date: Tue Aug 19 16:27:35 2025 +0900 first commit ハッシュ値やAuthorが表示されていれば完了です。お疲れ様でした!! 補足 今回は、BLOBを作成した後にインデックスファイルを作成しましたが、インデックスファイルを作成せずに、コミットオブジェクトを作成することも可能です。その場合に、面白い挙動が見られますので、シェルスクリプトを変更してぜひチャレンジしてみてください。 終わりに 今回は、手動でcommitをしてみました。Gitは非常に便利なツールであり、普段何気なく使っているコマンドは、私たちの代わりに複雑な処理を自動で実行してくれます。しかし、その裏側にある論理的な仕組みを理解することは単なる豆知識ではありません。これはGitに限らず、あらゆるツールに共通することであり、本質的な理解やトラブルシュートの力につながります。 この記事が、普段は意識しない部分にも目を向けるきっかけとなり、技術への理解をより深めるきっかけとなれば幸いです。 この記事を読んだ学生さんに向けて 入社して約4ヶ月ですが、弊社は本当に様々なことに挑戦できる環境だと感じています。 私の場合は新しいインフラ環境の構築や、企画会議でのファシリテーターなどに取り組みました。これらは全て初挑戦でしたが、どの場面でも周囲の手厚いサポートがあり、大きく成長できたと実感しています。 様々な技術に触れてみたい方、開発だけでなく企画にも参加してみたい方にとっては、弊社は非常に魅力的な環境だと思います。 また、弊社の新人研修で使用している資料も公開していますので、興味のある方はぜひ こちら もご覧ください。 次は、大型新人のパクさんの記事です。 どうぞご期待ください。 参考文献 https://drew.silcock.dev/blog/artisanal-git/ Git
はじめに エンジニアリングマネージャーをしています、芦川です。 エンジニアのためのドキュメントライティング (ジャレッド・バーティ 著 /ザッカリー・サラ・コ―ライセン 著 /ジェン・ランボーン 著 /デービッド・ヌーニェス 著 /ハイディ・ウォーターハウス 著 /岩瀬 義昌 訳) をインナーソースの観点から読んだ記録をブログにしたいと思います。 結論 インナーソースの観点から見たドキュメントライティングの重要ポイントは以下のとおりです。 READMEの重要性 プロジェクトの最初に見るドキュメントとして、READMEは極めて重要です。 協働プロセス ドキュメント編集はコードレビューと同様に協働的なプロセスであり、フィードバックを取り入れて改善していくことが大切です。 効率化 他者との協働は時間短縮につながり、強い人材のコントリビューションが効率を高めます。 建設的なフィードバック 個人を非難せず、コンテンツ改善を目的としたフィードバックが重要です。 感謝の姿勢 コントリビューションに対しては必ず感謝を示し、適切に検討して受け入れるかどうかを判断します。 完璧主義の回避 公開時に完璧なドキュメントは存在しないため、公開後のフィードバックと修正を重視します。 明確な責任者 最終承認者やコードオーナーを明確にし、管理責任を明確にします。 フィードバックの重視 ユーザーサーベイやフィードバックチャンネルを通じて、継続的な改善を図ります。 信頼関係の構築 フィードバックの反映状況を伝え、社内での小規模なDevRel関係を築きます。 適切な管理 ドキュメントオーナーを決め、放置されたリポジトリを防ぎます。必要に応じて廃止の判断も行います。 貢献への報酬 コントリビューションに対しては、適切な称賛と報酬を提供します。 インナーソースの観点の重要な記述の抜粋 CHAPTER1 読み手の理解 README インナーソースに限らず、そもそもREADMEは誰もが最初にみるドキュメントで超重要。 CHAPTER4 ドキュメントの編集 コードレビューと同じで、ドキュメント編集は協働的なプロセス。受け取ったフィードバックを取りいれて改善していく まさにこれはインナーソースと同義。「協働プロセス」という用語で広く調べていくと、インナーソースはもっと広がりを見せるだろう。 編集は他人とやれば時短になる 効率化という意味でも、自分でうんうん悩んですごく時間を使うよりは他人にまかせてフィードバックをもらったほうが時間短縮になる。単純にインナーソースにもそういうメリットがうまれる。そこに強い人がコントリビュートするほうが時間短縮になる。 フィードバックは、批難するものではなく、コンテンツの改善を目的としたものである これは、コントリビュートするときの重要なマインド設定。管理するトラステッドコミッターやチームに対して不平不満を言う場ではない。 必ずフィードバックをうけて改善しなければいけない、ではない。必ずするのは、感謝のみ 必ずコントリビュートされたらすることは感謝のみ。レビュー、マージはちゃんと検討して受け入れるかどうかを判断しよう。 CHAPTER7 コンテンツの公開 安心せよ、リリース時に完璧なドキュメントはない、公開してからフィードバックをうけて修正していけばよい インナーソース化する際のマインド設定に当てはまる。不完全とわかっててよいのだよ。 最終承認者は明確にしよう、有害なドキュメントをリリースしてはいけない 受け入れる際の制約はちゃんとつけよう。コードオーナー、トラステッドコミッターを明確にしよう。 CHAPTER8 フィードバックの収集と組み込み フィードバックチャンネルの作成を作ってユーザーサーベイをしよう ここもインナーソースに関連する。リポジトリ管理者が利用者やコントリビュートしてくれる方にアンケート取ろう。 ユーザーのフィードバックが伝わっていることをユーザーに届ける、信頼関係を構築する コントリビュートやフィードバックを信頼関係を作ろう。つまり、社内での小さいDevRel関係と言える。 CHAPTER11 ドキュメントの保守と非推奨化 ドキュメントオーナーを決める、NGな状態は「ドキュメントの責任は全員にある = 誰も責任を負っていない状態」 まさに管理者不在のゾンビリポジトリ。こうなってはいけない。捨てる判断も含め、コードオーナーを決めよう。 ドキュメントの保守に報いる コントリビュートしてくれたら、称賛と報酬は当然だ。 マインドマップ 終わりに インナーソースという観点から読むことで、普段見落としがちなドキュメントの奥深さを再認識できました。今回ご紹介したポイントが、皆さんの日々の業務やチーム運営に少しでも役立てば嬉しいです。 この学びを活かし、チームのドキュメント文化をさらに良いものにできるよう、これからも探求を続けていきたいと思います。