32
systemdいろいろ (かきかけ) 2014-11

systemdいろいろ(書きかけ)

Embed Size (px)

Citation preview

systemdいろいろ

(かきかけ)2014-11

systemdって?● RHEL7で導入されたシステムとサービスの管理をおこなう

たくさんのユーティリティ、サービス、ライブラリ群● 「 initの置き換え」とよく言われますが単純な置き換えではな

い● 目標は?

– 高速化– ディストリビューション独自実装の統廃合

● RHEL, Fedora, OpenSUSE, Debian, Gentoo, ArchLinux, Ubuntu でsystemd採用(または採用予定)

– ベストプラクティスの統合● よくあるバグの回避● セキュリティ向上の工夫を簡単に利用

systemdでの互換性の維持

● SysV, LSBの init scriptsからunitファイルを自動生成● インタフェースの互換性維持

– dbus: ConsoleKit等– ソケット: /dev/initctl, /dev/log互換ソケット– 「ランレベル」への対応: runlevelX.target, カーネルコマンドラ

インオプション(1,2,3,4,5,6,S,emergency 等)

● 互換コマンドの提供– halt, init, poweroff, reboot, runlevel, shutdown, telinit の置き

換えを同梱– serviceコマンドを実行するとsystemctlを呼びだす

# service cups startRedirecting to /bin/systemctl start cups.service

どのあたりをカバーするのか?

● 起動・終了・再起動に必要な処理全般– デバイスの検出・命名・初期化– fsのmount, autmount, 暗号化block device対応– サービス起動・管理– ロギング– 起動失敗時のレスキュー処理– パスワード確認– システムのlocale, TimeZone, キーボード, 仮想コンソール– 電源管理

● サービス管理で典型的に必要な属性全般の管理– control groups, namespace, ulimit, 通知, /tmp の掃除– ユーザセッション管理

どのあたりをカバーするのか?

● 起動・終了・再起動に必要な処理全般– デバイスの検出・命名・初期化 ← udev

– fsのmount, autmount, 暗号化block device対応 ← systemd-fstab-generator, systemd-cryptsetup-generator

– サービス起動・管理 ← systemd本体– ロギング ← journald

– 起動失敗時のレスキュー処理 ← rescue.service

– パスワード確認 ← systemd-ask-password-*

– システムのlocale, TimeZone, キーボード, 仮想コンソール ← localectl, timedatectl, systemd-vconsole-setup

– 電源管理 ← systemd-sleep

● サービス管理で典型的に必要な属性全般の管理– control groups, namespace, ulimit, 通知, /tmp の掃除 ← systemd本体, systemd-

tmpfiles*

– ユーザセッション管理 ← systemd-logind

– shutdown inihibitor ← systemd-inihibit

https://wiki.tizen.org/wiki/File:Systemd_arch.PNG より

サービス管理

サービス管理● serviceコマンドからsystemctlに● サービスの定義が宣言的

– 「unit」と呼ばれるオブジェクト群として管理する– /etc/init.d/* の微妙に異なる多数のシェルスクリプトは徐々になくして

行く。RHEL7ではほとんどのサービスが移行済み– 起動の高速化、メンテナンスの省力化、よくある問題の根絶– 設定変更時は systemctl daemon-reload で読み直させる

● 実行するタイミングでファイル内容を反映しないので注意

● systemdがunit間の依存関係や起動順序を計算して決定– 従来は人間が依存関係を考慮して起動・終了の順序を決定

● 起動・終了するだけでなくサービスの状態やログ、関係するプロセスを管理

/etc/init.d/* をどうする?

● (ほとんどの場合)そのままでOK:

– systemdは/etc/init.d以下のスクリプトを自動変換してserviceユニットを作成します

– service コマンドでのサブコマンドを独自拡張している場合は /usr/libexec/initscripts/legacy-actions/(ユニット名)/(サブコマンド名) に対応するスクリプトを配置する

● unitファイルへ移植– 基本的な起動・終了等ができるのは同じ– 起動エラー時の処理、タイムアウト処理、リソース制限(ulimit)、異常終

了時の自動再起動などを宣言的に記載するだけで利用– 他プロセスと共有しない/tmp, capabilityの制限, localのnetworkにの

み接続できる制限などによるセキュリティ強化も容易

initスクリプト移行例 - cupsd (1)cups.service [Service]ExecStart=/usr/sbin/cupsd -fPrivateTmp=true

[Install]Also=cups.socket cups.pathWantedBy=printer.target

● ExecStart= 起動時に実行するコマンド。ExecStop等の指定がなければ終了時はここで作成されたプロセスへ「SIGTERM送信→タイムアウト待ち→SIGKILL

送信」による終了処理を行う● PrivateTmp= namespaceを利用して自分のサービスからだけ見える /tmp を

作成して利用する。脆弱性回避に有効● Also= このunitを有効にする時に指定したunitも有効化する● WantedBy= 依存関係を挿入する。printer.tergetを有効化するとcups.service

を有効化するようになる

initスクリプト移行例 - cupsd (2)Socket Activation

cups.socket [Socket]ListenStream=/var/run/cups/cups.sock

● ListenStream= 指定したソケットをsystemdが待ちうけ● cups.socketだけをenable/startしている場合

– systemdがソケットのlistenを行い、はじめて接続がおこなわれた時点で対応するサービスを起動する(Socket Activation)

– この例ではcups.socketを待ちうけてcups.serviceを起動する● cups.socketとcups.serviceの両方をenable/startしている場

合– 起動完了待ち(printer.target)またはsocketが必要になるどちらか早いタイミングでサービスを起動する

initスクリプト移行例 - cupsd (3)Path based Activation

● ファイルやディレクトリの存在や変更を検知して対応するサービスを起動する(Path based activation)

● この例では/var/spool/cups/d*(未処理の印刷Jobに対応するファイル) が存在すればcups.serviceを起動する

cups.path

[Path]PathExistsGlob=/var/spool/cups/d*

[Install]WantedBy=multi-user.target

initスクリプト移行例 - iptables (1)

serviceコマンドの独自拡張● /etc/init.dスクリプトで独自拡張を行っている

– service iptables save

● 通常のserviceファイル以外に以下のファイルで saveコマンドを実装– /usr/libexec/initscripts/legacy-actions/iptables/save

● iptables.initスクリプトのsaveサブコマンドを呼ぶだけ– /usr/libexec/iptables/iptables.init

● 元の/etc/init.d/iptablesそのままで場所だけ変更

● これらを用意することで、service iptables saveを以前と同様に実行できる

initスクリプト移行例 - iptables (2)[Unit]Description=IPv4 firewall with iptablesAfter=syslog.targetConditionPathExists=/etc/sysconfig/iptables

[Service]Type=oneshotRemainAfterExit=yesExecStart=/usr/libexec/iptables/iptables.init startExecStop=/usr/libexec/iptables/iptables.init stopEnvironment=BOOTUP=serialEnvironment=CONSOLETYPE=serialStandardOutput=syslogStandardError=syslog

● ConditionalPathExists= でファイルが存在する場合のみ実行。同様のConditional* パラメータを多数提供

● Type=oneshotとRemainAfterExit=yesでiptables.initが実行終了してもサービスが実行中という状態が維持される

サービスを強制終了する

● あるサービスを今すぐ強制終了したい– サービスに関係するプロセスにkill -KILLする

● 「関係するプロセス」をどうやって発見するか?

– 伝統的手法: 起動したプロセスのPIDを/var/run以下に保存

– 直接の親子関係にあるプロセスは(ほぼ)みつけられる● double forkするプロセスはどうしよう?

– systemdではcontrol groupsで追跡● 関係するプロセスが明示的にcontrol groups を切り替えなけ

れば全て追跡可能

systemd-cgls, systemctl kill

● 各ユニット毎に所属するプロセス群を整理して表示● control groupによる追跡でdaemoniseされても問題ない● systemctl killでunit内全プロセスを対象としてシグナル送信systemctl kill -s 9 crond.service

– 代表プロセスのみ、シグナルの種類など選択可能

├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 23├─system.slice│ ├─avahi-daemon.service│ │ ├─956 avahi-daemon: running [snake.local│ │ └─979 avahi-daemon: chroot helpe│ ├─dbus.service│ │ └─926 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation│ ├─firewalld.service│ │ └─923 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid│ ├─ModemManager.service│ │ └─958 /usr/sbin/ModemManager│ ├─lvm2-lvmetad.service│ │ └─13929 /usr/sbin/lvmetad -f(以下略)

systemd-cgtop

● control groupを資源利用量で整列し、topのように一覧– CPU使用率、メモリ使用量、ディスクI/O量

journaldによるロギング

journaldイメージ図

kernel dmesg

/dev/log(syslog)

サービスのstdout/stderr

journald nativeインタフェース

systemd-journald

journalfile

journalfile

journalfile

rsyslogimjournal

journalctll

syslogfile

バイナリログuid毎に分離

テキストログ設定により

優先度等で分離

クエリによりjournal file群から

ログを検索・整形・表示

journaldが解決する問題 (1)

起動直後のログ保存● syslogdが起動する以前のログを統一的に扱う

– syslogdはroot fsマウント後に起動する– 「起動しない」トラブルではこの時点のログが必須

● 従来の対応:

– カーネルについては? → rc.sysinitで dmesg に出力– ユーザランドのものは? → plymouthで boot.logに出力

● journaldでの対応:

– journaldはinitramfsに含まれ、起動直後のroot fs mount以前から起動– メモリ(tmpfsの/run/log/journal)上にログを保存– syslogdがjournaldに接続し、通常のsyslog出力として起動直後のログ

をディスクへ保存

journaldが解決する問題 (2)

● syslogの制限– 取得できるがログに残せないメタデータが多数ある– 多くのメタデータをクライアントが偽装できてしまう

● ログの圧縮● ログ改竄検知● logrotateにたよらないログファイルの切り替え● ログの検索、インデクシング● ログの権限管理

– ユーザが自分自身で出力したログは参照させたい

journaldによるロギング● メタデータ付加

– マイクロ秒64bitでのタイムスタンプ, 起動からの時間, ログの優先度, systemdのunit, cgroup,

SELinuxコンテキスト, boot ID, machine ID等– クライアントから送られる情報と照合できる

● 独自バイナリフォーマット– 圧縮・インデクシング・改竄検出対応– ユーザ毎に分離

● journaldによる自動的かつ透過的なrotate

– SIGUSR2送信による強制rotateも可● journalctlコマンドによるクエリ

– メタデータによる絞り込み● デフォルトではjournaldのログは揮発性。永続化はrsyslogで行う

– tmpfsの/run/log/journal 以下に収集する。サイズ上限になれば古いものから消す– rsyslogのimjournalモジュールでjournaldから読みだし、syslogとして保存

● mkdir /var/log/journal するとここへjournaldのログを保存

journaldで付加されるメタデータ例__CURSOR=s=70bed981e31a46e2a70c56776402e0eb;i=342;b=982826bc22454f079fd46ec94e2b__REALTIME_TIMESTAMP=1407830743019247__MONOTONIC_TIMESTAMP=1792842_BOOT_ID=982826bc22454f079fd46ec94e2b67fcPRIORITY=6_UID=0_GID=0_MACHINE_ID=025b7ff2c8af43f78513996f06584c4c_HOSTNAME=localhost.localdomainSYSLOG_IDENTIFIER=systemdSYSLOG_FACILITY=3CODE_FILE=src/core/unit.cCODE_LINE=1115CODE_FUNCTION=unit_status_log_starting_stopping_reloadingMESSAGE_ID=7d4958e842da4a758f6c1cdc7b36dcc5_TRANSPORT=journal_PID=1_COMM=systemd_EXE=/usr/lib/systemd/systemd_CAP_EFFECTIVE=1fffffffff_SYSTEMD_CGROUP=/_CMDLINE=/usr/lib/systemd/systemd --switched-root --system --deserialize 20_SELINUX_CONTEXT=system_u:system_r:init_t:s0UNIT=rsyslog.serviceMESSAGE=Starting System Logging Service..._SOURCE_REALTIME_TIMESTAMP=1407830743019153

カーソル位置時刻(usec)

起動からの経過時間BOOT IDログ優先度

UIDGID

マシンIDホスト名

syslogのIDと ファシリティソースコード 内の行番号 内の関数名

メッセージのID接続方法

PIDコマンド名実行ファイルCAPABILITY

CGROUPコマンドライン

SELinuxコンテキストsystemdのunit名メッセージ本文

出力時の時刻(usec)

journalctlでのクエリ例

journalのサイズ指定

● 自動設定のロジック– (TODO: ディスクサイズの20%とかのロジックを

ここにかく。● 手動での設定

– (TODO: journald.confでの設定

systemdの設定ファイル

systemdの各サービスのconfig

● /etc/systemd/bootchart.conf● /etc/systemd/journald.conf● /etc/systemd/logind.conf● /etc/systemd/system.conf● /etc/systemd/user.conf

各種config

● /etc/hostname

– ホスト名– インストール時に設定, hostnamectlコマンドで操作– /etc/sysconfig/network から移行

● /etc/locale.conf

– システムのlocale

– インストール時に設定, localectlコマンドで操作– systemdから起動されるunitは基本的にこのlocaleで実行される

● /etc/localtime

– システムのtimezone

– /etc/timezoneから移行– インストール時に設定, timedatectlコマンドで操作

各種config

● /etc/machine-id

– システムに固有な128bit ID

– インストール時に生成, 一旦ファイルを消してからsystemd-

machine-id-setupコマンドで再生成– journaldやdbusで利用– /var/lib/dbus/machine-idから移行

● /etc/machine-info

– ホスト名の別名やアイコン等(主にデスクトップ用途で利用)

– hostnamectlで操作● /etc/vconsole.conf

– 仮想コンソールのキーマップやフォント設定– インストール時に設定, localectlやsystem-config-keyboardで操作

各種config

● /etc/crypttab

– 暗号化ブロックデバイスの設定● /etc/os-release

– OS名やバージョン番号、バグレポート時の製品ID等– /etc/redhat-releaseを強化したもの。redhat-

releaseも引き続き提供

設定ディレクトリ

● binfmt.d● modules-load.d● sysctl.d● tmpfiles.d