Knativeによるオープンソース入門 パート3:API変更 ¶
公開日:2024-05-30
Knativeによるオープンソース入門 パート3:API変更¶
著者:Calum Murray ソフトウェアエンジニアリングインターン @ Red Hat、および Leo Li ソフトウェアエンジニアリングインターン @ Red Hat
皆さん、こんにちは。そしてブログシリーズへようこそ!このブログ記事では、Knativeのコードに実際のコード変更を加え始めます。具体的には、KnativeにおけるAPIとは何か、そしてどのように変更できるかを学習します。これと将来のコーディングに焦点を当てたブログ記事を容易にするために、Knativeのサンプルソースコードに基づいた単純なイベントソースを構築します。私たちのソースはサンプルソースと同様に機能し、間隔でイベントを送信しますが、送信される各イベントで変数が設定されるテキストテンプレートを作成できます。このブログ記事の最後までに、KnativeにおけるAPIの理解と、新しい機能(テキストテンプレート)をサポートするようにサンプルソースAPIを変更する方法を習得できるはずです。
APIとは何か?¶
APIは「アプリケーションプログラミングインターフェース」です。アプリケーションがユーザーにインターフェースを提供し、ユーザーはそれを利用してアプリケーションに実行させたい操作をプログラム的に指定できると考えてください。
Knativeでは、APIはKubernetes CustomResourceDefinitions (CRD) の形で存在します。これらは、Knativeがクラスタ内で提供できるリソースの定義です。たとえば、構築中のイベント駆動型アプリケーションにイベントブローカーが必要な場合、Knative Eventing Broker CRDを使用できます。ユーザーはこのAPIと、クラスタ内でカスタムリソースのインスタンスを作成することで対話します。これは、オブジェクトがクラスのインスタンスであるのと同じように考えることができます。カスタムリソースはカスタムリソース定義のインスタンスです。
KubernetesがCRDを認識すると(たとえば、`kubectl apply -f mycrd.yaml`によって)、ユーザーは通常のKubernetesリソースのようにカスタムリソースと対話できます。たとえば、`my-namespace`名前空間内のすべてのブローカーを取得したい場合は、`kubectl get brokers -n my-namespace`を実行できます。これは非常に強力な概念であり、Knativeの哲学の大きな部分を占めています。つまり、ユーザーにKubernetesネイティブなリソースを提供することで、Kubernetes上でアプリケーションをより簡単に構築できるようにします。Knativeでは、CustomResourceDefinitions のコアKubernetes APIを使用してユーザーにAPIを提供することで、Kubernetesネイティブであるという哲学を実現しています。
APIをどのように変更できるか?¶
APIとは何か(一般的に、そしてKnativeの文脈において)が分かったので、APIへの変更方法を探求する準備ができました。APIを更新する際には、実行する必要がある3つのステップがあります。
オブジェクトの構造体を更新します。私たちの場合、SampleSource構造体を更新する必要があります。Knativeでは、これらは多くの場合、`pkg/apis/
v1/
├── apiserver_conversion.go
├── apiserver_conversion_test.go
├── apiserver_defaults.go
├── apiserver_defaults_test.go
├── apiserver_lifecycle.go
// +genclient
// +genreconciler
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type SampleSource struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ObjectMeta `json:"metadata,omitempty"`
// Spec holds the desired state of the SampleSource (from the client).
Spec SampleSourceSpec `json:"spec"`
// Status communicates the observed state of the SampleSource (from the controller).
// +optional
Status SampleSourceStatus `json:"status,omitempty"`
}
このコードを見ると、`metav1.TypeMeta`埋め込み構造体、`metav1.ObjectMeta`埋め込み構造体、そして`Spec`と`Status`埋め込み構造体があることがわかります。これは、Knativeオブジェクト(そしてほとんどのk8sリソース)が構造化される方法です。TypeMetaとObjectMetaは、型とオブジェクトに関するメタデータを提供し、一般的にそれらについて知る必要があるのは、構造体がそれらを含める必要があるということです。SpecとStatusは、実際に変更する構造体です。`Spec`には、Knativeのユーザーに提供するすべてのオプションが格納され、`Status`には、特定のオブジェクトのステータスに関するユーザーに提供するすべての情報が格納されます。
構造体の仕組みが理解できたので、実際の変更を行いましょう。ユーザーが各イベントでメッセージを設定できるように、サンプルソースにメッセージテンプレートフィールドを追加してみてください。「解決策」を読む前に、各コーディングステップを自分で試してみてください。ブログ記事を読み進める中で、この点について改めてお知らせします。
// SampleSourceSpec holds the desired state of the SampleSource (from the client).
type SampleSourceSpec struct {
// inherits duck/v1 SourceSpec, which currently provides:
// * Sink - a reference to an object that will resolve to a domain name or
// a URI directly to use as the sink.
// * CloudEventOverrides - defines overrides to control the output format
// and modifications of the event sent to the sink.
duckv1.SourceSpec `json:",inline"`
// ServiceAccountName holds the name of the Kubernetes service account
// as which the underlying K8s resources should be run. If unspecified
// this will default to the "default" service account for the namespace
// in which the SampleSource exists.
// +optional
ServiceAccountName string `json:"serviceAccountName,omitempty"`
// Interval is the time interval between events.
//
// The string format is a sequence of decimal numbers, each with optional
// fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time
// units are "ns", "us" (or "µs"), "ms", "s", "m", "h". If unspecified
// this will default to "10s".
Interval string `json:"interval"`
// MessageTemplate is the text/template which is used for every event sent.
//
// The string format is any valid go text/template template string where
// the fields are any variables set in the config map
MessageTemplate string `json:"messageTemplate"`
}
追加したのは、`Spec`への`MessageTemplate`文字列だけです。JSONタグに注意してください - これは非常に重要です!JSONタグがないと、コントローラーがAPIサーバーから情報を受け取るときにこのフィールドはJSONオブジェクトから読み取られず、APIサーバーに送り返すJSONにも書き込まれないため、etcdに保存されません。
構造体を更新した後、通常はコードジェネレーターを更新することをお勧めします。Knativeは、カスタムコードジェネレーターを使用して、リコンサイラーの一部(今後のブログ記事で詳しく説明します)と、ディープコピー関数、構造体、自動生成されたAPIドキュメントを自動的に実装します。私たちの場合、SampleSourceSpec構造体のDeepCopy関数を更新する必要があります。Knativeで生成されたコードを更新するには、`./hack/update-codegen.sh`を実行するだけです。特定のリポジトリでこれを実行するために必要な依存関係の特定のバージョンがある場合があるため、開発リポジトリを設定する際には常にDEVELOPMENT.mdファイルを確認してください。
構造体を更新した後、CRD yamlファイルも更新する必要があります。私たちが編集しているCRDは次のようになります。
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
labels:
samples.knative.dev/release: devel
eventing.knative.dev/source: "true"
knative.dev/crd-install: "true"
annotations:
registry.knative.dev/eventTypes: |
[
{ "type": "dev.knative.sample" }
]
name: samplesources.samples.knative.dev
spec:
group: samples.knative.dev
versions:
- &version
name: v1alpha1
served: true
storage: true
subresources:
status: {}
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
interval:
type: string
messageTemplate:
type: string
serviceAccountName:
type: string
sink:
type: object
properties:
ref:
type: object
properties:
apiVersion:
type: string
kind:
type: string
name:
type: string
status:
type: object
properties:
status:
type: string
sinkUri:
type: string
これらの手順に従うことで、新しい機能であるテキストテンプレートをサポートするようにSampleSource APIを正常に変更しました。この変更により、ユーザーはテキストテンプレートを提供できるようになり、今後のブログ記事で、ソースによって送信された各イベントの変数を設定するために使用します。これは、KnativeのAPIシステムの強力さと柔軟性、そして特定のニーズを満たすために拡張できる方法を示しています。
次のブログ記事では、プロジェクトを継続し、サンプルソースのコントローラーの変更方法を学習します。これにより、ユーザーが新しいAPIオプションを使用すると、システム内で実際に何かが変化します!
次回のブログ記事でお会いできるのを楽しみにしています!それまでの間、ご質問がありましたら、#knative-contributorsまでご連絡ください。喜んでお手伝いさせていただきます。