衝突なしでコンテナ内のPID 1プロセスをホット交換します。

衝突なしでコンテナ内のPID 1プロセスをホット交換します。

ご存知のように、OCIコンテナ(通常Dockerコンテナと呼ばれます)は、エントリポイントプロセス(コンテナのネームスペース内でPID1とも呼ばれます)が終了すると終了します。

ただし、このコンテナ内にシェルアクセス権限とroot権限がある場合は、このPID 1プロセスをホット交換する方法があるかどうか疑問に思います。

PID1がプロセスであるとしましょう。コンテナをシャットダウンせずにPIDを維持しながら(プロセス自体で実行されているように)、[/bin/sleep, 99999]まったく新しいプロセスに置き換える方法はありますか?[/bin/sleep, 100]

この質問は、実行可能ファイルを置き換えるのではなく、実行中のプロセス自体を別のプロセスに置き換えることについてです。

ベストアンサー1

まるでプロセス自体で実行されたかのように

方法は、プロセスにexecveを呼び出すことです。

これがデバッガがすることです。

少なくともプロセスを実行するユーザーの権限が必要です。設定によって異なるkernel.yama.ptrace_scope、コンテナ内でルートになる必要があるかもしれません。これは通常同じです。コンテナの外部にどの権限が適用されるのかわかりません。どうすればいいのかわかりません。ptrace アクセス確認ルールDockerとやり取りします。

shとgdbを使用するスクリプトです。コンテナの内部(PIDに1転送)または外部(コンテナ初期化プロセスのPID転送)で実行できます。

#!/bin/sh
set -e

help_and_exit () {
  cat <<EOF
Usage: $0 PID COMMAND [ARG...]
Use gdb to replace the running process PID by the specified command.
EOF
  exit $1
}
if [ "$1" = "--help" ]; then
  help_and_exit
elif [ $# -lt 2 ]; then
  help_and_exit 120 >&2
fi

pid=$1; shift

# Quote the command path and the arguments as a C string.
args=
add_arg () {
  args="$args\""
  while case "$1" in *[\\\"]*) true;; *) false;; esac; do
    set -- "${1#*[\\\"]}" "${1%"${1#*[\\\"]}"}"
    args="$args${2%?}\\${2#"${2%?}"}"
  done
  args="$args$1\", "
}
add_arg "$1"
args="$args$args"; shift
for x; do
  add_arg "$x"
done
args="${args}(char*)0"

gdb -n -pid "$pid" -batch -ex "call execlp($args)"

gdbをインストールしたくない場合は、PythonまたはC(または必要な言語)で必要なインストールを実行する小さなプログラムを書くことができます。ptrace着信電話。

コンテナのPID 1がinitとして使用するためのプログラムである場合は、それを再実行するように指示する方法がある可能性があるため、それを使用する必要があります。プログラムは実行前に削除することができ、後続の実行可能ファイルにファイルや環境変数などの追加データを渡すことができます。

おすすめ記事