跳至內容

開始使用 Knative 開源專案 Part 3:API 變更

發布於:2024-05-30

開始使用 Knative 開源專案 Part 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 事件代理 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 時,您需要執行三個步驟。

更新物件的結構。在我們的案例中,我們想要更新 SampleSource 結構。在 Knative 中,這些通常位於 pkg/apis/<groupname>/<version>/<resourcename>_types.go 中。查看此結構,我們可以發現它有一個所有資源通常都遵循的結構

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"`
}

我們新增的只是 MessageTemplate 字串到 Spec。請注意 JSON 標籤 - 這非常重要!如果沒有 JSON 標籤,當控制器從 API 伺服器接收到有關它的資訊時,將不會從 JSON 物件中讀取此欄位,並且該值不會寫入我們傳回 API 伺服器的 JSON 中,因此它不會儲存在 etcd 中。

在更新結構之後,我們通常想要更新 codegen。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 中聯絡我們,我們很樂意提供協助。

我們使用分析和 Cookie 來了解網站流量。您使用我們網站的資訊會與 Google 分享以達到此目的。了解更多。