paint-brush
Systemd を使用した Micro-DevOps: 通常の Linux サーバーをスーパーチャージする@tylerjl
5,280 測定値
5,280 測定値

Systemd を使用した Micro-DevOps: 通常の Linux サーバーをスーパーチャージする

Tyler6m2023/09/05
Read on Terminal Reader

長すぎる; 読むには

Kubernetes のようなコンテナ オーケストレーターは、目まぐるしいほどの機能を提供しますが、さらに複雑になるというコストを支払う必要がありますか? systemd の最新機能が Linux 上のワークロードのセキュリティと復元力を管理し、小規模で効率的に実行するのにどのように役立つかについて学びます。
featured image - Systemd を使用した Micro-DevOps: 通常の Linux サーバーをスーパーチャージする
Tyler HackerNoon profile picture
0-item
1-item

Kubernetes、Nomad、またはクラウドでホストされるサービスとしてのプラットフォーム (Paas) などのプラットフォームは、さまざまな強力な機能を提供します。ワークロードのスケーリングからシークレット管理、展開戦略に至るまで、これらのワークロード オーケストレーターは、さまざまな方法でインフラストラクチャを拡張できるように最適化されています。


しかし、通信事業者は常に最大限のスケーラビリティを得るためにコストを支払う必要があるのでしょうか?場合によっては、複雑さと抽象化によるコストがその利点を上回ることがあります。代わりに、多くのビルダーは、管理を容易にするために、非常にシンプルな展開アーキテクチャに依存するようになります。ロード バランサーの背後にある 2 つの仮想プライベート サーバーは、コンテナ ホストのフリート全体にわたるマイクロサーバーの無秩序なクラスターと比較して、管理が大幅に簡単なスタックです。これは、問題が発生したときにデバッグする可動部分が少なくなったり、メンテナンスの時期が来たときにアップグレードしたりするときに効果を発揮し始める可能性があります。


多くの最新の Linux ディストリビューションの基盤はsystemdであり、コンテナ オーケストレーターや PaaS システムに匹敵する強力な機能セットが付属しています。この記事では、最新の systemd 機能を活用して、管理に頭を悩ませることなく他の大規模システムの多くの機能を獲得し、通常のLinuxサーバーを非常に有能なアプリケーション プラットフォームに強化する方法を説明します。

systemd 入門書

単一ホストで systemd .serviceファイルを作成するのは、管理対象プロセスを実行する理想的な方法です。ほとんどの場合、アプリケーションを変更する必要はまったくありません。systemd はさまざまな種類のサービスをサポートしており、それに応じて適応できます。


たとえば、単純な Web サービスの実行方法を定義する次の単純な.serviceについて考えてみましょう。


 [Unit] Description=a simple web service [Service] ExecStart=/usr/bin/python3 -m http.server 8080


systemd サービスのデフォルトを思い出してください。ExecStart ExecStart=は絶対パスである必要があり、プロセスはバックグラウンドにフォークしてはならず、場合によっては、 Environment=オプションを使用して必要な環境変数を設定する必要があります。


/etc/systemd/system/webapp.serviceのようなファイルに配置すると、 systemctlで制御できるサービスが作成されます。


  • systemctl start webappプロセスを開始します。
  • systemctl status webappサービスが実行されているかどうか、その稼働時間、 stderrおよびstdoutからの出力、プロセスの ID およびその他の情報を表示します。
  • systemctl stop webappサービスを終了します。


さらに、 stderrおよびstdoutに出力されるすべての出力は、journald によって集約され、システム ジャーナル ( journalctlを使用) 経由でアクセスするか、 --unitフラグを使用して特にターゲットを指定してアクセスできます。


 journalctl --unit webapp


Journald はデフォルトでストレージをローテーションして管理するため、ジャーナルを介してログを収集することは、ログ ストレージを管理するための優れた戦略です。


この記事の残りの部分では、このようなサービスを強化するオプションを検討します。

秘密

Kubernetes などのコンテナ オーケストレーターは、 Secret を安全に注入する機能をサポートしています。これは、安全なデータストアから取得され、実行中のワークロードに公開される値です。 API キーやパスワードなどの機密データは、意図しない公開を避けるために、環境変数や構成ファイルとは異なる処理が必要です。


LoadCredential=systemd オプションは、ディスク上のファイルから機密値をロードし、それらを安全な方法で実行中のサービスに公開することをサポートします。シークレットをリモートで管理するホスト型プラットフォームと同様に、systemd は資格情報を環境変数などの値とは異なる方法で扱い、安全に保管します。


シークレットを systemd サービスに挿入するには、まずシークレット値を含むファイルをファイルシステム上のパスに配置します。たとえば、API キーを.serviceユニットに公開するには、再起動後もファイルを保持するために/etc/credstore/api-keyにファイルを作成するか、ファイルが永続的に保持されるのを避けるために/run/credstore/api-keyファイルを作成します。 path は任意ですが、systemd はこれらのcredstoreパスをデフォルトとして扱います)。どちらの場合も、 chmod 400 /etc/credstore/api-keyのようなコマンドを使用して、ファイルに制限されたアクセス許可を設定する必要があります。


.serviceファイルの[Service]セクションで、 LoadCredential=オプションを定義し、コロン ( :で区切られた 2 つの値 (資格情報の名前とそのパス) を渡します。たとえば、 /etc/credstore/api-keyファイルを「トークン」と呼ぶには、次の systemd サービス オプションを定義します。


 LoadCredential=token:/etc/credstore/api-key


systemd がサービスを開始すると、シークレットは${CREDENTIALS_DIRECTORY}/token形式のパスで実行中のサービスに公開されます。 ${CREDENTIALS_DIRECTORY}は systemd によって設定される環境変数です。アプリケーション コードは、API トークンやパスワードなどの安全な値を必要とするライブラリやコードで使用するために、この方法で定義された各シークレットを読み取る必要があります。たとえば、Python では、次のようなコードを使用してこのシークレットを読み取ることができます。


 from os import environ from pathlib import Path credentials_dir = Path(environ["CREDENTIALS_DIRECTORY"]) with Path(credentials_dir / "token").open() as f: secret = f.read().strip()


その後、API トークンまたはパスワードを必要とする可能性のあるライブラリに対して、シークレットの内容を含むsecret変数を使用できます。

再起動

Nomadのようなオーケストレーターのもう 1 つの機能は、クラッシュしたワークロードを自動的に再起動する機能です。未処理のアプリケーション エラーによるものであっても、その他の原因によるものであっても、障害が発生したアプリケーションの再起動は非常に便利な機能であり、多くの場合、アプリケーションの回復力を設計する際の防御の最前線となります。


Restart= systemdオプションは、 systemd が実行中のプロセスを自動的に再起動するかどうかを制御します。このオプションにはいくつかの値が考えられますが、基本的なサービスの場合は、 on-failure設定がほとんどのユースケースを満たすのに適しています。


自動再起動を構成するときに考慮すべきもう 1 つの設定はRestartSec RestartSec=オプションです。これは、サービスを再起動するまで systemd が待機する時間を指定します。通常、この値は、タイトなループで失敗したサービスが再起動され、プロセスの再起動に CPU 時間が過剰に消費される可能性を避けるためにカスタマイズする必要があります。通常は、 5sなど、待ち時間が長くなりすぎない短い値で十分です。


期間または時間ベースの値を受け入れるRestartSec=などのオプションは、ニーズに応じて5min 10s1hourなどのさまざまな形式を解析できます。詳細については、systemd.time のマニュアルを参照してください。


最後に、他の 2 つのオプションは、systemd が最終的に諦める前に、失敗したユニットの再起動をどの程度積極的に試みるかを決定します。 StartLimitIntervalSec=およびStartLimitBurst=指定された期間内にユニットの起動を許可する頻度を制御します。たとえば、次のような設定です。


 StartLimitBurst=5 StartLimitIntervalSec=10


ユニットは 10 秒間で最大 5 回まで起動を試行できます。構成されたサービスが 10 秒以内に 6 回目の起動を試行すると、systemd はユニットの再起動を停止し、代わりにユニットをfailedとしてマークします。


これらの設定をすべて組み合わせると、 .serviceユニットに次のオプションを含めて自動再起動を構成できます。


 [Unit] StartLimitBurst=5 StartLimitIntervalSec=10 [Service] Restart=on-failure RestartSec=1


この構成では、サービスが失敗した場合 (つまり、ゼロ以外の終了コードなどで予期せず終了した場合) に 1 秒待機した後に再起動し、途中で 5 回を超えてサービスの起動を試行した場合はサービスの再起動を停止します。 10秒間。

サービスの強化

コンテナ内で実行する主な利点の 1 つは、セキュリティ サンドボックスです。アプリケーション プロセスを基盤となるオペレーティング システムからセグメント化することで、サービスに存在する可能性のある脆弱性が本格的な侵害に発展することがはるかに困難になります。 Docker のようなランタイムは、cgroup と他のセキュリティ プリミティブを組み合わせてこれを実現します。


いくつかの systemd オプションを有効にして、基盤となるホストを予測できないワークロード動作から保護するのに役立つ同様の制限を適用できます。


  • ProtectSystem= /boot/usrなどの機密システム パスへの書き込みアクセスを制限できます。このオプションのドキュメントには、使用可能なすべてのオプションが列挙されていますが、一般に、これらのファイルシステム パスを保護するには、このオプションをfullに設定するのが妥当なデフォルトです。
  • ProtectHome=読み取り専用設定で/home/root 、および/run/userディレクトリをread-onlyに設定するか、 trueに設定すると、サービスのファイル システムに空のディレクトリとしてマウントできます。アプリケーションがこれらのディレクトリにアクセスする必要がある場合を除き、これをtrueに設定すると、これらのディレクトリへの不正アクセスに対してシステムを安全に強化できます。
  • PrivateTmp=構成されたサービスに対して個別の/tmpおよび/var/tmpを維持するため、このサービスおよび他のプロセスの一時ファイルは非公開のままになります。プロセスが一時ファイルを介して情報を共有するやむを得ない理由がない限り、これは有効にすると便利なオプションです。
  • NoNewPrivileges=実行されたプロセスが特権を昇格できないようにすることで、サービスを強化するもう 1 つの安全で簡単な方法です。他の強化オプションを使用できるかどうかわからない場合は、通常、これを有効にしても問題が最も少ないオプションの 1 つです。


systemd.exec のマニュアル ページは、サービスなどの実行可能なワークロードに適用されるさまざまなオプションを調べるのに役立つリソースです。

参考文献

systemd プロジェクトのマニュアル ページは広範であり、独自のアプリケーションを実行するために利用できるすべてのオプションについて学ぶのに役立ちます。 Web サーバーなどの永続サービスを実行している場合でも、cron ジョブを置き換えるための定期的な.timerユニットを実行している場合でも、systemd ドキュメントが役立つガイダンスを提供します。