Prepare the infrastructure

Requirements

  • GitLab;

  • Linux host to install the GitLab Runner, featuring:

  • Argo CD.

Installing the GitLab Runner

Follow official instructions to install the GitLab Runner on your dedicated host.

Installing werf

To install werf on the GitLab Runner host, run the following command:

curl -sSL https://werf.io/install.sh | bash -s -- --ci

Registering the GitLab Runner

Follow official instructions to register GitLab Runner in GitLab: set Shell as the executor. Once the registration is complete, you may want to perform additional GitLab Runner configuration.

Configuring the container registry

Enable garbage collection for your container registry.

Preparing the system for cross-platform building (optional)

This step only needed to build images for platforms other than host platform running werf.

Register emulators on your system using qemu-user-static:

docker run --restart=always --name=qemu-user-static -d --privileged --entrypoint=/bin/sh multiarch/qemu-user-static -c "/register --reset -p yes && tail -f /dev/null"

Installing Argo CD Image Updater

Install Argo CD Image Updater with the “continuous deployment of OCI Helm chart type application” patch:

kubectl apply -n argocd -f https://raw.githubusercontent.com/werf/3p-argocd-image-updater/master/manifests/install.yaml

Configure the project

Configuring Argo CD Application

  1. Apply the following Application CRD to the target cluster to deploy a bundle from the container registry:

     kubectl create -f - <<EOF
     ---
     apiVersion: argoproj.io/v1alpha1
     kind: Application
     metadata:
       annotations:
         argocd-image-updater.argoproj.io/chart-version: ~ 1.0
         argocd-image-updater.argoproj.io/pull-secret: pullsecret:myproject-production/myproject-regcred
       name: myproject
       namespace: argocd
       finalizers:
       - resources-finalizer.argocd.argoproj.io
     spec:
       destination:
         namespace: myproject-production
         server: https://kubernetes.default.svc
       project: default
       source:
         chart: myproject
         repoURL: registry.mycompany.org/myproject
         targetRevision: 1.0.0
       syncPolicy:
         automated:
           prune: true
           selfHeal: true
     EOF
    

    The value of argocd-image-updater.argoproj.io/chart-version="~ 1.0" means that the operator must automatically deploy the chart updated to the latest patch version in the SEMVER range 1.0.*.

  2. Create a pull secret to access the project container registry:

     kubectl create -f - <<EOF
     ---
     apiVersion: v1
     kind: Secret
     metadata:
       name: myproject-regcred
       namespace: myproject-production
     type: kubernetes.io/dockerconfigjson
     data:
       .dockerconfigjson: BASE64_DOCKER_CONFIG_JSON
     EOF
    

Configuring the GitLab project

  • Create and save the access token for cleaning up the no longer needed images in the container registry; use the following parameters:

    • Token name: werf-images-cleanup;

    • Role: developer;

    • Scopes: api.

  • Add the following variables to the project variables:

    • Access token to clean up the no longer needed images:

      • Key: WERF_IMAGES_CLEANUP_PASSWORD;

      • Value: <"werf-images-cleanup" access token you saved earlier>;

      • Protect variable: yes;

      • Mask variable: yes.

    • kubeconfig encoded in base64, used to access the Kubernetes cluster:

      • Key: WERF_KUBECONFIG_BASE64;

      • Value: <base64-encoded contents of your kubeconfig file>;

      • Protect variable: yes (if the cluster is used only in protected branches);

      • Mask variable: yes.

  • Add a scheduled nightly task to clean up the no longer needed images in the container registry and set the main/master branch as the Target branch.

Configuring CI/CD of the project

This is what the repository that uses werf for building and deploying might look like:

.helm
app
.gitlab-ci.yml
werf.yaml
stages:
  - release
  - cleanup

default:
  before_script:
    - source $(~/bin/trdl use werf 2 stable)
    - source $(werf ci-env gitlab --as-file)
  tags: ["<GitLab Runner tag>"]

Build and publish release:
  stage: release
  script:
    - werf bundle publish --tag "1.0.${CI_PIPELINE_ID}"
  only:
    - main
  except:
    - schedules

Cleanup registry:
  stage: cleanup
  script:
    - werf cr login $WERF_REPO
    - werf cleanup
  only:
    - schedules

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      containers:
      - name: app
        image: {{ .Values.werf.image.app }}

apiVersion: v1
kind: Service
metadata:
  name: app
spec:
  selector:
    app: app
  ports:
  - name: app
    port: 80

FROM node

WORKDIR /app
COPY . .
RUN npm ci

CMD ["node", "server.js"]

{
  "name": "app",
  "version": "1.0.0",
  "lockfileVersion": 2,
  "requires": true,
  "packages": {
    "": {
      "name": "app",
      "version": "1.0.0"
    }
  }
}

{
  "name": "app",
  "version": "1.0.0",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  }
}

const http = require('http');

const hostname = '127.0.0.1';
const port = 80;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

configVersion: 1
project: myproject
---
image: app
dockerfile: Dockerfile
context: ./app

Working with sources locally
git clone https://github.com/werf/website
cp -rf website/examples/configurator/ci-cd/simple/argocd-with-gitlab-ci-cd/host-runner/linux/docker example
cd example
git init
git add .
git commit -m-

Extras:

  • Add authorization options for werf cleanup in the container registry by following the instructions;
  • See the authentication guide for more information on accessing the Kubernetes cluster.