Crossplane provider for IBM Cloud を使ってみる

[Crossplane infrastructure provider for IBM Cloud](https://github.com/crossplane-contrib/provider-ibm-cloud)を使ってみます。対象はv0.1.1です。なお、Crossplaneはv1.0.0です。


# Crossplaneとは

## 目的

kuberenetesのCustom resources definition (CRD)で様々なクラウドのリソースをkubectlコマンドにより宣言的に払い出し、管理します。Crossplaneでは払い出す環境をProviderといい、少なくともAWS、GCP、Azure、Alibabaが対応しています。それぞれのクラウドにあるデータベースやVPCを作成、管理できるだけでなく、 Open Application Model ([OAM](https://oam.dev/))を実装しアプリケーションも対応します（ただし現在アルファ機能）。なお、１つのAPIで様々なProviderに対応するのではなく、ProviderごとにAPIがあり、当然対応するリソースは異なるので注意が必要です（アプリケーションはその限りではない）。

## 開発状況

現在、Cloud Native Computing Foundation (CNCF) Sandbox プロジェクトです。[Upbound](https://upbound.io/)が開発し公開しました。開発は現在に至るまで、ほぼ[Upbound](https://upbound.io/)により行われています。他には、Alibaba、Qiniu、InfraCloud、Red Hat、Microsoftなどです。

# Crossplane infrastructure provider for IBM Cloudとは

Crossplane infrastructure provider for IBM Cloudは、[Crossplane communityによって管理されているオープンソース](https://github.com/crossplane-contrib/provider-ibm-cloud)の[IBM Cloud](https://cloud.ibm.com)に対応するCrossplaneのproviderです。

# 使ってみる

[Docker Desktop WSL 2 backend](https://docs.docker.com/docker-for-windows/wsl/)を使って、Ubuntu 20.04で実行しました。

## インストールと設定

[Getting Started and Documentation](https://github.com/crossplane-contrib/provider-ibm-cloud#getting-started-and-documentation) に従います。

### IBM Cloud CLIインストールと設定

[IBM Cloud CLI の概説](https://cloud.ibm.com/docs/cli)に従います。

コマンドを実行してIBM Cloud CLIをインストールします。

```bash
curl -sL https://raw.githubusercontent.com/IBM-Cloud/ibm-cloud-developer-tools/master/linux-installer/idt-installer | bash
```

IBMid を使用して IBM Cloud にログインします。 私はフェデレーテッド ID を使用してログインしました。

```bash
$ ibmcloud login --sso
（以降省略）
```

### Crossplaneのインストール

[Install Crossplane](https://crossplane.io/docs/v1.0/getting-started/install-configure.html#install-crossplane)に従います。[Helm](https://helm.sh/)はインストール済であるとします。

```bash
$ kubectl create namespace crossplane-system
namespace/crossplane-system created
$ helm repo add crossplane-stable https://charts.crossplane.io/stable
"crossplane-stable" has been added to your repositories
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "crossplane-stable" chart repository
Update Complete. ⎈Happy Helming!⎈
$ helm install crossplane --namespace crossplane-system crossplane-stable/crossplane
NAME: crossplane
LAST DEPLOYED: Thu Jan 14 16:27:49 2021
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 extends any cluster with the ability to provision and manage cloud infrastructure, services, and applications using kubectl, GitOps, or any tool that works with the Kubernetes API.
Chart Version: 1.0.0
Chart Application Version: 1.0.0

Kube Version: v1.19.3
$
```

Crossplaneの状態を確認します。

```bash
$ helm list -n crossplane-system
NAME            NAMESPACE               REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
crossplane      crossplane-system       1               2021-01-14 16:27:49.2554043 +0900 JST   deployed        crossplane-1.0.0        1.0.0      
```

[Install Crossplane CLI](https://crossplane.io/docs/v1.0/getting-started/install-configure.html#install-crossplane-cli)に従い、Crossplane CLIをインストールします。

```bash
$ curl -sL https://raw.githubusercontent.com/crossplane/crossplane/release-1.0/install.sh | sh
kubectl plugin downloaded successfully! Run the following commands to finish installing it:

sudo mv kubectl-crossplane /usr/local/bin
kubectl crossplane --help

Visit https://crossplane.io to get started. 🚀
Have a nice day! 👋

$
```

```bash
$ sudo mv kubectl-crossplane /usr/local/bin
```

### IBM Cloud Providerのインストール

[Install IBM Cloud Provider](https://github.com/crossplane-contrib/provider-ibm-cloud/tree/v0.1.1#install-ibm-cloud-provider)に従います。

```bash
$ kubectl crossplane install provider crossplane/provider-ibm-cloud:alpha
provider.pkg.crossplane.io/crossplane-provider-ibm-cloud created
$
```

### IBM Cloud API Keyの生成

[Generate IBM Cloud API Key](https://github.com/crossplane-contrib/provider-ibm-cloud/tree/v0.1.1#generate-ibm-cloud-api-key)に従います。

```bash
$ if [[ -z "${IBMCLOUD_API_KEY}" ]]; then
>   echo "*** Generating new APIKey"
>   IBMCLOUD_API_KEY=$(ibmcloud iam api-key-create provider-ibm-cloud-key -d "Key for Crossplane Provider IBM Cloud" | grep "API Key" | awk '{ print $3 }')
> fi
*** Generating new APIKey
Please preserve the API key! It cannot be retrieved after it's created.
$
```

### Provider Secret生成

[Create a Provider Secret](https://github.com/crossplane-contrib/provider-ibm-cloud/tree/v0.1.1#create-a-provider-secret)に従います。

```bash
$ kubectl create secret generic provider-ibm-cloud-secret --from-literal=credentials=${IBMCLOUD_API_KEY} -n crossplane-system
secret/provider-ibm-cloud-secret created
$
```

### Providerの設定

[Configure the Provider](https://github.com/crossplane-contrib/provider-ibm-cloud/tree/v0.1.1#configure-the-provider)に従います。

```bash
$ cat <<EOF | kubectl apply -f -
> apiVersion: ibm-cloud.crossplane.io/v1beta1
> kind: ProviderConfig
> metadata:
>   name: ibm-cloud
> spec:
>   credentials:
>     source: Secret
>     secretRef:
>       namespace: crossplane-system
>       name: provider-ibm-cloud-secret
>       key: credentials
>   region: us-south
> EOF
providerconfig.ibm-cloud.crossplane.io/ibm-cloud created
$
```

作成されたことを確認します。

```bash
$ kubectl get providerconfig
NAME        PROJECT-ID   AGE
ibm-cloud                67s
$
```

## リソースを利用する

それでは実際に使ってみます。v0.1.1 ではまだリソースを作成することができず、すでに作成されたリソースをCrossplaneにインポートすることしかできません。[PostgreSQLの例](https://github.com/crossplane-contrib/provider-ibm-cloud/blob/v0.1.1/examples/resourcecontrollerv2/resource-instance-postgres.yaml)をただ実行しても何も怒らないので注意が必要です。

以降の手順は[Resource Controller V2 API examples](https://github.com/crossplane-contrib/provider-ibm-cloud/tree/v0.1.1/examples/resourcecontrollerv2)に従います。

作成するリソースはなんでもいいですが、CrossplaneのサイトではPostgreSQLを作成する例が載っているため、ここでもPosgreSQLを作成します。

[IBM Cloud Catalog](https://cloud.ibm.com/catalog/services/databases-for-postgresql)から作成します。

作成した後、状態がactiveとなったことを確認します。xxxxxxxxは実際のアカウント名です。

```bash
$ ibmcloud resource service-instances
Retrieving instances with type service_instance in all resource groups in all locations under account xxxxxxxx...
OK
Name                              Location   State    Type   
Databases for PostgreSQL-z5       us-south   active   service_instance   
$
```

マニフェストファイルに埋め込むための環境変数を設定します。

```bash
$ NAME="Databases for PostgreSQL-z5"
$ INFO="$(ibmcloud resource service-instance "${NAME")"}')
$ ID=$(echo "$INFO" | grep ^ID | awk '{print $2}')
$ TARGET=$(echo "$INFO" | grep ^Location | awk '{print $2}')
$ SERVICE_NAME=$(echo "$INFO" | grep "^Service Name" | awk '{print $3}')
$ RG_NAME=$(echo "$INFO" | grep "^Resource Group Name" | awk '{print $4}')
$ RP_NAME=$(echo "$INFO" | grep "^Service Plan Name" | awk '{print $4}')
$ META_NAME=$(echo "$NAME" | awk '{print tolower($0)}' | tr " " - | tr "." -)
$
```

マニフェストファイルを適用します。

```bash
$ cat <<EOF | kubectl apply -f -
> apiVersion: resourcecontrollerv2.ibm-cloud.crossplane.io/v1alpha1
> kind: ResourceInstance
> metadata:
>   name: $META_NAME
>   annotations:
>     crossplane.io/external-name: "$ID"
> spec:
>   forProvider:
>     name: $NAME
>     target: $TARGET
>     resourceGroupName: $RG_NAME
>     serviceName: $SERVICE_NAME
>     resourcePlanName: $RP_NAME
>   providerConfigRef:
>     name: ibm-cloud
> EOF
resourceinstance.resourcecontrollerv2.ibm-cloud.crossplane.io/databases-for-postgresql-z5 created
$ 
```

リソースが作成されたことを確認します。

```bash
$ kubectl get resourceinstance
NAME                          STATUS   STATE    CLASS   AGE
databases-for-postgresql-z5            active           35s
$
```

ただ表示されただけじゃないのか？と思ったので、削除してみます。

```bash
$ kubectl delete resourceinstance databases-for-postgresql-z5
resourceinstance.resourcecontrollerv2.ibm-cloud.crossplane.io "databases-for-postgresql-z5" deleted
```

```
$ kubectl get resourceinstance
No resources found
```
Crossplane上は削除されたようです。

実際に削除されたことを確認します。

```bash
$ ibmcloud resource service-instances
Retrieving instances with type service_instance in all resource groups in all locations under account xxxxxxxx...
OK
No service instance found.
$
```

確かに削除されていました。

# 所感

リソースを作成できず驚きました。今後に期待しましょう。。

# 参考
- https://github.com/crossplane-contrib/provider-ibm-cloud
- [IBM joins the Crossplane community](https://developer.ibm.com/technologies/containers/blogs/ibm-joins-the-crossplane-community/)
- [Crossplane](https://crossplane.io/)
- https://crossplane.devstats.cncf.io/d/5/companies-table