Kubernetes で Pod(正確にはコンテナ単位)に securityContext.readOnlyRootFilesystem: true
を設定すると,ルートファイルシステムを読み取り専用にして書き込み操作を抑止できる.アプリケーションのセキュリティ対策として使える.補足をすると Kubernetes 固有の機能ではなく,Docker にも docker run
コマンドに --read-only
オプションが用意されている.
securityContext: readOnlyRootFilesystem: true
検証 : BusyBox
まず securityContext.readOnlyRootFilesystem: true
を設定して BusyBox を起動するサンプルマニフェストを作る.
apiVersion: v1 kind: Pod metadata: name: busybox spec: containers: - name: busybox image: busybox:1.34 command: ['sh', '-c', 'sleep 3600'] securityContext: readOnlyRootFilesystem: true
実際に Pod を起動して,書き込み操作(とファイル削除)をすると Read-only file system
というエラーになった.
$ kubectl apply -f busybox.yaml $ kubectl exec -it busybox -- /bin/sh / # touch hello.txt touch: hello.txt: Read-only file system / # rm /bin/sh rm: remove '/bin/sh'? y rm: can't remove '/bin/sh': Read-only file system
検証 : nginx
次は securityContext.readOnlyRootFilesystem: true
を設定して nginx を起動するサンプルマニフェストを作る.
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx:1.21 securityContext: readOnlyRootFilesystem: true
今度は Pod を起動することができなかった.Pod のログを確認すると Read-only file system
というエラーで nginx を起動すらできていなかった.実際にアプリケーションに securityContext.readOnlyRootFilesystem: true
を設定するのは簡単ではなく,書き込みをする可能性のあるディレクトリを洗い出しておく必要がある.
$ kubectl apply -f nginx.yaml $ kubectl logs nginx /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh 10-listen-on-ipv6-by-default.sh: info: can not modify /etc/nginx/conf.d/default.conf (read-only file system?) /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh /docker-entrypoint.sh: Configuration complete; ready for start up 2022/04/13 00:00:00 [emerg] 1#1: mkdir() "/var/cache/nginx/client_temp" failed (30: Read-only file system) nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (30: Read-only file system)
nginx の例だと,Docker Hub の nginx ドキュメントに載っている Running nginx in read-only mode が参考になる.デフォルト構成の nginx では /var/cache
と /var/run
に書き込み操作をすると書いてある.他にもログを確認しながらサンプルマニフェストを修正する.
最終的に以下のサンプルマニフェストでうまく Pod を起動できるようになった.今回は emptyDir
でボリュームを作って,以下の 3 ディレクトリにマウントした.
/etc/nginx/conf.d
/var/cache/nginx
/var/run
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx:1.21 securityContext: readOnlyRootFilesystem: true volumeMounts: - name: etc-nginx mountPath: /etc/nginx/conf.d - name: var-cache mountPath: /var/cache/nginx - name: var-run mountPath: /var/run volumes: - name: etc-nginx emptyDir: {} - name: var-cache emptyDir: {} - name: var-run emptyDir: {}
参考 : EKS Best Practices Guides
EKS Best Practices Guides にも securityContext.readOnlyRootFilesystem: true
を設定する件が載っている.