在雲端原生應用程式開發中,有效管理和組合雲端資源至關重要。Crossplane 提供了 Composition 作為一個強大的工具,實作更精細的資源組態和管理。本文將以 PostgreSQL 資料函式庫在 Google Cloud 上的組態為例,探討 Composition 的進階用法,包含如何透過 Composition Selector 進行資源客製化,如何管理資料函式庫連線資訊,以及如何根據不同的雲端供應商(例如 AWS、Azure 和 Google Cloud)調整組態。透過 Composition,開發者可以根據不同的環境或應用程式需求選擇不同的組態,簡化組態流程並提升效率。同時,Crossplane Secret 的使用也確保了連線資訊的安全性和易用性。透過本文的實戰,讀者將能夠更有效地運用 Crossplane Composition,精準組態和管理雲端資源。

擺脫 CRD 的束縛:使用 CompositeResourceDefinition 開發靈活雲端資源組態

在雲端原生應用開發中,CustomResourceDefinition (CRD) 提供了一種擴充套件 Kubernetes API 的強大方式。但當我們需要更進一步,設計跨越多個雲端服務的複合資源時,CompositeResourceDefinition 就成為更合適的選擇。

CompositeResourceDefinition 本質上與建立 CRD 非常相似,但它允許我們定義更高階別的抽象,將多個底層資源組合在一起。這使得使用者可以像操作單一資源一樣管理複雜的雲端服務組合。

讓我們來看看如何利用 CompositeResourceDefinition 的額外特性,修改現有的定義。

kubectl apply --filename compositions/sql-v3/definition.yaml

透過 PatchSet 最佳化資源組態

在定義了 CompositeResourceDefinition 之後,我們可以修改 Composition 來利用這些變更。Composition 定義瞭如何將複合資源轉換為底層的受管資源。

以下是一個修改後的 Composition 範例,展示瞭如何使用 patchSets 來簡化組態:

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
  patchSets:
    - name: metadata
      patches:
        - fromFieldPath: metadata.annotations
          toFieldPath: metadata.annotations
        - fromFieldPath: spec.id
          toFieldPath: metadata.name
  resources:
    - name: sql
      patches:
        - type: PatchSet
          patchSetName: metadata
        - fromFieldPath: spec.parameters.version
          toFieldPath: spec.forProvider.databaseVersion
          transforms:
            - type: string
              string:
                fmt: POSTGRES_%s
        - fromFieldPath: spec.parameters.size
          toFieldPath: spec.forProvider.settings[0].tier
          transforms:
            - type: map
              map:
                small: db-custom-1-3840
                medium: db-custom-16-61440
                large: db-custom-64-245760

內容解密:

  • spec.patchSets: 定義了一組可重複使用的 patches,例如 metadata,用於將 metadata.annotations 從複合資源傳播到受管資源。
  • fromFieldPathtoFieldPath: 定義了資料從複合資源到受管資源的路徑。
  • spec.id: 一個自定義欄位,用於指定資料函式庫資源的唯一識別符。

移除硬編碼,擁抱靈活性

在先前的版本中,spec.resources[0].base.spec.forProvider.rootPasswordSecretRef.name 包含了硬編碼的值 my-db-password。但密碼的名稱應該根據複合資源的名稱,並加上 -password 字尾。因此,我們移除了硬編碼的值,並將在後續步驟中使用更靈活的方法。

類別似地,spec.resources[0].base.spec.forProvider.databaseVersion 也被設定為硬編碼的值 POSTGRES_13。這個值應該由使用者在 version 欄位中指定。tier 欄位也被移除,並將被 size 欄位取代。

使用轉換器適應不同雲平台的特性

不同雲端平台對於資源組態的要求可能有所不同。例如,Google Cloud 要求 PostgreSQL 版本以 POSTGRES_13 的格式指定,而使用者可能更傾向於使用 13 這樣的簡潔格式。

為了適應這種差異,我們可以使用 transforms 來轉換輸入值。例如,以下組態將使用者輸入的版本號轉換為 Google Cloud 要求的格式:

- fromFieldPath: spec.parameters.version
  toFieldPath: spec.forProvider.databaseVersion
  transforms:
    - type: string
      string:
        fmt: POSTGRES_%s

內容解密:

  • transforms.type: string: 指定轉換型別為字串格式化。
  • string.fmt: POSTGRES_%s: 定義字串格式,其中 %s 將被 spec.parameters.version 的值取代。

另一個常見的需求是將使用者友好的值(例如 smallmediumlarge)對映到雲端平台特定的值。這可以使用 transforms.type: map 來實作:

- fromFieldPath: spec.parameters.size
  toFieldPath: spec.forProvider.settings[0].tier
  transforms:
    - type: map
      map:
        small: db-custom-1-3840
        medium: db-custom-16-61440
        large: db-custom-64-245760

內容解密:

  • transforms.type: map: 指定轉換型別為對映。
  • map: 定義輸入值到輸出值的對映關係。

在 AWS 或 Azure 上,您會看到類別似的對映,但具有不同的值,因為它們根據這些雲端平台提供的尺寸。

應用修改後的 Composition

在完成修改後,我們可以應用這些變更:

kubectl apply --filename compositions/sql-v3

整合新功能到 Composite Resource

最後,我們可以將這些新功能整合到我們使用的 Composite Resource 中。玄貓將在後續的文章中展示如何更新 Composite Resource 以利用這些新功能。

總之,CompositeResourceDefinitionComposition 提供了一種強大而靈活的方式來管理雲端資源。透過使用 patchSetstransforms,我們可以簡化組態,並適應不同雲端平台的特性,為使用者提供更友好的體驗。

Crossplane Composition:客製化雲端資源組態的進階

在雲端原生應用程式開發中,Crossplane 提供了一種強大的方式來管理和組合雲端資源。本文將探討 Crossplane Composition 的進階用法,包括如何透過 Composition 自定義資源組態、管理連線資訊,以及如何根據不同的雲端供應商進行調整。

透過 Composition Selector 實作雲端資源客製化

Composition Selector 允許我們根據標籤來選擇不同的 Composition,從而實作更細緻的資源客製化。例如,我們可以根據不同的環境(開發、測試、生產)或不同的應用程式需求,選擇不同的 Composition。

以下是一個 Composition 的範例,它定義了一個 PostgreSQL 資料函式庫在 Google Cloud 上的組態:

apiVersion: devopstoolkitseries.com/v1alpha1
kind: SQL
metadata:
  name: my-db
  annotations:
    organization: DevOps Toolkit
    author: 玄貓 <blackcat@example.com>
spec:
  id: my-db
  compositionSelector:
    matchLabels:
      provider: google
      db: postgresql
  parameters:
    version: "13"
    size: small

在這個範例中,compositionSelector 定義了兩個標籤:provider: googledb: postgresql。這表示只有同時具有這兩個標籤的 Composition 才會被選中。

此外,我們還增加了 metadata.annotations,以便測試我們定義的補丁是否生效。spec.idspec.parameters.versionspec.parameters.size 欄位也被增加進來。

這個設定檔可以被翻譯成:「給我一個在 Google Cloud 上的 PostgreSQL 伺服器,版本是 13,大小是 small,而與我不需要知道 Google Cloud 中哪些節點被歸類別為 small。」

使用者可以更自由地指定重要的內容,而無需處理底層細節和雲端供應商的複雜性。

如果使用 Azure,你會注意到我們將名稱從 my-db 更改為 my-db-2。Azure 不允許對某些資源(如 SQL)重複使用名稱,即使這些資源已被刪除。因此,spec.id 更改為 my-db-2。否則,由於我們已經有 my-db 並將其刪除,因此使用相同的名稱建立一個新的 my-db 將會失敗。

應用 Composite Resource 並追蹤進度

讓我們應用 Composite Resource…

kubectl apply --filename examples/$HYPERSCALER-sql-v3.yaml

…並追蹤進度。

crossplane beta trace sql my-db

以下是輸出的範例(為了簡潔起見,已截斷):

NAME     SYNCED   READY   STATUS
SQL/my-db   True     False   Creating...
├─ DatabaseInstance/my-db   True     False   Creating
└─ User/my-db      False    False   ReconcileError:...

這些資源最終會準備就緒,在等待的同時,我們可以進行一些觀察。

首先,受管資源的名稱現在是 my-db。不再有自動產生的字尾。我們得到這個變更,是因為其中一個補丁確保資源的名稱與我們增加到定義中的新 spec.id 欄位的值相同。使用自動產生的字尾是一個好的做法,可以幫助我們避免衝突,但我喜歡我的資源具有「正確」的名稱,因此我們忽略了「最佳實踐」。

接下來,我們將檢查增加到 Composite Resource 的註解是否確實已增加到受管資源。為此,我們將使用受管資源的完整名稱建立一個環境變數 XR

# 將 `[...]` 替換為受管資源的完整名稱。
export XR=[...]

…並將該資源輸出為 YAML。

kubectl get $XR --output yaml

以下是輸出的範例(為了簡潔起見,已截斷):

apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
metadata:
  annotations:
    author: 玄貓 <blackcat@example.com>
  ...
  organization: DevOps Toolkit
...

我們可以看到,受管資源確實已使用來自 Composite Resource 的註解進行修補。

你可以隨意確認是否也應用了其他補丁,或者 просто trust me when I say that they all did. 我們指定的大小和版本已應用於相關資源。

管理連線資訊:Crossplane Secret 的妙用

現在 PostgreSQL 伺服器已啟動並執行,我們需要弄清楚如何連線到它。否則,擁有一個無法使用的資料函式庫有什麼意義?

Crossplane 可以將受管資源產生的所有金鑰合併到一個 Kubernetes Secret 中。我們只需要告訴它將該 Secret 放在哪裡。

讓我們看一下 Composition 的修改版本。

cat compositions/sql-v4/$HYPERSCALER.yaml

以下是輸出的範例(為了簡潔起見,已截斷):

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
...
spec:
  writeConnectionSecretsToNamespace: crossplane-system
...
resources:
- name: sql
  base:
    apiVersion: sql.gcp.upbound.io/v1beta1
    kind: DatabaseInstance
    spec:
      ...
      writeConnectionSecretToRef:
        namespace: crossplane-system
      patches:
      ...
      - fromFieldPath: spec.id
        toFieldPath: spec.writeConnectionSecretToRef.name
      ...

首先,我們透過 spec.writeConnectionSecretsToNamespace 告訴 Crossplane 將包含透過受管資源產生的所有機密和連線資訊的 Secret 儲存在 crossplane-system 名稱空間中。將該欄位視為 Secret 的預設位置,可以針對特定資源覆寫。

更重要的是,我們透過 spec.resources[0].base.spec.writeConnectionSecretToRef.namespace 值覆寫將儲存 Secret 的名稱空間。這並非真正必要,因為該值 (crossplane-system) 與我們透過 spec.writeConnectionSecretsToNamespace 設定的值相同,但我想展示我們可以從該特定資源覆寫 Secret 的名稱空間。當我們切換到名稱空間範圍的資源時,該功能將變得重要。

最後,由於所有 SQL Secret 都具有相同的名稱將會很愚蠢,因此我們使用修補將該資源的 spec.writeConnectionSecretToRef.name 的值設定為 Composite Resource 中 spec.id 的值。

現在,讓我們應用 Compositions…

kubectl apply --filename compositions/sql-v4

…並輸出 crossplane-system 名稱空間中的 Secrets。

kubectl --namespace crossplane-system get secrets

以下是輸出的範例(為了簡潔起見,已截斷):

NAME             TYPE                                  DATA   AGE
...
my-db             connection.crossplane.io/v1alpha1   10     13s
my-db-password    Opaque                                1      8m24s
...

我們可以看到,除了我們建立的 my-db-password Secret 作為提供初始密碼的方式之外,現在還有 my-db,它應該包含有關如何連線到資料函式庫伺服器的所有資訊。

由於如果你使用 AWS 或 Google Cloud,資料函式庫和 Secret 都稱為 my-db,或者如果你使用 Azure,則稱為 my-db- 加上時間戳記字尾,因此演示存在一些複雜情況。為了減輕這種差異,我們將資料函式庫的名稱儲存到環境變數中。