Kubernetesのお勉強はじめました
久しぶりのアウトプットです。業務で間接的にKubernetesを利用するため、勉強がてらKubernetesの本をAmazonで購入しました。
最終的にはCKAの取得を目指しているので、ここでアウトプットして知識定着していこうと思います。
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を採用しました。
どのようなデプロイ方法があるか気になる方は以下ご参照ください。
Kindでデプロイ
家にKubernetes用に購入したミニサーバがあるので、そこにデプロイしていきます。
OSはUbuntu22.04です。
基本的に公式のクイックスタートを参考に構築していきます。
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が削除されたことを確認
$ sudo kubectl get pods
No resources found in default namespace.
【TIPS】
マニフェストファイルを修正した場合、修正内容を適用するコマンドはkubectl apply
である。
このコマンドはリソースが存在しない場合は、kubectl create
コマンドと同じ動きをするため、基本的にはkubect applyコマンドを使った方が利便性が高いと言えます。
Podの再起動
Podの再起動の注意点として、Pod指定の再起動はできません。
Deploymentなどのリソースに紐づいている全てのPodに対してのみ再起動が可能です。
そのため、Deploymentの作成を行います。
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コマンドで設定も可能
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
$ 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
Discussion