$ docker-compose -f docker-compose.dev.yml up -d
Then open your browser to http://localhost:3000
This repository includes a chart for Helm, the package manager for Kubernetes, to simplify deploying the application.
- A private Docker registry. Follow the Azure Container Registry getting started guide to create one.
- A Kubernetes cluster. Follow the Azure Container Service walkthrough to create one.
-
Ensure
kubectl
is configured for your cluster, and that the Helm client is on your path. See the Helm quickstart guide for instructions. -
Build the app's React client. From the repository root:
$ docker-compose -f docker-compose.build-client.yml up
The chart expects these
images, where your-registry.azurecr.io
is your private registry:
image name | source directory |
---|---|
your-registry.azurecr.io/stickerapp/apigateway:1.0 |
apigateway |
your-registry.azurecr.io/stickerapp/checkout:1.0 |
checkoutService |
your-registry.azurecr.io/stickerapp/session:1.0 |
sessionService |
your-registry.azurecr.io/stickerapp/stickers:1.0 |
stickerService |
The chart's imageTag
value is used for these images. It defaults to 1.0
and
can be overridden. You can build and push the images from the command line, e.g.
for the sticker service:
$ docker login your-registry.azurecr.io -u adminName -p password
$ cd stickerService
$ docker build -t your-registry.azurecr.io/stickerapp/stickers:1.0 .
$ docker push your-registry.azurecr.io/stickerapp/stickers:1.0
-
Install Tiller, Helm's server-side component:
$ helm init
-
Deploy an ingress controller, if your cluster doesn't have one already:
$ helm install -f nginx-ingress-values.yaml --namespace kube-system stable/nginx-ingress
nginx-ingress-values.yaml
, in this repository'sk8s
directory, contains settings which override thenginx-ingress
chart's defaults to disable SSL redirecting and use a more recent controller image
-
The app requires a Kafka cluster. You can deploy a small one with Helm:
$ helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator $ helm install -n kafka --set Replicas=1 --set zookeeper.Servers=1 --set zookeeper.Storage="1Gi" incubator/kafka
-
Open a shell in the
k8s
directory. -
Generate the docker-registry secret Kubernetes will use to pull the app's images. The included script can do this:
$ node generate-dockercfg.js
-
Set required values in
values.yaml
(you can provide these on the command line with--set
instead, if you don't mind a very long command line)required value description azureActiveDirectory.clientId
client ID for your Azure AD app azureActiveDirectory.clientSecret
secret for your Azure AD app azureActiveDirectory.destroySessionUrl
URL used to end AAD session azureActiveDirectory.redirectUrl
post-login redirect URL azureActiveDirectory.tenant
Azure AD tenant registry
Docker registry, e.g. your-registry.azurecr.io
dockercfg
docker-registry secret kafkaBroker
DNS name and port of a Kafka broker zookeeperConnect
DNS name and port of a ZooKeeper instance -
Collect the chart's dependencies:
$ helm dependency update stickerapp
-
Install the chart:
$ helm install stickerapp NAME: honest-deer ...
You can inspect the deployment with the Kubernetes UI, helm
, or kubectl
:
$ helm status honest-deer
LAST DEPLOYED: Mon Jun 5 15:00:38 2017
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
...
$ kubectl get all -l release=honest-deer
NAME READY STATUS RESTARTS AGE
po/honest-deer-apigateway-1160103434-9q3vr 1/1 Running 0 7m
po/honest-deer-checkout-545275974-f2rt5 1/1 Running 0 7m
po/honest-deer-session-1173111989-x7x37 1/1 Running 0 7m
...
The app is reachable through the ingress controller's external IP address. To
find this, inspect the ingress controller's service in the Kubernetes UI,
or use kubectl
. For example, for an ingress controller deployed as described above:
$ kubectl get svc -l app=nginx-ingress --namespace kube-system
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
awesome-narwhal-nginx-ingress-controller 10.0.190.16 52.173.17.217 80:32493/TCP,443:31437/TCP 40m
Like any Kubernetes app, you can control this one with kubectl
. For
example, scaling the apigateway
deployment to add a second pod:
$ kubectl get deploy -l component=apigateway
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
honest-deer-apigateway 1 1 1 1 9m
$ kubectl scale --replicas=2 deploy/honest-deer-apigateway
deployment "honest-deer-apigateway" scaled
$ kubectl get deploy -l component=apigateway
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
honest-deer-apigateway 2 2 2 2 10m
The steps in this section describe how to use Jenkins to setup a CI pipeline for the Sticker App. Specifically, each time that the pipeline runs, the following steps will be performed:
- Docker images are created for each of the app's microservices
- The Docker images are pushed to the Azure Container Registry
- The app's microservices are deployed using the images stored in the Azure Container Registry via Kubernetes\Helm
- A test environment is deployed and mocha integration tests run to verify the app
- If the integration tests pass, a production environment is deployed
A few additional points to note:
- If the app has never been installed, the pipeline will perform a clean install
- If the app has been installed before, the pipeline perform an upgrade of the app
- The pipeline can be triggered to run with each change that is pushed to the GitHub repo (optionally, the pipeline may be manually triggered to make the pipeline easier to run)
Ensure that these resources have been created (if they haven't already):
-
A private Docker registry. Follow the Azure Container Registry getting started guide to create one.
-
A Kubernetes cluster. Follow the Azure Container Service walkthrough to create one.
-
Deploy an ingress controller to your cluster:
$ helm install -f nginx-ingress-values.yaml --namespace kube-system stable/nginx-ingress
nginx-ingress-values.yaml
, in this repository'sk8s
directory, contains settings which override thenginx-ingress
chart's defaults to disable SSL redirecting and use a more recent controller image
-
The app requires a Kafka cluster. You can deploy a small one with Helm:
$ helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator $ helm install -n kafka --set Replicas=1 --set zookeeper.Servers=1 --set zookeeper.Storage="1Gi" incubator/kafka
-
Create an Azure VM with Jenkins installed (these instructions assume that the Jenkins server will be installed outside of the Kubernetes cluster). To create a Jenkins VM, follow the quick start.
Once you have the Jenkins VM setup, log into the Jenkins web portal and perform the following configuration:
- Install required plug-ins if they are not already installed.
- NodeJS (configure this to install both npm and Mocha; go to Jenkins->Global Tool Configuration under the NodeJS installations section)
- GitHub (should be installed by default)
- Add credentials required by the pipeline script. Go to Credentials->System, create the following credentials using the IDs outlined below:
- Kind: Username with password, ID: AAD
- Stores the AAD client and secret needed by the Sticker App to authenticate users of the app.
- Kind: Username with password, ID: DOCKER
- Stores the Azure Container Registry user id and secret needed to push images to the registry.
- Kind: Secret text, ID: ACR
- Stores the Docker secret that is needed by Kunernetes to deploy images from the registry.
- Create the pipeline and add the script. To do this, under New Item, enter a name and choose to create Pipeline. In the pipeline's configuration, save the following changes:
- In the General section, check the GitHub project and add the url to the Sticker App repo.
- In the Build Triggers section, check the GitHub hook trigger for GITScm polling.
- In the Pipeline section, add the jenkins-script\ci-pipeline.groovy script located within Sticker App repo. You can either copy and paste the script into Jenkins or configure to load the script from SCM.
- Modify the env vars used within the script:
- ACR_NAME (Azure container docker registry where the images are pushed\pulled from, e.g. .azurecr.io)
- KAFKA_BROKER (DNS name of the kafka broker with port, e.g. "kafka:9092")
- ZK_CONNECT (DNS name of a zookeeper instance with port, e.g. "zookeepr:2181")
- INGRESS_IP (IP address of nginx ingress controller)
- PROD_RELEASE (Release name for the production version of the app)
- TEST_RELEASE (Release name for the test version of the app)
- AAD_TENANT (Name of the AAD tenant used for the app's B2C authentication, e.g. .onmicrosoft.com)
- Run the pipeline script. There are 2 ways to trigger the pipeline script to run.
- You can push a change to GitHub. Note that this requires you to add a webhook to Jenkins within GitHub's settings. In GitHub, under the repo's settings, select Integrations & services. Choose to Add a service and select Jenkins (GitHub plugin). In the Jenkins hook url field, specify the url to your Jenkins VM followed by "/github-webhook". For example: http://:8080/github-webhook/. Ensure that the Active checkbox is checked.
- Or, within Jenkins, you can click the Build Now link.
The app's authentication service is implemented as part of the API Gateway and supports both basic email and facebook authentication by using Azure AAD B2C. The API Gateway acts as the primary entry point into th eserver by providing a wrapper over all calls to the microservices' endpoints. The advantage of this approach is:
-
The gateway is responsible for ensuring that the user is authenticated before it calls into each microservice; this way, none of the microservices themselves need to worry about authenticating the user.
-
The microservices' endpoints are not exposed publicly; only the API Gateway is able to access these endpoints which helps make the server more secure.
The auth service is implemented using Passport and Passport-Azure-AD npm packages.
To configure AAD, follow these steps - this is required in order to log in\log out of the app and to complete a sticker order:
- Note that the Reply URL will need to include the external IP address of the cluster's ingress controller, e.g. "https:///users/auth/return"
In addition, refer to the 'Create an application' and 'Create your policies' sections that are included here
Note that there are steps missing from this - the signup/login policies need to be added the new Facebook provider too.