TECH PLAY

ニフティ株式会社

ニフティ株式会社 の技術ブログ

487

はじめに 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な状態は「ドキュメントの責任は全員にある = 誰も責任を負っていない状態」 まさに管理者不在のゾンビリポジトリ。こうなってはいけない。捨てる判断も含め、コードオーナーを決めよう。 ドキュメントの保守に報いる コントリビュートしてくれたら、称賛と報酬は当然だ。 マインドマップ 終わりに インナーソースという観点から読むことで、普段見落としがちなドキュメントの奥深さを再認識できました。今回ご紹介したポイントが、皆さんの日々の業務やチーム運営に少しでも役立てば嬉しいです。 この学びを活かし、チームのドキュメント文化をさらに良いものにできるよう、これからも探求を続けていきたいと思います。
アバター
はじめに こんにちは!新卒1年目のなべしまです。 現在、ジョブローテ期間中で、サービスシステムグループ 第二開発チームに所属しています。所属先では、ニフティポイントクラブの運用開発業務を日々行っています。 ニフティポイントクラブでは、開発言語としてRubyを利用しています。今回は、開発環境を構築する中でつまずいたことやそこから得た学びをまとめてみました。 この記事を通して、知識の整理や新たな学びのきっかけになれば嬉しいです。 筆者プロフィール 入社:2025年4月 入社前のスキル Ruby:名前を聞いたことはある程度、環境構築はしたことがない 現在の担当:サービスシステムグループ 第二開発チーム(ニフティポイントクラブ) RUBY_CONFIGURE_OPTS でのつまづき 今回、macOS でrbenv というツールを利用して、Ruby のインストールを行いました。このとき、SSLライブラリを指定してインストールを実行しました。 環境構築ログ $ brew install openssl@3 ... $ export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@3)" $ rbenv install 3.3.3 ==> Downloading ruby-3.3.3.tar.gz... -> curl -q -fL -o ruby-3.3.3.tar.gz https://cache.ruby-lang.org/pub/ruby/3.3/ruby-3.3.3.tar.gz % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 21.0M 100 21.0M 0 0 11.9M 0 0:00:01 0:00:01 --:--:-- 11.9M ==> Installing ruby-3.3.3... ruby-build: using libyaml from homebrew ruby-build: using gmp from homebrew -> ./configure "--prefix=$HOME/.rbenv/versions/3.3.3" --enable-shared --with-libyaml-dir=/opt/homebrew/opt/libyaml --with-gmp-dir=/opt/homebrew/opt/gmp --with-ext=openssl,psych,+ --with-openssl-dir=/opt/homebrew/opt/openssl@3 -> make -j 10 -> make install ==> Installed ruby-3.3.3 to /Users/{ユーザ名}/.rbenv/versions/3.3.3   ここで、こんなことを思っていました。 export コマンドを実行しているな… 確かこのコマンド、シェル起動時の設定ファイルで使っていた気がする! RUBY_CONFIGURE_OPTS は .zshrc や .zsh_profile に記録されているのでは? しかし、 .zshrc や .zsh_profile の中身を見ても RUBY_CONFIGURE_OPTS は記録されていませんでした。ここが今回の私の 勘違いしていた点 でした。 改めて環境構築のログを見てみると以下のコマンドが実行されています。 ./configure make make install よく調べてみると、これらはソースコードからソフトウェアをビルド・インストールするための標準的な手順のようです。 RUBY_CONFIGURE_OPTS は ビルドプロセス中に使われる環境変数 だったのです。 今回はこの気づきをきっかけに、 ソフトウェアがどのようにインストールされるのか その基本的な流れについて整理してみたいと思います。 ソフトウェアがインストールされるまで ソフトウェアがインストールされるまでの処理を、3つのコマンドとともに説明していきます。 configure ./configure は、ソフトウェアをビルドするための設計図を作成する処理です。 $ ./configure [オプション] ./configure では主に以下の処理が行われます。 使用されている環境(OSやライブラリ)を調査 その結果をもとに、環境に最適な設定ファイル(Makefile など)を自動で作成 環境構築ログの ./configure が実行された行を見てみると、 --with-openssl-dir=/opt/homebrew/opt/openssl@3 というオプションが含まれています。これは最初に設定した環境変数 RUBY_CONFIGURE_OPTS の内容が反映されていることを示しています。 今回の export コマンドは、このオプションを指定するために使用したコマンドであることがわかりました。 -> ./configure "--prefix=$HOME/.rbenv/versions/3.3.3" --enable-shared --with-libyaml-dir=/opt/homebrew/opt/libyaml --with-gmp-dir=/opt/homebrew/opt/gmp --with-ext=openssl,psych,+ --with-openssl-dir=/opt/homebrew/opt/openssl@3 make make は、作成された設計図を基に、ソフトウェアを組み立てる処理です。 $ make [オプション] [対象ファイル] make では、主に以下の処理が行われます。 configureで作成されたMakeFileに基づいてソースコードをコンパイル 実行ファイルを作成 環境構築ログでは、以下のように make が実行されていました。このコマンドでは対象ファイルが指定されていないため、デフォルトで Makefile を参照しています。そして、 -j オプションは複数の処理を並列で実行するためのものです。rbenvではシステムの CPU コア数を取得して、自動的に -j の値を調整しているようです。 -> make -j 10 make install make install は、組み立てられたソフトウェアを配置(インストール)する処理です。 $ make install make install では、主に以下の処理が行われます。 Makefile に定義された install というラベルから処理を実行 make によって作成された実行ファイルを指定されたディレクトリにコピー 環境構築ログでは、以下のように Ruby が /home/hogeta/.rbenv/versions/3.3.3 にインストールされていたことがわかります。このインストール先のパスは、 ./configure の実行時に指定したパスに基づいています。 -> make install ==> Installed ruby-3.3.3 to /Users/{ユーザ名}/.rbenv/versions/3.3.3 例えるならば… ソフトウェアをインストールの流れを、通販で例えてみると… ./configure は「通販の注文フォームに入力」 make は「注文を受けて、倉庫で商品を組立て」 make install 「商品を家に配送」 fig. ソフトウェアインストールと通販の対応関係 このように置き換えることで、ソースからのインストール手順がどのように役割分担されているかがイメージしやすくなったのではないでしょうか。 まとめ export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@3)" は、シェル起動時の設定ではなくrbenv install のための設定だった 今回のようなインストール時に標準と異なる設定を使用するケースでは、この一連の流れを知っておく必要がありそうです。 普段何気なく使用しているツールやコマンドでも、原理を知ることで対応できる問題が増えると感じました。 今回の経験を活かして、今後も実行されている処理を分析しながら業務に励んでいきたいと思います。 学生の皆様に向けて ニフティには、今回の環境構築をはじめ、些細な疑問でも気軽に議論ができ、丁寧にアドバイスをもらえる文化があります。 今回の件を通して、ニフティでは 日頃から活発なコミュニケーションが行われている ことを改めて実感しました。 私は会社で働くうえでコミュニケーションは欠かせない要素だと考えています。その点において、ニフティは非常に良い環境だと感じています。 そんなニフティで、一緒に楽しく働いてみませんか?皆様とご一緒できる日を、心から楽しみにしています! 参考文献 https://www.postgresql.jp/docs/17/install-make.html#CONFIGURE https://github.com/rbenv/ruby-build/blob/master/bin/ruby-build https://www.ibm.com/docs/ja/aix/7.2.0?topic=m-make-command#make__row-d3e116694
アバター
オープンスペーステクノロジー(OST)を社内と社外でそれぞれ実践した二人の司会者による対談記事です。どちらも10人規模で行われたOSTですが、 テーマは違えどOST自体に対する成果や課題には興味深い違いがありました。 はじめに オープンスペーステクノロジー(Open Space Technology、以下OST)は、参加者が自由にテーマを出し合い、自発的に話し合う場を作る手法です。 「4つの原則」があります。 ここにやってきた人は、誰もが適任者である 何が起ころうと、それが起こるべき唯一のことである いつ始まろうと、始まった時が適切な時である いつ終わろうと、終わった時が終わりの時である 要するに、上下・役割関係なく誰でも参加していいし、OSTで話されることは全部学びとなる。また、いつ話し出してもいいし、いつ話を終えてもよいです、ってことです。めっちゃいいね、ってことで特に技術勉強会やテックカンファレンスの中でよく行われる場の作り方になります。 詳細は、 「オープンスペーステクノロジー(OST)」でググってみてください! (他にも蜂とかキリンなど、4 つの役割なんてのもあります。) 今回は、社外コミュニティと社内チームでそれぞれOSTを実践した芦川(私)と西原さんに、その違いについて雑談したことがあったので、それをネタに対談風に記事にしました。 司会者プロフィール 芦川:InnerSource Commons Japan Meetupで「チームの壁、ぶっ壊そ!壁の乗り越え方、一緒に考えよう!」というテーマのOSTを主催。インナーソースの実践者コミュニティでのファシリテーターを務める。(InnerSource Commons Japanは、 InnerSource Commons の日本ローカルコミュニティです。OSSの開発の仕方・コミュニティの形成方法などいいところを社内に取り入れようぜ、というものです。) 西原:社内で「職場での悩み事」をテーマにしたOSTを実施。労働組合の執行委員長という立場から会社内のコミュニケーション活性化や関係性醸成に取り組む。 対談 ― それぞれのOSTのテーマと参加者層について教えてください 芦川:社外OSTでは「インナーソース 組織内の壁と感じていることはなにか?」という大テーマで開催しました。参加者は約10名で、インナーソースに関心がある、あるいは既に実践している方々が集まりました。業界も会社も違う方々が集まり、「上下関係の壁」「チーム間の利害関係」などについて議論しました。 資料は公開しておりこちらです。 西原:社内OSTでは「職場での悩み事」という大テーマで、運営サイドもあわせて10名ほどが参加しました。OSTそのものの馴染みが薄いと思っていたのでイベントタイトルを「ユニオンカフェ」とし、「抱えてるモヤモヤ、誰かと話し合ってみませんか?」という謳い文句で「OST」という単語はあまり出さずに募集をしました。テーマとしては「新規事業について」「今後のキャリアについて」「評価の上げ方」など、かなり具体的な職場の課題が挙がりました。全一般社員を対象にしたのですが、参加者の大半がエンジニア職でした。このあたりはイベント参加に対する部署ごとの文化の差もあったのかなと思います。 ― 参加者の積極性や議論の深さやオープンさに違いはありましたか? 芦川:社外の場合、みなさん自発的に参加されているので、積極性が高かったですね。特に「インナーソースについて知見がある人・何らかの形で実践している人・悩みを抱えている人が集まった」ので、非常に濃い議論ができました。新しい参加者と運営の方の人数バランスも良かったと思います。会社名や具体的な事例を出しながらも、比較的オープンに話せる雰囲気がありました。異なる会社の方々だからこそ、「こうしたら解決した」「うちではこうしている」といった経験を率直に共有できたと思います。 西原:社内の場合は少し違いました。社内のセミナー用会議室を借りての開催でしたので「とりあえず来てみた」という声もあり、参加の動機が様々でした。セッションがスタートすると、どの卓も活発に議論がされていました。 芦川:印象に残ったセッションとかありました? 西原:自分も参加したのですが、営業の方が出した「エンジニアにやりたいことを伝えるには」というテーマのセッションが印象的でした。エンジニアには「これをやりたいです」と伝えるより「これってどうやったら実現できますか?」って聞くほうが前のめりになりそうという話で盛り上がりました。ただ、ここで1つ気づきがありまして、同じ社内でバックグラウンドが共通しているほうが議論しやすいだろうと思っていたのですが、むしろ社外の人同士のほうが後腐れがないため、深く話せるのではないかということにも気づきました。これは正直なところ盲点でした。 芦川:いや、そうかもしれませんね。社外OSTでは、もともとの人間関係が薄い分、悩みだけにフォーカスすることができて深く相談できる、なんてことはカウンセラーに相談する、とかそういったことに近いのかも。 西原:もう少し人数が集まるかなと思っていたんですが、参加者募集時に「職場での悩み」の例として挙げたものが「キャリアプラン」や「チームビジョン」などで、重たい印象を与えて参加のハードルをあげてしまっていた可能性もあります。もっとライトな例を多く用意してもよかったかもしれません。 ― 場の雰囲気づくりで工夫した点はありますか? 芦川:社外OSTではWeWorkという場所を選び、ドリンク(ビールも!)を用意したのが好評でした!「ビール飲みながらは最高」「場所の静かさ・ゆるさ(空気感)など、非常に良かった」という声がありました。リラックスした雰囲気が対話を促進したと思います。 西原:芦川さんの社外OSTを参考に、こちらもアルコールを含めたドリンクと、あとはサンドイッチやおにぎりなどの議論の合間に片手で食べられる軽食を用意しました。食べることに集中してしまわないように箸やフォークが必要なオードブルなどは避けました。開始まではゆるめのBGMを流したりしたのですが参加人数が少ないこともあってか最初は少し重ための空気でした。 芦川:なるほどね、BGM。場作りはほんと大事ですよね。WeWorkはそもそも普通にコワーキングスペースとして働いている方がいる中だったので、カフェのような生活音があるような感じでした。そこもよかったのかもしれない。 西原:そうか、社内OSTであってもコミュニティスペースなどすこし広い場所でやってもよかったのかな。途中参加してもらえる人もいたかも。 ― セッションの進め方に違いはありましたか? 芦川:社外OSTでは「1セッション35分(議論30分、発表5分)はちょうどよかった」という評価を得ました。また、2セッション目では「その場の流れで深追いしたいところについてテーマを新しく作成した」という柔軟な対応も行いました。ただ、司会者側がここ深堀りしたいと決めてしまったところがあり、これはよかったのか悪かったのか。 西原:社内OSTでもほぼ同様の時間配分でしたが、テーマが「昼食の場所や宴会のお店選び」から「キャリアプランの悩み」まで幅広く、時間配分の調整が難しい場面もありました。また今回一般参加者が少ないことから私含め運営側も全員セッションに入ってしまったことで、厳密なタイムキープが出来なかったのは反省です。 ― OST実践から得た最大の学びは何ですか? 芦川:「InnerSourceという同じ軸でも、悩み方の軸に対する考え方は多様だ」という気づきが大きかったです。また、参加者からは「定期開催したい!」という声もあり、継続的なコミュニティ形成の場としての価値も感じました。 西原:「社内の知らない人に悩みを話すことのハードル」に対する認識を得たのと「部署によって文化に差がある」ことを再認識しました。他には「悩み」や「モヤモヤ」というマイナスのテーマで募るより、「いまの職場環境をよりよくする方法」のようなプラスのテーマで検討するべきだったかと思いました。ただ、参加者からは好評の声も多く聞こえたので次回につなげたいと思っています。 ― お2人お話ありがとうございました!では、社内・社外OSTのお話から、今後のOST開催に関する成功要因をまとめてみたいと思います。 これが OSTの成功要因!! 意欲ある多様な参加者を集める 自発的に参加しようとする人が多いほど議論は活発になる。 異なる部署・会社・業界の人が集まると、率直な意見交換や具体的な経験共有がしやすい。 新規参加者と運営メンバーの人数バランスがよいと安心感が生まれる。 適切なテーマ設定 社外OSTでは「組織の壁」という抽象度のあるテーマで広がりのある議論が可能になった。 社内OSTでは「職場の悩み」をテーマにしたが、例示された議題の重さと社内の人に話すことに対する心理的ハードルなどもあり参加者が増えにくかった。 ライトなテーマや具体例を混ぜることで、参加のハードルを下げられる。 安心感ある場づくり 社外OSTでは人間関係が希薄なため、むしろ率直に悩みを深く話しやすかった。 社内OSTでは関係性が近い分、テーマによっては話しにくさが出る場合がある。ここはテーマ選びをちゃんと考える必要がある点。 WeWorkといった快適な場所選びやドリンク(ビール含む)の用意が好評。 静かでゆるい空気感が対話を促進し、意見交換を自然に進めやすくした。生活音があるような空間がよいのかも。 クローズドな場よりもオープンな場がよさそうだ。 まとめ 社外と社内、どちらが良いということはありませんが、OSTは場のデザインによって大きく成果が変わることが今回2つのOSTの結果を比較することでわかりました。 みなさんもOSTを実践する際には、「参加者」「テーマ」「場」の特性を考慮したデザインを心がけてみてください!! OSTめっちゃいいですよ!!
アバター
はじめに こんにちは。ニフティの仲上です。 今回は、Terraformを使用してECSクラスターで「Container Insights」を有効にする方法を説明します。 Container Insightsとは 「Container Insights」は、Amazon EKSやAmazon ECSで動作するコンテナ化されたアプリケーションやマイクロサービスの監視・分析を行うAWSサービスです。コンテナの健全性やパフォーマンスを包括的に把握できます。 実は「Container Insights」には「オブザーバビリティが強化された Container Insights」という、もう1つの設定があります。 「オブザーバビリティが強化された Container Insights」は、「Container Insights」の進化版で、従来の監視機能を大幅に拡張したサービスです。 従来の「Container Insights」は、CPU使用率やメモリ使用量などのインフラレベルの監視が中心でしたが、「オブザーバビリティが強化された Container Insights」では、APIのレスポンス時間やエラー率など、アプリケーションレベルの詳細な追跡が可能となっています。 「オブザーバビリティが強化された Container Insights」を使用することで、障害の根本原因をより迅速に特定できるようになります。 Terraform で Container Insights を有効にする方法 クラスターの設定に以下の項目を入れると「Container Insights」が有効になります。 resource "aws_ecs_cluster" "blacklist_db_update_batch" { name = "test-cluster" setting { name = "containerInsights" value = "enabled" } } 先ほど紹介した「オブザーバビリティが強化された Container Insights」を使う方法を調べてみました。 どうやら enhanced という設定があるようです。 resource "aws_ecs_cluster" "blacklist_db_update_batch" { name = "test-cluster" setting { name = "containerInsights" value = "enhanced" } } 設定できました! おわりに 今回は、Terraformを使用してECSクラスターで「Container Insights」を有効にする方法を説明しました。 簡単に設定できるので、ぜひ「オブザーバビリティが強化された Container Insights」の設定を検討してみてください。
アバター
はじめに 皆さんこんにちは! 新卒一年目の宮村です! 現在の業務では、主にOpenID Connect(OIDC)を使用した基幹システムを運用しています。 そのため今回は、業務を通じて学んだOIDCの基礎について発信していきたいと思います。 この記事の前提 今回のハンズオンはWindowsのPowerShellを前提にしています。 おそらく、MacやLinuxでも動作すると考えておりますが、保証はできません。 以下の記事等を閲覧し、OIDCの概要がわかっている前提で説明します。 https://qiita.com/TakahikoKawasaki/items/498ca08bbfcc341691fe   ハンズオン準備 今回使用するソースコードのクローン まず、準備として今回使用するOIDCのサーバー django-oidc-provider をGit cloneし、exampleディレクトリに移動します。 $ git clone https://github.com/juanifioren/django-oidc-provider.git $ cd django-oidc-provider/example   このexampleディレクトリには、実際にdjango-oidc-providerを導入した際のOpenID Provider(OP)の実装例があります。 Dockerコンテナの作成 exampleが少し古くそのままでは動かなかった点と今回のハンズオンの都合上、DockerFileの内容を以下に変更してください。 ※あくまでテストであるため、スーパーユーザー情報をファイルに直書きしています。 FROM python:3.10 WORKDIR /app COPY . /app RUN pip install --upgrade pip RUN pip install --no-cache-dir -r requirements.txt RUN python manage.py migrate RUN python manage.py creatersakey # 環境変数でデフォルトのスーパーユーザー情報を設定 ENV DJANGO_SUPERUSER_USERNAME=admin ENV DJANGO_SUPERUSER_EMAIL=admin@example.com ENV DJANGO_SUPERUSER_PASSWORD=admin # スーパーユーザーを作成(既存の場合はスキップ) RUN python manage.py createsuperuser --noinput || echo "Superuser already exists" EXPOSE 8000 CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]   以下のコマンドで実際に起動してみましょう! $ docker build -t django-oidc-provider . $ docker run -d -p 8000:8000 django-oidc-provider   http://localhost:8000 で以下の画像が確認出来たら成功です。 テストClientの追加 Create your clients をクリックしましょう。 ここでいうclientはOPを使用するクライアントのことを指し、Relying Party(RP)とも呼ばれます。 クリック後、ログイン画面が表示されるため、ID、パスワードどちらも admin を入力しましょう。 ログイン後は 左サイドバーのClientsの隣 にある +Add をクリックします。 その後、以下を入力します。(それ以外はそのままでOKです) Name: テスト Response types code id_token id_token token Redirect URIs: http://example.com Scopes: openid profile email address phone 入力例 この後、Saveをクリックし、生成したclientを確認すると以下のようにClient IDとClient Secretが自動生成されたことが確認できます(以下はあくまで例です)。 これらの情報は、リクエストを送信したclientが正規のclientであることをOPが確認するために使用します。 この後のハンズオンで使用するため、これらの情報をメモしておきましょう。 テストユーザの作成 左サイドバーのUsersの隣 にある +Add をクリックします。 すると、以下の画面に遷移するため、以下の情報を入力しSaveをクリックします Username: test_user01 password: test_user01 すると、以下の画面へ遷移するため First name: user01 Last name: test Email address: example@google.com と入力しSaveをクリックします。 これで、下準備は完了しました。 ハンズオン 実際に設定したOPに対してログインしてみましょう。 今回は、OIDCのシーケンスの中で最も一般的なAuthorization Code Flowで試してみます。 ログイン(Authorization Request) 初めにブラウザの シークレットブラウザモード を立ち上げ、以下のURLを張り付けてください。 http://localhost:8000/authorize/?client_id=【先ほど生成されたClient ID】&redirect_uri=http://example.com&response_type=code&state=123456&scope=openid+profile+email   このURLは、OPに対して認可コードの発行を要求するAuthorization Requestです。 ここでは、 /authorize エンドポイントを指定していますが、エンドポイントがどのURLに存在するかの情報は、 .well-known/openid-configuration を参照すれば知ることができます。 実際にブラウザでアクセスしてみると、今回使用する authorization_endpoint 等のURLが記載されているのが確認できます。これはOIDCのDiscovery(発見)機能と呼ばれます。 以下に主要なパラメータの詳細を一部抜粋して説明します。 client_id : client(RP)の識別子 redirect_uri : 認証終了後にリダイレクトされるURI。 response_type : 認証後にどの情報を返すか(Authorization Code Flowだと code を指定) scope : ClientがOPに要求したいユーザー情報の範囲(プロフィール、メールアドレスなど)を指定します。ここで要求したスコープに対応する情報が、後のUserInfoレスポンスで取得できます。 張り付けた後Enterを押すと、ログイン画面が表示されるため、先ほど作成したユーザでログインします。 以下の画面へ移動します。 この画面は、Clientに対して以下の情報を渡すことをユーザに対して許可を求めていることを意味します。 ここではAcceptをクリックします。 その後、example.comにリダイレクトします。 リダイレクトした際のURLパラメータに存在するcodeは認可コードのことを表し、トークンの発行に使用します。 この認可コードを使用して、実際にトークンを発行してみましょう。 以下のコマンドをPowerShellに張り付けましょう。 このコマンドはToken Requestを送信するものであり。OPに対してトークンの発行を申請します。 $ curl -s -X POST -H "Cache-Control: no-cache" -H "Content-Type: application/x-www-form-urlencoded" "http://localhost:8000/token/" -d "client_id=【先ほど生成されたClient ID】" -d "client_secret=【先ほど生成されたClient Secret】" -d "code=【発行された認可コード】" -d "state=123456" -d "redirect_uri=http://example.com" -d "grant_type=authorization_code"   すると、以下の例のようなレスポンスが返ってきます。 { "access_token": "df6e0afa50e14a879f151feda46295b7", "refresh_token": "d6649365913f4c56abefe3f2b8b8732d", "token_type": "bearer", "expires_in": 3600, "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ijk1YjBmY2I5NDI4NTI1YjM0MGRlZWM4ZjJlNTFhYmNlIn0.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAiLCJzdWIiOiIxIiwiYXVkIjoiOTI0NDIyIiwiZXhwIjoxNzU0OTgxMTkwLCJpYXQiOjE3NTQ5ODA1OTAsImF1dGhfdGltZSI6MTc1NDk3NjE0MiwiYXRfaGFzaCI6ImlkRHRjVjdvYzl4Ny1yTFNoSTg5bHcifQ.fzlqjsHJycYrSx2EsGjsGsgLZC3z4mRVpKPATG0D_mU6bDD7ZLv4G3Sk5kXmibBekaLR5zBIUr84ZmQ77qo3CdARxLOn7rB4CLE3-9d-JEoQpwI9uHac3iQXdx6HVN2zBQJjm6CPkx8t0Z9-d1ErRzJiAeiJChPq4JbxsmtFJzgFwssdKeUdMwgsjR64wIY8uP9KV9NFG3X0vKfnAVSPdsp9QpfV68xkqwmhnotKHShSbDYsNPOAIGvryCxyb74h87BEVxk8OHmg79SsyXkf2eBpaA9ykg43EK-tMh2MZg3dfLqoFb0ZbUYgojJACMBsXAo9_WdF5MeEUczMsSs8HQ" }   主要な部分を抜粋すると、 Access Token : ユーザ情報を取得するために使用されるトークンです。 Refresh Token : ID TokenとAccess Tokenを再生成する際に使用されるトークンです。 IDトークン は: OPが正規なものであることと、ユーザーが認証されていることを証明するトークンです。 IDトークン検証 この後、ID Tokenの中身を検証し、OPが正規なものであるか確認します。今回は手動でIDトークンを検証しましょう。 以下のWebサイト(jwt.io)にID Tokenを張り付けてみましょう。 https://www.jwt.io/ja 張り付けた後、以下の画面が右側表示されるはずです。 主要な部分を以下に抜粋します。 ヘッダー部分 alg : 署名アルゴリズム kid : 署名の検証に使用する鍵のid ペイロード部分 iss : ID Tokenの発行元でURLが表示されます。 sub : ユーザの識別子(ID)を示します。 aud : ID Tokenを使用するClientを示します。 exp : ID Tokenの有効期限(Unix time) at_hash : アクセストークンをハッシュ化したもの。アクセストークンが正しいものかどうかを検証するために使用 これらの値を実際のものと見比べると正しいものであることを確認できるはずです。   また、IDトークンは . で区切られた3つの部分(ヘッダー・ペイロード・署名)から構成されており、最後の部分が署名です。 http://localhost:8000/jwks にアクセスすると署名の検証に使用する公開鍵の情報があります。 IDトークンの署名は、ヘッダーとペイロードを . で連結したものから計算したハッシュ値を、OPが持つ秘密鍵で暗号化したものです。RP側では、OPの公開鍵を使ってこの署名を 検証 します。これにより、トークンが改ざんされておらず、確かにそのOPから発行されたものであることを確認できます。詳しい検証プロセスは複雑なため省略します。 ※余談ですが、jwt.ioの仕様上ID Tokenから署名の検証に必要な公開鍵を、左下に自動で割り出してくれます。実際に、 http://localhost:8000/jwks の情報と比較してみると一致するはずです。 UserInfo Request IDトークンの検証が終了した後、実際にユーザ情報を取得します。 以下のコマンドをPowerShellで叩いてください。 $ curl -s -X GET -H "Authorization: Bearer 【発行されたアクセストークン】" "http://localhost:8000/userinfo/"   すると、Authorization RequestのScopeで指定した、profile, emailの情報が取得できます。 { "sub": "2", "given_name": "user01", "family_name": "test", "nickname": "test_user01", "email": "example@google.com" }   最後に OIDCはだいたい、このような流れとなっています。 今回は一連の流れを手作業で行いましたが、実際使用する際は、OIDCのClient用ライブラリを使用するため、OPのアドレス(issパラメータ)やClient ID, Client Secretさえ指定してしまえば、あとはほぼすべて自動でやってくれます。
アバター
概要 こんにちは。ニフティの山田です。 2025/07/17に、ECS組み込みBlue/Greenデプロイがリリースされました。 https://aws.amazon.com/jp/blogs/news/accelerate-safe-software-releases-with-new-built-in-blue-green-deployments-in-amazon-ecs/ 従来、ECSの組み込みデプロイ機能はローリングアップデートにしか対応しておらず、Blue/Greenデプロイを行うためにはCodeDeployを使用する必要がありました。 今回の変更によりECSだけでBlue/Greenデプロイが可能になったほか、CodeDeployによる制約がなくなりました。 これらの変更点について解説していきます。 ALB + ECS構成の場合に従来と比べてどうなるかを解説します CodeDeploy Blue/Greenデプロイと比べて変わること 単にCodeDepoloyが要らなくなる、という点以外にも仕様の違いはいくつかあります。 切り替え方法 (上記はテストリスナー(ルール)有効時のパターンですが、無効時はテストトラフィックのシフトはスキップされます) 基本的な動作原理はCodeDeployのものと同じですが、以下の点で異なります。 本番・テストトラフィックの管理がリスナー単位からリスナールール単位に変わった CodeDeploy Blue/Greenでテスト用アクセスを行うにはポートを変えるしかなかった ルールに変わったことにより、ヘッダなどの条件でも切り替えられるようになった 常にBlue/Green両方のターゲットグループへの参照を保持するようになった CodeDeploy Blue/Greenでは使わない方のターゲットグループへの参照は外れていた ECS Blue/Greenでは重み付きで両方保持するようになった ライフサイクルフック CodeDeploy同様に、決められたタイミングにライフサイクルフックが設定されており、Lambdaを呼び出して処理を実行、必要に応じてデプロイを停止させることができます。 フックの種類 名前は異なっていますが、同等+αのフックが用意されています。 CodeDeploy Blue/Green BeforeInstall / AfterInstall AfterAllowTestTraffic BeforeAllowTraffic / AfterAllowTraffic ECS Blue/Green PRE_SCALE_UP / POST_SCALE_UP TEST_TRAFFIC_SHIFT / POST_TEST_TRAFFIC_SHIFT PRODUCTION_TRAFFIC_SHIFT / POST_PRODUCTION_TRAFFIC_SHIFT REONCILE_SERVICE フック戻り値の種類 フックで呼び出されたLambdaが返すことのできる値として、 IN_PROGRESS が追加になっています。 SUCCEEDED 成功(デプロイ続行) FAILED 失敗(デプロイを停止してロールバック) IN_PROGRESS 実行中 IN_PROGRESSを返した場合、30秒後にまたLambdaが呼び出されます。 別途ロングランの確認(ex. E2Eテスト)を呼び出し、その終了を待つ、といった場合に使用できます。 CodeDeployの制約からの開放 CodeDeployを使用する場合、ECSのDeploymentControllerとして CODE_DEPLOY を指定する必要があります。このモードではECS serviceの保つ機能が制限されるという問題がありました。 ex) networkConfigurationなど、一部のECS serviceの設定を直接更新できなくなり、CodeDeployでのデプロイで更新する必要がある このせいでデプロイ側でサービス定義を管理する必要があった ECSが持つサーキットブレーカーの機能は使えず、CodeDeploy側の機能で代替する必要がある ECS Service Connectが使えない ECS Blue/Greenでは ECS の指定になるため、この制約がなくなります。 以上、基本的にはECS Blue/Greenの方が使い勝手が良くなっています。 AWS公式としてもECS Blue/Greenを推奨しており、AWSコンソール上では既にECSサービスの新規構築時にCodeDeployが選択できなくなっているため、今後の構築にはECS Blue/Greenを使いたいところです。 (後述の注意点を要確認)  Terraformでの設定 ECS Blue/Green対応は AWS Provider v6.4.0から入っていますが、不具合があるためv6.6.0以降を使ってください https://github.com/hashicorp/terraform-provider-aws/issues/43552 考慮事項 ECS Blue/Greenではリスナールール単位でトラフィックを管理するようになったのだが、これによりTerraformでは設定できないパターンが発生してしまっている問題があります。 リスナーにルールが1つしかない場合、以下のように設定してきたかと思います。 resource "aws_lb_listener" "listener" { ... default_action { type = "forward" target_group { ... } } } ここで default_action でデフォルトリスナールールのアクションを定義しますが、このルールのARNは Terraformで取得することができません 。ECS Blue/Greenの設定時にARNが必要になるため、この設定は行えないことになります。 なので、default_actionはダミーの設定として実質使用せず、別途リスナールールを定義する必要があります。 なお、以下のようにdataで取得できないかも検証しましたが、priorityの値にdefaultを受け付けず失敗しました。 ata "aws_lb_listener_rule" "default" { listener_arn = aws_lb_listener.listener.arn priority = "default" } 設定 ALB resource "aws_lb_listener" "listener" { ... # 基本的にこのルールには来ない想定 default_action { type = "fixed-response" fixed_response { content_type = "text/plain" message_body = "Not Found" status_code = "404" } } } # ARNを取得できるように、別途リスナールールを用意 # テスト用ルールを用意する場合は、別途もう1つ作る resource "aws_lb_listener_rule" "prd" { listener_arn = aws_lb_listener.listener.arn priority = 100 action { type = "forward" # CodeDeployと異なり、2つのTGを両方登録してweightで制御する forward { target_group { arn = aws_lb_target_group.blue.arn weight = 100 } target_group { arn = aws_lb_target_group.green.arn weight = 0 } } } # default_action代わりに使う場合は、必ずヒットする条件にしておく # 他のルールがある場合はpriorityとあわせて要調整 condition { path_pattern { values = ["*"] } } } 上記考慮事項を踏まえ、 default_action をダミーにして別途リスナールールを用意 CodeDeployと異なり、ターゲットグループを2つとも登録しておく必要あり ターゲットグループ自体の設定は従来と変わらないので割愛 ECS resource "aws_ecs_service" "service" { ... deployment_controller { type = "ECS" } deployment_configuration { strategy = "BLUE_GREEN" bake_time_in_minutes = 1 # 切り替え後にGreen環境を残しておく時間(分)、要調整 } deployment_circuit_breaker { enable = true rollback = true } network_configuration { # ここは変わらず } load_balancer { target_group_arn = aws_lb_target_group.blue.arn container_name = "app" container_port = 8080 advanced_configuration { alternate_target_group_arn = aws_lb_target_group.green.arn production_listener_rule = aws_lb_listener_rule.prd.arn # テスト用リスナールールを用意する場合 # test_listener_rule = "<テスト用リスナールールARN>" role_arn = "<Blue/Green切り替え用のARN>" } } lifecycle { ignore_changes = [ task_definition, desired_count ] } depends_on = [ "<ALB>" ] } 従来との主な違い  deployment_controllerを type = ECS に設定したうえで、deployment_configurationで strategy = BLUE_GREEN を設定することでECS Blue/Greenの設定になる load_balancerの設定に advanced_configuration が増える alternate_target_group_arn: Green側のターゲットグループARN production_listener_rule: 本番用リスナールールARN test_listner_rule: テストリスナールールARN role_arn: Blue/Green切り替えに使われるRoleのARN(別途作成が必要) 必要なポリシー Assume Role Policy { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowAccessToECSForInfrastructureManagement", "Effect": "Allow", "Principal": { "Service": "ecs.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } Policy AmazonECSInfrastructureRolePolicyForLoadBalancers 中身 { "Version": "2012-10-17", "Statement": [ { "Sid": "ELBReadOperations", "Effect": "Allow", "Action": [ "elasticloadbalancing:DescribeListeners", "elasticloadbalancing:DescribeRules", "elasticloadbalancing:DescribeTargetGroups", "elasticloadbalancing:DescribeTargetHealth" ], "Resource": "*" }, { "Sid": "TargetGroupOperations", "Effect": "Allow", "Action": [ "elasticloadbalancing:RegisterTargets", "elasticloadbalancing:DeregisterTargets" ], "Resource": "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*" }, { "Sid": "ALBModifyListeners", "Effect": "Allow", "Action": "elasticloadbalancing:ModifyListener", "Resource": [ "arn:aws:elasticloadbalancing:*:*:listener/app/*/*/*" ] }, { "Sid": "NLBModifyListeners", "Effect": "Allow", "Action": "elasticloadbalancing:ModifyListener", "Resource": [ "arn:aws:elasticloadbalancing:*:*:listener/net/*/*/*" ] }, { "Sid": "ALBModifyRules", "Effect": "Allow", "Action": "elasticloadbalancing:ModifyRule", "Resource": [ "arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/*/*" ] } ] }   参考: Amazon ECS infrastructure IAM role for load balancers (EFSをつけたり、Service Connectをつけたりしている場合は追加のポリシーが必要なので注意) 従来はecs_serviceのほとんどの項目を ignore_changes で無視する必要があったが、その必要はなくなる デプロイで変わるtask_definition、オートスケールで変わるdesired_countだけignoreすればよい serviceはすべてTerraformで管理する形にできそう もちろん従来同様の管理方法にしてもよい その他 デプロイ時のRole(or User)に以下のポリシーが必要 { "Version": "2012-10-17", "Statement": [ { "Action": "iam:PassRole", "Effect": "Allow", "Resource": ["{上記role_arnに指定したarn}"], "Condition": { "StringEquals": {"iam:PassedToService": "ecs.amazonaws.com"} } } ] } CodeDeploy Blue/Greenからの切り替え 公式に移行方法が解説されています。 が、稼働中のシステムを移行させるのは正直困難だと思った方が良いです。 前述のように構成が一部変わっており、デプロイ前に変更しなければならない 切り戻しができない deploymentControllerをCODE_DEPLOY → ECSにはできるが、逆は不可能 切り戻せないのが致命的なのでインプレースでのアップデートは避けたほうが良く、やるならALB+ECSのセットをもう1つ作って切り替えるのがよいでしょう。 注意事項 リスナールールのforward以外のアクションが消滅する 2025/08/01時点で本事象について暫定対応され、forward以外のアクションが設定されていると デプロイが失敗する ようになりました Blue/Greenデプロイ対象となるリスナールールには通常、forwardアクション1つだけがついている状態になっているはずです。 一方、 authenticate-oidc のように認証を付けた場合、アクションは2つになります。 ex) Terraformでの例 resource "aws_lb_listener_rule" "prd" { ... action { type = "authenticate-oidc" ... } action { type = "forward" ... } } この状態でBlue/Greenデプロイを行うと、 forward以外のactionが消滅します 。上記ではauthenticate-oidcのアクションが消えてしまいます。 CodeDeploy Blue/Greenでは保持してくれるので、ECS Blue/Greenのみで発生する事象です。 Canaryリリースが未実装 CodeDeployと異なり、リリース戦略を選択するパラメータが存在せず、Canaryリリースができません。 そのうち実装されそうではありますが、現段階では一括リリースしかできません。 ecspressoの取り扱い デプロイにecspressoを使用している場合のみ影響します。 ECS Blue/Greenに移行することにより、サービス定義を全てTerraformで管理できるようになり、デプロイでの書き換えが不要になりました。つまり、タスク定義のみのデプロイでよくなったということになります。 一方でecspressoはサービス定義・タスク定義をセットで管理することを前提としており、この恩恵を受けることができません。一応タスク定義のみでの実行は可能だが想定した使い方ではなく、サポート外と明言されています。 https://github.com/kayac/ecspresso/issues/871 このため、 サービス定義をデプロイ側で管理する(Terraform側で変更しない)運用を継続する ecspressoでのデプロイをやめる サポート外と知りつつ(自己責任で)使う の3択を迫られることとなります。 おわりに 今回は、2025/07/17にリリースされた、ECS組み込みBlue/Greenデプロイについて解説しました。 参考になれば幸いです。
アバター
この記事は、リレーブログ企画「25新卒リレーブログ」の記事です。 はじめに こんにちは。新卒1年目の大村です。 先日、初めてfirewalldというツールに触れました。 これを一般的なACLと同じように送信元アドレス(sources)について設定したら、意図しないパケットが通過してしまい設定に悩まされました。 今回なぜこのような挙動になったのか、想定通り動作させるにはどのような設定にすれば良いかについて、この経験を踏まえたうえで、firewalldに始めて触れる人に向けてまとめたいと思います。 筆者プロフィール 入社時期: 2025年4月 入社前のスキル: ネットワーク, Linux 現在の担当: ISPオペレーション・OAチーム 今回どのような設定を投入していたのか あるインタフェース(仮: eth1)において、IPアドレス(仮: 192.0.2.1)からのみサービス(仮: 22/tcp)を許可するルールを追加することになりました。 このとき、私は以下のような設定に変更しました。 意図としては”eth1に到達したパケットについて、送信元IPアドレスが192.0.2.1、宛先ポートが22/tcpなら許可”といった具合です。 しかし、実際の挙動としては、 192.0.2.1以外のホストもアクセス可能 となりました。 firewalld基本とACLとの違い なぜこのような挙動になったのかの前に、まずfirewalldがどのよう動作するかを紹介しようと思います。 まず、firewalldは、多くの人が触れてきたであろう”プロトコル、IPアドレスとポート番号の送信元や宛先、許可/拒否のみでルールを記述するACL”とレイヤが異なるものです。 ACLイメージ図 firewalldは独自の概念に基づいて設定し、上記のようなルールを生成するものであるという認識が重要になります。 一般的なACLは、インタフェースが中心であり、インタフェースごとにルールを追加していくかと思います。 一方、firewalldは、” ゾーン “というものが中核となっており、このゾーンにインタフェースや送信元IPアドレスを追加していきます。 このゾーンとは、そのインタフェースや送信元IPアドレスがどの程度信頼できるか、どのようなルールでパケットを通過させるかのプロファイルのようなものです。 firewalldにデフォルトで存在するゾーンの種類 1 パケットが到達すると、送信元IPアドレス、次にインタフェースの順で先にマッチしたゾーンに割り振られます 2 。 最初に送信元IPアドレスがマッチするか判定する 1でマッチしなければ、次に受信したインタフェースで判定 またゾーンには、通過が可能なポート番号やプロトコル、後述するリッチルールを割り当てられます。 最初の設定の問題点 ACLでは送信元IPアドレスは許可(拒否)のルールの一部なため、同様だと認識していました。 しかし、firewalldにおいての送信元IPアドレスは、ゾーンの振り分けのためのルール 3 です。 今回のケースは、sourcesにマッチしなくても、interfacesにマッチしてしまい、publicゾーンで評価されるようになったため、アクセスが可能となった訳です。 では、意図した通りの動作をさせるにはどのようにするか。 私は次のようにリッチルールを使用して設定を変更しました。 リッチルールでは、ACLのルールと似たような設定方法で、送信元/宛先のIPアドレス、ポート番号、プロトコルの組み合わせで許可/拒否が可能です。 今回の要件では、”192.0.2.1からのSSH”を許可が要件なため、以下のようなリッチルールを追加しました。 これで意図したように192.0.2.1からのみSSHが通るようになりました。 firewalldで設定するには firewalldを上手く設定するには、まずfirewalldのアプローチを理解することが大切です。 インタフェースや送信元アドレスでゾーンに振り分け、そのゾーンでパケットを通過させるかを決定します。 この仕組みを理解したうえで、通過させたいルールを宛先ポート番号やリッチルールなどに落としこむことが鍵になるかと思います。 まとめ firewalldにおけるsourcesは、一般的なACLのような”許可/拒否するIPアドレス”の設定ではありませんでした。 sourcesはゾーンを選択するための設定項目です。 もし、ACLのような設定を追加するのであれば、リッチルールを使用することで可能となります。 【終わりに】 学生の皆様に向けて まだ入社して間もないですが、ニフティには、成長・挑戦を支えてくれる仕組みが整っていると感じています。 制度は こちら で紹介されているものや無料で使えるUdemyなど数多く揃っていますし、入社後の 研修 も魅力の一つです。 また、配属後も困っていることがあれば丁寧に指導頂け、挑戦したいことがあれば、それを受け入れる文化もあります。 そんなニフティでは、この制度・文化を活用して挑戦していける仲間を募集中です。 成長・挑戦を軸にしている人には、とても良い環境だと思います。 この記事をご覧になっているあなたが、一緒に働きたいと思って頂けますと幸いです。 次は、なべしまさんの記事です。 どんな記事か楽しみですね。 参考文献 各事前定義されたゾーンについて: https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/10/html/configuring_firew all s_and_packet_filters/using-and-configuring-firewalld#firewalld-zones ︎ Previous Behaviorのセクション: https://firewalld.org/2023/04/zone-priorities ︎ https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/10/html/configuring_firewalls_and_packet_filters/adding-a-source ︎
アバター
はじめに おはようございます。IWS です 最近、クラウドコスト把握のため、AWS Lambda を使って各アカウントの利用料を取得するというのをしていました。いくつかあるアカウントからデータを取得しようとしていたのですが、それぞれに AWS Lambda を作るというのはしたくなかったのでスイッチロールを使って他所のアカウントのデータを1箇所から取得できるようにしました。今回はそのことについて書いてみようかと思います。   スイッチロール? 簡単に言うと IAM ロールを使って各アカウントの切り替えを簡単にできるようにするものです。 作成した IAM ロールの持っているポリシーの範囲内でスイッチ先のアカウントを操作できます。今回は スイッチ元のアカウント A にある AWS Lambda からスイッチ先の アカウント B で get_cost_and_usage を使ってコストを取得します。   やってみる まずはスイッチ先のアカウントで IAM ロールを作成します。 IAM ロールの作成の信頼されたエンティティで「AWS アカウント」を選択、下の選択では「別の AWS アカウント」でスイッチ元のアカウント ID を入力します。 これだけです。あとは通常のロール作成時と同じようにポリシーの設定などを行ってください。スイッチ先のアカウントの準備はこれだけです。 AWS Lambda 側準備 使用するのは boto3 の sts_client.assume_role です # スイッチ元のセッション base_session = boto3.Session(region_name="ap-northeast-1") sts_client = base_session.client("sts") # スイッチ先のセッション assumed_role = sts_client.assume_role( RoleArn="<作成した IAM ロールの ARN>", RoleSessionName="AssumeRoleSession", )   なんとこれだけです。レスポンスの Credentials の中にアクセスキーやシークレットキーといった情報が入っているのでこれを使って新しいセッションを発行するだけでスイッチロールができます。 credentials = assumed_role["Credentials"] assume_role_session = boto3.Session( aws_access_key_id=credentials["AccessKeyId"], aws_secret_access_key=credentials["SecretAccessKey"], aws_session_token=credentials["SessionToken"], ) # スイッチ先アカウントで ce が使える! ce = assume_role_session.client("ce")   あとは client("ce") などを使ってポリシーの範囲内で操作ができます。 res = ce.get_cost_and_usage( TimePeriod={"Start": start, "End": end}, Granularity="MONTHLY", Metrics=["UnblendedCost"], ) total_amount = float(res["ResultsByTime"][0]["Total"]["UnblendedCost"]["Amount"]) # アカウント B の料金 : 300 USD   まとめ 別の AWS アカウントを操作できる「スイッチロール」をやってみました。今回はコストを取得してみただけですが、ポリシーを変えれば当然 Amazon ECS を操作したり Amazon Cloudwatch を操作したりもできるため、あるアカウントから別のアカウントに対して簡単に CLI が使えるということだけでも覚えておくといつか役に立つかもしれません。 みなさんもぜひ「スイッチロール」役立ててみてください!
アバター
こんにちは。NIFTY engineeringブログ運用チームです。 ブログ運用チームでは、ニフティのエンジニアについての情報を世の中に広めるための活動をしています。 その活動の一環として、リレーブログを実施しています。 昨年好評だった新卒リレーブログを今年も実施しています!! 【リレーブログ企画】24新卒リレーブログをやります! 本記事に、25新卒社員のブログ記事のリンクをまとめていきますので、ぜひチェックしてください。 25新卒リレーブログは以下のスケジュールで投稿予定です。お楽しみに! 投稿予定 執筆者 記事タイトル 2025年7月28日 宮村さん 【イベント参加レポ】いままでAWSを触ってこなかった一年目が、AWS Summitに参加してきました 2025年7月29日 moriさん Rancher Desktopにディスクが異常消費される問題の対処法 2025年8月5日 大村さん (仮)Firewalldの引っかかったポイント 2025年8月13日 石田さん 未定 2025年8月19日 なべしまさん 未定 2025年8月22日 高垣さん gitコマンドを使わずにcommitする 2025年8月26日 パクさん 未定 2025年8月29日 やまだ25さん (仮)オンプレのファイルサーバをAzureファイル共有へリプレイス
アバター
はじめまして! こんにちは!2025年度新卒エンジニアのパクです。 OJTとしてマイニフティチームに所属しています。 よろしくお願いします   AWS Summitって何? AWS Summitは、 AWS(Amazon Web Service) の技術を中心に開催されるITイベントです。Amazonというと、「あの物流会社の…?」と思うかもしれませんが、その通りです!   そのアマゾンが運営するAWSは、簡単に言うと、 インターネットでコンピュータを借りるサービス です。 以前はWebサイトをサービスするには、24時間稼働できる高価なPCサーバーを購入し、自分で管理しなければなりませんでしたが、AWSを使えば、ネットで必要な分だけ柔軟にコンピュータを借りることができます。 そんなAWSに関連するすべてのことが集まり、年1回開催される日本最大のクラウドコンピューティングイベントがAWS Summitです! 今年は6月25日と26日の2日間、幕張メッセで開催され、私は2日連続で参加しました。   参加申し込みからセッション予約まで AWS Summitに参加のためには、公式Webページから事前に申請する必要があります! https://aws.amazon.com/jp/summits/japan (来年はリンクが変更される可能性があります) リンクをクリックすると、イベント全体の内容とともに、どんな技術講演(セッション)があるのかが確認できます。様々なセッションがありますが、各セッションには 「Level」 があります。AWSに慣れていない方は、AWS初心者向けのLevel 100~200のセッションを先に予約することをおすすめします。 人気なセッションはすぐに満席になってしまいますが、当日会場に空席があれば、自由に入場して聞くこともできるので、あまり心配する必要はありません。   私は聞きたかったセッションがほとんど満席で予約は出来なかったのですが、当日会場で全部参加できました。 何をもっていけばいいかな? 必須 事前予約の後、マイページからアクセスできるQRコード 身分証 (名刺、免許証等) あるといいもの 水 バッグパック (ノベルティを沢山もらうなら) PC(ワークショップに参加するなら)   幕張メッセへGo! 会場に入場するためには、事前登録の後に発行されるマイページの QRコード と 身分証 を用意します。 入口で確認後、入場証(チケット)を受け取ることができます。 午前9時から始まる「ウェルカムパフォーマンス」が気になったので、少し早めに到着しました。早い時間だからか、思ったより入場列は長くなかったです。   今年は先着4,000人にクッションとお弁当がもらえる特典がありました!クッションは基調講演を事前に予約していれば、その講演会場の席で受け取ることができ、お弁当は9時20分頃に配布が終了しました。 来年もお弁当がほしいなら、少し急いだ方がいいですね   さあ、お楽しみの時間です! 会場に入ったら、いよいよ本格的にSummitを楽しむ時間です!初心者の視点で、2日間回りながら「これは楽しめる!」と思ったことを紹介します。 まずは基調講演を聴こう 数あるセッションの中で何を聞くべきか迷ったら、基調講演を聴きましょう。 AWS Summitの最も核となるセッションで、AWSの新しい技術と様々な企業の成功事例を紹介します。 基調講演を聞いて、「AWSが日本国内で貴重な価値を生み出しているんだ」「思った以上に巨大な技術なんだな」と気づき、AWSへの興味が湧きました。   企業ブースも一通り回ってみよう GitLab、IBM、IBM、Postman、AMDなどなど馴染みのある企業はもちろん、「こんなサービスもあるんだ!」と思う企業まで、様々な企業が出展しています。 各ブースでは、自社の技術やサービスをアピールするために独特なイベントを開催しており、それを見るだけでもとても興味深く、楽しい経験でした。 一部のブースでは、その場で気軽に聞ける ミニセッション を開催しているところもあるので、興味のあるテーマがあれば参加するのもいいでしょう。 そして、ブースを回っていると、両手一杯の 戦利品 を手に入れることができます。かわいいステッカーや便利グッズを申し訳ないくらいたくさんもらえますので、AWS Summitに参加するときは、ぜひバッグパックを持って行きましょう!   ゲームで学ぶ、AWS体験ラボ 「セッションが難しいです」と思う方には、ここもおすすめです! AWS体験ラボはAWSに初めて触れる初心者の方もゼロから楽しく学習できる体験型ブースです。 Cloud Quest: ゲームでAWSのスキルを学んでいきます。 SIMULEARN : チャットでAIと話ししながら、ビジネス問題をAWSでどのように解決するかを学ぶシミュレーションです。 私はCloud Questを1時間ほど体験してみました。体験を始めると、実習用の仮AWSアカウントがすぐに作成され、必要なファイルもすべて用意されているので、本当に「学習」に集中できたのが良かったです。 「AWS何もわからない素人だけど…」という方はぜひ参加してみてください!   この他にも ハンズオン、ワークショップできる エキスポ や、AWSの技術を活用した様々なプロジェクトが展示されている 展示ブース もありました。 余裕があったら回るのも楽しみの一つです!   最後に 最初は、「AWSの知識がないと楽しめないのでは…」と心配していたのですが、AWS Summitは「専門家だけのイベント」ではなく、私のような新人エンジニアも一緒に楽しみながら学べる、とても有意義で楽しい時間でした。 ITを超え、アニメーション制作、物流の自動化、食品廃棄物の問題解決に至るまで使われるAWSの姿に、クラウドコンピューティングの無限の可能性を感じました。 今回の経験で、AWSは難しい技術とした偏見がなくなり、今後ニフティで新しい技術をもっと探求したいと思う貴重なきっかけを得ました。 この記事を読んでいる皆さんも、次のSummitでお会いできることを願っています  
アバター
CCoEや生産性向上に関する仕事をしている石川です。 今回は開発生産性向上を目指して、2025年3月から様々なAIエージェントを試してみた 個人的な 感想を書いていこうと思います。GitHub Copilot以外のツールは数日から1ヶ月使用しただけなので、深く使い込んだわけではありません。 GitHub Copilot Agent mode / Coding Agent 良い点 GitHub提供の安心感と将来性への期待 GitHubとの高い親和性 困る点 従量課金要素がある(Premium Request) 世間で流行している機能が実装されるまで時間差がある ChatGPTで簡単なコード生成を試した以外では、GitHub Copilotが私が本格的に使った最初のコーディングAIです。ニフティでは2023年9月から正式導入されています。 VSCodeと統合されているため使い方に迷うことがなく、初めてコーディングAIを使う方にも最適だと思います。GitHub.com上でレビューやスキャン結果を即Copilotで修正できるのも親切です。 約2年間使い続けていますが、その間に利用可能なモデルが増え、EditモードやAgentモードなども追加され生産性は大幅に向上しています。最近ではInstructionファイルを認識してくれるケースも増え、日々着実に便利になっています。 一方で、最新のトレンド機能がまだ取り込まれていないこともあります。ですが必要な機能は最終的にすべてCopilotに統合され、結局はCopilotに落ち着くのではないかと個人的には期待しています。 Cline / Roo Code Copilot Agent modeが一般公開されるまでの間に、ClineやRoo Codeなどのツールを試したことはありますが、十分な感想を書けるほど使い込んでいないため、ここでは割愛します。 Devin ※2025年3月時点におけるDevinの感想となります 良い点 早い段階から自立型AIエージェントとして完成度が高かった GitHubやSlackから簡単に利用できる Devin自体がブラウザやエディターを内蔵しており、独立した環境でタスクを実行できる 困る点 認証情報の管理が難しい BotとしてのDevinに強い権限が付与される SAML/SSOを利用するにはEnterpriseプランが必要 自立型AIエージェントを体験するのに最適なSaaSだと思います。 Devin上で様々な機能を試せますし、GitHubやSlackなど必要なIntegrationも揃っています。 限られた範囲で使う分には問題は少ないですが、全社展開を考えると、アカウント管理、認証情報管理、従量課金の予算管理などの課題が出てきます。これらに対応するには運用ルールをしっかり決めておく必要があります。Devinが予期せぬ動作をした場合、社内のAI普及にも悪影響を及ぼす可能性があるため、展開するとしてもチーム単位で段階的に進めるのが賢明です。 Jules 良い点 Google提供のコーディングエージェント 無料で使える(1日60タスク) 困る点 まだパブリックベータ段階で機能が限定的 GitHubリポジトリとの連携が必須 現時点ではエンジニア向けの無料AIコーディング体験SaaSという印象です。 純粋なコーディングエージェントなので、Devinのような汎用性はなく、GitHubとの連携が必要となります。Devinが自動的にプルリクエストまで作成するのに対し、Julesはブランチ作成までで止まるなど、提供会社ごとにAIエージェントの作業範囲も異なります。 Claude Code 良い点 内部プロンプトの優秀さを実感できる エディターやGUIに縛られずに利用できる 困る点 従量課金要素がある(API) CLIだと日本語入力がやや不便 使用前は世間のあまりの評判の高さに懐疑的でしたが、実際に使ってみると体験が非常に良かったです。 他のAIエージェントと同様に「計画立案 → タスク化 → 処理」という基本的な流れは共通していますが、進捗の伝え方、結果サマリーの適切さ、そして他の作業を邪魔せずに動作する点が優れています。内部で使われているであろうプロンプトが非常に優秀だということも伝わってきて、これらが総合的に良い体験を生み出しています。 CLIについては、エディターを占有しない&複数のタスクを並列実行できる点で有利なインターフェースだったんだと再発見した気分です。 CLIでの日本語入力はやや不便ではありますが、長文のプロンプトが必要な場合はカスタムスラッシュコマンドを活用できますし、最悪コピペすればいいので慣れればそこまで困るものではありませんでした。 Kiro 良い点 Specモードによる要件定義から行う体験が優れている AWS提供のエディター 困る点 利用にはWaitlistの登録が必要 Kiroによるコーディング処理が非常に遅い セッション切れによるIAM Identity Centerログインし直しがちょっと面倒 Kiroはエディターの基本機能として、AIエージェントを効果的に活用するための一つの模範解答を提供しています。 Claude CodeのPlanモードやRoo CodeのArchitectモードなど類似機能はありましたが、「要件定義 → Design Doc → プラン作成」を対話形式で自動化してくれる体験はすばらしかったです。既存の重厚なプロンプトテンプレートを持っていない限り、SpecモードでAIとプランを立てる体験は、今後のAIエージェントとの効果的な関わり方を学ぶ良い機会になると思います。 Gemini Canvas コーディングやエージェント以外に、情報収集やスライド作成に関するツールも調査していたので、おまけとして紹介します。 良い点 Geminiの一機能として手軽に利用できる Deep Researchで調べた結果を即座にレポートや一枚絵(html)にまとめられる 困る点 Googleスライドに直接流用できない(キャプチャなら可能) スライドに適したフォーマットをプロンプトで指定するのが面倒 私は発表用のスライドをGeminiに与え、Canvasでhtmlページを作成し、それをキャプチャしてスライドに挿入する方法で活用していました。便利ではありますが、デザインの微調整が非常に難しいのが欠点です。 この問題を解決してくれるツールとして Manus があります。スライド機能やデータ可視化機能は非常に優秀ですが、気になる点もあるため現時点ではプライベートでの検証に留めています。 ほかにも ChatGPT Agentでもスライドが作成できるようになりました し(現状ではデザイン面が不十分)、数ヶ月後には他のツールも対応してくると思われる(願望)ので、このあたりはまだ様子見でも良いかもしれません。 まとめ GitHub CopilotやNotion AIを過去に導入した経緯もあり、流れで最近のAIエージェントも調査を進めてきましたが、種類の多さと進化の速さに追いつくだけでも疲弊しますね。 半年から1年ほど待って落ち着いてから導入を検討するのが最も効率的ではありますが、AI技術は実際に体験して初めて理解できる要素が多いと考えています。日々の情報収集と手を動かすことで得られる経験値が非常に重要だとも思います。 様々なツールを検証した結果、主な使い方と必要となる情報(InstructionやKnowledgeなどのカスタム要素)さえ集約できていれば、自分に合ったものを選んで使うのが現時点での最適解でしょう。さらに言えば、一つのツールに固執せず、様々なものを試す柔軟な姿勢も大切だと思います。 未来は常に変化していくため、どのツールをどの程度社内に展開するかの計画は立てにくいですが、実際に優れた体験価値を提供したツールについては積極的に社内展開を進めていきたいと考えています。
アバター
はじめに 皆さんこんにちは、宮村です。 今回は、2025年 6月25日と6月26日にAWS Summit Japan 2025に参加してきたため、アマゾン ウェブ サービス(AWS)をほぼ触っていない入社一年目のエンジニアの目線で感想を語っていきたいと思います。 AWS Summitとは 公式サイト での記載は以下の通りです。 AWS Summit は、共に未来を描くビルダーが一堂に会して、アマゾン ウェブ サービス (AWS) に関して学習し、ベストプラクティスの共有や情報交換ができる、クラウドでイノベーションを起こすことに興味がある全ての皆様のためのイベントです。 https://aws.amazon.com/jp/summits/japan/ 簡潔に言うと、Amazon Web Services, Inc.様をはじめとする多くの企業が一堂に会し、情報交換を行ったり、企業が抱える課題を解決するための製品やサービスを紹介したりする場、と言えるでしょう。 なぜ参加したのか 弊社では全社的にAWSが使用されているため、技術的知見を増やしたかった点と、一人のビジネスパーソンとして技術系イベント参加したかったためです。   会場の様子 会場は多くの来場者と出展企業で、大変な熱気に包まれていました。 Amazon Web Services, Inc.様やその他の様々な企業によるセッション会場のほか、ブースがたくさんありました。 この業界ではなじみの深いAMD様やGitLab様、いま注目を集めているAnthropic様など、多種多様な企業が集っていました。 ブースでは、様々な企業様から「自社の製品いかがですか?」とアピールしてきます。 事前に自社や担当プロダクトの課題を整理しておくと、『この製品はあの課題を解決できるかもしれない』といった発見があり、より有意義にブースを見て回れると感じました。 また、話を聞いていると、いろいろなノベルティやオリジナルステッカーなども配布されていました。 特に印象的だったのは、Red Hat様のブースで配布されていたred hat(トレードマークの赤い中折れ帽)です。   セッションの様子 両日とも、10時から11時半まで基調講演があり、その後各ブースで個別セッションが行われる形です。 来年参加される方へのアドバイスですが、基調講演を良い席で聞きたい場合、早めに会場へ到着することをおすすめします。今年の例では、開場後すぐに席が埋まり始め、早く来た人にはクッションや昼食券が配布されるなどの特典もありました。 様々なセッションを見ましたが、その中でも特に印象に残ったものをいくつかピックアップして紹介したいと思います。 Amazon Web Services, Inc.様による「生成 AI を活用したデータベースのスキーマ変換で移行を加速しよう : AWS Database Migration Service Schema Conversion」 生成AIを活用することにより、自社で保有しているサーバからAWSへのデータベース移行を大きな労力をかけずに実現できるとのことです。 これまでは、Oracle DatabaseなどからAWSのデータベースへ移行する際、関数やストアドプロシージャといった複雑なコードは自動変換が難しく、手作業での修正が多く発生していました。 セッションによると、従来は全体の8%程度しか自動変換できなかった処理が、生成AIを活用することで約85%まで自動化できるようになったとのことです。 これも、ただ、生成AIを活用すればいいだけでなく、コンテキストや難読化したコードの修正やLarge Language Model(LLM)の選定等、考慮事項が多いため、AIをどう活用していくかが重要となりそうだと感じました。 弊社でもこのようなAWSへの移行は課題となっているため、参考にしたいと思いました。 Amazon Web Services, Inc.様による「セキュアなソフトウェア開発ライフサイクルのための生成 AI」 本番環境へのデプロイ後等に、脆弱性が見つかることはたびたび発生するため、継続的なスキャンや、依存関係になっているシステム全体の把握が必要となります。 近年のサイバー攻撃の巧妙化を受け、ソフトウェアを構成するコンポーネント(部品)を一覧化した『ソフトウェア部品表(SBOM)』の重要性が高まっています。しかし、開発の過程で常に最新の状態に保つのは容易ではありません。 この課題に対し、AWSの脆弱性管理サービスである『Amazon Inspector』は、スキャンしたリソースからSBOMを自動で継続的に生成・管理してくれるとのことです。 弊社でも、SBOMに関する話が出始めており、この分野に関する知見をより広げていこうと感じました。 株式会社ドワンゴ様による基調講演および、個別セッション「ニコニコの大規模セキュリティ改革」 ネット文化を代表するサービスの一つともいえる『ニコニコ』を運営する株式会社ドワンゴ様は2024年6月に大規模なサイバー攻撃を受けました。 対応の際には、Amazon Web Services, Inc.様の社員の方々も含めてセキュリティチームを構成したそうです。 発表によると、攻撃を受けた際、自社で運用していたオンプレミス環境は大きな被害を受けましたが、以前から移行を進めていたAWS上の環境は被害を最小限に食い止められたとのことです。 この経験から、残っていたシステムのAWSへの移行計画を大幅に前倒しして、サービス復旧を進めたそうです。 AWSが提供する堅牢なセキュリティ基盤の有効性を、改めて認識させられる事例でした。 また、このような被害は他人ごとではないという言葉が、特に印象に残りました。 全体を通しての感想およびまとめ この二日間を通して、AWSに対する興味がより一層上がりました。 AWSにより、様々なソリューションを実現できることを知り、弊社でも活かしてみたいとも思いました。 私のようなAWS初心者でも、Simple Storage Service(Amazon S3)やAmazon EC2といった基本的なサービスの役割を把握していれば、各セッションの目的を理解できると感じました。 来年の開催までには、さらにAWSの知識や自社の課題への理解を深め、より多くの学びを得られるよう再挑戦したいです。
アバター
はじめに はじめまして。ニフティ株式会社の森です。 筆者プロフィール 入社時期: 2025年 4月 新卒入社 入社前スキル: 言語: C, Python, JavaScript 他: Docker, Linux, Flutter, AWSは未経験 現在の担当: 課金システムチーム 現在弊社では、Docker Desktopの代替としてRancher Desktopを使用しています。 そのRancher Desktopにディスクを異常に消費されたので、原因と対処法について記しておきます。 Rancher Desktopの利用も広まっていますので、同問題に直面する人の助けになれば幸いです。 環境 OS: Windows 11 24H2 ハードウェア構成は関係ないと思いますので割愛します。 背景 Docker Composeを使用したローカル検証環境作成の過程で、コンテナを何度も作成、削除する作業を繰り返していたところ、マシンのディスク使用量が急激に増加するという問題が発生しました。 当初、イメージやコンテナに対してpruneコマンドを実行して一時的な対処をしていましたが、根本的な解決には至りませんでした。 結果として、使用しているマシンのディスクが埋め尽くされ、作業に支障が出る状況になりました。イメージやコンテナ、ボリュームを削除しても、ディスクの消費量は増え続けるようです。 肥大化した仮想ディスクファイル 原因 Rancher Desktopがデータを保存する仮想ディスクである C:\\Users\\{ユーザ名}\\AppData\\Local\\rancher-desktop\\distro-data\\ext4.vhdx のサイズが大きくなったまま縮まないことが原因です。 コンテナの作成→削除には以下のような処理が実行されていると考えられるのですが、中にあるデータが消去されたあとも、仮想ディスクが確保した領域が開放されず、サイズが大きくなり続けているようです[1,2]。 コンテナが作成される コンテナのデータを保存するために仮想ディスクファイルのサイズが大きくなる コンテナが削除される 仮想ディスク内のデータ”は”削除される 一度仮想ディスクが膨らんでしまうと、中身を消しても効果がありませんでした。 それに気づかないまま compose up , compose down を繰り返した結果が先程の画像です。 pruneコマンドを使用してリソースを削除しても仮想ディスクが縮まない様子 解決方法 調査した中で効果の確認できた解決方法は2つです。 diskpartを使用して仮想ディスクを縮小する Factory ResetをしてRancher Desktop環境を再構築する diskpartを使用した方法だと、若干手間がかかりますが必要なデータを残したまま仮想ディスクを縮小できます。Factory Resetですと作業は単純ですが全てのコンテナやイメージが消えるのでご注意ください。 diskpartを使用した仮想ディスクの縮小方法 事前に不要なコンテナ、イメージ、ボリューム等を削除して仮想ディスクの使用量を下げる PowerShellから wsl --shutdown を実行してWSLを終了させる diskpart もしくは diskpart.exe を実行 diskpartで select vdisk file=”C:\\Users\\{ユーザ名}\\AppData\\Local\\rancher-desktop\\distro-data\\ext4.vhdx” を実行、ユーザ名は自分のものに置き換えてください。 diskpartで compact vdisk を実行 この際「ディスクが使用されている」のようなエラーが出て失敗した場合WSLが終了していないです Factory Resetをする方法 こちらは仮想ディスクファイルを縮小させるというよりは、一旦全てを削除してしまう方法です。 私の場合は、イメージの数が多くなりすぎて必要、不要の判断ができない状況に陥ってましたので、こちらを実行しました。先ほども書きましたが、コンテナやイメージなど全てが消えますのでご注意ください。 手動で仮想ディスクファイルを削除した後、WSLインスタンスの削除、Rancher Desktopの再セットアップを行っても、同じ効果を得られますが、ひと手間かかります。 Troubleshootingを選択 Factory Resetを押す 警告が出るのでOKを選択 再びRancher Desktopを開くと、インストール時と同じようなウィンドウが出るのでそれぞれの環境にあったセットアップをしてください。 参考資料 https://github.com/rancher-sandbox/rancher-desktop/issues/2398 https://qiita.com/tamanegisoul/items/82b1fe8ed638c79cbe96 終わりに 今回はRancher Desktop使用時にディスクを異常消費される問題への対応策を調査、紹介しました。 同じ問題に遭遇した人の助けになれば幸いです。 この記事を読んだ学生さんに向けて この記事を書いた時点で入社して半年経たないですが、弊社では新人でも様々なことに挑戦できる環境だと感じています。 例えば私の場合は、既存プロジェクトの使用している言語、ライブラリの更新を提案したところ挑戦させてもらい、改修に参加しています。 このように、年次や経験にかかわらず、アイデアは積極的に取り入れ、挑戦の機会を与えてくれるのが弊社の文化です。もちろん、わからないことを聞けば経験豊富な先輩方がしっかり教えてくれるので、失敗を恐れず安心して新しいことに取り組める環境です。
アバター
こんにちは。ニフティ株式会社の仲上です。 今回は、先日開催された SRE NEXT 2025 での発表内容と補足情報についてご紹介します! イベント概要 先日、SRE NEXT 2025 が開催されました。 https://sre-next.dev/2025/ 当社はゴールドスポンサーとして参加し、スポンサーブースの出展などを行いました。 当社が力を入れている分野については、技術広報もさることながらコミュニティとの繋がりも重視しているのでイベントの協賛を行っています。 SREもその分野の1つで、「SRE NEXT」のような大きなイベントには、2022年から毎年協賛しています。 ブースの詳細については担当者が別記事を作成していますので、こちらをご覧ください! SRE NEXT 2025に参加してきました! 登壇内容について 本イベントでは10分間の登壇枠をいただき、私のチームが実施した監視基盤リプレイスについて発表しました。 初めての外部イベント登壇だったため緊張しましたが、非常に貴重な経験となりました。 発表資料はSpeakerDeckに公開していますので、興味のある方はぜひご覧ください。 本日発表した、仲上の資料です。 モニタリング統一への道のり 〜分散モニタリングツール統合のためのオブザーバビリティプロジェクト〜 https://t.co/h4DrxdWz5V #srenext — NIFTY Developers (@NIFTYDevelopers) July 11, 2025 発表内容の補足 発表時間が限られていたため内容を圧縮せざるを得ず、いくつか説明が不足していた部分がありました。この場を借りて補足説明をさせていただきます。 Grafana/Prometheusのコスト評価について 発表時の比較表では、Grafana + Prometheus の構成をコスト面で「高い」と評価しました。 この評価は、純粋なインフラコストだけでなく、運用工数も含めた総合的なコスト計算に基づいています。 Grafana + Prometheus はオープンソースツールであり、サーバーにインストールするだけで利用できますが、実運用では設定や基盤の運用・メンテナンスに予想以上の工数がかかるため、総合的なコスト面で「△」評価としました。 今回は時間の制約から、すでに利用経験のあるOSS版のみを検証対象としましたが、クラウドサービス版では結果が異なる可能性もあります。 もし同様の比較検証をされている方がいらっしゃれば、ぜひ情報共有いただけると幸いです。 具体的なコスト試算結果 今回は以下の条件でコスト試算を実施しました。 監視対象: サーバー20台 ログイベント: 800万イベント/月 ログ保持期間: 30日間 ログデータ量: 1イベントあたり1KBと仮定し、月間 8GB のログデータ(800万イベント × 1KB/イベント ≈ 8GB) 為替レート: $1 = 158円 リージョン: AWSは東京、Azureは東日本リージョン、Datadogは日本 試算結果は以下の通りです。 サービス メトリクス ログ 合計(月額) Datadog ¥72,680 ¥2,150 ¥74,830 Amazon CloudWatch ¥6,600(詳細メトリクス有効時) ¥1,000 ¥7,600 Azure Monitor ¥0(メトリクスはログ料金に含む) ¥6,300 ¥6,300 Azure Monitor については、DCR(データ収集ルール)の設定により保存料金が変動しますが、おおよそAWSと同程度のコスト感になると予想されます。 クラウドネイティブな監視ツールはコスト面で明らかな優位性がありますが、機能性や使いやすさ、既存環境との親和性なども含めた総合的な判断が重要です。 Ask the speaker について Ask the speaker では、監視設定周りの管理が課題になっていたという話題で盛り上がりました。実際、監視周りはGUIでつけるとルールが煩雑になって管理が大変なのでコードで管理したほうが良いですが、コードで管理すると作成コストが重くのしかかってきます。 今回の発表で紹介したコードのエクスポート機能はコードの作成コストを大きく抑える事ができるので、みなさんもぜひ試してみてください! また、オンプレミス環境や他クラウド環境への監視についても話題があがりました。現状はまだ監視できていませんが、環境のリプレイスが増えてきたら必要に応じて監視対象にする予定です! まとめ SRE NEXT 2025での発表を通じて、監視基盤リプレイスに関する経験や知見を多くの方と共有できたことを嬉しく思います。 今後も監視基盤の改善を継続し、このブログ記事が皆さんの参考になれば幸いです。 最後に、SRE NEXTを開催してくださった運営・関係者の皆様・ブースに来ていただいた皆さん、発表まで支えてくれた仲間たち、その他関係していただいた方に心より感謝申し上げます。 ありがとうございました!
アバター