Le blog tech de Nicolas Steinmetz (Time Series, IoT, Web, Ops, Data)
fsync()
, l’astuce consiste ici à désactiver fsync()
et/ou à mettre le dossier des données de votre base en RAM pour accélérer les temps de déroiulement de tests. Testé chez un client, c’est un gain d’au moins 20s qui a été constaté sur une opération de quelques minutes (< 5).Rien de tel que la finalisation du bilan de cette seconde année d’activité pour faire un petit bilan sur l’année écoulée et les perspectives pour 2019.
Au global, tout va bien, tant d’un point de vue comptable que d’activité. L’année a été moins morcelée et compliquée que 2017.
D’un point de vue comptable, cela donne :
2018 | 2017 | Variation | |
---|---|---|---|
Chiffre d’affaires | ~130 K€ | ~100 K€ | +30% |
Résultat après impôts | ~10 K€ | ~20 K€ | -50% |
Jours facturés | ~190 | ~160 | +20% |
TJM | ~685€ | 625€ | +10% |
La baisse du résultat au regard de l’augmentation du chiffre s’explique surtout par une meilleure rémunération.
Comptablement, c’est donc une bonne année, les objectifs de soutenabilité de l’entreprise sont atteints.
J’en profite pour remercier Fabrice et son équipe pour son accompagnement. Je l’ai déjà dit, mais avoir confiance dans son expert comptable et pouvoir compter sur lui pour apporter de bons conseils aux bons moments et être serein sur la gestion de l’entreprise, c’est indispensable.
D’un point de vue activité, c’est aussi une bonne année :
D’un point de vue contribution à la communauté :
Dans le cadre du partage de connaissance, ce fut aussi l’occasion de tester un partage de connaissance chez LesFurets.com sous la forme d’un meetup hebdomadaire autour de Docker, Docker-Compose et Swarm auprès des équipes de développement et d’infrastructure en vue d’un passage de relais. L’occasion de prendre le temps de présenter les concepts et leurs applications sur une longue période.
D’un point de vue formation et veille, je me suis rendu aux conférences suivantes :
Coté formation, j’ai pu suivre la formation Kubernetes Fundamentals et la formation Déployer ses applications avec Kubernetes. Pour la certification Certified Kubernetes Administrator, j’ai jusqu’à Novembre 2019 pour la passer…
L’activité jusqu’à fin juin est assurée - n’hésitez pas à me contacter si vous avez des sujets à me proposer pour le second semestre.
Sur les conférences, j’ai décidé de me limiter en terme de nombre de conférences mais d’aller à des conférences où je n’étais pas allé comme KubeCon & CloudNativeCon à Barcelone et la SRECon à Dublin. Peut-être irais-je également à la prochaine DockerCon Euope ?
Voici quelques objectifs que je me suis fixé :
Si certains sujets vous interpellent ou si vous avez des contacts à me suggérer, n’hésitez pas à me contacter.
kubectl diff
montrera les différences entre la ressource existante et celle décrite dans la nouvelle version du fichier yaml.L’objectif est 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 de secrets et de ne plus avoir à provisionner un volume pour les stocker.
Installons déjà 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 issuer.yml
Notre contexte de déploiement utilisant Traefik comme ingress, je remets ci-dessous la configuration que j’utilise avec les ajustements nécessaires pour l’utilisation de cert-manager. Il n’est en effet plus possible et il devient désormais inutile de déclarer la section “acme” dans traefik.toml. J’ai aussi supprimé la redirect automatique http vers https, il faudra la gérer au niveau des ingress.
Créons le namespace traefik :
# Create namespace
kubectl create ns traefik
# Change context to this namespace so that all commands are by default run for this namespace
# see https://github.com/ahmetb/kubectx
kubens traefik
Commençons par traefik/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
)
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: traefik
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: traefik-ingress-controller
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
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: traefik
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: traefik
Ensuite, pour Traefik, j’ai besoin d’un fichier traefik.toml
avec la configuration que je mets à disposition sous la forme d’une ConfigMap
dans un fichier traefik/traefik-toml-configmap.yml
:
apiVersion: v1
kind: ConfigMap
metadata:
name: traefik-conf
data:
traefik.toml: |
defaultEntryPoints = ["http", "https"]
logLevel = "INFO"
insecureSkipVerify = true
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[entryPoints.api]
address = ":8080"
[api]
entryPoint = "api"
dashboard = true
debug = false
[kubernetes]
Le dashboard est à protéger par une authentification pour éviter tout accès non souhaité. Je l’ai supprimé de la configuration par simplicité.
Je peux donc enfin déployer Traefik via le fichier traefik/traefik-deployment.yml
:
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: traefik-ingress-controller
labels:
k8s-app: traefik-ingress-lb
spec:
replicas: 1
selector:
matchLabels:
k8s-app: traefik-ingress-lb
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
containers:
- image: traefik:1.7.16
name: traefik-ingress-lb
volumeMounts:
- mountPath: /config
name: traefik-config
ports:
- name: http
containerPort: 80
- name: admin
containerPort: 8080
- name: secure
containerPort: 443
args:
- --configfile=/config/traefik.toml
volumes:
- name: traefik-config
configMap:
name: traefik-conf
Nous déployons donc :
Pour permettre au cluster d’accéder aux différents ports, il faut définir un service via le fichier traefik-service-clusterip.yml
:
---
kind: Service
apiVersion: v1
metadata:
name: traefik-ingress-service-clusterip
spec:
selector:
k8s-app: traefik-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: traefik-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 traefik/traefik-api-ingress.yml
:
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: traefik
cert-manager.io/issuer: letsencrypt-prod
traefik.ingress.kubernetes.io/redirect-entry-point: https
traefik.ingress.kubernetes.io/redirect-permanent: "true"
ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/ssl-temporary-redirect: "false"
name: traefik-web-ui
spec:
rules:
- host: traefik.k8s.cerenit.fr
http:
paths:
- path: /
backend:
serviceName: traefik-ingress-service-clusterip
servicePort: admin
tls:
- hosts:
- traefik.k8s.cerenit.fr
secretName: traefik-cert
L’idée est donc de rentre le dashboard accessible via l’url traefik.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éé.
Les annotations permettent :
Les deux premières annotations permettent de ne pas avoir à déclarer soi même le certificat - il est automatiquement généré via ingress-shim. Cela vous fait donc un objet kubernetes en moins à gérer dans votre configuration. Si vous ne souhaitez pas vous appuyer sur ce méchanisme d’ingress-shim, il vous faudra ne pas utiliser ces annotations et gérer vous même un objet “Certificate”.
Il ne reste plus qu’à faire pour instancier le tout :
kubectl create -f traefik/
Pour la génération du certificat, il conviendra de vérifier la sortie de
kubectl describe certificate traefik-cert
Et voilà - maintenant que le problème des certificats est corrigé, je vais pouvoir passer dans un contexte de déploiement multi-nodes.
Pour faire suite au billet sur le déploiement de Traefik sous la forme d’un DaemonSet chez OVH, j’ai profité de la sortie en mode beta des Load Balancers pour revoir ma copie :
Par simplicité, je n’ai toujours qu’une node en plus du master fourni par OVH. Cela m’évite la problématique du stockage distribué des certificats. Cela fera l’objet d’un autre billet.
Créons le namespace traefik :
# Create namespace
kubectl create ns traefik
# Change context to this namespace so that all commands are by default run for this namespace
# see https://github.com/ahmetb/kubectx
kubens traefik
Commençons par traefik/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
)
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: traefik
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: traefik
Ensuite, pour Traefik, j’ai besoin d’un fichier traefik.toml
avec la configuration que je mets à disposition sous la forme d’une ConfigMap
dans un fichier traefik/traefik-toml-configmap.yml
:
apiVersion: v1
kind: ConfigMap
metadata:
name: traefik-conf
data:
traefik.toml: |
defaultEntryPoints = ["http", "https"]
logLevel = "INFO"
insecureSkipVerify = true
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[entryPoints.api]
address = ":8080"
[acme]
email = "contact@cerenit.fr"
storage = "/acme/acme.json"
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"
[api]
entryPoint = "api"
dashboard = true
debug = false
[kubernetes]
Le dashboard est à protéger par une authentification pour éviter tout accès non souhaité. Je l’ai supprimé de la configuration par simplicité.
Ensuite, pour stocker mes certificats, il me faut un volume que je défini via le fichier traefik/traefik-certificates-pvc.yml
:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: traefik-certificates
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 1Gi
storageClassName: cinder-classic
1 Go pour des certificats, c’est clairement trop mais il n’est pas possible pour le moment d’avoir un stockage plus réduit.
Je peux donc enfin déployer Traefik via le fichier traefik/traefik-deployment.yml
:
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: traefik-ingress-controller
labels:
k8s-app: traefik-ingress-lb
spec:
replicas: 1
selector:
matchLabels:
k8s-app: traefik-ingress-lb
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
containers:
- image: traefik:1.7.7
name: traefik-ingress-lb
volumeMounts:
- mountPath: /config
name: traefik-config
- mountPath: /acme
name: certificates
ports:
- name: http
containerPort: 80
- name: admin
containerPort: 8080
- name: secure
containerPort: 443
args:
- --configfile=/config/traefik.toml
volumes:
- name: traefik-config
configMap:
name: traefik-conf
- name: certificates
persistentVolumeClaim:
claimName: traefik-certificates
Nous déployons donc :
Pour permettre au cluster d’accéder aux différents ports, il faut définir un service via le fichier traefik-service-clusterip.yml
:
---
kind: Service
apiVersion: v1
metadata:
name: traefik-ingress-service-clusterip
spec:
selector:
k8s-app: traefik-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: traefik-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 traefik/traefik-api-ingress.yml
:
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-web-ui
spec:
rules:
- host: traefik.k8s.cerenit.fr
http:
paths:
- path: /
backend:
serviceName: traefik-ingress-service
servicePort: admin
Il ne nous reste plus qu’à faire :
# Create k8s ressources for traefik
kubectl create -f traefik/
# Watch service to get IPs
kubectl get svc -w
Une fois votre IP obtenue, il suffit de faire pointer votre entrée DNS vers cette IP ou de tester via :
curl -H "Host: traefik.k8s.cerenit.fr" https://xxx.xxx.xxx.xxx/
Pour l’obtention du certificat Let’s Encrypt, il faut que votre enregistrement DNS soit à jour préalablement. Sinon vous aurez un certificat autosigné par Traefik en attendant.
Dès lors, vous pouvez accéder au dashboard de Traefik via l’url définie. Pour donner accès à d’autres sites, il faut déclarer d’autres ingress sur le même modèle et le tour est joué.
Comparativement au dernier tutoriel :
Il reste encore le problème des stockage des certificats à résoudre pour passer à un contexte multi-nodes. Ce sera l’objet d’un prochain billet avec idéalement l’intégration de Traefik avec cert-manager (plutôt que de devoir déployer une base clé/valeur comme etcd ou consul pour y stocker les infos de traefik).
N’hésitez pas à me faire part de vos retours.