ANZ technical zeyu
assuming you are familiar with git (and already have git installed and configured
git clone https://github.com/Shuliyey/technical-tests.git
cd technical-tests
below terminal applications/tools needs to be installed
- bash
- docker
- make
- curl
- git
- go
- terraform (
>=1.3.0
, https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli) - kubernetes-cli (kubectl, https://kubernetes.io/docs/tasks/tools/)
- gcloud (e.g debian distro
sudo apt-get install google-cloud-sdk
, https://cloud.google.com/sdk/docs/install) - gke-gcloud-auth-plugin (e.g debian distro
sudo apt-get install google-cloud-sdk-gke-gcloud-auth-plugin
, https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke)
The finalised Dockerfile
is available at Dockerfile
- multi-stage build
- the
builder
section is responsible for producing the final application binary/app/golang-test
- the final docker image uses
alpine
as the minimal based image and port the final application/app/golang-test
produced by thebuilder
section. This keeps the final image at its minimum, as the runtime image doesn't need the full dependency for building the application (golang packages dependent libraries along side with the application into a single executable binary)
- the
- cache optmisation
Dockerfile
structure has been designed to achieve cache optmisation as it puts the static defined steps before the dynamic dependend steps, meaning the static steps will be cached for optmisation
for more details on
- cicd - branching strategy, versioning, release page, github actions and etc.
- testing - unit testing, lint test
- running/building the application locally
- dockerization on the application
refer to q2-application-containerisation-and-cicd-pipeline
- generate info - generates the application related information (e.g
version
,lastcommitsha
,description
and etc)
make info.generate
- test - runs lint and unit test
make go.test
- run locally - runs application on local workstation
make go.run
- build locally - builds application on local workstation
make go.build
- build docker image - builds docker image locally with certain convention (e.g uses default
short git commit sha
as<tag>
), behaviour can be altered based on environment variables.
make docker.build
- run docker image - runs docker image locally with certain convention (e.g uses binds to port
8000
on host workstation), behaviour can be altered based on environment variables.
make docker.run
Note: make sure the HOST_PORT
is available and not in use by other processes
there'll be message indicating the local url
to visit (running in local mode (docker run), visit app at localhost:HOST_PORT
/version), below is an example
cicd pipeline is implemented in github actions, pipeline is defined in .github/workflows/go.yml
quick overview of github-actions
on:
defines set of github events that will trigger the pipeline
on:
push:
branches:
- '*/*'
- master
tags:
- v*
pull_request:
branches:
- master
In our case above, the pipeline will trigger on push event matching branch */*
or master
and matchings tags v*
, pull_request event against destination branch master
jobs:
defines a set of jobs that will get triggered.
jobs:
golang:
name: Golang Pipline
runs-on: ubuntu-latest
In our case above golang
job will be triggered and it runs on ubuntu-latest
vm
steps:
defines a sequence of steps to be run in order
- name: Publish to Github Registry
id: publish-github-registry
uses: elgohr/Publish-Docker-Github-Action@v5
env:
GO_VERSION: 1.20.2
ALPINE_VERSION: 3.17
with:
name: ${{ steps.calculate-docker-info.outputs.repository }}/app2
registry: docker.pkg.github.com
username: ${{ steps.calculate-docker-info.outputs.actor }}
password: ${{ github.token }}
buildargs: GO_VERSION,ALPINE_VERSION
tags: ${{ steps.calculate-docker-info.outputs.tags }}
cache: ${{ github.event_name != 'schedule' }}
if: contains(github.ref, 'refs/tags/v') || contains(github.ref, 'refs/heads/master')
In our case above, the step have id publish-github-registry
and reuses elgohr/Publish-Docker-Github-Action@v5
github-action template (this is a github repo available at elgohr/Publish-Docker-Github-Action), with:
condition defines set of parameters to be passed to the github-action template, lastly if:
condition defines the criteria that must match (or else the step will be skipped)
list of triggered pipelines can be visited on the repo's github-actions page (https://github.com/Shuliyey/technical-tests/actions)
below are three examples of triggered pipelines
- 456994692 (on push to
master
branch) - 456989568 (on push to
'*/*'
branch) - 456992006 (on pull_request to
master
branch) - 456898515 (on push
'v*'
tags)
#4 is an example pull requests (github-actions pipeline will runs a set of test to ensure quality of the pull request before it is merged to master
(the "stable" branch), preventing bad code gets merged to "stable" master
branch)
assuming your local kubectl
is already pointing to the desired kubernetes context (this can be verified through kubectl config current-context
)
- deploy application manifests to kubernetes
make k8s.deploy
there'll be a section (like below) indicating the endpoint to visit the application and more information such as tailing the application service logs
- remove application manifests from kubernetes
make k8s.delete
- more info refer to extra-deployments-kubernetes (note: the
make k8s.deploy
andmake k8s.delete
are self explanatory and does the creation and removal of the required application resources on kubernetes, this is just for more reference)
IMPORTANT NOTE: DO NOT RUN THIS IN WELL ESTABLISHED GCP PROJECT, RUN THIS IN DUMMY GCP PROJECT, TERRAFORM CODE INCLUDE ENABLEMENT OF GOOGLE APIS THROUGH google_project_service
, WHEN TERRAFORM DESTROY IS RUN, IT COULD DELETE EXISTING GOOGLE APIS THAT'S ENABLED THROUGH OTHER METHODS
assuming your local gcloud
/terraform
is set up correctly (gcloud auth login
, gcloud auth application-default login
)
- spin up GKE infrastructure
make terraform.apply
- tear down GKE infrastructure
make terraform.destroy
- more info refer to bonus-infrastructure-terraform (note: the
make terraform.apply
andmake terraform.destroy
are self explanatory and does the creation and removal of the required application resources on kubernetes, this is just for more reference)
doing all of above with one command
- spin up GKE infrastructure and deploy application to GKE
TF_VAR_project="<project>" make up
- delete application from GKE and tear down GKE infrastructure
TF_VAR_project="<project>" make down
- https://github.com/features/packages
- https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions
- https://github.community/t5/GitHub-Actions/set-output-Truncates-Multiline-Strings/td-p/37870
- https://docs.github.com/en/actions/using-jobs/defining-outputs-for-jobs
- https://help.github.com/cn/actions/reference/contexts-and-expression-syntax-for-github-actions
- https://github.community/t5/GitHub-Actions/run-step-on-if-branch-tag-is/td-p/38874
- https://github.com/actions/upload-artifact
- https://github.com/actions/create-release
- https://github.com/actions/upload-release-asset
- https://github.com/marketplace/actions/publish-docker
- https://github.community/t5/GitHub-Actions/Github-Actions-CI-CD-pipeline-branch-gt-master-gt-release-tag/td-p/29924
- https://kubernetes.io/docs/tutorials/stateful-application/zookeeper/#tolerating-node-failure
- https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
- https://kubernetes.io/docs/tasks/administer-cluster/namespaces-walkthrough/
- https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/
- https://www.freeformatter.com/mime-types-list.html
- https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
- https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli
- https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_firewall
- https://discuss.hashicorp.com/t/how-to-show-sensitive-values/24076/8
- https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/container_cluster
- https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_subnetwork#nested_secondary_ip_range
- https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_network