Bonnes pratiques
Applicatifs
Une application Cloud π Native doit respecter les Twelve-Factor
D'autres bonnes pratiques à réspecter impérantivement:
Base de code
Le code de l'application et de déploiement doit etre versionné dans un dépôt de source de type Git (Public/Privée) accessible depuis internet.
Dépendances
TOUTES dépendances necessaires à la constuction de l'application (Libraries,Images, ...) doivent provenir des dépôts de librairies connus tels que Maven, Composer et Node. Il est aussi possible de construire les dépendences par l'offre Cloud π Native et les déposer dans son gestionnaire d'artefact.
Configuration / Service Externe
TOUTES la configuration applicative pouvant être amenée a être modifié, par exemple la configuration entre deux environnements applicatifs est la plus part du temps différente. Elle doit donc être injectée par des variables d'environnement au runtime ou via un fichier de configuration dynamique via une ConfigMap
Port
Afin de respecter les préconisation de sécurité, les applications déployées doivent écouter sur des ports > 1024.
Logs
L'application NE DOIT PAS écrire dans un fichier de logs spécifique mais écrire l'ensemble de ces logs dans la sortie standards (stdout) au format GELF ou à defaut JSON.
Les logs seront accessibles plus facilement de cette manière depuis les outils de supervisions.
Processus
Les applications doivent être STATELESS, si des données de session/cache doivent être utilisé et partagé par l'application alors elles doivent faire l'objet d'un service externe prévus à cet effet telsque Redis.
Processus d’administration
Les opérations d'administrations doivent être faites via des initContainer (Init/Migration bdd, ...) ou des CronJob (Backup bdd, ...) FAQ
L'ensemble de ces bonnes pratiques sont détaillés dans la documentation OpenShift ici
Architectures
L'application déployée doit être conteneurisée (sous la forme d'un ou plusieurs conteneurs).
- Les Dockerfiles doivent être dans le dépôt pour permettre à la chaine de reconstruire l'application.
- Les images de bases des Dockerfiles doivent être accessibles publiquement ou reconstuire par l'offre Cloud π Native .
- Les images doivent être rootless, l'utilisateur qui lance le processus au sein du conteneur ne doit pas être
root
. - L'utilisateur lançant le processus dans le conteneur doit avoir les droits adéquats en lecture / écriture sur le système de fichiers si l'application doit manipuler ce dernier.
- Des sondes de "Readiness"/"Liveness" doivent être implémenté.
- Des limits/requests doivent etre mise en place.
Déploiement
L'application doit se déployer à l'aide de fichiers d'Infrastructure As Code:
- Utiliser des manifestes kubernetes avec Kustomize pour variabliser vos manifestes (cf. tutoriels)
- Utiliser des charts helm (cf. tutoriels pour avoir des exemples de fichiers).
- Utiliser Kustomize
Labels
Les ressources doivent comporter des labels permettant de les identifier. les labels pourraient etre decomposés de la facon suivante :
App : " "
Env : " "
Tier : " "
Criticality : " "
Component : " "
Tous les labels disponibles ici.
Tag d'images
Les images poussées dans le registry devront etre unique et identifiés via un Sha ou Short-Sha qui pourrait etre lié au commit Git. Grace a cela une gestion des releases et un rollback seront possibles.
Exemple de valeur pour le Tag de l'image :
CI_COMMIT_SHA
CI_COMMIT_SHORT_SHA
CI_COMMIT_TAG
CI_JOB_ID
Politiques de nommage
Les noms de toutes les ressources Openshift ne doivent jamais etre trop longs, il est donc conseillé de choisir des noms courts. il se pourrait que des ressources ne soient pas déployées si le nom est trop long. Coté exploitation, cela facilite grandement la gestion.
Exemple :
Service : env-ms-svc
Deployment : env-ms-dep
Statefulset : env-ms-sts
ConfigMap : env-ms-cm
Secret : env-secret
CronJob : env-name-cj
Route : env-route
PVC : env-name-pvc
Secrets
Les secrets comportent toutes les informations sensibles. Les différents types de secrets peuvent etre :
- Passwords
- Certificats
- Usernames
- Tokens
Toutes les secrets devront etre contenus dans un Vault qui sera mis a disposition pour l'ensemble des projets. Les objets contenus dans le Vault sont séparés par projets (NS).
Liveness et Readiness
Il est très important de mettre en place ces checks afin de vérifier l'etat de vos applications. Ceci est nécessaire pour assurer la haute disponibilité et la résilience de vos applications. Cela peut-etre une fonctionnalité de l'application, une page d'un site web, une entrée en base de donnée, etc.
livenessProbe:
httpGet:
path: /
port: 80
httpHeaders:
initialDelaySeconds: 3
periodSeconds: 3
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 3
periodSeconds: 3
SSL
Afin d'optimiser un flux sécurisé,il est préférable que cela soit de bout en bout.
Exemple du schéma de distribution de la requete.
Users --HTTPS-> ReverseProxy --HTTPS-> Ingress Kubernetes --HTTPS-> Container (Best Case)
Users --HTTPS-> ReverseProxy --HTTPS-> Ingress Kubernetes --HTTP-> Container (Usual Case)
HPA (Horizontal Pod Autoscaling)
Le scaling est très important afin de répondre aux besoins en termes d'affluence. il est aujourd'hui un atout majeur pour avoir une application qui soit le plus disponible possible avec des performances élevées. Pour cela il est donc possible de définir des triggers afin d'upscale l'applicatif (CPU, RAM, Métriques Applicatives).
QOS
Il est important de définir les consommations de chaque POD (prévisionnelles), Savoir si il serait intéressant que certains disposent d’une "request" égal a la "limit" afin d’assurer une réservation des ressources. (Guaranteed Class) L'utilisation du "Burstable" n'est pas pas une bonne pratique. il est vraiment necessaire d'avoir une "limit" même si celle-ci n'est pas équivalente a la "request".
Exemple :
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
Taille des images
Il est très important de construire des images les plus légères possibles, c'est a dire utiliser uniquement les paquets nécéssaires au bon fonctionnement de l'application ainsi que la meilleure image de base. C'est un gros vecteur de sécurité, de charge stockage et réseau.
Exemple d'image base Lightway : Alpine
Politiques réseau
Les "Network policies" sont par défaut en "Deny ALL". Il est donc à vous de déifnir les flux entrants et sortants sur les namespaces de vos projets.
ReverseProxy-->Networkpolicies-->Pods (Ingress)
Pods-->Networkpolicies-->Proxy (Egress)
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-external
spec:
podSelector:
matchLabels:
Tier: frontend
ingress:
- ports:
- port: 80