Provider
Os providers permitem que o Crossplane controle um recurso utilizando uma API externa. Novos providers sempre estão surgindo e podemos conferir na lista de providers da documentação oficial.
Os providers do Crossplane permitem:
- Criar recursos gerenciados nas plataformas de nuvem (como AWS, Azure, GCP) ou outros serviços
- Gerenciar o ciclo de vida desses recursos (criação, atualização, exclusão)
- Reconciliar o estado desejado com o estado atual dos recursos
Os exemplos disponíveis na documentação do Crossplane demonstram sua utilização para criação de recursos em cloud, mas já sabemos que o Crossplane é muito mais que isso.
Quem fornece os providers?
- Upbound
- Comunidade (contrib)
- Outras empresas
Uma lista dos providers mais utilizados:
- provider-family-aws (upbound)
- provider-aws (contrib) também é um provider da AWS, mas desenvolvido pela comunidade.
- provider-family-gcp (upbound) e provider-family-gcp-beta (upbound)
- provider-gcp (contrib) também é um provider o GCP, mas desenvolvido pela comunidade.
- provider-family-azure (upbound)
- provider-azure (contrib) também é um provider da Azure, mas desenvolvido pela comunidade.
- provider-azuread (upbound) no caso da sua empresa utilizar o Active Directory
- provider-kubernetes (upbound)
- provider-terraform (upbound) e provider-opentofu (upbound)
- provider-vault (upbound)
- provider-helm (upbound) e também temos o da comunidade.
- provider-argocd (contrib)
- provider-confluent (contrib) para trabalhar com o kafka
- provider-github (coopnorge)
- provider-gitlab (contrib)
- provider-jenkins (ankasoftco)
- provider-okta (contrib)
- provider-keycloack (contrib)
- provider-harbor (contrib)
- provider-grafana (grafana)
- provider-postgresql (tages)
- provider-http (contrib)
Vamos instalando providers de acordo com a nossa necessidade. Por isso acho interessante não instalar nada durante a instalação do helm chart do Crossplane.
Os providers são responsáveis por todos os aspectos da conexão com recursos não Kubernetes. Isso inclui autenticação, fazendo chamadas de API externas e fornecendo a lógica do Kubernetes Controller para quaisquer recursos externos.
Como um provider se comunica com uma API externa é necessário também criar uma configuração que conterá os dados necessários para a autenticação com essa API.
Veja quantos providers só para AWS.

Aqui o repositório da Upbound para o provider aws.
Este é o repositório do provedor AWS oficial mantido pela equipe Upbound. A Upbound é a empresa que lidera o desenvolvimento do Crossplane e de alguns provedores nativos, como este para a AWS.
Sendo o provedor oficial, ele provavelmente receberá mais suporte e atualizações frequentes.
Ele segue as diretrizes e as especificações oficiais do Crossplane.
O provider-aws community também faz o mesmo trabalho mas é mantido pela comunidade. Os provedores mantidos pela comunidade podem ser igualmente úteis e confiáveis, mas podem ter diferenças nas implementações e no suporte em comparação com o provedor oficial. Se existe oficial com uma empresa por trás use-o!
A vantagem dos providers mantidos pela comunidade é que eles podem fornecer recursos ou funcionalidades específicas que podem não estar presentes no provider oficial, mas também pode acontecer o contrário.
Cada um desses providers estendem a API do Kubernetes de um jeito diferente, por isso o objeto de um provider não funcionará no outro, apesar de conseguir fazer o que precisa com qualquer um dos dois.
#upbound
apiVersion: s3.aws.upbound.io/v1
kind: Bucket
...
#commnity
apiVersion: s3.aws.crossplane.io/v1
kind: Bucket
Vamos instalar o provider para o AWS S3.
# Instala APENAS o provider do S3
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-s3
spec:
package: xpkg.upbound.io/upbound/provider-aws-s3:v1
EOF
❯ k get provider
NAME INSTALLED HEALTHY PACKAGE AGE
provider-aws-s3 True True xpkg.upbound.io/upbound/provider-aws-s3:v1 19s
upbound-provider-family-aws True True xpkg.upbound.io/upbound/provider-family-aws:v1.20.1 14s
❯ k get pods -n crossplane-system
NAME READY STATUS RESTARTS AGE
crossplane-654d5644f4-mbr7j 1/1 Running 0 14h
crossplane-rbac-manager-59d8fcb968-kxrql 1/1 Running 0 14h
provider-aws-s3-e91dae831b35-5885cbd9b9-5fdhn 1/1 Running 0 19s
upbound-provider-family-aws-49b8fc96b73c-6b6b9d8bb5-t9c2q 1/1 Running 0 25s
#Com as instalação desse provider já temos os resources que podemos usar para declarar recursos
❯ k get customresourcedefinitions.apiextensions.k8s.io -n crossplane-system -o custom-columns=NAME:.metadata.name | grep s3.aws.upbound.io
bucketaccelerateconfigurations.s3.aws.upbound.io
bucketacls.s3.aws.upbound.io
bucketanalyticsconfigurations.s3.aws.upbound.io
bucketcorsconfigurations.s3.aws.upbound.io
bucketintelligenttieringconfigurations.s3.aws.upbound.io
bucketinventories.s3.aws.upbound.io
bucketlifecycleconfigurations.s3.aws.upbound.io
bucketloggings.s3.aws.upbound.io
bucketmetrics.s3.aws.upbound.io
bucketnotifications.s3.aws.upbound.io
bucketobjectlockconfigurations.s3.aws.upbound.io
bucketobjects.s3.aws.upbound.io
bucketownershipcontrols.s3.aws.upbound.io
bucketpolicies.s3.aws.upbound.io
bucketpublicaccessblocks.s3.aws.upbound.io
bucketreplicationconfigurations.s3.aws.upbound.io
bucketrequestpaymentconfigurations.s3.aws.upbound.io
buckets.s3.aws.upbound.io
bucketserversideencryptionconfigurations.s3.aws.upbound.io
bucketversionings.s3.aws.upbound.io
bucketwebsiteconfigurations.s3.aws.upbound.io
directorybuckets.s3.aws.upbound.io
objectcopies.s3.aws.upbound.io
objects.s3.aws.upbound.io
A instalação automática do provider-family-aws ocorre devido à dependência obrigatória definida nos providers de serviço individuais da Upbound (como o S3). Isso é um comportamento intencional da arquitetura de provider families.
O provider provider-aws-s3 declara em seu manifesto uma dependência hard-coded para o provider-family-aws. O Crossplane Package Manager resolve essa dependência automaticamente.
Propósito do Family Provider é:
- gerenciar configurações compartilhadas (como
ProviderConfig, autenticação AWS) - Fornecer recursos comuns a todos os serviços da família (ex: IAM Roles, políticas de segurança)
- Atuar como ponto único de atualização para múltiplos serviços.
Se instalarmos o provider-aws-ec2 várias dependências são obrigatórias entre os custons resources então ele também irá instalar tudo que será necessário.
❯ cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-ec2
spec:
package: xpkg.upbound.io/upbound/provider-aws-ec2:v1
EOF
provider.pkg.crossplane.io/provider-aws-ec2 created
# Não criou outro upbound-provider-family...
❯ k get provider
NAME INSTALLED HEALTHY PACKAGE AGE
provider-aws-ec2 True True xpkg.upbound.io/upbound/provider-aws-ec2:v1 107s
provider-aws-s3 True True xpkg.upbound.io/upbound/provider-aws-s3:v1 7m59s
upbound-provider-family-aws True True xpkg.upbound.io/upbound/provider-family-aws:v1.20.1 7m54s
# E agora temos esses CRDs para o ec2.
k get customresourcedefinitions.apiextensions.k8s.io -n crossplane-system -o custom-columns=NAME:.metadata.name | grep ec2.aws.upbound.io
amicopies.ec2.aws.upbound.io
amilaunchpermissions.ec2.aws.upbound.io
amis.ec2.aws.upbound.io
availabilityzonegroups.ec2.aws.upbound.io
capacityreservations.ec2.aws.upbound.io
carriergateways.ec2.aws.upbound.io
customergateways.ec2.aws.upbound.io
defaultnetworkacls.ec2.aws.upbound.io
defaultroutetables.ec2.aws.upbound.io
defaultsecuritygroups.ec2.aws.upbound.io
defaultsubnets.ec2.aws.upbound.io
defaultvpcdhcpoptions.ec2.aws.upbound.io
defaultvpcs.ec2.aws.upbound.io
ebsdefaultkmskeys.ec2.aws.upbound.io
ebsencryptionbydefaults.ec2.aws.upbound.io
ebssnapshotcopies.ec2.aws.upbound.io
ebssnapshotimports.ec2.aws.upbound.io
ebssnapshots.ec2.aws.upbound.io
ebsvolumes.ec2.aws.upbound.io
egressonlyinternetgateways.ec2.aws.upbound.io
eipassociations.ec2.aws.upbound.io
eips.ec2.aws.upbound.io
fleets.ec2.aws.upbound.io
flowlogs.ec2.aws.upbound.io
hosts.ec2.aws.upbound.io
instances.ec2.aws.upbound.io
instancestates.ec2.aws.upbound.io
internetgateways.ec2.aws.upbound.io
keypairs.ec2.aws.upbound.io
launchtemplates.ec2.aws.upbound.io
mainroutetableassociations.ec2.aws.upbound.io
managedprefixlistentries.ec2.aws.upbound.io
managedprefixlists.ec2.aws.upbound.io
natgateways.ec2.aws.upbound.io
networkaclrules.ec2.aws.upbound.io
networkacls.ec2.aws.upbound.io
networkinsightsanalyses.ec2.aws.upbound.io
networkinsightspaths.ec2.aws.upbound.io
networkinterfaceattachments.ec2.aws.upbound.io
networkinterfaces.ec2.aws.upbound.io
networkinterfacesgattachments.ec2.aws.upbound.io
placementgroups.ec2.aws.upbound.io
routes.ec2.aws.upbound.io
routetableassociations.ec2.aws.upbound.io
routetables.ec2.aws.upbound.io
securitygroupegressrules.ec2.aws.upbound.io
securitygroupingressrules.ec2.aws.upbound.io
securitygrouprules.ec2.aws.upbound.io
securitygroups.ec2.aws.upbound.io
serialconsoleaccesses.ec2.aws.upbound.io
snapshotcreatevolumepermissions.ec2.aws.upbound.io
spotdatafeedsubscriptions.ec2.aws.upbound.io
spotfleetrequests.ec2.aws.upbound.io
spotinstancerequests.ec2.aws.upbound.io
subnetcidrreservations.ec2.aws.upbound.io
subnets.ec2.aws.upbound.io
tags.ec2.aws.upbound.io
trafficmirrorfilterrules.ec2.aws.upbound.io
trafficmirrorfilters.ec2.aws.upbound.io
transitgatewayconnectpeers.ec2.aws.upbound.io
transitgatewayconnects.ec2.aws.upbound.io
transitgatewaymulticastdomainassociations.ec2.aws.upbound.io
transitgatewaymulticastdomains.ec2.aws.upbound.io
transitgatewaymulticastgroupmembers.ec2.aws.upbound.io
transitgatewaymulticastgroupsources.ec2.aws.upbound.io
transitgatewaypeeringattachmentaccepters.ec2.aws.upbound.io
transitgatewaypeeringattachments.ec2.aws.upbound.io
transitgatewaypolicytables.ec2.aws.upbound.io
transitgatewayprefixlistreferences.ec2.aws.upbound.io
transitgatewayroutes.ec2.aws.upbound.io
transitgatewayroutetableassociations.ec2.aws.upbound.io
transitgatewayroutetablepropagations.ec2.aws.upbound.io
transitgatewayroutetables.ec2.aws.upbound.io
transitgateways.ec2.aws.upbound.io
transitgatewayvpcattachmentaccepters.ec2.aws.upbound.io
transitgatewayvpcattachments.ec2.aws.upbound.io
volumeattachments.ec2.aws.upbound.io
vpcdhcpoptions.ec2.aws.upbound.io
vpcdhcpoptionsassociations.ec2.aws.upbound.io
vpcendpointconnectionnotifications.ec2.aws.upbound.io
vpcendpointroutetableassociations.ec2.aws.upbound.io
vpcendpoints.ec2.aws.upbound.io
vpcendpointsecuritygroupassociations.ec2.aws.upbound.io
vpcendpointserviceallowedprincipals.ec2.aws.upbound.io
vpcendpointservices.ec2.aws.upbound.io
vpcendpointsubnetassociations.ec2.aws.upbound.io
vpcipampoolcidrallocations.ec2.aws.upbound.io
vpcipampoolcidrs.ec2.aws.upbound.io
vpcipampools.ec2.aws.upbound.io
vpcipams.ec2.aws.upbound.io
vpcipamscopes.ec2.aws.upbound.io
vpcipv4cidrblockassociations.ec2.aws.upbound.io
vpcpeeringconnectionaccepters.ec2.aws.upbound.io
vpcpeeringconnectionoptions.ec2.aws.upbound.io
vpcpeeringconnections.ec2.aws.upbound.io
vpcs.ec2.aws.upbound.io
vpnconnectionroutes.ec2.aws.upbound.io
vpnconnections.ec2.aws.upbound.io
vpngatewayattachments.ec2.aws.upbound.io
vpngatewayroutepropagations.ec2.aws.upbound.io
vpngateways.ec2.aws.upbound.io
Durante a criação de um recurso na aws, por exemplo um s3, o manifesto irá pedir qual o provider irá usar e a configuração deste, ou seja, a autenticação que ele irá usar. Se fossemos fazer um paralelo ao terraform, é ncessário que que as variáveis de ambiente estejam carregadas ou apontadas. Nesse caso iremos apontar recurso chamado ProviderConfig.
Primeiramente vamos criar uma secret no kubernetes igual o conteúdo abaixo, mas com valores válidos. Crie um IAM na AWS que será usado pelo provider, gere a secret, adicione a permissão de AdministratorAccess (somente para o estudo, não faça isso em produção).
Crie um arquivo aws-creds.txt com o conteúdo abaixo e vamos aplicar no namespace do crossplane
echo "[default]
aws_access_key_id = XXXXXXXXXXXXXXX
aws_secret_access_key = YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY" > aws-creds.txt
kubectl create secret \
generic aws-secret \
-n crossplane-system \
--from-file=creds=./aws-creds.txt
Agora que temos a secret de nome aws-secret vamos fazer o providerconfig.
cat <<EOF | kubectl apply -f -
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-secret
key: creds
EOF
Vários providers diferentes poderão utilizar essa configuração, desde que seja apontada. Pense na configuração como um método de autenticação. É possível autenticar utilizando outros métodos também, como Roles, WebIdentity, OIDC etc, veja em https://docs.upbound.io/providers/provider-aws/authentication/.
Já temos um provider-aws e temos um config, agora vamos criar algum recurso para ver se está funcionando.
Vale lembrar que este é um exemplo na AWS, mas outros providers de outras clouds podem ser usados como Azure, GCP e até mesmo o próprio Kubernetes. A tendência é que os providers crescam para tudo que existe, assim como o Terraform e Ansible. O que vale no estudo é entender a ferramenta e os conceitos.
Fluxo
- Quando um usuário aplica um manifesto relacionado ao Crossplane (como um recurso gerenciado ou uma composition), essa requisição primeiro vai para o kube-api-server que valida o recurso contra o CRD apropriado e o armazena no etcd.
- Depois, o kube-api-server notifica os controllers registrados (incluindo os controllers do Crossplane) sobre as mudanças relevantes.
- Os controllers do Crossplane (tanto o core quanto os providers) continuamente consultam o kube-api-server (usando LIST/WATCH) para obter informações sobre recursos que estão gerenciando. Quando o Crossplane precisa atualizar o status de um recurso ou criar recursos dependentes, ele faz chamadas para o kube-api-server. O Crossplane também se comunica com o kube-api-server para registrar CRDs, criar eventos e atualizar o status dos recursos.
Este modelo segue o padrão padrão de controllers do Kubernetes, onde os controllers são clients do kube-api-server e interagem com ele de forma bidirecional, obtendo informações e enviando atualizações conforme necessário para reconciliar o estado desejado.

Boa Prática
O provider é a ponte entre o Kubernetes e um recurso externo. Não é necessário instalar duas vezes o mesmo provider, apenas passamos para um provider config diferente é o necessário. Como um provider-config-dev e um provider-config-prod.
Instalar o mesmo provider Upbound S3 com a mesma tag (versão) duas vezes, mesmo com nomes diferentes, não traz nenhuma vantagem real e pode causar problemas.
#Não Faça Isso
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-ec2-a
spec:
package: xpkg.upbound.io/upbound/provider-aws-ec2:v1
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-ec2-b
spec:
package: xpkg.upbound.io/upbound/provider-aws-ec2:v1
Quando você instala o mesmo provider com a mesma versão, ele tentará registrar os mesmos Custom Resource Definitions (CRDs), o que resultará em:
- Conflito de recursos: Ambas as instâncias tentarão registrar os mesmos CRDs, resultando em conflitos no API Server
- Controladores duplicados: Dois controladores tentando reconciliar os mesmos recursos, levando a comportamentos imprevisíveis
- Desperdício de recursos: Consumo desnecessário de CPU e memória para executar controladores redundantes
- Possível "race condition": Os controladores podem competir entre si durante a reconciliação dos recursos
A maioria desses problemas surge porque os CRDs são recursos globais no Kubernetes, independentemente do namespace ou do nome da instância do provider. O padrão correto para gerenciar múltiplas configurações é:
- Instalar o provider apenas uma vez
- Criar múltiplos ProviderConfigs que referenciam diferentes credenciais ou configurações
- Especificar qual ProviderConfig deve ser usado com cada recurso gerenciado através da referência providerConfigRef
Isso permite gerenciar recursos em múltiplos ambientes ou contas sem a sobrecarga e os problemas causados por instâncias duplicadas do mesmo provider.
Importante Entender
Os providers criam e gerenciam Managed Resources que representam recursos nas plataformas de destino.
Uma Composition é um conjunto ou template de recursos gerenciados que são agrupados para formar uma abstração de nível mais alto. Se não entendeu, mais para frente irá entender. Se fossemos comparar seria como um módulo no terraform, mas não é exatamente assim.
O Crossplane Core gerencia as Compositions e Composite Resources (XRs), não os providers. Os providers apenas "enxergam" e interagem com os recursos gerenciados individuais, não tendo conhecimento direto das abstrações de nível superior como Compositions.
Quando você define uma Composition, o Crossplane Core é responsável por decompô-la nos recursos gerenciados correspondentes, e então os providers cuidam desses recursos individuais. Essa separação de responsabilidades é um aspecto fundamental da arquitetura do Crossplane.
Continue em Managed Resources para entender melhor sobre isso.