Deploying K3s with Ansible - Part 7
Deploying Gitlab with Helm Charts
In the previous posts, we create VMs for a k3s cluster, deployed the k3s cluster, added traefik for proxying requests to service, added cert-manager to handle issuing certifications from LetsEncrypt, deployed the Rancher-UI and installed Longhorn for persistent storage across our nodes, and configured hostname overrides on unbound dns service running on my OPNsense firewall.
I wanted to host gitlab internally as well so I checked out their documentation to see what was needed and how to setup the helm chart values to work with traefik. You can look at those for your self here. Like the Rancher UI the Gitlab deployment uses its own ingress proxy with nginx. Leaving the defaults works, but I would have to manage that ingress separately and if I want to make it public I would not be able to ports 443 to both traefik and nginx.
Ansible Playbook for gitlab
Nothing new here I am using the same workflow as before. This is a role that is placed in ./roles/install-gitlab/tasks/main.yml
.
- Start by adding the helmchart to your helm repo.
- Create a new namespace for gitlab.
- Install gitlab
- Create a middleware for the namespace
- Apply the ingress route for gitlab in the namespace.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
---
- block:
- name: Add gitlab Helm repository
kubernetes.core.helm_repository:
name: gitlab
repo_url: https://charts.gitlab.io/
- name: Update Helm repositories
kubernetes.core.helm_repository:
name: gitlab
repo_url: https://charts.gitlab.io/
force_update: yes
- name: Create gitlab namespace
kubernetes.core.k8s:
api_version: v1
kind: Namespace
name: gitlab
state: present
- name: Install gitlab-staging Helm chart
kubernetes.core.helm:
name: gitlab
chart_ref: gitlab/gitlab
release_namespace: gitlab
values: "{{ staging_gitlab_values }}"
state: present
- name: Apply default headers
kubernetes.core.k8s:
state: present
definition: "{{ lookup('template', 'default-headers.j2') }}"
- name: Apply Traefik-Gitlab staging ingress
community.kubernetes.k8s:
state: present
definition: "{{ lookup('template', 'staging-ingress.j2') }}"
register: ingress_output
tags: staging-install
Gitlab Helm Values
Finding the correct helm values was a little tricky, but they are all listed here. The important stuff that we need to make changes to are below.
gitlab global
- You need to set the root domain so this would be homelab.example.com
- edition comes defaulted to enterprise edition and we are not paying for this so change it to community edition
- ingress is enabled, but the provider is traefik and the class is the traefik-external we setup in the begining.
- annotations for the ingress that we will have a certificate, it will be on port 443 and the entrypoint will be websecure. Again this was something created with the installation of traefik at the beginning.
- Cert-Manager is already installed and gitlab helm does not need to manage any certificates for the ingress.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
staging_gitlab_values:
global:
hosts:
domain: "{{ commonname | replace('*.', '') }}"
edition: ce
ingress:
enabled: true
provider: traefik
class: traefik-external
annotations:
kubernetes.io/tls-acme: true
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.entrypoints: websecure
configureCertmanager: false
additional gitlab settings
- Cert-Manager is already installed
- certmanager-issuer we will use our cloudflare email
- nginx is set to false so it is not installed
- postgresql image can be changed to a different version, but this is the recommended version for this helm chart.
- persistence is enabled and it will use the longhorn application for this storage.
- Registry, minio, gitlab, gitlab-pages, and webservice are all seperate services we will need to create ingress routes for. The helm chart needs to be informed of this and the certificate we intend to use. So use the secret name we setup for staging to validate this all works.
- The toolbox configuration ensures that there is one instance of the GitLab Toolbox component running and that it is scheduled on a different node than instances of the Gitaly component to improve fault tolerance and reliability of the GitLab deployment. ```yaml
staging_gitlab_values: certmanager: install: false certmanager-issuer: email: “{{ cf_email }}” nginx-ingress: enabled: false postgresql: image: tag: 13.6.0 persistence: enabled: true gitaly: enabled: true storageClassName: my-gitaly-storage # CUSTOM - Required for separately managed certmanager registry: ingress: tls: secretName: “{{ staging_secret }}” minio: ingress: tls: secretName: “{{ staging_secret }}” gitlab: gitlab-pages: ingress: tls: secretName: “{{ staging_secret }}” webservice: ingress: path: tls: secretName: “{{ staging_secret }}” toolbox: replicas: 1 antiAffinityLabels: matchLabels: app: ‘gitaly’
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
### Default headers and Ingress Route
The last two tasks in this playbook are apply the default headers middleware from the Traefik playbook, but in the gitlab namespace. The ingress route is where what hostname gets routed to which service.
Default Headers
```yaml
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: default-headers
namespace: gitlab
spec:
headers:
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 15552000
customFrameOptionsValue: SAMEORIGIN
customRequestHeaders:
X-Forwarded-Proto: https
IngressRoute: There is one configuration for each service that gitlab uses - ./roles/install-gitlab/templates/staging-ingress.j2
- gitlab main website or web service
- MinIO in GitLab serves as a scalable and reliable object storage solution, enabling efficient storage and management of artifacts, backups, and other data generated and consumed by GitLab instances.
- GitLab Container Registry serves as a centralized repository for storing Docker images used in GitLab projects, providing seamless integration with CI/CD pipelines, facilitating collaboration and sharing, and offering security and access control features to manage container image storage effectively.
- SSH service in GitLab plays a crucial role in enabling secure communication and authentication for Git operations, providing a reliable and secure method for users to interact with GitLab repositories and for CI/CD pipelines to execute tasks securely.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: gitlab
namespace: gitlab
annotations:
kubernetes.io/ingress.class: traefik-external
spec:
entryPoints:
- websecure
- web
routes:
- match: Host(`gitlab.{{ install_domain }}`) && PathPrefix(`/admin/sidekiq`)
kind: Rule
services:
- name: gitlab-webservice-default
port: 8080
- match: Host(`gitlab.{{ install_domain }}`)
kind: Rule
services:
- name: gitlab-webservice-default
port: 8181
middlewares:
- name: default-headers
namespace: gitlab
tls:
secretName: {{ staging_secret }}
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: minio
namespace: gitlab
annotations:
kubernetes.io/ingress.class: traefik-external
spec:
entryPoints:
- websecure
routes:
- match: Host(`minio.{{ install_domain }}`)
kind: Rule
services:
- name: gitlab-minio-svc
port: 9000
tls:
secretName: {{ staging_secret }}
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: registry
namespace: gitlab
annotations:
kubernetes.io/ingress.class: traefik-external
spec:
entryPoints:
- websecure
routes:
- match: Host(`registry.{{ install_domain }}`)
kind: Rule
services:
- name: gitlab-registry
port: 5000
tls:
secretName: {{ staging_secret }}
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
name: gitlab-ssh
namespace: gitlab
annotations:
kubernetes.io/ingress.class: traefik-external
spec:
entryPoints:
- gitlab-ssh
routes:
- match: HostSNI(`*`)
kind: Rule
services:
- name: gitlab-gitlab-shell
port: 22
Getting SSH to work with Traefik took me a minute to figure out. The missing piece was not the ingress route but understanding that I needed to create an entry point that I could use before this would work with Traefik. If you recall when setting up traefik I mentioned this piece. Make sure that your traefik_values included this section called gitlab-ssh.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ports:
web:
redirectTo:
port: websecure
priority: 10
websecure:
tls:
enabled: true
gitlab-ssh:
port: 22
expose: true
exposedPort: 22
protocol: TCP
Once all of these are in place you should be ready to install gitlab.