Kubernetes 入門

複数ホスト間でもコンテナな環境を統合的に管理することができるKubernetesについて、以下の構成でまとめました。

  • アーキテクチャ

  • リソース種類

  • マニフェストの設定

  • kubectlの使用方法

  • トラブルシューティング

  • 監視(Prometheus+Grafana)

  • EKS固有

Architecture

Components

大きく以下のコンポーネントで構成

  • Control Plane

    • kube-apiserver : Kubernetes APIを受けるAPI Server

    • etcd : 全クラスターのデータを保存する一貫性と高可用性を備えたKVS

    • kube-scheduler : 新たに作成されて、未割り当て状態のノードを監視し、それらをkube-apiserverにリクエストを送ってスケジューリング

    • kube-controller-manager : プロセス制御。Node controller, Replication controller, Endpoints controller, Service Account & Token controllersを含む

    • cloud-controller-manager : クラウド固有の制御ロジックを埋め込み、クラウドプロバイダーAPIとクラスターを関連付け

  • Node

    • kubelet : Pod上でコンテナの起動や停止を管理

    • kube-proxy : Serviceリソースが作られた際にClusteIPやNodePort宛のトラフィックがPodに転送

    • Container Runtime : コンテナを稼働させるソフトウェア。Docker, containerd, CRI-O等

各コンポーネント詳細については、Kubernetes Components を参照

Diagram

Kubernetesのアーキテクチャ

(Reference) Kubernetes Components

Resources

Overview

リソースは大きく以下の5種類。詳細はConceptsを参照。

  • Workloads : クラスター上にコンテナを起動させるのに利用するリソース

    • Pod

    • ReplicaSet

    • Deployment

    • StatefulSet

    • Job

    • CronJob

  • Discovery & LB : クラスター上のコンテナに対するエンドポイントの提供やラベルに一致するコンテナのディスカバリーに利用されるリソース

    • Service : L4ロードバランシング

      • ClusterIP

      • NodePort

      • LoadBalancer

      • Headless

      • ExternalName

    • Ingress : L7ロードバランシング

  • Config & Storage : コンテナに対して設定ファイル、パスワードなどの機密情報などをインジェクトしたり、永続化ボリュームを提供したりするためのリソース

    • Secret

    • ConfigMap

    • PersistentVolumeClaim

  • Cluster : セキュリティ周りの設定やクォータの設定等、クラスターの挙動を制御するリソース

    • Node

    • NameSpace

    • PersistentVolume

    • ResourceQuota

    • ServiceAccount

    • Role

    • ClusterRole

    • RoleBinding

    • ClusterRoleBinding

    • NetworkPolicy

  • Metadata : クラスター上にコンテナを起動させるのに利用するリソース

    • LimitRange

    • HorizontalPodAutoscaler

    • PodDisruptionBudget

    • CustomResourceDefinition

(参考) Kubernetes完全ガイド

Example

Workloads

PodがWorkloadsリソースの最小単位となります。Podのマニフェストファイルの例は以下のようになります。

それに対してReplicaSetによりPodのレプリカが作成され、指定した数のPodを維持し続けるようにします。 spec.template,spec.containersでPod定義を行います。

そして、Deploymentが複数のReplicaSetを管理することで、ローリングアップデートやロールバック等を実現します。 spec以下でReplicaSetの定義を行い、spec.template.spec.containers以下でPod定義を行います。

ReplicaSetで起動したインスタンスに対してリクエストを割り振るには、Serviceリソースでロードバランサーの作成を行い、こちらのエンドポイントに対してアクセスすることで可能です。

実際にEKSでKubernetesのクラスターの作成を行い、Auto Scalingで起動したインスタンスをNLBでリクエストを受けるような構成の組み方は以下を参照ください。

EKSを利用してKubernetesでSpring MVCをデプロイ(NLB + Auto Scaling)

Serviceリソース、Secretリソース、Deploymentリソースを使用します。マニフェストファイルのみの概要を説明すると大きく以下の3つに別れます。

  1. NLBの設定

  2. 機密情報の受け渡し設定

  3. コンテナ設定

NLBの設定のマニフェストファイルについては以下のようになります。

  • service-nlb.yaml

機密情報の受け渡し設定のためのマニフェストファイルについては以下のようになります。YAMLファイルとして作成する場合は、Pod上から呼び出す名前の変数名に対してBase64でエンコーディングした値を設定することがポイントとなります。この例では、サンプルのエンドポイントに対してBase64でエンコードしたものを記載していますが、実際にはデコードはかなり容易なため管理には注意ください。

  • secret-mywebsite.yaml

PodがWorkloadsリソースの最小単位となります。それに対してReplicaSetによりPodのレプリカが作成され、指定した数のPodを維持し続けるようにします。そして、Deploymentが複数のReplicaSetを管理することで、ローリングアップデートやロールバック等を実現します。

Pod定義部分のenv以下でアプリケーションから読み込む環境変数名と先ほどSecretで指定した変数名と関連付けます。Secretリソースの機能を使用せずに直接値を指定する場合は、valueFrom:の代わりにvalue:で目的の値を指定します。

  • deployment-mywebiste.yaml

Kind

YAMLファイル中のkindで指定するオブジェクトの種類一覧

  • Binding

  • ComponentStatus

  • ConfigMap

  • Endpoints

  • Event

  • LimitRange

  • Namespace

  • Node

  • PersistentVolume

  • Pod

  • PodTemplate

  • ResourceQuota

  • Secret

  • ServiceAccount

  • Service

  • APIService

  • ControllerRevision

  • DaemonSet

  • Deployment

  • ReplicaSet

  • StatefulSet

  • TokenReview

  • SubjectAccessReview

  • CronJob

  • Job

  • Lease

  • ENIConfig

  • Event

  • DaemonSet

  • Deployment

  • Ingress

  • NetworkPolicy

  • PodSecurityPolicy

  • ReplicaSet

  • Ingress

  • NetworkPolicy

  • RuntimeClass

  • PodDisruptionBudget

  • PodSecurityPolicy

  • ClusterRoleBinding

  • ClusterRole

  • RoleBinding

  • Role

  • PriorityClass

  • CSIDriver

  • CSINode

  • StorageClass

  • VolumeAttachment

kubectl api-resources

kubectlからAPIを通して操作できるKubernetesのリソース一覧 (kubectl Version: 1.18.2)

KubernetesのapiVersion

マニフェスト中のapiVersionは、[APIGROUP]/<[APIVERSION]の形式で記載します。[APIGROUP]はkubectl api-resourcesコマンドの結果で各種リソースがどのAPIグループに対応するか確認できます。APIグループが空欄の場合はコアグループに属し、[APIVERSION]のみの形式となります。

(参考) Kubernetesの apiVersion に何を書けばいいか

kubectl

Use case

ローカルからコンテナで稼働しているサービスにアクセス

ローカルマシンのポートからDeployment,Service,Podへポートフォワード。kubectl proxy はローカルマシンのポートとAPIサーバーのポートをポートフォワードするためのもの。

シェルを取得

クラスターの切り替え

コンテキストに登録されているクラスター一覧の取得

現在のコンテキストを確認

コンテキストの切り替え

Others

  • 全namespaceの詳細を把握

-Aで全namespaceの情報、-o wideオプションでより詳細に情報表示 

  • Podのログ確認

コンテナから標準出力された内容を確認できます。

  • 直近1時間のイベント確認

  • リソースの詳細表示

以下の形式でリソースの詳細を確認できます。例えば、Podの場合、kubectl describe pods deployment-mywebsite-68b6fbcd95-bvjr9コマンドのように実行することでイベントを含めた詳細情報を確認できます。

Get Started

Reference

Cheetsheet

Troubleshooting

  • 共通

    • 以下のコマンドの結果

      • Podのリスト取得

        • kubectl get pods -A -o wide

      • 全Pod情報の詳細取得

        • kubectl describe pods -A

      • 全リソース情報取得

        • kubectl get "$(kubectl api-resources --namespaced=true --verbs=list -o name | tr "\n" "," | sed -e 's/,$//')" -A

      • ワーカーノードのリスト取得

        • kubectl get nodes -o wide

      • 全ワーカーノード情報の詳細取得

        • kubectl describe nodes

  • kubectlの接続性の調査 : デバッグレベルを上げてHTTPレイヤーのレベルで確認

    • kubectl get pods --v=9

  • ワーカーノードの接続性の調査

    • kubeletログ

      • sudo journalctl -u kubelet > kubelet.log

    • Dockerログ

      • journalctl -u docker > docker.log

    • /var/log/messages

  • Amazon VPC CNI PluginのL-IPAMDの動作の調査

    • CNI Log Collection Toolより生成した/var/log/aws-routed-eni/aws-cni-support.tar.gz

    • kubeletログ

      • sudo journalctl -u kubelet > kubelet.log

  • RBAC認証テーブルの調査 : IAMユーザーとKubernetesのRBACの関連付けを管理 

    • kubectlコマンドの実行に失敗するマシンにて以下のコマンドの結果

      • aws sts get-caller-identity

    • 管理者IAMエンティティを使用して以下のコマンドの結果

      • kubectl describe configmap -n kube-system aws-auth

  • Podの調査

    • Pod のログ

      • kubectl logs <Pod name>

    • 終了した Pod のログ

      • kubectl logs <Pod name> -p

  • (EKS) Control Planeのログ

    • Kubernetes API server component logs (api)

    • Audit (audit)

    • Authenticator (authenticator)

    • Controller manager (controllerManager)

    • Scheduler (scheduler)

  • その他確認事項 

    • マニフェストYAMLファイル

    • Helmチャート

(参照) Amazon EKS control plane logging

Podが起動しない

  • コンテナログ

    • アプリケーション側に問題がある場合

    • アプリケーションから標準出力したログ

    • kubectl logs コマンド

  • Kubernetesの設定やリソース設定に問題がある場合

    • kubectl describe コマンド

  • コンテナのシェル上で確認

    • 起動したアプリケーションが停止することによるPodの実行停止を避けるために、アプリケーションのENTRYPOINTを上書きして一時的にコンテナを立ち上げ

    • kubectl run --image=nginx:1.12 --restart=Never --rm -it sample-debug --command -- /bin/sh

ログ収集 

ワーカーノード上で以下を実行

一応、CNI ログ収集ツールというのもあるが、基本的にEKS Log Collectorを使用

設計

リソース設計

eksctlコマンドでは、Control Planeに加えて、オプション次第でワーカーノードやVPC環境の作成を行います。

VPC環境は別途CloudFormationやTerraformで管理する場合やマニュアルでカスタマイズした環境を使用する場合にはkubectlとは別に作成するといった対応が可能です。 ワーカーノードを別個管理する場合、--without-nodegroupオプションを指定してノードグループを作成せずにEKSクラスターを作成し、eks create nodegroupコマンドでノードグループの作成を行います。

「eksctl」コマンドの使い方 (応用編)

マニフェスト設計

マニフェストファイルは1つのファイルに複数のリソースを記述することもできます。その場合、上から順に実行されます。途中で文法エラーなどの問題が発生した場合にはそれ以降のリソースは適用されません。

kubectl apply -f ./ -R コマンドとすることで複数のマニフェストファイルを一つのコマンドで適用することもできます。その場合、ファイル名の順に適用されるため、インデックス番号等をつけておくことで順番制御できます。  1つのマニフェストファイルでエラーが発生しても他のマニフェストファイルは実行されます。

リソース間の制御や厳密な実行順序制御をする必要がある場合は、複数のリソースを一つのマニフェストファイルに分けていただき、設定ファイルやパスワードなどConfigMapやSecretリソースなど共通で利用するものはマニフェストファイルを分割するといった形で対応します。 1つのディレクトリで一括管理することや、サブディレクトリごとに管理、もしくはマイクロサービス毎に管理するなど管理体制に合わせて管理方法をわけることもできます。

モニタリング

Container Insightsの導入

用意されたコマンド1つで、CloudWatchエージェントとFluentdをDaemonSetによってPodをサイドカーとして配置することで導入します。

メトリクスとログをCloudWatchに送信できるようにするために、EC2にアタッチされているIAMロールを確認し、こちらにCloudWatchAgentServerPolicyのポリシーをアタッチします。例えば、eksctl-mywebsite-cluster-nodegrou-NodeInstanceRole-XXXXXXXXXXXXのような名前のIAMロールになります。

mywebsite-clusterというクラスター名で、us-west-2のリージョンを使用している場合は、以下のように実行することで導入準備完了です。これはmetric_name{"tag"="value"[,...]} valueのようなPrometheusの形式となります。

Amazon EKS での Container Insights のクイックスタートセットアップ

Control PlaneのメトリクスをPrometheusでグラフ表示

APIサーバーに対して、/metricsのパスにHTTP APIでメトリクスの生データを参照することができます。

Helmを使用するため、インストールしていない場合、Amazon EKS での Helm の使用等参照して利用できるようにしておきます。

MacOSの場合、Homebrewでインストールできます。

brew install コマンド実行後、バージョン確認できます。 

Helmのバージョン3には自動でstableレポジトリがインストールされないため、stableレポジトリを追加します。 (参照) (Optional) Set Up Sample Containerized Workloads for Prometheus Metric Testing, Quickstart Guide

Prometheusをインストールします。

Deploymentをポートフォワーディングします。

Podをポートフォワーディングすることでも問題ありません。

http://localhost:9090 にアクセスすることで、Prometheusの画面を見ることができます。

"- insert metric at cursor -"から対象のメトリクスを選択して、"Execute"を選択します。すると、Consoleタブ上に各要素のログが出力されます。 Graphタブに切り替えることでグラフとして見ることができます。

(参照)Prometheus を使用したプレーンメトリクスのコントロール

Prometheus + Grafanaの連携

ユーザー名はAdmin、パスワードは以下のコマンドの出力

アクセス先のELBが出力されます。

Kubernetes cluster monitoring (via Prometheus)のダッシュボードを表示できるようにします。

  1. PrometheusからのデータをGrafanaに取り込むために、画面右側の"+"マークを選択

  2. "Import"を選択

  3. Grafana.com Dashboardに"9135"を入力して"Load"

  4. Folderとして"General"、prometheusの項目に"Prometheus"を選択して"Import"を選択。

同様にして、9144を入れることでKubernetes pod monitoringをインストールできます。  7279を入れることでCoreDNSのダッシュボードをインポートできます。

Container InsightsによるPrometheusメトリクスのモニタリング(Beta版)

こちらはBeta版の機能となりますので、利用の際には十分に理解の上で実施ください。

EC2にアタッチされている、例えば、eksctl-mywebsite-cluster-nodegrou-NodeInstanceRole-XXXXXXXXXXXXのような名前のIAMロールを確認し、CloudWatchAgentServerPolicyのポリシーをアタッチしていなければアタッチする。

以下を実行するのみ。

以下のようにPodが稼働していることを確認できます。

CloudWatchエージェントで他のワークロードからメトリクスを取得するために、prometheus-eks.yamlをダウンロードしてきて、追加で取得するメトリクスの設定を記載します。

logs.metrics_collected.prometheus.emf_processor.metric_declaration[]以下に以下を追記します。

元からあったリソースは削除して編集後の内容を適用します。

JMX Exporter等を利用することで、Container InsightsがJVMやTomcatなどからもPrometheusのメトリクスを取得できるようになります。

JMX Exporterのエージェントファイルをダウンロードしてきます。

JAVA_OPTSの環境変数の設定を行います。

  • setenv.sh

JMX Exporterの設定ファイルを作成します。ここでは、ドキュメントの例をそのまま使用していますが、詳細はJMX ExporterのREADMEを参照

  • config.yaml

次にwarファイルをTomcatで稼働させていたWebアプリケーションのDockerfileの編集を行います。 

元のDockerfileは以下の内容でした。

こちらに以下の4行を追加します。

変更後のDockerfileは以下の内容になります。

上記内容からDockerイメージを作成して、Kubernetesのクラスターにデプロイします。

すると、以下のようにPodに対して9404番ポートにアクセスすることで、Prometheus形式のメトリクスが取得できるようになっていることを確認できます。

この9494番ポートはprometheus-configのConfigMapで定義されています。

また、Podの定義にPrometheusのサービスディスカバリー用のアノテーションを追加します。

  • prometheus.io/scrape

    • Podをスクレーピングの対象にするか

  • prometheus.io/port

    • Prometheusメトリクスを取得できるポート

  • prometheus.io/path

    • Prometheusメトリクスが/metricsのパスで取得できない場合に取得

例えば、Deploymentリソースを使用している場合、以下のように定義します。

GrafanaにKubernetes JMX Dashboardを追加します。前述の要領で11131を追加して読み込むことで監視可能です。 

EKS

ConfigMap

  • aws-authはkube-systemのnamespaceに属するConfigMapでIAMエンティティをRBACを関連付け。EKSクラスターにアクセス可能なIAMユーザーやIAMロールの追加に使用 クラスターのユーザーまたは IAM ロールの管理

    • IAMユーザーやIAMロールにsystem:mastersのグループに追加することで管理者権限を付与

    • ConfigMap中で以下に対応付けを記載します。

      • IAMユーザー : mapUsers

      • IAMロール : mapRoles

DaemonSet

  • aws-nodeはkube-systemのnamespaceに属し、Podを起動し、Amazon VPC CNI PluginというNetworking Pluginが呼び出される。

    • Amazon VPC CNI Pluginは以下の2つで構成

      • CNI Plugin

        • ホストネットワークの接続 (例: インターフェイスと仮想イーサネットペアの設定) とPod名前空間への正しいインターフェイスの関連付け

      • L-IPAMD (Local IP Address Managed Daemon)

        • インスタンスへの Elastic Network Interface の接続

        • Elastic Network Interface へのセカンダリ IP アドレスの割り当て

        • スケジュールされた際に Kubernetes ポッドに割り当てるために各ノードにおける IP アドレスの「ウォームプール」の維持

CNI

  • コンテナにおけるネットワークインターフェイスを構成するプラグイン

  • 種類

    • Calico : レイヤー3の仮想ネットワークを構成可能

    • Cilium : 負荷分散、プロトコルのフィルタリングが可能

    • CNI-Genie : 複数NICに異なるプラグインを割り当て、同時利用が可能

    • Contiv : ポリシーベースの管理、ACL、QoS

    • Infoblox : 複数のrktホストに対応

    • Linen : 仮想スイッチを作成し、VXLANを構成可能

    • Multus : 複数のCNIプラグインのグループ化が可能

    • Nuage : オーバーレイネットワークを提供。Mesos, Kubernetes, OpenShiftに対応

    • Romana : フラットなL2,L3に対応

    • Silk : L3オーバーレイネットワークを提供

    • Weave : オーバーレイネットワークを提供

(参考) Docker実践ガイド 第2版

Kubernetes Dashboard

Kubernetes Dashboardではメトリクスサーバーを使用するためデプロイ。

Dashboardのデプロイ

Dashboardへのユーザーのアクセス制限があるため、eks-admin サービスアカウントおよびクラスターロールバインディングを作成して、管理者レベルのアクセス権限による接続をします。

  • eks-admin-service-account.yaml

認証のためのトークンを取得します。

プロキシでローカルからブラウザでアクセスできるようにします。

以下のURLにアクセスします。

  • http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#!/login

認証方法でKubeconfigとTokenが選択できますので、Tokenを選択肢、先程取得したトークンを貼り付けて、サインインします。

(参考) チュートリアル: Kubernetes ダッシュボード (ウェブ UI) のデプロイ

Addon

Operation

補完

補完システムをアクティベートする。

補完を有効にする。

予め、補完システムをアクティベートしておかないと以下のエラーになる。

GitHub

Best Practice

Architecture

Get Started

Last updated