在雲原生環境中,Kubernetes 提供了名稱空間來隔離資源,但 Crossplane Composite Resources 預設是叢集級別的,這限制了多團隊分享叢集時的資源隔離和管理。Composite Claims 則允許在名稱空間內宣告資源需求,Crossplane 再根據需求建立對應的 Composite Resources,提升了資源管理的靈活性。首先,佈署 Provider,例如 crossplane/provider-sql,Kubernetes Provider 需要組態 ServiceAccount、ClusterRoleBinding 和 ControllerConfig,確保其擁有必要的許可權。透過 kubectl apply 指令佈署 Provider YAML 檔,並確認 PackageRevisions 狀態為 HEALTHY。接著,應用修改後的 Composite,使名稱空間範圍的資源管理生效。最後,使用 psql 客戶端驗證資料函式庫是否成功建立,並確認 Composite Claims 的作用。為了進一步提升資源管理效率,需要從叢集級別的 Composite Resources 切換到名稱空間級別的 Composite Claims。移除原有的 Composite Resource 後,定義 Composite Claims,利用 spec.claimNames 欄位設定 Composite Claims 的種類別,例如 SQLClaim。修改 Composition,使其在套用 Claim 的名稱空間內建立具有資料函式庫驗證的 Secret,實作更精細的資源控制。

玄貓:跨雲組合拳 - 如何用 Crossplane 組建多雲資料函式庫服務

在雲端原生應用程式的世界裡,擁抱多雲策略已成為常態。然而,管理分散在不同雲平台的資源卻是一項挑戰。這時候,Crossplane 就跳出來扮演了關鍵角色,它讓我們能夠以統一的方式管理多個雲平台的資源。今天,玄貓(BlackCat)將帶領大家深入 Crossplane 的 Composition 功能,看看如何透過它來組建一個跨雲的 PostgreSQL 資料函式庫服務。

為何需要統一 Secret 格式?玄貓的解讀

在開始之前,讓玄貓(BlackCat)先問大家一個問題:當我們在不同的雲平台上建立資料函式庫服務時,每個雲平台提供的 Secret 格式可能都不一樣,這會造成什麼問題?

答案是:這會讓我們的應用程式需要針對不同的雲平台進行客製化,增加了複雜度和維護成本。因此,統一 Secret 格式是實作跨雲應用程式的關鍵一步。

接下來,玄貓(BlackCat)將以 Google Cloud 為例,展示如何從 Secret 中提取所需的資訊。

Google Cloud Secret 解碼:玄貓帶你一步步來

在 Google Cloud 中,Crossplane 產生的 Secret 包含了連線到資料函式庫所需的各種資訊,例如密碼和 Public IP。不過,這些資訊都是經過 Base64 編碼的,所以我們需要先將它們解碼才能使用。

以下是一個 Secret 範例:

apiVersion: v1
data:
  attribute.root_password: cG9zdGdyZXM=
  connectionName: ZG90LTIwMjQwMTAzMTk0MDU2OnVzLWVhc3QxOm15LWRi
  password: cG9zdGdyZXM=
  privateIP: ""
  publicIP: MzUuMTk2LjQ3LjEwNQ==
  serverCACertificateCert: LS0tLS1CRUd...
  serverCACertificateCommonName: Qz1VUyxP...=
  serverCACertificateCreateTime: MjAyNC0wMS0wM1QxOT...
  serverCACertificateExpirationTime: MjAzMy0xMi0zMV...
  serverCACertificateSha1Fingerprint: OWMyNzVjNjB...
kind: Secret
...

要解碼這些資訊,可以使用 kubectl 指令:

export PGUSER=postgres
export PGPASSWORD=$(kubectl --namespace crossplane-system \
get secret $DB --output jsonpath="{.data.password}" \
| base64 -d)
export HOST_KEY=publicIP
export PGHOST=$(kubectl --namespace crossplane-system \
get secret $DB --output jsonpath="{.data.$HOST_KEY}" \
| base64 -d)

解碼後,我們就可以使用這些資訊來連線到資料函式庫了。

跨雲連線:玄貓教你如何組合不同 Provider

有了資料函式庫伺服器,下一步當然是連線到它並確認其運作正常。玄貓(BlackCat)在這裡要強調的是,由於不同雲平台 Secret 的格式差異,我們需要針對不同的雲平台執行不同的指令。

以下是在不同雲平台上取得資料函式庫資訊的指令:

  • Azure/AWS:
    export PGUSER=$(kubectl --namespace crossplane-system \
    get secret $DB --output jsonpath="{.data.username}" \
    | base64 -d)
    
  • Google Cloud:
    export PGUSER=postgres
    

取得密碼的指令:

export PGPASSWORD=$(kubectl --namespace crossplane-system \
get secret $DB --output jsonpath="{.data.password}" \
| base64 -d)

取得 Host Key 的指令:

  • Azure:
    export HOST_KEY=endpoint
    
  • AWS:
    export HOST_KEY=host
    
  • Google Cloud:
    export HOST_KEY=publicIP
    

最後,取得 Host 的指令:

export PGHOST=$(kubectl --namespace crossplane-system \
get secret $DB --output jsonpath="{.data.$HOST_KEY}" \
| base64 -d)

現在,我們可以使用這些資訊來連線到資料函式庫了。為了方便起見,玄貓(BlackCat)建議大家可以使用 bitnami/postgresql 映象來執行 psql

kubectl run postgresql-client --rm -ti --restart='Never' \
--image docker.io/bitnami/postgresql:16 \
--env PGPASSWORD=$PGPASSWORD --env PGHOST=$PGHOST \
--env PGUSER=$PGUSER --command -- sh

進入容器後,就可以執行 psql 指令來連線到遠端的 PostgreSQL 伺服器:

psql --host $PGHOST -U $PGUSER -d postgres -p 5432

擴充套件 Composition:玄貓帶你開發統一 Secret 格式

到目前為止,我們只能看到系統層級的資料函式庫,而沒有一個可以讓應用程式使用的資料函式庫。此外,不同雲平台 Secret 的格式差異也增加了管理的複雜度。因此,我們需要擴充套件 Composition,以便在 PostgreSQL 伺服器中建立資料函式庫,並提供統一的 Secret 格式。

幸運的是,Crossplane 允許我們在 Composition 中組合不同的 Provider。例如,我們可以同時使用 Google Cloud Provider 和 SQL Provider。

以下是一個擴充套件後的 Composition 範例:

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: google-postgresql
spec:
  ...
  resources:
  ...
  - name: sql-config
    base:
      apiVersion: postgresql.sql.crossplane.io/v1alpha1
      kind: ProviderConfig
      metadata:
        name: default
      spec:
        credentials:
          source: PostgreSQLConnectionSecret
          connectionSecretRef:
            namespace: crossplane-system
        sslMode: require
    patches:
    - type: PatchSet
      patchSetName: metadata
    - fromFieldPath: spec.id
      toFieldPath: spec.credentials.connectionSecretRef.name
  ...

在這個範例中,我們新增了一個名為 sql-config 的資源,它是一個 SQL ProviderConfig。這個 Config 使用來自 Secret 的憑證來驗證 PostgreSQL 伺服器。

玄貓(BlackCat)在這裡要提醒大家,SQL ProviderConfig 期望 Secret 採用特定的格式。因此,除了需要統一不同雲平台 Secret 的格式之外,我們還需要確保 Secret 的格式符合 SQL ProviderConfig 的要求。

深入解析 Crossplane Composition:資源組態與 Kubernetes 整合

在雲原生應用程式的佈署和管理中,Crossplane 提供了一種強大的方式來定義和組合基礎設施資源。作為玄貓,我將帶領大家深入瞭解 Crossplane Composition,特別是如何組態資源以及與 Kubernetes 整合。

Composition 的核心概念

Composition 允許我們將多個基礎設施資源定義為一個單元,從而簡化應用程式的佈署和管理。透過 Composition,我們可以定義資源之間的依賴關係、組態引數以及自動化的佈署流程。

ProviderConfig:連線 SQL Provider

首先,我們需要設定 ProviderConfig,以便 SQL Provider 可以與 PostgreSQL 資料函式庫伺服器進行通訊。這就像設定資料函式庫連線,確保 Crossplane 能夠正確地管理資料函式庫資源。

Database Managed Resource:建立資料函式庫

接下來,我們新增 Database Managed Resource,並確保它使用正確的設定。這可以透過 Patching spec.providerConfigRef.name 來實作,使用 spec.id 的值。這個資源會建立並管理一個與資源本身同名的資料函式庫。

Kubernetes ProviderConfig:連線 Kubernetes 叢集

為了能夠建立 Kubernetes 資源(包括 Secrets),我們需要設定 ProviderConfig,告訴 Kubernetes Provider 如何找到要建立 Secret 的叢集。透過設定 sourceInjectedIdentity,我們可以讓 Provider 在正在執行的叢集中管理資源。

Object Resource:建立 Kubernetes Secret

最後,我們建立一個 Object,它可以是任何 Kubernetes 資源。在這個例子中,我們建立一個 Secret,其中 port 硬編碼為 5432。更有趣的是 references 區段,它允許我們從 Kubernetes 叢集中的任何資源取得資訊,並將其新增到 Secret 中。

例如,我們可以從 User 資源取得使用者名稱,從其他 Secret 取得密碼和端點。這些值會透過 patchesFrom 進行設定,並透過 patches 來 Patching patchesFrom

佈署 Providers

我們需要佈署這些 Providers。對於 Kubernetes Provider,我們需要額外設定 ServiceAccountClusterRoleBindingControllerConfig,以確保 Provider 具有足夠的許可權來管理 Kubernetes 資源。

以下是 Kubernetes Provider 的設定範例:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: crossplane-provider-kubernetes
  namespace: crossplane-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: crossplane-provider-kubernetes
subjects:
  - kind: ServiceAccount
    name: crossplane-provider-kubernetes
    namespace: crossplane-system
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: pkg.crossplane.io/v1alpha1
kind: ControllerConfig
metadata:
  name: crossplane-provider-kubernetes
spec:
  serviceAccountName: crossplane-provider-kubernetes
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: crossplane-provider-kubernetes
spec:
  package: xpkg.upbound.io/crossplane-contrib/provider-kubernetes:v0.9.0
  controllerConfigRef:
    name: crossplane-provider-kubernetes

內容解密

  • ServiceAccount:為 Kubernetes Provider 建立一個服務帳戶,以便它可以與 Kubernetes API 進行互動。
  • ClusterRoleBinding:將 cluster-admin 角色繫結到服務帳戶,授予 Provider 管理叢集中所有資源的許可權。
  • ControllerConfig:設定 Provider 的控制器組態,指定要使用的服務帳戶。
  • Provider:佈署 Kubernetes Provider,指定要使用的套件和控制器組態。

玄貓觀點

從玄貓的角度來看,Crossplane Composition 提供了一種強大而靈活的方式來管理雲原生應用程式的基礎設施。透過將多個資源定義為一個單元,我們可以簡化佈署和管理流程,並確保資源之間的一致性和可靠性。此外,透過與 Kubernetes 的整合,我們可以利用 Kubernetes 的強大功能來管理應用程式的各個方面。

總之,Crossplane Composition 是一個值得深入研究和應用的技術,它可以幫助我們更好地管理雲原生應用程式,並提高開發和維運效率。

Kubernetes 擴充套件:使用 Crossplane Composite Claims 實作名稱空間級別的 SQL 管理

在雲原生架構中,Kubernetes 作為容器協調平台已經被廣泛採用。然而,當涉及到跨多個雲平台的資源管理時,挑戰依然存在。Crossplane 是一個開源的 Kubernetes 擴充套件,它允許我們使用 Kubernetes 的宣告式 API 來管理任何基礎設施。在先前的文章中,玄貓(BlackCat)介紹瞭如何使用 Crossplane Composite Resources(XR)來建立和管理 SQL 伺服器。但那些資源都是叢集範圍的,這在某些情況下可能不夠靈活。本文將探討如何使用 Crossplane Composite Claims,將資源的管理範圍限定在名稱空間(Namespace)內,從而提供更好的隔離性和控制。

從叢集級別到名稱空間級別:為何需要 Composite Claims?

在 Kubernetes 中,名稱空間是用於隔離叢集資源的一種機制。每個名稱空間都可以有自己的 RBAC 策略、資源配額等。當多個團隊分享一個 Kubernetes 叢集時,使用名稱空間可以有效地避免資源衝突和許可權混亂。

然而,Crossplane Composite Resources 預設是叢集範圍的,這意味著它們不受名稱空間的限制。這在某些情況下可能不理想。例如,如果我們希望每個團隊都能夠在自己的名稱空間中建立和管理 SQL 伺服器,那麼使用叢集範圍的 Composite Resources 就無法實作這種隔離。

這時,Composite Claims 就派上用場了。Composite Claims 允許我們在名稱空間中宣告資源需求,然後 Crossplane 會根據這些需求建立相應的 Composite Resources。這樣,我們就可以將資源的管理範圍限定在名稱空間內,從而提供更好的隔離性和控制。

佈署 Provider

首先,我們要先佈署好 Provider,這裡以 crossplane/provider-sql 為例。Kubernetes Provider 比較複雜,因為需要授權它透過 Kubernetes API 建立資源。以下是具體步驟:

  1. 建立 ServiceAccount 和 ClusterRoleBinding
apiVersion: v1
kind: ServiceAccount
metadata:
  name: crossplane-kubernetes-provider
  namespace: crossplane-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: crossplane-kubernetes-provider
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: crossplane-kubernetes-provider
  namespace: crossplane-system

這段 YAML 建立了一個 ServiceAccount,並授予它叢集管理員許可權。玄貓(BlackCat)認為,在實際生產環境中,應該遵循最小許可權原則,僅授予必要的許可權。

  1. 建立 ControllerConfig
apiVersion: pkg.crossplane.io/v1
kind: ControllerConfig
metadata:
  name: crossplane-kubernetes-provider
  namespace: crossplane-system
spec:
  serviceAccountName: crossplane-kubernetes-provider

ControllerConfig 參照了前面建立的 ServiceAccount。

  1. 佈署 Kubernetes Provider
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-kubernetes
spec:
  package: crossplane/provider-kubernetes:v0.14.0
  controllerConfigRef:
    name: crossplane-kubernetes-provider

這個 Provider 透過 controllerConfigRef 使用了 ControllerConfig。

佈署這些 Provider:

kubectl apply --filename providers/sql-v5.yaml
kubectl apply --filename providers/kubernetes.yaml

確認所有 PackageRevisions 都處於 HEALTHY 狀態:

kubectl get pkgrev

應用 Composite

一旦 Provider 準備就緒,我們就可以應用修改後的 Composite。

kubectl apply --filename compositions/sql-v5

現在,我們可以回到 container 中,使用 psql 客戶端來驗證資料函式庫是否已成功建立。

kubectl run postgresql-client --rm -ti --restart='Never' \
--image docker.io/bitnami/postgresql:16 \
--env PGPASSWORD=$PGPASSWORD --env PGHOST=$PGHOST \
--env PGUSER=$PGUSER --command -- sh

進入客戶端:

psql --host $PGHOST -U $PGUSER -d postgres -p 5432

列出所有資料函式庫:

\l

預期輸出(已截斷):

Name      | Owner        |...
---
-
---
-
---
-
---
+
---
-
---
-
---
-
---
-
---
+...
cloudsqladmin | cloudsqladmin      |...
my-db         | my-db            |...
postgres      | cloudsqlsuperuser  |...
template0   | cloudsqladmin      |...
template1   | cloudsqlsuperuser  |...
(5 rows)

可以看到,這次多了一個名為 my-db 的資料函式庫。這表示任務成功了。從現在開始,每次有人選擇在任何超大規模雲端服務商中建立 PostgreSQL 伺服器時,都會建立一個具有統一格式的資料函式庫和 Secret。

從 Composite Resources 到 Composite Claims

雖然前面的方法可行,但它仍然不是一個好的解決方案,因為我們需要從叢集範圍的 Composite Resources 切換到名稱空間範圍的 Composite Claims。不過,在執行此操作之前,讓我們先移除 Composite Resource,以便重新開始。

exit
exit
kubectl delete --filename examples/$HYPERSCALER-sql-v3.yaml
kubectl get managed

可能需要一些時間才能刪除所有 Managed Resources。因此,請重複執行 kubectl get managed 命令,直到看到所有內容都已消失。

如果資料函式庫伺服器先被刪除,則可能無法刪除資料函式庫。如果發生這種情況,請執行以下命令:

kubectl patch database.postgresql.sql.crossplane.io $DB \
--patch '{"metadata":{"finalizers":[]}}' --type=merge

定義 Composite Claims

到目前為止,我們建立的所有資源都是叢集範圍的。這意味著它們是在叢集層級進行管理,而不是在名稱空間內。這可能會產生問題,因為名稱空間通常用於分離團隊或資源型別、應用 RBAC 和策略,以及我們通常在 Kubernetes 中執行的許多其他操作。

不幸的是,我們無法變更 Composite 和 Managed Resources 的範圍。它們始終是叢集範圍的。但是,我們可以將新型的 Crossplane 資源新增到組閤中。我們可以使用 Composite Claims,它們是名稱空間範圍的,可用於建立 Composite Resources。不僅如此,透過 Claims,我們還可以更好地控制 Secrets、Objects 和其他名稱空間範圍資源的位置。

讓我們再次看看先前套用的 Composite Resource Definition。

cat compositions/sql-v5/definition.yaml

輸出如下(已截斷):

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: sqls.devopstoolkitseries.com
spec:
  ...
  names:
    kind: SQL
    plural: sqls
  claimNames:
    kind: SQLClaim
    plural: sqlclaims
  ...

spec.names 欄位是我們用作 Composite Resources 種類別的欄位。在其下方是 spec.claimNames,它對 Composite Claims 執行相同的操作。

就這樣。我們不需要執行任何「特殊」操作。透過 spec.claimNames,我們可以建立名稱空間範圍的 Claims,而不是直接使用叢集範圍的 Compositions。在這種情況下,我們只需將種類別設定為 SQLClaim 而不是 SQL。因此,我們可以立即建立 Claim,但我們暫時不會這麼做。相反,我們將對 Compositions 進行一些修改。具體來說,我們將變更 Compositions,以便在我們將套用 Claim 的相同名稱空間中建立具有資料函式庫驗證的 Secret。

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

cat compositions/sql-v6/$HYPERSCALER.yaml