G-gen の佐々木です。当記事では Google Cloud ( 旧称 GCP ) の Google Kubernetes Engine ( GKE ) で作成した Ingress に対して、Cloud Armor セキュリティポリシー を構成することで、ワークロードに対するアクセス元 IP アドレス制限を実装します。
- 前提知識
- GKE クラスタの準備
- GKE クラスタにサンプルアプリケーションをデプロイする
- Ingress を作成してアプリケーションを公開する
- Cloud Armor のセキュリティポリシーを作成する
- BackendConfig を作成する
- Service を更新して BackendConfig に紐づける
- 許可していない IP アドレスからアクセスしてみる
前提知識
Google Kubernetes Engine とは
Google Kubernetes Engine (以下、GKE ) は、Google Cloud のインフラストラクチャ上に構築された マネージドな Kubernetes クラスタ を利用することができるサービスです。
サービスの詳細は以下の記事で解説しています。
Ingress とは
Ingress は Kubernetes の API リソースの 1 つで、Kubernetes クラスタ内のワークロードに対する L7 ロードバランシングを提供します。
Ingress は Service に関連付けることで、その背後にある Pod にデプロイされたアプリケーションを外部に公開することができます。
GKE では、組み込みのコントローラである GKE Ingress Controller によって、Kubernetes によって管理される HTTP(S) ロードバランサを GKE クラスタ外に作成することができます。
当記事では省略しますが、Ingress によって作成される HTTP(S) ロードバランサで HTTPS を使用する場合、Ingress と SSL 証明書を紐づける設定をする必要があります。
詳細な手順については以下の記事をご一読ください。
Cloud Armor とは
Cloud Armor は Google 製のクラウド型 WAF であり、Cloud Armor の セキュリティポリシー を HTTP(S) ロードバランサのバックエンドに紐づけることで、バックエンドに対するアクセス元の制限をかけることができます。
Cloud Armor の詳細については、以下の記事で解説しています。
GKE クラスタの準備
当記事では Autopilot モードの限定公開クラスタを使用していきます。
クラスタの作成方法については 公式ドキュメント、または Terraform を使用した以下の記事を参照してください。
GKE クラスタにサンプルアプリケーションをデプロイする
Google Cloud が提供するサンプルのコンテナイメージを使用し、アプリケーションを GKE クラスタに登録します。
マニフェストファイルは以下のようになります。
# deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: hello namespace: default spec: replicas: 3 selector: matchLabels: app: hello template: metadata: labels: app: hello spec: containers: - name: hello image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0 ports: - containerPort: 8080 protocol: TCP
続いて、アプリケーションを公開するための Service を GKE クラスタに登録します。
Service のマニフェストファイルは後に編集するため、当記事ではファイル名を service.yaml
と定めます。
# service.yaml apiVersion: v1 kind: Service metadata: name: hello namespace: default annotations: cloud.google.com/neg: '{"ingress": true}' spec: ports: - port: 8080 protocol: TCP targetPort: 8080 selector: app: hello type: NodePort
それぞれのプロビジョニングが完了するまで待ちます。
$ kubectl get deployments hello NAME READY UP-TO-DATE AVAILABLE AGE hello 3/3 3 3 15m $ kubectl get services hello NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello NodePort 172.31.236.34 <none> 8080:32678/TCP 10m
Ingress を作成してアプリケーションを公開する
まずは Cloud Armor のセキュリティポリシーを構成せずに Ingress を作成してみます。
この Ingress によって作成される HTTP(S) ロードバランサはアクセス元の制限がされておらず、ロードバランサの IP アドレスを知っていれば誰でもアプリケーションにアクセスすることができてしまいます。
# ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: hello-ingress namespace: default annotations: kubernetes.io/ingress.class: "gce" # 外部 HTTP(S) ロードバランサを指定 spec: defaultBackend: service: name: hello port: number: 8080
Ingress によって作成された HTTP(S) ロードバランサの外部 IP アドレスを確認し、ブラウザからアクセスしてみます。
$ kubectl get ingresses hello-ingress NAME CLASS HOSTS ADDRESS PORTS AGE hello-ingress <none> * 34.117.255.169 80 19m
Cloud Armor のセキュリティポリシーを作成する
アプリケーションに対するアクセス元 IP アドレスを制限するセキュリティポリシーを作成します。
ここで設定したセキュリティポリシーの名前は後で使用します。
セキュリティポリシーは Cloud Armor の機能ですが、gcloud compute
コマンドグループを使用して作成、編集を行うことができます。
当記事では hello-sec-policy
という名前のセキュリティポリシーを作成します。
# セキュリティポリシーの作成
$ gcloud compute security-policies create hello-sec-policy
ポリシーのデフォルトルール(優先度 2,147,483,647 )を更新し、すべてのアクセス元を拒否します。
# デフォルトルールの更新 $ gcloud compute security-policies rules update 2147483647 \ --security-policy hello-sec-policy \ --action "deny-403"
特定の IP アドレス範囲からのアクセスを許可するルールを追加します。
ルールの優先度はデフォルトのルールより高ければよいので、ここでは優先度 1000 で設定します。
# 許可ルールの追加 $ gcloud compute security-policies rules create 1000 \ --security-policy hello-sec-policy \ --src-ip-ranges "<許可する IP アドレス範囲>" \ --action "allow"
BackendConfig を作成する
Ingress に対して Cloud Armor セキュリティポリシーを紐づけるため、GKE のカスタムリソースである BackendConfig リソースをクラスタに登録します。
BackendConfig リソースを使用することで、セキュリティポリシーだけではなく、Cloud CDN や Identity-Aware Proxy など、HTTP(S) ロードバランサで利用できる様々な機能を Kubernetes から有効化することができます。
BackendConfig のマニフェストファイルでは、先ほど作成したセキュリティポリシーの名前を使用します。
# backendconfig.yaml apiVersion: cloud.google.com/v1 kind: BackendConfig metadata: name: hello-backend-config spec: securityPolicy: name: hello-sec-policy # 作成したセキュリティポリシーの名前
Service を更新して BackendConfig に紐づける
BackendConfig は、Ingress に対してではなく、HTTP(S) ロードバランサのバックエンドとなる Service に対して紐づけます。
バックエンドが使用するポートと BackendConfig を組み合わせた cloud.google.com/backend-config
アノテーションを service.yaml
に追記します。
annotations のキー | 値 |
---|---|
cloud.google.com/backend-config | '{"ports": {"8080":"hello-backend-config"}}' |
# service.yaml apiVersion: v1 kind: Service metadata: name: hello namespace: default annotations: cloud.google.com/backend-config: '{"ports": {"8080":"hello-backend-config"}}' # 追記 cloud.google.com/neg: '{"ingress": true}' spec: ports: - port: 8080 protocol: TCP targetPort: 8080 selector: app: hello type: NodePort
許可していない IP アドレスからアクセスしてみる
Ingress によって作成された HTTP(S) ロードバランサに Cloud Armor セキュリティポリシーが構成されたので、ポリシーで許可していない IP アドレス範囲からのアクセスが拒否されることを確認します。
ブラウザで、HTTP(S) ロードバランサの外部 IP アドレスに再度アクセスしてみます。
最後に、ポリシーで許可された IP アドレスからアクセスし、サンプルアプリケーションの画面が表示されることを確認します。
佐々木 駿太 (記事一覧)
G-gen最北端、北海道在住のクラウドソリューション部エンジニア
2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2025 Fellowに選出。好きなGoogle CloudプロダクトはCloud Run。
趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。
Follow @sasashun0805