EKSにおけるSecurity Group変更の注意点
長くなるので結論を先に書きます。
EKSのノードインスタンスにおいてセキュリティグループを変更(アタッチ or デタッチ)する際は、ノードグループを更新しましょう。要するに手動での変更は止めましょうということです。ちなみにアタッチ済のセキュリティグループのルール変更は問題ありません。
手動で変更したために、疎通に関して問題が起こったので経緯と原因について書きたいと思います。
やりたかったこと
以下のような構成でPodからRDSへ疎通させたかった。
構成
対応内容
上記のような構成でノードのセキュリティグループを手動で変更しました。
具体的な設定内容としては、自己参照設定されているセキュリティグループををノードインスタンスとRDSにアタッチしました。
そもそもノードグループはオートスケーリンググループのため、手動変更がよくないことは認識していましたが、開発環境ということや諸々の状況から、一時的な対応として手動で新しいセキュリティグループをアタッチしました。(要するに手抜きでやってしまいました。)
発生事象
上記の対応後に、PodからRDSに接続できたりできなかったりする事象が発生。
原因調査
この時点で以下の確認を行いました。
1.セキュリティグループ
ソース、ポートに設定誤りがないことを確認
全てのインスタンスにセキュリティグループが付与されていることを確認
2.ネットワークACL
何も設定されていないことを確認
3.テスト用Podから接続確認
PodをCreateした直後は高確率でRDSに対して接続可能となるが、Podをkillしてリスタートすると接続できたりできなかったりというかなり微妙な結果となりました。特定のノードで接続できないとか特定のPodに問題があるのかなど確認しましたが特にそういった問題は見受けられませんでした。
4.セキュリティグループの設定変更
RDSのSGにおいて、自己参照ではなくインバウンドのソースにSharedNodeSecurityGroup(eksctlでデフォルトで作成されるノードのSG)を指定するように変更したところ、RDSへ接続が可能となることが判明。
この時点では、明確な原因が分かるところまでは調査できませんでした。
他の環境において全く同様の設定でDB接続に問題は発生していなかったため、自己参照のSGに問題があるとは考えづらかったのですが、状況から見ると何か問題がありそうということで、一旦自己参照における設定はやめることとしました。(結果的に自己参照が問題ではありませんでした。)
余談ですが、この調査の際に以下の方法を利用してホスト側に接続しtcpdumpなどで調査を進めました。
SSH接続しなくてよいのでかなり便利です。
dev.classmethod.jp
EKSのネットワークについて調査
原因がはっきりとしなかったため、後日改めてEKSのネットワークについて調べてみました。
EKSのネットワークについては、Amazon VPC CNI plugin for Kubernetesというプラグインを使用することで、PodについてもVPCネットワーク上のアドレスと同じIPを利用することが可能となっています。
このため、ノードインスタンスではPod数分のIPを確保する必要があるため、ネットワークインターフェースを1ノードに複数アタッチする構成となっています。以下AWSの資料です。
問題が起こった環境では、インスタンスタイプはt3.mediumを利用していました。このタイプのネットワーク制限は以下となり、最大18個のIPが利用可能となります。
■t3.medium
アタッチ可能なENI数 | 3 |
---|---|
ENIあたりのIPv4数 | 6 |
ここでENIが複数アタッチされていることに改めて着目しました。
そもそもセキュリティグループはインスタンスに対して割り当てられるものではなく、ENIにセットされるものとなります。通常、あまり複数ENIを利用することも少ないこともあり、EC2のコンソールからはインスタンスにセットされているように見えますが実際にはENIにセットされていることになります。
この時、EC2のコンソールからセキュリティグループを追加した際に全てのENIに反映されていないのではないかと思い至り、検証してみました。
もし上記の通りの動作だとすると、セキュリティグループがアタッチされたENIからのみRDSへ疎通が可能となり、それ以外のENIからは通信できないという動きになると考えられます。
ENIに対しセキュリティグループがどのようにアタッチされるか?
以下のようにセキュリティグループが割り当てられているインスタンスを用意しました。
3つのセキュリティグループが割り当てられています。
このインスタンスには以下のように3つのENIがアタッチされており、セキュリティグループについても全て同様となっています。
このインスタンスに対してEC2コンソールからadd_sgというセキュリティグループをアタッチしました。
アタッチ完了後にENIを確認したところプライマリENIのみadd_sgが付与されていることが分かりました。
■プライマリENI
■セカンダリENI
検証結果から上記の想定通りの動作ということが確認できました。
接続不具合となった原因
改めて状態を図にしてみると以下のようなイメージになります。
EC2コンソールから手動でセキュリティグループを変更するとENI_1にのみadd_sgがアタッチされることとなります。
そのため、ENI_1に紐付くIPが割り当てられたPodからのみRDSへの疎通が可能となり、そうでないENIに紐付くIPが割り当てられたPodからは疎通ができません。ということで、今回発生した事象について原因が判明しました。
ちなみに何度か検証した際に気付きましたが、EC2コンソールからのセキュリティグループ変更時には、以下のようにインターフェースIDが表示されていました・・・コンソールはしっかり確認する必要がありますね。
全てのENIに手動でセキュリティグループをアタッチすれば問題ないか?
完全に一時しのぎとしてなのですが、仮に全てのENIのセキュリティグループを手動で変更すれば問題ないかという観点でもう少し考えてみました。オートスケーリンググループのテンプレートの問題は一旦おいておきます。
ノードインスタンスは、起動直後にPodの数が少ない場合、ENIは1つしかアタッチされていません。
そこからPodの数が増えて1つのENIで割り当て可能なIP数を超えた場合は、新たにENIがアタッチされることになります。その際、増えたENIはどのようなセキュリティグループがセットされているかを確認してみました。
以下のようなENIが一つのみのインスタンスを用意し、add_sgというセキュリティグループをセットします。
インスタンにENIが一つアタッチされている状態です。
この状態でPodの数を増やし、各ENIの状態を確認しました。
プライマリENIにはadd_sgが付与されていることが分かります。
追加された2つのENIを確認すると、add_sgは付与されていませんでした。
おそらくテンプレートから引っ張ってきてると思うので当然の動作かもしれません。
ということから、仮に全てのENIのセキュリティグループを手動で変更したとしてもENIが勝手に増える可能性があるため、突然、通信できなくなる問題が起こりそうですね。