Certified Kubernetes Security Specialist (CKS) #20 フルスケール実技模擬試験: 16 のタスク + 解説

#1 試験環境 から #19 試験のコツ まで、全 6 ドメインを一周しました。このシリーズの最終回は読む記事ではなく 解く記事 です。実際の CKS と同じく、全ドメインを統合した 16 のタスクを一か所に集めました。択一式ではなく、空のターミナルとノードの上で直接クラスターをより安全に変える実技シナリオで、各タスクには配点が付いています。

推奨される制限時間は実際の試験と同じ 2 時間 です。合格ラインは 67% で、16 のタスクの配点を合算して採点します。あるタスクで詰まったら印を付けて飛ばし、配点が高く手に馴染んだタスクから点数を積み上げる運用が合格ラインを越える道です。

CKS もクラスターが複数あるため、コンテキスト切り替えを最初に 行う習慣が誤答を防ぎます。各タスクは指定されたコンテキストで解いて初めて採点され、AppArmor・seccomp・Falco のようにノードの中に入って Linux のセキュリティツールを直接扱うタスクが多いので、SSH・systemctl・ファイル編集の感覚も併せて必要です。各タスクは まず自力で最後まで解いてから 正解を開いてください。先に正解を読むと手が慣れません。

解き方 #

  1. CKA が前提なので、ノードに SSH で入って systemctl・ファイル編集をするタスクは慣れているべきです。ローカルで難しければ、クラウド VM 2、3 台で control plane 1 台とワーカー 1 台を立てておきます。AppArmor・seccomp・Falco は単一ノードの minikube では感覚が活きないため、カーネルのセキュリティモジュールが有効な一般的な Linux ノードで解くのが実戦に近いです。
  2. タスクごとに指定された コンテキストを先に切り替えます。このシリーズで繰り返したとおり、コンテキストの設定ミスは正解を書いても 0 点です。
k config use-context <問題で指定したコンテキスト>
  1. SSH でノードに入るタスクがあるので、試験が提示するホスト名 (node01 など) で接続できるかを事前に確認します。ノードの上で root 権限が必要なら sudo -i で切り替えます。
  2. 16 個を 最後まで解いてから 正解を開いて一度に採点します。途中で正解を見ると実際の試験感覚が薄れます。kubernetes.io/docs と併せて Falco・Trivy・AppArmor・gVisor の公式ドキュメントの閲覧が許可されるので、各ツールのドキュメントでプロファイルの文法やコマンドオプションがどこにあるかを事前に把握しておくと時間を節約できます。

ドメイン分布 #

実際の CKS のドメイン比重に合わせて 16 のタスクを配置しました。後ろの 3 ドメイン (マイクロサービス・サプライチェーン・ランタイム) がそれぞれ 20% で合わせて 60% を占めるため、タスク数もそちらに多く載せました。

#ドメインタスク数タスク番号
1Cluster Setup21, 2
2Cluster Hardening23, 4
3System Hardening35, 6, 7
4Minimize Microservice Vulnerabilities38, 9, 10
5Supply Chain Security311, 12, 13
6Monitoring, Logging and Runtime Security314, 15, 16

配点はドメイン比重とタスクの難易度を反映し、合計 100 点としました。採点基準は記事末にまとめています。


タスク 1 (6 点): Cluster Setup #

コンテキスト cluster1 のネームスペース payments に default deny を適用してください。このネームスペースのすべての Pod は ingress と egress がデフォルトで遮断される必要がありますが、ただしすべての Pod がクラスター DNS (kube-system の 53 ポート、TCP・UDP) には出られる必要があります。

正解

すべての ingress・egress を塞ぐ default deny と DNS egress の許可を併せて適用します。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: payments
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: payments
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53
k apply -f deny.yaml
k -n payments get netpol

解説: 空の podSelector: {} はネームスペースのすべての Pod を対象にします。policyTypesIngressEgress を両方入れてルール本体を空にすると双方向の default deny になります。NetworkPolicy は累積許可なので、2 つ目のポリシーで DNS だけを再び開けます。egress を塞ぐと DNS のクエリまで切れて、すべての通信が名前解決の段階で失敗するのが最もよくある落とし穴なので、53 ポートの許可を落とさないようにします。

タスク 2 (6 点): Cluster Setup #

control plane ノードで kube-bench を実行して CIS benchmark を点検した結果、--profiling がオンで --insecure-port が 0 ではないという FAIL が出ました。kube-apiserver の 2 つの設定を CIS 推奨に合わせて直し、FAIL を解消してください。

正解

control plane ノードで apiserver の static Pod マニフェストを修正します。

ssh cluster1-controlplane
sudo -i

vim /etc/kubernetes/manifests/kube-apiserver.yaml

問題になった 2 つのフラグを次のように置きます。

    - --profiling=false
    - --insecure-port=0

kubelet がマニフェストの変更を検知して apiserver Pod を再生成するまで待った後、もう一度点検します。

crictl ps | grep kube-apiserver
kube-bench run --targets master

解説: --profiling=false はデバッグ用のプロファイリングエンドポイントを閉じて情報の露出を減らすという CIS 推奨で、--insecure-port=0 は認証なしの平文ポートを切るという推奨です。apiserver は static Pod なのでマニフェストを直すと kubelet が自動的に再生成するため、文法エラーで Pod が立たなければ crictl logs で原因を確認します。最新バージョンでは --insecure-port 自体が削除されていることがあるので、点検結果のフラグ名をそのまま踏襲するのが安全です。


タスク 3 (7 点): Cluster Hardening #

コンテキスト cluster1 で ClusterRole cluster-admin が ClusterRoleBinding で ServiceAccount dev:ci-runner に紐付いていて権限が過剰です。このバインディングを削除し、代わりにネームスペース dev で Pod と Deployment を照会 (get・list・watch) だけできる最小権限の Role と RoleBinding に置き換えてください。

正解

過剰な ClusterRoleBinding を消して、最小権限の Role を新たに紐付けます。

k delete clusterrolebinding ci-runner-admin

k -n dev create role ci-reader \
  --verb=get,list,watch \
  --resource=pods,deployments.apps
k -n dev create rolebinding ci-runner-read \
  --role=ci-reader \
  --serviceaccount=dev:ci-runner

権限が意図どおりに狭まったかを検証します。

k -n dev auth can-i list pods --as=system:serviceaccount:dev:ci-runner
k -n dev auth can-i delete pods --as=system:serviceaccount:dev:ci-runner

解説: 最小権限の原則は、主体に必要な動詞・リソース・ネームスペースだけを与えることです。cluster-admin は全クラスターのすべての動作を許可するため、CI ランナーには過剰です。検証では list podsyesdelete podsno になって初めて意図どおりに狭まったことになります。ClusterRole はそのままにしてバインディングだけを削除するのが核心で、ClusterRole 自体を消すと他の主体に影響を与えることがあります。

タスク 4 (7 点): Cluster Hardening #

ネームスペース legacy の ServiceAccount default とそのトークンをマウントして動く Pod report が API サーバーに不必要にアクセスします。report Pod が ServiceAccount トークンを自動マウントしないように止めてください。Pod を再生成してもかまいません。

正解

Pod マニフェストに automountServiceAccountToken: false を入れて再生成します。

k -n legacy get pod report -o yaml > report.yaml

spec の下に次のフィールドを追加します。

spec:
  automountServiceAccountToken: false
  containers:
    - name: report
      image: report:1.0
k -n legacy delete pod report
k apply -f report.yaml

マウントが消えたかを確認します。

k -n legacy exec report -- ls /var/run/secrets/kubernetes.io/serviceaccount

解説: automountServiceAccountToken: false は Pod の /var/run/secrets/kubernetes.io/serviceaccount パスにトークンを注入しないようにして、コンテナが奪取されても API サーバーの資格情報が漏れないようにします。このフィールドは Pod spec と ServiceAccount の両方に置けますが、Pod spec 側が優先されます。検証コマンドでディレクトリがないというエラーが出れば正常で、トークンがもうマウントされないという意味です。


タスク 5 (8 点): System Hardening #

ワーカーノード node01 に AppArmor プロファイル k8s-deny-write をロードし、ネームスペース apps の Pod guarded (イメージ nginx) がこのプロファイルをコンテナ web に適用するようにしてください。プロファイルは /etc/apparmor.d/k8s-deny-write にあり、ファイル書き込みを拒否する enforce モードのプロファイルです。

正解

ノードでプロファイルを enforce モードでロードします。

ssh node01
sudo -i

apparmor_parser -q /etc/apparmor.d/k8s-deny-write
aa-status | grep k8s-deny-write
exit

Pod に AppArmor プロファイルを指定します。

apiVersion: v1
kind: Pod
metadata:
  name: guarded
  namespace: apps
spec:
  containers:
    - name: web
      image: nginx
      securityContext:
        appArmorProfile:
          type: Localhost
          localhostProfile: k8s-deny-write
k apply -f guarded.yaml
k -n apps get pod guarded

解説: AppArmor プロファイルは コンテナが立つノードにあらかじめロードされていてこそ 適用されるため、apparmor_parser で enforce ロードする段階が抜けると Pod が Blocked 状態で止まります。最新の Kubernetes は securityContext.appArmorProfile フィールドを使い、type: LocalhostlocalhostProfile にプロファイル名 (ファイルパスではなくプロファイル名) を書きます。旧バージョンの container.apparmor.security.beta.kubernetes.io/<コンテナ> アノテーション方式も同じ効果ですが、試験のバージョンの方式に従います。

タスク 6 (8 点): System Hardening #

ネームスペース apps に Pod seccomp-web (イメージ nginx) を作りつつ、コンテナが RuntimeDefault seccomp プロファイルを使うようにしてください。このプロファイルはコンテナランタイムのデフォルトのブロックリストで危険なシステムコールを制限します。

正解

securityContext.seccompProfile を RuntimeDefault に置きます。

apiVersion: v1
kind: Pod
metadata:
  name: seccomp-web
  namespace: apps
spec:
  securityContext:
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: web
      image: nginx
k apply -f seccomp-web.yaml
k -n apps get pod seccomp-web

解説: RuntimeDefault はコンテナランタイム (containerd など) が提供するデフォルトの seccomp プロファイルを適用して、別途のファイルなしで危険なシステムコールを遮断します。Pod レベルの securityContext に置くとすべてのコンテナに継承され、コンテナレベルに置くとそのコンテナだけに適用されます。カスタムプロファイルが必要なら type: LocalhostlocalhostProfile でノードの /var/lib/kubelet/seccomp/profiles の下の JSON を指しますが、このタスクはデフォルトプロファイルなのでファイルは不要です。

タスク 7 (7 点): System Hardening #

ネームスペース apps の Deployment api が過剰な Linux capability を持って動きます。この Deployment のコンテナがすべての capability を捨てて NET_BIND_SERVICE 1 つだけを再び持つように、そして権限昇格を防ぐように securityContext を直してください。

正解

Deployment のコンテナの securityContext を修正します。

k -n apps edit deploy api

コンテナ spec に次を置きます。

        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop:
              - ALL
            add:
              - NET_BIND_SERVICE

ロールアウトが終わった後、新しい Pod に反映されたかを確認します。

k -n apps rollout status deploy api
k -n apps get pod -l app=api -o jsonpath='{.items[0].spec.containers[0].securityContext}'

解説: capabilities.drop: [ALL] ですべての権限をまず捨て、必要なものだけを add で復活させるのが最小権限のパターンです。NET_BIND_SERVICE は 1024 未満のポートのバインドに必要な権限なので、80 ポートを開く Web サーバーによく残します。allowPrivilegeEscalation: false は setuid バイナリなどでプロセスが親より大きな権限を得ることを防ぎます。Deployment を直すと template が変わり、Pod が新しく立ってから反映されます。


タスク 8 (7 点): Minimize Microservice Vulnerabilities #

ネームスペース restricted に Pod Security Admission の restricted 標準を enforce モードで強制してください。その後、この標準に違反する (root で動く) Pod を作ると拒否されるかを確認してください。

正解

ネームスペースに PSA ラベルを付けます。

k label namespace restricted \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=latest

違反 Pod の生成を試みて拒否されるかを確認します。

k -n restricted run rooty --image=nginx

拒否メッセージを確認した後、標準を通過する Pod で検証します。

apiVersion: v1
kind: Pod
metadata:
  name: compliant
  namespace: restricted
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: web
      image: nginx
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop:
            - ALL

解説: Pod Security Admission はネームスペースのラベルで動作し、enforceauditwarn の 3 モードがあります。enforce=restricted は違反 Pod の生成を完全に拒否します。restricted 標準は runAsNonRootallowPrivilegeEscalation: falsecapabilities.drop: [ALL]seccompProfile をすべて要求するため、普通の nginx Pod は root で立って拒否されます。ラベルキーが pod-security.kubernetes.io/enforce で正確でないと適用されません。

タスク 9 (7 点): Minimize Microservice Vulnerabilities #

control plane で etcd の保存データの Secret 暗号化をオンにしてください。AES-CBC (aescbc) 方式で新しい Secret が暗号化されて保存されるように EncryptionConfiguration を構成し、apiserver に適用してください。

正解

control plane ノードで暗号化設定ファイルを作ります。

ssh cluster1-controlplane
sudo -i

vim /etc/kubernetes/enc/enc.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64 でエンコードした 32 バイトのキー>
      - identity: {}

apiserver マニフェストに設定ファイルを連結します。

    - --encryption-provider-config=/etc/kubernetes/enc/enc.yaml

/etc/kubernetes/enc を apiserver コンテナに hostPath ボリュームとしてマウントした後、既存の Secret まで再暗号化します。

k get secrets --all-namespaces -o json | kubectl replace -f -

解説: providers リストの 順序 が重要です。最初の provider が書き込み暗号化に使われ、読み込みは上から試すため、aescbc を先頭に、identity (平文) を後ろに置きます。キーは 32 バイトを base64 でエンコードする必要があり、head -c 32 /dev/urandom | base64 で作ります。設定をオンにしても既存の Secret は自動的に再暗号化されないため、replace で書き直して初めて実際に暗号文になります。

タスク 10 (6 点): Minimize Microservice Vulnerabilities #

ランタイムの隔離が必要なワークロードのために gVisor を使う RuntimeClass gvisor (handler runsc) を作り、ネームスペース apps の Pod sandboxed (イメージ nginx) がこの RuntimeClass で立つようにしてください。ノードにはすでに runsc ハンドラーがインストールされています。

正解

RuntimeClass を作り、Pod から参照します。

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: gvisor
handler: runsc
---
apiVersion: v1
kind: Pod
metadata:
  name: sandboxed
  namespace: apps
spec:
  runtimeClassName: gvisor
  containers:
    - name: web
      image: nginx
k apply -f gvisor.yaml
k -n apps get pod sandboxed

解説: gVisor はシステムコールをユーザー空間で横取りするサンドボックスランタイムなので、コンテナエスケープの危険を大きく減らします。RuntimeClass の handler はノードランタイム (containerd) の設定に登録されたハンドラー名 (runsc) と正確に一致する必要があります。ハンドラーがないノードにスケジュールされると Pod がコンテナ生成の段階で失敗するため、隔離ノードを指す nodeSelector や toleration が併せて必要な場合が多いです。


タスク 11 (7 点): Supply Chain Security #

ネームスペース apps の Deployment legacy-app が重い node:18 イメージを使います。同じアプリを distroless ベースイメージの gcr.io/distroless/nodejs18-debian12 に変えて攻撃対象領域を減らしてください。イメージだけ置き換えればよく、ビルドはすでにできていると仮定します。

正解

Deployment のイメージを distroless に置き換えます。

k -n apps set image deploy/legacy-app \
  legacy-app=gcr.io/distroless/nodejs18-debian12

k -n apps rollout status deploy legacy-app

置き換えられたイメージを確認します。

k -n apps get deploy legacy-app -o jsonpath='{.spec.template.spec.containers[0].image}'

解説: distroless イメージはシェル・パッケージマネージャー・不要な OS ユーティリティを除き、アプリの実行に必要なランタイムだけを残して脆弱性の数と攻撃対象領域を大きく減らします。シェルがないので kubectl exec ... -- sh が動作しない点、そして ENTRYPOINT がアプリバイナリに固定される点がデバッグ時の落とし穴です。set image はコンテナ名を正確に指定する必要があり、名前が違うと新しいコンテナが追加されるのではなくコマンドが失敗します。

タスク 12 (7 点): Supply Chain Security #

control plane ノードでイメージ nginx:1.21.0 を Trivy でスキャンして HIGHCRITICAL 等級の脆弱性だけを抽出し、ファイル /opt/trivy-report.txt に保存してください。Trivy はノードにすでにインストールされています。

正解

深刻度をフィルタリングしてスキャンし、結果を保存します。

ssh cluster1-controlplane
sudo -i

trivy image --severity HIGH,CRITICAL nginx:1.21.0 > /opt/trivy-report.txt
cat /opt/trivy-report.txt

脆弱性のないきれいな結果だけを通過させるには終了コードを活用します。

trivy image --severity CRITICAL --exit-code 1 nginx:1.21.0

解説: --severity で等級をカンマでまとめて抽出し、--exit-code 1 は該当等級の脆弱性が 1 つでもあれば 1 で終了して CI パイプラインでデプロイを止めるのに使います。試験では「CRITICAL があるイメージを見つけてその Deployment を安全なイメージに変えよ」のようにスキャンと置き換えをまとめて出すことが多いので、スキャン結果を読んでどのワークロードがそのイメージを使うかを kubectl get で逆追跡する流れも併せて必要です。

タスク 13 (6 点): Supply Chain Security #

ネームスペース apps にデプロイしようとするイメージ registry.local/web@sha256:abc... が信頼されたキーで署名されているかを cosign で検証してください。公開鍵は /opt/cosign.pub にあります。検証に成功したイメージだけをデプロイするという方針を前提とします。

正解

公開鍵でイメージ署名を検証します。

cosign verify --key /opt/cosign.pub registry.local/web@sha256:abc...

検証が成功したら、その digest でデプロイします。

k -n apps set image deploy/web web=registry.local/web@sha256:abc...

解説: cosign verify はイメージ署名が与えられた公開鍵で作られたかを確認し、成功すると署名ペイロードを出力して 0 で終了します。タグ (:latest) ではなく digest (@sha256:...) で検証・デプロイして初めて、検証したまさにそのイメージがデプロイされます。タグは後で別のイメージに上書きされることがあり、署名検証の意味がなくなるのが核心的な落とし穴です。クラスター側で未署名のイメージを塞ぐには、Kyverno の verifyImages や sigstore policy-controller で admission の段階で強制します。


タスク 14 (8 点): Monitoring, Logging and Runtime Security #

クラスターに Kyverno がインストールされています。すべてのネームスペースで latest タグを使うかタグを省略したコンテナイメージを拒否する ClusterPolicy disallow-latest-tag を enforce モードで作ってください。

正解

イメージタグを検証する Kyverno ClusterPolicy を作ります。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-latest-tag
spec:
  validationFailureAction: Enforce
  rules:
    - name: require-image-tag
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "イメージに明示的なタグが必要で、latest は禁止されます。"
        pattern:
          spec:
            containers:
              - image: "!*:latest"
k apply -f disallow-latest.yaml
k run probe --image=nginx:latest

解説: validationFailureAction: Enforce はポリシー違反のリソースを admission の段階で拒否します (Audit は警告だけを記録)。パターン !*:latestlatest タグを否定マッチで塞ぎ、タグを省略するとランタイムが latest と解釈するため併せて引っかかります。上の検証コマンドの nginx:latest は拒否されて正常です。同じポリシーを OPA/Gatekeeper で書くと ConstraintTemplate と Constraint の 2 リソースに分かれる点が Kyverno との違いです。

タスク 15 (7 点): Monitoring, Logging and Runtime Security #

ワーカーノード node01 に Falco がインストールされています。コンテナの中でシェル (bash または sh) が実行されると Warning でログを残すカスタム Falco ルール Shell in container を追加し、Falco を再起動してルールを適用してください。

正解

ノードの Falco ローカルルールファイルにルールを追加します。

ssh node01
sudo -i

vim /etc/falco/falco_rules.local.yaml
- rule: Shell in container
  desc: コンテナの中でシェルの実行を検知します
  condition: >
    spawned_process and container
    and proc.name in (bash, sh)
  output: >
    Shell spawned in container
    (user=%user.name container=%container.id command=%proc.cmdline)
  priority: WARNING

Falco を再起動し、ルールがロードされたかを確認します。

systemctl restart falco
journalctl -u falco -e | grep "Shell in container"

解説: カスタムルールはメインの falco_rules.yaml ではなく falco_rules.local.yaml に置いてこそ、パッケージのアップグレード時に上書きされません。condition には spawned_process (プロセス生成) と container (コンテナコンテキスト) を AND でまとめ、priority は大文字の等級名を使います。ルール追加後に Falco を再起動してこそ適用され、kubectl exec <pod> -- bash でシェルを立てて Warning ログが出るかで検証します。

タスク 16 (8 点): Monitoring, Logging and Runtime Security #

control plane で apiserver の監査ロギングをオンにしてください。Secret リソースのすべての要求は RequestResponse レベルで、それ以外のすべての要求は Metadata レベルで記録する audit policy を作り、ログを /var/log/kubernetes/audit.log に残すように apiserver に適用してください。

正解

control plane ノードで audit policy ファイルを作ります。

ssh cluster1-controlplane
sudo -i

vim /etc/kubernetes/audit/policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  - level: RequestResponse
    resources:
      - group: ""
        resources:
          - secrets
  - level: Metadata

apiserver マニフェストに audit フラグを追加し、policy・ログのディレクトリを hostPath でマウントします。

    - --audit-policy-file=/etc/kubernetes/audit/policy.yaml
    - --audit-log-path=/var/log/kubernetes/audit.log
    - --audit-log-maxage=30
crictl ps | grep kube-apiserver
tail -f /var/log/kubernetes/audit.log

解説: audit policy のルールは 上から最初にマッチするルール が適用されるため、より詳しい Secret ルール (RequestResponse) を上に、包括ルール (Metadata) を下に置きます。RequestResponse は要求・応答の本体まで記録して最も詳細で、Metadata は誰が何をしたかだけを残します。policy ファイルとログディレクトリを apiserver コンテナに hostPath ボリュームとしてマウントしないと、コンテナの中でパスを見つけられず apiserver が立たないのがよくある落とし穴です。


採点基準 #

各タスクの配点を合算して採点します。合計は 100 点で、67 点以上が合格圏 です。

ドメインタスク・配点小計
Cluster Setup1(6) · 2(6)12
Cluster Hardening3(7) · 4(7)14
System Hardening5(8) · 6(8) · 7(7)23
Minimize Microservice Vulnerabilities8(7) · 9(7) · 10(6)20
Supply Chain Security11(7) · 12(7) · 13(6)20
Monitoring, Logging and Runtime Security14(8) · 15(7) · 16(8)23
合計(合計)112

配点の小計の合計は上表のとおり 112 点で、実際の採点は各タスクの配点を 100 点満点に換算して合算します。CKS は CKA・CKAD の 66% より一段高い 67% が合格ラインなので、ツールが手に馴染んだタスクから確実に点数を積み上げる運用がより重要です。

採点は実際の試験と同じく 成果物基準 です。コマンドをどう打ったかではなく、作られたリソースとより安全になったクラスターの状態が要件と一致するかを見ます。1 つのタスクの中でもラベル・フィールド・プロファイルの適用・フラグのような項目別に部分点が分かれるため、詰まる項目があっても埋められる部分は最後まで埋めるほうが点数に有利です。

ドメイン別の弱点復習 #

採点後、点数が低いドメインを下表の該当記事に戻って復習してください。

ドメイン関連タスク復習する記事
Cluster Setup1, 2#2 · #3
Cluster Hardening3, 4#4 · #5
System Hardening5, 6, 7#6 · #7 · #8
Minimize Microservice Vulnerabilities8, 9, 10#9 · #10 · #11
Supply Chain Security11, 12, 13#13 · #14 · #15
Monitoring, Logging and Runtime Security14, 15, 16#16 · #17 · #18

特定のタスクで時間が足りなかったなら、ドメイン知識より手の速さの問題かもしれません。その場合は #19 試験のコツ を読み直し、同じ 16 のタスクを時間を計ってもう一度解いてください。AppArmor のロード・seccomp の適用・etcd 暗号化・Falco ルールの追加は、一度手に馴染むとタスクあたりの所要時間が目に見えて減ります。

シリーズを終えて #

#1 の試験環境から出発し、NetworkPolicy・kube-bench・RBAC 最小権限・ServiceAccount トークン・AppArmor・seccomp・capabilities・Pod Security Admission・etcd 暗号化・gVisor・distroless・Trivy・cosign・Kyverno・Falco・audit log まで、CKS の全 6 ドメインを 20 編で通過しました。この模擬試験で 67 点を越えたなら、実際の試験会場でも十分に合格ラインを越えられる力がついています。おめでとうございます。

CKAD が開発者のワークロードの実技、CKA が運用者のクラスターの実技だったとすれば、CKS はそのクラスターを攻撃から守るセキュリティ専門家の実技です。3 つのシリーズをすべて終えた方なら、CNCF Kubernetes 認定資格 3 種 (CKAD・CKA・CKS) の全領域を手を動かして通り抜けたことになります。3 資格の達成を心からお祝いします。

X