mirror of https://github.com/crossplane/docs.git
docs snapshot for crossplane version `master`
This commit is contained in:
parent
253a8b386c
commit
c6571d5b24
|
@ -156,10 +156,10 @@ Use [stack-gcp][stack-gcp], [stack-aws][stack-aws], and [stack-azure][stack-azur
|
||||||
[services-user-guide]: services-guide.md
|
[services-user-guide]: services-guide.md
|
||||||
[stack-user-guide]: stacks-guide.md
|
[stack-user-guide]: stacks-guide.md
|
||||||
[stack-developer-guide]: developer-guide.md
|
[stack-developer-guide]: developer-guide.md
|
||||||
[stack-manager]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#terminology
|
[stacks-manager]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#terminology
|
||||||
[crossplane-cli]: https://github.com/crossplaneio/crossplane-cli
|
[crossplane-cli]: https://github.com/crossplaneio/crossplane-cli
|
||||||
[crossplane-cli-usage]: https://github.com/crossplaneio/crossplane-cli#usage
|
[crossplane-cli-usage]: https://github.com/crossplaneio/crossplane-cli#usage
|
||||||
[stack-sercurity-design]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-stacks-security-isolation.md
|
[stack-security-design]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-stacks-security-isolation.md
|
||||||
|
|
||||||
[stack-wordpress-registry]: https://hub.docker.com/r/crossplane/sample-stack-wordpress
|
[stack-wordpress-registry]: https://hub.docker.com/r/crossplane/sample-stack-wordpress
|
||||||
[stack-wordpress]: https://github.com/crossplaneio/sample-stack-wordpress
|
[stack-wordpress]: https://github.com/crossplaneio/sample-stack-wordpress
|
||||||
|
|
|
@ -1,54 +1,56 @@
|
||||||
---
|
---
|
||||||
title: "AWS Stack Setup"
|
title: "Stacks Guide: AWS Setup"
|
||||||
toc: true
|
toc: true
|
||||||
weight: 530
|
weight: 530
|
||||||
indent: true
|
indent: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# Crossplane Stacks Guide: AWS Setup
|
# Stacks Guide: AWS Setup
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
1. [Crossplane Stacks Guide: AWS Setup](#crossplane-stacks-guide-aws-setup)
|
|
||||||
1. [Table of Contents](#table-of-contents)
|
|
||||||
1. [Introduction](#introduction)
|
1. [Introduction](#introduction)
|
||||||
1. [Before you begin](#before-you-begin)
|
1. [Install the AWS stack](#install-the-aws-stack)
|
||||||
1. [Install AWS stack](#install-aws-stack)
|
|
||||||
1. [Configure the AWS account](#configure-the-aws-account)
|
1. [Configure the AWS account](#configure-the-aws-account)
|
||||||
1. [Configure Crossplane Provider for
|
1. [Configure Crossplane Provider for
|
||||||
AWS](#configure-crossplane-provider-for-aws)
|
AWS](#configure-crossplane-provider-for-aws)
|
||||||
1. [Set Up Network Configuration](#set-up-network-configuration)
|
1. [Set Up Network Configuration](#set-up-network-configuration)
|
||||||
1. [Configure Provider Resources](#configure-provider-resources)
|
1. [Configure Provider Resources](#configure-provider-resources)
|
||||||
1. [Recap](#recap)
|
1. [Recap](#recap)
|
||||||
|
1. [Next Steps](#next-steps)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
In this guide we are focusing on WordPress stack, and will show how it could be
|
In this guide, we will set up an AWS provider in Crossplane so that we
|
||||||
deployed using AWS resources. WordPress stack uses a generic Kubernetes cluster
|
can install and use the [WordPress sample
|
||||||
and a MySQL database as its resource, which are not tied to a specific provider
|
stack][sample-wordpress-stack], which depends on MySQL and Kubernetes!
|
||||||
(also known as **resource claims**). Instead, these resource claims could be
|
|
||||||
configured to use a be satisfied by a specific cloud provider.
|
|
||||||
|
|
||||||
We will walk you through installing the AWS stack, configuring an aws account,
|
Before we begin, you will need:
|
||||||
and setting up cloud-specific resources in order to create and configure a
|
|
||||||
network configuration in which these cloud resources can communicate with each
|
|
||||||
other. Once the network configuration is done, we will specify a resource class
|
|
||||||
for each resource claim type. Then we will install WordPress stack, which will
|
|
||||||
create related external resources for each claim in AWS.
|
|
||||||
|
|
||||||
## Before you begin
|
* Everything from the [Crossplane Stacks Guide][stacks-guide] before the
|
||||||
|
cloud provider setup
|
||||||
|
- A `kubectl` pointing to a Crossplane control cluster
|
||||||
|
- The [Crossplane CLI][crossplane-cli] installed
|
||||||
|
* An account on [AWS][aws]
|
||||||
|
* The [aws cli][installed]
|
||||||
|
|
||||||
Before continuing in this guide, make sure that all the following are true:
|
At the end, we will have:
|
||||||
|
|
||||||
- Crossplane is installed
|
* A Crossplane control cluster configured to use AWS
|
||||||
- [crossplane-cli] is installed
|
* The boilerplate of an AWS-based project spun up
|
||||||
- `kubectl` is configured to target the Crossplane cluster
|
* Support in the control cluster for managing MySQL and Kubernetes
|
||||||
- An aws account is available
|
cluster dependencies
|
||||||
|
* A slightly better understanding of:
|
||||||
|
- The way cloud providers are configured in Crossplane
|
||||||
|
- The way dependencies for cloud-portable workloads are configured in
|
||||||
|
Crossplane
|
||||||
|
|
||||||
## Install AWS stack
|
## Install the AWS stack
|
||||||
|
|
||||||
Once Crossplane is installed, it can be extended to support AWS by installing
|
After Crossplane has been installed, it can be extended with more
|
||||||
AWS **stack**.
|
functionality by installing a [Crossplane Stack][stack-docs]! Let's
|
||||||
|
install the [stack for Amazon Web Services][stack-aws] (AWS) to add
|
||||||
|
support for that cloud provider.
|
||||||
|
|
||||||
The namespace where we install the stack, is also the one that our managed AWS
|
The namespace where we install the stack, is also the one that our managed AWS
|
||||||
resources will reside. Let's call this namespace `infra-aws`, and go ahead and
|
resources will reside. Let's call this namespace `infra-aws`, and go ahead and
|
||||||
|
@ -61,38 +63,37 @@ INFRA_NAMESPACE=infra-aws
|
||||||
kubectl create namespace ${INFRA_NAMESPACE}
|
kubectl create namespace ${INFRA_NAMESPACE}
|
||||||
```
|
```
|
||||||
|
|
||||||
The output will look like the following:
|
Now we can install the AWS stack using Crossplane CLI. Since this is an
|
||||||
|
infrastructure stack, we need to specify that it's cluster-scoped by
|
||||||
```bash
|
passing the `--cluster` flag.
|
||||||
namespace/infra-aws created
|
|
||||||
```
|
|
||||||
|
|
||||||
Now we can create the AWS stack by using Crossplane CLI. Since this is an
|
|
||||||
infrastructure stack, we need to specify that it's cluster-scoped via
|
|
||||||
`--cluster` flag.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
kubectl crossplane stack generate-install --cluster 'crossplane/stack-aws:master' stack-aws | kubectl apply --namespace ${INFRA_NAMESPACE} -f -
|
kubectl crossplane stack generate-install --cluster 'crossplane/stack-aws:master' stack-aws | kubectl apply --namespace ${INFRA_NAMESPACE} -f -
|
||||||
```
|
```
|
||||||
|
|
||||||
The next steps assume that you installed the AWS stack into the `infra-aws`
|
The rest of the steps assume that you installed the AWS stack into the
|
||||||
namespace.
|
`infra-aws` namespace.
|
||||||
|
|
||||||
## Configure the AWS account
|
## Configure the AWS account
|
||||||
|
|
||||||
An [aws user] with `Administrative` privileges is needed to enable Crossplane to
|
An [aws user][] with `Administrative` privileges is needed to enable Crossplane to
|
||||||
create the required resources. Once the user is provisioned, an [Access Key]
|
create the required resources. Once the user is provisioned, an [Access Key][]
|
||||||
needs to be created to enable the user to have API access. Next, using these set
|
needs to be created so the user can have API access.
|
||||||
of access key credentials, one needs to have [`aws` command line tool]
|
|
||||||
[installed] and [configured]. Then, the credentials and configuration will
|
|
||||||
reside in `~/.aws/credentials` and `~/.aws/config` respectively, which will be
|
|
||||||
consumed in the next step.
|
|
||||||
|
|
||||||
When configuring aws CLI, it is recommended that the user credentials are
|
Using the set of access key credentials for the user with the right
|
||||||
configured under a specific [aws named profile] other than `default`. In this
|
access, we will to have [`aws` command line tool][] [installed][], and
|
||||||
guide we are assuming that the credentials are configured under
|
then we will need to [configure it][aws-cli-configure].
|
||||||
`crossplane-user` profile, but you can use other profiles as well. Let's store
|
|
||||||
the profile name in `aws_profile` variable to use later:
|
When the aws cli is configured, the credentials and configuration will
|
||||||
|
be in `~/.aws/credentials` and `~/.aws/config` respectively. These will
|
||||||
|
be consumed in the next step.
|
||||||
|
|
||||||
|
When configuring the aws cli, it is recommended that the user credentials are
|
||||||
|
configured under a specific [aws named profile][], and not under
|
||||||
|
`default`. In this guide, we assume that the credentials are configured
|
||||||
|
under the `crossplane-user` profile, but you can use a different profile
|
||||||
|
name if you want. Let's store the profile name in a variable so we can
|
||||||
|
use it in later steps:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
aws_profile=crossplane-user
|
aws_profile=crossplane-user
|
||||||
|
@ -100,10 +101,11 @@ aws_profile=crossplane-user
|
||||||
|
|
||||||
## Configure Crossplane Provider for AWS
|
## Configure Crossplane Provider for AWS
|
||||||
|
|
||||||
Crossplane uses the aws user credentials that was configured in the previous
|
Crossplane uses the aws user credentials that were configured in the previous
|
||||||
step, to create resources in AWS. These credentials will be stored as a
|
step to create resources in AWS. These credentials will be stored as a
|
||||||
[secret], and is managed them by an [`aws provider`] instance. In addition to
|
[secret][] in Kubernetes, and will be used by an [aws
|
||||||
the credentials, the AWS region is also read from the configuration to target a
|
provider][aws-provider-docs] instance. The AWS region is also pulled
|
||||||
|
from the cli configuration, so that the aws provider can target a
|
||||||
specific region.
|
specific region.
|
||||||
|
|
||||||
To store the credentials as a secret, run:
|
To store the credentials as a secret, run:
|
||||||
|
@ -117,7 +119,7 @@ AWS_REGION=$(awk '/["$aws_profile"]/ {getline; print $3}' ${HOME}/.aws/config)
|
||||||
```
|
```
|
||||||
|
|
||||||
At this point, the region and the encoded credentials are stored in respective
|
At this point, the region and the encoded credentials are stored in respective
|
||||||
variables. Next, we'll need to create an instance of [`aws provider`]:
|
variables. Next, we'll need to create an instance of [`aws provider`][]:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cat > provider.yaml <<EOF
|
cat > provider.yaml <<EOF
|
||||||
|
@ -158,25 +160,25 @@ provider.aws.crossplane.io/aws-provider created
|
||||||
|
|
||||||
When configured in AWS, WordPress resources map to an EKS cluster and an RDS
|
When configured in AWS, WordPress resources map to an EKS cluster and an RDS
|
||||||
database. In order to make the RDS instance accessible from the EKS cluster,
|
database. In order to make the RDS instance accessible from the EKS cluster,
|
||||||
they both need to live within the same VPC. However VPC is not the only AWS
|
they both need to live within the same VPC. However, a VPC is not the only AWS
|
||||||
resource that needs to be created to enable inter-resource connectivity. In
|
resource that needs to be created to enable inter-resource connectivity. In
|
||||||
general, a **Network Configuration**, which is built of a set of VPCs, Subnets,
|
general, a **Network Configuration**, which consists of a set of VPCs, Subnets,
|
||||||
Security Groups, Route Tables, IAM Roles and other resources, is required for
|
Security Groups, Route Tables, IAM Roles and other resources, is required for
|
||||||
this purpose. For more information, see [AWS resource connectivity] design
|
this purpose. For more information, see [AWS resource connectivity][] design
|
||||||
document.
|
document.
|
||||||
|
|
||||||
In this section we will build a simple network configuration, by creating AWS
|
In this section, we will build a simple network configuration, by creating AWS
|
||||||
resources that are managed by Crossplane. There are a couple of challenges when
|
resources that are managed by Crossplane. There are a couple of challenges when
|
||||||
creating these resources:
|
creating these resources:
|
||||||
|
|
||||||
- Some of these resources depend on other ones. For instance, a Subnet is
|
- Some of these resources depend on other ones. For instance, a Subnet
|
||||||
dependent on a VPC, so creating a Subnet needs to be done after creating the
|
depends on a VPC, so creating a Subnet needs to be done after creating
|
||||||
VPC.
|
the VPC.
|
||||||
|
|
||||||
To solve this issue, we will need to create the resoruces in order, so the
|
To solve this issue, we will need to create the resources in order, so
|
||||||
depependent resources are provisioned after creating their dependencies. Since
|
resources are provisioned after their dependencies exist. Since
|
||||||
provisioning a resource might take some time, we need to make sure the
|
provisioning a resource might take some time, we need to make sure the
|
||||||
resource is ready, before moving forward to the next step. Let's create the
|
resource is ready before moving forward to the next step. Let's create the
|
||||||
following function for this purpose:
|
following function for this purpose:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -192,23 +194,22 @@ creating these resources:
|
||||||
|
|
||||||
- Some of these resources have identifying attributes that are
|
- Some of these resources have identifying attributes that are
|
||||||
non-deterministic. In other words, they become known after the resource is
|
non-deterministic. In other words, they become known after the resource is
|
||||||
provisioined. For instance, a VPC has a ID (VPC_ID) attribute which is
|
provisioined. For instance, a VPC has an ID (VPC_ID) attribute which is
|
||||||
consumed by other resources (like a Subnet), and only becomes known after the
|
consumed by other resources (such as a Subnet), and the ID only
|
||||||
VPC is created.
|
becomes known after the VPC is created.
|
||||||
|
|
||||||
To tackle this challege, we will need to retrieve the non-deterministic
|
To tackle this challege, we will need to retrieve the non-deterministic
|
||||||
identifiers of the resources after their creation, and inject them to the
|
identifiers of the resources after their creation, and inject them to the
|
||||||
dependent resources that require those attribute.
|
consumer resources that require those attributes.
|
||||||
|
|
||||||
The rest of this section creates the resources for a configuration described in
|
The rest of this section creates the resources for a configuration described in
|
||||||
[the EKS user
|
[the EKS user guide][eks-user-guide].
|
||||||
guide](https://docs.aws.amazon.com/eks/latest/userguide/create-public-private-vpc.html).
|
For grouping all these resources together, we will use a `CONFIG_NAME` variable,
|
||||||
For grouping all these resources together we will use a `CONFIG_NAME` variable,
|
which will be prepended to the names of these resources in Crossplane,
|
||||||
which will be prepended to the names of these resources in Crossplane, and their
|
and also their corresponding external resources in AWS. Keep in mind
|
||||||
corresponding external resources in AWS. Keep in mind that if you create
|
that if you create multiple such configurations in the same Crossplane
|
||||||
multiple such configuration in the same Crossplane cluster or the same AWS
|
cluster or the same AWS account, you will need to use different config
|
||||||
account, you will need to use different config names, otherwise there will be
|
names. Otherwise, there will be naming conflicts.
|
||||||
naming conflicts.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# the name of the aws network configuration
|
# the name of the aws network configuration
|
||||||
|
@ -217,7 +218,7 @@ CONFIG_NAME=aws-network-config
|
||||||
|
|
||||||
### VPC
|
### VPC
|
||||||
|
|
||||||
A [Virtual Private Network] or VPC is a virtual network in AWS.
|
A [Virtual Private Network][] or VPC is a virtual network in AWS.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# build vpc yaml
|
# build vpc yaml
|
||||||
|
@ -249,13 +250,13 @@ vpc.network.aws.crossplane.io/aws-network-config-vpc created
|
||||||
vpc.network.aws.crossplane.io/aws-network-config-vpc condition met
|
vpc.network.aws.crossplane.io/aws-network-config-vpc condition met
|
||||||
```
|
```
|
||||||
|
|
||||||
Once the VPC is created, you can see the full object and its status by running
|
Once the VPC is created, you can see the full object and its status by running:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
kubectl get -f "vpc.yaml" -o yaml
|
kubectl get -f "vpc.yaml" -o yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
The output will look like:
|
The output will look something like:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: network.aws.crossplane.io/v1alpha2
|
apiVersion: network.aws.crossplane.io/v1alpha2
|
||||||
|
@ -296,7 +297,8 @@ status:
|
||||||
vpcState: available
|
vpcState: available
|
||||||
```
|
```
|
||||||
|
|
||||||
Now, we can retrieve the VPCID to use in subsequent resources:
|
Now that we have a VPC, we can retrieve the VPCID to use in subsequent
|
||||||
|
resources and save it to a variable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
VPC_ID=$(kubectl get -f "vpc.yaml" -o jsonpath='{.status.vpcId}')
|
VPC_ID=$(kubectl get -f "vpc.yaml" -o jsonpath='{.status.vpcId}')
|
||||||
|
@ -304,7 +306,7 @@ VPC_ID=$(kubectl get -f "vpc.yaml" -o jsonpath='{.status.vpcId}')
|
||||||
|
|
||||||
### Subnets
|
### Subnets
|
||||||
|
|
||||||
In this configuration we create three public [Subnet]s.
|
In this configuration we create three public [Subnet][]s.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# build subnet yaml
|
# build subnet yaml
|
||||||
|
@ -369,7 +371,8 @@ subnet.network.aws.crossplane.io/aws-network-config-subnet2 condition met
|
||||||
subnet.network.aws.crossplane.io/aws-network-config-subnet3 condition met
|
subnet.network.aws.crossplane.io/aws-network-config-subnet3 condition met
|
||||||
```
|
```
|
||||||
|
|
||||||
We need to retrieve the SubndtIDs for subsequent resources:
|
We need to retrieve the SubnetIDs for subsequent resources and save them
|
||||||
|
to variables:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
SUBNET1_ID=$(kubectl get -f "subnets.yaml" -o=jsonpath='{.items[0].status.subnetId}')
|
SUBNET1_ID=$(kubectl get -f "subnets.yaml" -o=jsonpath='{.items[0].status.subnetId}')
|
||||||
|
@ -379,8 +382,8 @@ SUBNET3_ID=$(kubectl get -f "subnets.yaml" -o=jsonpath='{.items[2].status.subnet
|
||||||
|
|
||||||
### Internet Gateway
|
### Internet Gateway
|
||||||
|
|
||||||
An [Internet Gateway] enables the resources in the VPC to have access to the
|
An [Internet Gateway][] allows the resources in the VPC to have access to the
|
||||||
Internet. Since the WordPress application will be addressed from the internet,
|
Internet. Since the WordPress application will be accessed from the internet,
|
||||||
this resource is required in the network configuration.
|
this resource is required in the network configuration.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -411,7 +414,7 @@ internetgateway.network.aws.crossplane.io/aws-network-config-internetgateway cre
|
||||||
internetgateway.network.aws.crossplane.io/aws-network-config-internetgateway condition met
|
internetgateway.network.aws.crossplane.io/aws-network-config-internetgateway condition met
|
||||||
```
|
```
|
||||||
|
|
||||||
To retrieve the internete gateway ID (IG_ID):
|
Retrieve the internet gateway's ID (IG_ID) and save it in a variable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
IG_ID=$(kubectl get -f "internetgateway.yaml" -o=jsonpath='{.status.internetGatewayId}')
|
IG_ID=$(kubectl get -f "internetgateway.yaml" -o=jsonpath='{.status.internetGatewayId}')
|
||||||
|
@ -419,9 +422,9 @@ IG_ID=$(kubectl get -f "internetgateway.yaml" -o=jsonpath='{.status.internetGate
|
||||||
|
|
||||||
### Route Table
|
### Route Table
|
||||||
|
|
||||||
A [Route Table] sets rules to direct traffic in a virtual network. We use a
|
A [Route Table][] specifies rules to direct traffic in a virtual network. We use a
|
||||||
Route Table to redirect internet traffic from all Subnets to the Internet
|
Route Table to redirect internet traffic from all Subnets to the Internet
|
||||||
Gateway instance that we created in previous step.
|
Gateway instance that we created in the previous step.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# build route table yaml
|
# build route table yaml
|
||||||
|
@ -460,8 +463,8 @@ routetable.network.aws.crossplane.io/aws-network-config-routetable condition met
|
||||||
|
|
||||||
### Cluster Security Group
|
### Cluster Security Group
|
||||||
|
|
||||||
A [Security Group] is created to later to be assigned to the EKS cluster. This
|
A [Security Group][] is created so that later we can assign it to the EKS cluster. This
|
||||||
security group enables the cluster to communicate with the worker nodes
|
security group allows the cluster to communicate with the worker nodes.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# build the cluster security group yaml
|
# build the cluster security group yaml
|
||||||
|
@ -493,7 +496,8 @@ securitygroup.network.aws.crossplane.io/aws-network-config-cluster-sg created
|
||||||
securitygroup.network.aws.crossplane.io/aws-network-config-cluster-sg condition met
|
securitygroup.network.aws.crossplane.io/aws-network-config-cluster-sg condition met
|
||||||
```
|
```
|
||||||
|
|
||||||
Retrieve the SecurityGroupID for cluster security group:
|
Retrieve the SecurityGroupID for cluster security group and save it to a
|
||||||
|
variable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
CLUSTER_SECURITY_GROUP_ID=$(kubectl get -f "cluster_sg.yaml" -o=jsonpath='{.status.securityGroupID}')
|
CLUSTER_SECURITY_GROUP_ID=$(kubectl get -f "cluster_sg.yaml" -o=jsonpath='{.status.securityGroupID}')
|
||||||
|
@ -501,9 +505,9 @@ CLUSTER_SECURITY_GROUP_ID=$(kubectl get -f "cluster_sg.yaml" -o=jsonpath='{.stat
|
||||||
|
|
||||||
### Database Security Group
|
### Database Security Group
|
||||||
|
|
||||||
A [Security Group] is created to later to be assigned to the RDS database
|
A [Security Group][] is created so that later we can assign it to the RDS database
|
||||||
instance. This security group enables the database instance to accept traffic
|
instance. This security group allows the database instance to accept traffic
|
||||||
from the internet in a certain port.
|
from the internet on a certain port.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# build the rds security group yaml
|
# build the rds security group yaml
|
||||||
|
@ -542,7 +546,8 @@ securitygroup.network.aws.crossplane.io/aws-network-config-rds-sg created
|
||||||
securitygroup.network.aws.crossplane.io/aws-network-config-rds-sg condition met
|
securitygroup.network.aws.crossplane.io/aws-network-config-rds-sg condition met
|
||||||
```
|
```
|
||||||
|
|
||||||
Retrieve the SecurityGroupID for rds security group:
|
Retrieve the SecurityGroupID for rds security group and store it in a
|
||||||
|
variable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
RDS_SECURITY_GROUP_ID=$(kubectl get -f "rds_sg.yaml" -o=jsonpath='{.status.securityGroupID}')
|
RDS_SECURITY_GROUP_ID=$(kubectl get -f "rds_sg.yaml" -o=jsonpath='{.status.securityGroupID}')
|
||||||
|
@ -550,7 +555,7 @@ RDS_SECURITY_GROUP_ID=$(kubectl get -f "rds_sg.yaml" -o=jsonpath='{.status.secur
|
||||||
|
|
||||||
### Database Subnet Group
|
### Database Subnet Group
|
||||||
|
|
||||||
A [Database Subnet Group] creates a group of Subnets which can communicate with
|
A [Database Subnet Group][] creates a group of Subnets which can communicate with
|
||||||
an RDS database instance.
|
an RDS database instance.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -589,7 +594,7 @@ dbsubnetgroup.storage.aws.crossplane.io/aws-network-config-dbsubnetgroup created
|
||||||
dbsubnetgroup.storage.aws.crossplane.io/aws-network-config-dbsubnetgroup condition met
|
dbsubnetgroup.storage.aws.crossplane.io/aws-network-config-dbsubnetgroup condition met
|
||||||
```
|
```
|
||||||
|
|
||||||
We need to retrieve the SubndtIDs for subsequent resources:
|
We need to retrieve the SubnetIDs so other resources can use them:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
RDS_SUBNET_GROUP_NAME=$(kubectl get -f "dbsubnetgroup.yaml" -o=jsonpath='{.spec.groupName}')
|
RDS_SUBNET_GROUP_NAME=$(kubectl get -f "dbsubnetgroup.yaml" -o=jsonpath='{.spec.groupName}')
|
||||||
|
@ -597,9 +602,9 @@ RDS_SUBNET_GROUP_NAME=$(kubectl get -f "dbsubnetgroup.yaml" -o=jsonpath='{.spec.
|
||||||
|
|
||||||
### Cluster IAM Role
|
### Cluster IAM Role
|
||||||
|
|
||||||
An [IAM Role] gives permissions to the principal that assumes that role. We
|
An [IAM Role][] gives permissions to the principal which assumes that role. We
|
||||||
Create a role to be assumed by the cluster, which later is granted the required
|
create a role to be assumed by the cluster, which later is granted the
|
||||||
permissions to talk to required resources in AWS.
|
permissions needed to talk to our resources in AWS.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# build vpc yaml
|
# build vpc yaml
|
||||||
|
@ -643,7 +648,7 @@ iamrole.identity.aws.crossplane.io/aws-network-config-eks-cluster-role created
|
||||||
iamrole.identity.aws.crossplane.io/aws-network-config-eks-cluster-role condition met
|
iamrole.identity.aws.crossplane.io/aws-network-config-eks-cluster-role condition met
|
||||||
```
|
```
|
||||||
|
|
||||||
To retrieve the IAM Role Arn:
|
Retrieve the IAM Role Arn and store it in a variable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
EKS_ROLE_ARN=$(kubectl get -f "iamrole.yaml" -o=jsonpath='{.status.arn}')
|
EKS_ROLE_ARN=$(kubectl get -f "iamrole.yaml" -o=jsonpath='{.status.arn}')
|
||||||
|
@ -651,7 +656,7 @@ EKS_ROLE_ARN=$(kubectl get -f "iamrole.yaml" -o=jsonpath='{.status.arn}')
|
||||||
|
|
||||||
### Cluster IAM Role Policies
|
### Cluster IAM Role Policies
|
||||||
|
|
||||||
An [IAM Role Policy] grants a role a certain permission. We add two policies to
|
An [IAM Role Policy][] grants a role a certain permission. We add two policies to
|
||||||
the Cluster IAM Role that we created above. These policies are needed for the
|
the Cluster IAM Role that we created above. These policies are needed for the
|
||||||
cluster to communicate with other aws resources.
|
cluster to communicate with other aws resources.
|
||||||
|
|
||||||
|
@ -704,9 +709,10 @@ iamrolepolicyattachment.identity.aws.crossplane.io/aws-network-config-role-clust
|
||||||
|
|
||||||
Once we have the network configuration set up, we also need to tell Crossplane
|
Once we have the network configuration set up, we also need to tell Crossplane
|
||||||
how to satisfy WordPress's claims for a database and a Kubernetes cluster, using
|
how to satisfy WordPress's claims for a database and a Kubernetes cluster, using
|
||||||
AWS resources. The following resource classes allow the EKSCluster and
|
AWS resources. [Resource classes][resource-classes-docs] serve as
|
||||||
RDSInstance claims to be satisfied, using the network configuration we created
|
templates for the new claims we make. The following resource classes
|
||||||
in the previous step:
|
allow the claims for the database and Kubernetes cluster to be satisfied
|
||||||
|
with the network configuration we just set up:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# build resource classes yaml, by using the configured network resources
|
# build resource classes yaml, by using the configured network resources
|
||||||
|
@ -761,11 +767,13 @@ EOF
|
||||||
kubectl apply -f "resource_classes.yaml"
|
kubectl apply -f "resource_classes.yaml"
|
||||||
```
|
```
|
||||||
|
|
||||||
So far we have been creating resources in `INFRA_NAMESPACE`, where all resources
|
So far we have been creating resources in `$INFRA_NAMESPACE`, where a
|
||||||
are to configure AWS stack with the AWS account, create a network configuration,
|
bunch of resources live: the ones to configure the AWS stack with the
|
||||||
and define resources classes that will satisfied the claims. Now, we will create
|
AWS account; to create a network configuration; and to define resources
|
||||||
an app namespace and populate it with resources that are used to let Crossplane
|
classes that will satisfy our claims. Now, we will create an app
|
||||||
know how to satisfy the claims. Let's call this namespace `app-project1-dev`
|
namespace and populate it with resources that are used to let Crossplane
|
||||||
|
know how to satisfy the claims. Let's call this namespace
|
||||||
|
`app-project1-dev`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# the namespace that the app resources will be created
|
# the namespace that the app resources will be created
|
||||||
|
@ -776,8 +784,8 @@ kubectl create namespace ${APP_NAMESPACE}
|
||||||
|
|
||||||
Now that we have a namespace, we need to tell Crossplane which resource classes
|
Now that we have a namespace, we need to tell Crossplane which resource classes
|
||||||
should be used to satisfy our claims in that namespace. We will create [portable
|
should be used to satisfy our claims in that namespace. We will create [portable
|
||||||
classes][portable-classes-docs] that have have references to the cloud-specific
|
classes][portable-classes-docs] that have references to the
|
||||||
classes that we created earlier.
|
cloud-specific classes that we created earlier.
|
||||||
|
|
||||||
For example, `MySQLInstanceClass` is a portable class. It may refer to AWS's
|
For example, `MySQLInstanceClass` is a portable class. It may refer to AWS's
|
||||||
`RDSInstanceClass`, which is a non-portable class.
|
`RDSInstanceClass`, which is a non-portable class.
|
||||||
|
@ -824,12 +832,12 @@ on resource claims][resource-claims-docs].
|
||||||
|
|
||||||
To recap what we've set up now in our environment:
|
To recap what we've set up now in our environment:
|
||||||
|
|
||||||
- Our provider account, both on the provider side and on the Crossplane side.
|
* Our provider account, both on the provider side and on the Crossplane side.
|
||||||
- A Network Configuration for all instances to share.
|
* A Network Configuration for all instances to share.
|
||||||
- An EKSClusterClass and an RDSInstanceClass with the right configuration to use
|
* An EKSClusterClass and an RDSInstanceClass with the right configuration to use
|
||||||
the mentioned networking setup.
|
the mentioned networking setup.
|
||||||
- A namespace for our app resources to reside with default MySQLInstanceClass
|
* A namespace for our app resources, with a default MySQLInstanceClass and
|
||||||
and KubernetesClusterClass that refer to our EKSClusterClass and
|
a default KubernetesClusterClass that refer to our EKSClusterClass and
|
||||||
RDSInstanceClass.
|
RDSInstanceClass.
|
||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
@ -838,17 +846,32 @@ Next we'll set up a Crossplane App Stack and use it! Head [back over to the
|
||||||
Stacks Guide document][stacks-guide-continue] so we can pick up where we left
|
Stacks Guide document][stacks-guide-continue] so we can pick up where we left
|
||||||
off.
|
off.
|
||||||
|
|
||||||
|
<!-- Links -->
|
||||||
|
[stacks-guide]: stacks-guide.md
|
||||||
|
|
||||||
|
[aws]: https://aws.amazon.com
|
||||||
|
[stack-aws]: https://github.com/crossplaneio/stack-aws
|
||||||
|
[sample-wordpress-stack]: https://github.com/crossplaneio/sample-stack-wordpress
|
||||||
|
|
||||||
|
[stack-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#crossplane-stacks
|
||||||
|
|
||||||
[aws user]: https://docs.aws.amazon.com/mediapackage/latest/ug/setting-up-create-iam-user.html
|
[aws user]: https://docs.aws.amazon.com/mediapackage/latest/ug/setting-up-create-iam-user.html
|
||||||
[Access Key]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html
|
[Access Key]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html
|
||||||
|
|
||||||
[`aws provider`]: https://github.com/crossplaneio/stack-aws/blob/master/aws/apis/v1alpha2/types.go#L43
|
[`aws provider`]: https://github.com/crossplaneio/stack-aws/blob/master/aws/apis/v1alpha2/types.go#L43
|
||||||
|
[aws-provider-docs]: https://github.com/crossplaneio/stack-aws/blob/master/aws/apis/v1alpha2/types.go#L43
|
||||||
|
|
||||||
[`aws` command line tool]: https://aws.amazon.com/cli/
|
[`aws` command line tool]: https://aws.amazon.com/cli/
|
||||||
[AWS SDK for GO]: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/setting-up.html
|
[AWS SDK for GO]: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/setting-up.html
|
||||||
|
|
||||||
[installed]: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html
|
[installed]: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html
|
||||||
[configured]: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html
|
[aws-cli-configure]: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html
|
||||||
[AWS security credentials]: https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html
|
[AWS security credentials]: https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html
|
||||||
[secret]: https://kubernetes.io/docs/concepts/configuration/secret/
|
[secret]: https://kubernetes.io/docs/concepts/configuration/secret/
|
||||||
[aws named profile]: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html
|
[aws named profile]: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html
|
||||||
|
|
||||||
[crossplane-cli]: https://github.com/crossplaneio/crossplane-cli
|
[crossplane-cli]: https://github.com/crossplaneio/crossplane-cli
|
||||||
|
|
||||||
[Virtual Private Network]: https://aws.amazon.com/vpc/
|
[Virtual Private Network]: https://aws.amazon.com/vpc/
|
||||||
[Subnet]: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html#vpc-subnet-basics
|
[Subnet]: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html#vpc-subnet-basics
|
||||||
[AWS resource connectivity]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-resource-connectivity-mvp.md#amazon-web-services
|
[AWS resource connectivity]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-resource-connectivity-mvp.md#amazon-web-services
|
||||||
|
@ -858,6 +881,10 @@ off.
|
||||||
[Database Subnet Group]: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.WorkingWithRDSInstanceinaVPC.html
|
[Database Subnet Group]: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.WorkingWithRDSInstanceinaVPC.html
|
||||||
[IAM Role]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html
|
[IAM Role]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html
|
||||||
[IAM Role Policy]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html
|
[IAM Role Policy]: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html
|
||||||
|
|
||||||
[portable-classes-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-default-resource-class.md
|
[portable-classes-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-default-resource-class.md
|
||||||
[stacks-guide-continue]: stacks-guide.html#install-support-for-our-application-into-crossplane
|
[resource-classes-docs]: concepts.md#resource-claims-and-resource-classes
|
||||||
|
|
||||||
|
[stacks-guide-continue]: stacks-guide.md#install-support-for-our-application-into-crossplane
|
||||||
[resource-claims-docs]: concepts.md#resource-claims-and-resource-classes
|
[resource-claims-docs]: concepts.md#resource-claims-and-resource-classes
|
||||||
|
[eks-user-guide]: https://docs.aws.amazon.com/eks/latest/userguide/create-public-private-vpc.html
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
---
|
---
|
||||||
title: "Azure Stack Setup"
|
title: "Stacks Guide: Azure Setup"
|
||||||
toc: true
|
toc: true
|
||||||
weight: 540
|
weight: 540
|
||||||
indent: true
|
indent: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# Crossplane Stacks Guide: Azure Setup
|
# Stacks Guide: Azure Setup
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@ indent: true
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
In this guide, we will set up an Azure provider in Crossplane so that we can
|
In this guide, we will set up an Azure provider in Crossplane so that we
|
||||||
install and use the WordPress sample stack, which depends on MySQL and
|
can install and use the [WordPress sample
|
||||||
Kubernetes!
|
stack][sample-wordpress-stack], which depends on MySQL and Kubernetes!
|
||||||
|
|
||||||
Before you begin, you will need:
|
Before you begin, you will need:
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ Before you begin, you will need:
|
||||||
- A `kubectl` pointing to a Crossplane control cluster
|
- A `kubectl` pointing to a Crossplane control cluster
|
||||||
- The [Crossplane CLI][crossplane-cli] installed
|
- The [Crossplane CLI][crossplane-cli] installed
|
||||||
* An account on [Azure][azure]
|
* An account on [Azure][azure]
|
||||||
|
* The [jq][jq] tool for interacting with some JSON, or equivalent
|
||||||
|
|
||||||
At the end, we will have:
|
At the end, we will have:
|
||||||
|
|
||||||
|
@ -48,24 +49,27 @@ document][crossplane-concepts] for that.
|
||||||
|
|
||||||
## Install the Azure Stack
|
## Install the Azure Stack
|
||||||
|
|
||||||
After Crossplane has been installed, it can be extended with more functionality
|
After Crossplane has been installed, it can be extended with more
|
||||||
by installing a Crossplane Stack! Let's install the stack for Microsoft Azure to
|
functionality by installing a [Crossplane Stack][stack-docs]! Let's
|
||||||
add support for that cloud provider. We can use the Crossplane CLI for this
|
install the [stack for Microsoft Azure][stack-azure] to add
|
||||||
operation:
|
support for that cloud provider. We can use the [Crossplane
|
||||||
|
CLI][crossplane-cli] for this operation. Since this is an infrastructure
|
||||||
|
stack, we need to specify that it's cluster-scoped by passing the
|
||||||
|
`--cluster` flag.
|
||||||
|
|
||||||
```
|
To install to a specific namespace, we can use the `generate-install`
|
||||||
kubectl crossplane stack install 'crossplane/stack-azure:master' stack-azure
|
command and pipe it to `kubectl apply` instead, which gives us more
|
||||||
```
|
control over how the stack's installation is handled. Everything is
|
||||||
To install to a particular namespace, you can use the `generate-install` command
|
a Kubernetes object!
|
||||||
and pipe it to `kubectl apply` instead, which gives you more control over how
|
|
||||||
the stack's installation is handled. Everything is Kubernetes object!
|
|
||||||
|
|
||||||
Since this is an infrastructure stack, we need to specify that it's
|
|
||||||
cluster-scoped via `--cluster` flag.
|
|
||||||
```
|
```
|
||||||
kubectl crossplane stack generate-install --cluster 'crossplane/stack-azure:master' stack-azure | kubectl apply --namespace crossplane-system -f -
|
kubectl crossplane stack generate-install --cluster 'crossplane/stack-azure:master' stack-azure | kubectl apply --namespace crossplane-system -f -
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If we wanted to use whatever the current namespace is, we could have
|
||||||
|
used `kubectl crossplane stack install` instead of using
|
||||||
|
`generate-install`.
|
||||||
|
|
||||||
We have installed the Azure stack into the `crossplane-system` namespace, but we
|
We have installed the Azure stack into the `crossplane-system` namespace, but we
|
||||||
want to group our Azure-specific resources in their own environment namespaces.
|
want to group our Azure-specific resources in their own environment namespaces.
|
||||||
For the purpose of this guide, we will create all Azure-specific resources in
|
For the purpose of this guide, we will create all Azure-specific resources in
|
||||||
|
@ -89,8 +93,8 @@ We will make use of the following services on Azure:
|
||||||
* Subnetwork
|
* Subnetwork
|
||||||
* Virtual Network Rule
|
* Virtual Network Rule
|
||||||
|
|
||||||
In order to utilize each of these services, you will need to follow the Adding
|
In order to utilize each of these services, you will need to follow the [Adding
|
||||||
Microsoft Azure to Crossplane [guide][provider-azure-guide] to obtain
|
Microsoft Azure to Crossplane guide][provider-azure-guide] to obtain
|
||||||
appropriate credentials in a JSON file referred to as
|
appropriate credentials in a JSON file referred to as
|
||||||
`crossplane-azure-provider-key.json`.
|
`crossplane-azure-provider-key.json`.
|
||||||
|
|
||||||
|
@ -144,7 +148,8 @@ other Crossplane resources.
|
||||||
|
|
||||||
We also will need to use our Azure subscription id to provision some of the
|
We also will need to use our Azure subscription id to provision some of the
|
||||||
resources we will need. You can set an environment variable so that you will
|
resources we will need. You can set an environment variable so that you will
|
||||||
have access when creating resources that require it:
|
have access when creating resources that require it. If you have a JSON
|
||||||
|
tool like [jq][jq], you can use:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export SUBSCRIPTION_ID=$(cat crossplane-azure-provider-key.json | jq -j '.subscriptionId')
|
export SUBSCRIPTION_ID=$(cat crossplane-azure-provider-key.json | jq -j '.subscriptionId')
|
||||||
|
@ -152,11 +157,12 @@ export SUBSCRIPTION_ID=$(cat crossplane-azure-provider-key.json | jq -j '.subscr
|
||||||
|
|
||||||
## Set Up Network Resources
|
## Set Up Network Resources
|
||||||
|
|
||||||
Wordpress needs a SQL database and a Kubernetes cluster. But *those* two
|
Wordpress needs a SQL database and a Kubernetes cluster. But **those** two
|
||||||
resources need a private network to communicate securely. They must also be
|
resources need a private network to communicate securely. They must also be
|
||||||
deployed into a Resource Group, a service that Azure uses to logically group
|
deployed into a [Resource Group][azure-resource-group-docs], a service
|
||||||
resources together. So, we need to set up these resources before we get to the
|
that Azure uses to logically group resources together. So, we need to
|
||||||
database and Kubernetes creation steps. Here's an example network setup:
|
set up these resources before we get to the database and Kubernetes
|
||||||
|
creation steps. Here's an example network setup:
|
||||||
|
|
||||||
```
|
```
|
||||||
cat > network.yaml <<EOF
|
cat > network.yaml <<EOF
|
||||||
|
@ -220,8 +226,8 @@ kubectl apply -f network.yaml
|
||||||
For more details about networking and what happens when you run this command,
|
For more details about networking and what happens when you run this command,
|
||||||
see [this document with more details][crossplane-azure-networking-docs].
|
see [this document with more details][crossplane-azure-networking-docs].
|
||||||
|
|
||||||
It should not take too long for these resources to provision. You can monitor
|
It should not take too long for these resources to provision. You can
|
||||||
their status with the following command:
|
check their statuses with the following command:
|
||||||
|
|
||||||
```
|
```
|
||||||
kubectl describe -f network.yaml
|
kubectl describe -f network.yaml
|
||||||
|
@ -289,21 +295,22 @@ EOF
|
||||||
kubectl apply -f environment.yaml
|
kubectl apply -f environment.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
The steps that we have taken so far have been related to things that can be
|
The steps that we have taken so far have been related to things that can
|
||||||
shared by all resources in all namespaces of that Crossplane cluster. Now, we
|
be shared by all resources in all namespaces of the Crossplane control
|
||||||
will keep going with an app namespace which we will populate with resources that
|
cluster. Now, we will use a namespace specific to our application, and
|
||||||
will help Crossplane know with what configuration it should satisfy the claims.
|
we'll populate it with resources that will help Crossplane know what
|
||||||
You can use any namespace for your app's resources but for this tutorial we'll
|
configuration to use to satisfy our application's resource claims.
|
||||||
use the `app-project1-dev` namespace we created.
|
You can use any namespace for your app's resources, but for this
|
||||||
|
tutorial we'll use the `app-project1-dev` namespace we created.
|
||||||
|
|
||||||
Now we need to tell Crossplane which resource classes should be used to satisfy
|
Now we need to tell Crossplane which resource classes should be used to satisfy
|
||||||
our claims in that app namespace. We will create portable classes that have have
|
our claims in that app namespace. We will create portable classes that have have
|
||||||
reference to non-portable ones that we created earlier. In our claims, we can
|
reference to non-portable ones that we created earlier. In our claims, we can
|
||||||
refer to those portable classes directly or label one as the default portable
|
refer to those portable classes directly, or label one as the default portable
|
||||||
class to be used in claims that do not have class reference.
|
class to be used in claims that do not have class reference.
|
||||||
|
|
||||||
For example, MySQLInstanceClass is a portable class that can refer to Azure's
|
For example, `MySQLInstanceClass` is a portable class that can refer to Azure's
|
||||||
SQLServerClass, which is a cloud-specific class.
|
`SQLServerClass`, which is a cloud-specific class.
|
||||||
|
|
||||||
```
|
```
|
||||||
cat > namespace.yaml <<EOF
|
cat > namespace.yaml <<EOF
|
||||||
|
@ -381,8 +388,9 @@ while kubectl -n azure-infra-dev get mysqlservers -o yaml | grep -q 'items: \[\
|
||||||
echo -n "." >&2
|
echo -n "." >&2
|
||||||
sleep 5
|
sleep 5
|
||||||
done
|
done
|
||||||
|
echo "done" >&2
|
||||||
|
|
||||||
export MYSQL_NAME=$(kubectl -n azure-infra-dev get mysqlservers -o json | jq -j '.items[0].metadata.name')
|
export MYSQL_NAME=$(kubectl -n azure-infra-dev get mysqlservers -o=jsonpath='{.items[0].metadata.name}')
|
||||||
|
|
||||||
sed "s/MYSQL_NAME/$MYSQL_NAME/g" vnet-rule.yaml | kubectl apply -f -
|
sed "s/MYSQL_NAME/$MYSQL_NAME/g" vnet-rule.yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
@ -391,6 +399,9 @@ EOF
|
||||||
chmod +x vnetwatch.sh && ./vnetwatch.sh
|
chmod +x vnetwatch.sh && ./vnetwatch.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The script should be left running in the background while we go through
|
||||||
|
the rest of the guide and install the Wordpress stack.
|
||||||
|
|
||||||
## Recap
|
## Recap
|
||||||
|
|
||||||
To recap what we've set up now in our environment:
|
To recap what we've set up now in our environment:
|
||||||
|
@ -415,15 +426,22 @@ Stacks Guide document][stacks-guide-continue] so we can pick up where we left
|
||||||
off.
|
off.
|
||||||
|
|
||||||
<!-- Links -->
|
<!-- Links -->
|
||||||
[crossplane-cli]: https://github.com/crossplaneio/crossplane-cli
|
[sample-wordpress-stack]: https://github.com/crossplaneio/sample-stack-wordpress
|
||||||
[crossplane-azure-networking-docs]: TODO
|
|
||||||
[stacks-guide]: stacks-guide.html
|
[crossplane-cli]: https://github.com/crossplaneio/crossplane-cli/tree/release-0.1
|
||||||
|
[crossplane-azure-networking-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-resource-connectivity-mvp.md#microsoft-azure
|
||||||
|
[stacks-guide]: stacks-guide.md
|
||||||
[provider-azure-guide]: cloud-providers/azure/azure-provider.md
|
[provider-azure-guide]: cloud-providers/azure/azure-provider.md
|
||||||
|
|
||||||
[crossplane-concepts]: TODO
|
[stack-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#crossplane-stacks
|
||||||
[portable-claims]: TODO
|
[stack-azure]: https://github.com/crossplaneio/stack-azure
|
||||||
|
|
||||||
|
[crossplane-concepts]: concepts.md
|
||||||
|
[portable-classes-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-default-resource-class.md
|
||||||
|
|
||||||
[azure]: https://azure.microsoft.com
|
[azure]: https://azure.microsoft.com
|
||||||
[azure-vnet-rule]: https://docs.microsoft.com/en-us/azure/mysql/concepts-data-access-and-security-vnet
|
[azure-vnet-rule]: https://docs.microsoft.com/en-us/azure/mysql/concepts-data-access-and-security-vnet
|
||||||
|
[azure-resource-group-docs]: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-overview
|
||||||
|
|
||||||
[stacks-guide-continue]: stacks-guide.html#install-support-for-our-application-into-crossplane
|
[stacks-guide-continue]: stacks-guide.md#install-support-for-our-application-into-crossplane
|
||||||
|
[jq]: https://stedolan.github.io/jq/
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
---
|
---
|
||||||
title: "GCP Stack Setup"
|
title: "Stacks Guide: GCP Setup"
|
||||||
toc: true
|
toc: true
|
||||||
weight: 520
|
weight: 520
|
||||||
indent: true
|
indent: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# Crossplane Stacks Guide: GCP Setup
|
# Stacks Guide: GCP Setup
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
|
@ -56,7 +56,6 @@ CLI][crossplane-cli] for this operation. Since this is an infrastructure
|
||||||
stack, we need to specify that it's cluster-scoped by passing the
|
stack, we need to specify that it's cluster-scoped by passing the
|
||||||
`--cluster` flag.
|
`--cluster` flag.
|
||||||
|
|
||||||
|
|
||||||
To install to a specific namespace, we can use the `generate-install`
|
To install to a specific namespace, we can use the `generate-install`
|
||||||
command and pipe it to `kubectl apply` instead, which gives us more
|
command and pipe it to `kubectl apply` instead, which gives us more
|
||||||
control over how the stack's installation is handled. Everything is
|
control over how the stack's installation is handled. Everything is
|
||||||
|
@ -83,6 +82,22 @@ resource claims][resource-claims-docs].
|
||||||
For convenience, the next steps assume that you installed GCP stack into
|
For convenience, the next steps assume that you installed GCP stack into
|
||||||
the `gcp` namespace.
|
the `gcp` namespace.
|
||||||
|
|
||||||
|
### Validate the installation
|
||||||
|
|
||||||
|
To check to see whether our stack installed correctly, we can look at
|
||||||
|
the status of our stack:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl -n gcp get stack
|
||||||
|
```
|
||||||
|
|
||||||
|
It should look something like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
NAME READY VERSION AGE
|
||||||
|
stack-gcp True 0.0.1 5m19s
|
||||||
|
```
|
||||||
|
|
||||||
## Configure GCP Account
|
## Configure GCP Account
|
||||||
|
|
||||||
We will make use of the following services on GCP:
|
We will make use of the following services on GCP:
|
||||||
|
@ -111,14 +126,15 @@ assigned][gcp-assign-roles]:
|
||||||
* Kubernetes Engine Admin
|
* Kubernetes Engine Admin
|
||||||
* Service Account User
|
* Service Account User
|
||||||
|
|
||||||
You need to get JSON file of the service account you’ll use. In the next
|
### Set up cloud provider credentials
|
||||||
sections, this file will be referred to as
|
|
||||||
`crossplane-gcp-provider-key.json`
|
|
||||||
|
|
||||||
You can create the JSON file by using the [gcloud
|
This guide assumes that you have created a JSON file which contains the
|
||||||
command][gcp-create-keys] and specifying a file name of
|
credentials for the cloud provider. In later sections, this file will be
|
||||||
`crossplane-gcp-provider-key.json`. If you use Crossplane's [GCP
|
referred to as `crossplane-gcp-provider-key.json`. There are quite a few
|
||||||
credentials script][gcp-credentials], this is taken care of for you.
|
steps involved, so the steps are in [a different document which you
|
||||||
|
should take a look at][cloud-provider-setup-gcp] before moving to the
|
||||||
|
next section. Or, there is also [a script in the Crossplane
|
||||||
|
repo][gcp-credentials] which helps with creating the file.
|
||||||
|
|
||||||
## Configure Crossplane GCP Provider
|
## Configure Crossplane GCP Provider
|
||||||
|
|
||||||
|
@ -177,6 +193,21 @@ The name of the `Provider` resource in the file above is `gcp-provider`;
|
||||||
we'll use the name `gcp-provider` to refer to this provider when we
|
we'll use the name `gcp-provider` to refer to this provider when we
|
||||||
configure and set up other Crossplane resources.
|
configure and set up other Crossplane resources.
|
||||||
|
|
||||||
|
### Validate
|
||||||
|
|
||||||
|
To check on our newly created provider, we can run:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl -n gcp get provider.gcp.crossplane.io
|
||||||
|
```
|
||||||
|
|
||||||
|
The output should look something like:
|
||||||
|
|
||||||
|
```
|
||||||
|
NAME PROJECT-ID AGE
|
||||||
|
gcp-provider crossplane-playground 37s
|
||||||
|
```
|
||||||
|
|
||||||
## Set Up Network Resources
|
## Set Up Network Resources
|
||||||
|
|
||||||
Wordpress needs a SQL database and a Kubernetes cluster. But **those**
|
Wordpress needs a SQL database and a Kubernetes cluster. But **those**
|
||||||
|
@ -278,6 +309,17 @@ assumes the GCP stack is installed in `gcp` namespace:
|
||||||
kubectl -n gcp get connection.servicenetworking.gcp.crossplane.io/example-connection -o custom-columns='NAME:.metadata.name,FIRST_CONDITION:.status.conditions[0].status,SECOND_CONDITION:.status.conditions[1].status'
|
kubectl -n gcp get connection.servicenetworking.gcp.crossplane.io/example-connection -o custom-columns='NAME:.metadata.name,FIRST_CONDITION:.status.conditions[0].status,SECOND_CONDITION:.status.conditions[1].status'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The output should look something like:
|
||||||
|
|
||||||
|
```
|
||||||
|
NAME FIRST_CONDITION SECOND_CONDITION
|
||||||
|
example-connection True True
|
||||||
|
```
|
||||||
|
|
||||||
|
The conditions we're checking for are `Ready` and `Synced`. The reason
|
||||||
|
we are using `FIRST_CONDITION` and `SECOND_CONDITION` is because we
|
||||||
|
don't know what order they'll be in when we run the command.
|
||||||
|
|
||||||
## Configure Provider Resources
|
## Configure Provider Resources
|
||||||
|
|
||||||
Once we have the network set up, we also need to tell Crossplane how to
|
Once we have the network set up, we also need to tell Crossplane how to
|
||||||
|
@ -331,9 +373,13 @@ EOF
|
||||||
|
|
||||||
kubectl apply -f environment.yaml
|
kubectl apply -f environment.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
The example YAML also exists in [the Crossplane
|
The example YAML also exists in [the Crossplane
|
||||||
repository][crossplane-sample-gcp-environment].
|
repository][crossplane-sample-gcp-environment].
|
||||||
|
|
||||||
|
We don't need to validate that these are ready, because they don't
|
||||||
|
require any reconciliation.
|
||||||
|
|
||||||
The steps that we have taken so far have been related to things that can
|
The steps that we have taken so far have been related to things that can
|
||||||
be shared by all resources in all namespaces of the Crossplane control
|
be shared by all resources in all namespaces of the Crossplane control
|
||||||
cluster. Now, we will use a namespace specific to our application, and
|
cluster. Now, we will use a namespace specific to our application, and
|
||||||
|
@ -397,6 +443,9 @@ kubectl apply -f namespace.yaml
|
||||||
The example YAML also exists in [the Crossplane
|
The example YAML also exists in [the Crossplane
|
||||||
repository][crossplane-sample-gcp-namespace].
|
repository][crossplane-sample-gcp-namespace].
|
||||||
|
|
||||||
|
We don't need to validate that these are ready, because they don't need
|
||||||
|
to reconcile for them to be ready.
|
||||||
|
|
||||||
## Recap
|
## Recap
|
||||||
|
|
||||||
To recap what we've set up now in our environment:
|
To recap what we've set up now in our environment:
|
||||||
|
@ -421,7 +470,7 @@ the Stacks Guide document][stacks-guide-continue] so we can pick up
|
||||||
where we left off.
|
where we left off.
|
||||||
|
|
||||||
<!-- Links -->
|
<!-- Links -->
|
||||||
[crossplane-cli]: https://github.com/crossplaneio/crossplane-cli
|
[crossplane-cli]: https://github.com/crossplaneio/crossplane-cli/tree/release-0.1
|
||||||
[crossplane-gcp-networking-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-resource-connectivity-mvp.md#google-cloud-platform
|
[crossplane-gcp-networking-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-resource-connectivity-mvp.md#google-cloud-platform
|
||||||
[stacks-guide]: stacks-guide.md
|
[stacks-guide]: stacks-guide.md
|
||||||
|
|
||||||
|
@ -448,3 +497,5 @@ where we left off.
|
||||||
[crossplane-sample-gcp-network]: https://github.com/crossplaneio/crossplane/blob/master/cluster/examples/workloads/kubernetes/wordpress/gcp/network.yaml
|
[crossplane-sample-gcp-network]: https://github.com/crossplaneio/crossplane/blob/master/cluster/examples/workloads/kubernetes/wordpress/gcp/network.yaml
|
||||||
[crossplane-sample-gcp-environment]: https://github.com/crossplaneio/crossplane/blob/master/cluster/examples/workloads/kubernetes/wordpress/gcp/environment.yaml
|
[crossplane-sample-gcp-environment]: https://github.com/crossplaneio/crossplane/blob/master/cluster/examples/workloads/kubernetes/wordpress/gcp/environment.yaml
|
||||||
[crossplane-sample-gcp-namespace]: https://github.com/crossplaneio/crossplane/blob/master/cluster/examples/workloads/kubernetes/wordpress/gcp/namespace.yaml
|
[crossplane-sample-gcp-namespace]: https://github.com/crossplaneio/crossplane/blob/master/cluster/examples/workloads/kubernetes/wordpress/gcp/namespace.yaml
|
||||||
|
|
||||||
|
[cloud-provider-setup-gcp]: cloud-providers/gcp/gcp-provider.md
|
||||||
|
|
|
@ -5,7 +5,7 @@ weight: 510
|
||||||
indent: false
|
indent: false
|
||||||
---
|
---
|
||||||
|
|
||||||
# Crossplane Stacks Guide
|
# Stacks Guide
|
||||||
|
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
@ -43,14 +43,17 @@ Let's go!
|
||||||
|
|
||||||
## Concepts
|
## 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!
|
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]
|
* [Crossplane concepts][crossplane-concepts]
|
||||||
* [Kubernetes concepts][kubernetes-concepts]
|
* [Kubernetes concepts][kubernetes-concepts]
|
||||||
|
|
||||||
## Before you get started
|
## 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:
|
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
|
* The terminal environment
|
||||||
* Setting up cloud provider accounts for the cloud provider you want to
|
* Setting up cloud provider accounts for the cloud provider you want to
|
||||||
|
@ -73,8 +76,7 @@ CLI][crossplane-cli], because it's more convenient. To install it, we
|
||||||
can use the one-line curl bash:
|
can use the one-line curl bash:
|
||||||
|
|
||||||
```
|
```
|
||||||
RELEASE=0.0.1
|
RELEASE=release-0.1 && curl -sL https://raw.githubusercontent.com/crossplaneio/crossplane-cli/"${RELEASE}"/bootstrap.sh | RELEASE=${RELEASE} bash
|
||||||
curl -sL https://raw.githubusercontent.com/crossplaneio/crossplane-cli/"${RELEASE}"/bootstrap.sh | bash
|
|
||||||
```
|
```
|
||||||
|
|
||||||
To use the latest release, you can use `master` as the `RELEASE` instead
|
To use the latest release, you can use `master` as the `RELEASE` instead
|
||||||
|
@ -103,7 +105,7 @@ documentation][crossplane-install-docs].
|
||||||
|
|
||||||
### Create the application namespace
|
### Create the application namespace
|
||||||
|
|
||||||
[Kubernetes namespaces][kubernetes-namespace-docs] are used to isolate
|
[Kubernetes namespaces][kubernetes-namespaces-docs] are used to isolate
|
||||||
resources in the same cluster, and we'll use them in our Crossplane
|
resources in the same cluster, and we'll use them in our Crossplane
|
||||||
control cluster too. Let's create a namespace for our application's
|
control cluster too. Let's create a namespace for our application's
|
||||||
resources. We'll call it `app-project1-dev` for the purposes of this
|
resources. We'll call it `app-project1-dev` for the purposes of this
|
||||||
|
@ -180,6 +182,19 @@ EOF
|
||||||
kubectl apply --namespace app-project1-dev -f my-wordpress.yaml
|
kubectl apply --namespace app-project1-dev -f my-wordpress.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To validate that it has been set up correctly, we can run:
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl -n app-project1-dev get stack
|
||||||
|
```
|
||||||
|
|
||||||
|
The output should look something like:
|
||||||
|
|
||||||
|
```
|
||||||
|
NAME READY VERSION AGE
|
||||||
|
sample-stack-wordpress True 0.0.1 48s
|
||||||
|
```
|
||||||
|
|
||||||
If the control cluster doesn't recognize the Wordpress instance type, it
|
If the control cluster doesn't recognize the Wordpress instance type, it
|
||||||
could be because the stack is still being installed. Wait a few seconds,
|
could be because the stack is still being installed. Wait a few seconds,
|
||||||
and try creating the Wordpress instance again.
|
and try creating the Wordpress instance again.
|
||||||
|
@ -203,6 +218,11 @@ kubectl get -n app-project1-dev kubernetesapplication
|
||||||
kubectl get -n app-project1-dev kubernetesapplicationresource
|
kubectl get -n app-project1-dev kubernetesapplicationresource
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For validation that these resources are spinning up, you can check in
|
||||||
|
the usual way for your cloud provider, or you can ask for the
|
||||||
|
statuses of some of the cloud-specific Kubernetes resources provided by
|
||||||
|
the infrastructure stack that we installed.
|
||||||
|
|
||||||
For more information about how Crossplane manages databases and
|
For more information about how Crossplane manages databases and
|
||||||
Kubernetes clusters for us, see the more complete documentation about
|
Kubernetes clusters for us, see the more complete documentation about
|
||||||
[claims][claims-docs], [resource classes][resource-classes-docs], and
|
[claims][claims-docs], [resource classes][resource-classes-docs], and
|
||||||
|
@ -217,7 +237,7 @@ which represents the workload's service. Here's a way to watch for the
|
||||||
ip:
|
ip:
|
||||||
|
|
||||||
```
|
```
|
||||||
kubectl get kubernetesapplicationresource -n app-project1-dev -o custom-columns='NAME:.metadata.name,NAMESPACE:.spec.template.metadata.namespace,KIND:.spec.template.kind,SERVICE-EXTERNAL-IP:.status.remote.loadBalancer.ingress[0].ip' --watch
|
kubectl get --watch kubernetesapplicationresource -n app-project1-dev -o custom-columns='NAME:.metadata.name,NAMESPACE:.spec.template.metadata.namespace,KIND:.spec.template.kind,SERVICE-EXTERNAL-IP:.status.remote.loadBalancer.ingress[0].ip'
|
||||||
```
|
```
|
||||||
|
|
||||||
The ip will show up on the one which has a `Service` kind.
|
The ip will show up on the one which has a `Service` kind.
|
||||||
|
@ -243,8 +263,7 @@ kubectl delete -n app-project1-dev wordpressinstance my-wordpressinstance
|
||||||
We can also remove the stack, using the Crossplane CLI:
|
We can also remove the stack, using the Crossplane CLI:
|
||||||
|
|
||||||
```
|
```
|
||||||
kubectl crossplane stack uninstall sample-stack-wordpress -n
|
kubectl crossplane stack uninstall sample-stack-wordpress -n app-project1-dev
|
||||||
app-project1-dev
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Removing the stack removes any Wordpress instances that were created.
|
Removing the stack removes any Wordpress instances that were created.
|
||||||
|
@ -282,12 +301,13 @@ guide][stack-developer-guide].
|
||||||
## References
|
## References
|
||||||
|
|
||||||
* [The Crossplane Concepts guide][crossplane-concepts]
|
* [The Crossplane Concepts guide][crossplane-concepts]
|
||||||
|
* [Crossplane API Reference][crossplane-api-reference]
|
||||||
* [The Stacks Concepts guide][stack-concepts]
|
* [The Stacks Concepts guide][stack-concepts]
|
||||||
* [Crossplane Install Guide][crossplane-install-docs]
|
* [Crossplane Install Guide][crossplane-install-docs]
|
||||||
* [The Crossplane CLI][crossplane-cli]
|
* [The Crossplane CLI][crossplane-cli]
|
||||||
* [Stacks Quick Start][stack-quick-start]
|
* [Stacks Quick Start][stack-quick-start]
|
||||||
* [Stack Registry][stack-registry]
|
|
||||||
* [Stacks Developer Guide][stack-developer-guide]
|
* [Stacks Developer Guide][stack-developer-guide]
|
||||||
|
* [Stack Registry][stack-registry]
|
||||||
* [Provider Stack Developer Guide][provider-stack-developer-guide]
|
* [Provider Stack Developer Guide][provider-stack-developer-guide]
|
||||||
* [AWS documentation][aws-docs]
|
* [AWS documentation][aws-docs]
|
||||||
* [GCP documentation][gcp-docs]
|
* [GCP documentation][gcp-docs]
|
||||||
|
@ -295,12 +315,13 @@ guide][stack-developer-guide].
|
||||||
* [Kubernetes documentation][kubernetes-docs]
|
* [Kubernetes documentation][kubernetes-docs]
|
||||||
|
|
||||||
<!-- Named links -->
|
<!-- Named links -->
|
||||||
[crossplane-cli]: https://github.com/crossplaneio/crossplane-cli
|
[crossplane-cli]: https://github.com/crossplaneio/crossplane-cli/tree/release-0.1
|
||||||
[crossplane-cli-docs]: https://github.com/crossplaneio/crossplane-cli/blob/master/README.md
|
[crossplane-cli-docs]: https://github.com/crossplaneio/crossplane-cli/blob/release-0.1/README.md
|
||||||
[crossplane-concepts]: concepts.md
|
[crossplane-concepts]: concepts.md
|
||||||
[crossplane-install-docs]: install-crossplane.md
|
[crossplane-install-docs]: install-crossplane.md
|
||||||
|
[crossplane-api-reference]: api.md
|
||||||
|
|
||||||
[kubernetesapplicationresource-docs]: TODO
|
[kubernetesapplicationresource-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-complex-workloads.md
|
||||||
[claims-docs]: concepts.md#resource-claims-and-resource-classes
|
[claims-docs]: concepts.md#resource-claims-and-resource-classes
|
||||||
[resource-classes-docs]: concepts.md#resource-claims-and-resource-classes
|
[resource-classes-docs]: concepts.md#resource-claims-and-resource-classes
|
||||||
[portable-classes-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-default-resource-class.md
|
[portable-classes-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-default-resource-class.md
|
||||||
|
@ -317,15 +338,15 @@ guide][stack-developer-guide].
|
||||||
[gcp-docs]: https://cloud.google.com/docs/
|
[gcp-docs]: https://cloud.google.com/docs/
|
||||||
[azure-docs]: https://docs.microsoft.com/azure/
|
[azure-docs]: https://docs.microsoft.com/azure/
|
||||||
|
|
||||||
[aws-setup]: TODO
|
[aws-setup]: stacks-guide-aws.md
|
||||||
[gcp-setup]: stacks-guide-gcp.md
|
[gcp-setup]: stacks-guide-gcp.md
|
||||||
[azure-setup]: TODO
|
[azure-setup]: stacks-guide-azure.md
|
||||||
|
|
||||||
[stack-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#crossplane-stacks
|
[stack-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#crossplane-stacks
|
||||||
[stack-quick-start]: https://github.com/crossplaneio/crossplane-cli#quick-start-stacks
|
[stack-quick-start]: https://github.com/crossplaneio/crossplane-cli/tree/release-0.1#quick-start-stacks
|
||||||
[stack-concepts]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#crossplane-stacks
|
[stack-concepts]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#crossplane-stacks
|
||||||
|
[stack-registry]: https://hub.docker.com/search?q=crossplane&type=image
|
||||||
[stack-manager-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#installation-flow
|
[stack-manager-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-format-docs]: https://github.com/crossplaneio/crossplane/blob/master/design/design-doc-stacks.md#stack-package-format
|
||||||
[stack-registry]: TODO
|
[stack-developer-guide]: developer-guide.md
|
||||||
[stack-developer-guide]: TODO
|
[provider-stack-developer-guide]: developer-guide.md
|
||||||
[provider-stack-developer-guide]: TODO
|
|
||||||
|
|
Loading…
Reference in New Issue