TECH PLAY

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

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

1141

こんにちは SCSK 野口です。 前回の記事 (LifeKeeper for Windows v8.11.0) では基本要件やノード設定についてご紹介いたしました。 まだ、お読みではない方はこちらのリンクからご覧ください。 LifeKeeper for Windows のインストール要件 今回は LifeKeeper for Windows の基本要件について、まとめてみました。バージョン v8.11.0 時点のまとめとなるためご注意ください。 blog.usize-tech.com 2025.11.19 本記事では「LifeKeeper for Windows v10の基本要件や変更点」についてご紹介いたします。 LifeKeeper for Windows v10になってから基本要件が変わっていないか、新機能が追加されていないか注目していきます。 基本要件について システム要件 LifeKeeper for Windows v10は、以下のシステム要件を満たす必要があります。(2026年1月時点) なお、LifeKeeper for Windows v8.11から変更された箇所は赤文字で記載しております。 ※ プロセッサーについてはこちらのリングからご確認ください。 Windows Server プロセッサーの要件   LifeKeeper for Windows v10でも、システム要件はほぼ変わってないね! オペレーティングシステム LifeKeeper for Windows v10は、以下のオペレーティングシステム(OS)がサポートされています。(2026年1月時点) ■サーバーコンポーネント ・Microsoft Windows Server 2025 Standard / Datacenter Editions ・Microsoft Windows Server 2022 Standard / Datacenter Editions ・Microsoft Windows Server 2019 Standard / Datacenter Editions ・Microsoft Windows Server 2016 Standard / Datacenter Editions ※ 全てのバージョンで Microsoft .NET Framework 4.5.2以上が必要です。 ■ユーザーインターフェイス コンポーネント ・Windows 11 ・Microsoft Windows Server 2025 ・Microsoft Windows Server 2019 ・Microsoft Windows Server 2016 ※ 全てのバージョンで Microsoft .NET Framework 4.5.2以上が必要です。 LifeKeeper for Windows v10では、Windows Server 2016 以降から使用できるんだね! ストレージとアダプタ LifeKeeper for Windows v10は、以下のストレージとアダプタ要件を満たす必要があります。(2026年1月時点) また、共有ストレージを使用することも、複製ストレージを使用することもできます。 ■ストレージデバイス ・アプリケーション要件に基づき、必要なデータストレージの種類と数を判断する ・共有ファイルを使用する場合、ディスクアレイ(RAID)に配置する ・多数のハードウェア RAID 周辺機器を使用することができる ■アダプタ ・構成タイプと周辺機器数から、必要な SCSI または FCホストアダプタの種類と数を判断する ・選択したアダプタを Microsoft がサポートしており、ドライバを入手できることが重要である ※ ストレージとアダプタ、それから周辺機器については、Microsoft のサポートが前提となります。 詳細情報については、こちらのリンクからご確認ください。 Microsoft のハードウェア互換リスト ■ 共有ストレージ構成 ・LifeKeeper for Windows によって保護されるディスクはすべてパーティションに分割する ・Windows ディスクの管理ユーティリティを使用し、共有ディスクアレイのパーティション (ボリューム)を構成する ・パーティションは NTFS ファイルシステムで フォーマット する ・コミュニケーションパスに使用する小さい raw(未 フォーマット ) パーティションを指定 *¹ ・クラスタ内の他のサーバの電源を投入して、すべてのサーバが共有ディスクを認識している ・バックアップサーバから、共有ボリュームのドライブの割り当てが最初のサーバとまったく同じにする ・ディスクの管理ユーティリティを開くのは 1 度に 1 台のサーバだけにする (推奨) ・クラスタ内の各サーバで、これらのフォルダのファイル共有属性をオンにする *² ※ ダイナミックディスクは共有ストレージではサポート対象外です。 *¹  共有ディスクコミュニケーションパスを使用する場合に必要です。 *²  共有ボリュームでファイル共有を作成した場合に必要です。 ■ 複製ボリューム構成 (DataKeeper) ・Windows ディスクの管理ユーティリティを使用し、複製されるディスクパーティション (ボリューム) を作成する ・パーティションは NTFS ファイルシステムで フォーマット する ※ ソースボリューム と ターゲットボリュームには同じドライブレターを割り当ててください。 LifeKeeper for Windows v10でも、ストレージとアダプタ要件は変わってないね! 変更点について LifeKeeperの用語 LifeKeeper v10になってから、以下のように LifeKeeperの用語変更されました。(2026年1月時点) ■リソース拡張の際、拡張元サーバと拡張先サーバの呼称が変更されました。 拡張元: Template Server  →「 Primary Server 」 拡張先: Target Server/Target Node →「 Standby Server/Standby Node 」 ■ サーバの待機状態を表す用語が変更されました。 待機状態: Standby →「 Passive 」    使用例: Active / Passive ■リカバリーキットの表記が変更されました。 表記: ~ Recovery Kit →「 Recovery Kit for ~ 」 ■サポートマトリックスの名称が変更されました。 名称: サポートマトリックス →「 認定 情報 」 LifeKeeper for Linux v10も同様に用語変更されたわよ! LifeKeeper for Windows v10から廃止された機能 LifeKeeper for Windows v10から、以下の機能が廃止されました。(2026年1月時点) ■ 製品:LifeKeeper Core ・DISKCAコミュニケーションパスのサポートを廃止。 ■製品:Recovery Kit for Microsoft Internet Information Services ・LifeKeeperは、Microsoft Windows Serverの全バージョンにおいて、 SMTP仮想サーバー機能を廃止。この機能は将来のリリースで削除される予定。 ■製品:Recovery Kit for LAN Manager ・LAN Managerはサポートされなくなり、今後のリリースでLifeKeeperの機能から削除される予定。 なお、新しいLifeKeeper Web Management Console (LKWMC) では使用不可。 ■製品:Recovery Kit for IP Address ・IPリソースのバックアップネットワークアダプターを廃止。 以前のバージョンでバックアップネットワークアダプターを設定していた場合は無視。 IPリソースのバックアップアダプター設定は、 v10にバージョンアップしたら『無視』されるから注意だね! LifeKeeper for Windows v10の新機能 LifeKeeper for Windows v10から、WebベースのGUI (LKWMC) 「LifeKeeper Web Management Console」がリリースされました。(2026年1月時点) LifeKeeper for Windows v10の LKWMCを使用する場合、以下のような要件があります。 動作環境 ■ クライアント環境(OS) ・Windows 11 (64bit) ・Windows Server 2016 (64bit) ・Windows Server 2019 (64bit) ・Windows Server 2022 (64bit) ・Windows Server 2025 (64bit) ■ ブラウザー ・Google Chrome (最新版) ・Microsoft Edge (最新版) ・Mozilla Firefox (最新版) ファイアウォールの設定 ■ クラスタ対象サーバ間の双方向で許可が必要 ・TCP 5000       : REST API サーバ通信で使用    (LKWMC 用) ■GUIクライアントとクラスタ対象サーバ間の双方向で許可が必要 ・ TCP 5110       : GUI サーバ通信で使用            (LKWMC用) ※ その他の新機能についてはこちらのリングからご確認ください。 LifeKeeper for Windows Version10の新機能 LifeKeeper for LinuxのLKWMCと同じポートを使用してるわね! まとめ 今回は LifeKeeper for Windows v10の基本要件や変更点についてご紹介しましたが、いかがでしたか。 ・システム要件では、LifeKeeper for Windows v10になってもほとんど変更されていないこと。 ・オペレーティングシステムでは、Windows Server 2016 以降から使用可能になってること。 ・変更点では、LifeKeeper for Windows v10から、LKWMCがリリースされ使用可能になっていること。 詳細情報をご希望の方は、以下のバナーからSCSK Lifekeeper公式サイトまで
アバター
当記事は、前回の記事「 Ansibleを使用してNW機器設定を自動化する(PaloAlto-セキュリティポリシー編①) 」からの改善となります。 設定情報がベタ書きで使い勝手が悪い点 を 設定情報をまとめてINPUT(JSON)できる使い勝手の良い仕組みとしました!! これにより、Anibleとの連携ができるようになりますので、ご参考になれば幸いです。 Ansibleを使用してNW機器設定を自動化する(PaloAlto-セキュリティポリシー編①) 当記事は、日常の運用業務(NW機器設定)の自動化により、運用コストの削減および運用品質の向上を目標に「Ansible」を使用し、様々なNW機器設定を自動化してみようと試みた記事です。 blog.usize-tech.com 2026.01.06 当記事は、 日常の運用業務(NW機器設定)の自動化 により、 運用コストの削減 および 運用品質の向上  を目標に 「Ansible」 を使用し、様々なNW機器設定を自動化してみようと 試みた記事です。 Ansibleは、OSS版(AWX)+OSS版(Ansible)を使用しております。   PaloAltoの「セキュリティポリシー」の登録/変更/削除を実施してみた 事前設定 Templateを作成し、インベントリーと認証情報を設定する。 インベントリー:対象機器(ホスト)の接続先を設定。 ※ホストには以下変数で接続先IPを指定 ansible_host: xxx.xxx.xxx.xxx 認証情報:対象機器へのログイン情報(ユーザ名/パスワード)を設定。 ユーザ名は  変数:ansible_user   に保持される パスワードは 変数:ansible_password に保持される 各設定値(送信元/宛先/サービス)は、以下の関連記事で登録された値を使用します。※参考にして下さい ・ Ansibleを使用してNW機器設定を自動化する(PaloAlto-アドレス編①) ・ Ansibleを使用してNW機器設定を自動化する(PaloAlto-アドレスグループ編①) ・ Ansibleを使用してNW機器設定を自動化する(PaloAlto-サービス編①) ・ Ansibleを使用してNW機器設定を自動化する(PaloAlto-サービスグループ編①)   事前設定2:設定情報をまとめてINPUT(JSON)できるように、「Survey」を活用 テンプレートが読み込むことができる変数(Survey)を設定する。※今回は、各設定のデフォルト値に値を設定する。 実際の値(JSON) ・input_policy1: {"rule_name":"policy001","description":"policy001","source_zone":"trust","source_address":"test_address001","destination_zone":"trust","destination_address":"test_address002","service":"test_service001","action":"allow"} ・input_policy2: {"rule_name":"policy001","description":"policy001","source_zone":"trust","source_address":"test_address001,test_addressgroup001","destination_zone":"trust","destination_address":"test_address002,test_addressgroup001","service":"test_service001,test_servicegroup001","action":"allow"} ・input_policy3: {"rule_name":"policy001","description":"policy001","source_zone":"trust","source_address":"test_address003","destination_zone":"trust","destination_address":"test_address003","service":"test_service003","action":"allow"}   Playbook作成(YAML) 使用モジュール paloaltonetworks.panos.panos_security_rule  を使用。 ※参考ページ: Ansible Galaxy galaxy.ansible.com   接続情報(provider)の設定 providerには、ip_address/username/password の指定が必要。 vars: provider:   ip_address: '{{ ansible_host }}'   ← インベントリーのホストで設定   username: '{{ ansible_user }}'    ← 認証情報で設定   password: '{{ ansible_password }}'  ← 認証情報で設定   変数(Survey)の値取得 vars で 各変数(Survey)の値取得。 ※各変数(Survey)の値は、構造化データのように見えて「文字列」なので、ディクショナリ(構造化データ)として正しく扱えるように、from_json フィルターを使用すること!!                     vars: wk_input1: '{{ input_policy1 | from_json}}' wk_input2: '{{ input_policy2 | from_json}}' wk_input3: '{{ input_policy3 | from_json}}'   セキュリティポリシーの登録 ★変数(Survey)の値をそのまま使用した場合…エラーとなる 接続情報と ポリシー(送信元/宛先/サービス「 Survey:input_policy1 」) を指定して登録( state: ‘present’ )を行う。 - name: Security_Policy Present paloaltonetworks.panos.panos_security_rule: provider: '{{ provider }}' rule_name: '{{ input_policy1.rule_name }}' description: '{{ input_policy1.description }}' source_zone: '{{ input_policy1.source_zone }}' source_ip: '{{ input_policy1.source_address }}' destination_zone: '{{ input_policy1.destination_zone }}' destination_ip: '{{ input_policy1.destination_address }}' service: '{{ input_policy1.service }}' action: '{{ input_policy1.action }}' state: 'present' register: wk_result_data 実行結果:構造化データではないので、オブジェクトに項目が無いという エラー となる。 ※Ansibleの実行結果を抜粋 "msg": "The task includes an option with an undefined variable. The error was: 'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'name'. ...     セキュリティポリシーの登録 接続情報とポリシー(送信元/宛先/サービス)を指定して登録( state: ‘present’ )を行う。 - name: Security_Policy Present paloaltonetworks.panos.panos_security_rule: provider: '{{ provider }}' rule_name: '{{ wk_input1.rule_name }}' description: '{{ wk_input1.description }}' source_zone: '{{ wk_input1.source_zone }}' source_ip: '{{ wk_input1.source_address }}' destination_zone: '{{ wk_input1.destination_zone }}' destination_ip: '{{ wk_input1.destination_address }}' service: '{{ wk_input1.service }}' action: '{{ wk_input1.action }}' state: 'present' register: wk_result_data 実行結果:対象のセキュリティポリシーが登録された。 ※Ansibleの実行結果(diff)を抜粋 "before": "", "after" : "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<entry name=\"policy001\">\n\t<from>\n\t\t<member>trust</member>\n\t</from>\n\t<to>\n\t\t<member>trust</member>\n\t</to>\n\t<source>\n\t\t<member>test_address001</member>\n\t</source>\n\t<source-user>\n\t\t<member>any</member>\n\t</source-user>\n\t<hip-profiles>\n\t\t<member>any</member>\n\t</hip-profiles>\n\t<destination>\n\t\t<member>test_address002</member>\n\t</destination>\n\t<application>\n\t\t<member>any</member>\n\t</application>\n\t<service>\n\t\t<member>test_service001</member>\n\t</service>\n\t<category>\n\t\t<member>any</member>\n\t</category>\n\t<action>allow</action>\n\t<log-start>no</log-start>\n\t<log-end>yes</log-end>\n\t<description>policy001</description>\n\t<rule-type>universal</rule-type>\n\t<negate-source>no</negate-source>\n\t<negate-destination>no</negate-destination>\n\t<disabled>no</disabled>\n\t<option>\n\t\t<disable-server-response-inspection>no</disable-server-response-inspection>\n\t</option>\n</entry>\n"   セキュリティポリシーの登録 ※セキュリティポリシーが既に存在する場合 接続情報とポリシー(送信元/宛先/サービス)を指定して登録( state: ‘present’ )を行う。  ※セキュリティポリシーが既に存在する場合は、既存設定の置き換えとなる(state: ‘replaced’と同様) - name: Security_Policy Present paloaltonetworks.panos.panos_security_rule: provider: '{{ provider }}' rule_name: '{{ wk_input2.rule_name }}' description: '{{ wk_input2.description }}' source_zone: '{{ wk_input2.source_zone }}' source_ip: '{{ wk_input2.source_address }}' destination_zone: '{{ wk_input2.destination_zone }}' destination_ip: '{{ wk_input2.destination_address }}' service: '{{ wk_input2.service }}' action: '{{ wk_input2.action }}' state: 'present' register: wk_result_data 実行結果:対象のセキュリティポリシーが登録された。 ※Ansibleの実行結果(diff)を抜粋 "before": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<entry name=\"policy001\">\n\t<from>\n\t\t<member>trust</member>\n\t</from>\n\t<to>\n\t\t<member>trust</member>\n\t</to>\n\t<source>\n\t\t<member>test_address001</member>\n\t</source>\n\t<source-user>\n\t\t<member>any</member>\n\t</source-user>\n\t<hip-profiles>\n\t\t<member>any</member>\n\t</hip-profiles>\n\t<destination>\n\t\t<member>test_address002</member>\n\t</destination>\n\t<application>\n\t\t<member>any</member>\n\t</application>\n\t<service>\n\t\t<member>test_service001</member>\n\t</service>\n\t<category>\n\t\t<member>any</member>\n\t</category>\n\t<action>allow</action>\n\t<log-start>no</log-start>\n\t<log-end>yes</log-end>\n\t<description>policy001</description>\n\t<rule-type>universal</rule-type>\n\t<negate-source>no</negate-source>\n\t<negate-destination>no</negate-destination>\n\t<disabled>no</disabled>\n\t<option>\n\t\t<disable-server-response-inspection>no</disable-server-response-inspection>\n\t</option>\n</entry>\n", "after" : "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<entry name=\"policy001\">\n\t<from>\n\t\t<member>trust</member>\n\t</from>\n\t<to>\n\t\t<member>trust</member>\n\t</to>\n\t<source>\n\t\t<member>test_address001</member>\n\t\t<member>test_addressgroup001</member>\n\t</source>\n\t<source-user>\n\t\t<member>any</member>\n\t</source-user>\n\t<hip-profiles>\n\t\t<member>any</member>\n\t</hip-profiles>\n\t<destination>\n\t\t<member>test_address002</member>\n\t\t<member>test_addressgroup001</member>\n\t</destination>\n\t<application>\n\t\t<member>any</member>\n\t</application>\n\t<service>\n\t\t<member>test_service001</member>\n\t\t<member>test_servicegroup001</member>\n\t</service>\n\t<category>\n\t\t<member>any</member>\n\t</category>\n\t<action>allow</action>\n\t<log-start>no</log-start>\n\t<log-end>yes</log-end>\n\t<description>policy001</description>\n\t<rule-type>universal</rule-type>\n\t<negate-source>no</negate-source>\n\t<negate-destination>no</negate-destination>\n\t<disabled>no</disabled>\n\t<option>\n\t\t<disable-server-response-inspection>no</disable-server-response-inspection>\n\t</option>\n</entry>\n"   セキュリティポリシーの変更 ※登録のつづき 接続情報とポリシー(送信元/宛先/サービス)を指定して変更( state: ‘replaced’ )を行う。  ※replacedの場合は、既存設定の置き換えとなる - name: Security_Policy Replaced paloaltonetworks.panos.panos_security_rule: provider: '{{ provider }}' rule_name: '{{ wk_input2.rule_name }}' description: '{{ wk_input2.description }}' source_zone: '{{ wk_input2.source_zone }}' source_ip: '{{ wk_input2.source_address }}' destination_zone: '{{ wk_input2.destination_zone }}' destination_ip: '{{ wk_input2.destination_address }}' service: '{{ wk_input2.service }}' action: '{{ wk_input2.action }}' state: 'replaced' register: wk_result_data 実行結果:対象のセキュリティポリシーが登録された。 ※Ansibleの実行結果(diff)を抜粋 "before": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<entry name=\"policy001\">\n\t<from>\n\t\t<member>trust</member>\n\t</from>\n\t<to>\n\t\t<member>trust</member>\n\t</to>\n\t<source>\n\t\t<member>test_address001</member>\n\t</source>\n\t<source-user>\n\t\t<member>any</member>\n\t</source-user>\n\t<hip-profiles>\n\t\t<member>any</member>\n\t</hip-profiles>\n\t<destination>\n\t\t<member>test_address002</member>\n\t</destination>\n\t<application>\n\t\t<member>any</member>\n\t</application>\n\t<service>\n\t\t<member>test_service001</member>\n\t</service>\n\t<category>\n\t\t<member>any</member>\n\t</category>\n\t<action>allow</action>\n\t<log-start>no</log-start>\n\t<log-end>yes</log-end>\n\t<description>policy001</description>\n\t<rule-type>universal</rule-type>\n\t<negate-source>no</negate-source>\n\t<negate-destination>no</negate-destination>\n\t<disabled>no</disabled>\n\t<option>\n\t\t<disable-server-response-inspection>no</disable-server-response-inspection>\n\t</option>\n</entry>\n", "after" : "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<entry name=\"policy001\">\n\t<from>\n\t\t<member>trust</member>\n\t</from>\n\t<to>\n\t\t<member>trust</member>\n\t</to>\n\t<source>\n\t\t<member>test_address001</member>\n\t\t<member>test_addressgroup001</member>\n\t</source>\n\t<source-user>\n\t\t<member>any</member>\n\t</source-user>\n\t<hip-profiles>\n\t\t<member>any</member>\n\t</hip-profiles>\n\t<destination>\n\t\t<member>test_address002</member>\n\t\t<member>test_addressgroup001</member>\n\t</destination>\n\t<application>\n\t\t<member>any</member>\n\t</application>\n\t<service>\n\t\t<member>test_service001</member>\n\t\t<member>test_servicegroup001</member>\n\t</service>\n\t<category>\n\t\t<member>any</member>\n\t</category>\n\t<action>allow</action>\n\t<log-start>no</log-start>\n\t<log-end>yes</log-end>\n\t<description>policy001</description>\n\t<rule-type>universal</rule-type>\n\t<negate-source>no</negate-source>\n\t<negate-destination>no</negate-destination>\n\t<disabled>no</disabled>\n\t<option>\n\t\t<disable-server-response-inspection>no</disable-server-response-inspection>\n\t</option>\n</entry>\n"   接続情報とポリシー(送信元/宛先/サービス)を指定して変更( state: ‘merged’ )を行う。 - name: Security_Policy Merged paloaltonetworks.panos.panos_security_rule: provider: '{{ provider }}' rule_name: '{{ wk_input3.rule_name }}' description: '{{ wk_input3.description }}' source_zone: '{{ wk_input3.source_zone }}' source_ip: '{{ wk_input3.source_address }}' destination_zone: '{{ wk_input3.destination_zone }}' destination_ip: '{{ wk_input3.destination_address }}' service: '{{ wk_input3.service }}' action: '{{ wk_input3.action }}' state: 'merged' register: wk_result_data 実行結果:エラーとなり変更処理はできない。 ※変更は、state:present/replacedで実施する必要あり。。。要注意!!   "msg": "Failed update source_devices" ※msgの抜粋   セキュリティポリシーの削除 ※変更のつづき 接続情報とポリシーを指定して削除( state: ‘absent’ )を行う。 - name: Security_Policy Absent paloaltonetworks.panos.panos_security_rule: provider: '{{ provider }}' rule_name: '{{ wk_input1.rule_name }}' state: 'absent' register: wk_result_data 実行結果:対象のセキュリティポリシーが削除された。 ※Ansibleの実行結果(diff)を抜粋 "before": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<entry name=\"policy001\">\n\t<from>\n\t\t<member>trust</member>\n\t</from>\n\t<to>\n\t\t<member>trust</member>\n\t</to>\n\t<source>\n\t\t<member>test_address001</member>\n\t\t<member>test_addressgroup001</member>\n\t\t<member>test_address003</member>\n\t</source>\n\t<source-user>\n\t\t<member>any</member>\n\t</source-user>\n\t<hip-profiles>\n\t\t<member>any</member>\n\t</hip-profiles>\n\t<destination>\n\t\t<member>test_address002</member>\n\t\t<member>test_addressgroup001</member>\n\t\t<member>test_address003</member>\n\t</destination>\n\t<application>\n\t\t<member>any</member>\n\t</application>\n\t<service>\n\t\t<member>test_service001</member>\n\t\t<member>test_servicegroup001</member>\n\t</service>\n\t<category>\n\t\t<member>any</member>\n\t</category>\n\t<action>allow</action>\n\t<log-start>no</log-start>\n\t<log-end>yes</log-end>\n\t<description>policy001</description>\n\t<rule-type>universal</rule-type>\n\t<negate-source>no</negate-source>\n\t<negate-destination>no</negate-destination>\n\t<disabled>no</disabled>\n\t<option>\n\t\t<disable-server-response-inspection>no</disable-server-response-inspection>\n\t</option>\n</entry>\n", "after" : ""   最後に 今回、変数(Survey)を活用したことで、Ansibleに INPUT(JSON)を設定 できるようになりました。 設定情報がYAMLにベタ書きではなくなったので、使い勝手は増しましたが、 都度 変数(Survey)のデフォルト値に値を設定しての実行の為、まだまだ 使い勝手が悪い。。。                       今後 外部からAnsibleの INPUT(JSON)に値を連携し実行させる仕組みを試みたいと思います。
アバター
こんにちは、SCSKの伊藤です。 使っているLifeKeeperのサポート期間終了が近くなったのでバージョンアップを検討したい! LifeKeeper for Linux v9.6のフルサポート終了も間近に迫り、このような問い合わせが増えました。 前編の本記事では、LifeKeeperをバージョンアップする際の事前準備とLifeKeeper for Linuxのバージョンアップ画面を ご紹介いたします。   LifeKeeperのプロダクトライフサイクルについて LifeKeeperのプロダクトライフサイクルについては過去の記事にて詳細な説明がありますので、ここでは簡単なおさらいになります。 LifeKeeperは、3年間のフルサポート、2~3年間のメンテナンスサポートのサポートフェイズが設定されております。 更に、メンテナンスサポート終了後に追加契約することで、サポート期間を延長することも可能です。   フルサポート期間 ユーザーポータルから技術支援および問題対応支援の問い合わせ、不具合パッチの提供依頼が可能 メンテナンスサポート期間 ユーザーポータルから技術支援および問題対応支援の問い合わせが可能 ライフサイクル延長期間 「ライフサイクル延長」または「ライフサイクル延長プラス」を追加契約時のみ、メンテナンスサポート期間と同様の問い合わせが可能   使用しているバージョンによってサポート期間のカウント基準が異なりますので、詳細なサポート期間はプロダクトライフサイクルの ライフサイクル表を確認する必要があります。  ■プロダクトライフサイクル プロダクトライフサイクル|サイオステクノロジー株式会社 LifeKeeper, DataKeeper, Single Server Protectionのサポートフェイズとプロダクトライフサイクル一覧を紹介します。 bccs.sios.jp   LifeKeeperをバージョンアップする際の事前準備 LifeKeeperのバージョンアップに際して、何点か事前準備や確認が必要になります。 主な内容は下記の通り。   1.認定情報(サポートマトリックス)の確認 オペレーティングシステムおよびミドルウェアがLifeKeeperバージョンアップ後にサポートされているか確認する必要があります。  ■LifeKeeper for Linux認定情報(v10.0) https://docs.us.sios.com/spslinux/10.0/ja/topic/sios-protection-for-linux-support-matrix docs.us.sios.com   ■LifeKeeper for Windows認定情報(v10.0) https://docs.us.sios.com/sps/10.0/ja/topic/sios-protection-suite-for-windows-support-matrix docs.us.sios.com   2.バージョンアップ方法の確認 LifeKeeper for Linuxは、 マイナーバージョンが “3” 以上離れたバージョンからの直接バージョンアップをサポートしていない ため、中間バージョンへのバージョンアップが必要になる場合があります。 例として、LifeKeeper for Linuxを「 v9.6.0 」から「 v9.9.0 」にアップデートする場合、「 v9.6.0 」から「 v9.7.X 」の中間バージョンにバージョンアップしてから、「 v9.9.0 」にバージョンアップする必要があります。 LifeKeeper for Windowsは、 すべてのバージョンから最新版までのアップデートがサポートされています。   3.バージョン変更の申請 LifeKeeperをバージョンアップする場合は バージョン変更の申請 が必要になります。 変更を申請することで、指定したバージョンのインストールメディアがダウンロード可能になります。   ■バージョン変更の申請 バージョン変更の申請 有効な保守契約、又はサブスクリプション契約のあるお客様は、無償で最新バージョンや任意のバージョンに変更することが可能です。変更方法と申請における注意点は以下のとおりです。 ご利用中のバージョン別申請方法現在ご利用のバージョン申請方法v8/9... lkdkuserportal.sios.jp   4.注意事項および前提を確認 バージョンアップ後、一部設定値の初期化および必要権限の変更、アプリケーションリカバリーキットの仕様変更がされている場合があり、従来の設定では リソース起動ができなくなる等の障害が発生するケース があります。 また、バージョンアップ中にバージョン差異がある状態では対向側サーバのステータスが「不明」状態になり、 通常の手順ではスイッチオーバーなどの操作ができなくなる場合 があります。 事前に、ユーザーポータルまたはサポートベンダーへの問い合わせを行い、注意事項や必要な作業を確認するようにしてください。   LifeKeeper for Linuxのバージョンアップやってみた。 さっそく、LifeKeeper for Linuxのバージョンアップを実施していきます。 作業環境は以下の通り。 ■環境情報 ホスト名 アクティブサーバ = rhel01 スタンバイサーバ = rhel02 OS Red Hat Enterprise Linux release 8.6 (Ootpa) LifeKeeper製品 バージョンアップ前 = LifeKeeper for Linux v9.9.1 バージョンアップ後 = LifeKeeper for Linux v10.0 ■リソース階層 /kdump ファイルシステムリソース  datarep-kdump データレプリケーションリソース   ip-192.168.10.200 IPアドレスリソース ■インストールイメージ ファイルパス /work/LifeKeeper_linux_10-0-0.img   1.LifeKeeperGUIから、LifeKeeperのリソースが正常状態であることを確認します。   2.スタンバイサーバのLifeKeeperを停止します。 [root@rhel02 ~]# /opt/LifeKeeper/bin/lkstop Removed /etc/systemd/system/lifekeeper-graphical.target.requires/lifekeeper.service. Removed /etc/systemd/system/lifekeeper-multi-user.target.requires/lifekeeper.service.   3.スタンバイサーバでインストールイメージファイルをマウントして、セットアップを実行します。 [root@rhel02 ~]# mount /work/LifeKeeper_linux_10-0-0.img /media -t iso9660 -o loop mount: /media: 警告: デバイスは書き込み禁止です、読み込み専用でマウントします。 [root@rhel02 ~]# cd /media [root@rhel02 media]# ./setup   4.環境によっては『Pre-Install Warning』のファイアウォール警告が表示されますので、「Continue」を選択してエンターで 決定します。   5.『Main Configuration』が表示されるので必要に応じて内容の確認をした後、「Done」を選択してエンターで決定します。   6.インストール開始確認画面が表示されるので、「Yes」を選択してエンターで決定します。   7.セットアップ処理が完了することを確認します。 Configure LifeKeeper management group Setup complete.   8.スタンバイサーバのLifeKeeperバージョンアップ後のバージョンを確認します。 [root@rhel02 ~]# rpm -qa | grep steeleye-lk- steeleye-lk-systemd-10.0.0-7800.noarch steeleye-lk-10.0.0-7800.x86_64   9.スタンバイサーバのLifeKeeperを起動します。 [root@rhel02 media]# /opt/LifeKeeper/bin/lkstart Created symlink /etc/systemd/system/lifekeeper-graphical.target.requires/lifekeeper.service → /usr/lib/systemd/system/lifekeeper.service. Created symlink /etc/systemd/system/lifekeeper-multi-user.target.requires/lifekeeper.service → /usr/lib/systemd/system/lifekeeper.service.   10.LifeKeeperGUIから、すべてのリソースをアクティブサーバからスタンバイサーバにスイッチオーバーします。   1 1.スタンバイサーバでリソース起動が完了したことを確認します。   12.アクティブサーバのLifeKeeperを停止します。 [root@rhel01 ~]# /opt/LifeKeeper/bin/lkstop Removed /etc/systemd/system/lifekeeper-graphical.target.requires/lifekeeper.service. Removed /etc/systemd/system/lifekeeper-multi-user.target.requires/lifekeeper.service.   13.アクティブサーバにてインストールイメージファイルをマウントして、セットアップを実行 [root@rhel01 ~]# mount /work/LifeKeeper_linux_10-0-0.img /media -t iso9660 -o loop mount: /media: 警告: デバイスは書き込み禁止です、読み込み専用でマウントします. [root@rhel01 ~]# cd /media [root@rhel01 media]# ./setup   14.スタンバイサーバと同様に、『Pre-Install Warning』のファイアウォール警告が表示されますので「Continue」を選択して エンターで決定します。   15.『Main Configuration』が表示されるので必要に応じて内容の確認をした後、「Done」を選択してエンターで決定します。   16.インストール開始確認画面が表示されるので、「Yes」を選択してエンターで決定します。   17.セットアップ処理が完了することを確認します。 Configure LifeKeeper management group Setup complete.   18.アクティブサーバのLifeKeeperバージョンアップ後のバージョンを確認します。 [root@rhel01 ~]# rpm -qa | grep steeleye-lk- steeleye-lk-systemd-10.0.0-7800.noarch steeleye-lk-10.0.0-7800.x86_64   19.アクティブサーバのLifeKeeperを起動します。 [root@rhel01 media]# /opt/LifeKeeper/bin/lkstart Created symlink /etc/systemd/system/lifekeeper-graphical.target.requires/lifekeeper.service → /usr/lib/systemd/system/lifekeeper.service. Created symlink /etc/systemd/system/lifekeeper-multi-user.target.requires/lifekeeper.service → /usr/lib/systemd/system/lifekeeper.service.   20.LifeKeeperGUIから、すべてのリソースをスタンバイサーバからアクティブサーバにスイッチバックします。   21.アクティブサーバでリソース起動が完了したら、LifeKeeper for Linuxのバージョンアップは完了です。   さいごに LifeKeeper for Linuxのバージョンアップはインストールと殆ど変わらないので、インストールしたことがあれば楽な作業です。 次回は、LifeKeeper for Windowsのバージョンアップ画面をご紹介します。   詳しい内容をお知りになりたいかたは、以下のバナーからSCSKLifekeeper公式サイトまで
アバター
こんにちは、SCSKの池田です LifeKeeperを導入する場合、ライセンスをいくつ購入すれば良いか迷うことがありますよね。特にDR(DisasterRecovery・災害)サイトを立てる場合のライセンス数の数え方には判りにくいところがあります。今回の記事では、一般的なライセンスの考え方の種類や、LifeKeeperの通常のライセンスの考え方をおさらいした上で、DR環境のライセンスについて解説します。複雑化するライセンスの考え方を正しく理解して、ライセンス違反を起こさないようにしましょう! ライセンスのカウントの仕方はアプリケーションによって違う 世の中には様々なアプリケーションがあり、必要なライセンスの数え方も千差万別です。身近なところでは個人で使用するアプリケーションなどでは、ひとつ購入すればスマホやタブレット、パソコンなどの複数のガジェットで利用できるものもあります。一方、ビジネス利用のアプリケーションでは、CPUの数や、中にはコア数によってカウントするものもありますし、10人や1000人といった利用者数あたり1つのライセンスが必要といったものもあります。 主なライセンスの種類 項番 ライセンスの単位 説明 例 1 デバイス数(端末・PC単位) 何台のコンピュータにインストールできるかでカウント 1つのライセンスで5デバイスまで利用可能 2 サーバ数 サーバ製品の場合、インストールする台数でカウント 1つのライセンスでサーバ1台にインストール可能 3 コア数/CPU数 高度な業務用ソフトやサーバ製品では、CPUの物理数やコア数でカウント 4コアあたり1つのライセンスが必要 CPU1つあたり1つのライセンスが必要 4 ユーザー数 利用者の人数でカウント 1つのライセンスで10ユーザーまで利用可能 5 同時接続数 同時に利用できる人数や端末数でカウント 1つのライセンスで同時接続10ユーザまで利用可能 6 サブスクリプション 定期的に使用料を支払うことで、一定期間そのサービスの利用可能となる 1ヶ月ごとに購入 ライセンスの種類がたくさんあって覚えられないわね LifeKeeperのカウントは? 様々なライセンスの種類がある中で、LifeKeeperはどのようにライセンスをカウントするのでしょうか? LifeKeeperは 「サーバ数」 でカウントします。 ここで一つの疑問が浮かぶかたもいらっしゃると思います。ベアメタルの物理サーバの場合は物理的なサーバ数をカウントすれば良いのですが、vSphereなどの仮想環境上のVirtual Macine(ゲストOS)でHAクラスタ構成を組んだ場合のカウントはどうなるのでしょうか? 以下のイメージ図を見た時に、物理サーバ数でカウントする場合はLifeKeeperのライセンスは2つで良さそうですが、Virtual Macine数でカウントする場合は6つ必要になりそうです。 正解は、 6つ必要 となります。 vSphereのような仮想環境においては、LifeKeeperをインストールするVirtual Macineの数分だけライセンスが必要となりますのでご注意ください。 ※仮想サーバ用のお得なライセンスも用意されていますので、そちらは改めて記事にさせていただこうと思います。 災害対策(Disaster Recovery)の重要性 一般的なLifeKeeperのライセンス体系をご理解いただけたところで、災害対策環境の重要性についてお話ししたいと思います。 地球規模で深刻化する異常気象や、地震、火山の噴火、津波に代表される自然災害、国家間の武力紛争、最近では特定の企業グループを狙ったランサムウェア攻撃など、経営者はこれまで以上に事業継続に対する喫緊のリスクとして捉えています。 ミッションクリティカルなシステムであればあるほど、システム停止に伴ってサービスの提供ができなくなるという事態は、自社の収益悪化に直結し、経営基盤を揺るがしかねません。 その為、多くのシステムで可用性(冗長化)が重要視されている状況にあります。 ※冗長構成だけで上記のリスクを完全に回避できるものではありませんので、ご注意ください。 一方で、通常時のシステムと比較して、可用性を考慮したシステムは、地理的にも離れた場所に同じシステムを構築するなど、倍以上のコストがかかることから、費用の面で二の足を踏んでしまうケースも見られます。可用性システムを採用するかどうかの判断に迷った時は、そのシステムが停止した場合のビジネス機会の損失やシステム利用を安定的に提供できないことによる信頼失墜などによるコストを試算し、構築、維持費用と比較をすることをお薦めします。 と、ここまで災害対策の重要性をお伝えしてきましたが、本題のLifeKeeperの災害対策環境のライセンス費用について考えてみましょう。 LifeKeeperのDRサイトのライセンスの考え方 aws上で、LifeKeeperを使って本番サイトとDRサイトを考えた時にいくつかの構成パターンが考えられます。 (1)Disaster Recovery add-on構成 まず、障害発生時に自動的にDRサイトにフェイルオーバすることができるDisaster Recovery add-on構成を考えてみたいと 思います。構成イメージは以下となります。 東京リージョン側でAZ跨ぎのHAクラスター(データはリアルタイム同期)を組み、大阪リージョンにもEC2インスタンスを立てて、Linbit社のデータレプリケーションソフトウェアであるDRBDを用いて非同期でデータを送る形になります。この構成では、3台のEC2インスタンスが常に起動しており、それぞれにLifeKeeperがインストールされています。 この場合、LifeKeeperのライセンスは 3つ 必要となります。 (2)Amazon Machine Image(AMI)を使ったDR 次にAMIを使って、DR発動時にDRサイトでシステムを起動させる方式を考えてみましょう。 構成イメージは以下となります。 本番サイトである「東京リージョン」でAMIを取得し、DR発動時にそのAMIから「大阪リージョン」にサーバを作成するような使い方となります。 このケースでは、 ライセンスの考え方に注意が必要 です。 a.「東京リージョン」と「大阪リージョン」に同時にEC2インスタンスが存在していない(必ずどちらかにしか存在しない)場合 ⇒ 必要ライセンス数は 2つ b.「東京リージョン」と「大阪リージョン」に同時にEC2インスタンスが存在する場合 ⇒ 必要ライセンス数は 4つ 上記のように、 同じサーバが同時に存在しているか否か によってライセンスの要否が変わります。 メーカーであるサイオステクノロジー社の考え方は、以下の様になっています。 項番 ライセンス 必要ライセンス 1 移動 本番サイト分のみ 2 複製 本番サイトとDRサイトの両方 もう少し具体的にご説明すると、本番サイト側が災害など何らかの原因で利用できなくなった際に、DRサイト側にリストアに利用するといった場合は、「移動」という考え方が当てはまり、本番サイト分のみのライセンスの購入で問題ありません。一方、本番サイトで利用していて、同じライセンスのサーバがDRサイト側にも存在する場合は、「複製」という考え方が当てはまり、本番とDRの両サイトのライセンス購入が必要となります。 繰り返しとなりますが、同じサーバが 本番サイトとDRサイトで同時に存在するかどうか が判断のポイントとなりますので、例えば、年に一度のDRサイトへの切替試験を行う場合であっても、本番サイトのインスタンスは必ず削除した上で実施するようにし、ライセンス違反を起こさないようにご注意ください。   (3)クラウド事業者が提供するDRを使用したケース もう一つのパターンとして、クラウド事業者が提供するDRを使用したケースがあります。 対象は以下となります。 ✔ VMware Site Recovery Manager ✔ Azure Site Recovery ✔ AWS Elastic Disaster Recovery このケースでは、DRサイト側のライセンスは特別価格でのご提供となりますので、ご相談いただければと思います。 ※平常時には本番サイトとDRサイトの両サイトで同時にクラスターシステムが起動されることがない等の条件がございます。   まとめ 今回は、一般的なライセンスの種類や、災害対策の重要性と、LifeKeeperの場合のDRサイトで必要となるライセンスについてご説明させていただきました。考え方が少し難しい部分でもありますので、不安な場合は、弊社やメーカーに問い合わせいただき、確実なライセンス数の確保をお願いします。 LifeKeeperについて、詳しい内容をお知りになりたいかたは、以下のバナーからSCSK LifeKeeper公式サイトまで
アバター
こんにちは、SCSKの坂木です。 システム運用において、監視ツールからの通知をどのようにハンドリングするかは重要なテーマです。 今回は、 統合監視ツールであるZabbixと、インシデント管理プラットフォームであるPagerDutyを連携させる設定手順 をご紹介します。   Zabbix × PagerDutyについて Zabbixは非常に強力な監視ツールであり、検知からメール通知、slackなどのチャットツールへの連携まで単体で完結させることも可能です。 しかし、システム規模が大きくなったり、複数の監視ツール(AWS CloudWatch, Datadogなど)を併用したりする場合、PagerDutyを導入することで以下のような 運用の一元化 によるメリットが生まれます。 アラートの集約と一元管理 Zabbixだけでなく、様々なソースからのアラートをPagerDutyに集めることで、運用担当者はPagerDutyの画面だけを見ていれば状況を把握できるようになります。 柔軟なオンコール管理 「日中はチームA、夜間はチームB」「一次対応者が反応しなければ二次対応者へ」といった複雑なシフトやエスカレーションルールを、Zabbixの設定を触らずにPagerDuty側のGUIで柔軟に変更・管理できます。 ステータスの同期 Zabbixで障害が検知されたらPagerDutyでインシデント起票、Zabbixで復旧したらPagerDutyもクローズ、というようにステータスを同期させることで、常に最新の状況をインシデント管理ツール側に反映させることができます。   連携の仕組み 本記事で構築する連携フローは以下の通りです。 Zabbixが障害(または復旧)を検知したタイミングでWebhookを投げ、PagerDutyがそれを受け取るという流れになります。 [Zabbix] —-(Webhook)—-> [PagerDuty] —-(通知)—-> [運用担当者] 本記事では、このフローの中核となる ZabbixからPagerDutyへイベントを送る設定にフォーカスして解説 します。   PagerDuty側の設定 まずは受け皿となるPagerDuty側の設定です。 PagerDutyのメニューから [Services] > [Service Directory] を開き、[+ New Service] をクリックします。   Name に分かりやすい名前(今回はZabbix Alarts)を入力します。 Escalation Policy等は運用のルールに合わせて選択し、Nextへ進みます。 Integrations の選択画面で、表示された [Zabbix] を選択し、[Create Service] をクリックして作成を完了します。   作成後の画面に表示される Integration Key をコピーして控えておきます 。 ※このキーがZabbixからの通信を受け入れるための認証キーとなります。   Zabbix側の設定 続いて、Zabbixから通知を送るための設定を行います。 メディアタイプの有効化 Zabbix管理画面の [通知] > [メディアタイプ] を開きます。 一覧から PagerDuty を探し、ステータスが 無効 の場合はクリックして 有効 にします。   ユーザー設定(Integration Keyの設定) 通知を受信するユーザーに、PagerDutyのキーを紐付けます。 [ユーザー] > [ユーザー] を開き、通知対象のユーザーを選択します。(今回はAdminに紐づけています) [メディア] タブを選択し、[追加] をクリックして以下の通り設定します。 タイプ: PagerDuty 送信先: 「PagerDuty側の設定」で取得した Integration Key を貼り付けます。   グローバルマクロの設定 PagerDutyのメディアタイプにzabbix_urlを設定する項目があり、マクロで設定します。   [管理]  > [マクロ] を開きます。 マクロ {$ZABBIX.URL} に、ZabbixサーバのURLを設定します。   トリガーアクションの設定 障害発生時と復旧時に通知を行う設定です。 [通知] > [アクション] > [トリガーアクション] を開き、アクションを新規作成します。 [実行内容] タブ(障害発生時の動作): 送信先に先ほど設定したユーザー(Admin)を指定し、メディアタイプに PagerDuty を指定します。   [復旧実行内容] タブ(復旧時の動作): 実行内容と同様に、PagerDutyへの送信設定を追加します。 これにより、Zabbixが「解決(OK)」になった情報をPagerDutyが受け取り、 PagerDuty上のインシデントも自動的に「Resolved」となります 。   動作検証 設定完了後、実際に連携が行われるかテストします。 障害検知テスト トリガーアクションの動作条件で設定したトリガーを障害状態にし、PagerDuty側でインシデントが起票(Triggered)され、通知が届くことを確認します。 Zabbixの「監視データ」>「障害」画面を確認します。 障害発生とともにアクションが実行され、メッセージ/コマンドの欄に「PagerDuty 送信済」と表示されていることが確認できます。   続いてPagerDutyの画面を確認します。 Zabbixからの通知を受け取り、ステータスが Triggered (未解決)の状態でインシデントが自動的に起票されました 。   復旧連携テスト 次に、障害状態を解消し、Zabbix上のステータスを正常に戻します。 トリガーの障害ステータスが「解決済」に変わると、設定した復旧アクションが実行されます。 アクションログを見ると、解決時にもPagerDutyへ送信が行われていることがわかります。   PagerDutyのアクティビティログ(またはインシデント一覧)を確認します。 Zabbixからの復旧通知を受け取り、インシデントのステータスが自動的に Resolved に変化しました 。   これにより、「Zabbixで検知してPagerDutyへ通知」→「Zabbixで復旧してPagerDutyもクローズ」という一連の流れが正常に動作していることが確認できました。   まとめ 今回の設定により、「Zabbixが検知したシステムの状態」と「PagerDuty上のインシデントステータス」が同期されるようになりました。 これにより、運用担当者は PagerDutyを確認するだけで、現在対応が必要な障害がどれで、既に復旧したものはどれかを正確に把握できる ようになります。 監視ツールと管理ツール、それぞれの得意分野を活かした運用フロー構築の参考になれば幸いです。   ▼ Zabbixに関するおすすめ記事 【Zabbix】UserParameterでスクリプト実行結果を監視する方法 ZabbixのUserParameter設定ガイド。独自の監視項目を追加する方法、引数を使ったコマンドの使い回し、system.runとの違いを具体例で紹介。監視業務を効率化したい方はぜひ。 blog.usize-tech.com 2025.11.06 【Zabbix】system.runでスクリプト実行結果を監視する方法 Zabbixのsystem.run設定方法をステップバイステップで解説。標準アイテムにないカスタム監視を実現するため、zabbix_agentd.confの修正、安全なAllowKeyの使い方、スクリプトの権限設定までを網羅。初心者でも安心のガイドです。 blog.usize-tech.com 2025.11.04   弊社ではZabbix関連サービスを展開しています。以下ページもご参照ください。 ★Zabbixの基礎をまとめたeBookを公開しております!★ Zabbix資料ダウンロード|SCSK Plus サポート for Zabbix Zabbix監視構築に必要な知識と最新機能についての資料をダウンロードできるページです。世界で最も人気のあるオープンソース統合監視ツール「Zabbix」の導入構築から運用保守までSCSKが強力にサポートします。 www.scsk.jp   ★SCSK Plus サポート for Zabbix★ SCSK Plus サポート for Zabbix 世界で最も人気のあるオープンソース統合監視ツール「Zabbix」の導入構築から運用保守までSCSKが強力にサポートします。 www.scsk.jp   ★SCSK Zabbixチャンネル★ SCSK Zabbixチャンネル SCSK Zabbixチャンネルでは、最新のZabbixトレンドや実際の導入事例を動画で解説。明日から使える実践的なノウハウを提供します。 今すぐチャンネル登録して、最新情報を受け取ろう! www.youtube.com   ★X(旧Twitter)に、SCSK Zabbixアカウントを開設しました!★ https://x.com/SCSK_Zabbix x.com
アバター
こんにちは、音楽の聴き過ぎでイヤホンがすぐ壊れてしまうことが悩みの佐藤です。 少し前のデータになりますが、楽天インサイトの調査(2021年)によると、 音楽を聴く人のうち約4割の人が「ほぼ毎日聴く」 と回答しているそうです。 ( https://insight.rakuten.co.jp/report/20210518/ ) サブスク全盛の今、私たちは呼吸をするように音楽を、 そしてその音楽に込められた歌詞を体内に取り込んでいることになります。 しかし、ここでふと、ある懸念が頭をよぎりました。 我々が毎日摂取しているその歌詞、 医学的に見て「健康」なのでしょうか? 「胸が張り裂ける」「燃えるような恋」「息ができない」「震えが止まらない」……。 これ、冷静に考えると 身体的・精神的にかなり危険な状態 ではないでしょうか? もしこれを冗談とか比喩とかが通じないタイプの人が聞いたら即入院を勧めるレベルかも•••。 ということで今回は、AWSの医療文書解析AIサービス Amazon Comprehend Medical  を使い、 アーティストの歌詞を勝手に問診し、 医学的な観点から最も不健康な楽曲はどれなのか を 至って真面目に!技術検証しようと思います。 Amazon Comprehend Medical とは? あえて自然言語処理を用いずやってみる まずは今回の主役、 Amazon Comprehend Medical(以下ACM) について簡単にご紹介します。 通常、AWSでテキスト分析を行う場合は「 Amazon Comprehend 」を使用します。 こちらは 感情分析(ポジティブ/ネガティブ) や、 一般的なエンティティ抽出(人名、地名、組織名など) が得意です。 しかし、今回の目的はあくまで アーティストの問診票作り です。 ならば 「部位:Chest(胸部)」「症状:Pain(疼痛)」 と、具体的かつ医学的に判定してもらう必要があります。 ACMは、機械学習を使用して 非構造化テキスト(医師のカルテ、治験データなど) から、病状から薬剤に至るまで、 幅広い医療情報を高精度に抽出する ことに特化したサービスです。 本来は、膨大な医療記録を効率的に処理し、医療従事者の負担を減らすために使われる非常にお堅いサービスなのですが、 「医学用語以外をノイズとして無視する」「比喩を理解しない」 という活用?して勝手にアーティストを診断してあげようってわけです。   歌詞をどうやって「診断」する? Amazon Translate で ACM が読める状態に ですが、今回の検証には大きな壁があります。 ACMは現在、日本語のテキスト解析に対応していないのです(英語のみ)。 J-POPの歌詞は当然日本語ですよね。 「日本語未対応なら、英語に翻訳してから読ませればいいじゃない」 というマリー・アントワネット的な発想で、間に Amazon Translate を噛ませてみることにしました。 実はこの Amazon Translate を挟むという構成も、今回の検証結果に大きく関わってきます。 こいつがどんな翻訳を見せてくれるのか、 J-POP特有の抒情的な歌詞をどう英語に落とし込んでくれるのか 。 期待が高まります。 構成図と処理フロー 今回はこんな超簡易的パイプラインを組んでみました。 1. インプット: J-POPの歌詞テキスト(日本語) 2. 翻訳:Amazon Translate で英語に翻訳 例:「君がいなくて胸が苦しい」 → “My chest hurts without you” 3. 診断:Comprehend Medical ( DetectEntitiesV2 API) に投げる 判定: Anatomy: Chest , Condition: Pain 4. アウトプット: 抽出された病名・症状リストと、信頼度スコア(Confidence Score) 「恋の痛み」を強制的に診断させる、近年稀に見る謎ETLパイプラインの完成です。   実践!J-POP患者たちのカルテ Python を使ってスクリプトを書き、実際にいくつかの「名曲」を診断にかけてみました。 ACM 先生は、アーティストの魂の叫びをどう受け止めるのでしょうか。 今回は著作権的に実際の曲を載せられなかったので、本当にありそうな歌詞を AI に生成してもらい投入してみました。   なお今回の実行は CloudShellから Amazon Translate や ACM を呼び出して実行しておりますので、実際にやってみたい方は以下のコードをご利用ください! ▶ ここをクリックして検証用コードを表示する 以下のコマンドを入力してファイルを作成します。 nano doctor_jpop.py 開いたエディタに、以下のコードを 丸ごとコピー&ペースト してください。 import boto3 import time # ========================================== # 診断対象のプレイリスト # ========================================== PLAYLIST = [ { "Artist": "失恋太郎", "Song": "眠れない夜", "Lyrics": "胸が張り裂けそうで眠れない夜。食事が喉を通らない。" }, { "Artist": "炎のロッカー", "Song": "バーニング・ラブ", "Lyrics": "燃えるような恋心。叫びすぎて声が枯れた。息ができない。" }, { "Artist": "純愛ちゃん", "Song": "1000年の愛", "Lyrics": "1000年先も愛を誓う。君の光で目が眩む。体が砕けても守る。" }, { "Artist": "健康キッズ", "Song": "お野菜のうた", "Lyrics": "お日様を浴びて、トマトとキャベツを食べよう。元気いっぱい。" }, { "Artist": "激しいメタル", "Song": "ブラッディ・レイン", "Lyrics": "頭が割れるように痛い。血が騒ぐ。毒のようなキス。意識が遠のく。" } ] # 設定エリア TARGET_REGION = 'us-east-1' # Comprehend Medical用 def main(): # クライアント初期化 translate = boto3.client('translate', region_name=TARGET_REGION) medical = boto3.client('comprehendmedical', region_name=TARGET_REGION) print(f"--- J-POP 健康診断を開始します(全 {len(PLAYLIST)} 曲) ---\n") # 結果格納用リスト ranking_data = [] for track in PLAYLIST: artist = track['Artist'] song = track['Song'] lyrics = track['Lyrics'] print(f"Now Checking... [{artist} / {song}]") # 1. 翻訳 (JA -> EN) try: trans_resp = translate.translate_text( Text=lyrics, SourceLanguageCode='ja', TargetLanguageCode='en' ) en_text = trans_resp['TranslatedText'] except Exception as e: print(f" 翻訳エラー: {e}") continue # 2. 診断 (Comprehend Medical) try: med_resp = medical.detect_entities_v2(Text=en_text) entities = med_resp['Entities'] except Exception as e: print(f" 診断エラー: {e}") continue # 3. 集計 symptom_count = len(entities) # どんな症状が見つかったかテキストでまとめる symptoms_list = [e['Text'] for e in entities] symptoms_str = ", ".join(symptoms_list) if symptoms_list else "なし(健康)" ranking_data.append({ "Artist": artist, "Song": song, "Score": symptom_count, "Details": symptoms_str }) # APIレート制限考慮で少し待機 time.sleep(0.5) # ========================================== # 結果発表(ランキング表示) # ========================================== ranking_data.sort(key=lambda x: x['Score'], reverse=True) print("\n" + "="*80) print(f"{'RANK':<5} | {'ARTIST':<15} | {'SCORE (危険度)':<15} | {'DIAGNOSIS (主な症状)'}") print("="*80) for i, data in enumerate(ranking_data, 1): score = data['Score'] if score == 0: judge = "健康優良児" elif score < 3: judge = f"要経過観察 ({score})" else: judge = f"即入院 ({score})" print(f"{i:<5} | {data['Artist']:<15} | {judge:<15} | {data['Details']}") print("="*80) if __name__ == "__main__": main() 以下のコマンドでスクリプトを実行します。 python3 doctor_jpop.py 結果発表! 出力された結果から、特に重症なものをいくつかピックアップして紹介します。 症例1:失恋直後のバラード患者 対象: 失恋太郎 / 『眠れない夜』 まずは定番、失恋ソングです。 「喉を通らない」「心が引き裂かれる」といった比喩表現が、ACM にはどう伝わったのでしょうか。 【ACM先生の診断結果(ログ抜粋)】 ・SYMPTOM: Meals don't go through my throat (食事が喉を通らない) ・INJURY/TRAUMA: heart was torn (心臓裂傷) 一発目からかなりの大誤診。 「切ない」という情緒は一切考慮されず、 嚥下障害や心臓裂傷 といった今すぐ外科的な緊急手術が必要なレベルです。   症例2:情熱的なロックバンド患者 対象: 炎のロッカー / 『バーニング・ラブ』 続いて、熱いロックバンド。 「声が枯れるまで」「息ができない」といった表現はどうなるでしょうか。 【ACM先生の診断結果(ログ抜粋)】 ・SYMPTOM: voice died (失声症) ・SYMPTOM: can't breathe (呼吸困難) こちらは呼吸器系の疾患ですかね•••? 声が出ず呼吸困難 という状態に対して  「要経過観察」 との診断を下しました。   データ可視化:「不健康ランキング」の結果は? 診断結果をスコアリングし、危険度順に並べ替えた出力結果がこちらです。  RANK | ARTIST | SCORE (危険度) | DIAGNOSIS (主な症状) ================================================================================ 1 | 激しいメタル | 即入院 (5) | head hurts, Blood..., poison, Consciousness... 2 | 失恋太郎 | 即入院 (4) | heart was torn, Meals don't go... 3 | 純愛ちゃん | 即入院 (3) | love, eyes, body 4 | 炎のロッカー | 要経過観察 (2) | voice died, can't breathe 5 | 健康キッズ | 健康優良児 | なし (健康)   最も医療費がかかりそうなアーティストは? 圧倒的なスコアで1位になったのは 「激しいメタル」 でした。 「血(Blood)」 や 「毒(Poison)」 といった単語のオンパレードにより、内科・脳神経外科・救急科のすべての項目でハイスコアを叩き出しました。   やはり野菜は正義 一方で、ランキングの最下位(最も健康)に輝いたアーティストがいます。 「健康キッズ」 です。 『お野菜のうた』に含まれる「キャベツ」「トマト」といった単語に対し、ACMは全く反応しませんでした。 診断結果は 「なし(健康)」 。 やはり明らかに健康そうな歌詞に対しては問題なしと診断する ACM、優秀です!   まとめ 今回は Amazon Comprehend Medical を使って、歌詞の「健康診断」をしてみました。 皆さんも、お気に入りの曲を聴いて「いい歌詞だなあ」と感動しているとき、ふと 「これ、Comprehend Medical に通したらどうなるんだろう?」 と想像してみてください。 きっと、感動が台無しになるはずです笑 今回紹介した Medical 以外にも、 画像認識(Rekognition) や 時系列予測(Forecast) など、それぞれの目的に特化した AI サービスがたくさんあります。 「こんな使い方したらどうなるんだろう?」という好奇心から、新しい技術の活用法が見つかるかもしれません(今回の使い方は完全に誤用ですが•••)。 ただ今回の処理は、非構造化データ(歌詞テキスト)から構造化データ(病名・部位・確信度)を抽出する、典型的なETL(Extract, Transform, Load)プロセスを応用したもの。 ビジネスの現場でも、「顧客のアンケート(自由記述)」から「不満の原因(商品・配送・接客)」を抽出して数値化したい、というニーズに活かせるのでは?と思いました。 ぜひ皆さんも、お手元のデータで遊んでみてください! それでは、また次回の記事でお会いしましょう。
アバター
こんにちは。SCSK渡辺(大)です。 Savings Plans の 使用状況を確認するための勉強として、ユーザーガイド、AWSマネジメントコンソール上の説明文、AWS Black Belt、有志ブログ等を見たのですが、各項目についての説明や考え方がしっくりこなかったので、当記事で自分なりに整理してみました。 当記事ではAWSマネジメントコンソールは「コンソール」と短縮して表記しています。 整理した結果 下図は各項目の位置づけをイメージしやすくしたものです。 「消失したコミットメント」なのに使われている風に見えてしまう感じになってしまいましたね。難しい…。     下表はコンソール上に表示される情報について算出方法などを整理したものです。 私は見つけることが出来なかったのですが、AWS公式の算出方法が欲しいです…。 レポート コンソール 算出方法 CSVファイルでの見方 使用状況レポート Savings Plans の支出 ※1 日付範囲内で適用された全Savings Plansにおける以下合計 [ 1時間当たりのコミット金額 ]×[ 24時間 ]×[ 日付範囲の日数 ] ※2 使用状況レポートの [ 合計コミットメント ] の合計 オンデマンド支出の相当額 日付範囲内で適用された全Savings Plansにおける以下合計 [ SPsが適用された使用量 ]× [オンデマンド単価 ] ※3 カバレッジレポートの [ Savings Plan の対象となる支出 ] の合計 正味の合計削減額 日付範囲内で適用された全Savings Plansにおける以下合計 [ オンデマンド支出の相当額 ] - [ Savings Plans の支出 ] 使用状況レポートの [ 正味の削減額 ] の合計 カバレッジレポート オンデマンド支出は対象外 日付範囲内で適用された全Savings Plansにおける以下合計 [ オンデマンド支出の相当額 ] ÷ [ 平均カバレッジ ]  ×( 1 -  [ 平均カバレッジ ] ) カバレッジレポートの [ オンデマンド支出 ] の合計 平均カバレッジ ※4 日付範囲内で適用された全Savings Plansにおける以下平均 [ Savings Plans の支出 ] ÷( [ Savings Plans の支出 ] + [ オンデマンド支出は対象外 ]) カバレッジレポートの [ カバレッジ ] の平均 オンデマンドと比べて月額削減 の可能性 ※5 以下のガイドを参照 推奨事項の計算について - 積立プラン Savings Plans 推奨事項の計算について説明します。 docs.aws.amazon.com 推奨事項レポートの [ 推定月間削減額 ]   下表はCSVファイル(テーブル)上に表示される情報について算出方法などを整理したものです。 レポート CSVファイル 算出方法 コンソールでの見方 使用状況レポート 使用状況 [ 使用済みのコミットメント ] ÷ [ 合計コミットメント ] – 合計コミットメント ※1 [ 1時間当たりのコミット金額 ]×[ 24時間 ]×[ 日付範囲の日数 ] ※2 合計すると使用状況レポートの [ Savings Plans の支出 ] になる 使用済みのコミットメント [ 合計コミットメント ] × [ 使用状況 ] – 正味の削減額 [ Savings Plan の対象となる支出 ] - [ 合計コミットメント ] 合計すると使用状況レポートの [ 正味の合計削減額 ] になる カバレッジレポート Savings Plan の対象となる支出 [ Savings Plans が適用された使用量 ]× [ オンデマンド単価 ] ※3 合計すると使用状況レポートの [ オンデマンド支出の相当額 ] になる オンデマンド支出 [ Savings Plan の対象となる支出 ] ÷ [ カバレッジ ]  ×( 1 -  [ カバレッジ ] ) 合計するとカバレッジレポートの [ オンデマンド支出は対象外 ] になる カバレッジ [ Savings Plan の対象となる支出 ] ÷( [ Savings Plan の対象となる支出 ] + [ オンデマンド支出 ]) 平均するとカバレッジレポートの [ 平均カバレッジ ] になる ※1:日付範囲内でActiveなSavings Plansが同じであれば、日付範囲を変更しても同じ日数であれば同じ金額になる 例)1/1~1/19で切れるSavings Plans無し、追加購入等も無しの場合 1/1~1/9の10日間:$100 1/10~1/19の10日間:$100 ※2:各アカウントの各Savings Plansの[ 1時間当たりのコミット金額 ] はインベントリレポートの [ totalHourlyCommitment ] を確認 ※3:[ Savings Plans が適用された使用量 ]と[ オンデマンド単価 ]はCostExplorerやAWS公式の料金表で確認 ※4:ユーザーガイドに書かれている通り「大まか」なのか、CSVファイルの情報から算出した値と比較するとコンソール上の表示は-5%~+5%の範囲にあることが多かった ※5:Compute Savings Plans の 以下条件が表示されていた 支払者レベル、1年間、全額前払い、ルックバック30日   レポートの確認方法 使用状況レポートは次の画面から確認することができます。 Billing and Cost Management > Savings Plans > 使用状況レポート   カバレッジレポートは次の画面から確認することができます。 Billing and Cost Management > Savings Plans > カバレッジレポート   以上。 難しいですね…。 おかしな部分がありましたらご連絡ください。 当記事が誰かのお役に立てれば幸いです。 Savings Plans完全に理解した Savings Plansの概念を大まかに理解できるような解説記事です。 blog.usize-tech.com 2025.07.14
アバター
SCSKの畑です。 今回は、前回の投稿でも触れていた通り、アプリケーションにおける更新差分データの表示を効率化・高速化するための一連の取り組みや試行錯誤の過程について説明していきます。   はじめに アプリケーションにおける更新差分データの表示の導出・表示機能について、概要を簡単に説明します。 本アプリケーションにおける管理対象のテーブルについて、データの更新差分を表示できるようにしています。ケースとしては以下2パターンがありますが、どちらも同じ仕組みで更新差分を導出・表示しています。 異なるデータバージョン(例えば最新データとその一世代前のデータ)間での更新差分導出・表示 編集中のデータと最新のデータ(=編集前のデータ)間での更新差分導出・表示 画面としては、以下のように更新差分の種類(追加/削除/変更)ごとに行ないしはセルの色を変更することで、更新差分の内容が視覚的に分かりやすくなるよう工夫しています。(スクショの都合上、更新差分行に絞って表示しています) また、この更新差分導出処理を非同期処理に変更した話を今年度 初回のエントリ にて触れていたかと思いますが、導出自体は昨年度投稿した以下エントリの内容に概ね従って実装しており、 テーブルデータの差分比較を pandas で実施する Redshift テーブルデータのメンテナンスアプリケーションにおいて、テーブルデータの差分比較機能を実装したので内容について記載してみます。バックエンド側の話です。 blog.usize-tech.com 2025.03.26 導出した差分情報は同じく昨年度投稿した以下エントリに記載の Amplify スキーマ定義に従ってアプリケーション上で扱っていました。 Amplify codegen で自動生成される query にネストされた type が 含まれない タイトルの通り、Amplify codegen で自動生成される query にネストされた type が 含まれない事象が発生したため、原因と解決策についてまとめてみました。 blog.usize-tech.com 2025.02.19 この更新差分情報の画面表示のレスポンスが、特にデータ量の大きいテーブルで著しく悪化するケース(場合によっては数分程度)が散見されるようになり実用上支障をきたすことから、改善に向けた取り組みが必要となりました。   今回の取り組みに至った原因とその背景 前回のエントリで半ば予告していましたが「 本アプリケーションで扱うテーブルデータの長大化、及びテーブルデータ更新パスの多様化に伴い更新差分データ量が増大したことで、更新差分情報の画面表示に時間を要するケースが増えた 」ことが主な原因です。 前者の要因については 初回のエントリ にて説明した通りですが、後者の要因については、本プロジェクトにおける ETL/ELT 処理改善の取り組みの結果として、本アプリケーションで扱うテーブルの一部に対してバッチ更新が入るようになったことが背景にあります。 例えば、機種別の売上データの集計を行う ELT 処理において、機種マスタに登録されていない新しい機種に紐付くような売上データが存在した場合はそのデータの集計を保留した上で、ユーザにより問題ない(=機種マスタに追加すべき)と判断されたデータについては機種マスタに自動追加(バッチ更新)するようなロジックを追加しています。このようなロジックを一連の ETL/ELT 処理において複数の観点から導入することで、特にマスタ関連テーブルの手動メンテナンスの負担を軽減するというのが狙いでしたが、一方で複数のテーブルがバッチ更新の対象となった結果、今回のようなケースが増えてしまったということになります。 補足すると、上記の例(機種マスタに対する新しい機種データの追加)であれば、ユーザが手動メンテナンスした場合でも更新(差分)量としては同一であるため、本質的にはバッチ更新そのものが問題となる訳ではありません。ただし、一連の処理フローにおいてこのように差分情報を導出できない or 導出するための計算コストが膨大になってしまうケースもあり、その場合は全テータの洗い替えによって対応する必要があります。すると結果的に更新差分の量もより大きくなってしまいます。 元々の本アプリケーションの設計思想としては、対象のテーブルを本アプリケーション経由で手動更新することを前提としていたため、必然的に更新差分の量もそれほど多くはならないだろうという見込みでしたが、バッチ更新が実装されたことでそのような更新パターンも発生し得ることになりました。   実装上の問題点 ということで前置きが長くなりましたが、具体的な実装の話に入っていきます。 まず、更新差分情報は以下のようなフォーマット(型定義)で扱っていました。DataDiffInfo 配下の AddedRowsInfo に追加された行、DeletedRowsInfo に削除された行、UpdatedRowsInfo に更新された行の情報がそれぞれネストして格納されます。更新された行については更新された列を特定するために、列名の情報も合わせて持たせています。 type DataDiffInfo { diff_summary: RSS3DiffStatus! added_rows_info: [AddedRowsInfo]! deleted_rows_info: [DeletedRowsInfo]! updated_rows_info: [UpdatedRowsInfo]! } type RSS3DiffStatus{ column: Boolean constraint: Boolean data: Boolean } type PKInfo { name: String! value: String! } type AddedRowsInfo { pk: [PKInfo!]! row_data: String! } type DeletedRowsInfo { pk: [PKInfo!]! row_data: String! } type UpdatedRowsInfo { pk: [PKInfo!]! cols: [String!]! row_data: String! } さて、この更新差分情報を画面に表示・反映するためには、当たり前の話ですがアプリケーション画面から参照しているテーブルデータのどの行/列が更新差分に該当しているかを導出する必要があります。そこで昨年度の実装時点では、上記定義の通り更新差分情報に PK の値を含めた上で、PK の値が一致するかどうかで導出していました。本アプリケーションで扱う全てのテーブルに PK が定義されており、PK の値が一致する行は当然ながら一意となるため、更新差分情報を表示・反映すべき行を導出することが可能となります。 厳密には DeletedRowsInfo(削除された行)に限りその必要がありません。削除されている以上、画面から参照しているテーブルデータにも存在しないためです。このため、更新差分の画面表示時には、画面から参照しているテーブルデータにこれらの行データを一時追加することで画面上に表示できるようにしています。 と、ここまでは特段違和感のある内容ではないと思うのですが、結論から言うとこの 「PK の値が一致する行を導出(検索)する処理」 が、更新差分情報の画面表示に時間を要する最も大きな原因となってしまっていました。 普通に考えると、もちろんデータ量に依存する前提とはいえ、表データ(オブジェクト(連想配列)の配列)の検索にそこまで時間を要するか?と疑問に思うところなのですが・・この検索を tabulator という、テーブルデータを画面上で表形式で扱うためのライブラリ経由で実施する必要があった、という点がミソでした。ある意味当たり前の話ですが、tabulator を使用してテーブルデータを画面に表示している以上は、tabulator 上でどの行が更新差分情報に該当するかを導出(検索)する必要があるためです。 なお、tabulator については昨年度概要について紹介していますので、ご興味のある方はこちらのエントリもご覧頂ければと思います。 Tabulator についての簡単な紹介 Redshift テーブルのデータメンテナンスアプリケーションの実装にあたり、テーブルデータの表示/編集に使用したライブラリの Tabulator について、使用した理由や特徴をまとめてみました。 blog.usize-tech.com 2025.03.03 tabulator 自体は多機能なライブラリであるため値の検索機能も充実しており、当初はこの機能を使用して PK を検索する実装としていました。ただ多機能とはいえさすがに RDBMS のように O(1) のオーダーで PK を検索できる訳ではなく、アルゴリズムなどを工夫する余地もありませんでした。そして何よりも、画面から検索機能が大量に連続実行されるようなことはライブラリ側では(おそらく)想定されておらず、ライブラリの処理によるオーバーヘッドも増大した結果・・先述の通りテーブルデータや更新差分の行数が数万行単位になってくるとパフォーマンスが大幅に悪化してしまいました。 また、tabulator 経由でテーブルデータを検索する処理としている以上、tabulator による表データの構築・画面レンダリングが完了したイベントを以ってこの処理を実行せざるを得ないという点も扱いづらい点でした。(以下 URL の tableBuilt というイベントが該当します) Tabulator - Events Tabulator provides a range of events, triggered during table usage that allow you to handle user interaction and system ... tabulator.info 例えば、検索アルゴリズムに工夫の余地がないなら、更新差分情報取得直後に他の重い処理と並列実行することで処理時間を稼ぐようなチューニングの方向性もあり得ると思うのですが、事実上ほとんどの処理が完了したタイミングからでないと tabulator 経由での検索ができなかったため、そのようなアプローチも取れませんでした。 以上の理由により、これまでの実装を大幅に見直す必要がありました。 参考までに当時のコードの一部抜粋も載せておきます。tableBuilt イベントをフックして呼び出される処理となっており、tabulator の検索機能を使用して更新差分情報に該当する行/列を検索の上、フォーマットを変更しています。こう見るとコードの流れ自体はシンプルですが、一部抜粋と記載した通り実際にはもう少しややこしいデータ変換処理などが入っていたため、ここまで見やすくはなかったです。。 tabulator.value.on("tableBuilt", function(){   // 差分行記録用配列の初期化   diffROWIDs = {}   // PKの条件に合致する行を探して削除された行を赤色に変更   for (const row of diffinfo.deleted_rows_info) {       let searchConditions = []       for (const pk of row.pk) {           searchConditions.push({field: pk.name, type: "=", value: pk.value})       }       let target_row = tabulator.value.searchRows(searchConditions);       diffROWIDs[target_row[0].getIndex()] = {type:'DELETED'}   }   // PKの条件に合致する行を探して追加された行を青色に変更   for (const row of diffinfo.added_rows_info) {       let searchConditions = []       for (const pk of row.pk) {           searchConditions.push({field: pk.name, type: "=", value: pk.value})       }       let target_row = tabulator.value.searchRows(searchConditions);       diffROWIDs[target_row[0].getIndex()] = {type:'ADDED'}   }   // PKの条件に合致する行を探して更新されたセルを黄色に変更   for (const row of diffinfo.updated_rows_info) {       let searchConditions = []       for (const pk of row.pk) {           searchConditions.push({field: pk.name, type: "=", value: pk.value})       }       let target_row = tabulator.value.searchRows(searchConditions);       diffROWIDs[target_row[0].getIndex()] = {type:'UPDATED', cells: row?.cols}   }   // 更新差分該当行を再レンダリングして、変更したフォーマットを反映   for (const row of tabulator.value.getRows()){       if (Object.keys(diffROWIDs).map(str => parseInt(str, 10)).includes(row.getIndex())){           row.reformat();       }   } });   改修その1:改善したが完全解決には至らず 以上を踏まえて解決策の検討を始めました。まずは、アプリケーション側で更新差分に該当する行を導出(検索)する際の計算コストを抑えるのが目標となりました。 また実のところ、テーブルデータの編集画面において NOT NULL 制約の存在する列(≒入力必須の列)の色を変更するような、条件に応じて行/列の色を変更する処理自体は他にもあったのですが、いずれもパフォーマンスの問題が発生していませんでした。よって、更新差分情報の表示においてもそれらのロジックと同じような実装に改修できればよいのではないかと考えられたため、早期に方向性を定めることができました。 具体的には、tabulator によりテーブルデータの構成・レンダリングを実施する前に rowFormatter コールバックを使用して、特定の行/列のフォーマット(もちろん色も含みます)を変更するのかをあらかじめ定義しておくような流れとなります。以下 URL の実装例ではコールバック内で対象の行データを取得した上で、「col」という列の値が「blue」である行の色を  #1e3b20 に変更しています。 Tabulator - Component Objects Component objects allow you to interact directly with the components that make up your tables, such as rows, columns and... tabulator.info rowFormatter という名前通りテーブルの全行に対してこのコールバックは適用されるため、上記と同じような処理における条件を PK の値が一致するかどうかに変更すれば、少なくとも現行の実装よりは計算コストを抑えることができるのではないかと考えて実装を変更しました。すると確かに改善は見られたものの、今回特に問題となっているようなデータサイズの大きなテーブルでは差分情報の画面表示が完了するまでに一定の時間を要してしまい、完全解決には至りませんでした。 当初実装より改善していることは間違いないものの、PK の一致チェックをするために結果的に全行の値を取得している以上、データサイズの影響を多少なりとも受けてしまうことは確かです。また、PK が複数の列による複合キーで定義されるテーブルが今回のタイミングで複数追加され、PK の一致チェック自体の計算コストも今後増大し得る傾向が見て取れたため、より抜本的な対策を取れないかどうかを引き続き検討することにしました。 正直なところ、現時点のデータ量・テーブル定義であれば実用に供する結果はこの時点で得られていたのですが、これまでの経緯を鑑みるともう一頑張りできないかどうかを検討しておく方が将来的には有益と考えました。データ量に関してはアーキテクチャやライブラリ上の限界があるものの、一部のテーブル定義については今後も複雑化・長大化していくであろうことが予想できたためです。   改修その2:そして完全解決へ・・ さてそうなると、tabulator の仕様上 rowFormatter コールバックを使用する必要があるため改修の方向性自体は大きく変わらないものの、より計算コストを抑えるためには、実質的に行データを取得することなく更新差分に該当する行を導出するようなアプローチを考える必要がありました。言い換えると、 PK 以外で更新差分に該当する行を導出できるように更新差分情報のフォーマットを変更する必要がある ということになります。 これが難題で、正直しばらくは八方塞がりというか、ひとまず改善できたし一旦妥協しない?と何回も自問自答するくらいには悩み倒しました。。↑のセクションでは偉そうなこと書いてますが・・ というのも、テーブルデータにおいて特定の一意な行を検索するために使用するのって基本 PK なんですよね。もちろん UK (Unique Key) を別に定義することもできますし、その PK や UK を包含した複数行の値で検索することもできるので十分条件にはなりますが、わざわざそういった他の方法を取る意味がないよねというのは自明なところだと思います。(蛇足ですが、本アプリケーションで扱うテーブルに UK が定義されたものはありません) つまり、更新差分情報のフォーマットを見直そうにも見直しようがないという理屈になってしまい、先述の通り悩み倒す羽目になったのですが・・どうにか改善できる箇所ないかなーと思いながらコードを見ていた時にふと気づきました。 あ、行番号(ROW_ID列)が使えるじゃん!!! と。 いきなりすっ飛ばして結論を言うとこれで解決したのですが、、順を追って説明します。 まず tabulator で表データを編集するにあたり、以下 URL の通り Row Index(以下行番号と呼称)としてどの列を指定するかを定める必要があります。全く同じ列の値を持つ行が複数行あったとしても、ライブラリとしてはそれらのデータを別物として扱う必要があるためですね。 よって、その列の値は PK と同じように、行ごとに一意な値を持つ必要があります。つまり、PK などと同じように特定の一意な行を導出するための情報として使用できるということになります。 当然、本アプリケーションで扱う Redshift のテーブルデータ内には行番号のようなデータは含まれていないため、Redshift から S3 経由でアプリケーションにデータを読み込む際にバックエンド側で行番号を動的に生成・付与する形としています。また、アプリケーション経由で表データの編集をする際は、行の追加・削除操作において行番号が重複しないような採番ロジックを組んでいます。 また、その用途・目的上デフォルトでは tabulator のテーブル上には表示されません。意図的に表示することはできますが、特に編集画面で表示する場合はユーザに編集されないように注意しましょう。(行番号が一意でなくなってしまう可能性があるため) Tabulator - Loading Data Tabulator can load data from a wide range of sources, learn how to load data from arrays, JSON and AJAX sources tabulator.info 余談ですが、RDBMS においても内部的に同等の(より高度な)情報を持っていたりします。例えば ORACLE の場合は「ROW_ID」列ですね。普段は意識することはあまりないかと思いますが、この列の情報を意識したオペレーションが稀に必要になることもあります。 ちなみに上記で tabulator の Row Index に指定した列名を「ROW_ID」としていますが、実態はただの行番号で ORACLE のROW_ID列のフォーマットとは全く異なるものです・・ORACLE を意識したネーミングなことは確かですが、念のため。 また、上記の通り tabulator において行を一意に特定する情報として扱われていることから、先述した rowFormatter コールバック内の処理においても getIndex() メソッドを使用することで行番号のみを取得できます 。先述の通り rowFormatter コールバックはテーブル全行が対象となるため行数の影響は受けてしまいますが、それでも行データの取得処理や PK 一致チェック処理をスキップできる分計算コスト的にも有利となるということで、この方針でフロントエンド/バックエンドを改修していくことにしました。 以下、具体的な実装例を記載していきます。コード全量を記載するとさすがに長くなるため一部抜粋である旨ご容赦ください。   バックエンド (Amplify/AppSync) まず、行番号を使用して更新差分に該当する行を導出できるよう、更新差分情報のフォーマットを変更しました。以下の通り、PK 列の代わりに行番号を使用するように定義を変更しています。PKInfo タイプが不要となった分、相対的にシンプルになっています。 type DataDiffInfo { diff_summary: RSS3DiffStatus! added_rows_info: [AddedRowsInfo]! deleted_rows_info: [DeletedRowsInfo]! updated_rows_info: [UpdatedRowsInfo]! } type RSS3DiffStatus{ column: Boolean constraint: Boolean data: Boolean } type AddedRowsInfo { row_data: String! index: Int! } type DeletedRowsInfo { row_data: String! index: Int } type UpdatedRowsInfo { cols: [String!]! row_data: String! index: Int! }   バックエンド (Lambda) 次にこのフォーマットに合わせてバックエンドの各処理(主に更新差分導出用の Lambda 関数)を改修していくことになりましたが、さすがに一筋縄ではいかず少々苦労しました。というのも、上記の通り行番号の情報はあくまで tabulator(フロントエンド)側で必要な情報であり、バックエンド側でその情報をどこまで考慮して処理するようにすれば良いかの見極めがやや難しかったためです。 本アプリケーションによる2つのテーブルデータの更新差分導出・表示機能は冒頭で述べた通り、以下2パターンが存在します。 異なるデータバージョン(例えば最新データとその一世代前のデータ)間での更新差分導出・表示 編集中のデータと最新のデータ(=編集前のデータ)間での更新差分導出・表示 この内、1.のパターンではいずれのデータも Redshift から UNLOAD で取得してきたデータであるため、そもそも対象となるデータに行番号が含まれていません。2.のパターンにおける編集中のデータにのみ行番号が含まれています。先述の通り Amplify/AppSync のスキーマ定義を行番号を返すように変更している以上、Redshift から UNLOAD で取得してきたデータにも行番号を付加する必要があるのでは?と当初懸念していたのですが・・よくよく考えると全くその必要はありませんでした。 まず 1.のパターンにおいては、表データを DataFrame として読み込む際に暗黙的に index を持つため、これをそのまま行番号として返してあげれば OK でした。index には特定の列を指定することもできますが、指定しない場合はデータの頭から 0 オリジンの連番が割り当てられます。そして、バックエンドからフロントエンドにテーブルデータを返す際も全く同じロジックで行番号を付与していたため、DataFrame の index 値をそのまま行番号として使用することができました。 当初からこれを見越した実装にしていたと言えると格好良いのですが、、正直に言うと偶然の一致です。とは言え、バックエンドにおける行番号の付与ロジックを 0 オリジンの連番に変更すること自体は支障がなかったため、いずれにせよ最終的にはこのような実装にしていたかと思います。 次に 2. のパターンにおいては、編集中のデータに対して最新のデータとの更新差分を導出する以上、更新差分情報に含まれる行番号は編集中データのものを使用しないと画面上に更新差分情報が正しく表示されなくなってしまうため、そもそも最新データへの行番号付加は不要でした。最も、フロントエンドから S3 上に編集中のデータを差分導出用に一時保存する際に行番号も合わせて含めておかないと Lambda 関数から行番号を返せなくなるので、その部分の改修は必要でした。 また、2つのテーブルデータ間における差分情報を導出するにあたり行番号は言わずもがな不要な情報となるため、pandas による差分計算時はテーブルデータ(が格納されている DataFrame)からは編集中のデータの行番号を一時的に削除しておき、得られた差分情報に再度行番号を付加するというやや複雑な処理が必要になりました。 具体的には、まず以下のように編集中のデータが格納されている DataFrame (df_dst) のサブセットとしてPK列+ROW_ID列のみの Daraframe (df_dst_row_id_subset) を作成してから、差分計算のために df_dst から ROW_ID列(行番号)を削除しています。 # 編集中のデータと最新のデータ間比較の場合(編集中のROW_ID値を反映するため) df_dst_row_id_subset = None if diff_type == 'btwn_temp_and_latest':     # df_dstのサブセットを作成(PK列 + ROW_ID列)     subset_columns = pk_constraints + ['ROW_ID']     df_dst_row_id_subset = df_dst[subset_columns].copy() # df_dstからROW_ID列を削除 df_dst = df_dst.drop(columns=['ROW_ID']) その上で、以下のように得られた差分情報と PK の値が一致する行を上記で作成したサブセットから検索して、その行の ROW_ID を最終的な差分情報に含める形で出力する、というような流れで実装しています。 # index_valueの算出ロジック if diff_type == 'btwn_temp_and_latest': # PK列が一致する行のROW_IDを取得 pk_query_conditions = [] for pk_name, pk_value in zip(pk_constraints, pk_cols): pk_query_conditions.append(f'{pk_name} == "{pk_value}"') pk_query_str = ' & '.join(pk_query_conditions) matched_row_id = df_dst_row_id_subset.query(pk_query_str) index_value = int(matched_row_id['ROW_ID'].iloc[0])   フロントエンド (typescript) ここまでできればフロントエンド側ではある意味どうとでもなるのですが、具体的には以下のような実装となりました。 diffROWIDs 変数が更新差分情報を格納している連想配列(キーが行番号)となっており、row.getIndex() メソッドで取得した対象行の行番号が同連想配列に含まれているかを判定し、含まれている場合は差分の内容(追加/削除/更新)に従って行またはセルの色を変更するような処理となっています。改修前のコードと比較すると処理自体が大きく変更されているのが分かるかと思います。 // rowFormatter設定(差分行の色付け) const diffRowsFormatter = function(row){ const row_id = row.getIndex() if (Object.keys(diffROWIDs).map(str => parseInt(str, 10)).includes(row_id)){ // 追加行の色付け if (diffROWIDs[row_id].type === 'ADDED'){ row.getElement().style.backgroundColor = "#93c5fd"; } // 削除行の色付け else if (diffROWIDs[row_id].type === 'DELETED'){ row.getElement().style.backgroundColor = "#fca5a5"; } // 更新行の色付け else if (diffROWIDs[row_id].type === 'UPDATED'){ for (const cell of row.getCells()){ for (const diff_cell_name of diffROWIDs[row_id].cells){ if (cell.getColumn().getDefinition().field === diff_cell_name){ cell.getElement().style.backgroundColor = "#fde047"; } } } } // 例外処理 else { addErrorInfo('未定義の差分定義情報です') } } } 以上の一連の対応により、データサイズ/更新差分が数万行単位となる大きなテーブルにおいても、差分情報の画面表示は概ね1秒未満で完了するまでにパフォーマンスを改善できたため、完全解決と相成りました。 ここまで書いてみると、フロントエンドで実装していた PK による検索処理がバックエンド側に移ったと言ってもある意味差し支えないかもしれません。ただ、同じ処理をするとしても pandas (DataFrame) で実施した方が効率的に思われますし、今回の問題を解決するためにフロントエンドでボトルネックとなっていた処理をバックエンドに移すというアプローチの方向性自体も正しかったかなと思います。少なくともトータルでのレスポンスは比べ物にならないくらい早くなったので。   まとめ 改めて今振り返っても、元々の更新差分情報の型定義自体は特に問題のない仕様だったかと思います。先述の通り、一意な行を導出するために使用できるテーブルデータ内の情報はやはり PK になるからです。 ただ、それはあくまでテーブル内の情報を使用するという前提で考えた場合の話であり・・この情報をアプリケーション側でどう扱うのか、どのような型定義の方が性能面も含めてより扱いやすいか、というような観点が欠けていたことも事実であり、個人的にはとても良い勉強になりました。最も RDBMS で言うところの正規化の問題みたいなものだと考えると、(私の元々の専門が DB なだけに)もうちょっと最初から気を使えただろうという反省もあるのですが、、 本記事がどなたかの役に立てば幸いです。
アバター
AWS Lambdaが好きでよく使っていますが、 Azureでも同じようなFaaSとしてAzure Functionsがあると知り、使ってみました。 正直なところLambdaのようなお手軽さはなく、なかなか複雑で使いづらいなという印象でした。 まずは試しに使って動かしてみたいレベルの人向けにこの記事がお役に立てばうれしいです。 開発環境の準備 今回はAzure Functionsの開発をVisual Studio Code(VSCode)で行います。 VSCodeで開発するにあたり、端末で以下の準備が必要です。 VSCodeのインストール pythonのインストール (※Azure Functionで使用するPythonバージョンと同じバージョン) VSCode拡張機能として「Azure Functions」と「Azurite」のインストール Azure Functions Core Toolsのインストール VSCodeのインストールとpythonのインストールはインターネット上に情報が十分にありますので、 インストール手順は省略します。 VSCode拡張機能として「Azure Functions」と「Azurite」のインストール VSCodeの拡張機能でAzure Functions検索してインストールできます。 Azuriteも同様にインストールできます。 Azure Functions Core Toolsのインストール VSCodeの拡張機能でAzure Functionsをインストールすると、「Azure Functions Core Tools」はこの拡張機能からインストールできます。 VSCode上で「Ctrl + Shift + p」でコマンドパレットが起動できますので、 そこで「Azure」と入力して、「Azure Functions: Install or Update Azure Functions Core Tools」を実行します。 以下のように自動でnpm installが実行されます。   Pythonコード開発 開発環境の準備ができましたらここからAzure Functions内で実行させるPythonコードの開発になります。 ローカルプロジェクトの作成 VSCodeのメニューに「Azure」のメニューが追加されていますので、 そこから「WORKSPACE」で「Create Function Project…」で作業スペースが作成されます。 WORKSPACEはローカルPC上のフォルダになりますので、お好きな場所を指定してください。 プロジェクトは「python」を選択します。 使用されるPythonのバージョンを選択します。 私はPython3.13をインストールしておきましたので、選択肢に出てきています。 実行トリガーを指定します。 トリガーは多様な種類があり、定期実行やHTTP実行、EventGridによりイベント駆動なども選択可能です。 今回はとりあえず動作を見るということで定期実行の「Time Trigger」を選んでみます。 作成するPythonコードの関数名を指定できます。 お好みがあれば指定いただけますし、デフォルトでもOKです。 定期実行のタイミングをcron形式で指定できます。 今回は早く実行結果を見たいので1分間隔にします。各自お好みの間隔に設定してOKです 設定値を入力しきるとWORKSPACEが作成されてVSCodeでオープンされます。 必要なファイルも自動で作成されていますね。 処理実装 作成されている「function_app.py」の中に処理を実装していくことになります。 赤枠の部分に実装していきましょう。 注意 @app.timer_triggerが、定期実行をつかさどる部分になりますので、この行は削除NGです。 設定した定期実行のタイミングを変更したい等あれば、この部分の「schedule=」の部分変更しましょう。 注意 追加のPythonライブラリを使う場合は、requirements.txtに追加してください。 requirements.txtに記載しないとライブラリがインストールされず、importに失敗します。 とりあえず動かすだけなので、処理内容は変えずこのまま動作テストしてみます。 Timer Triggerを使うにはStorage Accountが必要になるのですが、ローカルPC環境にはないので、「Azurite」で代替します。 VSCode上で「Ctrl + Shift + p」でコマンドパレットを起動して、「Azurite: Start」を実行しましょう。 Azuriteが起動したら、VSCodeでコマンドプロンプトのターミナルを起動して以下のコマンドを実行しましょう。 func start 無事に「Python timer trigger function executed.」が1分おきに実行されていることがわかりますね。 これでローカル環境上では正常にAzure FunctionがTimer Triggerで実行されることがわかりましたので、 実際のAzure Functionsにデプロイしていきましょう。 Azure Functionsデプロイ メニューからAzureのマークに移動して、「ACCOUNTS & TENANTS」で「Singn in to Azure…」を押下しましょう。 MicroSoftのログイン画面が表示されますので、デプロイ先のAzureアカウントのユーザーでログインしましょう。 ログインできたら、「WORKSPACE」の「Local Project」で雲のマークを押します。 「Create new function app…」でデプロイ先のAzure Functionsを作成しましょう。 もし、既に作成済みなら、そのFunctions名を指定しましょう。 作成するAzure Functionsの名前を指定します。 Local Projectと名前が異なっても大丈夫ですが、全世界で一意の必要があるので、誰かが使っていたらNGになります。 リージョンを指定します。 Pythonはローカル環境に入れたものと同じバージョンを指定します。 認証方式は「Secrets」を選択します。 設定に沿って自動でAzure Functionsや必要な周辺リソースを作成してくれます。 正常に完了したら、自身のAzureアカウントにAzure Functionsが作成され、コードもデプロイされています。 注意 VSCodeの作成方法では、リソースグループやインスタンス メモリ、プランなどがコントロールできません。 実際に使われる際には、事前にAzureポータルで作成して、コードだけデプロイする方をお勧めします。 実行確認 作成されたAzure Functionsで「監視 > ログ」で「requests」テーブルを参照してみましょう。   見事に1分間隔で実行されていますね。 別のテーブルでtracesを見ると実行ログも確認できます。 まとめ 開発開始するまでのVSCodeの事前準備が思ったより手間取りましたが、 そこを超えれば何とかなりそうです。 ローカル環境でStorage Accountの代替が可能なAzuriteが必要だったり、 実行前にAzuriteを起動させないといけなかったり、知らずにやると落とし穴に落ちますが、 少しでもこの記事が参考になれば幸いです。
アバター
こんにちは。SCSK1年目の渡辺です。 今年の re:Invent、皆さんご覧になられたでしょうか。 今年も例年どおり多くの発表があり、かなり盛り上がっていましたね。 私はリアルタイムでの参加はできず、いくつかアーカイブを視聴した程度ですが、 現地に行かれた方の話を聞く機会があり、来年は絶対行ってやる!!と思いました。 会場の熱量など、日本とは別世界なんだな、と改めて感じました。 (kiroのぬいぐるみ欲しかった、、、) 前置きはこのあたりにして、今回の re:Invent の中でも、特に注目を集めていたサービスの一つが AWS DevOps Agent だったと思います。 社内外を含めて「今回の目玉はAWS DevOps Agent」と言っている方も多く、 実際のところどんなことができて、運用業務でどこまで使えそうなのかが気になりました。 そこで今回は、 AWS DevOps Agent を実際に触ってみて、管理画面や挙動を確認しながら、運用目線での所感を整理 してみました。 本記事では、「サービス概要の紹介」と、「実際に触ってみてどう感じたか」 といった観点でまとめています。 AWS DevOps Agentとは AWS DevOps Agent は、インシデント発生時の初動対応や原因調査を、AI エージェントが支援するためのサービスです。 CloudWatch をはじめとした監視・可観測性の情報をもとに、影響範囲の特定や原因候補の洗い出しを自動で行い、運用担当者の判断をサポートします。 従来の運用では、アラートを受け取った後に 「どのリソースが影響を受けているのか」 「直前に何が変更されたのか」 「どこから調査を始めるべきか」 といった点を、人が個別に確認する必要がありました。 AWS DevOps Agent は、こうした作業を横断的に整理し、インシデントの状況をまとめて提示してくれます。 また、単に障害の原因を示すだけでなく、 過去の事例や検知したパターンをもとに、再発防止のための改善案(監視設定や構成見直しの提案など)を提示してくれます。 「調査して終わり」ではなく、次のアクションまでを意識した設計になっている点は、実運用を強く意識したサービスだと感じました。 また幅広い他ツールとの連携も特徴の一つで、New RelicやDatadogなどの監視ツールや、ServiceNowなどのチケット管理ツールなどと連携することができ、従来の運用フローを大きく変更することなく、DevOps Agentを導入することが出来ます。 AWS DevOps Agent は、運用を完全に自動化するものではなく、あくまで 人の判断を前提とした支援ツール という位置づけです。 インシデント対応のスピード向上や、調査観点の標準化といった点で、運用業務の負荷軽減に貢献するサービスになっています。 インシデントを発生させてみる それでは早速、アラートを発砲させてみましょう! 今回はEC2インスタンスのCPU使用率が80%を越えるとアラートを発砲するようにアラームを作成し、SSMでインスタンスに接続、CPU負荷コマンドを実行しました。コマンド実行からしばらく置いてから、 AWS DevOps Agent に調査を依頼しました。 実行コマンド stress --cpu 1 --timeout 300 --load 50   調査プロンプト #Please investigate the incidents that occurred within the last 24 hours. 実際の調査画面 さて、、どのように調査を進めてくれるでしょうか、、、、 見ていきましょう! 1.調査開始→アラート検知 こんな感じの画面で調査が進みます。 画面中央には調査対象リソースが表示され、画面下部で調査の進捗が確認できます。 画面右側はAIチャットエリアになっており、調査を進めながらAIと対話をすることが出来ます。   無事今回のアラートを検知してくれましたね! 2.障害調査 アラート前後で発生した事象や、アラートが発生したと同時に何が起こっていたかなどを、調査しながら、グラフを用いて説明してくれています。 情報が多く載せきれないですが、直近のログや、AWS環境内の細かな変化など、かなり様々な角度から調査をしてくれます。 3.根本原因特定→対応策提示 調査開始から5分ほどで根本原因まで特定し、 「今回はSSM接続でCPU負荷をかけるコマンドが実行された」と結論付けてくれました。 大正解!!ですね。   対応策も見てみると、「とりあえずは必要ありません。今回は意図的にCPう負荷コマンドが実施されただけなので」と言っており、場合にもよりますが、テストまで見抜けるのはさすがだなと感じました。   今回はCloudWatchアラームの設定のみのため、SSM接続した際に実行したコマンドのログなどは取得できていません。 CloudWatch Agentを用いることで、OSレベルのログも取得できるため、原因となったコマンドまで特定することが出来ます。 終わりに ということで、今回は AWS DevOps Agent を実際に触って検証してみましたが、いかがだったでしょうか。 個人的には、想像していた以上に多角的な観点から分析を行ってくれる点が印象的でした。 アラート発生時の初動対応や、原因のあたりを付ける段階において、 「まず DevOps Agent に調査させてみる」という使い方は十分に有効だと感じました。 一方で、実運用するうえで課題になりそうな点も感じました。 今回の検証は構成が非常にシンプルだったため、調査はシンプルに完了しましたが、 リソース数が多い環境や、アラートが複雑に組み合わさったケースでは、調査時間が長くなってしまったり、思わぬ部分で意外とコストが重なってしまった。ということになる可能性があると感じました。 また、現時点ではプレビュー段階ということもあり、 バージニア北部リージョン(us-east-1)のみ対応、UI が英語のみといった制約もあります。 日本語対応の日が待ち遠しいですね!! 今回はDevOps Agentの管理画面内で完結する形で検証しましたが、Lambda と連携してアラート発生時に自動で調査を開始したり、 Slackなどと連携して調査結果を随時通知するといった使い方など、運用フローに組み込む余地は多く、活用の幅はかなり広そうです。 まだ発展途上のサービスではありますが、 運用効率化の観点から、一度は実際に触ってみる価値のあるサービスだと感じました。 興味のある方は、ぜひ実際に触ってみてください!!
アバター
Azure環境を構築するうえで、メール送信機能が必要になったので実現できるサービスを実際に使ってみました。 使い勝手としては、AWSで例えてしまって申し訳ないですが、Amazon SESとほぼ一緒でした。 Amazon SESを使ったことがある人なら、特に苦戦せずに使えそうなサービスです。 リソース構成 Azure Communication Servicesでメールを送信する場合、2つサービスを使用することになります。 1つがAzure Communication Servicesです。 こちらは今回メール送信に使用しますが、その他チャット送信などの通知機能も持っており、統括的な通知サービスになっています。 そのような背景もあり、主体ではあるのですが、メール送信関連のコンフィグはもう1つの方で持つことになります。 2つ目がEmail Communication Servicesです。 こちらがAzure Communication Servicesからメール送信するときに参照されるメール関連のコンフィグになります。 使用するドメインやメールアドレス、メールテンプレート等の設定を保持します。 構築手順 Email Communication Services Email Communication Services作成 Azure Portalで「Email Communication Services」を検索し、移動。 左上の「作成」を押下。 必要事項を入力して、「確認と作成」を押下して、確認画面で「作成」を押します。 Email Communication Services設定 作成が完了したら、リソースのリンクを押下して、設定画面に遷移。 「Settings」-「Provision domains」を押下。 「Add domain」でメール送信ドメインを追加する。 ※「Azure domain」だと、Azureにて自動でメールドメインが払い出される。 ※「Custom domain」だと自身が所有するドメインを追加することができる。 ドメインを追加する。 「Azure domain」の場合は、押下すると即時に利用可能なレベル。 右上に進行中の表示が出て、数分後にはメールアドレスが払い出される。 払い出されるドメインは<乱数>.azurecomm.net が払い出される。                   注意 Email Communication Services上だとドメインは、「.azurecomm.net」ですが、 実際に届くメールアドレスは、「.jp1.azurecomm.net」で届きました。 ドメインレベルで受信許可等が必要な場合は、ご注意ください。       「Custom Domain」の場合は、所有しているドメインを入力して、「Confirm」して「Add」を押下。 所有するドメインのDNSにレコード追加の指示が出るので、追加を行う。 指示されたTXTレコードを追加。 レコードを追加して数分すると「Verified」になる。 そのまま、SPFとDKIM、DKIM2も有効化するために「Configure」を押下して、指定されたDNSレコードを登録する。 ※SPFはドメイン認証のためのTXTレコードと重複するので値に2行目として追加する。 以下はRoute 53で行った場合の画面イメージ。 SPF、DKIM、DKIM2の列が全て「Verified」になれば、ECSの設定は完了。 Azure Communication Servicesリソース作成 Azure Portalで「Communication Services」を検索し、移動。 左上の「作成」を押下。 必要事項を記入して、「Review + Create」を押下。その後の確認画面でも「Create」を押下。 出来上がったリソースのリンクを押下。 左メニューから「メール」-「ドメイン」を押下。 「Connect domains」を押下。 作成したEmail Communication Servicesとドメインを指定して、「Connect」を押下。 ※以下の画面は、Azure domainを追加してみた際の画面 追加したドメインが「Connected」になればOK。 機能検証 試しに追加したドメインでメールを送信してみます。 作成したAzure Communication Servicesのリソースで「メール」-「メールを試す」を押下。 送信メールの情報を入力して、「Send」を押下。 (改行はHTML) 無事に受信完了。 注意 初期状態だと送信元メールアドレスは「DoNotReply」だけが使用できます。 送信元アドレスを追加したい場合は次の手順を実施してください。 補足(送信元メールアドレスの追加) 送信元メールアドレスは、Email Communication Servicesの方で、「Provision domains」に登録したドメインの中に設定されています。 左メニューの「Email services」-「MailFrom addresses」に登録されています。 そしてこの画面の「Add」から追加できるはずなのですが、グレーアウトされていて使用できません。 なぜか探していたら、同様の事象で困っている人がMicrosoft Igniteで問合せしていました。 https://learn.microsoft.com/en-us/answers/questions/1630281/add-button-disabled-in-email-communication-service どうやら原因はわからないですが、Azure CLIからなら追加できたという情報です。 ということで、仕方ないのでAzure CLIから追加してみます。Azure CLIはCloudShellから実行しました。 CloudShellを起動。 CloudShellで対象のサブスクリプションにログイン。 az account set –subscription “ <サブスクリプション名> “ 送信元アドレスを追加してみます。 az communication email domain sender-username create \ --domain-name "<追加先のドメイン名>" \ --email-service-name "<EmailCommunicationServicesのリソース名>" \ --sender-username "<送信元アドレス名>" \ --resource-group "<リソースグループ>" \ --display-name "<表示名>" \ --username "<送信元アドレス名>""<送信元アドレス名>" 注意 「Azure domain」の場合は、「–domain-name」の引数を「AzureManagedDomain」にする必要があります。 カスタムドメインの場合は、登録したドメイン名でOKです。 画面に追加されました。 「メールを試す」画面でも、「Sender email username」に追加したユーザー名が選択肢に出てきます。 無事に設定したユーザー名と表示名でメールを受信しました。 まとめ カスタムドメインやAzureのサブドメインでメール送信が簡単に行えました。 ファイルの添付等も可能なので、Azure上のサービスと連携させて、メール通知させるのに適していることがわかりました。
アバター
こんにちは!SCSKの斉藤です🐧 Snowflakeの安全対策をちゃんとやってますか?「まあ大丈夫でしょ」と油断していると、思わぬ落とし穴が…! 今回は、安全に使うために管理者がやるべき「3つの制限」についてご紹介します!   ①クレジット使い過ぎを制限 Snowflakeを使ってて、気づけばクレジットを消費しすぎて、恐ろしい請求が… そんなことにならない為に、”リソースモニター”という機能があります! 用途 指定したクレジット量を超過した場合、通知や停止を実施 使用例 アカウント全体で毎月5クレジットを超過時に通知、毎月10クレジットを超過時に強制停止 主な設定項目 クレジット閾値 ルール適用の開始日 監視のスケジュール周期(日次 / 週次 / 月次 / 年次 / リセット無し) 作成したルールの適用先(アカウント / 任意のウェアハウス) アクション(通知 / 超えた瞬間に停止 / 超えた後に最後の実行後に停止) 注意事項 開始日として月の最後の日を指定すると、その月の日数に関係なく、 後続月のすべてで、月の最終日に使用済みクレジットをリセット       3/15を開始日、周期は月次に設定:次回は4/15 0時にリセット 3/31を開始日、周期は月次に設定:次回は4/30 0時にリセット (管理者 > コスト管理 > +リソースモニター から設定可能) (実際の設定画面) リソースモニターの操作 | Snowflake Documentation docs.snowflake.com   ②IPアドレスによるログイン制御 「知らない人はお断り!」…これはオフィスの入口だけでなく、Snowflakeのログインにも言えること。 IPアドレスでしっかり門番を立てて、社外からの怪しいアクセスはシャットアウト! “ネットワークポリシー”を設定すれば、情報漏洩リスクもグッと減ります。 用途 IPアドレスによるログイン制御 使用例 社内IPアドレス 123.456.789.0/24からのアクセスのみ、ログイン許可 主な設定項目 アクセス許可 or 拒否するIPアドレス 注意事項 ログイン制御ルール作成時に、新規DBの作成が必要 (ガバナンスとセキュリティ > ネットワークポリシー > +ネットワークポリシー から設定可能) (実際の設定画面) ネットワークポリシーを使用したネットワークトラフィックの制御 | Snowflake Documentation docs.snowflake.com   ③MFA未登録ユーザーへの対応 以下のポップアップを、見て見ぬふりしていませんか? 管理者が未登録ユーザーをリストアップして「MFA登録お願いします」と優しく声をかけましょう。 みんなで協力して、低セキュリティなログインをゼロに! (ガバナンスとセキュリティ > ユーザーとロール > MFA項目 から確認可能) 多要素認証(MFA) | Snowflake Documentation docs.snowflake.com   さいごに 制限をかけると「ちょっと面倒…?」と思うかもしれませんが、これも安全なSnowflakeライフのため! 他にも様々な安全対策がありますが、まずはこの3つから初めてみましょう 安心・安全なデータ活用で、Snowflakeをもっと楽しく使いこなしてください!
アバター
こんにちは。SCSKの井上です。 New Relicエージェントを導入した後、サーバーの見方や検索方法を理解し、UIを使いこなすための基本操作を紹介します。この記事を読むことで、効率的な監視と分析ができる一助になれば幸いです。   はじめに New Relicを導入したものの、機能が多くてどこから確認すればよいかわからないことがあります。サーバの観測状況を把握したい、異常の兆候を見つけたいと思っても、UIの見方がわからなければ運用効率化につながりません。障害対応の初動が遅れるとビジネスへの影響も大きくなります。この記事では、New Relicで観測対象として登録されているデータを効率的に検索する方法について解説します。   エンティティとは New Relicでは、 アプリケーション、ホスト、データベース、コンテナなどの観測対象となるリソースやコンポーネントを”エンティティ” と呼びます。一意のID(entityGuid)によって識別されるデータや、New Relicがアクセス可能なリソースを指します。UI上で”entity”という表記があれば、New Relicが管理・観測しているリソースやコンポーネントの対象を意味すると理解しておけばよいですね。   New Relicエンティティの詳細 | New Relic Documentation The definition of 'entity' at New Relic, and how to use and organize entities. docs.newrelic.com   システムの健全性の見方を効率化させるUI機能 一元管理されたエンティティをわかりやすく表示するため、New RelicはUI機能が充実しています。用途に応じて使う機能は異なるため、この記事では代表的な画面の見方を解説します。 エンティティエクスプローラー New Relicが対象のアカウントで観測するすべてのリソースを集約し、問題の特定やパフォーマンス分析するための中心的な画面 になります。All Entitiesをクリック後に、リスト形式でエンティティが表示されています。何が観測対象として登録されているか、どこのエンティティに問題があるかをすばやく把握するための始点になります。 この画面で以下のようなことができます。 ・すべてのエンティティを一覧表示    アプリケーション、ホスト、コンテナなどをカテゴリ別に表示 ・問題のあるエンティティを強調表示    パフォーマンス異常やアラート状態のエンティティを赤色で表示    Activity streamでシステム内で発生したイベントをリアルタイムで表示 ・フィルタリングと検索機能    虫眼鏡マークの横からタグや属性で絞り込み、対象エンティティだけを表示   Navigator New Relicの観測対象全体の健全性をハニカム表示で確認する画面 です。大量のエンティティを色によって状態確認できるように設計されていますので、 視覚的にどこのエンティティに問題があるかがすぐに分かります 。この画面は右上のListのとなりに表示されているNavigatorからアクセスできます。 色 意味 緑 正常状態。問題なし。 黄色 警告状態。注意が必要。 赤 重大状態。即時対応が必要。 グレー データ未取得、エージェント非アクティブ、アラート未設定のいずれかの状態。   ハニカムアイコンで何のエンティティかわからない場合は、Include dataのピッカーをオンにすることで、ハニカム内にエンティティ情報が表示されます。また、「Show only alerting entities」のピッカーをオンにすることで、アラートが起きているエンティティのみに表示を絞ることができます。   Lookout 最近の異常な変化の大きさを色付きの円にて視覚化する画面 です。過去1時間の平均と直近5分間のデータを比較し、通常の動作から逸脱しているエンティティを視覚的に表示します。円のサイズで変化の規模を表し、色で変化の方向(増加・減少)を示しています。 アラートの閾値に達する前に過去1時間前と直近5分間のデータを比較するため、リソースの急激な変化の予兆を察知 することができます。この画面は右上のNavigatorのとなりに表示されているLookoutからアクセスできます。 画面 説明 【 Filter by rate of deviation 】 変化率のしきい値でフィルタリングします。スライダーを左から右に寄せると大きな変化だけを表示させます。 【 Hide non-deviating entities 】 変化していないエンティティを非表示する場合に選択します。     【 Enable square view 】 円ではなく四角い場合に選択します。   【 Size by volume 】 どのエンティティが影響度が大きいかを確認したい場合に選択します。   【 Color settings 】  5種類のカラーセットから色を選択することができます。   New Relicエンティティエクスプローラー、Lookout、Navigatorを使用して、システムを把握 | New Relic Documentation Use the New Relic entity explorer, and New Relic Lookout and Navigator, to see all your monitored entities in one place ... docs.newrelic.com   エンティティ間の視覚化:Service map フロントエンドからバックエンドまでのアーキテクチャ全体を視覚化し、システムを構成するアプリケーション、データベース、ホスト、外部サービスなどの相互関係を動的に表示します。Webサイトやアプリの表側(フロントエンド)から裏側(バックエンド)まで、どんな部品がつながっているかを地図のように示すため、対象のエンティティがどこでつながっているのか、どのエンティティにも影響があるのかを一目でわかることができます。   サービス マップ: エンティティを視覚化する | New Relic Documentation New Relic's service maps are visual, customizable representations of your application architecture. docs.newrelic.com   データの整理と検索を効率化させるタグ機能 New Relicのコンソールには、エンティティから集約された多様なデータが表示されます。そのため、データを整理・検索・分析するうえで、タグ付けは運用を効率化する重要な手段となります。どのようなシーンで効力を発揮するのか、タグのつけ方や検索の仕方について、解説していきます。 タグの利用シーン タグを使用する場面の一例を表にまとめました。タグを使用することで、対象のエンティティを早くフィルタできることや、タグベースで対象のエンティティのメトリクス集計などができるようになります。命名規則がなければ、管理が複雑になりますので、タグを設定する場合のルールは決めておく必要があります。タグはキーと値のペア(key:value)で構成されます。 利用シーン タグ例(key:value) 目的・メリット 環境の識別 env:production, env:staging 本番・開発・テスト環境を簡単にフィルタリング サービス分類 service:payment, service:api 複数サービスを検索しやすくする チーム・担当者管理 team:backend, team:frontend 担当チームごとに整理 コスト分析 billing:infra, billing:app 担当ごとのリソース利用状況を把握し、コスト最適化 アラートポリシー設定 alert:ignore, alert:disabled アラート対象の通知、非通知を判別   自動的に付与されるタグ New Relicにはエンティティに自動的に付与されるタグがあります。これらのタグは削除することはできません。例として以下があります。 カテゴリ タグ名(key) 説明 アカウント関連 account New Relicアカウント名   accountId New RelicアカウントID エージェント関連 agentName New Relicエージェント名   agentVersion New Relicエージェントバージョン アプリケーション関連 language アプリケーションの言語   appName APMで設定されたアプリケーション名 ホスト関連 host ホスト名   hostname OSレベルのホスト名 クラウド関連 availabilityzone,InstanceId,instanceType等 アベイラビリティゾーン、インスタンスID、インスタンスタイプ等   タグのつけ方 タグのつけ方はNew Relicコンソールからタグを付ける方法とデータ送信時にタグを付ける方法の2つのパターンを解説します。タグを一つずつ付与するには大変な量になっている場合は、自動化でタグをつけることも可能ですが、別の記事にて紹介します。 タグは、1つのエンティティ(サーバー、アプリ、コンテナなど)につき最大100個まで設定できます。文字数の上限は、キーが128文字、値が256文字で、いずれも日本語は使用できません。 タグを使用すると、データの整理と検索に役立ちます | New Relic Documentation How to use tags to improve organization and findability of your observability data. docs.newrelic.com   New Relic コンソールからタグを付ける方法 New Relic コンソールからタグを付ける方法は、以下の画面以外にもあります。一例として解説します。タグ付け後、タグを使って検索したい場合、反映に数分程度がかかることがあります。 1.All entitiesからタグを付けたいエンティティ名をクリックします。 2.上部の「Tags」をクリックし、key:value形式で記入後、Enterを押します。 3.タグが付与されていることを確認します。デフォルトのタグは削除できませんが、任意で追加したタグは、タグの横のxにて削除できます。   データ送信時にタグを付ける方法 エージェント側の設定ファイルにタグ情報記載する必要があります。タグを追加した時点以降のデータにはタグが反映されますので、 後付けで転送するログに対してタグを付けた場合は、過去分には反映されません。 以下は、Infrastructure エージェントを導入したホストに対してタグを付ける方法になります。 記載場所:/etc/newrelic-infra/logging.d/logging.yml custom_attributes: environment: production team : infra ・・・・   タグを用いた検索の仕方 タグを使った代表的な検索方法について解説します。主にNRQL(New Relic Query Language)と呼ばれるNew Relic独自の言語を用いてデータを検索・分析に効果を発揮します。NRQLの説明については以下の記事をご参照ください。 【New Relic】データを自在に分析するNRQLの使い方 New Relicで柔軟にデータを分析したいけれど、分析方法に迷う方も多いのではないでしょうか。本記事では、New Relicで収集したデータの分析手法を解説します。 blog.usize-tech.com 2026.01.07 画面 説明 【UIフィルタ】 特定のエンティティ群のみを抽出したい場合に有効 【NRQL】 高度な検索やダッシュボード、アラートをカスタマイズして作成する際に使用 【Logs】 大量のログから特定のタグが付いたログを抽出する際に有効   workloadを使ったエンティティのグループ化 関連するエンティティをグループ化し、サービスやチーム単位で観測するエンティティを集約 することで、問題の特定を効率化します。チームが管理するエンティティ毎にグループ化することで、定常的な健全性の確認や障害発生時に誰がどのシステムを対応しなければならないかを迅速に把握することができます。その結果、対応時間を短縮し、チーム間の連携につながります。 workloadの作り方 1.All Capabilitiesをクリックし、検索ボックスに「workloads」と入力した結果から「Workloads」をクリックします。左メニューに固定化して表示させる場合は、画鋲のマークをクリックすることで、有効になります。 2. 「Create a workload」をクリックします。   3.グループ名にあたる「Give it a name」を入力し、対象とするエンティティを「+Add」します。完了後、「Create a workload」をクリックします。 4.対象のエンティティが集約されて表示されていれば完了です。   ワークロードの作成と定義 | New Relic Documentation In New Relic, create a workload, which helps you group together monitored entities that are related. docs.newrelic.com   workloadの見方 ワークロードでどのような使い方ができるのか、画面ごとに説明します。 画面 説明 【Summary】 ワークロードに登録されているエンティティのステータス状態が表示。全体の健全性を確認したい場合に利用。 【Errors】 ワークロードに登録されているエンティティのエラー状態が表示。どのサービスでエラーが多発しているかを確認したい場合に利用。 【Activity】 システムの変更やデプロイによってレスポンスタイムやスループットに異常があるかを確認したい場合に利用。 【Map】 エンティティ間の依存関係を可視化し、障害が起きた際に、他のサーバにも影響があるかを確認したい場合に利用。 【Change tracking】 コミット情報を紐づけし、特定のコード変更がパフォーマンスやエラーに影響があるかを確認したい場合に利用。   ワークロード UI | New Relic Documentation In New Relic, use workloads to group together entities that make up a specific business service, making it easier to iso... docs.newrelic.com   さいごに この記事では、New Relicで登録されているエンティティの健全性を確認する方法や、タグ機能を活用した効率的な管理手法について解説しました。エンティティの数が増えると、視認性が低下し、予兆検知や障害対応のスピードが遅れるリスクがあります。UI機能やタグを駆使することで、迅速に問題を特定し、運用効率を高めることが可能です。 New Relicにはアラート設定、NRQLクエリ、ダッシュボードなどの高度な機能があり、これらを組み合わせることで、より包括的な観測と分析が実現します。アラートポリシーの設計やNRQLを使ったカスタムクエリの作成方法についても紹介していきますので、今後も参考に頂ければ幸いです。 SCSKはNew Relicのライセンス販売だけではなく、導入から導入後のサポートまで伴走的に導入支援を実施しています。くわしくは以下をご参照のほどよろしくお願いいたします。
アバター
こんにちは! SCSK株式会社 小鴨です。 震えるぞServiceNow!燃え尽きるほどServiceNow! 今日は前回の続きということで 【ServiceNow技術】問題のステータス遷移を制御したい その① ~フローフォーマッター~ 問題管理のステータス遷移について、制御の方法をまとめた記事。 第一版として、問題管理フォーム上に表示される矢羽根の見せ方について解説。 blog.usize-tech.com 2026.01.29 問題モデル についての解説をさせていただきます!! 多くの皆様にとっては釈迦に説法かもしれませんが そういった方はぜひ、コメントにてより高次元の使い方をご教示いただけると幸いです!   問題モデルとは? 問題管理のステータスが遷移しない! 「state」に選択肢を追加し、フローフォーマッターでその値を指定した状態でも 時にはステータス遷移するアクションを起こした際に、赤いバナーで 「 エラーメッセージ 問題モデル「○○○○」では、△△から◆◆ への状況移行が抑制されています」 といったようなエラーメッセージが表示されることがあるのではないでしょうか。 これは「問題モデル」という問題管理のステータスが進むべき道路のようなものが定義されないことにより起きる現象です。 これが問題モデルだ! 「prb_model」というテーブルを開くとデフォルトでは以下のようなレコードが用意されていると思います。 中を覗いてみると、画面下部に各種ステータスが書かれていると思います。 まだよくわからないと思うので一つ開いてみましょう 今回は「評価」を選びます。 また似たような構成になっているので更に片方の「[アセスメント] から [根本原因分析]」を開いてみましょう。 これ以上は下層がないことが分かります。 では画面上部の内容を確認してみましょう「宛先」という欄に「根本原因分析」という値が入っています。 感づいた方が多いと思いますが、これらのレコードはステータス遷移のルールを定義しています。 例えば上の内容は、ステータスが「評価」である場合に「根本原因分析」へ遷移することを許しています。 特定のステータスからステータスへの道路をかけているみたいなイメージですね。 このルールで定義されていないルートを通ろうとすると赤いバナーの注意書きが出てきてしまいます。 注意点として、多くの場合進む方向にのみ問題モデルのルールを作成しがちなのですが 時には承認が却下された場合など、ステータスが戻る場合もあると思います。 そういった場合に備え、必ずすべてのステータス遷移のルートを事前に洗い出しておく必要があることに注意しましょう。 また、これらの設定は自作したステータスにも有効であり 遷移ルールを定義すればOOTBのステータスから新規作成したステータスへの遷移も可能となります。 前回の記事で書いた「フローフォーマッター」と組み合わせ、自分だけのステータス遷移を作ってみましょう。
アバター
こんにちは! SCSK株式会社 小鴨です。 最近はServiceNow以外のことは考えられなくなってきました。 そんな自分ですが今日はITSM機能の備忘録という側面もありつつ フローフォーマッター  についての解説をさせていただきます!! 多くの皆様にとっては釈迦に説法かもしれませんが そういった方はぜひ、コメントにてより高次元の使い方をご教示いただけると幸いです!   フローフォーマッターとは? この矢羽根、編集できないの? 問題管理画面には、常に下の画像のような、6つの矢羽根が表示されていると思います。 OOTBでは下のような並びですが もっとステップを増やしたい ステップ名称を変更したい といったような要望はいくらでも出てくるのではないでしょうか。 とはいえフォームビルダーをいじっても該当箇所の編集はできなそうだし… どうすりゃええのよこれ そこで設定するのが「フローフォーマッター」という機能です。 テーブル名「sys_process_flow」からアクセスし、以下のようなテーブルを表示しましょう。 (コマンド「sys_process_flow.list」) これだけだと何が何やらだと思うので一つ「テーブル」が「問題(problem)」であるレコードで搾ってみます。 すると。。。6つのレコードが表示されました。 「Label」列から名前をよく見てみると、問題レコード画面に表示されていた矢羽根の各名称と一致していませんか? だんだん分かってきたかと思いますのでレコードを開いてみましょう。 以下では各項目の説明をします。 項目名 説明 Table どこのテーブルのレコード画面に矢羽根を表示したいかを示す Name 内部で管理するための名前 ※矢羽根に表示される文言とは違うので注意 Label 矢羽根の中に表示される文字列 Order 矢羽根の順序を示す ※数字が小さいものから左に並ぶ Condition 矢羽根が緑に色塗りされる条件を指定する ※上の画像では「State」が「New」の時という条件が指定されている Description メモ欄 注意点は矢羽根が塗りつぶされるのは条件を満たした結果であり フローフォーマッターを作ることが、問題管理のステータス制御をしているというわけではないということです。 今日の内容はここまでですが まだ矢羽根の増やし方を知っただけで、状態遷移などの本当の意味での制御はまだ実現できていません。 あくまで、現時点では問題管理において自分がどこにいるのかが分かる「地図」を作っただけなのです。 次回の記事では「問題モデル」という概念を説明します。 これは「道路」に近いものであり、各ステータス遷移のルールを定義するものになります。 フローフォーマッターと組み合わせて初めて円滑な問題管理が実現できますので是非ご活用ください。
アバター
CatoクラウドにおけるDHCPの仕様について、アップデートが行われたため解説いたします。 はじめに:DHCPとCatoクラウド DHCPは、ネットワークに接続する機器に対してIPアドレスなどの必要な情報を自動で配布する、非常に多くの環境で利用される機能です。ADサーバやルータ等の機器に搭載されていることが多いものですが、Catoクラウドにおいてルータに相当する役割となるCato Socketにも当然DHCP機能が存在します。 このCatoのDHCP機能、従来はかゆいところに手の届かない仕様だったのですが、近日のアップデートによって使い勝手が向上しました。この記事では、その内容について紹介していきます。 DHCPの機能強化:Site編 まず、Catoと接続された拠点(Site)におけるDHCP機能の強化を解説いたします。 複数のDHCPレンジ指定に対応! DHCPの設定を行う上では、DHCPレンジ、すなわち「どのIPアドレスを配布して良いか」の指定が必須となります。 CatoのSite配下におけるDHCP設定には「1つのサブネットにつき、連続した1つのDHCPレンジしか設定できない」という制約があったのですが、アップデートにより 複数レンジの設定が可能 となりました。 これが何を意味するのか、具体的な例を挙げて確認します。 Cato Socketを配置した拠点の内部ネットワークが、以下のような使われ方をしていたとします。 A拠点:192.168.1.0/24 Cato Socket:192.168.1.1 固定IPの機器(プリンタ、一部PC等)用レンジ:192.168.1.101 – 192.168.1.150 スイッチ類:192.168.1.251 – 253 この場合、「連続した1レンジしか設定できない」という従来の仕様では、DHCPレンジは広く取っても以下のいずれかということになります。 ・192.168.1.2 – 192.168.1.100 ・192.168.1.151 – 192.168.1.250 仮にDHCPでつなぐ機器が100を超えたら、従来の仕様では対応できなくなるわけです。 (※厳密には固定IP用レンジのIPすべてに「Static Host Reservation」を設定すれば対処可能ではあるのですが、少々厳しい対処方法です。) アップデートにより、上記のようなケースでも「2つのレンジを指定する」であっさり対応できるようになりました。IPアドレスの利用範囲が1か所に固まっていないケースは決して珍しくないため、うれしい仕様変更です。 DHCPに高度なセキュリティを!「Microsegmentation」機能 Site内のDHCPには、新たなオプション機能として「Microsegmentation」機能が追加されました。 デフォルトでは無効となっているこの機能を有効にすると、DHCPによってIPアドレスを配布するときに「/32」のセグメントとして配布を行うようになります。 ローカルネットワークにおいて、「同じサブネットであれば、通信はスムーズに通る」場合が大半です。これ自体は別に悪いことではないのですが、悪意のある利用者が存在する場合、同セグメント内の偵察や攻撃は比較的簡単にできてしまう、という構造上の弱点にもなりえてしまいます。 Microsegmentationを有効にすると、DHCPにより配布されたIPを使用する機器は、内部的には/32のセグメントに分割されているため、別の機器と通信する場合には必ずCato Socket、つまりLAN FirewallまたはWAN Firewallを経由することになります。これによって、確実にセキュリティチェックを行うことが可能となるのです。 注意点として、この機能の対象とするIPレンジは、全てCatoによるDHCPの対象レンジとなっている必要があります。上の図であれば、サーバである「192.168.x.a」も含めたDHCPレンジを設定したうえで、サーバには「Static Host Reservation」によってCatoから固定IPの払い出しをする必要があります。 また、LAN FirewallやWAN Firewallによる制御が必ず入る以上、許可設定が適切に行わなれなければ必要な通信もブロックされる恐れがあります。本機能の利用を検討する場合、少しずつテストを行いながら導入範囲を広げることが推奨されます。 決して必須の機能ではありませんが、セキュリティを更に高めたい場合には注目の機能です!   DHCPの機能強化:モバイル編 Cato Clientを用いてモバイル接続によってCatoを利用する場合、CMA上で事前に定義されたIPレンジからIPアドレスが割り振られます。DHCPと銘打たれている機能ではありませんが、類似した性質を持つので本記事でまとめて紹介いたします。 Dynamic IP RangeとStatic IPレンジが複数定義可能に! Cato Client向けに配布されるIPレンジは原則として単一のCIDRとなりますが、 これとは別に「Dynamic IP Range」「Static IP Range」という設定が存在します。 Dynamic IP Rangeは特定のユーザグループに、Static IP Rangeは特定のSDPユーザに、 それぞれ通常のIP配布レンジとは別のIPレンジからIPアドレスを配布することが可能です。 IPアドレスでアクセスを制限するような機器・サービスが存在する環境において、「特定のユーザ(管理者)やグループ(IT部門など)にだけアクセス可能なIPアドレスを配布したい」といった需要に応えられる機能となっています。 Dynamic IP RangeおよびStatic IP Rangeの概要については、 下記の記事もご参照ください。 【Catoクラウド】最新版!モバイルユーザのIPアドレス割り当て方法 – TechHarmony 従来はDynamic IP Range、Static IP Rangeそれぞれ一つずつしか作成できませんでしたが、 アップデートにより複数のレンジを定義可能になりました。 これにより、「複数のグループ会社について、モバイル接続時に会社によって別々のIPレンジを割り振る」といった運用が可能となりました。大きな組織でIPアドレスによる管理を行いたい場合には、ぜひチェックしておきたいアップデートです。   参考:DHCPの設定箇所 2026年1月現在の、DHCP設定を行うためのCMA上の設定箇所を提示します。 Site向けDHCP設定 CMAにログインし、[Network] > [Site]から設定を行いたいSiteを選択します。 Site画面の[Site Configuration] > [Networks]に移動し、 対象のNativeレンジもしくはVLANをクリックします。 開いた設定ウィンドウの「DHCP Type」を「DHCP Range」とすることで、任意の範囲を指定可能です。複数のレンジを指定したい場合は、「Additional DHCP Ranges」から追加していきます。 設定完了後、画面右上の「Save」の実行を忘れないようにしましょう。 モバイル向けIP Allocation設定 モバイルユーザ向けのIPレンジは、[Access] > [IP Allocation Policy]から設定します。 IPレンジの定義は、[Settings]タブで実施します。 Dynamic IP RangeやStatic IP Rangeを定義した場合、それぞれ[Dynamic IP Allocation] [Static IP Allocation]にて適用条件を指定しなければ割り振られることはありません。 複数のルールを設定することが可能ですが、上からチェックして最初に合致したルールだけが適用されるので注意しましょう。   おわりに Catoの他の機能と同じく、DHCP機能も繰り返しアップデートが行われています。 本記事で紹介したアップデートにより、Catoネイティブの機能でのDHCP実装のハードルは大きく下がったように思います。DHCP機能を兼ねたルータをCato Socketに置き換えたい場合など、ぜひ参考にしてみてください。
アバター
こんにちは!SCSKの野口です。 前回のプロローグでは、AP基盤ドキュメントに「必要な情報へたどり着きにくい」という課題があり、RAGで“探すコスト”を下げられないか、という問題意識を共有しました(連載の背景は前回のプロローグ記事をご覧ください) 「その質問、ドキュメントに書いてある」問題を終わらせたい:RAG連載を始めます 社内ナレッジをRAGで活用し、膨大なドキュメントから必要情報を素早く見つける仕組みを目指します。本記事では連載開始の背景と、RAG基礎〜Bedrock実装・アプリ/エージェント構築までの構成を紹介します。 blog.usize-tech.com 2026.01.27 本連載は4シリーズ構成で、今回から始まるシリーズ1では、RAGを実装手順ではなく「構成要素と設計判断」として理解するための基礎を整理します(RAG/チャンキング/評価/ベクトルDB/ハイブリッド検索/課題)。 第1回の本記事では、 RAGの定義、必要性、基本フロー(Indexing / Retrieval / Augmentation / Generation) を俯瞰し、次回以降の議論の土台を作ります。 それでは早速、RAGとは何かから見ていきましょう。 RAGとは RAG(検索拡張生成:Retrieval-Augmented Generation)とは、LLMが回答を生成する直前に、信頼できる外部データソースから関連情報を 検索(Retrieval) し、その結果を コンテキストとして付与(Augmentation) したうえで 回答を生成(Generation) させるアーキテクチャです。これはモデルの重みを更新する「ファインチューニング」とは異なり、推論時に動的なコンテキストを提供する「検索」と「生成」のハイブリッドソリューションとなります。 図解してみると下記のようになります。 要点は、LLMの パラメータに内蔵された知識 だけに依存せず、 推論時に必要な情報を動的に取り込む 点にあります。AWSブログでも、RAGについて下記のように説明されています。 (原文)  It allows LLMs to reference authoritative knowledge bases or internal repositories before generating responses, producing output tailored to specific domains or contexts while providing relevance, accuracy, and efficiency.  (日本語訳) RAGにより、LLMは応答を生成する前に信頼できる知識ベースや内部リポジトリを参照できるようになり、関連性、精度、効率性を維持しながら、特定のドメインやコンテキストに合わせた出力を生成します。 引用元: https://aws.amazon.com/jp/blogs/machine-learning/evaluate-the-reliability-of-retrieval-augmented-generation-applications-using-amazon-bedrock/   なぜRAGが必要か? LLMは非常に汎用的ですが、業務適用で問題になりやすい制約があります。 いくつかの例を挙げてみましょう。 答えがないにも関わらず、虚偽の情報を提示すること ユーザーが最新の応答を期待しているにも関わらず、古い情報を提示する ユーザーが社内規約などの特定の情報に関する応答を期待しているにも関わらず、一般的な情報を提示する 上記の例はつまるところ、下記のような問題が発生しているということです。 ナレッジカットオフ: モデルが学習した時点以降の出来事や、更新された規定・仕様をそのまま反映できない ハルシネーション: 根拠がない内容でも、それらしく断定してしまう 社内固有情報の欠如: 社内情報・手順書・契約・設計資料など、非公開データを参照できない RAGはこれらの課題を解決するための1つのアプローチです。信頼できるドキュメント等をナレッジソースとして保存しておき、LLMへの問い合わせを行う前にこれらのナレッジソースから関連情報を取得します。ユーザーは信頼できるドキュメントから得られた情報に基づいて生成された回答を受け取ることができます。   RAGの基本フロー RAGは大きく4つの工程に分解することができます。 インデックス作成(Indexing) 文書を検索しやすい単位に分割し(チャンキング)、埋め込み(Embeddings)に変換して保存します。 文書の分割粒度(どの程度のチャンクサイズとするか?)、文書構造の扱い(階層構造に意味を持たせるか等)、メタデータ付与など、ここでの設計が後続の検索品質に大きく影響します。 チャンキング手法・Amazon Bedrock Knowledge Basesで利用できるチャンキング戦略などについては別記事で詳しくまとめる予定ですので、そちらを参照いただければ幸いです。 検索(Retrieval) ユーザーの質問(クエリ)も埋め込みに変換し、意味的に近いチャンクを取得します。 このときにどの程度のチャンクを取得するかも回答品質に影響を与えます。単純に多くのチャンクを取得すればよいというわけではありません。取得したチャンクが全てユーザーのクエリに強く関連するものであれば問題ありませんが、そこまで関連性がないチャンクを取得してしまい、ユーザーが求めていた回答が得られない可能性もあります。 そのため、何件のチャンクを取得するかも重要な設計項目となります。 なお、「あえてRAGからの取得時は多くのチャンクを取得しておき、リランキングによって絞り込む」といった設計も可能となります。 こちらの詳細は下記ブログに書かれているので、一度目を通してみてください。 リランキング モデルによる RAG の日本語検索精度の向上 埋め込みモデルの Llama-3.2-NV-EmbedQA-1B-v2 およびリランキング モデルの Llama-3.2-NV-RerankQA-1B-v2 を利用して、日本語検索精度の高い RAG の構築方法を分かり易く解説します。 developer.nvidia.com コンテキスト構築(Augmentation) 取得したチャンクから、重複除去・整形・並べ替えなどを行い、LLMに渡すコンテキストを組み立てます。 生成(Generation) コンテキストと質問(クエリ)に基づき、LLMが回答を生成します。 重要なのは、 回答がコンテキストに接地(Grounding)していること です。 接地(Grounding:グラウンディング) とは、 モデルからの回答がソースに基づいて事実上正確であるか ということです。 詳しくはAmazon Bedrockの下記ユーザーガイドでご確認ください。 コンテキストグラウンディングチェックを使用して、レスポンスのハルシネーションをフィルタリングする - Amazon Bedrock Amazon Bedrock のガードレールは、リファレンスソースとユーザークエリが提供されたとき、モデルレスポンスのハルシネーションを検出してフィルタリングするためのコンテキストグラウンディングチェックに対応しています。サポートされている... docs.aws.amazon.com   RAGと似た概念とその違い RAGと似た概念として、「ファインチューニング」があります。 ファインチューニング :モデルの重み(パラメータ)を更新し、出力スタイル・形式・判断の癖を学習させる RAG :外部知識(ナレッジソース)を検索し、推論時に動的に与えて正確性・最新性・組織固有性を補う 上記からも分かる通り、ファインチューニングには学習させるための計算コストがかかりますが、RAGは外部知識をつなげるだけなので、ファインチューニングよりもコストが低くなります。 IBMの記事では、RAGとファインチューニングの比較を料理人に例えて比較しています。 (RAG) RAGを概念化するために、AIモデルをアマチュアの家庭料理人と想像してみてください。彼らは料理の基礎は知っていますが、特定の料理の訓練を受けたシェフの専門知識(組織独自のデータベース)が欠けています。RAGは、家庭料理人にその料理のレシピ本を提供するようなものです。料理に関する一般的な知識と料理本のレシピを組み合わせることで、家庭料理人は自分の好きな料理に特化した料理を簡単に作ることができます。 (ファインチューニング) もう一度、生成AIモデルを家庭料理人に例えると、ファイン・チューニングは特定の料理を作るためのコースとなります。コースを受講する前に、家庭料理人は料理の基礎について大まかな理解をしておく必要があります。しかし、料理の訓練を受けて分野特有の知識を習得すれば、その種類の料理をもっと上手に作れるようになるでしょう。 引用元: https://www.ibm.com/jp-ja/think/topics/rag-vs-fine-tuning   RAGとファインチューニングの比較表です。 比較項目 RAG ファインチューニング 主な目的 最新知識・情報の補強 回答スタイル・形式の習得 コスト 低い(既存モデルをそのまま活用) 極めて高い(再学習に莫大な計算資源が必要) 情報の更新頻度 リアルタイム(外部データを差し替えるだけ) 遅い(再学習に数日〜数週間かかる) 根拠(出典)の提示 明確に提示可能(引用へのリンクをつけるなど) 困難(モデルの記憶に依存するため) 専門性 特定のドキュメントに強い 専門的な口調や特定形式の出力に強い   RAGで重要な設計論点(どこで品質が決まるか) RAGで難しいのは、LLMの性能ではなく、取り込み・分割・検索・コンテキスト設計など“前段”で品質が大きく変わる点です。特に次の観点はRAGにおいて非常に重要です。 データ取り込み(Parsing / 整形) 表やPDF構造が崩れると、正しい情報が検索に乗りません チャンキング(チャンク化) チャンキングが大きすぎても小さすぎてもだめです。ユースケースに応じて適切なチャンキング戦略を考える必要があります 検索(Retrieval) top-kの取り方(いくつのチャンクを検索するか)、ハイブリッド検索、リランキングで適切な情報を「拾える / 拾えない」が変わります コンテキスト構築 (Augmentation) 重複除去・並び順・引用の付け方で、LLMが参照できる根拠が変わります 生成制御(Generation) 接地(Grounding)と棄却(わからないときは答えない)を設計しないと、もっともらしい誤答(ハルシネーション)が残ります 評価(Evaluation) 改善できているかを定量的に評価しなければ、主観的な評価のみとなってしまいます 次回記事では、上記の「チャンキング(チャンク化)」を取り上げ、チャンク化戦略と選択方法を整理します。   まとめ 本記事では、RAG(検索拡張生成)を「外部データソースを検索し、その結果をコンテキストとして付与して回答を生成する」仕組みとして整理しました。LLM単体では難しい、最新性・正確性・社内固有情報の参照を補ううえで有効なアプローチです。 また、RAGの品質はLLMの性能だけではなく、データ取り込み・チャンキング・検索・コンテキスト構築・生成制御・評価といった設計要素の組み合わせで決まります。 次回は、この中でも影響が大きい 「チャンキング(チャンク化)」 を取り上げ、チャンク化戦略と選択方法を整理します。 次回もぜひご覧ください。
アバター
こんにちは!SCSKの野口です。 早速ですが皆さんに質問です。 「業務でRAGを活用していますか?」 本記事は、これからTechHarmoneyでRAGに関する記事をシリーズとして執筆していくにあたり、 なぜ書こうと思ったのか 、 そして 今後どのようなテーマを扱う予定か を最初に整理する”プロローグ”です。 背景:ドキュメントはあるのに、探すのが難しい 私は普段、アプリケーション基盤(AP基盤)チームに所属しており、業務チームから基盤部品に関する質問を受けることがあります。 AP基盤部品は部品の提供だけでなく、方式書や開発ガイドも公開しており、業務チーム側でも参照できる状態です。 それでも、開発ガイドに書いてある内容であるにも関わらず、次のような質問を受けることが少なくありません。 「この部品の使い方は?」 「この部品のデフォルト設定値は?」 「急に動かなくなった」 「質問の前にドキュメントを確認してほしい」という気持ちがある一方で、 1つあたり何十~何百ページの資料が複数ある中から、必要箇所をピンポイントで探すのは大変 という事情も理解できます。私自身、配属後の研修中は同じように苦労した記憶があります。 つまり問題は、「ドキュメントがない」ではなく、” 必要なときに、必要な情報にたどり着きにくい ”にあります。   きっかけ:AP基盤ドキュメントをRAGで提供できないか この課題に対して、AP基盤チーム内で下記の議論を行いました。 “生成AI”を活用し、 質問から関連箇所を検索して提示 できれば、問い合わせの往復が減る 回答に根拠(引用元資料の章・節)を添えられれば、 再現性のあるナレッジ共有 になる 業務チームの自己解決率が上がれば、AP基盤チームの支援が”説明”から”改善”に寄る そこで、 AP基盤部品のドキュメントをRAGで提供しよう! となったわけです。 本連載は、その取組を進めるうえでの個人的な学習も兼ねて、RAGの理解と実装・運用の勘所を整理していくものです。   本連載で目指すこと 本連載を通じて狙っているのは、次の3点です。 社内ドキュメントの”検索体験”を改善するための考え方を整理する RAGの設計要素(チャンキング、評価、検索方式など)を分解し、 どこで精度が落ちるか / 何を改善すべきか の共通認識を作る 最終的に、Amazon Bedrock等を用いた構成で、 再利用可能な形の RAGアプリ / RAGエージェント  へ展開する   今後のシリーズ 記事は大きく4シリーズを予定しています。加えて、シリーズとは別枠でTips記事も各予定です。 シリーズ1:RAGに関する基本的知識 まずは、RAGの構成要素と設計判断として理解するための土台を作ります。 RAGとは チャンキング(チャンク化)とは RAGの評価方法 ベクトルデータベースについて ハイブリッド検索について RAGの課題 (シリーズ1:RAGの基本情報 / 第1回)RAGとは:全体像、なぜ必要か、基本フローと設計の勘所 RAG(検索拡張生成)の定義、なぜ必要か、基本フロー(Indexing/検索/補強/生成)を整理します。 blog.usize-tech.com 2026.01.27 シリーズ2:Tips(Amazon Knowledge Bases中心を予定) 「公式機能を理解して試す」「構築の手間を減らす」等を主眼に置き、検証記事をまとめる予定です。 Amazon Knowledge Basesで利用できるチャンク化戦略をすべて試してみる Amazon Knowledge Basesのコンソールで簡単にKnowledge Base作成(S3 Vectors) MCPサーバー経由でKB呼び出し ※上記は現時点(2026/1/24)での案です。追加検証は随時こちらにも反映していきます。 シリーズ3:RAGアプリケーション構築 + AWSデプロイ 構築対象を明確にし、実用を意識したアプリケーションを組み上げます。 構築していく予定のRAGアプリケーションについての説明 アプリケーション全体アーキテクチャ図についての説明 RAGアプリ構築(FastAPI編) RAGアプリ構築(LibreChat編) インフラ構築 シリーズ4:RAGエージェント構築 Strands Agents + Amazon Bedrock AgentCore + Amazon Bedrock Knowledge Basesを利用したRAGエージェント構築を予定しています。 こちらの詳細については現時点でまだ詰め切れていないので、決まり次第更新します。   シリーズ記事とは別に:Tipsも随時まとめます シリーズは体系立てて理解することを目的としていますが、実際の構築では「細かい詰まりどころ」が出てくると思います。 そのため、シリーズとは別に、RAGやAWS上でRAG環境を構築する際のTips(設定の落とし穴、検証観点、運用メモなど)も随時まとめる予定です。   まとめ 本記事では、AP基盤ドキュメントを扱う中で感じた「必要な情報にたどり着きにくい」という課題を出発点に、RAGを活用して“探すコスト”を下げられないか、という問題意識と、連載として整理していく方針を共有しました。 この連載では、まずシリーズ1でRAGの基本要素(チャンキング、評価、ベクトルDB、検索方式、課題)を分解し、 どこが品質を決めるのか を押さえます。その上でシリーズ2〜4で、Amazon Bedrock Knowledge Basesを中心に、検証・構築・デプロイ・エージェント化へと段階的に進めていく予定です。 次回からは、シリーズ1の第1回として、 「RAGとは」 をテーマに、RAGの定義、なぜ必要か、基本フローを整理していきます。続きもぜひご覧ください。 (シリーズ1:RAGの基本情報 / 第1回)RAGとは:全体像、なぜ必要か、基本フローと設計の勘所 RAG(検索拡張生成)の定義、なぜ必要か、基本フロー(Indexing/検索/補強/生成)を整理します。 blog.usize-tech.com 2026.01.27
アバター
LifeKeeperの『困った』を『できた!』に変える!サポート事例から学ぶトラブルシューティング&再発防止策 こんにちは、SCSKの前田です。 いつも TechHarmony をご覧いただきありがとうございます。 システムを長く安定して運用する上で、避けて通れないのが「OSのアップデート」や「セキュリティパッチの適用」です。「脆弱性が見つかったので、カーネルの更新をお願いします」といったタスクは、インフラエンジニアにとって日常茶飯事かもしれません。 しかし、HAクラスターシステム、特にデータをリアルタイムで保護するDataKeeper環境において、この「いつものアップデート」が思わぬトラブルの引き金になることがあります。「OSのメジャーバージョンは変わらないから大丈夫だろう」と高を括っていたら、 メンテナンス当日にリソースが起動せず 、顔面蒼白に…なんて事態は絶対に避けたいですよね。 本連載企画「LifeKeeper の『困った』を『できた!』に変える!サポート事例から学ぶトラブルシューティング&再発防止策」では、実際にサポートセンターに寄せられた「生の事例」を紐解き、安定運用のための知恵を共有していきます。 今回からは、多くの運用担当者が直面する「OSやLifeKeeper本体のバージョンアップ」に伴うトラブルにフォーカスを当てていきます。 その第一弾となる今回は、最も見落とされがちな「OSカーネルの更新」について。「OSのバージョン数値は変わっていないのに動かない!?」というミステリーの真相と、確実に成功させるための回避策について解説します。 はじめに:そのアップデート、「OSバージョン」だけ見ていませんか? 今回の記事のテーマは、ズバリ「OSのカーネルアップデート」です。 一般的に、OSのメジャーバージョンアップ(例:RHEL 8から9への移行)を行う際は、アプリケーションへの影響調査や入念な検証計画が立てられます。一方で、マイナーバージョン内でのカーネル更新や、パッケージのセキュリティパッチ適用( dnf update )は、比較的軽い気持ちで、あるいは自動的に実施されているケースも少なくありません。 しかし、LifeKeeper、とりわけデータをリアルタイムで複製する「DataKeeper」をご利用の環境において、この「軽微なアップデート」という認識は禁物です。なぜなら、DataKeeperは単なるアプリケーションではなく、OSのカーネルモジュールとして動作しており、 「OSのリリース番号(8.1など)」よりも「カーネルのバージョン(4.18.0-xxxなど)」に対して 非常に敏感に反応する からです。 本記事では、実際に発生した「OSのバージョン表記は変わっていないのに、LifeKeeperが起動しなくなった」という事例を通して、以下のポイントを解説します。 カーネル更新がLifeKeeperに与える影響のメカニズム サポートマトリクスの「注釈」に隠された重要な条件 トラブルを未然に防ぐための正しい確認プロセス 「手順通りやったはずなのに動かない…」と頭を抱える前に、ぜひ押さえておきたい勘所を整理しました。 その他の連載企画は以下のリンクからどうぞ! 【リソース起動・フェイルオーバー失敗の深層 #1】EC2リソースが起動しない!クラウド連携の盲点とデバッグ術 – TechHarmony 【リソース起動・フェイルオーバー失敗の深層 #2】ファイルシステムの思わぬ落とし穴:エラーコードから原因を読み解く – TechHarmony 【リソース起動・フェイルオーバー失敗の深層 #3】設定ミス・通信障害・バージョン違いの深層と再発防止策 – TechHarmony 実録!「困った」事例:事前確認は「OK」だったのに… 今回は、単なるエラー事例ではありません。運用担当者が「事前にベンダーへ確認し、お墨付きをもらっていた」にも関わらず発生してしまった、少し根が深いトラブルの事例です。 事象の概要:慎重に進めたはずのアップデート ある運用中のシステム(RHEL 8.1 / LifeKeeper v9.5.1)にて、セキュリティ要件を満たすため、OSの「カーネルとファームウェアのみ」をRHEL 8.3相当へアップデートすることになりました。 運用担当者は非常に慎重でした。作業前にベンダー(サポート)に対し、「RHEL 8.3へアップデートするが、LifeKeeperの動作に問題はないか?」と問い合わせを行い、「LifeKeeperの更新インストールを行えば問題ない」という回答を得ていました。 「これで準備は万端だ」 そう確信して臨んだ作業当日。カーネル更新とLifeKeeperの更新インストールを完了させ、いざサービスを起動しようとすると… 「DataReplication(データレプリケーション)リソースの開始に失敗しました」 発生時の状況:深まる謎と焦り ログを確認すると、データ同期に必要なミラーリングデバイスの作成部分でエラーが出ていました。 すぐにサポートへ問い合わせましたが、事態はすぐには収束しませんでした。 サポート側:  「RHEL 8.3へのアップデートであれば、通常はこの手順で動くはずです」 現場:  「手順通りやりました。でも動きません。OSのリリースファイル( /etc/redhat-release )は 8.1 のままですが、これが悪いのでしょうか?」 サポート側:  「8.1…? 8.3に上げたのではなかったのですか?」 実はここに、 「ボタンの掛け違い」 が潜んでいました。 原因究明のプロセス:言葉の定義の違い 何度かのやり取りの末、ようやく互いの認識のズレと、技術的な根本原因が判明しました。 「OSアップデート」の解釈違い 運用担当者 は、「カーネルとファームウェアを8.3相当にする」ことを指して「RHEL 8.3へのアップデート」と伝えていました。 サポート担当者 は、それを「OS全体(マイナーバージョン)をRHEL 8.3へ移行する」と受け取り、標準的な8.3用の手順を案内していました。 インストーラーの誤認 現場のOS環境は「見た目は8.1(リリースファイル等の表記)、中身は8.3(カーネル)」という特殊な状態でした。 LifeKeeperのインストーラーは「見た目(8.1)」を信じて、RHEL 8.1用の標準モジュールをインストールしていました。しかし、実際に動いているカーネルは8.3相当だったため、ドライバが噛み合わず起動に失敗していたのです。 判明した根本原因 最終的な技術的原因は、LifeKeeperの サポートマトリクスの「注釈(Notes)」 にありました。 RHEL 8.3相当のカーネルを使用する場合、標準のインストーラーに含まれるモジュールではなく、 「特定の修正パッチ(HADRモジュール)」を手動で適用する必要があった のです。 「OSは8.1だから」という安心感と、「事前に8.3で確認したから」という確信の狭間で、 「現在のカーネルバージョンに合致したパッチが必要」 という極めてピンポイントな要件が見落とされてしまった事例でした。 「再発させない!」ための対応策と学び 今回の事例は、最終的にサポートから提供された「当該カーネル専用の修正パッチ(HADRモジュール)」を適用し、不要な標準パッケージを削除することで解決に至りました。 しかし、ここで得られた学びは「パッチを当てれば直る」という技術的なことだけではありません。 今後、同様の「迷宮入り」を防ぐために、私たちが実践すべき防止策を整理しました。 1. サポートへの問い合わせは「カーネルバージョン」で語る 今回の最大の教訓は、 「OSのバージョン名(RHEL 8.3など)」だけで会話をしない ということです。 特にDataKeeperのようなカーネル依存の製品に関する問い合わせでは、以下の情報をセットで伝えることが、正確な回答を引き出す鍵となります。 現在のOS/カーネル:   uname -r  の結果(例: 4.18.0-147…) 更新予定のカーネル:  アップデート後に適用される具体的なバージョン数値(例: 4.18.0-240…) アップデートの手法:  「OS全体のマイナーバージョンアップ」なのか、「カーネルのみの個別更新」なのか 「RHEL 8.3相当にします」と伝えるよりも、「カーネルを 4.18.0-240 に上げます」と伝えていれば、サポート担当者も「そのカーネルバージョンなら、この注釈のパッチが必要です」と即座に案内できたかもしれません。 2. サポートマトリクスは「注釈」こそが本体 対応OS一覧表(サポートマトリクス)を見る際、どうしても「RHEL 8.3 … ○」という記号に目が行きがちです。しかし、トラブルの種は表の外側に書かれた小さな文字、 「注釈(Notes)」 や 「既知の問題(Known Issues)」 に潜んでいます。 「特定の手順に従う必要があります」 「追加のモジュールが必要です」 こうした記述を見つけたら、それは「ただの推奨事項」ではなく「必須要件」であると捉えてください。 3. 【保存版】アップデート前の確認チェックリスト 最後に、作業前の確認漏れを防ぐためのチェックリストをまとめました。 ■カーネルアップデート前の確認チェックリスト [  ] アップデート後の「カーネルバージョン」を特定しましたか? dnf check-update kernel 等で、適用されるバージョン数値(例: 4.18.0-xxx)を確認しましょう。 [  ] サポートマトリクスの「注釈」まで確認しましたか? 対象のOSバージョンに「※」や「Note」が付いていないか、欄外までスクロールして確認しましょう。 [  ] 「OSの更新方法」をベンダー/サポートへ正確に伝えましたか? 「カーネルのみ更新」「OSバージョンは維持」といった特殊な要件がある場合は、必ず背景として伝えましょう。 [  ] 作業前のバックアップ(lkbackup)は取得しましたか? 万が一の切り戻し手順も確立しておきましょう。 まとめ:DataKeeperは「カーネルの一部」と心得る 今回の事例を通じて、私たちが得た最大の教訓は、 「OSのアップデート」という言葉の裏にあるリスクの大きさ でした。 セキュリティ対策や機能要件でOSの更新は避けられませんが、DataKeeperを利用している環境において、それは単なるアプリの再起動では済みません。「OSの見た目(リリースバージョン)」が変わらなくても、「中身(カーネル)」が変われば、DataKeeperにとっては全く別の環境になり得るのです。 サポートマトリクスは、ただの「対応表」ではありません。安全に目的地へたどり着くための「地図」であり、そこに書かれた小さな「注釈」は、崖崩れや落とし穴を避けるための重要な道標です。 そして何より、 「正確な情報をサポートへ伝えること」 。これが、トラブルの迷宮から最短で脱出するための命綱となります。「カーネルバージョン」という共通言語を使って、ベンダーと認識を合わせることから始めてみてください。 日々の運用の中で、ふと「これ、バージョン上げても大丈夫かな?」と思った時、この記事のチェックリストが皆様の助けになれば幸いです。 次回予告 さて、今回の「OS周りのアップデート」に続き、次回はLifeKeeperそのもののバージョンアップに焦点を当てます。 「LifeKeeperを最新版に上げたいけれど、手順書通りにやってエラーが出たらどうしよう…」 「かなり古いバージョンからのジャンプアップ、本当に大丈夫?」 そんな不安をお持ちの方、必見です。次回は、「LifeKeeperバージョンアップ失敗事例と成功へのロードマップ」と題し、実際のバージョンアップ作業で発生したトラブル事例や、意外なハマりポイント、そして安全確実に移行するためのステップを解説します。 更新インストール時に出る「謎のエラーメッセージ」の正体とは? バージョンをまたぐ更新で注意すべき「廃止機能」や「仕様変更」 転ばぬ先の杖として役立つ情報をお届けしますので、ぜひお楽しみに! 詳しい内容をお知りになりたいかたは、以下のバナーからSCSK LifeKeeper公式サイトまで
アバター
こんにちは。SCSKの北川です。 今回はServiceNowでバージョンの異なるナレッジ記事を比較する方法をご紹介します。 前回の記事はこちら 【ServiceNow】ナレッジの活用② ナレッジフロー – TechHarmony 本記事は執筆時点(2026年1月)の情報です。最新の情報は製品ドキュメントを参考にしてください。 手順は以下の通りです。 ①ワークスペースからナレッジ記事を選択します。 ②画面右上の[Edit]を押下します。 ③[Related records]内の[Article Versions]を選択します。 ④比較したいバージョンをチェック後、画面右上の[Compare]を押下します。    ⑤変更箇所が色付けされて表示されます。 まとめ 今回はバージョンの異なるナレッジ記事を比較する方法をご紹介しました。 ワークスペースから操作することによって記事のどこに変更が加えられたのかが分かりやすく表示されます。 ぜひ活用してみてください!
アバター