Comment créer un cluster Kubernetes sécurisé par défaut avec un pipeline CI / CD de base sur AWS

Écrit par Matthew Sheppard et Donald Carnegie

Kuber-what-es?

Kubernetes (prononcé «koo-burr-NET-eez») est une plate-forme open source permettant d'automatiser le déploiement, la mise à l'échelle et l'exploitation de conteneurs d'applications. Les enfants cools se réfèrent souvent à cela par l'abréviation «k8s» pas très bonne (IOHO). Le travail de Kubernetes consiste à optimiser l’utilisation de votre infrastructure tout en veillant à ce que vos charges de travail conteneurisées soient disponibles et qu’elles puissent évoluer en fonction des besoins. Certaines entreprises ont déclaré être en mesure de réduire leurs coûts d'infrastructure cloud de 50% à 70% par rapport à une architecture traditionnelle basée sur une machine virtuelle.

Contenir votre succès

Kubernetes est une success story massive pour la Cloud Native Computing Foundation et la communauté open source qui la sous-tend. Annoncé pour la première fois à la mi-2014 en tant que petit projet dirigé par une équipe d'ingénieurs de Google, il s'est développé pour devenir la plate-forme d'orchestration de conteneurs de facto et un produit de base dans l'écosystème de cloud public. Microsoft, Google, Amazon et IBM ont tous une offre gérée de Kubernetes. Pour ce qui est des contributeurs et de la vélocité, Kubernetes n’est en second lieu que dans les projets open-source du noyau Linux. Il alimente Pokemon Go pour que les abonnés de HBO GO puissent diffuser en douceur la saison 7 de Game of Thrones.

Kubernetes continu

En tant qu’utilisateurs et ingénieurs d’applications Web modernes, nous nous attendons à ce qu’elles soient disponibles 24 heures sur 24, 7 jours sur 7, et qu’elles puissent en déployer de nouvelles versions plusieurs fois par jour. Kubernetes en soi ne suffit pas pour atteindre cet objectif. Cela garantit que nos applications conteneurisées fonctionnent quand et où nous le voulons et peuvent trouver les outils et les ressources dont elles ont besoin. Cependant, pour que nos ingénieurs disposent de toutes leurs ressources, nous devons créer un pipeline CI / CD autour de Kubernetes.

Weaveworks a inventé GitOps pour décrire l'utilisation de Git comme source déclarative de vérité pour l'état du cluster Kubernetes. Git devient notre moyen de suivi de l'état du système, et nous utilisons des constructions au sein de git, telles que les demandes d'extraction, comme moyen de fusionner l'état détenu par git avec l'état de l'infrastructure de cloud. En résumé, les demandes de tirage approuvées entraînent des modifications en direct de la production. Il s’agit d’une approche vraiment puissante puisqu’un flux de travail de code source éprouvé peut être appliqué à la gestion d’infrastructures. La saisir pleinement peut nous débarrasser des processus de contrôle du changement bureaucratiques traditionnels qui sont compliqués, prennent trop de temps et manquent de responsabilité. Les modifications apportées à votre infrastructure sont toujours visibles, traçables et comptables à 100%. L'historique est stocké en permanence dans le référentiel git, et revenir à un point de l'histoire est un jeu d'enfant.

Pourquoi devrais-je utiliser Kubernetes?

Les conteneurs sont déjà une grande réussite dans le cloud computing. En dépit de leur période de temps relativement courte dans notre boîte à outils, ils sont devenus un aliment de base du cloud computing moderne et sont exploités par de nombreuses applications grand public. Toutefois, le fardeau de l’orchestration, de la gestion et de la maintenance des systèmes conteneurisés peut être énorme - c’est là que Kubernetes entre en jeu. Kubernetes exploite tous les atouts de la conteneurisation et fournit une plate-forme pour les déployer et les gérer plus facilement.

Kubernetes est un facilitateur pour DevOps; il aide à mettre en œuvre les pratiques clés de DevOps et ouvre la voie aux organisations pour implémenter DevOps. Où que vous l'installiez, que ce soit sur votre ordinateur portable, chez un fournisseur de cloud ou dans un centre de données sur site, il fournit des déploiements automatisés de vos applications conteneurisées avec des environnements entièrement cohérents. Avec Kubernetes, il n’est plus temps de construire et de tester avec succès au niveau local, pour constater que votre application se comporte différemment dans les environnements de test ou de production!

YATR? (Encore un autre tutoriel, vraiment?)

Il existe de nombreux tutoriels sur Kubernetes, alors pourquoi en écrire un autre? Bonne question! Pour construire des clusters Kubernetes pour notre propre plaisir et pour nos clients, nous n'avons pas trouvé de didacticiel rassemblant tous les éléments nécessaires à la configuration d'un cluster sur AWS pouvant être préparé pour la production. La documentation est en grande partie présente, mais c’est une chasse au trésor que de la retrouver et de la faire fonctionner dans chaque situation particulière. Cela rend particulièrement difficile toute personne qui entreprend son premier projet pilote Kubernetes ou qui passe à l’étape supérieure à partir d’un cluster de minikube local.

Le but de ce tutoriel est de combler cette lacune et de passer en revue la configuration du cluster Kubernetes qui:

  • Haute disponibilité: nous voulons nous assurer que nos environnements peuvent gérer les défaillances et que nos applications conteneurisées continueront à s'exécuter si certains de nos nœuds échouent ou si une zone de disponibilité AWS connaît une panne. Pour ce faire, nous exécuterons des maîtres et des noeuds Kubernetes sur 3 zones de disponibilité AWS.
  • Applique le «principe du moindre privilège»: par défaut, tous les pods doivent s'exécuter dans un contexte de sécurité restrictif. ils ne devraient pas avoir la possibilité d'apporter des modifications au cluster Kubernetes ou à l'environnement AWS sous-jacent. Tout pod qui doit apporter des modifications au cluster Kubernetes doit utiliser un compte de service nommé avec le rôle et les stratégies appropriés attachés. Si un pod doit passer des appels à l'API AWS, ces appels doivent être gérés afin de garantir que le pod dispose des autorisations suffisantes pour les établir et utilise uniquement des informations d'identification IAM temporaires. Nous y parviendrons en utilisant le contrôle d’accès basé sur le rôle (RBAC) de Kubernetes afin de s’assurer que les pods s’exécutent par défaut sans possibilité de modifier la configuration du cluster. Lorsque des services de cluster spécifiques nécessitent des autorisations, nous allons créer un compte de service spécifique et le lier à une étendue d'autorisations requise (c'est-à-dire à l'échelle du cluster ou dans un seul espace de noms) et accorder les autorisations requises à ce compte de service. L'accès à l'API AWS sera négocié via kube2iam; tout le trafic provenant des pods destinés à l'API AWS sera redirigé vers kube2iam. Sur la base des annotations dans les configurations du pod, kube2iam fera un appel à l'API AWS pour extraire les informations d'identification temporaires correspondant au rôle spécifié dans l'annotation et les renvoyer à l'appelant. Tous les autres appels d'API AWS seront soumis à un proxy via kube2iam afin de garantir l'application du principe de privilège minimal et d'éviter que la stratégie ne soit contournée.
  • S'intègre à Route53 et à Classic Load Balancers: lorsque nous déployons une application, nous voulons pouvoir déclarer dans la configuration comment elle est mise à la disposition du monde et où elle peut être trouvée, et l'automatiser pour nous. Kubernetes fournira automatiquement un équilibreur de charge classique à une application et external-dns nous permettra de lui attribuer un nom de domaine complet (FQDN) convivial, le long de l'infrastructure sous forme de code.
  • Possède un pipeline de base CI / CD: nous souhaitons automatiser la manière dont nous apportons des modifications au cluster et à la manière dont nous déployons / mettons à jour des applications. Les fichiers de configuration spécifiant notre configuration de cluster seront validés dans un référentiel Git et le pipeline CI / CD les appliquera au cluster. Pour ce faire, nous utiliserons Travis-CI pour appliquer la configuration validée dans notre branche principale au cluster Kubernetes. C’est un premier pas dans la direction de GitOps, mais cela ne nous donne pas une capacité complète de GitOps.

À la fin du didacticiel, nous nous retrouverons avec un cluster Kubernetes ressemblant à ceci:

Notre cluster Kubernetes à l'état final

Avant de commencer

Nous supposons que vous connaissez déjà Kubernetes. Si vous êtes nouveau dans Kubernetes, il est recommandé de consulter le didacticiel Kubernetes Basics et de vous familiariser avec ses concepts clés.

Pour construire notre cluster, nous devons nous assurer que les outils suivants sont installés:

  • Kubectl
    kubectl (Kubernetes Control) est un outil de ligne de commande permettant d’interagir avec un cluster Kubernetes, qu’il soit exécuté localement sur votre ordinateur (à l’aide de minikube) ou dans le cloud.
  • kops
    Le projet Kubernetes Operations (kops) fournit des outils pour la construction et l’exploitation de clusters Kubernetes dans le cloud. Il prend actuellement en charge Google Cloud et AWS (avec d'autres fournisseurs en version bêta). Nous utiliserons kops pour créer et gérer notre cluster dans ce didacticiel.
  • Terraform
    Terraform est un outil IAC (Infrastructure as Code) qui permet aux utilisateurs de définir une infrastructure dans un langage de configuration de haut niveau, qui peut ensuite être utilisé pour créer une infrastructure dans un fournisseur de services tel qu'AWS ou Google Cloud Platform. Nous allons utiliser Terraform pour créer nos conditions préalables pour kops et pour modifier les stratégies IAM créées par kops.
  • AWS CLI
    AWS CLI est un outil de ligne de commande permettant d'interagir avec AWS. Cela est requis par kops et Terraform pour effectuer des opérations sur AWS.

Les instructions d'installation sont disponibles sur les liens fournis.

Ce tutoriel a été créé avec Kubernetes v1.8 et kops v1.8.1.

Nous utilisons Mac OS X avec Homebrew. Il suffit donc d’exécuter les commandes suivantes pour les installer:

mise à jour de $ brasser
$ brew installer kubectl
$ brasser installer kops
$ brew installer python3
$ easy_install pip
$ pip install awscli - mise à jour - utilisateur
$ export PATH = ~ / .local / bin: $ PATH
$ brasser installer terraform

Créer le cluster

Étape 1: Clonez notre référentiel

$ git clone https://github.com/slalom-london/k8s-tutorial

Étape 2: Configurez un nom de domaine complet qui sera utilisé pour le cluster dans Route53

Le cluster Kubernetes que nous allons configurer utilisera un nom de domaine complet hébergé sur Route53 pour exposer les points de terminaison de service et le plan de contrôle de l'API. Vous pouvez enregistrer un nouveau nom de domaine complet ou transférer un nom de domaine complet existant. AWS propose une procédure complète pour chacune de ces options:

Étape 3: créez les conditions préalables requises pour kops

Pour que le groupe puisse créer le cluster, un magasin S3 doit contenir la configuration du cluster et un compte d'utilisateur IAM associé aux stratégies suivantes:

AmazonEC2FullAccess
AmazonRoute53FullAccess
AmazonS3FullAccess
IAMFullAccess
AmazonVPCFullAccess

prereqs / kops_pre_reqs.tf le créera pour vous. Il créera également un compartiment S3 qui sera utilisé comme magasin distant pour notre état Terraform. Cela permet à plusieurs utilisateurs de travailler avec un ensemble d'infrastructure en tant que code sans provoquer de conflits. Vous devrez mettre à jour le fichier pour remplacer {my_bucket_name} et {my_tf_bucket_name} par le nom de votre compartiment choisi.

Puis exécutez les commandes suivantes:

$ cd prereqs
$ terraform init
plan de terraform $
$ terraform s'appliquent

Si vous vous connectez à votre compte AWS, vous verrez maintenant un utilisateur IAM kops nouvellement créé, un compartiment S3 pour le magasin d'état kops et un autre compartiment S3 pour le magasin d'état Terraform.

Étape 4: utilisez kops pour mettre en place le cluster

Dans l'étape précédente, nous avons créé un compte IAM pour kops. Nous devons maintenant configurer notre client AWS CLI pour utiliser ce compte. Nous pouvons récupérer l'ID IAM et la clé secrète kops du fichier que Terraform utilise pour stocker l'état de ce qu'il a créé à l'étape précédente. Ouvrez terraform.tfstate dans votre éditeur de texte et recherchez la section similaire à celle ci-dessous:

Notez les valeurs dans les champs {iam_id} et {aws_secret_key}, puis exécutez la commande suivante:

$ aws configure --profile kops
ID de clé d'accès AWS [Aucun]: {iam_id}
Clé d'accès secrète AWS [Aucune]: {aws_secret_key}
Nom de région par défaut [Aucun]: {your_chosen_aws_region}
Format de sortie par défaut [Aucun]: texte

Ensuite, nous devons définir quelques variables d'environnement afin que kops sache quel compte AWS IAM utiliser et où il doit placer son magasin d'état:

$ export AWS_PROFILE = kops
$ export KOPS_STATE_STORE = s3: // {my_bucket_name}

Passons maintenant à l’événement principal: utilisons kops pour construire notre cluster. Exécutez la commande suivante en remplaçant votre région AWS, votre zone DNS et le nom du cluster que vous avez choisi:

$ kops crée un cluster --cloud aws \
 --bastion \
 --node-compte 3 \
 --node-size t2.medium \
 - taille maître t2.medium \
 --zones {your_chosen_aws_region} a, {votre_chosen_aws_region} b, {votre_chosen_aws_region} c \
 --master-zones {votre_chosen_aws_region} a, {votre_chosen_aws_region} b, {votre_chosen_aws_region} c \
 --dns-zone {your_dns_zone} \
 --topologie privée \
 --réseau calicot \
 --autorisation RBAC \
 --name {your_cluster_name} \
 --out = k8s \
 --target = terraform --yes

Cette commande indique à kops que nous voulons construire un cluster qui:

  • Utilisera AWS
  • A un noeud maître de taille t2.medium dans chacune des zones de disponibilité spécifiées
  • Possède 3 nœuds de travail de taille t2.medium. kops répartira les nœuds de travail de manière uniforme sur chacune des zones de disponibilité
  • Utilise une topologie de réseau privé, ce qui signifie que tous les nœuds ont des adresses IP privées et ne sont pas directement accessibles depuis Internet public.
  • Utilise Calico comme interface réseau de conteneur remplaçant kubenet en raison des exigences de la topologie de réseau privé
  • Utilise les autorisations d'accès RBAC pour Kubernetes
  • Est décrit dans un fichier de configuration Terraform à écrire dans le répertoire spécifié par --out

kops génère un ensemble de fichiers de configuration Terraform dans un nouveau répertoire k8s pouvant être appliqué à la création du cluster. Avant de créer notre cluster, nous voulons ajouter un fichier de configuration pour indiquer à Terraform de conserver son magasin d'état sur le compartiment S3 que nous venons de créer.

$ cd k8s
$ terraform init
plan de terraform $
$ terraform s'appliquent

Il faudra entre 10 et 15 minutes pour que votre cluster soit disponible. Vous pouvez vérifier l'état du cluster en exécutant la commande suivante:

$ kops valide le cluster

Une fois la construction du cluster terminée, vous devriez voir une sortie comme celle-ci:

Utilisation de cluster à partir du contexte kubectl: cluster.zigzag-london.com
Validation du cluster cluster.zigzag-london.com
GROUPES D'INSTANCE
NOM RÔLE MACHINETYPE MIN MAX SUBNETS
bastions Bastion t2.micro 1 1 utilitaire-eu-west-1a, utilitaire-eu-west-1b, utilitaire-eu-west-1c
master-eu-west-1a Master t2.medium 1 1 eu-west-1a
master-eu-west-1b Master t2.medium 1 1 eu-west-1b
master-eu-west-1c Master t2.medium 1 1 eu-west-1c
noeuds Noeud t2.medium 3 3 eu-west-1a, eu-ouest-1b, eu-west-1c
NODE STATUS
NOM ROLE READY
ip-172-20-107-234.eu-west-1.compute.internal master True
ip-172-20-124-39.eu-west-1.compute.internal node True
ip-172-20-44-152.eu-west-1.compute.internal master True
ip-172-20-60-188.eu-west-1.compute.internal node True
ip-172-20-79-79.eu-west-1.compute.internal master True
ip-172-20-87-125.eu-west-1.compute.internal node True
Votre cluster cluster.zigzag-london.com est prêt

Mettre en place un environnement CI / CD

Afin de mettre en œuvre GitOps, nous avons besoin d’un environnement CI / CD pour surveiller notre référentiel et exécuter les mises à jour. Pour ce tutoriel, nous allons configurer notre environnement CI / CD pour qu'il exécute les étapes de déploiement lors de chaque envoi vers la branche principale de notre référentiel. Nous le faisons à des fins de démonstration; permettre aux développeurs de faire cela est définitivement une mauvaise pratique. Dans un projet réel, nous recommandons une stratégie de branchement des fonctionnalités avec une révision du code et une étape d'approbation du responsable du développement.

Pour ce tutoriel, nous allons utiliser TravisCI, un service de CI basé sur le cloud. TravisCI est gratuit tant que:

  • Vous hébergez votre dépôt dans Github
  • Le référentiel est accessible au public

Étape 1: Configuration du référentiel comptes et clonage

  • Accédez à GitHub et inscrivez-vous \ connectez-vous
  • Créez un nouveau référentiel vide et nommez-le “k8s-ci”
  • Clonez ce référentiel sur votre machine locale:
$ git clone 
  • Accédez à TravisCI et inscrivez-vous avec votre compte GitHub. Accédez à votre profil d'utilisateur en cliquant sur votre nom en haut à droite.
  • Cliquez sur le curseur en regard du rapport GitHub pour activer TravisCI pour ce référentiel.

Étape 2: Configuration des déclencheurs

En pratiquant GitOps, nous souhaitons uniquement nous déployer sur une demande de tirage approuvée. Nous pouvons le configurer dans Travis en cliquant sur Plus d’options → Paramètres.

  • Assurez-vous que «construire les branches poussées» est activé
  • Assurez-vous que l'option «Construire les demandes d'extraction poussées» est activée.

Travis obtient la grande majorité de ses instructions d’un fichier yaml stocké dans votre référentiel. Créez un fichier vide nommé .travis.yml à la racine de votre référentiel et nous pourrons commencer à le configurer en fonction du fichier .travis.yml de notre référentiel:

  • Ligne 1: Spécifie que nous voulons uniquement qu'une construction soit exécutée sur la branche principale. Dans un environnement réel, nous déploierions probablement également en poussant une branche, mais dans un environnement de test plutôt que dans un environnement de production. Une solution consiste à utiliser des variables d'environnement pour appliquer une logique conditionnelle au script de déploiement, mais cette tâche est hors de portée.
  • Ligne 4: Spécifie que nous avons besoin d'autorisations root avec sudo pour installer nos dépendances.
  • Ligne 5: C'est le début du bloc où nous définissons les autorisations sur chacun de nos scripts pour qu'ils soient exécutables.
  • Ligne 10: C'est le début du bloc où nous spécifions les scripts qui doivent être exécutés en premier afin de configurer l'environnement CI avant de pouvoir exécuter les scripts qui effectuent le déploiement réel.
  • Ligne 13: C'est le début du bloc où nous spécifions les scripts à exécuter pour exécuter les tâches de déploiement.

Étape 3: Gérer les secrets

Nous ne voulons pas conserver nos secrets AWS dans un référentiel public en texte clair; ce serait une très mauvaise pratique en matière de sécurité de l'information. Travis fournit facilement un outil CLI qui peut être utilisé pour stocker vos secrets à injecter au moment de la construction. Travis génère une nouvelle paire de clés publique / privée pour chaque nouveau compte. Ces secrets seront chiffrés à l'aide de cette paire de clés et injectés sous forme de variables d'environnement à chaque exécution de la génération. Pour configurer cela, exécutez les commandes suivantes à la racine de votre référentiel et connectez-vous à l'aide des informations demandées:

$ sudo gem installer travis
$ travis login --org

Il existe deux scripts pré-chargés dans le répertoire build-scripts de notre référentiel, prêts à recevoir vos secrets. Copiez le répertoire build_scripts de votre copie locale de notre référentiel k8s-tutorial dans votre propre référentiel k8s-ci et mettez-les à jour comme suit:

  • large-secrets.txt: Ajoutez vos clés d'accès Kubernetes. Ceux-ci peuvent être trouvés dans ~ / .kube / config
  • setup-secrets.sh: Ajoutez votre mot de passe Kubernetes (à nouveau trouvé dans ~ / .kube / config) et les clés d'accès AWS à partir de ~ / .aws / credentials

Ensuite, à partir de la racine de votre référentiel, exécutez le script setup-secrets.sh à l'aide de la commande suivante:

$ chmod 755 build-scripts / setup-secrets.sh
$ ./build-scripts/setup-secrets.sh

Notez la commande openssl que le script setup-secrets.sh renvoie pour plus tard, car nous en aurons besoin pour déchiffrer les secrets.

Ce script chiffrera vos secrets en utilisant Travis et mettra à jour votre fichier .travis.yml. Commettez les secrets chiffrés dans votre référentiel:

$ git add scripts de construction / large-secrets.txt.enc .travis.yml
$ git commit -m "Validation de secrets cryptés"

Maintenant que vos secrets sont sécurisés dans Travis, nous vous suggérons fortement de les supprimer de tous les fichiers et scripts. Il peut être très facile de commettre accidentellement des secrets au contrôle de la source, et vos auteurs sont coupables de ce péché! Pour attraper des secrets accidentels, nous utilisons git-secrets. Vous pouvez le configurer en procédant comme suit:

$ brasser installe git-secrets
$ git-secrets --install

Étape 4: Installez les dépendances

Comme TravisCI exécute chaque construction dans un conteneur Docker propre, nous devons installer nos dépendances à chaque fois. Ces dépendances sont les mêmes que celles décrites dans la section «Avant de commencer» de ce message. Créez un fichier appelé install-dependencies.sh dans le dossier build-scripts et collez-y la configuration suivante:

Maintenant, validez ce fichier dans votre référentiel:

$ git add install-dependencies.sh
$ git commit -m "Ajout d'un script pour installer des dépendances"

Étape 5: Injectez nos secrets

Nous avons maintenant besoin d'un script pour configurer nos secrets dans le conteneur Docker dans lequel nous allons effectuer nos étapes de construction. Créez un fichier nommé inject-secrets.sh dans le dossier des scripts de construction. Collez le script ci-dessous et mettez-le à jour comme suit:

  • Remplacez {votre URL de cluster ici} par l'URL de votre cluster Kubernetes.
  • Remplacez la commande OpenSSL notée à l’étape 3 de cette section par {Votre commande openssl à partir de l’étape de chiffrement des secrets ici} en ajoutant ./build-scripts/ avant large-secrets.txt.enc.
  • Remplacez {your-aws-region} par la région AWS que vous utilisez.

Ce script va extraire nos secrets de l'environnement Travis, les décrypter et les injecter dans les fichiers de configuration pertinents.

Vous remarquerez dans le script ci-dessus qu'il fait référence à un fichier du répertoire de scripts de construction appelé kubeconfig - nous devrons le créer également. Collez le contenu ci-dessous en remplaçant la variable {Votre URL de cluster ici} par l'URL de votre cluster Kubernetes.

Engagez ces deux fichiers dans votre référentiel:

$ git add inject-secrets.sh kubeconfig
$ git commit -m "Ajout d'un script pour injecter des secrets et un fichier kubeconfig"

Étape 6: Configuration de l'environnement

Avant de pouvoir déployer des applications, nous devons préparer le cluster en déployant la configuration pour kube2iam et external-dns. La configuration de chacun de ces outils doit être appliquée dans un ordre défini:

  • Appliquez la configuration Terraform pour créer un nouveau rôle AWS IAM (et les attributions de stratégie requises à ce rôle), ainsi qu'une relation de confiance avec le rôle AWS IAM sous lequel les nœuds sont exécutés. La relation de confiance permet à un nœud d'assumer le nouveau rôle IAM.
  • Appliquez la configuration de Kubernetes RBAC pour créer un compte de service, le lier à une étendue d'autorisations requise et attribuer les autorisations requises à ce compte de service. Ce compte de service est ensuite spécifié dans le cadre de la configuration des pods fournissant chacun des services spécifiques.
  • Appliquez les configurations Kubernetes pour déployer les services. Selon le service déployé, il peut s'agir d'un déploiement Kubernetes ou de DaemonSet.

Nous allons construire notre script de déploiement pour que le cluster soit toujours configuré en premier.

Copiez les dossiers contenant les modèles pour external-dns et kube2iam de notre référentiel vers votre référentiel.

Tout d'abord, nous allons créer un script qui appliquera notre configuration Terraform. Créez un fichier appelé deploy-terraform.sh dans le répertoire build-scripts et ajoutez-y le code suivant:

Ce script parcourt la structure de répertoires de notre référentiel et applique tous les fichiers de configuration Terraform trouvés.

(Remarque: dans un environnement de production réel, nous ajouterions des contrôles dans notre pipeline CI pour nous assurer que Terraform n'est pas utilisé de manière malveillante.)

Engagez-le dans votre référentiel:

$ git add deploy-terraform.sh
$ git commit -m "Ajout du script de déploiement Terraform"

Nous sommes maintenant prêts à mettre à jour et à valider la configuration Terraform pour chacun de nos 3 services dans le référentiel:

  • Mettez à jour le fichier external_dns / pod-role-trust-policy.json et remplacez {your-node-iam-role-arn} par le nœud IAM ARN pour Kubernetes de votre cluster. Cela peut être trouvé en exécutant la commande suivante:
$ aws iam list-roles | noeud grep
  • Mettez à jour external_dns / main.tf pour remplacer {your-aws-region} par la région AWS dans laquelle vous travaillez et {your-tf-bucket} par le nom du compartiment dans lequel vous avez choisi de stocker le magasin d'état Terraform.

Commit la configuration du service dans votre référentiel:

$ git add external_dns / pod-role-trust-policy.json external_dns / external-dns-iam-setup.tf external_dns / external-dns-role-rights.json external_dns / main.tf
$ git commit -m "Ajout de la configuration du service Terraform du cluster"

Travis est configuré pour appliquer la configuration à chaque transfert au maître. Par conséquent, si nous exécutons un transfert maintenant:

$ git push

Nous devrions pouvoir voir toute notre configuration Terraform appliquée à notre compte AWS dans le journal des tâches.

Nous avons maintenant créé tous les rôles IAM et les relations de confiance nécessaires à notre environnement Kubernetes.

Ensuite, nous avons besoin d’un script pour appliquer nos configurations Kubernetes aux conditions préalables de notre environnement. Pour terminer cette étape, vous devrez copier et mettre à jour les fichiers suivants de notre référentiel dans votre référentiel:

  • external_dns / external_dns.yaml: remplacez {votre-zone-dns} par la zone DNS que vous utilisez, {votre-identifiant} par quelque chose qui différenciera les enregistrements DNS produits par external-dns (par exemple, votre nom) et {votre -external-dns-iam-role-arn} avec l'ARN IAM du rôle créé lors de l'application de la configuration Terraform. Cela peut être trouvé en exécutant la commande suivante:
$ aws iam get-role - nom_rôle external_dns_pod_role
  • kube2iam et rbac /: Aucune mise à jour requise

Ces mises à jour spécifient le rôle IAM que chaque pod devrait assumer lorsqu'il doit accéder à l'API AWS.

Maintenant, validez ces fichiers dans le référentiel:

$ git add external_dns / external_dns.yaml rbac / kube2iam /
$ git commit -m "Ajout de la configuration external-dns k8s"

Nous allons maintenant commencer à créer notre script de déploiement pour nos services Kubernetes. Créez un fichier nommé deploy-k8s.sh dans le dossier build-scripts. Commencez le fichier avec un en-tête comme ceci:

Ensuite, ajoutez les étapes ci-dessous qui déploient la configuration de Kubernetes RBAC sur le cluster:

Ces étapes sont nécessaires car le service external-dns nécessite des droits d'API Kubernetes pour pouvoir s'exécuter et fournir son service au cluster. Pour rappel, RBAC s'assure que les pods n'ont pas accès à l'API Kubernetes par défaut. Ceci est conforme au «principe du moindre privilège» et empêche les pods de pouvoir modifier les paramètres du cluster s'ils sont compromis pour une raison quelconque.

Afin que TravisCI applique ces modifications, nous devons ajouter une étape supplémentaire à notre fichier .travis.yml pour exécuter deploy-k8s.sh. Ajoutez ce qui suit à la section before_install:

- chmod + x ./build-scripts/deploy-k8s.sh

Et les éléments suivants dans le script: section:

- "./build-scripts/deploy-k8s.sh"

Maintenant, validez deploy-k8s.sh, .travis.yml et transmettez à votre référentiel le contrôle et assurez-vous qu'il n'y a pas d'erreur dans le journal de construction de Travis:

$ git add scripts de construction / deploy-k8s.sh .travis.yml
$ git commit -m "Ajout de la configuration Travis pour déployer la configuration k8"
$ git push

Maintenant que la configuration Terraform et RBAC est ajoutée à notre pipeline CI / CD, ajoutons les étapes pour déployer kube2iam dans notre script deploy-k8s.sh:

kube2iam est déployé en premier car external-dns passera des appels à l'API AWS en utilisant kube2iam en tant que courtier.

Poussez maintenant votre référentiel à maîtriser et assurez-vous qu'il n'y a pas d'erreur dans le journal de construction:

$ git add scripts de construction / deploy-k8s.sh
$ git commit -m "Mise à jour de la configuration de Travis pour déployer la configuration de k8"
$ git push

Voyons maintenant sur notre cluster pour nous assurer que tous les services ont été correctement déployés. external-dns est un déploiement, nous pouvons donc exécuter la commande suivante pour obtenir son statut:

$ kubectl obtenir les déploiements --namespace = kube-system

Si tout a été déployé correctement, nous devrions voir quelque chose comme:

NOM DÉSIRÉ ACTUEL ACTUEL À JOUR DISPONIBLE ÂGE
contrôleurs de calico-kube 1 1 1 1 1h
calico-policy-controller 0 0 0 0 1h
contrôleur-dns 1 1 1 1 1h
external-dns 1 1 1 1 1 1m
kube-dns 2 2 2 2 1h
kube-dns-autoscaler 1 1 1 1 1h

kube2iam est déployé en tant que DaemonSet car il doit être exécuté sur tous les nœuds pour pouvoir échanger des appels avec l'API AWS. Nous lançons la commande suivante pour obtenir son statut:

$ kubectl get ds --namespace = kube-system

Si tout va bien, nous devrions voir quelque chose comme:

NOM DU SÉLECTEUR DE NOEUD DISPONIBLE ACTUEL À JOUR DÉSIRÉ DÉSIRÉ DÉSIRÉ
calico-node 6 6 6 6 6  1h
kube2iam 3 3 3 3 3  7m

Étape 7: Déployer une application de test

Il est maintenant temps de tirer parti du travail acharné de configuration de notre cluster et de voir la puissance de notre flux de travail et de notre infrastructure en tant que code pour déployer facilement une application de test!

Premièrement, nous devons ajouter une étape de déploiement à notre script deploy-k8s.sh qui déploiera nos applications:

Cette étape appliquera tous les fichiers de configuration Kubernetes du répertoire apps de notre référentiel au cluster. Commettez ce changement et poussez pour maîtriser:

$ git add scripts de construction / deploy-k8s.sh
$ git commit -m "Mise à jour de la configuration de Travis pour déployer la configuration de k8s pour les applications"
$ git push

Au moment où nous entamons notre cheminement vers GitOps, suivons le déroulement du processus GitOps pour le déploiement d’une application de test:

  • Créez une branche locale en exécutant la commande suivante:
$ git checkout -b testapp
  • Créez un dossier sous les applications appelées dans votre référentiel
  • Dans le dossier des applications, créez un fichier appelé hello_app_deployment.yaml et ajoutez-y les éléments suivants:

Cette configuration comporte 2 sections:

  1. Déploiement: spécifie les détails du conteneur que nous allons exécuter, la quantité de ressources à lui attribuer, le portage de l'application à l'intérieur du conteneur et le nombre de réplicas de cette application à exécuter. Dans ce cas, nous allons exécuter un conteneur simple qui affiche «Salutations, globe!», Puis le nom d'hôte du conteneur sur le port 8080. Nous spécifions que nous allons exécuter 3 réplicas - une pour chacun de nos nœuds de cluster.
  2. Service: Ceci spécifie comment le déploiement doit être exposé, en interne ou en externe. Dans le cas de notre application de test, nous l'exposons en interne sur l'IP de cluster sur le port 80. Nous spécifions également le nom de domaine complet (par exemple, quelque chose comme salations.votredomaine.com) auquel notre application est accessible ici. Vous devrez remplacer {votre nom de domaine complet ici} par votre nom de domaine complet (FQDN) convivial.

Maintenant, validez ce fichier dans votre branche locale et placez-la dans le référentiel distant:

$ git add hello_app_deployment.yaml
$ git commit -m "Ajout d'une application de test"
$ git push -u origin testapp

Si nous nous connectons à GitHub, nous devrions maintenant voir que nous avons une nouvelle branche appelée "testapp":

Nous voulons soulever une demande d'extraction et fusionner pour maîtriser, alors cliquez sur «Comparer et extraire une demande» et suivez le processus pour mener à bien cette activité.

Une fois le déploiement terminé, nous pouvons vérifier que notre application de test s'est correctement déployée en exécutant les commandes ci-dessous et en recherchant une sortie similaire:

$ kubectl obtenir les déploiements salutations-deployment
NOM DÉSIRÉ ACTUEL ACTUEL À JOUR DISPONIBLE ÂGE
salutations-déploiement 3 3 3 3 24d
$ kubectl obtenir des services salutations-service
NOM DU (DES) PORT (S) EXTERNE-IP IP DE CLUSTER-IP
salutations-service 100.65.66.9 a78b874f74ed0 ... 80: 32439 / TCP 6d

La vraie preuve, cependant, est la connexion à notre application à l'aide de notre nom de domaine complet! Si tout s'est correctement déployé, vous devriez voir quelque chose comme ceci:

Succès! Si vous actualisez maintenant cette page, vous devriez voir le nom d'hôte changer lorsque votre navigateur accède à l'application s'exécutant sur un autre nœud Kubernetes via l'équilibreur de charge classique.

Sommaire

À l'aide de ce didacticiel, nous avons construit un cluster Kubernetes avec un bon jeu de valeurs de sécurité par défaut, puis encapsulé un simple pipeline CI / CD. Nous avons ensuite spécifié via Infrastructure as Code comment nous souhaitions déployer une application conteneurisée simple et utilisé notre pipeline CI / CD et notre cluster Kubernetes pour le déployer tel que défini - automatiquement.

Il ne s'agit que d'une simple illustration des nombreux avantages que Kubernetes peut apporter à vos développeurs et à vos fonctionnalités DevOps lorsqu'ils sont inclus dans votre chaîne d'outils!