💭

Kubernetesのお勉強はじめました

2024/02/23に公開

久しぶりのアウトプットです。業務で間接的にKubernetesを利用するため、勉強がてらKubernetesの本をAmazonで購入しました。
最終的にはCKAの取得を目指しているので、ここでアウトプットして知識定着していこうと思います。
https://www.amazon.co.jp/Kubernetes完全ガイド-第2版-Top-Gear-青山/dp/4295009792/ref=sr_1_1?crid=NVE1UKZIDPQW&dib=eyJ2IjoiMSJ9.GLRz7TapHQu79BCToFzwEC8usstVg6foAI4N6d-FqZZKWuMCiK8PCZtIq70u2cZI9crbW9KVyK3l1XOozx7o8W3Cc-7bZtv0GvIb2XfQtT5pmfTl6DbSzATWQFrCty2l8fw7K-beXeoxQ7tfB1bYNz0mHKlyyzmkWXgXMAIzsQ5XKkirRqg4EBYVuFIM18Z4r4cov_sbr8cu_NchBwIboDs2TPZLGDc9HluOsPNT-ULCaPezxyLjWt-_02YLkhGt3D55vPJLZyAIv9g46AGeDF5Olqm_E-8aS7pg0bWtWik.wZNG_GKID5b2rB23LjcelWnID9Lw-PLWF-_BBymHMwU&dib_tag=se&keywords=kubernetes完全ガイド&qid=1708663350&sprefix=kubernetes%2Caps%2C483&sr=8-1

Kubernetes概要

Kubernetesについては、他に詳しく説明してくださっている先輩方がいらっしゃるので、軽く概要だけ紹介します。
Kubernetesはコンテナ化されたアプリケーションのデプロイ、スケーリングなどの管理を自動化するためのプラットフォームです。
コンテナをホストしたマシンを複数台協調して動作させたり、一元的に管理したりするためにKubernetesが利用されるのが一般的です。
またKubernetesで利用できるコンテナランタイムはDocker以外にもcontainerdやcri-oなどを実装可能です。
Kuberntetesは、Kubernetes MasterとKubernetes Nodeの2種類のノードから成り立っています。
Kubernetes MasterはAPIエンドポイントの提供、コンテナのスケジューリング/スケーリングなどを担います。
Kubernetes NodeはいわゆるDockerホストに相当し、実際にコンテナが起動するノードです。

基本的にkubernetesの操作はマニフェスト(YAML/JSON形式)を作成し、それを基にKubernetes MasterのAPIへリクエストを送り、リソースの管理を行います。

Kubernetesでできること

No 機能 概要
1 Infrastructure as Code Kubernetesでは、YAMLやJSON形式で記述した宣言的なコードによってデプロイするコンテナや周辺リソースを管理可能
2 スケーリング/オートスケーリング コンテナの複製/負荷分散や耐障害性の確保が可能
3 コンテナのスケジューリング コンテナをデプロイするNode先を決定することができる。コンテナ化されたアプリケーションのワークロード(メモリ使用率が高いなど)の特徴から、デプロイ先のNodeを制御可能
4 リソース管理 コンテナ配置の指定がない場合、NodeのCPUやメモリのリソースの空き具合から配置先を決定する機能
5 障害時のセルフヒーリング コンテナのプロセス監視を行い、プロセスが停止を検知すると自動的にコンテナを際デプロイする機能
6 ロードバランシング 複数台恒星のアプリケーションのエンドポイントを用意する機能
7 データの管理 etcdデータストアに各種設定ファイルや認証情報などを管理可能

Kubernetesのデプロイ

Kubernetesのデプロイ方法にはいくつか手法があり、今回は勉強目的用ということもあり、Kindを採用しました。
どのようなデプロイ方法があるか気になる方は以下ご参照ください。
https://qiita.com/tmurakam99/items/b27d1055f7c881a03ba0

Kindでデプロイ

家にKubernetes用に購入したミニサーバがあるので、そこにデプロイしていきます。
OSはUbuntu22.04です。

基本的に公式のクイックスタートを参考に構築していきます。
https://kind.sigs.k8s.io/docs/user/quick-start/

Kindのインストール

$ curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-amd64
$ chmod +x ./kind
$ sudo mv ./kind /usr/bin/kind

kubectlのインストール

kindにkubectlは必須では無いですが、無いと使えない機能もあるっぽいので、一応インストールします。

$ curl -LO https://dl.k8s.io/release/v1.29.1/bin/linux/amd64/kubectl
$ sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
$ kubectl version --client
    Client Version: v1.29.1
    Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3

これで、一応準備は完了かな。。。??
これ以降は本書に沿って、Kubernetes機能に触れていきます。

シングルクラスターの作成

kind create clusterコマンドを実行し、クラスターを構築します。
コマンドオプションに--nameでクラスターネームを指定ができます。
指定がない場合はデフォルトでkindが設定されます。

$ sudo kind create cluster
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.29.2) 🖼
 ✓ Preparing nodes 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

Not sure what to do next? 😅  Check out https://kind.sigs.k8s.io/docs/user/quick-start/

kubectl cluster-infoコマンドで、Kubernetesクラスターのマスターとサービスのアドレスを表示します

$ sudo kubectl cluster-info --context kind-kind
Kubernetes control plane is running at https://127.0.0.1:44497
CoreDNS is running at https://127.0.0.1:44497/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

クラスターを作成したことで、kubeconfigが作成されました。
kubeconfigには、Kubernetes Masterと通信する際の接続先や認証情報が記述されています。

$ sudo cat /root/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRV**********VRFLS0tLS0K
    server: https://127.0.0.1:44497
  name: kind-kind
contexts:
- context:
    cluster: kind-kind
    user: kind-kind
  name: kind-kind
current-context: kind-kind
kind: Config
preferences: {}
users:
- name: kind-kind
  user:
    client-certificate-data: LS0tLS1CRUdJTiB**********lDQVRFLS0tLS0K
    client-key-data: LS0tLS**********TQSBQUklWQVRFIEtFWS0tLS0tCg==

Podの作成

クラスター上にPodを作成してみます。
Podを作成する方法として、kubectlコマンドで作成する方法と、マニフェストファイルを基に作成する方法があります。
ここではマニフェストファイルからの作成する方法を試してみます。
本書通りにマニフェストファイルを用意します。

サンプル用のマニフェストファイル
apiVersion: v1
kind: Pod
metadata:
  name: sample-pod
spec:
  containers:
  - name: nginx-container
    image: nginx:1.16

kubectl createコマンドに引数として、YAMLファイルを渡しPodを作成します。

$ sudo kubectl create -f sample-pod.yaml
pod/sample-pod created

kubectl get podsコマンドを実行し、Podのステータスを確認できます。
READYが1/1となっており、1台のPodが立ち上がったことがわかります。

$ sudo kubectl get pods
NAME         READY   STATUS              RESTARTS   AGE
sample-pod   0/1     ContainerCreating   0          14s
$ sudo kubectl get pods
NAME         READY   STATUS    RESTARTS   AGE
sample-pod   1/1     Running   0          60s

Podの削除

次に作成したPodを削除してみます。
kubectl deleteコマンドで削除することができます。

$ sudo kubectl delete -f sample-pod.yaml
pod "sample-pod" deleted

Podが削除されたことを確認

kubectl getコマンドでの確認
$ sudo kubectl get pods
No resources found in default namespace.

【TIPS】

マニフェストファイルを修正した場合、修正内容を適用するコマンドはkubectl applyである。
このコマンドはリソースが存在しない場合は、kubectl createコマンドと同じ動きをするため、基本的にはkubect applyコマンドを使った方が利便性が高いと言えます。

Podの再起動

Podの再起動の注意点として、Pod指定の再起動はできません。
Deploymentなどのリソースに紐づいている全てのPodに対してのみ再起動が可能です。
そのため、Deploymentの作成を行います。

deployment-sample.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

kubectl applyコマンドでDeploymentを作成します。

$ sudo kubectl apply -f deployment-sample.yaml

kubectl get podコマンドを実行し、podが作成されたことを確認します。

$ sudo kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE     IP           NODE                 NOMINATED NODE   READINESS GATES
nginx-deployment-86dcfdf4c6-k4cjr   1/1     Running   0          4m11s   10.244.0.7   kind-control-plane   <none>           <none>
nginx-deployment-86dcfdf4c6-lsbqq   1/1     Running   0          4m11s   10.244.0.9   kind-control-plane   <none>           <none>
nginx-deployment-86dcfdf4c6-szmqc   1/1     Running   0          4m11s   10.244.0.8   kind-control-plane   <none>           <none>

続けて、kubectl rollout restartコマンドで再起動を実施します。

$ sudo kubectl rollout restart deployment nginx-deployment

再度、kubectl get podコマンドを実行すると、 再起動したためPodが作り替えられたことによってNameが変更されていることがわかりみます。

$ sudo kubectl get pod -o wide
NAME                               READY   STATUS    RESTARTS   AGE   IP            NODE                 NOMINATED NODE   READINESS GATES
nginx-deployment-8f7c474d7-252jr   1/1     Running   0          6s    10.244.0.11   kind-control-plane   <none>           <none>
nginx-deployment-8f7c474d7-mprvj   1/1     Running   0          5s    10.244.0.12   kind-control-plane   <none>           <none>
nginx-deployment-8f7c474d7-pwzsn   1/1     Running   0          8s    10.244.0.10   kind-control-plane   <none>           <none>

続きはまた今度。
色々とやれることが多いため、検証するのも一苦労です。。。


2024/02/24追記

マニフェストファイルの設計指針

マニフェストファイルの設計の代表的なパターン例

  • マイクロサービス単位にマニフェストファイルを作成する
  • サブシステム単位にマニフェストファイルを作成する
  • 開発チームや組織構造単位ディレクトリを切りマニフェストファイルを作成する

アノテーションとラベル

Kubernetesでは、各リソースに対してアノテーションとラベルを付与することできます。
これは、メタデータの一種です。違いは次のとおりです。

名称 概要
アノテーション システムコンポーネントが利用するメタデータ
ラベル リソース管理に利用するメタデータ

アノテーション

アノテーションの用途

用途 概要
システムコンポーネントのためにデータを保存する 例として、kubectl.kubernetes.io/las-applied-configuration(前回適用したマニフェストの内容が含まれる)もアノテーションの一種です。こういったアノテーションはシステムが自動で付与します
全ての環境では利用できない設定を行う 例として、GKE/AKS/EKSなど別々のクラウドプロバイダーが独自に提供する機能をアノテーションを使って実現しています。
正式に組むこまれる前に設定を行う 評価中の機能を有効にするためにも使われます。

アノテーションをマニフェストファイルに書く場合はキーバリューの形で記述します。
kubectlコマンドで設定も可能

apiVersion: v1
kind: Pod
metadata:
  name: sample-annotations
  annotations:          #annotationsを宣言する
    annotation1: val1   #キーバリューの形で記述
    annotation2: "200"  #キーバリューの形で記述、ただし、値が数値の場合はダブルクォーテーションで囲むこと
spec:
  containers:
  - name: nginx-container
    image: nginx:1.16

ラベル

ラベルはリソースを分割するための情報です。
Kubernetesはマイクロサービスアーキテクチャへの親和性が高いことから、Podという小さな単位のサービスが大量に構築されます。
その時に、大量のリソースをラベルでグルーピングしたり、何らかの処理に対する条件分岐に利用できます。

マニフェストファイルへの設定方法次のとおりです。
kubectlコマンドで設定も可能

sample-label.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-label
  labels:
    label1: val1
    label2: val2
spec:
  containers:
  - name: nginx-container
    image: nginx:1.16

kubectl pod getsコマンドで対象のラベルでフィルタリングするには、オプションの-lをつけます。

$ sudo kubectl get pods -l label1
NAME           READY   STATUS    RESTARTS   AGE
sample-label   1/1     Running   0          49s

オプションで-Lにすると、設定されたラベルも確認できます。

$ sudo kubectl get pods -L label2,label1
NAME                               READY   STATUS    RESTARTS   AGE   LABEL2   LABEL1
nginx-deployment-8f7c474d7-252jr   1/1     Running   0          21h
nginx-deployment-8f7c474d7-mprvj   1/1     Running   0          21h
nginx-deployment-8f7c474d7-pwzsn   1/1     Running   0          21h
sample-label                       1/1     Running   0          86s   val2     val1

推奨されるラベルキー名

ラベルキー名 概要
app.kubernetes.io/name アプリケーションの名前
app.kubernetes.io/version アプリケーションのバージョン
app.kubernetes.io/component アプリケーション役割
app.kubernetes.io/part-of アプリケーションが全体として構成するシステムの名前
app.kubernetes.io/instance アプリケーションやシステムが識別するインスタンス名
app.kubernetes.io/managed-by このアプリケーションが管理されているツール

editコマンドによる編集

kubectl editコマンドを使えば、エディター編集が可能です。
試しに、sample-labelのlabel3:val3を追加してみます。

$ sudo kubectl edit pod sample-label #label3:val3と追加
pod/sample-label edited
$ sudo kubectl apply -f sample-label.yaml #設定を反映
pod/sample-label unchanged
$ sudo kubectl get pods -l label3 #確認
NAME           READY   STATUS    RESTARTS   AGE
sample-label   1/1     Running   0          85m

setコマンドによる設定の繁栄

マニフェストファイルを更新せずとも、一部の設定値に限りkubectl setコマンドを使用して簡単に動作状態を変更することができます。

  • env
  • image
  • resources
  • selector
  • serviceaccount
  • subject

検証してみます。
sample-labelPodのnginxイメージのバージョンを変更します。

現在のバージョンを確認
$ sudo kubectl describe pod sample-label| grep Image:
    Image:          nginx:1.16
setコマンドでイメージのバージョンアップを実施
$ sudo kubectl set image pod sample-label nginx-container=nginx:1.17
pod/sample-label image updated
$ sudo kubectl describe pod sample-label| grep Image:
    Image:          nginx:1.17

execコマンドによるコンテナ上でのコマンド実行

kubectl execコマンドを利用することで、Pod内のコンテナに対して/bin/bashなどのシェルを実行することができます。
さらに擬似的にコンテナにログインしているようにもできます。

単発のシェルコマンドを実行する方法

$ sudo kubectl exec -it sample-label -- /bin/ls
bin   dev  home  lib64	mnt  proc	   product_uuid  run   srv  tmp  var
boot  etc  lib	 media	opt  product_name  root		 sbin  sys  usr

コンテナにログインする方法

$ sudo kubectl exec -it sample-label -- /bin/bash
root@sample-label:/#

ポートフォワーディング

ローカルマシンからPod内のコンテナで起動しているNginxにアクセスしてみます。
その他にも、アプリケーションのデバッグ用としても利用されています。
kubectl port-forwardコマンドでポートフォワード設定を行います。
ポート指定の意味は、localhost:8888宛の通信はPodの80ポート宛に転送する設定です。

$ sudo kubectl port-forward deployment/nginx-deployment 8888:80
Forwarding from 127.0.0.1:8888 -> 80
Forwarding from [::1]:8888 -> 80

上記はポートフォワード設定をdeploymentに対して実行していますが、Pod単位やservice単位でも可能です。

# Podに対するポートフォワード設定
$ sudo kubectl port-forward sample-label 8888:80
# serviceに対するポートフォワード設定
$ sudo kubectl port-forward service/sample-service 8888:80

localhostのポート8888宛へcurlコマンドを実行すると、200OKが返ってきました。

$ curl -I localhost:8888
HTTP/1.1 200 OK
Server: nginx/1.14.2
Date: Sat, 24 Feb 2024 04:44:23 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 04 Dec 2018 14:44:49 GMT
Connection: keep-alive
ETag: "5c0692e1-264"
Accept-Ranges: bytes

Workloads API

Discussion