出会って2ヶ月でCKA合格

2021/05/04に公開

2021 年 5 月に CKA(Certified Kubernetes Administrator)に合格いたしましたので、合格体験記を記載します。

ちなみに基準点が 66%でスコアは 66%というギリギリのスコアでした(

https://twitter.com/azukiazusa9/status/1389014667276668928

受験目的

3 月に転職したら Kubernetes だったので、知識を得るために勉強の一環として受験しました。
Kubernetes の関しては全くの未経験の状態から勉強を始めて 2 ヶ月の勉強期間で合格しました。

試験の概要

試験時間は 2 時間で 66%スコアを取得すれば合格です。
多肢選択式の試験ではなく、ハンズオン形式の試験となっており、実際にコマンドラインから Kubernetes を実行して提示されるタスクを解く必要があります。

私が受験した際には、Kubernetesv1.20 が使用されました。

受験中には、下記ドメインのサイトを参照できます。つまりは、kubetcl のコマンドやマニフェストの書き方は必ずしも暗記する必要がないということです。

また1 つだけ外部ディスプレイを使用できます。

試験はすべてオンラインで行われ試験会場・試験日時はある程度自由に決めることができます。
試験会場は、他人が入ってこず、かつ他人の声が聞こえない静かな個室である必要があります。私は自宅で受験しました。

CKA の出題範囲は以下のとおりです。

対象領域とコンピテンシー 割合
クラスタのアーキテクチャ、インストール、構成 25%
サービスとネットワーク 20%
トラブルシューティング 30%
ワークロードとスケジューリング 15%
ストレージ 10%

https://training.linuxfoundation.org/ja/cka-program-changes-2020/

見ていただくとおり、トラブルシューティングの割合が高く設定されていますので、重点的に対策を行うのが効果的です。

Kubernetes の管理者としての試験ですので、kubectl コマンド以外にも以下の知識が必要です。

etcdCoreDNSのドキュメントは試験中には参照できないので注意してください。

試験の流れ

  • 試験開始15分前からPortalサイトTake Examが有効になるので、クリックして試験サイトへアクセスします。
  • 試験官とのやり取りはすべて英語のチャットで行われます。CKA-JP (日本語監督版)を申し込んだ場合、日本語のチャットでやり取りできるようです。(ちなみに試験問題自体は自然な日本語です)
    • 基本チャットでは試験官からの指示を受けるだけなのでこちらから発言することはほぼありません。(「パスポートを持っていないか?」と問われたの対して「I don't have passport」と応答したくらいです)
  • Web カメラをつけることと、画面を共有することが支持されます。外部ディスプレイを使用している場合には、2 画面共有する必要があります。
    • 誤って同じ画面を共有してしまいましたが、おそらく?共有を止める方法がありませんでした。(ブラウザをリロードすることを指示されました)
  • できるだけゆっくり部屋の様子を写すことを指示されます。特に、机の周りや下は丁寧に。ここでは特に何も言われずに終了しました
  • option + command + esc で「強制終了」ウィンドウを出して Google ChromeFinder 以外のアプリケーションを終了するのと、試験以外のタブを閉じるように指示されます。私はあらかじめ kubernetes.io を開いていたのですがそのタブも試験官の指示があるまで開いてはいけないようです。
  • 本人確認のための証明書の提示が求められます。パスポートを提示するのが良いようですが、私は所持しておりませんでしたので「デビットカード」と「運転免許証」を提示しました。
  • 試験官から試験の説明・注意などがあり、それが終了したら試験を開始できます。ここまででだいたい 20 分程でした。
  • 試験開始時にチュートリアルが表示されるので、それを終えてから 2 時間が試験時間です。プログレスバーで残り時間がわかりますが詳細の時間は表示されません。
    • 私が受けたときには残り時間の表示がバグってわからなくなりましたw
  • 試験時間が終了すると同時にコマンドを受け付けなくなります。
  • 試験の 36 時間以内には結果がメールで通知されます。

勉強方法

Kubernetes や CKA を学習するにあたって参考にした参考書などを記載いたします。

Kubernetes完全ガイド 第2版

完全ガイドの書名通り、Kubernetes の知識について羅列的に学ぶことができます。はじめは全体を俯瞰するように読み、学習をすすめるうえで関連する章を詳細に閲覧する読み方が良いでしょう。

Udemy – Certified Kubernetes Administrator (CKA) with Practice Tests

言わずとしれた Udemy の CKA 対策コースです。CKA の出題範囲をほぼ羅列しています。

講師による映像講義だけでなく、試験に近い環境でのハンズオン形式で学ぶことができるので、とても効果的です。ゼロから Kubernetes を学習するうえでハードルの高い環境の構築が不要ですので嬉しいですね。

またUdemy といえば定番ですが定期的に 90%オフセールを開催しているので確実にセール中に購入するようにしましょう(

kubernetes.io

いわゆる Kubenertes の公式ドキュメントですが、ドキュメントを俯瞰しておくことがとても重要です。
なぜなら、kubernetes.ioは試験中に参照できるためです。

ドキュメントは量が膨大なのですべてを読むことは難しいですが、だいたいどのページにどのようなことが書いてあるのかを把握しておくとよいでしょう。

特に、Tasksページは CKA を受験する腕有益な情報が記載されています。

CKA Self-Study Course

CKA も出題範囲を具体的に整理できます。
内容は簡素にまとめられているので、試験前に知識の確認としてぴったりでした。

試験のTips

kubernetes.ioのブックマークを作成しておく

試験中にドキュメントを参照できるので、勉強中に参照したページをブックマークをしておくとすぐにアクセスできるので時間の短縮となります。

私は以下からブックマークをインポートさせていただきました。

https://gist.github.com/jonatasbaldin/4e76846ce8fb17e5d2fa64bdea594930

簡単な問題から回答する

CKA の Tips というか資格試験全般に言えることですが。詰まってしまうような難しい問題に出会ったら一度スキップして後から戻って回答するようにしましょう。

試験問題にはフラグを建てることができます。

指定された要件で Pod を作成する・レプリカをスケールするといったような簡単な問題も用意されています。

viの操作になれる

試験中に yaml ファイルを編集する場面が多々ありますが使えるエディタは vinano だけですので普段から使い慣れていないようなほう vi の練習をしておくとよいでしょう。

私めも恥ずかしながらモード変更とファイルの保存・終了コマンドしか使えていかなったレベルです(

最低限、以下コマンドが使えると役に立ちます。

  • dd
    • カーソルの行を削除
  • u
    • アンドゥ
  • /
    • 前方検索
    • e.g. /image
  • n
    • 次の検索結果
  • N
    • 前の検索結果
  • :<数値>
    • <数値>で指定した行へ移動

エイリアスを設定する

試験中は kubectl コマンドをよく使用するのでエイリアスを設定しておくと時間短縮になります。
試験が開始したら次のコマンドを打ちます。

$ alias k=kubectl

上記コマンドは暗記せずともドキュメントのチートシートに記載されているのでそこからコピペすれば OK です。

コマンドからリソースのひな形を作成する

-o yaml --dry-run=client オプションを付与することによって、大抵のリソースに対してコマンドからマニフェストのひな形を作成できるので大変重宝します。

Pod

$ kubectl run nginx --image nginx -o yaml --dry-run=client > nginx.yaml

Deployment

$ kubectl create deployment nginx --image nginx -o=yaml --dry-run=client > deployment.yaml

Service

$ kubectl expose deployment nginx --port=80 --dry-run=client -o=yaml > service.yaml

explainと --helpコマンド

explain

マニフェストの記述方法がわからなくなったときは、explain コマンドを使用します。

kubectl explain <type>.<fieldName>[.<fieldName>]

例えば、PersistentVolume の hostPath の書き方がわからなくなったときには

$ kubectl explain pv.spec --recursive | grep -i hostpath
   hostPath     <Object>

--recursive は、詳細を表示しないオプションです。
結果は <Object> と表示されているので、更に掘り下げて確認します。

$ kubectl explain pv.spec.hostPath
KIND:     PersistentVolume
VERSION:  v1

RESOURCE: hostPath <Object>

DESCRIPTION:
     HostPath represents a directory on the host. Provisioned by a developer or
     tester. This is useful for single-node development and testing only!
     On-host storage is not supported in any way and WILL NOT WORK in a
     multi-node cluster. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#hostpath

     Represents a host path mapped into a pod. Host path volumes do not support
     ownership management or SELinux relabeling.

FIELDS:
   path <string> -required-
     Path of the directory on the host. If the path is a symlink, it will follow
     the link to the real path. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#hostpath

   type <string>
     Type for HostPath Volume Defaults to "" More info:
     https://kubernetes.io/docs/concepts/storage/volumes#hostpath

hostPath には path フィールド指定する必要があることがわかります。
マニフェストには次のように記載すればよいことがわかりました。

hostPath: 
  path: "/mnt/data"

--help

宣言的な方法でリソースを作成するときのオプションの指定方法がわからなくなったときには、--help コマンドを利用します。

# pod
$ kubectl run --help
# service
$ kubectl expose --help
$ kubectl create <type> --help

サービスを作成するときに、サービス名を指定する方法を確認します。

$ kubectl expose --help
Expose a resource as a new Kubernetes service.

 Looks up a deployment, service, replica set, replication controller or pod by name and uses the selector for that
resource as the selector for a new service on the specified port. A deployment or replica set will be exposed as a
service only if its selector is convertible to a selector that service supports, i.e. when the selector contains only
the matchLabels component. Note that if no port is specified via --port and the exposed resource has multiple ports, all
will be re-used by the new service. Also if no labels are specified, the new service will re-use the labels from the
resource it exposes.

 Possible resources include (case insensitive):

 pod (po), service (svc), replicationcontroller (rc), deployment (deploy), replicaset (rs)

Examples:
  # Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000.
  kubectl expose rc nginx --port=80 --target-port=8000
  
  # Create a service for a replication controller identified by type and name specified in "nginx-controller.yaml",
which serves on port 80 and connects to the containers on port 8000.
  kubectl expose -f nginx-controller.yaml --port=80 --target-port=8000
  
  # Create a service for a pod valid-pod, which serves on port 444 with the name "frontend"
  kubectl expose pod valid-pod --port=444 --name=frontend
  
  # Create a second service based on the above service, exposing the container port 8443 as port 443 with the name
"nginx-https"
  kubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https
  
  # Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'.
  kubectl expose rc streamer --port=4100 --protocol=UDP --name=video-stream
  
  # Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on
port 8000.
  kubectl expose rs nginx --port=80 --target-port=8000
  
  # Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000.
  kubectl expose deployment nginx --port=80 --target-port=8000

Options:
      --allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
      --cluster-ip='': ClusterIP to be assigned to the service. Leave empty to auto-allocate, or set to 'None' to create
a headless service.
      --dry-run='none': Must be "none", "server", or "client". If client strategy, only print the object that would be
sent, without sending it. If server strategy, submit server-side request without persisting the resource.
      --external-ip='': Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP
is routed to a node, the service can be accessed by this IP in addition to its generated service IP.
      --field-manager='kubectl-expose': Name of the manager used to track field ownership.
  -f, --filename=[]: Filename, directory, or URL to files identifying the resource to expose a service
      --generator='service/v2': The name of the API generator to use. There are 2 generators: 'service/v1' and
'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed
in v2. Default is 'service/v2'.
  -k, --kustomize='': Process the kustomization directory. This flag can't be used together with -f or -R.
  -l, --labels='': Labels to apply to the service created by this call.
      --load-balancer-ip='': IP to assign to the LoadBalancer. If empty, an ephemeral IP will be created and used
(cloud-provider specific).
      --name='': The name for the newly created object.
  -o, --output='': Output format. One of:
json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-as-json|jsonpath-file.
      --overrides='': An inline JSON override for the generated object. If this is non-empty, it is used to override the
generated object. Requires that the object supply a valid apiVersion field.
      --port='': The port that the service should serve on. Copied from the resource being exposed, if unspecified
      --protocol='': The network protocol for the service to be created. Default is 'TCP'.
      --record=false: Record current kubectl command in the resource annotation. If set to false, do not record the
command. If set to true, record the command. If not set, default to updating the existing annotation value only if one
already exists.
  -R, --recursive=false: Process the directory used in -f, --filename recursively. Useful when you want to manage
related manifests organized within the same directory.
      --save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
      --selector='': A label selector to use for this service. Only equality-based selector requirements are supported.
If empty (the default) infer the selector from the replication controller or replica set.)
      --session-affinity='': If non-empty, set the session affinity for the service to this; legal values: 'None',
'ClientIP'
      --target-port='': Name or number for the port on the container that the service should direct traffic to.
Optional.
      --template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
      --type='': Type for this service: ClusterIP, NodePort, LoadBalancer, or ExternalName. Default is 'ClusterIP'.

Usage:
  kubectl expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UDP|SCTP] [--target-port=number-or-name]
[--name=name] [--external-ip=external-ip-of-service] [--type=type] [options]

Use "kubectl options" for a list of global command-line options (applies to all commands).

どうやら --name オプションを使うようです。確認してみましょう。

$ kubectl expose po nginx --name=nginx-service --port 80 --dry-run=client -o yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx-service
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: nginx
status:
  loadBalancer: {}

部屋の掃除をする

今回の試験での最難関ポイントでした。
自宅で受験する場合には、部屋を一通り試験管に Web カメラで写す必要があります。

終わりに

Kubernetes のコアの部分について学習できたので、大変有意義な試験でした。
多肢選択式ではなくハンズオン形式の試験ですので、しっかりとした知識の証明となりうると感じました。

GitHubで編集を提案

Discussion