mirror of https://github.com/crossplane/docs.git
docs snapshot for crossplane version `master`
This commit is contained in:
parent
399a9314e4
commit
34f3be89db
File diff suppressed because it is too large
Load Diff
|
|
@ -4,7 +4,8 @@ toc: true
|
|||
weight: 440
|
||||
indent: true
|
||||
---
|
||||
# Deploying Wordpress in Azure
|
||||
|
||||
# Azure Services Guide
|
||||
|
||||
This user guide will walk you through Wordpress application deployment using
|
||||
Crossplane managed resources and the official Wordpress Docker image.
|
||||
|
|
@ -12,12 +13,18 @@ Crossplane managed resources and the official Wordpress Docker image.
|
|||
## Table of Contents
|
||||
|
||||
1. [Pre-requisites](#pre-requisites)
|
||||
2. [Preparation](#preparation)
|
||||
3. [Set Up AKS Cluster](#set-up-aks-cluster)
|
||||
4. [Set Up Crossplane](#set-up-crossplane)
|
||||
5. [Install Wordpress](#install-wordpress)
|
||||
6. [Uninstall](#uninstall)
|
||||
7. [Conclusion and Next Steps](#conclusion-and-next-steps)
|
||||
1. [Preparation](#preparation)
|
||||
1. [Set Up Crossplane](#set-up-crossplane)
|
||||
1. [Install in Target Cluster](#install-in-target-cluster)
|
||||
1. [Cloud Provider](#cloud-provider)
|
||||
1. [Resource Classes](#resource-classes)
|
||||
1. [Configure Managed Service Access](#configure-managed-service-access)
|
||||
1. [Provision MySQL](#provision-mysql)
|
||||
1. [Resource Claim](#resource-claim)
|
||||
1. [Virtual Network Rule](#virtual-network-rule)
|
||||
1. [Install Wordpress](#install-wordpress)
|
||||
1. [Clean Up](#clean-up)
|
||||
1. [Conclusion and Next Steps](#conclusion-and-next-steps)
|
||||
|
||||
## Pre-requisites
|
||||
|
||||
|
|
@ -35,65 +42,24 @@ local machine.
|
|||
## Preparation
|
||||
|
||||
This guide assumes that you have setup the Azure CLI and are logged in to your
|
||||
desired account.
|
||||
desired account. It also assumes that you have an existing AKS cluster in a
|
||||
Virtual Network. Make sure to populate the environment variables below with the
|
||||
relevant values for your AKS cluster.
|
||||
|
||||
*Note: environment variables are used throughout this guide. You may use the
|
||||
values below or create your own.*
|
||||
*Note: environment variables are used throughout this guide.*
|
||||
|
||||
```bash
|
||||
export RESOURCE_GROUP_NAME=myResourceGroup
|
||||
export RESOURCE_GROUP_LOCATION=eastus
|
||||
export AKS_NAME=myAKSCluster
|
||||
export AKS_NODE_COUNT=1
|
||||
export AKS_RESOURCE_GROUP=MC_${RESOURCE_GROUP_NAME}_${AKS_NAME}_${RESOURCE_GROUP_LOCATION}
|
||||
export AKS_RESOURCE_GROUP=myAKSResourceGroup
|
||||
export AKS_VNET=myAKSVnet
|
||||
export AKS_NAME=myAKSName
|
||||
export SUBSCRIPTION_ID=$(az account list | jq -j '.[0].id')
|
||||
```
|
||||
|
||||
### Set Up AKS Cluster
|
||||
## Set Up Crossplane
|
||||
|
||||
Azure maintains a succinct [walkthrough][aks-walkthrough] for setting up an AKS
|
||||
cluster using the Azure CLI. The basic steps are as follows:
|
||||
### Install in Target Cluster
|
||||
|
||||
1. Create a Resource Group
|
||||
```bash
|
||||
az group create --name $RESOURCE_GROUP_NAME --location $RESOURCE_GROUP_LOCATION
|
||||
```
|
||||
|
||||
2. Create AKS Cluster (this may take a few minutes)
|
||||
```bash
|
||||
az aks create \
|
||||
--resource-group $RESOURCE_GROUP_NAME \
|
||||
--name $AKS_NAME \
|
||||
--node-count $AKS_NODE_COUNT \
|
||||
--enable-addons monitoring \
|
||||
--generate-ssh-keys
|
||||
```
|
||||
|
||||
3. Enable SQL Service Endpoint
|
||||
|
||||
Get name of AKS node Virtual Network:
|
||||
```bash
|
||||
export AKS_VNET=$(az network vnet list -g $AKS_RESOURCE_GROUP | jq -j '.[0].name')
|
||||
```
|
||||
|
||||
Add Service Endpoint to AKS subnet:
|
||||
```bash
|
||||
az network vnet subnet update -g $AKS_RESOURCE_GROUP --vnet-name $AKS_VNET -n aks-subnet --service-endpoints Microsoft.Sql
|
||||
```
|
||||
|
||||
4. Connect to AKS Cluster
|
||||
```bash
|
||||
az aks get-credentials --resource-group $RESOURCE_GROUP_NAME --name $AKS_NAME
|
||||
```
|
||||
|
||||
5. Make sure `kubectl` is able to communicate with AKS Cluster
|
||||
```bash
|
||||
kubectl cluster-info
|
||||
```
|
||||
|
||||
### Set Up Crossplane
|
||||
|
||||
Using the newly provisioned cluster:
|
||||
Assuming you are [connected][aks-kubectl] to your AKS cluster via `kubectl`:
|
||||
|
||||
1. Install Crossplane from alpha channel. (See the [Crossplane Installation
|
||||
Guide][crossplane-install] for more information.)
|
||||
|
|
@ -108,13 +74,8 @@ helm install --name crossplane --namespace crossplane-system crossplane-alpha/cr
|
|||
|
||||
```yaml
|
||||
cat > stack-azure.yaml <<EOF
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: azure
|
||||
---
|
||||
apiVersion: stacks.crossplane.io/v1alpha1
|
||||
kind: StackRequest
|
||||
kind: ClusterStackInstall
|
||||
metadata:
|
||||
name: stack-azure
|
||||
namespace: crossplane-system
|
||||
|
|
@ -128,88 +89,24 @@ kubectl apply -f stack-azure.yaml
|
|||
3. Obtain Azure credentials. (See the [Cloud Provider Credentials][cloud-creds]
|
||||
docs for more information.)
|
||||
|
||||
#### Infrastructure Namespaces
|
||||
### Cloud Provider
|
||||
|
||||
Kubernetes namespaces allow for separation of environments within your cluster.
|
||||
You may choose to use namespaces to group resources by team, application, or any
|
||||
other logical distinction. For this guide, we will create a namespace called
|
||||
`app-project1-dev`, which we will use to group our Azure infrastructure
|
||||
components.
|
||||
It is essential to make sure that the GCP user credentials are configured in
|
||||
Crossplane as a provider. Please follow the steps [provider
|
||||
guide][azure-provider-guide] for more information.
|
||||
|
||||
* Define a `Namespace` in `azure-infra-dev-namespace.yaml` and create it:
|
||||
### Resource Classes
|
||||
|
||||
```yaml
|
||||
cat > azure-infra-dev.yaml <<EOF
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: azure-infra-dev
|
||||
EOF
|
||||
|
||||
kubectl apply -f azure-infra-dev-namespace.yam
|
||||
```
|
||||
|
||||
* You should see the following output:
|
||||
|
||||
> namespace/azure-infra-dev.yaml created
|
||||
|
||||
#### Azure Provider
|
||||
|
||||
It is essential to make sure that the Azure Service Principal is configured with
|
||||
all permissions outlined in the [provider guide][azure-provider-guide].
|
||||
|
||||
Using Azure Service Principal `crossplane-azure-provider-key.json`:
|
||||
|
||||
* Generate BASE64ENCODED_AZURE_PROVIDER_CREDS encoded value:
|
||||
To keep your resource configuration organized, start by creating a new
|
||||
directory:
|
||||
|
||||
```bash
|
||||
export BASE64ENCODED_AZURE_PROVIDER_CREDS=$(base64 crossplane-azure-provider-key.json | tr -d "\n")
|
||||
mkdir wordpress && cd $_
|
||||
```
|
||||
|
||||
* Define an Azure `Provider` and `Secret` in `azure-provider.yaml` and create
|
||||
them:
|
||||
|
||||
```yaml
|
||||
cat > azure-provider.yaml <<EOF
|
||||
---
|
||||
# Azure Admin service account secret - used by Azure Provider
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: demo-provider-azure-dev
|
||||
namespace: azure-infra-dev
|
||||
type: Opaque
|
||||
data:
|
||||
credentials: $BASE64ENCODED_AZURE_PROVIDER_CREDS
|
||||
---
|
||||
# Azure Provider with service account secret reference - used to provision resources
|
||||
apiVersion: azure.crossplane.io/v1alpha2
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: demo-azure
|
||||
namespace: azure-infra-dev
|
||||
spec:
|
||||
credentialsSecretRef:
|
||||
name: demo-provider-azure-dev
|
||||
key: credentials
|
||||
EOF
|
||||
|
||||
kubectl apply -f azure-provider.yaml
|
||||
```
|
||||
|
||||
* Verify Azure provider was successfully registered by the crossplane
|
||||
|
||||
```bash
|
||||
kubectl get providers.azure.crossplane.io -n azure-infra-dev
|
||||
kubectl get secrets -n azure-infra-dev
|
||||
```
|
||||
|
||||
#### Cloud-Specific Resource Classes
|
||||
|
||||
Cloud-specific resource classes are used to define a reusable configuration for
|
||||
a specific managed service. Wordpress requires a MySQL database, which can be
|
||||
satisfied by an [Azure Database for MySQL][azure-mysql] instance.
|
||||
Resource classes are used to define a reusable configuration for a specific
|
||||
managed service. Wordpress requires a MySQL database, which can be satisfied by
|
||||
an [Azure Database for MySQL][azure-mysql] instance.
|
||||
|
||||
* Define an Azure MySQL `SQLServerClass` in `azure-mysql-standard.yaml` and
|
||||
create it:
|
||||
|
|
@ -217,14 +114,16 @@ satisfied by an [Azure Database for MySQL][azure-mysql] instance.
|
|||
```yaml
|
||||
cat > azure-mysql-standard.yaml <<EOF
|
||||
---
|
||||
apiVersion: database.azure.crossplane.io/v1alpha2
|
||||
apiVersion: database.azure.crossplane.io/v1alpha3
|
||||
kind: SQLServerClass
|
||||
metadata:
|
||||
name: azure-mysql-standard
|
||||
namespace: azure-infra-dev
|
||||
labels:
|
||||
size: standard
|
||||
demo: true
|
||||
specTemplate:
|
||||
adminLoginName: myadmin
|
||||
resourceGroupName: $RESOURCE_GROUP_NAME
|
||||
resourceGroupName: $AKS_RESOURCE_GROUP
|
||||
location: EAST US
|
||||
sslEnforced: false
|
||||
version: "5.6"
|
||||
|
|
@ -253,7 +152,7 @@ kubectl apply -f azure-mysql-standard.yaml
|
|||
* You can verify creation with the following command and output:
|
||||
|
||||
```bash
|
||||
$ kubectl get sqlserverclasses -n azure-infra-dev
|
||||
$ kubectl get sqlserverclasses
|
||||
NAME PROVIDER-REF RECLAIM-POLICY AGE
|
||||
azure-mysql-standard demo-azure Delete 11s
|
||||
```
|
||||
|
|
@ -262,124 +161,48 @@ You are free to create more Azure `SQLServerClass` instances to define more
|
|||
potential configurations. For instance, you may create `large-azure-mysql` with
|
||||
field `storageGB: 100`.
|
||||
|
||||
#### Application Namespaces
|
||||
### Configure Managed Service Access
|
||||
|
||||
Earlier, we created a namespace to group our Azure infrastructure resources.
|
||||
Because our application resources may be satisfied by services from any cloud
|
||||
provider, we want to separate them into their own namespace. For this demo, we
|
||||
will create a namespace called `app-project1-dev`, which we will use to group
|
||||
our Wordpress resources.
|
||||
In order for the AKS cluster to talk to the MySQL Database, you must condigure a
|
||||
`Microsoft.Sql` service endpoint on the AKS Virtual Network. If you do not
|
||||
already have this configured, Azure has a [guide][service endpoint] on how to
|
||||
set it up.
|
||||
|
||||
* Define a `Namespace` in `app-project1-dev-namespace.yaml` and create it:
|
||||
## Provision MySQL
|
||||
|
||||
```yaml
|
||||
cat > app-project1-dev-namespace.yaml <<EOF
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: app-project1-dev
|
||||
EOF
|
||||
### Resource Claims
|
||||
|
||||
kubectl apply -f app-project1-dev-namespace.yaml
|
||||
```
|
||||
Resource claims are used for dynamic provisioning of a managed resource (like a
|
||||
MySQL instance) by matching the claim to a resource class. This can be done in
|
||||
several ways: (a) rely on the default class marked
|
||||
`resourceclass.crossplane.io/is-default-class: "true"`, (b) use a
|
||||
`claim.spec.classRef` to a specific class, or (c) match on class labels using a
|
||||
`claim.spec.classSelector`.
|
||||
|
||||
* You should see the following output:
|
||||
*Note: claims may also be used in [static provisioning] with a reference to an
|
||||
existing managed resource.*
|
||||
|
||||
> namespace/app-project1-dev created
|
||||
|
||||
#### Portable Resource Classes
|
||||
|
||||
Portable resource classes are used to define a class of service in a single
|
||||
namespace for an abstract service type. We want to define our Azure
|
||||
`SQLServerClass` as the standard MySQL class of service in the namespace that
|
||||
our Wordpress resources will live in.
|
||||
|
||||
* Define a `MySQLInstanceClass` in `mysql-standard.yaml` for namespace
|
||||
`app-project1-dev` and create it:
|
||||
|
||||
```yaml
|
||||
cat > mysql-standard.yaml <<EOF
|
||||
---
|
||||
apiVersion: database.crossplane.io/v1alpha1
|
||||
kind: MySQLInstanceClass
|
||||
metadata:
|
||||
name: mysql-standard
|
||||
namespace: app-project1-dev
|
||||
classRef:
|
||||
kind: SQLServerClass
|
||||
apiVersion: database.azure.crossplane.io/v1alpha2
|
||||
name: azure-mysql-standard
|
||||
namespace: azure-infra-dev
|
||||
EOF
|
||||
|
||||
kubectl apply -f mysql-standard.yaml
|
||||
```
|
||||
|
||||
* You should see the following output:
|
||||
|
||||
> mysqlinstanceclass.database.crossplane.io/mysql-standard created
|
||||
|
||||
* You can verify creation with the following command and output:
|
||||
|
||||
```bash
|
||||
$ kubectl get mysqlinstanceclasses -n app-project1-dev
|
||||
NAME AGE
|
||||
mysql-standard 27s
|
||||
```
|
||||
|
||||
Once again, you are free to create more `MySQLInstanceClass` instances in this
|
||||
namespace to define more classes of service. For instance, if you created
|
||||
`mysql-azure-large` above, you may want to create a `MySQLInstanceClass` named
|
||||
`mysql-large` that references it. You may also choose to create MySQL resource
|
||||
classes for other non-Azure providers, and reference them for a class of service
|
||||
in the `app-project1-dev` namespace.
|
||||
|
||||
You may specify *one* instance of a portable class kind as *default* in each
|
||||
namespace. This means that the portable resource class instance will be applied
|
||||
to claims that do not directly reference a portable class. If we wanted to make
|
||||
our `mysql-standard` instance the default `MySQLInstanceClass` for namespace
|
||||
`app-project1-dev`, we could do so by adding a label:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: database.crossplane.io/v1alpha1
|
||||
kind: MySQLInstanceClass
|
||||
metadata:
|
||||
name: mysql-standard
|
||||
namespace: app-project1-dev
|
||||
labels:
|
||||
default: "true"
|
||||
classRef:
|
||||
kind: SQLServerClass
|
||||
apiVersion: database.azure.crossplane.io/v1alpha2
|
||||
name: azure-mysql-standard
|
||||
namespace: azure-infra-dev
|
||||
```
|
||||
|
||||
#### Resource Claims
|
||||
|
||||
Resource claims are used to create external resources by referencing a class of
|
||||
service in the claim's namespace. When a claim is created, Crossplane uses the
|
||||
referenced portable class to find a cloud-specific resource class to use as the
|
||||
configuration for the external resource. We need a to create a claim to
|
||||
provision the MySQL database we will use with Azure.
|
||||
In the `SQLServerClass` above, we added the labels `size: standard` and `demo:
|
||||
true`, so our claim will be scheduled to that class using the labels are
|
||||
specified in the `claim.spec.classSelector`. If there are multiple classes which
|
||||
match the specified label(s) one will be chosen at random.
|
||||
|
||||
* Define a `MySQLInstance` claim in `mysql-claim.yaml` and create it:
|
||||
|
||||
```yaml
|
||||
cat > mysql-claim.yaml <<EOF
|
||||
apiVersion: database.crossplane.io/v1alpha1
|
||||
kind: MySQLInstance
|
||||
metadata:
|
||||
name: mysql-claim
|
||||
namespace: app-project1-dev
|
||||
spec:
|
||||
classRef:
|
||||
name: mysql-standard
|
||||
writeConnectionSecretToRef:
|
||||
name: wordpressmysql
|
||||
engineVersion: "5.6"
|
||||
kind: MySQLInstance
|
||||
metadata:
|
||||
name: mysql-claim
|
||||
spec:
|
||||
classSelector:
|
||||
matchLabels:
|
||||
size: standard
|
||||
demo: true
|
||||
engineVersion: "5.6"
|
||||
writeConnectionSecretToRef:
|
||||
name: wordpressmysql
|
||||
EOF
|
||||
|
||||
kubectl apply -f mysql-claim.yaml
|
||||
|
|
@ -390,7 +213,7 @@ indicates the managed resource was successfully provisioned and is ready for
|
|||
consumption. You can see when claim is bound using the following:
|
||||
|
||||
```bash
|
||||
$ kubectl get mysqlinstances -n app-project1-dev
|
||||
$ kubectl get mysqlinstances
|
||||
NAME STATUS CLASS VERSION AGE
|
||||
mysql-claim Bound mysql-standard 5.6 11m
|
||||
```
|
||||
|
|
@ -399,9 +222,9 @@ If the `STATUS` is blank, we are still waiting for the claim to become bound.
|
|||
You can observe resource creation progression using the following:
|
||||
|
||||
```bash
|
||||
$ kubectl describe mysqlinstance mysql-claim -n app-project1-dev
|
||||
$ kubectl describe mysqlinstance mysql-claim
|
||||
Name: mysql-claim
|
||||
Namespace: app-project1-dev
|
||||
Namespace: default
|
||||
Labels: <none>
|
||||
Annotations: kubectl.kubernetes.io/last-applied-configuration:
|
||||
{"apiVersion":"database.crossplane.io/v1alpha1","kind":"MySQLInstance","metadata":{"annotations":{},"name":"mysql-claim","namespace":"team..."}}
|
||||
|
|
@ -420,7 +243,7 @@ Spec:
|
|||
Name: mysql-standard
|
||||
Engine Version: 5.6
|
||||
Resource Ref:
|
||||
API Version: database.azure.crossplane.io/v1alpha2
|
||||
API Version: database.azure.crossplane.io/v1alpha3
|
||||
Kind: MySQLServer
|
||||
Name: mysqlinstance-6a7fe064-d888-11e9-ab90-42b6bb22213a
|
||||
Namespace: azure-infra-dev
|
||||
|
|
@ -442,24 +265,7 @@ Events: <none>
|
|||
*Note: You must wait until the claim becomes bound before continuing with this
|
||||
guide. It could take a few minutes for Azure to complete MySQL creation.*
|
||||
|
||||
We referenced our portable `MySQLInstanceClass` directly in the claim above, but
|
||||
if you specified that `mysql-standard` was the default `MySQLInstanceClass` for
|
||||
namespace `app-project1-dev`, we could have omitted the claim's `classRef` and
|
||||
it would automatically be assigned:
|
||||
|
||||
```yaml
|
||||
apiVersion: database.crossplane.io/v1alpha1
|
||||
kind: MySQLInstance
|
||||
metadata:
|
||||
name: mysql-claim
|
||||
namespace: app-project1-dev
|
||||
spec:
|
||||
writeConnectionSecretToRef:
|
||||
name: wordpressmysql
|
||||
engineVersion: "5.6"
|
||||
```
|
||||
|
||||
#### Virtual Network Rule
|
||||
### Virtual Network Rule
|
||||
|
||||
Before we install Wordpress, we need establish connectivity between our MySQL
|
||||
database and our AKS cluster. We can do this by creating a [Virtual Network
|
||||
|
|
@ -468,7 +274,7 @@ Rule][azure-vnet-rule].
|
|||
* Set `MYSQL_NAME` environment variable:
|
||||
|
||||
```bash
|
||||
export MYSQL_NAME=$(kubectl get -o json mysqlinstance mysql-claim -n app-project1-dev | jq -j '.spec.resourceRef.name')
|
||||
export MYSQL_NAME=$(kubectl get -o json mysqlinstance mysql-claim | jq -j '.spec.resourceRef.name')
|
||||
```
|
||||
|
||||
* Define a `MySQLServerVirtualNetworkRule` in `wordpress-vnet-rule.yaml` and
|
||||
|
|
@ -477,14 +283,13 @@ export MYSQL_NAME=$(kubectl get -o json mysqlinstance mysql-claim -n app-project
|
|||
```yaml
|
||||
cat > wordpress-vnet-rule.yaml <<EOF
|
||||
---
|
||||
apiVersion: database.azure.crossplane.io/v1alpha2
|
||||
apiVersion: database.azure.crossplane.io/v1alpha3
|
||||
kind: MySQLServerVirtualNetworkRule
|
||||
metadata:
|
||||
name: wordpress-vnet-rule
|
||||
namespace: app-project1-dev
|
||||
spec:
|
||||
name: wordpress-vnet-rule
|
||||
serverName: ${MYSQL_NAME
|
||||
serverName: ${MYSQL_NAME}
|
||||
resourceGroupName: ${AKS_RESOURCE_GROUP}
|
||||
properties:
|
||||
virtualNetworkSubnetId: /subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${AKS_RESOURCE_GROUP}/providers/Microsoft.Network/virtualNetworks/${AKS_VNET}/subnets/aks-subnet
|
||||
|
|
@ -500,7 +305,7 @@ kubectl apply -f wordpress-vnet-rule.yaml
|
|||
* You can verify creation with the following command and output:
|
||||
|
||||
```bash
|
||||
kubectl get mysqlservervirtualnetworkrules -n app-project1-dev
|
||||
kubectl get mysqlservervirtualnetworkrules
|
||||
NAME AGE
|
||||
wordpress-vnet-rule 27s
|
||||
```
|
||||
|
|
@ -516,11 +321,13 @@ the claim became `Bound`.
|
|||
* Check to make sure `wordpressmysql` exists and is populated:
|
||||
|
||||
```bash
|
||||
$ kubectl describe secret wordpressmysql -n app-project1-dev
|
||||
$ kubectl describe secret wordpressmysql
|
||||
Name: wordpressmysql
|
||||
Namespace: app-project1-dev
|
||||
Namespace: default
|
||||
Labels: <none>
|
||||
Annotations: <none>
|
||||
Annotations: crossplane.io/propagate-from-name: 6a7fe064-d888-11e9-ab90-42b6bb22213a
|
||||
crossplane.io/propagate-from-namespace: crossplane-system
|
||||
crossplane.io/propagate-from-uid: c539fcef-f698-11e9-a957-12a4af141bea
|
||||
|
||||
Type: Opaque
|
||||
|
||||
|
|
@ -538,7 +345,6 @@ cat > wordpress-app.yaml <<EOF
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
namespace: app-project1-dev
|
||||
name: wordpress
|
||||
labels:
|
||||
app: wordpress
|
||||
|
|
@ -577,7 +383,6 @@ spec:
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
namespace: app-project1-dev
|
||||
name: wordpress
|
||||
labels:
|
||||
app: wordpress
|
||||
|
|
@ -608,55 +413,42 @@ becomes available, then navigate to the address. You should see the following:
|
|||
|
||||

|
||||
|
||||
## Uninstall
|
||||
|
||||
### Wordpress
|
||||
## Clean Up
|
||||
|
||||
All Wordpress components that we installed can be deleted with one command:
|
||||
Because we put all of our configuration in a single directory, we can delete it
|
||||
all with this command:
|
||||
|
||||
```bash
|
||||
kubectl delete -f wordpress-app.yaml
|
||||
kubectl delete -f wordpress/
|
||||
```
|
||||
|
||||
### Crossplane Configuration
|
||||
|
||||
To delete all created resources, but leave Crossplane and the Azure stack
|
||||
running, execute the following commands:
|
||||
If you would like to also uninstall Crossplane and the AWS stack, run the
|
||||
following command:
|
||||
|
||||
```bash
|
||||
kubectl delete -f wordpress-vnet-rule.yaml
|
||||
kubectl delete -f mysql-claim.yaml
|
||||
kubectl delete -f mysql-standard.yaml
|
||||
kubectl delete -f azure-mysql-standard.yaml
|
||||
kubectl delete -f app-project1-dev-namespace.yaml
|
||||
kubectl delete -f azure-provider.yaml
|
||||
kubectl delete -f azure-infra-dev-namespace.yaml
|
||||
kubectl delete namespace crossplane-system
|
||||
```
|
||||
|
||||
## Conclusion and Next Steps
|
||||
|
||||
In this guide we:
|
||||
|
||||
* Setup an AKS Cluster using the Azure CLI
|
||||
* Installed Crossplane from alpha channel
|
||||
* Installed the Azure stack
|
||||
* Created an infrastructure (`azure-infra-dev`) and application
|
||||
(`app-project1-dev`) namespace
|
||||
* Setup an Azure `Provider` with our account
|
||||
* Created a `SQLServerClass` in the ` with configuration for a MySQL database on
|
||||
Azure
|
||||
* Created a `MySQLInstanceClass` that specified the `SQLServerClass` as
|
||||
`mysql-standard` in the `app-project1-dev` namespace
|
||||
* Created a `MySQLInstance` claim in the `app-project1-dev1` namespace that
|
||||
referenced `mysql-standard`
|
||||
* Created a `MySQLInstance` claim in the that was scheduled to the
|
||||
`mysql-standard` resource class
|
||||
* Created a `MySQLServerVirtualNetworkRule` to establish secure connectivity
|
||||
between our AKS Cluster and MySQL database
|
||||
* Created a `Deployment` and `Service` to run Wordpress on our AKS Cluster and
|
||||
assign an external IP address to it
|
||||
|
||||
If you would like to try out a similar workflow using a different cloud
|
||||
provider, take a look at the other [services guides][services]. If you would like
|
||||
to learn more about stacks, checkout the [stacks guide][stacks]
|
||||
provider, take a look at the other [services guides][services]. If you would
|
||||
like to learn more about stacks, checkout the [stacks guide][stacks].
|
||||
|
||||
<!-- Named links -->
|
||||
[azure-cli]: https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest
|
||||
|
|
@ -664,8 +456,8 @@ to learn more about stacks, checkout the [stacks guide][stacks]
|
|||
[install-kubectl]: https://kubernetes.io/docs/tasks/tools/install-kubectl/
|
||||
[using-helm]: https://docs.helm.sh/using_helm/
|
||||
[jq-docs]: https://stedolan.github.io/jq/
|
||||
|
||||
[aks-walkthrough]: https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough
|
||||
[service endpoint]: https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-service-endpoint-policies-overview
|
||||
[aks-kubectl]: https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough#connect-to-the-cluster
|
||||
|
||||
[crossplane-install]: ../install-crossplane.md#alpha
|
||||
[azure-stack-install]: ../install-crossplane.md#azure-stack
|
||||
|
|
@ -675,6 +467,7 @@ to learn more about stacks, checkout the [stacks guide][stacks]
|
|||
|
||||
[azure-mysql]: https://azure.microsoft.com/en-us/services/mysql/
|
||||
[azure-vnet-rule]: https://docs.microsoft.com/en-us/azure/mysql/concepts-data-access-and-security-vnet
|
||||
[static provisioning]: ../concepts.md#dynamic-and-static-provisioning
|
||||
|
||||
[services]: ../services-guide.md
|
||||
[stacks]: ../stacks-guide.md
|
||||
|
|
|
|||
|
|
@ -7,26 +7,6 @@ indent: true
|
|||
|
||||
# GCP Services Guide
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Introduction](#introduction)
|
||||
2. [Pre-requisites](#pre-requisites)
|
||||
3. [Preparation](#preparation)
|
||||
1. [GKE Cluster Steps](#gke-cluster-steps)
|
||||
2. [Crossplane Steps](#crossplane-steps)
|
||||
1. [Installation](#installation)
|
||||
2. [GCP Provider](#gcp-provider)
|
||||
3. [Cloud Specific Resource Classes](#cloud-specific-resource-classes)
|
||||
4. [Namespaces](#namespaces)
|
||||
5. [Portable Resource Classes](#portable-resource-classes)
|
||||
6. [Connecting MySQL Instance and GKE Cluster](#connecting-mysql-instance-and-gke-cluster)
|
||||
4. [Install Wordpress](#install-wordpress)
|
||||
5. [Clean Up](#clean-up)
|
||||
1. [Wordpress](#wordpress)
|
||||
2. [Crossplane](#crossplane)
|
||||
|
||||
## Introduction
|
||||
|
||||
This user guide will walk you through Wordpress application deployment using
|
||||
your existing Kubernetes cluster and Crossplane managed resources. We will:
|
||||
* Install Crossplane to your cluster.
|
||||
|
|
@ -34,10 +14,23 @@ your existing Kubernetes cluster and Crossplane managed resources. We will:
|
|||
* Create network resources to get GKE cluster to connect to MySQL instance.
|
||||
* Deploy Wordpress.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Pre-requisites](#pre-requisites)
|
||||
1. [Preparation](#preparation)
|
||||
1. [Set Up Crossplane](#set-up-crossplane)
|
||||
1. [Install in Target Cluster](#install-in-target-cluster)
|
||||
1. [Cloud Provider](#cloud-provider)
|
||||
1. [Resource Classes](#resource-classes)
|
||||
1. [Configure Managed Service Access](#configure-managed-service-access)
|
||||
1. [Provision MySQL](#provision-mysql)
|
||||
1. [Resource Claim](#resource-claim)
|
||||
1. [Install Wordpress](#install-wordpress)
|
||||
1. [Clean Up](#clean-up)
|
||||
1. [Conclusion and Next Steps](#conclusion-and-next-steps)
|
||||
|
||||
## Pre-requisites
|
||||
|
||||
* [gcloud CLI](https://cloud.google.com/sdk/docs/quickstarts)
|
||||
* Make sure to configure the authentication after installing gcloud cli.
|
||||
* [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
|
||||
* A GKE cluster.
|
||||
|
||||
|
|
@ -46,8 +39,8 @@ your existing Kubernetes cluster and Crossplane managed resources. We will:
|
|||
This guide assumes that you have setup the gcloud CLI and are logged in to your
|
||||
desired account.
|
||||
|
||||
*Note: environment variables are used throughout this guide. You should use
|
||||
your own values.*
|
||||
*Note: environment variables are used throughout this guide. You should use your
|
||||
own values.*
|
||||
|
||||
Run the following:
|
||||
```bash
|
||||
|
|
@ -56,123 +49,37 @@ export NETWORK_NAME=default # the network that your GKE cluster lives in.
|
|||
export SUBNETWORK_NAME=default # the subnetwork that your GKE cluster lives in.
|
||||
```
|
||||
|
||||
### GKE Cluster Steps
|
||||
## Set Up Crossplane
|
||||
|
||||
We are assuming you've got a GKE cluster up and running created either via
|
||||
GCP Console or gcloud CLI. If you don't, the basic command to create one is
|
||||
the following:
|
||||
### Installation
|
||||
|
||||
1. Create a GKE cluster:
|
||||
```bash
|
||||
gcloud beta container --project "${PROJECT_ID}" clusters create "my-existing-cluster" \
|
||||
--zone "us-central1-a" \
|
||||
--cluster-version "1.13.7-gke.8" \
|
||||
--machine-type "n1-standard-1" \
|
||||
--image-type "COS" \
|
||||
--disk-type "pd-standard" \
|
||||
--disk-size "100" \
|
||||
--metadata disable-legacy-endpoints=true \
|
||||
--scopes "https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append" \
|
||||
--num-nodes "1" \
|
||||
--enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias --enable-autoupgrade --enable-autorepair --no-enable-basic-auth \
|
||||
--network "projects/${PROJECT_ID}/global/networks/${NETWORK_NAME}" \
|
||||
--subnetwork "projects/${PROJECT_ID}/regions/us-central1/subnetworks/${SUBNETWORK_NAME}" \
|
||||
--default-max-pods-per-node "110" \
|
||||
--addons HorizontalPodAutoscaling,HttpLoadBalancing
|
||||
```
|
||||
|
||||
This may take a while to finish.
|
||||
|
||||
2. Connect to your GKE cluster
|
||||
```bash
|
||||
gcloud container clusters get-credentials "my-existing-cluster" --zone us-central1-a --project "${PROJECT_ID}"
|
||||
```
|
||||
|
||||
3. Make sure `kubectl` is able to communicate with your GKE cluster
|
||||
```bash
|
||||
kubectl cluster-info
|
||||
```
|
||||
4. Make sure Helm is installed with permissions to work on `crossplane-system`
|
||||
namespace. The easiest way to achieve that is to run the following command
|
||||
that makes Helm's server side component `tiller` cluster admin:
|
||||
```bash
|
||||
kubectl -n kube-system create serviceaccount tiller
|
||||
kubectl create clusterrolebinding tiller --clusterrole cluster-admin --serviceaccount=kube-system:tiller
|
||||
helm init --service-account=tiller
|
||||
```
|
||||
|
||||
### Crossplane Steps
|
||||
|
||||
#### Installation
|
||||
Assuming you are
|
||||
[connected](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl)
|
||||
to your GKE cluster via `kubectl`:
|
||||
|
||||
* Install Crossplane from alpha channel using the [Crossplane Installation
|
||||
Guide](../install-crossplane.md#alpha)
|
||||
* Install the GCP stack into Crossplane using the [GCP stack
|
||||
section](../install-crossplane.md#gcp-stack) of the install guide.
|
||||
|
||||
We will be using `gcp-infra-dev` namespace to store our cloud-specific resource
|
||||
classes, cloud resources and providers. But you can use any namespace name for
|
||||
that matter.
|
||||
To keep your resource configuration organized, start by creating a new
|
||||
directory:
|
||||
|
||||
```bash
|
||||
kubectl create namespace gcp-infra-dev
|
||||
export INFRA_NAMESPACE=gcp-infra-dev
|
||||
mkdir wordpress && cd $_
|
||||
```
|
||||
|
||||
#### GCP Provider
|
||||
### Cloud Provider
|
||||
|
||||
It is essential to make sure that a GCP service account to be used by
|
||||
Crossplane is configured with all the necessary permissions outlined in the
|
||||
[provider guide](../cloud-providers/gcp/gcp-provider.md).
|
||||
It is essential to make sure that the GCP user credentials are configured in
|
||||
Crossplane as a provider. Please follow the steps [provider
|
||||
guide](../cloud-providers/gcp/gcp-provider.md) for more information.
|
||||
|
||||
Using the service account json `crossplane-gcp-provider-key.json` that you
|
||||
acquired from GCP:
|
||||
### Resource Classes
|
||||
|
||||
* Generate Base64 encoded value to store in a `Secret`:
|
||||
|
||||
```bash
|
||||
export BASE64ENCODED_GCP_PROVIDER_CREDS=$(base64 crossplane-gcp-provider-key.json | tr -d "\n")
|
||||
```
|
||||
|
||||
* Define a GCP `Provider` and `Secret`:
|
||||
|
||||
```bash
|
||||
cat > gcp-provider.yaml <<EOF
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
credentials.json: $BASE64ENCODED_GCP_PROVIDER_CREDS
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: gcp-provider-creds
|
||||
type: Opaque
|
||||
---
|
||||
apiVersion: gcp.crossplane.io/v1alpha2
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: gcp-provider
|
||||
spec:
|
||||
credentialsSecretRef:
|
||||
name: gcp-provider-creds
|
||||
key: credentials.json
|
||||
projectID: $PROJECT_ID
|
||||
EOF
|
||||
|
||||
kubectl -n $INFRA_NAMESPACE apply -f gcp-provider.yaml
|
||||
unset BASE64ENCODED_GCP_PROVIDER_CREDS # we don't need this anymore.
|
||||
```
|
||||
|
||||
* Verify GCP provider was successfully registered by the crossplane
|
||||
|
||||
```bash
|
||||
kubectl -n $INFRA_NAMESPACE get providers.gcp.crossplane.io
|
||||
kubectl -n $INFRA_NAMESPACE get secrets
|
||||
```
|
||||
|
||||
#### Cloud-Specific Resource Classes
|
||||
|
||||
Cloud-specific resource classes are used to define a reusable configuration for
|
||||
a specific managed service. Wordpress requires a MySQL database, which can be
|
||||
satisfied by a [Google Cloud SQL Instance](https://cloud.google.com/sql/docs/mysql/).
|
||||
Resource classes are used to define a reusable configuration for a specific
|
||||
managed service. Wordpress requires a MySQL database, which can be satisfied by
|
||||
a [Google Cloud SQL Instance](https://cloud.google.com/sql/docs/mysql/).
|
||||
|
||||
* Define a GCP CloudSQL class `CloudSQLInstanceClass`:
|
||||
|
||||
|
|
@ -183,7 +90,10 @@ apiVersion: database.gcp.crossplane.io/v1beta1
|
|||
kind: CloudSQLInstanceClass
|
||||
metadata:
|
||||
name: standard-cloudsql
|
||||
labels:
|
||||
size: standard
|
||||
specTemplate:
|
||||
writeConnectionSecretsToNamespace: crossplane-system
|
||||
forProvider:
|
||||
databaseVersion: MYSQL_5_7
|
||||
region: us-central1
|
||||
|
|
@ -197,18 +107,17 @@ specTemplate:
|
|||
privateNetwork: projects/$PROJECT_ID/global/networks/$NETWORK_NAME
|
||||
providerRef:
|
||||
name: gcp-provider
|
||||
namespace: $INFRA_NAMESPACE
|
||||
reclaimPolicy: Delete
|
||||
EOF
|
||||
|
||||
kubectl -n $INFRA_NAMESPACE apply -f gcp-mysql-standard.yaml
|
||||
kubectl apply -f gcp-mysql-standard.yaml
|
||||
```
|
||||
|
||||
* You can verify creation with the following command and output:
|
||||
|
||||
*Command*
|
||||
```bash
|
||||
kubectl get cloudsqlinstanceclass -n ${INFRA_NAMESPACE}
|
||||
kubectl get cloudsqlinstanceclasses
|
||||
```
|
||||
*Output*
|
||||
```bash
|
||||
|
|
@ -220,185 +129,11 @@ You are free to create more GCP `CloudSQLInstanceClass` instances to define more
|
|||
potential configurations. For instance, you may create `large-gcp-mysql` with
|
||||
field `storageGB: 100`.
|
||||
|
||||
#### Namespaces
|
||||
### Configure Managed Service Access
|
||||
|
||||
Kubernetes namespaces allow for separation of environments within your cluster.
|
||||
You may choose to use namespaces to group resources by team, application, or any
|
||||
other logical distinction. For this demo, we will create a namespace called
|
||||
`app-project1-dev`, which we will use to group our Wordpress resources.
|
||||
|
||||
```bash
|
||||
kubectl create namespace app-project1-dev
|
||||
```
|
||||
|
||||
#### Portable Resource Classes
|
||||
|
||||
Portable resource classes are used to define a class of service in a single
|
||||
namespace for an abstract service type. We want to define our GCP
|
||||
`CloudSQLInstanceClass` as the standard MySQL class of service in the namespace
|
||||
that our Wordpress resources will live in.
|
||||
|
||||
* Define a `MySQLInstanceClass` in `mysql-standard.yaml` for namespace `app-project1-dev`:
|
||||
|
||||
```bash
|
||||
cat > mysql-standard.yaml <<EOF
|
||||
---
|
||||
apiVersion: database.crossplane.io/v1alpha1
|
||||
kind: MySQLInstanceClass
|
||||
metadata:
|
||||
name: mysql-standard
|
||||
classRef:
|
||||
kind: CloudSQLInstanceClass
|
||||
apiVersion: database.gcp.crossplane.io/v1beta1
|
||||
name: standard-cloudsql
|
||||
namespace: $INFRA_NAMESPACE
|
||||
EOF
|
||||
|
||||
kubectl -n app-project1-dev apply -f mysql-standard.yaml
|
||||
```
|
||||
|
||||
* You can verify creation with the following command and output:
|
||||
|
||||
*Command*
|
||||
|
||||
```bash
|
||||
kubectl -n app-project1-dev get mysqlinstanceclasses
|
||||
```
|
||||
|
||||
*Output*
|
||||
|
||||
```bash
|
||||
NAME AGE
|
||||
mysql-standard 27s
|
||||
```
|
||||
|
||||
Once again, you are free to create more `MySQLInstanceClass` instances in this
|
||||
namespace to define more classes of service. For instance, if you created
|
||||
`mysql-gcp-large` above, you may want to create a `MySQLInstanceClass` named
|
||||
`mysql-large` that references it. You may also choose to create MySQL resource
|
||||
classes for other non-GCP providers, and reference them for a class of service
|
||||
in the `app-project1-dev` namespace.
|
||||
|
||||
> Portable classes are the resource classes that are not cloud specific and
|
||||
their purpose is to refer to cloud specific resource classes that will be
|
||||
used for provisioning. For example, MySQLInstanceClass is a portable class
|
||||
that can refer to CloudSQLInstanceClass (GCP) or RDSInstanceClass (AWS).
|
||||
|
||||
You may specify *one* instance of a portable class kind as *default* in each
|
||||
namespace. This means that the portable resource class instance will be applied
|
||||
to claims that do not directly reference a portable class. If we wanted to make
|
||||
our `mysql-standard` instance the default `MySQLInstanceClass` for namespace
|
||||
`app-project1-dev`, we could do so by adding a label:
|
||||
|
||||
```bash
|
||||
kubectl -n app-project1-dev label mysqlinstanceclass mysql-standard default="true"
|
||||
```
|
||||
For more details about resource classes in Crossplane, see
|
||||
[Default Resource Classes One-Pager](https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-default-resource-class.md).
|
||||
|
||||
#### Resource Claims
|
||||
|
||||
Resource claims are used to create external resources by referencing a class of
|
||||
service in the claim's namespace. When a claim is created, Crossplane uses the
|
||||
referenced portable class to find a cloud-specific resource class to use as the
|
||||
configuration for the external resource. We need to create a claim to
|
||||
provision the MySQL database we will use in GCP.
|
||||
|
||||
* Define a `MySQLInstance` claim in `mysql-claim.yaml`.
|
||||
You can omit `spec.classRef` if you want to use the default MySQLInstanceClass:
|
||||
|
||||
```bash
|
||||
cat > mysql-claim.yaml <<EOF
|
||||
---
|
||||
apiVersion: database.crossplane.io/v1alpha1
|
||||
kind: MySQLInstance
|
||||
metadata:
|
||||
name: mysql-claim
|
||||
spec:
|
||||
classRef:
|
||||
name: mysql-standard
|
||||
engineVersion: "5.7"
|
||||
# A secret is exported by providing the secret name
|
||||
# to export it under. This is the name of the secret
|
||||
# in the crossplane cluster, and it's scoped to this claim's namespace.
|
||||
writeConnectionSecretToRef:
|
||||
name: wordpressmysql
|
||||
EOF
|
||||
|
||||
kubectl -n app-project1-dev apply -f mysql-claim.yaml
|
||||
```
|
||||
|
||||
What we are looking for is for `STATUS` value to become `Bound` which indicates
|
||||
the managed resource was successfully provisioned and is ready for consumption.
|
||||
You can see when claim is bound using the following:
|
||||
|
||||
*Command*
|
||||
```bash
|
||||
kubectl -n app-project1-dev get mysqlinstances
|
||||
```
|
||||
|
||||
*Output*
|
||||
```bash
|
||||
NAME STATUS CLASS VERSION AGE
|
||||
mysql-claim Bound mysql-standard 5.6 11m
|
||||
```
|
||||
|
||||
If the `STATUS` is blank, we are still waiting for the claim to become bound.
|
||||
You can observe resource creation progression using the following:
|
||||
|
||||
*Command*
|
||||
```bash
|
||||
kubectl -n app-project1-dev describe mysqlinstance mysql-claim --watch
|
||||
```
|
||||
|
||||
*Output*
|
||||
```
|
||||
Name: mysql-claim
|
||||
Namespace: app-project1-dev
|
||||
Labels: <none>
|
||||
Annotations: kubectl.kubernetes.io/last-applied-configuration:
|
||||
{"apiVersion":"database.crossplane.io/v1alpha1","kind":"MySQLInstance","metadata":{"annotations":{},"name":"mysql-claim","namespace":"team..."}}
|
||||
API Version: database.crossplane.io/v1alpha1
|
||||
Kind: MySQLInstance
|
||||
Metadata:
|
||||
Creation Timestamp: 2019-09-16T13:46:42Z
|
||||
Finalizers:
|
||||
finalizer.resourceclaim.crossplane.io
|
||||
Generation: 2
|
||||
Resource Version: 4256
|
||||
Self Link: /apis/database.crossplane.io/v1alpha1/namespaces/app-project1-dev/mysqlinstances/mysql-claim
|
||||
UID: 6a7fe064-d888-11e9-ab90-42b6bb22213a
|
||||
Spec:
|
||||
Class Ref:
|
||||
Name: mysql-standard
|
||||
Engine Version: 5.6
|
||||
Resource Ref:
|
||||
API Version: database.gcp.crossplane.io/v1beta1
|
||||
Kind: CloudSQLInstance
|
||||
Name: mysqlinstance-6a7fe064-d888-11e9-ab90-42b6bb22213a
|
||||
Namespace: gcp-infra-dev
|
||||
Write Connection Secret To Ref:
|
||||
Name: wordpressmysql
|
||||
Status:
|
||||
Conditions:
|
||||
Last Transition Time: 2019-09-16T13:46:42Z
|
||||
Reason: Managed claim is waiting for managed resource to become bindable
|
||||
Status: False
|
||||
Type: Ready
|
||||
Last Transition Time: 2019-09-16T13:46:42Z
|
||||
Reason: Successfully reconciled managed resource
|
||||
Status: True
|
||||
Type: Synced
|
||||
Events: <none>
|
||||
```
|
||||
|
||||
*Note: You must wait until the claim becomes bound before continuing with this
|
||||
guide. It could take a few minutes for GCP to complete CloudSQL creation.*
|
||||
|
||||
#### Connecting MySQL Instance and GKE Cluster
|
||||
|
||||
Before we install Wordpress, we need to establish connectivity between our MySQL
|
||||
database and our GKE cluster. We can do this by creating a [Private Service
|
||||
Before we install Wordpress, we need to establish connectivity between the the
|
||||
MySQL database and the GKE cluster. We can do this by creating a [Private
|
||||
Service
|
||||
Connection](https://cloud.google.com/vpc/docs/configure-private-services-access).
|
||||
|
||||
You can create it by following the instructions at the link above, or you could
|
||||
|
|
@ -411,14 +146,13 @@ use Crossplane to do it:
|
|||
---
|
||||
# example-globaladdress defines the IP range that will be allocated for cloud services connecting
|
||||
# to the instances in the given Network.
|
||||
apiVersion: compute.gcp.crossplane.io/v1alpha2
|
||||
apiVersion: compute.gcp.crossplane.io/v1alpha3
|
||||
kind: GlobalAddress
|
||||
metadata:
|
||||
name: example-globaladdress
|
||||
spec:
|
||||
providerRef:
|
||||
name: gcp-provider
|
||||
namespace: $INFRA_NAMESPACE
|
||||
reclaimPolicy: Delete
|
||||
name: example-globaladdress
|
||||
purpose: VPC_PEERING
|
||||
|
|
@ -428,22 +162,21 @@ use Crossplane to do it:
|
|||
---
|
||||
# example-connection is what allows cloud services to use the allocated GlobalAddress for communication. Behind
|
||||
# the scenes, it creates a VPC peering to the network that those service instances actually live.
|
||||
apiVersion: servicenetworking.gcp.crossplane.io/v1alpha2
|
||||
apiVersion: servicenetworking.gcp.crossplane.io/v1alpha3
|
||||
kind: Connection
|
||||
metadata:
|
||||
name: example-connection
|
||||
spec:
|
||||
providerRef:
|
||||
name: gcp-provider
|
||||
namespace: $INFRA_NAMESPACE
|
||||
reclaimPolicy: Delete
|
||||
parent: services/servicenetworking.googleapis.com
|
||||
network: projects/$PROJECT_ID/global/networks/$NETWORK_NAME
|
||||
reservedPeeringRanges:
|
||||
- example-globaladdress
|
||||
reservedPeeringRangeRefs:
|
||||
- name: example-globaladdress
|
||||
EOF
|
||||
|
||||
kubectl -n $INFRA_NAMESPACE apply -f network.yaml
|
||||
kubectl apply -f network.yaml
|
||||
```
|
||||
|
||||
* You can verify creation with the following command and output:
|
||||
|
|
@ -451,17 +184,172 @@ use Crossplane to do it:
|
|||
*Command*
|
||||
|
||||
```bash
|
||||
kubectl -n $INFRA_NAMESPACE get connection example-connection -o custom-columns='NAME:.metadata.name,FIRST_CONDITION:.status.conditions[0].status,SECOND_CONDITION:.status.conditions[1].status'
|
||||
kubectl describe connection.servicenetworking.gcp.crossplane.io example-connection
|
||||
```
|
||||
|
||||
*Output*
|
||||
|
||||
```bash
|
||||
NAME FIRST_CONDITION SECOND_CONDITION
|
||||
example-connection True True
|
||||
```yaml
|
||||
Name: example-connection
|
||||
Namespace:
|
||||
Labels: <none>
|
||||
Annotations: crossplane.io/external-name: example-connection
|
||||
kubectl.kubernetes.io/last-applied-configuration:
|
||||
{"apiVersion":"servicenetworking.gcp.crossplane.io/v1alpha3","kind":"Connection","metadata":{"annotations":{},"name":"example-connection"}...
|
||||
API Version: servicenetworking.gcp.crossplane.io/v1alpha3
|
||||
Kind: Connection
|
||||
Metadata:
|
||||
Creation Timestamp: 2019-10-28T14:10:23Z
|
||||
Finalizers:
|
||||
finalizer.managedresource.crossplane.io
|
||||
Generation: 1
|
||||
Resource Version: 7245
|
||||
Self Link: /apis/servicenetworking.gcp.crossplane.io/v1alpha3/connections/example-connection
|
||||
UID: aeae7e4d-f98c-11e9-8275-42010a800122
|
||||
Spec:
|
||||
Network: projects/crossplane-playground/global/networks/default
|
||||
Parent: services/servicenetworking.googleapis.com
|
||||
Provider Ref:
|
||||
Name: gcp-provider
|
||||
Reclaim Policy: Delete
|
||||
Reserved Peering Ranges:
|
||||
example-globaladdress
|
||||
Status:
|
||||
Conditions:
|
||||
Last Transition Time: 2019-10-28T14:10:23Z
|
||||
Reason: Successfully resolved managed resource references to other resources
|
||||
Status: True
|
||||
Type: ReferencesResolved
|
||||
Last Transition Time: 2019-10-28T14:10:23Z
|
||||
Reason: Managed resource is being created
|
||||
Status: False
|
||||
Type: Ready
|
||||
Last Transition Time: 2019-10-28T14:10:23Z
|
||||
Reason: Successfully reconciled managed resource
|
||||
Status: True
|
||||
Type: Synced
|
||||
Events: <none>
|
||||
```
|
||||
|
||||
Wait for both conditions to be true to continue.
|
||||
We are looking for the `Connection` resource to report `Type: Ready` `Status:
|
||||
True` in its `status.conditions`.
|
||||
|
||||
## Provision
|
||||
|
||||
### Resource Claim
|
||||
|
||||
Resource claims are used for dynamic provisioning of a managed resource (like a
|
||||
MySQL instance) by matching the claim to a resource class. This can be done in
|
||||
several ways: (a) rely on the default class marked
|
||||
`resourceclass.crossplane.io/is-default-class: "true"`, (b) use a
|
||||
`claim.spec.classRef` to a specific class, or (c) match on class labels using a
|
||||
`claim.spec.classSelector`.
|
||||
|
||||
*Note: claims may also be used in [static
|
||||
provisioning](../concepts.md#dynamic-and-static-provisioning) with a reference
|
||||
to an existing managed resource.*
|
||||
|
||||
In the `CloudSQLInstanceClass` above, we added the label `size: standard`, so
|
||||
our claim will be scheduled to that class using the label is specified in the
|
||||
`claim.spec.classSelector`. If there are multiple classes which match the
|
||||
specified label(s) one will be chosen at random.
|
||||
|
||||
* Define a `MySQLInstance` claim in `mysql-claim.yaml`:
|
||||
|
||||
```bash
|
||||
cat > mysql-claim.yaml <<EOF
|
||||
---
|
||||
apiVersion: database.crossplane.io/v1alpha1
|
||||
kind: MySQLInstance
|
||||
metadata:
|
||||
name: mysql-claim
|
||||
spec:
|
||||
classSelector:
|
||||
matchLabels:
|
||||
size: standard
|
||||
engineVersion: "5.7"
|
||||
# A secret is exported by providing the secret name
|
||||
# to export it under. This is the name of the secret
|
||||
# in the crossplane cluster, and it's scoped to this claim's namespace.
|
||||
writeConnectionSecretToRef:
|
||||
name: wordpressmysql
|
||||
EOF
|
||||
|
||||
kubectl apply -f mysql-claim.yaml
|
||||
```
|
||||
|
||||
What we are looking for is for the claim's `STATUS` value to become `Bound`
|
||||
which indicates the managed resource was successfully provisioned and is ready
|
||||
for consumption. You can see when claim is bound using the following:
|
||||
|
||||
*Command*
|
||||
```bash
|
||||
kubectl get mysqlinstances
|
||||
```
|
||||
|
||||
*Output*
|
||||
```bash
|
||||
NAME STATUS CLASS-KIND CLASS-NAME RESOURCE-KIND RESOURCE-NAME AGE
|
||||
mysql-claim Bound CloudSQLInstanceClass standard-cloudsql CloudSQLInstance default-mysql-claim-vtnf7 3m
|
||||
```
|
||||
|
||||
If the `STATUS` is blank, we are still waiting for the claim to become bound.
|
||||
You can observe resource creation progression using the following:
|
||||
|
||||
*Command*
|
||||
```bash
|
||||
kubectl describe mysqlinstance mysql-claim
|
||||
```
|
||||
|
||||
*Output*
|
||||
```
|
||||
Name: mysql-claim
|
||||
Namespace: default
|
||||
Labels: <none>
|
||||
Annotations: kubectl.kubernetes.io/last-applied-configuration:
|
||||
{"apiVersion":"database.crossplane.io/v1alpha1","kind":"MySQLInstance","metadata":{"annotations":{},"name":"mysql-claim","namespace":"defa...
|
||||
API Version: database.crossplane.io/v1alpha1
|
||||
Kind: MySQLInstance
|
||||
Metadata:
|
||||
Creation Timestamp: 2019-10-28T14:18:55Z
|
||||
Finalizers:
|
||||
finalizer.resourceclaim.crossplane.io
|
||||
Generation: 3
|
||||
Resource Version: 9011
|
||||
Self Link: /apis/database.crossplane.io/v1alpha1/namespaces/default/mysqlinstances/mysql-claim
|
||||
UID: e0329d69-f98d-11e9-8275-42010a800122
|
||||
Spec:
|
||||
Class Ref:
|
||||
API Version: database.gcp.crossplane.io/v1beta1
|
||||
Kind: CloudSQLInstanceClass
|
||||
Name: standard-cloudsql
|
||||
UID: 431580bd-f989-11e9-8275-42010a800122
|
||||
Class Selector:
|
||||
Match Labels:
|
||||
Size: standard
|
||||
Engine Version: 5.7
|
||||
Resource Ref:
|
||||
API Version: database.gcp.crossplane.io/v1beta1
|
||||
Kind: CloudSQLInstance
|
||||
Name: default-mysql-claim-vtnf7
|
||||
UID: e07c42c5-f98d-11e9-8275-42010a800122
|
||||
Write Connection Secret To Ref:
|
||||
Name: wordpressmysql
|
||||
Status:
|
||||
Conditions:
|
||||
Last Transition Time: 2019-10-28T14:18:56Z
|
||||
Reason: Managed claim is waiting for managed resource to become bindable
|
||||
Status: False
|
||||
Type: Ready
|
||||
Last Transition Time: 2019-10-28T14:18:56Z
|
||||
Reason: Successfully reconciled managed resource
|
||||
Status: True
|
||||
Type: Synced
|
||||
Events: <none>
|
||||
```
|
||||
|
||||
*Note: You must wait until the claim becomes bound before continuing with this
|
||||
guide. It could take a few minutes for GCP to complete CloudSQL creation.*
|
||||
|
||||
## Install Wordpress
|
||||
|
||||
|
|
@ -472,31 +360,42 @@ variables. It should have been populated with our MySQL connection details after
|
|||
the claim became `Bound`.
|
||||
|
||||
> Binding status tells you whether your resource has been provisioned and ready
|
||||
to use. Crossplane binds the actual resource to the claim via changing the
|
||||
readiness condition to `Bound`. This happens only when the resource is ready
|
||||
to be consumed.
|
||||
to use. Crossplane binds the actual resource to the claim via changing the
|
||||
readiness condition to `Bound`. This happens only when the resource is ready to
|
||||
be consumed.
|
||||
|
||||
* Check to make sure `wordpressmysql` exists and is populated:
|
||||
|
||||
*Command*
|
||||
```bash
|
||||
kubectl -n app-project1-dev describe secret wordpressmysql
|
||||
kubectl describe secret wordpressmysql
|
||||
```
|
||||
|
||||
*Output*
|
||||
```bash
|
||||
Name: wordpressmysql
|
||||
Namespace: app-project1-dev
|
||||
Namespace: default
|
||||
Labels: <none>
|
||||
Annotations: <none>
|
||||
Annotations: crossplane.io/propagate-from-name: 330cccf5-f991-11e9-8275-42010a800122
|
||||
crossplane.io/propagate-from-namespace: crossplane-system
|
||||
crossplane.io/propagate-from-uid: 33581ec7-f991-11e9-8275-42010a800122
|
||||
|
||||
Type: Opaque
|
||||
|
||||
Data
|
||||
====
|
||||
endpoint: 75 bytes
|
||||
password: 27 bytes
|
||||
username: 58 bytes
|
||||
endpoint: 10 bytes
|
||||
password: 27 bytes
|
||||
publicIP: 13 bytes
|
||||
serverCACertificateCert: 1272 bytes
|
||||
serverCACertificateCommonName: 98 bytes
|
||||
serverCACertificateCreateTime: 24 bytes
|
||||
serverCACertificateExpirationTime: 24 bytes
|
||||
privateIP: 10 bytes
|
||||
serverCACertificateCertSerialNumber: 1 bytes
|
||||
serverCACertificateInstance: 25 bytes
|
||||
serverCACertificateSha1Fingerprint: 40 bytes
|
||||
username: 4 bytes
|
||||
```
|
||||
|
||||
* Define the `Deployment` and `Service` in `wordpress.yaml`:
|
||||
|
|
@ -555,7 +454,7 @@ username: 58 bytes
|
|||
type: LoadBalancer
|
||||
EOF
|
||||
|
||||
kubectl -n app-project1-dev apply -f wordpress.yaml
|
||||
kubectl apply -f wordpress.yaml
|
||||
```
|
||||
|
||||
* You can verify creation with the following command and output:
|
||||
|
|
@ -563,17 +462,17 @@ username: 58 bytes
|
|||
*Command*
|
||||
|
||||
```bash
|
||||
kubectl -n app-project1-dev get -f wordpress.yaml
|
||||
kubectl get -f wordpress.yaml
|
||||
```
|
||||
|
||||
*Output*
|
||||
|
||||
```bash
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
deployment.apps/wordpress 1/1 1 1 11m
|
||||
deployment.apps/wordpress 1/1 1 1 77s
|
||||
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/wordpress LoadBalancer 10.0.128.30 52.168.69.6 80:32587/TCP 11m
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/wordpress LoadBalancer 10.12.3.121 35.223.147.148 80:30287/TCP 77s
|
||||
```
|
||||
|
||||
If the `EXTERNAL-IP` field of the `LoadBalancer` is `<pending>`, wait until it
|
||||
|
|
@ -583,31 +482,21 @@ becomes available, then navigate to the address. You should see the following:
|
|||
|
||||
## Clean Up
|
||||
|
||||
### Wordpress
|
||||
|
||||
The `Service` and `Deployment` of Wordpress we installed can be removed with the following command:
|
||||
Because we put all of our configuration in a single directory, we can delete it
|
||||
all with this command:
|
||||
|
||||
```bash
|
||||
kubectl -n app-project1-dev delete -f wordpress.yaml
|
||||
kubectl delete -f wordpress/
|
||||
```
|
||||
|
||||
### Crossplane
|
||||
|
||||
To delete all created resources, but leave Crossplane and the GCP stack
|
||||
running, execute the following commands:
|
||||
If you would like to also uninstall Crossplane and the AWS stack, run the
|
||||
following command:
|
||||
|
||||
```bash
|
||||
kubectl -n app-project1-dev delete -f mysql-claim.yaml
|
||||
kubectl -n app-project1-dev delete -f mysql-standard.yaml
|
||||
kubectl -n $INFRA_NAMESPACE delete -f network.yaml
|
||||
kubectl -n $INFRA_NAMESPACE delete -f gcp-mysql-standard.yaml
|
||||
kubectl -n $INFRA_NAMESPACE delete -f gcp-provider.yaml
|
||||
|
||||
kubectl delete namespace app-project1-dev
|
||||
kubectl delete namespace $INFRA_NAMESPACE
|
||||
kubectl delete namespace crossplane-system
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
## Conclusion and Next Steps
|
||||
|
||||
We're done!
|
||||
|
||||
|
|
@ -620,21 +509,17 @@ In this guide, we:
|
|||
* Connected our GKE cluster to our MySQL database.
|
||||
* Installed Wordpress to our GKE cluster.
|
||||
|
||||
## Next Steps
|
||||
|
||||
In this guide, we used an existing GKE cluster but actually Crossplane can
|
||||
provision a Kubernetes cluster from GCP just like it provisions a MySQL
|
||||
database.
|
||||
|
||||
We deployed Wordpress using bare `Deployment` and `Service` resources
|
||||
but there is actually a Wordpress App stack that creates these resources
|
||||
for us!
|
||||
We deployed Wordpress using bare `Deployment` and `Service` resources but there
|
||||
is actually a Wordpress App stack that creates these resources for us!
|
||||
|
||||
Check out the [stack guides](link to stack guides page)!
|
||||
Check out the [stacks guides](../stacks-guide.md)!
|
||||
|
||||
## References
|
||||
|
||||
* [gcloud CLI](https://cloud.google.com/sdk/docs/quickstarts)
|
||||
* [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
|
||||
* [Crossplane Installation Guide](../install-crossplane.md#alpha)
|
||||
* [GCP Stack Installation](../install-crossplane.md#gcp-stack)
|
||||
|
|
|
|||
Loading…
Reference in New Issue