TL;DR;
プライベートsubnetsなど、閉じたネットワークにEKS Managed Worker Nodeを動かしていて、手元のローカルマシンから直接SSHできないけど、わざわざアクセス可能なネットワーク内にEC2とか立てたくない人のためのお手軽にWorker Nodeに手軽にSSHログインする方法
- 中継用PodをクラスタにデプロイしてそのPod経由でWorker Node (EC2)にSSHログインする
- ここではkubectl-plugin-ssh-jumpを紹介
(前提条件) EKS Managed Node GroupのSSH設定
前提条件としてSSHログインのためにEKS Node Group作成時にSSHアクセス設定が必要となる。以下簡単に、利用ツール別の設定マニュアルを紹介する
- CloudFormationの場合: AWS::EKS::Nodegroup RemoteAccessでssh鍵とソースとなるSecurity Groupを設定する
- eksctlの場合: eksctlのEKS Managed Nodegroups設定例のようにssh鍵とソースとなるSecurity Groupを設定する
中継用Podを経由してWorker NodeにSSHログイン
kubectl pluginのssh-jumpを利用して、中継用PodをクラスタにデプロイしてそのPod経由でWorker Node (EC2)にSSHログインする手順を紹介する
kubectl plugin管理ツールのkrewを使ってssh-jumpをインストールする。これで準備完了。
kubectl krew install ssh-jump
ログインしたいノード名もしくはIPアドレスを取得
kubectl get no -o custom-columns=Hostname:.metadata.name,Internal-IP:'{.status.addresses[?(@.type=="InternalIP")].address}'
Hostname Internal-IP
ip-10-110-19-10.ap-northeast-1.compute.internal 10.110.19.10
ip-10-110-19-88.ap-northeast-1.compute.internal 10.110.19.88
ip-10-110-38-34.ap-northeast-1.compute.internal 10.110.38.34
ここではip-10-110-19-10.ap-northeast-1.compute.internal
にログインする。 kubectlのssh-jumpコマンド (pluginコマンド)の-i
オプションにPEMキー(~/.ssh/yokawasa.pem)を指定し、ログイン先ホストにip-10-110-19-10.ap-northeast-1.compute.internal
を指定して実行する
kubectl ssh-jump -u ec2-user \
-i ~/.ssh/yokawasa.pem \
ip-10-173-62-96.ap-northeast-1.compute.internal
登録した鍵に問題がなければ、次のようなログインメッセージが出力されます
Last login: Thu Aug 6 01:57:57 2020 from ip-10-110-19-10.ap-northeast-1.compute.internal
__| __|_ )
_| ( / Amazon Linux 2 AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-2/
4 package(s) needed for security, out of 7 available
Run "sudo yum update" to apply all updates.
中身解説
上述のとおり、ssh-jumpプラグインコマンドは、EKSクラスタにssh jump用のPodを一時的にたてて、そこを踏み台にWorker NodeにSSHアクセスする。具体的には次のようなステップをコマンド内で実行している。
中継用Pod(sshjump)を立ち上げる
kubectl run sshjump --image=corbinu/ssh-server --port=22 --restart=Never
中継用PodにSSHログインするための一時公開・秘密鍵を作成
ssh-keygen -t rsa -f $HOME/.kube/kubectlssh/id_rsa_sshjump -N '' > /dev/null
バックグラウンドで中継用Podに2222->22でポートフォワードする
kubectl port-forward sshjump 2222:22 2>/dev/null &
中継用Podに上記ステップで作成した一時公開鍵を登録(中継用Podにはssh serverが動いている)
cat $HOME/.kube/kubectlssh/id_rsa_sshjump.pub | \
kubectl exec -i sshjump -- /bin/bash -c "cat > /root/.ssh/authorized_keys"
中継用Podを経由して、ターゲットノードにSSHログイン
ssh -i ~/.ssh/yokawasa.pem -p 22 ec2-user@ip-10-110-19-10.ap-northeast-1.compute.internal \
-o "ProxyCommand ssh root@127.0.0.1 -p 2222 -i $HOME/.kube/kubectlssh/id_rsa_sshjump -o \"StrictHostKeyChecking=no\" \"nc %h %p\""
使い終わったら中継用Podを削除し、 ポートフォワードも停止
kubectl delete pod sshjump
kill -3 <Portforward command PID> 2>/dev/null
まとめ
これはEKSクラスタの操作権限さえあれば手軽にできる手法であり、毎回アクセス元(+そのサーバー管理)を意識することなく、必要なときにオンデマンドで一時的に作って終わったら破棄できるところがポイント。是非プライベートsubnetsなど、閉じたネットワークでのSSHログインシナリオの際にはご活用いただけたらと。