Continuous deployment of containerized applications using GitLab
GitLab
This tutorial describes:
- Building an application into a Docker container.
- Deploying an application from a container in a Managed Service for Kubernetes cluster via GitLab using the Nebius AI tools.
Each commit to GitLab is followed by:
- Running a script that includes steps to build the Docker image.
- Applying a new Managed Service for Kubernetes cluster configuration specifying the application to deploy.
To set up the infrastructure needed to store the source code, build the Docker image, and deploy your applications, follow these steps:
If you no longer need the created resources, delete them.
Prepare your cloud
Go to the management console
Install additional dependencies
To run the script, install the following in the local environment:
- Nebius AI command line interface (Nebius AI CLI).
- The
jq
JSON stream processor . - The Helm package manager
.
Create Managed Service for Kubernetes and Container Registry resources
-
Create a Managed Service for Kubernetes cluster and a Container Registry registry.
Create the Managed Service for Kubernetes resources necessary to run the scripts: a cluster and node group.
To store Docker images, you need a Container Registry registry.
-
Create a Managed Service for Kubernetes cluster and a node group with the following settings:
-
Public address:
Auto
.Save the cluster ID: you'll need it in the next steps.
-
-
Save the ID of the registry created: you'll need it in the next steps.
-
-
Install kubectl
and configure it to work with the created cluster.
Get a Kubernetes service account token to authenticate with GitLab
Note
The Kubernetes service account is different from the Identity and Access Management service account.
To get the Kubernetes service account token:
-
Configure the local environment to work with the created Kubernetes cluster:
ncp managed-kubernetes cluster get-credentials <cluster ID or name> --external
-
Save the specification for creating a Kubernetes service account to a YAML file named
gitlab-admin-service-account.yaml
:gitlab-admin-service-account.yaml--- apiVersion: v1 kind: ServiceAccount metadata: name: gitlab-admin namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gitlab-admin roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: gitlab-admin namespace: kube-system
-
Create a service account:
kubectl apply -f gitlab-admin-service-account.yaml
-
Retrieve the service account token:
kubectl -n kube-system get secrets -o json | \ jq -r '.items[] | select(.metadata.name | startswith("gitlab-admin")) | .data.token' | \ base64 --decode
-
Save the token: you need it for the next steps.
Create a GitLab instance
Launch GitLab on a VM with a public IP.
-
On the folder page in the management console
, click Create resource and select Virtual machine instance. -
In the Name field, enter the VM name as follows:
ci-tutorial-gitlab
. -
Select an availability zone to place your VM in.
-
Under Image/boot disk selection, go to the Cloud Marketplace tab and click Show more. In the window that opens, select GitLab as your image and click Use.
-
Under Computing resources, specify the following configuration:
- vCPU:
4
- Guaranteed vCPU performance:
100%
- RAM:
8 GB
- vCPU:
-
Under Network settings:
- In the Public IP field, select the checkbox.
-
Under Access, specify the information required to access the instance:
-
Enter the username in the Login field.
Alert
Do not use the
root
username or other names reserved by the operating system. To perform operations that require superuser permissions, use thesudo
command. -
In the SSH key field, paste the contents of the public key file. You need to create a key pair for the SSH connection yourself. To learn how, see Connecting to a VM via SSH.
-
-
Click Create VM.
It may take a few minutes to create the VM. When the VM changes its status to RUNNING
and GitLab starts, you can proceed to setup.
Configure GitLab
To configure GitLab and enable Continuous Integration (CI), create a new project and enter the CI authorization parameters:
-
On the Compute Cloud page, select the created VM and copy its public IP.
-
Connect to the VM via SSH.
-
Get the GitLab administrator password using the following VM command:
sudo cat /etc/gitlab/initial_root_password
-
Copy the password (without spaces) from the
Password
row to the clipboard or a separate file. -
In the browser, open a link in the format
http://<public VM IP address>
. The GitLab web interface will open. -
Log in using the administrator account:
- Username or email:
root
. - Password: The previously copied password.
If you are unable to log in, reset the administrator account password
. - Username or email:
-
Log in to the system again using the administrator account and the new password.
-
Select Create a project.
-
Set the project name:
gitlab-test
. -
Click Create project.
Create a test application
Create a test application that can be deployed in a Managed Service for Kubernetes cluster:
- Add
Dockerfile
to the project:-
Log in to GitLab.
-
On the home page, select a repository.
-
Select the Repository → Files section.
-
Click + and select New file from the drop-down menu.
-
Name the file as
Dockerfile
and add the following code to it:FROM alpine:3.10 CMD echo "Hello"
-
Add a comment to the commit in the Commit message field:
Dockerfile for test application
. -
Click Commit changes.
-
- Add the manifest for the Managed Service for Kubernetes cluster resources to the project:
-
Select the Repository → Files section.
-
Click + and select New file from the drop-down menu.
-
Name the file as
k8s.yaml
:apiVersion: v1 kind: Namespace metadata: name: hello-world --- apiVersion: apps/v1 kind: Deployment metadata: name: hello-world-deployment namespace: hello-world spec: replicas: 1 selector: matchLabels: app: hello template: metadata: namespace: hello-world labels: app: hello spec: containers: - name: hello-world image: cr.ai.nebius.cloud/<registry ID>/hello:__VERSION__ imagePullPolicy: Always
-
In the
<registry ID>
field, specify the ID of the registry that you created previously. -
Add a comment to the commit in the Commit message field:
Docker image deployment config
. -
Click Commit changes.
-
Create a GitLab Runner
To run build tasks in the Managed Service for Kubernetes cluster, create a GitLab Runner
-
Connect a Helm repository containing the GitLab Runner distribution.
helm repo add gitlab https://charts.gitlab.io
-
Retrieve the GitLab Runner settings:
- Open the GitLab administration panel in the browser:
- If the GitLab has been deployed on a Compute Cloud VM instance, use its public IP.
- If the GitLab has been deployed in Managed Service for GitLab, use the instance FQDN.
- Select the project named
gitlab-test
. - On the left-hand side of the resulting window, click Settings and select the CI/CD option.
- Under Runners, click Expand.
- Save the
URL
and theregistration token
values as you will need them in the next step.
- Open the GitLab administration panel in the browser:
-
Create a file called
values.yaml
with the GitLab Runner settings:values.yaml--- imagePullPolicy: IfNotPresent gitlabUrl: <Public IP of the VM or the Managed Service for GitLab instance FQDN> runnerRegistrationToken: "<registration token>" terminationGracePeriodSeconds: 3600 concurrent: 10 checkInterval: 30 sessionServer: enabled: false rbac: create: true clusterWideAccess: true podSecurityPolicy: enabled: false resourceNames: - gitlab-runner runners: config: | [[runners]] [runners.kubernetes] namespace = "{{.Release.Namespace}}" image = "ubuntu:20.04" privileged = true
-
Install GitLab Runner using the following command:
helm install --namespace default gitlab-runner -f values.yaml gitlab/gitlab-runner
-
Wait for the GitLab Runner status to change to
Running
:kubectl get pods -n default | grep gitlab-runner
Now you can run automated builds inside your Kubernetes cluster.
For more information about installing and running GitLab Runner, see the GitLab documentation
Configure a Docker image build and deployment from CI
-
Create the GitLab environment variables
.-
Go to Settings in the left-hand GitLab panel and select CI/CD from the drop-down list.
-
Click Expand next to Variables.
-
Add two environment variables:
-
KUBE_URL
: Kubernetes master address. Retrieve it using this command:ncp managed-kubernetes cluster get <Kubernetes cluster ID or name> --format=json \ | jq -r .master.endpoints.external_v4_endpoint
-
KUBE_TOKEN
: Token that will use GitLab to apply the configuration. Use the token that you received previously.
To add a variable:
- Click Add variable.
- In the window that opens, enter the variable name in the Key field and the value in the Value field.
- Click Add variable.
-
-
-
GitLab enables you to configure build scripts
in a YAML file. Create a configuration file named.gitlab-ci.yml
:-
On the left-hand panel in GitLab, select Repository and click the Files tab.
-
To the right of the project name, click + and select New file from the drop-down menu.
-
Name the file
.gitlab-ci.yml
. Add the steps to build and push a Docker image and update the application configuration in the Kubernetes cluster:stages: - build - deploy build: stage: build image: name: gcr.io/kaniko-project/executor:debug entrypoint: [""] script: - mkdir -p /kaniko/.docker # Install jq. - wget -O jq https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 && chmod +x ./jq && cp jq /kaniko # Get a service account token from metadata. - wget --header Metadata-Flavor:Google 169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token && cp token /kaniko - echo "{\"auths\":{\"cr.ai.nebius.cloud\":{\"auth\":\"$(printf "%s:%s" "iam" "$(cat /kaniko/token | ./jq -r '.access_token')" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json - >- /kaniko/executor --context "${CI_PROJECT_DIR}" --dockerfile "${CI_PROJECT_DIR}/Dockerfile" --destination "cr.ai.nebius.cloud/<registry ID>/hello:gitlab-$CI_COMMIT_SHORT_SHA" # Delete the metadata file. - rm /kaniko/token deploy: image: gcr.io/cloud-builders/kubectl:latest stage: deploy script: - kubectl config set-cluster k8s --server="$KUBE_URL" --insecure-skip-tls-verify=true - kubectl config set-credentials admin --token="$KUBE_TOKEN" - kubectl config set-context default --cluster=k8s --user=admin - kubectl config use-context default - sed -i "s/__VERSION__/gitlab-$CI_COMMIT_SHORT_SHA/" k8s.yaml - kubectl apply -f k8s.yaml
-
In the given file, replace the
<registry ID>
with the ID of your previously created registry. -
Add a comment to the commit in the Commit message field:
CI scripts
. -
Click Commit changes.
In the
.gitlab-ci.yml
file, the following two steps of project build are described:- Build a Docker image using the
Dockerfile
from the previous step and push the image to Container Registry.- For this step, use your container for building Docker images and start a Docker server as a GitLab service
. - To get authentication credentials from the VM metadata, use an auxiliary public Docker image
cr.ai.nebius.cloud/yc/metadata-token-docker-helper:0.2
. It runs an internal Docker credential helper that obtains a Identity and Access Management token from the metadata service.
- For this step, use your container for building Docker images and start a Docker server as a GitLab service
- Set up an environment to work with Kubernetes and apply
k8s.yaml
configurations to Kubernetes clusters. This way the application is deployed on the previously created cluster.
-
-
After saving the file, the build script starts. To track its progress, in the drop-down menu, select CI/CD → Pipelines. Wait until both build steps are complete.
-
Check the results in the container logs in the Kubernetes cluster:
kubectl logs deployment/hello-world-deployment -n hello-world
Result:
Hello
Delete the resources you created
Some resources are not free of charge. Delete the resources you no longer need to avoid paying for them:
-
Delete the Managed Service for Kubernetes cluster and Container Registry registry:
-
Delete the GitLab VM that you created.