Newer
Older
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# CI/CD sur Openshift
## Runner
Pour créer un runner capable de déployer nos applications, il faut en faire la demande à partir du [Manager Openshift Synaaps](https://manager.apps.grandlyon.com/), dans la partie `Gestion des runners GITLAB`.
- Vers quel git le runner doit-il pointer => forge.grandlyon.com (GITLAB SYNAAPS)
- Nom du projet git pointé => nom du projet (sert à identifier le runner)
- Token Git => le registration token obtenu sur la forge
- Pour un projet : Settings > CI/CD > Runners > trois petits points à coté de `New project runner`
- Pour un groupe : Build > Runners > trois petits points à coté de `New group runner`
## Variables sur la forge
### Token d'accès au container registry
Pour qu'Openshift puisse lire les images Docker hébergées sur la forge il aura besoin d'un access token avec les droit read_registry et le rôle de Maintainer.
Ce token a été créé au niveau du [groupe Factory](https://forge.grandlyon.com/groups/web-et-numerique/factory/-/runners) sur la forge et sa valeur est contenue dans la variable `READ_REGISTRY_TOKEN`, accessible aux sous-projets.
### KUBECONFIG
Pour que le runner puisse appliquer des déploiements sur un namespace, il lui en faut les droits. Un compte de service nommé `cicd-robot` est créé sur chaque namespace avec le rôle `dock-air-deployer`, ce qui lui donne un certain périmètre d'autorisations.
Depuis la console openshift, se rendre sur `User Management > ServiceAccounts > cicd-robot et cliquer sur Actions > Download kubeconfig file`. Le contenu de ce fichier pourra être donné au runner pour avoir les mêmes autorisations que le compte `cicd-robot`
Le contenu de ce fichier pour les namespace cpd-p01 et cpd-r01 sont stockés dans des variables du groupe Factory sur la forge, respectivement `KUBE_CONFIG_CPD_PROD` et `KUBE_CONFIG_CPD_REC`
## .gitlab-ci.yml
### Cas simple : une seule branche à déployer
On écrit en dur le namespace, l'image à utiliser et l'URL de l'application dans les fichiers de config, exemple du `deployment.yml` de la doc self-data :
```yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: self-data-doc
namespace: ns-cpd-p01-syn
spec:
replicas: 1
selector:
matchLabels:
app: self-data-doc
template:
metadata:
labels:
app: self-data-doc
spec:
containers:
- name: self-data-doc
image: registry.forge.grandlyon.com/web-et-numerique/factory/llle_project/self-data-technical-doc:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
nodeSelector:
node-role.kubernetes.io/worker: ''
imagePullSecrets:
- name: forge-secret
```
Dans le fichier .gitlab-ci.yml, ajouter un stage deploy après celui de build, puis définir un job comme celui-ci (exemple d'un déploiement en prod sur la branche master):
```yaml
deploy_master:
stage: deploy
tags:
- ns-cpd-p01-syn
only:
- master
before_script:
- NAMESPACE=ns-cpd-p01-syn
- export KUBECONFIG=$KUBE_CONFIG_CPD_PROD
script:
- oc create secret -n $NAMESPACE docker-registry forge-secret --docker-server=$CI_REGISTRY --docker-username=forge-secret --docker-password=$READ_REGISTRY_TOKEN --dry-run=client -o yaml | oc apply -f -
- oc apply -f k8s/deployment.yml
- oc apply -f k8s/service.yml
- oc apply -f k8s/route.yml
- oc delete pod -l app=self-data-doc
```
Quelques remarques et explications :
- Le champ `tags` permet de sélectionner le runner à utiliser pour le déploiement (ici: `ns-cpd-p01-syn` pour la PROD)
- la commande `export KUBECONFIG=...` permet de donner les autorisations nécessaires au runner sur le bon namespace selon les variables stockées dans la forge (`$KUBE_CONFIG_CPD_PROD` ou `$KUBE_CONFIG_CPD_REC`)
- la commande `oc create secret ...` créé un secret nommé `forge-secret` dans Openshift basé sur la variable `$READ_REGISTRY_TOKEN` stockée sur la forge pour pouvoir tirer les images
- On utilise `oc apply ...` pour appliquer les différentes parties de l'application
!!! warning "Cette dernière étape entraîne une interruption de l'application le temps que le nouveau pod soit lancé (quelques secondes à une minute selon les cas)"
- La commande `oc delete pod -l app=self-data-doc` supprime un pod d'un déploiement basé sur le label défini dans son fichier de config. Cela a pour effet de forcer Openshift à rafraîchir l'image utilisée pour ce déploiement. Sans cela, le pod n'est pas mis à jour car le tag de l'image n'a pas changé, ce qui ne provoque pas la mise à jour du pod.
### Cas plus complexe : deux branches (recette et production) à déployer
Pour pouvoir paramétrer nos déploiement selon l'environnement ciblé, il faut variabiliser certains éléments dans les fichiers de déploiement. Pour cela on remplace leur valeur par un placeholder compris entre double accolades ex: `{{NAMESPACE}}`. Voici les paramètres à remplacer et leur placeholder associé :
- namespace sur lequel déployer => `{{NAMESPACE}}`
- tag de l'image à déployer => `{{IMAGE_TAG}}`
- url de l'application => `{{HOSTNAME}}`
Exemple du `deployment.yml` de landing page de Mes Papiers :
```yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: mes-papiers-landing-page
namespace: {{NAMESPACE}}
spec:
replicas: 1
selector:
matchLabels:
app: mes-papiers-landing-page
template:
metadata:
labels:
app: mes-papiers-landing-page
spec:
containers:
- name: mes-papiers-landing-page
image: registry.forge.grandlyon.com/web-et-numerique/factory/ma-bulle/mes-papiers-landing-page:{{IMAGE_TAG}}
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
nodeSelector:
node-role.kubernetes.io/worker: ''
imagePullSecrets:
- name: forge-secret
```
Ces placeholders seront remplacés par la commande **sed** par les valeurs correspondantes au moment de la pipeline de déploiement. Il faut mettre à jour le `gitlab-ci.yml` avec les deux jobs suivants :
```yaml
deploy_rec:
stage: deploy
before_script:
- NAMESPACE=ns-cpd-r01-syn
- export KUBECONFIG=$KUBE_CONFIG_CPD_REC
script:
- find k8s/ -name '*.yml' -exec sed -i "s/{{NAMESPACE}}/$NAMESPACE/g" {} \;
- sed -i "s/{{IMAGE_TAG}}/dev/" ./k8s/deployment.yml
- sed -i "s/{{HOSTNAME}}/mespapiers-rec.apps.grandlyon.com/g" ./k8s/route.yml
- oc create secret -n $NAMESPACE docker-registry forge-secret --docker-server=$CI_REGISTRY --docker-username=forge-secret --docker-password=$READ_REGISTRY_TOKEN --dry-run=client -o yaml | oc apply -f -
- oc apply -f k8s/deployment.yml
- oc apply -f k8s/service.yml
- oc apply -f k8s/route.yml
- oc delete pod -l app=mes-papiers-landing-page
tags:
- ns-cpd-r01-syn
only:
- dev
deploy_prod:
stage: deploy
before_script:
- NAMESPACE=ns-cpd-p01-syn
- export KUBECONFIG=$KUBE_CONFIG_CPD_PROD
script:
- find k8s/ -name '*.yml' -exec sed -i "s/{{NAMESPACE}}/$NAMESPACE/g" {} \;
- sed -i "s/{{IMAGE_TAG}}/main/" ./k8s/deployment.yml
- sed -i "s/{{HOSTNAME}}/mespapiers.apps.grandlyon.com/g" ./k8s/route.yml
- oc create secret -n $NAMESPACE docker-registry forge-secret --docker-server=$CI_REGISTRY --docker-username=forge-secret --docker-password=$READ_REGISTRY_TOKEN --dry-run=client -o yaml | oc apply -f -
- oc apply -f k8s/deployment.yml
- oc apply -f k8s/service.yml
- oc apply -f k8s/route.yml
- oc delete pod -l app=mes-papiers-landing-page
tags:
- ns-cpd-p01-syn
only:
- main
```
Quelques remarques et explications supplémentaires par rapport au cas simple :
- On utilise le bon namespace (**r**01-syn vs **p**01-syn) et les bonnes variables selon l'environnement ciblé (**dev** vs **main**)
- La commande `find k8s/ -name '*.yml' -exec sed -i "s/{{NAMESPACE}}/$NAMESPACE/g" {} \;` trouve toutes les occurrences du placeholder `{{NAMESPACE}}` dans les fichiers compris dans le dossier `k8s` et les remplace par la variable `$NAMESPACE` définie dans le `before_script`
- La commande `sed -i "s/{{IMAGE_TAG}}/main/" ./k8s/deployment.yml` remplace l'occurrence du placeholder `{{IMAGE_TAG}}` dans le fichier `k8s/deployment.yml` et la remplace par "main"
- La commande `sed -i "s/{{HOSTNAME}}/mespapiers.apps.grandlyon.com/g" ./k8s/route.yml` remplace l'occurrence du placeholder `{{HOSTNAME}}` dans le fichier `k8s/route.yml` et la remplace par l’environnement cible : "mespapiers.apps.grandlyon.com" vs "mespapiers**-rec**.apps.grandlyon.com"