This document is for an older version of Crossplane.

This document applies to Crossplane version v1.12 and not to the latest release v1.13.

Connect Crossplane to Azure to create and manage cloud resources from Kubernetes with the Upbound Azure Provider.

This guide is in three parts:

  • Part 1 walks through installing Crossplane, configuring the provider to authenticate to Azure and creating a Managed Resource in Azure directly from your Kubernetes cluster. This shows Crossplane can communicate with Azure.
  • Part 2 creates a Composite Resource Definition (XRD), Composite Resource (XR) and a Claim (XRC) to show how to create and use custom APIs.
  • Part 3 demonstrates how to patch Compositions with values used in a Claim and how to build a Crossplane Package to make a Crossplane platform portable and reusable.

Prerequisites

This quickstart requires:

Install Crossplane

Crossplane installs into an existing Kubernetes cluster.

Tip
If you don’t have a Kubernetes cluster create one locally with Kind.

Install the Crossplane Helm chart

Helm enables Crossplane to install all its Kubernetes components through a Helm Chart.

Enable the Crossplane Helm Chart repository:

1helm repo add \
2crossplane-stable https://charts.crossplane.io/stable && helm repo update

Run the Helm dry-run to see all the Crossplane components Helm installs.

1helm install crossplane \
2crossplane-stable/crossplane \
3--dry-run --debug \
4--namespace crossplane-system \
5--create-namespace

  1helm install crossplane \
  2crossplane-stable/crossplane \
  3--dry-run --debug \
  4--namespace crossplane-system \
  5--create-namespace
  6install.go:193: [debug] Original chart version: ""
  7install.go:210: [debug] CHART PATH: /home/vagrant/.cache/helm/repository/crossplane-1.10.1.tgz
  8
  9NAME: crossplane
 10LAST DEPLOYED: Thu Jan 19 15:52:08 2023
 11NAMESPACE: crossplane-system
 12STATUS: pending-install
 13REVISION: 1
 14TEST SUITE: None
 15USER-SUPPLIED VALUES:
 16{}
 17
 18COMPUTED VALUES:
 19affinity: {}
 20args: {}
 21configuration:
 22  packages: []
 23customAnnotations: {}
 24customLabels: {}
 25deploymentStrategy: RollingUpdate
 26extraEnvVarsCrossplane: {}
 27extraEnvVarsRBACManager: {}
 28image:
 29  pullPolicy: IfNotPresent
 30  repository: crossplane/crossplane
 31  tag: v1.10.1
 32imagePullSecrets: {}
 33leaderElection: true
 34metrics:
 35  enabled: false
 36nodeSelector: {}
 37packageCache:
 38  medium: ""
 39  pvc: ""
 40  sizeLimit: 5Mi
 41podSecurityContextCrossplane: {}
 42podSecurityContextRBACManager: {}
 43priorityClassName: ""
 44provider:
 45  packages: []
 46rbacManager:
 47  affinity: {}
 48  args: {}
 49  deploy: true
 50  leaderElection: true
 51  managementPolicy: All
 52  nodeSelector: {}
 53  replicas: 1
 54  skipAggregatedClusterRoles: false
 55  tolerations: {}
 56registryCaBundleConfig: {}
 57replicas: 1
 58resourcesCrossplane:
 59  limits:
 60    cpu: 100m
 61    memory: 512Mi
 62  requests:
 63    cpu: 100m
 64    memory: 256Mi
 65resourcesRBACManager:
 66  limits:
 67    cpu: 100m
 68    memory: 512Mi
 69  requests:
 70    cpu: 100m
 71    memory: 256Mi
 72securityContextCrossplane:
 73  allowPrivilegeEscalation: false
 74  readOnlyRootFilesystem: true
 75  runAsGroup: 65532
 76  runAsUser: 65532
 77securityContextRBACManager:
 78  allowPrivilegeEscalation: false
 79  readOnlyRootFilesystem: true
 80  runAsGroup: 65532
 81  runAsUser: 65532
 82serviceAccount:
 83  customAnnotations: {}
 84tolerations: {}
 85webhooks:
 86  enabled: false
 87
 88HOOKS:
 89MANIFEST:
 90---
 91# Source: crossplane/templates/rbac-manager-serviceaccount.yaml
 92apiVersion: v1
 93kind: ServiceAccount
 94metadata:
 95  name: rbac-manager
 96  labels:
 97    app: crossplane
 98    helm.sh/chart: crossplane-1.10.1
 99    app.kubernetes.io/managed-by: Helm
100    app.kubernetes.io/component: cloud-infrastructure-controller
101    app.kubernetes.io/part-of: crossplane
102    app.kubernetes.io/name: crossplane
103    app.kubernetes.io/instance: crossplane
104    app.kubernetes.io/version: "1.10.1"
105---
106# Source: crossplane/templates/serviceaccount.yaml
107apiVersion: v1
108kind: ServiceAccount
109metadata:
110  name: crossplane
111  labels:
112    app: crossplane
113    helm.sh/chart: crossplane-1.10.1
114    app.kubernetes.io/managed-by: Helm
115    app.kubernetes.io/component: cloud-infrastructure-controller
116    app.kubernetes.io/part-of: crossplane
117    app.kubernetes.io/name: crossplane
118    app.kubernetes.io/instance: crossplane
119    app.kubernetes.io/version: "1.10.1"
120---
121# Source: crossplane/templates/clusterrole.yaml
122apiVersion: rbac.authorization.k8s.io/v1
123kind: ClusterRole
124metadata:
125  name: crossplane
126  labels:
127    app: crossplane
128    helm.sh/chart: crossplane-1.10.1
129    app.kubernetes.io/managed-by: Helm
130    app.kubernetes.io/component: cloud-infrastructure-controller
131    app.kubernetes.io/part-of: crossplane
132    app.kubernetes.io/name: crossplane
133    app.kubernetes.io/instance: crossplane
134    app.kubernetes.io/version: "1.10.1"
135aggregationRule:
136  clusterRoleSelectors:
137  - matchLabels:
138      rbac.crossplane.io/aggregate-to-crossplane: "true"
139---
140# Source: crossplane/templates/clusterrole.yaml
141apiVersion: rbac.authorization.k8s.io/v1
142kind: ClusterRole
143metadata:
144  name: crossplane:system:aggregate-to-crossplane
145  labels:
146    app: crossplane
147    helm.sh/chart: crossplane-1.10.1
148    app.kubernetes.io/managed-by: Helm
149    app.kubernetes.io/component: cloud-infrastructure-controller
150    app.kubernetes.io/part-of: crossplane
151    app.kubernetes.io/name: crossplane
152    app.kubernetes.io/instance: crossplane
153    app.kubernetes.io/version: "1.10.1"
154    crossplane.io/scope: "system"
155    rbac.crossplane.io/aggregate-to-crossplane: "true"
156rules:
157- apiGroups:
158  - ""
159  resources:
160  - events
161  verbs:
162  - create
163  - update
164  - patch
165  - delete
166- apiGroups:
167  - apiextensions.k8s.io
168  resources:
169  - customresourcedefinitions
170  verbs:
171  - "*"
172- apiGroups:
173  - ""
174  resources:
175  - secrets
176  verbs:
177  - get
178  - list
179  - watch
180  - create
181  - update
182  - patch
183  - delete
184- apiGroups:
185  - ""
186  resources:
187  - serviceaccounts
188  - services
189  verbs:
190  - "*"
191- apiGroups:
192  - apiextensions.crossplane.io
193  - pkg.crossplane.io
194  - secrets.crossplane.io
195  resources:
196  - "*"
197  verbs:
198  - "*"
199- apiGroups:
200  - extensions
201  - apps
202  resources:
203  - deployments
204  verbs:
205  - get
206  - list
207  - create
208  - update
209  - patch
210  - delete
211  - watch
212- apiGroups:
213  - ""
214  - coordination.k8s.io
215  resources:
216  - configmaps
217  - leases
218  verbs:
219  - get
220  - list
221  - create
222  - update
223  - patch
224  - watch
225  - delete
226- apiGroups:
227  - admissionregistration.k8s.io
228  resources:
229  - validatingwebhookconfigurations
230  - mutatingwebhookconfigurations
231  verbs:
232  - get
233  - list
234  - create
235  - update
236  - patch
237  - watch
238  - delete
239---
240# Source: crossplane/templates/rbac-manager-allowed-provider-permissions.yaml
241apiVersion: rbac.authorization.k8s.io/v1
242kind: ClusterRole
243metadata:
244  name: crossplane:allowed-provider-permissions
245  labels:
246    app: crossplane
247    helm.sh/chart: crossplane-1.10.1
248    app.kubernetes.io/managed-by: Helm
249    app.kubernetes.io/component: cloud-infrastructure-controller
250    app.kubernetes.io/part-of: crossplane
251    app.kubernetes.io/name: crossplane
252    app.kubernetes.io/instance: crossplane
253    app.kubernetes.io/version: "1.10.1"
254aggregationRule:
255  clusterRoleSelectors:
256  - matchLabels:
257      rbac.crossplane.io/aggregate-to-allowed-provider-permissions: "true"
258---
259# Source: crossplane/templates/rbac-manager-clusterrole.yaml
260apiVersion: rbac.authorization.k8s.io/v1
261kind: ClusterRole
262metadata:
263  name: crossplane-rbac-manager
264  labels:
265    app: crossplane
266    helm.sh/chart: crossplane-1.10.1
267    app.kubernetes.io/managed-by: Helm
268    app.kubernetes.io/component: cloud-infrastructure-controller
269    app.kubernetes.io/part-of: crossplane
270    app.kubernetes.io/name: crossplane
271    app.kubernetes.io/instance: crossplane
272    app.kubernetes.io/version: "1.10.1"
273rules:
274- apiGroups:
275  - ""
276  resources:
277  - events
278  verbs:
279  - create
280  - update
281  - patch
282  - delete
283- apiGroups:
284  - ""
285  resources:
286  - namespaces
287  - serviceaccounts
288  verbs:
289  - get
290  - list
291  - watch
292- apiGroups:
293  - apiextensions.crossplane.io
294  resources:
295  - compositeresourcedefinitions
296  verbs:
297  - get
298  - list
299  - watch
300- apiGroups:
301  - pkg.crossplane.io
302  resources:
303  - providerrevisions
304  verbs:
305  - get
306  - list
307  - watch
308- apiGroups:
309  - apiextensions.k8s.io
310  resources:
311  - customresourcedefinitions
312  verbs:
313  - get
314  - list
315  - watch
316- apiGroups:
317  - rbac.authorization.k8s.io
318  resources:
319  - clusterroles
320  - roles
321  verbs:
322  - get
323  - list
324  - watch
325  - create
326  - update
327  - patch
328  # The RBAC manager may grant access it does not have.
329  - escalate
330- apiGroups:
331  - rbac.authorization.k8s.io
332  resources:
333  - clusterroles
334  verbs:
335  - bind
336- apiGroups:
337  - rbac.authorization.k8s.io
338  resources:
339  - clusterrolebindings
340  verbs:
341  - "*"
342- apiGroups:
343  - ""
344  - coordination.k8s.io
345  resources:
346  - configmaps
347  - leases
348  verbs:
349  - get
350  - list
351  - create
352  - update
353  - patch
354  - watch
355  - delete
356---
357# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
358apiVersion: rbac.authorization.k8s.io/v1
359kind: ClusterRole
360metadata:
361  name: crossplane-admin
362  labels:
363    app: crossplane
364    helm.sh/chart: crossplane-1.10.1
365    app.kubernetes.io/managed-by: Helm
366    app.kubernetes.io/component: cloud-infrastructure-controller
367    app.kubernetes.io/part-of: crossplane
368    app.kubernetes.io/name: crossplane
369    app.kubernetes.io/instance: crossplane
370    app.kubernetes.io/version: "1.10.1"
371aggregationRule:
372  clusterRoleSelectors:
373  - matchLabels:
374      rbac.crossplane.io/aggregate-to-admin: "true"
375---
376# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
377apiVersion: rbac.authorization.k8s.io/v1
378kind: ClusterRole
379metadata:
380  name: crossplane-edit
381  labels:
382    app: crossplane
383    helm.sh/chart: crossplane-1.10.1
384    app.kubernetes.io/managed-by: Helm
385    app.kubernetes.io/component: cloud-infrastructure-controller
386    app.kubernetes.io/part-of: crossplane
387    app.kubernetes.io/name: crossplane
388    app.kubernetes.io/instance: crossplane
389    app.kubernetes.io/version: "1.10.1"
390aggregationRule:
391  clusterRoleSelectors:
392  - matchLabels:
393      rbac.crossplane.io/aggregate-to-edit: "true"
394---
395# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
396apiVersion: rbac.authorization.k8s.io/v1
397kind: ClusterRole
398metadata:
399  name: crossplane-view
400  labels:
401    app: crossplane
402    helm.sh/chart: crossplane-1.10.1
403    app.kubernetes.io/managed-by: Helm
404    app.kubernetes.io/component: cloud-infrastructure-controller
405    app.kubernetes.io/part-of: crossplane
406    app.kubernetes.io/name: crossplane
407    app.kubernetes.io/instance: crossplane
408    app.kubernetes.io/version: "1.10.1"
409aggregationRule:
410  clusterRoleSelectors:
411  - matchLabels:
412      rbac.crossplane.io/aggregate-to-view: "true"
413---
414# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
415apiVersion: rbac.authorization.k8s.io/v1
416kind: ClusterRole
417metadata:
418  name: crossplane-browse
419  labels:
420    app: crossplane
421    helm.sh/chart: crossplane-1.10.1
422    app.kubernetes.io/managed-by: Helm
423    app.kubernetes.io/component: cloud-infrastructure-controller
424    app.kubernetes.io/part-of: crossplane
425    app.kubernetes.io/name: crossplane
426    app.kubernetes.io/instance: crossplane
427    app.kubernetes.io/version: "1.10.1"
428aggregationRule:
429  clusterRoleSelectors:
430  - matchLabels:
431      rbac.crossplane.io/aggregate-to-browse: "true"
432---
433# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
434apiVersion: rbac.authorization.k8s.io/v1
435kind: ClusterRole
436metadata:
437  name: crossplane:aggregate-to-admin
438  labels:
439    rbac.crossplane.io/aggregate-to-admin: "true"
440    app: crossplane
441    helm.sh/chart: crossplane-1.10.1
442    app.kubernetes.io/managed-by: Helm
443    app.kubernetes.io/component: cloud-infrastructure-controller
444    app.kubernetes.io/part-of: crossplane
445    app.kubernetes.io/name: crossplane
446    app.kubernetes.io/instance: crossplane
447    app.kubernetes.io/version: "1.10.1"
448rules:
449# Crossplane administrators have access to view events.
450- apiGroups: [""]
451  resources: [events]
452  verbs: [get, list, watch]
453# Crossplane administrators must create provider credential secrets, and may
454# need to read or otherwise interact with connection secrets. They may also need
455# to create or annotate namespaces.
456- apiGroups: [""]
457  resources: [secrets, namespaces]
458  verbs: ["*"]
459# Crossplane administrators have access to view the roles that they may be able
460# to grant to other subjects.
461- apiGroups: [rbac.authorization.k8s.io]
462  resources: [clusterroles, roles]
463  verbs: [get, list, watch]
464# Crossplane administrators have access to grant the access they have to other
465# subjects.
466- apiGroups: [rbac.authorization.k8s.io]
467  resources: [clusterrolebindings, rolebindings]
468  verbs: ["*"]
469# Crossplane administrators have full access to built in Crossplane types.
470- apiGroups:
471  - apiextensions.crossplane.io
472  resources: ["*"]
473  verbs: ["*"]
474- apiGroups:
475  - pkg.crossplane.io
476  resources: [providers, configurations, providerrevisions, configurationrevisions]
477  verbs: ["*"]
478# Crossplane administrators have access to view CRDs in order to debug XRDs.
479- apiGroups: [apiextensions.k8s.io]
480  resources: [customresourcedefinitions]
481  verbs: [get, list, watch]
482---
483# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
484apiVersion: rbac.authorization.k8s.io/v1
485kind: ClusterRole
486metadata:
487  name: crossplane:aggregate-to-edit
488  labels:
489    rbac.crossplane.io/aggregate-to-edit: "true"
490    app: crossplane
491    helm.sh/chart: crossplane-1.10.1
492    app.kubernetes.io/managed-by: Helm
493    app.kubernetes.io/component: cloud-infrastructure-controller
494    app.kubernetes.io/part-of: crossplane
495    app.kubernetes.io/name: crossplane
496    app.kubernetes.io/instance: crossplane
497    app.kubernetes.io/version: "1.10.1"
498rules:
499# Crossplane editors have access to view events.
500- apiGroups: [""]
501  resources: [events]
502  verbs: [get, list, watch]
503# Crossplane editors must create provider credential secrets, and may need to
504# read or otherwise interact with connection secrets.
505- apiGroups: [""]
506  resources: [secrets]
507  verbs: ["*"]
508# Crossplane editors may see which namespaces exist, but not edit them.
509- apiGroups: [""]
510  resources: [namespaces]
511  verbs: [get, list, watch]
512# Crossplane editors have full access to built in Crossplane types.
513- apiGroups:
514  - apiextensions.crossplane.io
515  resources: ["*"]
516  verbs: ["*"]
517- apiGroups:
518  - pkg.crossplane.io
519  resources: [providers, configurations, providerrevisions, configurationrevisions]
520  verbs: ["*"]
521---
522# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
523apiVersion: rbac.authorization.k8s.io/v1
524kind: ClusterRole
525metadata:
526  name: crossplane:aggregate-to-view
527  labels:
528    rbac.crossplane.io/aggregate-to-view: "true"
529    app: crossplane
530    helm.sh/chart: crossplane-1.10.1
531    app.kubernetes.io/managed-by: Helm
532    app.kubernetes.io/component: cloud-infrastructure-controller
533    app.kubernetes.io/part-of: crossplane
534    app.kubernetes.io/name: crossplane
535    app.kubernetes.io/instance: crossplane
536    app.kubernetes.io/version: "1.10.1"
537rules:
538# Crossplane viewers have access to view events.
539- apiGroups: [""]
540  resources: [events]
541  verbs: [get, list, watch]
542# Crossplane viewers may see which namespaces exist.
543- apiGroups: [""]
544  resources: [namespaces]
545  verbs: [get, list, watch]
546# Crossplane viewers have read-only access to built in Crossplane types.
547- apiGroups:
548  - apiextensions.crossplane.io
549  resources: ["*"]
550  verbs: [get, list, watch]
551- apiGroups:
552  - pkg.crossplane.io
553  resources: [providers, configurations, providerrevisions, configurationrevisions]
554  verbs: [get, list, watch]
555---
556# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
557apiVersion: rbac.authorization.k8s.io/v1
558kind: ClusterRole
559metadata:
560  name: crossplane:aggregate-to-browse
561  labels:
562    rbac.crossplane.io/aggregate-to-browse: "true"
563    app: crossplane
564    helm.sh/chart: crossplane-1.10.1
565    app.kubernetes.io/managed-by: Helm
566    app.kubernetes.io/component: cloud-infrastructure-controller
567    app.kubernetes.io/part-of: crossplane
568    app.kubernetes.io/name: crossplane
569    app.kubernetes.io/instance: crossplane
570    app.kubernetes.io/version: "1.10.1"
571rules:
572# Crossplane browsers have access to view events.
573- apiGroups: [""]
574  resources: [events]
575  verbs: [get, list, watch]
576# Crossplane browsers have read-only access to compositions and XRDs. This
577# allows them to discover and select an appropriate composition when creating a
578# resource claim.
579- apiGroups:
580  - apiextensions.crossplane.io
581  resources: ["*"]
582  verbs: [get, list, watch]
583---
584# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
585# The below ClusterRoles are aggregated to the namespaced RBAC roles created by
586# the Crossplane RBAC manager when it is running in --manage=All mode.
587apiVersion: rbac.authorization.k8s.io/v1
588kind: ClusterRole
589metadata:
590  name: crossplane:aggregate-to-ns-admin
591  labels:
592    rbac.crossplane.io/aggregate-to-ns-admin: "true"
593    rbac.crossplane.io/base-of-ns-admin: "true"
594    app: crossplane
595    helm.sh/chart: crossplane-1.10.1
596    app.kubernetes.io/managed-by: Helm
597    app.kubernetes.io/component: cloud-infrastructure-controller
598    app.kubernetes.io/part-of: crossplane
599    app.kubernetes.io/name: crossplane
600    app.kubernetes.io/instance: crossplane
601    app.kubernetes.io/version: "1.10.1"
602rules:
603# Crossplane namespace admins have access to view events.
604- apiGroups: [""]
605  resources: [events]
606  verbs: [get, list, watch]
607# Crossplane namespace admins may need to read or otherwise interact with
608# resource claim connection secrets.
609- apiGroups: [""]
610  resources: [secrets]
611  verbs: ["*"]
612# Crossplane namespace admins have access to view the roles that they may be
613# able to grant to other subjects.
614- apiGroups: [rbac.authorization.k8s.io]
615  resources: [roles]
616  verbs: [get, list, watch]
617# Crossplane namespace admins have access to grant the access they have to other
618# subjects.
619- apiGroups: [rbac.authorization.k8s.io]
620  resources: [rolebindings]
621  verbs: ["*"]
622---
623# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
624apiVersion: rbac.authorization.k8s.io/v1
625kind: ClusterRole
626metadata:
627  name: crossplane:aggregate-to-ns-edit
628  labels:
629    rbac.crossplane.io/aggregate-to-ns-edit: "true"
630    rbac.crossplane.io/base-of-ns-edit: "true"
631    app: crossplane
632    helm.sh/chart: crossplane-1.10.1
633    app.kubernetes.io/managed-by: Helm
634    app.kubernetes.io/component: cloud-infrastructure-controller
635    app.kubernetes.io/part-of: crossplane
636    app.kubernetes.io/name: crossplane
637    app.kubernetes.io/instance: crossplane
638    app.kubernetes.io/version: "1.10.1"
639rules:
640# Crossplane namespace editors have access to view events.
641- apiGroups: [""]
642  resources: [events]
643  verbs: [get, list, watch]
644# Crossplane namespace editors may need to read or otherwise interact with
645# resource claim connection secrets.
646- apiGroups: [""]
647  resources: [secrets]
648  verbs: ["*"]
649---
650# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
651apiVersion: rbac.authorization.k8s.io/v1
652kind: ClusterRole
653metadata:
654  name: crossplane:aggregate-to-ns-view
655  labels:
656    rbac.crossplane.io/aggregate-to-ns-view: "true"
657    rbac.crossplane.io/base-of-ns-view: "true"
658    app: crossplane
659    helm.sh/chart: crossplane-1.10.1
660    app.kubernetes.io/managed-by: Helm
661    app.kubernetes.io/component: cloud-infrastructure-controller
662    app.kubernetes.io/part-of: crossplane
663    app.kubernetes.io/name: crossplane
664    app.kubernetes.io/instance: crossplane
665    app.kubernetes.io/version: "1.10.1"
666rules:
667# Crossplane namespace viewers have access to view events.
668- apiGroups: [""]
669  resources: [events]
670  verbs: [get, list, watch]
671---
672# Source: crossplane/templates/clusterrolebinding.yaml
673apiVersion: rbac.authorization.k8s.io/v1
674kind: ClusterRoleBinding
675metadata:
676  name: crossplane
677  labels:
678    app: crossplane
679    helm.sh/chart: crossplane-1.10.1
680    app.kubernetes.io/managed-by: Helm
681    app.kubernetes.io/component: cloud-infrastructure-controller
682    app.kubernetes.io/part-of: crossplane
683    app.kubernetes.io/name: crossplane
684    app.kubernetes.io/instance: crossplane
685    app.kubernetes.io/version: "1.10.1"
686roleRef:
687  apiGroup: rbac.authorization.k8s.io
688  kind: ClusterRole
689  name: crossplane
690subjects:
691- kind: ServiceAccount
692  name: crossplane
693  namespace: crossplane-system
694---
695# Source: crossplane/templates/rbac-manager-clusterrolebinding.yaml
696apiVersion: rbac.authorization.k8s.io/v1
697kind: ClusterRoleBinding
698metadata:
699  name: crossplane-rbac-manager
700  labels:
701    app: crossplane
702    helm.sh/chart: crossplane-1.10.1
703    app.kubernetes.io/managed-by: Helm
704    app.kubernetes.io/component: cloud-infrastructure-controller
705    app.kubernetes.io/part-of: crossplane
706    app.kubernetes.io/name: crossplane
707    app.kubernetes.io/instance: crossplane
708    app.kubernetes.io/version: "1.10.1"
709roleRef:
710  apiGroup: rbac.authorization.k8s.io
711  kind: ClusterRole
712  name: crossplane-rbac-manager
713subjects:
714- kind: ServiceAccount
715  name: rbac-manager
716  namespace: crossplane-system
717---
718# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
719apiVersion: rbac.authorization.k8s.io/v1
720kind: ClusterRoleBinding
721metadata:
722  name: crossplane-admin
723  labels:
724    app: crossplane
725    helm.sh/chart: crossplane-1.10.1
726    app.kubernetes.io/managed-by: Helm
727    app.kubernetes.io/component: cloud-infrastructure-controller
728    app.kubernetes.io/part-of: crossplane
729    app.kubernetes.io/name: crossplane
730    app.kubernetes.io/instance: crossplane
731    app.kubernetes.io/version: "1.10.1"
732roleRef:
733  apiGroup: rbac.authorization.k8s.io
734  kind: ClusterRole
735  name: crossplane-admin
736subjects:
737- apiGroup: rbac.authorization.k8s.io
738  kind: Group
739  name: crossplane:masters
740---
741# Source: crossplane/templates/deployment.yaml
742apiVersion: apps/v1
743kind: Deployment
744metadata:
745  name: crossplane
746  labels:
747    app: crossplane
748    release: crossplane
749    helm.sh/chart: crossplane-1.10.1
750    app.kubernetes.io/managed-by: Helm
751    app.kubernetes.io/component: cloud-infrastructure-controller
752    app.kubernetes.io/part-of: crossplane
753    app.kubernetes.io/name: crossplane
754    app.kubernetes.io/instance: crossplane
755    app.kubernetes.io/version: "1.10.1"
756spec:
757  replicas: 1
758  selector:
759    matchLabels:
760      app: crossplane
761      release: crossplane
762  strategy:
763    type: RollingUpdate
764  template:
765    metadata:
766      labels:
767        app: crossplane
768        release: crossplane
769        helm.sh/chart: crossplane-1.10.1
770        app.kubernetes.io/managed-by: Helm
771        app.kubernetes.io/component: cloud-infrastructure-controller
772        app.kubernetes.io/part-of: crossplane
773        app.kubernetes.io/name: crossplane
774        app.kubernetes.io/instance: crossplane
775        app.kubernetes.io/version: "1.10.1"
776    spec:
777      securityContext:
778        {}
779      serviceAccountName: crossplane
780      initContainers:
781        - image: crossplane/crossplane:v1.10.1
782          args:
783          - core
784          - init
785          imagePullPolicy: IfNotPresent
786          name: crossplane-init
787          resources:
788            limits:
789              cpu: 100m
790              memory: 512Mi
791            requests:
792              cpu: 100m
793              memory: 256Mi
794          securityContext:
795            allowPrivilegeEscalation: false
796            readOnlyRootFilesystem: true
797            runAsGroup: 65532
798            runAsUser: 65532
799          env:
800          - name: POD_NAMESPACE
801            valueFrom:
802              fieldRef:
803                fieldPath: metadata.namespace
804          - name: POD_SERVICE_ACCOUNT
805            valueFrom:
806              fieldRef:
807                fieldPath: spec.serviceAccountName
808      containers:
809      - image: crossplane/crossplane:v1.10.1
810        args:
811        - core
812        - start
813        imagePullPolicy: IfNotPresent
814        name: crossplane
815        resources:
816            limits:
817              cpu: 100m
818              memory: 512Mi
819            requests:
820              cpu: 100m
821              memory: 256Mi
822        securityContext:
823            allowPrivilegeEscalation: false
824            readOnlyRootFilesystem: true
825            runAsGroup: 65532
826            runAsUser: 65532
827        env:
828          - name: POD_NAMESPACE
829            valueFrom:
830              fieldRef:
831                fieldPath: metadata.namespace
832          - name: LEADER_ELECTION
833            value: "true"
834        volumeMounts:
835          - mountPath: /cache
836            name: package-cache
837      volumes:
838      - name: package-cache
839        emptyDir:
840          medium:
841          sizeLimit: 5Mi
842---
843# Source: crossplane/templates/rbac-manager-deployment.yaml
844apiVersion: apps/v1
845kind: Deployment
846metadata:
847  name: crossplane-rbac-manager
848  labels:
849    app: crossplane-rbac-manager
850    release: crossplane
851    helm.sh/chart: crossplane-1.10.1
852    app.kubernetes.io/managed-by: Helm
853    app.kubernetes.io/component: cloud-infrastructure-controller
854    app.kubernetes.io/part-of: crossplane
855    app.kubernetes.io/name: crossplane
856    app.kubernetes.io/instance: crossplane
857    app.kubernetes.io/version: "1.10.1"
858spec:
859  replicas: 1
860  selector:
861    matchLabels:
862      app: crossplane-rbac-manager
863      release: crossplane
864  strategy:
865    type: RollingUpdate
866  template:
867    metadata:
868      labels:
869        app: crossplane-rbac-manager
870        release: crossplane
871        helm.sh/chart: crossplane-1.10.1
872        app.kubernetes.io/managed-by: Helm
873        app.kubernetes.io/component: cloud-infrastructure-controller
874        app.kubernetes.io/part-of: crossplane
875        app.kubernetes.io/name: crossplane
876        app.kubernetes.io/instance: crossplane
877        app.kubernetes.io/version: "1.10.1"
878    spec:
879      securityContext:
880        {}
881      serviceAccountName: rbac-manager
882      initContainers:
883      - image: crossplane/crossplane:v1.10.1
884        args:
885        - rbac
886        - init
887        imagePullPolicy: IfNotPresent
888        name: crossplane-init
889        resources:
890            limits:
891              cpu: 100m
892              memory: 512Mi
893            requests:
894              cpu: 100m
895              memory: 256Mi
896        securityContext:
897            allowPrivilegeEscalation: false
898            readOnlyRootFilesystem: true
899            runAsGroup: 65532
900            runAsUser: 65532
901      containers:
902      - image: crossplane/crossplane:v1.10.1
903        args:
904        - rbac
905        - start
906        - --manage=All
907        - --provider-clusterrole=crossplane:allowed-provider-permissions
908        imagePullPolicy: IfNotPresent
909        name: crossplane
910        resources:
911            limits:
912              cpu: 100m
913              memory: 512Mi
914            requests:
915              cpu: 100m
916              memory: 256Mi
917        securityContext:
918            allowPrivilegeEscalation: false
919            readOnlyRootFilesystem: true
920            runAsGroup: 65532
921            runAsUser: 65532
922        env:
923          - name: LEADER_ELECTION
924            value: "true"
925
926NOTES:
927Release: crossplane
928
929Chart Name: crossplane
930Chart 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.
931Chart Version: 1.10.1
932Chart Application Version: 1.10.1
933
934Kube Version: v1.24.9

Install the Crossplane components using helm install.

1helm install crossplane \
2crossplane-stable/crossplane \
3--namespace crossplane-system \
4--create-namespace

Verify Crossplane installed with kubectl get pods.

1kubectl get pods -n crossplane-system
2NAME                                      READY   STATUS    RESTARTS   AGE
3crossplane-d4cd8d784-ldcgb                1/1     Running   0          54s
4crossplane-rbac-manager-84769b574-6mw6f   1/1     Running   0          54s

Installing Crossplane creates new Kubernetes API end-points. Look at the new API end-points with kubectl api-resources | grep crossplane.

 1kubectl api-resources  | grep crossplane
 2compositeresourcedefinitions      xrd,xrds     apiextensions.crossplane.io/v1         false        CompositeResourceDefinition
 3compositionrevisions                           apiextensions.crossplane.io/v1alpha1   false        CompositionRevision
 4compositions                                   apiextensions.crossplane.io/v1         false        Composition
 5configurationrevisions                         pkg.crossplane.io/v1                   false        ConfigurationRevision
 6configurations                                 pkg.crossplane.io/v1                   false        Configuration
 7controllerconfigs                              pkg.crossplane.io/v1alpha1             false        ControllerConfig
 8locks                                          pkg.crossplane.io/v1beta1              false        Lock
 9providerrevisions                              pkg.crossplane.io/v1                   false        ProviderRevision
10providers                                      pkg.crossplane.io/v1                   false        Provider
11storeconfigs                                   secrets.crossplane.io/v1alpha1         false        StoreConfig

Install the Azure provider

Install the provider into the Kubernetes cluster with a Kubernetes configuration file.

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

The Crossplane Provider Custom Resource Definitions tells Kubernetes how to connect to the provider.

Verify the provider installed with kubectl get providers.

Tip
It may take up to five minutes for the provider to list HEALTHY as True.
1kubectl get providers
2NAME                     INSTALLED   HEALTHY   PACKAGE                                          AGE
3upbound-provider-azure   True        True      xpkg.upbound.io/upbound/provider-azure:v0.32.0   22m

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

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

Tip
See details about all the supported CRDs in the Upbound Marketplace.

Create a Kubernetes secret for Azure

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

This guide generates an Azure service principal JSON file and saves it as a Kubernetes Secret.

Tip
Other authentication methods exist and are beyond the scope of this guide. The Provider documentation contains information on alternative authentication methods.

Install the Azure command-line

Generating an authentication file requires the Azure command-line.
Follow the documentation from Microsoft to Download and install the Azure command-line.

Log in to the Azure command-line.

az login

Create an Azure service principal

Follow the Azure documentation to find your Subscription ID from the Azure Portal.

Using the Azure command-line and provide your Subscription ID create a service principal and authentication file.

1az ad sp create-for-rbac \
2--sdk-auth \
3--role Owner \
4--scopes /subscriptions/$$<subscription_id>$$

Save your Azure JSON output as azure-credentials.json.

Tip
The Azure Provider Authentication documentation describes other authentication methods.

Create a Kubernetes secret with the Azure credentials

A Kubernetes generic secret has a name and contents. Use kubectl create secret to generate the secret object named azure-secret in the crossplane-system namespace.

Use the --from-file= argument to set the value to the contents of the azure-credentials.json file.

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

View the secret with kubectl describe secret

Tip
The size may be larger if there are extra blank spaces in your text file.
 1kubectl describe secret azure-secret -n crossplane-system
 2Name:         azure-secret
 3Namespace:    crossplane-system
 4Labels:       <none>
 5Annotations:  <none>
 6
 7Type:  Opaque
 8
 9Data
10====
11creds:  629 bytes

Create a ProviderConfig

A ProviderConfig customizes the settings of the Azure Provider.

Apply the ProviderConfig with the command:

 1cat <<EOF | kubectl apply -f -
 2apiVersion: azure.upbound.io/v1beta1
 3metadata:
 4  name: default
 5kind: ProviderConfig
 6spec:
 7  credentials:
 8    source: Secret
 9    secretRef:
10      namespace: crossplane-system
11      name: azure-secret
12      key: creds
13EOF

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

The spec.credentials.secretRef.name value is the name of the Kubernetes secret containing the Azure 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 example creates an Azure Virtual Network with Crossplane. The Virtual Network is a managed resource.

Tip
Add your Azure Resource Group name. Follow the Azure documentation to create a resource group if you don’t have one.
 1cat <<EOF | kubectl create -f -
 2apiVersion: network.azure.upbound.io/v1beta1
 3kind: VirtualNetwork
 4metadata:
 5  name: crossplane-quickstart-network
 6spec:
 7  forProvider:
 8    addressSpace:
 9      - 10.0.0.0/16
10    location: "Sweden Central"
11    resourceGroupName: docs
12EOF

The apiVersion and kind are from the provider’s CRDs.

The spec.forProvider.location tells Azure which location to use when deploying the resource.

Use kubectl get virtualnetwork.network to verify Crossplane created the Azure Virtual Network.

Tip
Crossplane created the virtual network when the values READY and SYNCED are True.
This may take up to 5 minutes.
1kubectl get virtualnetwork.network
2NAME                            READY   SYNCED   EXTERNAL-NAME                   AGE
3crossplane-quickstart-network   True    True     crossplane-quickstart-network   10m

Delete the managed resource

Before shutting down your Kubernetes cluster, delete the virtual network just created.

Use kubectl delete virtualnetwork.network to delete the virtual network.

1kubectl delete virtualnetwork.network crossplane-quickstart-network
2virtualnetwork.network.azure.upbound.io "crossplane-quickstart-network" deleted

Next steps