GKE上にAirflowを構築してIAPによるアクセス制御を行う
GKE autopilot編はこちら
モチベーション
マネージドAirflow(Cloud ComposerとかMWAA)は高いから自前で作って運用出来ないものか
想定している読者
- 上記のモチベーションに共感できる
- kubectlちょっと出来る
- GCPちょっと出来る
- helmちょっと出来る
事前準備
ドメインの取得
今回はGoogle Domainsにて取得した momota.dev
を使用します
Cloud DNSゾーンの作成
まず、DNSゾーンを作成します。
作成するとNSレコードが自動で作成されているので、そこに記載されているネームサーバーを、登録したドメインレジストラのカスタムネームサーバーに登録して更新をします
カスタムネームサーバーの登録(Google Domainsの場合)
このネームサーバーの変更が反映されるまでに最大48時間ほどかかるようなので事前にしておくと良いです。
外部IPの予約
リージョン:グローバルにて外部IPを予約します。
名前は「airflow-v2-web-static-ip」とします(後にこの名前を使用します)
gcloud compute addresses create airflow-v2-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)の作成
GKEが使用するSAを作成します
GKEの作成
SAの部分は置き換えてください
gcloud container clusters create gke-sandbox \
--machine-type=n1-standard-2 \
--num-nodes=1 \
--disk-size=100 \
--region=asia-northeast1 \
--preemptible \
--scopes=cloud-platform \
--enable-cloud-logging \
--enable-stackdriver-kubernetes \
--image-type "COS" \
--service-account "gke-sandbox@<your-project>.iam.gserviceaccount.com"
namespaceの作成
今回は名前空間(namespace)を作成して、そこに構築することにします。
$ kubectl create namespace airflow-v2
namespace/airflow-v2 created
$ kubectl get namespace
NAME STATUS AGE
airflow-v2 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.2です)
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-sandbox-values.yaml
としてvaluesを作成し、変更後はhelm installでデプロイします
$ helm install airflow \
airflow-stable/airflow \
--values gke-sandbox-values.yaml \
--version 8.5.2 \
--namespace airflow-v2
デプロイ後の動作確認
- GKEのコンソールからワークロード、Service、Ingress全てのコンポーネントがグリーンであることを確認します
- managedcertificateがActiveになっていることを確認します
- managedcertificateがActiveになったあと、イングレスのフロントエンド画面にあるリンクからアクセスできることを確認します
$ kubectl get managedcertificate -n airflow-v2
NAME AGE STATUS
managed-cert 20m Active
ワークロード
Services
Ingress
アクセスの確認
マネージドSSL証明書の詳細
認証情報の初期設定
OAuth同意画面を作成します。ユーザーの種類は内部にしておいてください
IAPの有効化
Airflowの構成が正常にデプロイされてるなら、Identity-Aware ProxyのページでIAPが無効になっているリソース( airflow-v2/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-v2
# check
kubectl get secret -n airflow-v2
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-v2
spec:
domains:
- workflow.momota.dev
- apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
name: config-default
namespace: airflow-v2
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-sandbox-values.yaml \
--version 8.5.2 \
--namespace airflow-v2
デプロイ後の動作確認
-
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