Le blog tech de Nicolas Steinmetz (Time Series, IoT, Web, Ops, Data)
SELECT DISTINCT
entre 28x et 8000x. Cela est valable tant pour les données Timescale que les données natives Postgres. Une contribution upstream est prévue.Le mois prochain, dans le cadre d’InfluxDays London, j’aurai le plaisir de présenter un talk sur le passage d’un monitoring Bare Metal vers un monitoring dans un monde Kubernetes avec Telegraf et InfluxDB.
depends_on
, count
et for_each
. Cela devrait éviter des dépendances parfois cryptiques.Meilleurs voeux à tous pour cette nouvelle année !
docker-compose.yml
et ensuite il montre les apports de Docker App, qui permet d’avoir un niveau de personnalisation supplémentaire. Ainsi, on peut avoir un seul fichier docker-compose.yml de référence et auquel on rajoute un fichier avec des propriétés par environnement ou par client ou par instance par ex. Une combinaison intéressante pour améliorer l’industrialisation de vos containers.Avec la sortie de Traefik 2, il était temps de mettre à jour le billet Kubernetes @ OVH - Traefik et Cert Manager pour le stockage des certificats en secrets pour tenir compte des modifications.
L’objectif est toujours de s’appuyer sur Cert-Manager pour la génération et le stockage des certificats Let’s Encrypt qui seront utilisés par Traefik. L’idée est de stocker ces certificats sous la forme d’un objet Certificate
et de ne plus avoir à provisionner un volume pour les stocker. On peut dès lors avoir plusieurs instances de Traefik et non plus une seule à laquelle le volume serait attaché.
Installation de cert-manager :
# Install the CustomResourceDefinition resources separately
kubectl apply --validate=false -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.11/deploy/manifests/00-crds.yaml
# Create the namespace for cert-manager
kubectl create namespace cert-manager
# Add the Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io
# Update your local Helm chart repository cache
helm repo update
# Install the cert-manager Helm chart
helm install \
--name cert-manager \
--namespace cert-manager \
--version v0.11.0 \
jetstack/cert-manager
Nous allons ensuite devoir créer un Issuer dans chaque namespace pour avoir un générateur de certificats propre à chaque namespace. Cela est notamment du au fait que Traefik s’attend à ce que le secret et l’ingress utilisant ce secret soient dans le même namespace. Nous spécifions également que nous utiliserons traefik comme ingress pour la génération des certificats.
cert-manager/issuer.yml
:
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: letsencrypt-prod
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: user@example.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable HTTP01 validations
solvers:
- selector: {}
http01:
ingress:
class: traefik
Puis créons le “issuer” dans la/les namespace(s) voulu(s) :
# Create issuer in a given namespace
kubectl create -n <namespace> -f cert-manager/issuer.yml
Installons ensuite traefik V2
Créons le namespace traefik2 :
# Create namespace
kubectl create ns traefik2
# Change context to this namespace so that all commands are by default run for this namespace
# see https://github.com/ahmetb/kubectx
kubens traefik2
En premier lieu, Traefik V2 permet d’avoir un provider Kubernetes qui se base sur des Custom Ressources Definition
(aka CRD
).
Créeons le fichier traefik2/crd.yml
:
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutes.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRoute
plural: ingressroutes
singular: ingressroute
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: middlewares.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: Middleware
plural: middlewares
singular: middleware
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutetcps.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteTCP
plural: ingressroutetcps
singular: ingressroutetcp
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressrouteudps.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteUDP
plural: ingressrouteudps
singular: ingressrouteudp
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsoptions.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSOption
plural: tlsoptions
singular: tlsoption
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsstores.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSStore
plural: tlsstores
singular: tlsstore
scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: traefikservices.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TraefikService
plural: traefikservices
singular: traefikservice
scope: Namespaced
Vous pouvez retrouver les sources de ces CRD.
Continuons avec traefik2/rbac.yml
- le fichier défini le compte de service (Service Account
), le rôle au niveau du cluster (Cluster Role
) et la liaison entre le rôle et le compte de service (Cluster Role Binding
). Si vous venez d’une installation avec Traefik 1, ce n’est pas tout à fait la même définition des permissions.
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik2-ingress-controller
namespace: traefik2
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: traefik2-ingress-controller
namespace: traefik2
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- traefik.containo.us
resources:
- middlewares
- ingressroutes
- traefikservices
- ingressroutetcps
- ingressrouteudps
- tlsoptions
- tlsstores
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: traefik2-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik2-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik2-ingress-controller
namespace: traefik2
Nous pouvons alors songer à déployer Traefik V2 sous la forme d’un Deployment
. Mais avant de produire le fichier, ce qu’il faut savoir ici :
Ingress
. Dès lors, il faut activer les deux providers kubernetes disponibles avec Traefik V2 : KubernetesCRD
et KubernetesIngress
. Le premier provider permettra de profiter des nouveaux objets fournis par la CRD et le second permet que Traefik gère les Ingress traditionnelles de Kubernetes et notamment celles de cert-manager.KubernetesIngress
ne supporte pas les annotationsKubernetesIngress
, on se simplifie aussi la migration d’un socle Traefik V1 vers V2, au support des annotations près.traefik2/deployment.yml
:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik2-ingress-controller
labels:
k8s-app: traefik2-ingress-lb
spec:
replicas: 2
selector:
matchLabels:
k8s-app: traefik2-ingress-lb
template:
metadata:
labels:
k8s-app: traefik2-ingress-lb
name: traefik2-ingress-lb
spec:
serviceAccountName: traefik2-ingress-controller
terminationGracePeriodSeconds: 60
containers:
- image: traefik:2.1.1
name: traefik2-ingress-lb
ports:
- name: web
containerPort: 80
- name: admin
containerPort: 8080
- name: secure
containerPort: 443
readinessProbe:
httpGet:
path: /ping
port: admin
failureThreshold: 1
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 2
livenessProbe:
httpGet:
path: /ping
port: admin
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 2
args:
- --entryPoints.web.address=:80
- --entryPoints.secure.address=:443
- --entryPoints.traefik.address=:8080
- --api.dashboard=true
- --api.insecure=true
- --ping=true
- --providers.kubernetescrd
- --providers.kubernetesingress
- --log.level=DEBUG
Pour permettre au cluster d’accéder aux différents ports, il faut définir un service via le fichier traefik2/service.yml
:
---
kind: Service
apiVersion: v1
metadata:
name: traefik2-ingress-service-clusterip
spec:
selector:
k8s-app: traefik2-ingress-lb
ports:
- protocol: TCP
port: 80
name: web
- protocol: TCP
port: 8080
name: admin
- protocol: TCP
port: 443
name: secure
type: ClusterIP
Et pour avoir un accès de l’extérieur, il faut instancier un load-balancer via le fichier traefik/traefik-service-loadbalancer.yml
---
kind: Service
apiVersion: v1
metadata:
name: traefik-ingress-service-lb
spec:
selector:
k8s-app: traefik2-ingress-lb
ports:
- protocol: TCP
port: 80
name: web
- protocol: TCP
port: 443
name: secure
type: LoadBalancer
Pour donner l’accès au dashboard via une url sécurisée par un certificat Let’s Encrypt, il faut déclarer un Ingress, dans le fichier traefik2/api-ingress.yml
:
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik2-web-ui
spec:
entryPoints:
- secure
routes:
- match: Host(`traefik2.k8s.cerenit.fr`)
kind: Rule
services:
- name: traefik2-ingress-service-clusterip
port: 8080
tls:
secretName: traefik2-cert
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik2-web-ui-http
spec:
entryPoints:
- web
routes:
- match: Host(`traefik2.k8s.cerenit.fr`)
kind: Rule
services:
- name: traefik2-ingress-service-clusterip
port: 8080
L’idée est donc de rentre le dashboard accessible via l’url traefik2.k8s.cerenit.fr.
La section tls
de l’ingress indique le nom d’hôte pour lequel le certificat va être disponible et le nom du secret contenant le certificat du site que nous n’avons pas encore créé.
Il nous faut donc créer ce certificat :
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: traefik2-cert
namespace: traefik2
spec:
secretName: traefik2-cert
issuerRef:
name: letsencrypt-prod
commonName: traefik2.k8s.cerenit.fr
dnsNames:
- traefik2.k8s.cerenit.fr
Il ne reste plus qu’à faire pour instancier le tout :
kubectl apply -f traefik2/
Pour la génération du certificat, il conviendra de vérifier la sortie de
kubectl describe certificate traefik2-cert
A ce stade, il nous manque :
C’est là que les Middlewares rentrent en jeu.
Pour la redirection https: traefik2/middleware-redirect-https.yml
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: https-only
spec:
redirectScheme:
scheme: https
Pour l’authentification : traefik2/middleware-auth.yml
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: auth-traefik-webui
spec:
basicAuth:
secret: traefik-auth
Il faut alors créer un secret kubernetes qui contient une variable users
contenant la/les ligne(s) d’authentification :
apiVersion: v1
kind: Secret
metadata:
name: traefik-auth
namespace: traefik2
data:
users: |2
dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK
Cela correspond à 2 comptes test/test
et test2/test2
, encodés en base64 et avec un mot de passe chiffré via htpasswd.
test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/
test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0
On peut alors mettre à jour notre fichier traefik2/api-ingress.yml
et rajouter les deux middlewares que nous venons de définir :
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik2-web-ui
spec:
entryPoints:
- secure
routes:
- match: Host(`traefik2.k8s.cerenit.fr`)
middlewares:
- name: auth-traefik-webui
kind: Rule
services:
- name: traefik2-ingress-service-clusterip
port: 8080
tls:
secretName: traefik2-cert
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik2-web-ui-http
spec:
entryPoints:
- web
routes:
- match: Host(`traefik2.k8s.cerenit.fr`)
middlewares:
- name: https-only
kind: Rule
services:
- name: traefik2-ingress-service-clusterip
port: 8080
Et pour le prendre en compte:
kubectl apply -f traefik2/
Vous devez alors avoir une redirection automatique vers le endpoint en https et une mire d’authentification.
Pour ceux qui font une migration dans le même cluster de Traefik V1 vers Traefik V2 :
ingressClass
de Traefik et créer un issuer cert-manager qui utilise cette même ingressClass
.Certificate
Sources utiles:
Ce mercredi, j’ai le plaisir d’organiser la première édition du Paris Time Series Meetup - il reste des places, vous pouvez encore vous inscrire et nous rejoindre !
Ce meetup est organisé conjointement avec InfluxData suite à ma nomination en tant qu’InfluxAce lors d’InfluxDays London 2019. J’ai alors cherché à organiser le meetup en mettant en avant la communauté et les acteurs français autour de la série temporelle, de ne pas me limiter à des présentations produits mais de les enrichir avec des retours clients et aussi à proposer des usages plus avancés que de stocker ses données et de faire deux à trois graphiques avec ces métriques. Je pense que cette première édition respecte ces critères.
Au programme donc :
Time Series with Warp10 - Technology and Advanced Use Cases (because time series are way more than monitoring) par Mathias Herberts (CTO et Fondateur de SenX, la société éditrice de la plateforme opensource Warp10). Le talk sera en français et Mathias nous présentera Warp10 et différents cas d’usages autour de la platforme.
Pilotage du monitoring de datacenter grâce au Machine Learning par Christophe Rannou (OVH Machine Learning Services Team Leader) et Clément Bataille (OVH Machine Learning Services, Data Scientist) : Comment OVH utilise le Machine Learning appliqué au monitoring dans le but d’extraire des tendances et de détecter les anomalies afin de se prémunir d’incidents et de passer d’un entretien réactif a un entretien proactif. On y parlera notamment de leur offre Prescience mais pas uniquement !
Le meetup se fera dans les locaux de ManoMano qui nous font le plaisir de nous héberger.
Retrouvez toutes les informations sur la page de l’événement sur Meetup.