Stands up an Azure Kubernetes Service (AKS) cluster and a MongoDB-flavored instance of
CosmosDB. On top of the AKS cluster, we also deploy Helm Chart with a simple
Node.js TODO app (bitnami/node
), swapping out the usual in-cluster MongoDB instance
with our managed CosmosDB instance.
Ensure you have downloaded and installed the Pulumi CLI.
We will be deploying to Azure, so you will need an Azure account. If you don't have an account, sign up for free here. Follow the instructions here to connect Pulumi to your Azure account.
This example deploys a Helm Chart from Bitnami's Helm chart repository, so you will need to install the Helm CLI and configure it:
For Helm v2 users:
$ helm init --client-only
$ helm repo add bitnami https://charts.bitnami.com/bitnami
For Helm v3 users:
$ helm repo add bitnami https://charts.bitnami.com/bitnami
Now, install dependencies:
npm install
-
Create a new stack:
$ pulumi stack init Enter a stack name: azure-mean
-
Set the required configuration variables for this program:
$ pulumi config set azure:environment public $ pulumi config set password --secret [your-cluster-password-here] $ ssh-keygen -t rsa -f key.rsa $ pulumi config set sshPublicKey < key.rsa.pub $ az login
-
Perform the deployment:
Note: Due to an issue in Azure Terraform Provider, the creation of an Azure Service Principal, which is needed to create the Kubernetes cluster (see cluster.ts), is delayed and may not be available when the cluster is created. If you get a "Service Principal not found" error, as a work around, you should be able to run
pulumi up
again, at which time the Service Principal replication should have been completed. See this issue and this doc for further details.$ pulumi up Updating stack 'azure-mean' Performing changes: Type Name Status Info + pulumi:pulumi:Stack azure-mean-azure-mean created 1 warning + ├─ azure:core:ResourceGroup aks created + ├─ azure:ad:Application aks created + ├─ azure:ad:ServicePrincipal aksSp created + ├─ azure:ad:ServicePrincipalPassword aksSpPassword created + ├─ azure:cosmosdb:Account cosmosDb created + ├─ azure:containerservice:KubernetesCluster aksCluster created + ├─ pulumi:providers:kubernetes aksK8s created + ├─ kubernetes:core:Secret mongo-secrets created + └─ kubernetes:helm.sh:Chart node created + ├─ kubernetes:core:Service node-node created + └─ kubernetes:extensions:Deployment node-node created ---outputs:--- cluster : "aksclusterbfb9388b" frontendAddress: "40.76.25.71" info: 12 changes performed: + 12 resources created Update duration: 14m33.922322098s Permalink: https://app.pulumi.com/hausdorff/azure-mean/updates/1
We can see here in the
---outputs:---
section that our Node.js appwas allocated a public IP, in this case40.76.25.71
. It is exported with a stack output variable,frontendAddress
. We can usecurl
andgrep
to retrieve the<title>
of the site the proxy points at.$ curl -sL $(pulumi stack output frontendAddress) | grep "<title>" <title>Node/Angular Todo App</title>>
One of the interesting aspects of this example is the way it demonstrates how easy it is to use
Azure resources to configure Kubernetes resources, without the need for intermediate APIs such as
OSBA. In particular, this example uses the connection strings exposed by the
CosmosDB instance to configure the bitnami/node
Helm Chart to connect to CosmosDB, instead of
creating and connecting to an in-cluster MongoDB instance.
In index.ts
, we see the MongoDB-flavored CosmosDB resource definition:
// Create a MongoDB-flavored instance of CosmosDB.
const cosmosdb = new azure.cosmosdb.Account("cosmosDb", {
kind: "MongoDB",
resourceGroupName: config.resourceGroup.name,
location: config.location,
consistencyPolicy: { ... },
offerType: "Standard",
enableAutomaticFailover: true,
geoLocations: [ ... ]
});
And then subsequently, in the same file, we see that we use this CosmosDB object to create a
Kubernetes Secret
containing the connection credentials, which is then consumed by the
bitnami/node
Helm chart to connect.
// Create secret from MongoDB connection string.
const mongoConnStrings = new k8s.core.v1.Secret(
"mongo-secrets",
{
metadata: { name: "mongo-secrets" },
data: mongoHelpers.parseConnString(cosmosdb.connectionStrings)
},
{ provider: k8sProvider }
);
// Boot up nodejs Helm chart example using CosmosDB in place of in-cluster MongoDB.
const node = new k8s.helm.v2.Chart(
"node",
{
repo: "bitnami",
chart: "node",
version: "4.0.1",
values: {
serviceType: "LoadBalancer",
mongodb: { install: false },
externaldb: { ssl: true, secretName: "mongo-secrets" }
}
},
{ providers: { kubernetes: k8sProvider }, dependsOn: mongoConnStrings }
);