GCP Quickstart

Connect Crossplane to Google GCP to create and manage cloud resources from Kubernetes with the GCP Official Provider.

This guide walks you through the steps required to get started with the GCP Official Provider. This includes installing Upbound Universal Crossplane, configuring the provider to authenticate to GCP and creating a Managed Resource in GCP directly from your Kubernetes cluster.

Prerequisites

This quickstart requires:

  • a Kubernetes cluster with at least 3 GB of RAM
  • permissions to create pods and secrets in the Kubernetes cluster
  • a GCP account with permissions to create a storage bucket
  • GCP account keys
  • GCP Project ID
If you don’t have a Kubernetes cluster create one locally with minikube or kind.

Guided tour

All commands use the current kubeconfig context and configuration.

You need your:

  • GCP service account key

Install the Up command-line

The Up command-line helps manage Upbound Universal Crossplane, Upbound’s enterprise Crossplane distribution and manage Upbound user accounts.

Download and install the Upbound up command-line.

1
2
curl -sL "https://cli.upbound.io" | sh
sudo mv up /usr/local/bin/

Install Upbound Universal Crossplane

Upbound Universal Crossplane (UXP) consists of upstream Crossplane and Upbound-specific enhancements and patches. It’s open source and maintained by Upbound.

Install UXP with the Up command-line up uxp install command.

1
2
up uxp install
UXP 1.9.1-up.2 installed

Verify all UXP pods are Running with kubectl get pods -n upbound-system. This may take up to five minutes depending on your Kubernetes cluster.

1
2
3
4
5
6
kubectl get pods -n upbound-system
NAME                                        READY   STATUS    RESTARTS      AGE
crossplane-7fdfbd897c-pmrml                 1/1     Running   0             68m
crossplane-rbac-manager-7d6867bc4d-v7wpb    1/1     Running   0             68m
upbound-bootstrapper-5f47977d54-t8kvk       1/1     Running   0             68m
xgql-7c4b74c458-5bf2q                       1/1     Running   3 (67m ago)   68m
RESTARTS for the xgql pod are normal during initial installation.

For more details about UXP pods, read the UXP section.

Installing UXP and Crossplane creates new Kubernetes API end-points. Take a look at the new API end-points with kubectl api-resources | grep crossplane. In a later step you use the Provider resource install the Official Provider.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
kubectl api-resources  | grep crossplane
compositeresourcedefinitions      xrd,xrds     apiextensions.crossplane.io/v1         false        CompositeResourceDefinition
compositionrevisions                           apiextensions.crossplane.io/v1alpha1   false        CompositionRevision
compositions                                   apiextensions.crossplane.io/v1         false        Composition
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

Install the official GCP provider

Install the official provider into the Kubernetes cluster with the up command-line or a Kubernetes configuration file.

1
2
3
up controlplane \
provider install \
xpkg.upbound.io/upbound/provider-gcp:v0.15.0
1
2
3
4
5
6
7
8
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: upbound-provider-gcp
spec:
  package: xpkg.upbound.io/upbound/provider-gcp:v0.15.0
EOF

The kind: Provider uses the Crossplane Provider Custom Resource Definition to connect your Kubernetes cluster to your cloud provider.

Verify the provider installed with kubectl get providers.

It may take up to five minutes for the provider to list HEALTHY as True.
1
2
3
kubectl get providers
NAME                   INSTALLED   HEALTHY   PACKAGE                                        AGE
upbound-provider-gcp   True        False     xpkg.upbound.io/upbound/provider-gcp:v0.15.0   8s

A provider installs their own Kubernetes Custom Resource Definitions (CRDs). These CRDs allow you to create GCP resources directly inside Kubernetes.

You can view the new CRDs with kubectl get crds. Every CRD maps to a unique GCP service Crossplane can provision and manage.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
kubectl get crds
NAME                                                               CREATED AT
addresses.compute.gcp.upbound.io                                   2022-10-12T19:45:38Z
agents.dialogflowcx.gcp.upbound.io                                 2022-10-12T19:45:39Z
alertpolicies.monitoring.gcp.upbound.io                            2022-10-12T19:45:40Z
applications.appengine.gcp.upbound.io                              2022-10-12T19:45:37Z
attacheddisks.compute.gcp.upbound.io                               2022-10-12T19:45:38Z
autoscalers.compute.gcp.upbound.io                                 2022-10-12T19:45:38Z
backendbuckets.compute.gcp.upbound.io                              2022-10-12T19:45:38Z
backendbucketsignedurlkeys.compute.gcp.upbound.io                  2022-10-12T19:45:38Z
backendservices.compute.gcp.upbound.io                             2022-10-12T19:45:38Z
bucketaccesscontrols.storage.gcp.upbound.io                        2022-10-12T19:45:41Z
bucketacls.storage.gcp.upbound.io                                  2022-10-12T19:45:41Z
bucketiammembers.storage.gcp.upbound.io                            2022-10-12T19:45:41Z
bucketobjects.storage.gcp.upbound.io                               2022-10-12T19:45:41Z
buckets.storage.gcp.upbound.io                                     2022-10-12T19:45:41Z
capooliammembers.privateca.gcp.upbound.io                          2022-10-12T19:45:40Z
capools.privateca.gcp.upbound.io                                   2022-10-12T19:45:40Z
certificateauthorities.privateca.gcp.upbound.io                    2022-10-12T19:45:41Z
certificates.privateca.gcp.upbound.io                              2022-10-12T19:45:41Z
certificatetemplateiammembers.privateca.gcp.upbound.io             2022-10-12T19:45:41Z
certificatetemplates.privateca.gcp.upbound.io                      2022-10-12T19:45:41Z
clients.containerazure.gcp.upbound.io                              2022-10-12T19:45:39Z
clusters.container.gcp.upbound.io                                  2022-10-12T19:45:39Z
clusters.containeraws.gcp.upbound.io                               2022-10-12T19:45:39Z
clusters.containerazure.gcp.upbound.io                             2022-10-12T19:45:39Z
compositeresourcedefinitions.apiextensions.crossplane.io           2022-10-12T19:44:47Z
compositionrevisions.apiextensions.crossplane.io                   2022-10-12T19:44:47Z
compositions.apiextensions.crossplane.io                           2022-10-12T19:44:47Z
configurationrevisions.pkg.crossplane.io                           2022-10-12T19:44:47Z
configurations.pkg.crossplane.io                                   2022-10-12T19:44:47Z
connections.servicenetworking.gcp.upbound.io                       2022-10-12T19:45:41Z
consentstores.healthcare.gcp.upbound.io                            2022-10-12T19:45:40Z
contacts.essentialcontacts.gcp.upbound.io                          2022-10-12T19:45:40Z
controllerconfigs.pkg.crossplane.io                                2022-10-12T19:44:47Z
cryptokeyiammembers.kms.gcp.upbound.io                             2022-10-12T19:45:40Z
cryptokeys.kms.gcp.upbound.io                                      2022-10-12T19:45:40Z
databaseiammembers.spanner.gcp.upbound.io                          2022-10-12T19:45:41Z
databaseinstances.sql.gcp.upbound.io                               2022-10-12T19:45:41Z
databases.spanner.gcp.upbound.io                                   2022-10-12T19:45:41Z
databases.sql.gcp.upbound.io                                       2022-10-12T19:45:41Z
datasets.healthcare.gcp.upbound.io                                 2022-10-12T19:45:40Z
defaultobjectaccesscontrols.storage.gcp.upbound.io                 2022-10-12T19:45:41Z
defaultobjectacls.storage.gcp.upbound.io                           2022-10-12T19:45:41Z
defaultsupportedidpconfigs.identityplatform.gcp.upbound.io         2022-10-12T19:45:40Z
diskiammembers.compute.gcp.upbound.io                              2022-10-12T19:45:38Z
diskresourcepolicyattachments.compute.gcp.upbound.io               2022-10-12T19:45:38Z
disks.compute.gcp.upbound.io                                       2022-10-12T19:45:38Z
domainmappings.cloudrun.gcp.upbound.io                             2022-10-12T19:45:38Z
entitytypes.dialogflowcx.gcp.upbound.io                            2022-10-12T19:45:40Z
entries.datacatalog.gcp.upbound.io                                 2022-10-12T19:45:39Z
entrygroups.datacatalog.gcp.upbound.io                             2022-10-12T19:45:39Z
environments.composer.gcp.upbound.io                               2022-10-12T19:45:38Z
environments.dialogflowcx.gcp.upbound.io                           2022-10-12T19:45:39Z
environments.notebooks.gcp.upbound.io                              2022-10-12T19:45:40Z
externalvpngateways.compute.gcp.upbound.io                         2022-10-12T19:45:38Z
firewallpolicies.compute.gcp.upbound.io                            2022-10-12T19:45:38Z
firewallpolicyassociations.compute.gcp.upbound.io                  2022-10-12T19:45:38Z
firewallpolicyrules.compute.gcp.upbound.io                         2022-10-12T19:45:38Z
firewalls.compute.gcp.upbound.io                                   2022-10-12T19:45:38Z
flows.dialogflowcx.gcp.upbound.io                                  2022-10-12T19:45:40Z
folders.cloudplatform.gcp.upbound.io                               2022-10-12T19:45:37Z
forwardingrules.compute.gcp.upbound.io                             2022-10-12T19:45:38Z
functioniammembers.cloudfunctions.gcp.upbound.io                   2022-10-12T19:45:37Z
functions.cloudfunctions.gcp.upbound.io                            2022-10-12T19:45:37Z
globaladdresses.compute.gcp.upbound.io                             2022-10-12T19:45:38Z
globalforwardingrules.compute.gcp.upbound.io                       2022-10-12T19:45:38Z
globalnetworkendpointgroups.compute.gcp.upbound.io                 2022-10-12T19:45:38Z
globalnetworkendpoints.compute.gcp.upbound.io                      2022-10-12T19:45:38Z
havpngateways.compute.gcp.upbound.io                               2022-10-12T19:45:38Z
healthchecks.compute.gcp.upbound.io                                2022-10-12T19:45:38Z
httphealthchecks.compute.gcp.upbound.io                            2022-10-12T19:45:38Z
httpshealthchecks.compute.gcp.upbound.io                           2022-10-12T19:45:38Z
imageiammembers.compute.gcp.upbound.io                             2022-10-12T19:45:38Z
images.compute.gcp.upbound.io                                      2022-10-12T19:45:38Z
inboundsamlconfigs.identityplatform.gcp.upbound.io                 2022-10-12T19:45:40Z
instancefromtemplates.compute.gcp.upbound.io                       2022-10-12T19:45:38Z
instancegroupmanagers.compute.gcp.upbound.io                       2022-10-12T19:45:38Z
instancegroupnamedports.compute.gcp.upbound.io                     2022-10-12T19:45:38Z
instancegroups.compute.gcp.upbound.io                              2022-10-12T19:45:38Z
instanceiammembers.compute.gcp.upbound.io                          2022-10-12T19:45:38Z
instanceiammembers.notebooks.gcp.upbound.io                        2022-10-12T19:45:40Z
instanceiammembers.spanner.gcp.upbound.io                          2022-10-12T19:45:41Z
instances.compute.gcp.upbound.io                                   2022-10-12T19:45:38Z
instances.filestore.gcp.upbound.io                                 2022-10-12T19:45:40Z
instances.notebooks.gcp.upbound.io                                 2022-10-12T19:45:40Z
instances.redis.gcp.upbound.io                                     2022-10-12T19:45:41Z
instances.spanner.gcp.upbound.io                                   2022-10-12T19:45:41Z
instancetemplates.compute.gcp.upbound.io                           2022-10-12T19:45:38Z
intents.dialogflowcx.gcp.upbound.io                                2022-10-12T19:45:40Z
interconnectattachments.compute.gcp.upbound.io                     2022-10-12T19:45:38Z
jobs.cloudscheduler.gcp.upbound.io                                 2022-10-12T19:45:38Z
keyringiammembers.kms.gcp.upbound.io                               2022-10-12T19:45:40Z
keyringimportjobs.kms.gcp.upbound.io                               2022-10-12T19:45:40Z
keyrings.kms.gcp.upbound.io                                        2022-10-12T19:45:40Z
litereservations.pubsub.gcp.upbound.io                             2022-10-12T19:45:41Z
litesubscriptions.pubsub.gcp.upbound.io                            2022-10-12T19:45:41Z
litetopics.pubsub.gcp.upbound.io                                   2022-10-12T19:45:41Z
locks.pkg.crossplane.io                                            2022-10-12T19:44:47Z
managedsslcertificates.compute.gcp.upbound.io                      2022-10-12T19:45:38Z
managedzones.dns.gcp.upbound.io                                    2022-10-12T19:45:40Z
memberships.gkehub.gcp.upbound.io                                  2022-10-12T19:45:40Z
networkendpointgroups.compute.gcp.upbound.io                       2022-10-12T19:45:38Z
networkendpoints.compute.gcp.upbound.io                            2022-10-12T19:45:38Z
networkpeeringroutesconfigs.compute.gcp.upbound.io                 2022-10-12T19:45:38Z
networkpeerings.compute.gcp.upbound.io                             2022-10-12T19:45:38Z
networks.compute.gcp.upbound.io                                    2022-10-12T19:45:38Z
nodegroups.compute.gcp.upbound.io                                  2022-10-12T19:45:38Z
nodepools.container.gcp.upbound.io                                 2022-10-12T19:45:39Z
nodepools.containeraws.gcp.upbound.io                              2022-10-12T19:45:39Z
nodepools.containerazure.gcp.upbound.io                            2022-10-12T19:45:40Z
nodetemplates.compute.gcp.upbound.io                               2022-10-12T19:45:38Z
notes.containeranalysis.gcp.upbound.io                             2022-10-12T19:45:39Z
notificationchannels.monitoring.gcp.upbound.io                     2022-10-12T19:45:40Z
oauthidpconfigs.identityplatform.gcp.upbound.io                    2022-10-12T19:45:40Z
organizationiamauditconfigs.cloudplatform.gcp.upbound.io           2022-10-12T19:45:37Z
organizationiamcustomroles.cloudplatform.gcp.upbound.io            2022-10-12T19:45:37Z
organizationiammembers.cloudplatform.gcp.upbound.io                2022-10-12T19:45:37Z
ospolicyassignments.osconfig.gcp.upbound.io                        2022-10-12T19:45:40Z
packetmirrorings.compute.gcp.upbound.io                            2022-10-12T19:45:38Z
pages.dialogflowcx.gcp.upbound.io                                  2022-10-12T19:45:40Z
patchdeployments.osconfig.gcp.upbound.io                           2022-10-12T19:45:40Z
perinstanceconfigs.compute.gcp.upbound.io                          2022-10-12T19:45:39Z
policies.dns.gcp.upbound.io                                        2022-10-12T19:45:40Z
projectdefaultnetworktiers.compute.gcp.upbound.io                  2022-10-12T19:45:39Z
projectdefaultserviceaccounts.cloudplatform.gcp.upbound.io         2022-10-12T19:45:37Z
projectiamauditconfigs.cloudplatform.gcp.upbound.io                2022-10-12T19:45:37Z
projectiammembers.cloudplatform.gcp.upbound.io                     2022-10-12T19:45:37Z
projectmetadata.compute.gcp.upbound.io                             2022-10-12T19:45:39Z
projectmetadataitems.compute.gcp.upbound.io                        2022-10-12T19:45:39Z
projects.cloudplatform.gcp.upbound.io                              2022-10-12T19:45:37Z
projectservices.cloudplatform.gcp.upbound.io                       2022-10-12T19:45:37Z
projectusageexportbuckets.cloudplatform.gcp.upbound.io             2022-10-12T19:45:38Z
providerconfigs.gcp.upbound.io                                     2022-10-12T19:45:40Z
providerconfigusages.gcp.upbound.io                                2022-10-12T19:45:40Z
providerrevisions.pkg.crossplane.io                                2022-10-12T19:44:47Z
providers.pkg.crossplane.io                                        2022-10-12T19:44:47Z
queues.cloudtasks.gcp.upbound.io                                   2022-10-12T19:45:38Z
recordsets.dns.gcp.upbound.io                                      2022-10-12T19:45:40Z
regionautoscalers.compute.gcp.upbound.io                           2022-10-12T19:45:39Z
regionbackendservices.compute.gcp.upbound.io                       2022-10-12T19:45:39Z
regiondiskiammembers.compute.gcp.upbound.io                        2022-10-12T19:45:39Z
regiondiskresourcepolicyattachments.compute.gcp.upbound.io         2022-10-12T19:45:39Z
regiondisks.compute.gcp.upbound.io                                 2022-10-12T19:45:39Z
regionhealthchecks.compute.gcp.upbound.io                          2022-10-12T19:45:39Z
regioninstancegroupmanagers.compute.gcp.upbound.io                 2022-10-12T19:45:39Z
regionnetworkendpointgroups.compute.gcp.upbound.io                 2022-10-12T19:45:39Z
regionperinstanceconfigs.compute.gcp.upbound.io                    2022-10-12T19:45:39Z
regionsslcertificates.compute.gcp.upbound.io                       2022-10-12T19:45:39Z
regiontargethttpproxies.compute.gcp.upbound.io                     2022-10-12T19:45:39Z
regiontargethttpsproxies.compute.gcp.upbound.io                    2022-10-12T19:45:39Z
regionurlmaps.compute.gcp.upbound.io                               2022-10-12T19:45:39Z
registries.container.gcp.upbound.io                                2022-10-12T19:45:39Z
releases.firebaserules.gcp.upbound.io                              2022-10-12T19:45:40Z
repositories.sourcerepo.gcp.upbound.io                             2022-10-12T19:45:41Z
repositoryiammembers.sourcerepo.gcp.upbound.io                     2022-10-12T19:45:41Z
reservations.compute.gcp.upbound.io                                2022-10-12T19:45:39Z
resourcepolicies.compute.gcp.upbound.io                            2022-10-12T19:45:39Z
routerinterfaces.compute.gcp.upbound.io                            2022-10-12T19:45:39Z
routernats.compute.gcp.upbound.io                                  2022-10-12T19:45:39Z
routers.compute.gcp.upbound.io                                     2022-10-12T19:45:39Z
routes.compute.gcp.upbound.io                                      2022-10-12T19:45:39Z
rulesets.firebaserules.gcp.upbound.io                              2022-10-12T19:45:40Z
runtimeiammembers.notebooks.gcp.upbound.io                         2022-10-12T19:45:40Z
runtimes.notebooks.gcp.upbound.io                                  2022-10-12T19:45:40Z
schemas.pubsub.gcp.upbound.io                                      2022-10-12T19:45:41Z
secretciphertexts.kms.gcp.upbound.io                               2022-10-12T19:45:40Z
secretiammembers.secretmanager.gcp.upbound.io                      2022-10-12T19:45:41Z
secrets.secretmanager.gcp.upbound.io                               2022-10-12T19:45:41Z
secretversions.secretmanager.gcp.upbound.io                        2022-10-12T19:45:41Z
securitypolicies.compute.gcp.upbound.io                            2022-10-12T19:45:39Z
serviceaccountiammembers.cloudplatform.gcp.upbound.io              2022-10-12T19:45:37Z
serviceaccountkeys.cloudplatform.gcp.upbound.io                    2022-10-12T19:45:38Z
serviceaccounts.cloudplatform.gcp.upbound.io                       2022-10-12T19:45:37Z
serviceattachments.compute.gcp.upbound.io                          2022-10-12T19:45:39Z
serviceiammembers.cloudrun.gcp.upbound.io                          2022-10-12T19:45:38Z
servicenetworkingpeereddnsdomains.cloudplatform.gcp.upbound.io     2022-10-12T19:45:37Z
services.cloudrun.gcp.upbound.io                                   2022-10-12T19:45:38Z
sourcerepresentationinstances.sql.gcp.upbound.io                   2022-10-12T19:45:41Z
sshpublickeys.oslogin.gcp.upbound.io                               2022-10-12T19:45:40Z
sslcertificates.compute.gcp.upbound.io                             2022-10-12T19:45:39Z
sslcerts.sql.gcp.upbound.io                                        2022-10-12T19:45:41Z
storeconfigs.gcp.upbound.io                                        2022-10-12T19:45:40Z
storeconfigs.secrets.crossplane.io                                 2022-10-12T19:44:47Z
subnetworkiammembers.compute.gcp.upbound.io                        2022-10-12T19:45:39Z
subnetworks.compute.gcp.upbound.io                                 2022-10-12T19:45:39Z
subscriptioniammembers.pubsub.gcp.upbound.io                       2022-10-12T19:45:41Z
subscriptions.pubsub.gcp.upbound.io                                2022-10-12T19:45:41Z
targetgrpcproxies.compute.gcp.upbound.io                           2022-10-12T19:45:39Z
targethttpproxies.compute.gcp.upbound.io                           2022-10-12T19:45:39Z
targethttpsproxies.compute.gcp.upbound.io                          2022-10-12T19:45:39Z
targetinstances.compute.gcp.upbound.io                             2022-10-12T19:45:39Z
targetpools.compute.gcp.upbound.io                                 2022-10-12T19:45:39Z
targetsslproxies.compute.gcp.upbound.io                            2022-10-12T19:45:39Z
targettcpproxies.compute.gcp.upbound.io                            2022-10-12T19:45:39Z
tenantdefaultsupportedidpconfigs.identityplatform.gcp.upbound.io   2022-10-12T19:45:40Z
tenantinboundsamlconfigs.identityplatform.gcp.upbound.io           2022-10-12T19:45:40Z
tenantoauthidpconfigs.identityplatform.gcp.upbound.io              2022-10-12T19:45:40Z
tenants.identityplatform.gcp.upbound.io                            2022-10-12T19:45:40Z
topiciammembers.pubsub.gcp.upbound.io                              2022-10-12T19:45:41Z
topics.pubsub.gcp.upbound.io                                       2022-10-12T19:45:41Z
triggers.eventarc.gcp.upbound.io                                   2022-10-12T19:45:40Z
uptimecheckconfigs.monitoring.gcp.upbound.io                       2022-10-12T19:45:40Z
urlmaps.compute.gcp.upbound.io                                     2022-10-12T19:45:39Z
users.sql.gcp.upbound.io                                           2022-10-12T19:45:41Z
versions.dialogflowcx.gcp.upbound.io                               2022-10-12T19:45:40Z
vpngateways.compute.gcp.upbound.io                                 2022-10-12T19:45:39Z
vpntunnels.compute.gcp.upbound.io                                  2022-10-12T19:45:39Z
webbackendserviceiammembers.iap.gcp.upbound.io                     2022-10-12T19:45:40Z
webiammembers.iap.gcp.upbound.io                                   2022-10-12T19:45:40Z
webtypeappengineiammembers.iap.gcp.upbound.io                      2022-10-12T19:45:40Z
webtypecomputeiammembers.iap.gcp.upbound.io                        2022-10-12T19:45:40Z

Create a Kubernetes secret for GCP

The provider requires credentials to create and manage GCP resources. Providers use a Kubernetes Secret to connect the credentials to the provider.

First generate a Kubernetes Secret from a Google Cloud service account JSON file and then configure the Provider to use it.

Generate a GCP service account JSON file

For basic user authentication, use a Google Cloud service account JSON file.

The GCP documentation provides information on how to generate a service account JSON file.

Save this JSON file as gcp-credentials.json

The Configuration section of the Provider documentation describes other authentication methods.

Create a Kubernetes secret with the GCP credentials

A Kubernetes generic secret has a name and contents. Use kubectl create secret to generate the secret object named gcp-secret in the upbound-system namespace.
Use the --from-file= argument to set the value to the contents of the gcp-credentials.json file.

1
2
3
4
kubectl create secret \
generic gcp-secret \
-n upbound-system \
--from-file=creds=./gcp-credentials.json

View the secret with kubectl describe secret

The size may be larger if there are extra blank spaces in your text file.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
kubectl describe secret gcp-secret -n upbound-system
Name:         gcp-secret
Namespace:    upbound-system
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
creds:  2330 bytes

Create a ProviderConfig

A ProviderConfig customizes the settings of the GCP Provider.

Apply the ProviderConfig . Include your GCP project ID .

Add your GCP project ID into the output below.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
cat <<EOF | kubectl apply -f -
apiVersion: gcp.upbound.io/v1beta1
kind: ProviderConfig
metadata:
  name: default
spec:
  projectID: <PROJECT_ID>
  credentials:
    source: Secret
    secretRef:
      namespace: upbound-system
      name: gcp-secret
      key: creds
EOF

This attaches the GCP credentials, saved as a Kubernetes secret, as a secretRef .

The spec.credentials.secretRef.name value is the name of the Kubernetes secret containing the GCP credentials in the spec.credentials.secretRef.namespace .

Create a managed resource

A managed resource is anything Crossplane creates and manages outside of the Kubernetes cluster. This creates a GCP storage bucket with Crossplane. The storage bucket is a managed resource.

This will generate a random name for the storage bucket starting with upbound-bucket

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
bucket=$(echo "upbound-bucket-"$(head -n 4096 /dev/urandom | openssl sha1 | tail -c 10))
cat <<EOF | kubectl apply -f -
apiVersion: storage.gcp.upbound.io/v1beta1
kind: Bucket
metadata:
  name: $bucket
spec:
  forProvider:
    location: US
    storageClass: MULTI_REGIONAL
  providerConfigRef:
    name: default
  deletionPolicy: Delete
EOF

Notice the apiVersion and kind are from the Provider's CRDs.

The metadata.name value is the name of the created GCP storage bucket.
This example uses the generated name upbound-bucket-<hash> in the $bucket variable.

spec.storageClass defines the GCP storage bucket is single-region, dual-region or multi-region.

spec.forProvider.location is a GCP location based on the storageClass .

Use kubectl get buckets to verify Crossplane created the bucket.

Upbound created the bucket when the values READY and SYNCED are True.
This may take up to 5 minutes.
1
2
3
kubectl get bucket
NAME                       READY   SYNCED   EXTERNAL-NAME              AGE
upbound-bucket-cf2b6d853   True    True     upbound-bucket-cf2b6d853   3m3s

Optionally, log into the GCP Console and see the storage bucket inside GCP.

GCP console shows a storage bucket with the name upbound-bucket-cf2b6d853 that matches the bucket created by Crossplane.
GCP console shows a storage bucket with the name upbound-bucket-cf2b6d853 that matches the bucket created by Crossplane.

If the READY or SYNCED are blank or False use kubectl describe bucket to understand why.

A common issue is incorrect GCP credentials or not having permissions to create the GCP storage bucket.

The following output is an example of the kubectl describe bucket output when using the wrong GCP credentials.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 kubectl describe bucket
Name:         upbound-bucket-b7cf6b590
Namespace:
Labels:       <none>
Annotations:  crossplane.io/external-name: upbound-bucket-b7cf6b590
API Version:  storage.gcp.upbound.io/v1beta1
Kind:         Bucket
# Output trimmed for brevity
Spec:
  Deletion Policy:  Delete
  For Provider:
    Location:       US
    Storage Class:  MULTI_REGIONAL
  Provider Config Ref:
    Name:  default
Status:
  At Provider:
  Conditions:
    Last Transition Time:  2022-10-13T02:39:18Z
    Message:               observe failed: cannot run refresh: refresh failed: Error when reading or editing Storage Bucket "upbound-bucket-b7cf6b590": Get "https://storage.googleapis.com/storage/v1/b/upbound-bucket-b7cf6b590?alt=json&prettyPrint=false": private key should be a PEM or plain PKCS1 or PKCS8; parse error: x509: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format):
    Reason:                ReconcileError
    Status:                False
    Type:                  Synced
Events:
  Type     Reason                         Age              From                                                 Message
  ----     ------                         ----             ----                                                 -------
  Warning  CannotObserveExternalResource  1s (x4 over 7s)  managed/storage.gcp.upbound.io/v1beta1, kind=bucket  cannot run refresh: refresh failed: Error when reading or editing Storage Bucket "upbound-bucket-b7cf6b590": Get "https://storage.googleapis.com/storage/v1/b/upbound-bucket-b7cf6b590?alt=json&prettyPrint=false": private key should be a PEM or plain PKCS1 or PKCS8; parse error: x509: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format):

The error message in the Events log indicates the problem.
private key should be a PEM or plain PKCS1 or PKCS8; parse error: x509: failed to parse private key .

This indicates the GCP authorization JSON file

To fix the problem:

  • Update your GCP credentials in the gcp-credentials.json file.
  • Delete the original Kubernetes secret with
  • kubectl delete secret gcp-secret -n upbound-system
  • Create a new secret with
    kubectl create secret generic gcp-secret -n upbound-system --from-file=creds=gcp-credentials.json
  • Delete the ProviderConfig with
    kubectl delete providerconfigs.gcp.upbound.io/default
  • Recreate the ProviderConfig with the output in the ProviderConfig section.
  • Create the bucket again.
Deleting the ProviderConfig isn’t required, but is faster than waiting for Kubernetes to synchronize and update.

Still need help? Join the Crossplane Slack and ask in the #Upbound room to get help directly from Upbound employees and community members.

Delete the managed resource

Before shutting down your Kubernetes cluster, delete the S3 bucket just created.

Use kubectl delete bucket <bucketname> to remove the bucket.

1
2
kubectl delete bucket $bucket
bucket.storage.gcp.upbound.io "upbound-bucket-b7cf6b590" deleted

Look in the GCP Console to confirm Crossplane deleted the bucket from GCP.

The Google Cloud console showing no buckets exist, indicating Crossplane deleted the storage bucket managed resource.
The Google Cloud console showing no buckets exist, indicating Crossplane deleted the storage bucket managed resource.

Next steps