書籍情報
書籍名:つくって、壊して、直して学ぶ Kubernetes入門
著者名:高橋 あおい
本書を選んだ背景
実務経験はないものの、DockerやKubernetesに興味があったことと、以前参加した勉強会で本書が紹介されており興味を持ったことがきっかけです。
本書について
Kubernetesの実践的入門書として位置付けられています。ローカルクラスタを構築し手を動かしながら学べます。
ハンズオンは主に、リソースをつくる→意図的に壊す→設定ファイルなどを調査し直す、という流れで構成されており、トラブルシュートを体験できるようになっています。
また、イラストや漫画が豊富で、とても読みやすいのが特徴です。
Kuberneteについて、わからない→なんとなくわかる→もうちょっと知りたい に達することが本書の目標とのこと。
本書の内容
以下、個人的なメモを残します。
Part1 つくってみようKubernetes
-
Kubernetesは大きく分けてControl PlaneとWorker Nodeの2つの役割に分かれる。Control Planeとによって決まった内容に応じてWorker Nodeで実際にコンテナを起動する
-
アプリケーションサーバであるkube-apiserverにkubectlでアクセスして、インフラ環境を構築する
-
Worker NodeがControl Planeにアクセスすることで、Control Planeが壊れても即座にWorker Node上に起動するコンテナが破壊されるわけではない
-
本書でのローカルクラスタ構築にはkindを使う。マルチノードクラスタを作れるのが特徴。Dockerの環境の中にDockerを立ち上げてクラスタを作っているため、Dockerが必須
クラスタ構築は次のコマンドで行う(kindest/node:v1.29.0を利用する場合)kind create cluster --image=kindest/node:v1.29.0
バージョン確認は次のコマンド
kubectl cluster-info --context kind-kind
-
kubectlのconfig情報はhomeディレクトリの.kube/configに記載されている
-
Namespaceは、kubernetesにおいて単一クラスタ内のリソース群を分離するメカニズムを提供する。本書ではdefaultのNamespaceを使用する
-
マニフェストの適用
kubectl apply --filename <ファイル名> --namespace default
Part2 アプリケーションを壊して学ぶKubernetes
トラブルシューティングガイドとkubectlコマンドの使い方
-
Podの確認
kubectl get pod <Pod名>
- --output wideオプションでIPアドレスやNode情報が取得できる
- --output yamlオプションでYAMLファイオル形式でリソース情報を取得する
- --output jsonpath='{.spec.containers[].images}'オプションでJSON形式で出力
- --v=<ログレベル>オプションで出力結果のログレベルを変更する
-
リソースの詳細を取得する。エラーの原因調査にも役立つ
kubectl describe pod <Pod名>
-
コンテナのログを取得
kubectl logs <Pod名>
- --containerオプションでコンテナを指定する
- --selector =でラベルを指定して参照する
-
デバッグ用コンテナの起動
kubuctl debug --stdin --tty <デバッグ対象Pod名> --image=<デバッグ用コンテナのimage> --target=<デバッグ対象のコンテナ名>
-
コンテナを即座に実行する
kubectl run <Pod名> --image=<image名>
-
クラスタ外からのアクセス
kubectl port-forward <Pod名> <転送先ポート番号>:<転送元ポート番号>
-
マニフェストの編集
kubectl edit <リソース名>
-
リソースの削除
kubectl delete <リソース名>
Kubernetesリソースをつくって壊そう
- ReplicaSetはPodの複製。作成について、マニフェストファイルのkindをReplicasetに指定、specのreplicasに作成するPod数を指定する
次のコマンドで確認kubectl get replicaset
- DeploymentはReplicaSetの上位概念で、ローリングアップデートが可能となる。作成について、マニフェストファイルのkindをDeploymentに指定する
次のコマンドで確認kubectl get deployment
- Deploymentで作ったリソース(Pod)にアクセスするためにServiceというリソースを利用する。マニフェストファイルのkindをServiceに指定する
また、マニフェストファイル内でTypeを指定できる(デフォルトでClusterIP、他にNodePortなど)
次のコマンドで確認kubectl get service <Service名>
- ConfigMapはPodの外部から値を設定したいときに利用するリソース。マニフェストファイルのkindをConfigMapに指定する
次のコマンドで確認kubectl get configmap <ConfigMap名>
- Jobは1回限りのタスクを実行するのに利用するリソース。マニフェストファイルのkindをJobに指定する
また、kindをCronJobにすることで定期的にJobを実行できる
次のコマンドで確認kubectl get job kubectl get cronjob
安全なステートレス・アプリケーションをつくるには
-
Readines probeはコンテナがReadyになる時間やエンドポイントを制御
ここでは/healthzというヘルスチェック用エンドポイントの8080番ポートに対して、5秒に一度ヘルスチェック用リクエストを送る設定なっている。initialDelaySecondsは最初のProbeが実施されるまで5秒まつ.YAML〜略〜 readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 5 periodSeconds: 5
-
Liveness probeはReadines probeと似ているが、Probeが失敗した時の挙動が変わる。Readines probehはServiceから接続を外すのに対し、Liveness probeはPodを再起動する
.YAML〜略〜 livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 5 periodSeconds: 5
-
Startup probeは初回起動時のみに利用するProbeで、起動が遅いアプリケーションでの利用が想定される
このマニフェストでは最大30秒×10回=300秒コンテナの起動を待つ.YAML〜略〜 startupProbe: httpGet: path: /healthz port: liveness-port failureThreshold: 30 periodSeconds: 10
-
コンテナのリソース使用量の要求、制限は以下
.YAML〜略〜 resources: requests: memory: "64Mi" cpu: "10m" limits: memory: "64Mi" cpu: "10m"
-
Nodeを指定する。次の例では、SSD使っているNodeのみをスケジュールする
.YAML〜略〜 nodeSelector: disktype: ssd
-
Node Affinityは「可能ならスケジューリングする」
.YAML〜略〜 spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: #対応するNodeが見つからない場合、適当なNodeにスケジュールする - weight: 1 preference: matchExpressions: - key: disktype operator: In values: - ssd 〜略〜
-
Node Affinity/Node Anti-affinityは「Pod間のAffinity」で、すでにNodeにスケジュールされているPodのラベルに基づいてスケジューリングする
.YAML〜略〜 spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - nginx topologyKey: kubernetes.io/hostname 〜略〜
-
Pod Topology Spread ConstraintsはPodを分散するための設定
.YAML〜略〜 spec: topologySpreadConstraints: - maxSkew: 1 topologyKey: zone whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app: nginx 〜略〜
-
Taint/Tolerationは「あるNodeが特定のPod(とくに指定のないPodはスケジュールを拒否したい)」といった指定
NodeにTaintは次の方法で付けられるkubectl taint nodes <対象Node名> <label名>=<labelの値>:<Taintの効果>
このTaintに対応するtolerationは次のように指定する
.YAML〜略〜 tolerations: key: "disktype" value: "ssd" operator: "Equal" effect: "NoSchedule" 〜略〜
-
Horizontal Pod Autoscaler(HPA)を利用し水平スケール。事前にmetrics-serverをインストールしておく
次のようにマニフェストに書くことで水平スケールを実現する.YAML〜略〜 apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: hello-server-hpa spec: minReplicas: 1 maxReplicas: 10 metrics: - resource: name: cpu target: averageUtilization: 50 type: Utilization type: Resource scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: hpa-handson 〜略〜
-
Vertical Pod Autoscaler(VPA)を利用し垂直スケール。ただしVPAはHPAと同じリソースに対して同時に利用できないため、HPAのみ利用しているケースが多い
トラブルシューティングにおける原因の切り分け
原因を切り分けるにあたって、なるべくアプリケーションに近いところから切り分けると良い。まずPodについてdescribeとlogsで調査し、次にデバッグ用コンテナを立ち上げる。例えば次のように行う。
- Pod内からアプリケーションの接続確認を行う
- クラスタ内かつ別Podから接続確認を行う
- クラスタ内かつ別PodからService経由で接続確認を行う
よくあるエラーの例
- 設定ファイル内のリポジトリ名のタグをタイプミスする。kubectl describe で調べてみる
Part3 壊れても動くKubernetes
- Control Planeについて
- kube-apiserverはRESTで通信可能なAPIサーバ。etcdは分散型キーバリューストアで、データベースの一種
- kube-schedulerはPodをNodeにスケジュールする役割を担っている
- kube-controller-managerはKubernetesを最低限動かすための複数のコントローラーを動かしている - Worker Nodeについて
- kubeletは各コンテナ内で動いている。kubeletが起動しているNodeにPodがスケジュールされると、コンテナランタイムに指示してコンテナを起動する
- kube-proxyはKubernetes Serviceリソースなどに応じてネットワーク設定を行う
- コンテナランタイムはコンテナを実行するソフトウェア - デプロイ手法
- CIOpsはPush型のデプロイ手法。シンプルでわかりやすく、構築しやすい
- GitOpsはPull型のデプロイ手法。セキュリティリスクに強く、CIとCDを明確に分けることができる - マニフェスト管理
- Helmはパッケージマネージャとなっており、チャートというテンプレートを使用してデプロイや管理を簡略化する
- Kustomizeは基本設定を使い回して、環境ごとに微調整できる。基本設定をbaseディレクトリ、各環境固有の設定をoverlaysディレクトリ内のファイルに書く - オブザーバビリティとモニタリング
- Prometheusを使用しメトリクスを収集する。まずはPort-forwardを行うブラウザでhttp://localhost:9090にアクセスすると、メトリクスが確認できるkubectl port-forward service/kube-prometheus-stack-prometheus --namespace monitoring 9090:9090
- 続いてGrafanaにアクセスする。Port-forwardを行うブラウザでhttp://localhost:8080にアクセスすると、ログイン後にメトリクスが確認できるkubectl port-forward service/kube-prometheus-stack-grafana --namespace monitoring 8080:80
本書の感想
- 解説がわかりやすく、図も豊富なことから、特に躓くことなくハンズオンを行うことができました
- イラストや漫画が多く、視覚型の学習スタイルの人に合う書籍かと思います