You've already forked golang-saas-starter-kit
mirror of
https://github.com/raseels-repos/golang-saas-starter-kit.git
synced 2025-08-08 22:36:41 +02:00
devops migration
This commit is contained in:
391
build/cicd/README.md
Normal file
391
build/cicd/README.md
Normal file
@@ -0,0 +1,391 @@
|
||||
|
||||
cicd
|
||||
===
|
||||
|
||||
_cicd_ is a simple command line tool that facilitates build and deployment for your project. The goal is to help enable
|
||||
developers to easily setup a continuous build pipeline using [GitLab CI/CD](https://docs.gitlab.com/ee/ci/) and code
|
||||
driven deployment.
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
- [Overview](#overview)
|
||||
* [Deployment Environments](#deployment-environments)
|
||||
* [Services](#services)
|
||||
* [Functions](#functions)
|
||||
* [Schema Migrations](#schema-migrations)
|
||||
- [Installation](#installation)
|
||||
- [Getting Started](#getting-started)
|
||||
- [Usage](#usage)
|
||||
* [Commands](#commands)
|
||||
* [Examples](#examples)
|
||||
- [Join us on Gopher Slack](#join-us-on-gopher-slack)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
The command line tool provides the functionality to configure, build and deploy your code. When new code is push to GitLab,
|
||||
this tool will enable building, testing and deploying your code to [Amazon AWS](https://aws.amazon.com/).
|
||||
|
||||
Deploying your code to production always requires additional tooling and configuration. Instead of patching together a
|
||||
system of of existing tools and configuration files. This tool centralizes configuration for the application and any
|
||||
additional deployment resources needed.
|
||||
|
||||
Configuration is define with code. AWS resources are created/maintained using the [AWS SDK for Go](https://docs.aws.amazon.com/sdk-for-go/api/).
|
||||
|
||||
**This tool is used by GitLab CI/CD** and is configured by a file called `.gitlab-ci.yml` placed at the repository’s root.
|
||||
|
||||
**All code is deployed to Amazon AWS**.
|
||||
|
||||
Check out the [full presentation](https://docs.google.com/presentation/d/1sRFQwipziZlxBtN7xuF-ol8vtUqD55l_4GE-4_ns-qM/edit?usp=sharing)
|
||||
that covers how to setup your [GitLab CI/CD](https://docs.gitlab.com/ee/ci/) pipeline that uses autoscaling GitLab
|
||||
Runners on AWS.
|
||||
|
||||
Support is provided for both services and functions. The build process for both relies on docker and thus, neither are
|
||||
required to be written in go.
|
||||
|
||||
Configuration for build and deploy is provided by
|
||||
[gitlab.com/geeks-accelerator/oss/devops/pkg/devdeploy](https://godoc.org/gitlab.com/geeks-accelerator/oss/devops/pkg/devdeploy)
|
||||
|
||||
For additional details regarding this tool, refer to
|
||||
[gitlab.com/geeks-accelerator/oss/devops](https://gitlab.com/geeks-accelerator/oss/devops)
|
||||
|
||||
|
||||
|
||||
### Deployment Environments
|
||||
|
||||
All configuration for the deployment environments is defined in code that is located in the
|
||||
[internal/config](https://gitlab.com/geeks-accelerator/oss/saas-starter-kit/tree/master/build/cicd/internal/config)
|
||||
package. This includes configuration for the following deployment resources:
|
||||
|
||||
* [AWS ECR Repository](https://godoc.org/gitlab.com/geeks-accelerator/oss/devops/pkg/devdeploy#AwsEcrRepository)
|
||||
named `saas-starter-kit`
|
||||
|
||||
* [AWS EC2 VPC](https://godoc.org/gitlab.com/geeks-accelerator/oss/devops/pkg/devdeploy#AwsEc2Vpc) defined as using the
|
||||
default for the AWS Region.
|
||||
|
||||
* [AWS EC2 Security Group](https://godoc.org/gitlab.com/geeks-accelerator/oss/devops/pkg/devdeploy#AwsEc2SecurityGroup)
|
||||
named `saas-starter-kit-[dev|stage|prod]`
|
||||
* The name of the GitLab runner security group as `gitlab-runner` that will be added to the security group as ingress.
|
||||
|
||||
* Private [AWS S3 Bucket](https://godoc.org/gitlab.com/geeks-accelerator/oss/devops/pkg/devdeploy#AwsS3Bucket)
|
||||
named `saas-starter-kit-private` used by the `web-app` and `web-api` for large object storage.
|
||||
* A lifecycle policy is applied to the key prefix `tmp/` that will expire objects after 1 day for temporary storage
|
||||
like exports.
|
||||
* Configured to [block all public access](https://aws.amazon.com/blogs/aws/amazon-s3-block-public-access-another-layer-of-protection-for-your-accounts-and-buckets/)
|
||||
|
||||
* Public [AWS S3 Bucket](https://godoc.org/gitlab.com/geeks-accelerator/oss/devops/pkg/devdeploy#AwsS3Bucket)
|
||||
named `saas-starter-kit-public` used to serve static files primary for the `web-app`.
|
||||
* CORS rules for GET and POST to support static files served directly from the S3 Bucket or via Cloudfront.
|
||||
* Defined key prefix of `public/` used by deployment for uploading static files.
|
||||
* AWS CloudFront configured for the `prod` environment for serving static files from the S3 Bucket as origin.
|
||||
|
||||
* Redis [AWS Elastic Cache Cluster](https://godoc.org/gitlab.com/geeks-accelerator/oss/devops/pkg/devdeploy#AwsElasticCacheCluster)
|
||||
named `saas-starter-kit-[dev|stage|prod]` for ephemeral storage.
|
||||
* Configured using Redis version 5.0.4.
|
||||
* Deployed as a single node cache cluster using the instance type `cache.t2.micro`, 1vCPU with 512mbs of memory.
|
||||
* `maxmemory-policy` parameter set to `allkeys-lru` which will evict keys by trying to remove the less recently used
|
||||
(LRU) keys first, in order to make space for the new data added. This will prevent the cache cluster from ever
|
||||
running out of memory.
|
||||
|
||||
* Postgres [AWS RDS Database Instance](https://godoc.org/gitlab.com/geeks-accelerator/oss/devops/pkg/devdeploy#AwsRdsDBInstance)
|
||||
named `saas-starter-kit-[dev|stage|prod]`.
|
||||
* Configured with the default database `shared`, username `god` on port 5432.
|
||||
* The password is randomly generated during creation and stored in [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/).
|
||||
* Deployed as a single instance using the instance type `db.t2.small`, 1vCPU with 2GiB of memory.
|
||||
* 20GiB of disk space has been allocated.
|
||||
|
||||
* [AWS Iam Policy](https://godoc.org/gitlab.com/geeks-accelerator/oss/devops/pkg/devdeploy#AwsIamPolicy) named
|
||||
`saasStarterKitService[Dev|Stage|Prod]` that will be used to grants permissions for AWS ECS tasks and AWS Lambda
|
||||
functions to access to the defined AWS resources listed above.
|
||||
|
||||
* Support for datadog can be enabled by added your Datadog API key to [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/)
|
||||
using the key `saas-starter-kit/[dev|stage|prod]/datadog`
|
||||
|
||||
|
||||
Multiple development environments can easily be configured for more control. This tool supports three target deployment
|
||||
environments:
|
||||
* dev
|
||||
* stage
|
||||
* prod
|
||||
|
||||
`.gitlab-ci.yml` only has prod enabled.
|
||||
|
||||
|
||||
|
||||
### Services
|
||||
Services are generally applications that will need to be long running or continuously available. The configured services
|
||||
are:
|
||||
|
||||
* [web-app](https://gitlab.com/geeks-accelerator/oss/saas-starter-kit/tree/master/cmd/web-app) - Publicly accessible
|
||||
website and web application.
|
||||
* [web-api](https://gitlab.com/geeks-accelerator/oss/saas-starter-kit/tree/master/cmd/web-api) - Publicly accessible web
|
||||
API and documentation.
|
||||
|
||||
|
||||
The `Dockerfile` for both services is defined as [multi-stage build](https://docs.docker.com/develop/develop-images/multistage-build/)
|
||||
that includes building a base layer, running unittests and compiling the go application as static binary. The final
|
||||
layer in the multi-stage uses [alpine:3.9](https://hub.docker.com/_/alpine?tab=description) as its base image and copies
|
||||
in the compiled binary resulting in a docker container that is around 50mbs excluding any additional static assets. It's
|
||||
possible to swap out `alpine:3.9` with [busybox](https://willschenk.com/articles/2019/building_a_slimmer_go_docker_container/)
|
||||
for an even small resulting docker image.
|
||||
|
||||
A service is built using the defined Dockerfile. The resulting image is pushed to
|
||||
[Amazon Elastic Container Registry](https://aws.amazon.com/ecr/).
|
||||
|
||||
Amazon Elastic Container Registry (ECR) is a fully-managed Docker container registry that makes it easy for
|
||||
developers to store, manage, and deploy Docker container images. Amazon ECR is integrated with Amazon Elastic
|
||||
Container Service (ECS) simplifying the development to production workflow.
|
||||
|
||||
A service is configured for deployment in [services.go](https://gitlab.com/saas-starter-kit/oss/devops/blob/master/build/cicd/internal/config/service.go).
|
||||
Services are deployed to [AWS Fargate](https://aws.amazon.com/fargate/) based on the defined task definition.
|
||||
|
||||
AWS Fargate is a compute engine for Amazon ECS that allows you to run containers without having to manage servers or
|
||||
clusters. With AWS Fargate, you no longer have to provision, configure, and scale clusters of virtual machines to
|
||||
run containers.
|
||||
|
||||
If the docker file is a multi-stage build and it contains a stage with the name `build_base_golang`, additional caching will
|
||||
be implemented to reduce build times. The build command assumes for a stage named `build_base_golang` assumes that the
|
||||
stage will run `go mod download` to pull down all package dependencies. The build command computes a checksum for the
|
||||
project go.mod and then executes a docker build that targets the specific stage `build_base_golang`. The built container
|
||||
image is tagged with the go.mod hash and pushed to the projects
|
||||
[GitLab repository](https://docs.gitlab.com/ee/user/project/repository/).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### Functions
|
||||
|
||||
Functions are applications that can be executed in short period of time. The configured function is:
|
||||
|
||||
*
|
||||
|
||||
|
||||
|
||||
An python script for
|
||||
[Datadog Log Collection](https://gitlab.com/geeks-accelerator/oss/devops/tree/master/examples/aws-lambda-python-ddlogs)
|
||||
deployed as a function is provided by the devops project in
|
||||
[examples]((https://gitlab.com/geeks-accelerator/oss/devops/tree/master/examples).
|
||||
|
||||
A function is built using the defined
|
||||
[Dockerfile](https://gitlab.com/geeks-accelerator/oss/devops/blob/master/examples/aws-lambda-python-ddlogs/Dockerfile).
|
||||
|
||||
The `Dockerfile` should use a [lambdaci image](https://hub.docker.com/r/lambci/lambda/) as the base image.
|
||||
|
||||
Lambdaci images provide a sandboxed local environment that replicates the live AWS Lambda environment almost
|
||||
identically – including installed software and libraries, file structure and permissions, environment variables,
|
||||
context objects and behaviors – even the user and running process are the same.
|
||||
|
||||
The build command then uses `docker cp` to extract all files from the resulting container image that are located in
|
||||
`/var/task`. These files are zipped and uploaded to AWS S3 for deployment.
|
||||
|
||||
A function is configured for deployment in [functions.go](https://gitlab.com/geeks-accelerator/oss/devops/blob/master/build/cicd/internal/config/function.go).
|
||||
Functions are deployed to [AWS Lambda](https://aws.amazon.com/lambda/).
|
||||
|
||||
AWS Lambda lets you run code without provisioning or managing servers. You pay only for the compute time you consume
|
||||
- there is no charge when your code is not running.
|
||||
|
||||
|
||||
### Schema Migrations
|
||||
|
||||
_cicd_ includes a minimalistic database migration script that implements
|
||||
[github.com/geeks-accelerator/sqlxmigrate](https://godoc.org/github.com/geeks-accelerator/sqlxmigrate). It provides
|
||||
schema versioning and migration rollback. The schema for the entire project is defined globally and is located inside
|
||||
internal: [internal/schema](https://gitlab.com/geeks-accelerator/oss/devops/tree/master/build/cicd/internal/schema)
|
||||
|
||||
The example schema package provides two separate methods for handling schema migration:
|
||||
* [Migrations](https://gitlab.com/geeks-accelerator/oss/devops/blob/master/build/cicd/internal/schema/migrations.go) -
|
||||
List of direct SQL statements for each migration with defined version ID. A database table is created to persist
|
||||
executed migrations. Upon run of each schema migration run, the migration logic checks the migration database table to
|
||||
check if it’s already been executed. Thus, schema migrations are only ever executed once. Migrations are defined as a
|
||||
function to enable complex migrations so results from query manipulated before being piped to the next query.
|
||||
|
||||
* [Init Schema](https://gitlab.com/geeks-accelerator/oss/devops/blob/master/build/cicd/internal/schema/init_schema.go) -
|
||||
If you have a lot of migrations, it can be a pain to run all them. For example, when you are deploying a new instance of
|
||||
the app into a clean database. To prevent this, use the initSchema function that will run as-if no migration was run
|
||||
before (in a new clean database).
|
||||
|
||||
Another bonus with the globally defined schema is that it enables your testing package the ability to dynamically spin
|
||||
up database containers on-demand and automatically include all the migrations. This allows the testing package to
|
||||
programmatically execute schema migrations before running any unit tests.
|
||||
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Make sure you have a working Go environment. Go version 1.2+ is supported. [See
|
||||
the install instructions for Go](http://golang.org/doc/install.html).
|
||||
|
||||
|
||||
To install _cicd_, simply run:
|
||||
```
|
||||
$ go get geeks-accelerator/oss/saas-starter-kit/build/cicd
|
||||
```
|
||||
|
||||
Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can
|
||||
be easily used:
|
||||
```
|
||||
export PATH=$PATH:$GOPATH/bin
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
_cicd_ requires AWS permissions to be executed locally. For the GitLab CI/CD build pipeline, AWS roles will be used. This
|
||||
user is only nessissary for running _cicd_ locally.
|
||||
|
||||
1. You will need an existing AWS account or create a new AWS account.
|
||||
|
||||
2. Define a new [AWS IAM Policy](https://console.aws.amazon.com/iam/home?region=us-west-2#/policies$new?step=edit)
|
||||
called `saas-starter-kit-deploy` with a defined JSON statement instead of using the visual
|
||||
editor. The statement is rather large as each permission is granted individually. A copy of
|
||||
the statement is stored in the devops repo at
|
||||
[configs/aws-aim-deploy-policy.json](https://gitlab.com/geeks-accelerator/oss/devops/blob/master/configs/aws-aim-deploy-policy.json)
|
||||
|
||||
3. Create new [AWS User](https://console.aws.amazon.com/iam/home?region=us-west-2#/users$new?step=details)
|
||||
called `saas-starter-kit-deploy` with _Programmatic Access_ and _Attach existing policies directly_ with the policy
|
||||
created from step 1 `saas-starter-kit-deploy`
|
||||
|
||||
4. Try running the build for a single service.
|
||||
```bash
|
||||
cicd --env=dev build service --name=aws-ecs-go-web-api --release-tag=testv1
|
||||
```
|
||||
|
||||
4. Try running the deploy for a single service.
|
||||
```bash
|
||||
cicd --env=dev deploy service --name=aws-ecs-go-web-api --release-tag=testv1
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
$ cicd [global options] command [command options] [arguments...]
|
||||
```
|
||||
|
||||
### Global Options
|
||||
|
||||
* Target Environment - __required__
|
||||
|
||||
`--env [dev|stage|prod]`
|
||||
|
||||
* AWS Access Key - optional or can be set via env variable `AWS_ACCESS_KEY_ID`
|
||||
|
||||
`--aws-access-key value`
|
||||
|
||||
* AWS Secret Key - optional, can be set via env variable `AWS_SECRET_ACCESS_KEY`
|
||||
|
||||
`--aws-secret-key value`
|
||||
|
||||
* AWS Region - optional, can be set via env variable `AWS_REGION`
|
||||
|
||||
`--aws-region value`
|
||||
|
||||
* AWS Use Role - optional, can be set via env variable `AWS_USE_ROLE`, when enabled an IAM Role else AWS
|
||||
Access/Secret Keys are required
|
||||
|
||||
* Show help
|
||||
|
||||
`--help, -h`
|
||||
|
||||
* Print the version
|
||||
|
||||
`--version, -v`
|
||||
|
||||
### Commands
|
||||
|
||||
* `build service` - Executes a build for a single service
|
||||
|
||||
```bash
|
||||
$ cicd -env [dev|stage|prod] build service -name NNNNN [command options]
|
||||
```
|
||||
|
||||
Options:
|
||||
```bash
|
||||
--name value, -n value target service, required
|
||||
--release-tag value, --tag value optional tag to override default CI_COMMIT_SHORT_SHA
|
||||
--dry-run print out the build details
|
||||
--no-cache skip caching for the docker build
|
||||
--no-push disable pushing release image to remote repository
|
||||
```
|
||||
|
||||
* `build function` - Executes a build for a single function
|
||||
|
||||
```bash
|
||||
$ cicd -env [dev|stage|prod] build function -name NNNNN [command options]
|
||||
```
|
||||
|
||||
Options:
|
||||
```bash
|
||||
--name value, -n value target function, required
|
||||
--release-tag value, --tag value optional tag to override default CI_COMMIT_SHORT_SHA
|
||||
--dry-run print out the build details
|
||||
--no-cache skip caching for the docker build
|
||||
--no-push disable pushing release image to remote repository
|
||||
```
|
||||
|
||||
* `deploy service` - Executes a deploy for a single service
|
||||
|
||||
```bash
|
||||
$ cicd -env [dev|stage|prod] deploy service -name NNNNN [command options]
|
||||
```
|
||||
|
||||
Options:
|
||||
```bash
|
||||
--name value, -n value target service, one of [aws-ecs-go-web-api]
|
||||
--release-tag value, --tag value optional tag to override default CI_COMMIT_SHORT_SHA
|
||||
--dry-run print out the deploy details
|
||||
```
|
||||
|
||||
* `deploy function` - Executes a deploy for a single function
|
||||
|
||||
```bash
|
||||
$ cicd -env [dev|stage|prod] deploy function -name NNNNN [command options]
|
||||
```
|
||||
|
||||
Options:
|
||||
```bash
|
||||
--name value, -n value target function, required
|
||||
--release-tag value, --tag value optional tag to override default CI_COMMIT_SHORT_SHA
|
||||
--dry-run print out the deploy details
|
||||
```
|
||||
|
||||
* `schema` - Runs the database migration
|
||||
|
||||
```bash
|
||||
$ cicd -env [dev|stage|prod] schema
|
||||
```
|
||||
|
||||
* `help` - Shows a list of commands
|
||||
|
||||
```bash
|
||||
$ cicd help
|
||||
```
|
||||
|
||||
Or for one command:
|
||||
```bash
|
||||
$ cicd build help
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
Build the example service _aws-ecs-go-web-api_
|
||||
```bash
|
||||
$ cicid --env=dev build service --name=aws-ecs-go-web-api --release-tag=testv1 --dry-run=false
|
||||
```
|
||||
|
||||
Deploy the example service _aws-ecs-go-web-api_
|
||||
```bash
|
||||
$ cicid --env=dev deploy service --name=aws-ecs-go-web-api --release-tag=testv1 --dry-run=false
|
||||
```
|
||||
|
||||
|
||||
## Join us on Gopher Slack
|
||||
|
||||
If you are having problems installing, troubles getting the project running or would like to contribute, join the
|
||||
channel #saas-starter-kit on [Gopher Slack](http://invite.slack.golangbridge.org/)
|
Reference in New Issue
Block a user