説明
kubernetes(k8s)のマニフェストにSecurity Contextを設定することで、コンテナに対しての権限設定をすることができます。
主に以下のものが設定できます。
・ファイルやオブジェクトのアクセス制御、ユーザID(UID)・グループ(GID)の設定
・SELinux設定
・特権モードor非特権モードの設定
・Capability(Linux Capabilities)の設定
・AppArmor:プロファイルを適用して、個々のプログラムの機能を制限
・Seccomp:プロセスのシステムコールをフィルタリング
・AllowPrivilegeEscalation:プロセスがその親プロセスよりも多くの特権を取得可能かどうかの制御
・readOnlyRootFilesystem:コンテナのルートファイルシステムを読み取り専用としてマウント
など様々な設定ができます。
今回はお試しで一部の機能について紹介します。
雰囲気だけでも掴んでいただけたらよさげです。
環境
・VirutalBox
・vagrant
・ubuntu仮想サーバ(k8sのホスト)
・minikube
以下のDockerfileを用意します。
$ vi Dockerfile FROM centos:centos7 RUN yum update -y && \ yum install -y epel-release && \ yum install -y libcap-ng-utils
イメージの作成
docker build --tag codemogu/centos:0.1 .
ファイルやオブジェクトのアクセス制御
Dockerでコンテナを作成すると、デフォルトの場合ユーザやグループの権限である、uidやgidはroot(0)となります。
こちらを変更する際は、k8sのマニフェストに「runAsUser」「runAsGroup」に記載する必要があります。今回は、2つのコンテナを作成してコンテナ同士のボリュームの共有を確認のためにしたいので、「fsGroup」の設定もします。
確認のためにDockerでコンテナを作ると権限は以下のようになります。
$ docker run -itd --name test_container codemogu/centos:0.1 /bin/sh $ docker exec -it test_container /bin/bash [root@hogehoge /]# id uid=0(root) gid=0(root) groups=0(root)
①. Pod Security Contextを設定して、Pod全てに権限を付与し、ファイルを共有する
SecurityContextをcontainersと同じインデントの位置で設定することで、すべてのコンテナに同じ設定が追加されます。
マニフェストの作成
$vi security.yml apiVersion: v1 kind: Pod metadata: name: security spec: securityContext: runAsUser: 1000 runAsGroup: 3000 fsGroup: 2000 restartPolicy: OnFailure containers: - name: container1 image: codemogu/centos:0.1 command: ["/bin/sh"] args: ["-c", "while :; do sleep 10; done"] volumeMounts: - name: data-vol mountPath: /var/tmp/container1 - name: container2 image: codemogu/centos:0.1 command: ["/bin/sh"] args: ["-c", "while :; do sleep 10; done"] volumeMounts: - name: data-vol mountPath: /var/tmp/container2 volumes: - name: data-vol emptyDir: terminationGracePeriodSeconds: 0
実行&確認
$ kubectl apply -f security.yml pod/security created $ kubectl get po NAME READY STATUS RESTARTS AGE security 2/2 Running 0 3m18s
container1に入って、idの確認とテストファイルを作成します。
$ kubectl exec -it security -c container1 /bin/bash bash-4.2$ id uid=1000 gid=3000 groups=3000,2000 bash-4.2$ echo fafafa >> /var/tmp/container1/text.txt bash-4.2$ cat /var/tmp/container1/text.txt fafafa
container2に入ってidの確認とテストファイルが共有できているか確認します。
$ kubectl exec -it security -c container2 /bin/bash bash-4.2$ id uid=1000 gid=3000 groups=3000,2000 bash-4.2$ cat /var/tmp/container2/text.txt fafafa
確認できました。
②. コンテナ毎にSecurity Contextを設定して、ファイル共有できるか確認をする
SecurityContextをcontainersよりもインデントを下位に設定することで、コンテナ毎に設定ができます。
上記のマニフェスト書き方は違いますが、意味は同じです。
$vi security2.yml apiVersion: v1 kind: Pod metadata: name: security spec: restartPolicy: OnFailure securityContext: fsGroup: 2000 containers: - name: container1 image: codemogu/centos:0.1 command: ["/bin/sh"] args: ["-c", "while :; do sleep 10; done"] volumeMounts: - name: data-vol mountPath: /var/tmp/container1 securityContext: runAsUser: 1000 runAsGroup: 3000 - name: container2 image: codemogu/centos:0.1 command: ["/bin/sh"] args: ["-c", "while :; do sleep 10; done"] volumeMounts: - name: data-vol mountPath: /var/tmp/container2 securityContext: runAsUser: 1000 runAsGroup: 3000 volumes: - name: data-vol emptyDir: terminationGracePeriodSeconds: 0
実行と確認方法は①を参考にやってください。
※fsGroupは「Pod Security Context」扱いなので、containers内のsecurityContextに記載して実行することはできません。
以上です。
Capability(ケーパビリティ)の設定
Capability設定ををして、コンテナに時間設定をできるようにする
LinuxにはCapabilityという設定がいくつか存在し、rootが持っている絶対的な権限を細かく分けて、必要な権限だけを与えることができるそうです。( ゚д゚)
pscapコマンドで一覧が確認できます。
コンテナの場合はDockerコマンドのオプションやkubernetesのマニフェストに記載することで、このCapability設定をすることができます。
たとえば、通常デフォルトのコンテナでは、時間の設定をする権限がなく、時間変更ができません。
$ docker run -itd --name test_container codemogu/centos:0.1 /bin/sh $ docker exec -it test_container /bin/bash [root@hogehoge /]# pscap ppid pid name command capabilities 0 6 root bash chown, dac_override, fowner, fsetid, kill, setgid, setuid, setpcap, net_bind_service, net_raw, sys_chroot, mknod, audit_write, setfcap [root@hogehoge /]# date -s "04/01 13:00 2020" date: cannot set date: Operation not permitted
上記のように、rootユーザにも関わらず、日付の変更ができません。
kubernetesのマニフェストを用いて、Capability設定をコンテナに付加して、時間の変更できるようにします。
$vi security3.yml apiVersion: v1 kind: Pod metadata: name: security spec: restartPolicy: OnFailure containers: - name: container1 image: codemogu/centos:0.1 securityContext: capabilities: add: ["SYS_TIME"] command: ["/bin/sh"] args: ["-c", "while :; do sleep 10; done"] terminationGracePeriodSeconds: 0
実行
$ kubectl apply -f security3.yml pod/security created
コンテナに入って時間の変更
$ kubectl exec -it security -c container1 /bin/bash [root@security /]# date -s "04/01 13:00 2020" Wed Apr 1 13:00:00 UTC 2020 ・ ・ しばらくすると・・。 [root@security /]# date Mon Jan 4 07:37:59 UTC 2021 もとに戻った( ゚Д゚)
コンテナの時間の変更はできるようになりました!しかしなぜ戻ってしまったかは不明です。
なにかしらのkubernetesの便利機能なのかなー。( ゚Д゚)
まあ今回はこれくらいでいいやー。
その他
SecurityContextには上記以外にもいろいろあるので、試してみてください。
・特権・非特権コンテナ
・ spec: privileged: true ・
・親よりも強いプロセスにするかどうか
・ containers: - name: fafafa image: fafafa securityContext: allowPrivilegeEscalation: false ・
・ルートファイルシステムへの書き込みするかどうか
readOnlyRootFilesystem:false
・SELinuxの設定
・ ・ securityContext: seLinuxOptions: level: "s0:c123,c456" ・ ・
などなど調べたらいっぱい出てきます。
以上です。
コメント