serveur master : 192.168.60.20
serveur backup : 192.168.60.21
L'installation de Harbor et la configuration de la réplication maître-esclave ne seront pas détaillées ici. Nous nous concentrerons sur la configuration de keepalived.
Tout d'abord, installer keepalived sur les deux serveusr :
yum -y install keepalived
Fichier de configuration
1 ! Configuration File for keepalived
2
3 global_defs {
4 notification_email {
5 admin@domain.local
6 backup@domain.local
7 tech@domain.local
8 }
9 notification_email_from Keepalived@domain.local
10 smtp_server 192.168.100.1
11 smtp_connect_timeout 30
12 router_id HA_CLUSTER_01
13 vrrp_skip_check_adv_addr
14 # vrrp_strict # commenter pour permettre le ping du VIP
15 vrrp_garp_interval 0
16 vrrp_gna_interval 0
17 }
18
19 vrrp_instance VI_1 {
20 state MASTER # Rôle keepalived : MASTER (principal) ou BACKUP (secours)
21 interface ens33
22 virtual_router_id 60 # Identifiant du routeur virtuel (doit être identique entre MASTER et BACKUP)
23 priority 110 # Priorité (0-255, plus élevée = plus prioritaire)
24 advert_int 1
25 authentication { # Configuration de l'authentification
26 auth_type PASS
27 auth_pass secret123
28 }
29 virtual_ipaddress { # Adresses IP virtuelles
30 192.168.60.200/24
31 }
32 }
33
34 virtual_server 192.168.60.200 80 {
35 delay_loop 5
36 lb_algo rr
37 lb_kind NAT
38 persistence_timeout 60
39 protocol TCP
40
41 real_server 192.168.60.20 80 {
42 weight 1
43 TCP_CHECK {
44 connect_timeout 4
45 nb_get_retry 3
46 delay_before_retry 3
47 connect_port 80
48 }
49 }
50 }
Pour le serveur backup, modifier uniquement le rôle et la priorité.
Démarrer le service keepalived :
systemctl start keepalived.service
Vérifier l'attribution de l'adresse virtuelle :
ip addr
Test de basculement en arrêtant le master
Une fois keepalived validé, un script de surveillance peut être ajouté pour optimiser la détection de panne.
Script de détection de référence :
#!/bin/bash
harbor_check=$(netstat -anpt | grep :80 | wc -l)
[ $harbor_check -eq 0 ] && systemctl stop keepalived
Configuration keepalived pour le master
! Configuration File for keepalived
global_defs {
notification_email {
admin@domain.local
backup@domain.local
tech@domain.local
}
notification_email_from Keepalived@domain.local
smtp_server 192.168.100.1
smtp_connect_timeout 30
router_id HA_CLUSTER_01
vrrp_skip_check_adv_addr
# vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_harbor_service {
script "/etc/keepalived/harbor_monitor.sh"
interval 3
weight -3
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 60
priority 110
advert_int 1
authentication {
auth_type PASS
auth_pass secret123
}
track_script {
check_harbor_service
}
virtual_ipaddress {
192.168.60.200/24
}
}
virtual_server 192.168.60.200 80 {
delay_loop 5
lb_algo rr
lb_kind NAT
persistence_timeout 60
protocol TCP
real_server 192.168.60.20 80 {
weight 1
# TCP_CHECK {
# connect_timeout 4
# nb_get_retry 3
# delay_before_retry 3
# connect_port 80
# }
}
}
Configuration keepalived pour le backup
! Configuration File for keepalived
global_defs {
notification_email {
admin@domain.local
backup@domain.local
tech@domain.local
}
notification_email_from Keepalived@domain.local
smtp_server 192.168.100.1
smtp_connect_timeout 30
router_id HA_CLUSTER_01
vrrp_skip_check_adv_addr
# vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script check_harbor_service {
script "/etc/keepalived/harbor_monitor.sh"
interval 3
weight -3
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 60
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass secret123
}
track_script {
check_harbor_service
}
virtual_ipaddress {
192.168.60.200/24
}
}
virtual_server 192.168.60.200 80 {
delay_loop 5
lb_algo rr
lb_kind NAT
persistence_timeout 60
protocol TCP
real_server 192.168.60.21 80 {
weight 1
# TCP_CHECK {
# connect_timeout 4
# nb_get_retry 3
# delay_before_retry 3
# connect_port 80
# }
}
}
keepalived.confProcéder d'abord à l'arrêt de la réplication d'images, puis charger une image sur 192.168.60.20 afin de mieux distinguer le nœud actif via l'interface.
Vérification de l'adresse virtuelle sur le serveur
Arrêt du service Harbor sur le nœud master pour test
Vérification de la migration du VIP sur le serveur backup
La configuration est fonctionnelle.
Notes supplémentaires :
- Pour un accès par nom de domaine sans exposer les adresses IP réelles des serveurs backend, modifier le paramètre hostname dans harbor.yml
Cela évite de révéler les adresses IP backend lors des commandes de pull/push.
- Depuis la version 2.0 de Harbor, les pulls d'images n'affichent pas le numéro de version. Effectuer la configuration suivante :
[root@harbor harbor]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
365a19c83071 goharbor/nginx-photon:v2.1.0 "nginx -g 'daemon of…" 3 days ago Up 19 minutes (healthy) 0.0.0.0:80->8080/tcp nginx
ce931dcc3d3a goharbor/harbor-jobservice:v2.1.0 "/harbor/entrypoint.…" 3 days ago Up 19 minutes (healthy) harbor-jobservice
18a585196b55 goharbor/harbor-core:v2.1.0 "/harbor/entrypoint.…" 3 days ago Up 19 minutes (healthy) harbor-core
84cd91ad2d2d goharbor/harbor-portal:v2.1.0 "nginx -g 'daemon of…" 3 days ago Up 19 minutes (healthy) harbor-portal
039f375ff277 goharbor/registry-photon:v2.1.0 "/home/harbor/entryp…" 3 days ago Up 19 minutes (healthy) registry
d329617fe932 goharbor/harbor-registryctl:v2.1.0 "/home/harbor/start.…" 3 days ago Up 19 minutes (healthy) registryctl
b9a3b01fdf4e goharbor/harbor-db:v2.1.0 "/docker-entrypoint.…" 3 days ago Up 19 minutes (healthy) harbor-db
34f04df78acf goharbor/redis-photon:v2.1.0 "redis-server /etc/r…" 3 days ago Up 19 minutes (healthy) redis
e6fa18c6f576 goharbor/harbor-log:v2.1.0 "/bin/sh -c /usr/loc…" 3 days ago Up 19 minutes (healthy) 127.0.0.1:1514->10514/tcp harbor-log
Accéder au conteneur harbor-portal :
[root@harbor harbor]# docker exec -it 84cd91ad2d2d /bin/bash
nginx [ / ]$ cd /usr/share/nginx/html/
nginx [ /usr/share/nginx/html ]$ ls -l
total 8612
-rw-r--r-- 1 root root 149395 2020-09-16 02:45 3rdpartylicenses.txt
-rw-r--r-- 1 root root 11347 2020-09-16 02:28 LICENSE
-rw-r--r-- 1 root root 375069 2020-09-16 02:45 dark-theme.css
-rw-r--r-- 1 root root 7455 2020-09-16 02:45 favicon.ico
-rw-r-- 3 root root 18 2020-09-16 02:45 i18n
-rw-r-- 2 root root 220 2020-09-16 02:45 images
-rw-r--r-- 1 root root 856 2020-09-16 02:45 index.html
-rw-r--r-- 1 root root 389660 2020-09-16 02:45 light-theme.css
-rw-r--r-- 1 root root 5982703 2020-09-16 02:45 main.50faa391a4ae8743ad63.js
-rw-r--r-- 1 root root 71509 2020-09-16 02:45 polyfills-es5.c04cfdffe6ecc730c69c.js
-rw-r--r-- 1 root root 1440 2020-09-16 02:45 runtime.9ad22a88fcc70a015907.js
-rw-r--r-- 1 root root 860407 2020-09-16 02:45 scripts.f4c015c4300c31a9a23c.js
-rw-r--r-- 1 root root 203 2020-09-16 02:45 setting.json
-rw-r--r-- 1 root root 532512 2020-09-16 02:45 styles.fd4a2ff060f99b077bef.css
-rw-r--r-- 1 root root 148840 2020-09-16 02:35 swagger.json
-rw-r--r-- 1 root root 169645 2020-09-16 02:28 swagger.yaml
-rw-r--r-- 1 root root 63039 2020-09-16 02:35 swagger2.json
-rw-r--r-- 1 root root 13548 2020-09-16 02:35 swagger3.json
nginx [ /usr/share/nginx/html ]$
Copier le fichier main.50faa391a4ae8743ad63.js et quitter le conteneur.
[root@harbor harbor]# find / -name main.50faa391a4ae8743ad63.js
/var/lib/docker/overlay2/8041b6cd2fb0b67619f9ae569d4b7012232c23306727124519e85883f76ec486/diff/usr/share/nginx/html/main.50faa391a4ae8743ad63.js
/var/lib/docker/overlay2/322168b51d2b67ea2bc5226cfe6e61781646a8296045e76c2cd54f2db16bc482/merged/usr/share/nginx/html/main.50faa391a4ae8743ad63.js
[root@harbor harbor]#
Dans le répertoire merged, effectuer une sauvegarde préalable.
[root@harbor harbor]# cp /var/lib/docker/overlay2/322168b51d2b67ea2bc5226cfe6e61781646a8296045e76c2cd54f2db16bc482/merged/usr/share/nginx/html/main.50faa391a4ae8743ad63.js{,.bak}
[root@harbor harbor]# vim /var/lib/docker/overlay2/322168b51d2b67ea2bc5226cfe6e61781646a8296045e76c2cd54f2db16bc482/merged/usr/share/nginx/html/main.50faa391a4ae8743ad63.js
Rechercher la chaîne suivante :
artifactPullCommand
Remplacer le contenu :
t.type===e.type&&(e.pullCommand=t.pullCommand+" "+n.registryUrl+"/"+n.projectName+"/"+n.repoName+"@"+e.digest)
Par :
t.type===e.type&&(e.pullCommand=t.pullCommand+" "+n.registryUrl+"/"+n.projectName+"/"+n.repoName+":"+e.tags[0].name)
Enregistrer et quitter. Aucun redémarrage du conteneur n'est nécessaire, vider le cache du navigateur est recommandé.