📘

GKE上にAirflowを構築してIAPによるアクセス制御を行う(Autopilot編)

2022/05/31に公開

概要

以前書いたこちらの記事で利用しているGKEはスタンダードでしたので、Autopilotでの構築についても書きました。
https://zenn.dev/momota/articles/0fbdba643504e7

GKEだけ作り直せばあとは同じかと思っていましたが、WorkLoad Identityの設定やhelm valuesのupdateなども必要でしたのでそれらを追記した上で、手順を上の記事と同様に1から書いたものになります。

事前準備

ドメインの取得

今回はGoogle Domainsにて取得した momota.dev を使用します

https://domains.google/intl/ja_jp/

Cloud DNSゾーンの作成

まず、DNSゾーンを作成します。

作成するとNSレコードが自動で作成されているので、そこに記載されているネームサーバーを、登録したドメインレジストラのカスタムネームサーバーに登録して更新をします

カスタムネームサーバーの登録(Google Domainsの場合)

このネームサーバーの変更が反映されるまでに最大48時間ほどかかるようなので事前にしておくと良いです。

https://support.google.com/domains/answer/3290309

外部IPの予約

リージョン:グローバルにて外部IPを予約します。
名前は「airflow-web-static-ip」とします(後にこの名前を使用します)

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

割り当てたれたIPを先ほど作成したDNSゾーンのAレコードとして登録します。
今回は workflow.momota.dev のドメインで作成しました

登録後はnslookupでIPが表示されるか確認するとよいでしょう

nslookup workflow.momota.dev 
Server:         172.20.10.1
Address:        172.20.10.1#53

Non-authoritative answer:
Name:   workflow.momota.dev
Address: *****

Airflow環境の作成

サービスアカウント(SA)の作成

WorkloadIdentityでマッピングするためのSAを作成します(結果GKEが使用するSAとなります)
後述するhelm valuesの中では「"YOUR_SA@PROJECT_ID.iam.gserviceaccount.com"」と記載していますが、ここをご自身が作成したサービスアカウントのアドレスに置き換えてください。

GKEの作成

一度Standardで作成したGKEを後からAutopilotに変更することは出来ないので、新たに作成する必要があります。
また、前項で作成したSAはAutopilotモードでは強制的に有効となっているWorkLoad Identityの設定にて使用します。

gcloud container clusters create-auto CLUSTER_NAME \
--region REGION \
--project=PROJECT_ID

https://cloud.google.com/kubernetes-engine/docs/how-to/creating-an-autopilot-cluster?hl=ja

GCSの作成

今回はAirflowのログをGCSに吐き出すように設定しているので、そのためのログバケットを作成します。
後述するhelm valuesの中では「gs://your-log-bucket」と記載していますが、ここをご自身が作成したバケット名に置き換えてください。

namespaceの作成

今回は名前空間(namespace)を作成して、そこに構築することにします。
今回は airflow という名前空間で作成しています

$ kubectl create namespace airflow
namespace/airflow created

$ kubectl get namespace              
NAME              STATUS   AGE
airflow           Active   1s
default           Active   22m
kube-node-lease   Active   22m
kube-public       Active   22m
kube-system       Active   22m

Airflow-helmの利用

Airflowは様々なミドルウェアがあって成り立つものですが、それらのミドルウェアを管理してくれるhelmを使って構築していきます。

また、helmのchartは以下のリポジトリがすでに公開されているので、リポジトリにあるvaluesをカスタマイズして構築していきます。(Airflow2.1.2を利用するのでairflow-helmのバージョンは8.5.3です)

https://github.com/airflow-helm/charts/tree/airflow-8.5.3/charts/airflow

helm repoのインストール

$ helm repo add airflow-stable https://airflow-helm.github.io/charts
"airflow-stable" has been added to your repositories

$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "airflow-stable" chart repository
Update Complete. ⎈Happy Helming!⎈

$ helm repo list  
NAME            URL                                  
airflow-stable  https://airflow-helm.github.io/charts

httpsでのアクセスを可能にする

valuesのテンプレートはこちらです。

https://github.com/airflow-helm/charts/blob/airflow-8.5.3/charts/airflow/values.yaml

その上で、テンプレを以下のように更新します(ドメイン部分の記述は workflow.momota.dev で検索して引っかかった箇所を、自分のものに置き換えてください)

https://gist.github.com/momota10s/dd87fbe5fa6afd703ca7b65eb07f179a

valuesの変更箇所は以下です

  • airflow
    • fernetKey
    • webserverSecretKey
    • config
      • AIRFLOW__WEBSERVER__BASE_URL
  • web
    • service
  • flower
    • service
  • ingress
    • enabled
    • web
    • flower
  • extramanifests
    • ManagedCertificate

今回は gke-autopilot-values.yaml としてvaluesを作成し、変更後はhelm installでデプロイします

$ helm install airflow \
airflow-stable/airflow \
--values gke-autopilot-values.yaml \
--version 8.5.3 \
--namespace airflow

デプロイ後の動作確認

  1. GKEのコンソールからワークロード、Service、Ingress全てのコンポーネントがグリーンであることを確認します
  2. managedcertificateがActiveになっていることを確認します
  3. managedcertificateがActiveになったあと、イングレスのフロントエンド画面にあるリンクからアクセスできることを確認します
$ kubectl get managedcertificate -n airflow
NAME           AGE   STATUS
managed-cert   20m   Active

ワークロード

Services

Ingress

アクセスの確認

マネージドSSL証明書の詳細

https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs?hl=ja

Workload Identityの設定

詳細は以下のdocsに書いてあります
https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity

今回、Kubernetes サービス アカウント(KSA)の作成はhelm valuesで定義したので airflow-sa という名前のKSAができているはずです。

$ kubectl get sa -n airflow
NAME         SECRETS   AGE
airflow-sa   1         12d
default      1         12d

またサービスアカウント(SA)に必要なロールは付与できている前提で、ここではKSAがSAの権限の借用できるようにします。

kubectl annotate sa \
-n airflow \
airflow-sa  \
iam.gke.io/gcp-service-account=YOUR_SA@PROJECT_ID.iam.gserviceaccount.com

これにより、KSAとSAのマッピングが有効となりました。このことを確認します。
以下のkubectlを実行した際にAnnotationsにSAが記載されていればOKです。

$ kubectl describe sa -n airflow airflow-sa
Name:                airflow-sa
Namespace:           airflow
Labels:              app=airflow
                     app.kubernetes.io/managed-by=Helm
                     chart=airflow-8.5.2
                     heritage=Helm
                     release=airflow
Annotations:         iam.gke.io/gcp-service-account: YOUR_SA@PROJECT_ID.iam.gserviceaccount.com
...

認証情報の初期設定

OAuth同意画面を作成します。ユーザーの種類は内部にしておいてください

IAPの有効化

Airflowの構成が正常にデプロイされてるなら、Identity-Aware ProxyのページでIAPが無効になっているリソース( airflow/airflow-web )が出現するはずなので、これを有効にします。

その後、 ログインを許可させるgoogleアカウントに IAP-secured Web App User の権限を付与します。

作成されたoauth認証情報を元にkubectl create secretする

IAPが有効になった後、「OAuth 2.0 クライアント ID」が作成されているので、これの詳細画面から確認して、secretの変数として定義してcreateします

IAPを有効にすると作成される

クライアントID, クライアントシークレットをコピーする

以下を実行

# create
kubectl create secret generic airflow-iap-secret \
--from-literal=client_id=<your-client-id> \
--from-literal=client_secret=<your-client-secret> \
-n airflow

# check
kubectl get secret -n airflow
NAME                             TYPE                                  DATA   AGE
airflow-iap-secret               Opaque                                2      20s
...

BackendConfigの定義

先ほど共有したvaluesにて config-default でgrepすると3ヶ所出てくるのですが、そこのコメントアウトを外します。

web:
  ...
  service:
    # annotations: {}
    annotations:
      cloud.google.com/backend-config: '{"default": "config-default"}'
flower:
  ...
  service:
    # annotations: {}
    annotations:
      cloud.google.com/backend-config: '{"default": "config-default"}'
extraManifests:
  - apiVersion: networking.gke.io/v1
    kind: ManagedCertificate
    metadata:
      name: managed-cert
      namespace: airflow
    spec:
      domains:
        - workflow.momota.dev
  - apiVersion: cloud.google.com/v1
    kind: BackendConfig
    metadata:
      name: config-default
      namespace: airflow
    spec:
      iap:
        enabled: true
        oauthclientCredentials:
          secretName: airflow-iap-secret

上のvaluesを見ていただくとわかるかと思いますが、このvaluesでBackendConfigを定義することによりIAPを利用したアクセスが可能になります。

また、ここまでのGKEにおけるIAPの有効化については以下に詳細が書いています

https://cloud.google.com/iap/docs/enabling-kubernetes-howto

valuesを編集したらhelm upgradeを実行して構成を更新します。

$ helm upgrade airflow \
airflow-stable/airflow \
--values gke-autopilot-values.yaml \
--version 8.5.3 \
--namespace airflow

デプロイ後の動作確認

  1. IAP-secured Web App User を付与したgoogleアカウントでログインできることを確認する
  2. IAP-secured Web App User を付与してないgoogleアカウントでは403となることを確認する

最後に

  • この運用がうまくいくとマネージドAirflowよりコストを抑えることが出来るのでGKEとかhelmとかちょっと頑張れる余力がある場合はおすすめです。
  • valuesに定義してるimageは repository: apache/airflow ですが、これは自身が作成したDAGとDockerfileでbuildし、GCRにpushしたものを使用することも可能です。
  • この記事で作成したsandboxは全部消しました。

Discussion