クラスタのセキュリティー強化
このセクションでは、Kubernetes クラスタのセキュリティー強化に関する補足情報を紹介します。
ネットワークトポロジ
CircleCI Server システムでは主に、Kubernetes ノード、Nomad クライアント、外部 VM という 3 種類のコンピューティングインスタンスを実行します。
これらのインスタンスは、CIDR ブロックの異なるサブネットに分けてデプロイすることを強くお勧めします。 そうすることで、システムのコンポーネント間を流れるトラフィックの制御やそれぞれの分離がしやすくなります。 そうでない場合は、少なくとも circleci-proxy
ロード バランサー用にパブリックサブネットを 1 つ用意する必要があります。
リソースはできる限り非公開にすることがベストプラクティスです。
NGINX リバースプロキシは、 Kong の前に配置され、 circleci-proxy という名前の Kubernetes サービスとして公開されます。 NGINX はトラフィックを kong 、 vm-service 、 output-processor 、 nomad にルーティングします。 |
Amazon Certificate Manager (ACM) をご使用の場合は、NGINX のサービスは circleci-proxy ではなく circleci-proxy-acm になります。 TLS 証明書の処理を他の方法から ACM に変更した場合、ロードバランサーが再作成され、お客様の <domain> とアプリの <domain> の関連付けられている DNS レコードを再ルーティングする必要があります。 |
ネットワークトラフィック
このセクションでは、CircleCI Server システムの稼働に必要な最小要件について説明します。 ワークロードによっては、Nomad クライアントと VM の送信にルールを追加する必要があります。 クラウドプロバイダーごとに名称は異なります。 そのため、ファイアウォール ルールやセキュリティグループなどを使用した実装が必要になる可能性があります。
表中の "外部" は、特に断りがない限り、すべての外部 IPv4 アドレスを意味します。 ただし、外部トラフィックすべてにプロキシを使用している場合など、お使いの環境によっては、より具体的に指定することができます。
また、下記のルールは、特別な記載のない限り、TCP 接続に対してステートフルで設定するものとします。 ステートレスルールを使用する場合には、下表の各項目に該当する送受信ルールをそれぞれ作成してください。
リバースプロキシのステータス
CircleCI Server でサービスのルーティングトラフィックステータスを確認し、問題がある場合は警告したい場合があります。 CircleCI Server では NGINX と Kong の両方を使用しているため、両方のステータスページをポート 80 経由で公開しています。
サービス | エンドポイント |
---|---|
NGINX |
|
Kong |
|
Kubernetes ロードバランサー
お使いの環境によっては、ロードバランサーが透過的である (つまり、ネットワークトポロジの個別のレイヤーとしては扱われない) ことがあります。 この場合には、ロードバランサーの背後にあるネットワークトラフィックの送信先またはソースに対して、本セクションのルールを直接適用してください。 CircleCI Server システムで使用している負荷分散の種類に応じたネットワークセキュリティルールの適切な適用方法については、ご利用のクラウドプロバイダーのドキュメントをご覧ください。
受信
ロードバランサーのトラフィックルールが自動的に作成されていない場合は、次の各ポートを設定してください。
名前 | ポート | ソース | 用途 |
---|---|---|---|
circleci-proxy/-acm | 80 | 外部 | ユーザーインターフェースとフロントエンド API |
circleci-proxy/-acm | 443 | 外部 | ユーザーインターフェースとフロントエンド API |
circleci-proxy/-acm | 3000 | Nomad クライアント | Nomad クライアントとの通信 |
circleci-proxy/-acm | 4647 | Nomad クライアント | Nomad クライアントとの通信 |
circleci-proxy/-acm | 8585 | Nomad クライアント | Nomad クライアントとの通信 |
送信
必要な送信は、Kubernetes ロードバランサーのポート (30000 ~ 32767) 上にある Kubernetes ノードへの TCP トラフィックのみです。 ただし、ロードバランサーが透過的であればこの送信は必要ありません。
コンピューティングインスタンスの共通ルール
以下のルールは、ロードバランサーを除くすべてのコンピューティングインスタンスに適用されます。
受信
インスタンスに SSH でアクセスする必要がある場合は、該当するインスタンスへの TCP 接続用にポート 22 を開放してください。 ルールの範囲は、許可されたソースIPにできるだけ近いものにすること、または、必要な場合にのみそのようなルールを追加することをお勧めします。
送信
ほとんどの環境では、インスタンスすべてに対してインターネットリソースへのアクセスを許可することになります。 これを行うには、VPC 内にある DNS サーバーへのポート 53 からの UDP と TCP の送信を許可する必要があります。また、HTTP と HTTPS それぞれのトラフィックについて、ポート 80 と 443 からの TCP の送信を許可する必要もあります。 ジョブのビルドを行うインスタンス (Nomad クライアントや外部 VM) では、多くの場合、SSH 経由でご利用中の VCS からコードをプルする必要があります (TCP ポート 22)。 SSH は、外部 VM との通信にも使用されます。 そのため、少なくとも送信先が VM サブネットおよび VCS であるインスタンスすべてについて、SSH を許可する必要があります。
Kubernetes ノード
ノード間のトラフィック
デフォルトでは、Kubernetes クラスタ内のトラフィックはネットワークポリシーにより規定されています。 つまり、Kubernetes ノード間のトラフィックを特別に制限する必要はなく、Kubernetes ノード間のトラフィックはすべて許可してかまいません。
クラスタ内でネットワーク ポリシーを使用するには、クラウド プロバイダーや環境設定にもよりますが、追加の手順を実行する必要があります。 以下の資料を参考にしてください。
受信
マネージドサービスを使用している場合は、ロードバランサーおよび許可済みのポート範囲からの送信トラフィックに対して作成されているルールを確認できます。 受信側の設定では、Kubernetes ロードバランサーの標準のポート範囲 (30000 ~ 32767) を許可するだけで十分です。 ただし、透過的なロードバランサーを使用している場合は、上記のロードバランサー用受信ルールを適用する必要があります。
送信
ポート | 送信先 | 用途 |
---|---|---|
2376 | VM | VM との通信 |
4647 | Nomad クライアント | Nomad クライアントとの通信 |
すべてのトラフィック | その他のノード | クラスタ内トラフィックの許可 |
Nomad クライアント
Nomad クライアント同士は、通信する必要はありません。 Nomad クライアントインスタンス間のトラフィックを完全にブロックできます。
受信
ポート | ソース | 用途 |
---|---|---|
4647 | K8s ノード | Nomad サーバーとの通信 |
64535-65535 | 外部 | SSH でのジョブ再実行機能 |
送信
ポート | 送信先 | 用途 |
---|---|---|
22 | VM | VM との SSH 通信 |
2376 | VM | Docker と VM の 通信 |
3000 | VM サービスのロード バランサー | 内部通信 |
4647 | Nomad のロード バランサー | 内部通信 |
8585 | 出力プロセッサのロード バランサー | 内部通信 |
外部ポート
Nomad クライアントと同じく、外部 VM 同士も通信する必要はありません。
受信
ポート | ソース | 用途 |
---|---|---|
22 | Kubernetes ノード | 内部通信 |
22 | Nomad クライアント | 内部通信 |
2376 | Kubernetes ノード | 内部通信 |
2376 | Nomad クライアント | 内部通信 |
54782 | 外部 | SSH でのジョブ再実行機能 |
送信
設定が必要な送信ルールは、VCS へのインターネットアクセスと SSH 接続のみです。
VM サービスを使った AWS ネットワーキングにおける注意点
VM サービスで EC2 プロバイダーを使う場合、values.yaml
ファイルには assignPublicIP
オプションがあります。
vm_service:
...
providers:
ec2:
...
assignPublicIP: false
デフォルトではこのオプションは false に設定されており、VM サービスにより作成されたインスタンスにはプライベート IP アドレスのみが割り当てられます。
仮想マシン (VM) を起動し、ジョブを実行するための通信は、次の 2 つの段階で行われます。
-
vm-service
Pod が、ポート22
と2376
を介して新しく作成された VM への接続を確立 -
ジョブを実行する Nomad クライアントが、ポート
22
と2376
を介して新しく作成された VM への接続を確立
プライベート IP のみ
assignPublicIP
オプションを false に設定すると、 ソースセキュリティグループの ID パラメータ を使ってサービス間のセキュリティグループルールによるトラフィックを制限できます。
VM セキュリティグループの受信ルールでは、インストール環境のセキュリティーを強化するために以下のルールを作成できます。
ポート | 送信元 | 用途 |
---|---|---|
22 | Nomad クライアントのセキュリティグループ | Nomad クライアントによる VM への SSH |
2376 | Nomad クライアントのセキュリティグループ | Nomad クライアントによる VM での Docker への接続 |
22 | EKS クラスタのセキュリティグループ | vm-service Pod の VM への SSH |
2376 | EKS クラスタのセキュリティグループ | vm-service Pod の VM での Docker への接続の許可 |
54782 | 任意の CIDR 範囲 | 再試行およびデバッグのために失敗した VM ベースのジョブへの SSH 接続 |
パブリック IP の使用
assignPublicIP
オプションを true に設定すると、VM サービスにより作成されたすべての EC2 インスタンスに パブリック IPv4 アドレスが割り当てられます。従って、これらのインスタンスと通信するすべてのサービスがパブリックアドレスを介するようになります。
vm-service
Pod からの SSH トラフィックは、クラスタのサブネットの NAT ゲートウェイを通過します。 トラフィックは VPC の外部に移動するため、セキュリティグループの送信元ごとにトラフィックを制限することはできません。 代わりに、クラスタが使用する NAT ゲートウェイの IP をセーフリストに追加する必要があります。
Nomad クライアントと VM サービスの両方の VM にパブリック IP が割り当てられている場合、SSH と Docker のトラフィックは、サブネットのインターネットゲートウェイ経由でルーティングされます。 トラフィックはパブリックインターネットを通過するため、セキュリティグループはトラフィックを制限するためのオプションではなくなります。 これらのポートへのアクセスを制限するには、Nomad クライアントのパブリック IPv4 アドレスを VM サービスセキュリティグループの受信ルールのセーフリストに追加する必要があります。 これらの IP とマシンは一時的なものであり、変更時には VM サービスセキュリティグループを更新するメカニズムが必要になります。
VM サービスがパブリック IP を使用するインストール環境のセキュリティー強化では、以下のルールを作成できます。
ポート | 送信元 | 用途 |
---|---|---|
22 | すべての Nomad クライアントの各 IPv4 アドレス (または割り当てられる可能性のある IP 用に 0.0.0.0/0) | Nomad クライアントによる VM への SSH |
2376 | すべての Nomad クライアントの各 IPv4 アドレス (または割り当てられる可能性のある IP 用に 0.0.0.0/0) | Nomad クライアントによる VM での Docker への接続 |
22 | クラスタの NAT ゲートウェイの IPv4 範囲 |
|
2376 | クラスタの NAT ゲートウェイの IPv4 範囲 |
|
54782 | 任意の CIDR 範囲 | 再試行およびデバッグのために失敗した VM ベースのジョブへの SSH 接続 |