AWS EKS：アーキテクチャとモニタリング

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/2394896f-410f-0ac6-c7d7-2236d1f0bb84.png)

#はじめに
AWS Elastic Container Service for Kubernetes（EKS）は、重くて変動するワークロードを実行しているノードの大規模なクラスターに最適なマネージドKubernetesサービスです。 AWSでアカウントのアクセス許可が機能する方法のため、EKSのアーキテクチャは多少複雑であり、モニタリング戦略にいくつかの小さな違いが生じます。 ただし、言えることは全体的に見て、あなたが知っているKubernetesと同じものです。

#Kubernetesクラスターアーキテクチャ
Kubernetesは、[コントロールプレーンとデータプレーン](https://kubernetes.io/docs/concepts/overview/components/)で構成されています。コントロールプレーンには、Kubernetesがノードを管理するために必要なサービス、主にkube-apiserver（特に、[kubectl](https://kubernetes.io/docs/reference/kubectl/overview/)によって使用される）、controller-manager、およびkube-schedulerが含まれます。これらは通常、クラスター内の1つ以上のマスターノードで実行されます。マスターノードはフォールトトレランスのために複製できますが、コントロールプレーンコンポーネントはKubernetes自体の中にポッドとしてデプロイすることもできます。これは、たとえばminikubeで開発するときに表示されます。

データプレーンは、すべて[kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/)サービスと[kube-proxy](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/)を実行しているサーバーノードまたはVMノードで構成されており、Kubernetes構成の変更に対応できます。 Kubeletは、コンテナの実行を駆動する[ポッド](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#pod-v1-core)APIと[ノード](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#node-v1-core)APIも管理し、KubernetesのすべてのAPIと同様に、ツールや拡張機能の基盤として表示および利用できます。

クラスタ内のすべてのノードは[etcd](https://kubernetes.io/docs/concepts/overview/components/#etcd)を実行して、クラスタの状態をクラスタ全体で調整できるようにします。クラスターの状態を変更するリクエストがkube-apiserverに対して行われると、kube-apiserverはetcd内のオブジェクトを更新し、それがクラスター全体に伝播されます。次に、Kubeletはこれらの変更を各ノードに実装します。

マスターノードがダウンすると、ノードのグループは事実上クラスターではなくなりますが、アプリケーションは通常、マスターがなくても機能し続けます。ノードを再起動すると、マスターがバックアップされるまでDNSルーティングで問題が発生する可能性がありますが、通常、短時間の停止は大きな影響はありません。

#EKSのコントロールプレーン
EKSはマネージドKubernetesサービスであり、アカウントとAWSの間で2つのプレーンの責任を分担します。 これはKubernetesとすべて同じ可動部分で構成されているため、kubectlとapi-serverを介してクラスターを完全に制御できますが、マスターノードとコントロールプレーンはAWSによって独自のアカウントで管理および維持されます。 さらに、クラウドコントローラーマネージャーデーモンが実行され、AWSリソースとの相互作用を処理します。 ローカルkubectlがkube-apiserverに接続するための設定の詳細が提供され、AWSアカウントには、クラスター内のノードとして機能するアカウント上のインスタンスにアクセスするためのアクセス許可が付与されます。

これを設定するには、いくつかの要件があります。

- Kubernetesマスターノードには、各ノードのkubeletのAPIへのフルアクセスが必要です。 各kubeletは、見返りにマスターにアクセスする必要があります。
- Cloud-controller-managerはあなたのアカウントにアクセスする必要があります。
- etcdは、両方のアカウントのノード間で同期できる必要があります。 そして
- ノードとポッドは、相互に通信するために、静的なDNSで検出可能なIPアドレスを維持できる必要があります。

EKSを設定すると、AWSアカウントからノードへのアクセスを許可するために使用できるIAMロールを提供するように求められます。また、kubernetes固有のポートへのアクセスを許可するセキュリティグループも求められます。ポッドとノードがお互いを見つけるために使用できる静的（内部）アドレスを提供するために使用されるVPC（仮想プライベートクラウド）を求められます。

VPCアドレス空間のサイズにより、実行できるポッドの数が制限されるため、十分に広い範囲を選択してください。たとえば、/ 24サブネットは254個のアドレスしか提供せず、クラスター内の各ノードにもアドレスが必要です。これにより、ポッドで使用できる合計が減少します。また、ネットワークインターフェースの数と、それぞれが維持できるIPの数に基づいて、1つのノードに割り当てることができるIPの数にも制限があります。

EKSクラスターのスピンアップと管理のプロセスを簡素化するために、AWSはeksctlと呼ばれる小さなコマンドラインユーティリティを提供します。このユーティリティは、awscliによって保存された認証情報を使用して、ユーザーに代わってクラスターノードとロールを作成できます。クラスタを制御するために必要な資格情報がkubectlに自動的にエクスポートされます。

#EKSのサービス
サービスを起動すると、Kubernetesのcloud-controller-managerは、サービスの種類に応じて起動する適切なAWSリソースを選択します。 EKSでは、NodePortまたはClusterIPサービスは通常のKubernetesセットアップと同じように機能しますが、LoadBalancerまたはIngressサービスタイプは両方ともAWSリソースの作成をトリガーします。

- デフォルトでは、[LoadBalancerサービスタイプ](https://docs.aws.amazon.com/eks/latest/userguide/load-balancing.html)は、AWSによって作成された元のロードバランサーであるClassic Elastic LoadBalancerを作成します。このタイプのロードバランサーは、実際には、ラウンドロビンアプローチを使用して定義されたエンドポイントにリクエストをルーティングする小さなインスタンスで構成されています。

- または、プロトコル、送信元IP /ポート、宛先IP /ポート、およびTCPシーケンス番号に基づいてハッシュマップを作成することにより、要求をさまざまなエンドポイントにルーティングするネットワークロードバランサーを使用できます。 1つの- TCP接続のすべてのトラフィックは、同じエンドポイントに転送されます。サービスにアノテーションを設定することで、クラシックロードバランサーの代わりにネットワークロードバランサーを使用するようにKubernetesに指示できます：service.beta.kubernetes.io/aws-load-balancer-type：nlb‍
- Ingressサービスタイプは、要求された宛先URL（レイヤー7ルーティング）に基づいてトラフィックを異なるポッドに分散し、複数の宛先のトラフィックを同じIPアドレスに送信できるようにします。サービスは、URLに基​​づいて異なるポッドセットにトラフィックを送信します。実際に使用されました。 EKSの場合、このタイプのサービスは、AWS独自のレイヤー7ルーティングLBであるApplication LoadBalancerによって処理されます。

[このページ](https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/how-elastic-load-balancing-works.html)では、AWSのさまざまなロードバランサーによってトラフィックがどのようにルーティングされるかについて詳しく説明します。

#EKSのボリューム
Kubernetesは多数のストレージタイプをサポートしていますが、その中で最も単純なのは[emptyDir](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir)です。これは、ポッド内でのコンテナの再起動に関係なく、接続されているポッドの存続期間中持続するボリュームです。 デフォルトでは、emptyDirボリュームはノードのディスクスペースに作成されます。EKSでは、ノードはEC2インスタンスであるため、emptyDirに使用される実際のストレージタイプは（通常）Elastic BlockStorageボリュームです。 EC2は、[インスタンスストア](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html)と呼ばれる一時的なローカルストレージも提供しますが、一時的な性質のため、これはデフォルトではなくなりました。

Kubernetesは、[EBSボリューム](https://kubernetes.io/docs/concepts/storage/volumes/#awselasticblockstore)をストレージとして直接使用することもサポートしているため、ポッド間で永続するボリュームを作成できます。 オプションで、ポッドがアクセスする必要のあるデータをEBSボリュームにプリロードすることもできます。 EBSボリュームは、一度に1つのEC2インスタンスにのみマウントできます。これは、ポッドがアクセスするために必要です。

#EKSの監視
通常のKubernetesセットアップでは、監視する最も重要なことの1つはマスターノードです。これがないと、Kubernetesクラスターはクラスターでなくなるためです。 EKSでは、マスターノードとほとんどのコントロールプレーンはAWSによって管理されており、それらは手の届かないところにあります。クラスター全体に関するメトリックを取得できる場合がありますが、実際のマスターノードは取得できません。

Kubernetesの仕事の1つはノードとコンテナの停止に対処することであるため、独自のモニタリング設定の一部としてアクセスできるモニタリングが組み込まれています。 Kubeletは、ノード、ポッド、およびコンテナー（[cAdvisorが組み込まれている](https://kubernetes.io/docs/tasks/debug-application-cluster/resource-usage-monitoring/#resource-metrics-pipeline)）の状態に関するデータを収集して、コンテナーに問題があり、再起動が必要な場合に通知します。メトリックは、[メトリックサーバー](https://kubernetes.io/docs/tasks/debug-application-cluster/resource-metrics-pipeline/#metrics-server)から利用できます。メトリックサーバーは、短期ストレージを備えた非常に軽量なサービスであるため、リクエストに応じてKubernetesリソースの現在の状態をキャプチャするために使用されます。メトリックを時系列としてキャプチャし、それらをグラフとして使用するには、別のツールが必要です。

AWSは、CloudWatchに保存されているEC2インスタンスのモニタリングをすでに提供しています。また、[Container Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights.html)と呼ばれるサービスも提供します。これは、EKSクラスターでDaemonSetとして実行できるエージェントであり、[ノード、ポッド、コンテナー](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-metrics-EKS.html)に関するメトリクスを取得し、カスタムメトリクスとしてCloudWatchに送り返します。

ただし、CloudWatchではカスタムメトリクスのコストが比較的高くなります。アラートが追加される前のメトリクスあたり$ 0.30です。より一般的なアプローチは、Prometheusを使用してクラスターをモニタリングすることです。 KubernetesはProm形式のメトリクスをネイティブにサポートしているため、[簡単に起動して実行](https://www.metricfire.com/prometheus-tutorials/how-to-deploy-prometheus-on-kubernetes)できます。オプションで、Kubernetesパッケージマネージャーである[Helm](https://helm.sh/docs/using_helm/#quickstart-guide)をセットアップできます。これにより、Prometheusだけでなく、Alert Manager、PushGateway、Nodeやノンエクスポーターなどのすべてのサポートサービスがインストールおよび構成されます。 

AWS CloudWatchはAPIアクセスメトリクスを提供するため、CloudWatchからメトリクスを取得してPrometheusで利用できるようにするPrometheusCloudWatchエクスポーターの形で中間点があります。 Helmを使用して、または[github](https://github.com/helm/charts/blob/master/stable/prometheus/Chart.yaml)から直接インストールできます。

Prometheusでは、取得するメトリックデータをどこに保持するかを選択できます。 Prometheusポッドが意味をなす限り存続するemptyDirタイプのストレージボリューム（上記）。ただし、復元力は提供されません。個別のEBSボリュームは、ノードとコンテナーとは別に存在するため安全なオプションであり、必要に応じてサイズを増やすこともできます。ただし、最小サイズがあるため、そのすべてのストレージが必要ない場合は、無駄になる可能性があります。リモートストレージは復元力を提供し、アラートとダッシュボードをクラスターの外部でも作成できるようにする場合があります（たとえば、MetricFireのHosted Prometheusサービス）。

EKSは、大規模なクロスAZ展開に最適なサービスであり、それがKubernetesが最も得意とするサービスです。ただし、不要な高価なEC2インスタンスにお金をかけるのは非常に簡単なので、モニタリングは依然として不可欠です。クラスターの容量がリソース消費量と一致していることを確認することは非常に重要であり、適切な監視はそれを確実に達成するのに役立ちます。

ベストプラクティスの監視と発生している問題について詳しく知りたい方はPrometheusas-a-serviceとGraphiteas-a-serviceの両方を提供する[MetricFire](https://www.metricfire.com/japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=AWS%20EKS%3A%20Architecture%20and%20Monitoring)の[デモを予約](https://www.metricfire.com/demo-japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=AWS%20EKS%3A%20Architecture%20and%20Monitoring)して、自分に合った監視ソリューションについて直接お問い合わせいただくこともできます。