🔓

GKEで構築したアプリケーションに指定ドメイン&IAP有効の状態でアクセスする

2021/06/01に公開

以下のやりたいことを実現するためのhow toについて紹介します。

やりたいこと

  • GKEで構築したWebアプリケーションに指定のドメインでHTTPSアクセスしたい
  • その上で、IAPを適用して指定のユーザーのみアクセスできる様にしたい

今回は hello-web というアプリケーション名で gcr.io/google-samples/hello-app:2.0 というサンプルのDocker imageを利用して構築したいと思います。

前提条件

  • cloud DNSでゾーンを作成してレジストラにNSレコードを登録していること
  • gcloudコマンドが使えること&権限があること
  • kubectlが使えること
  • k8sの基礎知識があること
    • Kubernetesの各コンポーネントについて解説しません。コピペでも作成はできますが基礎を理解していると応用が効くと思います。

ソースコード

https://github.com/momota10/gcp-samples/tree/master/gke

手順

GKEクラスタの作成

まず、以下の様なコマンドでGKEクラスタを作成します

gcloud container clusters create hello-web \
--machine-type=n1-standard-1 \
--num-nodes=1 \
--disk-size=100 \
--region=asia-northeast1 \
--preemptible \
--scopes=cloud-platform \
--enable-cloud-logging \
--enable-stackdriver-kubernetes \
--image-type "COS"

作成が終わったらgkeへの接続をしておきます

gcloud container clusters get-credentials hello-web --region asia-northeast1 --project <your-project>

次に、namespaceを作成します。以降紹介するマニフェストやkubectlには以下で作成したnamespaceが入っています

kubectl create namespace hello-web

Deployment,Service, Ingressのapply

まず、静的IPアドレスの用意をします

gcloud compute addresses create hello-web-static-ip --global

任意のディレクトリを作成し、その下にdeploymentとserviceのマニフェストを用意します

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: hello-web
spec:
  selector:
    matchLabels:
      run: web
  template:
    metadata:
      labels:
        run: web
    spec:
      containers:
      - image: gcr.io/google-samples/hello-app:2.0
        imagePullPolicy: IfNotPresent
        name: web
        ports:
        - containerPort: 8080
          protocol: TCP

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: hello-web
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    run: web
  type: NodePort

ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hello-web-ingress
  namespace: hello-web
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "hello-web-static-ip"
spec:
  backend:
    serviceName: web
    servicePort: 8080

作成したマニフェストをapplyします

kubectl apply -f .

static-ipでアクセスできることを確認します。static-ipは以下のコマンドで確認出来ます

# static-ipの確認(describeにて表示されたIPを使用)
gcloud compute addresses describe hello-web-static-ip --global

# アクセス
curl -i http://<hello-web-static-ip>

ManagedCertificateのapply

sert.yaml

apiVersion: networking.gke.io/v1beta1
kind: ManagedCertificate
metadata:
  name: hello-web-iap
  namespace: hello-web
spec:
  domains:
    - your-domain.com

ingress.yaml(managed-certificatesの追記)

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: basic-ingress
  namespace: hello-web
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "hello-web-static-ip"
    networking.gke.io/managed-certificates: "hello-web-iap"
spec:
  backend:
    serviceName: web
    servicePort: 8080
kubectl apply -f .

ManagedCertificateの反映に数十分時間がかかりますが、これによりhttpsでのアクセスができる様になります。またTLS証明書はGoogleによって管理されます。

# managedcertificateの確認。StatusがActiveになっていればOK
kubectl get managedcertificate -n hello-web
curl -i https://your-domain.com

OAuthの同意、認証情報の作成

ここまでで指定ドメインによるHTTPSアクセスはできている状態です、最後にIAPを有効にする準備をしたいと思います。

まず、以下より OAuth同意画面 の作成を行い、 OAuth 2.0 クライアント ID の認証情報を作成します

OAuth同意画面の作成

https://console.cloud.google.com/apis/credentials/consent

OAuth 2.0 クライアント IDの認証情報を作成

https://console.cloud.google.com/apis/credentials

認証情報を作成すると発行されるクライアントidとシークレットを控えます

作成した認証情報の編集画面から、「承認済のリダイレクトURI」に以下を追記します

https://iap.googleapis.com/v1/oauth/clientIds/<your-client-td>:handleRedirect

最後に、BackendConfigで使用するシークレットを作成します

kubectl create secret generic hello-web-iap-oauth-client-id \
-n hello-web \
--from-literal=client_id=<先ほどのクライアントid> \
--from-literal=client_secret=<先ほどのシークレット>

BackendConfigのapply

backend-config.yaml

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: hello-web-backend-config
  namespace: hello-web
spec:
  iap:
    enabled: true
    oauthclientCredentials:
      secretName: hello-web-iap-oauth-client-id

ingress.yaml(allow-httpの追記)

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: basic-ingress
  namespace: hello-web
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "hello-web-static-ip"
    networking.gke.io/managed-certificates: "hello-web-iap"
    kubernetes.io/ingress.allow-http: "false"
spec:
  backend:
    serviceName: web
    servicePort: 8080

service.yaml(annotationsの追記)

apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: hello-web
  annotations:
    beta.cloud.google.com/backend-config: '{"default": "hello-web-backend-config"}'
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    run: web
  type: NodePort
kubectl apply -f .

最後に、IAPの画面からhello-webのバックエンドサービスにおけるIAPを有効にします

https://console.cloud.google.com/security/iap

これでyour-doamin.comへ改めてアクセスすると以下の様に認証を求められる様になりました 🎉

参考記事

https://cloud.google.com/iap/docs/enabling-kubernetes-howto?hl=ja
https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features?hl=ja
https://cloud.google.com/kubernetes-engine/docs/concepts/ingress-xlb
https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs?hl=ja#check_events_on_managedcertificate_and_ingress_resources

https://passing.breeze.cc/mt/archives/2020/11/gke-ingress.html
https://bravenewgeek.com/using-google-managed-certificates-and-identity-aware-proxy-with-gke/

Discussion