Skip to content

Commit

Permalink
Create a CI pipeline to reconcile, render and deploy an app on Circle…
Browse files Browse the repository at this point in the history
…CI. (#325)
  • Loading branch information
ezodude authored Oct 27, 2020
1 parent 351b23a commit cdc5431
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 3 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,7 @@ Check our [Roadmap][roadmap] for upcoming planned integrations.
- [Getting started with Kev](docs/tutorials/getting-started-with-kev.md)
- [Develop the app with Kev and Skaffold](docs/tutorials/kev-dev-with-skaffold.md)
- [Simple Node.js app development workflow example](docs/tutorials/simple-nodejs-app-workflow.md)

This is an example of how to use Kev to iterate and deploy a [WordPress Docker Compose application](https://docs.docker.com/compose/wordpress/) onto Kubernetes.
- [Simple Node.js app CI workflow example](docs/tutorials/simple-nodejs-app-ci-workflow.md)

## Configuration

Expand Down
138 changes: 138 additions & 0 deletions docs/tutorials/simple-nodejs-app-ci-workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
---
weight: 14
title: Kev CI workflow example with a simple Node.js App
---

# CI workflow example with a simple Node.js app

This example walks through using Kev in a commit based CI pipeline.

You will setup CircleCI to render, build, push and deploy to a remote staging environment.

We assume that you,
- Use [`git`](https://git-scm.com/) for source control and can push to a remote Git repo.
- Have a [CircleCI](https://circleci.com/) account connected to your Git repo.
- Have a [kube-config file](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) with access to a remote cluster.

## Get Kev

* Download [Kev](https://github.com/appvia/kev/releases/latest) & add it your `PATH`.

## Prepare for CI

### kube-config file

We need to connect our CI deployment to a remote cluster using a `kube-context` setup to access the remote cluster. This context will be defined in a `kube-config` file.

Make a copy of this `kube-config` file and remove any kube-contexts that do not relate to our final deployment.

> kube-config file: slimmed kube-context example.
```yaml
apiVersion: v1
kind: Config
clusters:
- cluster:
insecure-skip-tls-verify: false
server: https://xx.xx.xx.xx
name: remote-cluster
contexts:
- context:
cluster: remote-cluster
user: a-user
name: remote-cluster-context
current-context: remote-cluster-context
preferences: {}
users:
- name: a-user
user:
auth-provider:
...
```

Now encode the slimmed down `kube-config` file into base64.

```shell script
cat ~/path/to/remote/cluster/kube/config | base64
```

Then create the following [CircleCI Project Environment Variables](https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-project),
- `KUBE_CONFIG_STAGING`, to store the `kube-config` base64 value there.
- `KUBE_CONTEXT_STAGING`, to store the value of the `kube-context` there.

### Docker registry

We will also add `DOCKER_USERNAME` and `DOCKER_TOKEN` as CircleCI Project Environment Variables.

These allow us to push our app's image to a secure docker registry. Should that be a private registry then make sure that the remote Kubernetes cluster is able to [pull images from it](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/).

### config.yaml

Here is the [CircleCI config file](../../examples/node-app/.circleci/config.yml). It will create a CI pipeline that is triggered by a commit to your Git repo.

It assumes the necessary **CircleCI Environment Variables have been setup**, and the target cluster has a `staging` namespace already setup.

It also depends on the Kev staging environment that we will be creating shortly. Here's the relevant step that performs the actual deployment,

> CircleCI Deploy step: render staging, use Skaffold to build, push and deploy your app to Kubernetes.
```yaml
...
...
- run:
name: Deploy
command: |
echo ${KUBE_CONFIG_STAGING} | base64 -d > ${KUBE_CONFIG_STAGING_FILE}
./bin/kev/kev render -e staging
./bin/skaffold run --kubeconfig ${KUBE_CONFIG_STAGING_FILE} --kube-context ${KUBE_CONTEXT_STAGING} --profile staging-env --namespace staging
...
...
```

## Initialise project

To follow the tutorial, make a copy of the project directory (`./examples/node-app`).

> Inside the copied project directory (`./examples/node-app`) instruct Kev to:
> * create a `staging` based Kubernetes environment configuration.
> * prepare the app for use with [Skaffold](https://skaffold.dev/).
```sh
kev init -e staging --skaffold
```

You will notice the staging environment configuration file has been created:

> Added environment specific override files:
```
...
|- docker-compose.kev.staging.yaml # staging env
```

Adjust your Kubernetes `staging` application parameters for each of the components as needed. This is done via Compose [labels](../../docs/reference/config-params.md).

Also, you'll find that Kev has bootstrapped a Skaffold config file (`skaffold.yaml`). If a `skaffold.yaml` file previously existed, then the additional profiles will be added there.

Our CI pipeline will be using this Skaffold config file to power builds, pushes and deployments.

## Iterate on the application and commit

Iterate on the application as [described here](simple-nodejs-app-workflow.md#iterate-on-the-application).

When you're happy, commit the latest and push.

## App deployed to staging

The commit will trigger the CI pipeline.

After the `stage` job successfully finishes, inspect that the Node app is running in your remote cluster:

> List Kubernetes application pods for the Node.js app:
```sh
$ kubectl --context <remote_cluster_context> -n staging get po

NAME READY STATUS RESTARTS AGE
app-69d87ffbc8-wgs6 1/1 Running 0 9s
```

That's it! If you have an [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) configured then navigate to the correct Url.

Alternatively, you can choose to [port-forward](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/) the service and test the app on your localhost.
55 changes: 55 additions & 0 deletions examples/node-app/.circleci/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
version: 2.1

orbs:
kube-orb: circleci/[email protected]
docker: circleci/[email protected]

jobs:
stage:
environment:
machine:
image: ubuntu-1604:202007-01
steps:
- docker/check:
docker-username: DOCKER_USERNAME
docker-password: DOCKER_TOKEN
registry: quay.io
- checkout
- kube-orb/install-kubectl:
kubectl-version: latest
- run:
name: Setup
command: |
mkdir -p bin
mkdir -p hacks/deploy
- run:
name: Installing dependencies
command: |
sudo apt-get update
sudo apt install -y curl git
- run:
name: Installing Kev
command: |
curl --request GET -sL \
--url https://github.com/appvia/kev/releases/latest/download/kev-linux-amd64 \
--output bin/kev
chmod +x bin/kev
- run:
name: Installing Skaffold
command: |
curl --request GET -sL \
--url https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64 \
--output bin/skaffold
chmod +x bin/skaffold
- run:
name: Deploy
command: |
echo ${KUBE_CONFIG_STAGING} | base64 -d > ${KUBE_CONFIG_STAGING_FILE}
./bin/kev/kev render -e staging
./bin/skaffold run --kubeconfig ${KUBE_CONFIG_STAGING_FILE} --kube-context ${KUBE_CONTEXT_STAGING} --profile staging-env --namespace staging
workflows:
deploy-staging:
jobs:
- stage
4 changes: 3 additions & 1 deletion examples/node-app/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Node.js app example

See [workflow example with a simple Node.js App tutorial](../../docs/tutorials/simple-nodejs-app-workflow.md) for details.
Used by:
- [Simple Node.js app development workflow example](../../docs/tutorials/simple-nodejs-app-workflow.md) for details.
- [Simple Node.js app CI workflow example](../../docs/tutorials/simple-nodejs-app-ci-workflow.md) for details.

0 comments on commit cdc5431

Please sign in to comment.