Oracle Cloud Hangout Cafe Season5 #3「Kubernetes のセキュリティ」(2022年3月9日開催)

2023年4月18日(火)
市川 豊
連載第4回の今回は、2022年3月9日に開催された「Oracle Cloud Hangout Cafe Season5 #3『Kubernetes のセキュリティ』」の発表内容に基づいて紹介していきます。

Minimize Microservice Vulnerabilities

ここでは、マイクロサービスの脆弱性を最小限に抑えるという観点から、最初にContainerおよびPodにおけるSecurityContextについて解説します。次にPodSecurityPolicyの後継となるPod Security StandardsとPod Security Admissionについて解説し、最後にコンテナランタイムセキュリティにおけるgVisor およびKata Containersの概要を理解して、実際にRuntimeClassを利用してgVisorの環境を構築します。

SecurityContext

SecurityContextは、Pod全体およびPod内の各コンテナにアクセス制御を設定できる仕組みです。マニフェストで定義します。

SecurityContext for Pod

Podに設定できるSecurityContextの主な設定項目を下表に示します。

設定項目 概要
privileged Podの特権実行
readOnlyRootFilesystem RootファイルシステムをReadOnlyとするかの制御
drunAsUser 実行するユーザ
runAsGroup 実行するグループ
runAsNonRoot rootでの実行を拒否
fsGroup ファイルシステムのグループ指定
runtimeClass Podで許可するruntimeClassを指定
supplementalGroups プライマリGIDに追加付与するGIDリストを指定

以下は、「runAsNonRoot」によりNginx Podが作成できないマニフェストの例です。

apiVersion: v1
kind: Pod
metadata:
  name: pod-sc
spec:
  securityContext:
    runAsNonRoot: true
  containers:
  - name: nginx-container
    image: nginx:1.21

SecurityContext for Container

コンテナに設定できるSecurityContextの主な設定項目を下表に示します。

設定項目 概要
privileged 特権コンテナ実行
capabilities Capabilitiesの追加/削除
allowPrivilegeEscalation コンテナ実行時に親プロセス以上の権限を与えるか制御
readOnlyRootFilesystem RootファイルシステムをReadOnlyとするかの制御
runAsUser 実行するユーザ
runAsGroup 実行するグループ
runAsNonRoot rootでの実行を拒否
seLinuxOptions コンテナで使用するSELinuxオプション
seccompProfile コンテナで使用するseccompオプション
windowsOptions コンテナ(windows)で使用するWindows固有の設定

以下は、「runAsNonRoot」によりNginx Podが作成できないマニフェストの例です。

apiVersion: v1
kind: Pod
metadata:
  name: container-sc
spec:
  containers:
  - name: nginx-container
    image: nginx:1.21
    securityContext:
      runAsNonRoot: true

Podおよびコンテナの両方にSecurityContextを定義した場合は、コンテナのSecurityContextが優先されます。

apiVersion: v1
kind: Pod
metadata:
  name: both-test
spec:
  securityContext:
    runAsUser: 1000
  containers:
  - name: ubuntu
    image: ubuntu:21.10
    securityContext:
      runAsUser: 1001
    command:
      - sleep
      - infinity

Podに対するsecurityContextは、コンテナ間で共有されるリソースやコンテナの動作に関する制限を定義するのに適しています。一方、コンテナに対するsecurityContextは、個々のコンテナの動作に関する制限を定義するのに適しています。

Pod Security Standards & Pod Security Admission

PodSecurityPolicyはβ版として提供され続けてきましたが、Kubernetes v1.21から非推奨となりv1.25で廃止されました。発表時は、この過渡期にあたりPodSecurityPolicyの説明とデモを実施しました。執筆時は既にv1.25がリリースされているので、ここではPodSecurityPolicyの後継となるPod Security StandardsとPod Security Admission について解説します。

Pod Security Standardsは、PodセキュリティにおけるKubernetes公式のガイドラインです。以下3種類のポリシーがあります。

ポリシー 概要
Privileged 無制限ポリシー
Baseline 最小限の制限ポリシー
Restricted 最も厳しい制限ポリシー

【参考】「Pod Security Standards

上記の通り、Pod Security Standardsはガイドラインです。このガイドラインに準拠しているかを検証して、対象となるKubernetesクラスタに適用する/しない仕組みが必要となります。その仕組みがPod Security Admissionです。Admission ControllerとしてValidate機能(執筆時点でMutation機能は未提供)を提供します。そして、以下3つのモードを実装しています。

モード 概要
enforce 違反したPodの作成を拒否
audit 違反したらKubernetesのAudit Logのアノテーションとして記録(作成拒否はされない)
warn 違反したら警告表示(作成拒否はされない)

【参考】「Pod Security Admission

Pod Security StandardsのポリシーとPod Security Admissionのモードを組み合わせて、対象となるKubernetesクラスタのNamespaceに紐づけることで、Podのセキュリティを強化します。そのため、PodSecurityPolicyのように専用のリソースはありません。

Namespaceのマニフェストで、以下のように定義します。

apiVersion: v1
kind: Namespace
metadata:
  labels:
    pod-security.kubernetes.io/enforce: privileged
    pod-security.kubernetes.io/audit: privileged
    pod-security.kubernetes.io/warn: baseline
  name: sample

以下のようにバージョンも設定できます。

apiVersion: v1
kind: Namespace
metadata:
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/enforce-version: v1.26
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/audit-version: v1.26
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/warn-version: v1.26
  name: sample

マニフェストに定義しない場合、つまりデフォルト設定はenforce、audit、warn全てにおいてprivilegedです。バージョンはlatestです。Namespace毎に適用するのではなく、Kubernetesクラスタのデフォルトポリシーとして定義したい場合は「AdmissionConfiguration」としてマニフェストを作成し、kube-apiserverに設定できます。

kubectlコマンドにおいてdry-run実行できるため、適用前に検証できます。

Container Runtime Sandboxes

コンテナランタイムに関するセキュリティについて、コンテナランタイムをおさらいしながらgVisorとKata Containersを説明します。そして、Kubernetesクラスタ上でRuntime Classを利用してgVisorをコンテナランタイムとして利用する方法を学びます。

1. コンテナランタイム
Kubernetesにおけるコンテナランタイムは、ノード上のコンテナとコンテナイメージを管理します。コンテナランタイムには、高レベルコンテナランタイムと低レベルコンテナランタイムがあります。

高レベルコンテナランタイムは、イメージの取得や展開、ローカルイメージの管理を行います。そして、低レベルコンテナランタイムにコンテナの実行命令を受け渡します。主な高レベルコンテナランタイムはcontainerd、cri-oです。

低レベルコンテナランタイムは、高レベルコンテナランタイムからの実行命令を受け、Linuxカーネルの機能(namespace、cgroups)を使用してコンテナを作成します。低レベルコンテナランタイムの実体はバイナリです。主な低レベルコンテナランタイムはrunC、gVisor、Kata Containersです。

Kubernetesにおけるコンテナランタイム

※CRI(Container Runtime Interface)は、kubeletがコンテナランタイムを操作するためのインタフェース。

2. gVisor
gVisorはGoogle LLCが開発したコンテナランタイム(低レベルコンテナランタイム)です。コンテナ内のプロセスをサンドボックス化することで、高いセキュリティと信頼性を実現します。そして、Linuxカーネルのnamespaceとcgroups機能を利用してコンテナ内のプロセスを分離し、さらにLinuxのユーザーランドにおいて再実装することで、より強固なサンドボックス化を実現します。

Linuxユーザーランドでは、SentryというGoで作られたプログラムがカーネルとしてアプリケーションからのsyscallを処理するため、Linux カーネルに到達するsyscallが大幅に縮小し、攻撃対象を狭めることでよりセキュリティを強化します。

【参考】「What is gVisor?

3. Kata Containers
Kata Containersは、仮想化技術を利用して作成した軽量なハイパーバイザー上で動作し、コンテナ個別にカーネルを動作させることでコンテナ間の分離を図り、セキュリティを強化するコンテナランタイム(低レベルコンテナランタイム)です。

【参考】「Kata Containers

3. Runtime Class
Runtime Classは、KubernetesにおいてgVisorやKata ContainersなどのコンテナランタイムをPod起動時に選択できる仕組みです。Runtime Classを利用することで、コンテナランタイムレベルでセキュリティを強化できます。

実際に、Runtime ClassでcontainerdをgVisorに変更し、Nginx Podを起動する流れを見ていきます。

  1. kube-apiserverのAdmission ControlでRuntimeClassを有効化する
  2. gVisorのRuntimeClassマニフェストの作成および適用
    ※事前にgVisorインストールおよびcontainerdへの設定は完了前提
  3. Nginx PodをgVisorに指定して起動

Runtime Classの利用

1. kube-apiserverのAdmission ControlでRuntimeClassを有効化する
コントロールプレーンのノードにログインし、kube-apiserverのAdmission ControlでRuntimeClassを有効化します。「--enable-admission-plugins」に「RuntimeClass」を設定します。

$ vim /etc/kubernetes/manifests/kube-apiserver.yaml
・
・(省略)
・
spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=10.0.0.2
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=NodeRestriction,RuntimeClass
・
・(省略)
・

2. gVisorのRuntimeClassマニフェストの作成および適用
事前にgVisorインストールおよびcontainerdへの設定が必要となります。以下参考サイトです。

gVisor Install
Containerd Quick Start

RuntimeClassのマニフェストを作成します。

【マニフェスト:runtimeclass.yaml】
apiVersion: node.k8s.io/v1beta1
kind: RuntimeClass
metadata:
  name: gvisor
handler: runsc

マニフェストを適用します。

$ kubectl apply -f runtimeclass.yaml
runtimeclass.node.k8s.io/gvisor created

3. Nginx PodをgVisorに指定して起動
「pod.spec.runtimeClassName」にRuntimeClass名を定義したマニフェストを作成します。

【マニフェスト:gvisor-nginx.yaml】
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: gvisor-nginx
  name: gvisor-nginx
spec:
  runtimeClassName: gvisor
  containers:
  - image: nginx:1.21
    name: gvisor-nginx
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Never
status: {}

マニフェストを適用します。

$ kubectl apply -f gvisor-nginx.yaml
pod/gvisor-nginx created

「gvisor-nginx」Podに接続し、「Starting gVisor…」としてgVisorで起動していることを確認します。

$ kubectl exec -it gvisor-nginx -- /bin/bash

dmesg
[    0.000000] Starting gVisor...
[    0.168305] Creating cloned children...
[    0.433689] Creating bureaucratic processes...
[    0.491369] Daemonizing children...
[    0.798069] Mounting deweydecimalfs...
[    0.897569] Searching for needles in stacks...
[    0.967286] Reading process obituaries...
[    1.027207] Synthesizing system calls...
[    1.342101] Checking naughty and nice process list...
[    1.749487] Recruiting cron-ies...
[    2.123900] Singleplexing /dev/ptmx...
[    2.534325] Ready!
日本オラクル株式会社

Oracle Groundbreaker Advocate
Principal Cloud Solution Engineer

これまで、インフラエンジニア、フロントエンドエンジニアとして官公庁のシステム基盤を中心としたサーバの設計構築、運用保守、Webシステム開発を担当。技術教育者として専門学校でクラウド技術やOSS(Linux、Docker、Kubernetes)の授業を担当し、企業様向けプライベートトレーニング講師も担当。 アドボケート/エバンジェリストとしてミートアップ、カンファレンスで登壇。現在は、クラウドネイティブ技術を中心とするソリューションエンジニアとして活動。クラウドネイティブ技術に関連するコミュニティの運営にも積極的に参加。

Community:
Oracle Cloud Hangout Cafe メンバー (#ochacafe)
CloudNative Days Tokyo 実行委員会メンバー (#CNDT)

Book:
著書「Dockerコンテナ開発・環境構築の基本」(インプレス)
共著「RancherによるKubernetes活用完全ガイド」(インプレス)、「コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤」(翔泳社)

連載バックナンバー

仮想化/コンテナ技術解説
第6回

Oracle Cloud Hangout Cafe Season6 #1「Service Mesh がっつり入門!」(2022年9月7日開催)

2023/6/22
連載第6回の今回は、2022年9月7日に開催された「Oracle Cloud Hangout Cafe Season6 #1『Service Mesh がっつり入門!』」の発表内容に基づいて紹介していきます。
仮想化/コンテナ技術解説
第5回

Oracle Cloud Hangout Cafe Season5 #5「実験! カオスエンジニアリング」(2022年5月11日開催)

2023/5/18
連載第5回の今回は、2022年5月11日に開催された「Oracle Cloud Hangout Cafe Season5 #5『実験! カオスエンジニアリング』」の発表内容に基づいて紹介していきます。
仮想化/コンテナ技術解説
第4回

Oracle Cloud Hangout Cafe Season5 #3「Kubernetes のセキュリティ」(2022年3月9日開催)

2023/4/18
連載第4回の今回は、2022年3月9日に開催された「Oracle Cloud Hangout Cafe Season5 #3『Kubernetes のセキュリティ』」の発表内容に基づいて紹介していきます。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています