Blog de dada

DevOps, bidouilleur et routard plein de logiciels libres

Technologie

Wireguard sur Debian 9

Rédigé par dada / 07 janvier 2019 / 1 commentaire



Heztner, c'est vraiment un hébergeur qui propose un cloud peu cher et performant. Vraiment. Par contre, il n'y a que ça. Jusqu'à peu, nous n'avions pas la possibilité d'ajouter des volumes pour gonfler l'espace disque des machines et pas de réseau privé. Maintenant, les volumes sont là, mais toujours pas de réseau privé. Tant pis, on va le faire à la main.

On m'a parlé de Wireguard : un outil simple, puissant et sécurisé pour monter des VPN entre nos serveurs. J'ai testé, j'approuve. Je n'aime pas le réseau, c'est pas mon truc mais avec Wireguard et mes balades sous Kubernetes, je commence à presque apprécier cette chose.

Voici donc comment mettre en place des connexions privées entre vos machines pour y faire transiter ce que vous voulez sans que ça se balade sur l'Internet mondial.

Installation de Wireguard

Au moment où j'écris ces lignes, l'outil n'est disponible que dans les dépôts unstable. C'est chiant, mais rien de grave.

Ajouter les dépôts installables

# echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable-wireguard.list

Faire un peu de pinning

Pourquoi ? Parce qu'avec le dépôt que vous venez d'ajouter, si vous n'y faites pas attention, vous allez massacrer la stabilité de votre machine.
# printf 'Package: *\nPin: release a=unstable\nPin-Priority: 150\n' > /etc/apt/preferences.d/limit-unstable

Installer les paquets

On va d'abord installer les headers pour permettre à Wireguard de bien s'installer :
apt install linux-headers-$(uname -r)
On peut maintenant installer la bête :
# apt update && apt install wireguard
C'est installé !

Configuration

Exemple simple

On va prendre deux serveurs et on va s'amuser à les interconnecter. Sur les deux machines, nous allons générer les clés privées et publiques :
wg genkey | tee privatekey | wg pubkey > publickey

Configuration de l'interface réseau

Tout va se passer dans le fichier wg0.conf, qui sera placé dans /etc/wireguard/. Sur la première machine, son contenu va ressembler à ça :
# Votre premier serveur
[Interface]
Address = 10.0.42.1
PrivateKey = kEQpUJDtur3yHqtoto42Y0+FXNK5lyJoUhh2g21BFWo= 
ListenPort = 1190

# Votre deuxième serveur
[Peer]
PublicKey = MnL98kIZYrHgopn1U3kptoto42L/8MqgyqKh2g2Hixo=
Endpoint = IP.DE.MON.PEER:1190
AllowedIPs = 10.0.42.2/32
Sur la deuxième machine :
# Votre deuxième serveur
[Interface]
Address = 10.0.42.2
PrivateKey = kEQpUJDtur3yHqtoto42Y0+FXNK5lyJoUhh2g21BFWo= 
ListenPort = 1190

# Votre premier serveur
[Peer]
PublicKey = MnL98kIZYrHgopn1U3kptoto42L/8MqgyqKh2g2Hixo=
Endpoint = IP.DE.MON.PEER:1190
AllowedIPs = 10.0.42.1/32
Non, je n'ai pas changé les clés, la flemme. Pensez quand même à vérifier que vous n'avez pas fait de coquille en copiant/collant tout ça. C'est souvent en se trompant entre les clés qu'on perd un temps fou à déboguer.

Interface

La partie [Interface] porte bien son nom : c'est là que vous allez définir l'IP de la machine sur laquelle vous bossez, configurer sa clé privée et le port qui sera utilisé par Wireguard. Allez récupérer la clé privée générée quelques secondes auparavant et remplacez ma valeur de test.

Peer

La partie [Peer], qui porte aussi bien son nom si on speak l'english, permet de configurer un pair, c'est à dire un serveur distant qui va pouvoir passer par le VPN pour faire des coucous à votre première machine.
Endpoint est à remplir avec la véritable IP de la machine et AllowedIPs doit contenir les IP (ou range) VPN de vos machines clientes. Pas la véritable IP publique.

Tester la connexion

On va activer la connexion en tapant ça sur les deux machines :
root@master:/etc/wireguard# wg-quick up wg0
Vous devriez avoir une réponse, pour le premier serveur, dans le genre :
root@test1:/home/dada# wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip address add 10.0.42.1 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] ip route add 10.0.42.2/32 dev wg0
Et pour le deuxième :
root@test2:/home/dada# wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip address add 10.0.42.2 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] ip route add 10.0.42.1/32 dev wg0
Maintenant, si tout s'est bien passé, vous devriez pouvoir faire des pings sur les IPs VPN des machines !

Démarrer Wireguard avec la machine

Avec systemd :
systemctl enable wg-quick@wg0.service
Ça fait quelques semaines que mon infra tourne avec Wireguard sans le moindre souci de latence, de déconnexion ou de bogue. C'est du bon !

Kubernetes en multi-master sur du baremetal avec HAProxy

Rédigé par dada / 20 décembre 2018 / 6 commentaires



Quand on joue avec Kubernetes, on se rend compte que c'est aussi puissant que fragile. L'orchestration, ça ne s'improvise pas. Il faut vraiment passer des heures à se casser les dents sur des clusters de tests qui finiront toujours par s'écrouler. Que ce soit à cause d'un souci côté hébergeur, entraînant une indisponibilité de votre master ou une configuration laxiste permettant à des pods de consommer plus de ressources que ce qu'il y a de disponible, en massacrant chaque node disponible, méticuleusement, les uns après les autres, jusqu'à vous laisser sans rien.
Je ne parlerai pas ici du meilleur moyen pour contrôler la consommation des pods. On va s'attaquer au premier souci : votre unique master configuré en SPoF.

Le multi-master, ton ami

Pour éviter de voir un cluster HS à cause de l'absence de son maître, on va le configurer avec un quorum de... 3 masters. Tout simplement.

Pourquoi HAProxy ?

Mon environnement de test est basé sur des serveurs dans le cloud de Hetzner. J'ai essayé d'attendre aussi longtemps que possible des infrastructures abordables supportant k8s loin des AWS, GCP ou encore Azure, en vain. Il y a bien OVH et DigitalOcean mais le côté "abordable" n'y est pas. Le premier ouvre son infrastructure à partir de 22€ le serveur, et l'autre 20$ (node unique + LB). On est loin des 6€ par machine chez Hetzner.

L'idée

Comme l'indique la documentation officielle, HAProxy va faire ce qu'il sait faire de mieux : rediriger les requêtes. Comment peut-on faire croire à 3 serveurs séparés qu'ils bossent ensemble ? En installant un HAproxy sur chacun d'entre eux, configuré pour loadbalancer les requêtes qui seront balancées sur le 127.0.0.1 et le port 5443 (choisi arbitrairement).

En image, ça donne ça :


Configurés comme ça, nos masters vont s'amuser entre-eux sans aucun souci.

L'installation

Je passe sur la configuration de Kubernetes, j'en parle déjà ici. Notez quand même que vous pouvez suivre ce que je raconte jusqu'à l'init du cluster. Pas plus. Pourquoi ? Parce que sur le premier de vos masters, nous allons ajouter un fichier de configuration :
root@k8smaster1:~# cat kubeadm-config.yaml 
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: stable
apiServer:
  certSANs:
  - "127.0.0.1"
controlPlaneEndpoint: "127.0.0.1:5443"
networking:
   podSubnet: "10.244.0.0/16"
Ici, on voit bien que j'ai configuré mon k8s pour taper sur le localhost de la machine à travers le port 5443. C'est là que HAproxy prend la relève.
Je me suis permis d'ajouter la configuration nécessaire à Flannel, mon CNI, qui nécessite en CIDR particulier pour fonctionner correctement. C'est la partie networking.

On peut enchaîner sur la configuration de HAProxy :
global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

    ca-base /etc/ssl/certs
    crt-base /etc/ssl/private

    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
    ssl-default-bind-options no-sslv3

defaults
    log    global
    mode    tcp
    option    tcplog
    option    dontlognull
        timeout connect 5000
        timeout client  50000
        timeout server  50000
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

frontend api-front
    bind 127.0.0.1:5443
    mode tcp
    option tcplog
    use_backend api-backend

backend api-backend
    mode tcp
    option tcplog
    option tcp-check
    balance roundrobin
    server master1  10.0.42.1:6443 check
    server master2  10.0.42.2:6443 check
    server master3  10.0.42.3:6443 check
La partie global a l'exacte configuration par défaut. J'ai touché à rien.

Dans defaults, j'ai changé le mode de proxy pour le passer de http à tcp.

Les parties frontend et backend regroupent les configurations qui vont bien pour permettre à HAProxy de faire ce que je lui demande. Vous devriez pouvoir recopier tout ça en prenant seulement le soin de changer les IP des masters.

Pour comprendre plus clairement la configuration de HAproxy, je vous redirige vers cet excellent billet de Victor HÉRY.

Une fois configurés, n'oubliez pas de redémarrer les HAProxy sur tous les serveurs et de vérifier qu'ils écoutent bien sur le bon port :
root@k8smaster1:~# nc -v localhost 5443
localhost [127.0.0.1] 5443 (?) open
Astuce : pensez à installer hatop. C'est vraiment super ! Pour le lancer :
hatop -s /var/run/haproxy/admin.sock
Pour le moment, tout sera down, mais une fois le premier master en état, il apparaîtra UP.

On va maintenant initialiser le premier master :
kubeadm init --config=kubeadm-config.yaml
Une fois terminé, vous allez récupérer les informations classiques : le join qui va bien.
kubeadm join 127.0.0.1:5443 --token a1o01x.tokenblabla --discovery-token-ca-cert-hash sha256:blablablablalblawhateverlablablameans --experimental-control-plane
Notez que l'IP de l'API est bien 127.0.0.1 avec le port spécifié à HAProxy. C'est tout bon ! Faites un tour dans hatop et remarquez que le backend du master1 est enfin marqué comme étant UP.

Un get nodes vous confirmera l'arrivée du master1 et un get pods vous montrera les conteneurs de base.

Installons maintenant Flannel, toujours aussi simplement :
kubectl apply -f https://github.com/coreos/flannel/raw/master/Documentation/kube-flannel.yml
Et on aura un premier master en état de fonctionner !

Pour configurer les deux autres masters, il va falloir jouer du SCP. La doc officielle fournit 2 scripts bash que vous pouvez utiliser. Je ne m'étends pas sur le sujet ici et j’enchaîne sur la configuration des autres masters. Pensez quand même à bien configurer SSH et votre user de base.

Une fois que tout est copié, vous n'avez qu'à lancer la commande join sur les masters restant, un par un, et voir le résultat :
dada@k8smaster1:~$ k get nodes
NAME         STATUS   ROLES    AGE   VERSION
k8smaster1   Ready    master   12h   v1.13.1
k8smaster2   Ready    master   11h   v1.13.1
k8smaster3   Ready    master   11h   v1.13.1
Ou encore :
dada@k8smaster1:~$ k get pods --all-namespaces
NAMESPACE     NAME                                 READY   STATUS    RESTARTS   AGE
kube-system   coredns-86c58d9df4-cx4b7             1/1     Running   0          12h
kube-system   coredns-86c58d9df4-xf8kb             1/1     Running   0          12h
kube-system   etcd-k8smaster1                      1/1     Running   0          12h
kube-system   etcd-k8smaster2                      1/1     Running   0          11h
kube-system   etcd-k8smaster3                      1/1     Running   0          11h
kube-system   kube-apiserver-k8smaster1            1/1     Running   0          12h
kube-system   kube-apiserver-k8smaster2            1/1     Running   0          11h
kube-system   kube-apiserver-k8smaster3            1/1     Running   0          11h
kube-system   kube-controller-manager-k8smaster1   1/1     Running   1          12h
kube-system   kube-controller-manager-k8smaster2   1/1     Running   0          11h
kube-system   kube-controller-manager-k8smaster3   1/1     Running   0          11h
kube-system   kube-flannel-ds-amd64-55p4t          1/1     Running   1          11h
kube-system   kube-flannel-ds-amd64-g7btx          1/1     Running   0          12h
kube-system   kube-flannel-ds-amd64-knjk4          1/1     Running   2          11h
kube-system   kube-proxy-899l8                     1/1     Running   0          12h
kube-system   kube-proxy-djj9x                     1/1     Running   0          11h
kube-system   kube-proxy-tm289                     1/1     Running   0          11h
kube-system   kube-scheduler-k8smaster1            1/1     Running   1          12h
kube-system   kube-scheduler-k8smaster2            1/1     Running   0          11h
kube-system   kube-scheduler-k8smaster3            1/1     Running   0          11h
Un dernier tour sur hatop pour admirer la présence de tous vos backends enfin marqué UP.

Vous avez maintenant un cluster k8s en HA ! La suite serait peut-être de vous raconter comment sortir ETCd du cluster pour le mettre en place dans un cluster séparé dédié, mais non. Ce billet est déjà bien assez long.

Si tout ne se passe pas comme prévu, pensez à regarder la documentation officielle. Mon billet n'est qu'un complément qui peut contenir des coquilles. Pensez aussi à bien vérifier la configuration de votre firewall, ou encore de HAProxy, ou encore de Docker, ou encore votre VPN parce qu'on ne laisse pas tout traîner sur le réseau. Bref.


MariaDB en Master/Slave via ProxySQL

Rédigé par dada / 01 décembre 2018 / Aucun commentaire



On y est. J'ai enfin réussi à faire tourner ProxySQL comme je l'entendais pour que mes conteneurs tapent dans des BDD loin de Kubernetes. Sortir ses bases de données du cluster est un choix. Si vous êtes courageux, vous pouvez les laisser dedans. Ceci-dit, faut être un tantinet croyant pour se lancer dans la seconde solution. Dans ces histoires de hautes dispo et de résistance aux pannes, la bonne solution semble être de gérer son cluster de BDD en dehors de son cluster k8s.

Installation des MariaDB

Là, je devrais vous passer une pile de commandes pour installer des serveurs MariaDB en master/slave, mais bon. Tout est très clair dans la documentation officielle.

Sachez simplement que le master porte l'IP 192.168.0.17 et que le slave, lui, là 192.168.0.77.

Installation de ProxySQL

Helm ? Non, pas ici. On va donc pondre un YAML avec le Deployment et le Service qui va bien :
dada@master:~/proxysql$ cat proxysql.yaml

apiVersion: v1
kind: Deployment
metadata:
  name: proxysql
  labels:
    app: proxysql
spec:
  replicas: 2
  selector:
    matchLabels:
      app: proxysql
      tier: frontend
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: proxysql
        tier: frontend
    spec:
      restartPolicy: Always
      containers:
      - image: severalnines/proxysql:1.4.12
        name: proxysql
        volumeMounts:
        - name: proxysql-config
          mountPath: /etc/proxysql.cnf
          subPath: proxysql.cnf
        ports:
        - containerPort: 6033
          name: proxysql-mysql
        - containerPort: 6032
          name: proxysql-admin
      volumes:
      - name: proxysql-config
        configMap:
          name: proxysql-configmap
---
apiVersion: v1
kind: Service
metadata:
  name: proxysql
  labels:
    app: proxysql
    tier: frontend
spec:
  type: NodePort
  ports:
  - nodePort: 30033
    port: 6033
    name: proxysql-mysql
  - nodePort: 30032
    port: 6032
    name: proxysql-admin
  selector:
    app: proxysql
    tier: frontend

A remarquer

Le Deployment contient la configuration de ce qu'on appelle un ReplicatSet. Ça permet à k8s de toujours maintenir le nombre de pods déclaré en fonction. Quand un pod se casse la figure, il revient à lui. Dans un RS, quand un pod de casse la figure, il va aussi revenir à lui. Super. Sauf que, par exemple, dans le cas d'une mise à jour, k8s ne va pas terminer les pods d'un coup, mais les gérer un par un.

Le YAML contient aussi un Service de type NodePort qui va nous permettre de mapper les ports 30032 et 30033 internes aux pods sur les ports 6032 et 6033 accessibles depuis l'extérieur. Voyez la suite du billet pour découvrir qu'au lieu de taper sur le port 3306 de vos serveurs MariaDB, vous allez taper sur le port 6033.

On fait gober tout ça au cluster :
dada@master:~/proxysql$ kubectl apply -f proxysql.yaml
Et voilà le travail :
dada@master:~/proxysql$ kubectl get pods --all-namespaces  | grep proxysql
default            proxysql-5c47fb85fb-fdh4g                              1/1     Running     1          39h
default            proxysql-5c47fb85fb-kvdfv                              1/1     Running     1          39h

Configuration de ProxySQL

Tout va se jouer dans le fichier proxysql.cnf. Tout, ou presque, mais j'en parlerai après. Voici déjà de quoi faire :
datadir="/var/lib/proxysql"
admin_variables=
{
        admin_credentials="proxysql-admin:adminpwd"
        mysql_ifaces="0.0.0.0:6032"
        refresh_interval=2000
}
mysql_variables=
{
        threads=4
        max_connections=2048
        default_query_delay=0
        default_query_timeout=36000000
        have_compress=true
        poll_timeout=2000
        interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
        default_schema="information_schema"
        stacksize=1048576
        server_version="5.1.30"
        connect_timeout_server=10000
        monitor_history=60000
        monitor_connect_interval=200000
        monitor_ping_interval=200000
        ping_interval_server_msec=10000
        ping_timeout_server=200
        commands_stats=true
        sessions_sort=true
        monitor_username="proxysql"
        monitor_password="proxysqlpwd"
}
mysql_replication_hostgroups =
(
        { writer_hostgroup=10, reader_hostgroup=20, comment="MariaDB Replication" }
)
mysql_servers =
(
        { address="192.168.0.17", port=3306, hostgroup=10, max_connections=100, max_replication_lag = 5 },
        { address="192.168.0.77", port=3306, hostgroup=20, max_connections=100, max_replication_lag = 5}
)
mysql_users =
(
        { username = "nextcloud" , password = "nextcloudpwd" , default_hostgroup = 10 , active = 1 }
)
mysql_query_rules =
(
        {
                rule_id=100
                active=1
                match_pattern="^SELECT .* FOR UPDATE"
                destination_hostgroup=10
                apply=1
        },
        {
                rule_id=200
                active=1
                match_pattern="^SELECT .*"
                destination_hostgroup=20
                apply=1
        },
        {
                rule_id=300
                active=1
                match_pattern=".*"
                destination_hostgroup=10
                apply=1
        }
)
Il est long alors on va le découper ensemble.

Global

{
        admin_credentials="proxysql-admin:adminpwd"
        mysql_ifaces="0.0.0.0:6032"
        refresh_interval=2000
}
Ici, on retrouve surtout les accès administrateur de ProxySQL et son port qui écoute sans limite d'IP.

Mysql_variables

mysql_variables=
{
        threads=4
        max_connections=2048
        default_query_delay=0
        default_query_timeout=36000000
        have_compress=true
        poll_timeout=2000
        interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
        default_schema="information_schema"
        stacksize=1048576
        server_version="5.1.30"
        connect_timeout_server=10000
        monitor_history=60000
        monitor_connect_interval=200000
        monitor_ping_interval=200000
        ping_interval_server_msec=10000
        ping_timeout_server=200
        commands_stats=true
        sessions_sort=true
        monitor_username="proxysql"
        monitor_password="proxysqlpwd"
}
Là encore, je ne vais pas m'étendre sur toute la configuration (par défaut) mais sur deux points seulement : le port 6033 sera celui que vous allez rentrer dans les fichiers de configuration de vos services ayant besoin de MariaDB et l'utilisateur "monitor" est là pour vérifier l'état de vos serveurs MariaDB.

Mysql_replication_hostgroups

mysql_replication_hostgroups =
(
        { writer_hostgroup=10, reader_hostgroup=20, comment="MariaDB Replication" }
)
C'est à partir de là qu'on commence à s'amuser ! Ici, on déclare deux groupes de serveurs avec deux ID différents. Les writer, ceux qui ont le droit d'écrire et les reader, ceux qui n'auront que le droit de lire. Ça tombe bien, c'est plus ou moins ce qu'on veut.

Mysql_servers

mysql_servers =
(
        { address="192.168.0.17", port=3306, hostgroup=10, max_connections=100, max_replication_lag = 5 },
        { address="192.168.0.77", port=3306, hostgroup=20, max_connections=100, max_replication_lag = 5}
)
Si vous aviez suivi le blabla précédent, vous pouvez déchiffrer ces deux lignes en :

- Le serveur avec l'IP 192.168.0.17 fait partie du groupe des writers On lui demande de traiter 100 connexions actives maximum et d'avoir un lag avec son master de moins de 5 secondes.
- Le serveur avec l'IP 192.168.0.77 fait partie du groupe des reader. On lui demande de traiter 100 connexions actives maximum et d'avoir un lag avec son master de moins de 5 secondes.

Mysql_users

mysql_users =
(
        { username = "nextcloud" , password = "nextcloudpwd" , default_hostgroup = 10 , active = 1 }
)
Les utilisateurs MariaDB doivent être renseignés ici !
Dans mon cas, profitez de la configuration sécurisée de mon utilisateur nextcloud. Il sera assigné à un groupe d'utilisateur par défaut : le groupe des writer, et sera activé. Il est possible qu'un besoin particulier soit à l'origine de la création de la variable "active" mais j'ai du mal à comprendre pourquoi un compte MariaDB resterait renseigné avec active = 0 plutôt que dégagé. M'enfin.

Mysql_query_rules

mysql_query_rules =
(
        {
                rule_id=100
                active=1
                match_pattern="^SELECT .* FOR UPDATE"
                destination_hostgroup=10
                apply=1
        },
        {
                rule_id=200
                active=1
                match_pattern="^SELECT .*"
                destination_hostgroup=20
                apply=1
        },
        {
                rule_id=300
                active=1
                match_pattern=".*"
                destination_hostgroup=10
                apply=1
        }
Là, c'est la définition des règles qui seront automatiquement appliquées pour chaque serveur. La plus claire est la règle à l'ID 200 qui est assignée au hostgroup 20, celui des reader. C'est là que ProxySQL va faire un tri. Le hostgroup 20 n'ayant que la possibilité de faire des SELECT, on comprend bien qu'on parle de lecteurs uniquement.

ConfigMap

On charge tout ça dans une ConfigMap :
dada@master:~/proxysql$ kubectl create configmap proxysql-configmap --from-file=proxysql.cnf

Si on prend le temps de revenir sur le YAML pour comprendre la ConfigMap, on la repère ici :

      containers:
[...]
        volumeMounts:
        - name: proxysql-config
          mountPath: /etc/proxysql.cnf
          subPath: proxysql.cnf
[...]
      volumes:
      - name: proxysql-config
        configMap:
          name: proxysql-configmap

On comprend que les pods ProxySQL vont aller parcourir la liste des ConfigMaps disponibles pour repérer celle qui porte le nom "proxysql-config" et la monter dans /etc/proxysql.cnf.

Vérifier tout le système

Une commande que vous devriez connaître par cœur va nous prouver que tout fonctionne :

dada@master:~/proxysql$ kubectl logs proxysql-5c47fb85fb-fdh4g

Chez moi, elle sort quelque chose comme ça :

2018-12-01 08:30:19 [INFO] Dumping mysql_servers
+--------------+--------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+-----------------+
| hostgroup_id | hostname     | port | weight | status | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment | mem_pointer     |
+--------------+--------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+-----------------+
| 10           | 192.168.0.17 | 3306 | 1      | 0      | 0           | 100             | 5                   | 0       | 0              |         | 140637072236416 |
| 20           | 192.168.0.17 | 3306 | 1      | 0      | 0           | 100             | 5                   | 0       | 0              |         | 140637022769408 |
| 20           | 192.168.0.77 | 3306 | 1      | 0      | 0           | 100             | 5                   | 0       | 0              |         | 140637085320960 |
+--------------+--------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+-----------------+

On y retrouve la liste des serveurs et leurs rôles : mon master appartient aux groupes reader et writer. Normal puisqu'il doit écrire et lire. Mon slave, lui, n'appartient qu'au groupe des reader, comme convenu.

Le piège

Si j'ai pesté un certain temps contre ProxySQL sur Mastodon , c'est que ma configuration ne marchait pas alors que tout semblait normal. J'avais bien en tête ce que je viens de vous expliquer: Les reader, les writer, la configuration des users, etc. C'était clair.
Pourtant, quand je lancais mon conteneur Nextcloud pour qu'il s'installe comme un grand, il pété ma réplication en écrivant sur mon slave. Le con.
J'ai fini par ouvrir une issue pour crier à l'aide et on m'a expliqué ceci : ProxySQL vérifie la présence de la variable READ_ONLY sur tous les serveurs renseignés dans la rubrique mysql_replication_hostsgroups. Si la variable est a OFF sur votre slave, la réplication entre les deux serveurs MariaDB ne bronchera pas, mais ProxySQL ira taper dans votre slave, peu importe la configuration en place. Re le con.

Pour vous épargner des soucis, pensez bien à vérifier que votre slave affiche bien ceci :
MariaDB [(none)]> SHOW VARIABLES like 'read_only';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| read_only     | ON   |
+---------------+-------+
1 row in set (0.00 sec)
Vous êtes bons. Vous pouvez maintenant aller configurer vos pods pour aller taper sur vos MariaDB via proxysql:6033 en place et lieu de localhost:3306.

Prometheus et Graphana pour voir dans son cluster Kubernetes

Rédigé par dada / 23 novembre 2018 / 2 commentaires


Mes aventures avec Kubernetes ne se sont pas arrêtées, loin de là. J'ai actuellement 54 pods répartis sur 3 nodes et 1 master et 2 VM MariaDB en master/slave, le tout reparti sur mon laptop, mon PC fixe et un vieux PC portable datant de ma vie étudiante. Je pourrais aussi vous parler de mon Pi-Hole sur ma Raspberry qui voit passer toutes les requêtes. Bref.
Aujourd'hui, alors que je peste contre ProxySQL sur Mastodon, j'ai décidé de regarder du côté du monitoring de l'orchestrateur, histoire de prendre l'air. Si vous êtes un malheureux lecteur régulier, vous devriez savoir que j'adore Prometheus et que Grafana fait, à mes yeux, des dessins bien plus impressionnants que Klimt.

Note : ça n'a pas calmé ma frustration : c'est très rapide et simple à mettre en place.

Installer Prometheus

Avec pour base mes billets précédents, nous allons installer Prometheus, Grafana et l'AlertManager avec Helm.

Ajouter le dépôt dans helm

Là, à la manière d'APT, nous allons ajouter une source à Helm pour lui permettre d'installer ce qu'on lui demande.

helm repo add coreos https://s3-eu-west-1.amazonaws.com/coreos-charts/stable/

Installer l'operator

On enchaîne sur l'installation de l'operator, le grand patron qui va s'occuper pour nous de Prometheus dans k8s.

helm install coreos/prometheus-operator --name prometheus-operator --namespace monitoring
Une fois exécutée, vous devriez voir ça :
dada@master:~/prometheus$ kubectl get pods -n monitoring -o wide
NAME                                                   READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE
alertmanager-kube-prometheus-0                         2/2     Running   0          37m   10.244.3.140   node3    <none>
kube-prometheus-exporter-kube-state-65b6dbf6b4-b52jl   2/2     Running   0          33m   10.244.3.141   node3    <none>
kube-prometheus-exporter-node-5tnsl                    1/1     Running   0          37m   192.168.0.76   node1    <none>
kube-prometheus-exporter-node-fd7pt                    1/1     Running   0          37m   192.168.0.49   node3    <none>
kube-prometheus-exporter-node-mfdj2                    1/1     Running   0          37m   192.168.0.22   node2    <none>
kube-prometheus-exporter-node-rg5q6                    1/1     Running   0          37m   192.168.0.23   master   <none>
kube-prometheus-grafana-6f6c894c5b-2d6h4               2/2     Running   0          37m   10.244.2.165   node2    <none>
prometheus-kube-prometheus-0                           3/3     Running   1          37m   10.244.1.187   node1    <none>
prometheus-operator-87779759-wkpfz                     1/1     Running   0          49m   10.244.1.185   node1    <none>

Notez que si vous êtes, comme moi, sur une connexion ADSL classique, vous aller avoir le temps d'aller faire couler un grand café et d'aller le boire une clope au bec et au soleil. Votre cluster va télécharger beaucoup de pods et sur chaque nœud.

En y regardant bien, on retrouve :

  • L'AlertManager permettant de nous spammer en cas de souci,
  • Les exporter nodes placés logiquement sur chaque node et sur notre master,
  • Grafana, le copain de Prometheus qui vous fait des beaux dessins,
  • Le kube et l'operator.

Accéder à tout ça

L'installation est vraiment triviale. Le petit bonus de ce billet sera de vous passer une liste de commandes pour admirer le tout dans votre navigateur préféré : Firefox.

Pour accéder à l'interface de Prometheus

Commencez par ouvrir un tunnel SSH sur le port 9090 vers votre master :

ssh -L 9090:127.0.0.1:9090 dada@IPDuMaster

Puis lancez le port-foward :

kubectl port-forward -n monitoring prometheus-prometheus-operator-prometheus-0 9090

Pour accéder à l'interface de Grafana

Encore un tunnel SSH, sur le 3000 ce coup-ci :

ssh -L 3000:127.0.0.1:3000 dada@IPDuMaster

Et encore un port-forward :

kubectl port-forward $(kubectl get  pods --selector=app=grafana -n  monitoring --output=jsonpath="{.items..metadata.name}") -n monitoring  3000

Vous êtes bons ! Les dashboards sont maintenant accessibles en tapant http://localhost:PORT dans Firefox.

En image, ça devrait donner ça pour Grafana :

Et ça pour les alertes Prometheus :

Alors, oui. Vous avez aussi remarqué que des alertes étaient déjà levées ? Ce sont des outils/configurations que Prometheus attend de rencontrer dans votre cluster. Le mien n'a pas encore ces histoires de scheduler ou de controller manager. Ça va faire partie des découvertes à suivre dans les futurs billets.

Des bisous !

Prismo, le Reddit du fediverse

Rédigé par dada / 13 novembre 2018 / 6 commentaires


Je suis accroc à tout ce qui tourne autour de la fédération. Vraiment. Mon compte Mastodon tourne à plein régime et mon compte Pixelfed aussi, même s'il est en attente de réelle fédération, qui arrive.
Bref.
Dans la famille, nous pouvons maintenant ajouter un nouveau : Prismo !

C'est quoi ?

Prismo, c'est une sorte de Reddit, mais un Reddit fédéré, ou encore un Journal du Hacker. Il permet de partager des liens, d'en avoir un aperçu, de commenter ou encore de laisser la communauté en évaluer la pertinence avec des +1 ou des -1 et d'ainsi les faire apparaître sur la page d'accueil, bien en avant.

En images :


Vous avez ci-dessus la page d'accueil avec l'accès aux Stories, aux Comments et la liste des tags du moment. La page "Hot" permet d'accéder aux liens qui viennent d'être balancés, triés uniquement par date d'ajout.


Ci-dessus, un lien balancé par Valere. Même si l'article est super intéressant, ce sont des commentaires dont nous allons parler. Mon commentaire vient de mon compte Mastodon tout comme la réponse de Valere :


On se retrouve bien dans un cas typique de fédération ! Quand un lien est donné à manger à Prismo, celui-ci est directement envoyé dans notre univers fédéré, Mastodon en l’occurrence. Les interactions sont transmises dans les deux sens et tout le monde peut participer. C'est beau. Et vous avez des notifications pour vous alerter.

Prismo étant encore en développement, tout est encore possible. Dans les tuyaux, on peut déjà espérer voir rapidement arriver la fédération entre instances pour mettre en commun leurs communautés.
J'attends aussi l'arrivée d'un flux RSS, histoire de voir passer les nouvelles sur Mastodon mais aussi dans mon FreshRSS.
Une application Android/iOS ? Si des développeurs se motivent pour nous pondre ça, il y en aura. En attendant, la version mobile fonctionne bien.

L'utilité

Dans mon cas, je ne sais pas encore ce que je vais faire de ce nouvel outil. Je sais que je balance une quantité non négligeable de liens vers des articles autour de la politique internationale, du droit ou des nouvelles technologies. C'est un peu le cœur de métier de mon compte Mastodon. Est-ce que je vais déplacer tout ça dans une instance Prismo ? Je ne sais pas mais je vais y penser.

Par contre, si vous êtes un adepte de la veille technologiques et que vous n'avez pas vraiment d'intérêt à maintenir un compte Mastodon, vous êtes la cible privilégiée du petit nouveau. Il pourrait remplacer votre Shaarli ou vos billets de blog regroupant vos lectures de la semaine.

Où tester ?

Si vous êtes tentés par l'expérience, foncez faire un compte chez Hostux.news ! L'instance est gérée par Valere, ou Valere, ou Valere ou encore Valere.



On vous y attend pour découvrir ce que vous avez à nous faire lire !