はじめに
AWS re:Invent 2024 で Amazon EKS Hybrid Nodes が発表されました。これはオンプレミスにある皆様のマシンを、Amazon EKS が管理する AWS 上の Kubernetes コントロールプレーンに接続できるというハイブリッドの AWS サービスです。
EKS Hybrid Nodes は、オンプレミス環境と AWS の間に信頼できるプライベートなネットワーク接続が必要です。Kubernetes は、コンテナログの取得や kubectl exec など、コントロールプレーン側からノードへアクセスする場面があり、その際に AWS からオンプレミスへの通信が必要になるためです。一般的には、このような環境を用意するために、AWS Site-to-Site VPN または AWS Direct Connect を利用することになるでしょう。
しかし、個人的に Hybrid Nodes を少し試してみたい、というケースでは、そもそも手元にサーバーがなかったり、インターネットプロバイダーの制約により 「AWS とプライベート接続しているオンプレミスのサーバー」が気軽に用意できないこともあるかもしれません。
この記事は、そのような時に、Hybrid Nodes を AWS で完結する方法で試してみようというものです。
ご注意
本記事で紹介する AWS サービスを起動する際には、料金がかかります。builders.flash メールメンバー特典の、クラウドレシピ向けクレジットコードプレゼントの入手をお勧めします。
builders.flash メールメンバー登録
1. 注意点
3. 構成

4. 手順
4-1. オンプレミスを想定した VPC
まず、オンプレミスのネットワークを想定した VPC を作成します。ここで、Hybrid Nodes のネットワーク要件 を確認しましょう。
- 以下の IPv4 アドレス帯のいずれかであること
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- EKS クラスターのある VPC の CIDR、および Kubernetes の Service IPv4 CIDR と重複しないこと
EKS では Kubernetes の Service IPv4 CIDR を 設定できます が、デフォルトでは以下のいずれかになります。
- 10.100.0.0/16
- 172.20.0.0/16
今回は、これらの CIDR を外して設定します。一方、この VPC にはオンプレミスのサーバー役となる EC2 を起動するだけなので、 シンプルなネットワークをすることにします。以下は VPC のコンソール を利用した例です。
以下の値を入力しています。
- Name tag auto-generation: sandbox-hybrid-onpremise
- IPv4 CIDR block: 10.116.0.0/16
- Number of Availability Zones (AZs) : 1
- Number of public subnets : 1
- Number of private subnets : 0
- Customize subnet CIDR blocks : 10.116.0.0/16
- NAT gateways ($) : None
- VPC endpoints : None

使用する CIDR
上記の通り、VPC の CIDR として 10.116.0.0/16 を指定しています。今回は、この中から Pod 用に 10.116.128.0/17 を使用します。
後ほど、 Kubernetes の CNI として Cilium をインストールしますが、 Cilium にこの Pod 用 CIDR から IP を割り当ててもらうよう設定します。そのため、VPC の設定で、Pod 用の CIDR が利用されないよう、CIDR を予約 しておきましょう。

CIDR を指定
作成されたサブネットを選択し、図のようにサブネットの CIDR 予約画面へ移動して CIDR を指定します。


4-2. Amazon EKS クラスターのある VPC
同様に、クラウド側の VPC を作成します。この VPC では Amazon EKS のクラスターを運用します。そのため、一般的な Amazon EKS のベストプラクティスに則って、パブリックなサブネットとプライベートなサブネット、マルチ AZ 構成で VPC を作成することとします。
Name tag auto-generation : sandbox-hybrid-cloud
IPv4 CIDR block : 10.37.0.0/16
Number of Availability Zones (AZs) : 2
Number of public subnets : 2
Number of private subnets : 2
NAT gateways ($) : in 1 AZ
VPC endpoints : None

4-3. AWS とオンプレミスのルーティングを設定
クラウドとオンプレミスのルーティングを設定します。ルーティングについては こちらのドキュメント に記載があります。
AWS 側の VPC には、以下のオンプレミス側の CIDR へのルートが必要です。
オンプレミス側のノードの CIDR
オンプレミス側で起動する Pod の CIDR
オンプレミス側のノードは、今回の場合は sandbox-hybrid-onpremise VPC に割り振った CIDR (10.116.0.0/16) ですね。Pod の CIDR は前述の通り、10.116.128.0/17 とします。

VPC ピアリングの設定
ドキュメントの手順では、オンプレミスとルーティングするために AWS Direct Connect の Virtual Private Gateway などを設定 していますが、本手順ではオンプレミスネットワークを VPC で再現しているため、簡便化のため VPC ピアリングで AWS と オンプレミス (を模した VPC) を接続します。

ピアリング接続を作成
VPC のコンソールから Peering connections を選択し、「Create peering connection」からピアリング接続を作成しましょう。ここでは以下のように、これまでの手順で作成した二つの VPC を Requester と Accepter に設定します。
設定後、Approve すれば Peering connection の作成は完了です。

AWS 側のルーティングテーブルを設定
全てのサブネット (3 つ) のルートテーブルを編集して、AWS からオンプレミスへのルートを設定します。

オンプレミス側のルートテーブルを設定
次に、オンプレミス側のルーティングを設定するため、オンプレミスを表す VPC (sandbox-hybrid-onpremise) のサブネットにルートを設定します。ドキュメントの図 にあるように、オンプレミスでは AWS 側の VPC へルーティングするよう設定します。ここでは、sandbox-hybrid-cloud VPC に割り振った CIDR (10.37.0.0/16) ですね。
これで、Hybrid Nodes のネットワーク環境が構築できました。

4-4. Amazon EKS クラスターを作成
4-5. 必要な通信を許可する
4-6. オンプレミスで Kubernetes ノードを実行する
4-7. オンプレミスのノードに割り当てる IAM ロールを作成
EKS Hybrid Nodes では、オンプレミスのノードが Kubernetes コントロールプレーンに接続する際、IAM で認証します。オンプレミスのマシンに AWS の IAM 権限を付与するセキュアな方法として、AWS Systems Manager と IAM Roles Anywhere がありますが 、EKS Hybrid Nodes では どちらの方法も選択できます。この手順では、Systems Manager を利用します。
まずは、オンプレミスのマシンに割り当てる IAM ロールを作成します。ドキュメント によると、ハイブリッドノードに割り当てるロールには以下の権限が必要です。
EKS クラスターに対する読み取り権限
設定内容
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"eks:DescribeCluster"
],
"Resource": "*"
}
]
}
Systems Manager に登録されているマシンの読み取り権限と、登録解除の権限
設定内容
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ssm:DescribeInstanceInformation",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "ssm:DeregisterManagedInstance",
"Resource": "arn:aws:ssm:AWS_REGION:AWS_ACCOUNT_ID:managed-instance/*",
"Condition": {
"StringEquals": {
"ssm:resourceTag/TAG_KEY": "TAG_VALUE"
}
}
}
]
}
ARN の設定
TAG_KEY には EKSClusterARN を設定し、TAG_VALUE には作成したクラスターの ARN を入力します。本手順でクラスターを作成した場合は arn:aws:eks:ap-northeast-1:<ACCOUNT_ID>:cluster/sandbox-hybrid-eks となります。
二つの AWS マネージド IAM ポリシー
AmazonEC2ContainerRegistryPullOnly
AmazonSSMManagedInstanceCore
Trust Policy を設定
また、SSM でこの Role を Assume できるよう、以下の Trust Policy を設定します。
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"",
"Effect":"Allow",
"Principal":{
"Service":"ssm.amazonaws.com"
},
"Action":"sts:AssumeRole",
"Condition":{
"StringEquals":{
"aws:SourceAccount":"AWS_ACCOUNT_ID"
},
"ArnEquals":{
"aws:SourceArn":"arn:aws:ssm:AWS_REGION:AWS_ACCOUNT_ID:*"
}
}
}
]
}
IAM ロールを設定
オンプレミスマシンの IAM ロールから Amazon EKS のコントロールプレーンにアクセスできるようにする
4-8. オンプレミスのノードを EKS に接続する
これで、オンプレミスのノードを EKS のノードとして登録する準備ができました。ドキュメント記載の手順 にしたがって、マシンをノードとして初期化します。
nodeadm ツールのダウンロード
Hybrid Nodes でのノード管理は、nodeadm というツールをオンプレミスのマシンで実行することで行います。まず、このツールをダウンロードします。
$ ssh ubuntu@xx.xx.xx.xx
ubuntu@ip-10-116-0-10:~$ curl -OL 'https://hybrid-assets.eks.amazonaws.com/releases/latest/bin/linux/amd64/nodeadm'
ubuntu@ip-10-116-0-10:~$ chmod +x nodeadm
ノードとなるマシンに必要なソフトウェア類をインストール
Kubernetes のノードには、containerd などのコンテナ実行ランタイムやkubelet など、さまざまなソフトウェアが必要になります。nodeadm で、こうしたソフトウェアをインストールできます。
ubuntu@ip-10-116-0-10:~$ sudo ./nodeadm install 1.31 --credential-provider ssm
{"level":"info","ts":1738219344.2963061,"caller":"install/install.go:95","msg":"Creating package manager..."}
{"level":"info","ts":1738219344.2963915,"caller":"install/install.go:104","msg":"Validating Kubernetes version","kubernetes version":"1.31"}
{"level":"info","ts":1738219344.366482,"caller":"install/install.go:110","msg":"Using Kubernetes version","kubernetes version":"1.31.4"}
{"level":"info","ts":1738219344.3665466,"caller":"flows/install.go:42","msg":"Configuring package manager. This might take a while..."}
{"level":"info","ts":1738219344.3665597,"caller":"flows/install.go:64","msg":"Installing containerd..."}
{"level":"info","ts":1738219349.5372758,"caller":"flows/install.go:69","msg":"Installing iptables..."}
{"level":"info","ts":1738219349.5373924,"caller":"flows/install.go:83","msg":"Installing SSM agent installer..."}
{"level":"info","ts":1738219352.9538224,"caller":"flows/install.go:94","msg":"Installing kubelet..."}
{"level":"info","ts":1738219353.7074184,"caller":"flows/install.go:99","msg":"Installing kubectl..."}
{"level":"info","ts":1738219354.4058442,"caller":"flows/install.go:104","msg":"Installing cni-plugins..."}
{"level":"info","ts":1738219355.5251875,"caller":"flows/install.go:109","msg":"Installing image credential provider..."}
{"level":"info","ts":1738219355.5736701,"caller":"flows/install.go:114","msg":"Installing IAM authenticator..."}
{"level":"info","ts":1738219356.2909362,"caller":"flows/install.go:59","msg":"Finishing up install..."}
nodeadm でマシンを EKS に接続
nodeadm の init コマンドでマシンを EKS に接続できます。まず、Hybrid Nodes では、ノードの設定を yaml ファイルで定義できます。ここでは、以下のファイルを nodeConfig.yaml という名前で作成します。activationCode、activationId は前の手順で作成したものを設定してください。
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
cluster:
name: sandbox-hybrid-eks
region: ap-northeast-1
hybrid:
ssm:
activationCode: ACTIVATION_CODE
activationId: ACTIVATION_ID
nodeadm init コマンドの引数に指定
このファイルを、nodeadm init コマンドの引数に指定します。
ubuntu@ip-10-116-0-10:~$ sudo ./nodeadm init -c file://nodeConfig.yaml
オンプレミスのマシンを登録確認
手元のコンソールに戻り、オンプレミスのマシン (mi-xxxx) が登録されていることを確認します。
❯ kubectl get nodes
NAME STATUS ROLES AGE VERSION
i-03e64e460d7b1e59e Ready <none> 3h21m v1.31.3-eks-7636447
i-079e38f6f3d535092 Ready <none> 3h21m v1.31.3-eks-7636447
mi-021e8e7ae37d70b95 NotReady <none> 14s v1.31.4-eks-aeac579
4-9. CNI の設定
登録したオンプレミスのノードは、CNI が設定されていないため NotReady の状態になっています。Hybrid Nodes ではオンプレミスマシンに設定する CNI として、 Cilium と Calico をサポート しています。クラウドで利用する VPC CNI は、VPC の存在が前提のためオンプレミスのノードでは実行できません。
今回の手順では Cilium を利用します。ドキュメント記載の通り にインストール、設定します。
Cilium の設定ファイルを作成
Cilium は helm でインストールします。設定ファイルは、helm の values を yaml で定義することとします。以下のような yaml を cilium-values.yaml という名前で用意します。
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: eks.amazonaws.com/compute-type
operator: In
values:
- hybrid # オンプレミスのノードのみで実行する
envoy:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: eks.amazonaws.com/compute-type
operator: In
values:
- hybrid # オンプレミスのノードのみで実行する
ipam:
mode: cluster-pool
operator:
clusterPoolIPv4MaskSize: 28
clusterPoolIPv4PodCIDRList:
- 10.116.128.0/17 # 前の手順で設定した Pod CIDR
operator:
replicas: 1
unmanagedPodWatcher:
restart: false
Cilium のインストール
Cilium を helm でインストールします。Kubernetes のバージョンとサポートされる Cilium のバージョンは ドキュメントを参照 してください。
$ helm repo add cilium https://helm.cilium.io/
$ helm install cilium cilium/cilium \
--version 1.16.6 \
--namespace kube-system \
--values cilium-values.yaml
NAME: cilium
LAST DEPLOYED: Thu Jan 30 16:36:22 2025
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
You have successfully installed Cilium with Hubble.
Your release version is 1.16.6.
オンプレミスのノードの準備完了
これで、オンプレミスのノードが Ready になるはずです。
❯ kubectl get nodes
NAME STATUS ROLES AGE VERSION
i-03e64e460d7b1e59e Ready <none> 4h17m v1.31.3-eks-7636447
i-079e38f6f3d535092 Ready <none> 4h17m v1.31.3-eks-7636447
mi-021e8e7ae37d70b95 Ready <none> 56m v1.31.4-eks-aeac579
4-10. ワークロードをオンプレミスのノードにデプロイする
これで、Hybrid Nodes のクラスターが準備できました。さっそく、ワークロードをデプロイしてみましょう。以下のような yaml を workload.yaml という名前で用意します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-ex
spec:
selector:
matchLabels:
app: web-ex
replicas: 2
template:
metadata:
labels:
app: web-ex
spec:
containers:
- name: nginx
image: public.ecr.aws/nginx/nginx:1.27-alpine
ports:
- containerPort: 80
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: eks.amazonaws.com/compute-type
operator: In
values:
- hybrid
---
apiVersion: v1
kind: Service
metadata:
name: web-ex
spec:
selector:
app: web-ex
ports:
- protocol: TCP
port: 80
targetPort: 80
デプロイ
nodeAffinity でオンプレミスのノードを指定してデプロイできます。
$ kubectl apply -f workload.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
web-ex-55f796f547-wwzj2 1/1 Running 0 15s
web-ex-55f796f547-xdhsc 1/1 Running 0 10s
サービスにアクセス
起動したら、上記サービスにアクセスしてみます。
$ kubectl port-forward service/web-ex 8080:80
nginx のページにアクセス
ブラウザで http://localhost:8080 にアクセスして、nginx のページが表示されたら成功です。

4-11. オンプレミスのワークロードをロードバランサーと連携する
オンプレミスのワークロードは、AWS のサービスと連携することもできます。ここでは、ロードバランサーと連携してみましょう。
まず、オンプレミスの Pod へのトラフィックが、AWS のロードバランサーからルーティングされるようにします。本来は、Cilium の BGP 機能などで動的に設定できますが、今回は VPC ピアリングを利用しているため以下のように静的にルーティングを設定します。

起動している Pod の CIDR を確認
オンプレミスのノードで起動している Pod の CIDR は以下のコマンドで確認できます。
$ kubectl get cn -o=jsonpath='{.items[0].spec.ipam.podCIDRs[0]}'
10.116.128.0/28
オンプレミスノードの EC2 インスタンスから ENI をクリック
オンプレミス側のマシンに、この CIDR を設定することで、Pod へのトラフィックがノードへルーティングされるようになります。
オンプレミスノードの EC2 インスタンスから ENI をクリックします。

Change source/dest. check のチェックを外す
Change source/dest. check を選択し、チェックを外します。


Pod の CIDR を設定
つづけて、Manage prefixes を選択し、上記で調べた Pod の CIDR を設定します。


ingress-class.yaml を作成
Pod の CIDR をノードに設定したら、ロードバランサーを作成します。今回は EKS Auto Mode を利用しており、Ingress Class を設定することでロードバランサーを EKS Auto Mode に作成してもらうことができます。以下のような設定ファイルを ingress-class.yaml という名前で作成します。
apiVersion: eks.amazonaws.com/v1
kind: IngressClassParams
metadata:
name: alb
spec:
scheme: internet-facing
subnets:
ids:
- subnet-xxx # クラウド側 VPC のパブリックサブネット ID
- subnet-xxx # クラウド側 VPC のパブリックサブネット ID
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: alb
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: eks.amazonaws.com/alb
parameters:
apiGroup: eks.amazonaws.com
kind: IngressClassParams
name: alb
EKS から ELB を作成
これを適用することで、 EKS から ELB を作成できるようになります。
$ kubectl apply -f ingress-class.yaml
Pod の IP を紐づけ
Ingress リソースを作成することで、 EKS Auto Mode により Application Load Balancer が作成され、Pod の IP が紐づけられます。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ex
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /*
pathType: ImplementationSpecific
backend:
service:
name: web-ex
port:
number: 80
nginx のページを表示
以下へアクセスし、nginx のページが表示されたら完了です。 ここでは Pod へのルーティングを静的に設定しました。BGP が利用できず、ノードが増減しないような環境下であれば、今回のような設定は実際のオンプレミス環境でも有用です。
$ kubectl apply -f ingress.yaml
# ALB の URL を取得
$ kubectl get ingress web-ex -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
k8s-default-webex-xxx.ap-northeast-1.elb.amazonaws.com
5. クリーンアップ
余分なコストが発生しないよう、検証が終わったら作成したリソースを削除します。
ロードバランサーリソースを削除
$ kubectl delete -f ingress.yaml
オンプレミスのノードを削除
作成した オンプレミスのノードを EC2 のコンソールから削除します。
Hybrid Activation の削除
Systems Manager のコンソール から、作成した Hybrid Activation を削除します。
IAM Role の削除
IAM のコンソールから、オンプレミスのマシンに割り当てていた IAM Role を削除します。
EKS クラスターの削除
EKS のコンソールから 作成したクラスター を削除します。
VPC ピアリングの削除
作成した VPC ピアリングを コンソール から削除します。関連するルートテーブルのエントリも一緒に削除します。

オンプレミスの VPC を削除
オンプレミスの VPC (sandbox-hybrid-onpremise-vpc) をコンソールから削除します。
クラウド側の VPC を削除
まず、 NAT Gateway を コンソール から削除します。削除が完了したら、VPC (sandbox-hybrid-cloud-vpc) を コンソール から削除します。
6. まとめ
この記事では、Hybrid Nodes を AWS 上で構築しながら、ネットワークの設定やノードの初期化方法について一通りみてきました。
Amazon EKS Hybrid Nodes では、単に Kubernetes コントロールプレーンの管理を AWS に移譲できるだけではなく、 IAM でクラスターの権限を管理したり、 Amazon GuardDuty で Kubernetes の監査ログをモニタリングしたりといったハイブリッドな運用ができるようになっています。
また、AWS からオンプレミスへ通信できるため、AWS の Elastic Load Balancing にオンプレミスの Pod を登録する、といった連携が可能です。もちろん、オンプレミスから AWS への通信も可能で、これにより、AWS で稼働している Core DNS などのアドオンを利用したり、Pod Identity Agent により AWS の IAM をオンプレミスの Pod に割り当てて、アプリケーションから AWS サービスを利用したりできるようになっています。
さまざまな事情で、オンプレミスからワークロードを動かしにくいけれども、モダナイゼーションしてコンテナで運用したい、という要件があるのではないでしょうか。そのようなケースでは、ぜひ Amazon EKS Hybrid Nodes をご活用ください。
筆者プロフィール
アマゾン ウェブ サービス ジャパン合同会社
コンテナスペシャリスト ソリューションアーキテクト
フリーランスや Web 系企業で業務システムや Web サービスの開発、インフラ運用に従事。近年はベンダーでコンテナ技術の普及に努めており、現在、AWS Japan で Amazon ECS や Amazon EKS でのコンテナ運用や開発プロセス構築を中心にソリューションアーキテクトとして活動中。

Did you find what you were looking for today?
Let us know so we can improve the quality of the content on our pages