fbpx

次世代のIaC OSS「Crossplane」のQuickStartを試してみた #Crossplane #Kubernetes #GCP

Infrastructure as Code (IaC) と聞くと、Terraformや、たびたび当方でも紹介するPulumiなどが思い浮かびますが、インフラストラクチャの状態監視が可能と言われる、次世代のIaC OSS「Crossplane」について調査して、実際にGoogleCloudのリソースのプロビジョニングを試してみましたので、簡単にご紹介します。Crossplane初学者である当方ですが、Crossplane自体を詳しく知ったきっかけは 2023年7月20日 ~ 21日に開催された弊社イベント「Engineering All Hands」のLT大会でした(菅野さん、ご紹介いただきありがとうございました)。GoogleCloudでも似たような仕組みに「Anthos Config Management」があり、当方が携わる案件でよく触っているので、Crossplaneはどんなものかと、興味を持った次第です。

Crossplane について

概要

米国シアトルに会社を持つ Upboud が2018年に公開したオープンソースソフトウェアです。コンセプトは以下のように紹介されています(カッコ内はGoogle翻訳したものです)

  • Declarative configuration
    (宣言的な構成)
  • Unify application and infrastructure configuration and deployment
    (アプリケーションとインフラストラクチャの構成と展開を統合)
  • One source of truth for infrastructure configuration and setup
    (インフラストラクチャの構成とセットアップのための 1 つの信頼できる情報源)
  • Automate operational tasks with reconciling controllers
    (調整コントローラーによる運用タスクの自動化)
  • Built with high levels of extensibility
    (高度な拡張性を備えた構築)
  • A strong separation of concerns
    (懸念事項の強力な分離)
https://www.crossplane.io/why-control-planes

他のIaCツールでも似たようなコンセプトはよく見かけますが、特にCrossplaneで特徴的な点として「Automate operational tasks with reconciling controllers (調整コントローラーによる運用タスクの自動化)」が挙げられます。要はインフラストラクチャの状態を監視して、Crossplaneで宣言された状態と差分があれば、都度インフラストラクチャを修正する機能を有するとのことです。その実装として、Kubernetes Resource Model (KRM)を利用して拡張したものが「Crossplane」となり、KRMの宣言型かつ常時調整型の特性をGoogle CloudやAWSなど、複数のクラウドプロバイダにCrossplaneが活用できます。Terraformなどで一度デプロイしたインフラが、何かの拍子に実体のリソース設定が変更されちゃって、Terraformのコードが正しいのか、実体のリソース設定が正しいのか分からないケースが度々あるので、Crossplaneで「調整」してくれるのはとても便利ですね。

Crossplaneの構成要素

Crossplaneのコンセプトとして、以下のように紹介されています。

Packages

Crossplaneの機能を拡張されるものです。CrossplaneはKubernetesを利用するので、Kubernetes CRDs と controller のセットを追加するイメージですね。

Providers

Google Cloud / AWS / Azure などの外部サービスにリソースをプロビジョニングするための、前述のPackageとして提供されるのが Provider になります。サービス × リソース種別 毎に Provider が Crossplane で用意されているので、利用したい Provider があれば以下のようにClusterにインストールします(以下ではGoogle CloudのGCSのProviderをインストール)

$ cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-gcp-storage
spec:
  package: xpkg.upbound.io/upbound/provider-gcp-storage:v0.35.0
EOF

Managed Resources

例えば Google Cloud だと こちらのAPIリファレンスのように、各 Provider (Google Cloudなど) のリソース(Compute Engine Instance / Google Cloud Storage など)と1対1で対応するのがこの Managed Resource で、Kubernetes の Custom Resource になります。例えば Storage Bucket の Managed Resource だと、以下のようなmanifestがCrossplaneにデプロイされることで、Providerを通じて Google Cloud にリソースがプロビジョニングされ、実際にGoogle Cloudにリソースが作成されるイメージです。

apiVersion: storage.gcp.upbound.io/v1beta1
kind: Bucket
metadata:
  annotations:
    meta.upbound.io/example-id: storage/v1beta1/notification
  labels:
    testing.upbound.io/example-name: bucket
  name: bucket-${Rand.RFC1123Subdomain}
spec:
  forProvider:
    location: US

Composite Resources

1つ以上のManaged Resourceから構成されるもので、例えばネットワークに関連する「VPC/Subnet/Routing」などのリソースを1つのComposite Resourceにまとめることができます。他のComposite Resourceを別のComposite Resourceに含めることも可能です。例えば以下では VPC/InternetGateway/Subnet の Managed Resource と、あらかじめ別に作成している Composite Resource を、1つのComposite Resource にまとめています。

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
  resources:
    - name: vpc-resource
      base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: VPC
        # Removed for Brevity
    - name: gateway-resource
      base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: InternetGateway
        # Removed for Brevity
    - name: subnet-resource
      base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: Subnet
        # Removed for Brevity
  compositeTypeRef:
    apiVersion: aws.platformref.upbound.io/v1alpha1
    kind: XNetwork

Anthos Config Managementとの比較

Google Cloud にも似たようなサービスに「Anthos Config Management (ACM)」があります。弊社のBlogでも紹介していますが、ACMは「Policy Controller -> ポリシーチェック機能」「Config Sync -> GitOps機能」「Config Controller -> Google Cloud リソースのプロビジョニング」の3つのコンポーネントで構成されますが、Crossplaneはこのうち(筆者の理解としては)、「Config Controller」の機能に該当すると思います。ただし、ACMはGoogle Cloudのリソースに特化したサービスで、対してCrossplaneはGoogle Cloudの他、AWS/Azure/更にはTerraformなどのProviderが用意されていますので、「Google Cloud以外のサービスについても、1つの control plane を用意したい」場合などは、Crossplaneを試してみても良いかもしれません。ただし、ACMに似たことをCrossplaneで実施する場合、Policy ControllerやConfig Syncなどの機能は、他のThird-partyを利用して自身で組み上げる必要がありますので、Google Cloudのみでの利用を想定している場合は、公式ドキュメントの充実度などを考慮すると、素直にACMを利用した方が良いかもしれません。

Crossplane 試してみた

今回はGoogle Cloudのリソースについて、Crossplaneを利用してプロビジョニングしてみました。基本的な流れは公式のQuickstartをもとに実施しています。

前提

  • Google Cloud リソースを作成可能な一通りの権限を有する (Google Kubernetes Engine Clusterの接続/pods,secreetの作成/Google Compute Engine Instanceの作成)
  • Google Cloud で Project/GKE Clusterを作成済み
  • Kubernetes関連の基本的な知識 (kubectl/Helmの利用など)

構成

  • Google Cloud の 1つのProjectにGKE(Google Kubernetes Engine)/GCE(Google Compute Engine)などの必要なリソースをデプロイします
  • GKEにCrossplaneをデプロイします
  • GCEのManageed ResourceをCrossplaneでデプロイして、実際にGCEのリソースをGoogle Cloudにプロビジョニングします

手順

Crossplane インストール

  • CloudShell を起動して、対象のGKE Clusterに接続します。筆者の環境では project: CloudSolution-Blog の GKE Cluster: cs-cluster-1 に接続しています。
  • Crossplane Helm Chart レポジトリを追加します
$ helm repo add \
crossplane-stable https://charts.crossplane.io/stable

"crossplane-stable" has been added to your repositories
  • Crossplane Helm Chart をインストールします(インストール前に一度dry-run実施)
$ helm install crossplane crossplane-stable/crossplane --dry-run --debug --namespace crossplane-system --create-namespace

---
$ helm install crossplane \
crossplane-stable/crossplane \
--namespace crossplane-system \
--create-namespace

NAME: crossplane
LAST DEPLOYED: Fri Aug 18 08:48:40 2023
NAMESPACE: crossplane-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Release: crossplane

Chart Name: crossplane
Chart Description: Crossplane is an open source Kubernetes add-on that enables platform teams to assemble infrastructure from multiple vendors, and expose higher level self-service APIs for application teams to consume.
Chart Version: 1.13.2
Chart Application Version: 1.13.2

Kube Version: v1.27.3-gke.100
  • Crossplane関連のリソースが起動しているか確認します
$ kubectl get pods -n crossplane-system
NAME                                       READY   STATUS    RESTARTS   AGE
crossplane-8697f8cff4-qgbk5                1/1     Running   0          36s
crossplane-rbac-manager-6f8dbd9ffd-g8wjh   1/1     Running   0          36s
  • Crossplaneに関連するKubernetes APIが新しく追加されているか確認します
$ kubectl api-resources  | grep crossplane
compositeresourcedefinitions      xrd,xrds     apiextensions.crossplane.io/v1         false        CompositeResourceDefinition
compositionrevisions              comprev      apiextensions.crossplane.io/v1         false        CompositionRevision
compositions                      comp         apiextensions.crossplane.io/v1         false        Composition
environmentconfigs                envcfg       apiextensions.crossplane.io/v1alpha1   false        EnvironmentConfig
configurationrevisions                         pkg.crossplane.io/v1                   false        ConfigurationRevision
configurations                                 pkg.crossplane.io/v1                   false        Configuration
controllerconfigs                              pkg.crossplane.io/v1alpha1             false        ControllerConfig
locks                                          pkg.crossplane.io/v1beta1              false        Lock
providerrevisions                              pkg.crossplane.io/v1                   false        ProviderRevision
providers                                      pkg.crossplane.io/v1                   false        Provider
storeconfigs                                   secrets.crossplane.io/v1alpha1         false        StoreConfig

GCP Provider インストール

  • 以下のmanifestでGCP Providerをインストールします
$ cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-gcp-compute
spec:
  package: xpkg.upbound.io/upbound/provider-gcp-compute:v0.35.1
EOF

provider.pkg.crossplane.io/provider-gcp-compute created
  • 該当のProviderがインストールされていることを確認します。ちなみに upbound-provider-family-gcp はFamily Providerと呼ばれていて、Google Cloudの認証を管理するProviderで、GCE以外の全ての(Google Cloud関連の)Providerをインストールしても、このFamily Providerが用意されます。
$ kubectl get provider
NAME                          INSTALLED   HEALTHY   PACKAGE                                                AGE
provider-gcp-compute          True        True      xpkg.upbound.io/upbound/provider-gcp-compute:v0.35.1   9m39s
upbound-provider-family-gcp   True        True      xpkg.upbound.io/upbound/provider-family-gcp:v0.35.1    23m
  • Compute リソースに関連したKubernetes CRDsがインストールされているのを確認します
$ kubectl get crds | grep compute
addresses.compute.gcp.upbound.io                                 2023-08-18T09:22:32Z
attacheddisks.compute.gcp.upbound.io                             2023-08-18T09:22:32Z
autoscalers.compute.gcp.upbound.io                               2023-08-18T09:22:32Z
backendbuckets.compute.gcp.upbound.io                            2023-08-18T09:22:32Z
backendbucketsignedurlkeys.compute.gcp.upbound.io                2023-08-18T09:22:32Z
backendservices.compute.gcp.upbound.io                           2023-08-18T09:22:32Z
backendservicesignedurlkeys.compute.gcp.upbound.io               2023-08-18T09:22:32Z
diskiammembers.compute.gcp.upbound.io                            2023-08-18T09:22:32Z
diskresourcepolicyattachments.compute.gcp.upbound.io             2023-08-18T09:22:32Z
disks.compute.gcp.upbound.io                                     2023-08-18T09:22:32Z
~~~
instancegroupmanagers.compute.gcp.upbound.io                     2023-08-18T09:22:33Z
instancegroupnamedports.compute.gcp.upbound.io                   2023-08-18T09:22:33Z
instancegroups.compute.gcp.upbound.io                            2023-08-18T09:22:33Z
instanceiammembers.compute.gcp.upbound.io                        2023-08-18T09:22:33Z
instances.compute.gcp.upbound.io                                 2023-08-18T09:22:34Z
instancetemplates.compute.gcp.upbound.io                         2023-08-18T09:22:34Z
interconnectattachments.compute.gcp.upbound.io                   2023-08-18T09:22:33Z
managedsslcertificates.compute.gcp.upbound.io                    2023-08-18T09:22:33Z

Kubernetes Secret 作成

ProviderでGoogle Cloudリソースを作成するために必要となるクレデンシャルをKubernetes Secretとして用意します

  • Google Cloud コンソールでService Account を作成します。筆者は「crossplane-sa」という名前でService Accountを作成しました
  • Google Cloud コンソールのIAM画面で、作成したService Accountに「Compute 管理者」ロールを付与します
  • Service Accountの画面に戻って、該当SAの認証鍵(json)を作成します
  • Cloud Shellに戻って、作成した認証鍵(json)をCloud Shellにアップロードします。筆者は分かりやすいように、認証鍵のファイル名を「crossplane-sa.json」に変更してからアップロードしました
  • アップロードした認証鍵(json)をもとに、以下コマンドでKubernetes Secretを作成します。 --from-file には、アップロードした認証鍵のPathを指定します
$ kubectl create secret \
generic gcp-secret \
-n crossplane-system \
--from-file=creds=./crossplane-sa.json

secret/gcp-secret created
  • 作成したsecretを確認します
$ kubectl describe secret gcp-secret -n crossplane-system
Name:         gcp-secret
Namespace:    crossplane-system
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
creds:  2374 bytes

ProviderConfig 作成

Google Cloud Providerをカスタマイズするためのリソース「ProviderConfig」を作成します

  • 以下コマンドで ProviderConfig を作成します。 spec.projectID には、ご自身が用意した Google Cloud Project の ID を指定します(筆者の場合は cloudsolution-blog になります)
$ cat <<EOF | kubectl apply -f -
apiVersion: gcp.upbound.io/v1beta1
kind: ProviderConfig
metadata:
  name: default
spec:
  projectID: cloudsolution-blog
  credentials:
    source: Secret
    secretRef:
      namespace: crossplane-system
      name: gcp-secret
      key: creds
EOF

Managed Resource 作成

一通りの準備が整ったので、いよいよ Managed Resource を作成して、実際にリソースをGoogle Cloudにプロビジョニングします。

  • Compute Engine InstanceのAPIリファレンスを参考に、以下manifestを作成してデプロイします。
cat <<EOF | kubectl create -f -
apiVersion: compute.gcp.upbound.io/v1beta1
kind: Instance
metadata:
  annotations:
    meta.upbound.io/example-id: compute/v1beta1/testinstance
  labels:
    testing.upbound.io/example-name: test-instance
  name: test-instance
spec:
  forProvider:
    bootDisk:
      - initializeParams:
          - image: debian-cloud/debian-11
    machineType: e2-medium
    networkInterface:
      - network: default
    zone: asia-northeast1-a
EOF
  • Kubernetes側でリソースが作成されていることを確認します
$ kubectl get Instance
NAME            READY   SYNCED   EXTERNAL-NAME   AGE
test-instance   True    True     test-instance   33s
  • Google Cloud のコンソール画面で、該当のリソースが無事プロビジョニングされているのが確認できます

Crossplaneによるリソース自動調整確認

「要はインフラストラクチャの状態を監視して、Crossplaneで宣言された状態と差分があれば、都度インフラストラクチャを修正する機能を有する」とのことで、試しにGoogle Cloud側でCrossplaneで作成したリソースの設定を変えてみて、Crossplaneで自動修正されるか確認してみます。

  • Google Cloud コンソールで該当インスタンスを「停止」してから、「編集」をクリックします
  • マシンタイプを「E2」から「N2」に上げて、保存します
  • 保存後、数分(筆者の環境だと 5分くらい)待つと、「N2」から自動的に「E2」に戻るのが確認できました。

自動調整も無事行われていそうですね(ちなみに、一部フィールドは自動調整されないケースがあるようです)

Managed Resource 削除

  • Cloud Shellに戻り、以下コマンドでリソースを削除します。 --selector にリソースのラベルを指定して削除します。
$ kubectl get Instance
NAME            READY   SYNCED   EXTERNAL-NAME   AGE
test-instance   True    True     test-instance   27m

---
$ kubectl delete Instance test-instance
instance.compute.gcp.upbound.io "test-instance" deleted
  • Google Cloud コンソール画面に戻ると、該当インスタンスが削除されているのが確認できます

感想

今回はGoogle CloudリソースのCrossplaneによるプロビジョニングを試してみたのですが、Crossplaneのインストールから実際のリソースプロビジョニングまであまり手間が掛からず、リソースの宣言もyamlで記載することができるので、ヤムラー?(yaml使い)の方にとっても嬉しいポイントではないでしょうか?IaCについてはTerraformが浸透している昨今ですが、ライセンス変更の件もあり、この機会に、色々なIaCツールを試してみたいと思いました。

新規CTA