TECH PLAY

サイオステクノロジー(Tech.Lab)

サイオステクノロジー(Tech.Lab) の技術ブログ

610

こんにちは! 今月も「OSSのサポートエンジニアが気になった!OSSの最新ニュース」をお届けします。 アカマイ・テクノロジーズは、kernel.org にホスティングおよびインフラストラクチャサービスを提供する複数年契約を締結しました。 アカマイ、Linuxの開発を強化するためkernel.orgのホスティングを担当へ https://jp.investing.com/news/company-news/article-93CH-1059635 PC の各コンポーネントに高負荷をかけ、動作状況を確認できるユーティリティ「OCCT」の Linux 版がリリースされました。 システム負荷計測ユーティリティ「OCCT」にLinux版 – 無料で利用可能 https://www.mapion.co.jp/news/column/cobs2901203-1-all/ 「ChatGPT」ではない「ChatGTP」というアプリが、App Store における無料アプリ総合ランキングで上位になっています。 要注意? 「ChatGTP」がApp Storeのランキング上位に AI版「gmeil」か https://www.itmedia.co.jp/aiplus/articles/2504/21/news098.html ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【2025年4月】OSSサポートエンジニアが気になった!OSS最新ニュース first appeared on SIOS Tech. Lab .
今号では、前回紹介しきれなかったファイルのパーミッションについて、もう少し深堀りして見ていきます!<br/ > パーミッションの変更方法 ファイルやディレクトリのパーミッションは、 chmod コマンドで変更することができます。 chmod コマンドでは、 読み取り・書き込み・実行 の権限を、 Owner (所有者)・グループ・他のユーザ に対して設定できます。 パーミッションの指定方法には 2種類あり、 記号 (アルファベット) もしくは 数値 (8進数) で指定することができます。 ①記号で指定する場合 各権限を、下記のようにあらわします。 読み取り:r 書き込み:w 実行:x ユーザの種類を、下記のようにあらわします。 Owner:u グループ:g その他のユーザ:o 全員 (u + g + o):a さらに、 権限を付与する場合は +、権限を削除する場合は -、権限を完全に指定する場合は = を使用します。 ■ 例1:Owner (u) に実行 (x) 権限を付与 ( u+x ) $ chmod u+x test.txt ■ 例2:グループ (g) とその他のユーザ (o) から書き込み (w) 権限を削除 ( go-w ) $ chmod go-w test.txt ■ 例3:全員 (a) に読み取り (r) 権限のみを付与 ( a=r ) $ chmod a=r test.txt ②数値で指定する場合 各権限を、下記のようにあらわします。 読み取り:4 書き込み:2 実行:1 ■ 例4:Owner に読み取り・書き込み・実行権限を付与、グループとその他のユーザには読み取り・実行権限を付与 ( chmod 755 ) $ chmod 755 test.txt Owner (所有者):読み取り・書き込み・実行 (4 + 2 + 1 = 7) グループ:読み取り・実行 (4 + 1 = 5) 他のユーザ:読み取り・実行 (4 + 1 = 5) ■ 例5:Owner に読み取り・書き込み権限を付与、グループとその他のユーザには読み取り権限のみ付与 ( chmod 644 ) $ chmod 644 test.txt $ ls -l test.txt -rw-r--r--. 1 ykaino ykaino-group 0 Mar 24 12:00 test.txt Owner (所有者):読み取り・書き込み (4 + 2 = 6) グループ:読み取りのみ (4) 他のユーザ:読み取りのみ (4) のように、それぞれ権限が付与されます。 特殊なパーミッション 上記でご紹介した 読み取り (r)・書き込み (w)・実行 (x) に加え、特定の要件がある場合に使用する「特別な権限」について説明します。 SetUID (s):実行時「実行したユーザ」ではなく、「所有者の権限」で動作する SetGID (s):実行時「グループの権限」で動作する。ディレクトリの場合、中に作成されるファイルのグループが親ディレクトリと同じになる Sticky Bit (t):ディレクトリに指定すると、所有者以外は中のファイルを削除できないようになる ■ SetUID の使用例 ユーザが自分の権限ではできない操作を、一時的に「所有者の権限」で実行できるようになります。 例えば、パスワードの変更 (passwd コマンド) は、実行時 /etc/shadow を変更する必要がありますが、この操作は root しかできないため、passwd コマンド (/usr/bin/passwd) に SetUID を設定することで可能にしています。 下記の様に、Owner の実行権限が s になっています。 $ ls -l /usr/bin/passwd -rwsr-xr-x. 1 root root 33544 Dec 13 2019 /usr/bin/passwd ■ SetGID の使用例 ディレクトリに設定すると、中に誰がファイルを作成してもすべて親ディレクトリのグループが設定されます。 例えば、特定のディレクトリ配下をチームの共有ディレクトリとする場合に便利です。 下記の様に、グループの実行権限が s になっています。 $ chmod g+s share_directory/ $ ls -ld share_directory/ drwxrwsr-x. 2 ykaino ykaino 6 Apr 13 20:09 share_directory/ ■ Sticky Bit の使用例 他のユーザがアクセス可能なファイルやディレクトリを、誤って削除しないようにするために使用します。 例えば、/tmp ディレクトリでは誰でもファイルを作成できますが、所有者しか削除できないようになっています。 下記の様に、その他のユーザの実行権限が t になっています。 $ ls -ld /tmp drwxrwxrwt. 8 root root 172 Apr 13 20:05 /tmp ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 知っておくとちょっと便利!ファイルのパーミッションについて2 first appeared on SIOS Tech. Lab .
概要 前回は、OCP-VirtでMultus CNIを用いてVMに複数NICを付与する方法についてご紹介しました。 今回は、vSphereからVMのマイグレーションの概要について記載します。 前回の記事は こちら 今までに紹介したOpenShift Virtualization, SUSE Virtualization には、他のプラットフォームのVMを移行することができる移行ツールを提供しています。 今までの概要ブログでも簡単に触れていましたが、本記事でそれぞれのツールの概要と特徴について解説していきます。 OCP-Virt のマイグレーション マイグレーション概要 OCP-Virt ではVM移行のツールとして Migration Toolkit for Virtualization (MTV) が提供されています。 MTVは、様々なプラットフォームで稼働するVMをOCP-Virt上に移行できるようになっています。 画像1:OpenShift Webコンソール マイグレーション画面 MTV Operator として提供される形になり、オペレーターをインストール後Webコンソールに専用のダッシュボードが追加されます。CLIからも利用出来るようになっています。 移行元に選択できるプラットフォームは以下となります。 VMware vSphere Red Hat Virtualization (RHV) OpenStack VMware vSphere によって作成された Open Virtual Appliances (OVA) 他環境のOCP-Virt マイグレーションツールの利用 前提条件 vSphere環境からの移行の主な前提条件を記載します。 ネットワークの前提条件 の通信要件を満たすこと 互換性のあるバージョン のvSphereを使用していること vSphereユーザーに少なくとも 最小限のVMware権限 を持つこと VMware Tools が移行元のVMにインストールされていること 移行元のVMのOSが、 OCP-VirtでサポートするゲストOS および virt-v2vでのKVMへの変換 に対して認定およびサポートされていること Warmマイグレーションの実行には、VMおよびVMディスクで 変更ブロックのトラッキング(CBT) の有効化をしていること ESXiホストから同時に10台を超えるVMを移行する場合は、ESXiホストのNFCサービスメモリを追加していること その他、詳細の要件は参考リンクを参照して下さい。 第3章 前提条件 VMの移行 VMの移行は以下のようなフローで実施されます。 移行元のプラットフォームの情報を登録 vCenterまたはESXiのエンドポイントURLと認証情報を登録します VDDKイメージを作成していれば、イメージのパスの指定をします 移行プランの作成 移行元のプラットフォーム(vSphere)の選択と、対象のVMを選択します 移行元と移行先のネットワークとストレージをマッピングします 移行タイプ(Cold/Warm)を選択します 移行前後に自動実行する処理の指定します 移行プランの実行 移行完了の確認 実行した移行プランのステータスで移行完了を確認します VDDKイメージの作成 VDDKは、VMwareのVMのディスクにアクセスして操作したりするためのSDKです。 MTVでは、移行速度の高速化のために事前にVDDK(VMware Virtual Disk Development Kit (SDK)) イメージを作成することを推奨しています。 VDDKイメージの作成についての詳細は、参考リンクを参照して下さい。 3.7.1. VDDK イメージの作成 ツールの特徴 MTVは、オペレータとして提供されており追加のライセンスは必要なく利用出来るようになっています。 移行の設定・移行実施・ステータスやログ確認などを専用ダッシュボードで完結できる点があります。ダッシュボードから視覚的に分かりやすい方法で移行実施までを行う事が可能になっています。 また設定もCold/Warmの移行タイプの選択、複数VMの移行設定、移行前後の自動実行など豊富な設定が備わっていることも特徴の一つになります。 移行タイプのCold/Warm はそれぞれ以下の動作となります。 Coldマイグレーション: デフォルトの動作となり、VMを停止した状態で移行する方式です Warmマイグレーション: VMを実行中のままバックグラウンドでOCP-Virtにコピーを行う方式です 一定時間ごとに発生した差分データをコピーして対応します。切り替えのタイミングでVMを停止して最後の差分データのコピーを行います SUSE-Virt のマイグレーション マイグレーション概要 SUSE-Virt ではVM移行のツールとして vm-import-controller アドオンが提供されています。 vm-import-controllerは、VMware vSphere、OpenStackで稼働するVMをSUSE-Virt上に移行できるようになっています。 Image Source: https://docs.harvesterhci.io/v1.4/advanced/addons/vmimport vm-import-controllerは、HarvesterのWebコンソールからアドオンの有効化を行うことで使用出来るようになります。アドオンを有効化した後、簡易的な基本設定をするページが利用できます。移行の実施はCLIから利用する形になります。 マイグレーションツールの利用 前提条件 vSphere環境からの移行の主な前提条件を記載します。 Harvester上に、移行元のVMのディスクサイズの2倍のPVを用意すること VMのディスクをダウンロードするための一時ストレージとして利用される 移行元のvSphereのエンドポイントなどの情報をあらかじめ定義していること 移行元の資格情報をKubernetes シークレットとして定義していること その他、詳細の要件は参考リンクを参照して下さい。 VM Import VMの移行 VMの移行は以下のようなフローで実施されます。 vm-import-controller の基本設定 移行元のVMのディスクをダウンロードするためのストレージクラスの設定 移行元のプラットフォーム(vSphere)の情報を登録 vCenterまたはESXiのエンドポイントURLと認証情報をYAMLファイルで作成して、kubectlコマンドで登録する 移行設定の登録と実行 下記情報をYAMLファイルで作成して、kubectlコマンドで登録する 移行元のプラットフォーム(vSphere)の選択と、対象のVMを選択 移行元と移行先のネットワークのマッピング 移行完了の確認 登録した移行設定のステータスで移行完了を確認 ツールの特徴 vm-import-controllerは、アドオンとして提供されており追加のライセンスは必要なく機能を有効化するだけで利用出来るようになっています。 移行元のプラットフォームの情報登録と移行設定の登録を、カスタムリソースで用意してコマンド経由で移行実施する点が特徴となります。 まとめ vSphereからVMのマイグレーションが可能なマイグレーションツールについて解説しました。 どちらもVMの移行フローについては似たような流れになりますが、前提条件や特徴でそれぞれのツールの特色が出ているようでした。 この記事が読者の参考になれば幸いです。 参考文献 https://docs.redhat.com/ja/documentation/migration_toolkit_for_virtualization/2.7/html-single/installing_and_using_the_migration_toolkit_for_virtualization/index#mtv-software-requirements_mtv https://docs.redhat.com/ja/documentation/migration_toolkit_for_virtualization/2.7/html-single/installing_and_using_the_migration_toolkit_for_virtualization/index#creating-vddk-image_mtv https://docs.harvesterhci.io/v1.4/advanced/addons/vmimport   ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post vSphereからVMのマイグレーション 概要 first appeared on SIOS Tech. Lab .
概要 こんにちは、サイオステクノロジーの安藤 浩です。 Ethereum のテストネット: Sepolia でフルノードを構築したのでその手順を記載します。 Ethereumのログを取得したい、ノードを運用したい方はぜひ参考にしていただければと思います。 基本的に  Quickstart: Run a node and (optionally) stake  ETH  using Prysm  に従って構築します。 Nodes  の説明にありますが、Beacon node と Execution node が共に実行されてNodeが構築されます。バリデータになりたいなら、32ETHをステークしてValidator を実行する必要があります。いまはバリデータになる必要はないので、省略します。 なお、本日時点で  prysm v6.0.0  がリリースされていました。 今回は、prysm(consensus-layer client) + geth(execution-layer client) , beacon node と execution node 間の接続はHTTP-JWTとして、フルノードを構築していきます。 以下の図のNodeに対応する部分を構築します。 事前準備 物理マシンを利用したいところですが、調達が大変なのでCloud(Azure)上で構築しました。その際には以下を利用しました。 リソース名 備考 VM OS: Ubuntu コストを安くしたかったため、Spot VMとした Standard SSD 2025.04.03 時点で650GB程度必要。メインネットでは2TB以上必要。 その他、パブリックIPやネットワークセキュリティグループなどAzure のPortal 上から作成すると作成されるリソース。 Step1. prysm のインストール 適当な場所に以下のような階層でディレクトリを作成します。 📂ethereum ┣ 📂consensus ┣ 📂execution consensus ディレクトリに移動し、以下を実行します。(version 5.3 を利用) mv ./ethereum/consensus curl https://raw.githubusercontent.com/prysmaticlabs/prysm/master/prysm.sh --output prysm.sh && chmod +x prysm.sh beacon node と execution node 間の接続は HTTP-JWT とするため、JWT トークンの生成をします。 ./prysm.sh beacon-chain generate-auth-secret Prysm で jwt.hex が生成されるので、ethereum ディレクトリに移動します。 このような階層構造になります。 📂ethereum ┣ 📂consensus  ┣ 📄prysm.sh ┣ 📂execution ┣ 📄jwt.hex Step2. geth による Execution node の実行 geth Download Page  からダウンロードします。(version 1.15.5を利用) etherem/execution  に移動して、geth の実行ファイルを配置してあげればよいです。 配置出来たら、以下を実行します。 ./geth --sepolia --http --http.api eth,net,engine,admin --authrpc.jwtsecret=<PATH_TO_JWT_FILE> --datadir <PATH_TO_GETH_DIR> --syncmode snap PATH_TO_JWT_FILE  は  ethereum/jwt.hex  へのパスを指定します。  PATH_TO_GETH_DIR  は geth のデータディレクトリを指定します。 正確に検証していませんが、パスは絶対パスで指定したほうが良いかもしれません。 📂ethereum ┣ 📂consensus  ┣ 📄prysm.sh ┣ 📂execution  ┣ 📄geth ┣ 📄jwt.hex Step3. prysm による Beacon node の実行 Beacon node を同期する方法は2つあり、Genesis から同期する方法とCheckpointから同期する方法があります。 Checkpointから同期する方法が速く、推奨されているためCheckpointでの同期します。 ./prysm.sh beacon-chain --execution-endpoint=http://localhost:8551 --sepolia --jwt-secret=<PATH_TO_JWT_FILE> --checkpoint-sync-url=https://sepolia.beaconstate.info --genesis-beacon-api-url=https://sepolia.beaconstate.info --datadir=<PATH_TO_PRYSM_DIR> PATH_TO_PRYSM_DIR  は prysm のデータディレクトリを指定します。 Default の場合、 ~/.eth2  に作成されるため、ディレクトリ指定したかったため指定します。 Genesis から同期したい場合は  --genesis-state  のパラメータに  genesis.ssz  からダウンロードしたファイルを指定するようですが、試しましたが時間が掛かかっていた(5時間以上経っても同期が進んでいなさそうだった)ため断念しました。  Discord  でコミュニティに確認しましたが、同期は出来そうだとのことでした。 正常性チェック 同期されるまで時間が掛かる可能性があり、同期できているか不安になるので確認ポイントをいくつか挙げておきます。 データディレクトリの容量が増えているか geth コマンドで  net  の  peerCount  が増えているか geth コマンドで  eth.syncing  の  currentBlock  が増えているか (2時間以上待って、currentBlock が増えていないと遅すぎる気がします) geth コマンドでの同期の確認は以下のようになります。 コンソールの起動 ./geth attach http://127.0.0.1:8545 > net { listening: true, peerCount: 6, version: "11155111", getListening: function(callback), getPeerCount: function(callback), getVersion: function(callback) } > eth.syncing { currentBlock: 2406514, healedBytecodeBytes: 0, healedBytecodes: 0, healedTrienodeBytes: 0, healedTrienodes: 0, healingBytecode: 0, healingTrienodes: 0, highestBlock: 7800198, startingBlock: 0, syncedAccountBytes: 393532328, syncedAccounts: 1687120, syncedBytecodeBytes: 921068927, syncedBytecodes: 191721, syncedStorage: 14257899, syncedStorageBytes: 3217044931, txIndexFinishedBlocks: 0, txIndexRemainingBlocks: 1 } eth.syncing がfalse になったら、完全に同期されたことを意味します。 同期できない場合は Troubleshooting checklist  を参照すると良いと思います。 それでも解決できなければ、 Discord  で聞いてみるのが良いと思います。 eth.syncing がfalseになった後で、7000000 番目のブロックをGethで取得した結果(一部省略)を以下に記載しておきます。 このようにログが取得できました。 > eth.getBlock(7000000) { baseFeePerGas: 1740326177, blobGasUsed: 786432, difficulty: 0, excessBlobGas: 655360, extraData: "0xd883010d0b846765746888676f312e32312e36856c696e7578", gasLimit: 30000000, gasUsed: 23850754, hash: "0x7dedce8c46563ce800f91e3bdb2ef03282709fce14883ed1d496eb0dc9fb2e97", logsBloom: "0x0109280004014014021020860200000000c98014068204403010000202024200008800441818311000020003230440a00110000008000c600006121624200142022800020204000a401030ca0000000004800804000400008000020000201002024228490a0005030024862100800990000822c000410802200014144000e8008a22100100802004a008002020000008010514a0002086022001040a2400080802080000000040000a600800c00000530011c06000480a1000c0022a0420000b011008c204002800000900000a420a08404449000110000011224542000120a08230000040e801200100008020820000300882222a0000000c08a80400801000", miner: "0x9b7e335088762ad8061c04d08c37902abc8acb87", mixHash: "0x7ee4d0677635b1cc2fd443879da4715890042461ff57d0441ff0dcd9715e47e0", nonce: "0x0000000000000000", number: 7000000, parentBeaconBlockRoot: "0x83ac49f3eb40d5278d3857bedde44d67351ef01057f0e9d5be465e3224d95849", parentHash: "0x20f7a3250f0af68aafc4e6101a90d330a1238067e5dc5fcb3882c0c76d3a9c14", receiptsRoot: "0xcdc50cd52f33de7a52ba55cb26be903a98cd6be5cc59da8beb85151606865beb", sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", size: 27053, stateRoot: "0x17a59c5581a6be7e72ebae62df30efa8260ce4444b5aa3daee1141f1ee981c96", timestamp: 1730590644, transactions: ["0xe087184469bd23ed38701af221f3e633db981888bef1434010217474025643e6", "0x576bd50d7e565c327c68e6b9f0d2b92cc15627479cbf3a519a54cb796e2421e6", "0xdcb727a2e3272e9bdb550c3d0100fc929a7e9fdeda547fa891fd2e4501f984f7", "0x5ab5f34109fb65aa6b7b9ee9c88c49375d6ffa7e6f85451d09a781c7a42ae982", "0x371296c8648c4e441619e93edc378d097763fad6c4404c0c1cfb16f0f0eb72bc", "0xcc8da422c0b63bba9fac14d54c995519cfb7b79ffe232daf222e924da29fab14", "0x4f76de8ccc1342fc79460b310becd41870a9754f88ab7ea46d72ab36d854eb87", "0x4615a209ac88196a27fb43d85bb6461fa18ac3badf7dc3c8d2535d691f8e726a", "0x5bbcc5bdb8060be00f5c059bdd78cef85035a6f1ab16a002465714cb466d5529", "0xb3aaf6ed75a6112c1e9eacb8f040558071f0bc3b16135919c9894044693f10ed", "0xfc3fcc4cbef1fc2d81c0ab8b5c2fa47cf821af5e5321b3100bfe39f00dba2b70", "0xb0168aa3dbcc588d8434402f6bd1fe2bc98b058c8822d77ef1f57070d6fd3a33", "0x45111b4ad3b0c314d12854446ac97ffb66f2241be0d8cfd1d618b55cdccbb0a1", "0xdf0e0a9fa138d21a9003d718bde1cf51c428aefdf6067591c95600bf62b2fd6f", "0x58927b2bc9f07fd8e2339613a61950af45a3059f3519fab9c3b2f6617bc5eebc", "0x0b065efff51965ca268ca47cde6d4fdb4a62e76c8851aad5586f1ac66fedfe24", "0x36837e224a0bf1eb2e108a56df3b691e2734dc341c5f49104dab62ff88ba887b"], transactionsRoot: "0xcf8b30f13a064fd255c3a165a50c1b59b2c8f576f3190094521cca77a170b55f", uncles: [], withdrawals: [{ address: "0xe276bc378a527a8792b353cdca5b5e53263dfb9e", amount: "0x31c18", index: "0x3d2a6e9", validatorIndex: "0x38a" }, { address: "0xe276bc378a527a8792b353cdca5b5e53263dfb9e", amount: "0x31c18", index: "0x3d2a6ea", validatorIndex: "0x38b" }, { address: "0xe276bc378a527a8792b353cdca5b5e53263dfb9e", amount: "0x31c18", index: "0x3d2a6f7", validatorIndex: "0x398" }, { address: "0xe276bc378a527a8792b353cdca5b5e53263dfb9e", amount: "0x31c18", index: "0x3d2a6f8", validatorIndex: "0x399" }], withdrawalsRoot: "0x86e381c6550fb06fae784caf00bb758e85e135a64f1d4825988518d6e5526238" } まとめ Ethereumのテストネット「Sepolia」上でフルノードをPrysm(コンセンサスレイヤークライアント)+ Geth(実行レイヤークライアント)で以下の流れで構築しました。 事前準備 Prysmのインストールとセットアップ(JWT認証トークン生成) Gethによる実行ノードの設定と起動 Prysmによるビーコンノードの構成(チェックポイント同期を使用) 同期確認方法は以下が主になります。 データディレクトリ容量の増加確認 Gethコマンドによるピア数・同期状態の確認 eth.syncingがfalseになれば完全同期完了 最終的に同期が完了すると、ブロック情報の取得やトランザクション情報の確認が可能になります。 Ethereumのログを取得したい、ノードを運用したい方はぜひ構築してみてはいかがでしょうか。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post [web3] Ethereum の テストネット: Sepolia上での フルノード構築 first appeared on SIOS Tech. Lab .
こんにちは、OSSよろず相談室の神崎です。 今回は、 Apache のエラー AH00288 と logrotate の関係性に焦点を当てて、原因や対策を解説していきます。 AH00288: scoreboard is full, not at MaxRequestWorkers このメッセージが、logrotate 実行時の Apache HTTP Server のエラーログに出力されることがあります。 以下の流れでこのエラーを深堀りしていきます。 AH00288 メッセージについて 対象のMPM まず、このエラーは MPM が worker MPMの場合に出力されます。event MPMの場合は、AH003490 エラーが出力されます。 エラーメッセージの解説 次にエラーメッセージに着目します。 scoreboard is full はスコアボードに登録できるスレッドの枠が限界に達したことを意味します。 ※スコアボードとは、スレッドの接続数と各スレッドの処理状態をリアルタイムに記録・共有するためのメモリ構造です。 not at MaxRequestWorkers は MaxRequestWorkers に達していないことを意味します。 MaxRequestWorkers は、Apache が同時に処理できるリクエストの最大数です。 スコアボードのスレッドの接続数と MaxRequestWorkers が対応しています。 つまり、Apache が同時に処理できるリクエストの最大ではないのにも関わらず、スコアボードの接続数が埋まっているというエラーになります。 原因の一つとしては終了した古いプロセスやスレッドがスコアボード上に残ってしまっているということが考えられます。 logrotate とAH00248 エラーについて logrotate 時になぜ AH00248 エラーが発生するのかについて解説していきます。 logrotate とは Linux がサポートするログローテーションのツールです。logrotate の設定内容にもよりますが、ログローテーションの際に Apache の再起動させることが一般的です。通常は、サービスの停止を最小限にするために、graceful restart をプロセス数の少ない深夜に実行することで運用されています。 logrotate と graceful restart logrotate が実行されると、graceful restart が行われます。 graceful restart とは、Apache サーバの再起動時に、プロセスが行っている現在の処理を完了してから終了し、新しいログファイルを再オープンする動作のことを指します。これはプロセス単位で行われるため、プロセス内でのスレッドがすべての処理が完了後にそのプロセスが再起動します。 この処理の目的は、サーバが新しいリクエストを受け付けることができない時間を最小限に抑えるとともに、設定ファイルに記載されたパラメータを尊重することです。 しかし、上記で述べたように稼働中の古いプロセスはリクエストが終了するまでプロセスとスレッドは graceful restart 後のリクエストを受け付けることができない状態です。それに加えて、graceful restart 後に確保するアイドルスレッドや新しく受け付けたリクエストでスコアボードがうまってしまい、AH00288 エラーが出力されます。 ※古いプロセス内のスレッドは新しいリクエストを受け付けない状態なので MaxRequestWorkers と処理できるリクエスト数が一致しない Apacheのドキュメントにてこのエラーについての説明があります。 ※event MPM の説明ですが、worker MPM においても同様の現象だと考えます。 ※worker MPM には event MPM の “From 2.4.24 onward,” に記載の機能改善は行われていません。 Apache MPM event / Graceful process termination and Scoreboard usage 基本的には、古いプロセスは終了し次第プロセス内の全スレッドが解放されていくので、処理自体に問題はありません。 しかし、高負荷のシステムであればリクエストが処理しきれなくなるため、問題になる可能性があります。 AH00248 エラーの対策 解決策としては、2つの方法が考えられます。 MPM のパラメータの調整 rotatelogs の使用 MPM のパラメータの調整 エラーを出力されないように MPM のパラメータを調整します。 MPM のパラメータは、httpd.conf の <IfModule mpm_worker_module> タグ内で以下のように設定することができます。 <ifmodule mpm_worker_module> ServerLimit 16 //子プロセスの最大数 StartServers 2 //起動時に子プロセスの数(リクエスト処理用) MaxRequestWorkers 150 //最大リクエスト処理数 MinSpareThreads 25 //アイドルスレッド数の最小数 MaxSpareThreads 75 //アイドルスレッド数の最大数 ThreadsPerChild 25 //子プロセスが生成するスレッド数 </ifmodule> Apacheドキュメント / Apache MPM worker より設定の典型例を抜粋 graceful restart によって、リクエスト処理中の古い子プロセスのスレッドが解放されないため、スコアボードの上限 (MaxRequestWorkers や ServerLimit) を上げることや起動直後のプロセス数 (StartServers) を制限することにより、スコアボードが埋まるのを対策することができます。 ※graceful restart の仕様として、スレッドが一つでも稼働中だと子プロセスは再起動されないため、ServerLimit を調整が有効です。 ※パラメータを変更した場合、通常時の運用に影響が出る可能性があります。 1つのパラメータを変更すると、他のパラメータの調整が必要になる場合があります。以下を目安に調整してください。 ServerLimit × ThreadsPerChild >= MaxRequestWorkers MinSpareThreads + 想定最大アクティブスレッド数 < MaxRequestWorkers MaxSpareThreads + 想定最小アクティブスレッド数 < MaxRequestWorkers rotatelogs の使用 logrotate では graceful restart が実行されてしまうので、 rotatelogs を代わりに実行するという方法があります。 rotatelogs は Apache がサポートするログローテーションツールで Apache のアクセスログまたはエラーログを graceful restart の必要なくローテーションが可能です。 graceful restart しないのため AH00288 エラーはログローテーションの際には発生しませんが、設定の反映等のため定期的な再起動を必要とします。 参考文献 類似のエラーである AH03490 についてより詳細に解説していますので、ぜひご覧ください サポートエンジニアの現場から!Apacheエラー「AH03490」を徹底解説 StartServers、ServerLimit、ThreadsPerChild、MaxSpareThread等、各MPMの値のパラメータの説明は以下を参照してください。 Apacheドキュメント / Apache MPM Common Directives logrotate についての基本知識です。 知っておくとちょっと便利!logrotate の仕組みについて1 Red Hat社の公式ドキュメントで logrotate と rotatelogs について説明があります。(Red Hat社の有料ポータルログインIDが必要です) logrotate と rotatelogs を使用して Apache HTTPD のログをローテーションするにはどうすればよいですか? ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post [Apache エラー解説] logrotate 時に Apache で AH00288 エラーが出力される原因と対策 first appeared on SIOS Tech. Lab .
概要 前回は、OCP-Virt, SUSE-Virt, vSphere の3製品の比較についてご紹介しました。 今回は、OCP-VirtでMultus CNI(以下、Multus)を用いてVMに複数NICを付与する方法について記載します。 前回の記事は こちら 本記事では、Multusの基本的な概要、追加ネットワークの構築、VMへの追加NICの設定について解説します。 今回の作業におけるOCP-Virt環境は用意してあることを前提としています。 OCP-Virtの構築についての記事は こちら Multusとは Multusは、Kubernetes環境で複数のCNIを扱うことを可能にするCNIプラグインとなります。通常Podには一つのNICが接続されますが、Multusを用いることによりPodに追加NICを構成して、複数のネットワークに接続することが可能になります。 OCP-Virtでも同様にVMのPodに対して追加NICを構成して対応することができます。 Image Source: https://github.com/k8snetworkplumbingwg/multus-cni net0, net1は追加のNICとなり、他のCNIを使用して複数のネットワークに接続します。 この時、NetworkAttachmentDefinitions という設定により追加のネットワークを用意します。 NetworkAttachmentDefinitions (以下、NAD) Multusで追加のNICの構成を行いますが、NICが接続するネットワーク設定をNADというカスタムリソースで設定します。 NADは、ネットワーク設定をYAMLファイルとして用意しWeb コンソールまたはCLIなどを通してアプライすることで設定が出来るようになります。 使用出来るCNIは主に下記の種類があります。 Linux Bridge ノード上のBridgeと接続するネットワークを定義します クラスタ外部との通信が可能です OVN-Kubernetes OVN Kubernetes secondary localnet network OVN Kubernetes によるオーバーレイネットワークを定義します クラスタ内部の通信と、ノード上のBridgeと接続してクラスタ外部との通信が可能です OVN Kubernetes L2 overlay network OVN Kubernetes によるオーバーレイネットワークを定義します クラスタ内部の通信が可能です。クラスタ外部との通信は不可能です SR-IOV PodにSR-IOV 仮想機能(VF)を割り当てネットワークを構成します クラスタ外部との通信が可能です 事前準備 前回までの記事で紹介したOCP-Virt環境を使用します。 詳細は、 OCP-Virt 構築してみた を参照して下さい。 OCPへのログイン 下記コマンドを用いて、構築済みのOCPにログインしておきます。 $ oc login -u <ユーザー名> https://api.<クラスター名>.<管理ドメイン>:6443 追加ネットワークの構築 NADの作成 NADを作成して、2つ目のネットワークを作成します。 今回の手順では、CNIとしてOVN Kubernetes L2 overlay network を利用します。 NADのマニフェストファイルを作成します。 追加するネットワークのサブネットを172.31.0.0/24で定義します。 $ vi l2_overlay_nad.yaml apiVersion: k8s.cni.cncf.io/v1 kind: NetworkAttachmentDefinition metadata: name: vm-tutorial-l2-overlay-network namespace: vm-tutorial spec: config: |- { "cniVersion": "0.3.1", "name": "vm-tutorial-l2-overlay-network", "type": "ovn-k8s-cni-overlay", "topology": "layer2", "subnets": "172.31.0.0/24", "mtu": 1300, "netAttachDefName": "vm-tutorial/vm-tutorial-l2-overlay-network" } NADのマニフェストファイルを適用します。 $ oc apply -f l2_overlay_nad.yaml networkattachmentdefinition.k8s.cni.cncf.io/vm-tutorial-l2-overlay-network created NADの設定を確認します。 $ oc get net-attach-def -n vm-tutorial -oyaml apiVersion: v1 items: - apiVersion: k8s.cni.cncf.io/v1 kind: NetworkAttachmentDefinition metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"k8s.cni.cncf.io/v1","kind":"NetworkAttachmentDefinition","metadata":{"annotations":{},"name":"vm-tutorial-l2-overlay-network","namespace":"vm-tutorial"},"spec":{"config":"{\n \"cniVersion\": \"0.3.1\",\n \"name\": \"vm-tutorial-l2-overlay-network\",\n \"type\": \"ovn-k8s-cni-overlay\",\n \"topology\": \"layer2\",\n \"subnets\": \"172.31.0.0/24\",\n \"mtu\": 1300,\n \"netAttachDefName\": \"vm-tutorial/vm-tutorial-l2-overlay-network\"\n}"}} creationTimestamp: "2025-04-03T08:37:06Z" generation: 1 name: vm-tutorial-l2-overlay-network namespace: vm-tutorial resourceVersion: "33233267" uid: f26c98a1-9ad2-4713-911d-7afd1618458a spec: config: |- { "cniVersion": "0.3.1", "name": "vm-tutorial-l2-overlay-network", "type": "ovn-k8s-cni-overlay", "topology": "layer2", "subnets": "172.31.0.0/24", "mtu": 1300, "netAttachDefName": "vm-tutorial/vm-tutorial-l2-overlay-network" } kind: List metadata: resourceVersion: "" これで二つ目のネットワークを構成することが出来ました。 VMへの追加NICの設定 VMへ追加のNICを設定していきます。 追加のNICの設定は、OCPのWebコンソールで実施していきます。 追加のNICの設定 OCPのWebコンソールで [Virtualization] > [VirtualMachines]に移動します。 プロジェクトの選択をして、作成済みのVMを選択します。 [Configuration] -> [Network] を選択して、[Add network interface] をクリックします。 Networkに作成したNADを選択出来るようになっています。選択を行いSaveをクリックします。 追加のNICが付与されていることを確認します。 「Pending changes」と表示されるため、追加NICの反映のために画面右上のリスタートボタンを選択して再起動を行います。 数分後、ステータスがRunningであることを確認します。 画面右側のNetworksにnic-xxxと追加のNICの構成、IP(172.31.0.4)が付与されていることを確認します。 内容についての補足事項 今回のケースでは、NADでサブネットを定義しました。 その場合VMにはサブネットの範囲内でDHCPによってIPが割り振られる形になります。 VMで静的IPを使用する場合は、サブネットを定義しない状態でNADを設定する必要があります。 NADを設定後、VMに対して静的IPを定義する必要があることに注意してください。 詳細は、参考URLを参照していただければと思います。 参考URL: https://docs.redhat.com/ja/documentation/openshift_container_platform/4.17/html-single/virtualization/index#virt-connecting-vm-to-ovn-secondary-network https://ovn-kubernetes.io/features/multiple-networks/multi-homing/#network-configuration-reference まとめ Multusの基本的な概要、追加ネットワークの構築、VMへの追加NICの設定について解説しました。 Multus を使用してOCP上でもVMに複数のNICを構成することが確認出来ました。 追加のNICによるマルチネットワーク構成により、OCP上でもVMに対して柔軟性と利便性の高いネットワーク設計の提供が可能になります。 この記事がMultus利用の参考になれば幸いです。 参考文献 https://github.com/k8snetworkplumbingwg/multus-cni https://docs.redhat.com/ja/documentation/openshift_container_platform/4.17/html-single/virtualization/index#virt-connecting-vm-to-ovn-secondary-network https://ovn-kubernetes.io/features/multiple-networks/multi-homing/#network-configuration-reference ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift VirtualizationでMultusを利用してみた first appeared on SIOS Tech. Lab .
ども!一週間の業務がDocker関連業務で、悩まされている龍ちゃんです。Docker系の問題は単に使うだけでは出会わないので、調査も時間がかかります。今回は、そんな時に出会った問題です。 今回のテーマはDocker Desktop環境で発生した問題です。内容は「nodeのDocker Imageをビルドした際、 COPY --chown=node:node が動かず、1001や1002になる」です。 こちらの問題ですが、WSL+Docker CLIの構成のみでは起きませんでした。WSL+Docker Desktop環境でのみ発生した問題になっています。 起因については、わかりません。発生パターンと回避方法が分かったのでブログとしてまとめていきます。 発生した問題 以下のDockerfileをDocker Compose環境でビルドした際に発生していました。 COPY --chown=node:node ./next-app . でコンテナーに移したファイルの権限が、環境によっては node ・ 1001~1003 になってしまう問題が発生していました。 ARG NODE_VER="latest" FROM node:${NODE_VER} RUN npm install -g npm USER node WORKDIR /home/node/app RUN mkdir next-app WORKDIR /home/node/app/next-app RUN mkdir node_modules RUN chown node:node -R node_modules COPY --chown=node:node ./next-app . RUN npm install 発生パターン調査 まずは、WSL+Docker CLI環境では発生せずにDocker Desktop環境でのみ発生していました。上記の問題について、人によってはビルドが成功(ファイル権限がnode)していました。ですが、1001~1003までの広い範囲でファイル権限が変更されていました。 1001~1003までのファイル権限で、実行された環境のユーザーUID:GIDを調査したところファイル権限とUID:GIDが一致していました。よって問題としては、以下になります。 「Docker Desktop環境で COPY --chown コマンドを実行した際にWSL実行ユーザーでファイルがマウントされる」 対応法 暫定的な対応方法は以下の2ステップです WSL実行ユーザーのUID:GIDを取得する 修正したDockerfileに実行ユーザーのUID:GIDを指定してビルド まずは、以下のコマンドでWSL実行ユーザーのUIDとGIDを一括で取得します。 id 取得できた情報を以下のDockerfileへ反映させます。 ARG NODE_VER=latest FROM node:${NODE_VER} # 非rootユーザーを作成 ARG USERNAME=vscode # ユーザーのUIDとGIDを指定 # デフォルトは1000:1000 ARG USER_UID=1000 ARG USER_GID=$USER_UID ENV WORKDIR=/home/$USERNAME RUN npm install -g npm # nodeを削除(1000:1000を開ける) RUN userdel -r node RUN groupadd --gid $USER_GID $USERNAME \\ && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \\ && apt update \\ && apt install -y sudo \\ && echo $USERNAME ALL=\\(root\\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \\ && chmod 0440 /etc/sudoers.d/$USERNAME USER $USERNAME WORKDIR $WORKDIR RUN mkdir next-app WORKDIR $WORKDIR/next-app RUN mkdir node_modules RUN chown $USER_UID:$USER_GID -R node_modules COPY --chown=$USER_UID:$USER_GID ./next-app . RUN npm install nodeのDocker Imageでは、nodeユーザーが1000を使用しています。UIDを指定してユーザーを作成する場合は、そのUIDを使用しているユーザーがいる場合は失敗するため、先回りしてnodeユーザーを削除しています。 知りたいこと 本稿で紹介した問題について、以下の点がまだ不明確です。 なぜDocker Desktop環境でのみCOPYコマンドの挙動が異なるのか この問題に対する根本的な解決方法はあるのか これらの点について、さらなる調査や情報提供をいただけると幸いです。ぜひ!根本原因について知っている方、実行ユーザーのUID:GIDを移す方法に関してベストプラクティスを知っている方がいれば、教えてください。 おわり 本記事では、Docker Desktop環境でCOPYコマンドの挙動が異なる問題について解説しました。この問題に対する暫定的な解決策は見つかりましたが、根本的な原因についてはまだ調査が必要です。今後も新しい情報が得られ次第、アップデートしていきたいと思います。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Docker Desktopで起きるCOPY –chownが権限通りにマウントされない問題|調査と対応 first appeared on SIOS Tech. Lab .
ども!4月に年度が更新され、4年目のエンジニアになった龍ちゃんです。気づけば、また春の季節になっていますね。春といってもまだ寒いですね。 今回は、Azure OpenAI Serviceのお話になります。生成AIを活用したアプリを作成する際に、レスポンスがJSONで返答されるかどうかは重要な要素になります。DifyでもAOAIでも、方法を模索して実装していました。 Difyでの構造化:「 Dify入門ガイド:LLM出力を構造化する!JSONデータ作成の具体的手順 」 AOAIでの構造化:「 AOAI:Gpt-4oでJSON出力に失敗する対症療法 」 AOAIのバージョンアップに併せて「構造化出力」という機能がリリースされていました。こちらを用いてTypescript環境で構造化出力を行うサンプルの実装を行います。 公式のサンプル では、PythonとREST APIの記載があります。 前回は、 「json schema」での構造化出力を検証 しました。Open AIでは、「 Zod 」を使用した構造化出力を検証し実装していきます。 前提条件 公式リファレンス:構造化出力の情報 はこちらにあります。モデルによっては使えない機能なので、サポートされているモデルやバージョンなどを確認して使用してください。アップデートによっては使えなくなる可能性もあるので、公式の情報を確認して実装するのが一番です。 私の環境では、以下のモデルを使用してAPI Key認証で検証しています。 モデル名 モデルバージョン APIバージョン gpt-4o-mini 2024-07-18 2024-08-01-preview Typescriptのライブラリに関する情報ですが、発見できた情報としては以下の二つです。 TypeScript 用 Azure OpenAI ライブラリ – 2.0.0 Azure OpenAI library for TypeScript 実装は、OpenAIの「 Text Generation:Generate JSON data 」を参考に進めていきます。 サンプルでは、「 LINE×生成AI:チャットバトルゲームを作る! 」で作成したAPIのレスポンスオブジェクトを作成します。こちらのサンプルでは、「キャラクター同士を戦わせ戦いの勝者と描写を出力するゲーム」になっています。出力したいJSONは以下になります。 { "winner":"user"|"system", "combatLogs": { "round":number, "combatLog":string }[] } 構造化出力:Zodサンプル AOAIへ問い合わせて、構造化出力を行うサンプルの全文を張ります。 import { zodResponseFormat } from 'openai/helpers/zod'; import { AzureOpenAI } from 'openai'; import { z } from 'zod'; // Zod定義 const PromptResultTypeSchema = z.object({ winner: z .enum(['user', 'system']) .describe('戦いの勝者を記述する。ユーザー側が勝利した場合は「user」、システム側が勝利した場合は「sysytem」を代入'), combatLogs: z.array( z.object({ round: z.number().describe('戦いの記録の順序を記述する。'), combatLog: z.string().describe('戦いの記録の内容を記述する。'), }), ), }); // Zod ObjectからTypeを生成 type PromptResultTypeFromZod = z.infer<typeof PromptResultTypeSchemaZod>; async battlePrompotFormatJSON_Zod(): Promise<PromptResultType> { const AOAIClient = new AzureOpenAI({ endpoint: "xxxxxxxxxxxxxxxxxxxxx", apiKey: "xxxxxxxxxxxxxxxxxxxxx", apiVersion: "xxxxxxxxxxxxxxxxxxxxx", deployment: "xxxxxxxxxxxxxxxxxxxxx", }); const systemPrompt = ` ~~~~~~~~~略~~~~~~~~~ `; const response_format = zodResponseFormat(PromptResultTypeSchemaZod, 'combat_schema'); const res = await AOAIClient.chat.completions.create({ messages: [ { role: 'system', content: systemPrompt, }, { role: 'user', content: '剣士 主に剣で戦う' }, ], model: '', response_format: response_format, }); const math_combat_schema = res.choices[0].message; if (math_combat_schema.refusal) { return { winner: 'user', combatLogs: [ { round: 1, combatLog: 'JSON整形を正しく行うことができませんでした。よって開発者の負けです。', }, ], }; } const tmp = PromptResultTypeSchemaZod.safeParse(JSON.parse(res.choices[0].message.content)); if (!tmp.success) { console.log(tmp.error); return { winner: 'user', combatLogs: [ { round: 1, combatLog: 'JSON整形を正しく行うことができませんでした。よって開発者の負けです。', }, ], }; } return tmp.data; } 手順としては、AOAIとの通信部分にresponse_formatとしてZodから作成したフォーマットの定義を渡します。結果として構造化出力で返答が返されます。 出力サンプル 実行した結果として、以下のような情報が出力されます。 { "winner": "system", "combatLogs": [ { "round": 1, "combatLog": "リングの中央で立ちはだかるボクシングチャンピオン、彼の拳はまるで鉄の塊のようだ。挑戦者である剣士は、激しい視線を向け、自身の剣をしっかりと構える。初めのラウンドが始まると、チャンピオンが力強いジャブを繰り出す。それは剣士の顔面をかすめ、観客から驚嘆の声が上がる。" }, { "round": 2, "combatLog": "剣士は冷静を保ちながら、反撃のチャンスをうかがう。しかし再びチャンピオンが猛攻を仕掛け、フックが剣士の横っ面に見舞う。その強烈な一撃に、剣士は一歩後退し、動揺を隠せない。拳の力に打ちひしがれる剣士の表情が、リングの明るさに映える。" }, { "round": 3, "combatLog": "猛攻を続けるチャンピオンは、剣士のペースを完全に奪い取っている。挑戦者は必死に防御しようとするが、チャンピオンの強烈なアッパーカットが剣士の顎を捉える。剣士はついに膝をつき、観客たちはその劇的な光景に息を呑む。" }, { "round": 4, "combatLog": "剣士はなんとか立ち上がるものの、目の前には打撃の鬼が立ちはだかる。最後の力を振り絞って反撃しようとするが、チャンピオンのパンチが再度放たれ、その拳は剣士の顔を叩きつけてしまう。剣士は再び地面に崩れ落ち、審判のカウントが始まる。" }, { "round": 5, "combatLog": "カウントが進む中、剣士の意識が薄れていく。彼はまだ戦う力が残っているものの、チャンピオンの強力な防御と攻撃を前に完全に出遅れている。カウントが10に達する時、審判は試合を止め、チャンピオンの勝利を宣言する。" } ] } response_format定義方法 import { zodResponseFormat } from 'openai/helpers/zod'; const PromptResultTypeSchema = z.object({ winner: z .enum(['user', 'system']) .describe('戦いの勝者を記述する。ユーザー側が勝利した場合は「user」、システム側が勝利した場合は「system」を代入'), combatLogs: z.array( z.object({ round: z.number().describe('戦いの記録の順序を記述する。'), combatLog: z.string().describe('戦いの記録の内容を記述する。'), }), ), }); const response_format = zodResponseFormat(PromptResultTypeSchema, 'combat_schema'); Zodの形式で出力させたいオブジェクトを定義します。Zodオブジェクトから zodResponseFormat を通してフォーマットを生成します。Zodを学んでいれば、フォーマット定義に関してはスムーズに定義することができます。 zodResponseFormat を通すことでJSON Schemaを作成してくれています。説明( describe )を定義することで各項目の情報が保管されます。説明を詳細にしておくことで、構造化(JSON)の作成をサポートしてくれます。 構造化の検証 const math_combat_schema = res.choices[0].message; // Azure OpenAI Serviceのレスポンスからの確認処理 if (math_combat_schema.refusal) { return { winner: 'user', combatLogs: [ { round: 1, combatLog: 'JSON整形を正しく行うことができませんでした。よって開発者の負けです。', }, ], }; } // Zodのスキーマに対応できているかの確認処理 // Errorがある場合もレスポンスに含まれる const tmp = PromptResultTypeSchemaZod.safeParse(JSON.parse(res.choices[0].message.content)); if (!tmp.success) { console.log(tmp.error); return { winner: 'user', combatLogs: [ { round: 1, combatLog: 'JSON整形を正しく行うことができませんでした。よって開発者の負けです。', }, ], }; } 構造化の検証は、Azure OpenAI Serviceからの返答とZodによるスキーマを用いた二つの方法で検証しています。エラーが発生した場合は、固定メッセージを返答しています。 AOAIからの返答には、 モデルから返答された拒否メッセージ (choice.message.refusal)が含まれる場合があります。拒否メッセージが含まれる場合では、生成を開始したがうまく生成することができなかった場合に含まれます。 Zodのスキーマ判定では、AOAIからの返答をJSON構造化に変換して、 Zodを通じて検証(safeParse) を行っています。検証の結果には、成功した場合はデータが失敗した場合はZodErrorが出力されます。 Zodスキーマ判定:簡易的な例 const stringSchema = z.string(); stringSchema.safeParse(12); // => { success: false; error: ZodError } stringSchema.safeParse("billie"); // => { success: true; data: 'billie' } 構造化出力の精度を高める方法 システムプロンプトで出力形式の詳細な指示を事前に設定する Zodのオブジェクトの命名をシステムプロンプトの内容に合わせて適切に命名する 複雑な出力が必要な場合は、処理を小さな単位に分割する これらの方法を組み合わせることで、より高精度な構造化出力を実現できます。 あなたは決闘の審判です。二つのキャラクターの戦闘を見守り、勝敗までの流れを判定してください。 AI側がチャンピオン、ユーザー側が挑戦者です。 次の内容は必ず守ってください「チャンピオンのキャラクターが勝利した場合はsystem、挑戦者が勝利した場合はuserと明記してください。」 --- ボクシングチャンピオン主にこぶしで戦う --- 以下のType出力を守った内容を最後に付録として記載してください。 --- { "combatLogs": { "round":number, "combatLog":string }[] } --- 例は以下のようになります。combatLogは小説家のように過大に脚色して演出してください。決闘の勝者を明確にしてください。 --- { "combatLogs": [ { "round": 1, "combatLog": "訓練場の教官が鉄の剣で攻撃しました" }, { "round": 2, "combatLog": "訓練場の教官が鉄の盾で防御しました" } ] } --- システムプロンプトでの詳細な指示は、AIモデルが期待される出力形式を正確に理解するために重要です。出力の例(few-shot)を含めることで、より具体的な指示となります。 おわり 以上、Azure OpenAI Serviceの構造化出力(JSON)をZodを用いて検証する方法について解説しました。システムプロンプトの適切な設定と、Zodによる厳密な型チェックをセットで行うことで、より信頼性の高いAIアプリケーションを構築することができます。みなさんも是非試してみてください! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 今すぐ使える!Azure OpenAI × Zodで実現する高精度な構造化出力の実装方法 first appeared on SIOS Tech. Lab .
こんにちは PS/SLの佐々木です 今回はNext.jsにDIコンテナを導入したいと思います。 TypescriptのDIコンテナライブラリは inversifyJS と Tsyringe の二つが有名なようですが、今回は inversify を採用しました 今回は導入方法の動作の検証がメインのためDI、DIコンテナについては軽くしか触れません。 DIコンテナとは DI(Dependency Injection)コンテナ とは、「依存関係(=使いたい機能やクラス)」を自動で注入(Inject)してくれる仕組みです。 DIコンテナを導入するメリット 依存関係の管理が楽になる どのクラスがどの機能を使っているか、一元管理できる。 テストがしやすくなる モックやスタブの差し替えが簡単になる。 コードの再利用性・拡張性が上がる 実装の入れ替えが柔軟にできる(例えば本番用と開発用で処理を変える、など)。 導入方法 Next.js プロジェクト作成 npx create-next-app Inversify JS インストール npm install inversify@alpha reflect-metadata 今回作成するディレクトリ構成 今回使用するのはNext.js v15になります。 /app/apiを基準のディレクトリとして作業を行っています . ├── (controller) │   └── route.ts // ルーティング ├── instrumentation.ts // ├── interface │   ├── repository.ts │   └── service.ts ├── inversify.config.ts // 識別子と実装クラスの関係付け ├── repository │   └── index.ts // DBにアクセスするリポジトリ層 ├── service │   └── index.ts // ビジネスロジックを実装するservice層 └── type └── symbol └── type.ts // 識別の定義 それぞれのディレクトリとファイルの責務は上記の通りになります。 またDI を行う際に @Injectable() や @Inject() などのデコレーターを使用するためtsconfigに以下の設定を追加します。 { "compilerOptions": { "target": "ES2017", ... "experimentalDecorators": true, // 追加 "emitDecoratorMetadata": true, // 追加 ... } 実装 では早速動かしてみましょう 今回はDIコンテナなしの場合とありの場合でどれぐらい違うのかをみていただくために、DIコンテナを使用しないバージョンも載せておきます。 今回実装するのは簡単なUserの取得と作成の処理になります。 またDBはないのでRepository層はほぼ何も処理はしてません 動作確認(DIコンテナなしの場合) まずはDIコンテナなしの場合以下のようになります。(特に見なくても大丈夫の方はDIコンテナありの場合まで読み飛ばしてください) interface/repository.ts import { User } from "../type"; export interface IUserRepository { getById(id: string): User, create(user: User): void, } interface/service.ts import { User } from "../type"; export interface IUserService { get(id: string): User create(user: User): void } type.ts export type User = { id: string, name: string, email: string, address: string } route.ts import { NextResponse } from "next/server" import { UserService } from "../service" import { User } from "../type" export const GET = () => { const service = new UserService() const user = service.get('user0001') return NextResponse.json(user) } export const POST = () => { const service = new UserService() const body: User = { id: 'user0002', name: 'sasaki2', address: '東京都港区...', email: 'sasaki2@sios.jp' } const user = service.create(body) return NextResponse.json('ok') } service/index.ts import { IUserService } from "../interface/service"; import { UserRepository } from "../repository"; import { User } from "../type"; export class UserService implements IUserService{ private repository: UserRepository constructor(){ this.repository = new UserRepository() } get(userId: string){ return this.repository.getById(userId) } create(user: User) { this.repository.create(user) } } repository/index.ts import { IUserRepository } from "../interface/repository"; import { User } from "../type"; export class UserRepository implements IUserRepository { constructor(){} getById(id: string): User { return { id: id, name: 'kanta sasaki', email: 'sasaki@sios.jp', address: '東京都港区....' } } create(user: User): void { // prisma.create({}) ... } } DIコンテナを使用しない場合にはcontroller, seviceそれぞれで依存しているクラスのインスタンスを作成しているのがわかると思います。 これだと具体的な実装に依存してしまっており、テストの際にダミーのRepositoryと入れ替えが難しくなってしまったり、依存している実装の変更の影響を受けやすくなってしまいます。 では次にDIコンテナありの場合を見てみます。 動作確認(DIコンテナありの場合) 識別子の定義 type/symbol/type.ts const TYPES = { // repository IUserRepository: Symbol.for('IUserRepository'), // service IUserService: Symbol.for('IUserService') }; export default TYPES; 識別子と実装クラスの関係付け inversify.config.ts import { Container } from 'inversify'; import TYPES from './type/symbol/type'; import { IUserRepository } from './interface/repository'; import { UserRepository } from './repository'; import { IUserService } from './interface/service'; import { UserService } from './service'; const diContainer = new Container(); diContainer.bind<IUserRepository>(TYPES.IUserRepository).to(UserRepository); diContainer.bind<IUserService>(TYPES.IUserService).to(UserService); export { diContainer }; Symbolで定義した識別子と具体的な実装クラスは上記のように紐づけます。 DIコンテナを使用してRepositoryとServiceの依存関係を解決する controller/route.ts import { NextResponse } from "next/server" import { User } from "../type" import { diContainer } from "../inversify.config" import { IUserService } from "../interface/service" import TYPES from "../type/symbol/type" export const GET = () => { const service = diContainer.get<IUserService>(TYPES.IUserService) const user = service.get('user0001') return NextResponse.json(user) } export const POST = () => { const service = diContainer.get<IUserService>(TYPES.IUserService) const body: User = { id: 'user0002', name: 'sasaki2', address: '東京都港区...', email: 'sasaki2@sios.jp' } const user = service.create(body) return NextResponse.json('ok') } service/index.ts import { inject, injectable } from "inversify"; import { IUserService } from "../interface/service"; import { UserRepository } from "../repository"; import { User } from "../type"; import TYPES from "../type/symbol/type"; import type { IUserRepository } from "../interface/repository"; @injectable() export class UserService implements IUserService{ constructor( @inject(TYPES.IUserRepository) private readonly repository: IUserRepository ){} get(userId: string){ return this.repository.getById(userId) } create(user: User) { this.repository.create(user) } } repository/index.ts import { injectable } from "inversify"; import { IUserRepository } from "../interface/repository"; import { User } from "../type"; @injectable() export class UserRepository implements IUserRepository { constructor(){} getById(id: string): User { return { id: id, name: 'kanta sasaki', email: 'sasaki@sios.jp', address: '東京都港区....' } } create(user: User): void { // prisma.create({}) ... } } Point 依存される側のclassには @injectable() のデコレーターを付与する コンストラクタでDIコンテナを用いて依存解決する場合には @inject(識別子) private readonly repository: IUserRepository のように依存解決を行うことができ @inject デコレーターの引数に識別子を入れることによって inversify.config.ts で定義した関連付けに応じで解決することができる コンストラクタを使用しない場合には const service = diContainer.get<IUserService>(識別子) のような形で依存解決を行うことができる DIコンテナの初期化 最後にサーバー起動時にDIコンテナを初期化しておきましょう Next.js15より next.config に instrumentationHook:true を追加しなくても instrumentation.ts という名前のファイルを作成すればサーバー起動時に一回だけ読み込んでくれるようなのでこちらを使用します import 'reflect-metadata'; export async function register() { if (process.env['NEXT_RUNTIME'] === 'nodejs') { await import('./inversify.config'); } } こんな感じでAPIからユーザー情報が取得できていると思います。 またDIコンテナで依存関係を解決した後の型を見てみると IUserRepository となっているため抽象に依存していることがわかります。 これによってテストの際に使用する具象クラスの入れ替えも非常に楽になります。 使ってみた感想 inverifyJSを使用してみて非常にシンプルで軽量なライブラリのためキャッチアップも非常に楽で直感的に使えるライブラリだと感じました。 もちろんDIを使わないものと比べたら冗長な感じになりますが、それ以上に受けられる恩恵は大きいと感じています。 付録 各種バージョンの確認にお使いください { "name": "dicontainer", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev --turbopack", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "inversify": "^7.0.0-alpha.5", "next": "15.2.4", "react": "^19.0.0", "react-dom": "^19.0.0", "reflect-metadata": "^0.2.2" }, "devDependencies": { "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "tailwindcss": "^4", "typescript": "^5" } } ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Next.jsでDIコンテナを導入する方法(inversify編) first appeared on SIOS Tech. Lab .
こんにちは PS SLの佐々木です。 今回SBOMの導入ガイドをリリースしたので紹介させてください。 SBOM導入ガイドでは私のいるチームで1年間SBOMに関する調査検証をした中で、事前に整理をしておきたかったポイントや観点、導入にあたって悩ましかったポイントなどを整理し、スムーズにSBOMを導入するためのガイドになっています。 是非SBOMの導入を考えている方に読んでいただきたいと思います。 SBOMとは? 近年、ソフトウェアのサプライチェーン管理の重要性がますます高まっています。その中で注目されているのが SBOM(Software Bill of Materials) です。 SBOMは、ソフトウェアを構成するすべてのコンポーネントのリストを明示し、ソフトウェアの透明性を向上させる役割を果たします。特に、セキュリティリスクの特定やライセンス管理の観点で、多くの企業がSBOMの導入を進めています。 なぜSBOMが重要なのか? 脆弱性管理の強化 :使用しているソフトウェアコンポーネントの脆弱性を素早く把握できる。 ライセンスコンプライアンスの向上 :不適切なライセンス使用を防ぐために、すべてのコンポーネントのライセンスを確認可能。 ソフトウェアサプライチェーンの透明性 :外部提供ソフトウェアの構成を把握し、サイバー攻撃対策を強化。 SBOM導入ガイドの概要 今回、SBOMの基礎から導入方法までを詳しく解説した 「SBOM導入ガイド」 を無料でダウンロードできるようにしました! 本書は、以下のような方々に最適な内容となっています。 SBOMの基礎を学びたい方 ソフトウェアサプライチェーンの管理に関心がある方 実際にSBOMを導入しようと考えている開発者やセキュリティ担当者 本ガイドのポイント SBOMの基本概念を解説 SBOMの導入ステップを具体的に紹介 SBOMを運用する際の注意点やアンチパターンを解説 ダウンロードはこちら SBOM導入ガイドを読んで、ソフトウェアサプライチェーンの透明性とセキュリティを向上させましょう! [ダウンロードリンク] (https://mk.sios.jp/sbom-first-guide-form) [プレスリリース] (https://sios.jp/news/press/2025/20250408-sbom.html) ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post SBOM導入ガイド公開しました! first appeared on SIOS Tech. Lab .
はじめに こんにちはサイオステクノロジーの小野です。今回はOpenShift AIのモデルレジストリ機能について解説します。この機能を利用することで、モデルの各種情報を整理することができ、管理がしやすくなります。 モデルレジストリは2025年4月4日現在テクノロジープレビューです。この機能はサポート対象外であることと、製品版では変更される可能性があることに注意してください。 モデルレジストリ モデルレジストリはMLOpsにおける機械学習モデルの数々のメタデータを保持する機能です。この機能により、モデルのバージョン管理を行うことができるため、実験を再現したり、モデルの追跡を行ったり、簡単にモデルのデプロイを行えたりします。 以下の内容をモデルまたはそのバージョンごとに登録することが可能です モデルのS3ストレージ保管場所 モデルソースのフォーマット モデルのバージョン モデルの所有者 最終変更タイムスタンプ 説明文 ラベル プロパティ モデルレジストリ構築方法 前提条件 導入Operator Red Hat Authorino Operator Red Hat OpenShift Serverless Operator Red Hat OpenShift Servicemesh Operator Red Hat OpenShift AI Operator バージョン 2.14以上 S3ストレージにモデルを保存済み OpenShift AI構築済み OpenShift AIの構築は以前の記事を参考にしてください OpenShift AI を導入してみた DataScienceClusterを作成する際に、modelregistryコンポーネントをManagedにします。 DataScienceClusterのmodelregistryコンポーネントをManagedにする OpenShift AIの管理者権限を持つ OpenShift AI Operatorインストール時に作成されるグループにOpenShift AIにログインするユーザーを追加してください。 rhods-adminsグループに管理者権限を持たせるユーザーを追加する DB作成 モデルレジストリに登録するメタデータはDBに保存されます。そのため、最初にDBを作成します。 以下のyamlでリソースを作成してください。モデルレジストリ用のnamespaceのrhoai-model-registriesにMySQLのコンテナを作成します。MYSQL_ROOT_PASSWORD、MYSQL_DATABASE、MYSQL_USER、MYSQL_PASSWORDの環境変数は各自設定してください。 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc namespace: rhoai-model-registries spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi --- apiVersion: v1 kind: ConfigMap metadata: name: mysql-config namespace: rhoai-model-registries data: my.cnf: | [mysqld] default_authentication_plugin=mysql_native_password --- apiVersion: apps/v1 kind: Deployment metadata: name: mysql namespace: rhoai-model-registries spec: selector: matchLabels: app: mysql replicas: 1 template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:8.0 env: - name: MYSQL_ROOT_PASSWORD value: <MySQLのルートパスワード> - name: MYSQL_DATABASE value: <MySQLのデータベース> - name: MYSQL_USER value: <MySQLのユーザー名> - name: MYSQL_PASSWORD value: <MySQLのパスワード> ports: - containerPort: 3306 name: mysql volumeMounts: - name: mysql-persistent-storage mountPath: /var/lib/mysql - name: mysql-config-volume mountPath: /etc/mysql/my.cnf subPath: my.cnf volumes: - name: mysql-persistent-storage persistentVolumeClaim: claimName: mysql-pvc - name: mysql-config-volume configMap: name: mysql-config --- apiVersion: v1 kind: Service metadata: name: mysql namespace: rhoai-model-registries spec: ports: - port: 3306 targetPort: 3306 selector: app: mysql mysqlのリソースを作成する mysqlというDeploymentsによりpodがrhoai-model-registries内に作成されます。 リソースを作成するとmysqlのpodが作成される モデルレジストリ設定 DBの作成が完了したら、モデルレジストリの設定を行います。OpenShift AIに管理者権限を持っているアカウントでOpenShift AIにログインします。 Setting > Model Registry Settingsを開きます。 Setting > Model Registry Settingsを開く Create model registryを押下すると設定画面が表示されるので以下のように設定します: Name:モデルレジストリ名 Resource Name:モデルレジストリ名と同じ Connect to external MySQL database Host:mysqlのホスト名(yamlと同じ設定の場合mysql) DBが rhoai-model-registries とは異なる namespace で実行されている場合は、ホスト名を <host name>.<namespace>.svc.cluster.local 形式で入力します。 Port:mysqlのポート番号(yamlと同じ設定の場合3306) Username:MYSQL_USERに設定したユーザー名 Password:MYSQL_PASSWORDに設定したパスワード Database:MYSQL_DATABASEに設定したデータベース名 モデルレジストリを作成する モデルレジストリのStatusがAvailableになれば作成完了です。 StatusがAvailableになれば作成完了 モデルの登録 モデルレジストリの作成が完了すると、左のメニューのModel Registryからモデルの登録ができるようになります。 メニューのModel Registryからモデルの登録を行う Registry modelを押下するとモデルの登録ができます。各パラメータは以下のように設定します: Model details:モデル名 Version details:登録するモデルのバージョンとモデルの形式情報 Model location:モデルが保存されているS3オブジェクトストレージの接続情報 モデルの登録設定 登録が完了するとモデル名とVersionsの欄に登録したモデルのバージョンが表示されます。 登録するとモデルのバージョンが表示される 登録したバージョンを開くと登録した際に入力したメタデータが閲覧できます。 モデルのメタデータの閲覧 Description、Labels、Propertiesもここで編集できます。 Description、Labels、Propertiesも編集可能 新しいバージョンの登録 レジストリにモデルの新しいバージョンを登録するには、登録したモデルの画面からRegister new versionを押下します。 Register new versionから新しいバージョンの登録を行える モデルの登録したときと同じように新しいバージョン名と新しいモデルのS3の接続情報を入力します。 新しいバージョンのモデル情報を登録する 入力すると、モデルの新しいバージョンの登録ができます。 新しいバージョンが追加される モデルのデプロイ モデルレジストリを利用することで、登録したモデルのデプロイを行うことができます。 登録したモデルのバージョンの詳細画面のActionsからDeployを選択します。 ActionsのDeployからモデルデプロイを行える モデルをデプロイするデータサイエンスプロジェクトを選択して、デプロイ設定を行います。設定方法は以前の記事を参考にしてください。 OpenShift AIにLLMをデプロイしてみた モデルデプロイ設定 バージョンのDeplymentsの欄にデプロイしたモデル名が表示され、Statusに がつけばデプロイ完了です。 Statusに がつけばデプロイ完了。ここからモデルAPIのエンドポイントを取得できる。 モデルのアーカイブ モデルをアーカイブするには、バージョンの詳細画面のActionsからArchive model versionを選択します。 ActionsのArchive model versionからモデルのアーカイブができる バージョン名を入力すればアーカイブできます。 バージョン名を入力するとモデルをアーカイブできる アーカイブ完了 モデルの復元 アーカイブしたモデルを復元することが可能です。モデルのVersionsの三点メニューを開いて、View archived versionsを選択します。 三点メニューのView archived versionsからアーカイブしたモデルのバージョン一覧を表示できる アーカイブしたモデルバージョンの一覧が表示されるので、復元したいバージョンのモデルを開いて、Restore model versionを選択することでモデルの復元が実行されます。 アーカイブされたモデルのバージョン一覧 アーカイブされたモデルバージョンの詳細。Restore model versionにより復元できる。 モデル復元完了 バージョン単位ではなくモデル自体のアーカイブと復元も同様に行えます。 モデル単位でのアーカイブ、復元も可能 おわりに 以上により、モデルレジストリのDB作成、モデルレジストリの登録、モデルメタデータの登録、モデルのデプロイ、モデルのアーカイブ・復元について解説しました。 MLOpsにおいてAIモデルの更新が行われるため、その管理というのは非常に重要になってきます。ぜひモデルレジストリを活用することで、モデルの管理に役立ててください。 参考 モデルレジストリーの操作: https://docs.redhat.com/ja/documentation/red_hat_openshift_ai_self-managed/2.16/html/working_with_model_registries/index モデルレジストリーの管理: https://docs.redhat.com/ja/documentation/red_hat_openshift_ai_self-managed/2.16/html/managing_model_registries/index ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift AIのモデルレジストリ機能を使ってみた first appeared on SIOS Tech. Lab .
  こんにちは、サイオステクノロジーの佐藤 陽です。 相変わらずCosmosDBについての勉強しているので、引き続きアウトプットしていきたいと思います。 今回のテーマはCosmosDBでのベクトル検索についてです。 ベクトル検索って何? CosmosDBでどうベクトル検索を実装するの? RAGにCosmosDBを組み込みたい! といった方は是非最後までご覧ください! はじめに 2024年のMicrosoft IgniteにてCosmosDBのベクトル検索機能がGAとなることが発表されました。 同年のMicrosoft BuildではまだPublic Previewでしたが、これで本番環境でも安心して利用できます。 このベクトル検索ですが、昨今の生成AIのアプリケーションと非常に相性が良いです。 特にRAG(Retrieval Augmented Generation)ではベクトル検索がよく使われており、CosmosDBをRAGに導入するといったパターンが今後主流になってくるのではないかと思います。 そこで本記事では、「ベクトル検索とは?」といった点からCosmosDBでのベクトル検索の実装まで一通りご紹介したいと思います。 余談 本記事は JAZUG Shizuoka での登壇資料をベースとしているため、内容がやや静岡寄りのものとなっています。 そして是非、JAZUG Shizuokaが開催するイベントへも参加いただければと思います! ベクトル検索とは? ではまずベクトル検索についてご紹介します。 生成AIを活用するうえでベクトルは非常に重要な要素です。 高校生の時にベクトルとは「大きさ・向きを持つもの」として習い X,Y平面上に矢印を書いた図をたくさん見たかと思いますが、まさにあれです。 今回の記事においては、文章や画像などをベクトル化します。 例えば「犬」「猫」「花」の3つの単語をベクトル化すると、それぞれ以下のような値で表現されます。 (ベクトル値としては1000を超える次元数であるため一部のみ掲載します) 犬 猫 花 ベクトル値 [-0.019726261, -0.014364496, -0.011311122,…] [-0.013889334, -0.050191004, -0.03891719, …] [0.02033748, 0.027342353, 0.017839076, …] そしてこのベクトル値の特徴として、 似たような使われ方をする単語 は似たような値を取ることが言われています。 例えば 私は毎朝、犬にエサをあげる 私は毎朝、猫にエサをあげる といったような使い方はしますが 私は毎朝、花にエサをあげる といった使い方はしませんよね。 このように、同じような使われ方をする単語は、似たようなベクトル値を持ちます。 今回はこの「似たような値」を評価するためにコサイン類似度を利用します。 犬, 猫, 花の3つの単語のベクトルア値、それぞれの組み合わせでコサイン類似度を算出した値を以下に示します。 犬&猫 犬&花 猫&花 0.6180 0.4022 0.3522 この結果から、「犬」と「猫」のベクトル値の相関が高くなり、近しい意味を持つことを表しています。 人間の感覚からしたら明らかな結果ですが、コンピューターが定量的な値としてこの意味の近さを扱えることは大きなメリットです。 この仕組みを利用したのが ベクトル検索 です。 ベクトル検索は、ユーザーからの質問(クエリ)をベクトル化し、データベースなどから似たようなベクトル値を持つものを算出します。 これにより、キーワード的には一致していないとしても、意味的に近しいものをデータベースから取得することが可能となります。 CosmosDBでのベクトル検索 では実際にCosmosDBにおけるベクトル検索の例を見てみたいと思います。 まず初めに検索対象となるデータをCosmosDBに格納します。 今回は、静岡の観光地をテーマに格納するデータを用意しました。 観光地名 説明 富士山 世界文化遺産に登録された、標高3,776メートルの日本一高い象徴的存在の山。四季を通じて登山や観光で多くの人が訪れ、山頂からの日の出は特に有名。 伊豆半島 地中海のような青い海と豊富な自然が魅力的なリゾート地。温泉や海水浴、ダイビングなどのマリンスポーツが楽しめる。また、伊豆七島を望む絶景ポイントも多数存在する。 三島スカイウォーク 日本最長の歩行者専用吊り橋で、全長400メートル。橋の上からは富士山や駿河湾の壮大な景色を一望でき、特に晴れた日には絶景が広がる。 熱海温泉 江戸時代から続く歴史ある温泉地。海辺に多くの旅館が立ち並び、海を眺めながらの露天風呂が楽しめる。また、芸術作品や熱海の花火大会も観光の大きな魅力の一つ。 日本平 静岡市内からロープウェイでアクセス可能な展望公園。富士山や駿河湾の大パノラマを背景に、季節ごとの花々が美しい。 静岡県立美術館 静岡市内に位置し、地元出身の画家、レオナール・フジタの作品を中心に展示。また、世界的に著名な画家の作品も常設展示され、アートファンには見逃せないスポット。 清水エスパルスドリームプラザ 清水区にある大型のショッピングモールで、レストラン、ショップ、映画館、水族館などが集まる。家族連れで一日中楽しめる。 浜松城公園 浜松市にある城址公園で、徳川家康ゆかりの地。春には桜が咲き誇り、多くの花見客で賑わう。城内には歴史資料館もあり、歴史好きにはたまらない。 久能山東照宮 富士山の麓、久能山の山頂に鎮座する神社で、徳川家康を祀っている。豪華絢爛な彫刻や装飾が施された建物は国宝に指定されており、日本の伝統美を感じさせる。 沼津港深海水族館 沼津港に隣接する水族館で、深海に生息する珍しい生き物たちを展示。普段はなかなか見ることのできない深海生物の神秘的な世界を体験できる。 この項目に対して以下の処理を行います。 ベクトル化 CosomosDBへの登録 ベクトル化 まずはそれぞれのコンテンツをベクトル化します。 今回は 観光地名 と 説明 の2列に分かれているものを、一つの文字列としてベクトル化していきます。 ベクトル化するにあたってはEmbeddingモデルが必要となるので事前にデプロイしておきましょう。 今回はAzure OpenAI Service上で、 text-embedding-3-small のモデルをデプロイしておきました。 そのうえで今回は以下のような実装を行いました。 url = "https://{AOAIのエンドポイント}/openai/deployments/{Embeddingのモデル名}/embeddings?api-version=2023-05-15" content = [ "富士山 - 世界文化遺産に登録された、標高3,776メートルの日本一高い象徴的存在の山。四季を通じて登山や観光で多くの人が訪れ、山頂からの日の出は特に有名。", "伊豆半島 - 地中海のような青い海と豊富な自然が魅力的なリゾート地。温泉や海水浴、ダイビングなどのマリンスポーツが楽しめる。また、伊豆七島を望む絶景ポイントも多数存在する。", "三島スカイウォーク - 日本最長の歩行者専用吊り橋で、全長400メートル。橋の上からは富士山や駿河湾の壮大な景色を一望でき、特に晴れた日には絶景が広がる。", "熱海温泉 - 江戸時代から続く歴史ある温泉地。海辺に多くの旅館が立ち並び、海を眺めながらの露天風呂が楽しめる。また、芸術作品や熱海の花火大会も観光の大きな魅力の一つ。", "日本平 - 静岡市内からロープウェイでアクセス可能な展望公園。富士山や駿河湾の大パノラマを背景に、季節ごとの花々が美しい。", "静岡県立美術館 - 静岡市内に位置し、地元出身の画家、レオナール・フジタの作品を中心に展示。また、世界的に著名な画家の作品も常設展示され、アートファンには見逃せないスポット。", "清水エスパルスドリームプラザ - 清水区にある大型のショッピングモールで、レストラン、ショップ、映画館、水族館などが集まる。家族連れで一日中楽しめる。", "浜松城公園 - 浜松市にある城址公園で、徳川家康ゆかりの地。春には桜が咲き誇り、多くの花見客で賑わう。城内には歴史資料館もあり、歴史好きにはたまらない。", "久能山東照宮 - 富士山の麓、久能山の山頂に鎮座する神社で、徳川家康を祀っている。豪華絢爛な彫刻や装飾が施された建物は国宝に指定されており、日本の伝統美を感じさせる。", "沼津港深海水族館 - 沼津港に隣接する水族館で、深海に生息する珍しい生き物たちを展示。普段はなかなか見ることのできない深海生物の神秘的な世界を体験できる。" ] headers = {   'Content-Type': 'application/json',   'api-key': '{api-key}' } results = [] for spot in content:     payload = json.dumps({       "input": spot     })     response = requests.request("POST", url, headers=headers, data=payload)     response_data = response.json()     embedding = response_data['data'][0]['embedding']     result = {         "content": spot,         "contentVector": embedding     }     results.append(result) ここでresultとして出力された内容を一つ見てみます。 {     "content": "富士山 - 世界文化遺産に登録された、標高3,776メートルの日本一高い象徴的存在の山。四季を通じて登山や観光で多くの人が訪れ、山頂からの日の出は特に有名。",     "contentVector": [         0.015276342,         -0.04262919,         -0.010207734,         0.027943453,         0.033972893,         ...     ] } このように、元の情報(content)と、その値をベクトル化した値(contentVector)が用意できました。 CosmosDBへの登録 事前準備 ではこの用意出来た値をCosomosDBに登録してきます。 CosomosDBにベクトル値を登録するには事前準備が必要となるため、以下に手順を示します。 コンテナ作成時にベクトルポリシーを追加します。 以下が設定項目です。 パラメータ 概要 Path ベクトル値として扱うパラメータのパスです。今回は/contentVectorが対象となります。 Data データのタイプです。今回扱うEmbeddingモデルが float32で出力する ため、これに合わせてfloat32に設定します。 Distance function ベクトル間の距離を測るための関数です。こちらは先程ご紹介したコサイン類似度を利用します Dimensions ベクトルの次元数です。こちらは今回扱うEmbeddingモデルの次元数が1536となっているため、この値を設定します。 Index type インデックス方式です。このあたりは検索精度に関わってきますが、今回は詳細な説明は割愛します。diskANNとします コンテナ作成完了後、Settingsファイルを確認します。 先程設定した内容が正しくポリシーとして登録されていることが確認できます。 データアップロード 準備が出来たところで、こちらのコンテナに先程のデータを格納していきます。 今回は、先程のベクトル化の処理の最後に出力結果をjsonファイルとして出力しておき、その内容を以下のコードで改めてアップロードします。 # CosmosDBの接続情報 endpoint = "{CosnosDBのエンドポイント}" key = "{Key}" database_name = "sios-database" container_name = "vector-container" # CosmosDBクライアントの作成 client = CosmosClient(endpoint, key) database = client.get_database_client(database_name) container = database.get_container_client(container_name) # JSONファイルをアップロードする関数 def upload_json_to_cosmosdb(file_path):     with open(file_path, 'r', encoding='utf-8') as f:         data = json.load(f)         # idフィールドを追加         data['id'] = data['content']         container.upsert_item(data) # 先程出力したベクトル値を含むJSONファイルをアップロード # 今回は簡易的に`result_`から始まるファイルを指定 for file_name in os.listdir('.'):     if file_name.startswith('result_') and file_name.endswith('.json'):         upload_json_to_cosmosdb(file_name)         print(f"Uploaded {file_name} to CosmosDB") print("All files have been uploaded.") このコードを実行した後にCosmosDBのデータエクスプローラを見てみると、無事にデータが登録されていることが確認できました。 ベクトル検索 次に格納されたデータに対して検索を行っていきます。 今回は以下のような検索を行ってみたいと思います。 「景色が良い所は?」 まずは、この質問(クエリ)をベクトル化します。 先程と同様にEmbeddingモデルを利用してベクトル化したところ以下のような結果となりました。 [−0.01532, −0.02434, −0.05363, ...] この値を利用して検索を行います。 検索クエリとしては以下の通りです。 -- データベース内のコレクション "c" から、最も類似した10件のデータを取得するクエリ SELECT TOP 10     c.content, -- 各ドキュメントの "content" フィールドを取得     VectorDistance(        c.contentVector, -- ドキュメント内のベクトルデータ        [0.0015812921, -0.01822265, -0.011891554,...] -- クエリで指定したターゲットベクトル     ) AS SimilarityScore -- ベクトル間の距離を "SimilarityScore" として取得 FROM c -- ベクトル間の距離(類似度)で昇順に並べ替え ORDER BY VectorDistance(c.contentVector, [0.0015812921, -0.01822265, -0.011891554,...] ) これにより、CosmosDB上から最も類似したデータを検索することが可能です。 実行した結果を以下に示します。 順位 コンテンツ 類似度スコア 1 日本平 – 静岡市内からロープウェイでアクセス可能な展望公園。富士山や駿河湾の大パノラマを背景に、季節ごとの花々が美しい。 0.5055713624352297 2 伊豆半島 – 地中海のような青い海と豊富な自然が魅力的なリゾート地。温泉や海水浴、ダイビングなどのマリンスポーツが楽しめる。また、伊豆七島を望む絶景ポイントも多数存在する。 0.3731433864334767 3 久能山東照宮 – 富士山の麓、久能山の山頂に鎮座する神社で、徳川家康を祀っている。豪華絢爛な彫刻や装飾が施された建物は国宝に指定されており、日本の伝統美を感じさせる。 0.3712187302734037 4 三島スカイウォーク – 日本最長の歩行者専用吊り橋で、全長400メートル。橋の上からは富士山や駿河湾の壮大な景色を一望でき、特に晴れた日には絶景が広がる。 0.37086192839082927 5 熱海温泉 – 江戸時代から続く歴史ある温泉地。海辺に多くの旅館が立ち並び、海を眺めながらの露天風呂が楽しめる。また、芸術作品や熱海の花火大会も観光の大きな魅力の一つ。 0.34883694499412393 6 浜松城公園 – 浜松市にある城址公園で、徳川家康ゆかりの地。春には桜が咲き誇り、多くの花見客で賑わう。城内には歴史資料館もあり、歴史好きにはたまらない。 0.3407391717527575 7 富士山 – 世界文化遺産に登録された、標高3,776メートルの日本一高い象徴的存在の山。四季を通じて登山や観光で多くの人が訪れ、山頂からの日の出は特に有名。 0.31416708979179037 8 静岡県立美術館 – 静岡市内に位置し、地元出身の画家、レオナール・フジタの作品を中心に展示。また、世界的に著名な画家の作品も常設展示され、アートファンには見逃せないスポット。 0.30245339778589064 9 清水エスパルスドリームプラザ – 清水区にある大型のショッピングモールで、レストラン、ショップ、映画館、水族館などが集まる。家族連れで一日中楽しめる。 0.2622979141244738 10 沼津港深海水族館 – 沼津港に隣接する水族館で、深海に生息する珍しい生き物たちを展示。普段はなかなか見ることのできない深海生物の神秘的な世界を体験できる。 0.17702736397602103 このように、各観光地の概要の中に、「景色が良い」といった直接的なワードは含まれていないにも関わらず、景色がよさそうな観光地が上位の検索結果に表れました。 これは以下に示すような 「コンテンツに含まれている文章のベクトル値」 と、 「”景色が良い所は?”の文章のベクトル値」 が近い値を取った結果であると予想されます。 富士山や駿河湾の大パノラマを背景に、季節ごとの花々が美しい。 伊豆七島を望む絶景ポイントも多数存在する。 富士山の麓、久能山の山頂に鎮座する神社 これにてベクトル検索が完了です! 何となくイメージはつかめていただけたのではないでしょうか? 注意点 ベクトル検索で扱う ベクトル値 は、膨大な学習データに基づいて算出されています。 そのため、一般的な単語に対するベクトル値はある程度正確に算出することができますが、ユニークな単語などは苦手です。 例えば社内で「SIOS Innovation Program」といったオリジナルの制度があったとし、通称「SIP」と呼ばれているとします。 この場合、SIPの制度に関連した情報についてベクトル検索を行おうとした場合、期待した結果が得られない場合があります。 これは、SIPもしくはSIOS Innovation Programが一般的な単語ではなく、適切にベクトル化が行えないためです。 こういったケースはベクトル検索よりも、キーワード検索が適していると言われています。 このように必ずしもベクトル検索が優れているわけではなく、ケースに応じて検索方法を切り替える必要があります。 そして、このキーワード検索とベクトル検索を組み合わせたハイブリッド検索といった強力な検索手法も活用されているのですが 2025年のBuildにてCosmosDBでもベクトル検索の機能がGAされるとうわさされています。 また実際にGAされたら試してご紹介したいと思うので期待ください! おわり 本日はCosmosDBのベクトル検索の機能をご紹介しました。 CosmosDBでのベクトル検索機能がGAされたことにより、より生成AIソリューションとの親和性が高まり、今後の活用が期待されます。 また、ハイブリッド検索機能のGAも噂されていることにより、より一層の期待ができます。 これを機会にCosmosDBを是非活用してみてください! ではまた! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【Azure】CosmosDBにおけるベクトル検索入門ガイド【初心者向け】 first appeared on SIOS Tech. Lab .
こんにちは。サイオステクノロジーの橋本です。 皆さんは Ansible で環境構築をしているものの一回の実行時間がちょっと長くて… という事はありませんか 自動化してもやっぱり時間がかかるパッケージインストールをちょっと早くする方法を紹介します。 今回は以下の 4 回 dnf を実行している Playbook に関して、 1 回の dnf 実行に集約してます。 - name: "httpd のインストール"   ansible.builtin.dnf:     name: httpd   when:   - ansible_distribution_major_version == "9" - name: "DNS (bind) のバージョン指定" set_fact: bind_version: 9.16 - name: "DNS (bind) のインストール" ansible.builtin.dnf: name: "bind{{ bind_version }}" when: - ansible_distribution_major_version == "8" - name: "wget のインストール" ansible.builtin.dnf: name: wget - name: "sos のインストール" ansible.builtin.dnf: name: sos 上記 Playbook はわかりやすいというメリットは有るものの 4 回 dnf を実行しているため 都度都度 dnf モジュールを実行し毎回リポジトリのチェックなどが入りその分処理時間が長くなります。 そのため、dnf を可能な限り少ない回数にして、リポジトリチェックなどの回数 を抑えようという発想です。 Step 1 ドキュメント にもあるように dnf モジュールはパッケージ名を配列で渡すことができます。 まずは sos と wget を配列で渡しましょう。 Step 2 で活きてきますが配列は事前に定義します。 - name: "インストールパッケージの定義" ansible.builtin.set_fact: packages: - wget - sos - name: "必要パッケージのインストール" ansible.builtin.dnf: name: "{{ packages }}" ここまではよくある手順ですね。 Step 2 さて、問題は以下です。 OS や サーバの役割によってインストールパッケージが異なる運用はよくあるとおもいます。 そして、それが dnf の複数回実行になることもよくあるケースだと思います。 when 句で条件分岐していても、以下のように set_fact すれば同様の挙動をしてくれます。 - name: "インストールパッケージの定義" ansible.builtin.set_fact: packages: - wget - sos - name: "httpd を配列に追加" ansible.builtin.set_fact: packages: "{{ packages + \ ['httpd'] }}" when: - ansible_distribution_major_version == "9" - name: "DNS (bind) のバージョン指定" set_fact: bind_version: 9.16 - name: "bind を配列に追加" ansible.builtin.set_fact: packages: "{{ packages + \ ['bind{{ bind_version }}'] }}" when: - ansible_distribution_major_version == "8" - name: "必要パッケージのインストール" ansible.builtin.dnf: name: "{{ packages }}" 当初とインストールするパッケージに変わりはないですが、 dnf モジュールを呼び出す回数は 1 回になっているため処理時間も大幅に短くなります。 Ansible の処理速度が遅いとき、上記のようにパッケージのインストールを集約するのを検討してみてはいかがでしょうか。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Ansible をちょっと早く実行する dnf (yum) tips first appeared on SIOS Tech. Lab .
こんにちは、OSSよろず相談室のSKです。 日々、多くのOSSに関するお問い合わせをいただいているのですが、今回は、そもそもOSS(オープンソースソフトウェア)とはどんなものなのかというお話です。 オープンソースとは まず、座学的な話になりますが、オープンソースとは、 主に オープンソース・イニシアティブ(OSI) によって推進される概念で、実用性や協調開発を重視しています。 重視されることは、透過性(公開されていること)実用性、協調開発されコミュニティがあることです。 逆に見た目やデザイン、UI(使い勝手)、利益などは軽視され、サポートはありません。 OSIに掲載された10個の定義はこちらです。 オープンソースの定義 上記オープンソースの定義は、主に以下の内容について定義しています。 ソースコードの公開 – プログラムが実行ファイルとともにソースコードも提供・公開されること。 改変と配布の許可 – 誰でも改変や配布ができること。 差別の禁止 – 特定の人や団体に対する差別的な制限を設けないこと。 ここで疑問に思うことは、「いわゆるフリーウェアと何が違うのだろう?」だと思います。 フリーウェアはOSSと同様に無償ですが、プログラムの中身は公開されていないことが多いです。 公開されていないので、改変もできません。 OSSとフリーウェアの大きな違いは、この 「ソースコードが公開されている」 ことと、 「改変できる」 という点です。 OSSは皆で使おう!という精神が強くあります。 「世界中皆で使う」ものであるはずなのに、2024年10月にLinuxカーネルのメンテナーからロシア人が削除されたことが物議となりました。 以下は Linuxカーネルのメーリングリストのアーカイブが公開されたもの の一部です。差分情報がdiffとして記録されていますが、ロシアのドメインを示す「.ru」のメンテナー「M」が「-」で削除されていることが分かります。 Linuxの生みの親である Linus Torvalds 氏自ら「 I’m Finnish. Did you think I’d be supporting Russian aggression? (フィンランド人の私がロシアの侵略を支持すると思いますか?)」と言及しています。 これは OSS の定義に反するのではないか?と物議を醸しました。 OSSライセンスの探し方 それでは、OSSライセンスが具体的にどのように表記されているのか、見てみましょう。 例えば、Tomcatを見てみます。 ソースコードはGitHubで公開されています。 Apache Tomcatのソースコード OSSライセンスの記載場所は以下の4か所です。 ソースコード群に同梱されているテキストファイル ソースコードファイルのヘッダ プロジェクト公式Webサイト 製品に組み込みのドキュメント 「1.ソースコード群に同梱されているテキストファイル」を見てみましょう。 以下はソースコード群の中身です。 OSSライセンスは、ソースコード群にテキストファイルで同梱されています。 LICENSEファイル を開くと以下のようになっています。 Apache License Version 2.0 であることが明記されています。 Apache LicenseはOSSライセンスの1つです。 ここに書かれた http://www.apache.org/licenses/ をクリックすると、ライセンスの内容を見ることができます。 OSSライセンスを適用する では、自分のソフトウェアにApacheライセンスを適用する方法を紹介します。 適用イメージ 自分のソフトウェアにApacheライセンス適用する方法 全ソースコードの各ファイルの冒頭に、指定されたライセンスの告知文(license notice)を追加する必要があります。 例えばApacheライセンスの場合、 Apacheライセンス に明記されています。 付録: Apache Licenseの適用の仕方 あなたの製作物にApache Licenseを適用するときは、次の定型文を添付してください。ただし、"[]"で囲まれている部分は、あなた自身の識別情報に置き換えてください(その際、角括弧は取り除きます)。また、この文言を該当するファイル形式に合ったコメント構文で囲んでください。さらに、第三者アーカイブ内での識別を容易にするため、ファイル名またはクラス名ならびに趣旨説明が著作権表示と同じ「印刷ページ」に現れるようにすることをお勧めします。 Copyright [yyyy] [著作権所有者の名前] Apache License Version 2.0(「本ライセンス」)に基づいてライセンスされます。あなたがこのファイルを使用するためには、本ライセンスに従わなければなりません。本ライセンスのコピーは下記の場所から入手できます。 http://www.apache.org/licenses/LICENSE-2.0 例えば、Tomcat も Apache ライセンスを適用したソフトウェアです。 ossライセンスの探し方 で紹介した Tomcat が公開された GitHub の中から、jav aのファイルを選んでみましょう。 全てのjavaのソースコードの先頭にライセンスが記載されていることが確認できます。 OSSライセンスソフトを同梱する方法 次に、自分のソフトウェアにApacheライセンスを適用したTomcatを同梱する方法をご案内します。 さきほどの 自分のソフトウェアにApacheライセンス適用する方法 では、全てのソースコードの先頭にライセンスを表記しないといけませんでしたが、同じことをしなければいけないでしょうか? 答えは No です。 Tomcat内にあるLICENSEファイルとNOTICEファイルを入れ、readmeファイルにTomcatが入っていることを明記すればよいだけです。 今日のオープンソースの話はここまでにします。 次回は コピーレフト オープンソースにまつわるリアルな事例 についてご紹介します。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post オープンソースライセンスとは 1 first appeared on SIOS Tech. Lab .
はじめに アプリケーションのコンテナ化が一般的になった現在、コンテナイメージをどこに保存し、どうやって配布・管理するかは非常に重要な課題となっています。 本記事では、コンテナプラットフォーム向けのコンテナレジストリ選択肢として Red Hat Quay・Harbor・パブリッククラウドのマネージドイメージレジストリそれぞれの特徴について解説します。 各コンテナレジストリソリューションの概要 Red Hat Quay Red Hat QuayはRed Hat社が提供する セルフホスト型 のオープンソースコンテナレジストリです。 オープンソース版と有償版が存在し、アプリケーションの特性に応じて選択できます。 特徴 GitHubなどソースリポジトリからのプッシュイベントをトリガーにした自動ビルド機能が充実 地理的レプリケーションな機能によりグローバルにイメージを分散させることで多拠点環境下における高可用性と高パフォーマンスを実現 Red Hat社が提供する信頼性ある有償サポート付き RH社製品であるOpenShiftとの統合のしやすさ 開発からコンテナプラットフォームへのデプロイを高度に自動化したい開発チームや 既にOpenShift環境を利用しているチームなどでの利用が特に見込まれます。 Harbor HarborはVMware社が開発した セルフホスト型 のオープンソース コンテナレジストリです。 CNCFプロジェクトとなっており、他ツールとの連携も考慮しながら選択できます。 特徴 Kubernetesとの連携を前提とした設計で、幅広いコンテナプラットフォームに導入しやすい オープンソースなので、コストを抑えて導入することが可能 マルチテナント対応:複数プロジェクトを1つのインスタンス内で分離管理可能 アクセス権限やセキュリティポリシーなどを細かく制御することが可能 プロジェクト単位の設定、プロジェクトごとの分離 コンテナに関する知識(Docker、Kubernetes、Helmなど)が豊富でオープンソースを好む文化を持つチームや 設定のカスタマイズ性の高さを重視するチームなどでの利用が見込まれます。 パブリッククラウドのマネージドイメージレジストリ Amazon Elastic Container Registry(ECR)、Azure Container Registry(ACR)、Google Artifact Registry(旧GCR)など、クラウドベンダーが提供する フルマネージド型 のコンテナレジストリです。 特徴 インフラの構築・運用・スケーリングが不要。高可用性・冗長化もベンダー側で担保 IAMやサービスアカウントでの権限管理が容易 クラウドプロバイダーが提供するCI/CDとの統合が容易 AWS: Code Pipelineなど パブリッククラウドが提供するコンテナプラットフォームを利用しているチームや レジストリ運用をマネージド化させて運用負荷を削減したいチームなどでの利用が見込まれます。 まとめ コンテナレジストリはセキュリティ面での考慮やCI/CDにおいても起点となる重要なコンポーネントです。 各パブリッククラウドでマネージドサービスとして提供される中でOSSや有償ソリューションとしても、セルフホスト型でのソリューションが選択肢として多く存在します。 他のコンポーネントとの連携や運用負荷等を考慮しながらコンテナレジストリについては選定していく事が大きなポイントとなってきます。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post コンテナレジストリを選ぶなら?Quay / Harbor / マネージドサービスそれぞれの概要解説 first appeared on SIOS Tech. Lab .
こんにちは、RAG StarterPackチームです。 日頃より多くの皆さまにご利用いただき、心より感謝申し上げます。 さて、本日2025年4月1日、私たちは重大な決断をいたしました。 「RAG スターターパック、Internet Explorerに完全対応いたしました。」 なぜIE対応なのか? 現代のブラウザは進化を遂げましたが、あの独特の青いeマークに懐かしさを感じる方も多いはず。  「RAG × レトロでエモい体験を!」という熱い思いから、  IE6〜IE11までの完全対応 に踏み切りました。 機能ハイライト Chat UIの“謎のズレ”を忠実に再現 ボタンの角丸が消滅するノスタルジー RAGの回答を3秒遅らせて、ダイヤルアップの気持ちに! ActiveX風の謎ポップアップも出るかも?(仕様です) 開発裏話 私がエンジニアになった5年前 Reactで開発中にChrome, Edgeのテストは通過して最後のIEで正常に動作せずとてもつらかった日々 「DOCTYPEを外したら動いた!」と歓喜したあの日 IEのおかげで進捗が出ず爆詰めされたあの日 実装をしているときには悩みの種でしたがいざいなくなると寂しいものです お問い合わせ方法 ブログを閲覧いただきありがとうございました。 もしRAGに興味のある方がいらっしゃいましたら こちら からご連絡お待ちしています! Happy April Fools! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【重要なお知らせ】RAG スターターパック、Internet Explorerに完全対応しました(IE6もOK) first appeared on SIOS Tech. Lab .
こんにちは、伊藤です。今回は、Application Gatewayのカスタムエラーページを構成する手順を紹介します。 Application Gatewayではデフォルトのエラーページが用意されていますが、エラー番号とエラー内容が簡易に表示されるにとどまっています。そこで、カスタムエラーページを構成していきます。 Application Gatewayの作成 Application Gatewayの解説は過去記事で紹介されているので、参考にしてみてください。 参考: https://tech-lab.sios.jp/archives/30628 Application Gatewayを作成します。今回は以下の設定とします。 基本 フロントエンド バックエンド 構成 ルーティング規則(リスナー) ルーティング規則(リスナー)ではカスタムエラーページを設定する項目があり、リスナーごとにカスタムエラーページを設定できます。今回は、Application Gateway全体(グローバルレベル)でカスタムエラーページを設定するため、ここでは未設定とします。 ルーティング規則(バックエンドターゲット) Application Gatewayの作成後、概要のフロントエンドパブリックIPアドレスを確認し、アクセスします。バックエンドターゲットが存在しないのでエラーとなり、デフォルトのエラーページが表示されます。 ストレージアカウントの作成 カスタムエラーページを配置するストレージアカウントを作成します。今回は以下の設定とします。 基本情報 詳細 ネットワーク データ保護 暗号化 ストレージアカウントの作成後、コンテナ―にてカスタムエラーページを配置します。 「errorpage」というコンテナーを匿名アクセスレベル「BLOB」で新規作成し、その中にhtmlファイル(502.html)を作成します。カスタムエラーページの条件は以下を参考にしてみてください。 参考: https://learn.microsoft.com/ja-jp/azure/application-gateway/custom-error 502.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>エラー 502 - 不正なゲートウェイ</title> </head> <body> <div class="error-container"> <h1>エラー 502 - 不正なゲートウェイ</h1> <p>申し訳ありませんが、サーバーへの接続に問題が発生しました。</p> </div> </body> </html> htmlファイルのプロパティを開いてURLを確認し、アクセスします。アクセスでき、エラーページが表示されることを確認します。 Application Gatewayのカスタムエラーページ設定 Azure PowerShell を使用して、カスタム エラー ページ(グローバルレベル)を設定します。 $appgw = Get-AzApplicationGateway -Name testgw -ResourceGroupName <resource-group-name> $updatedgateway = Add-AzApplicationGatewayCustomError -ApplicationGateway $appgw -StatusCode HttpStatus502 -CustomErrorPageUrl "https://testgwerrorpage.blob.core.windows.net/errorpage/502.html" Set-AzApplicationGateway -ApplicationGateway $appgw カスタムエラーページの確認は以下のコマンドを実行します。 $appgw = Get-AzApplicationGateway -Name testgw -ResourceGroupName <resource-group-name> $appgw.CustomErrorConfigurations カスタムエラーページがすでに設定されており、設定変更したい場合は以下のコマンドを実行します。 $appgw = Get-AzApplicationGateway -Name testgw -ResourceGroupName <resource-group-name> $updatedgateway = Set-AzApplicationGatewayCustomError -ApplicationGateway $appgw -StatusCode HttpStatus502 -CustomErrorPageUrl "<errorpage-url>" Set-AzApplicationGateway -ApplicationGateway $appgw カスタムエラーページを削除する場合は、以下のコマンドを実行します。 $appgw = Get-AzApplicationGateway -Name testgw -ResourceGroupName <resource-group-name> $updatedgateway = Remove-AzApplicationGatewayCustomError -ApplicationGateway $appgw -StatusCode HttpStatus502 Set-AzApplicationGateway -ApplicationGateway $appgw 参考: https://learn.microsoft.com/ja-jp/powershell/module/az.network/?view=azps-13.3.0#application-gateway カスタムエラーページの設定後に、Application Gatewayにアクセスします。カスタムエラーページが表示されることを確認します。 ストレージアカウントのネットワーク設定 ここまでのストレージアカウントは、全てのパブリックネットワークアドレスからアクセスが許可されています。そのため、Application Gatewayのサブネットとカスタムエラーページを管理するクライアントPCからのみアクセスできるようにします。 ストレージアカウントの「ネットワーク」を選択すると、パブリックアクセスの設定が表示されます。「Manage」を選択して設定を変更します。 「Enable from selected networks」を選択して特定のネットワークからのアクセスを許可し、許可するネットワークとしてApplication GatewayのサブネットとクライアントPCのIPアドレスを設定し、設定保存します。 アクセス許可されていないIPアドレスからカスタムエラーページのURLにアクセスできないことを確認します。 Application Gatewayのカスタムエラーページ設定を変更する場合は、Azure PowerShell からカスタムエラーページのURLにアクセスできず設定変更に失敗するため、再度全てのパブリックネットワークアドレスからのアクセスを許可してから設定する必要があります。そのため、次のカスタムエラーページ設定を変更せずエラーページの内容を変更する方法が望ましいです。 カスタムエラーページ設定を変更せずエラーページの内容を変更したい場合は、ストレージアカウントにあるhtmlファイルのプロパティから編集することができます。 編集後のhtmlを反映するためには、Application Gatewayで任意の構成更新を実行して、ファイルのキャッシュを手動で更新します。 例えば、新しいリスナーを追加します。 まとめ 今回は、Application Gatewayのカスタムエラーページを構成する手順を紹介しました。 Application Gatewayの設定の参考になれば幸いです。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Application Gatewayのカスタムエラーページを構成する first appeared on SIOS Tech. Lab .
サイオステクノロジー武井です。Microsoftがグローバルで開催しているAIのイベント「Microsoft AI Tour」の東京バージョンに、Microsoft MVPとして、ブース対応とハンズオンのサポートスタッフ対応として参加いたしました。そのレポートになります。 東京ビッグサイトで行われたイベントなのですが、たくさんの来場者がいらっしゃって、熱気に包まれたイベントでした。 バッジのピックアップ 翌日の下見も兼ねて、前日にチェックインしてバッジを受け取りました。前日に受け取ることができるのは非常に助かりますね。 そしてその時に基調講演の優先席チケットもいただきました。これは非常にありがたいですね。 基調講演 そして、基調講演当日、Reservedと書いてある席に座ることができましたが、そこそこ後ろの方でした。最前列はおそらくメディアと、Microsoftのパートナー企業の方々が座っていたのだと思います。 豪華なライティングとスモークが炊かれていました。そんなかっこいいステージで、基調講演が行われました。そして、今回の本丸であるMicrosoftのCEO、Satya Nadella氏の登場です。 基調講演の内容はまさに、 AIエージェント 一色でした。AIエージェントで業務を革新していくぞーみたいな話から始まりました。 そしておなじみCopilot Stackですね。 一番上のCopilotはいわゆるユーザーインターフェースの層です。WordやPower PointなどのビジネスアプリケーションにCopilot(副操縦士)として、業務を補佐するためのUIが組み込まれているぞーみたいなお話。 そしてさらに、Resaercher agentを始めとした賢いエージェントがMicrosoft 365に搭載されるという話です。様々な業務データを分析して、より高度な推論を行うエージェントが業務の補佐を行うという話でした。 AgentsはMicrosoftが持っている様々なデータとシームレスに繋がりますという話です。Agentはもちろんデータなくして動かないので、このように様々なデータと繋がることができるのは非常に強力です。 そして、弊社が最も得意とする「Copilot & AI stack」です。 日本の東西リージョンが強化されるようです。これはよいことですね。Agentの利用に伴い、さらなるコンピューティングリソースの需要が増えることが予想されるため、リージョンの強化は非常に重要です。 そしてAzure AI Foundryです。これは、本イベントでもイチオシでありますし、私もワークショップを担当したAzure AI Agent Serviceの管理には欠かせないものです。今後、Azure AI Foundryの機能が強化されることが予想されます。 JALさんは、ローカルLLMをFine Tuningして、自社の業務に適用しているという話でした。これは非常に興味深いですね。ローコストで、高精度なAIモデルを構築するための手法として、ローカルLLMをFine Tuningするというのは非常に有用です。今後の動向に期待大です。 ということで、まさにAIエージェント一色の基調講演でした。   私が担当したブース 私は、Azure Application Platofromのブースを担当いたしました。Azure上でアプリケーションをどうっするための様々なプラットフォーム(Azure App Service、Azure Functions、Azure Container Appsなど)をご紹介するブースです。 他のブースに比べると、Copilot Stackでいうところの下の方に位置するレイヤーだったので、このブースにいらっしゃたお客様は非常にエンジニア寄りの方が多い印象でした。 やはり皆様、Azure上でAIアプリケーションを動作させるのに、どのようなプラットフォームがあるのか、どのような違いがあるのか、といったことに興味を持っていらっしゃいました。 Azureには、様々なアプリケーションプラットフォームがあるのですが、やはりAzure FunctionsがAIアプリケーションには非常に適しているということをお伝えしましたし、Azure Functionsをご検討されているお客様が多かったですね。私の推しも、Azure Functionsでした。やはり、Azure OpenAI ServiceのAPIのレスポンって非常に軽いリクエストとレスポンスのやり取りで、さらにステートレスなAPIなのでAzure Functionsが非常に適していると思います。 Azure AI Agent Serviceリリースの影響もあって、AIの基盤としてどれを選定したらよいのか、というご相談も多くありました。 AIは、そもそもそれを動かすためのアプリケーション基盤がないと動作しません。よって、AIアプリケーションを動かすためのアプリケーション基盤についての知識は非常に重要です。そのため、Azure Application Platformはこれからも重要な役割を担っていくと思います。   ごはん ウマウマなランチもいただけたので、とても満足でした。朝、昼、夜ともに食事が提供されました。 朝と夜は写真を取り忘れたのですが、昼の写真はあります。数種類のお弁当が提供されていました。 なんとその一つに、今半のすき焼き弁当がありました。これはすごい!!!と思い、早速いただきました。 ワークショップ 私は、以下のワークショップのサポーター(受講者の方のご質問に答える役割)を担当しました。 Azure AI エージェント サービスで最初のエージェントを構築する https://aitour.microsoft.com/ja-JP/sessions/a6cb7b8d-9f92-47e2-94dc-d58a0feb5d17 写真の通りワークショップは2回とも満席でした。 ワークショップではAzure AI Agent Serviceを使って、以下の役割を持つエージェントを構築するというものでした。 データベース(SQLite)からデータを取得するエージェント データベース(SQLite)から取得したデータをCode Interpreterでチャート図を作成するエージェント ベクトルデータベースから必要な情報を検索するエージェント Bingにアクセスして必要な情報を検索するエージェント 様々なユースケースに基づいて、エージェントを構築していき、その凄さを体感するものでした。 Azure AI Agent Serviceは、AIエージェントを開発するうえで非常に便利な以下の機能を提供しています。 スレッドという単位で会話履歴を永続化してくれる Bing SearchやCode Interpreterなどへのツールの利用が超簡単である OpenAPIなどを利用することで既存システムともシームレスに連携できる ワークショップの参加者の方々は、Azure AI Agent Serviceの簡単さに驚かれていました。これからも、Azure AI Agent Serviceは、AIエージェント開発の現場で非常に重要な役割を担っていくと思います。 ワークショップは大成功でした。(講師の本間咲来(さっくる)さん、Microsoft MVP河本さんと)   セッション セッションもたくさん開催されていました。私はブース担当とワークショップサポーターを担当していたので、多くのセッションには参加できませんでしたが、その中でも非常に気になったものを一つピックアップします。それは以下です。 Azure上でDifyを活用したAIアプリケーションの構築 https://aitour.microsoft.com/ja-JP/sessions/24da067e-6a85-437c-835d-8935467ba7cc Microsoft MVPとして、またLINE API Expertとしてご活躍されている平林さん(ひらりんさん)が登壇されていました。Azure上にDifyが稼働するためのアプリケーションインフラを構築するという内容でした。 DifyをAzure上に構築するための方法は、以下の3つがあります。 VM上に構築する Azure Kubernetes Service(AKS)上に構築する Azure Container Apps上に構築する このセッションでは、3の「Azure Container Apps上に構築する」をしていました。実は、Azure Container AppsでDifyを構築するためのTerraformは以下のGitHubリポジトリに公開されておるのですが、バージョンが古かったりして少々手を加えないと動きません。弊社でもそれは確認済みでした。 しかしながら、平林さんそれをBicepにリファクタリングして、Azure Container Apps上にDifyを構築する方法をご紹介されていました。スゴイです。以下のリポジトリでBicepのコードを公開されているとのことでした。 https://github.com/himanago/dify-azure-bicep 素晴らしいです!!   まとめ Microsoft AI Tour Tokyoは、AIエージェント一色のイベントでした。AIエージェントは、業務を効率化するための非常に強力なツールであり、今後ますますその重要性が高まっていくと思います。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Microsoft AI Tourレポート first appeared on SIOS Tech. Lab .
概要 今までの回で、プラットフォーム上でコンテナとVMを統合管理することが出来るOCP-Virt, SUSE-Virt についてご紹介しました。 紹介の中でも、簡易的にその他仮想化基盤との比較も行ってきました。 今回は、今までにご紹介したOCP-Virt, SUSE-Virt, 加えてvSphereを含めて3製品の比較について記載します。 vSphereについても、今までの回で軽く触れていますが改めて概要と特徴について簡単に触れておきたいと思います。 OCP-Virt, SUSE-Virt の概要については下記の記事をご覧ください。 OCP-Virtの概要は こちら SUSE-Virtの概要は こちら vSphereの概要と特徴 vSphereは、仮想化基盤として提供され複数のVMを実行して管理することができます。 リソース使用率の最適化、スケーラビリティの向上のため企業環境での広範な採用実績を持っています。 主な機能としては、以下があります。 ESXiホスト 物理サーバー上で動作するハイパーバイザーで、仮想マシンの実行環境を提供します vCenter Server 複数のESXiホストを集中管理するためのサーバーで、VMの管理、リソースの最適化などを行います vMotion 実行中のVMをダウンタイムなしで他のESXiホストに移動する機能です。この機能によりシステムのダウンタイムを最小化することができます。 DRS(Distributed Resource Scheduler) VMのリソース需要に応じて、リソースの負荷を自動的に分散させる機能です vSphere HA ESXiホスト障害時にVMを自動的に他のホストに移動させ、可用性を高める機能です vSphere Replication VMのデータを別の場所に複製し、災害復旧を実現するための機能です。この機能により、データセンターの障害に対して迅速に復旧が可能になります 主な特徴は、以下があります。 柔軟性とスケーラビリティ vSphereは、小規模から大規模な環境までスケーリングが可能で、リソースの追加や削減が簡単に行えます また、ハイブリッドクラウド環境にも対応しており、クラウドとオンプレミス環境を柔軟に組み合わせて運用できます 効率的なリソース管理 VMごとにリソースの割り当てや優先順位を設定し、リソースの効率的な利用が可能です 高可用性とフォールトトレランス 自動フェイルオーバー用の vSphere HA や予測障害検出用の Proactive HA など信頼性の高い仮想化基盤環境を提供します 簡単な管理インターフェース 直感的な管理インターフェースを提供し、管理者がvSphere ClientやvCenter Serverなどを通じて、VMやリソースを簡単に管理できるように設計されています 前提情報 本記事では、現時点で以下のバージョンを対象としています。 OpenShift Virtualization OpenShift v 4.17 OpenShift Virtualization v4.17.3 SUSE Virtualization harvester v 1.4.0 VMware vSphere VMware vSphere 8.0 OCP-Virt、SUSE-Virt、vSphere の比較 OCP-Virt、SUSE-Virt、vSphere の主な機能の比較を記載します。 比較区分は以下の通りです。 〇:機能が存在するあるいは、他のソリューションと比較し優れている △:オプションの機能と組み合わせて実現が可能、また機能はあるが他のソリューションと比較すると制限や制約が大きい ✕:機能がない   表1:OCP-Virt、SUSE-Virt、vSphere の比較表 大項目 中項目 小項目 OCP-Virt SUSE-Virt vSphere VM基本機能 VM操作 VMの作成 〇 〇 〇 VMの編集 〇 〇 〇 VMの削除 〇 〇 〇 VMのクローン 〇 〇 〇 リソース拡張(CPU/メモリ/ボリューム) 〇 ボリュームの削減はできない リソース拡張はVMの再起動が伴う 〇 ボリュームの削減はできない リソース拡張はVMの再起動が伴う 〇 ボリュームの削減はできない リソース拡張はVM無停止で可能 VM/ノード管理 VMの可用性 VMの自動復旧機能 〇 runStrategyで、VMの自動復旧機能を実現 〇 runStrategyで、VMの自動復旧機能を実現 〇 VMのライブマイグレーション 〇 〇 〇 クラスターノードの可用性 クラスターノードの自動復旧機能 △ Workload Availability *1でクラスターノードの自動復旧を実現 ✕ 手動で障害ノードを復旧するか、新規ノードを用意 ✕ ホストの自動復旧機能は提供されていない VM管理 テンプレート機能 〇 〇 〇 クォータ(リソース制限)の設定 〇 △ Rancherとの統合でnamespaceのクォータ設定を実現 〇 CPU/メモリ/ストレージ I/Oの上限を指定可能 ホスト名の名前設定の可否 〇 〇 〇 VM内部からホスト名を変更することも可能 認証 認証基盤連携 ユーザー認証基盤との連携機能 〇 〇 Rancherとの統合で、ユーザー認証基盤との連携を実現 〇 ネットワーク 負荷分散 複数VMへのアクセスの負荷分散 〇 Routeを使用してL7の負荷分散を実現 Metal LBを使用して、L2,L3の負荷分散を実現 〇 組み込みのHarvester LBを利用して、L4の負荷分散を実現 △ アドオン、または外部ソリューションとの組み合わせで負荷分散を実現 DNS設定 DNS設定 〇 〇 〇 Pod/VMのIP固定化 Pod/VMの静的IP 〇 VMに付与した2つ目のネットワークで静的IP設定が可能 〇 VMに付与した2つ目のネットワークで静的IP設定が可能 〇 モニタリング&ロギング モニタリング VM/クラスターノードの標準モニタリング(CPU/メモリ/IOPS) 〇 〇 〇 VM / クラスターノードの死活監視 〇 〇 〇 ロギング VM / クラスターノード のロギング 〇 △ 外部のログサーバーとの統合でログデータの保存を実現 〇 データ管理 スナップショット スナップショット 〇 〇 〇 バックアップ バックアップ △ OADP Operatorインストールで実現 〇 △ ホストのバックアップは可能 VMのバックアップは、VADP *2を使用して別バックアップツールと連携することで実現 スケジューリング スナップショットのスケジューリング ✕ 〇 〇 バックアップのスケジューリング △ OADP Operatorインストールで実現 〇 ✕ セキュリティ マルチテナント 異なるテナントごとにリソースを論理的に分離する機能 〇 OCPのプロジェクト機能を使用して テナントごとにリソースの分離、セキュリティの強化を実現 △ Kubernetes標準の機能で簡易的なリソース分離が可能。Rancherと統合することで十分なマルチテナント機能を実現 ✕ アクセス制限 VM間または外部へのアクセス制限 〇 OCPのネットワークポリシーを利用してアクセス制御を実現 〇 〇 RBACでのVM操作・管理の制御 〇 OCPのRBACを利用して、プロジェクトに対するユーザーの権限制御を実現 △ Rancherと統合しRBAC機能を活用してユーザーの権限制御を実現 〇 ストレージ ボリューム 永続ボリューム 〇 〇 〇 分散ストレージ △ ODFをインストールして分散ストレージを実現 〇 △ Storage vMotionに相当する機能 ✕ ✕ 〇 ボリューム形式の種類 – ブロック ファイル – ブロック ファイル – ブロック ファイル ストレージ バックエンドのストレージ対応種類 〇 多くのストレージベンダーのCSIプラグインが提供 〇 多くのストレージベンダーのCSIプラグインが提供 〇 クラスター管理 バージョンアップ バージョンアップのプロセスの容易さ 〇 簡単にバージョンアップすることが可能 バージョンアップ中にVMを停止する必要はない 〇 UIから簡単にバージョンアップすることが可能 バージョンアップ中にVMを停止する必要はない △ 事前準備、バージョンアップ作業が入る 対応プラットフォーム 対応プラットフォーム 対応プラットフォーム – オンプレミス AWS – オンプレミス Equinix – オンプレミス 多くのクラウドベンダー *3 *1 Workload Availability:Workload Availability for Red Hat OpenShift *2 VADP:VMware vStorage API for Data Protection *3 多くのクラウドベンダー:VMware Cloud on AWS、Azure VMware Solution、Google Cloud VMware Engine、Oracle Cloud VMware Solution に対応している   各製品の利用ケース どの仮想化基盤も基本的な機能の共通点が多く、優れた環境を提供しますが、それぞれが特定の利用ケースに適している場合があります。 OCP-Virtの利用ケース OpenShift(OCP) の機能を利用した効率的な運用 OpenShift(OCP) 側のセキュリティ、モニタリング、ロギング、ユーザー管理などの様々な機能をOCP-Virtでも利用できます。既存のコンテナ運用と統合して管理することで効率的な運用を実現できます 基盤となるノードの復旧対応の効率化 Workload Availability for Red Hat OpenShift機能を用いて構成するノードの自動復旧・自動追加機能を活用して柔軟なノード管理ができます RHEL OSの利用 多くのRHEL OSのVMを構成するユーザーは、ライセンス費用低減のメリットを享受できます SUSE-Virt利用ケース 標準のデータ管理機能 Harvester標準に備わっているスナップショット機能、バックアップ機能およびそれらのスケジューリング機能を使用して、安定したデータ管理機能を素早く実現できます Rancherとの統合 既存のKubernetesクラスターがあり、KubernetesクラスターとHarvesterをRancherで統合管理することができます Rancherと統合することにより、ユーザー認証基盤の連携、テナント管理、RBACなどの機能を一元的に管理することができます コストを抑えた仮想化基盤の利用 OSSの性質から基本的に無償で利用でき、大きな投資をせずに堅牢な仮想化基盤を必要とするユーザーに適しています vSphere利用ケース シンプルなネットワーク構成 vCenterでの包括的なvSwitchの管理などを実現できます。また複数のネットワーク構成をする際もシンプルな方法での構成を提供しています より広範なストレージ機器の利用 ストレージ機器の選定の幅が広いため、他の仮想化基盤に対応していないストレージ機器を使用したいユーザーに適しています バージョンアップ運用の負担軽減 Kubernetes環境のリリースの速さに追従する必要がないため、バージョンアップに係る運用面の負担を軽減できます まとめ 今回は、今までご紹介したOCP-Virt, SUSE-Virtと vSphere を含めて3製品の比較をしてみました。 基本的な機能についてはどの製品も提供していますが、利用ケースに応じた選定の一要素として、いくつか比較ポイントが見えました。 仮想化基盤を比較する上でこの記事が比較の参考になれば幸いです。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OpenShift Virtualization, SUSE Virtualization, VMware vSphere の比較 first appeared on SIOS Tech. Lab .
今号では、Linux におけるパーミッションについて説明します! パーミッションとは パーミッションとは、Linux におけるファイルやディレクトリに対する アクセス権限 のことです。 一般ユーザとして使用している場合、あまりパーミッションについて意識することは少ないかもしれませんが、普段利用しているすべてのファイルやディレクトリにパーミッションが設定されています。 「誰が」「どのような操作を」許可されているかを決める重要な仕組みであり、パーミッションが適切に設定されていないと 不正アクセス や データの改ざん 、 誤ってプログラムを実行してしまう 可能性があります。 なお、パーミッションはファイルを作成するごとに自分で設定する必要はなく、システム側の設定とアプリ側の設定を組み合わせた上で、それぞれデフォルトのパーミッションが割り振られます。 適宜、パーミッションを変更しながら運用していくことになります。 パーミッションの考え方 Linux では、ファイルやディレクトリのパーミッションは下記 3つのカテゴリに分けられます。 Owner (所有者) :ファイルを作成したユーザ Group (グループ) :Owner が所属するグループ Other (その他) :Owner 以外の全ユーザ また、各カテゴリに対して下記 3つの権限を設定できます。 r (読み取り) :ファイルの読み取り権限 w (書き込み) :ファイルの書き込み権限 x (実行) :ファイルの実行権限 (プログラムやスクリプトを実行する場合) パーミッションの確認方法 最も簡単なのは、 ls -l コマンドを実行してファイルの情報を表示する方法です。 $ ls -l test.txt -rw-r--r--. 1 ykaino ykaino-group 0 Mar 24 12:00 test.txt 出力された各内容を、それぞれ説明します。 -rw-r–r– :パーミッションを表す文字列 1 :リンク数。通常は 1となるが、ハードリンクがある場合は増加する ykaino :Owner。ファイルを作成したユーザ名 ykaino-group :group。Owner が所属するグループ名 1234 :ファイルサイズ (byte 単位) Mar 20 10:00 :ファイルの最終更新日時 example.txt :ファイル名 (ディレクトリの場合はディレクトリ名) 続いて、パーミッションを表す文字列について説明します。 上記で出力された文字列 ( -rw-r–r– ) を例にすると、 1文字目 (-):ファイルの種類。- は通常のファイル、d はディレクトリ、l はシンボリックリンクとなる 2~4文字目 (rw-):Owner (所有者) の権限。読み、書きは許可、実行は不可 5~7文字目 (r–):Owner がいるグループに所属する、他のユーザの権限。読みは許可、書き、実行は不可 8~10文字目 (r–):上記に該当しない他のユーザの権限。読みは許可、書き、実行は不可 なお、ls -l コマンドの他に、 getfacl コマンドを実行してファイルの情報を表示する方法もあります。 $ getfacl test.txt # file: test.txt # owner: ykaino # group: ykaino-group user::rw- group::r-- other::r-- デフォルトのパーミッション 上記の test.txt ファイルでは、ユーザに読み、書きの権限があり、グループおよびその他のユーザには読み取り権限のみが与えられていました。 これは、ファイルやディレクトリにデフォルトで設定されるパーミッションがあらかじめ決められているために上記のような結果となっています。 デフォルトのパーミッションは umask というパラメータで設定されます。 ls -l コマンドの実行結果では、各権限を r (読み取り)、w (書き込み)、x (実行) で表現しましたが、 umask では各権限を数値で表現します。 r (読み取り) :4 w (書き込み) :2 x (実行) :1 例えば、読み取りと書き込みの権限がある場合は 4 + 2 = 6 、読み取りと実行の権限がある場合は 4 + 1 = 5 のように考えます。 Linux ファイルシステムでは、ファイルの基本パーミッションが 666 (読み書きのみ、実行権限なし) 、ディレクトリの基本パーミッションが 777 (読み書き実行すべて可能) になっています。そこから umask の値を引き算して、最終的なパーミッションが決定します。 現在の umask の値は umask コマンドで確認できます。 # umask 0022 ファイルの場合は 666 から 022 を引いて 644 (Owner は読み、書き権限あり、グループおよびその他のユーザには読み取り権限あり) 、ディレクトリの場合は 777 から 022 を引いて 755 (Owner は読み、書き、実行権限あり、グループおよびその他のユーザには読み、実行権限あり) になります。 umask の値を一時的に変更する場合は umask コマンドを実行します。 $ umask 027 永続的に変更する場合は ~/.bashrc もしくは ~/.profile などのファイルに、下記の様な umask の設定を追加します。 umask 027 次号では、パーミッションの変更方法や、特殊なパーミッションについて説明します! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 知っておくとちょっと便利!ファイルのパーミッションについて1 first appeared on SIOS Tech. Lab .