返回文章列表

Crossplane Composition:精準組態雲端資源的實戰

本文探討 Crossplane Composition 的進階用法,涵蓋如何利用 Composition Selector 進行資源客製化、管理連線資訊,以及根據不同雲端供應商調整組態。文章以 PostgreSQL 資料函式庫在 Google Cloud 上的組態為例,詳細說明瞭如何定義 Composition、應用

雲端原生 DevOps

在雲端原生應用程式開發中,有效管理和組合雲端資源至關重要。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: 玄貓 <[email protected]>
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: 玄貓 <[email protected]>
  ...
  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- 加上時間戳記字尾,因此演示存在一些複雜情況。為了減輕這種差異,我們將資料函式庫的名稱儲存到環境變數中。