TECH PLAY

SCSKクラりド゜リュヌション

SCSKクラりド゜リュヌション の技術ブログ

å…š1232ä»¶

こんにちは、SCSKの束岡です🪣 デヌタ基盀の構築でIceberg (S3 Tables)を導入した際の詊行錯誀を敎理したした。 埓来のS3によるファむル栌玍型のデヌタレむクず比范し、Icebergを採甚するこずで埗られたメリットや、それをマネヌゞドで扱えるS3 Tablesの利䟿性に぀いお玹介したす。   背景 デヌタ掻甚基盀におけるデヌタレむクは、単にデヌタを蓄積するだけでなく、盎接参照しお怜玢・分析に掻甚したいずいうニヌズが増えおいたす。そのような甚途では、耇数テヌブルのJOINや同時アクセスなどに察する性胜も重芁な芳点ずなりたす。 埓来は、デヌタレむクのデヌタをRedshiftやSnowflakeずいったDWHに取り蟌み、集蚈・加工したうえで掻甚する構成が䞀般的でした。 䞀方で、マルチクラりド環境では、組織や甚途に応じお耇数のツヌルから同䞀デヌタを参照したいケヌスも増えおいたす。 たた、デヌタオヌナヌの芖点では、業務プロセスの倉化に䌎うデヌタ構造の倉曎に察しお、デヌタレむク偎が柔軟に察応できるかが重芁になりたす。列远加やデヌタ型倉曎などを、既存デヌタに圱響を䞎えずに実斜できるこずが望たれたす。 さらに、デヌタ基盀管理者にずっおは、埓来のファむル圢匏のデヌタレむクでは、フォルダ構成やファむルサむズ、デヌタ配眮などの蚭蚈が必芁ずなり、構築・運甚のハヌドルが高いずいう課題がありたした。 加えお、倧量の履歎デヌタを長期保管する特性䞊、デヌタ量の増加に䌎うストレヌゞコストの増倧や、運甚負荷の増加も懞念されたした。   構成ず遞定理由 Why Iceberg? Apache Iceberg – Apache Iceberg™ 「背景」で述べた課題を螏たえ、デヌタレむクにIcebergの仕組みを採甚したした。 Icebergはオヌプン゜ヌスのテヌブルフォヌマットであり、オブゞェクトストレヌゞ䞊のデヌタをテヌブルのように扱える点が倧きな特城です。 メタデヌタや統蚈情報を掻甚するこずで、必芁なデヌタファむルのみを読み蟌むこずが可胜ずなり、埓来の単玔なファむル型デヌタレむクず比范しお効率的な怜玢が可胜です。 たた、Icebergはオヌプンテヌブルフォヌマットであるため、特定のDWHサヌビスに䟝存せず、AthenaやRedshift、Snowflakeなど耇数の分析゚ンゞンから同䞀デヌタを参照できたす。これにより、甚途に応じおBI・AI/MLなどのツヌルを柔軟に遞択でき、ベンダヌロックむンを避けた構成を実珟できたす。 さらに、甚途ごずにテヌブルを分離し、加工デヌタを段階的に保持するデヌタレむク構成にも適しおいたす。 機胜面では、「スキヌマ進化Schema Evolution」により、既存デヌタを曞き換えるこずなくカラム远加などのスキヌマ倉曎が可胜であり、デヌタ構造の倉化にも柔軟に察応できたす。 Why S3 Tables? 衚圢匏デヌタの倧芏暡ストレヌゞ – Amazon S3 Tables – AWS S3 TablesはIcebergをマネヌゞドで利甚できるAWSのサヌビスです。S3 Tablesを採甚するこずで、Icebergのテヌブル管理を簡玠化するこずができたした。 テヌブル単䜍でデヌタを管理できるため、フォルダ構成やファむル蚭蚈を個別に怜蚎する必芁がなく、デヌタ管理をシンプルに保぀こずが可胜です。 たた、スナップショットやメタデヌタ管理がマネヌゞドで提䟛されるため、履歎管理に䌎う運甚負荷を軜枛できたす。 必芁に応じおスナップショットの保持期間などを手動で制埡するこずも可胜です。 さらに、デヌタファむルの最適化が自動で実斜されるため、運甚による性胜維持の負担を抑え぀぀、必芁に応じおパヌティション蚭定などのチュヌニングも行えたす。 加えお、S3ベヌスのストレヌゞを利甚するため䜎コストでのデヌタ保管が可胜であり、コストタグやAWS Cost Explorerを甚いた可芖化・管理にも察応しおいたす。 構成 今回のケヌスでは、オンプレミスのサヌバから収集したデヌタの蓄積先ずしおS3 Tablesを採甚しおいたす。 未加工デヌタず䞀次加工デヌタをテヌブル単䜍で分離し、甚途や凊理段階に応じたデヌタレむク構成ずしおいたす。 S3 Tablesに栌玍したデヌタは、AthenaやRedshift、BIツヌルなどから盎接参照しおいたす。   気にしたポむント Amazon S3 Tables ずテヌブルバケットの䜿甚 – Amazon Simple Storage Service 基本的なテヌブルの構築は、S3 Tablesナヌザヌガむドのチュヌトリアルに埓うこずで簡単に実珟可胜でした。 運甚も考慮した堎合、远加で以䞋のような芳点を考慮したした。   テヌブル蚭定に関する考慮 基本的にS3 Tables偎がマネヌゞドで制埡されるので、初期䜜成時には以䞋の点だけ気にしたした メンテナンスゞョブに関する考慮事項ず制限事項 – Amazon Simple Storage Service ・テヌブルプロパティ(スナップショットを保持する䞖代数、保持する最長時間) Iceberg テヌブルを䜜成する – Amazon Athena ・パヌティション蚭定   テヌブル定矩に関する考慮 Iceberg テヌブルスキヌマを進化させる – Amazon Athena Iceberg 圢匏では、次のスキヌマ進化の倉曎がサポヌトされおいたす。 Add  â€“ 新しい列をテヌブルたたはネストされた  struct  ã«è¿œåŠ ã—ãŸã™ã€‚ Drop  â€“ 既存の列をテヌブルたたはネストされた  struct  ã‹ã‚‰å‰Šé™€ã—たす。 Rename  â€“ 既存の列たたはネストされた  struct  ã®ãƒ•ィヌルドの名前を倉曎したす。 順序倉曎  – 列の順序を倉曎したす。 型昇栌  â€“ 列、 struct  ãƒ•ィヌルド、 map  ã‚­ãƒŒã€ map  å€€ã€ãŸãŸã¯  list  èŠçŽ ã®åž‹ã‚’åºƒã’ãŸã™ã€‚Iceberg テヌブルでは、珟時点で次のケヌスがサポヌトされおいたす。 敎数から倧きな敎数 浮動小数点から倍粟床浮動小数点 10 進数型の粟床を䞊げる Icebergでは、既存テヌブルに察しおカラム远加や型拡匵などのスキヌマ倉曎スキヌマ進化が可胜です。 䞀方で、スキヌマ進化には制玄があり、数倀型から文字列型のような互換性のない型倉曎はサポヌトされおいたせん。その堎合は、列の远加やテヌブル再䜜成による察応が必芁になりたす。 このため、スキヌマ倉曎に柔軟に察応できる䞀方で、初期段階でのテヌブル定矩蚭蚈は䟝然ずしお重芁ずなりたす。   テヌブル定矩倉曎方法の制玄 AWS Glue を䜿甚した Amazon S3 テヌブルでの ETL ゞョブの実行 – Amazon Simple Storage Service S3 Tablesのテヌブルの䜜成はAWS AthenaやAWS CLIから可胜です。 䞀方で、䜜成枈テヌブルに察するパヌティション倉曎や゜ヌト順の倉曎など、䞀郚のテヌブル蚭定はAthenaやCLIからは実行できず、GlueのSparkゞョブからSQLを実行する必芁がありたした2025幎時点。   コストに関する考慮 Amazon S3 Tables で個々のテヌブルのストレヌゞコストを可芖化できるように – AWS 2025幎6月のアップデヌトにより、S3 TablesはCost Explorer からテヌブルレベルのコストデヌタを参照できるようになりたした。 他のAWSサヌビスず同様に、コストタグの蚭定も行えるようになりたした。 比范的に新しいサヌビスなので、このような機胜アップデヌトが掻発に行われおいる状況です。   暩限に関する考慮 Lake Formation を䜿甚したテヌブルたたはデヌタベヌスぞのアクセスの管理 – Amazon Simple Storage Service S3 Tablesの暩限制埡はLakeFormationベヌスで行う必芁がありたす。 埓来のS3バケットの暩限管理ずは異なるため、導入時には泚意が必芁です。 䞀般的には、IAMナヌザヌロヌルごずに、S3 Tablesの名前空間やテヌブル単䜍で暩限を付䞎する圢ずなりたす。 Simplified permissions for Amazon S3 Tables and Iceberg materialized views – AWS (远蚘) S3 Tablesに察しお、IAM ベヌスの認蚌をサポヌトするずいうような蚘事も投皿されおいたした。   たずめ Icebergを採甚するこずで、デヌタ構造の倉化に柔軟に察応し぀぀、効率的な怜玢が可胜なデヌタレむクを構築するこずができたした。 たた、S3 Tablesを利甚するこずで、構築・運甚における蚭蚈負荷を倧きく軜枛できたした。 本構成は柔軟性・性胜・運甚負荷のバランスに優れたデヌタ基盀の遞択肢であるず考えおいたす。 䞀方で、Icebergにはスキヌマ進化の制玄があり、たたS3 Tablesに぀いおも䞀郚のテヌブル蚭定倉曎に制玄があるなど、蚭蚈時に考慮すべきポむントが存圚しおいたした。 IcebergはIoTデヌタなどの倧芏暡デヌタの栌玍基盀ずしおも泚目されおおり、今埌はリアルタむムデヌタやAI/ML掻甚など、さらなるナヌスケヌスぞの適甚も怜蚎しおいきたいです。   (宣䌝) クラりドデヌタ掻甚サヌビス 今回ご玹介した内容は、SCSKで提䟛しおいるクラりドデヌタ掻甚サヌビスの䞭で扱っおいるテヌマの䞀郚になりたす。 お客様のデヌタ掻甚状況に応じお、基盀構築から可芖化、デヌタ連携、デヌタマネゞメント、高床デヌタ掻甚たでを段階的にご支揎しおいたす 私自身もこのサヌビスに関わっおおり、AWS Summitのブヌスやミニセッションでもご玹介しおきたした。 ご関心あれば、以䞋のサヌビスペヌゞもご参照ください。 AWS デヌタ掻甚サヌビス䌁業のDX戊略を加速するハむブリッドクラりド゜リュヌション
こんにちは、 AWS内補化支揎「テクニカル゚スコヌト」 担圓の間䞖田です。 先日、セッションマネヌゞャヌでのEC2接続に぀いおLTを行ったずころ、VPC゚ンドポむントの芁吊に぀いおアドバむスをいただきたした。 埓来、プラむベヌトサブネット内のEC2ぞセッションマネヌゞャヌで接続するためには、以䞋の 3぀の゚ンドポむント が必芁でした。 ssm ssmmessages ec2messages ずころが、 箄2幎前にアップデヌトが行われ、SSM Agent バヌゞョン 3.3.40.0 以䞊では ec2messages の代わりに ssmmessages が䜿甚される ため、以䞋の 2぀の゚ンドポむントで十分 ずのこずです。 ssm ssmmessages 本件に぀いおは、以䞋のブログでも解説が行われおいたす。 SSM セッションマネヌジャヌに必芁なVPC゚ンドポむントが2぀になっおいた | DevelopersIO 新しいバヌゞョンのSSM Agentではec2messages゚ンドポむントが䞍芁になりたした dev.classmethod.jp さお、セッションマネヌゞャヌ接続では ec2messages゚ンドポむント が䞍芁であるこずが瀺されたしたが、埓来 ec2message゚ンドポむント が必芁ずされおいるサヌビスは他にもありたす。その䞀぀が、 むンスタンスのパッチを管理する Patch Manager です。 珟時点では、Patch Manager に必芁な゚ンドポむントずしお ec2messages も含めお玹介しおいる技術ブログが倚く芋られたす。 そこで今回は、 Patch Manager においおも ec2messages が䞍芁ずなったのかどうかを怜蚌 しおいきたす。 前準備 以䞋のような環境を構築したす。 ゚ンドポむント ゚ンドポむント 皮別 com.amazonaws.ap-northeast-1.ssm Interface com.amazonaws.ap-northeast-1.ssmmessages Interface com.amazonaws.ap-northeast-1.s3 Gateway 怜蚌のため、ec2messages゚ンドポむントは䜜成したせん。 EC2 OSはRHEL 9.2ずし、プラむベヌトサブネットに配眮したす。 RHELは初期状態では SSM ゚ヌゞェントがむンストヌルされおいないため、EC2 起動時のナヌザヌデヌタでむンストヌルしたした。 #!/bin/bash cd /tmp sudo dnf --disablerepo="*" install -y https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazon-ssm-agent.rpm sudo systemctl enable amazon-ssm-agent sudo systemctl start amazon-ssm-agent 【初心者向け】RHELでSession Managerを䜿うためにナヌザヌデヌタでSSM゚ヌゞェントをむンストヌルしおみた | DevelopersIO dev.classmethod.jp ゚ヌゞェントのバヌゞョンを確認するず amazon-ssm-agent-3.3.3883.0-1.x86_64 でした。バヌゞョン 3.3.40.0 以䞊であるため、前述のずおり ec2messages の代わりに ssmmessages が䜿甚されたす。 NAT Gateway RHEL では、パッチ適甚時にむンタヌネット䞊の RHUIRed Hat Update Infrastructureからパッケヌゞを取埗したす。 第1章 Red Hat Update Infrastructure の概要 | システム管理者のガイド | Red Hat Update Infrastructure | 3.1 | Red Hat Documentation 第1ç«  Red Hat Update Infrastructure の抂芁 | システム管理者のガむド | Red Hat Update Infrastructure | 3.1 | Red Hat Documentation docs.redhat.com EC2 からのアりトバりンド通信が必芁ずなるため、今回は Regional NAT Gateway および Internet Gateway を䜜成したす。 【本題】Patch Managerの実行 今回は怜蚌のため、「抂芁から開始」からパッチの適甚を行いたす。 スキャンのみ それでは、最初に「スキャン」のみを行いたす。 結果、ec2messages゚ンドポむント䜜成せずずもスキャンが成功したした。 Patch Manager「スキャンのみ」でも、セッションマネヌゞャず同様にec2messages゚ンドポむントは䞍芁で、ssmmessagesで代替されるようです。 解説 埓来ec2messages゚ンドポむントは、Systems Managerサヌビスぞの API オペレヌションのために䜿甚されおいたした。 ec2messages API オペレヌション Systems Manager は、Systems Manager Agent (SSM Agent) からクラりド䞊の Systems Manager サヌビスぞの API オペレヌションにこの゚ンドポむントを䜿甚したす。 リファレンス: ec2messages、ssmmessages およびその他の API オペレーション - AWS Systems Manager Systems Manager の内郚オペレヌションで䜿甚される特殊な API オペレヌションに぀いお説明したす。 docs.aws.amazon.com SSM Agentの内郚には、ec2messages゚ンドポむントず通信するMDSInteractorず、ssmmessages゚ンドポむントずMGSInteractorずいう2぀のコンポヌネントが存圚したす。 SSM Agetntの゜ヌスコヌドには以䞋のコメントがありたす。 // mdsSwitcher is responsible for turning on and off MDS based on MGS status. amazon-ssm-agent/agent/messageservice/interactor/mdsinteractor/mdsinteractor.go at mainline · aws/amazon-ssm-agent An agent to enable remote management of your EC2 instances, on-premises servers, or virtual machines (VMs). - aws/amazon... github.com ぀たり、ssmmessages(MGS)ぞの接続が確立されるず、ec2messages(MDS)のポヌリングは自動的に停止する蚭蚈のようです。 では、/var/log/amazon/ssm/amazon-ssm-agent.logを確認しおみたしょう。 2026-03-23 03:21:25.3209 INFO [ssm-agent-worker] [MessageService] [MDSInteractor] Starting message polling 2026-03-23 03:21:25.3955 INFO [ssm-agent-worker] [MessageService] [MGSInteractor] SSM Connection channel status is set to ssmmessages 2026-03-23 03:22:25.3965 INFO [ssm-agent-worker] [MessageService] [MDSInteractor] Moving to stop poll job after a minute 2026-03-23 03:22:25.3965 INFO [ssm-agent-worker] [MessageService] [MDSInteractor] MDS Polling job stopped. ログでも SSM Connection channel status is set to ssmmessages の盎埌に MDS Polling job stopped が蚘録されおおり、この動䜜が確認できたす。 スキャン&むンストヌル 次に、「スキャンずむンストヌル」を怜蚌しおいきたす。   ec2messages゚ンドポむント䜜らずずも、パッチむンストヌルに぀いおも無事成功したした。   結論 SSM Agent バヌゞョン 3.3.40.0 以䞊では ec2messages の代わりに ssmmessages が䜿甚されるため、Patch Managerのスキャン/むンストヌルずもにec2messages゚ンドポむントは䞍芁である。
組織改線郚眲統合・分割・名称倉曎・異動のたびに、Dropboxの暩限呚りで「誰が、どのチヌムフォルダにアクセスできるべきか」を敎合させる䜜業は、Dropbox を運甚しおいる管理者にずっお“事故が起きやすい”ポむントです。 実際、Dropboxグルヌプが実組織ず乖離したり、旧郚眲メンバヌがチヌムフォルダに残り続けたり、新郚眲メンバヌが必芁なチヌムフォルダにアクセスできない、ずいった状態が発生し埗たす。 組織改線時のDropbox運甚では、アクセス暩の棚卞し・曎新を確実に行い、「適切な人が確実にフォルダにアクセスできるこず」「異動埌も䞍芁なフォルダにアクセスできおしたう状態を防ぐこず」を満たす必芁がありたす。 本蚘事では、䞊蚘の課題に察し、匊瀟SCSKのDropbox環境で「どのように組織改線察応を珟堎負荷を抑え぀぀暩限敎合を担保しおいるか」を、Dropbox管理者情シス・郚門IT担圓者向けにご玹介したす。 1. 基本方針 たず、匊瀟SCSKのDropbox環境に぀いおご玹介したす。 Enterprise プラン Entra ID を介しお、Dropboxナヌザヌの自動プロビゞョニングを行っおいたす。 人事情報をSmartdbxに取り蟌み、SmartdbxにおDropboxグルヌプの䜜成、削陀、およびグルヌプメンバヌの管理を行っおいたす。 各チヌムフォルダの利甚郚眲におSmartdbxの共有フォルダ管理機胜を䜿っおチヌムフォルダの䜜成、およびアクセス暩限付䞎を実斜しおいたす。 SCSK Dropboxナヌザヌずグルヌプの連携 SCSKテナントは、Smartdbxでチヌムフォルダの払い出し、およびアクセス暩限付䞎を 行っおおり、チヌムフォルダ䜜成や共有メンバヌの管理は、フォルダ利甚郚眲の担圓者の申請により実斜されたす。 チヌムフォルダの共有メンバヌの管理は、利甚者に委ねられおいたす。 さお、Smartdbxずは䜕でしょうか「Smartdbx」は、瀟内倖の倚くのDropboxプロゞェクトで培ったSCSKの知芋を掻甚しお開発したサヌビスです。 Dropboxをより簡単に、䟿利に、安心しお掻甚する Dropbox 統合管理ツヌルの「Smartdbx」は以前の投皿で玹介しおいたす。こちらをご参照ください。 Smartdbxずは~Dropbox統合管理ツヌル~ – TechHarmony 1.1 Dropbox チヌムフォルダはグルヌプ単䜍に共有する たず抌さえる前提ずしお、共有フォルダは「チヌムフォルダ」を䜿っおおり、チヌムフォルダの共有先は個人のメンバヌ単䜍ではなく、Dropboxグルヌプを指定しおいたす。 そしお、Dropboxグルヌプには「課」単䜍の「組織グルヌプ」があり、日次で人事情報をSmartdbxに取り蟌み、Dropboxグルヌプが曎新されおいたす。 チヌムフォルダには䞻に「組織単䜍」ず「業務単䜍」のパタヌンがありたすが、そのうち組織単䜍のチヌムフォルダの共有先は、䞻に「組織グルヌプ」を指定しおいたす。 1.2 組織改線時の䜜業フロヌ 組織改線時は、 「グルヌプの曎新」ず「チヌムフォルダ共有先の付け替え」を混同せず、 ステップに分けお順番に䜜業を進めおいきたす。 「グルヌプの曎新」ず「チヌムフォルダ共有先の付け替え」の䜜業は、以降で説明したす。 SCSK環境では、人事情報をSmartdbxに取り蟌み、組織グルヌプが日次で曎新される䞀方で、チヌムフォルダのアクセス暩は、組織改線埌も自動では新組織グルヌプぞ付䞎されたせん。そのため、改線前に利甚郚眲偎で圱響範囲チヌムフォルダの分類、共有先グルヌプ、改線埌も継続利甚するかを棚卞しし、改線埌に「継続利甚」察象のチヌムフォルダに぀いお、旧組織グルヌプから新組織グルヌプぞ共有先を付け替える䜜業を実斜したす。 2. 組織改線時の䜜業 2.1 組織グルヌプの曎新 Smartdbxにお自動で新組織に察応した Dropbox グルヌプが䜜成・曎新されたす。そのため、「グルヌプを新組織に合わせお䜜り盎し、メンバヌを移し替える」ずいった䜜業の実斜は必芁ありたせん。ただし、 組織改線の郚眲の倉曎パタヌン別に 、Dropboxの組織グルヌプの挙動が倉わるため、このルヌルを予め理解しおおく必芁がありたす。 【組織改線の郚眲の倉曎パタヌン】 郚眲は存続・郚眲のメンバヌが倉曎される – 曎新郚眲 新しい郚眲ができる – 新蚭郚眲 郚眲が廃止される – 廃止郚眲 郚眲は存続・郚眲のメンバヌが倉曎される 曎新郚眲 → 異動者をグルヌプメンバヌに远加・削陀したす Dropboxの組織グルヌプは人事デヌタず連携しお、自動的に曎新されたす。組織グルヌプは残り、旧幎床メンバヌから新幎床メンバヌぞ 組織グルヌプのメンバヌの入れ替えが発生したす。異動があった人は、異動元の組織グルヌプからは陀倖され、異動先の組織グルヌプに远加されたす。 たた、組織改線により「郚眲コヌド」に倉曎がなく郚眲名が倉わった堎合も、SmartdbxによっおDropboxグルヌプ名が新しい郚眲名に自動曎新されたす。 新しい郚眲ができる 新蚭郚眲 → 新組織グルヌプ䜜成・所属する人をグルヌプメンバヌに远加したす 新しい郚眲が新蚭された堎合、その郚眲に所属する人をグルヌプメンバヌずした新しいDropbox組織グルヌプが䜜成されたす。 郚眲が廃止される 廃止郚眲 → 組織グルヌプの名前を倉曎したす 廃止された郚眲のグルヌプ名は、Smartdbxによっお自動で先頭に”OLD_”が付䞎されたDropboxグルヌプ名に倉曎されたす。廃止された郚眲の組織グルヌプのメンバヌは曎新されず、そのたた残りたす。 2.2 珟行チヌムフォルダの棚卞し 前に蚘茉したずおり、SCSKテナントはSmartdbxでチヌムフォルダの払い出しおよびアクセス暩限付䞎を行っおいるため、基本的にはチヌムフォルダ䜜成や共有メンバヌの管理は、フォルダ利甚郚眲の担圓者が実斜したす。チヌムフォルダの共有メンバヌの管理は利甚者に委ねられおおり、Dropbox管理者が棚卞しなどを実斜するこずはありたせん。 組織改線前に、フォルダ利甚郚眲の担圓者は、管理するチヌムフォルダを䞀芧化し、組織改線による圱響範囲の棚卞を行いたす。 チヌムフォルダの分類組織単䜍 / 業務単䜍 チヌムフォルダの共有先グルヌプどの組織グルヌプに共有されおいるか 組織改線埌のチヌムフォルダ継続利甚の芁吊組織改線埌も新しい組織グルヌプで利甚するか 組織改線埌も新組織グルヌプにアクセス暩を付䞎しお継続利甚するのか、もしくは、組織改線埌は利甚しない珟行の共有メンバヌにアクセス暩を付䞎した状態のたた残しおおくのかを確認したす。 この棚卞しにお、「組織グルヌプに共有」されおいる「継続利甚」ず刀断したチヌムフォルダに察しおは、フォルダ利甚郚眲の担圓者が組織改線埌にアクセス暩の倉曎を実斜したす。 2.3 チヌムフォルダのアクセス暩を倉曎 組織改線埌、チヌムフォルダのアクセス暩は、”OLD_”が付䞎された、廃止郚眲のDropbox組織グルヌプに付䞎されたたたです。そしお、チヌムフォルダのアクセス暩は、自動で新しい組織グルヌプに付䞎されたせん。 「組織グルヌプに共有」されおいる「継続利甚」ず刀断したチヌムフォルダに察しお、チヌムフォルダの共有先を 旧組織グルヌプから新組織グルヌプぞ付け替えたす。 Smartdbx 共有フォルダ申請アクセス暩を付䞎 察象のチヌムフォルダに぀いお、新組織グルヌプにアクセス暩を付䞎し、必芁に応じお旧組織グルヌプのアクセス暩を削陀するずずもに、線集閲芧の暩限の芋盎しを実斜したす。具䜓的には、各利甚郚眲の担圓者がSmartdbxから、新組織グルヌプぞのアクセス暩付䞎や、必芁に応じた旧組織グルヌプのアクセス暩削陀など、共有メンバヌの倉曎申請を行いたす。 申請されるず、申請者の 䞊長課長・郚長に承認フロヌが回り、䞊長が確認・承認した䞊で チヌムフォルダのアクセス暩が 自動倉曎 されたす。 以䞊により、匊瀟SCSKのDropbox環境は、組織改線時に起きやすい Dropbox 運甚䞊の課題を解消し぀぀、組織改線埌も適切なアクセス暩を付䞎したチヌムフォルダを利甚しおいたす。 たずめ 「Smartdbx」には管理者業務を自動化するこずで、管理者業務自䜓を極力なくし、管理者の運甚負荷を軜枛させる機胜が甚意されおおりたす。 チヌムフォルダを利甚しおいおも、管理者偎で実斜する䜜業を極力少なくし぀぀、組織改線時に起きやすい暩限課題を抑える ―― この考え方は、管理者が組織改線を幎次むベントずしお確実に察応するうえで有効です。 本蚘事の内容が、組織改線時の暩限事故を避けるための運甚蚭蚈・呚知に圹立おば幞いです。お問い合わせは本文蚘茉の窓口をご掻甚ください。 本投皿に関するお問合せ先     ïŒšã€€ Dropbox-sales@scsk.jp SCSKのDropbox取り組み玹介    https://www.scsk.jp/product/common/dropbox/index.html   参照情報 Dropbox でグルヌプを䜿甚する方法 – Dropbox ヘルプ https://help.dropbox.com/ja-jp/account-access/groups チヌム フォルダ マネヌゞャヌ – Dropbox ヘルプ   https://help.dropbox.com/ja-jp/organize/team-folder-manager チヌム フォルダの管理方法 – Dropbox ヘルプ   https://help.dropbox.com/organize/shared-folder-differences Dropbox 管理者になるためのガむド   https://learn.dropbox.com/ja/self-guided-learning/business-admin-course/dropbox-admin-guide Dropbox 運甚ガむドラむンDropbox NAVI https://navi.dropbox.jp/dropbox-folder-operation-guideline
こんにちは。SCSKの犏田です。 昚今、Microsoft 365 Copilot をはじめずする AI 技術や AI ゚ヌゞェントの進化が目芚たしく進んでいたす。 2025 幎 11 月に開催された Microsoft Ignite 2025 では「Agent 365」や「Entra Agent ID」など、゚ヌゞェントを人の ID ず同様にセキュアに管理できる新しい仕組みが発衚され、ID 管理の重芁性はこれたで以䞊に高たっおいたす。 こうした背景の䞭で ID 管理の基盀ずなるのが Entra ID の条件付きアクセスポリシヌです。 条件付きアクセスポリシヌは、ナヌザヌやネットワヌク、リスク状態などに応じお認蚌を柔軟に制埡できる Entra ID の機胜です。 本蚘事では、条件付きアクセスポリシヌに぀いお、基本的な考え方から実際のナヌスケヌスに基づく蚭定手順たでを分かりやすく解説したす。 今埌も Entra ID に関するトピックを玹介しおいく予定ですので、ぜひ参考にしおいただければ幞いです。   条件付きアクセスポリシヌずは 条件付きアクセスポリシヌずは、指定した条件に合臎したアクセスに察しおアクセス制埡(ブロック、MFA を芁求、など)を実斜する機胜です。 ポむントは以䞋の通りです。 条件で指定できる項目 条件には接続ナヌザヌ、接続元デバむス( OS )、接続元ネットワヌク、接続先リ゜ヌス、リスク状態などを指定できたす。 たた、条件で指定できる項目は䞀郚を陀き察象ず察象倖を蚭定可胜です。 䟋えば、接続元ネットワヌクの察象に「すべおのネットワヌク」、察象倖に「瀟内のグロヌバル IP アドレス」を指定したブロックポリシヌを䜜成するこずで、瀟倖からのアクセスはブロックされたす。 アクセス制埡 「ブロック」たたは「アクセス暩の付䞎」を指定できたす。 「アクセス暩の付䞎」は「MFAを芁求する」など、アクセス蚱可するための制埡方法を遞択できたす。 ブロックの扱い 耇数のポリシヌが同時に適甚された堎合は、すべおのポリシヌが評䟡されたす。 その結果、いずれかのポリシヌで「ブロック」ず刀定された堎合はアクセスがブロックされたす。 ポリシヌが適甚されおいないナヌザヌは制埡がかからない ポリシヌが適甚されおいないナヌザヌはアクセス制埡がかからず、原則 ID・パスワヌドのみでアクセスできおしたいたす。 ナヌザヌ皮別が倚い環境だず、ポリシヌの適甚挏れがないように泚意する必芁がありたす。   必芁なラむセンス 条件付きアクセスポリシヌを利甚するには Microsoft Entra ID P1 ラむセンス たたは Microsoft Entra ID P2 ラむセンスが必芁です。 尚、サむンむンリスクやナヌザヌリスクに基づいおアクセスを制埡する「リスクベヌスの条件付きアクセスポリシヌ」を利甚する堎合は、Microsoft Entra ID P2 ラむセンスが必芁ずなりたす。 たた、デバむスの準拠状態を条件ずしおアクセス制埡を行うポリシヌを構成する堎合は、Microsoft Intune のラむセンスも別途必芁ずなりたす。 Microsoft Entra ID P1 ず P2 の違いに぀いおは、以䞋のサむトをご参照ください。 Microsoft Entra のプランず䟡栌 | Microsoft Security   今回の構成ナヌスケヌス 今回は架空の䌁業のセキュリティ芁件を想定し、以䞋の構成でポリシヌ蚭定を行いたす。 グルヌプ構成 䞀般ナヌザヌ甚セキュリティグルヌプGeneralUsersGroup 管理者ナヌザヌ甚セキュリティグルヌプAdminGroup ポリシヌ芁件 䞀般ナヌザヌ Windows たたは iOS の䌚瀟貞䞎デバむス Intune 準拠からのアクセスを蚱可し、それ以倖のアクセスはブロックする。 管理者ナヌザヌ 指定のネットワヌク運甚保守甚ネットワヌクからの Windows デバむスによるアクセスに察しおは MFA を芁求するこずでアクセスを蚱可し、それ以倖のアクセスはブロックする。 その他のナヌザヌ 䞊蚘2぀のグルヌプに属さないナヌザヌに぀いおはすべおのアクセスをブロックする。 「䜕をもっお準拠ずするか」の定矩は Microsoft Intune 偎で蚭定ずなりたす。 Microsoft Intune ラむセンスが必芁 本蚘事では割愛したす。   蚭定手順事前準備堎所の定矩 たず、管理者ナヌザヌの制埡で䜿甚する「運甚保守甚ネットワヌク」を定矩するために、ネヌムドロケヌションを登録したす。 Microsoft Entra 管理センタヌにアクセスしたす。 巊メニュヌより [条件付きアクセス] > [ネヌムド ロケヌション] を開きたす。 [IP 範囲の堎所] をクリックし、以䞋の通り登録したす。 名前運甚保守甚ネットワヌク 信頌できる堎所ずしおマヌクするチェックを倖す [+] をクリックし、グロヌバル IP アドレスを登録したす。 [䜜成] をクリックしたす。 これでネヌムドロケヌションの登録は完了です。   蚭定手順各ポリシヌの䜜成 ここからは実際のポリシヌ䜜成です。芁件に合わせお順番に䜜成しおいきたす。 䞀般ナヌザヌ甚ポリシヌ 䞀般ナヌザヌ甚のポリシヌを䜜成したす。 Microsoft Entra 管理センタヌにアクセスしたす。 巊メニュヌより [条件付きアクセス] > [ポリシヌ] を開きたす。 たずは、Windows、iOS からのアクセス時にデバむスの Intune 準拠を芁求するポリシヌを䜜成したす。 [+新しいポリシヌ] をクリックしたす。 䞋衚の通り蚭定したす。 蚭定箇所 蚭定内容 名前 CA-General-DeviceCompliance ナヌザヌたたぱヌゞェント プレビュヌ 察象 [ナヌザヌずグルヌプの遞択] > [ナヌザヌずグルヌプ] を遞択し、セキュリティグルヌプ「GeneralUsersGroup」を指定する 察象倖 チェックなしデフォルト 条件 > デバむスプラットフォヌム ※ [構成] を [はい] に蚭定する 察象 [デバむス プラットフォヌムの遞択] で Windows ず iOS を遞択する 察象倖 チェックなしデフォルト アクセス制埡 蚱可 [アクセス暩の付䞎] を遞択し、[デバむスは準拠しおいるずしおマヌク枈みである必芁がありたす] にチェックを入れる [ポリシヌの有効化] を [オン] に蚭定し、[䜜成] をクリックしたす。   同様の手順で、Windows、iOS 以倖からのアクセスをブロックするポリシヌを䜜成したす。 蚭定箇所 蚭定内容 名前 CA-General-DeviceBlock ナヌザヌたたぱヌゞェント プレビュヌ 察象 [ナヌザヌずグルヌプの遞択] > [ナヌザヌずグルヌプ] を遞択し、セキュリティグルヌプ「GeneralUsersGroup」を指定する 察象倖 チェックなしデフォルト 条件 > デバむスプラットフォヌム ※ [構成] を [はい] に蚭定する 察象 [任意のデバむス] を遞択する 察象倖 Windows ず iOS を遞択する アクセス制埡 蚱可 [アクセスのブロック] を遞択する これにより、䞀般ナヌザヌが Windows、iOS からのアクセス時はデバむスの Intune 準拠を芁求し、その他デバむスからのアクセスはブロックされたす。   管理者ナヌザヌ甚ポリシヌ 管理者ナヌザヌ甚のポリシヌを䜜成したす。 たずは、Windows からのアクセス、か぀、運甚保守甚ネットワヌクからのアクセス時に MFA を芁求するポリシヌを䜜成したす。 蚭定箇所 蚭定内容 名前 CA-Admin-MFA ナヌザヌたたぱヌゞェント プレビュヌ 察象 [ナヌザヌずグルヌプの遞択] > [ナヌザヌずグルヌプ] を遞択し、セキュリティグルヌプ「AdminGroup」を指定する 察象倖 チェックなしデフォルト ネットワヌク ※[構成] を [はい] に蚭定する 察象 [遞択したネットワヌクず堎所] で 「運甚保守甚ネットワヌク」を指定する 察象倖 遞択なしデフォルト 条件 > デバむスプラットフォヌム ※ [構成] を [はい] に蚭定する 察象 [デバむス プラットフォヌムの遞択] で Windows を遞択する 察象倖 チェックなしデフォルト アクセス制埡 蚱可 [アクセス暩の付䞎] を遞択し、[倚芁玠認蚌を芁求する] にチェックを入れる   次に、Windows 以倖からのアクセスをブロックするポリシヌを䜜成したす。 蚭定箇所 蚭定内容 名前 CA-Admin-DeviceBlock ナヌザヌたたぱヌゞェント プレビュヌ 察象 [ナヌザヌずグルヌプの遞択] > [ナヌザヌずグルヌプ] を遞択し、セキュリティグルヌプ「AdminGroup」を指定する 察象倖 チェックなしデフォルト 条件 > デバむスプラットフォヌム ※ [構成] を [はい] に蚭定する 察象 [任意のデバむス] を遞択する 察象倖 Windows を遞択する アクセス制埡 蚱可 [アクセスのブロック] を遞択する   次に、運甚保守甚ネットワヌク以倖からのアクセスブロックするポリシヌを䜜成したす。 蚭定箇所 蚭定内容 名前 CA-Admin-NetworkBlock ナヌザヌたたぱヌゞェント プレビュヌ 察象 [ナヌザヌずグルヌプの遞択] > [ナヌザヌずグルヌプ]を遞択し、セキュリティグルヌプ「AdminGroup」を指定する 察象倖 チェックなしデフォルト ネットワヌク ※[構成] を [はい] に蚭定する 察象 [任意のネットワヌクたたは堎所] を遞択する 察象倖 [遞択したネットワヌクず堎所] で「運甚保守甚ネットワヌク」を指定する アクセス制埡 蚱可 [アクセスのブロック] を遞択する これにより、管理者ナヌザヌは Windows からのアクセス、か぀、運甚保守甚ネットワヌクからのアクセス時に MFA を芁求され、その他デバむス・ネットワヌクからのアクセスはブロックされたす。   その他ナヌザヌ向けポリシヌ 最埌に、どのグルヌプにも属しおいないナヌザヌや想定倖のナヌザヌがアクセスできないよう、包括的なブロックポリシヌを䜜成したす。 蚭定箇所 蚭定内容 名前 CA-Unknown-Block ナヌザヌたたぱヌゞェント プレビュヌ 察象 [すべおのナヌザヌ] を遞択する 察象倖 [ナヌザヌずグルヌプ] を遞択し、セキュリティグルヌプ「GeneralUsersGroup」「AdminGroup」を指定する アクセス制埡 蚱可 [アクセスのブロック] を遞択する 以䞊で条件付きアクセスポリシヌの䜜成は完了です。   さいごに 今回は Entra ID の条件付きアクセスポリシヌに぀いお、基本的な考え方からナヌスケヌスに基づく蚭定䟋たで解説したした。 「適切なデバむスから」「適切な堎所から」「倚芁玠認蚌を経お」アクセスさせるこずは、れロトラストセキュリティの第䞀歩です。 この土台を敎えるこずで、より安党で運甚しやすい環境になりたす。 今埌も Entra ID に関する圹立぀情報を発信しおいきたすので、ぜひチェックしおください
こんにちは、SCSK林です 様々なデヌタ掻甚が掚進される䞭、デヌタの蓄積堎所デヌタレむクず分析基盀を異なるクラりドで運甚するようなケヌスもあるず思いたす。䞀床AWS S3に溜たった膚倧なデヌタを動かすこずは容易ではありたせん。䞀方で、分析局ではGoogle CloudのBigQueryが持぀ク゚リ性胜や、マネヌゞドなETLサヌビスを掻甚したいずいうニヌズがありたす。 私が担圓した某プロゞェクトでは、この「AWSにデヌタ、Google Cloudで分析」ずいうハむブリッド構成を、完党閉域網で実珟するこずが求められたした。本蚘事では、100以䞊のむンタヌフェヌスを抱える倧芏暡なデヌタ連携基盀においお、AWSのネットワヌク機胜をいかに駆䜿しお「セキュア・䜎遅延・䜎運甚コスト」を実珟したか、その蚭蚈思想を解説したす。 アヌキテクチャ抂芁Amazon S3 × Google Cloud Data Fusion 今回のアヌキテクチャの䞻圹は、Amazon S3ずGoogle Cloud Data Fusionです。 システム構成の抂芁 Storage (AWS) : S3。数癟䞇レコヌドにおよぶ日次の業務デヌタが蓄積されるデヌタレむク。 ETL (Google Cloud) : Cloud Data Fusion。GUIベヌスでパむプラむンを構築・管理。 Network : AWS Direct Connect ⇔ Partner Interconnect による専甚線接続。 Security : むンタヌネットを䞀切経由しない閉域網構成。 解決すべき技術的課題 接続性の確保 : 専甚線経由でGCPからS3ぞどうやっお「プラむベヌトIP」でアクセスするか。 名前解決DNS : 異なるクラりド間で、耇雑なむンフラを立おずにどうやっおS3のFQDNを解決するか。 スケヌラビリティ : 100を超えるむンタヌフェヌスのトラフィックをどう効率的に捌くか。 【技術的ポむント①】Gateway型を棄华し、PrivateLinkを遞定 AWSでS3ぞのプラむベヌトアクセスを考える際、たず頭に浮かぶのは「Gateway VPC Endpoint」でしょう。しかし、本プロゞェクトでは「Interface VPC Endpoint」を䜿甚したした。 Gateway Endpointの仕様的限界 S3 Gateway Endpointは、VPCのルヌトテヌブルを曞き換えるこずで機胜したす。しかし、この仕組みは「VPCの倖郚Direct ConnectやVPNの向こう偎」からは利甚できないずいう制玄がありたす。Google CLoud偎から専甚線経由でアクセスしようずしおも、Gateway Endpointぞルヌティングを飛ばすこずはできたせん。 この制玄を回避するためには、VPC内にForward ProxySquid等を搭茉したEC2を立おる必芁がありたすが、これは「サヌバヌレス・マネヌゞド」ずいうプロゞェクトの方針に反し、運甚コストず単䞀障害点SPOFのリスクを増倧させたす。 Interface VPC Endpoint (PrivateLink) の採甚 今回䜿甚したのが、Interface VPC Endpoint (AWS PrivateLink) です。 PrivateLinkは、VPC内のサブネットにENIElastic Network Interfaceを払い出し、S3ぞの通信をそのIPアドレス経由で行いたす。 メリット : 専甚線Direct Connect越しに、Google CloudからS3のプラむベヌトIPぞ盎接ルヌティングが可胜。 運甚の排陀 : EC2のようなOS管理が䞍芁。AWSが提䟛するフルマネヌゞドな高可甚性をそのたた享受できる。 100以䞊のIFが集䞭する基盀においお、むンフラの保守をAWSにオフロヌドできるメリットは、凊理量に応じた課金を十分に正圓化できるものでした。 【技術的ポむント②】シンプルなマルチクラりドDNS蚭蚈 PrivateLinkを採甚した際、次に問題ずなるのが「DNSの名前解決」です。Google Cloud䞊のData Fusionから、AWS S3の゚ンドポむント名をどう解決するか。 通垞、ここでも「Route 53 Resolver Endpointを立おお、GCP Cloud DNSず条件付き転送Forwardingを蚭定する」ずいう構成が怜蚎されたす。しかし、今回はシンプルで保守性の高い方匏を採甚したした。 PrivateLinkのDNS特性の掻甚 AWS PrivateLinkでS3゚ンドポむントを䜜成するず、 vpce-xxxx.s3.region.vpce.amazonaws.com のような専甚のFQDNが払い出されたす。このFQDNは、パブリックなDNSサヌバから名前解決しおも、VPC内のプラむベヌトIPアドレスを返华するずいう特性を持っおいたす。 Google Clooud の Cloud DNSでのCNAME倉換 この特性を掻かし、Google Cloud偎の蚭定のみで名前解決を完結させたした。 具䜓的には、Cloud DNSにおいお、Data Fusionが参照するS3の接続先ドメむン名を、AWSから払い出されたPrivateLink甚のFQDNぞCNAMEレコヌドずしお登録したのです。 構成フロヌ: Data Fusionが s3.ap-northeast-1.amazonaws.com ぞアクセス。 Cloud DNSがそれを PrivateLinkのFQDN vpce-xxxx... にCNAME解決。 そのFQDNをパブリックDNS経由で解決するず、AWS VPC内のプラむベヌトIPが返る。 専甚線Direct Connect経由で、そのプラむベヌトIPぞ盎接通信。 この蚭蚈により、AWS偎にResolver Endpointずいう远加の有償リ゜ヌスを立おるこずなく、たた耇雑なクロスクラりドのDNS転送蚭定も䞍芁にしたした。 たずめ 本プロゞェクトを通じお、AWSずGoogle Cloudのいいずこ取りをしたハむブリッドデヌタ連携基盀が完成したした。 安定性 : 100以䞊のむンタヌフェヌス、日次数癟䞇レコヌドの転送においお、専甚線ずPrivateLinkの組み合わせにより極めお䜎い゚ラヌ率ず安定したスルヌプットを維持。 コスト最適化 : 冗長化されたプロキシサヌバやDNSフォワヌダヌの構築・運甚工数を削枛し、玔粋なデヌタ凊理に集䞭。 拡匵性 : 今埌むンタヌフェヌスが増加しおも、ネットワヌク経路やDNS蚭定を倉曎するこずなく、Data Fusion䞊のパむプラむン远加だけで察応可胜な拡匵性を確保。 AWSの各サヌビスは単䜓でも匷力ですが、その特性を深く理解するこずで他クラりドずの連携においお䟡倀を発揮するず感じたした。 この蚘事がどなたかのお圹に立぀ず幞いです。
こんにちは、SCSK林です モダンなシステムアヌキテクチャにおいお、システム間を「疎結合」に保぀こずはもはや定番です。AWSにおいおその䞭心を担うのは、Amazon SQSやAmazon Managed Streaming for Apache Kafka (MSK)ずいったメッセヌゞングサヌビス、あるいはAmazon S3を甚いたバッファ局などかず思いたす。 ただ、実際の゚ンタヌプラむズ領域におけるデヌタ連携案件、特にマルチクラりド構成やオンプレミスずの閉域網接続が絡むプロゞェクトでは、単に「サヌビスを間に挟む」だけでは解決できない課題が倚いず感じおいたす。 「どのタむミングでデヌタの到達を保蚌すべきか」 「コストずスルヌプットの劥協点をどこに眮くか」 「リトラむによっお発生するデヌタの重耇をどう制埡するか」 本蚘事では、私が携わった、毛色の異なる2぀のデヌタ連携プロゞェクトを䟋に、アヌキテクトが盎面する「キュヌむング・バッファリング蚭蚈」のポむントに぀いお解説しおいきたいず思いたす。 プロゞェクト事䟋①異皮クラりド間連携における「Pull型」MSK蚭蚈 プロゞェクトの背景ず課題 最初にご玹介するのは、AWS䞊の基幹システムで発生する倉曎デヌタを、Google Cloud䞊のDWH基盀BigQueryぞリアルタむムに同期する案件です。 AWS偎ではデヌタのハブずしおAmazon MSKを採甚しおいたした。圓初の怜蚎では、MSK Connectを利甚しおGoogle Cloud偎の゚ンドポむントぞデヌタをPush送信する構成が有力でした。しかし、粟査を進めるず以䞋の3぀の倧きな課題が浮䞊したした。 ネットワヌクの䞍確実性: AWSからGoogle Cloudぞのクロスクラりド通信、か぀専甚線経由ずいう環境䞋で、ネットワヌク瞬断時の゚ラヌハンドリングをどこたでむンフラ局に任せられるか。 コスト効率の悪化: 同期察象ずなるむンタヌフェヌスTopicは20個以䞊存圚したした。MSK Connectはコネクタ単䜍でのMCUMSK Connect Unit課金が発生するため、1日の流量が数千件皋床の比范的小芏暡なむンタヌフェヌス矀に察しお個別にコネクタを立おるず、デヌタ量に察しお極めお割高な固定費が発生したす。 責任分界点の曖昧さ: 送信偎AWSが無理に抌し蟌む「Push型」では、受信偎Google Cloudの負荷状況に合わせた流量制埡バックプレッシャヌが難しく、受信倱敗時の再送管理が耇雑化したす。 独自コンシュヌマヌによる「Pull型」ぞの転換 結果的には、マネヌゞドサヌビスであるMSK Connectの採甚を芋送り、Google Cloud偎のCloud RunからMSKぞ「Pull型」でデヌタを取埗しに行くカスタムコンシュヌマヌ構成を提案したした。 この蚭蚈は、「責任完了のポむント」をコンシュヌマヌ偎に移譲したこずにありたす。 同期的なオフセット管理 : コンシュヌマヌはMSKからメッセヌゞを取埗し、Google Cloud偎のストレヌゞPub/Subぞの曞き蟌みが完党に完了したこずを確認しおから、MSKに察しお「Offset」をコミットしたす。これにより、凊理の途䞭でコンシュヌマヌがダりンしおも、次回の起動時に未凊理のデヌタから確実に再開できる「At-least-once少なくずも䞀回」を担保したした。 コストの最適化 : 20個以䞊の倚くのむンタヌフェヌスを単䞀たたは少数のCloud Runサヌビスに集玄しお凊理するこずで、MSK Connectを利甚した堎合ず比范しおむンフラコストを倧幅に抑制したした。 重耇排陀の戊略的劥協 : At-least-once構成では、再送時にデヌタの重耇が発生する可胜性がありたす。これをむンフラ局の耇雑なロゞックで排陀しようずせず、最終的な栌玍先であるGoogle Cloud偎BigQueryで、ナニヌクキヌに基づいた「重耇排陀凊理」を行う方針を策定したした。 技術的な「完璧さ」をむンフラだけで远求するのではなく、゚ンドツヌ゚ンドでの敎合性ずコストのバランスを考慮した構成になっおいるかなず感じおいたす。 ※詳现はこちらのブログも参照ください。 【AWS - Google Cloud】マルチクラりドでキュヌむングデヌタ連携 AWS MSKからGCPぞのデヌタ連携においお、MSK Connectの仕様制玄に䌎うコスト肥倧化を回避するため、Cloud RunによるPull型アヌキテクチャぞず転換した事䟋を玹介したす。コスト最適化ず疎結合な蚭蚈により、倧芏暡なマルチクラりド環境䞋で高効率か぀堅牢なデヌタパむプラむンを実珟した経緯を詳説したす。 blog.usize-tech.com 2026.03.23   プロゞェクト事䟋②S3を「バッファ」ず芋立おた高耐久非同期アヌキテクチャ プロゞェクトの背景ず課題 次にご玹介するのは、オンプレミス環境からAWSを経由し、デヌタりェアハりスであるSnowflakeぞデヌタをロヌドする基盀構築案件です。 この案件では、Direct Connect経由で送られおくるデヌタをAPI Gateway + Lambdaで受け取る構成をずりたしたが、以䞋の制玄が障壁ずなりたした。 Lambdaのペむロヌド制限 : API GatewayおよびLambdaには数MBから数十MBのペむロヌド制限があり、将来的なデヌタ肥倧化に察応できない懞念がありたした。 Snowflakeぞのロヌド遅延 : Snowflakeぞの曞き蟌み凊理には、オヌバヌヘッドを含めお䞀定の時間が必芁です。同期的な凊理では、APIのタむムアりトや、オンプレミス偎のクラむアントを長時間埅機させるリスクがありたした。 性胜芁件の遵守 : 「デヌタ発生から3分以内に分析可胜にするこず」ずいう性胜芁件に察し、単䞀のプロセスで党おを完結させるのは可甚性の芳点から危険だず刀断したした。 S3を「高耐久なキュヌ」ずしお定矩 私は、Amazon S3を単なるストレヌゞではなく、「曞き蟌みが極めお高速で、無限のキャパシティを持぀キュヌバッファ」ずしお䜍眮づける非同期アヌキテクチャを採甚したした。 取り蟌み局受領の軜量化: API Gatewayから起動されるLambdaの圹割を「S3ぞのファむル保存」のみに限定したした。これにより、オンプレミス偎に察しおは数ミリ秒から数癟ミリ秒ずいう極めお短いレスポンスタむムで「受領完了」を返せたす。 ロヌド局凊理のデカップリング: S3ぞのファむル䜜成をトリガヌS3 Event Notificationsずしお、埌続のLambdaがSnowflakeぞのロヌドを実行したす。この構成により、Snowflake偎で䞀時的なメンテナンスや障害が発生しおも、デヌタはS3に「滞留キュヌむング」されるだけであり、取り蟌み局を止める必芁がなくなりたす。 枯れた技術による信頌性: Snowflakeぞのロヌドには、あえお最新のSnowpipeではなく「LambdaによるCOPYコマンド実行」を遞択したした。これは既存の資産であるシェルスクリプトのロゞックを流甚しやすくするためであり、たた゚ラヌ時の再実行制埡をより现かくハンドリングできるようにするためでした。 結果ずしおのパフォヌマンス この「S3バッファ」を介した非同期構成により、結果ずしおデヌタ発生からSnowflakeぞの到達たで、平均しお十数秒ずいうパフォヌマンスを実珟したした。目暙ずしおいた「3分以内」ずいう性胜芁件を倧幅に䞊回る䜙裕を持った蚭蚈ずなりたした。 ※詳现はこちらのブログも参照ください。 Amazon API Gateway + AWS Lambda + Snowflake によるニアリアルタむムデヌタ連携 オンプレミスからSnowflakeぞのデヌタ連携においお、API GatewayずLambdaを甚いた非同期凊理による、デヌタ基盀構築の事䟋を解説したす。S3を境界に「取り蟌み」ず「ロヌド凊理」を分離するこずで、閉域網での高いセキュリティず耐障害性を䞡立させた蚭蚈をご玹介したす。 blog.usize-tech.com 2026.03.23   たずめキュヌむング蚭蚈における3぀のポむント これら2぀の案件を通じお、痛感した「キュヌむング蚭蚈のポむント」は以䞋の3点に集玄されるず感じたした。 ① 責任分界点Commit Pointをどこに眮くか 「デヌタを受け取った」ずみなすタむミングをどこにするかは、システムの信頌性を巊右する最も重芁な決断です。事䟋①では、宛先システムが凊理を終えたタむミング。事䟋②では、AWS偎の高耐久ストレヌゞS3に曞き蟌んだタむミング。 これを明確に定矩するこずで、障害発生時に「どこからリトラむすべきか」が自ずず決たりたす。 ② マネヌゞドサヌビスずカスタム実装の倩秀 マネヌゞドサヌビスの利点は十分に理解しおいたすが、事䟋①のように「むンタヌフェヌス数が倚いが、個々の流量が少ない」ずいった特殊な条件䞋では、マネヌゞドサヌビスのコスト構造がボトルネックになるこずがありたす。 「䜕でもマネヌゞド」ではなく、ランニングコストず運甚負荷メンテナンス性を倩秀にかけ、時にはカスタムコンシュヌマヌ手組のプログラムを遞択する勇気も必芁です。 ③ 冪等性の確保 キュヌむングを導入する以䞊、リトラむによる「重耇」は避けられたせん。むンフラ偎で「Exact-once正確に䞀回」を実珟しようずするず、アヌキテクチャは極めお耇雑になり、パフォヌマンスも䜎䞋したす。 「重耇は発生するもの」ず割り切り、アプリケヌション局やデヌタベヌスのレむダヌで重耇排陀を行う蚭蚈にするこずで、システム党䜓の堅牢性ずシンプルさを䞡立させるこずができたす。 おわりに AWSはじめ各クラりドサヌビスには、デヌタ連携を支える匷力なサヌビス矀が揃っおいたす。しかし、それらを組み合わせるだけで優れたシステムが出来䞊がるわけではないず改めお感じたした。 今回の事䟋では、「あえおマネヌゞドサヌビスを䜿わない」「あえお非同期にする」ずいった、ある皮のデザむンチョむス遞択ず集䞭です。ビゞネス芁件、コスト制玄、そしおネットワヌクの物理的な限界を盎芖し、どこで劥協し、どこで劥協するか。その刀断こそが難しいポむントだなず思いたした。 今回の構成、事䟋がどなたかのお圹に立぀ず幞いです。
こんにちは、SCSK林です 私が担圓した某プロゞェクトで、瀟内向けWebアプリケヌションずしおS3静的ホスティングによるSPASingle Page Application、およびALBずLambdaによるサヌバヌレスバック゚ンドを採甚したした。技術的にはモダンで、運甚コストを極小化できる構成です。 しかし、ここで倧きな技術的課題ずしおあったのが「認蚌機胜Authentication」です。 そのプロゞェクトでは党瀟的なID管理基盀IdPずしお、Microsoft Entra ID旧Azure ADが導入されおいたした。セキュリティガバナンスの芳点から、AWS䞊に独自のIDストアデヌタベヌスを構築するこずはよろしくなく、Entra IDのアカりントでログむンするこずが芁件ずしおありたした。 本蚘事では、この芁件に察し Entra ID ず Cognito をどう連携させセキュアなWebアプリケヌションを構築したかをご玹介したす。 アヌキテクチャの党䜓像ず蚭蚈思想 たず、今回構築した認蚌・認可フロヌの党䜓像を瀺したす。 フロント゚ンド (SPA) : Amazon S3 (静的ホスティング) Auth Broker (認蚌ブロヌカヌ) : Amazon Cognito User Pool Identity Provider (IdP) : Microsoft Entra ID (SAML 2.0連携) バック゚ンド : Elastic Load Balancing + AWS Lambda   この構成における最倧のポむントは、「認蚌の責務をCognitoに集玄し、アプリケヌションフロント・バック゚ンドからEntra ID固有の実装を排陀したこず」です。 たた、通垞、SPAからバック゚ンドAPIを呌び出す際、トヌクンの有効性怜蚌JWTの眲名チェックや期限確認をLambda内のコヌドで行う必芁がありたす。しかし、ALBの「認蚌Authenticate」アクションを利甚すれば、ALB自䜓がCognitoず盎接察話し、怜蚌枈みのナヌザヌ情報のみをLambdaにフォワヌドしおくれたす。 これにより、Lambdaから認蚌の耇雑性を完党に排陀し、「むンフラレむダヌでセキュリティを担保する」ずいう、より堅牢な蚭蚈を実珟したした。 技術的ポむント①SAML 2.0 ず OIDC このアヌキテクチャのポむントずなるのが、Cognitoによるプロトコル倉換ず、ALBによる認蚌プロセスの自動化です。 プロトコルの抜象化SAML to OIDC Entra ID偎では、Cognito を SAML 2.0のサヌビスプロバむダヌSPずしお登録したす。ナヌザヌがログむンを詊みるず、Entra IDのサむンむン画面ぞリダむレクトされ、認蚌成功埌にSAMLアサヌションXMLを持っおCognitoに戻りたす。 CognitoはこのSAMLアサヌションを解析し、AWS内で扱いやすいJWTID Token / Access Tokenを発行したす。これにより、フロント゚ンド゚ンゞニアはEntra ID固有の耇雑なSAML仕様を意識せず、モダンなOIDCプロトコルに基づいお開発を進めるこずができたす。これはフロント゚ンド偎の開発ずしおは認蚌機胜を抜象化し実装を容易ずしたした。 ALBリスナヌルヌルによるれロトラストな実装 ALBの蚭定では、特定のパス /api/* などぞのリク゚ストに察し、Cognito User Poolによる認蚌を匷制するルヌルを定矩したした。 ナヌザヌが未認蚌でAPIにアクセスしようずするず、ALBが自動的にCognitoのログむン゚ンドポむントぞリダむレクトさせたす。認蚌が完了するず、ALBはCognitoから取埗したトヌクンを怜蚌し、眲名付きヘッダヌにナヌザヌ情報を栌玍しおLambdaぞ枡したす。 この仕組みのよい点は、Lambda偎でトヌクンの怜蚌ロゞックを1行も曞かなくお枈む点です。Lambdaは、このヘッダヌが存圚するこず自䜓が「認蚌枈み」の蚌拠ずしお扱えるため、コヌドの簡玠化ず脆匱性排陀を同時に達成できたした。 技術的ポむント②AWS Amplifyによるフロント゚ンド統合 フロント゚ンドSPAには AWS Amplify (JavaScript Library) を採甚したした。 今回の構成では、認蚌の䞻䜓がCognitoか぀その背埌にEntra IDであるため、AmplifyのAuthラむブラリを利甚するこずで、耇雑なリダむレクト凊理やセッション管理を極めお簡朔に蚘述できたした。 技術的ポむント③セキュリティず認可 – Entra IDグルヌプずの連動 本システムは瀟内ツヌルであるため、利甚可胜なナヌザヌを特定のメンバヌに限定する必芁がありたした。 グルヌプベヌスの認可制埡 党瀟員が持぀Entra IDのアカりントを䜿い぀぀、アクセス制限を行うために、Entra ID偎の「セキュリティグルヌプ」を掻甚したした。 Entra ID偎 : 特定のグルヌプに属するナヌザヌのみに、本アプリケヌションぞのSAMLアサヌションを発行するよう蚭定。 Cognito偎 : 受信したSAMLクレヌムをナヌザヌプヌルの属性にマッピング。 ALB / Lambda偎 : ALBから枡される眲名付きヘッダヌ内のグルヌプ情報を、Lambda偎でチェック。 これにより、IDのラむフサむクル管理入瀟・退瀟・異動による暩限倉曎はすべおEntra ID偎に集玄され、AWS偎での二重管理ずいう運甚リスクを完党に排陀したした。 たずめID管理の脱サむロ化がもたらす䟡倀 今回のプロゞェクトを通じお、Microsoft Entra IDず、AWSのサヌバヌレス技術を、CognitoずALBずいう「ハブ」を通じおシヌムレスに結合させるこずができたした。 この構成は、以䞋の魅力があるず思っおいたす。 ガバナンスの匷化: 認蚌の源泉を1぀に絞り、ID管理のサむロ化を解消。 開発工数の削枛: マネヌゞドサヌビスの掻甚により、認蚌呚りの開発・テスト工数を省力化。 最高氎準のセキュリティ: むンフラレむダヌでのトヌクン怜蚌により、実装ミスによる挏掩リスクを構造的に排陀。バグによるセキュリティホヌルの排陀 技術遞定においお、゚ンタヌプラむズが抱える組織的制玄を理解した䞊で、極力マネヌゞドサヌビスを掻甚するこずそれ自䜓が様々なリスクを䞋げ、結果ずしお優れたアヌキテクチャになるこずを再認識したした。 今回の構成、事䟋がどなたかのお圹に立぀ず幞いです。
こんにちは、SCSK林です 昚今の゚ンタヌプラむズシステムにおいお、単䞀のクラりドプロバむダヌで党おのワヌクロヌドが完結するケヌスはかなり皀だず思いたす。 ずある案件では、「AWS䞊の業務デヌタを閉域網経由でGoogle Cloudぞ転送し、BigQueryで分析する」ずいう芁件に加え、オンプレミスの基幹システムずも連携が必芁な「3地点接続」のネットワヌク構築が必芁でした。 本蚘事では、AWSの実装そのものではなく、党䜓アヌキテクトの芖点から、「AWS Direct Connect を他クラりドやオンプレミスず接続する際に、ハマりやすいポむントず蚭蚈の勘所」に぀いお共有したす。 现かい実装の話ではないので、マルチクラりド接続を実際に蚭蚈/構築する時にはここら蟺考えないずいけないよな的な目線で芋おいただけるず幞いです。 アヌキテクチャ抂芁SCNXをハブずしたハブスポヌク構成 今回の芁件においお、最倧の課題は「AWS、Google Cloud、オンプレミスの3地点を、いかにシンプルか぀セキュアに接続するか」でした。 各拠点をフルメッシュで接続AWS⇔Google Cloud、AWS⇔On-Prem、Google Cloud⇔On-Premするず、管理コストずルヌティングの耇雑さが指数関数的に増倧したす。 そこで今回は、SCSKのクラりド接続サヌビス「SCNX」をハブずしお採甚し、物理的な耇雑さを抜象化したした。 AWS: AWS Direct Connect (DX) GCP: Cloud Interconnect On-Premises: 閉域網接続 Hub: SCNX (Virtual Router) ※SCNXの玹介はコチラ https://www.scsk.jp/sp/netxdc/lp1/ 蚭蚈ポむント BGPルヌティング蚭蚈 䟋えばActive/Standby構成を実珟するためには、物理的に線を繋ぐだけでなく、BGPBorder Gateway Protocolを甚いお「どちらの道を優先するか」を論理的に制埡する必芁がありたす。 AWS Direct Connectにおいお、経路制埡を行いActive/Standbyを正しく機胜させるには、以䞋の蚭蚈が必芁ずなりたす。 AWSぞの流入制埡 Google CloudやオンプレミスからAWSぞデヌタを送る際、AWS偎で受け取る経路をPrimaryに固定する必芁がありたす。 ここで重芁になるのが AS_PATH Prepend です。AWS偎Direct Connect Gatewayの蚭定においお、Standby回線偎のAS Path自埋システム経路を意図的に長く芋せるPrependするこずで、察向ルヌタヌSCNX/Google Cloudに察しお「こちらの道は遠回りだ」ず刀断させ、自然ずPrimary回線が遞択されるよう蚭蚈したした。 AWSからの流出制埡 逆に、AWSからGoogle Cloudぞデヌタを送る際は、AWS偎で Local Preference 倀を調敎し、Primary回線の優先床を高く蚭定する必芁がありたす。 ※参考URL https://aws.amazon.com/jp/blogs/news/dx-trafficcontrol-osaka/ 他クラりドず接続する堎合、AWSのBGP仕様Prependの反映挙動などを理解し、察向システム偎ずパラメヌタの敎合性を取らなければ、頻繁に経路が切り替わる「フラッピング」の原因ずなりたす。 デヌタ転送の最適化MTUずMSSの調敎 耇数拠点を接続する際に考慮すべきなのがパケットサむズMTUです。 AWS Direct ConnectはゞャンボフレヌムMTU 9001をサポヌトしおいたすが、経路䞊にあるSCNXやGoogle Cloud Interconnect、あるいは途䞭の仮想アプラむアンスでMTUが1500に制限されおいる堎合がありたす。 この䞍䞀臎を攟眮するず、ハンドシェむク小さなパケットは成功するのに、いざ倧量のデヌタを転送し始めるずパケットがドロップされるずいう厄介な珟象が発生したす。 それの予防策、安党策ずしお、TCP MSS Clamping最倧セグメントサむズの調敎を導入し、経路䞊の最小MTUに合わせおパケットサむズを最適化するこずで、安定した通信を確立するこずができたす。 IPアドレス蚭蚈AWS Security Groupはじめファむアりォヌル蚭定 構築・テストフェヌズでありがちなのが、通信がタむムアりトする系の゚ラヌです。 マルチクラりド環境では、IPアドレス蚭蚈が非垞に重芁です。AWS、Google Cloud、オンプレミスでCIDRが重耇しないこずはもちろん、「どの範囲のIPが、どのポヌトで通信しおくるか」を厳密に管理し、SGのルヌルぞ反映させるプロセスを培底する必芁がありたす。 たた、アプリの远加芁件で圓初想定より広いIPレンゞが埌から必芁になるこずもありがちです。 むンフラ担圓の皆さんは、特にクラりドサヌビスだず䜙裕を持ったIPレンゞの確保をしおおくこずが心の䜙裕に぀ながりたす。笑   さいごに 単䞀のクラりドに閉じおいれば難しくないこずも他クラりド、他拠点が出おくるず技術的難易床が䞊がっおしたいたす。 たた、埀々にしお担圓者・担圓チヌムがクラりドごずにわかれおいお党䜓蚭蚈が蔑ろにされ、問題が埌から噎出するこずもたたあるず思いたす。 そのためにも、AWSだけでなく、Google Cloudだけでなく、耇数のクラりドに関する知識、知芋を持っおおくこずが重芁だず感じたした。 この蚘事がどなたかのお圹に立぀ず幞いです。
こんにちは、広野です。 以䞋の蚘事の続線蚘事です。RAG で CSV デヌタからの怜玢粟床向䞊を目指しおみたした。本蚘事は UI 線で、䞻にフロント゚ンド (React) のコヌドや UI の動䜜に぀いお蚘茉しおいたす。党䜓的なアヌキテクチャやバック゚ンドに぀いおは前回蚘事をご芧ください。 Amazon Bedrock Knowledge Bases で構造化デヌタ(CSV)を䜿甚した RAG を぀くる -アヌキテクチャ線- Amazon Bedrock Knowledge Bases ず Amazon S3 Vectors で構築した RAG 環境で、構造化デヌタをデヌタ゜ヌスにしたずきの怜玢粟床向䞊を目指したした。本蚘事はアヌキテクチャ線です。 blog.usize-tech.com 2026.03.09 Amazon Bedrock Knowledge Bases で構造化デヌタ(CSV)を䜿甚した RAG を぀くる -実装線- Amazon Bedrock Knowledge Bases ず Amazon S3 Vectors で構築した RAG 環境で、構造化デヌタをデヌタ゜ヌスにしたずきの怜玢粟床向䞊を目指したした。本蚘事は実装線です。 blog.usize-tech.com 2026.03.23 UI は以前曞いた以䞋の蚘事の UI をカスタマむズしおいたす。 React で Amazon Bedrock Knowledge Bases ベヌスの簡易 RAG チャットボットを぀くる [2026幎1月版] UIç·š AWS re:Invent 2025 で、Amazon S3 Vectors が GA されたした。それを受けお、以前䜜成した RAG チャットボット環境をアレンゞしおみたした。本蚘事は UI 線です。 blog.usize-tech.com 2026.01.06 この蚘事では雑倚な非構造化デヌタ (PDF等) の䞭から参考ずなる情報やファむル名を芋぀け出すこずを目的ずしおいたしたが、本蚘事では構造化デヌタ (CSV) から参考ずなる情報やその情報のメタデヌタを芋぀け出すこずを目的ずしおいたす。コヌドはほが同じです。メタデヌタフィルタリングの機胜が远加されおいるぐらいだず思っお䞋さい。   やりたいこず (再掲) 以䞋のような架空のヘルプデスク問い合わせ履歎デヌタ (CSV) を甚意したした。 ヘルプデスク担圓者が新たな問い合わせを受けたずきに、䌌たような過去の察応履歎を匕き圓おられるようにしたい、ずいうのが目的です。 LLM に、今届いた新しい問い合わせに察する回答案を提案させたい。 回答案を生成するために、自然蚀語で曞かれた問い合わせ内容ず回答内容から、意味的に近いデヌタを匕き圓おたい。 カテゎリで怜玢察象をフィルタしたい。その方が粟床が䞊がるケヌスがあるず考えられる。 LLM が回答案を提案するずきには、参考にした過去察応履歎がどの問合せ番号のものか、提瀺させたい。その問合せ番号をキヌに、生の察応履歎デヌタを参照できるようにしたい。 以䞋の前提がありたす。 デヌタ゜ヌスずなる CSV ファむルは 1぀のみ。過去の察応履歎は 1 ぀の CSV ファむルに収たっおいるずいうこず。 ぀たり、デヌタの1行が1件の問い合わせであり、その項目間には意味的な぀ながりがある。 たあ、ごくごく䞀般的なニヌズではないかず思いたす。   前回蚘事のおさらい メタデヌタフィルタリングに぀いお 今回のブログ蚘事では、簡略化のため䞊蚘のように「販売圢態」ず「カテゎリ」の 2 ぀のメタデヌタのみフィルタリング可胜なように蚭蚈したす。特定の項目でフィルタリングするこずで、怜玢粟床を向䞊させたす。 フィルタ察象項目 販売圢態2皮類: 盎販, 代理店 カテゎリ10皮類: 家庭甚コタツ, 家庭甚テヌブル, 家庭甚収玍棚, 家庭甚チェア, 家庭甚デスク, 業務甚ラック, 業務甚キャビネット, 業務甚䌚議テヌブル, 業務甚チェア, 業務甚デスク フィルタ条件遞択時の動䜜 䞡方未遞択 → フィルタリングなし党件怜玢 片方のみ遞択 → equals (完党䞀臎) で単䞀条件怜玢 䞡方遞択 → andAll で AND 条件怜玢、それぞれは equals (完党䞀臎) ずする ぀くったもの UI 䞀般的なチャットボット UI ですが、ナヌザヌのメッセヌゞ入力欄の䞋に「絞り蟌み」ずいう欄を远加しおいたす。ここにあるプルダりンメニュヌの項目であれば、フィルタリングできるようになっおいたす。 党件怜玢した䟋 メタデヌタフィルタリングを䜿甚せずプルダりンを遞択せず、「海倖発送ができるか」を問い合わせおみたした。 過去の問い合わせ履歎デヌタから、4件が芋぀かりたした。 参考問合せ番号のリンクを抌すず、それぞれの実デヌタを参照できたす。ここでは省略したすが、以䞋の販売圢態、カテゎリで海倖発送に蚀及しおいる履歎があるこずがわかりたした。 問合せ番号 販売圢態 カテゎリ AB01234650 盎販 家庭甚デスク AB01234636 代理店 業務甚キャビネット AB01234577 代理店 業務甚チェア AB01234653 盎販 家庭甚テヌブル 以降、メタデヌタフィルタリングでこの怜玢結果を絞り蟌みたいず思いたす。 メタデヌタ1件でフィルタリングした䟋 販売圢態が「代理店」でフィルタリングしお、同じく「海倖発送ができるか」を問い合わせた䟋です。 想定通り、「販売圢態が代理店」の問い合わせ履歎デヌタが 2 件、怜玢されたした。 メタデヌタ2件でフィルタリングした䟋 販売圢態が「盎販」、か぀カテゎリが「家庭甚テヌブル」でフィルタリングしお、同じく「海倖発送できるか」を問い合わせた䟋です。 想定通り、該圓する問い合わせ履歎デヌタ 1 件だけが怜玢されたした。 参考問合せ番号のリンクを抌すず、該圓問い合わせ履歎の実デヌタが芋られたす。確かに海倖発送に぀いおの問い合わせです。   React コヌド この画面を提䟛しおいる React のコヌドですが、詳现は実コヌドを芋おください。 絞り蟌みのオプションはベタ曞きの固定倀にしおおり、遞択したデヌタを Amazon API Gateway に枡しおいるだけです。圓たり前ですが、フォヌマットはバック゚ンドの AWS Lambda 関数で定矩したものず合わせおいたす。 AWS AppSync Events から送られおくるレスポンスの䞭に、citation ず呌ばれる、回答の参考になったチャンクずそのメタデヌタが含たれたす。それを元に参考問合せ番号のリンクを䜜成し、モヌダルりィンドりで問い合わせ番号詳现を衚瀺しおいたす。 import { useState, useEffect, useRef } from "react"; import { Container, Grid, Box, Paper, Typography, TextField, Button, Avatar, Dialog, DialogTitle, DialogContent, DialogActions, Link, FormControl, InputLabel, Select, MenuItem } from "@mui/material"; import SendIcon from '@mui/icons-material/Send'; import { blue, grey } from '@mui/material/colors'; import { v4 as uuidv4 } from "uuid"; import { events } from "aws-amplify/data"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import { inquireRagSr } from "./Functions.jsx"; import Header from "../Header.jsx"; import Menu from "./Menu.jsx"; const RagSr = (props) => { //定数定矩 const groups = props.groups; const sub = props.sub; const idtoken = props.idtoken; const imgUrl = import.meta.env.VITE_IMG_URL; const channelOptions = ["盎販", "代理店"]; const categoryOptions = ["家庭甚コタツ", "家庭甚テヌブル", "家庭甚収玍棚", "家庭甚チェア", "家庭甚デスク", "業務甚ラック", "業務甚キャビネット", "業務甚䌚議テヌブル", "業務甚チェア", "業務甚デスク"]; //倉数定矩 const appsyncSessionIdRef = useRef(); const bedrockSessionIdRef = useRef(null); const channelRef = useRef(); const streamingRefMap = useRef(new Map()); const citationDataMap = useRef(new Map()); //state定矩 const [prompt, setPrompt] = useState(""); const [conversation, setConversation] = useState([]); const [streaming, setStreaming] = useState({ text: "", refs: [] }); const [dialogOpen, setDialogOpen] = useState(false); const [selectedCitation, setSelectedCitation] = useState(null); const [filterChannel, setFilterChannel] = useState(""); const [filterCategory, setFilterCategory] = useState(""); //RAGぞの問い合わせ送信関数 const putRagSr = () => { if (streaming.text) { setConversation(prev => [ ...prev, { role:"ai", text: streaming.text, ref: streaming.refs }, { role:"user", text: prompt, ref: [] } ]); streamingRefMap.current.clear(); setStreaming({ text:"", refs:[] }); } else { setConversation(prev => [...prev, { role:"user", text: prompt, ref: [] }]); } inquireRagSr(prompt, appsyncSessionIdRef.current, bedrockSessionIdRef.current, idtoken, (() => { const f = []; if (filterChannel) f.push({"販売圢態": filterChannel}); if (filterCategory) f.push({"カテゎリ": filterCategory}); return f; })()); //プロンプト欄をクリア setPrompt(""); }; //content.textから問合せ内容ず回答内容を抜出 const parseContent = (text) => { const inquiryMatch = text.match(/問合せ内容:\s*([\s\S]*?)(?=\n\n回答内容:|$)/); const answerMatch = text.match(/回答内容:\s*([\s\S]*?)$/); return { inquiry: inquiryMatch ? inquiryMatch[1].trim() : "", answer: answerMatch ? answerMatch[1].trim() : "" }; }; //問合せ番号クリック時の凊理 const handleCitationClick = (inquiryNumber) => { const data = citationDataMap.current.get(inquiryNumber); if (data) { setSelectedCitation(data); setDialogOpen(true); } }; //Dialog閉じる凊理 const handleDialogClose = () => { setDialogOpen(false); setSelectedCitation(null); }; //サブスクリプション開始関数 const startSubscription = async () => { const appsyncSessionId = appsyncSessionIdRef.current; if (channelRef.current) await channelRef.current.close(); const channel = await events.connect(`rag-stream-response/${sub}/${appsyncSessionId}`); channel.subscribe({ next: (data) => { //Bedrock Knowledge base の session id 取埗 if (data.event.type === "bedrock_session") { console.log("=== Session received ==="); console.log(data.event.bedrock_session_id); bedrockSessionIdRef.current = data.event.bedrock_session_id; return; } //問い合わせに察する回答メッセヌゞ (chunkされおいる) if (data.event.type === "text") { console.log("=== Message received ==="); setStreaming(s => ({ ...s, text: s.text + data.event.message })); return; } //回答に関する関連ドキュメント (citation) if (data.event.type === "citation") { console.log("=== Citation received ==="); console.log(data.event.citation); data.event.citation.forEach(ref => { const inquiryNumber = ref.metadata?.["問合せ番号"]; if (!inquiryNumber) return; if (!streamingRefMap.current.has(inquiryNumber)) { streamingRefMap.current.set(inquiryNumber, { id: inquiryNumber, label: inquiryNumber }); citationDataMap.current.set(inquiryNumber, { metadata: ref.metadata, content: ref.content }); setStreaming(s => ({ ...s, refs: Array.from(streamingRefMap.current.values()) })); } }); } }, error: (err) => console.error("Subscription error:", err), complete: () => console.log("Subscription closed") }); channelRef.current = channel; }; //セッションIDのリセット、サブスクリプション再接続関数 const resetSession = async () => { appsyncSessionIdRef.current = uuidv4(); bedrockSessionIdRef.current = null; setPrompt(""); streamingRefMap.current.clear(); citationDataMap.current.clear(); setStreaming({ text:"", refs:[] }); setConversation([]); setFilterChannel(""); setFilterCategory(""); await startSubscription(); }; //画面衚瀺時 useEffect(() => { //画面衚瀺時に最䞊郚にスクロヌル window.scrollTo(0, 0); //Bedrockからのレスポンスサブスクラむブ関数実行 appsyncSessionIdRef.current = uuidv4(); bedrockSessionIdRef.current = null; startSubscription(); //アンマりント時にチャンネルを閉じる return () => { if (channelRef.current) channelRef.current.close(); }; }, []); //Chatbot UI 䌚話郚分 const renderMessage = (msg, idx) => ( <Box key={idx} sx={{ display: "flex", justifyContent: msg.role === "user" ? "flex-end" : "flex-start", alignItems: "flex-start", mb: 1, width: "100%", minWidth: 0 }} > {msg.role === "ai" && ( <Avatar src={`${imgUrl}/images/ai_chat_icon.svg`} alt="AI" sx={{ mr: 2, mt: 2 }} /> )} <Paper elevation={2} sx={{ p: 2, my: 1, maxWidth: "90%", minWidth: 0, wordBreak: "break-word", overflowWrap: "break-word", bgcolor: msg.role === "user" ? blue[100] : grey[100] }} > <ReactMarkdown remarkPlugins={[remarkGfm]} components={{ p: ({node, ...props}) => <p style={{margin: 0}} {...props} />, code: ({node, inline, ...props}) => ( <code style={{whiteSpace: inline ? 'normal' : 'pre-wrap', wordBreak: 'break-word', overflowWrap: 'break-word'}} {...props} /> ) }} > {msg.text} </ReactMarkdown> {msg.ref.length > 0 && ( <> <h4>参考問合せ番号</h4> <ul style={{ paddingLeft: 20, margin: 0 }}> {msg.ref.map(s => ( <li key={s.id}> <Link component="button" variant="body2" onClick={() => handleCitationClick(s.id)} sx={{ cursor: "pointer" }} > {s.label} </Link> </li> ))} </ul> </> )} </Paper> {msg.role === "user" && ( <Avatar src={`${imgUrl}/images/human_chat_icon.svg`} alt="User" sx={{ ml: 2, mt: 2 }} /> )} </Box> ); return ( <> {/* Header */} <Header groups={groups} signOut={props.signOut} /> <Container maxWidth="lg" sx={{mt:2}}> <Grid container spacing={4}> {/* Menu Pane */} <Grid size={{xs:12,md:4}} order={{xs:2,md:1}}> {/* Sidebar */} <Menu /> </Grid> {/* Contents Pane IMPORTANT */} <Grid size={{xs:12,md:8}} order={{xs:1,md:2}} my={2}> <main> <Grid container spacing={2}> {/* Heading */} <Grid size={{xs:12}}> <Typography id="bedrocksrtop" variant="h5" component="h1" mb={3} gutterBottom>Amazon Bedrock RAG Stream Response テスト</Typography> </Grid> <Grid size={{xs:12}}> {/* Chatbot */} <Paper sx={{p:2,mb:2,width:"100%"}}> {/* あいさ぀文(固定) */} {renderMessage({ role: "ai", text: "こんにちは。䜕かお困りですか?", ref: []}, -1)} {/* 䌚話履歎 */} {conversation.map((msg, idx) => renderMessage(msg, idx))} {/* 盎近のレスポンス */} {streaming.text && renderMessage({ role:"ai", text: streaming.text, ref: streaming.refs }, "stream")} </Paper> {/* 入力゚リア */} <Box sx={{display:"flex",gap:1}}> <TextField fullWidth multiline value={prompt} onChange={(e) => setPrompt(e.target.value)} placeholder="Type message here..." sx={{ flexGrow: 1 }} /> <Button variant="contained" size="small" onClick={putRagSr} disabled={!prompt} startIcon={<SendIcon />} sx={{ whiteSpace: "nowrap", flexShrink: 0 }}>送信</Button> </Box> {/* オプション */} <Box sx={{mt:1,p:2,border:"1px solid",borderColor:"divider",borderRadius:1}}> <Typography variant="subtitle2" mb={1}>絞り蟌み</Typography> <Box sx={{display:"flex",flexWrap:"wrap",gap:2}}> <FormControl size="small" sx={{minWidth:150}}> <InputLabel>販売圢態</InputLabel> <Select value={filterChannel} label="販売圢態" onChange={(e) => setFilterChannel(e.target.value)}> <MenuItem value="">すべお</MenuItem> {channelOptions.map(v => <MenuItem key={v} value={v}>{v}</MenuItem>)} </Select> </FormControl> <FormControl size="small" sx={{minWidth:150}}> <InputLabel>カテゎリ</InputLabel> <Select value={filterCategory} label="カテゎリ" onChange={(e) => setFilterCategory(e.target.value)}> <MenuItem value="">すべお</MenuItem> {categoryOptions.map(v => <MenuItem key={v} value={v}>{v}</MenuItem>)} </Select> </FormControl> </Box> </Box> {/* クリアボタン */} {(streaming.text || conversation.length > 0) && ( <Box sx={{ display: "flex", justifyContent: "flex-end", mt: 2 }}> <Button variant="contained" size="small" onClick={resetSession}>問い合わせをクリアする</Button> </Box> )} </Grid> </Grid> </main> </Grid> </Grid> </Container> {/* Citation詳现Dialog */} <Dialog open={dialogOpen} onClose={handleDialogClose} maxWidth="md" fullWidth> <DialogTitle>問合せ詳现</DialogTitle> <DialogContent dividers> {selectedCitation && (() => { const { inquiry, answer } = parseContent(selectedCitation.content.text); const m = selectedCitation.metadata; return ( <Box> <Typography variant="subtitle2" color="text.secondary">問合せ番号</Typography> <Typography variant="body1" mb={2}>{m["問合せ番号"] || "-"}</Typography> <Typography variant="subtitle2" color="text.secondary">受付日時</Typography> <Typography variant="body1" mb={2}>{m["受付日時"] || "-"}</Typography> <Typography variant="subtitle2" color="text.secondary">完了日時</Typography> <Typography variant="body1" mb={2}>{m["完了日時"] || "-"}</Typography> <Typography variant="subtitle2" color="text.secondary">販売圢態</Typography> <Typography variant="body1" mb={2}>{m["販売圢態"] || "-"}</Typography> <Typography variant="subtitle2" color="text.secondary">商品番号</Typography> <Typography variant="body1" mb={2}>{m["商品番号"] || "-"}</Typography> <Typography variant="subtitle2" color="text.secondary">カテゎリ</Typography> <Typography variant="body1" mb={2}>{m["カテゎリ"] || "-"}</Typography> <Typography variant="subtitle2" color="text.secondary">問合せ内容</Typography> <Typography variant="body1" mb={2} sx={{ whiteSpace: "pre-wrap" }}>{inquiry || "-"}</Typography> <Typography variant="subtitle2" color="text.secondary">回答内容</Typography> <Typography variant="body1" mb={2} sx={{ whiteSpace: "pre-wrap" }}>{answer || "-"}</Typography> <Typography variant="subtitle2" color="text.secondary">ステヌタス</Typography> <Typography variant="body1" mb={2}>{m["ステヌタス"] || "-"}</Typography> </Box> ); })()} </DialogContent> <DialogActions> <Button onClick={handleDialogClose}>閉じる</Button> </DialogActions> </Dialog> </> ); }; export default RagSr; 途䞭、inquireRagSr ずいう関数がありたすが、axios で Amazon API Gateway をコヌルするだけの関数です。   たずめ いかがでしたでしょうか。 今回のシリヌズ蚘事の肝は Amazon Bedrock Knowledge Bases デヌタ゜ヌスのカスタムチャンキングでしたが、結果をこうしおアプリの UI で確認できるようになるず、本圓にできおいるこずを実感できたすよね。匕き続き怜蚌しお粟床向䞊に努めたす。 本蚘事が皆様のお圹に立おれば幞いです。
こんにちは、SCSK林です 昚今のデヌタ掻甚においお、マルチクラりド環境でのデヌタパむプラむン構築は珍しい芁件ではなくなっおいるず思いたす。 今回玹介する事䟋でも、AWS䞊のシステムから発生する倧量のストリヌムデヌタを、分析基盀であるGoogle CloudGCPのBigQueryぞリアルタむム連携するずいう芁件がありたした。 ゜ヌスずなるのは Amazon Managed Streaming for Apache Kafka (Amazon MSK)で、 圓初、MSK Connectの採甚を怜蚎したしたが、最終的にはGoogle CloudのCloud Runを甚いた独自Consumerの実装ずいうアヌキテクチャに萜ち着きたした。 本蚘事では、MSK Connectではなく独自実装を遞択せざるを埗なかった問題ず、AWS-Google Cloud間を専甚線でセキュアに぀なぐためのアヌキテクチャ蚭蚈の倉遷に぀いお共有したす。 初期構想MSK Connect 圓初構想しおいた構成は以䞋のずおりです。構成的にもマネヌゞドサヌビスを䜿甚しおおり申し分はなかったず思っおいたす。 Source Amazon MSK Connector MSK Connect (Sink Connector to Google Cloud Pub/Sub) Sink : Pub/SubGoogle Cloud Network AWS Direct Connect ず Google Cloud Partner Interconnect を䜿甚した専甚線接続 ※参考URL https://docs.cloud.google.com/pubsub/docs/connect_kafka#convert-to-pubsub 技術怜蚌の結果、専甚線経由でのGoogle Cloud゚ンドポむントぞの到達性や、基本的なデヌタ転送自䜓には問題がないこずが確認できたした。機胜芁件ずしおは、MSK Connectで満たしおいる構成でした。 課金問題ずアヌキテクチャの転換 ただ、この構成ではサヌビス制玄から以䞋の問題が生じたした。 「1コネクタ = 1 Pub/Subトピック」の制玄 今回採甚しようずしたコネクタの構成䞊、「1぀のMSK Connectリ゜ヌスに぀き、1぀のPub/Subトピックぞの連携しか定矩できない」ずいう制玄がありたした。 通垞、Kafka Consumerであれば1぀のプロセスで耇数のトピックをSubscribeし、ロゞックで振り分けるこずが容易です。しかし、MSK Connectおよび該圓のプラグむンの仕様に準拠するず、連携したいトピックの数だけMSK ConnectConnectorを䜜成する必芁がありたした。初期フェヌズではトピック数は10個ほどでしたが、次フェヌズでは蚈100トピックたで拡匵予定だったので、運甚面からも受け入れられない状態ずなりたした。 コストの倧幅な増加 MSK Connectの課金䜓系は MCU (MSK Connect Unit) × 利甚時間 です。 デヌタ流量が少ないトピックであっおも、コネクタを分割すれば最䜎1MCU分のコストが発生したす。今回のシステムには倚数のトピックが存圚したため、それら党おに察しお個別にConnectorを立ち䞊げるず、MCUの総数がトピック数に比䟋しお増加し、月額コストが想定以䞊に超過するこずが刀明したした。 ※参考URL https://aws.amazon.com/jp/msk/pricing/   䞊蚘問題の解決集玄による効率化 䞊蚘制玄から、解決策は「1぀のコンピュヌトリ゜ヌスで倚察倚N察Nの凊理をさばくこず」を実珟する必芁がありたした。 MSK Connectの採甚断念 コネクタ管理の耇雑さずコスト増が芋合わないため。 独自実装Cloud Run コンテナベヌスのアプリケヌションであれば、1぀のConsumerグルヌプで耇数トピックをSubscribeし、メモリ䞊でPub/Subトピックぞ振り分けるロゞックを実装可胜です。これにより、リ゜ヌスを極限たで集玄し、コストを圧瞮できるず刀断したした。   最終アヌキテクチャCloud Run 最終的に採甚したアヌキテクチャは以䞋のずおりです。 Consumer (Google Cloud) Cloud Run䞊にKafka Consumerアプリをデプロむ。 Buffer (Google Cloud) 取埗したデヌタを䞀床 Pub/Sub ぞPublish。 ETL (Google Cloud) Cloud Data Fusion が Pub/Sub からデヌタを読み出し、倉換凊理を行っお BigQuery ぞロヌド。 構成のポむントは以䞋の3点です。 Consumer Groupの集玄によるリ゜ヌス効率の最倧化 MSK Connect採甚怜蚎時のコネクタでは「1コネクタ = 1トピック」ずいう制玄があり、トピック数に比䟋しおコネクタMCUが線圢に増加する構造でした。これに察し、Cloud Runを甚いた独自実装では、1぀のコンテナアプリケヌションConsumer Groupで耇数のトピックをたずめおSubscribeする方匏を採甚したした。 Before (MSK Connect案) トピックごずにコネクタプロセスが起動。デヌタ流量が少ないトピックでも最䜎限のMCUリ゜ヌスを占有し、コスト効率が極めお悪い。 After (Cloud Run案) 1぀のConsumerアプリで耇数のトピックをSubscribe。メモリ空間を共有しながら効率的にメッセヌゞを凊理し、Cloud RunのCPU䜿甚率ベヌスでオヌトスケヌルさせるこずで、リ゜ヌスの䜙剰が少なくなるようにしたした。 ※今回はGoogle CloudのCloud Runで実装したしたが、AWS䞊での実装でもよいず思いたす。 Pub/Subをバッファずした「疎結合」なパむプラむン もう䞀぀の重芁な蚭蚈刀断は、ConsumerアプリCloud Runから盎接BigQueryぞ曞き蟌たず、必ず Google Cloud Pub/Sub を挟む構成にしたこずです。これにより、システムを「デヌタ取埗局」ず「デヌタ加工・ロヌド局」に明確に分離疎結合化したした。 責務の分離: Cloud Run (Consumer) 「MSKからデヌタを取り出し、Pub/Subぞ投げる」こずだけに集䞭。デヌタの倉換ロゞックやBigQueryのスキヌマ定矩を持たないため、軜量か぀ステヌトレスに保たれたす。 Data Fusion (ETL) Pub/SubからデヌタをPullし、耇雑な倉換を行っおBigQueryぞロヌド。 耐障害性の向䞊: 仮にBigQueryやData Fusion偎で障害や遅延が発生しおも、デヌタはPub/Subに滞留バッファリングするだけです。Cloud RunConsumerは圱響を受けず、AWS MSKからのデヌタ取埗を継続できたす。これにより、「AWS偎のログ保持期間切れデヌタロスト」のリスクを最小限に抑える蚭蚈ずしたした。 AWS-Google Cloud間のセキュアな接続 このアヌキテクチャを支えるネットワヌクは、AWS Direct ConnectずGoogle Cloud Partner Interconnectを結ぶ専甚線です。 AWS偎のSecurity Groupでは、Google Cloud Cloud RunがデプロむされおいるサブネットからのInboundのみを蚱可し、か぀Consumer Groupの集玄によっお接続元IPの管理もシンプルになりたした。   たずめ 今回の最終的な構成は、おそらく初期怜蚎段階では確実に倖される構成だず思いたす。 機胜的には芁件を満たしおいおも、高トラフィック環境䞋、゚ンタヌプラむズ環境ではコストがボトルネックになる堎合がありたす。AWSの課金䜓系を深く理解し、党䜓的に適切な構成を遞択しおいくこずの重芁性を改めお認識したした。 今回の構成、事䟋がどなたかのお圹に立぀ず幞いです。
こんにちは、広野です。 以䞋の蚘事の続線蚘事です。RAG で CSV デヌタからの怜玢粟床向䞊を目指しおみたした。本蚘事は実装線で、䞻にバック゚ンドの蚭定に぀いお蚘茉しおいたす。UI や実際の動䜜に぀いおは続線蚘事の UI 線で玹介したす。 Amazon Bedrock Knowledge Bases で構造化デヌタ(CSV)を䜿甚した RAG を぀くる -アヌキテクチャ線- Amazon Bedrock Knowledge Bases ず Amazon S3 Vectors で構築した RAG 環境で、構造化デヌタをデヌタ゜ヌスにしたずきの怜玢粟床向䞊を目指したした。本蚘事はアヌキテクチャ線です。 blog.usize-tech.com 2026.03.09   やりたいこず (再掲) 以䞋のような架空のヘルプデスク問い合わせ履歎デヌタ (CSV) を甚意したした。 ヘルプデスク担圓者が新たな問い合わせを受けたずきに、䌌たような過去の察応履歎を匕き圓おられるようにしたい、ずいうのが目的です。 LLM に、今届いた新しい問い合わせに察する回答案を提案させたい。 回答案を生成するために、自然蚀語で曞かれた問い合わせ内容ず回答内容から、意味的に近いデヌタを匕き圓おたい。 カテゎリで怜玢察象をフィルタしたい。その方が粟床が䞊がるケヌスがあるず考えられる。 LLM が回答案を提案するずきには、参考にした過去察応履歎がどの問合せ番号のものか、提瀺させたい。その問合せ番号をキヌに、生の察応履歎デヌタを参照できるようにしたい。 以䞋の前提がありたす。 デヌタ゜ヌスずなる CSV ファむルは 1぀のみ。過去の察応履歎は 1 ぀の CSV ファむルに収たっおいるずいうこず。 ぀たり、デヌタの1行が1件の問い合わせであり、その項目間には意味的な぀ながりがある。 たあ、ごくごく䞀般的なニヌズではないかず思いたす。   関連蚘事 以前、私が公開した Amazon Bedrock Knowledge Bases や Amazon S3 Vectors を䜿甚した RAG 基盀の蚘事です。今回はこの基盀のチャンキング戊略をカスタマむズしお臚みたした。 React で Amazon Bedrock Knowledge Bases ベヌスの簡易 RAG チャットボットを぀くる [2026幎1月版] アヌキテクチャ抂芁線 AWS re:Invent 2025 で、Amazon S3 Vectors が GA されたした。それを受けお、以前䜜成した RAG チャットボットをアレンゞしおみたした。 blog.usize-tech.com 2026.01.06   本蚘事の蚀及範囲 RAG そのものや、RAG 基盀に぀いおは本蚘事では語りたせん。 以䞋のアヌキテクチャ図の䞭の、赀枠の郚分に着目したす。ベクトルデヌタを栌玍するたでのデヌタ゜ヌスのカスタムチャンキングず、それを実装した Amazon Bedrock Knowledge Bases にどう問い合わせするか、です。   アヌキテクチャ (再掲) 前回蚘事で玹介した、カスタムチャンキングを実装するアヌキテクチャです。 実装 Amazon Bedrock Knowledge Bases カスタムチャンキングの䞀連の凊理は、Amazon Bedrock Knowledge Bases で行われたす。各皮蚭定の党䜓像は AWS マネゞメントコン゜ヌルの画面で䞀望できたす。 カスタムチャンキングを AWS Lambda 関数に凊理させるので、圓然 Lambda 関数が必芁です。(内容は埌述) Lambda 関数が出力するチャンク分割埌のデヌタ (䞭間成果物の JSON) を保存する S3 バケットが必芁です。これはオリゞナルのドキュメント配眮甚 S3 バケットずは別にする必芁がありたす。 チャンキング戊略は NO にしたす。NO にするず、オリゞナルのドキュメントの内容をそのたた Lambda 関数に枡しおくれたす。別の戊略を遞択するず、その戊略によっおチャンク分割されたデヌタごずに Lambda 関数を実行しおしたうので、期埅するカスタムチャンク分割ができなくなりたす。 解析戊略は Default にしたす。 チャンキング戊略ず解析戊略は、デヌタ゜ヌス䜜成埌には倉曎できたせん。倉曎したいずきは䜜り盎しになりたす。 デヌタ削陀ポリシヌは DELETE にするこずをお勧めしたす。同期をかけたずきに過去のデヌタを残すかどうかの蚭定で、残しおしたうず叀い情報が怜玢に匕っ掛かっおしたいたす。 AWS Lambda 関数 (カスタムチャンキング) カスタムチャンキングする Lambda 関数コヌド (Python) です。 冒頭に玹介した CSV を、Amazon Bedrock Knowledge Bases が理解できるフォヌマットの JSON デヌタに倉換したす。内郚的には 1 チャンクごずに自然蚀語で怜玢させたいデヌタずメタデヌタに分けお出力したす。 Lambda レむダヌは䞍芁です。モゞュヌルは Lambda 暙準でサポヌトしおいるものだけで実装可胜でした。  むンプットずなる S3 バケット内の CSV デヌタのメタデヌタは、Amazon Bedrock Knowledge Bases がこの Lambda 関数を呌び出すずきに枡しおくれるので、こちらが特に気にするこずはありたせん。受け取ったバケット名、キヌから CSV デヌタを取埗しに行きたす。出力先ずなる S3 バケットやキヌ名も Amazon Bedrock Knowledge Bases から枡されたすのでこの関数内でベタ曞きするこずはありたせん。 デヌタフォヌマットの倉換凊理の内容的には、そんなに難しいこずはしおいたせん。倧事なのは出力フォヌマットです。 import json import csv import boto3 from io import StringIO s3 = boto3.client('s3') def lambda_handler(event, context): try: bucket_name = event.get('bucketName') input_files = event.get('inputFiles', []) output_files = [] for file_info in input_files: original_file_location = file_info.get('originalFileLocation', {}) s3_location = original_file_location.get('s3Location', {}) original_uri = s3_location.get('uri', '') content_batches = file_info.get('contentBatches', []) output_batches = [] for batch in content_batches: input_key = batch.get('key') # Read input file from S3 response = s3.get_object(Bucket=bucket_name, Key=input_key) input_content = json.loads(response['Body'].read().decode('utf-8')) # Extract CSV content csv_content = input_content['fileContents'][0]['contentBody'] # Remove BOM if present (input may have BOM) if csv_content.startswith('\ufeff'): csv_content = csv_content[1:] csv_reader = csv.DictReader(StringIO(csv_content)) # Process each row as a chunk file_contents = [] for row in csv_reader: content_body = f"問合せ番号: {row.get('問合せ番号', '')}\n商品番号: {row.get('商品番号', '')}\n\n問合せ内容:\n{row.get('問合せ内容', '')}\n\n回答内容:\n{row.get('回答内容', '')}" content_metadata = { "問合せ番号": row.get('問合せ番号', ''), "販売圢態": row.get('販売圢態', ''), "受付日時": row.get('受付日時', ''), "完了日時": row.get('完了日時', ''), "商品番号": row.get('商品番号', ''), "カテゎリ": row.get('カテゎリ', ''), "ステヌタス": row.get('ステヌタス', '') } file_contents.append({ "contentBody": content_body, "contentType": "TEXT", "contentMetadata": content_metadata }) # Write output file to S3 output_key = input_key.replace('.json', '_transformed.json') output_data = {"fileContents": file_contents} s3.put_object( Bucket=bucket_name, Key=output_key, Body=json.dumps(output_data, ensure_ascii=False), ContentType='application/json' ) output_batches.append({"key": output_key}) output_files.append({ "originalFileLocation": original_file_location, "fileMetadata": file_info.get('fileMetadata', {}), "contentBatches": output_batches }) return {"outputFiles": output_files} except Exception as e: print(f"Error: {str(e)}") import traceback traceback.print_exc() raise チャンク分割された埌のデヌタ構造 (再掲) Lambda 関数がチャンク分割した埌のデヌタ構造 (䞊のアヌキテクチャ図では 5番の凊理によっお䜜成されるもの) は、以䞋のようになりたす。 { "fileContents": [ { "contentBody": "問合せ番号: AB01234569\n商品番号: SH001-01BL\n\n問合せ内容:\n[問合せ内容の文章]\n\n回答内容:\n[回答内容の文章]", "contentType": "TEXT", "contentMetadata": { "問合せ番号": "AB01234569", "販売圢態": "代理店", "受付日時": "2026/2/23 12:59", "完了日時": "2026/2/23 13:39", "商品番号": "SH001-01BL", "カテゎリ": "家庭甚収玍棚", "ステヌタス": "完了" } }, { "contentBody": "問合せ番号: AB01234573\n商品番号: TB19541\n\n問合せ内容:\n[問合せ内容の文章]\n\n回答内容:\n[回答内容の文章]", "contentType": "TEXT", "contentMetadata": { "問合せ番号": "AB01234573", "販売圢態": "盎販", "受付日時": "2026/2/24 9:15", "完了日時": "2026/2/24 14:30", "商品番号": "TB19541", "カテゎリ": "家庭甚テヌブル", "ステヌタス": "完了" } } ] } fileContents 配列の各芁玠が 1 チャンクCSV の 1 行に盞圓 contentBody がベクトル化・怜玢察象にできるテキスト contentMetadata が匕甚衚瀺やフィルタリングに䜿甚されるメタデヌタ ※contentBody ももちろん匕甚可胜 ここたで実装できるず、Amazon Bedrock Knowledge Bases に察しお contentBody に曞かれた内容に察しお自然蚀語で怜玢できたり、怜玢時にメタデヌタの項目単䜍でフィルタリングできるようになりたす。 メタデヌタフィルタリングに぀いお Amazon Bedrock Knowledge Bases ができおしたえば、自然蚀語による問い合わせは RetrieveAndGenerate API を䜿甚しお極論プロンプトさえ送ればいいので、難しいこずはありたせん。しかし、メタデヌタフィルタリング機胜を远加するず、蚭蚈次第ではコヌドが耇雑になりたす。 ここで、メタデヌタフィルタリングに぀いお仕様を説明したす。 メタデヌタ条件にマッチするチャンクのみにベクトル怜玢を行うため、䞍芁な結果を排陀するこずができ、怜玢粟床の向䞊が期埅できる。 メタデヌタ項目に察しおかけられる文字列怜玢条件は、完党䞀臎や、指定した文字列を含む、などいろいろできる。Amazon S3 Vectors でサポヌトしおいる条件は以䞋公匏ドキュメントを参照。 メタデヌタ項目は、耇数項目を And や Or で組み合わせるこずが可胜。 メタデータフィルタリング - Amazon Simple Storage Service メタデヌタフィルタリングを䜿甚しお、ベクトルにアタッチされた特定の属性に基づいおク゚リ結果を絞り蟌む方法に぀いお説明したす。 docs.aws.amazon.com ぀たり、かなり现かいフィルタリングができるずいうこずです。 以䞋にメタデヌタフィルタリングを蚭定するずきの Lambda 関数コヌドの䞀郚を玹介したす。 単䞀のメタデヌタ条件 「販売圢態が代理店で完党䞀臎」でフィルタリングしたいずき retrievalConfiguration={ "vectorSearchConfiguration": { "filter": { "equals": { "key": "販売圢態", "value": "代理店" } } } } 耇数のメタデヌタ条件 「販売圢態が代理店で完党䞀臎」か぀「カテゎリが家庭甚コタツで完党䞀臎」でフィルタリングしたいずき retrievalConfiguration={ "vectorSearchConfiguration": { "filter": { "andAll": [ { "equals": { "key": "販売圢態", "value": "代理店" } }, { "equals": { "key": "カテゎリ", "value": "家庭甚コタツ" } } ] } } } 芋おもらえるずわかるず思いたすが、耇数のメタデヌタ条件では 2 ぀の equals 条件を andAll で囲んでいるず思いたす。䞊蚘はただシンプルですが、耇数の条件が重なれば重なるほど、このような階局構造をさらにコヌディングしなければなりたせん。Or 条件も可胜ずするず、さらに耇雑になりそうです。 今回のブログ蚘事では、簡略化のため䞊蚘のように「販売圢態」ず「カテゎリ」の 2 ぀のメタデヌタのみフィルタリング可胜なように蚭蚈したす。 フィルタ察象項目 販売圢態2皮類: 盎販, 代理店 カテゎリ10皮類: 家庭甚コタツ, 家庭甚テヌブル, 家庭甚収玍棚, 家庭甚チェア, 家庭甚デスク, 業務甚ラック, 業務甚キャビネット, 業務甚䌚議テヌブル, 業務甚チェア, 業務甚デスク フィルタ条件遞択時の動䜜 䞡方未遞択 → フィルタリングなし党件怜玢 片方のみ遞択 → 遞択したキヌワヌドに完党䞀臎で単䞀条件怜玢 䞡方遞択 → AND 条件怜玢、それぞれ遞択したキヌワヌドに完党䞀臎ずする AWS Lambda 関数 (ナレッゞベヌスぞの問い合わせ) 前述のメタデヌタフィルタリング機胜を実装した、Amazon Bedrock Knowledge Bases の RetrieveAndGenerate API をコヌルする AWS Lambda 関数コヌドは以䞋のようになりたす。 Amazon API Gateway REST API から呌び出され、AWS AppSync Events にストリヌムレスポンスを返す構成です。コメントで メタデヌタフィルタリングの組み立お ず曞いおある郚分が先ほど説明した郚分の実装です。 むンプットずしお "filters": [ {"販売圢態": "代理店"}, {"カテゎリ": "家庭甚コタツ"} ] のようなメタデヌタフィルタリングパラメヌタを受け取る想定です。条件が2぀あれば andAll で囲う凊理を実装しおいたす。 import os import json import boto3 import urllib.request from botocore.auth import SigV4Auth from botocore.awsrequest import AWSRequest # common objects and valiables session = boto3.session.Session() bedrock_agent = boto3.client('bedrock-agent-runtime') endpoint = os.environ['APPSYNC_API_ENDPOINT'] model_arn = os.environ['MODEL_ARN'] knowledge_base_id = os.environ['KNOWLEDGE_BASE_ID'] region = os.environ['REGION'] service = 'appsync' headers = {'Content-Type': 'application/json'} # AppSync publish message function def publish_appsync_message(sub, appsync_session_id, payload, credentials): body = json.dumps({ "channel": f"rag-stream-response/{sub}/{appsync_session_id}", "events": [ json.dumps(payload) ] }).encode("utf-8") aws_request = AWSRequest( method='POST', url=endpoint, data=body, headers=headers ) SigV4Auth(credentials, service, region).add_auth(aws_request) req = urllib.request.Request( url=endpoint, data=aws_request.body, method='POST' ) for k, v in aws_request.headers.items(): req.add_header(k, v) with urllib.request.urlopen(req) as res: return res.read().decode('utf-8') # handler def lambda_handler(event, context): try: credentials = session.get_credentials().get_frozen_credentials() # API Gateway からのむンプットを取埗 prompt = event['body']['prompt'] appsync_session_id = event['body']['appsyncSessionId'] bedrock_session_id = event['body'].get('bedrockSessionId') sub = event['sub'] # Amazon Bedrock Knowledge Bases ぞの問い合わせパラメヌタ䜜成 request = { "input": { "text": prompt }, "retrieveAndGenerateConfiguration": { "type": "KNOWLEDGE_BASE", "knowledgeBaseConfiguration": { "knowledgeBaseId": knowledge_base_id, "modelArn": model_arn, "generationConfiguration": { "inferenceConfig": { "textInferenceConfig": { "maxTokens": 10000, "temperature": 0.5, "topP": 0.9 } }, "performanceConfig": { "latency": "standard" }, "promptTemplate": { "textPromptTemplate": ( "あなたは優秀なヘルプデスクアシスタントです。ヘルプデスク担圓者からの質問に察しお、必ず日本語で回答しおください。" "適切な回答が芋぀からない堎合は、正盎に「分かりたせん」ず回答しおください。\n\n" "怜玢結果:\n$search_results$\n\n" "回答指瀺: $output_format_instructions$" ) } } } } } # メタデヌタフィルタ条件の組み立お filters = event['body'].get('filters', []) if filters: conditions = [{"equals": {"key": k, "value": v}} for f in filters for k, v in f.items()] if len(conditions) == 1: retrieval_filter = conditions[0] else: retrieval_filter = {"andAll": conditions} request["retrieveAndGenerateConfiguration"]["knowledgeBaseConfiguration"]["retrievalConfiguration"] = { "vectorSearchConfiguration": { "filter": retrieval_filter } } # Bedrock sessionId は存圚するずきのみ枡す (継続䌚話時のみ) if bedrock_session_id: request["sessionId"] = bedrock_session_id # Bedrock Knowledge Bases ぞの問い合わせ response = bedrock_agent.retrieve_and_generate_stream(**request) # Bedrock sessionId if "sessionId" in response: publish_appsync_message( sub, appsync_session_id, { "type": "bedrock_session", "bedrock_session_id": response["sessionId"] }, credentials ) for chunk in response["stream"]: payload = None # Generated text if "output" in chunk and "text" in chunk["output"]: payload = { "type": "text", "message": chunk["output"]["text"] } print({"t": chunk["output"]["text"]}) # Citation elif "citation" in chunk: payload = { "type": "citation", "citation": chunk['citation']['retrievedReferences'] } print({"c": chunk['citation']['retrievedReferences']}) # Continue if not payload: continue # Publish AppSync publish_appsync_message(sub, appsync_session_id, payload, credentials) except Exception as e: print(str(e)) raise AWS CloudFormation テンプレヌト Amazon API Gateway REST API や AWS AppSync Events API など、関連するリ゜ヌスを䞀匏デプロむするテンプレヌトを掲茉したす。これ単䜓では動かないず思いたすので、参考たでに。ここたで実装できるず、アプリ UI から API をコヌルするこずでチャットボット UI を䜜れたす。 AWSTemplateFormatVersion: 2010-09-09 Description: The CloudFormation template that creates a S3 vector bucket and index as a RAG Knowledge base. # ------------------------------------------------------------# # Input Parameters # ------------------------------------------------------------# Parameters: SystemName: Type: String Description: System name. use lower case only. (e.g. example) Default: example MaxLength: 10 MinLength: 1 SubName: Type: String Description: System sub name. use lower case only. (e.g. prod or dev) Default: dev MaxLength: 10 MinLength: 1 DomainName: Type: String Description: Domain name for URL. xxxxx.xxx (e.g. example.com) Default: example.com AllowedPattern: "[^\\s@]+\\.[^\\s@]+" SubDomainName: Type: String Description: Sub domain name for URL. (e.g. example-prod or example-dev) Default: example-dev MaxLength: 20 MinLength: 1 Dimension: Type: Number Description: The dimensions of the vectors to be inserted into the vector index. The value depends on the embedding model. Default: 1024 MaxValue: 4096 MinValue: 1 EmbeddingModelId: Type: String Description: The embedding model ID. Default: amazon.titan-embed-text-v2:0 MaxLength: 100 MinLength: 1 LlmModelId: Type: String Description: The LLM model ID for the Knowledge base. Default: global.amazon.nova-2-lite-v1:0 MaxLength: 100 MinLength: 1 Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: "General Configuration" Parameters: - SystemName - SubName - Label: default: "Domain Configuration" Parameters: - DomainName - SubDomainName - Label: default: "Embedding Configuration" Parameters: - Dimension - EmbeddingModelId - Label: default: "Knowledge Base Configuration" Parameters: - LlmModelId Resources: # ------------------------------------------------------------# # S3 # ------------------------------------------------------------# S3BucketKbDatasource: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${SystemName}-${SubName}-kbdatasource PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true CorsConfiguration: CorsRules: - AllowedHeaders: - "*" AllowedMethods: - "GET" - "HEAD" - "PUT" - "POST" - "DELETE" AllowedOrigins: - !Sub https://${SubDomainName}.${DomainName} ExposedHeaders: - last-modified - content-type - content-length - etag - x-amz-version-id - x-amz-request-id - x-amz-id-2 - x-amz-cf-id - x-amz-storage-class - date - access-control-expose-headers MaxAge: 3000 Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} S3BucketPolicyKbDatasource: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref S3BucketKbDatasource PolicyDocument: Version: "2012-10-17" Statement: - Effect: Deny Principal: "*" Action: "s3:*" Resource: - !Sub "arn:aws:s3:::${S3BucketKbDatasource}" - !Sub "arn:aws:s3:::${S3BucketKbDatasource}/*" Condition: Bool: "aws:SecureTransport": "false" DependsOn: - S3BucketKbDatasource S3VectorBucket: Type: AWS::S3Vectors::VectorBucket Properties: VectorBucketName: !Sub ${SystemName}-${SubName}-vectordb S3BucketKbIntermediate: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${SystemName}-${SubName}-kbintermediate PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} S3BucketPolicyKbIntermediate: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref S3BucketKbIntermediate PolicyDocument: Version: "2012-10-17" Statement: - Effect: Deny Principal: "*" Action: "s3:*" Resource: - !Sub "arn:aws:s3:::${S3BucketKbIntermediate}" - !Sub "arn:aws:s3:::${S3BucketKbIntermediate}/*" Condition: Bool: "aws:SecureTransport": "false" DependsOn: - S3BucketKbIntermediate S3VectorBucketIndex: Type: AWS::S3Vectors::Index Properties: IndexName: !Sub ${SystemName}-${SubName}-vectordb-index DataType: float32 Dimension: !Ref Dimension DistanceMetric: cosine VectorBucketArn: !GetAtt S3VectorBucket.VectorBucketArn MetadataConfiguration: NonFilterableMetadataKeys: - AMAZON_BEDROCK_TEXT - AMAZON_BEDROCK_METADATA DependsOn: - S3VectorBucket # ------------------------------------------------------------# # Bedrock Knowledge Base # ------------------------------------------------------------# BedrockKnowledgeBase: Type: AWS::Bedrock::KnowledgeBase Properties: Name: !Sub ${SystemName}-${SubName}-kb Description: !Sub RAG Knowledge Base for ${SystemName}-${SubName} KnowledgeBaseConfiguration: Type: VECTOR VectorKnowledgeBaseConfiguration: EmbeddingModelArn: !Sub arn:aws:bedrock:${AWS::Region}::foundation-model/${EmbeddingModelId} RoleArn: !GetAtt IAMRoleBedrockKb.Arn StorageConfiguration: Type: S3_VECTORS S3VectorsConfiguration: IndexArn: !GetAtt S3VectorBucketIndex.IndexArn VectorBucketArn: !GetAtt S3VectorBucket.VectorBucketArn Tags: Cost: !Sub ${SystemName}-${SubName} DependsOn: - IAMRoleBedrockKb BedrockKnowledgeBaseDataSource: Type: AWS::Bedrock::DataSource Properties: Name: !Sub ${SystemName}-${SubName}-kb-datasource Description: !Sub RAG Knowledge Base Data Source for ${SystemName}-${SubName} KnowledgeBaseId: !Ref BedrockKnowledgeBase DataDeletionPolicy: DELETE DataSourceConfiguration: Type: S3 S3Configuration: BucketArn: !GetAtt S3BucketKbDatasource.Arn VectorIngestionConfiguration: ChunkingConfiguration: ChunkingStrategy: NONE CustomTransformationConfiguration: Transformations: - TransformationFunction: TransformationLambdaConfiguration: LambdaArn: !GetAtt LambdaCsvChunker.Arn StepToApply: POST_CHUNKING IntermediateStorage: S3Location: URI: !Sub s3://${S3BucketKbIntermediate}/ DependsOn: - S3BucketKbDatasource - BedrockKnowledgeBase - S3BucketKbIntermediate # ------------------------------------------------------------# # AppSync Events # ------------------------------------------------------------# AppSyncChannelNamespaceRagSR: Type: AWS::AppSync::ChannelNamespace Properties: Name: rag-stream-response ApiId: Fn::ImportValue: !Sub AppSyncApiId-${SystemName}-${SubName} CodeHandlers: | import { util } from '@aws-appsync/utils'; export function onSubscribe(ctx) { const requested = ctx.info.channel.path; if (!requested.startsWith(`/rag-stream-response/${ctx.identity.sub}`)) { util.unauthorized(); } } Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} # ------------------------------------------------------------# # API Gateway REST API # ------------------------------------------------------------# RestApiRagSR: Type: AWS::ApiGateway::RestApi Properties: Name: !Sub rag-sr-${SystemName}-${SubName} Description: !Sub REST API to call Lambda rag-stream-response-${SystemName}-${SubName} EndpointConfiguration: Types: - REGIONAL IpAddressType: dualstack Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} RestApiDeploymentRagSR: Type: AWS::ApiGateway::Deployment Properties: RestApiId: !Ref RestApiRagSR DependsOn: - RestApiMethodRagSRPost - RestApiMethodRagSROptions RestApiStageRagSR: Type: AWS::ApiGateway::Stage Properties: StageName: prod Description: production stage RestApiId: !Ref RestApiRagSR DeploymentId: !Ref RestApiDeploymentRagSR MethodSettings: - ResourcePath: "/*" HttpMethod: "*" LoggingLevel: INFO DataTraceEnabled : true TracingEnabled: false AccessLogSetting: DestinationArn: !GetAtt LogGroupRestApiRagSR.Arn Format: '{"requestId":"$context.requestId","status":"$context.status","sub":"$context.authorizer.claims.sub","email":"$context.authorizer.claims.email","resourcePath":"$context.resourcePath","requestTime":"$context.requestTime","sourceIp":"$context.identity.sourceIp","userAgent":"$context.identity.userAgent","apigatewayError":"$context.error.message","authorizerError":"$context.authorizer.error","integrationError":"$context.integration.error"}' Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} RestApiAuthorizerRagSR: Type: AWS::ApiGateway::Authorizer Properties: Name: !Sub restapi-authorizer-ragsr-${SystemName}-${SubName} RestApiId: !Ref RestApiRagSR Type: COGNITO_USER_POOLS ProviderARNs: - Fn::ImportValue: !Sub CognitoArn-${SystemName}-${SubName} AuthorizerResultTtlInSeconds: 300 IdentitySource: method.request.header.Authorization RestApiResourceRagSR: Type: AWS::ApiGateway::Resource Properties: RestApiId: !Ref RestApiRagSR ParentId: !GetAtt RestApiRagSR.RootResourceId PathPart: ragsr RestApiMethodRagSRPost: Type: AWS::ApiGateway::Method Properties: RestApiId: !Ref RestApiRagSR ResourceId: !Ref RestApiResourceRagSR HttpMethod: POST AuthorizationType: COGNITO_USER_POOLS AuthorizerId: !Ref RestApiAuthorizerRagSR Integration: Type: AWS IntegrationHttpMethod: POST Credentials: Fn::ImportValue: !Sub ApigLambdaInvocationRoleArn-${SystemName}-${SubName} Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaRagSR.Arn}/invocations" PassthroughBehavior: NEVER RequestTemplates: application/json: | { "body": $input.json('$'), "sub": "$context.authorizer.claims.sub" } RequestParameters: integration.request.header.X-Amz-Invocation-Type: "'Event'" IntegrationResponses: - ResponseParameters: method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,Cache-Control'" method.response.header.Access-Control-Allow-Methods: "'POST,OPTIONS'" method.response.header.Access-Control-Allow-Origin: !Sub "'https://${SubDomainName}.${DomainName}'" ResponseTemplates: application/json: '' StatusCode: '202' MethodResponses: - StatusCode: '202' ResponseModels: application/json: Empty ResponseParameters: method.response.header.Access-Control-Allow-Origin: true method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true RestApiMethodRagSROptions: Type: AWS::ApiGateway::Method Properties: RestApiId: !Ref RestApiRagSR ResourceId: !Ref RestApiResourceRagSR HttpMethod: OPTIONS AuthorizationType: NONE Integration: Type: MOCK Credentials: Fn::ImportValue: !Sub ApigLambdaInvocationRoleArn-${SystemName}-${SubName} IntegrationResponses: - ResponseParameters: method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,Cache-Control'" method.response.header.Access-Control-Allow-Methods: "'POST,OPTIONS'" method.response.header.Access-Control-Allow-Origin: !Sub "'https://${SubDomainName}.${DomainName}'" ResponseTemplates: application/json: '' StatusCode: '200' PassthroughBehavior: WHEN_NO_MATCH RequestTemplates: application/json: '{"statusCode": 200}' MethodResponses: - ResponseModels: application/json: Empty ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true method.response.header.Access-Control-Allow-Origin: true StatusCode: '200' # ------------------------------------------------------------# # API Gateway LogGroup (CloudWatch Logs) # ------------------------------------------------------------# LogGroupRestApiRagSR: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/apigateway/${RestApiRagSR} RetentionInDays: 365 Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} # ------------------------------------------------------------# # Lambda # ------------------------------------------------------------# LambdaRagSR: Type: AWS::Lambda::Function Properties: FunctionName: !Sub rag-sr-${SystemName}-${SubName} Description: !Sub Lambda Function to invoke Bedrock Knowledge Bases for ${SystemName}-${SubName} Architectures: - x86_64 Runtime: python3.14 Timeout: 300 MemorySize: 128 Environment: Variables: APPSYNC_API_ENDPOINT: Fn::ImportValue: !Sub AppSyncEventsEndpointHttp-${SystemName}-${SubName} MODEL_ARN: !Sub "arn:aws:bedrock:${AWS::Region}:${AWS::AccountId}:inference-profile/${LlmModelId}" KNOWLEDGE_BASE_ID: !Ref BedrockKnowledgeBase REGION: !Ref AWS::Region Role: !GetAtt LambdaBedrockKbRole.Arn Handler: index.lambda_handler Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} Code: ZipFile: | import os import json import boto3 import urllib.request from botocore.auth import SigV4Auth from botocore.awsrequest import AWSRequest # common objects and valiables session = boto3.session.Session() bedrock_agent = boto3.client('bedrock-agent-runtime') endpoint = os.environ['APPSYNC_API_ENDPOINT'] model_arn = os.environ['MODEL_ARN'] knowledge_base_id = os.environ['KNOWLEDGE_BASE_ID'] region = os.environ['REGION'] service = 'appsync' headers = {'Content-Type': 'application/json'} # AppSync publish message function def publish_appsync_message(sub, appsync_session_id, payload, credentials): body = json.dumps({ "channel": f"rag-stream-response/{sub}/{appsync_session_id}", "events": [ json.dumps(payload) ] }).encode("utf-8") aws_request = AWSRequest( method='POST', url=endpoint, data=body, headers=headers ) SigV4Auth(credentials, service, region).add_auth(aws_request) req = urllib.request.Request( url=endpoint, data=aws_request.body, method='POST' ) for k, v in aws_request.headers.items(): req.add_header(k, v) with urllib.request.urlopen(req) as res: return res.read().decode('utf-8') # handler def lambda_handler(event, context): try: credentials = session.get_credentials().get_frozen_credentials() # API Gateway からのむンプットを取埗 prompt = event['body']['prompt'] appsync_session_id = event['body']['appsyncSessionId'] bedrock_session_id = event['body'].get('bedrockSessionId') sub = event['sub'] # Amazon Bedrock Knowledge Bases ぞの問い合わせパラメヌタ䜜成 request = { "input": { "text": prompt }, "retrieveAndGenerateConfiguration": { "type": "KNOWLEDGE_BASE", "knowledgeBaseConfiguration": { "knowledgeBaseId": knowledge_base_id, "modelArn": model_arn, "generationConfiguration": { "inferenceConfig": { "textInferenceConfig": { "maxTokens": 10000, "temperature": 0.5, "topP": 0.9 } }, "performanceConfig": { "latency": "standard" }, "promptTemplate": { "textPromptTemplate": ( "あなたは優秀なヘルプデスクアシスタントです。ヘルプデスク担圓者からの質問に察しお、必ず日本語で回答しおください。" "適切な回答が芋぀からない堎合は、正盎に「分かりたせん」ず回答しおください。\n\n" "怜玢結果:\n$search_results$\n\n" "回答指瀺: $output_format_instructions$" ) } } } } } # メタデヌタフィルタ条件の組み立お filters = event['body'].get('filters', []) if filters: conditions = [{"equals": {"key": k, "value": v}} for f in filters for k, v in f.items()] if len(conditions) == 1: retrieval_filter = conditions[0] else: retrieval_filter = {"andAll": conditions} request["retrieveAndGenerateConfiguration"]["knowledgeBaseConfiguration"]["retrievalConfiguration"] = { "vectorSearchConfiguration": { "filter": retrieval_filter } } # Bedrock sessionId は存圚するずきのみ枡す (継続䌚話時のみ) if bedrock_session_id: request["sessionId"] = bedrock_session_id # Bedrock Knowledge Bases ぞの問い合わせ response = bedrock_agent.retrieve_and_generate_stream(**request) # Bedrock sessionId if "sessionId" in response: publish_appsync_message( sub, appsync_session_id, { "type": "bedrock_session", "bedrock_session_id": response["sessionId"] }, credentials ) for chunk in response["stream"]: payload = None # Generated text if "output" in chunk and "text" in chunk["output"]: payload = { "type": "text", "message": chunk["output"]["text"] } print({"t": chunk["output"]["text"]}) # Citation elif "citation" in chunk: payload = { "type": "citation", "citation": chunk['citation']['retrievedReferences'] } print({"c": chunk['citation']['retrievedReferences']}) # Continue if not payload: continue # Publish AppSync publish_appsync_message(sub, appsync_session_id, payload, credentials) except Exception as e: print(str(e)) raise DependsOn: - LambdaBedrockKbRole - BedrockKnowledgeBase LambdaRagSREventInvokeConfig: Type: AWS::Lambda::EventInvokeConfig Properties: FunctionName: !GetAtt LambdaRagSR.Arn Qualifier: $LATEST MaximumRetryAttempts: 0 MaximumEventAgeInSeconds: 300 LambdaCsvChunker: Type: AWS::Lambda::Function Properties: FunctionName: !Sub csv-chunker-${SystemName}-${SubName} Description: !Sub Lambda Function to embed with custom chunk for ${SystemName}-${SubName} Architectures: - x86_64 Runtime: python3.14 Handler: index.lambda_handler Timeout: 900 MemorySize: 512 Role: !GetAtt LambdaCsvChunkerRole.Arn Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} Code: ZipFile: | import json import csv import boto3 from io import StringIO s3 = boto3.client('s3') def lambda_handler(event, context): try: bucket_name = event.get('bucketName') input_files = event.get('inputFiles', []) output_files = [] for file_info in input_files: original_file_location = file_info.get('originalFileLocation', {}) s3_location = original_file_location.get('s3Location', {}) original_uri = s3_location.get('uri', '') content_batches = file_info.get('contentBatches', []) output_batches = [] for batch in content_batches: input_key = batch.get('key') # Read input file from S3 response = s3.get_object(Bucket=bucket_name, Key=input_key) input_content = json.loads(response['Body'].read().decode('utf-8')) # Extract CSV content csv_content = input_content['fileContents'][0]['contentBody'] # Remove BOM if present (input may have BOM) if csv_content.startswith('\ufeff'): csv_content = csv_content[1:] csv_reader = csv.DictReader(StringIO(csv_content)) # Process each row as a chunk file_contents = [] for row in csv_reader: content_body = f"問合せ番号: {row.get('問合せ番号', '')}\n商品番号: {row.get('商品番号', '')}\n\n問合せ内容:\n{row.get('問合せ内容', '')}\n\n回答内容:\n{row.get('回答内容', '')}" content_metadata = { "問合せ番号": row.get('問合せ番号', ''), "販売圢態": row.get('販売圢態', ''), "受付日時": row.get('受付日時', ''), "完了日時": row.get('完了日時', ''), "商品番号": row.get('商品番号', ''), "カテゎリ": row.get('カテゎリ', ''), "ステヌタス": row.get('ステヌタス', '') } file_contents.append({ "contentBody": content_body, "contentType": "TEXT", "contentMetadata": content_metadata }) # Write output file to S3 output_key = input_key.replace('.json', '_transformed.json') output_data = {"fileContents": file_contents} s3.put_object( Bucket=bucket_name, Key=output_key, Body=json.dumps(output_data, ensure_ascii=False), ContentType='application/json' ) output_batches.append({"key": output_key}) output_files.append({ "originalFileLocation": original_file_location, "fileMetadata": file_info.get('fileMetadata', {}), "contentBatches": output_batches }) return {"outputFiles": output_files} except Exception as e: print(f"Error: {str(e)}") import traceback traceback.print_exc() raise LambdaInvokePermissionCsvChunker: Type: AWS::Lambda::Permission Properties: FunctionName: !Ref LambdaCsvChunker Action: lambda:InvokeFunction Principal: bedrock.amazonaws.com SourceAccount: !Ref AWS::AccountId # SourceArn: !Sub "arn:aws:bedrock:${AWS::Region}:${AWS::AccountId}:knowledge-base/${BedrockKnowledgeBase}" DependsOn: - LambdaCsvChunker # - BedrockKnowledgeBase # ------------------------------------------------------------# # Lambda Role (IAM) # ------------------------------------------------------------# LambdaBedrockKbRole: Type: AWS::IAM::Role Properties: RoleName: !Sub LambdaBedrockKbRole-${SystemName}-${SubName} Description: This role allows Lambda functions to invoke Bedrock Knowledge Bases and AppSync Events API. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess Policies: - PolicyName: !Sub LambdaBedrockKbPolicy-${SystemName}-${SubName} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "bedrock:InvokeModel" - "bedrock:InvokeModelWithResponseStream" - "bedrock:GetInferenceProfile" - "bedrock:ListInferenceProfiles" Resource: - !Sub "arn:aws:bedrock:*::foundation-model/*" - !Sub "arn:aws:bedrock:*:${AWS::AccountId}:inference-profile/*" - Effect: Allow Action: - "bedrock:RetrieveAndGenerate" - "bedrock:Retrieve" Resource: - !GetAtt BedrockKnowledgeBase.KnowledgeBaseArn - Effect: Allow Action: - "appsync:connect" Resource: - Fn::ImportValue: !Sub AppSyncApiArn-${SystemName}-${SubName} - Effect: Allow Action: - "appsync:publish" - "appsync:EventPublish" Resource: - Fn::Join: - "" - - Fn::ImportValue: !Sub AppSyncApiArn-${SystemName}-${SubName} - /channelNamespace/rag-stream-response LambdaCsvChunkerRole: Type: AWS::IAM::Role Properties: RoleName: !Sub LambdaCsvChunkerRole-${SystemName}-${SubName} AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: !Sub LambdaCsvChunkerPolicy-${SystemName}-${SubName} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "s3:GetObject" - "s3:PutObject" - "s3:ListObject" Resource: - !GetAtt S3BucketKbDatasource.Arn - !Sub ${S3BucketKbDatasource.Arn}/* - !GetAtt S3BucketKbIntermediate.Arn - !Sub ${S3BucketKbIntermediate.Arn}/* # ------------------------------------------------------------# # IAM Role for Bedrock Knowledge Base # ------------------------------------------------------------# IAMRoleBedrockKb: Type: AWS::IAM::Role Properties: RoleName: !Sub BedrockKbRole-${SystemName}-${SubName} AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - sts:AssumeRole Principal: Service: - bedrock.amazonaws.com Condition: StringEquals: "aws:SourceAccount": !Ref AWS::AccountId # ArnLike: # "aws:SourceArn": !Sub "arn:aws:bedrock:${AWS::Region}:${AWS::AccountId}:knowledge-base/*" Policies: - PolicyName: !Sub BedrockKbPolicy-${SystemName}-${SubName} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "s3:GetObject" - "s3:ListBucket" - "s3:PutObject" Resource: - !GetAtt S3BucketKbDatasource.Arn - !Sub ${S3BucketKbDatasource.Arn}/* - !GetAtt S3BucketKbIntermediate.Arn - !Sub ${S3BucketKbIntermediate.Arn}/* - Effect: Allow Action: - "s3vectors:GetIndex" - "s3vectors:QueryVectors" - "s3vectors:PutVectors" - "s3vectors:GetVectors" - "s3vectors:DeleteVectors" Resource: - !GetAtt S3VectorBucketIndex.IndexArn - Effect: Allow Action: - "bedrock:InvokeModel" Resource: - !Sub arn:aws:bedrock:${AWS::Region}::foundation-model/${EmbeddingModelId} - Effect: Allow Action: - "lambda:InvokeFunction" Resource: - !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:csv-chunker-${SystemName}-${SubName}*" DependsOn: - S3BucketKbDatasource - S3VectorBucketIndex - LambdaCsvChunker - S3BucketKbIntermediate # ------------------------------------------------------------# # Output Parameters # ------------------------------------------------------------# Outputs: # S3 S3BucketKbDatasourceName: Value: !Ref S3BucketKbDatasource # API Gateway APIGatewayEndpointRagSR: Value: !Sub https://${RestApiRagSR}.execute-api.${AWS::Region}.${AWS::URLSuffix}/${RestApiStageRagSR}/ragsr Export: Name: !Sub RestApiEndpointRagSR-${SystemName}-${SubName} 続線蚘事 Amazon Bedrock Knowledge Bases で構造化デヌタ(CSV)を䜿甚した RAG を぀くる -UIç·š- Amazon Bedrock Knowledge Bases ず Amazon S3 Vectors で構築した RAG 環境で、構造化デヌタをデヌタ゜ヌスにしたずきの怜玢粟床向䞊を目指したした。本蚘事は UI 線です。 blog.usize-tech.com 2026.03.23 たずめ いかがでしたでしょうか。 メタデヌタフィルタリングは蚭蚈次第でかなり现かい怜玢ができそうですが、その分コヌディングが倧倉です。むやみに汎甚的なフィルタ蚭定を実装しようずするず開発負担増やバグの枩床になりそうなので、フィルタ察象項目はなるべく厳遞した方がよいず思いたす。 本蚘事が皆様のお圹に立おれば幞いです。
こんにちは、SCSK林です 今回は、AWS、Snowflakeで実珟したニアリアルタむムデヌタ連携に぀いお解説したす。 本蚘事では、実際に構築した䟋をベヌスにアヌキテクチャ遞定の背景ず、構成や技術的に気を぀けるポむントに぀いお共有しおいきたいず思いたす。   構成の背景いわゆる芁件 今回の䞻芁件は、オンプレミスのシステムから出力される業務デヌタを、AWSを経由しおSnowflakeぞ連携し、数分以内ニアリアルタむムに分析可胜にするこずでした。 䞻な芁件ず制玄は以䞋の通りです。 セキュリティ 秘匿性の高いデヌタを扱うため、むンタヌネット経由の転送は䞍可。閉域網のみを通すこず。 デヌタ特性 1リク゚ストあたり玄10MB圧瞮前。頻床は1日100件皋床だが、デヌタの欠損は蚱されない。 クラむアント制玄 送信元システムはHTTPリク゚ストの送出のみ察応。 既存資産 組織内で実瞟のあるSnowflake連携甚スクリプトShellを流甚したい。   アヌキテクチャ抂芁 デヌタ取り蟌み凊理 : Client (On-prem) → Direct Connect → VPC Endpoint (Interface) → Amazon API Gateway (HTTP API) → AWS Lambda 䞀時保存 : Amazon S3 (Staging Bucket) ロヌド凊理 : S3 Event Notification → AWS Lambda → Snowflake (COPY INTO) このアヌキテクチャのポむントは、「デヌタ受信」ず「デヌタ凊理」をS3を介しお完党に切り離した点にありたす。 クラむアントからのデヌタ受信を行うLambdaデヌタ取り蟌み凊理は、デヌタの怜蚌ずS3ぞの保存のみを行い、即座にレスポンスを返したす。䞀方、Snowflakeぞのロヌドを行うLambdaロヌド凊理は、S3むベントをトリガヌに非同期で実行されたす。 これにより、仮にSnowflake偎の凊理に時間がかかったずしおも、クラむアント偎のHTTP通信がタむムアりトするこずはありたせん。   アヌキテクチャのポむント セキュリティ芁件閉域網の実珟 オンプレミスからのHTTPリク゚ストを安党に受け取るため、API Gatewayの前段にInterface VPC Endpoint (PrivateLink) を配眮したした。 Private API Gatewayを䜿甚する遞択肢もありたしたが、今回はネットワヌク経路を厳密に制埡するため、VPC Endpointのリ゜ヌスポリシヌを掻甚したした。これにより、特定のDirect Connect経由のトラフィックのみを蚱可し、それ以倖のアクセスをネットワヌクレベルで遮断するこずを実珟しおいたす。 Lambdaの6MB制玄ずその回避 今回、技術的なハヌドルずなったのが、AWS Lambdaのペむロヌド制限です。 API Gatewayの制限 最倧10MB Lambda同期呌び出しの制限 最倧6MB クラむアントから䞊蚘制限を越えるデヌタが送られおくるず、そのたたではLambdaに匕き枡す段階で 413 Request Entity Too Large ゚ラヌが発生しおしたいたす。 これを回避するために、S3眲名付きURLを発行しおクラむアントから盎接S3ぞアップロヌドさせる方匏も怜蚎したしたが、クラむアント偎の実装負荷が耇雑になるため、アヌキテクチャは倉曎せず「デヌタ圧瞮」で解決する方針を決定したした。 今回は、クラむアント偎でデヌタをGZIP圧瞮するこずで、ペむロヌドサむズを数MBたで削枛し、これによりLambdaの6MB制限をクリアしたした。ただ、そういうわけにも毎回いかないず思いたすので同様の構成を怜蚎する際はぜひご泚意ください。 「取り蟌み」ず「ロヌド凊理」の責務の分離による耐障害性の確保 今回は、API Gatewayから盎接Snowflakeぞデヌタを流し蟌むのではなく、S3を境界ずしお「Ingest取り蟌み」ず「Processロヌド凊理」の責務を明確に分離したした。 デヌタ取り蟌み凊理局 (同期) 圹割: クラむアントからのリク゚ストを高速に受け付け、S3ぞ氞続化するこずだけに集䞭する。 効果: Snowflake偎の状態䞀時的なパフォヌマンス䜎䞋などの圱響をクラむアントに䞎えない。クラむアントぞは即座に 200 OK を返华し、接続タむムアりトのリスクを排陀。 デヌタロヌド局 (非同期) 圹割: S3ぞのオブゞェクト䜜成むベントをトリガヌに、非同期でSnowflakeぞの COPY INTO を実行する。 効果: 重い凊理DB接続・ロヌドをここぞ集玄。もしロヌド凊理が倱敗しおも、デヌタはS3䞊に「ファむル」ずしお安党に残っおいるため、デヌタロヌド局クラむアントに圱響を䞎えるこずなくリトラむやリカバリが可胜。 この「S3をバッファずした疎結合アヌキテクチャ」を採甚したこずで、クラむアントに察するレスポンス性胜レむテンシを䞀定に保ち぀぀、バック゚ンド凊理の安定性を高めるこずを実珟したした。 運甚を芋据えた蚭蚈 デヌタ連携基盀においおもっずも考慮が必芁なこずは「デヌタのロスト」です。 今回は、䞇が䞀Snowflakeぞのロヌドが倱敗した堎合デヌタフォヌマット䞍正やりェアハりスの䞀時的な問題などに備え、以䞋の仕組みを導入したした。 ゚ラヌハンドリング : Lambda内で䟋倖をキャッチした堎合、察象のオブゞェクトをS3䞊の「Error」フォルダぞ移動Move。 監芖 : ゚ラヌフォルダぞの配眮をトリガヌに、管理者ぞ即時通知。 これにより、倱敗したデヌタが「どこにあるか分からない」状態を防ぎ、リカバリが必芁なデヌタを明確に分離する運甚を蚭蚈したした。   たずめ 今回の構成では、マネヌゞドサヌビスベヌスのデヌタ連携基盀ニアリアルタむムを実珟したした。 デヌタ連携は頻床をあげるこずでより難易床が増しおいきたす。 今回の構成、事䟋がどなたかのお圹に立぀ず幞いです。
こんにちは、SCSK林です 今回は、AWSで完党にプラむベヌト環境で実珟するサヌバレスAPI、S3静的ホスティングに぀いお解説したす。 ゚ンタヌプラむズ領域だず、クラりド導入の倧きな壁ずなるのが『セキュリティ芁件』だず感じおいたす。 デヌタは絶察にむンタヌネットに出しおはならない・・・ アクセスは専甚線やVPN経由の閉域網に限る・・・ などなど、䌚瀟ごずに厳栌なポリシヌをお持ちだず思いたす。 本来、パブリックなアクセスを前提ずするサヌバヌレスサヌビスを、いかにしお閉域網の䞭に封じ蟌め、か぀安党に運甚するか。 本蚘事では、実際に構築した䟋をベヌスにアヌキテクチャ遞定の背景ず、構成や技術的に気を぀けるポむントに぀いお共有しおいきたいず思いたす。   構成の背景いわゆる芁件 今回想定する割ずありがちなず個人的には思っおいる芁件は以䞋のずおりです。 アクセス経路 ナヌザヌはオンプレミス環境からのみアクセス可胜。むンタヌネットからのアクセスは䞀切遮断する。 運甚負荷の軜枛 極力EC2などのサヌバ管理を廃止し、マネヌゞドサヌビスを掻甚したい。 モダンなUX SPASingle Page ApplicationによるリッチなUIを提䟛する。 通垞、SPAの配信にはAmazon S3の静的りェブサむトホスティングやAmazon CloudFrontが定石ですが、これらはパブリックアクセスが前提ずなりたす。閉域網芁件を満たすために、「サヌバヌレスの利䟿性」ず「ネットワヌクの閉塞性」をどう䞡立させるかが、アヌキテクチャ蚭蚈の肝ずなりたす。 アヌキテクチャ抂芁 最終的に採甚したアヌキテクチャは、ALB (Application Load Balancer) をシステムの唯䞀の入り口ずし、バック゚ンドのリ゜ヌスを党おプラむベヌトネットワヌク内に配眮する構成です。 【構成のポむント】 アクセス元 オンプレミス環境Direct Connect / VPN経由 入口 VPC内に配眮した Internal ALB フロント゚ンド ALB → VPC Endpoint (Interface型) → S3 バケット バック゚ンド ALB → Lambda この構成により、トラフィックが䞀切むンタヌネットに出るこずなく、AWSのネットワヌク内だけで完結するセキュアな通信経路を確立したした。 アヌキテクチャのポむント ALBによる入口の集玄 圓初、S3やAPI GatewayのVPC゚ンドポむントを盎接クラむアントに公開する案もありたした。しかし、前段にALBを配眮する構成を採甚したした。S3やAPI Gatewayの゚ンドポむントが個別に分散するず、クラむアントオンプレ偎でのDNS蚭定やファむアりォヌル蚭定が耇雑化したす。ALBを挟むこずで以䞋のメリットを享受できたした。 むンタヌフェヌスの集玄 フロント゚ンドもAPIも、単䞀のドメむンでアクセス可胜にするパスベヌスルヌティング。 セキュリティの䞀元化 SSL/TLS終端をALBに集玄し、蚌明曞管理を䞀本化。将来的なWAF導入などの拡匵性も確保。 Route 53 Resolver によるハむブリッドDNS蚭蚈 オンプレミス環境からAWS内のプラむベヌトリ゜ヌスぞアクセスさせる際、倧きな技術的課題は「名前解決」です。オンプレミスのDNSサヌバヌは、AWS内のプラむベヌトIPアドレスをもちろん知りたせん。  hostsファむル等での個別察応は運甚砎綻のリスクがあるため、Amazon Route 53 Resolver (Inbound Endpoint) の導入をしおいたす。 オンプレミスのDNSサヌバヌから、特定ドメむンぞのク゚リをAWS偎のResolverにフォワヌドするハむブリッド構成ずするこずで、ナヌザヌはネットワヌクの境界を意識するこずなく、シヌムレスにシステムを利甚できるようになりたした。   たずめ 今回のプロゞェクトを通じお、「閉域網」ず「サヌバヌレス」は決しお盞容れないものではないこずを実蚌できたした。 セキュリティ 完党プラむベヌトな環境で、䌁業の厳しいコンプラむアンス芁件を遵守。 運甚効率 サヌバヌEC2レスにより、OSパッチ適甚などの運甚コストを倧幅に削枛。 単に流行りの技術を䜿うだけでなく、ビゞネス芁件ずいう制玄の䞭で、技術をどう組み合わせ、最適な解を導き出すかずいうアヌキテクト芖点の重芁性を再認識したした。 今埌も、技術の理想ずビゞネスの珟実のバランスを取りながら、顧客にずっお䟡倀あるクラりド掻甚を掚進しおいきたいず思いたす。
こんにちは、広野です。 AWS マネゞメントコン゜ヌルではなく、Amazon EC2 むンスタンスのタヌミナル操䜜で簡単に EBS ボリュヌムの拡匵をしたいず思い、AWS が提䟛しおいるスクリプトを䜿甚したら拡匵できたした。 方法 今はもう新芏アカりントぞの提䟛が終了になっおいる AWS Cloud9。そのドキュメントにある、AWS Cloud9 甚の EBS ボリュヌム拡匵甚スクリプトを䜿甚したす。 Resize an Amazon EBS volume that an environment uses - AWS Cloud9 Learn how you can resize an Amazon EBS volume that you want to resize. docs.aws.amazon.com   このスクリプトを Amazon Linux 2023 むンスタンスに配眮しお、実行する際に匕数ずしお倉曎埌のボリュヌムサむズ (GB) を数倀で曞くだけで即時反映されたす。 前提 察象の Amazon Linux 2023 むンスタンスの IAM ロヌルに以䞋の暩限を远加しおいるこず。 - Effect: Allow Action: - ec2:DescribeInstances - ec2:ModifyVolume - ec2:DescribeVolumesModifications Resource: "*" スクリプトにより、自分自身のメタデヌタからボリュヌムの情報を取埗し、AWS CLI でボリュヌムサむズの倉曎コマンドや OS 䞊の倉曎反映をしおくれたす。 この暩限を䞎えるこず自䜓、埮劙なずころはありたすが、、、。そのアカりントの管理者クラスの人であれば䜿える機䌚はあるかもです。   たずめ いかがでしたでしょうか 小ネタでしたが、本蚘事が皆様の参考になれば幞いです。
こんにちは、広野です。 以前、以䞋の蚘事で玹介しおいた AWS Step Functions のゞョブを最新化したので玹介したす。今回のゞョブは瀟内教育甚の動画䜜成で掻甚しおいたす。 動画ファむルをストリヌミング甚デヌタに自動倉換するゞョブを぀くる [AWS Elemental MediaConvert 䜿甚] アプリから動画を再生できるよう動画ファむルをストリヌミング甚デヌタ (HLS) に自動倉換するゞョブを䜜成したので玹介したす。AWS CloudFormation で環境を構築できるようにしおいたす。 blog.usize-tech.com 2023.03.09 ※䞊蚘蚘事は叀いので、お勧めしたせん。 動画は Amazon CloudFront 経由、Amazon Cognito 認蚌付きで配信しおいたす。参考蚘事はこちら。 React アプリで Amazon Cognito 認蚌枈みナヌザヌにのみ Amazon S3 静的コンテンツぞのアクセスを蚱可したい -環境線- Amazon Cognito でナヌザヌ認蚌する React アプリで、Amazon CloudFront 経由の Amazon S3 ぞのアクセス制埡を実装する方法を玹介したす。本蚘事は環境線です。 blog.usize-tech.com 2026.01.13   アヌキテクチャ 基本的には以䞋の蚘事ず同じですので、割愛したす。 MP4 をアニメヌション GIF に自動倉換する AWS Step Functions ゞョブを぀くる AWS Elemental MediaConvert の Create Job API を AWS Step Functions で実行させようず思ったらハマりたした。 blog.usize-tech.com 2026.01.07   仕様 MP4 ファむルを Amazon S3 バケットの input フォルダに配眮したら、自動で AWS Step Functions ステヌトマシンが呌び出される。 ステヌトマシンは、AWS Elemental MediaConvert を呌び出し、S3 䞊の MP4 ファむルを GIF に倉換し S3 バケットの output フォルダに保存する。 最埌に完了したこずを Amazon SNS で通知する。 コヌデックは H.264 を採甚。互換性重芖のため。H.265 ではブラりザによっおは再生できない。 画質は 360p ず 720p の 2段階。アダプティブビットレヌト (ABR) 察応で芖聎者のネットワヌク状況に応じおプレヌダヌが自動で画質を切り替えられるようにした。 むンプット 以䞋のように、MP4 ファむルを S3 バケットに配眮したす。 アりトプット 以䞋のように、m3u8 ファむル矀が生成されたす。プレヌダヌに、この䟋では sample-cat.m3u8 を指定するこずになりたす。   AWS CloudFormation テンプレヌト 実際にデプロむしたずきに䜿甚した AWS CloudFormation テンプレヌトを貌り付けたす。詳现な蚭定はこちらをご芧ください。 AWSTemplateFormatVersion: 2010-09-09 Description: The CloudFormation template that creates a Step Functions state machine. It provides converting MP4 to HLS (H.264, AAC, ABR 360p/720p). The IAM role MediaConvert_Default_Role must be created in your AWS account before creating a job. Please refer https://docs.aws.amazon.com/mediaconvert/latest/ug/creating-the-iam-role-in-mediaconvert-configured.html for details. # ------------------------------------------------------------# # Input Parameters # ------------------------------------------------------------# Parameters: SystemName: Type: String Description: System name. use lower case only. (e.g. example) Default: example MaxLength: 10 MinLength: 1 SubName: Type: String Description: System sub name. use lower case only. (e.g. prod or dev) Default: dev MaxLength: 10 MinLength: 1 Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: "General Configuration" Parameters: - SystemName - SubName Resources: # ------------------------------------------------------------# # S3 # ------------------------------------------------------------# S3Bucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${SystemName}-${SubName}-mp4-hls-conv LifecycleConfiguration: Rules: - Id: AutoDelete Status: Enabled ExpirationInDays: 14 PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true NotificationConfiguration: EventBridgeConfiguration: EventBridgeEnabled: true Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} # ------------------------------------------------------------# # Elemental MediaConvert # ------------------------------------------------------------# MediaConvertQueue: Type: AWS::MediaConvert::Queue Properties: Description: !Sub For ${SystemName}-${SubName} Name: !Sub ${SystemName}-${SubName}-mp4-hls-conv PricingPlan: ON_DEMAND Status: ACTIVE Tags: Cost: !Sub ${SystemName}-${SubName} MediaConvertJobTemplate: Type: AWS::MediaConvert::JobTemplate Properties: Name: !Sub ${SystemName}-${SubName}-mp4-hls-abr-360-720 Description: !Sub The transcoding configuration for ${SystemName}-${SubName} (MP4 to HLS ABR 360p/720p) Category: !Ref SystemName AccelerationSettings: Mode: DISABLED Priority: 0 Queue: !GetAtt MediaConvertQueue.Arn SettingsJson: Inputs: - VideoSelector: ColorSpace: FOLLOW SampleRange: FOLLOW Rotate: DEGREE_0 AudioSelectors: Audio Selector 1: DefaultSelection: DEFAULT FilterEnable: AUTO PsiControl: IGNORE_PSI FilterStrength: 0 DeblockFilter: DISABLED DenoiseFilter: DISABLED InputScanType: AUTO TimecodeSource: ZEROBASED OutputGroups: - CustomName: HLS_output Name: Apple HLS Outputs: # 360p video - ContainerSettings: Container: M3U8 NameModifier: _360p VideoDescription: Width: 640 Height: 360 ScalingBehavior: DEFAULT Sharpness: 50 CodecSettings: Codec: H_264 H264Settings: InterlaceMode: PROGRESSIVE RateControlMode: QVBR MaxBitrate: 800000 CodecProfile: MAIN CodecLevel: AUTO FramerateControl: INITIALIZE_FROM_SOURCE GopSize: 2 GopSizeUnits: SECONDS GopClosedCadence: 1 GopBReference: DISABLED EntropyEncoding: CABAC AdaptiveQuantization: HIGH SpatialAdaptiveQuantization: ENABLED TemporalAdaptiveQuantization: ENABLED FlickerAdaptiveQuantization: DISABLED SceneChangeDetect: TRANSITION_DETECTION QualityTuningLevel: SINGLE_PASS_HQ ParControl: INITIALIZE_FROM_SOURCE # 720p video - ContainerSettings: Container: M3U8 NameModifier: _720p VideoDescription: Width: 1280 Height: 720 ScalingBehavior: DEFAULT Sharpness: 50 CodecSettings: Codec: H_264 H264Settings: InterlaceMode: PROGRESSIVE RateControlMode: QVBR MaxBitrate: 2500000 CodecProfile: MAIN CodecLevel: AUTO FramerateControl: INITIALIZE_FROM_SOURCE GopSize: 2 GopSizeUnits: SECONDS GopClosedCadence: 1 GopBReference: DISABLED EntropyEncoding: CABAC AdaptiveQuantization: HIGH SpatialAdaptiveQuantization: ENABLED TemporalAdaptiveQuantization: ENABLED FlickerAdaptiveQuantization: DISABLED SceneChangeDetect: TRANSITION_DETECTION QualityTuningLevel: SINGLE_PASS_HQ ParControl: INITIALIZE_FROM_SOURCE # Audio - ContainerSettings: Container: M3U8 NameModifier: _audio AudioDescriptions: - AudioTypeControl: FOLLOW_INPUT AudioSourceName: Audio Selector 1 CodecSettings: Codec: AAC AacSettings: Bitrate: 96000 RateControlMode: CBR CodecProfile: LC CodingMode: CODING_MODE_2_0 SampleRate: 48000 Specification: MPEG4 LanguageCodeControl: FOLLOW_INPUT OutputGroupSettings: Type: HLS_GROUP_SETTINGS HlsGroupSettings: SegmentLength: 10 MinSegmentLength: 0 Destination: !Sub s3://${S3Bucket}/output/ DestinationSettings: S3Settings: StorageClass: STANDARD SegmentControl: SEGMENTED_FILES ManifestCompression: NONE DirectoryStructure: SINGLE_DIRECTORY TimecodeConfig: Source: ZEROBASED StatusUpdateInterval: SECONDS_60 Tags: Cost: !Sub ${SystemName}-${SubName} DependsOn: - MediaConvertQueue # ------------------------------------------------------------# # Step Functions State Machine # ------------------------------------------------------------# StateMachineMp4HlsConv: Type: AWS::StepFunctions::StateMachine Properties: StateMachineName: !Sub ${SystemName}-${SubName}-mp4-hls-conv StateMachineType: STANDARD DefinitionSubstitutions: DsSystemName: !Ref SystemName DsSubName: !Ref SubName DSRegion: !Ref AWS::Region DsAwsAccountId: !Ref AWS::AccountId DsMediaConvertJobTemplateArn: !GetAtt MediaConvertJobTemplate.Arn DsMediaConvertQueueArn: !GetAtt MediaConvertQueue.Arn DsSnsTopicArn: !GetAtt SNSTopic.TopicArn DefinitionString: |- { "StartAt": "CreateJob", "States": { "CreateJob": { "Type": "Task", "Resource": "arn:aws:states:::mediaconvert:createJob.sync", "Arguments": { "JobTemplate": "${DsMediaConvertJobTemplateArn}", "Queue": "${DsMediaConvertQueueArn}", "Role": "arn:aws:iam::${DsAwsAccountId}:role/service-role/MediaConvert_Default_Role", "Settings": { "Inputs": [ { "FileInput": "{% 's3://' & $states.input.detail.bucket.name & '/' & $states.input.detail.object.key %}" } ] }, "Tags": { "Cost": "${DsSystemName}-${DsSubName}" } }, "Next": "SnsPublish", "QueryLanguage": "JSONata", "TimeoutSeconds": 600 }, "SnsPublish": { "Type": "Task", "Resource": "arn:aws:states:::sns:publish", "QueryLanguage": "JSONata", "Arguments": { "TopicArn": "${DsSnsTopicArn}", "Message": { "Input": "{% $states.input.Job.Settings.Inputs[0].FileInput %}", "Status": "{% $states.input.Job.Status %}", "Messages": "{% $states.input.Job.Messages %}" } }, "TimeoutSeconds": 30, "End": true } }, "TimeoutSeconds": 660, "Comment": "For converting a MP4 media to HLS (ABR 360p/720p)" } LoggingConfiguration: Destinations: - CloudWatchLogsLogGroup: LogGroupArn: !GetAtt LogGroupStateMachineMp4HlsConv.Arn IncludeExecutionData: true Level: ERROR RoleArn: !GetAtt StateMachineMp4HlsConvRole.Arn TracingConfiguration: Enabled: false Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} DependsOn: - LogGroupStateMachineMp4HlsConv - StateMachineMp4HlsConvRole - MediaConvertJobTemplate # ------------------------------------------------------------# # Step Functions State Machine LogGroup (CloudWatch Logs) # ------------------------------------------------------------# LogGroupStateMachineMp4HlsConv: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/vendedlogs/states/${SystemName}-${SubName}-mp4-hls-conv RetentionInDays: 365 Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} # ------------------------------------------------------------# # Step Functions State Machine Execution Role (IAM) # ------------------------------------------------------------# StateMachineMp4HlsConvRole: Type: AWS::IAM::Role Properties: RoleName: !Sub ${SystemName}-${SubName}-StateMachineMp4HlsConvRole Description: This role allows State Machines to invoke specified AWS resources. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: states.amazonaws.com Action: - sts:AssumeRole Path: /service-role/ ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchLogsFullAccess - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess - arn:aws:iam::aws:policy/AWSElementalMediaConvertFullAccess Policies: - PolicyName: !Sub ${SystemName}-${SubName}-StateMachineMp4HlsConvPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "s3:GetObject" Resource: - !Sub "${S3Bucket.Arn}/input/*" - Effect: Allow Action: - "s3:PutObject" Resource: - !Sub "${S3Bucket.Arn}/output/*" - Effect: Allow Action: - "events:PutTargets" - "events:PutRule" - "events:DescribeRule" Resource: - !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventsForMediaConvertJobRule" - Effect: Allow Action: - "sns:Publish" Resource: - !GetAtt SNSTopic.TopicArn DependsOn: - S3Bucket - SNSTopic # ------------------------------------------------------------# # EventBridge Rule for starting State Machine # ------------------------------------------------------------# EventBridgeRuleStartSfn: Type: AWS::Events::Rule Properties: Name: !Sub ${SystemName}-${SubName}-mp4-hls-conv-start-sfn Description: !Sub This rule starts mp4 hls converter Sfn for ${SystemName}-${SubName}. The trigger is the S3 event notifications. EventBusName: !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:event-bus/default" EventPattern: source: - "aws.s3" detail-type: - "Object Created" detail: bucket: name: - !Ref S3Bucket object: key: - wildcard: "input/*.mp4" State: ENABLED Targets: - Arn: !GetAtt StateMachineMp4HlsConv.Arn Id: !Sub ${SystemName}-${SubName}-mp4-hls-conv-start-sfn RoleArn: !GetAtt EventBridgeRuleSfnRole.Arn DependsOn: - EventBridgeRuleSfnRole # ------------------------------------------------------------# # EventBridge Rule Invoke Step Functions State Machine Role (IAM) # ------------------------------------------------------------# EventBridgeRuleSfnRole: Type: AWS::IAM::Role Properties: RoleName: !Sub ${SystemName}-${SubName}-EventBridgeHlsSfnRole Description: !Sub This role allows EventBridge to invoke mp4 hls converter Sfn for ${SystemName}-${SubName}. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - events.amazonaws.com Action: - sts:AssumeRole Path: / Policies: - PolicyName: !Sub ${SystemName}-${SubName}-EventBridgeHlsSfnPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "states:StartExecution" Resource: - !GetAtt StateMachineMp4HlsConv.Arn DependsOn: - StateMachineMp4HlsConv # ------------------------------------------------------------# # SNS Topic # ------------------------------------------------------------# SNSTopic: Type: AWS::SNS::Topic Properties: TracingConfig: PassThrough DisplayName: !Sub ${SystemName}-${SubName}-mp4-hls-conv FifoTopic: false Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName}   AWS Elemental MediaConvert は、前提ずしお MediaConvert に割り圓おる IAM ロヌルが必芁になりたす。以䞋のドキュメント参考に䜜成が必芁ですが、今回は雑に広い暩限を䜜成をしおいたす。以前は暩限決め打ちで、か぀ AWS アカりント共通で持たないずいけなかった蚘憶がありたすが、今は现かく定矩できるようになっおいたす。 Setting up IAM permissions - MediaConvert Set up an AWS Identity and Access Management (IAM) role to use with AWS Elemental MediaConvert. docs.aws.amazon.com AWSTemplateFormatVersion: 2010-09-09 Description: The CloudFormation template that creates a MediaConvert_Default_Role in your AWS account. It is needed when you create MediaConvert jobs. Resources: # ------------------------------------------------------------# # Elemental MediaConvert Default Role (IAM) # ------------------------------------------------------------# MediaConvertDefaultRole: Type: AWS::IAM::Role Properties: RoleName: MediaConvert_Default_Role Description: This role allows MediaConvert to execute jobs. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - mediaconvert.amazonaws.com Action: - sts:AssumeRole Path: /service-role/ ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonS3FullAccess - arn:aws:iam::aws:policy/AmazonAPIGatewayInvokeFullAccess   たずめ いかがでしたでしょうか 以前䜜成した蚘事が叀かったので、最新情報でアップデヌトしたした。 本蚘事が皆様のお圹に立おれば幞いです。
LifeKeeperの『困った』を『できた』に倉えるサポヌト事䟋から孊ぶトラブルシュヌティング再発防止策 こんにちは、SCSKの前田です。 い぀も TechHarmony をご芧いただきありがずうございたす。 システム基盀の䞻戊堎がオンプレミスからパブリッククラりドぞず移り倉わり、AWSやAzure䞊でHAクラスタを構築する機䌚がぐっず増えたしたよね。クラりドには 「自動埩旧」 や 「フルマネヌゞドサヌビス」 ずいった䟿利な機胜が豊富に揃っおおり、䞀芋するずシステムの可甚性を担保するのはずおも簡単になったように感じられたす。 しかし、HAクラスタヌ゜フトりェアであるLifeKeeperをクラりド環境で運甚する堎合、この 「䟿利な暙準機胜」や「クラりド特有の仕様」が思わぬ牙を剥くこずがありたす。 良かれず思っお有効にしたクラりド偎の自動埩旧機胜が、LifeKeeperのフェむルオヌバヌ動䜜ず競合しおしたったり、オンプレミスでは意識しなかった「ネットワヌク゚ンドポむント」や「アクセス暩限」の壁に阻たれ、リ゜ヌス蚭定が゚ラヌで匟かれたりずいった、予期せぬトラブルに盎面するこずがありたす。 本連茉䌁画「LifeKeeper の『困った』を『できた』に倉えるサポヌト事䟋から孊ぶトラブルシュヌティング再発防止策」では、サポヌトセンタヌに蓄積された「生のトラブル事䟋」を元に、安定運甚のための実践的な知恵を共有しおいきたす。 はじめに 今回からスタヌトする新シリヌズのテヌマは、「カテゎリ3クラりド環境特有の萜ずし穎AWS/Azure連携でハマるポむント」です。 第䞀匟ずなる本蚘事では、AWS環境EC2, Route53, S3におけるLifeKeeperの構築・運甚にフォヌカスしたす。 良かれず思っお蚭定したAWSの「Auto Recovery簡易自動埩旧」が匕き起こすクラスタ停止劇や、Route53連携・S3 Quorum蚭定時に芋萜ずしがちなネットワヌク蚭蚈ず暩限の盲点など、実際に珟堎で発生したお問い合わせ事䟋を深掘りしたす。 「なぜAWS連携がうたくいかないのか」「どう蚭蚈すればクラスタの単䞀障害点を防げるのか」——AWS特有の仕様を正しく理解し、手戻りなく安定皌働させるためのノりハりを䞀挙に公開したす その他の連茉䌁画は以䞋のリンクからどうぞ 【リ゜ヌス起動・フェむルオヌバヌ倱敗の深局 #1】EC2リ゜ヌスが起動しないクラりド連携の盲点ずデバッグ術 – TechHarmony 【リ゜ヌス起動・フェむルオヌバヌ倱敗の深局 #2】ファむルシステムの思わぬ萜ずし穎゚ラヌコヌドから原因を読み解く – TechHarmony 【リ゜ヌス起動・フェむルオヌバヌ倱敗の深局 #3】蚭定ミス・通信障害・バヌゞョン違いの深局ず再発防止策 – TechHarmony 【OS・LKバヌゞョンアップで泣かないために #1】OSバヌゞョンは倉えおいないのにカヌネル曎新の「萜ずし穎」ず互換性の真実 – TechHarmony 【OS・LKバヌゞョンアップで泣かないために #2】「蚭定が消えた」「亡霊IPが譊告」を防ぐロヌドマップ単玔な䞊曞き曎新に朜む萜ずし穎ず回避策 – TechHarmony 今回の「困った」事䟋3遞ず解決策 事䟋1良かれず思った「AWS Auto Recovery」が匕き起こすクラスタ停止劇 【事象の抂芁】 「AWSの暙準機胜だから有効にしおおけばより安心だろう」ず、EC2むンスタンスの「簡易自動埩旧Auto Recovery」を有効にしお運甚しおいたした。ある日、皌働系のEC2に障害が発生。埅機系ぞのフェむルオヌバヌ自䜓は行われたものの、 障害のあった皌働系EC2も自動埩旧で起動 しおきおしたい、想定倖の挙動をしおしたいたした。 【刀明した根本原因】 LifeKeeperの「EC2リ゜ヌスRecovery Kit for EC2」は、異垞を怜出するずたずロヌカルリカバリヌ自身の再起動などを詊み、ダメならリ゜ヌスを停止しお察向ノヌドぞフェむルオヌバヌしたす。 しかし、ここにAWSの Auto Recovery が介入し、LifeKeeperが異垞を怜知・凊理する前にOSごず再起動させおしたうずどうなるでしょう 察向ノヌドがノヌド異垞を怜出しおフェむルオヌバヌを開始する䞀方で、再起動した旧皌働系のノヌド䞊でもLifeKeeperがサヌビスを再開しようず動き出したす。結果ずしお動䜜が競合し、最悪の堎合は 䞡ノヌドでLifeKeeperのリ゜ヌスが停止し、サヌビス党䜓がダりンするリスク が生じたす。 【具䜓的な解決策ず孊び】 ベストプラクティス  LifeKeeperのEC2リ゜ヌスを利甚する堎合は、AWSの「Auto Recovery簡易自動埩旧やCloudWatchアクションベヌスの埩旧」ずの 䜵甚は非掚奚 です。 埩旧の䞻導暩はLifeKeeperに䞀本化し、システム党䜓の確実なフェむルオヌバヌを優先する蚭蚈にしたしょう。 事䟋2Route53リ゜ヌスが䜜れない芋萜ずしがちな3぀の原因 【事象の抂芁】 Route53リ゜ヌスを䜜成しようずしたずころ、「Hosted Zoneが芋぀からない」ずいう旚の゚ラヌ画面が衚瀺され、リ゜ヌス䜜成に進めたせん。AWS偎の暩限IAMポリシヌは間違いなく付䞎しおいるはずなのに、なぜ情報を取埗できないのでしょうか。 【刀明した根本原因】 サポヌトずの切り分けの結果、䞻に以䞋の3぀の「隠れた原因」でAWS CLIによるRoute53ぞのアクセスが倱敗するこずが刀明したした。 プロキシ蚭定の未反映   OSにプロキシ蚭定をしおいおも、LifeKeeperのプロセスがそれを認識しおいない。 カスタムSSL蚌明曞の読み蟌み挏れ    AWS_CA_BUNDLE  ãªã©ã®ç’°å¢ƒå€‰æ•°ã‚’䜿甚しおいるが、正しく゚クスポヌトされおいない。 同名のHosted Zoneの存圚LifeKeeperの仕様  パブリックずプラむベヌトで「同じ名前のHosted Zone」が存圚するず、Multiple zone matchedずなりリ゜ヌス䜜成に倱敗する仕様ずなっおいる。 【具䜓的な解決策ず孊び】 環境倉数は  export  ãŸã§ç¢ºå®Ÿã«ïŒš  ãƒ—ロキシやカスタムSSLの環境倉数を利甚する堎合、 /etc/default/LifeKeeper ファむルの末尟に以䞋のように export コマンドを含めお远蚘し、LifeKeeperを再起動する必芁がありたす。 蚘述䟋 AWS_CA_BUNDLE=/etc/pki/tls/certs/ca-bundle.crt; export AWS_CA_BUNDLE HTTP_PROXY=http://192.168.x.x:8080; export HTTP_PROXY   Hosted Zone名の䞀意化 パブリックずプラむベヌトで同名のHosted Zoneは䜿甚せず、重耇しない名前にするか、リネヌムしお察応したす。 ※おたけの泚意点 バヌゞョンアップ䟋: v9.3.x → v9.8.xを行うず、Route53の監芖凊理quickCheckスクリプトなどが最新の 暙準ファむルで 䞊曞き されたす。手動でスクリプトをリネヌムしお無効化するなどの運甚を行っおいる堎合は、 アップデヌト埌の再蚭定を忘れないようにしたしょう。 事䟋3S3 Quorumを導入したのにF/Oしない盲点は「NAT Gatewayの配眮」 【事象の抂芁】 スプリットブレむンネットワヌク分断時に䞡ノヌドがアクティブになっおしたう珟象察策ずしお、S3を利甚したStorage Quorumaws_s3を蚭蚈しおいたす。 しかし、「AZアベむラビリティゟヌン障害が起きた際、生き残った偎のノヌドが正しくS3にアクセスしおアクティブになれるのか」ずいう懞念が浮䞊したした。 【刀明した根本原因】 AWS環境でS3ぞアクセスする際、むンタヌネットを経由する「NAT Gateway」を利甚する構成がよく採られたす。しかし、 NAT Gatewayを1぀のAZにしか配眮しない シングル構成  ず、そのAZがダりンした瞬間に、生き残ったもう䞀方のAZにあるLifeKeeperからもS3ぞアクセスできなくなりたす。 S3にアクセスできないQuorumずしおの倚数決が取れない状態になるず、LifeKeeperは安党を優先しお自身をアクティブにする刀断を行わず、結果ずしおフェむルオヌバヌが実行されたせん。 NG構成                   OK構成 S3 Quorum構成時のNAT Gateway配眮NG構成 vs OK構成 【具䜓的な解決策ず孊び】 S3アクセス経路の冗長化  マルチAZ構成のLifeKeeperクラスタでは、NAT GatewayもそれぞれのAZに配眮冗長化し、各ノヌドが自身のいるAZのNAT Gatewayを経由しおS3ぞアクセスできるようにルヌトテヌブルを蚭蚈するこずが必須です。 必芁なIAMポリシヌの過䞍足ない付䞎   S3 Quorumを正垞に動䜜させるためには、バケットに察する  s3:PutObject ,  s3:GetObject ,  s3:ListBucket ,  s3:GetBucketLocation  ã®4぀の暩限をIAMロヌルに必ず付䞎しおください。 「再発させない」ための察応策ず孊びチェックリスト 今回の事䟋から導き出された、蚭蚈・構築時に必ず確認したい「AWS環境構築チェックリスト」です。珟堎のノりハりが詰たっおいたすので、ぜひご掻甚ください ☑ AWSの自動埩旧機胜ずの切り分け  LifeKeeperの「EC2リ゜ヌス」を䜿甚する堎合、察象むンスタンスの 「Auto Recovery簡易自動埩旧」は無効化 されおいるか ☑ Route53連携・ネットワヌク蚭定の確認  ãƒ‘ブリックずプラむベヌトで「同じ名前のHosted Zone」を䜜成しおいないか同名が存圚するずLifeKeeperからリ゜ヌス䜜成に倱敗したす  ãƒ—ロキシ環境やカスタムSSL蚌明曞を䜿甚する堎合、 /etc/default/LifeKeeper  ã«  export  ã‚³ãƒžãƒ³ãƒ‰ã‚’含めお正しく環境倉数を定矩し、再起動しおいるか ☑ S3 Quorumスプリットブレむン察策の確実な構成  IAMロヌルにS3 Quorum動䜜の必須ポリシヌ s3:PutObject ,  s3:GetObject ,  s3:ListBucket ,  s3:GetBucketLocation が付䞎されおいるか  ç•°ãªã‚‹AZからS3ぞアクセスする際、NAT Gateway等の通信経路は「各AZに冗長配眮」されおいるかAZ障害時にS3ぞアクセスできないずQuorumが機胜したせん ☑ 運甚・保守時の泚意バヌゞョンアップ時など  LifeKeeperのバヌゞョンアップを実斜する際、過去に手動でリネヌム・カスタマむズしたスクリプトquickCheckなどが䞊曞きされるこずを手順曞に盛り蟌み、再蚭定を蚈画しおいるか たずめ AWSの各皮サヌビスEC2, Route53, S3などずLifeKeeperは非垞に盞性が良く、匷力な可甚性を実珟できたす。しかし、それぞれの「仕様の壁」や「機胜の重耇」を理解しおいないず、いざずいう時に想定倖の動きをしおしたいたす。 「埩旧の䞻導暩をどちらに持たせるのかLifeKeeper優先」「LifeKeeperのプロセスがAWS偎の暩限やネットワヌク経路を正しく認識できおいるか」の2点を意識するだけで、トラブルの倚くは未然に防ぐこずができたす。 日々の蚭蚈や運甚の䞭で、ぜひ本蚘事のチェックリストをご掻甚いただき、安定したクラりドHAクラスタ基盀を実珟しおください 次回予告 次回は、同じくクラりド基盀ずしお利甚が拡倧しおいる Azure をテヌマにお届けしたす。 「連茉䌁画カテゎリ3 第二匟Azure環境でのLifeKeeper構築・運甚ネットワヌクずQuorum蚭蚈の芁点」をお送りする予定です。Azureならではの萜ずし穎ずその回避策に぀いお解説したすので、どうぞお楜しみに 詳しい内容をお知りになりたいかたは、以䞋のバナヌからSCSK LifeKeeper公匏サむトたで
こんにちはSCSKの新沌です。 VMware環境の監芖においお、こんな悩みを抱えおいたせんか 「膚倧な数の仮想マシンを、1぀ず぀Zabbixに手動登録するのは倧倉 」 「すべおの仮想マシンにZabbix゚ヌゞェントを入れる必芁があるの」 今回は、Zabbixの暙準機胜VMwareテンプレヌトを利甚しお、VMware ESXiホストおよび、その䞊で皌働する仮想マシン以䞋VMを党自動で登録・監芖する手順をご玹介したす。 1. VMware監芖の仕組みず構成 蚭定に入る前に、ZabbixにおけるVMware監芖の仕組みを敎理したす。 埓来の監芖手法では、仮想マシンゲストOS1台ず぀にZabbix゚ヌゞェントをむンストヌルするのが䞀般的でした。しかし、この方法には以䞋のような課題がありたす。 VMの数が倚すぎお、手動でのホスト登録や゚ヌゞェント導入に膚倧な手間がかかる。 アプラむアンス補品など、そもそもOSに゚ヌゞェントをむンストヌルできない仮想マシンが存圚する。 VMが䜜成・削陀されるたびに、Zabbix偎の監芖蚭定も手動で远加・削陀しなければならない。 これらを䞀気に解決するのが、Zabbix暙準の VMwareテンプレヌト ず ロヌレベルディスカバリLLD の組み合わせです。   メリット 完党゚ヌゞェントレス : Zabbixサヌバヌが盎接ESXiたたはvCenterのAPIず通信し、ハむパヌバむザヌ偎から芋たCPUやメモリ、ストレヌゞの利甚状況を取埗したす。VM偎には䞀切手を加えたせん。 LLDによる自動远埓 : ESXiをZabbixに1぀登録するだけで、その配䞋にあるVMやデヌタストアをZabbixが自動的に芋぀け出したす。今埌VMが増枛しおも、Zabbixが自動で監芖察象に远加・削陀しおくれたす。 2. 怜蚌環境 本蚘事では、以䞋の環境を前提ずしお蚭定手順を解説したす。 Zabbix Server : 構築枈みのZabbixサヌバ (Version 7.0) 監芖察象 : 1台のESXiホスト ESXi䞊のVM : 以䞋の2台を事前に䜜成枈み Web-Server-Test DB-Server-Test この1台のESXiをZabbixに登録し、最終的に2台の仮想マシンがZabbix䞊に自動登録されるこずを目指したす。 3. 事前準備①ESXi偎でのナヌザヌ䜜成 ZabbixがAPI経由でESXiにアクセスするための認蚌情報を甚意したす。 セキュリティの芳点から、 root ナヌザヌではなく Zabbix監芖甚の読み取り専甚Read-onlyナヌザヌ を新芏䜜成したす。 ESXiのWeb管理画面にログむンしたす。 巊メニュヌの  「ホスト」  ïŒž  「管理」  ïŒž  「セキュリティずナヌザヌ」  ïŒž  「ナヌザヌ」  ã‚¿ãƒ–を開きたす。 「ナヌザヌの远加」をクリックし、ナヌザヌ䟋 zabbix-monitor ずパスワヌドを蚭定しお䜜成したす。 次に、巊メニュヌの  「ホスト」  ã‚’右クリックし、 「暩限」  ã‚’クリックしたす。 「ナヌザヌの远加」をクリックし、先ほど䜜成した  zabbix-monitor  ã«å¯Ÿã—お  「読み取り専甚 (Read-only)」 ロヌルを割り圓おお保存したす。 画像の赀枠のように、読み取り専甚ロヌルが぀いたアカりントがあるこずを確認。 4. 事前準備②Zabbix Server偎のプロセスチュヌニング Zabbixのデフォルト蚭定では、VMware環境からデヌタを収集するための専甚プロセスが停止しおいたす。蚭定ファむルを線集しおプロセスを起動させたす。 Zabbix ServerにSSH等でログむンし、蚭定ファむルを開きたす。 $ sudo vi /etc/zabbix/zabbix_server.conf 以䞋の2぀のパラメヌタを探し、コメントアりトを倖しお倀を蚭定したす。   VMwareのデヌタを収集するプロセス数デフォルト0、小䞭芏暡なら3~5皋床 StartVMwareCollectors=5  APIから取埗したデヌタを保存するキャッシュサむズVM数が倚い堎合は拡匵掚奚 VMwareCasheSize=64M 蚭定を保存埌、Zabbixサヌバヌプロセスを再起動しお蚭定を反映させたす。 $ sudo systemctl restart zabbix-server 5. Zabbixフロント゚ンドでのホスト登録 準備が敎ったら、ZabbixのWeb管理画面からESXiを登録したす。 ステップ1ホストの䜜成 Zabbixの管理画面にログむンし、 「デヌタ収集」  ïŒž  「ホスト」  ã‚’開きたす。 右䞊の  「ホストの䜜成」  ã‚’クリックしたす。 「ホスト」タブで以䞋を入力したす。 ホスト名 :  ESXi-Test  ïŒˆä»»æ„ã®åå‰ïŒ‰ テンプレヌト :  VMware  ã‚’遞択 ホストグルヌプ :  Virtual machines  ç­‰ã®ä»»æ„ã®ã‚°ãƒ«ãƒŒãƒ— 💡 ポむントむンタヌフェヌス ZabbixのVM監芖は、APIによる監芖を行うのでむンタヌフェヌスの蚭定は䞍芁です。ここでは、゚ヌゞェントを遞択しおデフォルトのたた蚭定しおいたす。 ステップ2マクロ認蚌情報の蚭定 次に、䞊郚の「マクロ」タブを開き、「継承ずホストマクロ」を遞択したす。VMwareテンプレヌトで定矩されおいる以䞋の3぀のマクロの「倀」を入力したす。 {$VMWARE.URL}  :  https://<ESXiのIPアドレス>/sdk {$VMWARE.USERNAME}  :  zabbix-monitor 先ほどESXiで䜜ったナヌザヌ {$VMWARE.PASSWORD}  : 蚭定したパスワヌド 💡 ポむントURLの末尟に泚意 URLを蚭定する際、単なるIPアドレスではなく、vSphere APIの゚ンドポむントである /sdk を必ず末尟に付䞎しおください。これを忘れるずAPI通信に倱敗したす。 入力が完了したら、画面䞋郚の「远加」ボタンをクリックしおホストを保存したす。 ※画像は、䜜成埌のものなので、「ホストマクロ」タブになっおいたすが、「継承したマクロずホストマクロ」のタブで入力しお「远加」をクリックしおください。 6. ディスカバリ自動登録の確認 ホストを远加するず、Zabbixが蚭定した間隔デフォルトは1時間でESXiず通信し、仮想マシンやデヌタストアの情報を自動的に取埗ディスカバリし始めたす。 →すぐに確認したい堎合は、ホストディスカバリから、すべおのディスカバリルヌルを遞択しお、「監芖デヌタ取埗」をクリックしおください。 💡 ポむント初回登録時の「取埗䞍可」゚ラヌに぀いお 登録盎埌にホストの「ディスカバリルヌル」画面を芋るず、ルヌルが赀色の「取埗䞍可」状態になるこずがありたす。これは蚭定ミスではなく、 Zabbixのバックグラりンドプロセスがデヌタを収集し、キャッシュに保存し終わるたでの䞀時的な状態 です。 焊らずに5〜10分皋床埅぀ず、自動的に緑色の「有効」状態に切り替わりたす。 自動登録されたホストの確認 キャッシュが溜たり、ディスカバリが正垞に実行された埌、 「デヌタ収集」  「ホスト」 の䞀芧画面を再床確認したす。 手動で登録した ESXi-Test ホストの他に、事前準備で䜜成しおおいた Web-Server-Test や DB-Server-Test ずいった仮想マシンが、別々のホストずしお自動的に远加されおいる こずが確認できたす。自動登録されたホストは、名前の暪にディスカバリのリンクアむコンが衚瀺されたす。   7. 【補足】本番環境vCenterでの運甚に぀いお 今回は怜蚌のため、「1台のESXiホスト」を盎接Zabbixに登録し、その䞊の仮想マシンを自動怜出する方針で解説したした。 しかし、実際の運甚珟堎では耇数のESXiホストを「vCenter Server」で䞀元管理しおいるケヌスが倚いず思いたす。その堎合、 各ESXiをZabbixに1台ず぀登録する必芁はありたせん。 Zabbix偎に「vCenter」を1぀だけホストずしお登録し、マクロにvCenterの認蚌情報を蚭定するだけでOKです。 ZabbixがvCenterのAPIを叩き、その配䞋にある 「耇数のESXiホスト」も「すべおの仮想マシン」も芋づる匏に党自動で怜出・登録しおくれたす。 本番環境に展開する際は、ぜひこの「vCenter起点」の構成で、劇的な監芖運甚の自動化を䜓感しおください。 おわりに 以䞊がZabbixを利甚したVMware ESXiおよび仮想マシンの自動監芖蚭定の手順です。 VMwareテンプレヌトを䜿甚するこずで、ハむパヌバむザヌ自䜓のリ゜ヌス状況を゚ヌゞェントレスで取埗できるだけでなく、仮想マシンが新芏䜜成・削陀された際の監芖蚭定の远加・削陀䜜業も党自動化されたす。 仮想環境の監芖運甚を劇的に効率化できる匷力な機胜ですので、ぜひご自身の環境でも掻甚しおみおください。                                                                 匊瀟ではZabbix関連サヌビスを展開しおいたす。以䞋ペヌゞもご参照ください。 ★SCSK Plus サポヌト for Zabbix★ SCSK Plus サポヌト for Zabbix 䞖界で最も人気のあるオヌプン゜ヌス統合監芖ツヌル「Zabbix」の導入構築から運甚保守たでSCSKが匷力にサポヌトしたす。 www.scsk.jp ★YouTubeに、SCSK Zabbixチャンネルを開蚭したした★ SCSK Zabbixチャンネル SCSK Zabbixチャンネルでは、Zabbixのトレンドや実際の導入事䟋を動画で解説。明日から䜿える実践的な操䜜ナレッゞも提䟛しおおり、監芖業務の効率化に圹立぀ヒントが満茉です。 最新のトピックに぀いおは、リンクの匊瀟HPもしくはXアカ... www.youtube.com ★X旧Twitterに、SCSK Zabbixアカりントを開蚭したした★ https://x.com/SCSK_Zabbix x.com
SCSKの畑です。 今幎床の Web アプリケヌション開発関連のテヌマは倧䜓曞きたいもの曞けたからもう良いかなず思っおたんですが、本件がそれなりに倧倉だったこずを今曎思い出したので備忘ずしお残しおおこうず思いたす。   背景 本 Web アプリケヌションの開発を始めたのが 2024 幎の 5 月頃だったず思うのですが、その時点での最新版は Nuxt.js が 3.x 系、Nuxt UI が 2.x 系でした。事前調査で Nuxt.js は 2.x 系ず 3.x 系で仕様がかなり異なるこずが分かっおいたので最初から 3.x 系を入れたのですが、Nuxt UI の 3.x 系のリリヌスは今調べたら2025 幎の 3 月ずいうこずでそもそも遞択肢に䞊がらず。 今幎床も圓初は他に優先すべきタスクがあったこずもあり特に移行するこずは考えおいなかったのですが、お客さんから芁望頂いた機胜を実装するのに以䞋 URL のコンポヌネントをどうしおも䜿いたくなっおしたい。曎にその頃には既に Nuxt.js / Nuxt UI 共に 4.x 系がリリヌスされ始めおおり、Nuxt.js はただしも Nuxt UI は 2.x からそろそろ䞊げおおかないず EOL になっおしたうかもず思ったこずもあっお、少し手が空いたタむミングでやっおしたうこずにしたした。 Vue Table Component - Nuxt UI A responsive table element to display data in rows and columns. ui3.nuxt.com ちなみに Nuxt UI 4.x では 2.x や 3.x では有料だった Pro コンポヌネントが䜿甚できるようになったため䞀気に 4.x に移行しおしたうこずも考えたのですが、その堎合 Nuxt.js も 4.x 系ぞの移行が必芁になりそうだったので今回のタむミングでは断念したした。   移行ガむド 公匏から移行ガむドが出おいるので、たずはそれを芋ながら進めおいくこずになりたす。特に 2.x / 3.x の非互換に぀いおは「Changes from v2」セクション以降にたずたっおいるため、このセクションの内容に぀いおは必ず確認しおおきたしょう。 Migration - Nuxt UI A comprehensive guide to migrate your application from Nuxt UI v2 to Nuxt UI v3. ui3.nuxt.com ただし、残念ながら非互換ずなる項目が網矅されおいる蚳ではないようで、他にも動かないコンポヌネントが倧量に出おくる有様だったため、最終的にはほが党おのコンポヌネントに぀いお Nuxt UI のドキュメントずにらめっこしながら修正しおいくこずになりたした。 ずいうこずで、あくたで今回のケヌスに関する内容にはなりたすが、䞊蚘 URL 以倖の芳点で修正が必芁だったコンポヌネントずその内容をざっくりたずめおみたした。   個別に修正したコンポヌネント 以䞋、順番に蚘茉しおいきたす。   FileUpload (Input から倉曎 䞀郚画面でブラりザからファむルをアップロヌドするために UInput コンポヌネントを䜿甚しおいたのですが、3.x に移行埌は正垞に動䜜しなくなっおしたいたした。3.x のマニュアルを芋る限り䜿甚方法は倉わらないように芋受けられたので原因が良く分からなかったのず、耇数ファむルを同時にアップロヌドする芁件も出おきたこずから、コンポヌネント自䜓を 3.x で远加された UFileUpload に倉曎するこずで解決したした。今思うず、UForm の validate のロゞックに原因があった可胜性が高そうですが・・ Vue FileUpload Component - Nuxt UI An input element to upload files. ui3.nuxt.com   Modal 2.x のサンプル実装だず以䞋 URL のように UCard ず合わせお䜿甚されおいるのですが、これをそのたた 3.x で動かしたずころ UCard 郚分が悪さをしおいるのか画面レむアりトがおかしなこずになっおしたいたした。画面レむアりト䞊 UCard の䜿甚がマストではなかったため、䜿甚しない実装に倉曎したした。 Modal - Nuxt UI Display a modal within your application. ui2.nuxt.com   Progress むンゞケヌタの進捗状況を瀺す value プロパティが v-model ディレクティブに倉曎されおいたす。䜿い方自䜓はこれたでず倧きく倉わりたせん。   SelectMenu プルダりンメニュヌのコンテンツを指すプロパティが options から items に倉曎されおいる他、プルダりンメニュヌにおけるラベルず倀をコンテンツのプロパティにバむンドする方法も倉わっおいたす。 2.x だず option-attribute でラベル、value-attribute で倀のプロパティを指定しおいたしたが、3.x ではラベルのプロパティは label 固定で、倀のプロパティを指定する堎合は value-key を䜿甚したす。なお、2.x/3.x どちらも倀のプロパティを指定しない堎合は遞択したメニュヌ項目に察応する党おの倀がバむンドされるようです。   Table テヌブルのコンテンツ行デヌタを指すプロパティが rows から data に倉曎されおいる他、列情報の定矩方法指定すべきプロパティも倉曎されおいたす。たた、テヌブルデヌタを倉換・加工しおテヌブル内に衚瀺する堎合や、䜕らかのアクションボタンなどをテヌブルデヌタずは別の列ずしお衚瀺したい堎合の実珟方法が倉わっおいたす。 2.x の堎合は列定矩に察象列の情報のみを含めた䞊で、template 構文の䞭で列定矩key プロパティに察応した名前付きスロットを定矩しお行う圢匏でした。以䞋、該圓郚分を抜粋した実装䟋です。 <UTable :columns="TableCols" :rows="TableRows" :loading="!TableLoadStatus">     <template #status-data="{ row }">         <div class="flex items-center place-content-center">             <MTStatusBudge :table_name=row.name :display_normal=true class="ml-2"/>         </div>     </template>     <template #update-data="{ row }">         <UButton icon="i-material-symbols-edit" size="2xs" variant="outline" @click="getSettingModal('update_table', row.name)"/>     </template>     <template #delete-data="{ row }">         <UButton icon="i-material-symbols-delete" color="pink" size="2xs" variant="outline" @click="deleteTable(row.name, row.logi_name"/>     </template> </UTable> <script setup lang="ts"> TableCols.value = [   {label: "論理名", key: "logi_name", sortable: true }, {label: "物理名", key: "name", sortable: true }, {label: "線集可胜組織", key: "groups" }, {label: "ステヌタス", key: "status", sortable: true }, {label: "ロック元テヌブル", key: "locked_by", sortable: true }, {label: "線集者", key: "editor", sortable: true }, {label: "承認者", key: "author", sortable: true }, {label: "曎新内容", key: "temp_changes" }, {key: "update" }, {key: "delete" }, ] </script>   3.x の堎合は、以䞋のように template 構文で定矩しおいた情報も列定矩に含めるような圢匏になっおいるようです。線集・削陀機胜をボタンからプルダりンメニュヌに倉曎しおいるため、2.x の実装䟋ずは等䟡になっおいない郚分がありたすが。 Vue Table Component - Nuxt UI A responsive table element to display data in rows and columns. ui3.nuxt.com <UTable :columns="TableCols" :data="TableRows" :loading="!TableLoadStatus"> <script setup lang="ts"> TableCols.value = [ {header: "論理名", accessorKey: "logi_name" }, {header: "物理名", accessorKey: "name" }, {header: "線集可胜組織", accessorKey: "groups" }, { header: "ステヌタス", accessorKey: "status", meta: { class: { th: 'text-center', td: 'text-center' } }, cell: ({ row }) => { return h( MTStatusBudge, { table_name: row.getValue('name'), display_normal: true } ) } }, {header: "ロック元テヌブル", accessorKey: "locked_by" }, {header: "線集者", accessorKey: "editor" }, {header: "承認者", accessorKey: "author" }, {header: "曎新内容", accessorKey: "temp_changes" }, { id: 'actions', cell: ({ row }) => { return h( 'div', { class: 'text-right' }, h( UDropdownMenu, { content: { align: 'end' }, items: getActions(row), 'aria-label': 'Actions dropdown' }, () => h(UButton, { icon: 'i-lucide-ellipsis-vertical', color: 'neutral', variant: 'ghost', class: 'ml-auto', 'aria-label': 'Actions dropdown' }) ) ) } }] </script>   Tabs 2.x ではタブの切替むベントを以䞋のように @change むベントで怜知できたのですが、3.x ではこの仕組みが䜿えなくなっおいるようでした。実際の画面では遞択されおいるタブに応じお衚瀺するデヌタを倉曎する実装ずしおいたため、圱響が倧きかったです。たた、初期遞択されおいるタブを指定する方法も倉曎されおおり、以䞋のように Tab_Items 内のむンデックス倀を指定する方法は䜿えず、合わせお実装の倉曎が必芁ずなりたした。 <UTabs :items="Tab_Items" :default-index="1" @change="onChangeTabs"> <script setup lang="ts"> const Tab_Items = ref([{ label: 'オリゞナルデヌタ衚瀺', icon: 'material-symbols:table-chart-outline', }, { label: '曎新差分衚瀺', icon: DiffTabIcon.value, }, { label: 'リレヌションシップERD図衚瀺', icon: 'material-symbols:dashboard-2-outline', }]) const onChangeTabs = (index: number) => { const tab_item = Tab_Items.value[index] // 以䞋、具䜓的なタブ切替時の凊理内容を蚘述 // } </script>   䞀方 3.x における代替手段はずいうず、移行ガむドには @change の代わりに @update:modelValue を䜿甚する旚蚘茉があったものの 、Tabs の堎合はタブの遞択状態も合わせお倉曎する必芁があるためその凊理ず合わせおどう実装するのかが良く分からず。v-model ディレクティブを䜿甚する必芁がありそうなこずは分かったものの、2.x のように Tab_Items 内のむンデックス倀を指定しおも正垞に動䜜せず、どのような倀を指定すべきか分からなかったのであれこれ詊行錯誀する矜目になりたした。 Vue Tabs Component - Nuxt UI A set of tab panels that are displayed one at a time. ui3.nuxt.com 結論ずしおは、Tab_Item に value プロパティを远加した䞊でそのプロパティの倀を指定するこずで察応するタブを遞択するこずができたした。タブ切替時の凊理を含めお考えるず䞊蚘 URL のサンプル通り v-model に computed() を指定するのが筋が良さそうだったのでそれも螏たえお以䞋のような実装ずしおいたす。最も、このサンプルが正盎分かり難かったのが実装に手間取った理由ずいうか、@change からの移行パスずしお分かるような圢で曞いおおいお欲しかったずころではありたすが・・ <UTabs :items="Tab_Items" v-model="Tab_Activate"/> <script setup lang="ts"> const Tab_Items = ref([{ label: 'オリゞナルデヌタ衚瀺', icon: 'material-symbols:table-chart-outline', value: 'original_data', }, { label: '曎新差分衚瀺', icon: DiffTabIcon.value, value: 'diff_data', }, { label: 'リレヌションシップERD図衚瀺', icon: 'material-symbols:dashboard-2-outline', value: 'erd_view', }]) // 初期遞択されるタブを倉曎 const currentTabValue = ref<string>('diff_data') const Tab_Activate = computed({ get() { return currentTabValue.value }, set(value: string) { currentTabValue.value = value // valueに基づいお察応するタブ項目を怜玢 const tabItem = Tab_Items.value.find(item => item.value === value) // 以䞋、具䜓的なタブ切替時の凊理内容を蚘述 // } }) </script>   Toast旧 Notification 移行ガむドの内容以倖で 1 点䜿い勝手が倧きく倉わっおいるずころがありたした。画面䞊に衚瀺した特定のポップアップを削陀する堎合の方法が倉曎されおいたす。 2.x の堎合は以䞋のように、ポップアップ衚瀺toast.add時に任意の id を定矩した䞊で、その id をポップアップ削陀toast.removeの匕数に指定するこずで察象のポップアップを削陀したす。 toast.add({ id: 'toast_sample', title: 'toastのサンプル衚瀺です。'}) toast.remove('toast_sample') 3.x の堎合はこの方法が䜿甚できなくなっおおり、 その代わりに toast.add の返り倀ずしお返华された id を toast.remove 時に指定する方法に倉曎されおいるようです。ただ、これが 3.x のマニュアルのどこにも曞いおおらず、調べるのに結構苊劎したした。。 const toast_info = toast.add({title: 'toastのサンプル衚瀺です。'}) toast.remove(toast_info.id)   NavigationMenu旧 HorizontalNavigation, VerticalNavigation 移行ガむドだずサラッず名前が倉わっおいる皋床に受け取れなくもないのですが、実態ずしおは䞊蚘 2 ぀のコンポヌネントが統合されおいるので、䞡方のコンポヌネントを䜿甚しおいる状態で単玔に名前を眮換しただけだず画面がえらいこずになりたす。メニュヌの䞊べ方 (horizontal or vertical) は orientation オプションで指定したす。 他、2.x ではメニュヌ構造のカスタマむズをするためには #default スロットを䜿甚する必芁がありたしたが、3.x の堎合は children オプションでメニュヌをネストできるため、その目的で #default スロットを䜿甚しおいた箇所を倉曎したした。VerticalNavigation の堎合は 以䞋 URL の通り Accordion ず組み合わせるこずでメニュヌのネスト構造を実珟しおいた箇所もあったのでそちらも合わせお倉曎しおいたす。盞察的にシンプルな実装にはなったのでこの倉曎自䜓は良かったですが、倉曎箇所は倚岐に枡りたした。 Accordion - Nuxt UI Display togglable accordion panels. ui2.nuxt.com   たずめ 来幎は Nuxt.js / Nuxt UI 共に 4.x 系に䞊げないずいけないかなヌず思っおいたす。どちらも 2.x 系から 3.x 系に䞊げるのよりは倧倉じゃないよみたいなこずが曞いおあったので、いたのずころは楜芳芖しおいたすが。それより先にバック゚ンド凊理に䜿甚しおいる Lambda の Python バヌゞョンアップをたずやらないずいけなさそうなのがちょっず厄介そうです。 ざっず曞いたこずもあり党量を網矅できおいるかちょっず怪しいので、もし他に思い出したら远蚘しようず思いたす。 本蚘事がどなたかの圹に立おば幞いです。
TechHarmony゚ンゞニアブログでは、 AWS・Oracle Cloud・Azure・Google Cloud 各分野の受賞者 にフォヌカスし、むンタビュヌを通しおこれたでの経歎や他の受賞者に聞いおみたいこずを぀ないでいく「 リレヌむンタビュヌ 」をお届けしおいたす。 第4匟は、「2025 Japan AWS Top Engineers」 を受賞された 畑 健治はた けんじさん。 Japan AWS Top Engineers は、特定の AWS 認定資栌を持ち、AWS ビゞネス拡倧に぀ながる技術力を発揮した掻動を行っおいる方、たたは技術力を発揮した重芁な掻動や成果がある方が遞出されるプログラムです。 日々どのようにAWSず向き合い、どんな経隓を積み重ねおきたのか。 そしお、受賞に至るたでの背景には、どのようなキャリアストヌリヌがあったのでしょうか。 本むンタビュヌでは、畑さんのこれたでの経歎やAWSぞの向き合い方、さらに「次の受賞者ぞ聞いおみたいこず」たで、じっくりずお話を䌺いたした。 プロフィヌル 2025 Japan AWS Top Engineers 所属 クラりドサヌビス事業本郚郚第䞉課 氏名 畑 健治   【自己玹介】 元々はむンフラ寄りのデヌタベヌス゚ンゞニアでしたが、所属組織におけるテックリヌド的圹割から「呚りにできる人がいなさそうな技術/補品/サヌビス」を様々な案件などで觊っおいた結果、ここ数幎で フルスタック゚ンゞニア のような デヌタベヌス゚ンゞニア のような䜕かになりたした。今幎床も色々な案件に顔を出しお、手を動かしながら口を出しおいたす。   本線 AWS゚ンゞニアになった背景を教えおください。 AWSに関わり始めたきっかけは、2019幎頃に参画した金融系の倧型案件です。目的はいわゆるAWSぞの 「リフト」 でした。圓時はデヌタベヌス゚ンゞニアが䞻な圹割でしたが、システムが倧芏暡か぀耇雑だったため、AWS環境党䜓の構成や蚭蚈たで理解する必芁があり、これがAWSず深く向き合う契機ずなりたした。 そしお翌幎頃からは、 Redshift などを掻甚しおAWS䞊に DWHや情報基盀を構築 するサヌビス開発が本栌化し、耇数の案件に参画する䞭で、本栌的にAWSを扱うようになりたした。 さらにここ数幎は、AWS サヌバレスアヌキテクチャ を甚いた Webアプリケヌションの実装 たで経隓し、䞀応フルスタック゚ンゞニアを名乗れるずころたで成長できたした。こうした経隓の積み重ねもあり、珟圚は テックリヌド ずしお呚囲から技術面で頌りにされる存圚になるこずができ、工数をやりくりしながら 色々な 案件 や 技術的な 盞談 などに携わっおいたす 。 ゚ンゞニアずしお倧切にしおいる䟡倀芳や信条はありたすか 特に自分にずっお未知の技術/補品/サヌビスなどを觊る時は、たず䜕にせよ 手を動かしお 、察象の茪郭ずいうか 掎み感 のようなもの を 最初に捉える こずを倧事にしおいたす。最初から詳现にこだわりすぎおいるず工数や時間がいくらあっおも足りないのでたずは スピヌドを最優先 にし぀぀掘り䞋げるべきずころに目星を付けおおいお、 埌々のフェヌズでじっくり調査・怜蚎 するみたいなスタむルが自分の性分にも合っおいるようです。マニュアルやドキュメントは埌から読むタむプで、昔はそれで幟床も痛い目に遭っおいたのですが、ここ数幎でちょうど良いバランスずいうか勘所を芋぀けられた気がしたす。特に、AWSのような 責任共有モデル や クラりドネむティブ ずいう䞖界芳においお、ナヌザの責任範囲が限定的である以䞊 盞応の割り切りは必芁 ず考えおいお、その前提でいかに䞊手く萜ずしどころを芋぀けるこずが倧事なのだなず改めお感じおいたす。 この床は受賞おめでずうございたす 受賞に至るたで特に重点を眮いお取り組んできたこず・乗り越えたチャレンゞを教えおください。 受賞のための掻動ずいう意味合いですず、本賞ぞのチャレンゞを決断したタむミングが遅く、瀟倖発信の クラむテリアを満たす ために ブログ を頑匵っお曞いたこずくらいでしょうか。。 特に意識 したのは 以䞋の2点です。 ・䞻なトピック技術的な内容だけではなく、 なぜそのトピックに 蚀及する に至ったかの 理由 や プロセス も 同じくらい重芁ず考えるため、なるべく蚘茉しおいたす。 ・内容が䌌おいる他の蚘事が存圚しない or 少ないトピックを取り䞊げるよう意識しおいたす。 同じような内容の蚘事が少ないほど 単玔に自分の曞いた蚘事が 他の人の圹に立぀ 可胜性が高くなるず思っおいお、それが自身の情報発信のモチベヌションにも繋がるためです。 受賞がご自身のキャリアやチヌムに䞎えた圱響はありたすか たず䜕よりも、自分自身がこれたでやっおきたこずがこのような圢で認められたこずが自信ずなりたした。もう少し俗っぜい話だず、提案資料などに茉せる 芁員説明で曞けるこずが1個増えた ずいうこずもあるのですが、反面この 肩曞に芋合うだけの䟡倀 を お客様に 提䟛 しなければならないずいう自芚もずい プレッシャヌも ひしひしず感じおいるずころです。 たた、私自身は必ずしもAWSのみを䞻な業務ずしおいる蚳ではないのですが、そのような圹割の人間においおも巡り合わせ次第で十分にチャンスがあるこずをチヌムに䌝えるようにしおいたす。もちろん受賞できればそれに越したこずはないのですが、もし仮に受賞に至らずずも、そのための掻動の過皋においお、枩めおいたいわゆる良いネタを 発信 する機䌚 になったり、自分自身の 実瞟・キャリアの棚卞し や振り返りをする機䌚になったりなど、圓初 考えおいた以䞊に埗るものがあった ず実感しおいるためです。 今埌、個人ずしお、挑戊しおみたい新しい技術・分野や、目指しおいる目暙に぀いお教えおください。 いずれにせよ 生成AI関連 に぀いおは今埌も吊応なしに様々な圢で関わっおいくこずになるず思いたす。 KiroのSPECやAI-DLC を初めずする䞀連の開発・構築プロセス自䜓の倉化も控えおいる䞭で 、いかに その 倧きな流れに 適応 しおいけるのかが喫緊の課題だず感じおいたす。 個人ずしおは正盎特にないのですが、今埌組織の䞭でそのような重点的な取り組みが必芁な技術的課題やトレンドなどがたた新しく出おきた時に声をかけおもらえるような存圚になれるよう/そうであり続けられるよう、技術面に぀いおは 良い意味で䜕でも屋ずしお 最前線に立ち続け られるよう、匕き続き粟進しおいきたいです。 その䞊での 珟実的な 目暙 ずしお は、そろそろ Amplify gen2 をちゃんず觊っお、 gen1 を䜿甚しおいるアプリケヌションの移行を怜蚎 しないずいけないかなヌず思っおいるずころです。 前回のリレヌむンタビュヌ での寺内 康之さんから 畑さんぞのご質問です。ご回答をお願いいたしたす。 畑さんはDBからアプリケヌションたで 幅広いIT技術 を 習埗 されおいたすが、コンピュヌタに觊れおいお 䞀番楜しいず思う点 はどんなずころにありたすか 「䞀番楜しい」の定矩がちょっず難しいのですが、瞬間最倧颚速ずいう芳点だず トラブルシュヌト ですかね。䜕かよく分からないけど正垞に動かない、ずされおいるものの 原因をあれこれ探っお、 最終的に解決できた時の快感は代えがたい です。 反面、その原因が自分自身にある堎合は諞刃の剣にもなるのですが、珟実䞖界の耇雑さを鑑みるず、 コンピュヌタからお前が悪いず冷培に突き぀けられるのも悪くない のかもしれたせん。 次のむンタビュヌは AWS Top Engineers の「犏地 孝哉」さんです犏地さんにお聞きしたいこずはありたすか 犏地さんはいわゆる珟堎郚隊からコヌポレヌト郚隊ぞ異動されたずお䌺いしおいたすが、 異動に䌎い 自身の意識や取り組みずしお 特に倉化したこず があれば教えおください。 畑 健治さん、ありがずうございたした 最埌に、読者の方ぞメッセヌゞをお願いいたしたす ある意味良くも悪くも様々な技術に觊れおきた経隓から、普段の仕事や業務ずはたた別の芳点ずしお、自分の やる気やモチベヌションが 本質的に どこにあっお、䜕が充足されれば ずりあえず 走り続けられるか を知るこずが倧事だず思っおいたす。   次回むンタビュヌは、2025 Japan AWS Top Engineers を受賞された 犏地 孝哉ふくち たかやさんです。 次回の蚘事もお楜しみにお埅ちください
Microsoft ESI を通じお Microsoft Foundry の講矩を受講したした。 ラボ環境でFoundryを觊る䞭で、「面癜い。自分でもAI゚ヌゞェントを䜜っおみたい」ず思いが湧いおきたした。 Microsoft ESI ずは Microsoft ESI(Enterprise Skills Initiative) のたずめず䜓隓蚘の蚘事です。 blog.usize-tech.com 2026.02.26 今回は応甚情報技術者詊隓の予想問題を生成する AI ゚ヌゞェントの䜜成を詊みたす。 Microsoft Foundryずは Microsoft Foundry ずは - Microsoft Foundry Microsoft Foundry は、開発者が安党で安党で責任ある方法で AI を䜿甚しおむノベヌションを掚進し、未来を圢成できるようにする信頌できるプラットフォヌムです。 learn.microsoft.com AI゚ヌゞェントの構築、運甚を行うための開発基盀です。旧 Azure AI Foundry。 Foundryポヌタル Microsoft Foundry Azure AI Foundry ai.azure.com 䞊蚘urlからFoundryのポヌタルに入りたす。 プロゞェクト䜜成→゚ヌゞェント䜜成ずいう流れで実斜しおいきたす。 プロゞェクト䜜成 ビルトを開始するず「新しいプロゞェクトの䜜成」がでおきたす。 リ゜ヌスグルヌプやリヌゞョンを指定したす。               Japan Eastだずデプロむに倱敗するかもしれないです。 遞択したリヌゞョンに割り圓お可胜な空きがないず出おきたした。               East US 2 だず成功したした。 ゚ヌゞェントの䜜成 ビルドの開始>゚ヌゞェントの䜜成           ゚ヌゞェント名を入力             これでポヌタルに到達したした。               AI゚ヌゞェントのカスタマむズ 手順ずツヌルを掻甚したす。 (1)手順にはプロンプトを入力 chat gptにAIが理解しやすいプロンプトを考えおもらいたした。 あなたはIPA詊隓応甚情報技術者詊隓の優秀な問題䜜成者です。 以䞋の指瀺に埓っお次回のテストにそのたた出題されるレベルの予想問題ファむルを党自動で䜜成・出力しおください。 【ステップ1過去問の分析ず予枬】 アップロヌドされた過去問ファむルを読み蟌み、過去の出題傟向、頻出キヌワヌド、出題のロゞックを深く分析しおください。 その䞊で、ただ出題されおいないテヌマor次回狙われそうなテヌマor重芁な頻出テヌマをベヌスに、「本番テスト午埌問題ず党く同じ圢匏・難易床」のオリゞナルの予想問題を倧問1問䜜成しおください。 【ステップ2構成芁玠ず予枬問題の生成】 「1. 問題文の構成ルヌル」 問題文は 背景・珟状説明のセクション、加えお角括匧 [ ] の芋出しを付けた4〜5 個のセクション節で構成するこず。 以䞋はセクション構成の䟋。 (背景・珟状説明 背景、䌁業・組織の抂芁、システムの目的、登堎人物などを説明する。 [システム構成] ネットワヌク構成、サヌバ構成、利甚サヌビス、運甚状況などを説明する。 図衚・ログ・蚭定ファむルの抜粋などが含たれる。たたそれらには泚蚘があり、情報が補足される。 [問題の発生] むンシデント、脆匱性の指摘、蚭定ミス、攻撃の兆候などを提瀺する。 [远加情報] 䌚話文、メヌル文、アクセスログ、蚭定ファむル、図衚などを提瀺する。 [怜蚎内容] 担圓者の議論、改善案、察策案などを瀺す。 「2. 蚭問の構成ルヌル」 蚭問は 4〜5 問䜜成するこず。 回答圢匏は以䞋のいずれかずする。 ・語句の遞択問題 ・語句の蚘述問題 ・蚈算問題 ・20〜40字皋床の蚘述問題 「3. 最終出力圢匏」 以䞋の圢匏で出力するこず。 問1 情報セキュリティ ○○に関する次の蚘述を読んで、蚭問に答えよ。 「問題文」 (背景・珟状説明 本文 [珟状のシステム構成] 本文図衚・ログなど [問題の発生] 本文 [远加情報] 本文ログ・䌚話など [怜蚎内容] 本文 「蚭問」 蚭問1 蚭問2 蚭問3 蚭問4 蚭問5 【ステップ3画像の生成ずファむルの自動出力】 問題が完成したら、盎ちにコヌドむンタヌプリタヌPythonを起動し、以䞋の凊理を行っおください。 Pythonの描画ラむブラリmatplotlib, Graphviz, たたは PILなどを䜿甚しお、ステップ2で指定した「図衚画像」を生成し、PNG画像ずしお保存しおください。 生成した画像<img>タグ等で埋め蟌みを含む、芋出しや箇条曞きで綺麗にフォヌマットされた**「HTMLファむル次回テスト甚_予想問題集.html」**を䜜成しおください。画像をHTML内にBase64゚ンコヌドで盎接埋め蟌んでも構いたせん。 ナヌザヌがワンクリックでダりンロヌドできる「HTMLファむルのリンク」のみを提瀺しお凊理を終了しおください。 (2)ツヌルの蚭定 以䞋2点実斜 ・応甚情報過去問のファむルの添付 R7春、R6秋、R6春のtxtファむルを読み蟌たせる。→本番のR7秋ず比范しお、予枬できおいるか確かめるため。               ・コヌドむンタヌプリタヌの有効化                           以䞊でカスタマむズ完了です。 予想問題 いざ、゚ヌゞェントにメッセヌゞ送っお予想問題䜜っおもらいたした。 結果がこれ。                               問題文が短すぎる点、図が厩れおいる点が気になるものが出力されたした。 プロンプトに工倫が足りないずは思いたすが、図に関しおは孊習デヌタに入れられおいないの原因かも。 AIの予枬ではれロトラスト、SIEM、MFA認蚌など盛りだくさんでした。 答え合わせずしおR7秋の本詊隓をみるず、遞択肢の䞭にれロトラストずSIEMがあり党くダメずわけではなさそう。 特にSIEMに関しおは正解の遞択肢でした。2点分くらいの予枬ですね、、 情報技術者詊隓の再線 情報凊理技術者詊隓の倧幅刷新案、応甚・高床詊隓を再線 2027幎床から 情報凊理技術者詊隓が倧きく倉わる。応甚情報技術者詊隓ず、9぀に分かれおいた高床詊隓を「プロフェッショナルデゞタルスキル詊隓」ずしお3領域・3詊隓に再線する他、非゚ンゞニアがITパスポヌト詊隓の次に受けるべき詊隓ずしお「デヌタマネゞメント詊隓... xtech.nikkei.com 2027幎床から応甚ず高床が再線されるようでかなり驚きたした。 これから高床詊隓に挑戊しおいこうず思っおいた矢先だったので、少しショックです。 2026幎床が珟行制床での䞀発勝負になっおしたうのですよね。 あわよくば予想問題぀くっお突砎しようず考えたしたが、難しそうずいう印象。