Drone est un système de livraison continue basé sur la technologie des conteneurs. Drone utilise un simple fichier de configuration YAML, un sur-ensemble de docker-compose, pour définir et exécuter des pipelines dans des conteneurs Docker.

Cela semble incroyable, un CD construit avec des conteneurs.
Drone est écrit en Go, supporte de nombreux plugins et est très facile à configurer.

Si vous ne connaissez pas Traefik, vous pouvez consulter mes précédents articles sur le sujet, ce n'est pas ce qui manque ;)

Nous déploierons Drone sur un cluster Kubernetes, ici en utilisant Google Cloud Platform (vous pouvez obtenir des crédits gratuits pendant un an).
Vous pouvez choisir le fournisseur que vous préférez, mais les instructions peuvent changer.

Création du cluster

Nous avons besoin d’un cluster actif pour démarrer.
Avec Google Kubernetes Engine, vous pouvez le faire avec une simple commande. Je suppose que vous avez installé gcloud et un compte Google Cloud actif.

Pour créer le cluster, il suffit de taper:

gcloud init 
gcloud config set compute/zone  COMPUTE_ZONE

Puis :

   gcloud container clusters create MY_KUBERNETES_CLUSTER \
  --enable-cloud-logging \
  --enable-cloud-monitoring \
  --subnetwork default

Utiliser Helm pour installer Traefik

Pour utiliser Traefik avec Let's Encrypt, le moyen le plus simple de l'installer consiste à utiliser Helm : le gestionnaire de paquets Kubernetes.

Pour rappel sur Mac :

brew install kubernetes-helm

Une fois Helm installé, vous pouvez lancer helm init. Il installera Tiller (le service côté cluster) sur votre cluster.

helm init 

Si vous avez plusieurs clusters, vérifiez que kubectl config current-context renvoie le cluster souhaité. Sinon, vous pouvez utiliser l'option --kube-context de helm pour l'installer sur un autre.

kubectl --namespace kube-system get pods | grep tiller

Puis :

helm repo update

Créons notre configuration de graphique Traefik. Voici mon fichier traefik-helm.yml

imageTag: 1.5                                    

ssl:
enabled: true
enforced: true
acme:
enabled: true
email: ""
staging: false
persistence.enabled: true
dashboard:
enabled: true
domain: ""

L'imageTag nous permet de spécifier la version de Traefik, ici la plus récente. ssl.enabled quant à lui, active HTTPS tandis que ssl.enforced, active la redirection HTTP vers HTTPS.
Ensuite, la section acme traite de la génération de certificats Let's Encrypt. La dernière section indique si vous souhaitez ou non configurer le dashboard de Traefik. Vous trouverez ici d'autres options de configuration, telles que les types de volume pour le stockage persistant ou la connexion à Prometheus. De plus, je ne l’ai pas spécifié, mais par défaut, le nombre de réplicas sera un, ce qui est la meilleure option lors de l’utilisation de Let's Encrypt pour le moment.

Et on envoie la sauce :

helm install --namespace kube-system --name traefik --values traefik-helm.yaml stable/traefik

NAME:   traefik
E1013 22:09:36.171229   41536 portforward.go:303] error copying from remote stream to local connection: readfrom tcp4 127.0.0.1:59640->127.0.0.1:59644: write tcp4 127.0.0.1:59640->127.0.0.1:59644: write: broken pipe
LAST DEPLOYED: Sat Oct 13 22:09:35 2018
NAMESPACE: kube-system
STATUS: DEPLOYED

RESOURCES:
==> v1/PersistentVolumeClaim
NAME          AGE
traefik-acme  1s

==> v1/Service
traefik-dashboard  1s
traefik            1s

==> v1/Deployment
traefik  1s

==> v1beta1/Ingress
traefik-dashboard  1s

==> v1/Pod(related)

NAME                      READY  STATUS   RESTARTS  AGE
traefik-78dbcb495f-kx9k4  0/1    Pending  0         1s

==> v1/Secret

NAME                  AGE
traefik-default-cert  1s

==> v1/ConfigMap
traefik  1s


NOTES:

1. Get Traefik's load balancer IP/hostname:

     NOTE: It may take a few minutes for this to become available.

     You can watch the status by running:

         $ kubectl get svc traefik --namespace kube-system -w

     Once 'EXTERNAL-IP' is no longer '<pending>':

         $ kubectl describe svc traefik --namespace kube-system | grep Ingress | awk '{print $3}'

2. Configure DNS records corresponding to Kubernetes ingress resources to point to the load balancer IP/hostname found in step 1

Ça marche ! Nous pouvons obtenir l'adresse IP externe pointant sur Traefik avec cette commande (vous devrez peut-être attendre quelques secondes):

kubectl describe svc traefik-traefik --namespace kube-system | grep Ingress | awk '{print $3}'
35.205.85.66

Nous devons maintenant éditer nos enregistrements DNS pour qu'ils correspondent à l'URL de notre tableau de bord avec cette adresse IP. Supposons que vous ayez le domaine example.com: vous aurez besoin d'un enregistrement A de cette adresse IP pour dashboard.example.com, d'un enregistrement A pour drone.exemple.com et d'un dernier pour appli.example.com.
Voici ce que j'obtiens en accédant au tableau de bord:

Capture-d-e-cran-2018-10-13-a--22.38.37-1

Tester Traefik avec un application de test

Maintenant que Traefik est opérationnel et avant de commencer à utiliser Drone, nous allons simplement déployer une application simple pour vérifier si Traefik fonctionne comme prévu.
Voici mon basic-deployment.yml:

apiVersion: apps/v1beta2                              
kind: Deployment
metadata:
    name: nginx
spec:
    selector:
        matchLabels:
            app: nginx
    replicas: 2
    template:
        metadata:
            labels:
                app: nginx
        spec:
            containers:
              - name: nginx
                image: stenote/nginx-hostname:latest
---
apiVersion: v1
kind: Service
metadata:
    name: nginx
    labels:
        apps: nginx
spec:
    selector:
      app: nginx
    ports:
      - protocol: TCP
        port: 80
        name: http

Il créera deux réplicas d’un serveur NGINX de base qui imprimera le nom d’hôte.
Nous l'appliquons avec:

$ kubectl apply -f basic-deployment.yml          
 deployment "nginx" created
 service "nginx" created

Nous devons maintenant créer une ingress pour dire à Traefik d'utiliser ce service comme point de terminaison de l'URL app.example.com. Voici mon basic-ingress.yml:

apiVersion: extensions/v1beta1                        

kind: Ingress
metadata:
name: drone
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: ""
http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: http

Et on applique :

$ kubectl apply -f basic-ingress.yml                  
 ingress "drone" created