Slide 1

Slide 1 text

#ochacafe FastAPIでKubernetesを 扱うときに役立つTips 2022/12/7 
 
 NTTコミュニケーションズ 奥井
 
 OCHaCafe Season6 #4

Slide 2

Slide 2 text

#ochacafe 自己紹介 NTTコミュニケーションズ Software Engineer 奥井 寛樹 略歴 ● 伝送システムのSDNコントローラ開発 ● DevOpsプラットフォーム開発 ● IoTデータ収集基盤のモダナイゼーション @HirokiOkui 2


Slide 3

Slide 3 text

#ochacafe はじめに ● FastAPIは、型安全性やOASの自動生成機能を備えた ASGIフレームワークで、さっとAPIを作るときに便利です ● Kubernetes API Serverをwrapしてドメインロジックを 追加することで、簡易なXaaSがつくれます ● FastAPIからKubernetes API Serverを叩くときのTipsを4つご紹介します 3
 Frontend API Kubernetes API Server TektonベースのCI/CDaaSを FastAPIを用いて作りました 構成イメージ

Slide 4

Slide 4 text

#ochacafe 1. k8s CRD => API => UI まで一気通貫で型を自動生成 ● FastAPIは、Pydantic型を用いることで「型指向開発」「 OASの自動生成」 「型のランタイム検査」などが可能になる ● datamodel-codegenを用いると、OASやJSON SchemaからPydantic型を 自動生成できる => KubernetesのCRDから、Pydantic型を生成できる ● Pydantic型を用いてAPIを定義するとFastAPIのOASを生成できるため、 openapi-generator-cli などを用いて、UIまで型を生成・流通できる Frontend API Kubernetes API Server k8s Custom Operator openapi-generator api client Pydantic CRD JSONSchema Go Struct datamodel-codegen generate OAS 4
 CIで全自動化 できます

Slide 5

Slide 5 text

#ochacafe 2. kubernetes-clientを型対応する ● Kubernetes API Machinery SIGから提供される公式のPython Client*1は、 typingをサポートしているが、型周りの体験が非常に悪い ● API callのresponseに型がない ○ 汎用のUnion型になる ➞ 都度 型ヒントが必要 ● dot notationで深い要素まで アクセス可能だが、 型がAnyになってしまう 5
 *1: https://github.com/kubernetes-client/python from kubernetes import client from kubernetes.client import V1Namespace v1 = client.CoreV1Api() res = v1.read_namespace('test') # 汎用のUnion型 res: V1Namespace # 型ヒントを書いても ... res.spec # 子要素はAnyになる OpenAPIGeneratorで生成されており、 かつ古いversionのため(v4.3.0) (最新化を検討中:#1943) 実質、構造体の全てのレイヤで 型ヒントが必要に

Slide 6

Slide 6 text

#ochacafe 2. kubernetes-clientを型対応する 6
 ● そもそもFastAPIを使っているので、Pydantic型で扱いたい ○ Pydantic型にすると、ランタイムチェックが効くし、 OASにも反映される ● kubernetes-clientをwrapして、Pydanticに対応する ○ この機能を提供している OSSは(多分)ないので、自作が必要 ○ Sample: https://github.com/hrk091/kubernetes-pydantic ● Tips1の型自動生成を 実現するには、 上記の対応が必要 手間ですが、 FastAPIでk8sを制御 するならやるべき 要望いただければ メンテします 型ヒントなしで型が 決定しており、ネスト先の 型も推論できている

Slide 7

Slide 7 text

#ochacafe 3. kubernetes-clientをasync対応する ● 公式のKubernetes Python Clientは、asyncに対応しているが、デフォルトは同期実行 ● FastAPIのASGIを活かしてPerformance改善するために、asyncモードで動かすと良い ○ k8s API Serverはリクエスト次第でレスポンスが良くないので、 blockingは回避すべし 7
 都度async処理を書くと ドメイン層が汚れるので client内に隠蔽するとよい

Slide 8

Slide 8 text

#ochacafe 4: FastAPIのPerformanceに注意 ● FastAPIは型のランタイム検査もしてくれるため便利だが、 大きなk8s Resourceを扱うと、CPU・メモリの消費がすごい ○ さらに、uvicornのメモリリークもあり、メモリが開放されない ● 型のランタイム検査をトグルする良い方法は現状ない (#5498) ○ 検査対象外にしたい場所で、 Pydantic型の使用をやめるしかない ● 性能が問題になる場合は、レスポンスのフィールドを 減らす工夫が必要 ○ last-applied-configuration、managedFields等は削る ○ 本当に必要なフィールドに限定する 8
 uvicorn v0.18.3で メモリリークが 直ったそうです #1624 *1: https://github.com/tiangolo/fastapi/issues/1624 OOM kill

Slide 9

Slide 9 text

#ochacafe まとめ Tips1: k8s CRD => API => UIまで一気通貫で型を自動生成 Tips2: kubernetes-clientを型対応する Tips3: kubernetes-clientをasync対応する Tips4: FastAPIのPerformanceに注意 9