Skip to content

streamdal/go-svc-template

Repository files navigation

go-svc-template

⚡ Batteries-included Golang microservice template ⚡️

Last updated: 06/11/2024

It includes:

  1. Makefile that is used for run, test, build, deploy actions
  2. Dockerfile for building a Docker image (alpine with multi-stage build)
  3. docker-compose.yml for local dev
  4. Github workflows for PR and release automation
  5. Sane code layout [1]
  6. Structured logging
  7. Good health-checking practices (uses async health-checking)
  8. Sample kubernetes deploy configs
  9. Configurable profiling support (pprof)
  10. Pre-instrumented with New Relic APM
  11. DigitalOcean container registry support

It uses:

  1. Go 1.22
  2. julienschmidt/httprouter for the HTTP router
  3. uber/zap for structured, light-weight logging
  4. alecthomas/kong for CLI args + ENV parsing
  5. newrelic/go-agent for APM (with logging)
  6. streamdal/rabbit for reliable RabbitMQ
  7. onsi/ginkgo and onsi/gomega for BDD-style testing

[1] main.go for entrypoint, deps/deps.go for dependency setup + simple dependency injection in tests, backends and services abstraction for business logic.

Makefile

All actions are performed via make - run make help to see list of available make args (targets).

For example:

  • To run the service, run make run
  • To build + push a docker img, run make docker/build
  • To deploy to staging, run make k8s/deploy/stage <- make sure to switch Kube context to staging!!!
  • To deploy to production, run make k8s/deploy/prod <- make sure to switch Kube context to production!!!

Secrets

Secrets are stored in K8S using their native Secret resource.

You can create them via kubectl:

kubectl create secret generic my-secret --from-literal=secret-key=secret-value

You can then edit it: kubectl edit secret my-secret

NOTE: That the secret values are base64 encoded - when copy/pasting, make sure to decode them first:

echo "dG9vdAo=" | base64 -D
toot

The secrets can be referenced as follows in the deploy config:

env:
  - name: MY_SECRET
    valueFrom:
      secretKeyRef:
        name: my-secret
        key: secret-key

Logging

This service uses a custom logger that wraps uber/zap in order to provide a structured logging interface. While NR is able to collect logs written via uber/zap, it does not include any "initial fields" set on the logger.

This makes it very difficult to create temporary loggers with base values that are re-used throughout a method. For example: In method A that is 100 lines long, we may want to create a logger with a base field "method" set to "A".

That would allow us to use the same logger throughout the method and not have to always include "method=A" attributes in each log message - the field will be included automatically.

The custom log wrapper provides this functionality.

PR and Release

PR and release automation is done via GitHub Actions.

When a PR is opened, a PR workflow is triggered.

When a PR is merged, a Release workflow is triggered. This workflow will build a docker image and push it to the DigitalOcean registry.

Deployment

Deployment is manual. This is done for one primary reason:

A deployment is a critical operation that should be handled with care.

Or in other words, we do not throw deployments over the wall. Just because we can automate them, does not mean we should or will.

Deployments are performed via make k8s/deploy/stage and make k8s/deploy/prod.

Deployments are just kubectl apply -f deploy.stage.yaml under the hood. The image the deployment will use is the CURRENT short git sha in the repo!


Template Usage

  1. Click "Use this template" in Github to create a new repo
  2. Clone newly created repo
  3. Find & replace:
    1. go-svc-template -> lower case, dash separated service name
    2. GO_SVC_TEMPLATE -> upper case, underscore separated service name (for ENV vars)
    3. your_org -> your Github org name
    find . -maxdepth 3 -type f -exec sed -i "" 's/go-svc-template/service-name/g' {} \;
    find . -maxdepth 3 -type f -exec sed -i "" 's/GO_SVC_TEMPLATE/SERVICE_NAME/g' {} \;
    find . -maxdepth 3 -type f -exec sed -i "" 's/your_org/your-org-name/g' {} \;
    mv .github.rename .github

Vendor

This template vendors packages by default to ensure reproducible builds + allow local dev without an internet connection. Vendor can introduce its own headaches though - if you want to remove it, remove -mod=vendor in the Makefile.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published