Blog de dada

DevOps, bidouilleur et routard plein de logiciels libres

DevOps

Welcome to Nginx, puis Wordpress

Rédigé par dada / 09 novembre 2018 / Aucun commentaire

Perdu ?

On y arrive. Après des heures d'attente, de commandes bizarres, de pods dans tous les sens, je vais enfin vous montrer comment mettre en place un Wordpress, sa base de données et y accéder depuis le navigateur !

Wordpress

Il existe une configuration simple pour avoir un Wordpress fonctionnel : ne nous privons pas !

La partie MySQL

Son fichier de configuration :
apiVersion: v1
kind: Service
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  ports:
    - port: 3306
  selector:
    app: wordpress
    tier: mysql
  clusterIP: None
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim2
  labels:
    app: wordpress
spec:
  storageClassName: rook-ceph-block
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: changeme
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim2
Vous y trouverez les volumes persistant pour Rook, le point de montage, la configuration du port MySQL, le mot de passe, etc. Vous avez le temps de lire tout ça.

On lance la création du conteneur :
dada@k8smaster:~$ kubectl create -f mysql.yaml
Et le résultat :
default            wordpress-mysql-75477bf794-89mzw                          1/1     Running     1          5h38m   10.244.2.50    k8snode2    <none>

On peut enchaîner avec la suite. C'est vrai qu'une BDD de Wordpress sans le CMS pour l'utiliser, c'est moyen.

La partie PHP

Notez que je parle de la partie "PHP", mais il n'y a pas que PHP. Il me fallait un titre, alors voilà.

Cette partie, je l'ai modifié par rapport à ce que vous trouverez dans les documentations officielles.
apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
  - port: 80
  selector:
    app: wordpress
    tier: frontend
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wp-pv-claim
  labels:
    app: wordpress
spec:
  storageClassName: rook-ceph-block
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      - image: wordpress:4.6.1-apache
        name: wordpress
        env:
        - name: WORDPRESS_DB_HOST
          value: wordpress-mysql
        - name: WORDPRESS_DB_PASSWORD
          value: changeme
        ports:
        - containerPort: 80
          name: wordpress
        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html
      volumes:
      - name: wordpress-persistent-storage
        persistentVolumeClaim:
          claimName: wp-pv-claim
Vous pouvez lancer tout ça :
 kubectl create -f wordpress.yaml
Le pod wordpress devrait apparaître:
default            wordpress-796698694f-sxbhb                                1/1     Running     1          3h35m   10.244.2.51    k8snode2    <none>

Ce qu'il faut saisir

La présence des services de Wordpress :
dada@k8smaster:~/$ kubectl get services 
NAME                                     TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)                      AGE
kubernetes                               ClusterIP      10.96.0.1        <none>         443/TCP                      4d8h
my-nginx-nginx-ingress-controller        LoadBalancer   10.100.45.147    192.168.0.50   80:32462/TCP,443:30337/TCP   3d5h
my-nginx-nginx-ingress-default-backend   ClusterIP      10.109.228.138   <none>         80/TCP                       3d5h
wordpress                                ClusterIP      10.102.55.203    <none>         80/TCP                       6m3s
wordpress-mysql                          ClusterIP      None             <none>         3306/TCP                     6h33m
La configuration du service wordpress-mysql, on ne va pas s'y attarder. Ça marche tout seul.
Le truc chouette, c'est la configuration du service wordpress.
dada@k8smaster:~/$ kubectl describe service wordpress
Name:              wordpress
Namespace:         default
Labels:            app=wordpress
Annotations:       <none>
Selector:          app=wordpress,tier=frontend
Type:              ClusterIP
IP:                10.102.55.203
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.2.61:80
Session Affinity:  None
Events:            <none>
On y retrouve les informations qu'il nous faut et surtout, surtout, le Endpoint ! C'est là qu'on peut savoir où vont se retrouver les requêtes ! Ici, on lit 10.244.2.61:80 : il s'agit de l'IP du pod qui fait tourner Wordpress et le port sur lequel l'attaquer.

On va pouvoir s'attaquer à la dernière configuration : le service Ingress

Le service Ingress

Ici, on va expliquer au videur du cluster qu'il peut laisser passer les requêtes vers Wordpress.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
  name: nginx-ingress
spec:
 backend:
   serviceName: wordpress
   servicePort: 80
Créez tout ça :
kubectl create -f ingress.yaml
Une fois créé, vérifiez qu'il est bien là :
dada@k8smaster:~/$ kubectl get ingresses
NAME            HOSTS   ADDRESS   PORTS   AGE
nginx-ingress   *                 80      6s
Et vérifiez sa configuration :
dada@k8smaster:~/$ kubectl describe ingress nginx-ingress
Name:             nginx-ingress
Namespace:        default
Address:         
Default backend:  wordpress:80 (10.244.2.61:80)
Rules:
  Host  Path  Backends
  ----  ----  --------
  *     *     wordpress:80 (10.244.2.61:80)
Annotations:
  kubernetes.io/ingress.class:  nginx
Events:
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  65s   nginx-ingress-controller  Ingress default/nginx-ingress
Normal  UPDATE  30s   nginx-ingress-controller  Ingress default/nginx-ingress

Dans les Rules, remarquez que le backend est bien présent. Ici, le backend est le service wordpress que nous avons mis en place un peu plus tôt. Tout va bien !

Maintenant ? Souvenez-vous de l'IP externe que vous avez réussi à récupérer dans mon précédent billet et allez voir !



Il existe des moyens bien plus simples pour arriver à ce résultat. Passer par un Ingress Controller n'est pas la plus rapide mais elle permet de mettre le nez dans cet outil qui, plus tard, vous permettra de rediriger le flux en fonction du host. Bref. C'est un choix qui invite à aller plus loin !

La suite ?

À voir...

Accéder au cluster k8s depuis l'extérieur

Rédigé par dada / 09 novembre 2018 / Aucun commentaire



Perdu ?

On vient de se battre pour mettre en place un cluster Ceph opérationnel, histoire de stocker ses données dans le cluster k8s et de les répliquer un peu. Maintenant que c'est bon, si on s'attaquait à des choses un peu plus visible, hors dashboard ?
Au programme de ce billet : Ingress, Service, Wordpress, des nouveaux pods.

Ingress Nginx

Cette chose-là va être le point d'entrée de notre cluster. Il va permettre à l'extérieur d'aller regarder à l'intérieur. Son rôle va être de comprendre la requête d'entrée et de l'orienter vers le pod qui y répondra. Dans le cas qui va suivre, aller sur l'IP du cluster pour y retrouver un Wordpress.

Installation via Helm

Comme on s'en sert déjà, on va continuer :
helm install stable/nginx-ingress --name my-nginx
Cette installation va faire apparaître les pods suivants :
dada@k8smaster:~$ kubectget pods -n default
NAME                                                      READY   STATUS    RESTARTS   AGE
my-nginx-nginx-ingress-controller-565bc9555b-pcqjz        1/1     Running   2          8h
my-nginx-nginx-ingress-default-backend-5bcb65f5f4-728tx   1/1     Running   2          8h
Et un service. On n'a pas encore parlé de services : je vous redirige vers la documentation officielle si vous voulez en savoir bien plus.
dada@k8smaster:~$ kubectl --namespace default get services -o wide -w my-nginx-nginx-ingress-controller
NAME                                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE   SELECTOR
my-nginx-nginx-ingress-controller   LoadBalancer   10.100.45.147   <pending>     80:32462/TCP,443:30337/TCP   8s    app=nginx-ingress,component=controller,release=my-nginx
Ça veut dire que l'Ingress Controller est bien installé. Notez le <pending> : ça veut dire que notre controller n'a pas d'IP externe. En gros : il ne sert à rien. Il lui faut une IP pour que nous puissions l'attaquer.
Dans une installation chez des gros fournisseurs d'informatique dans les nuages, nous aurions une sorte de plugin nous fournissant déjà l'IP tant désirée. Avec notre infrastructure sous Virtualbox, il va falloir faire autrement. Et autrement, ça veut dire avec MetalLB.

MetalLB

MetalLB, ce sont des pods que nous allons installer dans notre cluster et qui nous serviront à palier le problème cité juste au dessus. Il ira interroger notre DHCP, la Freebox dans mon cas, pour récupérer une IP publique.

Installer MetalLB

Toujours avec Helm :
helm install --name metallb stable/metallb
Un peu d'attente et vous devriez voir de nouveaux pods :
dada@k8smaster:~$ kubectl get pods -n metallb-system
NAME                         READY   STATUS    RESTARTS   AGE
controller-765899887-ck6bv   1/1     Running   2          8h
speaker-jdqg9                1/1     Running   2          8h
speaker-t4vtk                1/1     Running   2          8h
Il lui manque un fichier de configuration pour nous offrir une adresse IP externe :
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: default
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.0.50-192.168.0.60
Les adresses IP en bas de ce fichier de conf vont permettre à MetalLB d'aller titiller notre DHCP (Freebox pour moi) pour obtenir une adresse. Quelque chose entre 192.168.0.50 et 192.168.0.60 dans mon cas. Vérifiez bien la configuration de votre Freebox avant de choisir une plage d'IP.

On l'applique :
kubectl create -f config.yaml 

Retour à l'Ingress Nginx

Une fois après avoir configuré MetalLB, vous allez vérifier l'état du service :
dada@k8smaster:~/$ kubectl --namespace default get services -o wide -w my-nginx-nginx-ingress-controller
NAME                                TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                      AGE    SELECTOR
my-nginx-nginx-ingress-controller   LoadBalancer   10.100.45.147   192.168.0.50   80:32462/TCP,443:30337/TCP   3d3h   app=nginx-ingress,component=controller,release=my-nginx
Vous avez vu ? Une EXTERNAL-IP ! On va pouvoir taper dessus !

La suite ?


Installer Grafana, Prometheus et Node Exporter

Rédigé par dada / 31 janvier 2018 / 25 commentaires




Le monitoring, j'aime à dire que c'est ce que l'administrateur a de plus pervers : surveiller, voir et savoir tout ce qui se passe sur ses machines, sans limite, et de la façon qui lui est la plus agréable possible. Un admin, c'est un stalker, en fait.

De mon côté, après avoir testé Facette, Monitorix, Netdata et Munin, je joue en ce moment avec Grafana, Prometheus et les exporters qui vont avec. C'est l'objet de ce billet, ça tombe bien, alors voyons comment faire pour installer tout ça en quelques minutes.

Comprendre l'installation en quelques lignes

Vos serveurs vont avoir un exporter simple : le Node Exporter, qui va permettre à Prometheus de récupérer les différentes métriques qu'il partage. La bonne pratique consiste à installer Prometheus sur une serveur qui sera dédié à la collecte des informations. Si vous installez tout sur une seul et même machine, vous pourrez mettre du localhost dans presque tout ce qui suit. Grafana, quant à lui, va afficher ses données avec des jolies couleurs et dans des jolis graphiques.

Installer Prometheus

Pas de piège pour une Debian Stretch :
apt install prometheus 
C'est un peu plus compliqué pour une Jessie :
apt -t jessie-backports install prometheus 
Notez qu'essayer de lancer le service sous Jessie via systemd est foireux : il faut utiliser la bonne vieille méthode :
/etc/init.d/prometheus start 
Si vous ne faites pas ça et que vous avez des soucis, genre un service qui écoute déjà sur le 9090, vous ne verrez rien dans les logs.

A partir de là, vous devriez pouvoir accéder à Prometheus en tapant sur le port 9090 de votre serveur.



Quoi ? Jamais j'ai écrit que Prometheus était sexy ;-)

Installer Node Exporter

Prometheus ne sait pas collecter d'informations tout seul. Il lui faut des exporters. Le plus simple et le plus complet pour avoir une vision global de la situation d'une machine (CPU, RAM, Load, traffic, etc) est le bien nommé Prometheus Node Exporter. Pour l'installer :
apt install prometheus-node-exporter

Configurer le Node Exporter dans Prometheus

Maintenant que les deux premiers outils sont installés, il va falloir les faire bosser ensemble. On va simplement déclarer dans la configuration de Prometheus qu'il doit se mettre d'accord avec l'exporter :
vim /etc/prometheus/prometheus.yml
scrape_configs:
  - job_name: 'prometheus'

    scrape_interval: 5s
    scrape_timeout: 5s

    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node'
    static_configs:
      - targets: ['monserveur:9100','monserveurdeux:9100']

L'exemple de configuration ci-dessus est quasiment celle de base. Il faut noter que le job_name 'prometheus' est là pour expliquer que Prometheus est en local. Quant au job_name 'node',  il fait comprendre à Prometheus que le Node Exporter est présent sur les hosts cités entre crochets.

On sauvegarde tout ça et on recharge la configuration de Prometheus avec le curl qui va bien :
curl -X POST http://localhost:9090/-/reload
Si vous n'avez pas d'erreur, on va enfin s'attaquer à la partie artistique de l'opération : les graphiques !

Installer Grafana

L'installation est, là aussi, triviale :
apt-get install grafana 
C'est 'achement difficile, tout ça, hein ?

Configurer Nginx

Pour ne pas avoir à toujours taper le port de Grafana, voici un bout de conf pour Nginx :
server {
    listen 80;

        root /var/www/html/;

        server_name grafana.monserveur.tld;

        location / {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_redirect off;
                proxy_pass http://127.0.0.1:3000;
        }
}

Configurer Grafana

- Ajouter une data source

Grafana, ça marche tout seul. Une fois installé, il vit sa vie. Par contre, il va falloir le brancher à Prometheus, tout de même.
Comme blablater, c'est chiant, voici une capture d'écran de ce que vous devez faire :



En commentaire : cliquez sur le menu en haut à gauche de Grafana pour ajouter une nouvelle data source et récupérer les informations que vous voyez dans la capture.
Vous remarquerez que le port mis en place est bien celui de Prometheus et pas celui du Node Exporter : Grafana ne communique pas avec Node Exporter (sur le port 9100), mais uniquement avec Prometheus.

On arrive à la fin. Maintenant que l'exporter balance des informations, que Prometheus en est conscient et que Grafana arrive à échanger avec Prometheus, on va pouvoir mettre en place un dashboard pour profiter des graphiques !

- Installer le dashboard Node Exporter Full

Ici, c'est aussi simple (mais pourquoi est-ce que je m'emmerde à écrire ce billet si c'est si simple ?!), pour installer un dashboard, allez dans le Menu de Grafana, puis Dashboard et enfin Import. Je dis bien Import, pas New. Enfin, ajoutez le nombre 1860 dans la premier champ pour faire apparaître la fenêtre suivante :



Bon, j'ai aussi cliqué n'importe-où sur la fenêtre pour que Grafana prenne en compte la nouvelle information et, finalement, affiche la capture ci-dessus.

On a fait le tour. Tout est bon. Vous pouvez aller sur la page d'accueil de Grafana, cliquer sur le nom de votre nouveau dashboard et profiter du spectacle !



Astuces du dimanche #4

Rédigé par dada / 10 mai 2015 / 2 commentaires


Quatrième version des astuces du dimanche ! Je dois avouer que j'aime bien cette formule simple et rapide pour partager des astuces peu révolutionnaires mais qu'il fait bon rappeler de temps en temps.

Au programme de cette semaine : partager des fichiers en réseau sans se prendre la tête et comment créer une archive de sauvegarde (pour un backup, par exemple) et vous l'envoyer alors que vous n'avez pas de place sur le disque dur.

Partager ses fichiers via python

Sans clés USB ou système de partage en réseau, il est bien difficile de partager un fichier avec le PC du voisin. La solution suivante permet de se servir de python pour créer un serveur web simple. Il sera accessible depuis votre adresse IP et le port spécifié.

  • Avec python 2.7 ou plus
# python -m SimpleHTTPServer 80
  • Avec python 3 ou plus
# python -m http.server 80
Lancez l'une de ces commandes depuis un terminal ouvert là où se trouve le ficher à transférer, donnez votre IP et le port à votre pote/collègue et le tour est joué. Attention tout de même à ne pas lancer cette commande depuis votre /home/ sous peine de partager l’intégralité de votre vie privée ;-)

Création et envoie d'archive par le réseau

C'est un truc que je rencontre souvent au boulot : faut faire un gros tar.gz de sauvegarde et le placer bien au chaud sur une autre machine mais pas moyen d'y arriver avec l'espace disque disponible.
Pas de panique, la commande tar associée à ssh, à un pipe et cat permette de faire des miracles.

ssh -n ServeurDistant -p PORT 'tar zcvf - toto.txt' | cat - > toto.tar.gz

Avec ça, depuis votre terminal, vous récupérez le contenu de toto.txt, que vous archivez simplement sur votre disque dur local. Celui du serveur distant n'est plus utilisé : terminé le problème de place !

Bon dimanche ! :)