$30 off During Our Annual Pro Sale. View Details »

半年前の自分に教えたい systemd のハマりどころ

半年前の自分に教えたい systemd のハマりどころ

Sho Iizuka

May 19, 2019
Tweet

More Decks by Sho Iizuka

Other Decks in Programming

Transcript

  1. 半年前の自分に教えたい systemd のハマりどころ
    1
    @shora_kujira16
    dbus / systemd を話すお茶会

    View Slide

  2. 自己紹介
    2
    • 所属:サイボウズ株式会社 クラウド運用チーム
    • 2019年1月よりオンコールに参加中
    • 最近取り組んでいること
    • MySQL の IO 周りのチューニング
    • CPU やメモリのリソース割り当ての改善
    • 古いサービスの systemd への移植

    View Slide

  3. 発表内容
    3
    古いサービスを systemd に移植したときにいろいろな間違いをしてきました。
    「昔の自分に教えたいハマりどころ」を共有させてください。
    1. Wants = network.target はだいたい間違っている
    2. WantedBy = default.target?
    3. drop-in の意外な仕様
    4. Requires= は「このサービスの起動に必要」ではない
    5. Assert と Condition の微妙な違い
    6. After= が使えるのは正しく作られたサービスに限る
    資料作成間に合わず

    View Slide

  4. Wants = network.target はだいたい間違っている
    4
    ネットワーク接続が必要なサービスを作るとき ↓ は だいたい間違っている
    書くべきだったのは多くの場合これ
    もしくはこっち
    [Unit]
    Wants = network.target
    [Unit]
    After = network.target
    [Unit]
    Wants = network-online.target
    After = network-online.target

    View Slide

  5. Wants = network.target はだいたい間違っている
    5
    どうしてこういうことが起こるのか?
    • network.target と network-online.target の違いが知られていない
    • special passive system unit について知られていない

    View Slide

  6. Wants = network.target はだいたい間違っている
    6
    network.target と network-online.target の違い
    • network.target … ネットワーク管理スタックが起動した
    • network-online.target … ネットワークが使えるようになった
    (「使える」の定義はネットワーク管理スタックに依存する)
    ※ ネットワーク管理スタック … Ubuntu 18.04 では systemd-networkd
    以下に記載がある
    https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/

    View Slide

  7. Wants = network.target はだいたい間違っている
    7
    • (別のサーバーに接続するために)
    ネットワークが利用可能になるのを待つ必要があるサービスの場合
    • ネットワークが利用可能になるのを待たなくても
    起動してよいサービスの場合(例:apache, sshd)
    [Unit]
    Wants = network-online.target
    After = network-online.target
    [Unit]
    After = network.target シャットダウン時に graceful stop するために
    このサービスを止めた後にネットワークを止める
    (stop 時は ordering dependency が逆になることに注意)

    View Slide

  8. Wants = network.target はだいたい間違っている
    8
    special passive system unit とは
    • man 7 systemd.special の Special Passive System Units を参照
    • 起動順序の制御のために用意されている特殊な target
    • サービスの利用側 (consumer) が Wants= を設定するのではなく
    サービスの提供側 (provider) が Wants= を設定する
    consumer
    provider
    [Unit]
    Wants = network.target
    Before = network.target
    [Unit]
    After = network.target

    View Slide

  9. Wants = network.target はだいたい間違っている
    9
    multi-user.target
    foo.service
    network.target
    systemd-
    networkd.service
    Wants=
    Wants=, After=
    Wants=, After=
    まちがい

    View Slide

  10. Wants = network.target はだいたい間違っている
    10
    multi-user.target
    foo.service
    network.target
    systemd-
    networkd.service
    Wants=
    After=
    Wants=, Before=
    せいかい
    Wants=

    View Slide

  11. Wants = network.target はだいたい間違っている
    11
    結論
    • network.target は Wants= や Requires= に設定してはいけない
    (※ あなたがネットワーク管理スタックの開発者である場合を除く)
    • 多くの場合、書くべきだったのはこれ
    • ほかに気を付けたほうが良さそうなのは time-sync.target と
    nss-lookup.target
    [Unit]
    Wants = network-online.target
    After = network-online.target

    View Slide

  12. WantedBy = default.target?
    12
    OS 起動時に自動起動させたいサービスは次のように書くことが多い
    仕組み
    • systemd は OS 起動時に default.target を activate する
    • default.target は multi-user.target (≒ runlevel 3) や
    graphical.target (≒ runlevel 5) の symlink になっている
    • systemctl enable すると multi-user.target.wants 以下に
    symlink が生成される
    • multi-user.target が activate されるときに一緒に起動する
    [Install]
    WantedBy = multi-user.target

    View Slide

  13. WantedBy = default.target?
    13
    とある Web サイトの記載

    View Slide

  14. WantedBy = default.target?
    14
    • レスキューモードで起動すると default.target = rescue.target になる
    • WantedBy = default.target と指定すると当然起動する
    • そのサービス、レスキューモードでも必要???

    View Slide

  15. WantedBy = default.target?
    15
    • この書き方は Red Hat Customer Portal で見つけた
    • 間違っているのは私のほうではないかと疑心暗鬼になっています
    https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-managing_services_with_systemd-unit_files

    View Slide

  16. drop-in の意外な仕様
    16
    drop-in とは
    • /etc/systemd/system/foo.service.d に .conf ファイルを置くと
    オリジナルのファイルを override できる
    • sudo systemctl edit foo.service を使うとエディタが起動して
    いい感じにしてくれる

    View Slide

  17. drop-in の意外な仕様
    17
    • 例:ExecStopPost= を追加してサービス停止時に
    クリーンアップ処理を追加したい
    • 例:デフォルトのクリーンアップ処理を別の処理に置き換えたい
    # /etc/systemd/system/foo.service.d/override.conf
    [Service]
    ExecStopPost=/usr/local/bin/foo-cleanup
    # /etc/systemd/system/foo.service.d/override.conf
    [Service]
    ExecStopPost=
    ExecStopPost=/usr/local/bin/foo-cleanup

    View Slide

  18. drop-in の意外な仕様
    18
    man 5 systemd.unit の最後

    View Slide

  19. drop-in の意外な仕様
    19
    man 5 systemd.unit の最後

    View Slide

  20. drop-in の意外な仕様
    20
    • Before=, After=, Wants=, Requires= などは空行でリセットできない
    • systemd-sysv-generator で自動生成されたファイルは
    無駄な dependency が設定されていることがある(特に Ubuntu 16.04)
    • drop-in を使って直したくなるが、残念ながら使えない
    • 自作するか、Ubuntu 18.04 から backport してくるとよい
    (Ubuntu 18.04 は自動生成ではなく、ちゃんと作られていることが多い)
    # /etc/systemd/system/foo.service.d/override.conf
    [Unit]
    After=
    After=bar.service
    ← これはダメ

    View Slide