LoginSignup
4
5

More than 1 year has passed since last update.

CKAD&CKA対策の個人的メモ

Last updated at Posted at 2023-03-14

はじめに

CKAD&CKA対策用の個人的なメモです。
試験中に公式ドキュメントやkubectlのhelpオプションによる確認ができるため、本メモの内容を全て暗記する必要はないです。しかしながら、時間がシビアなので、ある程度覚えておかないときついです。(毎回調べていたら多分時間が足りない)また、実務のことを考えると、やはりある程度は頭に入っていた方がよいと思います。
一部、too muchな内容もありますが、理解を深めるために記載しています。
よろしければご活用ください。メモなので表記揺れとかはご容赦ください。

▼Container

Docker

dockerコマンド

  • カレントディレクトリにDockerfileからDockerイメージをbuildする
    • docker image build -t <image>:<tag> -f <Dockerfile> .
  • イメージタグの変更
    • docker image tag <before> <after>
    • つけられるタグは一つだけ
  • イメージpush
    • docker image push <image>:<tag>
  • Dockerイメージをダウンロードする
    • docker image pull <image>
  • Dockerイメージをtarにする
    • docker save <image> -o <tar>
  • tarを解凍してDockerイメージにする
    • docker load -i <tar>
  • イメージを軽くする(一例)
    • Alpineイメージを使う。python:3.6-alipneなど。
  • イメージからコンテナ起動する。公開ポート8282のコンテナポート8080。
    • docker container run -p 8282:8080 <image>
  • イメージからコンテナを起動してコマンド実行する
    • docker container run <image> cat /etc
  • 起動中コンテナに擬似的なSSHする
    • docker container exec -it <container> /bin/sh
  • コンテナのリソース使用状況を確認する
    • docker container stats <container>
  • コンテナのログを確認する
    • docker container logs <container>

Dockerfile

  • Dockerfileから独自のDockerイメージを定義して、docker run で起動する。
  • ADD <url> <container path> でリモートファイルをコンテナ上にコピーする。
  • COPY <local path> <container path> でローカルファイルをコンテナ上にコピーする。
  • RUNはビルド時に実行するコマンド
  • ENTRYPOINTはコンテナ起動時に実行するコマンド
  • CMDはENTRYPOINTと併用する際にはENTRYPOINTのコマンドの引数になる。
  • kubernetesのYAMLのspec.containers[].commandでENTRYPOINTを上書きする。spec.containers[].argsでCMDを上書きする。commandでCMDを上書きではない。

Podman

  • Dockerと同様のコンテナエンジン。Dockerfileも使える。
  • イメージビルド
    • podman build -t <image>:<tag> -f <Dockerfile> .
  • イメージ一覧
    • podman image ls
  • イメージpush
    • podman push <image>:<tag>
  • バックグラウントで実行
    • podman run -d --name <conatiner name> <image>:<tag>
  • コンテナ一覧
    • podman ps
  • コンテナログ出力
    • podman logs <container>

cri-o

  • Kubernetesに最適化された軽量なOCI準拠なコンテナランタイム。crictlでCLI操作する。
  • Dockerほど柔軟なCLIは用意されていないためローカル開発ではDockerが選択されるケースは依然として多いだろうが、今後のサーバ環境ではDockerからcri-oに置き換わるかもしれない。
  • コンテナの一覧を表示する
    • crictl ps -a
  • podの一覧を表示する
    • crictl pods
  • コンテナのイメージ一覧を表示する
    • crictl images
  • 実行中コンテナでコマンド実行
    • crictl exec -it <container id> <command>
  • ログを確認する
    • crictl logs <container id>

▼Workloads

Pod

kubectl

  • podを起動して環境変数を設定する
    • kubectl run <pod name> --image <image> --env=key1=val1
  • podを起動してClusterIPで公開する
    • kubectl run <pod name> --image <image> --expose=true --port=<port> --target-port=<target port>
  • podを起動してコマンドを実行する。
    • kubectl run <pod name> --image <image> --command -- <command> <args>
    • containers[].commandとcontainers[].argsが設定される。
  • podを起動してシェル経由でコマンドを実行する。
    • kubectl run <pod name> --image <image> -- /bin/sh -c '<command and args>'
    • containers[].commandは無しで、containers[].args配下に全て設定される。
  • 起動中のpod(メインコンテナ)に擬似的なSSH接続する
    • kubectl exec -it <pod name> -- /bin/sh
  • pod内の特定コンテナに擬似的なSSH接続する
    • kubectl exec -it <pod name> -c <container name> -- /bin/sh
  • 前のリビジョンのpodのログを取る
    • kubectl logs <pod> --previous
  • Pod中の特定コンテナのログを取る
    • kubectl logs <pod> -c <container>
  • 各podの少し詳しい情報を取得する
    • kubectl get pods -o wide
  • 各podの詳細情報を取得する
    • kubectl describe pods
  • 適当なpodを起動してpodに疎通確認
    • kubectl run tmp --image <image> --rm -it -- curl -m 5 <pod ip>
    • Serviceと違ってPod名では名前解決されないので要注意

YAML

  • spec.nodeNameで起動するNodeを指定する。
  • spec.terminationGracePeriodSecondsに削除するまで何秒かを設定する。
    • Podの削除命令がされた場合に、「Serviceからの除外処理」と「preStop処理+SIGTERM処理」が同時に実行される。terminationGracePeriodSecondsにこれらにかかるであろう時間を設定する。
  • spec.containers[].ports.containerPortでコンテナのポートを設定する。
  • spec.containers[].lifecycle.postStartにコンテナ起動直後に実行する処理(execかhttpGet)を指定する。
  • spec.containers[].lifecycle.preStopにコンテナ停止直前に実行する処理(execかhttpGet)を指定する。
  • podのyamlにcommandと引数を記述する場合は、リストで記述する。あるいはargsを活用する。
    • command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
    • command: ["printenv"]
    • args: ["HOSTNAME", "KUBERNETES_PORT"]

マルチコンテナ

  • マルチコンテナのpodを作成する
    • まず1コンテナのpodのyamlを作って、そのyamlに他podの情報を追記していく。kubectlだけではマルチコンテナpodは作れない。
  • initコンテナの設定はspec.initContainersで設定する
  • initコンテナが複数ある場合は順列に実行される。initコンテナ1 -> initコンテナ2 ...
  • initコンテナの情報を取得する
    • kubectl describe pod <pod>

Pod(Container)のリソース制限

  • spec.containers[].resources.requestsでcpuとmemoryの下限を指定。
  • spec.containers[].resources.limitsでcpuとmemoryの上限を指定。
  • containerの合計がPodのリソース制限になる
  • OOMKilledはPodに割り当てたメモリが不足している可能性。ノードに余裕あればlimitsのmemoryを増やすと起動するようになるかも。

ContainerのHealthCheck

  • spec.containers[].startupProbeはPodの初回起動が完了しているかをチェックする。失敗したら他のProbeは実行しない。
  • spec.containers[].readinessProbeはPodがリクエストを受け付けることができるかをチェックする。失敗したらトラフィックを流さない。再起動はしない。
  • spec.containers[].livenessProbeはPodが正常に動作しているかをチェックする。失敗したらPodを再起動する。
  • httpGetでヘルスチェック用エンドポイントを叩く。
  • exec.commandでヘルスチェック用のコマンドを実行する。
  • tcpSocketで特定ポートとの疎通を確認する。
  • initialDelaySeconds、periodSeconds、timeoutSeconds、successThreshold、failureThresholdを設定する。

ReplicaSet

  • spec.selector.matchLablesで指定したラベルのpod数を管理する。ラベルしか注目しないため、そのReplicaSet外のpodのラベルも見てしまう点に注意する。
  • Podの増減履歴を確認する
    • kubectl describe replicaset <rs>
  • editしてもpodは自動で更新されないので、手動でpodをdeleteする。

Deployment

  • Deploymentのimageを変更する
    • kubectl set image deployment <deployment> <container>=<new image>
    • Podは自動で再起動する
  • replicasの数を変更する
    • kubectl scale deployment <deployment> --replicas=<number>
  • HPAを設定する
    • kubectl autoscale deployment <deployment> --min=5 --max=10 --cpu-percent=80
  • HPAを削除する
    • kubectl delete hpa <hpa>
  • DeploymentをRolling Updateする
    • kubectl rollout restart deployment <name>
  • Deploymentによる変更履歴を確認する
    • kubectl rollout history
  • Deploymentを1つ前に戻す
    • kubectl rollout undo deployment <deployment>
    • (さらにもう一回実行すると元に戻る)
  • Deploymentを指定のバージョンに戻す
    • kubectl rollout undo deployment <deployment> --to-revision=<revision number>
  • DeploymentのStrategyを確認する
    • kubectl describe deployment <deployment>
  • spec.selectorは.spec.template.metadata.labelsと一致している必要がある
  • spec.strategy.typeはRecreateとRollingUpdateの二種類がある。RollingUpdateではmaxUnavailable(アップデート中にdesiredから何個減っても許容するか)とmaxSurge(アップデート中にdesiredから何個増えても許容するか)を調整する。
  • 複数のDeploymentが存在する環境において、特定のDeploymentへのトラフィックを少なくす。
    • 特定のDeploymentのpodの数を少なくすると、そのDeploymentへのトラフィックを少なくできる。各Deploymentが抱えるpodへのリクエスト加重は均等。
  • カナリアリリースする
    • 既存のDeploymentをコピーしてcanary用Deploymentを用意して、それぞれのDeploymentのPod数が目標の加重比率になるように調整する。例えばPrimary:Canary=80:20にする場合でPrimaryのDeploymentのPod数が4であれば、CanaryのDeploymentのPod数は1にする。
  • replaceやrollout restartしてもDeploymentのAGEは変わらない。PodのAGEを確認するとよい。

Label&Annotation

  • podにラベルをつける
    • kubectl label pod <pod> <key>=<value>
  • podのラベルを削除する
    • kubectl label pod <pod> <key>-
  • 特定のラベルが付いたPodにラベルをつける
    • kubectl label pod <key>=<value> -l <key>=<value>
  • 全てのpodにラベルをつける
    • kubectl label pods --all <key>=<value>
  • Deploymentのラベルを上書きする
    • kubectl label deployment <deployment> --overwrite <key>=<value>
  • 特定のラベルをノードにつけてそのノード上にpodを起動する
    • kubectl label node <node> <key>=<value>
    • podのYAMLでnodeSelectorかnodeAffinityでラベルを指定する。
  • Podをラベル付きで一覧表示する
    • kubectl get pods --show-labels
  • 特定のラベルを持ったpodを一覧表示する(複数ラベルでAND検索)
    • kubectl get pods -l <key1>=<value1>,<key2>=<value2>
  • 特定のラベルを持ったpodを一覧表示する(複数ラベルでOR検索)
    • kubectl get pods -l <key1>=<value1> -l <key2>=<value2>
  • 特定のラベルが貼られたpodを一覧表示する
    • kubectl get pods -L <key>
  • podにラベルをつけて起動する
    • kubectl run <name> --image <image> -l <key>=<value>
  • 特定ラベルのpodを削除する
    • kubectl delete pods -l <key>=<value>
  • podにdescriptionアノテーションをつける
    • kubectl annotate pod <pod> <key>=<value>
  • podのdescriptionアノテーションを削除する
    • kubectl annotate pod <pod> <key>-
  • 特定のラベルが付いたPodにアノテーションをつける
    • kubectl annotate pod <key>=<value> -l <key>=<value>
  • 全てのpodにアノテーションを付与する
    • kubectl annotate pods --all <key>=<value>

Job

  • spec.completions
    • Jobを何回成功するまで実行するか
  • spec.parallelism
    • Jobを何並列にするか
  • spec.backoffLimit
    • Job失敗時に何回までリトライするか
  • spec.suspend
    • trueでJobを一時停止する
  • spec.template.spec.restartPolicy
    • Job失敗時にAlways(Podが停止すると常に再起動)かOnFailure(同じPodで再起動)かNever(新しくPodを作り直す)
  • spec.template.spec.activeDeadlineSeconds
    • 起動して何秒後に削除するか
  • CronjobからJobを手動実行
    • kubectl create job <job name> --from=cronjob/<cronjob>
    • 明示的に削除しないと削除されない

Cronjob

  • Cronに関するものを設定する。Cronでない設定はJobの方。
  • spec.startingDeadLineSeconds
    • Cronが何秒遅れて実行されても許すか
  • spec.concurrencyPolicy
    • Cronで前のJobが完了していない場合に、Allow(同時実行許可)かForbid(同時実行不可)かReplace(前のJobを止めて新しいJobを開始)のどれか。
  • spec.successfulJobsHistoryLimit
    • Cronで成功したjobをいくつ保持するか
  • spec.failedJobsHistoryLimit
    • Cronで失敗したjobをいくつ保持するか
  • spec.suspend
    • trueでCronを一時停止する
  • spec.jobTemplate.specにJobの設定をする。
    • spec.jobTemplate.spec.activeDeadlineSecondsなど。
  • 毎分特定コマンドを実行するCronjobを作成する
    • kubectl create cronjob <name> --image=<image> --schedule="*/1 * * * *" -- /bin/sh -c 'echo Hello World'
  • no matches for kind "CronJob" in version "batch/v1" エラーになったら batch/v1beta1 にする。

▼Network

Service

  • CKADでは主にClusterIP(クラスタ内通信)かNodePort(クラスタ外通信)を使用する。
  • NodePort -> ClusterIP -> Podの順でトラフィックが流れる。
  • nodePortは全てのKubernetesノードで受けるポート、portはClusterIPのポート、targetPortはコンテナのポートを設定する。
  • ClusterIPのServiceを作成する
    • kubectl create service clusterip <name> --tcp=<port>:<targetPort>
  • NodePortのServiceを作成する
    • kubectl create service nodeport <name> --tcp=<port>:<targetPort> --node-port=<nodePort>
  • spec.selectorで指定したlabelが付いたPodへ転送する。
    • PodにはServiceの転送用目印となるlabelを付与しておく必要あり。
    • 意外だがYAMLでDeployment名を指定して紐づけるといったようなことはしないし、Deploymentのlabelではダメ。
  • Deploymentを公開する(Serviceを作成する)
    • kubectl expose deployment <deployment> --name <service name> --type <type> --port <port> --target-port <target port>
    • nodePortオプションはkubectlでは設定不可
    • exposeはselectorの設定が自動なので楽。
  • endpoint(転送先PodのIPとポート)を確認する
    • kubectl get endpoints <service>
  • sessionAffinity: ClientIPにより、送信元IPアドレスを使ってセッションアフィニティ(同じPod宛てにトラフィックを転送し続けること)ができる。
  • NodePortのexternalTrafficPolicyはLocal(Nodeでトラフィックを受けたあとに別Nodeへのホップを無効にする。トラフィックの処理が偏る可能性がある。)とCluster(Nodeでトラフィックを受けたあとに別Nodeへのホップを有効にする。別のNodeへホップを許可することでトラフィック処理を分散できる。)がある。デフォルトはCluster。
  • ServiceのIPレンジの確認
    • cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep service-cluster-ip-range
  • 適当なPodを起動してClusterIP経由でPodへの疎通確認
    • k run tmp --image nginx:alpine -n <namespace> --rm -it -- curl -m 5 <service name>:<port>
  • NodePort経由でPodへの疎通確認
    • curl -m 5 <node ip>:<nodePort>

Ingress

  • L7ロードバランサとしてクラスタ外からServiceへのアクセスを管理するリソース。
  • パスベースルーティング機能
    • spec.rules[].http.paths[]にpathとbackend(Serviceのnameとport)を設定する。このportはServiceのport(ClusterIPのportかNodePortのport)と一致させる。
    • pathTypeはPrefixかExact。
    • spec.rules[].hostを設定しない場合は*扱い。
  • SSL終端機能
    • spec.tls[]にhosts(TLS証明書を適用するドメイン名)とsecretName(TLS証明証を格納しているSecretの名前)を設定する。
  • spec.defaultBackendにrulesにマッチングしなかったリクエスト用の404の設定をする。
  • Ingressが動作するにはIngressコントローラ(NginxやIstioなど)が導入されている必要がある。
  • パスベースルーティングが設定されたingressを作る。pathTypeはPrefix。
    • kubectl create ingress <name> --rule="<host>/<path>*=<service name>:<service port>"

CNI(Container Network Interface)

  • 複数Node上のPod間の疎通性を確保するための機能。
  • プラグイン形式。様々なベンダーから提供される。WeaveやFlannelなど。controlplaneのNICが追加される。
  • CNIバイナリはデフォルトで /opt/cni/bin に配置される。
  • CNIの設定ファイルディレクトリはデフォルトで /etc/cni/net.d

kube-proxy

  • Service(ClusterIPやNodePort)宛のトラフィックをPodへ転送する機能。
  • Node上でDaemonsetで起動している。
  • userspaceモード
    • カーネル空間でなくユーザ空間でトラフィックを転送する。遅い。
  • iptablesモード
    • カーネル空間でトラフィックを転送する。userspaceよりも速く、枯れているが、そもそもロードバランシング用途で開発されたものではない。
  • ipvsモード
    • 速く、ロードバランシングのアルゴリズムに複数の選択肢が用意されている。ただし、枯れていない。

CoreDNS

  • CoreDNSのService/Deployment/Pod/Configmapはkube-systemネームスペース上に作成される。
  • 設定はCorefileで行う。
    • DeploymentのArgsでCorefileのパスを指定する。
    • CorefileはConfigMapで管理することも可能。
    • クラスターのドメイン名を設定する。
      • 例えば kubernetes svc.cluster.local
  • Serviceの名前解決は <service name>.<namespace>.<domain> で行う。
    • ドメイン名は省略可能。
    • 同じnamespaceであればnamespaceも省略可能。つまり、Service名のみで解決可能。
  • Service名は名前解決されるがPod名は名前解決されない。
  • Pod生成時に /etc/resolv.conf に自動で設定される。
    • search default.svc.cluster.local svc.cluster.local cluster.local
    • nameserver 10.96.0.10
      • CoreDNSのServiceのIP

▼ストレージ

ConfigMap

  • ConfigMapを作る(literal)
    • kubectl create configmap --from-literal=<key1>=<value1> --from-literal=<key2>=<value2>
  • ConfigMapを作る(file)
    • kubectl create configmap --from-file=<key1>=<file1> --from-file=<key2>=<file2>
  • ConfigMapを作る(env-file)
    • kubectl create configmap --from-env-file=<file>
  • 環境変数としてPod(Container)に渡す
    • spec.containers[].env.valueFrom.configMapKeyRefでConfigMapとkeyを指定する。
    • spec.containers[].envFrom.configMapRef.nameでConfigMapを指定する。
  • VolumeとしてPod(Container)に渡す
    • spec.volumes.configMapで指定して、spec.containers[].volumeMountsでマウントする。
    • 動的更新される

Secret

  • Secret(Opaque)を作成する。(literal)

    • kubectl create secret generic --from-literal=<key1>=<value1> --from-literal=<key2>=<value2>
  • Secret(Opaque)を作成する。(file)

    • kubectl create secret generic --from-file=<key1>=<file1> --from-file=<key2>=<file2>
  • Secret(Opaque)を作成する。(env-file)

    • kubectl create secret generic --from-env-file <file>
  • 環境変数としてPod(Container)に渡す

    • spec.containers[].env.valueFrom.secretKeyRefでSecretとkeyを指定する。
    • spec.containers[].envFrom.secretRef.nameでSecretを指定する。
  • VolumeとしてPod(Container)に渡す

    • spec.volumes.secretで指定して、spec.containers[].volumeMountsでマウントする。
    • 動的更新される
  • secretに登録されている値をbase64デコードして取得する

    • kubectl get secret <secret> -o yaml して echo <encoded value> | base64 -d
    • kubectl get secret <secret> -o jsonpath="{.data.<target>}" | base64 -d
    • describeでも確認できる場合がある

Volume

  • あらかじめ用意された利用可能なボリューム(Node、nfs、iscsiなど)を使用するだけ。Kubernetesが管理するものではない。
  • Podのspec.volumesで指定して、spec.containers[].volumeMountsでマウントする。
  • emptyDirはホスト(Node)上の一時的な領域をPodに確保する。
    • 同一Pod内のコンテナ間では共有可能だが、Pod間での共有は不可。
    • Podが削除されると消える。
    • emptyDirに関する設定を何もしない場合はemptyDir :{}
    • emptyDir.medium: Memoryとすると高速なtmpfsのメモリ領域を利用できる。
  • hostPathはホスト(Node)上の任意の領域をマウントする。
    • pathでホストのパスを指定する
    • 同一Node内の他Podとの共有は可能。
    • Podが削除されても消えないがNodeが停止すると消える。
    • typeはDirectoryOrCreate/Directory/FileOrCreate/Fileなどがある。

PersistentVolume(PV)

  • 外部の永続ボリュームサービス(AWSのEBSなど)と連携したり、Nodeのリソースを使って、Kubernetes管理のボリュームを提供するリソース。
  • 手動かStorageClassのDynamic Provisioningにより作成される。
  • PodからPVを直接利用できず、必ずPVC経由で利用する。
  • spec.capacity.storageで容量を設定する。
  • spec.volumeModeはFilesystem(デフォルト)/Blockのいずれか。
  • spec.accessModesはReadWriteOnce(単一NodeでReadWrite可能)/ReadOnlyMany(複数NodeでReadOnly可能)/ReadWriteMany(複数NodeでReadWrite可能)のいずれか。
  • spec.persistentVolumeReclaimPolicyでPVCが削除される際にPVをDeleteするかRetainするかを指定する。ただし、Retainしても再度マウントすることはできず、Releasedというステータスになる。
  • spec.storageClassNameを設定する。
  • hostPathの場合は、spec.hostPath.pathを設定する。

PersistentVolumeClaim(PVC)

  • PVをPodにアサインするリソース。
  • PodやDeploymentのspec.volumes[].persistentVolumeClaim.claimNameを設定して、spec.containers[].volumeMountsでマウントする。
  • spec.storageClassNameを設定する。
  • spec.accessModesを設定する。
  • spec.volumeModeを設定する。
    • Blockの場合は、Podにはspec.containers[].volumeDevicesでマウントする。
  • spec.resources.requests.storageを設定する。Dynamic Provisioningで生成されたPVでない場合は、実際にはこれよりも大きな容量のPVが割り当てられる可能性がある。
  • PVとPVCの設定が一致し、PVCのspec.resources.requests.storageを満たしたPVがbindされる。
  • selector.matchLabelsやselector.matchExpressionsにより、PVに付与されたlabelを使ってbindするPVを指定することも可能。
  • Podから使われ続ける限りPVCは削除できない。
  • PVはnamespaceスコープでないが、PVCはnamespaceスコープ。

StorageClass

  • ストレージの種類。例えば、低スループット・標準:高スループットなどの分類。Dynamic Provisioningも行う。
  • 手動でPVを作る場合、「PVとPVCのstorageClassName」と「StorageClassのname」が一致することで紐づく。
  • provisionerでAWSのEBSやOpenStackのCinderなどを指定する。
  • reclaimPolicyを設定する。PVとPVCとStorageClassのreclaimPolicyは一致する必要がある。
  • volumeBindingModeでDynamic ProvisioningによるPVの作成タイミングを設定する
    • Immediate(デフォルト)はPVCを作成すると即座にPVを作成する。
    • WaitForFirstConsumerはPodにアタッチされる直前のタイミングでPVを作成する。節約できる。
  • provisioner: kubernetes.io/no-provisionerによりDynamic ProvisioningをOFFにする。
  • allowVolumeExpansion: trueにすることで使用中のPVのサイズを拡張可能にする。サイズをあげる場合はPVCのYAMLでrequestsの値を増やす。

▼セキュリティ

Admission Control

  • KubernetesのAPI ServerへのAPIリクエストに対して、認証と認可を行った後のフェーズで、別途そのリクエストを受け入れるか制御する機能。
  • kube-apiserverコマンドはkube-systemネームスペースのkube-apiserver-controlplaneポッドで実行する
    • kubectl exec -it kube-apiserver-controlplane -n kube-system -- kube-apiserver -h
  • admission controlのenableになっているプラグインを取得する
    • kube-apiserver -h | grep 'enable-admission-plugins'
  • kube-apiserverコマンドの --enable-admission-plugins--disable-admission-plugins でカンマ区切りに有効無効にする認証方法を指定する。
  • admission controlのYAML上でのプラグインの設定状況を調べる(デフォルト設定までは確認できない)
    • cat /etc/kubernetes/manifests/kube-apiserver.yaml |grep admission
  • /etc/kubernetes/manifests配下にkube-apiserverとkube-controller-managerとkube-schedulerのPodのYAMLがある。これらのYAMLはviなどで編集すると自動で再起動する。
  • プラグインはMutating(リクエストの内容を検証)かValidating(リクエストの内容を検証)のどちらかあるいは両方に分類される。
  • 代表的なプラグイン
    • AlwaysAdmitは全てのリクエストを許可する。
    • AlwaysPullImagesはPodのimagePullPolicyをAlwaysに強制的に変更する。ノードにpull済みのprivateイメージが他のPodに使用されないようにするため。
    • AlwaysDenyは全てのリクエストを禁止する。テスト用。
    • ServiceAccountはServiceAccountが明示的に指定されていないPodに対して、デフォルトのもの紐付ける。また、トークンをPodに自動的にマウントする。
    • SecurityContextDenyはSecurityContextの設定のうち、SELinuxOptions、RunAsUserなどの設定をしているものを禁止する。
    • ResourceQuotaはリクエストがnamespace内のリソース制限を超えていないかを検証する。
    • LimitRangerはNamespaceに設定されるLimitRangeに対して、リクエストが適切かどうかを検証する。もしResourceが未設定の場合はデフォルト値を設定するときにも使われる。
    • NamespaceAutoProvisionは、存在しないnamespaceを指定してリソースを作ってもエラーにならず、自動でnamespaceを作成する。現在はdeprecated。
    • NamespaceLifecycleは、存在しないnamespaceや削除中のnamespaceへの指定を禁止する。
    • MutatingAdmissionWebhookは独自リソースに関するリクエストを必要に応じて改変する。ValidatingAdmissionWebhookは独自リソースに関するリクエストを検証する。Mutatingの後にValidatingが実行される。

証明書

  • /etc/kubernetes/manifests/kube-apiserver.yaml のkube-apiserverコマンドでapi-server関連の証明書を指定している。
  • /etc/kubernetes/manifests/etcd.yaml のectdコマンドでetcd関連の証明書を指定している。
  • 証明書に記載されたCommon Name、Issuer、Alternative Nameなどを確認する
    • openssl x509 -in <cert file> -text

UserAccount

  • UserAccountは人間用アカウント。AWSのIAMなどにも連携できる。
  • UserAccountの追加
    • 新規UserAccountのClusterアクセス用サーバ証明書の申請
      • 秘密鍵の作成
        • openssl genrsa -out <key file> 2048
      • 秘密鍵からCSRファイル(公開鍵にCNなどを付与したもの)の作成
        • openssl req -new -key <key file> -out <csr file>
      • CertificateSigningRequest(CSR)の作成
        • CSRは証明書発行要求。CSRファイルをCAに渡し、署名済みのサーバ証明書を発行して貰う。
        • spec.groupsには"system:authenticated"を設定する。
        • spec.requestにはCSRファイルをbase64エンコードした値を設定する。
        • spec.signerNameには"kubernetes.io/kube-apiserver-client"を設定する。
        • spec.usagesにはTLSクライアントの場合は"digitalsignature", "key encipherment", "client auth"を設定する。
      • CSRリソースの確認
        • kubectl get csr
    • 承認の場合
      • CAに承認される
        • kubectl certificate approve <csr>
      • 承認されるとCSRリソースのstatus.certificateにCRT(サーバ証明書)が出力されるため、それをファイルに出力する。
        • kubectl get csr <csr> -o jsonpath='{.status.certificate}' | base64 -d > <crt file>
      • CRTファイルを指定してUserAccountの認証情報を追加
        • kubectl config set-credentials <user name> --client-certificate=<crt file>
      • cluster, context, role, rolebindingを設定してリソース操作が可能になる。
    • 否認の場合
      • CAに否認される
        • kubectl certificate deny <csr>
      • CSRリソースの削除
        • kubectl delete csr <csr>

kubeconfig

  • UserAccount(認証情報)とclusterとcontext(userとclusterの組み合わせ)を管理する。
  • UserAccount(認証情報)の定義を追加
    • kubectl config set-credentials <user name> --client-certificate=<crt file>
  • clusterの定義を追加
    • kubectl config set-cluster <cluster name> --server=<url>
  • contextの定義を追加
    • kubectl config set-context <context name> --cluster=<cluster name> --user=<user name> --namespace=<namespace>
  • 現在のcontextを表示
    • kubectl config current-context
  • contextの変更
    • kubectl config use-context <context name>
  • 使用するkubeconfigを変える
    • --kubeconfig オプションで別のconfigを指定する
    • 環境変数KUBECONFIGで別のconfigを指定する
    • ~/.kube/config の中身を編集する
  • userを指定してリソース操作をする
    • kubectl get pods --as <user>

ServiceAccount

  • ServiceAccountはPod用アカウント。
  • ServiceAccountの作成
    • kubectl create serviceaccount <name>
    • v1.24以降はトークンは自動生成されなくなった
  • ServiceAccount用のトークンを作成する
    • kubectl create token <serviceaccount>
  • PodとServiceAccountを紐づける
    • Podのspec.serviceAccountNameを設定する。
  • ServiceAccountをPodに紐づけることで、Podは /var/run/secrets/kubernetes.io/serviceaccount にマウントされたServiceAccountのトークンを使ってKubernetesリソースの操作ができるようになる。

RBAC(Role Based Access Control)

  • Role(Podの操作権限)を作成する
    • kubectl create role <name> --verb=list,create,delete --resource=pods
  • RoleBindingを作成してroleとuserを紐づける
    • kubectl create rolebinding <name> --role=<role> --user=<user>
  • ClusterRoleを作成する
    • kubectl create clusterrole <name> --verb=<verb> --resource=<resource>
  • ClusterRoleBindingを作成してClusterRoleとServiceAccountを紐づける
    • kubectl create clusterrolebinding <name> --clusterrole=<cluster role> --serviceaccount=<serviceaccount>
  • Role一覧を取得する
    • kubectl get roles
  • RoleBinding一覧を取得する
    • kubectl get rolebindings
  • RoleBindingが紐づくSubjects (User、Group、ServiceAccount)を確認する
    • kubectl describe rolebinding <RoleBinding>
  • 1つのRoleに複数のSubjectを設定可能
  • YAMLでrole/clusterroleを作成する場合はapiGroupsを自分で設定する必要がある。resourceごとに設定すべき値は、kubectl api-resources のAPIVERSIONで確認できる。例えば、storage.k8s.io/v1であればstorage.k8s.ioをapiGroupsに指定すればよい。
  • クラスタの認証モードを確認する
    • kubectl describe pod kube-apiserver-controlplane -n kube-system を実行して、authorization-modeにRBACが含まれていればRBACが使える状態。

Private Registry Image

  • private registryのイメージを指定する
    • Podのspec.containers[].imageで <repository>/<image> と指定する
  • docker-registryのSecretを作成する
    • kubectl create secret docker-registry <secret name> --docker-username=<user> --docker-password=<password> --docker-email=<email> --docker-server=<server>
  • Secretを使う
    • Podのspec.imagePullSecretsでnameを指定する

SecurityContext

Podとコンテナ共通

  • runAsUser/runAsGroup/runAsNonRoot/seLinuxOptionsはPodとコンテナの両方のSecurityContextで設定可能。重複する場合はコンテナのSecurityContextの設定が優先される。
  • runAsUser でrootユーザを指定する場合はIDを0にする。
  • podの実行ユーザを調べる
    • kubectl exec <pod> -- whoami
  • 既存のpodの設定は変更できないため、変更する場合は一度podをdeleteする。

Podに関するSecurityContext

  • spec.securityContextに設定する。
  • spec.securityContext.fsGroupでマウントするvolumeのグループを変更する。
    • Podにマウントしたvolumeはowner:group=root:rootのため、runAsUserで実行ユーザを変更すると権限エラーになってしまう。

コンテナに関するSecurityContext

  • spec.containers[].securityContextに設定する。
  • capabilitiesでコンテナの特定の権限(SYS_ADMINなど)のadd/dropをする。
  • privileged: trueにより、特権コンテナとして起動させる。コンテナにホストのrootと同等の権限を与える。
  • allowPrivilegeEscalation: trueにより、権限昇格(コンテナにホストのroot以上の権限を与えること)させる。
  • readOnlyRootFilesystem: trueにより、/etc配下などのKernel関連ファイルをreadOnlyにする。

Network Policy

  • クラスタ内のPod同士のトラフィックルール。
    • デフォルト(NetworkPolicyがPodに適用されていない)では、Podは分離されていない状態となるため、すべてのトラフィックを許可する。
    • NetworkPolicyがPodに適用されると、そのPodは分離されるようになる。ホワイトリスト形式で許可するものだけを設定する。
    • 複数のNetworkPolicyがPodに適用される場合は、OR条件で制限される。
  • podSelector
    • spec.podSelectorでどのPodにこのNetwork Policyを有効にするかを指定する。ネットワーク系だけど意外とServiceと紐づけることはない。
      • podSelector: {} で全てのPodを対象にする。
    • spec.ingress.from.podSelector.matchLabelsで特定のラベルがついたPodからの通信を許可する
    • spec.egress.to.podSelector.matchLabelsで特定のラベルがついたPodへの通信を許可する。
  • nameSpaceSelector
    • spec.ingress.from.nameSpaceSelector.matchLabelsで特定のラベルが付いたnamespace上のpodからの通信を許可する
    • spec.egress.to.nameSpaceSelector.matchLabelsで特定のラベルが付いたnamespace上のpodへの通信を許可する。
  • ipBlock
    • spec.ingress.from.ipBlockでクラスタ外ネットワークの特定ipからの通信を許可する
    • spec.egress.to.ipBlockでクラスタ外ネットワークの特定ipへの通信を許可する。
  • fromやtoにnamespaceSelectorとpodSelectorとipBlockを設定する場合、 - が合わせて1つならばAND条件。それぞれに - があればOR条件。つまり、 - ごとにルールがまとまる。
  • ports
    • spec.ingress.portsで許可する送信元ポートを設定する。
    • spec.eggres.portsで許可する宛先ポートを設定する。
    • portsの設定がない場合は全てのポートを許可。
    • - 付き( - ports: )であれば、fromやtoの設定にOR条件。
    • - なし( ports:)であれば、fromやtoの設定にAND条件。
  • 全てのトラフィックを許可する場合は、ingress/egressに {} を設定する。
  • 全てのトラフィックを遮断する場合は、policyTypesだけ設定して、ingress/egressの設定を書かない。
  • fromあるいはtoをyamlに複数設定する場合は to:from: を複数書く。それぞれがOR条件になる。
  • kubectlではingressは作成できるがegressは作成できない。どちらにせよYAMLで書いたほうがわかりやすい。
  • Network Policy一覧を取得
    • kubectl get networkpolicy
  • 短縮名はnetpol

▼リソース制限

  • LimitRangeで特定namespaceのContainer/Pod/PersistentVolumeClaimに関するリソース(CPU、memory、容量)のmin/max/defaultなどの設定をする。
  • LimitRangeの設定を確認する
    • kubectl describe limitrange <limitrange>
  • ResourceQuotaで特定namespace全体での「リソース数」と「リソース使用量」の制限をする。
    • spec.hard.services
    • spec.hard.requests.memory
  • ResourceQuotaの設定を確認する
    • kubectl describe quota <quota>

▼Helm

  • repositoryのchartを使ってreleaseをデプロイすることで、簡単にKubernetes上にリソース一式(DeploymentやServiceなど)を用意するためのパッケージマネージャ。
  • プログラミング的に言うと、chartはクラスでreleaseはインスタンス。
  • Helm関連の環境変数表示
    • helm env
  • リポジトリの登録
    • helm repo add <repository name> <repository url>
  • リポジトリの一覧表示
    • helm repo list
  • リポジトリの更新
    • helm repo update
  • Artifact Hubからchartを探す
    • helm search hub <chart>
  • リポジトリから検索(versionなどを出力する)
    • helm search repo <repository>
  • chartで設定可能なvaluesを表示する
    • helm show values <repo/chart>
  • chartをインストールしてreleaseを生成(バージョン指定、パラメータを個別指定)
    • helm install <release> <chart> --version <version> --set <key=value>
  • chartをインストールしてreleaseを生成(バージョン指定、パラメータをvaluesファイルで読み込み)
    • helm install <release> <chart> --version <version> --values <file>
  • chartをアンインストールしてreleaseを削除
    • helm uninstall <release>
  • releaseの一覧
    • helm list
  • statusがdeployedでないreleaseも含めた一覧
    • helm list -a
  • releaseの詳細情報を表示
    • helm get all <release>
  • releaseをアップグレードする
    • helm upgrade <release> <repo/chart> --version <version> --set <key=value>
  • releaseの履歴を確認する
    • helm history <releasee>
  • releaseをロールバックする
    • helm rollback <release> <revision>
  • 独自chart用の雛形を作成する
    • helm create <chart>
  • 独自chartのインストール
    • helm install <release> <chart path>
  • 独自chartをパッケージ(tgz)化
    • helm package <chart path>
  • リポジトリからchartをDLして解凍する(インストールはしない)
    • helm pull <url or repo/chart> --untar
  • テンプレートとvaluesファイルからマニフェストを生成する。(releaseは作成しない。)
    • helm template <manifest name> <template> --version <version> --values <file>

▼CRD

  • CustomResourceDefinitionのYAMLで独自のCustomResourceの仕様を定義する。CustomResourceのYAMLでCustomResourceを設定する。CRDのYAMLをapplyしてもCRを生成するわけではない。(クラスやインスタンスのような関係ではない)
  • metadata.nameは <plural name>.<group> の形式にする。
  • spec.groupとspec.versions.nameを結合したものがそのリソースのApiVersionとして扱われる。
  • spec.versions[].servedでそのバージョンの有効無効を設定する。
  • spec.versions[].storageでetcdに保存するバージョンを設定する。storage: trueにできるのは一つのバージョンだけ。代表的なバージョン?みたいな理解。
  • spec.versions[].schema.openAPIV3SchemaでCustomResourceのプロパティを設定する。
  • spec.scopeはNamespacedかCluster。
  • spec.namesでplural/singular/kind/shortNamesを設定する。
  • CRD一覧を取得する
    • kubectl get crd
  • CRの一覧を取得する
    • kubectl get <cr>

▼API Version

  • rbac.authorization.k8s.ioのv1alpha1をenableにする

/etc/kubernetes/manifests/kube-apiserver.yaml--runtime-config=rbac.authorization.k8s.io/v1alpha1 を設定する。

  • deprecatedなAPI VersionのYAMLを更新してリソースを作成する
    • kubectl convert -f <yaml> |kubectl create -f -

▼Scheduling

Affinity

  • AffinityはNodeに付与されているビルトインノードラベルや自分で付与した独自ラベルを使って、ラベルベースに条件を最も満たすnodeにPodをSchedulingをする方式。
  • Podのspec.affinityに設定する。
  • spec.nodeSelectorは単純に、ラベルのkey/valueが一致するNodeにPodをSchedulingする。
  • spec.affinity.nodeAffinityはrequiredDuringSchedulingIgnoredDuringExecutionを満たすかつ、preferredDuringSchedulingIgnoredDuringExecutionをなるべく満たすNodeにPodをSchedulingする。
  • podAffinityはrequiredDuringSchedulingIgnoredDuringExecutionを満たすかつ、preferredDuringSchedulingIgnoredDuringExecutionをなるべく満たすPodが存在するドメイン(ノードかAZ)にPodをSchedulingする。topologyKeyでドメイン(ノードかAZ)を指定する。
  • podAntiAffinityはrequiredDuringSchedulingIgnoredDuringExecutionを満たすかつ、preferredDuringSchedulingIgnoredDuringExecutionをなるべく満たすPodが存在しないドメイン(ノード、AZなど)にPodをSchedulingする。
  • matchExpressionsのoperatorはIn/NotIn/Exists/DoesNotExist/Gt/Ltのいずれか。

Taints&Toleration

  • ノードにtaintsをつけておき、それをtolerationsできるPodのみをSchedulingする方式。
  • taintsを付与する
    • kubectl taint node <node> <key>=<value>:<effect>
  • taintsを削除する
    • kubectl taint node <node> <key>=<value>:<effect>-
  • taintsを確認する
    • kubectl describe node <node>
  • tolerationsはPodのYAMLに設定する。tolerationsはkubectlでは作成不可。
  • effectはPreferNoSchedule(なるべくスケジュールしない)/NoSchedule(スケジュールしない)/NoExecute(スケジュールしないし、既にスケジュールされているPodは停止する。)のどれか。
    • NoScheduleとNoExecuteの場合は、「taintsのkey/value/effect」と「tolerationsのkey/value/effect」が一致する場合のみ、そのNodeにPodをSchedulingする。
    • PreferNoScheduleの場合は一致しなくても優先度は下がるが、Scheduling自体はする。

PriorityClass

  • SchedulingにおけるPodの優先度。kind: PriorityClassで作成する。
  • valueが高いほど優先度は高い。
  • 既にリソースの限界までSchedulingされている状態でpriorityの高いPodを作成しようとすると、priorityの低いPodは退避される。また、複数のPodがScheduling待ちの状態ではpritoriy順にソートされる。
  • PodのYAMLのpriorityClassNameで紐づける。

cordon/uncordon/drain

  • ノードのSchedulingステータスを確認する
    • kubectl get nodes
  • ノードにSchedulingされないようにする
    • kubectl cordon <node>
  • ノードにSchedulingされるように戻す
    • kubectl uncordon <node>
  • ノードにSchedulingされないようにするかつ、起動中のpodは別のノードに退避させる。
    • kubectl drain <node> --force --ignore-daemonsets --delete-local-data
    • 対象ノード上でReplicaSet経由でないPodが起動しているとエラーになるため --force をつける。 そのPodは削除される。
    • 対象ノード上でDaemonSet経由で作られたPodが起動しているとエラーになるため --ignore-daemonsets をつける。
  • PodDisruptionBudgetでdrain時に全てのpodが停止しないようにminAvailable(podの最小起動数)を設定する。
    • 退避されずに残ったpodは、他のpodの退避が完了したら退避される。
    • selector.matchLabelsでラベルベースにPodDisruptionBudgetの対象のpodを指定する。
  • cordonするとノードにtaintsが付く仕組み。ただし単なるtaintsではない。したがって、cordonしてもpodのtolerationsをうまく設定すればSchedulingされてしまうのではないかという心配はしなくてよい。

リソースに関連するスケジューリング

  • requests基準でCluster Autoscaleのスケジューリング判断を行う。
    • requestsが高すぎると実際の負荷がそうでもないのにCluster Autoscaleされてしまう可能性がある。
    • requestsがlimitsに対して低すぎると実際の負荷がかなり高いのにCluster Autoscaleしてくれない可能性がある。
    • requestsは高すぎず、limitsと大きく離れた値にしないこと。実際の設定値は負荷試験で見極めていく。
  • Guranteed > Burstable > BestEffortの順で優先度が高い。
    • Guranteed
      • requests/limitsが同じでCPUとmemoryの両方が設定されている
    • Burstable
      • Guaranteedではないが1つ以上のrequests/limitsが設定されている
    • BestEffort
      • requests/limitsがどちらも未設定
  • HPAはレプリカ数をCPU負荷などに応じて水平スケジューリングする機能。
    • 各podのCPU使用率の平均値がtargetAverageUtilization(閾値)より高ければスケールアウトし、低ければスケールインする。
    • スケジューリング判断のチェックは30秒に1回だが、スケーリング時のノイズを除去するために実際のスケールアウトは最大3分に1回、スケールインは最大5分に1回。
    • いくつにスケーリングするかは、各podのCPU使用率の合計値をtargetAverageUtilizationで割った結果になる。(小数点切り上げ)

スケジューラその他

Podのspec.schedulerNameでschedulerを指定可能。

▼Monitoring&Observability

  • 各Nodeのリソース使用状況を確認する
    • kubectl top nodes
  • 各Podのリソース使用状況を確認する
    • kubectl top pods

▼kubeadmによるオンプレKubernetes環境の構築

kubeadmのインストール

以下を全てのNode(control planeおよびdata plane)で実施する。

// k8s.confの設定
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
> br_netfilter
> EOF
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
> net.bridge.bridge-nf-call-ip6tables = 1
> net.bridge.bridge-nf-call-iptables = 1
> EOF
sudo sysctl --system

// aptのupdate
sudo apt-get update
// 必要パッケージのインストール
sudo apt-get install -y apt-transport-https ca-certificates curl

// Google Cloudの公開鍵をダウンロード
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg

// Kubernetesのaptリポジトリを追加
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

// aptのupdate
sudo apt-get update
// kubelet, kubeadm, kubectlのインストール
sudo apt-get install -y kubelet=<version> kubeadm=<version> kubectl=<version>
// パッケージが更新されないようにする
sudo apt-mark hold kubelet kubeadm kubectl

control planeのセットアップ

controle planeのNodeで以下を実行する。Flannelを使用する為、--pod-network-cidr=10.244.0.0/16を指定する。

kubeadm init --apiserver-cert-extra-sans=controlplane --apiserver-advertise-address <ip eth0> --pod-network-cidr=10.244.0.0/16

data planeのセットアップ

kubeadm join tokenの作成とjoinコマンドの出力

controle planceのNodeで以下を実行する。

kubeadm token create --print-join-command

joinコマンドの実行(data planeのノードに入って実行)

data planeのNodeで以下を実行する。

kubeadm join 10.33.92.10:6443 --token d3qmbz.wbotnx9alm0gbi4s --discovery-token-ca-cert-hash sha256:ffaddad5d14644d9ec0d421b729a17a17a80726d78b301521efb48fd9af719eb

flannel CNIのインストール

data planeのNodeで以下を実行する。

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.20.2/Documentation/kube-flannel.yml

構築作業に失敗した場合

kubeadm initやkubeadm joinを実行する前の状態に戻す。
controle planceのNodeで以下を実行する。

sudo kubeadm reset

▼Clusterのバージョンアップ

現在のClusterのバージョンを確認する

kubectl get nodes

アップグレート可否とアップグレード可能なバージョンを確認する

kubeadm upgrade plan

起動中のPodを別のNodeに退避させる

kubectl drain <node> --force --ignore-daemonsets --delete-local-data

アップグレードする

Nodeを1つずつアップグレードする。

control planeのアップグレード

control planceのNodeで以下を実行する。

# kubeadmによるアップグレード
apt-get update
apt-get install kubeadm=<version>
kubeadm upgrade apply <version>

# kubeletのアップグレード
apt-get install kubelet=<version>
systemctl daemon-reload
systemctl restart kubelet

data planeのアップグレード

data planeのNodeで以下を実行する。

# kubeadmによるアップグレード
apt-get update
apt-get install kubeadm=<version>
kubeadm upgrade node

# kubeletのアップグレード
apt-get install kubelet=<version>
systemctl daemon-reload
systemctl restart kubelet

▼etcd

HA topology

Stacked etcd topology

概要

コントロールプレーンノードの内部にetcdを配置する構成。
セットアップやレプリケーションの管理がシンプルというメリットがある。
コントロールプレーンノードが故障するとetcdも故障するというデメリットがある。

見分け方

kubectl get pods -n kube-system でetcdのミラーPodが存在すればStacked etcd topology。

バックアップ

作業はコントロールプレーンノード上で行う。
バックアップファイルは耐障害性の観点から別のストレージに移動した方がよい。

etcdを起動した際のオプションを確認する
kubectl describe pod <etcd> -n kube-system

スナップショットを取得する
ETCDCTL_API=3 etcdctl snapshot save <backup path> --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key

スナップショットを確認する
ETCDCTL_API=3 etcdctl snapshot status <backup path> --write-out=table --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key

リストア

作業はコントロールプレーンノード上で行う。
バックアップファイルがコントロールプレーンノード以外の場所にある場合は、事前にscpなどでコントロールプレーンノードに持ってくる。

ETCDCTL_API=3 etcdctl snapshot restore <backup path> --data-dir <data path>

/etc/kubernetes/manifests/etcd.yamlのvolumesのetcd-dataのpathを--data-dirで指定したデータベース保存先パスに置き換える。自動でrebootされる。

External etcd topology

概要

クラスターの外部にetcdを配置する構成。
コントロールプレーンノードそれぞれに対してetcdのホストが必要になるためインフラコストは増加する。

ETCDCTL_API=3 etcdctl member list --endpoints=https://127.0.0.1:2379 --cacert=/etc/etcd/pki/ca.pem --cert=/etc/etcd/pki/etcd.pem --key=/etc/etcd/pki/etcd-key.pem でetcdノードの数を確認する

見分け方

kube-apiserverコマンドの--etcd-serversオプションで外部のサーバが指定されている場合はExternal etcd topology。

バックアップ

作業はetcdノード上で行う。
バックアップファイルは耐障害性の観点から別のストレージに移動した方がよい。

etcdを起動した際のオプションを確認する
ps -ef |grep etcd

スナップショットを取得する
ETCDCTL_API=3 etcdctl snapshot save <backup path>  --endpoints=https://127.0.0.1:2379 --cacert=/etc/etcd/pki/ca.pem --cert=/etc/etcd/pki/etcd.pem --key=/etc/etcd/pki/etcd-key.pem 

スナップショットを確認する
ETCDCTL_API=3 etcdctl snapshot status <backup path> --write-out=table --endpoints=https://127.0.0.1:2379 --cacert=/etc/etcd/pki/ca.pem --cert=/etc/etcd/pki/etcd.pem --key=/etc/etcd/pki/etcd-key.pem 

リストア

作業はetcdノード上で行う。
バックアップファイルがetcdノード以外の場所にある場合は、事前にscpなどでetcdノードに持ってくる。

ETCDCTL_API=3 etcdctl snapshot restore <backup path> --data-dir <data path>

/etc/systemd/system/etcd.serviceのvolumesのetcd-dataのpathを--data-dirで指定したデータベース保存先パスに置き換える。

systemctl daemon-reload
systemctl restart etcd

▼Static Pod

  • Static Podはkube-apiserverを介さずにkubeletが直接管理するPodのこと。例えば、control planeで動いているkube-api-server/scheduler/controller-manager/corednsなど。
  • kubeletは各Static Podに対応するmirror podを自動的にkube-apiserver上に作成するため、kubectl(kube-apiserver)で確認できる。
  • /etc/kubernetes/manifests 配下にStatic PodのYAMLを配置する。このパスは、kubeletコマンドのconfigオプションで指定したconfigファイル内のstaticPodPathで変更可能。
    • このパスにPodのYAMLを配置すればStatic Podとして扱われる。つまり、自作のStatic Podを作成できる。当然ながらapplyは不要。
    • Static Podを削除する場合はこのYAMLファイルを削除する。単にpodを削除しても自動で復活してしまう。

▼その他

テストハック系

  • hostPathのPVのYAML例は公式ドキュメントで「PV hostpath」と検索するとでてくる。
  • YAMLの設定項目を確認する
    • kubectl explain <resource> --recursive | less
    • 公式ドキュメントのYAMLの例が見当たらない場合や、YAMLを参考にしたのになぜかエラーになる場合はこれで確認する。
  • 実際にはリソース作成せずにYAMLだけ作る
    • kubectl run <pod name> --image <image> --dry-run=client -o yaml > <yaml>
  • editしても変更不可だった場合は/tmp配下にYAMLが自動生成される。そのファイルを--forceでapplyすれば変更できる。
    • editよりも k get <resource> -o yaml > <yaml> してそのyamlを編集してreplaceする方が速い。
  • podのyamlを編集してapply(replace)したところ、変更不可だった場合は--forceする。
  • ネットワーク繋がらない系問題の解き方
    • NetworkPolicyの問題
      • NetworkPolicyのspec.podSelectorで適切なPodのラベルが設定されているか
      • ルールが適切か
    • Ingressの問題
      • backendのnameとportは適切か
    • Serviceの問題
      • Serviceのspec.selectorで適切なPodのラベルを設定できているか(endpointsがserviceに設定されていない場合は特に怪しい)
    • Podの問題
      • Podの状態やログを確認する。imagePullBackOffやHealthCheckで落ちていないかなど。

kubectl系

  • 全てのnamespace
    • kubectl get all -A
  • イベントを取得する
    • kubectl get event -n <namespace>
  • リソース数を取得する
    • kubectl get <resource> --no-headers | wc -l
  • 大雑把に全リソースを取得する
    • kubectl get all
  • 全リソースを取得する
    • kubectl api-resources
    • 略称もこれで確認できる
  • PersistentVolume関連はkubectlでは作成不可。

kubectl結果からの抽出

  • Node名の一覧を抽出
    • kubectl get nodes -o jsonpath="{.items[*].metadata.name}"
  • PersistentVolumeを容量順にソート
    • kubectl get pv --sort-by=.spec.capacity.storage
  • PersistentVolumeを容量順にソートして、カラムを絞った上でカラム名をつける。
    • kubectl get pv --sort-by=.spec.capacity.storage -o=custom-columns=NAME:.metadata.name,CAPACITY:.spec.capacity.storage
  • 特定kubeconfigの特定ユーザのコンテキスト名を取得する
    • kubectl config view --kubeconfig my-kube-config -o jsonpath="{.contexts[?(@.context.user=='aws-user')].name}"

Linuxコマンド系

  • OSを確認する
    • cat /etc/os-release
  • grepで後10行も見たい
    • | grep -A10
  • grepで前10行も見たい
    • | grep -B10

ネットワーク系コマンド

  • NIC確認
    • ip a
  • ルーティング設定を確認
    • ip route
    • defaultがデフォルトゲートウェイ。
  • 各プロセスのIPやポートなどを確認
    • netstat -nplt
    • nで名前解決しないでIPで表示。
    • pでプログラムやプロセス名を表示。
    • lでLISTENのものを抽出。
    • tでTCPのものを抽出。

頻出バグ原因

Image名が不適切、ポート番号が不適切、ラベルが不適切、ファイル名が不適切、コマンドが不適切、Podの権限不足(RoleやRoleBindingの不備、ServiceAccountNameが設定されていない)、通信が通らない

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5