Adding Kubernetes Clusters to GitLab Instances using Ansible

16th November 2020·3 min read

Hey there,

I wanted to quickly share an automation step that you might want to find useful in your Ansible Playbooks. It’s about adding a Kubernetes cluster to a Gitlab instance (eg installed via Omnibus) using Ansible.

The documentation tells you about a lot of manual steps to do it, but one can also do it via the API and a couple of shell scripts in Ansible.


You need only two things:

  • kubectl should be installed and ready to talk with the Kubernetes cluster you want to integrate
  • the Gitlab API should be available under a valid domain name, although localhost:port would also work


Effectively it’s a four step process:

  1. add a new admin token to the instance (can be skipped if already exists)
  2. adding the service account and cluster role bindings to the K8s cluster
  3. retrieve the k8s api url, certificate and token
  4. register using the gitlab API

Ansible Script

Before we start, it needs two files to run: namely gitlab-admin-service-account.yaml and gitlab_add_k8s.j2 template.

The first looks like that, but can ultimately come from the documentation:

apiVersion: v1
kind: ServiceAccount
  name: gitlab
  namespace: kube-system
kind: ClusterRoleBinding
  name: gitlab-admin
  kind: ClusterRole
  name: cluster-admin
  - kind: ServiceAccount
    name: gitlab
    namespace: kube-system

The latter just encodes the REST request body, which is akin to what is documented in the API documentation:


Here’s the full script:

- name: integrate gitlab with kubernetes
  hosts: all
  become: true
    gitlab_admin_token: 'SUPER_SeCuRE_P4SSWORD_1237'
    gitlab_url: "https://{{ gitlab_domain }}"
    - name: install railties
        pkg: ruby-railties
    - name: add admin token
      become: true
      shell: |
          echo "token = User.find_by_username('root').personal_access_tokens.create(scopes: [:api, :sudo], name: 'Automation token'); token.set_token('{{ gitlab_admin_token }}');!" | gitlab-rails console --environment=production
    - name: store k8s api url
      shell: kubectl config view -o jsonpath='{.clusters[0].cluster.server}'
      register: k8s_api_url
    - name: add service account
      shell: kubectl apply -f gitlab-admin-service-account.yaml
    - name: set token secret
      shell: |
        SECRET_NAME=$(kubectl -n kube-system get secret -o name | grep gitlab)
        kubectl -n kube-system get ${SECRET_NAME} -o jsonpath="{['data']['token']}" | base64 -d
      register: k8s_gitlab_token
    - name: store k8s certificate
      shell: kubectl get secrets -o=name | xargs kubectl get -o jsonpath="{['data']['ca\.crt']}" | base64 -d | sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g'
      register: k8s_cert
    - name: add k8s cluster to gitlab
        url: "{{gitlab_url}}/api/v4/admin/clusters/add"
        method: POST
        body_format: json
        return_content: yes
        status_code: [201]
          Private-Token: "{{ gitlab_admin_token }}"
          Accept: application/json
          Content-Type: application/json
        body: "{{ lookup('template', './gitlab_add_k8s.j2') }}"

The most notable aspect is really how to set the token, let’s take a look at the script with proper Ruby formatting:

token = User.find_by_username('root').personal_access_tokens.create(scopes: [:api, :sudo], name: 'Automation token'); 
token.set_token('{{ gitlab_admin_token }}');!

The whole thing you just pipe into the gitlab-rails console gitlab-rails console --environment=production to persist it in the database.

Bonus: Localhost clusters

If you find yourself having the cluster running on the same host as the gitlab instance (eg for development purposes) you might find yourself hitting that error:

gitlab Import url is blocked: “Requests to the local network are not allowed”

This is somewhat explained in this GitLab issue, the TL;DR; is that it’s a security feature.

You can turn it off however, using the admin token we created above the Ansible script basically just becomes:

- name: allow localhost communication
    url: "{{gitlab_url}}/api/v4/application/settings?allow_local_requests_from_hooks_and_services=true"
        Private-Token: "{{ gitlab_admin_token }}"
    method: PUT

Hope it helps!


Thomas Jungblut

I'm Thomas Jungblut - welcome to my personal blog. Here you'll find a lot of posts around all the things I'm interested in writing about. Big Data, Bulk Synchronous Parallel, MapReduce, Machine Learning, Clustering, Graph Theory, Natural Language Processing, Computer Science and Open Source in general.

© Thomas Jungblut 2021. Built with Gatsby