Amazon Web Services ブログ

Amazon EKS クラスターエンドポイントへのプライベート接続とワーカノードVPC外からのDNS解決方法

本投稿は AWS のシニアコンテナスペシャリストソリューションアーキテクトである Jeremy Cowan による寄稿です。

Amazon EKS クラスターを作成した時点では、標準ではKubernetes クラスターのエンドポイントはパブリックな設定になっています。エンドポイントにはインターネット経由でアクセスし、Identity and Access Management (IAM) とKubernetes role-based access control (RBCA) のポリシーによるアクセス制御を行います。
ゆくゆくはあなたも Kubernetes クラスターのプライベートエンドポイントを設定する必要が出てくるかもしれません。Kubernetes クラスターのエンドポイントをパブリックからプラベートに変更すると、インターネットをはじめとしたパブリックな経路からのアクセスは完全に無効になります。

実際に、プライベートなアクセスのみを許可するように設定されたクラスタは、以下のネットワークからのみアクセスできます。

  • ワーカーノードが存在する VPC
  • その VPC とピアリングしているネットワーク
  • AWS Direct Connect (DX) または Virtual Private Network (VPN) を介して AWS に接続されているネットワーク

ただし、Kubernetes クラスターエンドポイントは、以下の理由からワーカーノードが存在する VPC からしか名前解決することができません。

  • エンドポイント用に作成された Amazon Route 53 プライベートホストゾーンは、ワーカーノード用 VPC にのみ関連付けられています。
  • プライベートホストゾーンは AWSが管理しているアカウントとは分けて作成されており、変更できません。

詳細については、プライベートホストゾーンの使用を参照してください。
この投稿では、ワーカーノードがあるVPCの外部からリクエストする場合に、Route 53 のインバウンド・アウトバウンドエンドポイントを使用してクラスターエンドポイントを名前解決する方法について説明します。

Route53 のインバウンドとアウトバウンド エンドポイント

Route 53 のインバウンドエンドポイントとアウトバウンドエンドポイントを使用すると、ハイブリッド DNS の設定を簡素化できます。AWS リソースに対する DNS クエリは Route 53 リゾルバーによって解決され、オンプレミスリソースに対する DNS クエリはオンプレミス DNS リゾルバーにフォワードされます。 これらの Route 53 エンドポイントを使用することで、EKS クラスターエンドポイントのように特定の VPC 内からのみ解決可能なエンドポイントの名前を解決することもできます。

次の図は、このソリューションの仕組みを示しています。

  • Route 53 インバウンドエンドポイントは各ワーカーノード用 VPC に作成され、外部サブネット/ CIDR 範囲からのインバウンド DNS リクエストを許可するセキュリティグループに関連付けられます。
  • Kubernetes クラスターエンドポイントへのリクエストがピアリングされたVPC から発信されている場合、それらのリクエストは Route 53 アウトバウンドエンドポイントを介してルーティングされる必要があります。
  • インバウンドエンドポイントと同様に、アウトバウンドエンドポイントは、ピアリングした VPC またはリージョン内の他の VPC からのインバウンドリクエストを許可するセキュリティグループに関連付けられています。
  • 転送ルールは各 Kubernetes クラスターエンドポイントに対して作成されます。 このルールは、アウトバウンドエンドポイントを介して、ワーカーノード用 VPC 内のインバウンドエンドポイントの IP アドレスにリクエストをルーティングします。そこで Route 53 によって解決されます。
  • Kubernetes クラスターエンドポイントに対する DNS クエリの結果がリクエスト元に返されます。

オンプレミス環境からのリクエストの場合はアウトバウンドエンドポイントを作成する必要はありません。 代わりに、Kubernetes クラスターエンドポイントへのリクエストをワーカーノード用 VPC 内の Route 53 インバウンドエンドポイントの IP アドレスに転送するための転送ルールを作成する必要があります。

 

ソリューションの概要

このソリューションは、以下の手順に従います。

  • ワーカーノード用 VPC にインバウンドエンドポイントを作成します。
  • ピアリングした VPC でアウトバウンドエンドポイントを作成します。
  • ワーカーノード用 VPC の Route 53 リゾルバーにリクエストを送信するアウトバウンドエンドポイント用の転送ルールを作成します。
  • 接続されたネットワークからのインバウンドトラフィックを許可する、セキュリティグループのルールを作成します。
  • (省略可能) Kubernetes クラスターエンドポイント用への転送ルールをオンプレミスの DNS に作成します。

前提条件

EKS ではクラスターエンドポイントのアクセスをパブリックからプライベートに変更するときに、各ワーカーノード用 VPC で DNS ホスト名と DNS 解決を有効にする必要があります。 この設定はこのソリューションだけでなく、Route 53 プライベートホストゾーンを使用するすべての場合にとっても前提条件です。
さらに、オンプレミスネットワークまたは VPC をワーカーノード用 VPC に接続する経路が必要です。 マルチ VPC 環境では、2つ以上の VPC 間にピアリング接続を作成し、それらのVPCのルートテーブルを更新することでこれを実現できます。 オンプレミス環境から DX または IPsec VPN を介して接続している場合は、ワーカーノード用 VPC へのルートが必要です。

 

インバウンドエンドポイントの設定

EKS クラスターをプロビジョニングすると、EKS はワーカーノード用 VPC 内の2つの異なるサブネットに、2つ以上のクロスアカウントの Elastic Network Interface (ENI) を自動的にプロビジョニングします。 これらのネットワークインタフェースは、kubectl execまたはkubectl proxyを使用する場合など、コントロールプレーンがワーカーノードとの接続をする必要がある場合に主に使用されます。 ただし、それらは Kubernetes API サーバーと通信するためにワーカーが使用することもできます。

EKS エンドポイントアクセスをプライベートに変更すると、EKS は Route 53 プライベートホストゾーンをワーカーノード用 VPC に関連付けます。 このプライベートホストゾーン内で、EKS はクラスターエンドポイントのリソースレコードを作成します。 これらのレコードは、クラスターをプロビジョニングしたときに VPC に作成された2つのクロスアカウントの Elastic Network Interface (ENI) の IP アドレスに対応しています。

これらのクロスアカウントの Elastic Network Interface (ENI) の IP アドレスが変わると、たとえば、EKS が異常なコントロールプレーンノードを置き換えた際にクラスターエンドポイントのリソースレコードが自動的に更新されます。 これにより、プライベートアクセスに切り替えたときにもワーカーノードがクラスターエンドポイントと通信し続けることができます。 パブリックアクセスを有効にしてプライベートアクセスを無効にするようにクラスターを更新すると、ワーカーノードはパブリック Kubernetes クラスターエンドポイントを使用するように戻ります。

ワーカーノード用 VPC に Route 53 インバウンドエンドポイントを作成することで、DNS クエリがワーカーノード用 VPC の VPC DNS リゾルバーに送信されます。 よってこのエンドポイントは、クラスターエンドポイントを解決できるようになりました。

ワーカーノード用 VPC にインバウンドエンドポイントを作成

  1. Route 53 コンソールで、インバウンドエンドポイント、インバウンドエンドポイントの作成の順に選択します。
  2. エンドポイント名に、<cluster_name> InboundEndpointなどの値を入力します。
  3. リージョン内の VPC の場合は、ワーカーノード用 VPC の VPC ID を選択します。
  4. このエンドポイントのセキュリティグループに、他のネットワークのクライアントまたはアプリケーションかこのエンドポイントへのアクセスを許可するセキュリティグループを選択します。 この記事の冒頭に示した Route 53 リゾルバーの図を、例として参照してください。
  5. IP アドレスセクションで、VPC のサブネットに対応するアベイラビリティーゾーンを選択します。
  6. IP アドレスで、自動的に選択された IP アドレスを使用します。を選択します。
  7. 2番目の IP アドレスに対して手順5と6を繰り返します。
  8. 送信を選択します。

または、次の AWS CLI コマンドを実行します。

export DATE=$(date +%s)
export INBOUND_RESOLVER_ID=$(aws route53resolver create-resolver-endpoint --name 
<name> --direction INBOUND --creator-request-id $DATE --security-group-ids <sgs> \
--ip-addresses SubnetId=<subnetId>,Ip=<IP address> SubnetId=<subnetId>,Ip=<IP address> \
| jq -r .ResolverEndpoint.Id)
aws route53resolver list-resolver-endpoint-ip-addresses --resolver-endpoint-id \
$INBOUND_RESOLVER_ID | jq .IpAddresses[].Ip

これにより、インバウンドエンドポイントに割り当てられている IP アドレスが出力されます。

インバウンドエンドポイントの作成が完了したら、コンソールからエンドポイントを選択して詳細を表示を選択します。 これにより、エンドポイントの設定概要がわかります。 転送ルールを設定するときに必要になるので、インバウンドエンドポイントに割り当てられた2つの IP アドレスを記録します。

 

ピアリングした VPC から接続する

アウトバウンドエンドポイントは、一連の規則に基づいて「ローカルに」解決できない DNS 要求を外部のリゾルバーに送信するために使用されます。

ピアリングした VPC から EKS クラスターに接続している場合は、その VPC でアウトバウンドエンドポイントと転送ルールを作成するか、別の VPC からアウトバウンドエンドポイントを公開します。 詳細については、「ネットワークへのアウトバウンド DNS クエリの転送」を参照ください。

アウトバウンドエンドポイントを作成

  1. Route 53 コンソールで、アウトバウンドエンドポイントアウトバウンドエンドポイントの作成の順に選択します。
  2. エンドポイント名に、<cluster_name> OutboundEnpoint などの値を入力します。
  3. リージョン内の VPC の場合、アウトバウンドエンドポイントを作成する VPC の VPC ID(ピアリングした VPC など)を選択します。
  4. このエンドポイントのセキュリティグループには、このVPCもしくは他のVPC ネットワークからクライアントおよびアプリケーションがこのエンドポイントにアクセスできるようにするセキュリティグループを選択します。 この記事の冒頭に示した Route 53 リゾルバーの図を、例として参照してください。
  5. IP アドレスセクションで、ピアリングした VPC のサブネットに対応するアベイラビリティーゾーンを選択します。
  6. IP アドレスで、自動的に選択された IP アドレスを使用します。を選択します。
  7. 2番目の IP アドレスに対して手順5と6を繰り返します。
  8. 送信を選択します。

または、次の AWS CLI コマンドを実行します。

export DATE=$(date +%s)
export OUTBOUND_RESOLVER_ID=$(aws route53resolver create-resolver-endpoint --name 
<name> --direction OUTBOUND --creator-request-id $DATE --security-group-ids <sgs> \
--ip-addresses SubnetId=<subnetId>,Ip=<IP address> SubnetId=<subnetId>,Ip=<Ip address> \
| jq -r .ResolverEndpoint.Id)
aws route53resolver list-resolver-endpoint-ip-addresses --resolver-endpoint-id \
$OUTBOUND_RESOLVER_ID | jq .IpAddresses[].Ip

これにより、アウトバウンドエンドポイントに割り当てられた IP アドレスが出力されます。

クラスターエンドポイントへの転送ルールを作成

転送ルールは、ローカルのリゾルバーで解決できない DNS リクエストを別の DNS リゾルバーに送信するために使用されます。 このソリューションが機能するためには、アウトバウンドエンドポイントを介して解決するように各クラスターエンドポイントの転送ルールを作成します。 詳細については、「ルールを作成または編集するときに指定する値」を参照してください。

  1. Route 53 コンソールで、ルールルールの作成の順に選択します。
  2. ルールに <cluster_name> Rule などの名前を付けます。
  3. ルールタイプ転送を選択します。
  4. ドメイン名に、EKS クラスターのクラスターエンドポイントの名前を入力します。
  5. このルールを使用する VPC に関しては、このルールを適用する必要があるすべての VPC を選択します。 クラスターエンドポイントにアクセスする必要がある VPC が複数ある場合は、それらを VPC のリストに含めます。
  6. アウトバウンドエンドポイントで、ワーカーノード用 VPC のインバウンドエンドポイントに DNS リクエストを送信するために使用するアウトバウンドエンドポイントを選択します。
  7. ターゲット IP アドレスセクションで、ドメイン名フィールドに入力した EKS エンドポイントに対応するインバウンドエンドポイントの IP アドレスを入力します。
  8. 送信を選択します。

または、次の AWS CLI コマンドを実行します。

export DATE=$(date +%s)
aws route53resolver create-resolver-rule --name <name> --rule-type FORWARD \
--creator-request-id $DATE --domain-name <cluster_endpoint> --target-ips \
Ip=<IP of inbound endpoint>,Port=53 --resolver-endpoint-id <Id of outbound endpoint>

 

クラスターエンドポイントへのアクセス

インバウンドエンドポイントとアウトバウンドエンドポイント、および DNS 転送ルールを作成したら、ピアリングした VPC からクラスターエンドポイントの名前を解決できるはずです。

$ dig 9FF86DB0668DC670F27F426024E7CDBD.sk1.us-east-1.eks.amazonaws.com 

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.68.rc1.58.amzn1 <<>> 9FF86DB0668DC670F27F426024E7CDBD.sk1.us-east-1.eks.amazonaws.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7168
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;9FF86DB0668DC670F27F426024E7CDBD.sk1.us-east-1.eks.amazonaws.com. IN A
;; ANSWER SECTION:
9FF86DB0668DC670F27F426024E7CDBD.sk1.us-east-1.eks.amazonaws.com. 60 IN A 192.168.109.77
9FF86DB0668DC670F27F426024E7CDBD.sk1.us-east-1.eks.amazonaws.com. 60 IN A 192.168.74.42
;; Query time: 12 msec
;; SERVER: 172.16.0.2#53(172.16.0.2)
;; WHEN: Mon Apr 8 22:39:05 2019
;; MSG SIZE rcvd: 114

クラスターエンドポイントにアクセスする前に、ピアリングした VPC の IP アドレス範囲を EKS コントロールプレーンセキュリティグループに追加する必要があります。 詳細については、チュートリアル:パブリックサブネットとプライベートサブネットを持つクラスター VPC を作成するには を参照してください。

EKS クラスターコントロールプレーンのセキュリティグループにルールを追加

  1. EC2 コンソールで、セキュリティグループを選択します。
  2. EKS クラスターのコントロールプレーンに関連付けられているセキュリティグループを見つけます。 eksctlを使用してクラスタをプロビジョニングした場合、セキュリティグループの名前は eksctl-<cluster_name>-cluster / ControlPlaneSecurityGroup になります。
  3. ピアリングした VPC の CIDR 範囲からのポート 443 の受信を許可するルールを追加します。
  4. 保存を選択します。

KUBECTL を実行

適切なセキュリティグループルールが設定されていれば、ピアリングした VPC 内のマシンからクラスターエンドポイントに対してkubectlコマンドを発行することが可能です。

$ kubectl get nodes
NAME                             STATUS    ROLES     AGE       VERSION
ip-192-168-18-187.ec2.internal   Ready     <none>    22d       v1.11.5
ip-192-168-61-233.ec2.internal   Ready     <none>    22d       v1.11.5

 

オンプレミス環境からの接続

オンプレミス環境から EKS クラスターを管理するには、オンプレミス DNS で転送ルールを構成して、DNS クエリをワーカーノード用 VPC のインバウンドエンドポイントに転送します。 以下に、BIND、dnsmasq、および Windows DNS でこれを行う方法について簡単にご紹介します。

BINDの場合

以下を BIND 設定ファイルに追加します。

zone "<cluster endpoint FQDN>" {
    type forward;
    forwarders { <インバウンドエンドポイントのIP 1>; <インバウンドエンドポイントのIP 2>; };
};

DNSMASQの場合

dnsmasq を使用している場合は、起動オプションに--server=/<クラスターエンドポイントのFQDN>/<インバウンドエンドポイントのIP> フラグを追加します。

WINDOWS DNSの場合

Windows DNS を使用している場合は、条件付きフォワーダを作成します。 DNS ドメインにはクラスターエンドポイントの FQDN を使用し、要求の転送先となるサーバーの IP アドレスにはインバウンドエンドポイントの IP を使用します。

クラスターコントロールプレーンのセキュリティグループにルールを追加

EKS クラスターコントロールプレーンのセキュリティグループにルールを追加”の追加の手順に従ってください。 今回は、ピアリングした VPCの代わりにオンプレミスネットワークの CIDR を使用します。

 

まとめ

EKS クラスターエンドポイントをプライベート専用に設定した場合、ワーカーノード用 VPC からのみ名前解決できます。 別の VPC またはオンプレミスネットワークからクラスターを管理するには、この記事でご説明したソリューションを使用してワーカーノード用 VPC 用のインバウンドリゾルバーを作成します。

このインバウンドエンドポイントは、DNS リゾルバーが AWS リソースのドメイン名を簡単に解決できるようにする機能です。 これには、EKS クラスターエンドポイントをプライベートにしたときに VPC に関連付けられるプライベートホストゾーンが含まれます。 詳細については、「VPC とネットワークの間における DNS クエリの解決」を参照してください。 このソリューションについてのフィードバックをお待ちしております。

翻訳はソリューションアーキテクト根本が担当しました。原文はこちらです。