mirror of https://github.com/crossplane/docs.git
docs snapshot for crossplane version `master`
This commit is contained in:
parent
34f3be89db
commit
037c397d01
|
@ -3,769 +3,141 @@ title: Services Guide
|
|||
toc: true
|
||||
weight: 410
|
||||
---
|
||||
# Services Guide
|
||||
Welcome to the Crossplane Services Guide!
|
||||
|
||||
Crossplane Services enables managed service provisioning from `kubectl`
|
||||
including for databases, caches, buckets and more, including secure usage with
|
||||
Kubernetes `Secrets`.
|
||||
|
||||
Crossplane Service follows established Kubernetes patterns like Persistent
|
||||
Volume Claims (PVC) to support dynamic provisioning of managed services and a
|
||||
clean separation of concerns between app teams and cluster administrators.
|
||||
|
||||
In this document, we will:
|
||||
* Manually provision a new managed Kubernetes cluster and install Crossplane.
|
||||
* Learn how to provision managed services from `kubectl`.
|
||||
* Introduce cloud-specific guides with step-by-step instructions:
|
||||
* [GCP Services Guide][gcp-services-guide]
|
||||
* [AWS Services Guide][aws-services-guide]
|
||||
* [Azure Services Guide][azure-services-guide]
|
||||
* Explore how workload portability is achieved and how to configure shared clusters for multiple teams using namespaces.
|
||||
* Provide next steps for learning more about Crossplane!
|
||||
|
||||
We will **not**:
|
||||
* Learn first principles (see the concepts document for that level of detail)
|
||||
* Deploy Crossplane as a dedicated control plane, it will run embedded in a single Kuberetes cluster.
|
||||
* Use advanced workload scheduling or multi-cluster management.
|
||||
|
||||
If you have any questions, please drop us a note on [Crossplane Slack][join-crossplane-slack] or [contact us][contact-us]!
|
||||
|
||||
Let's go!
|
||||
|
||||
# Concepts
|
||||
There are a bunch of things you might want to know to fully understand what's
|
||||
happening in this document. This guide won't cover them, but there are other
|
||||
ones that do. Here are some links!
|
||||
* [Crossplane concepts][crossplane-concepts]
|
||||
* [Kubernetes concepts][kubernetes-concepts]
|
||||
|
||||
# Before you get started
|
||||
This guide assumes you are using a *nix-like environment. It also assumes you have a basic working familiarity with the following:
|
||||
* The terminal environment
|
||||
* Setting up cloud provider accounts for the cloud provider you want to use
|
||||
|
||||
You will need:
|
||||
* A *nix-like environment
|
||||
* A cloud provider account, for the cloud provider of your choice (out of the supported providers)
|
||||
|
||||
# Provisioning managed services from kubectl
|
||||
Crossplane can be added to existing Kubernetes clusters and cleanly layers on
|
||||
top of clusters provisioned by GKE, EKS, AKS, and more. Cluster administrators
|
||||
install Crossplane, set cloud credentials, and offer classes of service for
|
||||
self-service provisioning using `kubectl`. Application teams can provision
|
||||
managed services with `Resource Claims` without having to worry about
|
||||
cloud-specific infrastructure details or manage credentials.
|
||||
|
||||
|
||||
# Overview
|
||||
|
||||
This guide shows how to provision a managed `MySQLInstance` and securely consume it from a Wordpress `Deployment`.
|
||||
|
||||
To provision a portable `MySQLInstance` for the Wordpress app we'd like to enable app teams to:
|
||||
|
||||
```sh
|
||||
kubectl create -f mysql-claim.yaml
|
||||
```
|
||||
with mysql-claim.yaml:
|
||||
```yaml
|
||||
apiVersion: database.crossplane.io/v1alpha2
|
||||
kind: MySQLInstance
|
||||
metadata:
|
||||
name: mysql-claim
|
||||
namespace: app-project1-dev
|
||||
spec:
|
||||
classRef:
|
||||
name: mysql-standard
|
||||
writeConnectionSecretToRef:
|
||||
name: mysql-claim-secret
|
||||
engineVersion: "5.6"
|
||||
```
|
||||
|
||||
Note there are no references in this `Resource Claim` to anything
|
||||
cloud-specific. As such any environment can be configured to satisfy this claim,
|
||||
using different configurations for different environments (dev, staging, prod),
|
||||
or different managed service providers such as CloudSQL, RDS, or Azure DB.
|
||||
|
||||
This portable experience is typically accomplished by:
|
||||
1. Defining **cloud-specific** `Resource Classes` in an infrastructure namespace.
|
||||
1. Offering **portable** `Resource Classes` in an app project namespace for provisioning with `kubectl`.
|
||||
1. Creating **portable** `Resource Claims` using `kubectl` to provision a managed service.
|
||||
|
||||
This enables the following usage: app -> portable claim -> portable class -> cloud-specific class -> provider.
|
||||
|
||||
## Steps
|
||||
### A) One-time cluster setup
|
||||
1. Manually provision a managed Kubernetes target cluster: GKE, EKA, AKS.
|
||||
1. Install Crossplane into the target cluster.
|
||||
1. Install a cloud provider Stack: GCP, AWS, Azure.
|
||||
1. Connect a cloud provider account to a shared infrastructure namespace.
|
||||
1. Create cloud-specific classes of service with best-practice configurations.
|
||||
|
||||
### B) Onboard app projects in a shared cluster
|
||||
1. Create an app project namespace `app-project1-dev`.
|
||||
1. Add portable classes of service for managed service provisioning using `kubectl`.
|
||||
1. Set default classes of service.
|
||||
|
||||
### C) Deploy Wordpress with a managed MySQLInstance
|
||||
1. Provision a `MySQLInstance` using `kubectl`.
|
||||
1. Securely connect to the database using a generated Kubernetes `Secret`.
|
||||
1. Verify Wordpress is working correctly.
|
||||
1. Delete all resources.
|
||||
1. Verify everything was cleanly deleted.
|
||||
|
||||
## Resulting Kubernetes objects
|
||||
|
||||
In an AWS envionment offering multiple classes of service, the following Kubernetes objects would result:
|
||||
```text
|
||||
namespaces
|
||||
└── aws-infra-dev
|
||||
└── provider # AWS provider configuration
|
||||
└── provider-creds # AWS provider account credentials
|
||||
└── rds-mysql-standard # RDS-specific class, non-portable config
|
||||
└── rds-mysql-replicated # RDS-specific class, non-portable config
|
||||
└── rds-postgres-standard # RDS-specific class, non-portable config
|
||||
└── rds-postgres-replicated # RDS-specific class, non-portable config
|
||||
└── app-project1-dev
|
||||
└── mysql-standard # portable MySQL class of service
|
||||
└── mysql-replicated # portable MySQL class of service
|
||||
└── postgres-standard # portable PostgreSQL class of service
|
||||
└── postgres-ha # portable PostgreSQL class of service
|
||||
└── mysql-claim # portable MySQL claim for mysql-standard class of service
|
||||
└── mysql-claim-secret # generated secret to access database
|
||||
└── wordpress-deployment # standard Kubernetes deployment
|
||||
└── wordpress-service # standard Kubernetes service
|
||||
```
|
||||
|
||||
# Cloud-specific Guides
|
||||
Use these step-by-step guides to provision a managed `MySQLInstance` and
|
||||
securely consume it from a Wordpress `Deployment`:
|
||||
* [GCP Services Guide][gcp-services-guide]
|
||||
* [AWS Services Guide][aws-services-guide]
|
||||
* [Azure Services Guide][azure-services-guide]
|
||||
|
||||
# Reviewing what happened across providers
|
||||
This section reviews the general flow of the cloud-specific guides, how workload
|
||||
portability is achieved using resource claims and classes, and techniques to
|
||||
organize a shared cluster using namespaces.
|
||||
|
||||
## A) One-time cluster setup
|
||||
### Managed Kubernetes Cluster
|
||||
Provision a new managed Kubernetes cluster, following the cloud-specific guides
|
||||
for [GCP][gcp-services-guide], [AWS][aws-services-guide], or [Azure][azure-services-guide]
|
||||
|
||||
### Install Crossplane
|
||||
1. [Install Crossplane from the alpha channel][install-crossplane-alpha].
|
||||
1. [Install a cloud provider Stack][install-provider-stacks]
|
||||
from the [Stacks registry][stack-registry] from one of:
|
||||
[stack-gcp][stack-gcp], [stack-aws][stack-aws], or [stack-azure][stack-azure].
|
||||
|
||||
### Connect Crossplane to a Cloud Provider
|
||||
Crossplane supports connecting multiple cloud provider accounts from a single
|
||||
cluster, so different environments (dev, staging, prod) can use separate
|
||||
accounts, projects, and/or credentials.
|
||||
|
||||
While the guides use a single infrastructure namespace (gcp-infra-dev,
|
||||
aws-infra-dev, or azure-infra-dev), you can create as many as you like using
|
||||
whatever naming works best for your organization.
|
||||
|
||||
To connect an infrastructure namespace to a cloud provider:
|
||||
1. Create an infrastructure namespace in the Kubernetes cluster.
|
||||
1. [Obtain Cloud Provider Credentials][cloud-provider-creds]
|
||||
and export to `BASE64ENCODED_PROVIDER_CREDS`.
|
||||
1. Add a Crossplane `Provider`.
|
||||
|
||||
For example, based on your cloud provider, add a `Provider` to your infrastructure namespace:
|
||||
|
||||
gcp-provider.yaml
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
credentials.json: $BASE64ENCODED_PROVIDER_CREDS
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: provider-creds
|
||||
namespace: gcp-infra-dev
|
||||
type: Opaque
|
||||
---
|
||||
## Crossplane GCP Provider
|
||||
apiVersion: gcp.crossplane.io/v1alpha2
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: provider
|
||||
namespace: gcp-infra-dev
|
||||
spec:
|
||||
credentialsSecretRef:
|
||||
name: provider-creds
|
||||
key: credentials.json
|
||||
projectID: $PROJECT_ID
|
||||
```
|
||||
|
||||
aws-provider.yaml
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: provider-creds
|
||||
namespace: aws-infra-dev
|
||||
type: Opaque
|
||||
data:
|
||||
credentials: $BASE64ENCODED_PROVIDER_CREDS
|
||||
---
|
||||
## Crossplane AWS Provider
|
||||
apiVersion: aws.crossplane.io/v1alpha2
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: provider
|
||||
namespace: aws-infra-dev
|
||||
spec:
|
||||
credentialsSecretRef:
|
||||
key: credentials
|
||||
name: provider-creds
|
||||
region: $REGION
|
||||
```
|
||||
|
||||
azure-provider.yaml
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: provider-creds
|
||||
namespace: azure-infra-dev
|
||||
type: Opaque
|
||||
data:
|
||||
credentials: $BASE64ENCODED_PROVIDER_CREDS
|
||||
---
|
||||
## Crossplane Azure Provider
|
||||
apiVersion: azure.crossplane.io/v1alpha2
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: provider
|
||||
namespace: azure-infra-dev
|
||||
spec:
|
||||
credentialsSecretRef:
|
||||
name: provider-creds
|
||||
key: credentials
|
||||
```
|
||||
|
||||
The `Provider` defined in the infrastructure namespace will be referenced by cloud-specific `Resource Classes` in the next step.
|
||||
|
||||
### Create classes of service with best-practice configurations
|
||||
**Cloud-specific** `Resource Classes` capture reusable, best-practice configurations for a specific managed service.
|
||||
|
||||
For example, Wordpress requires a MySQL database which can be satisfied by CloudSQL, RDS, or Azure DB.
|
||||
|
||||
Based on your cloud provider, add a **cloud-specific** `Resource Class` to your infrastructure namespace:
|
||||
|
||||
rds-mysql-standard.yaml
|
||||
```yaml
|
||||
---
|
||||
apiVersion: database.aws.crossplane.io/v1beta1
|
||||
kind: RDSInstanceClass
|
||||
metadata:
|
||||
name: rds-mysql-standard
|
||||
specTemplate:
|
||||
forProvider:
|
||||
dbInstanceClass: db.t2.small
|
||||
masterUsername: masteruser
|
||||
# vpcSecurityGroupIds:
|
||||
# - sg-ab1cdefg
|
||||
# - sg-05adsfkaj1ksdjak
|
||||
allocatedStorage: 20
|
||||
engine: mysql
|
||||
providerRef:
|
||||
name: demo
|
||||
namespace: aws-infra-dev
|
||||
reclaimPolicy: Delete
|
||||
```
|
||||
|
||||
cloudsql--mysql-standard.yaml
|
||||
```yaml
|
||||
---
|
||||
apiVersion: database.gcp.crossplane.io/v1beta1
|
||||
kind: CloudSQLInstanceClass
|
||||
metadata:
|
||||
name: cloudsql-mysql-standard
|
||||
namespace: gcp-infra-dev
|
||||
specTemplate:
|
||||
forProvider:
|
||||
databaseVersion: MYSQL_5_6
|
||||
region: us-central1
|
||||
settings:
|
||||
tier: db-n1-standard-1
|
||||
dataDiskType: PD_SSD
|
||||
dataDiskSizeGb: 10
|
||||
# Note from GCP Docs: Your Cloud SQL instances are not created in your VPC network.
|
||||
# They are created in the service producer network (a VPC network internal to Google) that is then connected (peered) to your VPC network.
|
||||
ipConfiguration:
|
||||
privateNetwork: projects/$PROJECT_ID/global/networks/example-network
|
||||
providerRef:
|
||||
name: demo
|
||||
namespace: gcp-infra-dev
|
||||
reclaimPolicy: Delete
|
||||
```
|
||||
|
||||
azuredb-mysql-standard.yaml
|
||||
```yaml
|
||||
---
|
||||
apiVersion: database.azure.crossplane.io/v1alpha2
|
||||
kind: SQLServerClass
|
||||
metadata:
|
||||
name: azuredb-mysql-standard
|
||||
namespace: azure-infra-dev
|
||||
specTemplate:
|
||||
adminLoginName: myadmin
|
||||
resourceGroupName: group-westus-1
|
||||
location: West US
|
||||
sslEnforced: false
|
||||
version: "5.6"
|
||||
pricingTier:
|
||||
tier: Basic
|
||||
vcores: 1
|
||||
family: Gen5
|
||||
storageProfile:
|
||||
storageGB: 25
|
||||
backupRetentionDays: 7
|
||||
geoRedundantBackup: false
|
||||
providerRef:
|
||||
name: demo
|
||||
namespace: azure-infra-dev
|
||||
reclaimPolicy: Delete
|
||||
```
|
||||
|
||||
Creating multiple classes of service in an AWS environment results in these Kubernetes objects:
|
||||
|
||||
```text
|
||||
namespaces
|
||||
└── aws-infra-dev
|
||||
└── provider # AWS provider configuration
|
||||
└── provider-creds # AWS provider account credentials
|
||||
└── rds-mysql-standard # RDS-specific class, non-portable config
|
||||
└── rds-mysql-replicated # RDS-specific class, non-portable config
|
||||
└── rds-postgres-standard # RDS-specific class, non-portable config
|
||||
└── rds-postgres-replicated # RDS-specific class, non-portable config
|
||||
```
|
||||
|
||||
However, cloud-specific `Resource Classes` are not portable across providers so
|
||||
we need something to represent a portable class of service for use in a portable
|
||||
`Resource Claim`.
|
||||
|
||||
The next section covers how to offer a cloud-specific `Resource Class` as a
|
||||
portable class of service, so an app team can provision managed services using
|
||||
`kubectl` in a portable way.
|
||||
|
||||
## B) Onboard app projects in a shared cluster
|
||||
### Offer Portable Classes of Service in App Project Namespaces
|
||||
[Portable Resource Classes][concept-portable-class]
|
||||
define a named class of service that can be used by portable `Resource Claims`
|
||||
in the same namespace. When used in a project namespace, this enables the
|
||||
project to provision portable managed services using `kubectl`.
|
||||
|
||||
```sh
|
||||
kubectl create -f mysql-claim.yaml
|
||||
```
|
||||
with mysql-claim.yaml:
|
||||
```yaml
|
||||
apiVersion: database.crossplane.io/v1alpha2
|
||||
kind: MySQLInstance
|
||||
metadata:
|
||||
name: mysql-claim
|
||||
namespace: app-project1-dev
|
||||
spec:
|
||||
classRef:
|
||||
name: mysql-standard
|
||||
writeConnectionSecretToRef:
|
||||
name: mysql-claim-secret
|
||||
engineVersion: "5.6"
|
||||
```
|
||||
Note the portable `Resource Claim` below uses a `spec.classRef.name` of
|
||||
`mysql-standard` to reference a portable `Resource Class` in the same namespace.
|
||||
It has no knowledge of which cloud provider will satisfy this claim or how a
|
||||
suitable cloud-specific `Resource Class` will be selected.
|
||||
|
||||
Adding portable classes of service to the `app-project1-dev` namespace, results in these Kubernetes objects:
|
||||
```text
|
||||
└── app-project1-dev
|
||||
└── mysql-standard # portable MySQL class of service
|
||||
└── mysql-replicated # portable MySQL class of service
|
||||
└── postgres-standard # portable PostgreSQL class of service
|
||||
└── postgres-ha # portable PostgreSQL class of service
|
||||
```
|
||||
|
||||
These portable `Resource Classes` could be defined as follows for an AWS dev
|
||||
environment, but alternate configurations could be provided for different
|
||||
environments (staging, prod) or different cloud provider like GCP or Azure, to
|
||||
satisfy the named classes of service:
|
||||
|
||||
mysql-standard.yaml
|
||||
```yaml
|
||||
apiVersion: database.crossplane.io/v1alpha1
|
||||
kind: MySQLInstanceClass
|
||||
metadata:
|
||||
name: mysql-standard
|
||||
namespace: app-project1-dev
|
||||
labels:
|
||||
default: true
|
||||
classRef:
|
||||
kind: RDSInstanceClass
|
||||
apiVersion: database.aws.crossplane.io/v1beta1
|
||||
name: rds-mysql-standard
|
||||
```
|
||||
|
||||
mysql-replicated.yaml
|
||||
```yaml
|
||||
apiVersion: database.crossplane.io/v1alpha1
|
||||
kind: MySQLInstanceClass
|
||||
metadata:
|
||||
name: mysql-replicated
|
||||
namespace: app-project1-dev
|
||||
classRef:
|
||||
kind: RDSInstanceClass
|
||||
apiVersion: database.aws.crossplane.io/v1beta1
|
||||
name: rds-mysql-replicated
|
||||
```
|
||||
|
||||
postgres-standard.yaml
|
||||
```yaml
|
||||
apiVersion: database.crossplane.io/v1alpha1
|
||||
kind: PostgreSQLInstanceClass
|
||||
metadata:
|
||||
name: postgres-standard
|
||||
namespace: app-project1-dev
|
||||
labels:
|
||||
default: true
|
||||
classRef:
|
||||
kind: RDSInstanceClass
|
||||
apiVersion: database.aws.crossplane.io/v1beta1
|
||||
name: rds-postgres-standard
|
||||
```
|
||||
|
||||
postgres-ha.yaml
|
||||
```yaml
|
||||
apiVersion: database.crossplane.io/v1alpha1
|
||||
kind: PostgreSQLInstanceClass
|
||||
metadata:
|
||||
name: postgres-ha
|
||||
namespace: app-project1-dev
|
||||
classRef:
|
||||
kind: RDSInstanceClass
|
||||
apiVersion: database.aws.crossplane.io/v1beta1
|
||||
name: rds-postgres-ha
|
||||
```
|
||||
|
||||
Note that some portable `Resource Classes` are marked with
|
||||
[`label.default: true`][concept-default-class]
|
||||
to indicate it's the default class of service for a given claim kind in the
|
||||
`app-project1-dev` namespace.
|
||||
|
||||
`Resource Claims` can rely on the default class of service in the same namespace for a given claim kind by omitting `spec.classRef`.
|
||||
|
||||
Claim-based provisioning and use of default `Resource Classes` will be covered in the next section.
|
||||
|
||||
With multiple classes of service available in the `app-project1-dev` namespace, these Kuberntes objects would be present:
|
||||
```text
|
||||
namespaces
|
||||
└── aws-infra-dev
|
||||
└── provider # AWS provider configuration
|
||||
└── provider-creds # AWS provider account credentials
|
||||
└── rds-mysql-standard # RDS-specific class, non-portable config
|
||||
└── rds-mysql-replicated # RDS-specific class, non-portable config
|
||||
└── rds-postgres-standard # RDS-specific class, non-portable config
|
||||
└── rds-postgres-replicated # RDS-specific class, non-portable config
|
||||
└── app-project1-dev
|
||||
└── mysql-standard # portable MySQL class of service
|
||||
└── mysql-replicated # portable MySQL class of service
|
||||
└── postgres-standard # portable PostgreSQL class of service
|
||||
└── postgres-ha # portable PostgreSQL class of service
|
||||
```
|
||||
|
||||
|
||||
## C) Deploy Wordpress with a managed MySQLInstance
|
||||
### Provision a MySQLInstance from kubectl
|
||||
Managed services can be provisioned in a portable way using `kubectl`, with the
|
||||
`app-project1-dev` namespace populated with available classes of service.
|
||||
|
||||
```sh
|
||||
kubectl create -f mysql-claim.yaml
|
||||
```
|
||||
with mysql-claim.yaml:
|
||||
```yaml
|
||||
apiVersion: database.crossplane.io/v1alpha2
|
||||
kind: MySQLInstance
|
||||
metadata:
|
||||
name: mysql-claim
|
||||
namespace: app-project1-dev
|
||||
spec:
|
||||
classRef:
|
||||
name: mysql-standard
|
||||
writeConnectionSecretToRef:
|
||||
name: mysql-claim-secret
|
||||
engineVersion: "5.6"
|
||||
```
|
||||
|
||||
The `spec.classRef` can be omitted from a `Resource Claim` to rely on the
|
||||
default class of service in the same namespace.
|
||||
```yaml
|
||||
apiVersion: database.crossplane.io/v1alpha2
|
||||
kind: MySQLInstance
|
||||
metadata:
|
||||
name: mysql-claim
|
||||
namespace: app-project1-dev
|
||||
spec:
|
||||
writeConnectionSecretToRef:
|
||||
name: mysql-claim-secret
|
||||
engineVersion: "5.6"
|
||||
```
|
||||
|
||||
The `Binding Status` of a `Resource Claim` will indicate `Bound` when the
|
||||
underlying managed service has been provisioned and the connection secret is
|
||||
available for use.
|
||||
|
||||
```sh
|
||||
kubectl get mysqlinstances -n app-project1-dev
|
||||
```
|
||||
Output:
|
||||
```sh
|
||||
NAME STATUS CLASS VERSION AGE
|
||||
mysql-claim Bound mysql-standard 5.6 11
|
||||
```
|
||||
|
||||
### Securely consume the MySQLInstance from a Wordpress Deployment
|
||||
```sh
|
||||
kubectl create -f wordpress-app.yaml
|
||||
```
|
||||
with wordpress-app.yaml:
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: wordpress-deployment
|
||||
namespace: app-project1-dev
|
||||
labels:
|
||||
app: wordpress
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: wordpress
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: wordpress
|
||||
spec:
|
||||
containers:
|
||||
- name: wordpress
|
||||
image: wordpress:4.6.1-apache
|
||||
env:
|
||||
- name: WORDPRESS_DB_HOST
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mysql-claim-secret
|
||||
key: endpoint
|
||||
- name: WORDPRESS_DB_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mysql-claim-secret
|
||||
key: username
|
||||
- name: WORDPRESS_DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mysql-claim-secret
|
||||
key: password
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: wordpress
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: wordpress-service
|
||||
namespace: app-project1-dev
|
||||
labels:
|
||||
app: wordpress
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
selector:
|
||||
app: wordpress
|
||||
type: LoadBalancer
|
||||
```
|
||||
|
||||
### Cleanly Delete Wordpress and the MySQLInstance
|
||||
```sh
|
||||
kubectl delete -f wordpress-app.yaml
|
||||
kubectl delete -f mysql-claim.yaml
|
||||
```
|
||||
|
||||
# Summary
|
||||
In this example we saw how to:
|
||||
* Add Crossplane to a managed Kubernetes cluster.
|
||||
* Install a cloud provider Stack for GCP, AWS, or Azure to add managed service provisoining.
|
||||
* Define cloud-specific classes of service in an infrastructure namespace.
|
||||
* Offer portable classes of service in an app project namespace.
|
||||
* Provision a managed MySQLInstance using kubectl.
|
||||
* Securely connect to the MySQLInstance from a Wordpress Deployment.
|
||||
* Cleanly delete all resources.
|
||||
|
||||
After one-time setup was done and app projects were onboarded into the shared
|
||||
cluster, managed services could be provisioned using `kubectl` with portable
|
||||
claims in a project namespace.
|
||||
|
||||
Resources were configured in infrastructure and app project namespaces:
|
||||
```text
|
||||
namespaces
|
||||
└── aws-infra-dev
|
||||
└── provider # AWS provider configuration
|
||||
└── provider-creds # AWS provider account credentials
|
||||
└── rds-mysql-standard # RDS-specific class, non-portable config
|
||||
└── rds-mysql-replicated # RDS-specific class, non-portable config
|
||||
└── rds-postgres-standard # RDS-specific class, non-portable config
|
||||
└── rds-postgres-replicated # RDS-specific class, non-portable config
|
||||
└── app-project1-dev
|
||||
└── mysql-standard # portable MySQL class of service
|
||||
└── mysql-replicated # portable MySQL class of service
|
||||
└── postgres-standard # portable PostgreSQL class of service
|
||||
└── postgres-ha # portable PostgreSQL class of service
|
||||
└── mysql-claim # portable MySQL claim for mysql-standard class of service
|
||||
└── mysql-claim-secret # generated secret to access database
|
||||
└── wordpress-deployment # standard Kubernetes deployment
|
||||
└── wordpress-service # standard Kubernetes service
|
||||
```
|
||||
|
||||
Crossplane Services brings managed service provisioning to `kubectl` and enables
|
||||
cluster admins to offer multiple classes of service to accelerate app delivery
|
||||
while ensuring best-practices and security in your cloud of choice.
|
||||
|
||||
Claim-based provisioning supports portability into different cloud environments
|
||||
since the app only depends on named or default classes of service that can
|
||||
provide wire-compatible managed services (MySQL, PostgreSQL, Redis, and more)
|
||||
independent of how a given cloud provider satisfies the claim. Claim-based
|
||||
provisioning also supports differentiated cloud services, so all managed
|
||||
services can work with Crossplane.
|
||||
|
||||
If you have any questions, please drop us a note on [Crossplane Slack][join-crossplane-slack] or [contact us][contact-us]!
|
||||
|
||||
# Learn More
|
||||
This guide covered deploying Crossplane into a single managed Kubernetes
|
||||
cluster, and using cloud provider Stacks to provision a managed MySQL instance for
|
||||
use with a Wordpress Deployment. However, this involved configuring multiple
|
||||
Kubernetes objects to get a fully functioning Wordpress instance securely
|
||||
deployed.
|
||||
|
||||
Stacks can also be used to simplify app management and automate operations. Our
|
||||
next guide shows how an App Stack can automate most of the steps covered in this
|
||||
guide and be run from a dedicated control plane that: (a) dynamically provisions
|
||||
the target cluster, (b) provisions the managed services, and (c) deploys the app
|
||||
itself with secure connectivity.
|
||||
|
||||
App Stacks simplify operations for an app by moving the steps covered in this guide into a Kubernetes controller that owns an app CRD (custom resource definition) with a handful of settings required to deploy a new app instance, complete with the managed services it depends on.
|
||||
|
||||
## Next Steps
|
||||
* [Crossplane Stacks Guide][stack-user-guide] to deploy the same Wordpress instance with a
|
||||
single yaml file, using the [portable Wordpress App Stack][stack-wordpress].
|
||||
* [Extend a Stack][stack-developer-guide] to add more cloud services to:
|
||||
[stack-gcp][stack-gcp], [stack-aws][stack-aws], or [stack-azure][stack-azure].
|
||||
* [Build a new Stack][stack-developer-guide] to add more cloud providers or
|
||||
independent cloud services.
|
||||
|
||||
If you have any questions, please drop us a note on [Crossplane Slack][join-crossplane-slack] or [contact us][contact-us]!
|
||||
|
||||
## References
|
||||
### Concepts
|
||||
* [Crossplane Concepts][crossplane-concepts]
|
||||
* [Claims][concept-claim]
|
||||
* [Classes][concept-class]
|
||||
* [Portable Classes][concept-portable-class]
|
||||
* [Default Classes][concept-default-class]
|
||||
* [Workloads][concept-workload]
|
||||
* [Stacks][concept-stack]
|
||||
* [Stacks Design][stack-design]
|
||||
* [Stacks Manager][stack-manager]
|
||||
* [Stacks Registry][stack-registry]
|
||||
* [Stack Install Flow][stack-install-docs]
|
||||
* [Stack Package Format][stack-format-docs]
|
||||
|
||||
### Getting Started
|
||||
* [Install Crossplane][install-crossplane]
|
||||
* [Install Provider Stacks][install-provider-stacks]
|
||||
* [Cloud Provider Credentials][cloud-provider-creds]
|
||||
* [Crossplane CLI][crossplane-cli]
|
||||
* [Crossplane CLI Docs][crossplane-cli-docs]
|
||||
|
||||
**GCP**
|
||||
* [GCP Services Guide][gcp-services-guide]
|
||||
* [GCP Stack][stack-gcp]
|
||||
* [GCP Docs][gcp-docs]
|
||||
|
||||
**AWS**
|
||||
* [AWS Services Guide][aws-services-guide]
|
||||
* [AWS Stack][stack-aws]
|
||||
* [AWS Docs][aws-docs]
|
||||
|
||||
**AWS**
|
||||
* [Azure Services Guide][azure-services-guide]
|
||||
* [Azure Stack][stack-azure]
|
||||
* [Azure Docs][azure-docs]
|
||||
|
||||
### Using and Building Stacks
|
||||
* [Stacks Guide][stack-user-guide]
|
||||
* [Stacks Developer Quick Start][stack-quick-start]
|
||||
* [Stacks Developer Guide][stack-developer-guide]
|
||||
|
||||
### Kubernetes
|
||||
* [Kubernetes Concepts][kubernetes-concepts]
|
||||
* [Kubernetes Docs][kubernetes-docs]
|
||||
* [kubectl docs][kubectl-docs]
|
||||
# Services Guide
|
||||
This guide is an overview of enabling cloud service provisioning on an existing
|
||||
Kubernetes target cluster, including how to integrate Crossplane with existing
|
||||
cloud networking configurations to provide secure managed service connectivity.
|
||||
Step-by-step instructions are provided for [GCP][gcp-services-guide],
|
||||
[AWS][aws-services-guide], and [Azure][azure-services-guide].
|
||||
|
||||
To dynamically provision a new Kubernetes target cluster see the Stacks Guides
|
||||
for [GCP][stack-guide-gcp], [AWS][stack-guide-aws], and
|
||||
[Azure][stack-guide-azure].
|
||||
|
||||
## Table of Contents
|
||||
1. [Introduction](#introduction)
|
||||
1. [Secure network connectivity for cloud
|
||||
services](#secure-network-connectivity-for-cloud-services)
|
||||
1. [Dynamic provisioning with claims and
|
||||
classes](#dynamic-provisioning-with-claims-and-classes)
|
||||
1. [Connection secrets for pods in a
|
||||
deployment](#connection-secrets-for-pods-in-a-deployment)
|
||||
1. [Next Steps](#next-steps)
|
||||
1. [Learn More](#learn-more)
|
||||
|
||||
## Introduction
|
||||
Cloud service provisioning can be added to existing clusters by
|
||||
installing Crossplane directly onto the target cluster. Crossplane is designed
|
||||
to integrate with existing cloud networking and security resources, so managed
|
||||
services like RDS, CloudSQL, and Azure DB can be provisioned using Kubernetes
|
||||
objects and securely consumed by pods in a cluster.
|
||||
|
||||
Crossplane achieves this by:
|
||||
1. establishing secure network connectivity between the worker nodes in a
|
||||
cluster and cloud services
|
||||
1. populating Kuberentes `Secrets` that pods in a `Deployment` can use to
|
||||
securely access the managed service
|
||||
|
||||
## Secure network connectivity for cloud services
|
||||
Crossplane currently supports private IP secure connectivity for AWS, GCP, and
|
||||
Azure Stacks. Managed services instances are made available on the cluster's
|
||||
prviate network(s) so pods can access them. Crossplane also supports
|
||||
configuring ingress/egress rules to further restrict allowed network traffic.
|
||||
|
||||
While each cloud provider uses different resources for establishing secure
|
||||
connectivity between a Kubernetes cluster (EKS, GKE, AKS) and managed services
|
||||
(RDS, CloudSQL, and Azure DB), the basic pattern is the same:
|
||||
1. Configure cluster networking
|
||||
* network(s) and subnet(s) - L3 networking for the worker nodes
|
||||
1. Enable managed service access:
|
||||
* private service connection / endpoint - make services available via
|
||||
peering or other
|
||||
* private IP range(s) or subnet group - the private IPs a managed service
|
||||
will get
|
||||
* security groups or network rules - to restrict network traffic
|
||||
1. Provision a managed service instance
|
||||
* creates an instance e.g. MySQL from RDS, CloudSQL, or Azure DB
|
||||
* assigns a private IP from the private IP range above
|
||||
1. Securely use the managed service with secrets
|
||||
* pods on a cluster node can access the managed service via private IP
|
||||
* pods use credentials to securely connect to a managed service
|
||||
|
||||
Crossplane provides Kubernetes resources for all of the above, so you can define
|
||||
a secure connectivity model for the managed services you want to make available
|
||||
for self-service provisioning in the cluster using claims and classes.
|
||||
|
||||
## Dynamic provisioning with claims and classes
|
||||
Crossplane employs a layered architecture consisting of managed resources that
|
||||
represent a cloud service, and resource claims and classes that enable dynamic
|
||||
provisioning of those services.
|
||||
|
||||
Managed resources are high fidelity representations of the API resources that
|
||||
make up a cloud service. They're not portable across clouds. A
|
||||
`CloudSQLInstance` is an example of a managed resource - it's relevant only to
|
||||
the Google Cloud Platform (GCP) and exposes all of the nitty gritty
|
||||
configuration details of a CloudSQL instance. The networking and security
|
||||
Kubernetes resources mentioned above fall into this category.
|
||||
|
||||
Resource claims and classes are the next layer up. Resource claims like
|
||||
`MySQLInstance` enable dynamic provisioning of managed resources by matching a
|
||||
claim to a class like a `CloudSQLInstanceClass` that provides the detailed
|
||||
configuration template to provision a new cloud service instance. Resource
|
||||
classes can reference secure connectivity resources (networks), such that new
|
||||
instances of that class can be made available on the cluster's private network.
|
||||
Resource classes, cluster networking, and secure connectivity resources are
|
||||
designed to work together to enable self-service provisioning of securely
|
||||
connected cloud services in a Kubernetes cluster.
|
||||
|
||||
Resource claims can be matched to a class in several ways:
|
||||
1. rely on a class marked `resourceclass.crossplane.io/is-default-class:
|
||||
"true"`
|
||||
1. match on class labels using a `claim.spec.classSelector`
|
||||
1. use a `claim.spec.classRef` to a specific class
|
||||
|
||||
The first two methods rely on a default class of service or use a
|
||||
`classSelector` that matches any suitable resource class available in the
|
||||
target cluster. As such, the first two methods are considered portable
|
||||
resource claims that can be used in any cluster that provides the desired class
|
||||
of service. You may have one cluster using GCP and another cluster using AWS,
|
||||
and the same claim can be used in either cluster so long as the claim can be
|
||||
matched to a suitable class of cloud service.
|
||||
|
||||
The third method uses an explicit `classRef` to a specific resource class like
|
||||
a `CloudSQLInstanceClass` which means the claim may only be used with that
|
||||
class. Since resource classes are specific to a single cloud, claims that use
|
||||
a `classRef` are not portable across different cloud providers.
|
||||
|
||||
## Connection secrets for pods in a deployment
|
||||
Resource claims automatically write a connection secret that pods in a
|
||||
deployment can use to securely access the underlying cloud service. The claim's
|
||||
`writeConnectionSecretToRef` field is used to specify the name of the secret
|
||||
that should be created, which can then be used in the deployment's
|
||||
configuration. Since the claim is created in Kubernetes, and the secret is
|
||||
automatically populated by Crossplane, all cloud service secrets are managed
|
||||
automatically without leaving Kubernetes.
|
||||
|
||||
## Next steps
|
||||
Step-by-step instructions for enabling cloud service provisioning on an
|
||||
existing cluster are provided in the service guides for:
|
||||
* [GCP][gcp-services-guide]
|
||||
* [AWS][aws-services-guide]
|
||||
* [Azure][azure-services-guide]
|
||||
|
||||
### Learn More
|
||||
* [Join Crossplane Slack][join-crossplane-slack]
|
||||
* [Contact Us][contact-us]
|
||||
* [Learn More][learn-more]
|
||||
|
||||
<!-- Named links -->
|
||||
[crossplane-concepts]: concepts.md
|
||||
[concept-claim]: concepts.md#resource-claims-and-resource-classes
|
||||
[concept-class]: concepts.md#resource-claims-and-resource-classes
|
||||
[concept-workload]: concepts.md#resources-and-workloads
|
||||
[concept-stack]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#crossplane-stacks
|
||||
[concept-portable-class]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-default-resource-class.md#proposal-default-class-reference-v2--claim-portability
|
||||
[concept-default-class]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-default-resource-class.md#denote-default-via-label
|
||||
|
||||
[kubernetes-concepts]: https://kubernetes.io/docs/concepts/
|
||||
[kubernetes-docs]: https://kubernetes.io/docs/home/
|
||||
[kubectl-docs]: https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands
|
||||
|
||||
[install-crossplane]: install-crossplane.md
|
||||
[install-crossplane-alpha]: install-crossplane.html#alpha
|
||||
[install-provider-stacks]: install-crossplane.md#installing-cloud-provider-stacks
|
||||
[cloud-provider-creds]: cloud-providers.md
|
||||
|
||||
[crossplane-cli]: https://github.com/crossplaneio/crossplane-cli
|
||||
[crossplane-cli-docs]: https://github.com/crossplaneio/crossplane-cli/blob/master/README.md
|
||||
|
||||
[stack-quick-start]: https://github.com/crossplaneio/crossplane-cli#quick-start-stacks
|
||||
[stack-registry]: https://hub.docker.com/search?q=crossplane&type=image
|
||||
[stack-design]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#crossplane-stacks
|
||||
[stack-manager]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#terminology
|
||||
[stack-install-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#installation-flow
|
||||
[stack-format-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#stack-package-format
|
||||
[stack-user-guide]: stacks-guide.md
|
||||
[stack-developer-guide]: developer-guide.md
|
||||
[contact-us]: https://github.com/crossplaneio/crossplane#contact
|
||||
[join-crossplane-slack]: https://slack.crossplane.io
|
||||
|
||||
[stack-gcp]: https://github.com/crossplaneio/stack-gcp
|
||||
[stack-aws]: https://github.com/crossplaneio/stack-aws
|
||||
[stack-azure]: https://github.com/crossplaneio/stack-azure
|
||||
[stack-wordpress]: https://github.com/crossplaneio/sample-stack-wordpress
|
||||
|
||||
<!-- Named links -->
|
||||
[gcp-services-guide]: services/gcp-services-guide.md
|
||||
[aws-services-guide]: services/aws-services-guide.md
|
||||
[azure-services-guide]: services/azure-services-guide.md
|
||||
|
||||
[aws-docs]: https://docs.aws.amazon.com/
|
||||
[gcp-docs]: https://cloud.google.com/docs/
|
||||
[azure-docs]: https://docs.microsoft.com/azure/
|
||||
[stack-guide-gcp]: stacks-guide-gcp.md
|
||||
[stack-guide-aws]: stacks-guide-aws.md
|
||||
[stack-guide-azure]: stacks-guide-azure.md
|
||||
|
||||
[contact-us]: https://github.com/crossplaneio/crossplane#contact
|
||||
[join-crossplane-slack]: https://slack.crossplane.io
|
||||
[learn-more]: learn-more.md
|
||||
|
|
Loading…
Reference in New Issue