Solaris Resource Manager システムは、 l ノードと呼ばれ、ユーザーごとに用意される構造体をカーネルに追加することを基礎に構築されます。l ノードは本質的には固定サイズのデータ空間のことで、いろいろなユーザー別データがここに格納され、更新されます。パスワードマップに定義されている固有のユーザー ID には必ず対応する l ノードが必要です。これは getpwent(3C) を呼び出したときに返される固有のユーザー ID です。パスワードマップに l ノードに対応するエントリがなくても存在できますが、推奨しません。l ノードはディスクに格納され、カーネルによって自動的にメモリーから出し入れされます。メモリー内の l ノードのコピーが、ディスクから読み込まれた後に変更されていると、通常のシステム同期操作の中で書き直されます。この書き直しは、sync コマンドを実行したときや、他の l ノードを読み込むために l ノードキャッシュの空間を解放する必要があるときにも行われます。
l ノードはツリー階層として維持されます。このツリーでは、中央のシステム管理者がツリーの最上部に位置し、他のユーザーはそれより小さなユーザーグループのグループヘッダーです。中央のシステム管理者は、システムのスーパーユーザーまたは root ユーザーです。
親のない l ノードやグループループなど、l ノードに関連するエラーについては、第 11 章「問題の解決」で説明します。
l ノードを管理する主要な責任は中央のシステム管理者にあります。Solaris Resource Manager では割り当てと管理が可能ないくつかの資源制御を使用しますが、一定の管理特権を root 以外のユーザーに選択して割り当てて、ユーザー管理の負担を分散できます。
適切なユーザーに管理特権を割り当てるには、そのユーザーの uselimadm または admin フラグを設定します。副管理者は、uselimadm フラグが設定されているユーザーで、スーパーユーザーと同じ limadm プログラム管理特権を持ちます。admin フラグが設定されているグループヘッダーユーザーはグループ管理者と呼ばれ、そのスケジューリンググループ内のユーザーに対し次の特権を持ちます。
中央のシステム管理者は、root を親に持つスケジューリンググループに対し制限値を設定して、割り当てることによって、システム資源の全体的な配分を制御します。グループ管理者も、通常、これと同じ資源制御を行いますが、対象はスケジューリンググループ内のユーザーに限定されます。グループ管理者が配分する資源は、グループに割り当てられた資源 (たとえば、グループヘッダーの l ノードに割り当てられた資源) だけです。グループ管理者は、スケジューリンググループ内のユーザーに admin フラグを割り当て、管理責任を分割できます。
グループ管理者は次のことができます。
スケジューリンググループ内のユーザーの資源制限値を変更できます。
グループ管理者は資源の制限値としてグループの制限値より大きい値を設定できます。しかし、グループメンバーが使用した資源はグループヘッダーが使用した資源でもあるため、グループヘッダーの制限値を超えそうになると、個々のユーザーの制限値が適用されます。
スケジューリンググループ内の l ノードのフラグまたは属性 (flag.uselimadm と cpu.usage を除く) を変更できます。
さらに、グループ管理者は、自分が所有していない特権をユーザーに与えることはできません。この制約により、グループ管理者が Solaris Resource Manager のセキュリティを侵害するのを防ぐことができます。
グループ管理者が使用する主なツールは limadm(1MSRM) と limreport(1SRM) コマンドです。limadm プログラムでは、制限値、フラグなど、既存ユーザーの Solaris Resource Manager 属性に対する操作を行います。レポート作成ツールである limreport とともに使うことにより、他の独立したスケジューリンググループの資源の割り当てや管理に関係なく、スケジューリンググループを別個に自己管理することができます。
スーパーユーザーにはどの資源制限値も適用されず、フラグの設定値とは関係なく常にすべての管理者特権を持ち、ユーザーアカウントの追加、削除、および変更を行うことができます。また、limadm コマンドを使ってどの l ノードの使用量、制限値、またはフラグの値でも変更できます。
Solaris Resource Manager は Solaris システムの管理に広範囲に影響を与えるため、Solaris Resource Manager のインストールや保守にあたっては、システムのセキュリティを損なわないようにすることが重要です。
システム管理者が Solaris Resource Manager のセキュリティを維持するための方法はいくつかあります。最も重要なことは、Solaris システムの場合と同様、root パスワードの機密を保護することです。root パスワードを知っていれば、だれでも中央のシステム管理者と同じようにシステム資源に無制限にアクセスできます。
Solaris Resource Manager のユーザーに与えることができる特別な管理特権がいくつかあります。そのためには、ユーザーの l ノードにあるシステムフラグを設定する必要があります。この方法では、ユーザーに完全なスーパーユーザー特権を与えることなく、特権を獲得したユーザーが必要な作業を実行できるため、システムのセキュリティが向上します。
これらの特権の中には簡単に与えてはならないものがあります。この特権を獲得するとユーザーは広範囲に権限を持つことになるからです。これらの特権を持つユーザーのパスワードは、スーパーユーザーのパスワードと同様、厳格に保護される必要があります。
副管理者が、与えられた管理特権を誤用することがないように、Solaris Resource Manager ではセキュリティに関していくつかの予防策が用意されています。一般的なアプリケーションサーバーと l ノードの保守プログラムを参照してください。
中央のシステム管理者は、スケジューリングツリーの構造を注意深く扱わないと、システムのセキュリティが侵害される場合があります。そのため、スケジューリングツリーを適切に変更する方法を理解し、現在の構造の潜在的な問題を発見する方法を知ることが重要です。これについては、スケジューリングツリーの構造で説明しています。
グループ管理者にとって、グループの制限値をグループメンバーと共有していることが問題になる場合があります。たとえば、グループヘッダーの l ノードにプロセスの制限値が設定されている場合には、グループヘッダーを含むグループ全体で使用できるプロセス数が制御されます。さらに制限が加えられない限り、スケジューリンググループのどのユーザーも、自分のプロセスリミットを超過することによって、グループ管理者が新しいプロセスを作成するのを妨げることができます。
これを防ぐ 1 つの方法は、グループ管理者がグループメンバーのそれぞれに個別に制限を設定することです。しかし、これを効果的なものにするには、制限を過度に厳しくしなければならないかもしれません。さらに、グループ管理者に個別の制限値を管理させるのは、階層的資源制御という Solaris Resource Manager の目標に反しています。
この問題を解決する別の方法は、中央の管理者がグループ内の l ノードの構造を変えることです。グループ管理者の l ノードの下に直接ユーザーを置く代わりに、グループ管理者の l ノードの下に唯一の子 l ノードとして「制御」 l ノードを作成し、ユーザーを制御 l ノードの子にします。この構造を次に示します。
図 5-1 で、グループ管理者のアカウントのユーザー ID は、「Actual」というラベルがあるツリーの親である l ノードのユーザー ID に対応します。admin フラグはこの l ノードに設定します。「Control」l ノードにはダミーアカウントを作成します。このアカウントに対してはログインを許可する必要はありません。「A」、「B」、「C」のラベルがある l ノードはグループ管理者の制御下にあるユーザーです。
この場合、プロセスリミットを「Actual」l ノード 100、「Control」l ノード 90、個々のユーザー 0 とするとします。そうすれば、ユーザー A、B、C が合わせて 90 のプロセスを使用しても (すべて許可されます)、副管理者はまだ 10 のプロセスを作成できます。
この場合でも、各ユーザーは他のユーザーがプロセスを作成するのを妨げることがあります。これを避ける唯一の方法は、各ユーザーに個別の制限値を設定することです。この例の場合、個別の制限値をそれぞれ 40 にすれば、1 人のユーザーが他のユーザーを完全に除外することはなく、柔軟性が保たれます。
さらに、この例では、管理者が「Control」l ノードの子として新しいユーザーの l ノードを作成しても、制限値のバランスが崩れる心配はありません。
リミットデータベースは、Solaris Resource Manager ソフトウェアがすべての資源制御を行うときに使用するユーザー情報のデータベースです。このデータベースにはユーザー ID ごとに 1 つの l ノードが含まれ、ユーザー ID を索引にして直接アクセスします。大きな数字のユーザー ID を持つ l ノードがあると、リミットデータベースが非常に大きくなることがあります。ユーザー ID が連続していないシステムでは、リミットデータベースに大きな間隙または穴があります。しかし、sparse ファイルをサポートするファイルシステムでは、リミットデータベースを sparse ファイルとして格納できます。したがって、実際には、ファイルの「空」領域にはディスクブロックは割り当てられません。ufs ファイルシステムは sparse ファイルをサポートしますが、tmpfs ファイルシステムはサポートしません。リミットデータベースの保存や復元で sparse ファイルがどのような意味を持つかについては、リミットデータベースの保存と復元を参照してください。
新しいユーザーを作成したら、新しい l ノードを必ず作成する必要があります。
Solaris Resource Manager の起動ファイル (/etc/init.d/init.srm) は、最初に呼び出されたときに初期リミットデータベースを作成します。それ以後の起動でも、データベースが存在しない場合は作成します。
リミットデータベースは通常、/var/srm ディレクトリに作成されます。
リミットデータベースは、root と、root が所有するグループが所有し、所有者だけが読み取れるようにするべきです。ファイルに書き込むのはスーパーユーザー資格を持つカーネルコードだけなので、書き込み権は必要ありません。
Solaris Resource Manager の起動ファイルにユーザーが書き込み権を持っていると、システムセキュリティが損われることがあります。
リミットデータベースは sparse ファイルの場合があるので、コピーするときには注意が必要です。sparse ファイルをサポートしないユーティリティで書き込まれたファイルは、通常、大量のディスク容量を使用します。ファイルの空領域は一連のゼロとして読み込まれ、書き直されるときには、空領域ではなく実ブロックとして書き込まれるからです。tar(1)、cpio(1)、cp(1) などのユーティリティでのファイルのコピーや、バックアップ、復元の場合などです。ufsdump(1M) や ufsrestore(1M) などのプログラムでは、「穴」のまま空領域として残せます。
limreport を使って ASCII ファイルを生成し、limadm を使ってこの ASCII ファイルから元のファイルを作成し直しても、リミットデータベースのバックアップと復元を行うことができます。たとえば、次のようにします。
# limreport 'flag.real' - lname preserve > /var/tmp/savelnodes |
このコマンドでは、パスワードマップの各ユーザーに対応する l ノードの ASCII 表示として /var/tmp/savelnodes を作成します。パスワードマップにエントリがない l ノードは保存されません。少なくともパスワードマップのすべてのユーザー ID に対しては l ノードを作成してください。
次のコマンドでは、保存したデータから l ノードを再作成します。
# limadm set -f - < /var/tmp/savelnodes |
保存しなかった l ノードは削除されないので、この方法を使えば、リミットデータベース全体ではなく l ノードを選択して保存し復元できます。
limreport と limadm コマンドの使い方については、limreport コマンドと limadm コマンドで詳しく説明します。管理者にとって、これらのコマンドの使い方を知っておくと、l ノードの保存や復元をするときに便利です。リミットデータベースに定義された l ノード構造の解釈に変更があったときに、これらのコマンドを使用することがあるからです。
リミットデータベースの内容は通常のシステム操作の間に定期的に変更されるので、システムが停止しているときや、シングルユーザーモードのときにバックアップをとる必要があります。同様に、リミットデータベース全体を復元する場合には、システムがシングルユーザーモードのときのように、Solaris Resource Manager が使用されていないときに行う必要があります。
新しいユーザーを作成したら、対応する l ノードを作成し、その制限値と特権を設定する必要があります。Solaris Resource Manager を使用する場合には、管理者がリミットデータベースと通常の Solaris パスワードマップを並行して保守する必要があります。次のコマンドを実行すると、対応する l ノードがないユーザーのユーザー ID とログイン名が表示されます。
# limreport \ !flag.real - uid lname |
l ノードの作成や削除は、アカウントの作成や削除に使うシステムコマンドで自動的には行われません。
これらのアクションを行うかどうかは、管理者次第です。しかし、ユーザーがログインするときに要求すれば、l ノードを自動的に作成できます。詳細は、PAM サブシステムを参照してください。
同様に、パスワードマップからユーザーアカウントを削除する場合は、その前に limadm(1MSRM) コマンドを使って、対応する l ノードをリミットデータベースから削除する必要があります。
サブツリーを削除する場合には、一番下の l ノードから順番に削除する必要があります。削除するサブツリーの一番上から始めると、親を削除された子は「親のない」状態になるため、削除した l ノードの子を制御できなくなります。
ユーザーのユーザー ID を変更する場合は、その l ノードの内容を、新しいユーザー ID に対応する新しい l ノードにコピーし、元の l ノードを削除します。l ノードのコピーと削除を参照してください。
子 l ノードがある場合は、新しく作成した l ノードか、他の適切な親 l ノードに接続します。次のコマンドを実行すると、ユーザー ID が X のスケジューリンググループ親を持つすべての l ノードを見つけ、それをユーザー ID が Y の l ノードの子にできます。
# limreport 'sgroup==X' '%u\tsgroup=Y\n' uid | limadm set -u -f - |
l ノードのユーザー ID を X から Y に変更するには、次の手順に従います。
ユーザー ID を変更する l ノードの状態を保存します。
# limreport 'uid==X' - lname preserve > /var/tmp/savelnode.X |
ユーザーのパスワードマップエントリのユーザー ID を古い値 (X) から新しい値 (Y) に変更します。
新しいユーザー ID の l ノードを作成し、前に保存した状態を復元します。
# limadm set -f /var/tmp/savelnode.X |
変更する l ノード (ユーザー ID X) のすべての子 l ノードに対し、スケジューリンググループを新しい l ノード (ユーザー ID Y) に変更します。
# limreport 'sgroup==X' '%u\tsgroup=Y\n' uid | limadm set -u -f - |
古い l ノードに接続されているプロセスがないか確認します。
chown(2) コマンドを使って、元のユーザー ID が所有するすべてのファイルの所有者を新しいユーザー ID に変更します。たとえば、次のように入力します。
# find / -user X -print | xargs chown Y |
古い l ノードを削除します。
# limadm delete X |
管理者は、ユーザーの l ノードを保守するツールとして主に limadm コマンドを使用します。このコマンドでは、指定する一連のユーザーアカウントに対し Solaris Resource Manager の属性値を変更します。これらのユーザーの l ノードが存在しない場合は、デフォルト値が設定されているブランクの l ノードが最初に作成されます。新しい l ノードのプロパティは次のように設定されます。
flag.real が set に設定される。
cpu.shares と cpu.myshares 属性が 1 に設定される。
uselimadm と admin フラグがクリアされる。
他のすべてのフラグは継承される。
すべてのリミット属性と使用量属性がゼロに設定される。
新しい l ノードのスケジューリンググループは、そのユーザーアカウントの l ノードが存在していればユーザー other (srmother) に、存在しなければ root l ノードにそれぞれ設定されます。
limadm を呼び出すには、変更を行うための管理特権が必要です。つまり、スーパーユーザーであるか、uselimadm フラグが設定されているか、自分のスケジューリンググループのメンバーの属性だけを変更できるグループ管理者である必要があります。グループ管理者が limadm を使用する場合には、次の制約があります。
グループ管理者の属性値を変更することはできません。
ユーザーの sgroup 属性は、limadm を使用するユーザーのスケジューリンググループのメンバーにしか割り当てることはできません。
グループ管理者は、スケジューリンググループ外のユーザーの属性を変更することはできません。
term usages 以外は、usages を格納するときに使用する属性値を変更することはできません。この制約がないと、グループ管理者は、いずれかの子の使用量を減らすことでグループの使用量を減らし、自分の l ノードのグループの制限値が適用されないようにできます。
フラグのデフォルト値以外の値に評価されるフラグがある場合には、グループ管理者は、このデフォルト値以外の、同じ値に変更するのであれば、グループのメンバーに対しこのフラグの値を変更できます
そのため、グループ管理者は、明示的に否定された特権を自分の影響下にあるユーザーに与えることはできません。
管理者は、limadm コマンドを使って l ノードを削除できます。このとき、対応するユーザーアカントはパスワードマップから削除されません。limadm を使用するには、スーパーユーザーであるか、uselimadm フラグが設定されている必要があります。admin フラグだけが設定されている場合には、自らがグループヘッダーであるスケジューリンググループのユーザーの l ノードしか変更できません。
Solaris Resource Manager の値は、次の 3 つの単位のいずれかで表わされます。
デフォルトでこの単位が使われます。値の表示や入力に使用する読みやすい形式です。拡張単位を使用すると、入力する桁数が減るため入力エラーが少なくなります。
基本単位は、値を表わす基本的な単位です。たとえば、仮想メモリー使用量の基本単位はバイトで、仮想メモリー累積の基本単位はバイト秒です。この単位は主に、使用量に対し課金する場合で正確な数値を必要とする場合に使用します。
内部単位は、Solaris Resource Manager がメモリー属性を格納するときにバイトの代わりに使用するマシンに依存した単位です。
属性値の格納に使用する内部単位は Solaris Resource Manager プログラムによって変換されるため、ユーザーには常に拡張単位か基本単位で表示されます。したがって、特別な場合を除き、ユーザーは、Solaris Resource Manager が使用する内部単位を気にする必要はありません。
Solaris Resource Manager では、エクサ、ペタ、テラ、ギガ、メガ、キロという用語を 10 のべき乗ではなく、2 のべき乗を表わすために使用します。たとえば、メガバイトは、1,000,000 バイトではなく、1,048,576 バイトです。2 のべき乗数はそれぞれ 60 (エクサ)、50 (ペタ)、40 (テラ)、30 (ギガ)、20 (メガ)、10 (キロ) です。
ユーザーと Solaris Resource Manager システムとのインタフェースには、主に limadm、liminfo、および limreport プログラムを使用します。これらのコマンドによって行われる変換と拡張について、次の各項で説明します。
limadm では、属性値を変更するときに数字に拡張文字 [EPTGMK][B][.][wdhms] を付けることができます。大文字と小文字の区別はありません。
属性が記憶域 (メモリー属性) か増加記憶域の大きさを表わす場合は、最初のグループ [EPTGMK] の文字を使用します。この数字には、1 エクサバイト (E)、1 ペタバイト (P)、1 テラバイト (T)、1 ギガバイト (G)、1 メガバイト (M)、1 キロバイト (K) のバイト数を掛けます。読みやすくするために B を付けることもありますが、特別な意味はありません。
属性が時間 (型が日付や時刻) か増加記憶域の大きさを表わす場合は、2 つ目のグループを使用します。この数字には、1 週 (w)、1 日 (d)、1 時間 (h)、1 分 (m)、1 秒 (s) の秒数を掛けます。
記憶域と時間の単位をピリオドで区切ることもできます。たとえば、mh、M.h、MB.h はすべて「メガバイト時間」を表わします。
M という接尾辞の意味があいまいな場合は、limadm が文脈から判断します。これができない場合は、分ではなくメガを使用します。
これらの変換文字を使用すれば、桁数のエラーを避けることができます。しかし、どの入力方法の場合でも、量は内部単位で格納されます。
メモリー属性値として特別な文字 u をそれだけで使用することがあります。これは、数字がバイト数ではなく、マシン依存 (内部) 単位数であることを示します。
liminfo(1SRM) コマンドで出力されている情報では、limadm の入力に使用するのと同じ接尾辞 (上の項を参照) が使用されます。liminfo コマンドでは一般に値を適切な拡張単位に変換して出力しますが、-r オプションを指定すると、値を基本単位 (非拡張) 形式で出力します。たとえば、メモリーは通常メガバイトなど (102M バイト) 適切な単位で表示されますが、-r オプションを指定すると、バイト数 (106954752 バイト) で出力されます。
limreport(1SRM) コマンドで出力される情報では、値が常に基本 (非拡張) 形式で表示されます。拡張単位で値を表示するには、変換単位を式で明示的に指定する必要があります。たとえば、すべてのユーザーの仮想メモリーの合計使用量をキロバイトで表示する場合は、次のように指定します。
# limreport 'flag.real' '%-8.8s %d KB\n' lname '(memory.usage+1k-1)/1k' |
この例でわかるように、数字の拡張接尾辞を式で指定できるので、基本単位から拡張単位への変換が簡単にできます。
属性によっては、内部単位がその「基本」形式と同じでない場合がありますが、すべての Solaris Resource Manager プログラムが拡張単位や基本単位への変換を行うため、ユーザーは通常このことを意識する必要はありません。しかし、たとえば、limreport の選択式に正確なバイト数を指定しても、数字が対応する内部単位の整数倍でない限り、この式が一致することはありません。
limreport や limadm コマンドを使用すれば、管理者は、何人のユーザーの l ノードでも、その内容を簡単に保存または復元できます。limreport コマンドでは保存する l ノードの選択と抽出を行い、limadm コマンドではそれを復元します。次の節で説明するように、l ノードのコピーと l ノード構造の変更では、このようなコマンドの組み合わせが最も一般的に使用されています。
limreport コマンドでは、ユーザー属性の選択や表示を柔軟に行えます。このコマンドには 2 つのレベルの選択があります。l ノードの選択と、選択した l ノードごとに表示する属性の選択です。l ノードの選択には選択式を使用します。この式は、1 つの式でも、C 形式の論理演算子で一連の条件を結合したものでもかまいません。属性の選択には、属性の記号名リストを使用します。属性をどのように表示するかは、C 形式に似た形式制御文字列で指定できます。この制御文字には Solaris Resource Manager の特別な型を処理する拡張を組み込むことができます。形式制御文字として「-」を指定すると、属性はデフォルト形式で表示されます。詳細は、limreport(1SRM) のマニュアルページを参照してください。
limadm コマンドでは、l ノードの属性内容を最小単位で変更します。ただし、このコマンドを使用するには、変更を行うための特権が必要です。変更コマンドはコマンド行に直接指定できます。あるいは、変更コマンドが入っているファイル名を -f オプションで指定することもできます。
limreport コマンドでは、limadm 構文を使って属性値割り当てを生成できます (limadm 構文の preserve 識別子を参照)。この出力は、-f オプションを使って limreport に入力できます。そのため、管理者は、2 つのプログラムを使ってリミットデータベースの内容を選択して、保存し復元することができます。
ユーザー ID X の l ノードをユーザー ID Y にコピーするには、次のようにします。
# limreport 'uid==X' - Y preserve | limadm set -u -f - |
「uid==X」はソースの l ノードを選択するための式です。preserve 識別子によって、limreport は、読み取り専用でないすべての属性値を limadm への入力に適した構文で出力します。preserve 識別子の前にユーザー ID Y を指定すると、これが limadm に渡されるデータの最初の項目になり、ターゲット l ノードの選択に使用されます。
必要なくなったソース l ノードは limadm で削除できます。
limreport の選択式としてユーザー ID を照合する場合は注意が必要です。複数のログイン名に同じユーザー ID が設定されていると、それらがすべて一致します。同じ l ノードデータが何回も保存され、読み込まれるため、上の例では問題とはなりません。Solaris 環境では、root と smtp のログイン名にユーザー ID 0 が設定されています。