GKE上にAirflowを構築してIAPによるアクセス制御を行う(Autopilot編)
概要
以前書いたこちらの記事で利用しているGKEはスタンダードでしたので、Autopilotでの構築についても書きました。
GKEだけ作り直せばあとは同じかと思っていましたが、WorkLoad Identityの設定やhelm valuesのupdateなども必要でしたのでそれらを追記した上で、手順を上の記事と同様に1から書いたものになります。
事前準備
ドメインの取得
今回はGoogle Domainsにて取得した momota.dev
を使用します
Cloud DNSゾーンの作成
まず、DNSゾーンを作成します。
作成するとNSレコードが自動で作成されているので、そこに記載されているネームサーバーを、登録したドメインレジストラのカスタムネームサーバーに登録して更新をします
カスタムネームサーバーの登録(Google Domainsの場合)
このネームサーバーの変更が反映されるまでに最大48時間ほどかかるようなので事前にしておくと良いです。
外部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
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です)
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のテンプレートはこちらです。
その上で、テンプレを以下のように更新します(ドメイン部分の記述は workflow.momota.dev
で検索して引っかかった箇所を、自分のものに置き換えてください)
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
デプロイ後の動作確認
- GKEのコンソールからワークロード、Service、Ingress全てのコンポーネントがグリーンであることを確認します
- managedcertificateがActiveになっていることを確認します
- managedcertificateがActiveになったあと、イングレスのフロントエンド画面にあるリンクからアクセスできることを確認します
$ kubectl get managedcertificate -n airflow
NAME AGE STATUS
managed-cert 20m Active
ワークロード
Services
Ingress
アクセスの確認
マネージドSSL証明書の詳細
Workload Identityの設定
詳細は以下のdocsに書いてあります
今回、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の有効化については以下に詳細が書いています
valuesを編集したらhelm upgradeを実行して構成を更新します。
$ helm upgrade airflow \
airflow-stable/airflow \
--values gke-autopilot-values.yaml \
--version 8.5.3 \
--namespace airflow
デプロイ後の動作確認
-
IAP-secured Web App User
を付与したgoogleアカウントでログインできることを確認する -
IAP-secured Web App User
を付与してないgoogleアカウントでは403となることを確認する
最後に
- この運用がうまくいくとマネージドAirflowよりコストを抑えることが出来るのでGKEとかhelmとかちょっと頑張れる余力がある場合はおすすめです。
- valuesに定義してるimageは
repository: apache/airflow
ですが、これは自身が作成したDAGとDockerfileでbuildし、GCRにpushしたものを使用することも可能です。 - この記事で作成したsandboxは全部消しました。
Discussion