#本記事の目的
社内でのDevOps検証に合わせて、Kubernetesの基礎知識を学び、アウトプットとして備忘録を記す。
本記事ではKubernetesのアーキテクチャ、操作方法、及び基本リソースの概念について説明する。
#クラスタのアーキテクチャ
※Control Planeのコンポーネントは赤、(Worker) Nodeのコンポーネントは青で記載する。
###1. etcd
- KVS(KeyとValueを組み合わせる構造を持つデータストア)の一種。
- etcdctlコマンドで操作可能。
- Kubernetesでは、etcdがクラスターに関連するオブジェクト(ノード、ポッド等)の情報を保持する。
###2. kube-apiserver
- KubernetesのAPIを提供するコンポーネント。
- ユーザーの認証/リクエストの検証/etcdからのデータ取り込み/etcdのアップデート/kube-schedulerとの通信/kubeletとの通信を実施する。
- Kubernetesのコンポーネントの中で、唯一etcdと直接通信が可能である。
###3. kube-controller-manager
- Kubernetesのオブジェクトを処理するコントローラを実行するコンポーネント群。
- ステータスの監視、(必要に応じて)オブジェクトの修復を実施する。
- オブジェクトを処理するために様々なコントローラーが用意されている。ex.)Node-Controller,Replicaset-Controller
###4. kube-scheduler
- Podを適切なNodeに割り当てるコンポーネント。
- spec.nodeName(起動するノード情報)が割り当てられていないPodを検知し、kube-apiserverにリクエストを送る事でspec.Nodenameを更新する。
###5. kubelet
- container runtimeに命令する事で、Podの起動/監視を実施するエージェント。
- kubeletによるPodの起動方法は、以下の2種類。
- kube-schedulerによるPodの割り当てに従い、自身のNode上でPodを起動させる。(デフォルト)
- Nodeの特定のパスにManifestファイルを配置する事で、自身のNode上でPodを起動させる。(Static Pod)
###6. kube-proxy
- Service宛のトラフィックをPodに転送する事で、Podのルーティングを実施するコンポーネント。
###7. container runtime
- kubeletからの命令を受け、コンテナを実際に操作するコンポーネント。
- Docker, containerd, cri-o等様々な種類が存在する。
#クラスタの操作方法
###1. kubectlとmanifest
- クラスタを手動で操作する場合は、KubernetesのCLIツールであるkubectlコマンドと、オブジェクトが定義されたmanifestファイルを用いる事が一般的である。
- クラスタでの一部の操作は、kubectlコマンドのみでも可能である。
- manifestファイルはYAML形式及びJSON形式での記載が必須である。一般的にYAML形式が用いられる。
###2. 命令型と宣言型
-
kubectlコマンドによる操作は、命令形と宣言型に分かれる。
-
命令型は、コマンド自身が具体的なクラスタ操作内容を指定する。コマンドが実施されると、コマンドで指定されたクラスタ操作内容に従って、特定のクラスタ操作が実施される。
kubectl apply
以外のコマンドが該当する。 -
宣言型は、コマンド自身は具体的なクラスタ操作内容を指定しない。コマンドが実施されると、指定されたmanifestファイルが履歴として保存される。また前回保存されたmanifestファイルの履歴と、コマンドで指定されたmanifestファイルの内容の差分を基に、適切なクラスタ操作が実施される。
kubectl apply
コマンドのみが該当する。
$ kubectl apply -f [manifestファイル名]
#Kubernetesの基本リソース
###1. Pod
- Kubernetesにデプロイ出来る最小単位のリソース。
- 1つ以上のコンテナで構成される。
- Pod内のコンテナは、同一のNICとストレージを共有する。
- manifestファイルを用いずに、以下のコマンドでPodを作成できる。
$ kubectl run [任意のPod名] --image=[コンテナイメージ名]
- manifestファイルを用いてPodを作成する場合、主に以下のフィールドを指定する必要がある。
フィールド名 | 設定内容 |
---|---|
apiVersion | Kubernetes APIにおける、オブジェクトが属するグループ及びバージョン。 ex.)v1, apps/v1 |
kind | オブジェクトの種類。 ex.) Pod, Replicaset, Deployment |
metadata | オブジェクトの基本情報。name フィールドには任意のオブジェクト名を指定する。labelsフィールドには任意のラベル名を指定する。 |
spec | オブジェクトの状態。containers > name フィールドには任意のコンテナ名を指定する。containers > image フィールドには任意のコンテナイメージ名を指定する。 |
- manifestファイル例
apiVersion: v1
kind: Pod
metadata:
name: sample-pod
labels:
app: sample-app
spec:
containers:
- name: sample-container
image: nginx
###2. ReplicaSet
- 指定した数のPodを複製し、維持し続けるリソース。
- 1つ以上のPodで構成される。
- manifestファイルを用いずに、既存のオブジェクトを対象として、Podを複製できる。
$ kubectl scale [対象のオブジェクトの種類] [対象のオブジェクト名] --replicas=[Podの複製数]
- manifestファイルを用いてReplicaSetを作成する場合、Podで必要なフィールドに加えて、主にspecフィールド配下に以下のフィールドを指定する必要がある。
フィールド名 | 設定内容 |
---|---|
replicas | Podの複製数。 |
selector | Labelを選択するための設定。matchLabels フィールドを設定すると等価ベースで比較し、指定したLabelと全て一致したものが対象となるように選択する。基本的にselector > matchLabels フィールドの定義と、template > metadata > labels フィールドの定義を一致させる必要がある。 |
template | 複製するPodの雛形。(内容はPodのmetadata及びspecと同一) |
- manifestファイル例
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: sample-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- image: nginx
name: sample-container
###3. Deployment
- 複数のReplicaSetを管理し、ローリングアップデートやロールバックを実現するリソース。
- 1つ以上のReplicaSetで構成される。
- manifestファイルを用いてDeploymentを作成する場合、ReplicaSetで必要なフィールドがそのまま必要となる。
- manifestファイルを用いずに、以下のコマンドでDeploymentを作成できる。
$ kubectl create deployment [任意のDeployment名] --image=[コンテナイメージ名]
- manifestファイル例
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment
spec:
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- image: nginx
name: sample-container
###4. Namespace
- クラスタを分離するリソース。
- 初期状態では、以下3種類のNamespaceが存在する。
Namespace名 | 使用用途 |
---|---|
kube-system | Clusterに必須のコンポーネントが配置される。 |
kube-public | 全ユーザが利用できる認証情報等が配置される。 |
default | デフォルトで使用される。 |
- ResourceQuotaリソースを用いる事で、Namespaceで使用できるCPU/メモリ/ストレージを制限できる。
- manifestファイルを用いずに、以下のコマンドでNamespaceを作成できる。
$ kubectl create namespace [任意のNamespace名]
- manifestファイル例
apiVersion: apps/v1
kind: Namespace
metadata:
name: sample-namespace
###5. Service
- 受信したトラフィックを複数のPodに負荷分散するリソース。
- Serviceには様々な種類が存在するが、以下3種類が特に使用される事が多い。
Service名 | 機能 |
---|---|
ClusterIP | クラスタ内部でIPアドレスが払い出され、各々のPod間での通信を可能にする。 |
NodePort | ClusterIPの機能に加え、クラスタ内部に存在する全てのNodeの特定のポートが受信したトラフィックを、各々のPodに転送する。 |
LoadBalancer | NodePortの機能に加え、クラスタ外部に存在するロードバランサーが受信したトラフィックを、各々のNodeに分散させる。 |
- manifestファイルを用いずに、既存のオブジェクトを対象として、以下のコマンドでServiceを作成できる。
$ kubectl expose [対象のオブジェクトの種類] [対象のオブジェクト名] --port=[使用するポート番号] --type=[Serviceの種類] --name=[任意のService名]
- manifestファイルを用いてServiceを作成する場合、Podで必要なフィールドに加えて、specフィールド内に以下のフィールドを指定する必要がある。
フィールド名 | 設定内容 |
---|---|
type | Serviceの種類。デフォルトはClusterIP 。 ex.) ClusterIP, NodePort, LoadBalancer |
ports | 使用するポート番号。port フィールドにはServiceで使用するポート番号を設定する。targetPort フィールドにはPodで使用するポート番号を設定する(デフォルトはportフィールドと同一のポート番号)。 |
selector | トラフィックをルーティングするPodのラベル。Podのmanifestファイルのmetadata > labels フィールドと同一の内容を記載する。 |
- manifestファイル例
apiVersion: v1
kind: Service
metadata:
name: sample-nodeport
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
selector:
type: front-end
#感想
個人的に、Kubernetesでの検証を行う際は、操作方法や基本リソースはもちろんだが、加えてアーキテクチャを理解する事が重要であると考える。
去年もKubernetesの構築やトラブルシューティングを実施したが、もしアーキテクチャの知識があればより作業のスピードを上げられたように感じている。
また今後機会があれば、Container Runtimeのアーキテクチャについてもまとめてみたい。
#参考文献