CI / CD avec drone, Kubernetes et Helm – Partie 1 – Avis Drones, test et guide d’achat

Cet article est une rediffusion de mon blog. Trouvez le post original ici.

L'intégration et la livraison continues sont difficiles. C'est un fait sur lequel tout le monde peut s'entendre. Mais maintenant, nous avons toute cette merveilleuse technologie et les problèmes sont principalement "Comment puis-je brancher ceci avec ça?" ou "Comment faire fonctionner ces deux produits ensemble?"

Eh bien, il y a jamais une réponse simple et universelle à ces questions. Dans cette série d'articles, nous allons progressivement construire un pipeline complet pour une intégration et une livraison continues en utilisant trois produits populaires, à savoir Kubernetes, Helm et Drone.

Ce premier article sert d'introduction aux différentes technologies utilisées tout au long de la série. Il est destiné aux débutants qui ont une certaine connaissance de Docker, comment fonctionne un conteneur et les bases de Kubernetes. Vous pouvez l'ignorer entièrement si vous avez un cluster k8s en cours d'exécution et une instance Drone en cours d'exécution.


Pas

  • Créer un cluster Kubernetes avec GKE
  • Créer un compte de service pour Tiller
  • Initialiser le casque
  • Ajouter un dépôt à Helm
  • Déployer Drone sur le nouveau cluster k8s
  • Activez HTTPS sur notre nouvelle instance de drone


Technologie impliquée


Drone

Drone est une plateforme de livraison continue construite sur Docker et écrite en Go. Drone utilise un simple fichier de configuration YAML, un surensemble de docker-compose, pour définir et exécuter des Pipelines à l'intérieur de conteneurs Docker.

Il a la même approche que Travis, où vous définissez votre pipeline comme code dans votre référentiel. La fonctionnalité intéressante est que chaque étape de votre pipeline est exécutée dans un conteneur Docker. Cela peut sembler contre-intuitif au premier abord, mais il permet un excellent système de plugins: chaque plugin pour Drone
utiliser est une image Docker, que Drone tirera en cas de besoin. Vous n'avez rien à installer directement dans Drone comme vous le feriez avec Jenkins par exemple.

Un autre avantage de l'exécution dans Docker est que la procédure d'installation de Drone est vraiment simple. Mais nous n'allons pas installer Drone sur un serveur nu ou à l'intérieur d'un
VM. Plus d'informations à ce sujet plus tard dans le didacticiel.


Kubernetes

Kubernetes (communément stylisé sous le nom de K8) est un système open source d'orchestration de conteneurs pour automatiser le déploiement, la mise à l'échelle et la gestion des applications conteneurisées qui a été initialement conçu par Google et maintenant géré par la Cloud Native Computing Foundation. Il vise à fournir une "plate-forme pour automatiser le déploiement, la mise à l'échelle et les opérations des conteneurs d'applications sur des clusters d'hôtes". Il fonctionne avec une gamme d'outils de conteneur, y compris Docker. Wikipédia

Wikipedia résume assez bien les k8. Fondamentalement, k8s résume les machines sous-jacentes sur lesquelles il s'exécute et offre une plate-forme où nous pouvons déployer nos applications. Il est chargé de distribuer correctement nos conteneurs sur
différents nœuds, donc si un nœud s'arrête ou est déconnecté du réseau, l'application est toujours accessible pendant que k8s travaille pour réparer le nœud ou en provisionne un nouveau pour nous.

Je recommande au moins de lire les bases de Kubernetes pour ce tutoriel.


Barre

Helm est le gestionnaire de packages pour Kubernetes. Il nous permet de créer, maintenir et déployer des applications dans un cluster Kubernetes.

Fondamentalement, si vous souhaitez installer quelque chose dans votre cluster Kubernetes, vous pouvez vérifier s'il existe un graphique pour cela. Par exemple, nous allons utiliser le Chart for Drone pour le déployer.

Helm vous permet de déployer votre application dans différents espaces de noms, de modifier la balise de votre image et de remplacer essentiellement tous les paramètres que vous pouvez placer dans vos fichiers de déploiement Kubernetes lors de son exécution. Cela signifie que vous pouvez utiliser le même graphique pour déployer votre application dans votre environnement de transfert et en production simplement en remplaçant certaines valeurs sur la ligne de commande ou dans un fichier de valeurs.

Dans cet article, nous verrons comment utiliser un graphique préexistant. Dans le prochain, nous verrons comment en créer un à partir de zéro.


Avertissements

Dans ce tutoriel, nous utiliserons Google Cloud Platform car il permet de créer facilement des clusters Kubernetes et dispose d'un registre de conteneurs privé que nous utiliserons plus tard.

Vous pouvez ignorer cette étape si vous possédez déjà un cluster k8s avec une version Kubernetes supérieure à 1.8.

Dans cette étape, nous aurons besoin du gcloud et kubectl CLI. Découvrez comment installer le SDK Google Cloud pour votre système d'exploitation.

Comme indiqué précédemment, ce didacticiel ne concerne pas la création et la maintenance d'un cluster Kubernetes. En tant que tel, nous allons utiliser Google Kubernetes Engine pour créer notre cluster de terrains de jeux. Il existe deux options pour le créer: soit dans l'interface Web offerte par GCP, soit directement à l'aide du gcloud commander. Au moment de la rédaction du présent document, la version par défaut des k8 proposés par Google est 1.8.8mais tant que vous êtes au-dessus 1.8 vous pouvez choisir la version que vous souhaitez.Même s'il n'y a aucune raison de ne pas choisir la version stable la plus élevée …

le 1.8 le choix est parce que dans cette version RBAC est activé par défaut et est le système d'authentification par défaut.

Pour réduire le coût de votre cluster, vous pouvez modifier le type de machine, mais essayez de conserver au moins 3 nœuds; cela permettra des migrations sans interruption de service vers différents types de machines et mettra à niveau la version k8s si vous souhaitez conserver ce cluster actif et en cours d'exécution.

Pour vérifier si votre cluster est en cours d'exécution, vous pouvez vérifier la sortie de la commande suivante:

$ gcloud container clusters list
NAME       LOCATION        MASTER_VERSION  MASTER_IP    MACHINE_TYPE   NODE_VERSION  NUM_NODES  STATUS
mycluster  europe-west1-b  1.10.2-gke.1      custom-1-2048  1.10.2-gke.1  3          RUNNING

Vous devriez également obtenir le MASTER_IP, PROJECT, et le LOCATION que j'ai supprimé de cet extrait. Désormais dans les extraits de code et les exemples de ligne de commande, $LOCATION fera référence à l'emplacement de votre cluster, $NAME fera référence au nom de votre cluster, et $PROJECT fera référence à votre projet GCP.

Une fois votre cluster en cours d'exécution, vous pouvez ensuite exécuter la commande suivante pour récupérer les informations d'identification pour vous connecter à votre cluster:

$ gcloud container clusters get-credentials $NAME --zone $LOCATION --project $PROJECT
Fetching cluster endpoint and auth data.
kubeconfig entry generated for mycluster.
$ kubectl cluster-info
Kubernetes master is running at https://
GLBCDefaultBackend is running at https:///api/v1/namespaces/kube-system/services/default-http-backend/proxy
Heapster is running at https:///api/v1/namespaces/kube-system/services/heapster/proxy
KubeDNS is running at https:///api/v1/namespaces/kube-system/services/kube-dns/proxy
kubernetes-dashboard is running at https:///api/v1/namespaces/kube-system/services/kubernetes-dashboard/proxy
Metrics-server is running at https:///api/v1/namespaces/kube-system/services/metrics-server/proxy

Maintenant kubectl est configuré pour fonctionner sur votre cluster. La dernière commande imprimera toutes les informations dont vous avez besoin pour savoir où se trouve votre cluster.

Tout d'abord, nous aurons besoin du helm commander. Voir cette page pour les instructions d'installation.

Le casque est en fait composé de deux parties. Helm lui-même est le client et Tiller est le serveur. Tiller doit être installé dans notre cluster k8s pour que Helm puisse fonctionner avec, mais nous allons d'abord avoir besoin d'un compte de service pour Tiller. Tiller doit pouvoir interagir avec notre cluster k8s, il doit donc être capable de créer des déploiements, des cartes de configuration, des secrets, etc. Bienvenue à RBAC.

Créons donc un fichier nommé tiller-rbac-config.yaml

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system

Dans ce fichier yaml, nous déclarons un ServiceAccount nommé tiller, puis nous déclarons un ClusterRoleBinding qui associe le compte de service du tiller à l'autorisation d'administrateur de cluster.

Maintenant, nous pouvons déployer tiller en utilisant le compte de service que nous venons de créer comme ceci:

$ helm init --service-account tiller

service de barre

Notez que ce n'est pas nécessairement une bonne pratique de déployer tiller de cette façon. En utilisant RBAC, nous pouvons limiter les actions que Tiller peut exécuter dans notre cluster et les espaces de noms sur lesquels il peut agir. Consultez cette documentation pour savoir comment utiliser RBAC pour restreindre ou modifier le comportement de Tiller dans votre cluster k8s.

Cette étape est vraiment importante pour les parties suivantes de cette série, car nous utiliserons plus tard ce compte de service pour interagir avec les k8 de Drone.


I.P statique

Si vous avez un nom de domaine et souhaitez associer un sous-domaine à votre instance Drone, vous devrez créer une adresse IP externe dans votre console Google Cloud. Donnez-lui un nom et souvenez-vous de ce nom, nous l'utiliserons juste après lors de la configuration de la carte Drone.

Associez cette adresse IP statique à votre domaine (et gardez à l'esprit que la propagation DNS peut prendre un certain temps).

Pour les besoins de cet article, le nom de l'adresse IP externe sera drone-kube et le domaine sera drone.myhost.io.


L'intégration

Nous devons d'abord configurer l'intégration Github pour notre instance Drone. Jetez un œil à cette documentation ou si vous utilisez un autre système de contrôle de version, vérifiez dans la documentation du Drone comment créer la bonne intégration. Actuellement, Drone prend en charge les VCS suivants:

Gardez à l'esprit que si vous n'utilisez pas l'intégration Github, les changements dans les variables d'environnement dans la section suivante doivent correspondre.


Graphique et configuration

Après une recherche rapide sur Google, nous pouvons voir qu'il y a un graphique pour Drone. Et c'est dans le incubator des graphiques Helm, nous devons donc d'abord ajouter le dépôt à Helm.

$ helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/
$ helm repo update

Maintenant que c'est fait, nous pouvons jeter un œil à la partie configuration de ce graphique. Nous allons créer un values.yaml fichier qui contiendra les informations requises pour que notre instance de drone fonctionne correctement.

service:
  httpPort: 80
  nodePort: 32015
  type: NodePort
ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: "gce"
    kubernetes.io/ingress.global-static-ip-name: "drone-kube"
    kubernetes.io/ingress.allow-http: "true"
  hosts:
    - drone.myhost.io
server:
  host: "http://drone.myhost.io"
  env:
    DRONE_PROVIDER: "github"
    DRONE_OPEN: "false"
    DRONE_GITHUB: "true"
    DRONE_ADMIN: "me"
    DRONE_GITHUB_CLIENT: "the github client secret you created earlier"
    DRONE_GITHUB_SECRET: "same thing with the secret"

Bien! Nous avons notre IP statique associée à notre domaine. Nous devons mettre le nom de cette adresse IP réservée dans les annotations Ingress afin qu'il sache à quelle adresse IP il doit se lier. Nous allons utiliser un équilibreur de charge GCE, et comme nous n'avons pas de certificat TLS, nous allons dire à Ingress qu'il est acceptable d'accepter les connexions HTTP. (Veuillez ne pas me frapper, je vous promets que nous verrons comment activer TLS plus tard.)

Nous déclarons également toutes les variables utilisées par Drone lui-même pour communiquer avec notre VCS, dans ce cas Github.

C'est ça. Nous sommes prêts. Allumons Helm!

$ helm install --name mydrone -f values.yaml incubator/drone

Étant donné que votre enregistrement DNS est maintenant propagé, vous devriez pouvoir accéder à votre instance de drone en utilisant le drone.myhost.io URL!


Déployer cert-manager

Dans le passé, nous avions kube-lego qui est maintenant déconseillé au profit de cert-manager.

La documentation indique que l'installation de cert-manager est aussi simple que l'exécution de cette commande:

$ helm install --name cert-manager --namespace kube-system stable/cert-manager


Création d'un émetteur ACME

Cert-manager est composé de plusieurs composants. Il utilise ce qu'on appelle des définitions de ressources personnalisées et permet d'utiliser kubectl pour contrôler les certificats, les émetteurs, etc.

Un Issuer ou ClusterIssuer représente une autorité de certification auprès de laquelle des certificats x509 peuvent être obtenus.

La différence entre un émetteur et un ClusterIssuer est que l'émetteur ne peut gérer que les certificats dans son propre espace de noms et être appelé à partir de cet espace de noms. Le ClusterIssuer ne dépend pas d'un espace de noms spécifique.

Nous allons créer un Let'sEncrypt ClusterIssuer afin que nous puissions émettre un certificat pour notre instance Drone et pour nos futurs déploiements. Créons un fichier nommé acme-issuer.yaml:

apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
  name: letsencrypt
spec:
  acme:
    server: https://acme-v01.api.letsencrypt.org/directory
    email: your.email.address@gmail.com
    privateKeySecretRef:
      name: letsencrypt-production
    http01: {}

Ici, nous créons le ClusterIssuer avec le défi HTTP activé. Nous allons seulement voir ce défi dans cet article, reportez-vous à la documentation pour plus d'informations sur les défis. N'oubliez pas de changer l'adresse e-mail associée dans votre émetteur!

$ kubectl apply -f acme-issuer.yaml

Nous pouvons également créer un ClusterIssuer à l'aide de l'environnement de stadification Let'sEncrypt qui est plus permissif avec des erreurs sur les requêtes. Si vous souhaitez tester sans émettre de vrais certificats, utilisez celui-ci à la place. Créer un nouveau fichier acme-staging-issuer.yaml:

apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    server: https://acme-staging.api.letsencrypt.org/directory
    email: your.email.address@gmail.com
    privateKeySecretRef:
      name: letsencrypt-staging
    http01: {}
$ kubectl apply -f acme-staging-issuer.yaml


Certificat

Maintenant que nous avons notre ClusterIssuer qui utilise la production de Let'sEncrypt, nous pouvons créer un manifeste qui résoudra le défi ACME pour nous. Nous allons d'abord avoir besoin du nom de l'entrée créée par le graphique Drone:

$ kubectl get ingress
NAME            HOSTS             ADDRESS       PORTS     AGE
mydrone-drone   drone.myhost.io   xx.xx.xx.xx   80        1h

Maintenant que nous avons ces informations, créons le drone-cert.yaml fichier:

apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: mydrone-drone
  namespace: default
spec:
  secretName: mydrone-drone-tls
  issuerRef:
    name: letsencrypt # This is where you put the name of your issuer
    kind: ClusterIssuer
  commonName: drone.myhost.io # Used for SAN
  dnsNames:
  - drone.myhost.io
  acme:
    config:
    - http01:
        ingress: mydrone-drone # The name of your ingress
      domains:
      - drone.myhost.io

Il y a de nombreux champs à expliquer ici. La plupart d'entre eux sont assez explicites et peuvent être trouvés dans la documentation sur la validation HTTP.

Les choses importantes ici sont:

  • spec.secretName: Le secret dans lequel le certificat sera stocké. habituellement
    ce sera préfixé avec -tls donc ça ne se mélange pas avec les autres
    secrets.
  • spec.issuerRef.name: Le nom que nous avons défini plus tôt pour notre ClusterIssuer
  • spec.issuerRef.kind: Spécifiez que l'émetteur est un ClusterIssuer
  • spec.acme.config.http01.ingress: Le nom de l'entrée déployée avec Drone

Appliquons maintenant ceci:

$ kubectl apply -f drone-cert.yaml
$ kubectl get certificate
NAME            AGE
mydrone-drone   7m
$ kubectl describe certificate mydrone-drone
...
Events:
  Type     Reason                 Age              From                     Message
  ----     ------                 ----             ----                     -------
  Warning  ErrorCheckCertificate  33s              cert-manager-controller  Error checking existing TLS certificate: secret "mydrone-drone-tls" not found
  Normal   PrepareCertificate     33s              cert-manager-controller  Preparing certificate with issuer
  Normal   PresentChallenge       33s              cert-manager-controller  Presenting http-01 challenge for domain drone.myhost.io
  Normal   SelfCheck              32s              cert-manager-controller  Performing self-check for domain drone.myhost.io
  Normal   ObtainAuthorization    6s               cert-manager-controller  Obtained authorization for domain drone.myhost.io
  Normal   IssueCertificate       6s               cert-manager-controller  Issuing certificate...
  Normal   CertificateIssued      5s               cert-manager-controller  Certificate issued successfully

Nous devons attendre que cette dernière ligne apparaisse, le CertificateIssued avant de pouvoir mettre à jour nos valeurs Ingress. Cela peut prendre un certain temps, soyez patient car la mise à jour de Google Cloud Load Balancers peut prendre plusieurs minutes.


Améliorez les valeurs du drone

Maintenant que nous avons notre secret contenant le certificat TLS approprié, nous pouvons revenir à notre values.yaml fichier que nous avons utilisé plus tôt pour déployer Drone avec sa carte et ajouter le secret TLS à la section d'entrée! Nous allons également désactiver HTTP sur notre entrée (seul HTTPS sera servi) et modifier notre server.host pour refléter ce changement HTTPS.

service:
  httpPort: 80
  nodePort: 32015
  type: NodePort
ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: "gce"
    kubernetes.io/ingress.global-static-ip-name: "drone-kube"
    kubernetes.io/ingress.allow-http: "false" # ← Let's disable HTTP and allow only HTTPS
  hosts:
    - drone.myhost.io
  # Add this ↓
  tls:
    - hosts:
      - drone.myhost.io
      secretName: mydrone-drone-tls
  # End
server:
  host: "https://drone.myhost.io" # ← Modify this too 
  env:
    DRONE_PROVIDER: "github"
    DRONE_OPEN: "false"
    DRONE_GITHUB: "true"
    DRONE_ADMIN: "me"
    DRONE_GITHUB_CLIENT: "the github client secret you created earlier"
    DRONE_GITHUB_SECRET: "same thing with the secret"

Et nous devons juste mettre à niveau notre déploiement:

$ helm upgrade mydrone -f values.yaml incubator/drone

Vous devrez également modifier votre application Github.

Dans cet article, nous avons vu comment déployer un cluster Kubernetes sur GKE, comment créer un compte de service avec la liaison de rôle de cluster appropriée pour déployer Tiller, comment utiliser Helm et comment déployer un graphique avec l'exemple de drone.

Dans le prochain article, nous verrons comment rédiger un pipeline de qualité pour un projet Go ainsi que comment passer à Google Cloud Registry.

Grâce à @shirley_leu pour relire cet article et corriger mes erreurs en anglais!

Cet article est une rediffusion de mon blog. Trouvez le post original ici.

Nous serions ravis de connaître votre avis

      Laisser un commentaire