Cet article en deux parties décrit comment utiliser Istio, External-Dns et Cert-Manager dans un cluster Kubernetes pour déployer automatiquement une application accessible en HTTPS et que les entrées DNS et le certificat Let's Encrypt soient créés automatiquement lors de ce déploiement. Dans cette première partie, nous allons décrire le contexte et l'installation d'Istio ainsi que d'External-Dns.
Commençons par décrire le contexte et l’installation d’Istio et External-Dns.
Context
Le nom d’hôte utilisé dans ce document est application.sample.com cela suppose de possèder le nom de domaine sample.com.
Logiciels utilisés
Kubernetes v1.15
Kubernetes est un système open-source pour automatiser le déploiement, la mise à l’échelle et la gestion des applications conteneurisées.
Istio v1.5.0
Istio est un maillage de services (service mesh) qui assure la gestion du trafic, l’application des politiques de sécurité et la collecte de mesures.
External-DNS v0.7.0
External-Dns synchronise les services et les entrées Kubernetes exposés avec les fournisseurs de DNS.
Cert-Manager v0.13.1
Cert-Manager fournit des “certificats en tant que service” aux développeurs travaillant au sein du cluster Kubernetes. Il apporte notamment la prise en charge d’ACME (Let’s Encrypt), de HashiCorp Vault, de Venafi, des autorités de certification autosignée et interne. Il est extensible pour prendre en charge les Autorités de Certification personnalisées, internes ou non prises en charge.
Cluster
Le cluster Kubernetes est déployé sur AWS (EKS).
Le cluster possède 3 points d’entrée exposés via des Classic Load Balancer AWS:
Un point d’entrée privé accessible uniquement via le réseau privé de l’entreprise. La terminaison SSL est réalisée sur le Load Balancer sur lequel un certificat wildcard est déployé (*.sample.com), ce certificat est généré par AWS ACM.
Un point d’entrée public avec terminaison SSL réalisée sur le Load Balancer sur lequel un certificat wildcard est déployé (*.sample.com), le même qu’utilisé sur le point d’entrée privé.
Un point d’entrée public avec terminaison ssl réalisée sur l’Ingress Gateway Istio avec des certificats SSL générés par Let’s Encrypt.
Les namespaces Istio-system, cert-manager, external-dns et apps sont nécessaires. Le namespace apps doit avoir le label istio-injection=enabled pour que l’injection des sidecar Istio se fasse automatiquement.
Istio
Fichier de configuration
On commence par générer un fichier manifest.yaml qui va contenir la description de toutes les ressources Istio nécessaires:
Les lignes importantes ici sont:
--set "values.gateways.istio-ingressgateway.sds.enabled=true" qui va permettre d’injecter le certificat automatiquement sur les Istio Ingress Gateway en se basant sur le nom du secret contenant le certificat.
--set "values.global.k8sIngress.enabled=true" qui va permettre à Istio de détecter les objets Ingress de Kubernetes et d’ajouter un routage vers ceux-ci. Cette configuration est nécessaire car Cert-Manager, pour effectuer le challenge HTTP, va créer un pod pour répondre au challenge et va exposer ce pod via un ingress Kubernetes.
--set "values.global.k8sIngress.gatewayName=ingressgateway-ssl" qui permet de déterminer à partir de quelle Istio Ingress Gateway le trafic sera routé sur les Ingress Kubernetes détectés par Istio. Dans notre cas, on souhaite que cela soit par la gateway qui va gérer les certificats SSL de Let’s Encrypt. En effet, nous allons utiliser le challenge HTTP et c’est cette gateway qui sera appelée par Let’s Encrypt lors du challenge.
Les autres paramètres sont là pour déployer Kiali. Kiali est une console d’observabilité pour Istio avec des capacités de configuration de service mesh. Elle aide à comprendre la structure du service mesh en déduisant la topologie, et fournit également la santé de celui-ci. Kiali fournit des mesures détaillées, et une intégration Grafana de base est disponible pour les requêtes avancées. Le traçage distribué est fourni par l’intégration de Jaeger. C’est utile pour voir ce qui est déployé mais n’a pas d’utilité dans le déploiement de l’application.
Personnalisation du déploiement Istio
Avant de déployer Istio, nous allons enrichir le fichier de configuration avec les éléments correspondants à l’Istio Ingress Gateway qui va effectuer la terminaison SSL avec les certificats Let’s Encrypt.
Public SSL Istio Ingress Gateway
Une Ingress Gateway Istio est composée d’un Service Kubernetes et d’un ou plusieurs Pods correspondants à un proxy Envoy qui sera en charge de router les requêtes.
Le service est ici de type Load Balancer. Ainsi, lorsque le service est créé, cela provisionne automatiquement un Load Balancer sur AWS qui sera utilisé pour exposer ce service à l’extérieur du cluster Kubernetes.
Le routage des requêtes est réalisé au niveau du Pod (qui n’est rien d’autre qu’un proxy Envoy). Les règles sont décrites dans deux types d’objets Istio :
Les objets de type Gateway qui contiennent la configuration concernant les ports utilisés, les hostnames acceptés ainsi que la configuration TLS (SSL)
Les objets de type VirtualService qui contiennent les informations de routage en fonction d’URIs, de noms d’hôtes ou de headers particulier notamment.
Fichier de configuration
Copier le contenu suivant dans le fichier manifest.yaml.
Déploiement
Le déploiement s’effectue avec kubectl dans le namespace istio-system:
External-Dns
Fonctionnement
External-Dns est à l’écoute des déploiements d’objets Gateway. Attention, Il ne s’agit pas des Istio Ingress Gateway mais bien des custom resources Gateway qui sont déployées avec les applications (1).
Si un objet gateway porte l’annotation attendue par External-Dns et que le nom de domaine de l’hôte configuré dans l’objet Gateway est dans la liste de ceux gérés par External-Dns (2), alors External-Dns va chercher sur l’Istio Ingress Gateway concernée par l’objet Gateway le nom DNS du point d’entrée correspondant (ici un Load Balancer AWS) (3) et va créer un enregistrement dans Route 53 (4).
Configuration
Copier la configuration suivante dans un fichier nommé external-dns-deployment.yaml :
Les arguments du conteneur sont les suivants:
--source=istio-gateway indique que ce sont les hôtes configurés sur des Gateway Istio qui seront traités. Ici, ceux configurés sur des Ingress ou Services Kubernetes seront ignorés.
--annotation-filter=externaldns=ssl indique que seul les objets Gateway avec l’annotation externaldns: ssl seront traités.
--domain-filter=sample.com indique que seuls les noms d’hôtes appartenant au domaine sample.com seront pris en compte.
--provider=aws indique que nous utilisons Route 53
--policy=upsert-only indique que l’enregistrement ne sera pas supprimé si on supprime l’objet Gateway correspondant (valeurs possibles : sync ou upsert-only).
--aws-zone-type=public indique que nous n’utilisons que les zones Publique de Route 53 (les valeurs possibles sont: public, private ou vide pour les deux ).
--registry=txt et --txt-owner-id=ser-test indique que pour chaque enregistrement DNS créé, un enregistrement TXT sera créé pour le documenter. Il contiendra entre autre, la valeur owner-id=ser-test. C’est utile quand il y a plusieurs instances de Cert-Manager qui créent des enregistrements dans un même DNS.
--log-level=debug indique que je débute avec External-Dns :)
Déploiement
Le déploiement s’effectue avec kubectl dans le namespace default:
Nous terminons ici la première partie. La suite, disponible ici, traitera de Cert-Manager et du déploiement de l’application.