This document is for an unreleased version of Crossplane.

This document applies to the Crossplane master branch and not to the latest release v1.13.

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

This guide is in two parts:

  • Part 1 walks through installing Crossplane, configuring the provider to authenticate to AWS and creating a Managed Resource in AWS directly from your Kubernetes cluster. This shows Crossplane can communicate with AWS.
  • Part 2 shows how to build and access a custom API with Crossplane.

Prerequisites

This quickstart requires:

  • a Kubernetes cluster with at least 2 GB of RAM
  • permissions to create pods and secrets in the Kubernetes cluster
  • Helm version v3.2.0 or later
  • an AWS account with permissions to create an S3 storage bucket
  • AWS access keys

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
3helm 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:200: [debug] Original chart version: ""
   7install.go:217: [debug] CHART PATH: /home/vagrant/.cache/helm/repository/crossplane-1.13.0.tgz
   8
   9NAME: crossplane
  10LAST DEPLOYED: Fri Jul 28 13:57:41 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: {}
  28extraVolumeMountsCrossplane: {}
  29extraVolumesCrossplane: {}
  30hostNetwork: false
  31image:
  32  pullPolicy: IfNotPresent
  33  repository: crossplane/crossplane
  34  tag: ""
  35imagePullSecrets: {}
  36leaderElection: true
  37metrics:
  38  enabled: false
  39nodeSelector: {}
  40packageCache:
  41  configMap: ""
  42  medium: ""
  43  pvc: ""
  44  sizeLimit: 20Mi
  45podSecurityContextCrossplane: {}
  46podSecurityContextRBACManager: {}
  47priorityClassName: ""
  48provider:
  49  packages: []
  50rbacManager:
  51  affinity: {}
  52  args: []
  53  deploy: true
  54  leaderElection: true
  55  managementPolicy: Basic
  56  nodeSelector: {}
  57  replicas: 1
  58  skipAggregatedClusterRoles: false
  59  tolerations: []
  60registryCaBundleConfig:
  61  key: ""
  62  name: ""
  63replicas: 1
  64resourcesCrossplane:
  65  limits:
  66    cpu: 100m
  67    memory: 512Mi
  68  requests:
  69    cpu: 100m
  70    memory: 256Mi
  71resourcesRBACManager:
  72  limits:
  73    cpu: 100m
  74    memory: 512Mi
  75  requests:
  76    cpu: 100m
  77    memory: 256Mi
  78securityContextCrossplane:
  79  allowPrivilegeEscalation: false
  80  readOnlyRootFilesystem: true
  81  runAsGroup: 65532
  82  runAsUser: 65532
  83securityContextRBACManager:
  84  allowPrivilegeEscalation: false
  85  readOnlyRootFilesystem: true
  86  runAsGroup: 65532
  87  runAsUser: 65532
  88serviceAccount:
  89  customAnnotations: {}
  90tolerations: []
  91webhooks:
  92  enabled: true
  93xfn:
  94  args: []
  95  cache:
  96    configMap: ""
  97    medium: ""
  98    pvc: ""
  99    sizeLimit: 1Gi
 100  enabled: false
 101  extraEnvVars: {}
 102  image:
 103    pullPolicy: IfNotPresent
 104    repository: crossplane/xfn
 105    tag: ""
 106  resources:
 107    limits:
 108      cpu: 2000m
 109      memory: 2Gi
 110    requests:
 111      cpu: 1000m
 112      memory: 1Gi
 113  securityContext:
 114    allowPrivilegeEscalation: false
 115    capabilities:
 116      add:
 117      - SETUID
 118      - SETGID
 119    readOnlyRootFilesystem: true
 120    runAsGroup: 65532
 121    runAsUser: 65532
 122    seccompProfile:
 123      type: Unconfined
 124
 125HOOKS:
 126MANIFEST:
 127---
 128# Source: crossplane/templates/rbac-manager-serviceaccount.yaml
 129apiVersion: v1
 130kind: ServiceAccount
 131metadata:
 132  name: rbac-manager
 133  namespace: crossplane-system
 134  labels:
 135    app: crossplane
 136    helm.sh/chart: crossplane-1.13.0
 137    app.kubernetes.io/managed-by: Helm
 138    app.kubernetes.io/component: cloud-infrastructure-controller
 139    app.kubernetes.io/part-of: crossplane
 140    app.kubernetes.io/name: crossplane
 141    app.kubernetes.io/instance: crossplane
 142    app.kubernetes.io/version: "1.13.0"
 143---
 144# Source: crossplane/templates/serviceaccount.yaml
 145apiVersion: v1
 146kind: ServiceAccount
 147metadata:
 148  name: crossplane
 149  namespace: crossplane-system
 150  labels:
 151    app: crossplane
 152    helm.sh/chart: crossplane-1.13.0
 153    app.kubernetes.io/managed-by: Helm
 154    app.kubernetes.io/component: cloud-infrastructure-controller
 155    app.kubernetes.io/part-of: crossplane
 156    app.kubernetes.io/name: crossplane
 157    app.kubernetes.io/instance: crossplane
 158    app.kubernetes.io/version: "1.13.0"
 159---
 160# Source: crossplane/templates/secret.yaml
 161# The reason this is created empty and filled by the init container is that it's
 162# mounted by the actual container, so if it wasn't created by Helm, then the
 163# deployment wouldn't be deployed at all with secret to mount not found error.
 164# In addition, Helm would delete this secret after uninstallation so the new
 165# installation of Crossplane would use its own certificate.
 166apiVersion: v1
 167kind: Secret
 168metadata:
 169  name: webhook-tls-secret
 170  namespace: crossplane-system
 171type: Opaque
 172---
 173# Source: crossplane/templates/clusterrole.yaml
 174apiVersion: rbac.authorization.k8s.io/v1
 175kind: ClusterRole
 176metadata:
 177  name: crossplane
 178  labels:
 179    app: crossplane
 180    helm.sh/chart: crossplane-1.13.0
 181    app.kubernetes.io/managed-by: Helm
 182    app.kubernetes.io/component: cloud-infrastructure-controller
 183    app.kubernetes.io/part-of: crossplane
 184    app.kubernetes.io/name: crossplane
 185    app.kubernetes.io/instance: crossplane
 186    app.kubernetes.io/version: "1.13.0"
 187aggregationRule:
 188  clusterRoleSelectors:
 189  - matchLabels:
 190      rbac.crossplane.io/aggregate-to-crossplane: "true"
 191---
 192# Source: crossplane/templates/clusterrole.yaml
 193apiVersion: rbac.authorization.k8s.io/v1
 194kind: ClusterRole
 195metadata:
 196  name: crossplane:system:aggregate-to-crossplane
 197  labels:
 198    app: crossplane
 199    helm.sh/chart: crossplane-1.13.0
 200    app.kubernetes.io/managed-by: Helm
 201    app.kubernetes.io/component: cloud-infrastructure-controller
 202    app.kubernetes.io/part-of: crossplane
 203    app.kubernetes.io/name: crossplane
 204    app.kubernetes.io/instance: crossplane
 205    app.kubernetes.io/version: "1.13.0"
 206    crossplane.io/scope: "system"
 207    rbac.crossplane.io/aggregate-to-crossplane: "true"
 208rules:
 209- apiGroups:
 210  - ""
 211  resources:
 212  - events
 213  verbs:
 214  - create
 215  - update
 216  - patch
 217  - delete
 218- apiGroups:
 219  - apiextensions.k8s.io
 220  resources:
 221  - customresourcedefinitions
 222  verbs:
 223  - "*"
 224- apiGroups:
 225  - ""
 226  resources:
 227  - secrets
 228  verbs:
 229  - get
 230  - list
 231  - watch
 232  - create
 233  - update
 234  - patch
 235  - delete
 236- apiGroups:
 237  - ""
 238  resources:
 239  - serviceaccounts
 240  - services
 241  verbs:
 242  - "*"
 243- apiGroups:
 244  - apiextensions.crossplane.io
 245  - pkg.crossplane.io
 246  - secrets.crossplane.io
 247  resources:
 248  - "*"
 249  verbs:
 250  - "*"
 251- apiGroups:
 252  - extensions
 253  - apps
 254  resources:
 255  - deployments
 256  verbs:
 257  - get
 258  - list
 259  - create
 260  - update
 261  - patch
 262  - delete
 263  - watch
 264- apiGroups:
 265  - ""
 266  - coordination.k8s.io
 267  resources:
 268  - configmaps
 269  - leases
 270  verbs:
 271  - get
 272  - list
 273  - create
 274  - update
 275  - patch
 276  - watch
 277  - delete
 278- apiGroups:
 279  - admissionregistration.k8s.io
 280  resources:
 281  - validatingwebhookconfigurations
 282  - mutatingwebhookconfigurations
 283  verbs:
 284  - get
 285  - list
 286  - create
 287  - update
 288  - patch
 289  - watch
 290  - delete
 291---
 292# Source: crossplane/templates/rbac-manager-allowed-provider-permissions.yaml
 293apiVersion: rbac.authorization.k8s.io/v1
 294kind: ClusterRole
 295metadata:
 296  name: crossplane:allowed-provider-permissions
 297  labels:
 298    app: crossplane
 299    helm.sh/chart: crossplane-1.13.0
 300    app.kubernetes.io/managed-by: Helm
 301    app.kubernetes.io/component: cloud-infrastructure-controller
 302    app.kubernetes.io/part-of: crossplane
 303    app.kubernetes.io/name: crossplane
 304    app.kubernetes.io/instance: crossplane
 305    app.kubernetes.io/version: "1.13.0"
 306aggregationRule:
 307  clusterRoleSelectors:
 308  - matchLabels:
 309      rbac.crossplane.io/aggregate-to-allowed-provider-permissions: "true"
 310---
 311# Source: crossplane/templates/rbac-manager-clusterrole.yaml
 312apiVersion: rbac.authorization.k8s.io/v1
 313kind: ClusterRole
 314metadata:
 315  name: crossplane-rbac-manager
 316  labels:
 317    app: crossplane
 318    helm.sh/chart: crossplane-1.13.0
 319    app.kubernetes.io/managed-by: Helm
 320    app.kubernetes.io/component: cloud-infrastructure-controller
 321    app.kubernetes.io/part-of: crossplane
 322    app.kubernetes.io/name: crossplane
 323    app.kubernetes.io/instance: crossplane
 324    app.kubernetes.io/version: "1.13.0"
 325rules:
 326- apiGroups:
 327  - ""
 328  resources:
 329  - events
 330  verbs:
 331  - create
 332  - update
 333  - patch
 334  - delete
 335- apiGroups:
 336  - ""
 337  resources:
 338  - namespaces
 339  - serviceaccounts
 340  verbs:
 341  - get
 342  - list
 343  - watch
 344# The RBAC manager creates a series of RBAC roles for each namespace it sees.
 345# These RBAC roles are controlled (in the owner reference sense) by the namespace.
 346# The RBAC manager needs permission to set finalizers on Namespaces in order to
 347# create resources that block their deletion when the
 348# OwnerReferencesPermissionEnforcement admission controller is enabled.
 349# See https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement
 350- apiGroups:
 351  - ""
 352  resources:
 353  - namespaces/finalizers
 354  verbs:
 355  - update
 356- apiGroups:
 357  - apiextensions.crossplane.io
 358  resources:
 359  - compositeresourcedefinitions
 360  verbs:
 361  - get
 362  - list
 363  - watch
 364# The RBAC manager creates a series of RBAC cluster roles for each XRD it sees.
 365# These cluster roles are controlled (in the owner reference sense) by the XRD.
 366# The RBAC manager needs permission to set finalizers on XRDs in order to
 367# create resources that block their deletion when the
 368# OwnerReferencesPermissionEnforcement admission controller is enabled.
 369# See https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement
 370- apiGroups:
 371  - apiextensions.crossplane.io
 372  resources:
 373  - compositeresourcedefinitions/finalizers
 374  verbs:
 375  - update
 376- apiGroups:
 377  - pkg.crossplane.io
 378  resources:
 379  - providerrevisions
 380  verbs:
 381  - get
 382  - list
 383  - watch
 384# The RBAC manager creates a series of RBAC cluster roles for each ProviderRevision
 385# it sees. These cluster roles are controlled (in the owner reference sense) by the
 386# ProviderRevision. The RBAC manager needs permission to set finalizers on
 387# ProviderRevisions in order to create resources that block their deletion when the
 388# OwnerReferencesPermissionEnforcement admission controller is enabled.
 389# See https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement
 390- apiGroups:
 391  - pkg.crossplane.io
 392  resources:
 393  - providerrevisions/finalizers
 394  verbs:
 395  - update
 396- apiGroups:
 397  - apiextensions.k8s.io
 398  resources:
 399  - customresourcedefinitions
 400  verbs:
 401  - get
 402  - list
 403  - watch
 404- apiGroups:
 405  - rbac.authorization.k8s.io
 406  resources:
 407  - clusterroles
 408  - roles
 409  verbs:
 410  - get
 411  - list
 412  - watch
 413  - create
 414  - update
 415  - patch
 416  # The RBAC manager may grant access it does not have.
 417  - escalate
 418- apiGroups:
 419  - rbac.authorization.k8s.io
 420  resources:
 421  - clusterroles
 422  verbs:
 423  - bind
 424- apiGroups:
 425  - rbac.authorization.k8s.io
 426  resources:
 427  - clusterrolebindings
 428  verbs:
 429  - "*"
 430- apiGroups:
 431  - ""
 432  - coordination.k8s.io
 433  resources:
 434  - configmaps
 435  - leases
 436  verbs:
 437  - get
 438  - list
 439  - create
 440  - update
 441  - patch
 442  - watch
 443  - delete
 444---
 445# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
 446apiVersion: rbac.authorization.k8s.io/v1
 447kind: ClusterRole
 448metadata:
 449  name: crossplane-admin
 450  labels:
 451    app: crossplane
 452    helm.sh/chart: crossplane-1.13.0
 453    app.kubernetes.io/managed-by: Helm
 454    app.kubernetes.io/component: cloud-infrastructure-controller
 455    app.kubernetes.io/part-of: crossplane
 456    app.kubernetes.io/name: crossplane
 457    app.kubernetes.io/instance: crossplane
 458    app.kubernetes.io/version: "1.13.0"
 459aggregationRule:
 460  clusterRoleSelectors:
 461  - matchLabels:
 462      rbac.crossplane.io/aggregate-to-admin: "true"
 463---
 464# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
 465apiVersion: rbac.authorization.k8s.io/v1
 466kind: ClusterRole
 467metadata:
 468  name: crossplane-edit
 469  labels:
 470    app: crossplane
 471    helm.sh/chart: crossplane-1.13.0
 472    app.kubernetes.io/managed-by: Helm
 473    app.kubernetes.io/component: cloud-infrastructure-controller
 474    app.kubernetes.io/part-of: crossplane
 475    app.kubernetes.io/name: crossplane
 476    app.kubernetes.io/instance: crossplane
 477    app.kubernetes.io/version: "1.13.0"
 478aggregationRule:
 479  clusterRoleSelectors:
 480  - matchLabels:
 481      rbac.crossplane.io/aggregate-to-edit: "true"
 482---
 483# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
 484apiVersion: rbac.authorization.k8s.io/v1
 485kind: ClusterRole
 486metadata:
 487  name: crossplane-view
 488  labels:
 489    app: crossplane
 490    helm.sh/chart: crossplane-1.13.0
 491    app.kubernetes.io/managed-by: Helm
 492    app.kubernetes.io/component: cloud-infrastructure-controller
 493    app.kubernetes.io/part-of: crossplane
 494    app.kubernetes.io/name: crossplane
 495    app.kubernetes.io/instance: crossplane
 496    app.kubernetes.io/version: "1.13.0"
 497aggregationRule:
 498  clusterRoleSelectors:
 499  - matchLabels:
 500      rbac.crossplane.io/aggregate-to-view: "true"
 501---
 502# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
 503apiVersion: rbac.authorization.k8s.io/v1
 504kind: ClusterRole
 505metadata:
 506  name: crossplane-browse
 507  labels:
 508    app: crossplane
 509    helm.sh/chart: crossplane-1.13.0
 510    app.kubernetes.io/managed-by: Helm
 511    app.kubernetes.io/component: cloud-infrastructure-controller
 512    app.kubernetes.io/part-of: crossplane
 513    app.kubernetes.io/name: crossplane
 514    app.kubernetes.io/instance: crossplane
 515    app.kubernetes.io/version: "1.13.0"
 516aggregationRule:
 517  clusterRoleSelectors:
 518  - matchLabels:
 519      rbac.crossplane.io/aggregate-to-browse: "true"
 520---
 521# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
 522apiVersion: rbac.authorization.k8s.io/v1
 523kind: ClusterRole
 524metadata:
 525  name: crossplane:aggregate-to-admin
 526  labels:
 527    rbac.crossplane.io/aggregate-to-admin: "true"
 528    app: crossplane
 529    helm.sh/chart: crossplane-1.13.0
 530    app.kubernetes.io/managed-by: Helm
 531    app.kubernetes.io/component: cloud-infrastructure-controller
 532    app.kubernetes.io/part-of: crossplane
 533    app.kubernetes.io/name: crossplane
 534    app.kubernetes.io/instance: crossplane
 535    app.kubernetes.io/version: "1.13.0"
 536rules:
 537# Crossplane administrators have access to view events.
 538- apiGroups: [""]
 539  resources: [events]
 540  verbs: [get, list, watch]
 541# Crossplane administrators must create provider credential secrets, and may
 542# need to read or otherwise interact with connection secrets. They may also need
 543# to create or annotate namespaces.
 544- apiGroups: [""]
 545  resources: [secrets, namespaces]
 546  verbs: ["*"]
 547# Crossplane administrators have access to view the roles that they may be able
 548# to grant to other subjects.
 549- apiGroups: [rbac.authorization.k8s.io]
 550  resources: [clusterroles, roles]
 551  verbs: [get, list, watch]
 552# Crossplane administrators have access to grant the access they have to other
 553# subjects.
 554- apiGroups: [rbac.authorization.k8s.io]
 555  resources: [clusterrolebindings, rolebindings]
 556  verbs: ["*"]
 557# Crossplane administrators have full access to built in Crossplane types.
 558- apiGroups:
 559  - apiextensions.crossplane.io
 560  resources: ["*"]
 561  verbs: ["*"]
 562- apiGroups:
 563  - pkg.crossplane.io
 564  resources: [locks, providers, configurations, providerrevisions, configurationrevisions]
 565  verbs: ["*"]
 566# Crossplane administrators have access to view CRDs in order to debug XRDs.
 567- apiGroups: [apiextensions.k8s.io]
 568  resources: [customresourcedefinitions]
 569  verbs: [get, list, watch]
 570---
 571# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
 572apiVersion: rbac.authorization.k8s.io/v1
 573kind: ClusterRole
 574metadata:
 575  name: crossplane:aggregate-to-edit
 576  labels:
 577    rbac.crossplane.io/aggregate-to-edit: "true"
 578    app: crossplane
 579    helm.sh/chart: crossplane-1.13.0
 580    app.kubernetes.io/managed-by: Helm
 581    app.kubernetes.io/component: cloud-infrastructure-controller
 582    app.kubernetes.io/part-of: crossplane
 583    app.kubernetes.io/name: crossplane
 584    app.kubernetes.io/instance: crossplane
 585    app.kubernetes.io/version: "1.13.0"
 586rules:
 587# Crossplane editors have access to view events.
 588- apiGroups: [""]
 589  resources: [events]
 590  verbs: [get, list, watch]
 591# Crossplane editors must create provider credential secrets, and may need to
 592# read or otherwise interact with connection secrets.
 593- apiGroups: [""]
 594  resources: [secrets]
 595  verbs: ["*"]
 596# Crossplane editors may see which namespaces exist, but not edit them.
 597- apiGroups: [""]
 598  resources: [namespaces]
 599  verbs: [get, list, watch]
 600# Crossplane editors have full access to built in Crossplane types.
 601- apiGroups:
 602  - apiextensions.crossplane.io
 603  resources: ["*"]
 604  verbs: ["*"]
 605- apiGroups:
 606  - pkg.crossplane.io
 607  resources: [locks, providers, configurations, providerrevisions, configurationrevisions]
 608  verbs: ["*"]
 609---
 610# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
 611apiVersion: rbac.authorization.k8s.io/v1
 612kind: ClusterRole
 613metadata:
 614  name: crossplane:aggregate-to-view
 615  labels:
 616    rbac.crossplane.io/aggregate-to-view: "true"
 617    app: crossplane
 618    helm.sh/chart: crossplane-1.13.0
 619    app.kubernetes.io/managed-by: Helm
 620    app.kubernetes.io/component: cloud-infrastructure-controller
 621    app.kubernetes.io/part-of: crossplane
 622    app.kubernetes.io/name: crossplane
 623    app.kubernetes.io/instance: crossplane
 624    app.kubernetes.io/version: "1.13.0"
 625rules:
 626# Crossplane viewers have access to view events.
 627- apiGroups: [""]
 628  resources: [events]
 629  verbs: [get, list, watch]
 630# Crossplane viewers may see which namespaces exist.
 631- apiGroups: [""]
 632  resources: [namespaces]
 633  verbs: [get, list, watch]
 634# Crossplane viewers have read-only access to built in Crossplane types.
 635- apiGroups:
 636  - apiextensions.crossplane.io
 637  resources: ["*"]
 638  verbs: [get, list, watch]
 639- apiGroups:
 640  - pkg.crossplane.io
 641  resources: [locks, providers, configurations, providerrevisions, configurationrevisions]
 642  verbs: [get, list, watch]
 643---
 644# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
 645apiVersion: rbac.authorization.k8s.io/v1
 646kind: ClusterRole
 647metadata:
 648  name: crossplane:aggregate-to-browse
 649  labels:
 650    rbac.crossplane.io/aggregate-to-browse: "true"
 651    app: crossplane
 652    helm.sh/chart: crossplane-1.13.0
 653    app.kubernetes.io/managed-by: Helm
 654    app.kubernetes.io/component: cloud-infrastructure-controller
 655    app.kubernetes.io/part-of: crossplane
 656    app.kubernetes.io/name: crossplane
 657    app.kubernetes.io/instance: crossplane
 658    app.kubernetes.io/version: "1.13.0"
 659rules:
 660# Crossplane browsers have access to view events.
 661- apiGroups: [""]
 662  resources: [events]
 663  verbs: [get, list, watch]
 664# Crossplane browsers have read-only access to compositions and XRDs. This
 665# allows them to discover and select an appropriate composition when creating a
 666# resource claim.
 667- apiGroups:
 668  - apiextensions.crossplane.io
 669  resources: ["*"]
 670  verbs: [get, list, watch]
 671---
 672# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
 673# The below ClusterRoles are aggregated to the namespaced RBAC roles created by
 674# the Crossplane RBAC manager when it is running in --manage=All mode.
 675apiVersion: rbac.authorization.k8s.io/v1
 676kind: ClusterRole
 677metadata:
 678  name: crossplane:aggregate-to-ns-admin
 679  labels:
 680    rbac.crossplane.io/aggregate-to-ns-admin: "true"
 681    rbac.crossplane.io/base-of-ns-admin: "true"
 682    app: crossplane
 683    helm.sh/chart: crossplane-1.13.0
 684    app.kubernetes.io/managed-by: Helm
 685    app.kubernetes.io/component: cloud-infrastructure-controller
 686    app.kubernetes.io/part-of: crossplane
 687    app.kubernetes.io/name: crossplane
 688    app.kubernetes.io/instance: crossplane
 689    app.kubernetes.io/version: "1.13.0"
 690rules:
 691# Crossplane namespace admins have access to view events.
 692- apiGroups: [""]
 693  resources: [events]
 694  verbs: [get, list, watch]
 695# Crossplane namespace admins may need to read or otherwise interact with
 696# resource claim connection secrets.
 697- apiGroups: [""]
 698  resources: [secrets]
 699  verbs: ["*"]
 700# Crossplane namespace admins have access to view the roles that they may be
 701# able to grant to other subjects.
 702- apiGroups: [rbac.authorization.k8s.io]
 703  resources: [roles]
 704  verbs: [get, list, watch]
 705# Crossplane namespace admins have access to grant the access they have to other
 706# subjects.
 707- apiGroups: [rbac.authorization.k8s.io]
 708  resources: [rolebindings]
 709  verbs: ["*"]
 710---
 711# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
 712apiVersion: rbac.authorization.k8s.io/v1
 713kind: ClusterRole
 714metadata:
 715  name: crossplane:aggregate-to-ns-edit
 716  labels:
 717    rbac.crossplane.io/aggregate-to-ns-edit: "true"
 718    rbac.crossplane.io/base-of-ns-edit: "true"
 719    app: crossplane
 720    helm.sh/chart: crossplane-1.13.0
 721    app.kubernetes.io/managed-by: Helm
 722    app.kubernetes.io/component: cloud-infrastructure-controller
 723    app.kubernetes.io/part-of: crossplane
 724    app.kubernetes.io/name: crossplane
 725    app.kubernetes.io/instance: crossplane
 726    app.kubernetes.io/version: "1.13.0"
 727rules:
 728# Crossplane namespace editors have access to view events.
 729- apiGroups: [""]
 730  resources: [events]
 731  verbs: [get, list, watch]
 732# Crossplane namespace editors may need to read or otherwise interact with
 733# resource claim connection secrets.
 734- apiGroups: [""]
 735  resources: [secrets]
 736  verbs: ["*"]
 737---
 738# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
 739apiVersion: rbac.authorization.k8s.io/v1
 740kind: ClusterRole
 741metadata:
 742  name: crossplane:aggregate-to-ns-view
 743  labels:
 744    rbac.crossplane.io/aggregate-to-ns-view: "true"
 745    rbac.crossplane.io/base-of-ns-view: "true"
 746    app: crossplane
 747    helm.sh/chart: crossplane-1.13.0
 748    app.kubernetes.io/managed-by: Helm
 749    app.kubernetes.io/component: cloud-infrastructure-controller
 750    app.kubernetes.io/part-of: crossplane
 751    app.kubernetes.io/name: crossplane
 752    app.kubernetes.io/instance: crossplane
 753    app.kubernetes.io/version: "1.13.0"
 754rules:
 755# Crossplane namespace viewers have access to view events.
 756- apiGroups: [""]
 757  resources: [events]
 758  verbs: [get, list, watch]
 759---
 760# Source: crossplane/templates/clusterrolebinding.yaml
 761apiVersion: rbac.authorization.k8s.io/v1
 762kind: ClusterRoleBinding
 763metadata:
 764  name: crossplane
 765  labels:
 766    app: crossplane
 767    helm.sh/chart: crossplane-1.13.0
 768    app.kubernetes.io/managed-by: Helm
 769    app.kubernetes.io/component: cloud-infrastructure-controller
 770    app.kubernetes.io/part-of: crossplane
 771    app.kubernetes.io/name: crossplane
 772    app.kubernetes.io/instance: crossplane
 773    app.kubernetes.io/version: "1.13.0"
 774roleRef:
 775  apiGroup: rbac.authorization.k8s.io
 776  kind: ClusterRole
 777  name: crossplane
 778subjects:
 779- kind: ServiceAccount
 780  name: crossplane
 781  namespace: crossplane-system
 782---
 783# Source: crossplane/templates/rbac-manager-clusterrolebinding.yaml
 784apiVersion: rbac.authorization.k8s.io/v1
 785kind: ClusterRoleBinding
 786metadata:
 787  name: crossplane-rbac-manager
 788  labels:
 789    app: crossplane
 790    helm.sh/chart: crossplane-1.13.0
 791    app.kubernetes.io/managed-by: Helm
 792    app.kubernetes.io/component: cloud-infrastructure-controller
 793    app.kubernetes.io/part-of: crossplane
 794    app.kubernetes.io/name: crossplane
 795    app.kubernetes.io/instance: crossplane
 796    app.kubernetes.io/version: "1.13.0"
 797roleRef:
 798  apiGroup: rbac.authorization.k8s.io
 799  kind: ClusterRole
 800  name: crossplane-rbac-manager
 801subjects:
 802- kind: ServiceAccount
 803  name: rbac-manager
 804  namespace: crossplane-system
 805---
 806# Source: crossplane/templates/rbac-manager-managed-clusterroles.yaml
 807apiVersion: rbac.authorization.k8s.io/v1
 808kind: ClusterRoleBinding
 809metadata:
 810  name: crossplane-admin
 811  labels:
 812    app: crossplane
 813    helm.sh/chart: crossplane-1.13.0
 814    app.kubernetes.io/managed-by: Helm
 815    app.kubernetes.io/component: cloud-infrastructure-controller
 816    app.kubernetes.io/part-of: crossplane
 817    app.kubernetes.io/name: crossplane
 818    app.kubernetes.io/instance: crossplane
 819    app.kubernetes.io/version: "1.13.0"
 820roleRef:
 821  apiGroup: rbac.authorization.k8s.io
 822  kind: ClusterRole
 823  name: crossplane-admin
 824subjects:
 825- apiGroup: rbac.authorization.k8s.io
 826  kind: Group
 827  name: crossplane:masters
 828---
 829# Source: crossplane/templates/service.yaml
 830apiVersion: v1
 831kind: Service
 832metadata:
 833  name: crossplane-webhooks
 834  namespace: crossplane-system
 835  labels:
 836    app: crossplane
 837    release: crossplane
 838    helm.sh/chart: crossplane-1.13.0
 839    app.kubernetes.io/managed-by: Helm
 840    app.kubernetes.io/component: cloud-infrastructure-controller
 841    app.kubernetes.io/part-of: crossplane
 842    app.kubernetes.io/name: crossplane
 843    app.kubernetes.io/instance: crossplane
 844    app.kubernetes.io/version: "1.13.0"
 845spec:
 846  selector:
 847    app: crossplane
 848    release: crossplane
 849  ports:
 850  - protocol: TCP
 851    port: 9443
 852    targetPort: 9443
 853---
 854# Source: crossplane/templates/deployment.yaml
 855apiVersion: apps/v1
 856kind: Deployment
 857metadata:
 858  name: crossplane
 859  namespace: crossplane-system
 860  labels:
 861    app: crossplane
 862    release: crossplane
 863    helm.sh/chart: crossplane-1.13.0
 864    app.kubernetes.io/managed-by: Helm
 865    app.kubernetes.io/component: cloud-infrastructure-controller
 866    app.kubernetes.io/part-of: crossplane
 867    app.kubernetes.io/name: crossplane
 868    app.kubernetes.io/instance: crossplane
 869    app.kubernetes.io/version: "1.13.0"
 870spec:
 871  replicas: 1
 872  selector:
 873    matchLabels:
 874      app: crossplane
 875      release: crossplane
 876  strategy:
 877    type: RollingUpdate
 878  template:
 879    metadata:
 880      labels:
 881        app: crossplane
 882        release: crossplane
 883        helm.sh/chart: crossplane-1.13.0
 884        app.kubernetes.io/managed-by: Helm
 885        app.kubernetes.io/component: cloud-infrastructure-controller
 886        app.kubernetes.io/part-of: crossplane
 887        app.kubernetes.io/name: crossplane
 888        app.kubernetes.io/instance: crossplane
 889        app.kubernetes.io/version: "1.13.0"
 890    spec:
 891      securityContext:
 892        {}
 893      serviceAccountName: crossplane
 894      hostNetwork: false
 895      initContainers:
 896        - image: "crossplane/crossplane:v1.13.0"
 897          args:
 898          - core
 899          - init
 900          imagePullPolicy: IfNotPresent
 901          name: crossplane-init
 902          resources:
 903            limits:
 904              cpu: 100m
 905              memory: 512Mi
 906            requests:
 907              cpu: 100m
 908              memory: 256Mi
 909          securityContext:
 910            allowPrivilegeEscalation: false
 911            readOnlyRootFilesystem: true
 912            runAsGroup: 65532
 913            runAsUser: 65532
 914          env:
 915          - name: GOMAXPROCS
 916            valueFrom:
 917              resourceFieldRef:
 918                containerName: crossplane-init
 919                resource: limits.cpu
 920          - name: GOMEMLIMIT
 921            valueFrom:
 922              resourceFieldRef:
 923                containerName: crossplane-init
 924                resource: limits.memory
 925          - name: POD_NAMESPACE
 926            valueFrom:
 927              fieldRef:
 928                fieldPath: metadata.namespace
 929          - name: POD_SERVICE_ACCOUNT
 930            valueFrom:
 931              fieldRef:
 932                fieldPath: spec.serviceAccountName
 933          - name: "WEBHOOK_TLS_SECRET_NAME"
 934            value: webhook-tls-secret
 935          - name: "WEBHOOK_SERVICE_NAME"
 936            value: crossplane-webhooks
 937          - name: "WEBHOOK_SERVICE_NAMESPACE"
 938            valueFrom:
 939              fieldRef:
 940                fieldPath: metadata.namespace
 941          - name: "WEBHOOK_SERVICE_PORT"
 942            value: "9443"
 943      containers:
 944      - image: "crossplane/crossplane:v1.13.0"
 945        args:
 946        - core
 947        - start
 948        imagePullPolicy: IfNotPresent
 949        name: crossplane
 950        resources:
 951            limits:
 952              cpu: 100m
 953              memory: 512Mi
 954            requests:
 955              cpu: 100m
 956              memory: 256Mi
 957        ports:
 958        - name: webhooks
 959          containerPort: 9443
 960        securityContext:
 961            allowPrivilegeEscalation: false
 962            readOnlyRootFilesystem: true
 963            runAsGroup: 65532
 964            runAsUser: 65532
 965        env:
 966          - name: GOMAXPROCS
 967            valueFrom:
 968              resourceFieldRef:
 969                containerName: crossplane
 970                resource: limits.cpu
 971          - name: GOMEMLIMIT
 972            valueFrom:
 973              resourceFieldRef:
 974                containerName: crossplane
 975                resource: limits.memory
 976          - name: POD_NAMESPACE
 977            valueFrom:
 978              fieldRef:
 979                fieldPath: metadata.namespace
 980          - name: POD_SERVICE_ACCOUNT
 981            valueFrom:
 982              fieldRef:
 983                fieldPath: spec.serviceAccountName
 984          - name: LEADER_ELECTION
 985            value: "true"
 986          - name: "WEBHOOK_TLS_SECRET_NAME"
 987            value: webhook-tls-secret
 988          - name: "WEBHOOK_TLS_CERT_DIR"
 989            value: /webhook/tls
 990        volumeMounts:
 991          - mountPath: /cache
 992            name: package-cache
 993          - mountPath: /webhook/tls
 994            name: webhook-tls-secret
 995      volumes:
 996      - name: package-cache
 997        emptyDir:
 998          medium:
 999          sizeLimit: 20Mi
1000      - name: webhook-tls-secret
1001        secret:
1002          # NOTE(muvaf): The tls.crt is used both by the server (requires it to
1003          # be a single cert) and the caBundle fields of webhook configs and CRDs
1004          # which can accept a whole bundle of certificates. In order to meet
1005          # the requirements of both, we require a single certificate instead of
1006          # a bundle.
1007          # It's assumed that initializer generates this anyway, so it should be
1008          # fine.
1009          secretName: webhook-tls-secret
1010---
1011# Source: crossplane/templates/rbac-manager-deployment.yaml
1012apiVersion: apps/v1
1013kind: Deployment
1014metadata:
1015  name: crossplane-rbac-manager
1016  namespace: crossplane-system
1017  labels:
1018    app: crossplane-rbac-manager
1019    release: crossplane
1020    helm.sh/chart: crossplane-1.13.0
1021    app.kubernetes.io/managed-by: Helm
1022    app.kubernetes.io/component: cloud-infrastructure-controller
1023    app.kubernetes.io/part-of: crossplane
1024    app.kubernetes.io/name: crossplane
1025    app.kubernetes.io/instance: crossplane
1026    app.kubernetes.io/version: "1.13.0"
1027spec:
1028  replicas: 1
1029  selector:
1030    matchLabels:
1031      app: crossplane-rbac-manager
1032      release: crossplane
1033  strategy:
1034    type: RollingUpdate
1035  template:
1036    metadata:
1037      labels:
1038        app: crossplane-rbac-manager
1039        release: crossplane
1040        helm.sh/chart: crossplane-1.13.0
1041        app.kubernetes.io/managed-by: Helm
1042        app.kubernetes.io/component: cloud-infrastructure-controller
1043        app.kubernetes.io/part-of: crossplane
1044        app.kubernetes.io/name: crossplane
1045        app.kubernetes.io/instance: crossplane
1046        app.kubernetes.io/version: "1.13.0"
1047    spec:
1048      securityContext:
1049        {}
1050      serviceAccountName: rbac-manager
1051      initContainers:
1052      - image: "crossplane/crossplane:v1.13.0"
1053        args:
1054        - rbac
1055        - init
1056        imagePullPolicy: IfNotPresent
1057        name: crossplane-init
1058        resources:
1059            limits:
1060              cpu: 100m
1061              memory: 512Mi
1062            requests:
1063              cpu: 100m
1064              memory: 256Mi
1065        securityContext:
1066            allowPrivilegeEscalation: false
1067            readOnlyRootFilesystem: true
1068            runAsGroup: 65532
1069            runAsUser: 65532
1070        env:
1071          - name: GOMAXPROCS
1072            valueFrom:
1073              resourceFieldRef:
1074                containerName: crossplane-init
1075                resource: limits.cpu
1076          - name: GOMEMLIMIT
1077            valueFrom:
1078              resourceFieldRef:
1079                containerName: crossplane-init
1080                resource: limits.memory
1081      containers:
1082      - image: "crossplane/crossplane:v1.13.0"
1083        args:
1084        - rbac
1085        - start
1086        - --manage=Basic
1087        - --provider-clusterrole=crossplane:allowed-provider-permissions
1088        imagePullPolicy: IfNotPresent
1089        name: crossplane
1090        resources:
1091            limits:
1092              cpu: 100m
1093              memory: 512Mi
1094            requests:
1095              cpu: 100m
1096              memory: 256Mi
1097        securityContext:
1098            allowPrivilegeEscalation: false
1099            readOnlyRootFilesystem: true
1100            runAsGroup: 65532
1101            runAsUser: 65532
1102        env:
1103          - name: GOMAXPROCS
1104            valueFrom:
1105              resourceFieldRef:
1106                containerName: crossplane
1107                resource: limits.cpu
1108          - name: GOMEMLIMIT
1109            valueFrom:
1110              resourceFieldRef:
1111                containerName: crossplane
1112                resource: limits.memory
1113          - name: LEADER_ELECTION
1114            value: "true"
1115
1116NOTES:
1117Release: crossplane
1118
1119Chart Name: crossplane
1120Chart 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.
1121Chart Version: 1.13.0
1122Chart Application Version: 1.13.0
1123
1124Kube Version: v1.27.4

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              comprev      apiextensions.crossplane.io/v1         false        CompositionRevision
 4compositions                      comp         apiextensions.crossplane.io/v1         false        Composition
 5environmentconfigs                envcfg       apiextensions.crossplane.io/v1alpha1   false        EnvironmentConfig
 6configurationrevisions                         pkg.crossplane.io/v1                   false        ConfigurationRevision
 7configurations                                 pkg.crossplane.io/v1                   false        Configuration
 8controllerconfigs                              pkg.crossplane.io/v1alpha1             false        ControllerConfig
 9locks                                          pkg.crossplane.io/v1beta1              false        Lock
10providerrevisions                              pkg.crossplane.io/v1                   false        ProviderRevision
11providers                                      pkg.crossplane.io/v1                   false        Provider
12storeconfigs                                   secrets.crossplane.io/v1alpha1         false        StoreConfig

Install the AWS provider

Install the AWS S3 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: provider-aws-s3
6spec:
7  package: xpkg.upbound.io/upbound/provider-aws-s3:v0.37.0
8EOF

The Crossplane Provider installs the Kubernetes Custom Resource Definitions (CRDs) representing AWS S3 services. These CRDs allow you to create AWS resources directly inside Kubernetes.

Verify the provider installed with kubectl get providers.

1kubectl get providers
2NAME                          INSTALLED   HEALTHY   PACKAGE                                               AGE
3provider-aws-s3               True        True      xpkg.upbound.io/upbound/provider-aws-s3:v0.37.0       2m53s
4upbound-provider-family-aws   True        True      xpkg.upbound.io/upbound/provider-family-aws:v0.37.0   2m48s

The S3 Provider installs a second Provider, the upbound-provider-family-aws.
The family provider manages authentication to AWS across all AWS family Providers.

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

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

Create a Kubernetes secret for AWS

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

Generate a Kubernetes Secret from your AWS key-pair and then configure the Provider to use it.

Generate an AWS key-pair file

For basic user authentication, use an AWS Access keys key-pair file.

Tip
The AWS documentation provides information on how to generate AWS Access keys.

Create a text file containing the AWS account aws_access_key_id and aws_secret_access_key.

1[default]
2aws_access_key_id = 
3aws_secret_access_key = 

Save this text file as aws-credentials.txt.

Tip
The Authentication section of the AWS Provider documentation describes other authentication methods.

Create a Kubernetes secret with the AWS credentials

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

Use the --from-file= argument to set the value to the contents of the aws-credentials.txt file.

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

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 aws-secret -n crossplane-system
 2Name:         aws-secret
 3Namespace:    crossplane-system
 4Labels:       <none>
 5Annotations:  <none>
 6
 7Type:  Opaque
 8
 9Data
10====
11creds:  114 bytes

Create a ProviderConfig

A ProviderConfig customizes the settings of the AWS Provider.

Apply the ProviderConfig with the this Kubernetes configuration file:

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

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

The spec.credentials.secretRef.name value is the name of the Kubernetes secret containing the AWS 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 guide creates an AWS S3 bucket with Crossplane.

The S3 bucket is a managed resource.

Tip
AWS S3 bucket names must be globally unique. To generate a unique name the example uses a random hash. Any unique name is acceptable.
 1bucket=$(echo "crossplane-bucket-"$(head -n 4096 /dev/urandom | openssl sha1 | tail -c 10))
 2cat <<EOF | kubectl apply -f -
 3apiVersion: s3.aws.upbound.io/v1beta1
 4kind: Bucket
 5metadata:
 6  name: $bucket
 7spec:
 8  forProvider:
 9    region: us-east-2
10  providerConfigRef:
11    name: default
12EOF

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

The metadata.name value is the name of the created S3 bucket in AWS.
This example uses the generated name crossplane-bucket-<hash> in the $bucket variable.

The spec.forProvider.region tells AWS which AWS region to use when deploying resources.

The region can be any AWS Regional endpoint code.

Use kubectl get buckets to verify Crossplane created the bucket.

Tip
Crossplane created the bucket when the values READY and SYNCED are True.
This may take up to 5 minutes.
1kubectl get buckets
2NAME                          READY   SYNCED   EXTERNAL-NAME                 AGE
3crossplane-bucket-45eed4ae0   True    True     crossplane-bucket-45eed4ae0   61s

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.

1kubectl delete bucket $bucket
2bucket.s3.aws.upbound.io "crossplane-bucket-45eed4ae0" deleted

Next steps