プラクティス集@Kubernetes¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. リポジトリ構成規約¶
リポジトリ分割のメリット¶
リポジトリを分割することにより、以下のメリットがある。
- 認可スコープをリポジトリ内に閉じられるため、運用チームを別に分けられる。
アプリとIaCを同じリポジトリで管理¶
アプリケーションと同じリポジトリにて、kubernetes
ディレクトリを作成し、ここにマニフェストを配置する。
repository/
├── app/ # アプリケーション
├── manifests/
│ └── kubernetes/
│ ├── foo/
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ ├── persistent-volume.yaml
│ │ └── persistent-volume-claim.yaml
│ │
...
アプリとIaCを異なるリポジトリで管理 (推奨)¶
▼ 各マイクロサービスを同じリポジトリで管理¶
repository/
├── foo/ # fooサービス
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── persistent-volume.yaml
│ └── persistent-volume-claim.yaml
│
├── bar/ # barサービス
└── baz/ # bazサービス
▼ 各マイクロサービスを異なるリポジトリで管理¶
repository/ # fooサービス
├── deployment.yaml
...
repository/ # barサービス
├── deployment.yaml
...
repository/ # bazサービス
├── deployment.yaml
...
01-02. ディレクトリ構成規約¶
ディレクトリ/ファイルの構成¶
▼ マイクロサービス別¶
マイクロサービス別にディレクトリを作成し、Kubernetesリソースごとに異なるマニフェストを定義する。
kubectl
コマンドの実行時にマニフェストの送信の順番を制御しにくいデメリットがある。
repository/
├── foo/ # fooサービス
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── persistent-volume.yaml
│ └── persistent-volume-claim.yaml
│
├── bar/ # barサービス
└── baz/ # bazサービス
加えて、実行環境やコンポーネント (app、db) 別に分割しても良い。
repository/
└── foo/ # fooサービス
├── tes # テスト環境
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── persistent-volume.yaml
│ └── persistent-volume-claim.yaml
│
├── prd # 本番環境
└── stg # ステージング環境
repository/
└── foo/ # fooサービス
├── app/ # appコンポーネント
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── persistent-volume.yaml
│ └── persistent-volume-claim.yaml
│
└── db/ # dbコンポーネント
├── stateful-set.yaml
├── service.yaml
├── persistent-volume.yaml
└── persistent-volume-claim.yaml
▼ ディレクトリ無し¶
ディレクトリを作成しない。
代わりに、マイクロサービス別にマニフェストを定義し、関連する全てのKubernetesリソースをこの中で定義する。
repository/
├── foo.yaml # fooサービス (Deployment、Service、PersistentVolume、...)
├── bar.yaml # barサービス
└── baz.yaml # bazサービス
02. 命名規則¶
リソース名¶
▼ 冗長な名前が嫌いな場合¶
冗長な名前が嫌いな場合は <マイクロサービス名>
とする。
基本はこれを使用する。
ケバブケースとする。
Kubernetesリソース | 例 |
---|---|
Service | foo |
Deployment | foo |
PersistentVolume | foo |
... | ... |
▼ 冗長な名前が嫌いでない場合¶
嫌いでない場合は <マイクロサービス名>-<Kubernetesリソース名>
とする。
ケバブケースとする。
Kubernetesリソース | 例 |
---|---|
Service | foo-service |
Deployment | foo-pod |
PersistentVolume | foo-persistent-volume |
... | ... |
マニフェストのファイル名¶
▼ 重複しない場合¶
ファイル名は、Kubernetesリソース名 (例:deployment.yaml
ファイル) になるようにする。
基本的にはこれを使用する。
ケバブケースとする。
GitHubの公式チャートを見ると、命名方法が参考になる。
repository/
├── deployment.yaml
├── service.yaml
├── persistent-volume.yaml
└── persistent-volume-claim.yaml
▼ ファイル名重複する場合¶
1
個のディレクトリ内でKubernetesリソースが重複する場合、Kubernetesリソース名をつけることができない。
その場合、app.kubernetes.io
キーの値 (例:<マイクロサービス名>
または <マイクロサービス名>-<Kubernetesリソース名>
) と同じにする。
# 全てApplication
# 各Applicationは、fooマイクロサービス、barマイクロサービス、bazマイクロサービス、にデプロイする。
repository/
├── foo.yaml
├── bar.yaml
└── baz.yaml
# 全てApplication
# 各Applicationは、fooマイクロサービス、barマイクロサービス、bazマイクロサービス、にデプロイする。
repository/
├── foo-application.yaml
├── bar-application.yaml
└── baz-application.yaml
拡張子¶
Kubernetesに関する開発プロジェクトを確認すると、そのほとんとで、yaml
ファイルの拡張子をyml
ではなく yaml
に統一している。
そこで、Kubernetesや関連技術 (Istio、Helm、Skaffold、Envoyなど) の yaml
ファイルの拡張子を yaml
で統一する。
repository/
├── foo/ # fooサービス
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── persistent-volume.yaml
│ └── persistent-volume-claim.yaml
│
├── bar/ # barサービス
└── baz/ # bazサービス
マニフェストの粒度¶
1
個のマニフェストに、1
個のKubernetesリソースを定義する。
03. 実行環境¶
開発環境¶
▼ Kubernetesの実行環境¶
開発環境でKubernetesリソースの機能追加を検証するツールの例を記載する。
Minikube | Docker for Desktop | Kind | クラウドプロバイダー (AWS EKS、Google Cloud GKEなど) | |
---|---|---|---|---|
概要 | カスタマイズ性が高いため、カスタマイズ次第で本番環境と開発環境の差異を小さくできる。2022年3月の現在では、Kubernetesの開発環境として、ベタープラクティスである。 | セットアップが非常に簡単 (有効化するだけ) なため、開発に取り掛かるまでが早い。 | セットアップが簡単なため、開発に取り掛かるまでが早い | 実行環境を開発環境としても使用する。開発者ごとに異なるNamespaceを作成する。これを採用している企業が多い。 |
セットアップの難易度 | 簡単 | 非常に簡単 | 簡単 | 難しい |
コンテナランタイム | docker、containerd、cri-o | docker | containerd (ホストOSのdockerコンテナを作成し、この中にcontainerdコンテナを作成する) | docker、containerd |
Kubernetesのバージョン | 任意のバージョンを指定できる。 | Docker for Desktopのバージョンごとに、Kubernetesのバージョンが固定される。 | 任意のバージョンを指定できる。 | 任意のバージョンを指定できる。 |
マルチNode | 可能 | 可能 | 可能 | 可能 |
Nodeのカスタマイズ性 | 高い | 低い | 高い | 高い |
料金 | 無料 | 無料 | 無料 | 非常に高い |
- https://minikube.sigs.k8s.io/docs/tutorials/multi_node/
- https://codefresh.io/kubernetes-tutorial/local-kubernetes-mac-minikube-vs-docker-desktop/
- https://blog.cybozu.io/entry/2019/07/03/170000
- https://qiita.com/Hiroyuki_OSAKI/items/2395e6bbb98856df12f3#2%E9%87%8D%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%B3
▼ Kubernetesリソースのapply¶
Skaffold | Telepresence | |
---|---|---|
概要 | CIOpsによって、Kubernetesの開発環境にKubernetesリソースを作成する。本番環境へのCIOpsは非推奨であるが、開発環境であれば問題ない。 | ローカルマシンに対するリクエストを、リモートにあるKubernetesのテスト環境に転送する。 ・https://thinkit.co.jp/article/17853 |
テスト環境、ステージング環境、本番環境¶
▼ Kubernetesの実行環境¶
開発環境で検証後、Kubernetesリソースの機能追加を検証するツールの例を記載する。
全て自前 | オンプレ | クラウド | |
---|---|---|---|
Kuberbetesオーケストレーションツール | 全て自前なため、自由にカスタマイズできる。 | Kubeadm、Rancher、Kops、Kubespray、ベアメタル (例;EKS Anywhere、Anthos on Baremetal)など | AWS EKS、Google Cloud GKEなど |
説明 | オンプレミス上にコントロールプレーンNodeやワーカーNodeとなる仮想サーバーを事前に作成しておく。ユーザー自身が、Clusterを作成し、仮想サーバーにコントロールプレーンNodeあるいはワーカーNodeとしての役割を割り当てる。 | オンプレミス上にコントロールプレーンNodeやワーカーNodeとなる仮想サーバーを事前に作成しておく。ツールを使用して、仮想サーバーをClusterに参加させ、仮想サーバーにコントロールプレーンNodeあるいはワーカーNodeとしての役割を割り当てる。マニフェストの DB として KVS を使用する必要があるが、KVS 用クエリを RDB 用クエリに変換するツール (例:Kine) を使用すれば、RDB も使用できる。 | セルフマネージドワーカーNodeの場合は、ワーカーNodeとなる仮想サーバーを事前に作成しておく。コントロールプレーンNodeは必ずマネージドになる。クラウドプロバイダーを使用して、仮想サーバーをClusterに参加させ、仮想サーバーにコントロールプレーンNodeあるいはワーカーNodeとしての役割を割り当てる。 |
メリット | 全て自前なため、自由にカスタマイズできる。 | カスタマイズ性が高い。 | マネージドであるため、ユーザーがKubernetesのワーカーNodeを管理するコストが低い。執筆時点 (2022年3月) では、Kubernetesの本番環境として、ベタープラクティスである。 |
デメリット | ユーザーが Kubernetes のワーカーNodeを管理するコストが高い。 | ユーザーが Kubernetes のワーカーNodeを管理するコストが高い。 | カスタマイズ性が低い |
▼ Kubernetesリソースのapply¶
CIOps | GitOps | |
---|---|---|
概要 | CIOpsによって、Kubernetesの本番環境にKubernetesリソースを作成する。非推奨である。 | GitOpsによって、Kubernetesの本番環境にKubernetesリソースを作成する。 |
▼ 実行環境の分割¶
Clusterの複数の実行環境 (dev-*
、stg-*
、prd-*
) を用意したい場合、個人的にはその分Clusterを増やすようにする。
実行環境が 5
個や 10
個となってくると、Clusterの分だけアップグレードやSync漏れ (手動の場合) が発生するため、運用コストが高くなるというデメリットはある。
一方で、Namespaceを実行環境の粒度とすると、上記のデメリットは少ないが、Namespaceのプレフィクスに実行環境名を付与することとなり、名前が長くなってしまう。
これらを比較して、より自身に合った方法を選ぶ。
04. バージョンの互換性¶
kube-apiserver¶
▼ kube-apiserverが冗長化されている場合¶
冗長化されたkube-apiserverのバージョン差は、前方の 1
個のマイナーバージョン以内に収める必要がある。
kubectl¶
▼ kube-apiserverの場合¶
kubectl
コマンドとkube-apiserverのバージョン差は、前方/後方の 1
個のマイナーバージョン以内に収める必要がある。
06. CIDRブロックの設計¶
ワーカーNodeの場合¶
Kubernetesでは、稼働する可能性のあるPod数から、ワーカーNodeのCIDRブロックを算出すると良い。
アプリケーションのPodがスケーリングすることや、カスタムリソース (例:Istio、Linkerd) を導入することも考慮して、尤もらしいIPアドレス数を算出できる。
削除されるPodと作成されるPodが別のIPアドレスになるようにするために (IPアドレスの再利用を防ぐために) 、Podの最大数の 2
倍のIPアドレスを持つCIDRブロックを設定すると良い。
Node当たりの最大Pod数 | ワーカーNode当たりのCIDRブロック | IPアドレス数 |
---|---|---|
1 |
/32 |
2 |
8 |
/28 |
16 |
9 ~16 |
/27 |
32 |
17 ~32 |
/26 |
64 |
33 ~64 |
/25 |
128 |
65 ~110 |
/24 |
256 |
サブネットの場合¶
AWS EKSでの目安であるが、サブネットごとに /19
や /20
なるように設計するのが、個人的にはおすすめ。
07. 監視ポリシー¶
メトリクスエンドポイント¶
Kubernetesの以下のコンポーネントが、メトリクスエンドポイント (/metrics
) を持つ。
- kube-controller-manager
- kube-proxy
- kube-apiserver
- kube-scheduler
- kubelet
ハードウェアリソース系¶
▼ ハードウェアリソース系¶
ハードウェアリソースの性能指標に関するメトリクスである。
収集ツールとして、node-exporterがある。
▼ Cluster¶
メトリクス | 単位 | 説明 | アラート条件例 (合致したら発火) |
---|---|---|---|
CPU | % | 同じCluster内のワーカーNodeのCPU使用率をデータポイントとする。 | ・統計 : 期間内平均使用率 ・期間 : 5 分・閾値 : >= 80 |
Memory | % | 同じCluster内のワーカーNodeのメモリ使用率をデータポイントとする。 | ・統計 : 期間内平均使用率 ・期間 : 5 分・閾値 : >= 80 |
▼ Pod¶
メトリクス | 単位 | 説明 | アラート条件例 (合致したら発火) |
---|---|---|---|
CPU | % | Pod全体のCPU使用率をデータポイントとする。 | ・統計 : 期間内平均使用率 ・期間 : 5 分・閾値 : >= 80 |
Memory | % | Pod全体のメモリ使用率をデータポイントとする。 | ・統計 : 期間内平均使用率 ・期間 : 5 分・閾値 : >= 80 |
▼ コンテナ¶
メトリクス | 単位 | 説明 | アラート条件例 (合致したら発火) |
---|---|---|---|
CPU | % | コンテナのCPU使用率をデータポイントとする。 | ・統計 : 期間内平均使用率 ・期間 : 5 分・閾値 : >= 80 |
Memory | % | コンテナのメモリ使用率をデータポイントとする。 | ・統計 : 期間内平均使用率 ・期間 : 5 分・閾値 : >= 80 |
ネットワーク系¶
▼ ネットワーク系¶
ネットワークの性能指標に関するメトリクスである。
収集ツールとして、kuebeletに内蔵されたcAdvisorがある。
メトリクス | 単位 | 説明 | アラート条件例 (合致したら発火) |
---|---|---|---|
container_network_receive_bytes_total |
カウント | 同じCluster内の受信したバイトの累積数をデータポイントとする。 | 記入中... |
container_network_transmit_bytes_total |
カウント | 同じCluster内の送信したバイトの累積数をデータポイントとする。 | 記入中... |
状態系¶
▼ 状態系¶
状態に関するメトリクスである。
収集ツールとして、kube-state-metricsがある。
▼ Cluster¶
Clusterをディメンションとしたメトリクスの監視ポリシーは以下の通りである。
メトリクス | 単位 | 説明 | アラート条件例 (合致したら発火) |
---|---|---|---|
Nodeの必要最低数 | カウント | 同じCluster内のワーカーNode数の必要最低数をデータポイントとする。 | ・統計 : 期間内合計数 ・期間 : 5 分・閾値 : <= 2 |
Podの必要最低数 | カウント | 同じCluster内のワーカーNodeのPod必要最低数をデータポイントとする。 | ・統計 : 期間内合計数 ・期間 : 5 分・閾値 : <= 1 |
▼ Pod¶
Pod全体をディメンションとしたメトリクスの監視ポリシーは以下の通りである。
メトリクス | 単位 | 説明 | アラート条件例 (合致したら発火) |
---|---|---|---|
Podの最低必要数 | カウント | 同じDeployment内のPodの必要最低数をデータポイントとする。 | ・統計 : 期間内合計数 ・期間 : 5 分・閾値 : <= 2 |
▼ コンテナ¶
コンテナをディメンションとしたメトリクスの監視ポリシーは以下の通りである。
メトリクス | 単位 | 説明 | アラート条件例 (合致したら発火) | 補足 |
---|---|---|---|---|
readinessProbe | カウント | コンテナのreadinessProbeの失敗数をデータポイントとする。 | ・統計 : 期間内合計数 ・期間 : 1 分・閾値 : >= 2 |
ネットワーク由来の問題で発生することがあるため、連続的に発生した上でアラートする。 |
08. デバッグ¶
便利なイメージ¶
▼ Deployment系¶
Deploymentが正しくPodを作成できない場合、それだけでHelloWorldのアプリケーションを起動できるイメージがある。
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
- name: foo
image: paulbouwer/hello-kubernetes:1.10
ports:
- containerPort: 8080
protocol: TCP
▼ ネットワーク系¶
ネットワークのトラブルシューティングに役立つツールがインストールされているイメージがある。
kubectl debug
コマンドと組み合わせる。
$ kubectl debug node/<Node名> \
-n default \
-it \
--image=praqma/network-multitool
09. CIパイプライン¶
マニフェストのホワイトボックステスト¶
▼ 静的解析¶
マニフェストのブラックボックステスト¶
▼ 結合テスト¶
テスト環境に対して kubectl apply
コマンドを実行することにより、追加/変更を含む複数のマニフェストを組み合わせた結合テストを実施する。
▼ システムテスト¶
テスト環境に対して kubectl apply
コマンドを実行することにより、既存機能/追加/変更を含む全てのチャートを組み合わせたシステムテストを実施する。
09-02. CDパイプライン¶
マニフェストのホワイトボックステスト¶
▼ 静的解析¶
GitOpsの場合、CIパイプライン上だけでなく、CDパイプライン上でもホワイトボックステストを実施できる。
ただし、kube-apiserverのvalidating-admissionステップ時にこれを実施する必要がある。
観点 | 説明 | 補足 |
---|---|---|
マニフェストのコード規約違反 | 外部のPaCツール (例:Gatekeeper、Kyverno) を使用する。ポリシー (regoなど) の定義に基づいて、そのプロダクトのコード規約違反を検証する。 | ・https://qiita.com/Udomomo/items/10ed2dbfef85812808da#conftest%E3%81%A7policy%E3%82%92%E6%9B%B8%E3%81%84%E3%81%A6%E3%81%BF%E3%82%8B |
デプロイ¶
▼ デプロイとは¶
本番環境に対して、ローカルマシンまたはCDツールを使用して、マニフェストをデプロイする。
▼ インプレースデプロイメント (非推奨)¶
KubernetesのDeploymentのReplace戦略を採用する。非推奨である。ダウンタイムが発生する。
▼ ローリングアップデート (推奨)¶
KubernetesのDeploymentのRollingUpdate戦略を採用する。
▼ BGデプロイメント (推奨)¶
Kubernetes自体はブルー/グリーンデプロイメントの能力を持たない。CDツール (例:Argo Rollouts) のBGデプロイメント機能を採用する。
▼ カナリアリリース (推奨)¶
Kubernetes自体はカナリアリリースの能力を持たない。CDツール (例:Argo Rollouts) やサービスメッシュツール (例:Istio、Linkerdなど) のカナリアリリース機能を採用する。
注意点として、サービスメッシュツールであると、重み付けの段階的な変更が手動になってしまう。
▼ Progressive Delivery (推奨)¶
Kubernetes自体はProgressive Deliveryの能力を持たない。CDツール (例:Argo Rollouts) のProgressive Delivery機能を採用する。
ロールバック¶
デプロイ方法の採用状況 | 方法 | 推奨/非推奨 |
---|---|---|
DeploymentのRollingUpdate戦略を採用している場合 | 過去のリリースタグ (リビジョン) を再デプロイする。あるいはGitHubによるコミットのリバートを使用し、現在のコミットを打ち消すコミットを作成し、PRを作成する。 | 非推奨 |
CDツールのBGデプロイメントを採用している場合 | 削除せずに残してある現環境に再ルーティングする。手順は、CDツールによる。 | 推奨 |
CDツールのカナリアリリースを採用している場合 | 現環境へのルーティングの重みづけを100%にする。手順は、CDツールによる。 | 推奨 |
CDツールのProgressive Deliveryを採用している場合 | 削除せずに残してある現環境に再ルーティングする。手順はCDツールによる。 | 推奨 |
09-03. 事後処理¶
デプロイの通知¶
▼ Kubernetesを使用する場合¶
Kubernetesには通知能力がなく、手動で知らせる必要がある。
▼ Kubernetes以外を使用する場合¶
CDツールの通知機能 (例:ArgoCD Notification) を使用して、CDパイプラインの結果が通知されるようにする。
通知があることと品質を高めることは直接的には関係ないが、開発者の作業効率が上がるため、間接的に品質を高めることにつながる。