microk8sでエフェメラルコンテナをさわってみた
microk8s 1.18.0(latest/stable 4/13時点)の環境でエフェメラルコンテナをさわってプロセステーブルの共有を確認しました。
動かすまでそこそこ苦労したので記録を残しておきます。
kubelet/kube-apiserverにオプションを追加
--feature-gatesというオプションでEphemeralContainers=trueと、kubeletならびにkube-apiserverに対してカツを入れてやる必要があります。
microk8s v1.18では、
> /snap/microk8s/current/kube-apiserver --help
<snip>
--feature-gates mapStringBool
<snip>
EphemeralContainers=true|false (ALPHA - default=false)
> /snap/microk8s/current/kubelet --help
<snip>
--feature-gates mapStringBool
<snip>
EphemeralContainers=true|false (ALPHA - default=false)
とどちらもデフォルトでfalseになってるんですな。
今回は(正直よくわからんかったので)コマンド引数の設定ファイルを編集することで対応しました。
対象ファイルはどこかいなと探してみると、/snap以下に/snap/microk8s/current/default-args/というディレクトリがあり、kube-apiserverとkubeletというファイルが収められています。中を見るとまんま引数が書いてあるので、喜び勇んでrootで編集しようとするとパーミッションで撥ねられます。
今まで全然知らなかったんですけど、snapのディレクトリは
> mount -l
<snip>
/var/lib/snapd/snaps/microk8s_1320.snap on /snap/microk8s/1320 type squashfs (ro,nodev,relatime,x-gdu.hide)
と、イメージをroでマウントしとるんですな。
/snap以下をremountするとか恐ろしい方法もなくはないんでしょうが、他にファイルがあるんじゃないかと探してみると/var/snap/microk8s/current/argsにファイルがあるのでこいつでトライしてみます。
--feature-gates=EphemeralContainers=true
という行を、ファイルkube-apiserverとkubeletにそれぞれ追加し、systemctlでsnap.microk8s.daemon-apiserver.serviceとsnap.microk8s.daemon-kubelet.serviceを再起動します。(関係ないがこのオプションの書き方、最近よく見かけるけどすげえ気持ち悪い・・・)
すると、
> pgrep -a kubelet
134465 /snap/microk8s/1320/kubelet --kubeconfig=/var/snap/microk8s/1320/credentials/kubelet.config \
--cert-dir=/var/snap/microk8s/1320/certs --client-ca-file=/var/snap/microk8s/1320/certs/ca.crt \
--anonymous-auth=false --network-plugin=cni --root-dir=/var/snap/microk8s/common/var/lib/kubelet \
--fail-swap-on=false --cni-conf-dir=/var/snap/microk8s/1320/args/cni-network/ \
--cni-bin-dir=/snap/microk8s/1320/opt/cni/bin/ --feature-gates=DevicePlugins=true \
--eviction-hard=memory.available<100Mi,nodefs.available<1Gi,imagefs.available<1Gi \
--container-runtime=remote --container-runtime-endpoint=/var/snap/microk8s/common/run/containerd.sock\
--node-labels=microk8s.io/cluster=true --cluster-domain=cluster.local --cluster-dns=10.152.183.10 \
--feature-gates=EphemeralContainers=true
と最終行に反映されていたので、きっと対処としては間違ってなかったのでしょう・・・
ちなみに、kube-apiserverにオプションつけないときは後述のkubectl replace実行時に
Error from server (NotFound): the server could not find the requested resource
と怒られ、kubeletにつけないときは特にエラーを出さずにimage pull以降をサボタージュするという素敵な振る舞いをします。
Pod起動
今回は以下の定義でnginxを起動しました。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
shareProcessNamespace: true
containers:
- name: nginx-container
image: nginx:latest
ports:
- containerPort: 80
shareProcessNamespaceってのが、Pod内のコンテナがプロセステーブルを共有する設定になります。
エフェメラルコンテナの起動
以下のファイルを用意します。なんでこっちはjsonなんだと自分でも思いますがとりあえず気にせず進めましょう。
{
"apiVersion": "v1",
"kind": "EphemeralContainers",
"metadata": {
"name": "nginx"
},
"ephemeralContainers": [{
"command": [
"sh"
],
"image": "ubuntu:latest",
"imagePullPolicy": "IfNotPresent",
"name": "debugger",
"stdin": true,
"tty": true,
"terminationMessagePolicy": "File"
}]
}
このファイルをkubectl replaceに食わせます。
> kubectl replace --raw /api/v1/namespaces/default/pods/nginx/ephemeralcontainers -f ec.json
{"kind":"EphemeralContainers","apiVersion":"v1",
"metadata":
{"name":"nginx",
"namespace":"default",
"selfLink":"/api/v1/namespaces/default/pods/nginx/ephemeralcontainers",
"uid":"359938c9-6053-47af-96a1-8d2bc2be9948",
"resourceVersion":"606335",
"creationTimestamp":"2020-04-13T09:40:59Z"},
"ephemeralContainers":
[{"name":"debugger",
"image":"ubuntu:latest",
"command":["sh"],
"resources":{},
"terminationMessagePolicy":"File",
"imagePullPolicy":"IfNotPresent",
"stdin":true,
"tty":true}]}
(適当に改行してます)
podを確認してみると、
> kubectl describe pods nginx
Name: nginx
Namespace: default
Priority: 0
Node: xxx/192.168.1.13
Start Time: Mon, 13 Apr 2020 18:40:59 +0900
Labels: <none>
Annotations: Status: Running
IP: 10.1.2.7
IPs:
IP: 10.1.2.7
Containers:
nginx-container:
Container ID: containerd://d399885861114d018c8cf51d89ee5c8a45c8ef9ae948d494092b8a63e57d850c
Image: nginx:latest
Image ID: docker.io/library/nginx@sha256:282530fcb7cd19f3848c7b611043f82ae4be3781cb00105a1d593d7e6286b596
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Mon, 13 Apr 2020 18:41:05 +0900
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-z6rfv (ro)
Ephemeral Containers:
debugger:
Container ID: containerd://ab534051c891ea7daf9d1d6042dd8956acabb4021f79dacda3a4c3846c092377
Image: ubuntu:latest
Image ID: docker.io/library/ubuntu@sha256:bec5a2727be7fff3d308193cfde3491f8fba1a2ba392b7546b43a051853a341d
Port: <none>
Host Port: <none>
Command:
sh
State: Running
Started: Mon, 13 Apr 2020 18:41:14 +0900
Ready: False
Restart Count: 0
<snip>
という感じで、エフェメラルコンテナの状態がState: Runningで表示されました。Ready: Falseというのが何事かと思いますが、公式のドキュメントを見ても同様でしたのでとりあえず気にしないことにします。
エフェメラルコンテナの利用
kubectl attachを使ってシェルログインしてみます。
> kubectl attach -it nginx -c debugger
If you dont see a command prompt, try pressing enter.
# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 1020 4 ? Ss 12:01 0:00 /pause
root 6 0.0 0.0 10628 5468 ? Ss 12:01 0:00 nginx: master process nginx -g daemon off;
101 11 0.0 0.0 11084 2588 ? S 12:01 0:00 nginx: worker process
root 12 0.0 0.0 4624 1604 pts/0 Ss 12:05 0:00 sh
root 617 0.0 0.0 18504 3464 pts/0 S 12:26 0:00 bash
root 624 0.0 0.0 34400 2912 pts/0 R+ 12:27 0:00 ps aux
という感じで、psでお隣のコンテナのnginxプロセスを捕捉できます。
調子に乗ってサーバ側で
# echo 0 > /proc/sys/kernel/yama/ptrace_scope
した上でdebugコンテナにgdbをインストールして動かしてみましたが、
# gdb --pid 6
<snip>
Attaching to process 6
warning: "target:/usr/sbin/nginx": could not open as an executable file: Operation not permitted.
<snip>
と怒られてしまいました。記憶域は共有してないんでそりゃそうですね。nginxの実行環境をdebugコンテナに用意してやればよさそうですが完全に同一な環境を作るのは結構めんどくさそうですね。そうでもないかな?
gcoreでcoreを吐かせることもできました。
プロセス状態
ホスト側からプロセス状態を見ると
> pstree -ATp
(snip)
|-containerd(14073)-+-containerd-shim(15655)---pause(15676)
(snip)
| |-containerd-shim(22806)---nginx(22837)---nginx(22853) (nginxコンテナ)
| `-containerd-shim(29248)---sh(29265) (debugコンテナ)
という感じで、まぁ別コンテナなので当たり前といえば当たり前の状態でした。
同様にホスト側で/proc下を見たところ、
# ll /proc/{15676,22837,29265}/ns/pid
lrwxrwxrwx 1 root root 0 Apr 13 21:22 /proc/15676/ns/pid -> 'pid:[4026532745]'
lrwxrwxrwx 1 root root 0 Apr 13 21:22 /proc/22837/ns/pid -> 'pid:[4026534072]'
lrwxrwxrwx 1 root root 0 Apr 13 21:22 /proc/29265/ns/pid -> 'pid:[4026534072]'
となっており、nginxコンテナとdebugコンテナで別コンテナでありながら同じプロセステーブルを見ていることがわかります。
というわけで簡単ですが以上です
追記(2020/11/20)
gdbつかって解析する場合は当然、gcore使ってのコア出力の場合でも、対象コンテナとエフェメラルコンテナのglibcバージョンは揃える必要があります。アプリごとに好きな実行環境(ベースイメージ)を使っていいというのがマイクロサービスのいいところだと思うのですが、あまりバラバラだと面倒ですね。対象コンテナと同一イメージつかってエフェメラルコンテナ作るのが手っ取り早いんでしょうね
参考:
https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/
https://kubernetes.io/ja/docs/tasks/configure-pod-container/share-process-namespace/
Author And Source
この問題について(microk8sでエフェメラルコンテナをさわってみた), 我々は、より多くの情報をここで見つけました https://qiita.com/runaway_cat/items/b91817d0c041c9586a00著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .