TECH PLAY

SCSKクラウドソリューション

SCSKクラウドソリューション の技術ブログ

1141

業務でデータの不整合を調査したり、リリース後のデータ確認を行ったりする際、毎回同じようなクエリを書いていることに気づきました。 そこで、いざという時に焦らずコピペで使えるよう、データ調査でよく使うBigQueryのクエリパターンをまとめました。 【タイムトラベル】過去のある時点のデータを参照する データを誤って更新・削除してしまった時に使います。 バックアップテーブルからリストアしなくても、クエリに一行足すだけで過去の状態を参照できます。 ※タイムトラベル期間(デフォルト7日間)内であれば参照可能です。 SELECT * FROM `[プロジェクトID].[データセット名].[テーブル名]` -- 以下の時刻時点のデータを表示します FOR SYSTEM_TIME AS OF TIMESTAMP("2024-01-01 10:00:00+09"); -- ここに戻りたい日時を指定(JST) 【重複チェック】プライマリキーが重複していないか探す Step1:まずは重複の有無を検知する(GROUP BY) 「ユニーク(一意)であるべき項目」でグループ化し、数が2つ以上あるものを探します。 SELECT `[重複チェックしたいカラム名]`, -- 例: order_id, user_code など count(*) as duplicate_count -- 重複している件数 FROM `[プロジェクトID].[データセット名].[テーブル名]` GROUP BY `[重複チェックしたいカラム名]` -- SELECTと同じカラムを指定 HAVING count(*) > 1; -- 「件数が1より大きい(重複)」のみ抽出 GROUP BY: 指定したカラムの値が同じデータを1行にまとめる機能です。 Step2:重複行の全カラムを表示して差異を確認する(QUALIFY) 重複が見つかった後、「行ごとの登録日時はいつか?」「他のカラムに違いはあるか?」を確認するために、行を1行にまとめずに全カラムを表示します。 SELECT * FROM `[プロジェクトID].[データセット名].[テーブル名]` -- 「指定したカラム」ごとに集計し、2件以上ある行だけをフィルタリングして表示 QUALIFY count(*) OVER( PARTITION BY `[重複チェックしたいカラム名]` ) > 1 ORDER BY `[重複チェックしたいカラム名]`; -- 重複行が隣り合うように並べ替え QUALIFY: 集計した結果に対して、WHERE のように条件を指定して絞り込む句です。 PARTITION BY: 行を1行にまとめず、グループ集計するための機能です。 ORDER BY: 結果を並べ替えます。これがないと重複行がバラバラに表示されて比較しにくいため、指定します。 【異常値検知】データの偏りや異常値を調べる 「特定の値しか入っていないはずなのにエラーが出る」といった場合、想定外の値(空文字やNULLなど)が入っていないか確認します。 カラムに入っている値ごとの件数を集計します。 SELECT `[値の内訳を見たいカラム名]`, -- 例: status, category など count(*) AS count -- その値が何件あるか FROM `[プロジェクトID].[データセット名].[テーブル名]` GROUP BY `[値の内訳を見たいカラム名]` -- SELECTと同じカラムを指定 ORDER BY count DESC; -- 件数が多い順に並べる(異常値を見つけやすくする) DESC(降順): 多い順に並べます。主要な値を把握したい時に使います。 ASC(昇順): 少ない順に並ぶため、「数件だけ混じっているレアな異常値」を見つけたい時に便利です。 <Tips>異常値が見つかった場合の修正例 本来 ‘0’ であるべき場所に、空文字(何も表示されない行)が見つかった場合の対処法です。 UPDATE `[プロジェクトID].[データセット名].[テーブル名]` SET `[修正したいカラム名]` = "0" -- 正しい値(例: "0")に書き換える WHERE `[修正したいカラム名]` = ""; -- 異常値(例: 空文字)を条件指定 【環境比較】本番と検証でデータ件数に差がないか確認する リリース作業の前後や、本番環境と検証環境で「データが正しく移行できているか」を比較します。 2つのクエリ結果を結合して表示します。もし count の数が合わなければ、データ移行漏れや更新処理の不備が疑われます。 ※タイムトラベル期間(デフォルト7日間)内であれば参照可能です。 -- 環境A(例:本番)のデータ件数 SELECT '本番環境' AS env, count(*) AS count FROM `[プロジェクトID].[データセット名].[本番テーブル]` UNION ALL -- 環境B(例:検証)のデータ件数 SELECT '検証環境' AS env, count(*) AS count FROM `[プロジェクトID].[データセット名].[検証テーブル]`; 最後に これまではその場しのぎで都度調べてクエリを書いていましたが、こうしてまとめてみると それぞれの句の意味を改めて復習する良い機会になりました。 データ調査をスピード感をもって実施できるよう、皆様もぜひこのテンプレートを活用してみてください。
アバター
前回の記事 では、Bicepを用いたネットワークリソースの構築を実践いたしました。 Bicepを含むIaCを活用するメリットは、インフラの状態をコードで定義し、その構成を確実に再現できる点にあります。 そこで今回は、Bicepデプロイをより使いこなすために試した、2つのオプションをご紹介します。実際に試して分かった活用のポイントや、使用上の注意点についても併せてお伝えします。 オプション①:–confirm-with-what-if このオプションを設定することで、デプロイ実行前に差分確認を行うことができます。 現在の環境とBicepファイルの内容を比較し、どのような変更が発生するかを事前にシミュレーションできます。 Bicep の What-If: デプロイ前に変更をプレビューする - Azure Resource Manager Bicep ファイルをデプロイする前に、リソースに対してどのような変更が行われるかを確認します。 learn.microsoft.com 実行例 コマンドを実行すると、以下のように変更内容が可視化されます。 ターミナル上には、変更内容が色付きの記号で表示されます。 Create (+):新規に作成されるリソース Modify (~):既存の設定が変更されるリソース Delete (-):削除されるリソース(Completeモード時など) NoChange (=):変更がないリソース 表示内容に問題がなければ「y」で実行、想定外であれば「n」で中断してコード修正へ戻れます。 デプロイ前にこの差分をしっかりと検証することで、環境への予期せぬ影響を未然に防ぐことができます。 オプション②:–mode Complete このオプションを設定することで、コードを環境の正として管理することができます。 Bicepのデプロイモードには「Incremental(増分)」と「Complete(完全)」の2種類があります。 Incremental(デフォルト):コードにあるリソースを追加・更新します。コードにないリソースが環境に存在していても、そのまま残ります。 Complete:環境の状態をコードと完全に一致させます。コードに記述されていないリソースは、デプロイ時に自動的に削除されます。 デフォルトはIncrementalですが、より厳格な構成管理を目指す場合にはCompleteモードが有効です。 デプロイ モード - Azure Resource Manager Azure Resource Manager で完全デプロイ モードと増分デプロイ モードのどちらを使用するかを指定する方法について説明します。 learn.microsoft.com ※補足:現在、MicrosoftではCompleteモードよりも、さらに安全にリソースの削除や保護を管理できる「デプロイスタック(Deployment Stacks)」の使用を推奨しています。Completeモードは強力ですが、影響範囲が広いため、より厳格かつ安全な管理を求める場合は、デプロイスタックの活用も検討してみてください。  Bicep で Azure デプロイ スタックを作成してデプロイする - Azure Resource Manager Bicep でデプロイ スタックを作成する方法について説明します。 learn.microsoft.com 実行例 コードの一部をコメントアウトし、Completeモードでコマンドを実行すると、以下のようにリソースの削除が行われます。 ①コメントアウト ここでは、削除したいリソースをコードから完全に消去するのではなく、コメントアウトにてデプロイを行いました。 あえてコメントアウトを利用することで、どのリソースを、どのタイミングで削除しようとしているのかという作業過程が明確になります。 ②デプロイ前 ③デプロイ実施 ④デプロイ後 Incrementalモードでは、コードにないリソースは「変更なし」と判断されて環境に残ってしまいますが、Completeモードであれば不要なリソースを確実に削除できます。 注意点 すでに運用されている環境でいきなりCompleteモードを適用すると、Bicepで管理していない共有リソースや、別メンバーが作成したリソースが削除されてしまうリスクがあります。 適用する際は、以下のルールを徹底することをおすすめします。 影響範囲の確認 Completeモードは、デプロイ対象のスコープ全体に影響します。 What-Ifとの併用 Completeモードを使う際は、必ず事前にWhat-Ifを実行し、削除対象に意図しないリソースが含まれていないかを確認してください。 まとめ 自動化されたデプロイにおいて、What-If による事前の差分確認や、Complete モードの仕組みを理解することは、作業の確実性を高めるための助けとなると考えます。 管理方法はプロジェクトの規模や方針によって様々だと思いますが、まずはこうしたオプションを試してみて、ご自身の環境に合った安全な構築・運用を検討してみてください。
アバター
本記事では、Azureのリソース管理ツールであるBicepを活用し、ネットワーク基盤をコード化してデプロイ(構築)する過程をご紹介します。 私自身、Bicepの実装は手探りからのスタートでしたが、その中で得られた構築プロセスを整理してまとめました。 Bicepをこれから触ってみたいと思っている方の、参考になれば嬉しいです。 Bicepとは Bicepは、宣言型の構文を用いてAzureリソースをデプロイするためのドメイン固有言語(DSL)です。 従来のARMテンプレート(JSON形式)と比較して可読性が高く、VS Code拡張機能による型補完やエラーチェックを活用することで、構築ミスを未然に防ぎながら少ないコード量で記述できる点が特徴です。 Bicepのより詳細な仕様や最新情報については、以下の公式サイトを参照ください。 Bicep とは - Azure Resource Manager インフラストラクチャを Azure にデプロイするための Bicep 言語を理解します。 JSON を使用してテンプレートを開発する場合に比べてオーサリングがしやすくなります。 learn.microsoft.com 今回作成するリソース 今回は、Azureインフラの土台となる「ネットワーク基本セット」を構築します。 複数のサブネットで共通のセキュリティポリシーやルーティングを適用する、実務でもよくある構成を想定しています。 作成するリソース ①仮想ネットワーク (VNet) × 1 2つのサブネットを含みます(今回は同じ役割のサブネットとして構築)。 ②ネットワークセキュリティグループ (NSG) × 1 共有設定として両方のサブネットへ紐付けます。 ③ルートテーブル (RT) × 1 共有設定として両方のサブネットへ紐付けます。 事前準備:開発環境を整える Bicepの作成をスムーズに進めるために、以下の3つのツールを準備します。 ①Visual Studio Code (VS Code) コードの作成・編集に使用するメインエディタです。 ②Bicep 拡張機能 (VS Code内) VS Codeにインストールすることで、コードの自動補完(型補完)や、記述ミスを教えてくれるエラーチェックが有効になります。 ③Azure CLI 作成したBicepファイルを、手元のPCからAzure環境へデプロイするために使用します。 Bicepコードを書いてみる Bicepには、複雑な構成を小さく管理しやすい単位に分割する「モジュール」という仕組みがあります。 今回は、将来の拡張性や再利用性を考慮し、単一のファイルにすべてを記述するのではなく、「全体を制御するメインファイル」と「各リソースを定義するモジュール」を分ける構成を採用しました。 ファイル構成 . ├── main.bicep # 全体の司令塔(各モジュールを呼び出す) ├── main.bicepparam # パラメータファイル(環境ごとの設定値) └── modules/ # リソース定義を格納するフォルダ  └── network.bicep # ネットワークリソースの定義 この構成の大きなメリットは、管理がしやすい点にあります。 今後、ストレージやデータベースなど構築対象のリソースが増えていく場合も、 modules/ フォルダの中に storage.bicep や database.bicep といった形でファイルを追加していくことで、 シンプルに構成を拡張していくことが可能です。 Bicep モジュール - Azure Resource Manager この記事では、Bicep ファイルでモジュールを定義する方法と、モジュール スコープを使用する方法について説明します。 learn.microsoft.com 構築コード 以下の通り、コードを記述いたしました。 network.bicep(モジュール) ここでは、ネットワークの基盤となるリソースを定義します。 @description('リソースを配置するリージョンを指定します。') param location string @description('作成する仮想ネットワーク(VNet)の名前を指定します。') param vnetName string @description('VNet全体のアドレス空間(CIDR)を指定します。') param vnetAddressPrefix string @description('サブネット名の配列。各サブネットの名称とアドレスプレフィックスを含めます。') param subnetConfigs array @description('共通で適用するネットワークセキュリティグループ(NSG)の名前です。') param nsgName string @description('共通で適用するルートテーブル(RT)の名前です。') param rtName string // 1. ネットワークセキュリティグループ (NSG) の定義 resource nsg 'Microsoft.Network/networkSecurityGroups@2023-11-01' = { name: nsgName location: location properties: { securityRules: [] } } // 2. ルートテーブル (RT) の定義 resource rt 'Microsoft.Network/routeTables@2023-11-01' = { name: rtName location: location properties: { disableBgpRoutePropagation: false routes: [] } } // 3. 仮想ネットワーク (VNet) の定義 resource vnet 'Microsoft.Network/virtualNetworks@2023-11-01' = { name: vnetName location: location properties: { addressSpace: { addressPrefixes: [ vnetAddressPrefix ] } subnets: [for subnet in subnetConfigs: { name: subnet.name properties: { addressPrefix: subnet.addressPrefix // 作成したNSGとRTのIDを各サブネットに紐付け networkSecurityGroup: { id: nsg.id } routeTable: { id: rt.id } } }] } } main.bicep(メイン) 司令塔となるこのファイルでは、network.bicep モジュールを呼び出します。 具体的なパラメータの値は直接書かず、後述するパラメータファイルから受け取った値をモジュールへ渡す役割を担います。 targetScope = 'resourceGroup' @description('デプロイ先のリージョン。デフォルトはリソースグループの場所を引き継ぎます。') param location string = resourceGroup().location @description('VNetの名称を指定します。') param vnetName string @description('VNetのアドレス空間を指定します(例: 10.0.0.0/16)。') param vnetAddressPrefix string @description('サブネット構成情報のリストです。') param subnetConfigs array @description('共通NSGの名称です。') param nsgName string @description('共通ルートテーブルの名称です。') param rtName string // ネットワークモジュールの呼び出し module network './modules/network.bicep' = { name: 'networkDeployment' params: { location: location vnetName: vnetName vnetAddressPrefix: vnetAddressPrefix subnetConfigs: subnetConfigs nsgName: nsgName rtName: rtName } } main.bicepparam(パラメータファイル) 環境ごとの設定値(リソース名やIPアドレス範囲など)を記述します。 Bicepのパラメータファイルには、従来の「.json」形式と、新しい「.bicepparam」形式の2種類があります。 公式ドキュメントではどちらの形式もサポートされているため、既存の運用に合わせて選択して問題ありません。 今回は.bicepparamで記述いたします。 Bicepのデプロイメント用のパラメーターファイルを作成する - Azure Resource Manager スクリプトでインライン値としてパラメーターを渡すのではなく、Bicep パラメーター ファイルを作成する方法について説明します。 learn.microsoft.com using 'main.bicep' // --- ネットワーク基本設定 --- param vnetName = 'vnet-test-001' param vnetAddressPrefix = '10.0.0.0/16' // --- サブネット定義(同じ役割を担う2つのセグメント) --- param subnetConfigs = [ { name: 'snet-test-001' addressPrefix: '10.0.1.0/24' } { name: 'snet-test-002' addressPrefix: '10.0.2.0/24' } ] // --- 共通リソース設定 --- param nsgName = 'nsg-test--001' param rtName = 'rt-test--001' Bicepの記述に関する詳細な情報は公式サイトに多数掲載されており、以下に一部を抜粋いたします。 Bicep ファイルの構造と構文 - Azure Resource Manager 宣言構文を使用して、Bicep ファイルの構造とプロパティを理解する方法について説明します。 learn.microsoft.com Azure リソース リファレンス - Bicep, ARM template & Terraform AzAPI reference Bicep、Azure Resource Manager テンプレート、Terraform AzAPI プロバイダーを使用してリソースをデプロイするためのリファレンス ドキュメントを参照してください。 すべてのリソースの種類を表示します。 learn.microsoft.com デプロイの実行と結果の確認 リソースグループの作成 今回は最も一般的な「リソースグループレベル」でのデプロイを行うため、 デプロイを実行する前に、まずはリソースを格納するための「リソースグループ」をあらかじめ作成します。 # リソースグループの作成 az group create --name [リソースグループ名] --location japaneast Bicepファイルのデプロイ リソースグループが準備できたら、作成した main.bicep を展開します。 パラメータファイルを使用する場合は、コマンドの引数に –parameters を追加します。 # Bicepファイルのデプロイ実行 az deployment group create \ --resource-group [リソースグループ名] \ --template-file main.bicep \ --parameters main.bicepparam 実行結果の確認 デプロイ完了後、Azureポータルで対象のリソースグループを確認してみましょう。 画面を確認すると、VNet、NSG、ルートテーブルが1つのリソースグループ内に正しく作成されていることがわかります。 さらにVNetのサブネット設定を開くと、あらかじめ定義した通り、両方のサブネットに同じNSGとルートテーブルが紐づいた状態で出来上がっています。 まとめ 実際にBicepを触ってみて、これまでポータルで一つずつ行っていた作業がコマンド一発で完了する点に、自動化ならではの効率の良さを実感しました。 また、VS Codeの補完機能やAIを活用することで、詳細なリファレンスを読み込まずともスムーズに実装ができました。 IaC化によって管理のしやすさも向上するため、今後は他のリソースも順次コンポーネント化を進めていきたいと考えています。 Bicepに興味がある方は、まずは手近なリソースから触れてみることをおすすめします。
アバター
こんにちは。SCSKの谷です。 本記事ではAmazon WorkSpaces Pools について、とりあえず利用できるように最低限の設定を行い、WorkSpaces Client からWorkSpaces Pools へ接続するまでの手順を紹介しようと思います。 最低限の設定となるため、設定の詳細説明は省略しています。詳細については以下参考資料をご確認いただければと思います。 参考資料 今回WorkSpaces Poolsを使用するにあたり、以下のサイトを参考にしています。 Amazon WorkSpaces Poolsを試してみた | DevelopersIO SAML 2.0 を設定して WorkSpaces Pools ディレクトリを作成する – Amazon WorkSpaces 前提条件 以下を作成済みであることを前提とします。 VPC(NATゲートウェイ作成済み) Azure Portal のアカウント(無料登録可能) ⇒今回IdPとしてEntra IDを使用するため 概要 Amazon WorkSpaces Pools を利用するには、SAMLに対応したIdPとの連携が必要になります。今回はIdPとしてEntra IDを使用するため、AWSだけでなくEntra ID の設定も必要になってきます。 今回設定するサービスは以下になります。 Entra ID(エンタープライズアプリケーション) IAM ID プロバイダ IAMロール WorkSpaces プールディレクトリ WorkSpaces Pools 手順 1.Azure Portal へサインイン(Azure) Azure Portal へサインインし、[Entra ID]の概要からプライマリドメイン名をメモしておきます。 アカウントを登録していない場合は無料登録します。                            2.WorkSpaces プールディレクトリの仮作成(AWS) AWSコンソールより、[WorkSpaces]>[ディレクトリ]>[ディレクトリの作成]を選択します。 以下のように設定を行います。 WorkSpace タイプ: プール ユーザアクセスURL: https://dammy ⇒後続のEntra ID の設定が完了した後に再設定するため、一旦ダミー値を設定しています。 ディレクトリ名: 手順1でメモした Azure Portal のプライマリドメイン名 インターネットへのアクセス: チェックを外す VPC: 用意したもの(デフォルトでも可) サブネット: プライベートサブネット セキュリティグループ: デフォルトのセキュリティグループ 他の設定はデフォルトで、[ディレクトリの作成]をクリックします。 3.Entra ID でエンタープライズアプリケーションを作成(Azure) エンタープライズアプリケーションを作成 Azure Portal へサインイン >[Entra ID]>左ペインの[エンタープライズアプリケーション]>[新しいアプリケーション]>[独自のアプリケーションの作成]を選択します。 以下のように設定を行い、[作成]をクリックします。 アプリの名前: AWS WorkSpaces Pools(任意) アプリの操作: ギャラリーに見つからないその他のアプリケーションを統合します (ギャラリー以外) シングルサインオンの設定 次に、作成されたアプリケーションから[シングルサインオン]>[SAML]>[メタデータファイルをアップロードする]より、以下のXMLファイルをアップロードします。 以下URLよりXMLファイルをダウンロードします。 signin.aws.amazon.com/static/saml-metadata.xml アップロード後に表示される、「基本的なSAML構成」についてはそのまま[保存]をクリックします。 フェデレーションメタデータ XML の取得 次に、「SAML証明書」セクションより、「フェデレーション メタデータ XML」を[ダウンロード]します。 このXMLファイルは次の「IAMでのIDプロバイダの作成」で使用します。 4.IAMでのIDプロバイダの作成(AWS) AWSコンソールより、[IAM]>[IDプロバイダ]>[プロバイダを追加]を選択し、以下のように設定しプロバイダを作成します。 プロバイダのタイプ: SAML プロバイダ名: EntraID-WorkSpacesPools(任意) メタデータドキュメント: 先ほど取得したフェデレーション メタデータ XML ファイル 5.フェデレーション用IAMロールの作成(AWS) IAMロールの作成 AWSコンソールより、[IAM]>[ロール]>[ロールの作成]を選択し、以下のように設定します。 信頼されたエンティティタイプ: SAML 2.0 フェデレーション SAML 2.0 ベースのプロバイダー: 先ほど作成したIDプロバイダ(EntraID-WorkSpacesPools) 許可されるアクセス: プログラムによるアクセスのみを許可する 属性: SAML:sub_type 値: persistent 許可ポリシー: 選択しない ロール名: WorkSpacesPools-SAML-Role(任意) その他はデフォルトで、一旦ロールを作成します。 IAMロールの「信頼されたエンティティ」の編集 IAMロール作成後、IAMロールの「信頼されたエンティティ」を編集します。 以下のように、”Action”内に”sts:TagSession”を追記して更新します。 インラインポリシーの追加 次に、作成したIAMロールにインラインポリシーを追加します。 追加するポリシーの内容は以下です。 { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "workspaces:Stream", "Resource": "<WorkSpacesプールディレクトリのARN>", "Condition": { "StringEquals": {"workspaces:userId": "${saml:sub}"} } } ] } <WorkSpacesプールディレクトリのARN>は以下のように入力してください。 arn:aws:workspaces: <リージョン>:<アカウントID> :directory/ <WorkSpacesプールディレクトリID> 例) arn:aws:workspaces:ap-northeast-1:123456789098:directory/wsd-xxxxxxxxx 6.Entra ID エンタープライズアプリケーションの設定更新(Azure) 新しいクレームの追加・既存クレームの更新 再度Azure Portal に戻り、「属性とクレーム」セクションの[編集]を選択します。 (Azure Portal を閉じてしまった場合は、Azure Portal にサインインし[Entra ID]>[エンタープライズアプリケーション]>[作成したエンタープライズアプリケーション(AWS WorkSpaces Pools)]>[シングルサインオン]より、「属性とクレーム」セクションの[編集]を選択してください。) [新しいクレームの追加]を選択し、以下を追加してください。 名前 ソース ソース属性 https://aws.amazon.com/SAML/Attributes/Role 属性 <IAMロールのARN>,<IDプロバイダのARN> https://aws.amazon.com/SAML/Attributes/RoleSessionName 属性 user.userprincipalname https://aws.amazon.com/SAML/Attributes/PrincipalTag:Email 属性 Azure Portal 登録時に登録したメールアドレス 「https://aws.amazon.com/SAML/Attributes/Role」のソース属性については、手順4,5で作成したIAMロールとIDプロバイダのARNを”,”(カンマ)でつないだものを入力します。 例) arn:aws:iam::123456789098:role/WorkSpacesPools-SAML-Role,arn:aws:iam::123456789098:saml-provider/EntraID-WorkSpacesPools   続けて、「一意のユーザー識別子(名前 ID)」の内容を修正します。 「属性とクレーム」セクションの[編集]より「一意のユーザー識別子(名前 ID)」を選択し、以下のように設定します。 名前識別子の形式: 永続的 ソース: 属性 ソース属性: user.userprincipalname 「リレー状態」の追加 続けて、「基本的な SAML 構成」セクションの[編集]を選択します。 編集画面の下部にある「リレー状態」に以下の値を入力して保存します。 https:// <リレー状態リージョンエンドポイント> /sso-idp?registrationCode= <WorkSpacesプールディレクトリの登録コード> 例) https://workspaces.euc-sso.ap-northeast-1.aws.amazon.com/sso-idp?registrationCode=wsnrt+XXXXXX ※<リレー状態リージョンエンドポイント>については以下サイトより選択する。 SAML 2.0 を設定して WorkSpaces Pools ディレクトリを作成する – Amazon WorkSpaces ※<WorkSpacesプールディレクトリの登録コード>については以下より確認する。   利用ユーザの登録 続けて、エンタープライズアプリケーションの左ペインより、[ユーザーとグループ]>[Add user/group]を選択してユーザを追加します。 今回は「testuser1」を追加しています。 ※ユーザについては、Azure Portal 上部の検索バーから「ユーザー」と検索し、[新しいユーザー]より新規作成できます。 7.WorkSpaces プールディレクトリの本作成(AWS) AWSコンソールより、[WorkSpaces]>[ディレクトリ]>[手順2で仮作成したプールディレクトリ]>認証セクションの[編集]>[SAML 2.0 アイデンティティプロバイダーの編集]を選択し、以下のように設定します。 SAML 2.0 認証の有効化: チェック ユーザーアクセス URL: https://myapps.microsoft.com/signin/<エンタープライズアプリケーションID>?tenantId=<Entra IDテナントID> ※ <エンタープライズアプリケーションID> と <Entra IDテナントID> については以下より確認できます。 WorkSpaces Pools を作成するための事前準備は以上です。 8.WorkSpaces Pools の作成(AWS) WorkSpaces Pools を作成していきます。 AWSコンソールより、[WorkSpaces]>[WorkSpaceの作成]を選択し、以下のように設定します。 オンボーディングのオプション: 私は、自分のユースケースに必要な WorkSpace オプションを認識しています。 WorkSpace タイプ: プール 名前、説明: 任意の値 バンドル: Standard with Windows 10 (Server 2022 based) WorkSpace プールディレクトリ: 今回作成したWorkSpacesプールディレクトリ 今回は接続することが目的なので、その他の設定はデフォルトで[WorkSpace プールの作成]をクリックします。 WorkSpaceプールが停止済みで作成されるので起動します。(起動までに10分程かかります。) 状態が「実行中」になったことを確認し、「登録コード」をメモします。(「登録コード」は次の手順で使用します。) 9.WorkSpaces Pools へ接続する(WorkSpaces Client) WorkSpaces Client から、作成したWorkSpaces Pools へ接続してみます。 WorkSpaces Client がインストールされていない場合は以下よりインストールできます。 Amazon WorkSpaces Client Download WorkSpaces Client を起動し、WorkSpaces Pools の登録コードを入力し[Register]>[Continue to sign in WorkSpaces]をクリックします。 ブラウザにてシングルサインオンの画面が表示されるので、Entra ID で登録した利用ユーザの情報を入力します。 ユーザ名は「ユーザープリンシパル名」を、パスワードは利用ユーザー作成時に設定したものを入力してください。 ※「ユーザープリンシパル名」はAzure Portal より確認してください。 少し待つと、WorkSpaces Client の画面に戻り、以下のように接続することができました! 苦労したこと 初回設定後にWorkSpaces Client からWorkSpaces Pools へ接続を試みた際、WorkSpaces Client の画面に「Something went wrong」というエラーが表示され接続ができませんでした。原因としてはEntra ID 側での設定ミスだったのですが、エラーが詳細に記載されているわけではないため原因特定に時間がかかりました。。 接続がうまくいかない場合は、設定値の確認、VPCやセキュリティグループなどネットワークの確認をお願いします。設定値については環境によって手順通りではない可能性もありますので、公式ドキュメントや他の技術ブログなども参考にしてみてください。ネットワークとしては、インターネットへの経路があるか、インバウンドルール・アウトバウンドルールで特別な制限をしていないか等の確認をお願いします。 まとめ Amazon WorkSpaces Pools について、最低限の設定を行いWorkSpaces Client から接続をしてみました。 Poolsについては多数のユーザからの接続を想定したものになりますので、今回はデフォルト値としましたが、スケーリングの設定を行うことができます。今後はPoolsのスケーリング設定などをいじってみてどのようなスケーリングの挙動となるのか、またファイルはユーザ毎に保存できるのか等を試していければと思います。
アバター
こんにちは! SCSK株式会社 小鴨です。 ServiceNowは何より重い…!そこの認識をごまかす輩は生涯地を這う…! ということで本日はリリースについて必ず付きまとう課題、、、 データ移行 についての解説をさせていただきます!! 多くの皆様にとっては釈迦に説法かもしれませんが そういった方はぜひ、コメントにてより高次元の使い方をご教示いただけると幸いです! 更新セット以外のデータ取り込み なぜ更新セットにすべて入ってくれないのか。。。 開発環境にて様々な開発を行い、さあいよいよ本番反映だ! となったときに、 あれ?この情報って更新セットに入らないの? という疑問を持った経験はないでしょうか? 例えば作成した「グループ」や「ユーザ」であったり グループに紐づいた「メンバー」や「ロール」といった情報は更新セットに入らず 別の方法を使用してテーブルへ直接取り込む必要があります。 今回はその中でexcelを用いた取り込みについてご説明します。 Excelインポートをしてみよう 今回は例としてグループテーブルに2つほどレコードを追加する場合を想定します。 まずは取り込み用のテンプレート取得から始めます。 ①「インポート」の選択 対象テーブルを開き、列名が並んでいる部分を右クリック するとアクション一覧が表示されますので「インポート」を選択します ②テンプレート取得 画面中央の「Excelテンプレートを作成」をクリックすることでダウンロード画面が表示されます。 (「すべてのフィールドをテンプレートに含めますか?」にチェックを入れると、テーブルが持つすべてのフィールドが取得するテンプレートに含まれ、チェックを入れなかった場合は前の画面に表示されていた列のみテンプレートに含まれます。) 「ダウンロード」をクリックすることでテンプレートのダウンロードが可能   ③テンプレート編集 以下のように、取り込みたい情報をExcelに記載していきます。 ※全て埋める必要はなく、入れる値がない場合は空欄でOK ④取り込み 再び以下の画面へ戻り、右クリックから「インポート」を選択。 進んだ画面で「ファイルの選択」から作成したテンプレートを指定し 「アップロード」をクリックします。 ⑤最終確認 この画面になったら「Preview Imported Data」をクリックします 進んだ画面で取り込もうとしたデータの数だけ「インポートセット行」というレコードが作成されているので 試しに開いてみると 以下のように、どこの値にExcelに入力した内容が反映されるか確認することができます ※想定と違う場所に値が入ることもあります。その場合は次回の記事を参照ください。 ⑥取り込み完了 問題なければ元の画面に戻り、画面下部へスクロールし「インポート完了」を選択します。   ※忘れやすいので注意! 完了後、該当のテーブルを覗くと。。。 正しく入っていますね!これにてインポート完了です! 次回予告 上のケースは何の問題もなく、とても平和に事が運んだ場合の紹介になります。 実際は値があべこべに入るような事象もいくらでもあります。 次回はそうした場合の対処法を紹介しようと思います。 「インポートセット」、「変換マップ」という概念にご興味のある方は是非お付き合いください。
アバター
SCSKの伊吹です。 今回はServiceNowのダッシュボードに触れてみたいと思います。 ダッシュボードとは? 日々の業務を行っていると様々な情報が蓄積されていきます。 ServiceNowではレポートとしてそれらの情報を視覚的にわかりやすくグラフや表として表示できます。 しかしレポートが大量にあると確認したい情報に応じてあちこちのレポートを探す必要があります。 そこでダッシュボードという機能を使い、1つの画面の中に関連するレポートなどをまとめておくことで、その手間を省くことができます。 更に用途に応じて複数のダッシュボードを用意しておくことで、インシデント情報が見たければインシデント用のダッシュボード、問題情報が見たければ問題用のダッシュボードを選択することで素早く情報を得ることが出来ます。   ダッシュボードにアクセス ①ServiceNowにログインします。 ②アプリケーションメニューから[セルフサービス > ダッシュボード]を選択します。   ③ダッシュボードの一覧が表示されます。 ServiceNowには導入時点で複数のダッシュボードが準備されています。 ④用途に応じたダッシュボードをクリックします。(ここでは例としてIncident Management) 各ダッシュボードには様々なレポートが紐づけられております。(下図で表示されているのは全体の一部です。)   ダッシュボードを作ってみよう 前段ではServiceNowが予め用意していたダッシュボードにアクセスしました。 しかし「あのレポートとこのレポートを組み合わせることで、より自分の業務にあった使いやすいダッシュボードになるのに・・・」という要望が出てくると思います。 ここでは自分の用途にあったダッシュボードを作成してみたいと思います。 ①ダッシュボードの一覧画面の右上にある「新規ダッシュボードを作成」ボタンをクリックします。 ②「インラインエディター」を選択し、名前と説明を入力し、「新規ダッシュボードを作成ボタン」をクリックします。 ※「テクニカルエディター」を使うことでより詳細なカスタマイズを行えますが本投稿では割愛。 ③「新しい要素を追加」ボタンをクリックします。 ④「新しい要素を追加」ボタンをクリックし、追加したい要素を選択します。 ここでは「データの可視化」と「イメージ」を追加してみます。 ⑤「データの可視化」をクリックし、「保存済みの可視化」を選択します。 ※自分で新しい可視化(=レポート)を作成したい場合は「新しい可視化」を選択します。 ⑥登録されているレポートの一覧が表示されます。 例として「Incident created (by priority)」を選択し、「ダッシュボードに追加」ボタンをクリックします。 ⑦続いて④の画面から「イメージ」をクリックします。 画面右側に構成画面が表示されますので、「Choose a custom image」をクリックして表示させたい画像を選択します。 ⑧画面に追加した要素が表示されたのを確認し、「保存」→「編集モードを終了」をクリックします。 ⑨ダッシュボード一覧を確認すると、作成したダッシュボードの名前が表示されます。 名前をクリックすると先ほど作成したダッシュボードが表示されます。   まとめ ServiceNowのダッシュボードについて紹介しました。 ServiceNowには様々なダッシュボードやレポートが最初から登録されていますので、まずはどんなものがあるのか覗いてみてください。 その上で自分にあった組合せがない場合は、オリジナルのダッシュボードを作成してみては如何でしょうか。
アバター
SCSKの畑です。 とある案件において 他クラウド IaaS 上の Redis から Amazon Elasticache(Redis OSS)へのデータ移行要件があったため、移行方式についてどの方式を採用したのかを含めてまとめてみました。   背景 前回のエントリでも軽く触れた通り Redis は KVS のため、例えばキャッシュのような揮発性の高いデータのみが格納されているようなケースではデータの移行要件がないこともありますし、移行対象のデータがあるとしても新しく立てた Elasticache にアプリケーション/バッチなどから必要なデータを改めて入れ直すなど、現行の Redis からデータを移行する必要がないことも多いと思います。 ただ今回の案件については、現行の Redis からデータを移行する要件がお客さんとの会話等などから明確であったため、それを踏まえて Redis から Elasticache(Redis OSS)へのデータ移行方式を検討することとなりました。 なお、当初は Elasticache(Valkey)への移行も検討されましたが、今回の案件では非互換の可能性を極力排除して AWS への移行(リフト)のみにフォーカスしたいというお客さんの意向もあり、Redis OSS を採用することとなりました。   Amazon Elasticache の移行方式  Elasticache への移行方式は以下3種類となります。一括移行 or 初期移行+差分移行という考え方そのものは RDBMS などと同じですね。 ちなみに、初期移行は差分移行を開始する前に現行環境から新環境にデータを移行する工程、差分移行は現行環境の更新データを初期移行直後の時点から新環境に対して継続的にレプリケーションする工程をそれぞれ指します。一括移行は言葉通りの意味ですね。 一括移行 初期移行+差分移行(AWS マネージド) 初期移行+差分移行(RIOT などの外部移行ツール) 当初は初期移行+差分移行の選択肢として DMS を使えると思っていたのですが、改めて調べるとサポートされているのは移行ターゲットのみであることが分かり、今回のケースでは採用できませんでした。 Sources for AWS DMS - AWS Database Migration Service Use the listed data stores as sources for different AWS DMS features. docs.aws.amazon.com Elasticache における一括移行は、移行元の Redis で save コマンドなどで rdb ファイルのバックアップを取得して S3 に転送・配置した上で、そのバックアップを使用して新しく Elasticache のインスタンスを立ち上げる流れとなります。 バックアップから新しいキャッシュへの復元 - Amazon ElastiCache Valkey から既存のバックアップを新しい Valkey キャッシュまたはノードベースのクラスターに復元し、既存の Redis OSS バックアップを新しい Redis OSS キャッシュまたはノードベースのクラスターに復元できます。また... docs.aws.amazon.com 対して、初期移行+差分移行の方式は、AWSマネージドの方式と、RIOTなどの外部移行ツールを使用する方式の2種類があります。AWSマネージドの方式については、以下 AWS ドキュメントに一通りの記載があります。 Valkey または Redis OSS のオンライン移行 - Amazon ElastiCache オンライン移行を使用して、セルフホスト型 Valkey または Redis OSS から Amazon ElastiCache にデータを移行します。 docs.aws.amazon.com 外部移行ツールを使用する場合は、ある意味当然ながらそのツール仕様に準じます。今回移行方式としては採用しなかったのでざっくり調べた程度ですが、ツールとしては Redis 公式?の RIOT が最もメジャーなようです。 Redis Input/Output Tools (RIOT) redis.github.io 必ずしも Elasticache 固有の内容ではありませんが、それぞれの移行方式の特徴についても簡単にまとめておきます。 一括移行 メリット 移行(切替)当日に移行対象の全データを現行環境から新環境に移行する方式のため、初期移行+差分移行と比較して相対的に手順がシンプル 移行に要するトータルの工数も(一般的に)少ない デメリット 移行(切替)当日の所要時間・工数は初期移行+差分移行と比較すると多くなる このため、移行(切替)時のスケジュールが一括移行の所要時間に収まらない場合は、スケジュールを見直す or  初期移行+差分移行方式を採用する、の2択となる 初期移行+差分移行 メリット 一括移行と比較して、移行(切替)当日の所要時間・工数は少ない 差分移行に使用する製品・サービス(例えば DMS など)によっては差分移行中に現行環境/新環境間のデータ整合性チェックを実施することも可能 移行(切替)当日に現行環境/新環境間でデータの整合性をチェックできるのが理想だが、移行対象のデータが大きい場合は移行(切替)時のスケジュールに収まらなくなる可能性があるため、このような方式で整合性チェックを行うことも選択肢に入ってくる デメリット 移行方式における制約や注意すべき事項が多い 初期移行において現行環境からデータを移行する際、現行環境への影響を考慮の上で具体的な方式・手順を決定する必要がある 初期移行は現行環境のシステムが稼働している状態で実施することが方式の特性上ほぼ前提となるため 逆に言うと、初期移行時に現行環境のシステムを停止できるのであれば事実上一括移行が可能と言えるため、この移行方式をわざわざ採用する必要がない 差分移行に使用する製品・サービスにおける各種制約に抵触していないかを確認する必要がある 制約に抵触することの影響度合いはケースバイケースだが、方式自体の採用可否に影響する場合もある 差分移行の特性上現行環境と新環境が相互通信できる必要があるため、通信経路の確立や帯域制限などが方式上のネックになる場合もある 上記内容も相まって、移行に要するトータルの工数は(一般的に)多い   今回採用した Amazon Elasticache の移行方式  結論から言うと、今回は「一括移行」を採用しました。上記で移行方式の特徴をまとめた通り、一括移行の採用可否は実質的に移行(切替)当日の想定スケジュールに一括移行の所要時間が収まるかどうかですが、検証環境で時間を計測したところ無事に収まりそうなことが分かったためです。具体的な所要時間の試算は以下のような流れで行いました。 ちなみに今回はデータベース(MySQL)の移行も同時に行うのですが、時間的にはそちらがボトルネックになるということも理由の一つでした。データベースの移行所要時間内に収まっていれば大丈夫だろうということで。 まず、今回移行対象となる Redis は 2 個あります。キャッシュサイズはそこそこ差があり、大きい方が約 100 GB だったため、ほぼ同じサイズのキャッシュデータをオンプレミス仮想環境上の Redis に用意した上で、Redis から rdb ファイルにバックアップする所要時間、及び S3 上のバックアップを Elasticache for Redis OSS にリストアする所要時間をそれぞれ計測しました。 Redis から rdb ファイルにバックアップ: 20 分 rdb ファイルのサイズは約 98 GB お客さんの IaaS 環境上ではもう少し早くなりそうですが(10-15分程度)、試算では上記計測値を使用 S3 から Elasticache for Redis OSS にリストア: 35 分 インスタンスサイズは cache.r7g.8xlarge 一括移行の所要時間としては上記に加えて Redis サーバから S3 へのバックアップファイル転送時間がプラスされますが、こちらはお客さんの IaaS 環境上で試算したところ 20 分程度見ておけば良さそうということで、合計で 20 + 20 + 35 = 75 分となりました。もう 1 個のキャッシュサイズは小さいため、トータルの所要時間への影響はほぼないと判断しています。 また、先述の通りバックアップを使用して Elasticache インスタンスを新しく作成する手順となるため、作成後に単体テスト・動作確認を実施する方針となりました。直列で作業する前提で 1 個につき 30 分かかるとしても 2 個で 60 分、合計すると 135 分 となります。 移行(切替)当日の想定スケジュールにおいて、データベース/Elasticache の移行に使用できる時間は 最大 6 時間 であるため、無事 Elasticache については時間内に一括移行できる見立てとなりました。 ただし、一括移行において「 バックアップを使用して新しく Elasticache を作成する 」という手順(仕様)により別の課題も想定されたため別途対策が必要になりました。そのあたりの話はまた別エントリでしたいと思います。 なお、このような検討過程であったため差分移行については真剣に検討するまで至らなかったのですが、ざっくり調査した内容及び所感を以下にまとめておきます。(真剣に検討していないのであくまでも参考程度で・・) AWS マネージド 初期移行および差分移行の両方をカバーしており、使用方法自体も非常に簡単  そもそもコンソール/コマンドから設定できる項目も必要最低限(実質的に移行元 Redis への接続情報のみ) https://docs.aws.amazon.com/cli/latest/reference/elasticache/start-migration.html その反面、使用に際しては様々な制約があるため、特に本番環境の移行で使用できるケースは限定的と思われる 特に「 転送(接続)時のSSL無効化 」や「 認証の無効化 」が必要なため、移行元の Redis でこれらの制約を満たさない場合は使用できない(今回の案件でもこの時点で採用 NG)  https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/dg/Migration-Prepare.html 移行対象の論理データベースやデータをフィルタリングするような機能はない レプリケーション開始時にターゲットとなる Elasticache のキャッシュデータが削除される仕様も良し悪し レプリケーションが失敗した場合の再試行自体は行いやすい反面、失敗した時点から再開するようなことはおそらくできないものと思われる(自動復旧した場合は別かも?) 外部ツール(RIOT) AWS マネージドの場合と比較して、認証や転送(接続)時の SSL が有効な場合も対応可能 RIOT が動作する中間サーバを用意する必要あり レプリケーション動作モードに scan と liveonly、及び 両方を併用した live の3種類がある scan は実質的な初期移行、対象の key や type、回数などをオプションとして指定可能 liveonly は実質的な差分移行(レプリケーション)だが、ドキュメント曰くデータの整合性を保証しないとのこと NW 障害時に Redis 上データの更新通知を RIOT が受け取れなかったり、Redis 上の大量データ更新時に Redis 自身が大量データの更新に追随できない(更新通知を送れない)可能性がある レプリケーション動作時の挙動も dump/restore コマンドを使用するモード、及びデータタイプにより異なるコマンドを使用するモードの 2 種類がある模様 こちらは特別な理由がない限り前者で良さそう(デフォルトも前者) もし今回の案件で使用せざるを得ない場合は上記制約との兼ね合いで RIOT になりますが、設計には正直骨が折れそうです。。 ちなみに RIOT 自体はメンテナンスを終了しており、後継ツールとして RIOT-X が開発されているようです。 RIOT-X :: RIOT-X redis.github.io   まとめ Elasticache に限った話ではありませんが、このようなデータ移行についてはまず一括移行できないかどうかを優先して考えるべきです。逆に言うと、初期移行+差分移行は対象システムの重要度や特性に基づく移行要件、及びデータ量などを鑑みた場合に(ある意味)やむを得ず選択する方式というくらいの位置づけで考えて良いと思っています。もちろん、DMS を始めとして初期移行+差分移行に使用できる製品・サービスはここ 10 年くらいで大分充実してきているので、取り得る選択肢が広がっているのはいいことですが。 最も、Elasticache(Redis)はインメモリベースであるため、一般的な RDBMS のようなディスクベースの製品・サービスと比較して相対的に高速にデータ移行できるであろう点も踏まえると、一括移行する方針により倒しやすいとは思います。。 本記事がどなたかの役に立てば幸いです。
アバター
最近、EC2によるWebサーバの構築にあたり、ダッシュボードを使う機会があり、大変便利だということに気づきました。 今更ながらですが紹介します。 EC2に限った話ではありませんが、例として読んでください。 EC2の監視項目について EC2を監視するにあたり、監視する項目は一般的には以下のようなところでしょうか。 標準メトリクス CPU使用率やEC2のStatusCheckFailedなど カスタムメトリクス メモリ使用率や、cloudwatch logs に転送したログに定義したメトリクスフィルターによるものなど OS/MWログ cloudwatch agentでログを転送しているケースで、特に特定ワードでエラーを検知しているようなケース 各種アラーム 上記のメトリクスなどに設定したアラームのステータス これらをあれこれ見たい場合は画面の遷移が多くなり、思った以上に面倒です。 見る項目は大抵決まっていますが、いちいち対象を選択しないといけないのも面倒です。   ダッシュボード例 サンプルサーバで上記をカバーするダッシュボードを作成してみました。 例として、CPU使用率(標準メトリクス)、メモリ使用率(カスタムメトリクス)、サンプルのアラームステータス、および転送ログを一覧表示しています。参照する対象がほぼ固定の場合は一つ作っておけば大変便利です。これを普通にそれぞれ確認するとなると、複数画面を横断する必要があります。   作り方 先ずはダッシュボードの作成です。要件に応じて適当な単位で作りましょう。(サーバ毎、VPC毎、案件毎、など) 名前は適当につければよいです。         次に各種のメトリクスなどを追加していきます。 からの データ型はメトリクス、ログ、アラームと3種類あり、メトリクスは例で挙げた画像の左半分、ログは右下部分、アラームは右上部分に対応しています。 個々のグラフの作り方には触れませんが、やればわかると思います。各種色々なタイプがあるので試してみましょう。 注意:アラームは通知はされません。通知は別途、アラーム定義のアクションでSNSを定義するなどの必要があります。   ログウィジェットについて メトリクスとアラームは簡単なのですが、ログウィジェットについて触れておきます。 ログのウィジェットは以下のように、ロググループを選択し、CloudWatch Insightsのクエリで表示を絞ることができます。 (* ウィジェットタイプは”ログテーブル” を選択しましょう。) 上記は特定のロググループに対して”Error” 文字列を含むレコードのみを抽出しています。ダッシュボードに表示させたいレコードのみを抽出して表示させるのがよいでしょう。ダッシュボードはこうなります。 特に、ロググループに対してメトリクスフィルターでエラー検知をしている場合、アラートが発報してもどのレコードが探すのが大変というケースはあります。その場合はメトリクスフィルターと同等のクエリー定義を使ってダッシュボードに表示させれば異常レコードはすぐに判明するでしょう。   最後に EC2の、と書いてしまいましたが、EC2でなくともどのようなメトリクスも含めることができます。 環境内の主要な監視項目をまとめておけば、必要な情報にすぐにアクセスできるため、大変便利に感じました。 簡単に作成できますので、色々試されるとよろしいかと思います。
アバター
こんにちは。SCSKの松渕です。 今回は 2026年1月27日に発表 されたばかりのGeminiの超強力な新機能、 Agentic Vision について検証したのでブログ書いていきます!! はじめに Agentic Visionとは 端的に言うと Gemini 3 の 拡張機能 です。(flashの機能と広く説明されてますが、proでも利用できました) Geminiが 自ら動的にコードを書いて 画像を能動的に『調査』する機能 です。 いままでのマルチモーダルAIでは、画像認識は静的なもの(一度見るだけ)でした。 この機能を活用すると、Geminiが Pythonコードを自動生成 し、特定の領域をクロップ(切り抜き)したり、ズームしたりといった 自律的にアクション をして、結果をさらに観測するというループを回すことができるようになります。   なお、 Googleがデモを公開 しているので、ぜひ一度体験してみてください!!   主なユースケース 主なユースケースは以下のように考えられているようです。 1. 精密な検査とズーム Geminiに処理させたい内容次第では、画像は大きいが処理内容としては一部分だけ必要になることがあります その際、 必要な部分だけをズームする と精度が上がるため、Gemini自身が拡大の必要性を判断して実行します。   2. 正確なカウントとアノテーション 飲み会とかで人数カウントする際、10人超えてくるとぱっと見でわからなくなりますよね? そういうとき、一人ひとりカウントしていくかと思います。 同様に、「数えた」という印を画像につけていくことで カウントを正確にする といったことも可能です。   3. アナログデータのデジタル資産化 アナログデータを画像認識し、そのまま Pythonでグラフ化して可視化 する、といった一連の処理が自律的に完結します。 また、Google検索等のグラウンディング機能を併用すれば、 画像から読み取ったデータと「世の中の最新トレンドや統計データ」を掛け合わせた分析レポートを自動作成 する、といった活用も可能になります。   設定方法 試し方としては大きく2つのやり方があります。 1. Google AI Studio で試す(最速30秒) まずは手元の画像で動かしてみたい、という方はこちらが一番早いです。 モデルの選択 : 右側の設定パネルで Gemini 3 Flash を選択します。 ツールの有効化 : 同じ設定パネル内にある 「Tools」 セクションを探し、 「Code Execution」 のチェックボックスをオンにします。 画像をアップロード : プロンプト入力欄に解析したい画像を貼り付けます。 依頼を投げる : 「画像内の〇〇を詳しく調べて」など、精密な調査が必要な指示を出します。  ズームが必要だとGeminiが判断すれば、勝手にPythonコードが走り、ズームされた画像(クロップ画像)が生成され始めます。   2. Vertex AI (Python SDK) で実装する Google Cloud環境でアプリに組み込む場合は、SDKからツールとして定義します。 Python SDKであれば、gemini API呼び出し時configに 以下一行追記するだけ です。 tools=[types.Tool(code_execution=types.ToolCodeExecution())] 簡単そう!と思って今回はVertex AI Studioでやってみることにしてみました。 が、意外にもちょっと面倒でした。。。   前準備 インプット画像準備 読み取りにくそうなpdfサンプル準備します。手書きの何かの申込書らしきものを作成してみました。 あえて反転 させております。 ※住所、カード番号、電話番号は架空のものです。   Agentic Vision無しで読み取り 失敗例が欲しく、一度Vertex AI Studioで普通に読み取り処理流します。 利用したプロンプトはこちら。システムプロンプトにもう少しちょこちょこ書きましたが割愛。 # 以下の項目を読み取ってください - ふりがな - 氏名 - 性別 - 所在地(郵便番号) - 所在地(住所) - 電話番号 - メールアドレス - 申し込みコース - サービス開始希望日 - 追加オプション ※複数申し込み可能 - お支払い方法  ※単一選択。丸印での選択 - 請求締日  ※「お支払い方法」で請求書払いを選択している場合のみ - カード名義  ※「お支払い方法」でクレジットカードを選択している場合のみ - クレジットカード種別  ※「お支払い方法」でクレジットカードを選択している場合のみ   単一選択 - カード番号  ※「お支払い方法」でクレジットカードを選択している場合のみ - カード有効期限  ※「お支払い方法」でクレジットカードを選択している場合のみ  "XX年XX月" の形式で出力すること - 請求先名   ※「お支払い方法」で請求書払いを選択している場合のみ 出力結果は以下でした。 { "ふりがな": "まつぶち けんた", "氏名": "松渕 健太", "性別": "男", "所在地(郵便番号)": "012-3456", "所在地(住所)": "東京都千代田区千代田1-1-1", "電話番号": "090-1234-5678", "メールアドレス": "xxx@gmail.com", "申し込みコース": "A. プラン1", "サービス開始希望日": "2026年2月20日", "追加オプション": [ "追加サービスC" ], "お支払い方法": "1. クレジットカード", "請求締日": "", "カード名義": "Kenta Matsubuchi", "クレジットカード種別": "VISA", "カード番号": "123456789012", "カード有効期限": "26年12月", "請求先名": "", "請求先住所": "" } あれ。。 Agentic Vision無しで成功 しちゃった。。Gemini 3 flash 賢すぎないですか? でもまぁ、突き進みます!!   設定と実行 Vertex AI Studioでの実施試みるがNG Google Cloudの画面から、Vertex AI Studioの画面を開きます。 プロンプトを入れて、資料添付した状態にします。 右上の「コード」ボタンを押下。   以下の画面に遷移します。   「2.Use the following code in your application to request a model response」のところに1行入力するだけ! と思ってたら、入力できませんでした。   APIキーの発行 ということで、 面倒ですがNotebookから実行 することにします。 先ほどの画面の上部の「ここですべてのAPIキーを表示するか、新しいAPIキーを作成できます」を押下。   設定画面へ遷移するので、「APIキーを作成」を押下。APIキーが作成されます。 「鍵を表示します」をクリックして APIキーをコピー しておきます。  →   → 今回、検証には Google AI Studio で発行したAPIキーを使用しました。非常に便利な一方、 間違って公開等してしまった場合には、不正利用されて高額請求が来てしまう等のリスクがあります !! ソースコードへのべた書きし、そのままGitHubで公開してしまう等の事象はよく聞きますので、十分ご注意ください。   Vertex AI Studioの画面に再度戻り、「ノートブックを開く」を押下。   Colab EnterpriseのNotebookからの実行 ノートブック画面に遷移します。「YOUR_API_KEY」部分に先ほどコピーしたAPIキーを貼り付けて、まずは実行します。 正常に動きました。   次のセクションですが、 ノートブックを開く前から入力していたプロンプトがすでに反映された状態 かと思います。   そのため、generate_content_configの中に「 tools=[types.Tool(code_execution=types.ToolCodeExecution())], 」 の一行だけを追記して実行すればAgentic Visionは動作します! ただし、私はブログ用に途中での思考や画像加工した出力も出すようにいろいろと変えたので、追記部分太字で記載します。 from google import genai ~~省略~~ text1 = types.Part.from_text(text="""# 以下の項目を読み取ってください。 読み取る上で、画像反転や拡大等必要であれば実施ください。 # 画像出力に関する重要ルール 画像を保存(imwriteなど)したら、必ずその直後に以下のコードを実行して、 画像データを標準出力に書き出してください。これがないと画像が見えません。 ~~省略~~ generate_content_config = types.GenerateContentConfig( temperature = 1, top_p = 0.95, max_output_tokens = 65535, ★★以下一行追加★★ tools=[types.Tool(code_execution=types.ToolCodeExecution())], ~~省略~~ for chunk in client.models.generate_content_stream( model = model, contents = contents, config = generate_content_config, ): for part in chunk.candidates[0].content.parts: # ★★ 以下、プロセスの出力のため追加★★ # 1. 思考プロセスの表示(青文字) if part.thought: print(f"\033[34m[Thinking]:\033[0m {part.text}") # 2. 実行したコードの表示(緑文字) elif part.executable_code: print(f"\n\033[32m[Action - Python Code]:\033[0m\n{part.executable_code.code}\n") # 3. 生成された「画像」をその場で表示! elif part.code_execution_result: output = part.code_execution_result.output print(f"[Execution Output]: {output}") # ログとして表示 if output and "FILE_DATA:" in output: # AIが吐き出したbase64データを探す for line in output.split("\n"): if line.startswith("FILE_DATA:"): _, filename, b64data = line.split(":", 2) # ローカルに保存 with open(f"debug_{filename}", "wb") as f: f.write(base64.b64decode(b64data)) print(f"\n★画像を保存しました: debug_{filename}") # Colabなら表示 display(Image(f"debug_{filename}")) # ★★ここまでプロセスの出力のため追加★★ # 4. 最終回答 elif part.text: print(part.text, end="") generate()     結果確認 実行結果 [Thinking]: **Contemplating Image Processing** I've been working on extracting data from a scanned form. Right now, I'm focusing on the initial image processing steps. I've realized the image needs a 180-degree rotation . After that, I will attempt to identify and segment the various fields within the document, such as the provided "ふ" field. ~~省略~~ [Action - Python Code]: import cv2 import numpy as np # Load the image img = cv2.imread('input_file_0.png') # Rotate the image 180 degrees rotated_img = cv2.rotate(img, cv2.ROTATE_180) cv2.imwrite('rotated_form.png', rotated_img) ~~省略~~ ★画像を保存しました: debug_top.png ★画像を保存しました: debug_middle.png ★画像を保存しました: debug_bottom.png ★画像を保存しました: debug_rotated_form.png [Thinking]: **Examining the Fields** I'm now able to see the images with much greater clarity. This has led me to re-examine the identified fields. Right now, I'm taking a close look at the details within them, such as `ふりがな`, `氏名`, `性別`, and `所在地(郵便番号)`. The circled "男" for gender is particularly helpful. ~~省略~~ 黄色マーカー部分だけ読んでもらえればと思いますが、 最初に180度回転させる必要があると判断 して 自律的にアクション しているのが見て取れます。ローテーションだけでなく3分割した画像も作っておりますね。 最後に、 クリアに見れるようになったと自分でコメント してます!! なお、出力されたファイル群は以下の通り。 反転が戻った画像 と、 1/3ずつに拡大した画像 が中間ファイルとして作成されておりました。   もちろん最終的な出力JSONは、 すべて正しく読み取れておりました。 Agentic Vision使う前から読み取れていたので当然ですが。。。   まとめ 今回は、Googleの最新機能である Agentic Vision を使い、手書きの反転画像をJSON化する検証を行いました。 特に印象的だったのは、Geminiが自ら「画像が逆さまだから180度回転させよう」「文字が小さいから3分割して拡大しよう」と 判断し、Pythonコードを生成・実行 したプロセスです。これまでの「ただ画像を見るだけ」のAIとは一線を画す、まさ に 「意思を持った調査員」のような挙動でした。 また、本来の目的とは違いますが、 Gemini 3 flashがそもそも画像認識能力が非常に高い と感じました。 破線〇への○付きや、かすれたチェックボックスをすべて一発で正確に読み取る とは思っていなかったので、その点も非常に驚きでした。 画像解析の「精度」の壁に悩んでいた方は、ぜひ一度このAgentic Visionを試してみてください。きっと、AIが「自分で虫眼鏡を取り出す」瞬間に驚くはずです!
アバター
SCSKでは、Dropbox導入案件の多くで、オンプレファイルサーバやNASなどからDropboxにデータ移行のお手伝いをさせていただいております。近年、弊社がデータ移行する際はDropbox社が推奨するMovebotというデータ移行ツールを利用することがほとんどです。 しかし、実は別記事(「 【決定版】Dropboxへのデータ移行を自力で効率化!SCSK「セルフデータ移行ツール」忖度なしレビュー 」)でも紹介しているように、弊社ではDropbox APIを使ったセルフ データ移行ツール を開発しています。 そこで、今回は、Dropbox APIによるデータ移行方法、移行で利用するAPIの説明や開発時に苦労した点などをご紹介したいと思います。 ちょっと脱線 – Dropboxへのデータ移行方法 本題に入る前に、少しDropboxへのデータ移行方法についてお話したいと思います。 筆者が初めてDropboxへのデータ移行案件に関わった2018年頃の話です。 まだDropboxへのデータ移行ツールが存在せず(という記憶があります)、Dropboxデスクトップクライアントのデータ同期機能を使って移行するしか方法がありませんでした。ただ、この方法にはいくつか大きな課題がありました。 Dropboxデスクトップクライアントでのデータ移行って大変なんです Dropboxデスクトップクライアントを使ったデータ移行については、以前のブログ記事「 Dropboxへのデータ移行ってどうやるの? 」に詳しいことをご紹介していますので、そちらを見てください。 課題をまとめると次の3点です PCのローカルストレージ容量問題です Dropboxデスクトップクライアントの最大同期数の問題です データ同期の結果を確認することができないことです このように、Dropboxデスクトップクライアントを使ったデータ移行は、PCストレージ容量と同期ファイルサイズに大きく影響され、100GB以下の小規模なデータ移行までが限界という感じです。Dropbox導入企業様自身でデータ移行するには良い方法かもしれませんが、ファイルサーバのような大規模データ移行には向いてません。 Movebotは… 冒頭でお話したとおり、近年弊社ではDropbox導入案件のデータ移行作業において、Movebotを受かってデータ移行を行っています。その主な理由は、下記の3点です。 Movebotは、データ移行に用いるPCのローカルストレージを利用しないこと (ストレージ容量の影響を受けない) WEB画面からリモート操作が できること データ移行ログが充実していること 特に、1. のPCローカルストレージの容量に影響しない仕組みのため、大容量のデータ移行に向いたツールです。 ただ、Movebotにもデメリットはあります。Movebotはデータ転送容量課金ですので、データ移行容量によってはデータ移行コストが高くなってしまいがちです。データ移行作業に回せる予算が少ないと、Movebotの採用は難しい場合も…。 Movebotについては、別のブログ記事で詳しくご紹介していますので、そちらもご覧ください。 「 Dropboxへのデータ移行ってどうやるの? 」 「 Movebot×Dropbox!データ移行ツールMovebot 」 Dropbox APIによるデータ移行ツール! Movebotのように、PCストレージ容量に影響を受けないようにするには、ファイルサーバから読み取ったデータを直接Dropboxにアップロードする必要があります。これを実現するのが、Dropbox社が公開しているDropbox APIです。 Dropbox APIにはたくさんの機能エンドポイントが用意されていますが、その中にファイルアップロードするためのAPIも含まれています。これを使ったデータ移行ツールを開発し、お客様自身で比較的簡単にデータ移行できるようなにツールを提供できれば、喜んでいただけるのではないか。そうして開発したのが  sxtool です (GUI付き版が 「セルフデータ移行ツール」となります) 。弊社自身、気楽に使えるデータ移行ツールが必要だったというのも理由の一つですが…。 それでは、Dropbox APIを使ったデータ移行処理について詳しくご紹介したいと思います。 「 SCSKにてDropbox APIで作成したツールを紹介します 」 【決定版】Dropboxへのデータ移行を自力で効率化!SCSK「セルフデータ移行ツール」忖度なしレビュー 」 Dropbox APIを使ったデータ移行処理 データ移行処理って? ファイルサーバのデータをDropboxに移行するには、下記のようにファイルサーバからファイルのデータを読み込み、Dropbox APIを使ってDropboxに書き込むことで実現できます。  図1: データ移行ロジック ファイルサーバのファイル読み込みは、開発言語に用意されているファイルI/Oのライブラリ(関数)を利用すれば簡単に実装できます。Python だと、下記のようにopen関数やread関数を使います。 with open(path, 'rb') as f: # path変数で指定したパスのファイルを開く   data = f.read()          # データ読み込み処理 Dropbox へのファイルアップロード Dropboxに読み込んだファイルデータを書き込む(アップロード)には、Dropbox APIの upload エンドポイントを使用します。下図は、Dropbox開発向けサイトの upload エンドポイントのマニュアルを抜粋したものです。(出典: HTTP – Developers – Dropbox ) 図2: uploadエンドポイントマニュアル(抜粋) 上記マニュアルに記載されてるように、upload エンドポイントは、Dropbopxでのファイルパスや書込みモードなど、いくつかのパラメータと(読み込んでおいた)ファイルのバイナリデータを指定し、Dropboxにアップロードします。 upload エンドポイントのパラメータ: path: ファイルパス mode: 書込みモード (追加(add) / 上書き(overwrite) / 更新(update)) autorename: 自動でファイル名を変える (上書きせず、番号をつける) mute: 通知をする/しない client_modified: 移行元のファイルタイムスタンプを指定 (更新タイムスタンを保持できる) など pythonでDropboxにファイルアップロードする処理を実装すると、下記のようになります。 with open(path, 'rb') as f: # path変数で指定したパスのファイルを開く         data = f.read() # 移行元のデータを読み込み       url = 'https://content.dropboxapi.com/2/files/upload'     param = { # upload エンドポイントのパラメータを指定         "path": path,         "mode": mode,         "autorename": False,         "client_modified": source_file_timestamp,         "mute": False,         "strict_conflict": False     }     headers = {         "Authorization": "Bearer " + oauth_token,         "Content-Type": "application/octet-stream",         "Dropbox-API-Arg": json.dumps(param),     }     response = requests.post(url, headers=headers, data=data) # APIコール このコードを実際に動かすには、Dropboxの認証情報である OAUTH_TOKEN を事前に取得し、”oauth_token” 変数に代入するか、oauth_token 部分を OAUTH_TOKEN文字列に置き換える必要があります。 また、他にも、uploadエンドポイントの結果確認処理や例外処理など実現すべき点はたくさんあります。 フォルダ単位のデータ移行 1ファイルのみアップロードする処理は、先程ご紹介したとおりです。この処理を移行元フォルダ配下の全ファイル分繰り返し実施すれば、フォルダ単位の「データ移行」が実現できます。移行元フォルダにサブフォルダが存在した場合、サブフォルダの作成処理とサブフォルダの移行処理(フォルダ単位の移行処理を再帰的に呼び出す)を実施します。 これをチャートにすると、ざっくり下図のようになります。 図3: データ移行ロジック2 この仕組みでデータ移行すると、1ファイルずつファイルサーバから読み込んでは、Dropboxにアップロードすることになります。要は、シーケンシャルに1ファイルずつしか移行できないわけです。 例えば、1MBのファイルを1つアップロードするのに、0.2 秒掛かると仮定すると、1MB x 1万ファイルのデータ移行に 約 33 分掛かります。 式) 0.2 秒 x 10,000 = 2,000 秒 ≒ 33分 このときのデータ転送速度は 5MB/sec です。 式) 1MB x 10,000 ÷ 2,000 秒 = 5 MB/sec   ネットワーク帯域が 1Gbps (=125MB/sec) の回線だと仮定すると、データ移行ではネットワーク帯域を少ししか使っていないことになりますね。ネットワーク帯域の1Gbpsという数値は理論値なので 実際には理論値の 5~6割程度が利用可能な帯域だとしても、帯域の 1/10 くらいしか使っていませんね。ネットワーク帯域をすべて使い切ってしまうと他の業務に影響がでるため好ましくありませんが、業務に影響が出ない範囲でデータ移行が利用する帯域を増やして、移行時間を短縮する必要があります。 データ移行の並列化 さて、ネットワーク帯域をもっと有効活用するにはどうすればいいでしょうか? そうです、Dropboxサーバへのファイルアップロード処理を何個も同時実行すればいいのです。 例えば、4ファイル同時にアップロードできれば、5MB/sec x 4 = 20 MB/sec の帯域を使いますが、4ファイル順番に移行するよりも単純計算で移行時間が 1/4 になります。1万ファイルの移行時間もたったの 8分ちょっとに短縮できちゃいます。ファイルアップロードの並列化は移行時間の短縮にとても効果がありそうです。 APIコール数の削減 また、APIコール数の削減も移行時間の短縮に効果があります。 Dropbox APIの処理時間は「リクエスト送信 +サーバでの処理+レスポンス受信」の合計となります。例えば リクエスト送信 0.2秒、サーバサイド処理 0.3 秒、レスポンス受信 0.2 秒 と仮定すると、1 APIコールの処理時間の合計が 0.7 秒。「リクエスト送信」と「レスポンス受信」で 0.4 秒。「サーバサイド処理」が 0.3 秒 ですので、「リクエスト送信とレスポンス受信」の処理時間のほうが「サーバサイトの処理」よりも長くなってしまっていますね。 Dropboxのデータ移行先サブフォルダを作成する場面で計算してみましょう。 移行元には500個のサブフォルダが存在するとします。1サブフォルダずつフォルダ作成を行うとすると、create_folder エンドポイントを 500 回コールすることになります。これだけで、350秒 (約 6 分) もかかっちゃいます。 式) 500 x 0.7 秒 = 350 秒 (約 6 分) 1回のサブフォルダ作成リクエストで複数のサブフォルダをまとめて作成できると、 APIコール数を削減できますね。1リクエストで 500個作成できるとすると、499 x 0.4秒(リクエスト+レスポンスの時間) ≒ 200秒 (約 3.5分) の短縮になります。 データアップロードの並列化とAPIコール数を削減するAPI Dropbox APIには、「ファイルアップロード処理の並列化」と「APIコール数の削減」ができるエンドポイントも用意されています。それが create_folder_batch エンドポイントと upload_session エンドポイント群です。 まとめてフォルダ作成エンドポイント create_folder_batch と create_folder_batch/check create_folder_batch エンドポイントを利用すると、Dropboxサーバに複数のフォルダ作成を依頼できます。最大 1000フォルダ分を1リクエストのパラメータに指定できます。サーバサイドの処理が非同期処理になった場合は、終了待ちを行う create_folder_batch/checkエンドポイントで処理完了の待ち合わせを行うことが可能です。 ファイルアップロード並列化エンドポイント upload_session/start Dropboxサーバにファイルデータ送信のセッションを作成するためのエンドポイント。 このエンドポイントと次の append エンドポイントを利用して、ファイルデータ送信を行います。 ファイルアップロード処理の完了は、upload_session/finish エンドポイントを使います。 upload_session/append upload_sessoin/start で作成したファイルデータ送信用セッションを使って、ファイルデータをアップロードできます。何度も append エンドポイントを繰り返し利用することで、大きなファイルをアップロードすることも可能です。 ファイルメタデータまとめてエンドポイント upload_session/finish_batch upload_session/start および append エンドポイントで送信したファイルデータに対して、メタデータ(ファイル名や更新時間など、ファイル情報と呼ばれるもの)をつけてDropboxサーバに保存するためのエンドポイントです。             upload_session/finish エンドポイントでは 1ファイル分のメタデータを書込みできますが、upload_session/finish_batch エンドポイントを利用すれば 最大 1000ファイル分のメタデータを書込むことができ、APIコール数の削減が可能です。 upload_session/finish_batch/check upload_session/finish_batchで多くのファイルメタデータを書き込もうとした場合、非同期処理になる場合があります。この場合、finish_batch/checkエンドポイントを使って、finish_batchエンドポイントの終了確認を行う必要があります。 弊社が開発したデータ移行ツールでは、これらのエンドポイントを駆使して、データ移行時間の短縮を図っています。データ移行のロジックも図4のようにサブフォルダの作成処理、ファイルアップロード処理に分割し、おまとめエンドポイントの利用と並列化を実現しやすいように変えています。 図4: 改良版データ移行ロジック これにより、サブフォルダの作成をまとめることができ、最大1000個のサブフォルダを1回のAPIコールで済ますことができます。サーバサイドの処理時間は変わらないとしても、リクエスト送信+レスポンス受信 の時間 1,000回分を 1回分 だけに削減できます。 また、ファイルアップロード処理は、upload_session/start + upload_session/append を用い、並列してファイルデータをアップロードすることでデータ移行時間を短縮します。 upload_sessionエンドポイントのもうひとつのメリット upload_sessionエンドポイントを利用する、メリットがもうひとつあります。 uploadエンドポイントでは、最大 150MB までしかアップロードできないという制限があります。ということは、150MBより大きなファイルはDropboxにアップロードできないということになってしまうのですが、その制限をクリアするのが upload_session エンドポイントなのです。 upload_session/start や upload_sessoin/append も 1コールで指定できるファイルデータサイズは最大 150MB と upload エンドポイントと変わりないのですが、元のファイルを 150MB単位でブロック化し、upload_session/append エンドポイントで追加ブロック分を繰り返し送信することで、最大 2TB までアップロードできるようになっています。 エンドポイント アップロードできるファイルサイズ upload 最大 150MB upload_session/* 最大 2 TB ファイルサイズが 150MB 以下だと、upload_session/start と append, finish の 3つのエンドポイントを使ってファイルアップロードすることになるため、uploadエンドポイントより不利な面がありますが、finish_batch を使えばAPIコール数の削減も実現できますし、大きなファイルを送信できるという点で upload_session 系エンドポイントを利用する価値があります。 upload_sessoin系エンドポイントのサンプルコード upload_sessionエンドポイントを使った簡単なサンプルコードを紹介します。 まずは、ファイルデータの送信部分です。 下記のサンプルコードは、1ファイル分のファイルデータをアップロードする処理です。upload_session/start ではファイルデータを添付せず、ファイルデータのアップロードはすべて upload_sessoin/append で行っています。 with open(source_path, 'rb') as f:     offset = 0       if <移行元ファイルサイズ> == 0:         flag_close = True     else:         flag_close = False       # upload session開始     url = "https://content.dropboxapi.com/2/files/upload_session/start"     param = {         "close": flag_close     }     headers = {         "Authorization": "Bearer " + oauth_token,         "Content-Type": "application/octet-stream",         "Dropbox-API-Arg": json.dumps(param),     }     response = requests.post(url, headers=headers, data="") # APIコール     response_json = response.json()     session_id = response_json["session_id"]       # ファイルデータは upload_session/append で送信     while True:         chunk = f.read(UPLOAD_CHUNK_SIZE) # UPLOAD_CHUNK_SIZE は 150MB           if len(chunk) > 0:             if len(chunk) < UPLOAD_CHUNK_SIZE: # 詠み込んだ量が 150MB 以下ならこの append で終わり                 flag_close = True             else:                 flag_close = False               url = "https://content.dropboxapi.com/2/files/upload_session/append_v2"             param = {                 "cursor": {                     "session_id": session_id,                     "offset": offset                 },                 "close": flag_close             }             headers = {                 "Authorization": "Bearer " + oauth_token,                 "Dropbox-API-Arg": json.dumps(param),                 "Content-Type": "application/octet-stream",             }             response = requests.post(url, headers=headers, data=chunk) # APIコール             offset += len(chunk) この処理を並列実行できるように関数化し、ファイル単位でプロセスを分けることで並列実行を実現します。 ファイルメタデータの書込み処理は、上記のファイルデータのアップロードセッション 1,000個分をまとめて finish_batch を使うため、ファイルデータアップロード部分と分離しておきます。 upload_session/finish_batch を使ったメタデータ書込み処理 entries = []   # session_ids = データアップロードのセッションIDリスト        for session_id in session_ids:     entry = {         "cursor": {             "session_id": session_id, # ファイルアップロード時の session_id (session_ids リストで保存しておく)             "offset": offset # ファイルアップロード時の offset値 (session_ids リストで保存しておく)         },         "commit": {             "path": target_path, # session_ids リストで保存しておいた移行先パス             "mode": mode,             "autorename": False,             "client_modified": client_modified, # session_ids リストで保存しておいた移行元ファイルタイムスタンプ             "mute": False,             "strict_conflict": False         }     }     entries.append(entry)   # APIコール部分 url = "https://api.dropboxapi.com/2/files/upload_session/finish_batch_v2" headers = {     "Authorization": "Bearer " + oauth_token,     "Content-Type": "application/json", } data = {     "entries": entries } response = requests.post(url, headers=headers, data=data) # APIコール # このあと  # finish_batch がバックグランドジョブになった場合は、upload_session/finish_batch/check で定期的に終了確認を行う おわりに 今回は前編ということで、データ移行に関係する Dropbox API の紹介と弊社が開発したデータ移行ツールの処理ロジック、サンプルコードをご紹介を致しました。 後編では、並列化の効果や他の機能や工夫点などをご紹介する予定にしています。 SCSKでは、お客様のご要件に合わせたDropbox APIツールの開発も行っております。Dropbox運用の効率化や棚卸しなどでツールがほしい!といったご要望があれば、是非 SCSKまでご遠絡頂けたらと思います。 問合せ先: dropbox-sales@scsk.jp 弊社Dropbox紹介ページ: https://www.scsk.jp/product/common/dropbox/index.html
アバター
こんにちは!SCSKの三浦です。 ServiceNowの運用業務を行う中で、少しずつ知識がついてきました。 今回は、ServiceNowの数多くあるモジュールの中から「サービスポータル」、「要求アイテム」、 「アイテムデザイナー」、「アイテムの管理」をご紹介します。   ①サービスポータル(Service Portal) サービスポータルは、利用者が申請や問い合わせを行う場所です。 パスワードリセット PCやソフトウェアの申請 問い合わせ登録 FAQの参照 などを行うことができます。 管理者向けの画面ではなく、エンドユーザー向けの窓口サイトという位置づけです。   実際に名刺作成申請をしてみます。   使用したいカタログアイテムをクリックすると、申請フォームに入力することができます。   申請が完了しました!   ②要求アイテム(Requested Items) 要求アイテムは、ユーザーが申請した内容を1件ずつ管理するためのモジュールです。 サービスポータルのカタログから申請が行われると、その申請内容が「要求アイテム」として登録されます。   先ほどサービスポータルから申請した名刺作成が、要求アイテムに1件のレコードとして登録されていますね。 ここでは、 申請内容の確認 ステータスの管理 担当グループの割り当て 作業状況の確認 などを行います。 ↑要求の処理状態や申請内容を見ることができます   つまり要求アイテムとは、サービスポータルからエンドユーザーが送った要求を、技術者が管理するモジュールです。   ③アイテムデザイナー(Item Designer) 次にカタログアイテムを作成するモジュールをご紹介します。   アイテムデザイナーは、カタログアイテムのフォーム内容を作成するモジュールです。   関連リンクから申請フォームの質問項目を追加したり、必須設定や表示・非表示設定を行ったりすることができます。     プログラミングを行わなくても画面操作で設定できるなんて便利だなぁ     ④アイテムの管理(Maintain Items) アイテムの管理はカタログアイテムそのものを管理するモジュールです。 ここでは カタログアイテムの作成 変数(申請フォームの質問項目)やスクリプトの設定→表示順序等 ワークフローやフローとの紐づけ カタログアイテムの公開・非公開の設定 などを行います。 アイテムデザイナーがカタログアイテムの入力フォームを作る場所とすると、アイテムの管理はカタログアイテム全体の設定を行う場所です。   まとめ 今回、「サービスポータル」、「要求アイテム」、「アイテムデザイナー」、「アイテムの管理」の4つをご紹介しました。いずれもサービスカタログに関係するモジュールです。それぞれの役割を整理すると以下のようになります。 サービスポータル:エンドユーザーが使う申請・問い合わせ画面 要求アイテム:申請された内容を管理する アイテムデザイナー:カタログアイテムの申請フォームを作成する アイテムの管理:カタログアイテム自体を管理する   モジュール名だけでは、その機能や役割の違いが分かりにくいと感じる方も多いと思います。 この記事を通じて少しでも理解が深まり、お役に立てれば嬉しいです。   ここまで読んでくださり、ありがとうございました!
アバター
こんにちは、SCSK株式会社の中野です。 本記事ではZabbix 7.0.xからZabbix 7.4.xの最新バージョンへアップグレードする手順について説明します。             新しい機能などをお試しいただきたい方など、最新バージョンへバージョンアップしてみてはいかがでしょうか。 今回の構成は以下とさせていただきます。 OS DISTRIBUTION: Red Hat Enterprise Linux OS VERSION: 9 DATABASE: MySQL WEB SERVER: Apache Zabbix7.4の新機能(抜粋) Zabbix 7.4における、主な主な新機能は以下となります。 ・TimescaleDB、MySQL、PostgreSQL、MariaDBの最大サポートバージョンが定期的に拡張 ・Zabbix agent MSIインストーラーに多数のコマンドラインパラメータオプションを追加 ・RedisプラグインにTLS対応およびTLS起動時検証機能を新規搭載 ・OracleプラグインでTNS名サポートおよび追加ロール対応を実装 ・SNMPv3認証情報の自動リロードとsmart.disk.discoveryアイテムにtypeパラメータ追加 Zabbix 7.0から 7.4へバージョンアップ まずはZabbixプロセスを停止させます。 systemctl stop zabbix-server エージェント、エージェント2もアップグレードする場合は、同様に停止します。 systemctl stop zabbix-agent2 ※バージョンアップ時の想定外の事象によるデータ損失を防ぐため、必要に応じてDBのバックアップを実施ください。 本記事ではZabbix設定ファイル、および関連ファイルのみバックアップを取得します。 mkdir /opt/zabbix-backup/ ※設定ファイル cp /etc/zabbix/zabbix_server.conf /opt/zabbix-backup/ cp /etc/httpd/conf.d/zabbix.conf /opt/zabbix-backup/ ※PHPファイルとZabbixバイナリ設定 cp -R /usr/share/zabbix/ /opt/zabbix-backup/ cp -R /usr/share/zabbix-* /opt/zabbix-backup/ リポジトリパッケージを最新バージョンに更新する。 rpm -Uvh https://repo.zabbix.com/zabbix/7.4/release/rhel/9/noarch/zabbix-release-latest.el9.noarch.rpm Zabbixコンポーネントのアップグレードする。 dnf clean all dnf install zabbix-server-mysql zabbix-web-mysql zabbix-agent2 zabbix-agent2-plugin-* ※Zabbixコンポーネントをアップグレード後にWebフロントエンドをアップグレードする dnf install zabbix-apache-conf systemctl restart httpd Zabbixプロセスを起動させる。 systemctl start zabbix-server systemctl start zabbix-agent2 ログを確認して、「database upgrade fully completed」が出力されていることを確認する。 tail /var/log/zabbix/zabbix_server.log -n 1000 15109:20260202:083721.036 completed 97% of database upgrade 15109:20260202:083721.041 completed 98% of database upgrade 15109:20260202:083721.046 completed 100% of database upgrade 15109:20260202:083721.050 database upgrade fully completed バージョンアップ作業は完了です。 最後に バージョンアップ作業は比較的簡単に実施することはできます。 ただ既存バージョンとの異なる点や、バージョンアップ時の注意点が上記の手順以外で環境ごとに発生する可能性がございます。    そのため、バージョンアップを実施する際は、検証環境等で十分に検証したうえで実施いただければと思います。 以上、最後まで読んでいただき、ありがとうございました!!
アバター
こんにちは、SCSK株式会社の中野です。 Zabbixのダウンロードページを見ると最新バージョンであるZabbix 8.0のPRE-RELEASE版がリリースされておりましたので、 早速インストールしてみたいと思います。 今回は、AWS環境上にRHEL10.1を立てて、その中にZabbixをインストールしてみました。 Zabbixとは まずはZabbixの説明を簡単にさせていただきます。 Zabbixは、エンタープライズ対応のオープンソース統合監視ツールです。 サービスやそれを支える ITシステム(サーバ、ネットワーク機器等)の状態を把握し、障害の予兆やサービスへ影響を及ぼす事象が発生した際に、システム管理者やオペレータに通知を行うオープンソースの統合監視ソリューションです。 数万デバイス規模のエンタープライズ環境でも多数の稼動実績を誇っています。 Zabbixの詳細情報については、下記リンクよりご確認ください。 Zabbix :: The Enterprise-Class Open Source Network Monitoring Solution ZabbixはITインフラストラクチャ・コンポーネントの可用性やパフォーマンスを監視するためのエンタープライス向けソフトウェアです。Zabbixはオープンソース・ソフトウェアとして開発されており、無料でダウンロードいただくことが可能です。 www.zabbix.com   導入手順 早速、Zabbix8.0 PRE-RELEASE版を導入していきたいと思います。今回の構成は以下とさせていただきます。 ZABBIX VERSION: 8.0 PRE-RELEASE OS DISTRIBUTION: Red Hat Enterprise Linux OS VERSION: 10 DATABASE: MariaDB WEB SERVER: Apache Firewalld: 無効 関連パッケージのインストール、DB初期設定 Zabbixをインストールする前に、MySQLとApacheをインストールしておきます。 # 関連パッケージのインストール dnf install mariadb-server httpd # データベースを起動 systemctl start mariadb systemctl enable mariadb 続いて、Zabbix用データベースを作成します。                                          DB名、アカウント名やパスワード環境に応じて設定いただければと思います。 # DBへの接続 mysql -uroot -p Enter password: (MySQLのrootアカウントのパスワードを入力) # DB、アカウントを作成 > create database zabbix character set utf8mb4 collate utf8mb4_bin; > create user zabbix@localhost identified by 'password'; > grant all privileges on zabbix.* to zabbix@localhost; > set global log_bin_trust_function_creators = 1; > exit Zabbixサーバのインストール Zabbixをインストールする前に、専用のリポジトリを追加します。 # 専用リポジトリのインストール rpm -Uvh https://repo.zabbix.com/zabbix/8.0/release/rhel/10/noarch/zabbix-release-latest-8.0.el10.noarch.rpm # キャッシュのクリア dnf clean all # Zabbixサーバのインストール dnf install zabbix-server-mysql zabbix-web-mysql zabbix-web-japanese zabbix-apache-conf zabbix-sql-scripts zabbix-agent zabbix-selinux-policy 続いて、Zabbix用データベースへ初期データをインポートします。 # DBへ初期データをインポート zcat /usr/share/zabbix/sql-scripts/mysql/server.sql.gz | mysql --default-character-set=utf8mb4 -uzabbix -p zabbix Enter password: (MySQLのzabbixアカウントのパスワードを入力) 初期データのインポート後、log_bin_trust_function_creatorsを無効にします。 # DBへの接続 mysql -uroot -p Enter password: (MySQLのrootアカウントのパスワードを入力) > SET global log_bin_trust_function_creators = 0; > exit その後、Zabbixサーバーの設定と起動を行います。 # 各パラメータ設定 /etc/zabbix/zabbix_server.conf DBHost=localhost DBName=zabbix DBUser=zabbix DBPassword=zabbix # サービスの起動 systemctl start zabbix-server zabbix-agent httpd php-fpm systemctl enable zabbix-server zabbix-agent zabbix-agent httpd php-fpm Zabbix WEBコンソールへのアクセス Zabbixのインストールは完了しましたので、Webコンソール上でセットアップしていきます。 ブラウザを立ち上げて、以下にアクセスします。 http://xxx.xxx.xxx.xxx/zabbix xxxには、今回構築したIPアドレスを入れてください。例えば、もしZabbixサーバーのIPアドレスが192.168.0.1なら、アドレスバーには”http://192.168.0.1/zabbix”と入力します。 言語を【日本語(ja_JP)】に変更して、【次のステップ】をクリックします。 すべての項目が「OK」になっていることを確認し、【次のステップ】をクリックします。 パスワード欄に先ほど設定したZabbixDBのパスワードを入力し、【次のステップ】をクリックします。 タイムゾーン欄で【(UTC+9:00) Asia/Tokyo】を選択、Zabbixサーバ名を記入し、【次のステップ】をクリックします。 設定内容に問題がなければ、【次のステップ】をクリックします。 【終了】をクリックすると、以下のようなログイン画面が表示されます。 初期状態でユーザーが登録されているので、以下のユーザー名・パスワードでログインします。 ユーザ名:Admin パスワード:zabbix ログインすると、WEBコンソール画面が表示されます。 以上でZabbixのインストールは完了です。   最後に Zabbix 8.0 PRE-RELEASE版は以前のバージョンと比較的に変わりなく、インストールすることができました。 今回はインストールのみでしたが、新機能も試してみて情報を発信していきたいと思います。                     最後まで読んでいただき、ありがとうございました。
アバター
LifeKeeperの『困った』を『できた!』に変える!サポート事例から学ぶトラブルシューティング&再発防止策 こんにちは、SCSKの前田です。 いつも TechHarmony をご覧いただきありがとうございます。 システムのリプレースやハードウェア更新のタイミングで訪れる、「ミドルウェアのバージョンアップ」。 「サポート切れ(EOS)対応」や「魅力的な新機能の追加」など、OSのパッチ適用とはまた違った、期待と緊張が入り混じる一大イベントではないでしょうか。 しかし、HAクラスターソフトウェアであるLifeKeeperにおいて、この「バージョンアップ」は単なるファイルの置き換えではありません。 「インストーラーを実行して、バージョン番号が上がれば完了!」 ……そう思い込んで作業を進めた結果、再起動後に設定ファイルが初期値に戻っていたり、長年動いていたスクリプトが突然エラーを吐き始めたりといった、予期せぬトラブルに直面することがあります。 本連載企画「LifeKeeper の『困った』を『できた!』に変える!サポート事例から学ぶトラブルシューティング&再発防止策」では、サポートセンターに蓄積された「生のトラブル事例」を元に、安定運用のための実践的な知恵を共有していきます。 はじめに:成功へのロードマップを描く 連載第2回となる今回は、LifeKeeper本体やDataKeeperのバージョンアップに焦点を当てます。 バージョンアップ作業において、最も怖いのは 「見えない変化」 です。 インストーラーは便利ですが、それが裏側でどの設定を引き継ぎ、どの設定をリセットするのか、また新しいバージョンが古い設定をどう解釈するのかは、リリースノートの細部を読み込まない限り見えてきません。 今回は、実際にサポートへ寄せられた「バージョンアップ失敗事例」を以下の3つの「落とし穴(Trap)」に分類しました。 設定と環境の「サイレント変化」 過去の「まあいいか」が牙をむく 近道は「急がば回れ」 これらの事例から「なぜ失敗したのか」を学び、確実に成功させるためのチェックポイント(ロードマップ)を解説します。 その他の連載企画は以下のリンクからどうぞ! 【リソース起動・フェイルオーバー失敗の深層 #1】EC2リソースが起動しない!クラウド連携の盲点とデバッグ術 – TechHarmony 【リソース起動・フェイルオーバー失敗の深層 #2】ファイルシステムの思わぬ落とし穴:エラーコードから原因を読み解く – TechHarmony 【リソース起動・フェイルオーバー失敗の深層 #3】設定ミス・通信障害・バージョン違いの深層と再発防止策 – TechHarmony 【OS・LKバージョンアップで泣かないために #1】OSバージョンは変えていないのに!?カーネル更新の「落とし穴」と互換性の真実 – TechHarmony 【実録】LifeKeeperバージョンアップの「困った!」事例ファイル ここからは、実際のサポート問い合わせをベースにしたケーススタディです。 「自分の環境でも起こりうるかもしれない」 という視点でご覧ください。 Trap 1:設定と環境の「サイレント変化」 バージョンアップによって、今まで使っていた設定や環境が 「静かに」 変わってしまう ケースです。 ■ケースA:アップデートしたら設定が消えた!?(Linux版) 「v9.5.2からv9.9.1へアップデートしました。エラーなく完了したのですが、再起動後になぜかプロキシ設定などが効かなくなっています…」 発生状況:  アップデート作業自体は成功したものの、LifeKeeperの動作設定ファイル( /etc/default/LifeKeeper )に記述していたカスタム設定が消失していました。 原因: LifeKeeperの仕様により、更新インストール時に 一部の設定ファイルがデフォルト値に戻る(上書きされる) 挙動となっていました。 教訓:  「設定はすべて自動的に引き継がれるはず」という思い込みは危険です。特にメジャーバージョンをまたぐ更新では、バックアップと復元手順が必須です。 ■ケースB:スクリプトが動かない!Perlの罠(Windows版) 「v8.9からv8.10.2へ上げようとしています。パラメータ変更は不要と聞きましたが、本当にそのまま上げて大丈夫でしょうか?」 リスク:  調査の結果、LifeKeeperに同梱されているPerlのバージョンが、v8.10.1以降で「5.8系」から「5.32系」へと一気にアップグレードされていることが判明しました。 教訓:  GenericリソースなどでPerlスクリプトを使用している場合、言語仕様の変更によりスクリプトが動作しなくなる可能性があります。アプリケーションだけでなく、ミドルウェアが依存する 「言語環境」の変化 も重要なチェックポイントです。 Trap 2:過去の「まあいいか」が牙をむく 古いバージョンでは許容されていた(あるいは無視されていた)設定の不備が、新しいバージョンの「厳格なチェック」によってエラーとして顕在化するケースです。 ■ケースC:亡霊IPがアラートを引き起こす 「OSとLifeKeeperを更新した後、ログに failed quickCheck due to ALRM signal というエラーが多発するようになりました。以前は出ていなかったのですが…」 原因:  IPリソースの監視リスト( pinglist )に、既に撤去済みで疎通できない古いIPアドレスが残っていました。 なぜ今?:  バージョンアップに伴い チェック処理やリトライの挙動が変化(厳格化) し、古いIPへの応答待ちが積み重なった結果、タイムアウト(ALRM signal)が発生していました。 教訓:  「今は使っていないけど残っている設定」は、バージョンアップ時の最大の敵です。更新作業はゴミ掃除の絶好の機会と捉えましょう。 ■ケースD:ディスクに名前がない!?(UUID問題) 「バージョンアップ後、DataKeeperリソースで『一意の識別子がない』という警告が出たり、パーティション情報が正しく取得できなくなりました」 原因:  LifeKeeper/DataKeeperの新しいバージョンでは、ディスクを一意に特定するために 「UUID」の使用が必須化(または厳格化) されました。古い環境で「MBR形式」のパーティションを使っていたため、UUIDを持たず、新しいバージョンの要件を満たせなくなっていました。 教訓:  ソフトウェアの進化に合わせて、インフラ側(パーティションテーブル等)もGPT形式へのモダン化が必要になることがあります。 Trap 3:近道は「急がば回れ」 手順を省略したり、無理なアップデートパスを通ろうとして失敗するケースです。 ■ケースE:飛ばしすぎたバージョンアップ 「v9.6.xからv9.8.1へ一気にアップデートしようとしたら失敗しました。2世代前からの更新はサポートされているはずですが…」 原因:  基本的には直接アップデートが可能ですが、 この特定のバージョン(v9.8.1)においては 内部パッケージの大幅な構成変更 があったため、例外的にv9.7やv9.8.0を経由する「ステップアップグレード」が必要でした。 教訓:  「いつものルール(N-2までOKなど)が今回も適用される」とは限りません。リリースノートには必ず 「アップグレードの注意点」や「例外的なパス」 が記載されていますので、慣れている作業でも必ず目を通しましょう。 ■ケースF:GUIの表示がおかしい 「DataKeeper更新後、GUI上でジョブ情報が表示されなくなりました」 解決策: 調査の結果、内部情報の不整合が起きていました。このケースでは、無理に修正するよりも「再インストールしてジョブを再作成」した方が、結果として早く、確実に解消しました。 教訓:   バージョンが大きく離れている場合や挙動がおかしい場合 は、上書きアップデートに固執せず、設定バックアップをとった上での「作り直し(再作成)」が最短ルートになることがあります。 「再発させない!」成功へのチェックリスト 上記の失敗事例から導き出した、バージョンアップ作業前に確認すべき「転ばぬ先の杖」チェックリストです。計画段階でぜひご活用ください。 ■LifeKeeper/DataKeeper バージョンアップ事前確認シート [  ] 【パスの確認】 現在のバージョンからターゲットバージョンへ「直接」アップデート可能ですか?(中継バージョンが必要ありませんか?) [  ] 【設定ファイルのバックアップ】 更新時に初期化されるファイル( /etc/default/LifeKeeper 等)を特定していますか? それらの手動バックアップを取得し、更新後に復元する手順を組み込みましたか? [  ] 【言語・環境の差異】 PerlやPythonなど、LifeKeeperが利用するランタイムのバージョンに変更はありませんか?(自作スクリプトへの影響確認) ディスクのパーティション形式は新しいバージョンの要件(UUID必須/GPT推奨など)を満たしていますか? [  ] 【不要設定の削除(ゴミ掃除)】 IPリソースの pinglist に、現在疎通できない「亡霊IP」が残っていませんか? [  ] 【OSとの整合性】 OS自体のカーネルアップデートを行う場合、LifeKeeperの再インストールやモジュール再コンパイルの手順を確認しましたか? [  ] 【リカバリプラン】 更新インストールが不整合を起こした場合に備え、一度アンインストールして「新規インストール+設定復元(または再作成)」に切り替える判断基準を持っていますか? ベストプラクティス:成功への近道 トラブルを防ぐために、明日からできる「ベストプラクティス」を3つ提案します。 「リリースノート」は宝の地図 リリースノートを「バグ修正のリスト」だと思っていませんか? 本当に見るべきは「制限事項 (Known Issues)」 と 「変更点 (Migration/Changes)」です。ここには「設定ファイルが初期化される」「UUIDが必須になる」といった重要情報が必ず書かれています。 ステージング環境でのリハーサルは必須 机上の確認だけでは、「pinglistのタイムアウト」や「Perlの互換性」といった環境依存のトラブルは見抜けません。本番環境のクローン(または同等構成)を用意し、実際にバージョンアップ手順を流すリハーサルを行ってください。 大幅な更新は「再作成」も視野に 数年前のバージョンから一気に最新版にするような場合、継ぎ接ぎのアップデートを繰り返すより、「設定情報を控えて、クリーンインストール後に再設定する」方が、潜在的なゴミが残らず、結果的に安定稼働につながることが多々あります。「上書き」にこだわらない柔軟性も重要です。 まとめ バージョンアップ時のトラブルは、多くの場合「準備不足」や「思い込み」の隙間に入り込むものです。 しかし、今回ご紹介した事例のように、事前に 「何が変わるのか」「何が消えるのか」「今の設定にゴミはないか」 を確認しておけば、そのほとんどは防げます。 「LifeKeeperの『困った』を『できた!』に変える」 今回のロードマップを参考に、ぜひ安心・安全なバージョンアップ計画を立ててください。 次回予告 次回からは新章に突入! テーマは「クラウド環境特有の落とし穴:AWS/Azure連携でハマるポイント」です。 クラウドならではの「オンプレミスと同じ感覚で設定したら動かない!?」というトラブル。 その第一弾として、 AWS環境でのLifeKeeper安定稼働術 にフォーカスします。 「Route53のDNSが切り替わらない!」「便利なはずの『Auto Recovery』がLifeKeeperと喧嘩する!?」といったAWS特有の事例と、EC2・S3連携の注意点を徹底解説します。お楽しみに! 詳しい内容をお知りになりたいかたは、以下のバナーからSCSK LifeKeeper公式サイトまで
アバター
こんにちは。SCSK志村です。 Azure SQL Database で SQL Server を構成する際の設定項目に「接続ポリシー」があります。 設定値は「既定値」「リダイレクト」「プロキシ」の3種類から選択しますが、この「既定値」設定における挙動(特に Private Endpoint 利用時)について、私がドキュメントを読み間違えて悩んでしまったため、備忘録として記事にしました。 1. ドキュメントの記載 接続ポリシーは以下の公式ドキュメントに記載されています。 接続のアーキテクチャ – Azure SQL Database | Microsoft Learn ドキュメントによると、選択できるポリシーは以下の3つのオプションで構成されています。 リダイレクト (推奨): クライアントは、データベースをホストしているノードへの直接接続を確立します。これにより、待機時間が短縮され、スループットが向上します。 ※ポート 11000 - 11999 および 1433 の許可が必要です。 プロキシ: すべての接続が Azure SQL Database ゲートウェイ経由でプロキシ化されます。待機時間が長くなりスループットが低下する可能性がありますが、必要なポートは 1433 のみです。 既定値: 明示的に接続ポリシーを変更しない限り有効になる設定です。接続元に応じて、自動的に以下の挙動を使い分けます。             Azure 内からの接続(例:Azure VM) → Redirect として動作 外部からの接続(例:ローカルPC) → Proxy として動作 こちらの記事を読んで、私は最初、以下のような解釈をしていました。 当初の私の解釈: 「Azure内(仮想マシン)から発信する接続は『Redirect』だから、VMからSQL Databaseへの接続(Private Endpoint経由)も、リダイレクトになるはずだ。」 しかし、実際には Private Endpoint(プライベートエンドポイント)接続の場合、 既定値は「プロキシ」となります。 この事実は別のドキュメントに記載してありました。 Azure Private Link – Azure SQL Database | Microsoft Learn クライアントは明示的に リダイレクト接続ポリシーを選択する 必要があります。 既定 の接続ポリシーを使用する既存のプライベート エンドポイントでは、ポート 1433 でプロキシ接続ポリシーを使用します。 これを行う理由は、リダイレクトに必要なポート範囲が開いていないことが原因でクライアントのトラフィックが SQL Database に到達できなくなる状況を回避するためです。 Private Endpoint 経由では、リダイレクト接続ポリシーを明示的に指定する必要があるということですね。 リダイレクトに必要なポート範囲が開いていないことに対するケアとして、既定値がプロキシになっているようです。 事実はドキュメントからわかりましたが、せっかく調べたので実機検証もしてみました。 2. 実機検証 VMから Private Endpoint 経由で SQL Database へ接続した時の 接続ポート を比較してみました。 確認方式: SSMSで Azure SQL Database に接続し、 netstat コマンドで接続ポートを確認 検証結果サマリ まとめると以下の通りです。「既定値」は「プロキシ方式」で通信していることがわかります。 設定値 接続ポート 通信方式 リダイレクト 1433以外 (例: 12119) リダイレクト接続 プロキシ 1433 プロキシ接続 既定値 1433 プロキシ接続  参考:コマンド実行結果(クリックで展開) コマンド実行結果です。 ① リダイレクト設定の場合 ▼ netstat 結果:ポート 12119 (Redirect) TCP 10.0.0.4:53852 10.x.x.x:12119 ESTABLISHED ② プロキシ設定の場合 ▼netstat 結果:ポート 1433 (Proxy) TCP 10.0.0.4:53855 10.x.x.x:1433 ESTABLISHED ③ 既定値の場合         ▼ netstat 結果:ポート 1433 (Proxy) VMからの接続ですが、ポートは1433とProxyと同じポートになっています。 TCP 10.0.0.4:53860 10.x.x.x:1433 ESTABLISHED 3. まとめ Azure SQL Database への接続は、Microsoft としてはリダイレクトを推奨しています。 ※2026年2月時点でプロキシ推奨と読み取れる記述もありますが、恐らく自動翻訳によるミスです。 それにも関わらず既定値がプロキシなのは、ユーザーが複雑なネットワーク要件を意識せずとも繋がることを優先した安全側の設計思想だと思われます。(あくまで所感ですが) 接続方式の違いはパフォーマンスに直結するため、この仕様は設計時にしっかり把握しておきたいポイントです。 この記事が、Azure における SQL Database 設計のご参考になれば幸いです。
アバター
こんにちは、SCSKの坂木です。 AWS環境でのシステム監視において、標準機能である Amazon CloudWatch を利用されている方は多いと思います。CloudWatchのアラームは通常メール(SNS)等で通知されますが、運用が大規模になると「大量のメールに埋もれる」「対応状況がわからない」といった課題が発生しがちです。 そこで、インシデント管理ツールである PagerDuty と連携することで、以下のような運用の一元化・効率化によるメリットが生まれます。 アラートの集約と一元管理 CloudWatchだけでなく、オンプレミスのZabbixやAzureなど、様々な監視ツールからのアラートをPagerDutyに集約できます。 柔軟なオンコール管理 「平日日中は担当者A、夜間休日は担当者B」「15分反応がなければマネージャーへエスカレーション」といった柔軟な通知ルールを、AWS側の設定を変更せずにPagerDuty側だけで管理できます。 ステータスの同期(自動Resolve) CloudWatchでアラーム状態(ALARM)になったらPagerDutyでインシデント起票、CloudWatchが正常(OK)に戻ったらPagerDutyも自動クローズ(Resolve)、というようにステータスを同期させることで、手動でのチケットクローズ作業をなくすことができます。 今回は、この連携の中核となる CloudWatchからPagerDutyへイベントを送り、自動復旧させる設定 にフォーカスして解説します。   連携の仕組み 本記事で構築する連携フローは以下の通りです。 CloudWatchのアラーム状態の変化をトリガーに、Amazon SNSへメッセージを送信し、それをPagerDutyのHTTPSエンドポイントが受け取る形になります。 [CloudWatch Alarm] –(状態変化)–> [Amazon SNS] –(HTTPS)–> [PagerDuty] –(通知)–> [運用担当者] 特に重要なのが、 障害検知(ALARM) だけでなく 復旧(OK) の通知も送る 点です。これにより PagerDuty上のインシデントが自動的に解決済み になります。   PagerDuty側の設定 まずは受け皿となるPagerDuty側の設定を行い、通知先となるURLを取得します。 PagerDutyのメニューから  [Services] > [Service Directory]  を開き、 [+ New Service] をクリックします。     Serviceの名称(例: CloudWatchAlerts)などを入力し、Integrationの設定画面まで進みます。 Integration Typeの選択で、 Amazon CloudWatch  を検索して選択(チェック)します。 [Create Service]  をクリックしてサービスを作成します。   サービス作成後に表示される画面で、 Integration URL ( https://events.pagerduty.com/integration/xxxxxxxx... )をコピーしておきます。このURLがAWS側からの通知先となります。   AWS側の設定(SNSトピックの作成) 次にAWSマネジメントコンソールで、PagerDutyへ通知を送るためのSNSトピックを作成します。 Amazon SNS  コンソールを開き、 トピックの作成 へ進みます。 タイプは スタンダードを選択し、名前(例:  pagerduty-cloudwatch-topic )を入力してトピックを作成します。   作成したトピックの画面で  [サブスクリプションの作成] をクリックします。以下の通り設定し、作成します。 プロトコル :  HTTPS エンドポイント : 先ほどPagerDutyで取得した  Integration URL を貼り付け これで、このSNSトピックにメッセージが飛ぶと、自動的にPagerDutyへ連携されるパイプラインが完成しました。 ※PagerDutyの連携URLは自動的にサブスクリプションの確認(Confirm)を行うため、手動での承認作業は不要です。   AWS側の設定(CloudWatchアラームの設定) 最後に、CloudWatchのアラーム設定で、先ほどのSNSトピックをアクションに指定します。 CloudWatchのアラーム作成 (または編集)画面の「アクションの設定」にて、以下の2つの通知を設定します。 ① 障害発生時の通知(Trigger) アラーム状態トリガー: アラーム状態 を選択 SNSトピックの選択: 作成した pagerduty-cloudwatch-topic を選択 ② 復旧時の通知(Resolve )  ここが自動復旧を実現するための肝となる設定です。 アラーム状態トリガー: OK を選択 SNSトピックの選択: ①と同じ pagerduty-cloudwatch-topic を選択   このように「アラーム状態」と「OK状態」の両方で同じPagerDuty連携用トピックへ通知するように設定することで、 PagerDuty側がメッセージの内容(AlarmかOKか)を判別し、インシデントの起票とクローズを自動で行ってくれるようになります 。   動作確認 設定が完了したら実際に動作を確認してみましょう。   障害発生(Trigger) 対象のメトリクスが閾値を超えるように調整します。   CloudWatchアラームが「アラーム状態」になると、PagerDuty上でインシデントが Triggered状態になることを確認 できました。   自動復旧(Resolve) その後、CloudWatchアラームを「OK」状態に遷移させます。 すると、PagerDutyのアクティビティログに “Resolved through the integration API” と表示され、 インシデントステータスが自動的に Resolved(解決済み) に変わることを確認しました 。   まとめ Amazon CloudWatchとPagerDutyを連携することで、単なるメール通知では難しかった「インシデントの一元管理」と「ステータスの自動同期」が実現できます。 特にCloudWatchの OKアクション を設定しておくことで、夜間に一時的な高負荷でアラートが鳴ったとしても、負荷が下がれば自動でクローズされるため、運用担当者が手動で「解決済みにする」というオペレーションから解放されます。 Zabbixとの連携と合わせて導入することで、ハイブリッド環境でも迷うことなくPagerDutyだけを見ていれば良い状態を作り出せるため、ぜひ導入を検討してみてください。   ▼ AWSに関するおすすめ記事 Gemini活用!フローチャートからチャットボット(Amazon Lex)を自動構築してみた Geminiを活用しExcelからAWS LexのTerraformコードを自動生成する手法を解説。IAMロールや会話分岐の自律的な判断など、AIによる開発効率化の実例を紹介。インフラ構築の工数削減に役立つエンジニア必見の活用術です。 blog.usize-tech.com 2026.01.22 Terraformで実装するAWSファイルストレージ入門:EFSとFSxを構築してみた Terraformを使い、AWSのファイルストレージであるEFSとFSx for Windowsの構築手順を解説します。Linux/Windowsそれぞれに最適なストレージをIaCでコード管理。インフラ構築の再現性を高め、効率化を実現したい方はぜひご覧ください。 blog.usize-tech.com 2025.12.15 【Amazon Bedrock】ナレッジベースを用いた社内資料管理ーめざせ生産性向上ー 社内資料の管理、効率的ですか?様々な形式の文書が散在し、必要な情報を探すのに時間を取られていませんか? ファイルサーバーの奥底に埋もれどこにあるか分からない、バージョン管理が混乱する、などといった課題を抱えていませんか?これらの非効率は、業務の生産性低下に直結します。 今こそ、社内資料の一元管理体制を見直しましょう!ということで、AWS Bedrockのナレッジベースを用いた資料の一括管理およびその検索方法をご紹介します! blog.usize-tech.com 2025.02.14
アバター
SCSKの畑です。 初投稿以来ほぼ Web アプリケーション開発およびサーバレスアーキテクチャの話しかしてこなかったのですが、別の案件で最近にしては珍しくデータベース関連のサービス(Amazon RDS/Amazon ElastiCache)を扱っていたりするので、ボチボチそちらの話題についても書いていこうと思います。まあ Elasticache は KVS (Key-Value Store)でデータベース関連のサービスとまとめてしまうべきではないと思いつつも、文章的にそうした方が楽なので見逃してください。 ちなみに同案件における RDS は Aurora MySQL 及び RDS for MySQL あたりが中心です。ということで最初は小ネタから。   本題 RDS にはマネージドな PITR (Point-In-Time Recovery)機能があります。マネジメントコンソール上では「特定時点への復旧」メニューが該当します。 同案件では MySQL のレプリケーションを使用しているのですが、特定の障害パターンにおけるMySQL のレプリケーションの復旧手順において同機能を使用する予定で、マネジメントコンソールから使い方や機能を検証していました。その際、トータルでの復旧時間を短縮するために「 (PITR 可能な)最新の時刻まで PITR する 」手順にしようと考えていました。ただ、同機能における RPO は 以下 URL の通り最大 5 分となっています。 Amazon RDS の DB インスタンスを特定の時点に復元する - Amazon Relational Database Service Amazon RDS DB インスタンスを特定の時点に復元します。 docs.aws.amazon.com RDS は、DB インスタンスのトランザクションログを 5 分ごとに Amazon S3 にアップロードします。 Amazon RDS を使った災害復旧戦略の実装 | Amazon Web Services Amazon RDS (Relational Database Service) は、リレーショナルデータベー aws.amazon.com ご使用の DB インスタンスで自動バックアップが有効化されていると、Amazon RDS は 1 日の全データをスナップショットとして自動的に保存します。このスナップショットは、設定されたバックアップウィンドウの間に実行されます。同時にこの処理は、Amazon S3 へのトランザクションログを、(DB インスタンスが更新される) 5 分間に一度キャプチャーします。 基本的に RDBMS における PITR は、特定断面のバックアップをリストアした後に、データベースに対する更新内容と時刻情報がセットで記録されているトランザクションログ(REDOログ、バイナリログなど呼び方は製品によって異なります)をロールフォワードリカバリすることで実現します。つまり上記注釈の文言に従って言い換えると、トランザクションログがどの時点まで S3 にキャプチャーされているのかによって、どの時点まで DB をリカバリできるのかが変わってくるということになります。そして取得間隔は5分間であるため、RPO も最大5分となります。 上記のような仕組みであるが故に、どの時刻まで PITR できるのかをどうやって確認するのかなと当初考えていたのですが、以下のように「復元可能な最新時刻」という項目があり時刻情報も表示されているため、この項目を選択して RDS を復旧すれば (PITR 可能な)最新の時刻まで PITR することが可能 と考えました。 念のため、対象の RDS に対して 0.1 – 0.2 秒ごとにレコードを INERT している状態で、先述の通り「復元可能な最新時刻」を選択した上で PITR の動作を検証してみたところ、以下のように想定通りの時点までデータがリカバリされていることを確認しました。なお、仕様上手順検証時の状況を再現できないので、今回のエントリ用に再現試験したものを載せている点ご了承ください。 PITR の期待動作は 「指定した時刻」の直前の更新までがリカバリされていること です。上記例のように 2026-02-08 14:34:21 を指定して PITR した場合は、2026-02-08 14:34:20.999… までの更新がリカバリされ、DB 上に反映されていることが期待されます。 なお、製品やサービスによっては異なる挙動をする可能性も0とは言えないですが、私が今まで触ってきた RDBMS では全て同じ挙動をしていましたので基本的には共通認識のはず・・です。 mysql> select * from record_table order by id; +------+---------------------+ | id | updated_at | +------+---------------------+ | 9309 | 2026-02-08 14:34:20 | | 9308 | 2026-02-08 14:34:20 | | 9307 | 2026-02-08 14:34:20 | | 9306 | 2026-02-08 14:34:20 | | 9305 | 2026-02-08 14:34:20 | | 9304 | 2026-02-08 14:34:20 | | 9303 | 2026-02-08 14:34:20 | | 9302 | 2026-02-08 14:34:19 | | 9301 | 2026-02-08 14:34:19 | | 9300 | 2026-02-08 14:34:19 | (中略) 9310 rows in set (0.03 sec) そこで改めて MySQL のレプリケーション復旧も含めた一連の復旧手順をテストしてみたところ・・なんと復旧した MySQL のレプリケーションにてデータの不整合が発生し、エラーで停止してしまいました。具体的には、レプリケーションにて本来伝播されるべき更新が PITR にてリカバリしたデータに既に含まれており、データの不整合(重複)が発生してしまったのが原因でした。一連の手順におけるオペミスはなかったことから、先般 PITR によりリカバリしたデータに問題があるのではないかと考えました。 込み入った話になるので今回の障害パターンにおける一連の復旧手順については深堀しませんが、ものすごく簡単に説明すると「MySQL のデータをマネージド PITR で特定時刻の断面にリカバリした後、その時刻以降のトランザクションログを対象としてレプリケーションすることで復旧する」という手順でした。 このため、PITR が先述したような期待動作をしないと、レプリケーションによる更新データの欠損ないしは重複が発生し、データの不整合が発生してしまいます。今回発生した事象は後者(更新データの重複)ですね。 そこで、改めてリカバリ直後のデータ断面を見たところ・・なんと、以下のように 2026-02-08 14:34:21 の更新データが含まれており、想定より先の時点までデータがリカバリされてしまっていることが発覚しました。2026-02-08 14:34:21 の更新データが4件含まれている分、合計のレコード数も1回目のリカバリデータと比較して増えています。 なお「復元可能な最新時刻」の仕様上同じ条件でのリトライができないため、以下データ例は1回目のリカバリ操作において異なる結果となったデータを想定して記載しています。(厳密には今回の再現試験では2回目が実際の試験結果で、1回目は想定の試験結果となりましたが、そのあたりの詳細は後ほど) mysql> select * from record_table order by id; +------+---------------------+ | id | updated_at | +------+---------------------+ | 9313 | 2026-02-08 05:34:21 | | 9312 | 2026-02-08 05:34:21 | | 9311 | 2026-02-08 05:34:21 | | 9310 | 2026-02-08 05:34:21 | | 9309 | 2026-02-08 05:34:20 | | 9308 | 2026-02-08 05:34:20 | | 9307 | 2026-02-08 05:34:20 | | 9306 | 2026-02-08 05:34:20 | | 9305 | 2026-02-08 05:34:20 | | 9304 | 2026-02-08 05:34:20 | | 9303 | 2026-02-08 05:34:20 | (中略) 9314 rows in set (0.03 sec) 1回目は想定通りの結果であったのにも関わらず2回目でこのような結果になったのが当初理解できずに混乱したのですが、、AWSのドキュメントを改めてもう一度見てみると、「復元可能な最新時刻」を選択した場合は以下の通り できるだけ最新の時点に復元する という記載となっていました。 「 Latest restorable time 」 を選択してできるだけ最新の時点に復元するか、「 カスタム 」 を選択して時刻を選択します。 あ、これはひょっとしてそういうことか?と思い当たり、以下のように「特定時刻を明示的に指定してPITRを実行」を選択してリトライしたところ・・ 想定通りの時点(=1回目の試験結果の通り)にデータが PITR されました!念のため何回か試しましたが、全て期待通りの結果になっていました。つまりそれぞれ以下のような動作となるため、(厳密な)PITR を使用したい場合は 「特定時刻を明示的に指定してPITRを実行」 を選択する必要がある、というのが結論となります。 「復元可能な最新時刻」は、表示されている時刻を指定した PITR ではなく 、 S3 にキャプチャーされているトランザクションログを全て使用して復元可能な最新時点までリカバリを実行 「特定時刻を明示的に指定してPITRを実行」は、 表記の通り PITR を実行 その時刻指定において「復元可能な最新時刻」に表示されている時刻を参考にすることは可能 先の検証において1回目と2回目の結果に差異があったのも頷けるところで、1回目は本来 PITR により期待したデータ断面にたまたまリカバリできただけということですね。先述の通り今回のエントリ用の再現試験では2回目の結果となったのもその裏返しと言えます。 RDBMS においてこのように「戻せるところまで戻す」というロールフォワードリカバリ操作はもちろん可能です。一例として ORACLE では SQL だと「alter database recover database until cancel」文、RMAN だと「recover database」コマンドがそれぞれ対応しています。そしてこのコマンド例を見ると分かる通り「戻せるところまで戻す」という操作には本質的に時刻情報は含まれないはずなんですよね。戻せるところまで戻した結果として「何月何日何時何分の時点に復旧された」ということが分かるので。 それが故にマネジメントコンソールの画面が分かりづらかったところはあります。横に最新時刻が表示されているということは、その時刻に PITR するオペレーションを項目として独立しているのかな?と早とちりしてしまったというか。「復元可能な最新時刻」に表示されている時刻はあくまで目安というか、S3 にキャプチャ済みのトランザクションログの最新時刻なのでしょうかね? AWS のドキュメントの記述は、上記のようなトランザクションログを使用した DB のリカバリ操作の挙動を理解している人であればそう解釈できなくもないですが、本来の PITR ではないということは明記しておいた方が良いように思いました。   まとめ 繰り返しになりますが、正直「復元可能な最新時刻」という表記が分かりづらいというか誤解を招くと思うので、表記だけでも直した方がいいと思いました。私のように画面だけ見ると絶対勘違いする人いるんじゃないかと思います。。まあ今回のように一回テストすれば大体分かることではありますが。 論理障害からの復旧にこういう機能を使う分にはデータの中身を見て判断することになると思うのでそこまで気にならない挙動かもしれません。が、今回のようなMySQLレプリケーションの復旧など、データの断面を厳密に特定する必要がある用途での使用は NG ですので気を付けましょう。 本記事がどなたかの役に立てば幸いです。
アバター
本記事は 新人ブログマラソン2025 2/9付の記事です。 こんにちは。2025年にSCSKへ入社した出口です。 本記事では、 Azure の重要概念である「スコープ」をテーマに、AZ-900 ラーニングパスの演習中に実際に発生した仮想マシン(VM)作成エラーを題材として解説します。単なるエラー紹介ではなく、「なぜサブスクリプションというスコープが影響したのか」を整理する ことで、Azure におけるリソース管理の理解を深めることを目的としています。 演習の内容と環境 この演習は、AZ-900 ラーニングパス内の「Azure コンピューティングサービスとネットワークサービス:演習 – Azure 仮想マシンを作成する」が対象です。 社内アカウントではリソース作成に必要な権限が不足していたため、検証には個人用の Azure サブスクリプションを新たに作成して実施しました。 演習の流れは次のとおりです。 1. リソース グループの作成 2. 仮想マシン(VM)の作成 3. VM 上に Nginx をインストール リソースグループ作成は問題なく完了したため、本記事では② 仮想マシン(VM)の作成 にフォーカスして解説します。 以下のコマンドを使用して、仮想マシンの作成を試みました。 az vm create --resource-group "IntroAzureRG" --name my-vm --size Standard_D2s_v5 --public-ip-sku Standard --image Ubuntu2204 --admin-username azureuser --generate-ssh-keys 発生したエラーと表面的な原因 エラーメッセージの要点は次のとおりです。 (QuotaExceeded) Operation could not be completed as it results in exceeding approved standardDSv5Family Cores quota. Location: eastus Current Limit: 0 Additional Required: 2 このメッセージから、eastus リージョンで Standard_D2s_v5(DSv5 ファミリ)に割り当てられている vCPU クォータが 0 のため、必要な 2 vCPU を確保できないことが分かります。 つまり、このサブスクリプションでは eastus リージョンにおいて Standard_D2s_v5 の VM を作成できない状態であることが分かります。 az vm list-usage コマンドでも確認したところ、DSv5 ファミリの vCPU クォータは CurrentValue / Limit ともに 0 であることが分かりました(下図)。 Azureの重要概念:スコープ Azure では、リソース管理とアクセス制御のために 階層構造(スコープ) を採用しており、主に次の 4 階層で構成されています。今回のエラーは、このうち サブスクリプションというスコープ に設定されているクォータが影響していました。   管理グループ :複数のサブスクリプションをまとめて管理し、ポリシーや RBAC を一括適用できる最上位のスコープ サブスクリプション :課金単位となるスコープであり、リソースのデプロイ制限(クォータ)や RBAC の適用単位となる リソース グループ :同じライフサイクルを持つ関連リソースを論理的にまとめる単位 リソース :仮想マシン、ストレージ アカウント、仮想ネットワークなどの実体   以下の図では、管理グループ → サブスクリプション → リソース グループ → リソース という階層構造を視覚的に確認できます。今回、私が操作していたのは リソース グループ と リソース のみ でしたが、エラーの原因はその上位である サブスクリプション にありました。 また、公式ドキュメントでも、スコープは「必要なアクセスのみを付与する」ための重要な概念であると説明されています。RBAC のロールをどのスコープに割り当てるかによって、アクセス可能なリソースの範囲が決まります。 Azure RBAC のスコープについて スコープ は、アクセスが適用されるリソースのセットです。 ロールを割り当てるときは、実際に必要なアクセスのみをセキュリティ プリンシパルに付与できるように、スコープを理解することが重要です。 スコープを制限することで、セキュリティ プリンシパルが侵害された場合に危険にさらされるリソースを制限します。(公式ドキュメントより引用) RBAC(ロールベース アクセス制御) は、これらのスコープに対してアクセス権限を割り当てる仕組みです。今回のエラーの直接原因は RBAC ではありませんが、 クォータも「サブスクリプション」というスコープに紐づく設定 である点が重要です。 私はリソース グループと VM(リソース)の作成を行っていましたが、その上位スコープである サブスクリプションに設定された vCPU クォータ(DSv5 ファミリ:0) によって作成がブロックされていました。リソース グループ側をいくら確認しても原因が見つからなかったのは、 確認すべきスコープが一段上だったため です。 解決策 VM サイズを Standard_D2s_v5 から Standard_B1s に変更することで、クォータ制限によるエラーを解消できました。Standard_B1s は B シリーズに属しており、今回使用したサブスクリプションでは eastus リージョンに十分な vCPU クォータが割り当てられていたためです。 演習手順では、 サブスクリプション固有のクォータ設定 について説明がありません。そのため、利用しているサブスクリプションごとに 使用可能な VM ファミリやサイズが異なる 点を理解し、必要に応じてサイズ変更やクォータ確認を行うことが重要だと感じました。 まとめ 今回実行したコマンドは、既存のリソース グループ内に新しい仮想マシン(VM)を作成・起動するためのものです。 しかし、指定した VM サイズ(Standard_D2s_v5)が属する DSv5 ファミリに対して、対象リージョン(eastus)におけるサブスクリプションの vCPU クォータが 0 に設定されていたため、必要な vCPU 数(2 vCPU)を確保できず、VM の作成に失敗しました。 この事象はリソース グループの設定ではなく、 サブスクリプションという上位スコープで管理される「リージョン別・VM ファミリ別の vCPU クォータ制限」 に起因するものです。   解決策としては、主に次の 2 つが考えられます。 1. すでに利用可能な vCPU クォータが割り当てられている VM ファミリ(例:B シリーズ)を利用する 2. 対象リージョンにおける DSv5 ファミリの vCPU クォータ増加申請を行う クォータの増加申請自体は無料ですが、 審査に時間がかかる、または却下される場合がある ため、今回は 1 の方法を採用しました。 いずれも、「どのスコープにどのような制限がかかっているか」を意識して確認することが重要です。 振り返り(学びと所感) ・Azure では必要に応じてクォータ増加申請が必要であり、「料金を払えばリソースを無制限に利用できるわけではない」という点を学びました。 ・この演習の目的は、Azure で仮想マシンを作成し、Web サーバーをインストールする一連の流れを CLI で体験することでした。AWS と比較すると、Azure はサブスクリプション単位でのクォータ管理や RBAC の適用スコープが明確に体系化されており、リソース作成時の制約がより“見えやすい”と感じました。 ・最終的に AZ-900 試験には無事合格できました。演習では実際の Azure ポータルや CLI を操作することで理解が深まりましたが、短時間の利用でも少額の課金が発生する点には注意が必要だと感じました。 ・ Azureコンピューティングサービスとネットワークサービスについて説明する ・ クウォータの概要 ・ Azure RBAC のスコープについて
アバター
こんにちは SCSKの酒井です。 ServiceNowのナレッジ機能にて、テンプレートを作成する機会があったので、その方法を紹介させていただきます。 本記事は執筆時点(2026年2月)の情報です。最新の情報は製品ドキュメントを参考にしてください。 投稿の経緯 ユーザー管理を行っている中で気づいたことと、実装修正の対応中に得た気づきを2点ほどまとめました。 どちらも細かい内容ですが、もし同様の作業をされる際の参考になればと思い、共有します。   1. 個人アカウントのMFAリセット手順 事象 ServiceNowでMFAが有効化された環境において、社用携帯の初期化や認証アプリケーションのアンインストール、認証情報の削除を行った結果、MFA認証ができなくなる事象が発生しました。 対応手順 1, メニューから[user_multifactor_auth]テーブルに移動して対象ユーザーのレコードを開く 2, Validatedのチェックを外して保存 ※ユーザーが改めてログインするときに再度trueになる 対応手順はこれで以上です。 あとは、対象のユーザーレコードがActiveになっているか等チェックして連携してください。 (今回の場合は無事にMFA再設定ができて、ログインができました。)   2. 選択肢項目から文字列へ変更した際に気づいた設定漏れと解決方法 事象 項目を新規作成する際に選択肢タイプとして定義したのですが、のちの要件変更により文字列タイプへ変更する必要がありました。 項目タイプの変更自体は行えたものの、一部設定が不足していたため、実際のデータ入力時に選択肢の名残が表示される事象が発生しました。 原因 項目の[ Choice List Specification ]の[ Choice ]が以下のようにドロップダウンあり[Dropdowm with –None–]の形式のままになっていたことが原因 ※今回は選択肢はまだ未作成でしたが、選択肢項目を作成して保存をしただけで[ Choice List Specification ]は自動的に設定されます。 対応手順 [ Choice List Specification ]の[ Choice ]を[–None–]に設定して保存 備考 実際の選択肢が残っていた場合、[ Choice List Specification ]の[ Choice ]を[–None–]に設定するだけで入力時に選択肢にはならないのか気になったので確認しましたが、たとえ実際の選択肢が残っていた状態でも上記設定を修正すれば文字列で入力が可能でした。 また、項目の設定をきちんと行ったのに入力できないということがまれにありますが、その場合は該当の項目にすでに何らかのデータが入力されているレコードが存在することが原因である可能性が高いです。 データをクリアにして再度入力できるか確認をしてみてください。 感想 今回の対応を通して、ServiceNowでは設定変更そのものだけでなく、変更後の影響範囲や実際の動作確認まで含めて対応することの重要性を改めて感じました。(当たり前ですが、、) 今後も実装や運用の中で得た気づきは、引き続きまとめていきたいと思います。
アバター
こんにちは!SCSKの野口です。 別の記事で、LangChainを利用したチャンキングのデモを行いました。 その際に、日本語のチャンキング結果が文字化けしてしまうという事象が発生したので、後学のためのに記事にまとめます。 事象 記事内で行った3つのデモの中で、デモ2(分割アルゴリズムの比較)では固定長分割のためにLangChainの「TokenTextSplitter」を利用してチャンキングを行おうとしていました。具体的なコードは下記となります。 from langchain_text_splitters import TokenTextSplitter # TokenTextSplitterを利用したチャンキングメソッド def token_splitter(chunk_size: int, chunk_overlap: int): return TokenTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap) # テキスト作成メソッド def make_doc(noise_repeat: int) -> str: return ( "背景説明。" * noise_repeat + "A部品の設定方針は次の通り。基本はX=ONとする。" + "ただしBモード時のみ例外でX=OFFとする。" ) # チャンキング対象テキスト作成 noise_repeat = 20 doc = make_doc(noise_repeat) # チャンキング設定 chunk_size = 25 chunk_overlap = 0 # チャンキング chunks = token_splitter(chunk_size, chunk_overlap).split_text(doc) # 表示 for i, chunk in enumerate(chunks, 1): print(f"Chunk {i}:\n{chunk}\n---") 上記コードを実行してみると、一部文字化けが発生していることに気が付きました。 原因 なぜ文字化けが発生したのか?それは、 TokenTextSplitterの仕様 が原因でした。 「TokenTextSplitter」 はトークン境界を優先して分割しますが、日本語や中国語などの マルチバイト文字を含む文字列 では、分割後の文字列再構成時に文字境界が崩れるケースがあるようです。   その結果として、UTF-8 として無効な並びが `�` として崩れて表示されるようです。 LangChainの公式ドキュメントにも、 「TokenTextSplitter」を使用すると不正なUnicode文字が発生する可能性がある と記載されています。 (原文) Some written languages (e.g. Chinese and Japanese) have characters which encode to two or more tokens. Using the TokenTextSplitter  directly can split the tokens for a character between two chunks causing malformed Unicode characters. Use  RecursiveCharacterTextSplitter.from_tiktoken_encoder  or  CharacterTextSplitter.from_tiktoken_encoder  to ensure chunks contain valid Unicode strings. ——————————————– (日本語訳) 一部の表記言語(中国語や日本語など)には、2つ以上のトークンにエンコードされる文字があります。 を TokenTextSplitter 直接使用すると、文字のトークンが2つのチャンクに分割され、不正なUnicode文字が発生する可能性があります。 RecursiveCharacterTextSplitter.from_tiktoken_encoder またはを使用する CharacterTextSplitter.from_tiktoken_encoder ことで、チャンクに有効なUnicode文字列が含まれるようにすることができます。 https://docs.langchain.com/oss/python/integrations/splitters/split_by_token   対応方法 公式ドキュメントに記載がある通り、TokenTextSplitterを下記のいずれかに置き換えます。 (修正前) TokenTextSplitter (修正後) RecursiveCharacterTextSplitter.from_tiktoken_encoder CharacterTextSplitter.from_tiktoken_encoder   先ほど文字化けが発生していたコードを書き換えて確認してみましょう。 RecursiveCharacterTextSplitterへの置き換え from langchain_text_splitters import RecursiveCharacterTextSplitter # RecursiveCharacterTextSplitterを利用したチャンキングメソッド def token_splitter(chunk_size: int, chunk_overlap: int): return RecursiveCharacterTextSplitter.from_tiktoken_encoder( chunk_size=chunk_size, chunk_overlap=chunk_overlap ) # テキスト作成メソッド def make_doc(noise_repeat: int) -> str: return ( "背景説明。" * noise_repeat + "A部品の設定方針は次の通り。基本はX=ONとする。" + "ただしBモード時のみ例外でX=OFFとする。" ) # チャンキング対象テキスト作成 noise_repeat = 20 doc = make_doc(noise_repeat) # チャンキング設定 chunk_size = 25 chunk_overlap = 0 chunks = token_splitter(chunk_size, chunk_overlap).split_text(doc) for i, chunk in enumerate(chunks, 1): print(f"Chunk {i}:\n{chunk}\n---")   実行結果: 文字化けしていない ⇒ 改善された!   CharacterTextSplitterへの置き換え from langchain_text_splitters import CharacterTextSplitter # CharacterTextSplitterを利用したチャンキングメソッド def token_splitter(chunk_size: int, chunk_overlap: int):   return CharacterTextSplitter.from_tiktoken_encoder(       chunk_size=chunk_size,       chunk_overlap=chunk_overlap,       separator="",     ) # テキスト作成メソッド def make_doc(noise_repeat: int) -> str:   return (       "背景説明。" * noise_repeat       + "A部品の設定方針は次の通り。基本はX=ONとする。"       + "ただしBモード時のみ例外でX=OFFとする。"     ) # チャンキング対象テキスト作成 noise_repeat = 20 doc = make_doc(noise_repeat) # チャンキング設定 chunk_size = 25 chunk_overlap = 0 chunks = token_splitter(chunk_size, chunk_overlap).split_text(doc) for i, chunk in enumerate(chunks, 1):   print(f"Chunk {i}:\n{chunk}\n---")   実行結果: 文字化けしていない ⇒ 改善された!   まとめ 意外と気にせず「TokenTextSplitter」を利用している人もいらっしゃるかと思います。 文字化けが発生している場合の原因がわからない場合、日本語ドキュメントに「TokenTextSplitter」を利用してチャンキングしていないかを確認してみると良いかもしれません。   「その質問、ドキュメントに書いてある」問題を終わらせたい:RAG連載を始めます 社内ナレッジをRAGで活用し、膨大なドキュメントから必要情報を素早く見つける仕組みを目指します。本記事では連載開始の背景と、RAG基礎〜Bedrock実装・アプリ/エージェント構築までの構成を紹介します。 blog.usize-tech.com 2026.01.27   (シリーズ1:RAGの基本情報 / 第1回)RAGとは:全体像、なぜ必要か、基本フローと設計の勘所 RAG(検索拡張生成)の定義、なぜ必要か、基本フロー(Indexing/検索/補強/生成)を整理します。 blog.usize-tech.com 2026.01.27
アバター