k8sの実行中のコンテナで対話型シェルを実行してアレコレやってみた

dockerコマンドで、コンテナにログインする様な行為、docker run -it centos:6 bash と同じことを Kubernetesの環境ではどうするんだっけ? と基本的なことから、ポッドに二つのコンテナを動作させた場合の特徴的な振る舞いについて、書きました。

NGINXコンテナを起動する

kubectl apply -f shell-demo.yaml を実行して、NGINXのHTTPサーバーのポッドを起動する。

shell-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: shell-demo
spec:
  volumes:
  - name: shared-data
    emptyDir: {}
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
$ kubectl apply -f shell-demo.yaml
pod "shell-demo" created

ポッドを起動を確認する

$ kubectl get pod shell-demo
NAME         READY     STATUS    RESTARTS   AGE
shell-demo   1/1       Running   0          36s

NGINXコンテナで対話型シェルを動かす

コンテナには、ユーザーIDとパスワードで、利用者を識別して、利用を許可するという機能は無く、ポッド名(=コンテナ)とシェルを指定してコンテナのプロセス空間にアクセスする。

$ kubectl exec -it shell-demo -- /bin/bash
root@shell-demo:/# ls /
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

コンテナにパッケージを追加

コンテナは、カーネルをコンテナのホストに依存するが、OSソフトウェアパッケージは、独立したLinuxディストリビューションなので、パッケージを更新したり、インストールしたりできる。

root@shell-demo:/# apt-get update
...
root@shell-demo:/# apt-get install -y tcpdump

コンテナでカーネルが同じことを確認

わき道に逸れるのですが、コンテナ・ホストのカーネルを共有している事を見たいと思います。

ノードOSのカーネル

まずは、ノードであるコンテナ・ホストのOSカーネルを見ておきます。

$ uname -a
Linux k8s1 4.4.0-121-generic #145-Ubuntu SMP Fri Apr 13 13:47:23 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

NGINXのポッドのカーネル

Linuxのディストリビューションは、GNU/Debian 9 なんだけど、カーネルは、コンテナ・ホストと同じです。

$ kubectl exec -it shell-demo -- sh
root@shell-demo:/# uname -a
Linux shell-demo 4.4.0-121-generic #145-Ubuntu SMP Fri Apr 13 13:47:23 UTC 2018 x86_64 GNU/Linux
root@shell-demo:/# cat /etc/issue
Debian GNU/Linux 9 \n \l

CentOS6のポッドのカーネル

CentOS6 のコンテナを起動して、カーネルのバージョンを見ます。 以下、CentOS 6.9 なのに、Ubuntu カーネル 4.4.0です。

$ kubectl apply -f shell-demo-c6.yaml 
pod "shell-demo-c6" created

$ kubectl exec -it shell-demo-c6 -- bash
[root@shell-demo-c6 /]# uname -a
Linux shell-demo-c6 4.4.0-121-generic #145-Ubuntu SMP Fri Apr 13 13:47:23 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
[root@shell-demo-c6 /]# cat /etc/issue
CentOS release 6.9 (Final)
Kernel \r on an \m

以下はポッドのYAMLファイルで、imageは、公式コンテナ CentOS:6 です。

shell-demo-c6.yaml
apiVersion: v1
kind: Pod
metadata:
  name: shell-demo-c6
spec:
  volumes:
  - name: shared-data
    emptyDir: {}
  containers:
  - name: centos-v6
    image: centos:6
    volumeMounts:
    - name: shared-data
      mountPath: /mnt
    command: ["sleep","3600"]

2つのコンテナを動かすポッドで、指定して対話シェルを起動

ポッドの最大の特徴は、一つのポッドで複数のコンテナを動作させる事ができる点だと思います。以下のYAMLファイルを利用して、2つのコンテナが動作するポッドを起動します。

$ kubectl apply -f shell-demo-2in1.yaml

YAMLファイルの補足として、spec.containers で、 二つの名前があり、一つはnginxで、もう一つはbusyboxです。 そのままコンテナのイメージ名となっていますが、異なる名前を付与する事ができます。 busyboxはコマンドを指定して、1時間は終了しない様にしておきます。

shell-demo-2in1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: shell-demo-2in1
spec:
  volumes:
  - name: shared-data
    emptyDir: {}
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
  - name: busybox
    image: busybox
    volumeMounts:
    - name: shared-data
      mountPath: /work
    command: ["sleep","3600"]

起動結果

このポッドは、READYの列で, 2/2 となっていて、 コンテナを2つ持っており、2つともREADYであることを示しています。

vagrant@k8s1:/vagrant/yaml/demo-shell$ kubectl get po
NAME                        READY     STATUS    RESTARTS   AGE
shell-demo                  1/1       Running   0          19m
shell-demo-2in1             2/2       Running   0          15s
shell-demo-c6               1/1       Running   0          19m

コンテナを指定して対話シェルの実行

次の様に、YAMLファイルで指定したコンテナ名を利用して、同一ポッド内のそれぞれのコンテナで、シェルを実行できます。

  • $ kubectl exec -it shell-demo-2in1 --container nginx -- sh
  • $ kubectl exec -it shell-demo-2in1 --container busybox -- sh

nginxコンテナと対話シェル実行

nginxを動作させるだけに、最小化されているので、psコマンドも入っていません。 echoでindex.htmlを作って、busyboxからアクセスを試みます。

$ kubectl exec -it shell-demo-2in1 --container nginx -- sh

# ps aux
sh: 1: ps: not found

# hostname
shell-demo-2in1

# echo Hello Container in same Pod > /usr/share/nginx/html/index.html

# cat /usr/share/nginx/html/index.html
Hello Container in same Pod

busyboxコンテナと対話シェル実行

ps コマンで観ても、nginxは動作していません。 しかし、ローカルホストのHTTP(80)番ポートへアクセスすると 前述で書き込んだindex.htmlの結果が帰ってきます。 ホスト名、ネットワーク、ファイルシステムの一部を共有して、しかも、OSのプロセス空間が区切られているという事が判ると思います。

$ kubectl exec -it shell-demo-2in1 --container busybox -- sh

/ # wget -O - -q http://localhost:80/
Hello Container in same Pod

/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 sleep 3600
    6 root      0:00 sh
   13 root      0:00 ps aux

/ # hostname
shell-demo-2in1

参考資料

  1. https://kubernetes.io/docs/tasks/debug-application-cluster/get-shell-running-container/
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.