K8s - Didacticiels

Débuter

Se connecter à l'UI Rancher

cegedim.cloud utilise Rancher comme plateforme de gestion de Kubernetes.

Rancher supporte la même authentification SSO que ITCare.

Instances Rancher

Selon la localisation de votre cluster, Rancher est accessible avec les URL suivantes :

Region

EB (Boulogne-Billancourt)

ET (Toulouse-Labège)

Dans ITCare, vous pouvez trouver l'URL de votre cluster dans la page de détail de celui-ci :

Se connecter à Rancher

Rancher demandera une authentification lors de la première connexion : cliquez simplement sur "Login with Keycloak".

Vous serez ensuite redirigé vers la mire de connexion :

Une fois connecté, vous devriez avoir un écran listant tous les clusters auxquels vous avez accès :

Si l'interface se coince après l'authentification, merci d'essayer ces liens :

Si lors de la première connexion vous ne voyez pas votre cluster dans la liste des clusters, vous pouvez vous déconnecter et vous reconnecter.

Gérer vos préférences

Vous pouvez gérer vos préférences d'interface utilisateur (thème sombre, nombre de lignes par tableau...) en configurant vos préférences utilisateur. Veuillez vous référer ici à la documentation complète ci-dessous.

Configurer kubectl

Afin de se connecter au cluster en utilisant la CLI, vous avez deux options :

  • par kubectl normal à distance

  • en utilisant rancher online kubectl.

Les deux sont disponibles en accédant à la page "cluster" dans Rancher.

Il y a deux façons de le faire :

  • Cliquez sur le nom du cluster dans la liste des clusters.

  • Cliquez sur le nom du cluster dans le menu supérieur gauche.

En utilisant le fichier de configuration kubectl

Une fois sur la page d'accueil du cluster, vous pouvez télécharger le "KubeConfig File" :

Ou bien juste copier le contenu du "Kubeconfig File" :

Si vous ne disposez pas dekubectl,nous vous conseillons vivement d'installer kubectlsur votre poste d'administration en suivant le lien ci-dessous.

https://kubernetes.io/docs/tasks/tools/install-kubectl/

Cette configuration peut être mélangée avec d'autres configurations kubectl.

L'authentification peut être partagée avec tout cluster géré par la même instance de rancher.

Utilisation du cli web

Une fois sur la page d'accueil du cluster, vous pouvez utiliser le web CLI en cliquant sur l'icône ci-dessous:

Cela devrait lancer un shell web comme celui-ci :

Ce shell est temporaire, tout changement effectué à l'intérieur sera supprimé une fois la fenêtre fermée.

Cette session peut être déconnectée si aucune entrée/sortie n'est observée.

Obtenir un jeton API

La gestion des jetons est disponible juste en dessous de l'avatar de l'utilisateur :

Portée des jetons

Il existe deux champs d'application :

  • no-scope : global scope : utilisé pour interagir avec l'API globale de Rancher

  • cluster-scoped : jeton dédié à l'accès à un cluster spécifique

Un jeton à portée de cluster est nécessaire pour utiliser helm 3. Cela signifie que vous avez besoin d'un jeton par cluster dans vos pipelines CI/CD

Cycle de vie des jetons

Les jetons peuvent avoir des cycles de vie différents :

  • Une durée de vie illimitée, il suivra le cycle de vie du compte qui lui est rattaché

  • Une durée limitée

Gestion des nœuds

Redimensionner un cluster

Vous pouvez utiliser ITCare pour ajouter ou supprimer des nœuds à votre cluster.

Gérer les Namespaces

Comprendre les projets - Un concept de Rancher

Rancher gère les espaces de noms via project, qui est un concept n'existant spécifiquement que dans les clusters Kubernetes gérés par Rancher.

Le projet n'est pas une ressource native de Kubernetes. Par défaut, un cluster Kubernetes est provisionné avec 2 projets :

  • System : contenant les espaces de noms des composants principaux comme : kube-system, etc.

  • Default : contenant l'espace de noms "par défaut".

Les utilisateurs sont libres de créer d'autres projets si nécessaire. En se basant sur le niveau du projet, Rancher offre une automatisation intégrée comme : l'octroi de droits d'accès, l'isolation du réseau, etc.

Les utilisateurs sont fortement encouragés à classer les espaces de noms dans un projet.

Comment créer correctement un espace de noms

  • Passer à la vue projet

  • Créer un nouvel espace de noms à partir de la vue du projet

  • Insérez un nom unique et remplissez les autres champs si nécessaire, puis cliquez sur "Créer"

Si vous créez un espace de noms avec le CLI de kubernetes, par exemple kubectl, l'espace de noms créé sera déplacé dans le projet parent de l'espace de noms "default" (qui est, par défaut, le projet nommé Default).

Gestion des droits

cegedim.cloud recommande et supporte officiellement la gestion des droits d'accès via les groupes AD.

Seuls les groupes AD commençant par G_EMEA_* et G_K8_* sont connus par Rancher.

Par défaut, lors de la création d'un cluster :

  • Le rôle d'utilisateur standard est donné au groupe G_K8_<NOM_DU_CLUSTER>_USERS qui contient les power users du Cloud associé.

  • Le rôle d'administrateur est attribué au groupe G_K8_<NOM_DU_CLUSTER>_ADMINS qui est vide par défaut et peut être complété par des utilisateurs compétents et certifiés via un ticket ITCare vers l'équipe de support AD.

Par exemple, l’utilisateur user1@cegedim.com a besoin d’accès standard au cluster test-preprod, il doit faire une demande pour l'ajouter dans le groupe AD nommé G_K8_TEST_PREPROD_USERS.

Lorsque les utilisateurs créent un nouveau projet, en tant que propriétaire par défaut, ils sont libres de lier n'importe quel rôle à n'importe quel groupe AD dans le cadre de ce projet.

Si les rôles prédéfinis de Rancher ne peuvent pas répondre à vos besoins, veuillez contacter les administrateurs de votre cluster pour configurer un rolebinding personnalisé ou un clusterrolebinding.

Gérer les droits

Gestion des droits au niveau du projet

Dans cette partie, nous supposerons que les droits sont donnés à un groupe et non à un utilisateur.

Pour gérer les droits sur un projet, il existe deux moyens : L'interface utilisateur ou l'API.

L'un des rôles les plus élevés que vous pouvez attribuer est "Project Admin".

Utilisation de l'interface utilisateur

Éditez le projet dont vous êtes propriétaire ou sur lequel vous avez suffisamment de droits accordé par le propriétaire.

Sélectionnez le groupe et le rôle dans la formulaire.

A noter que seuls les groupes préfixés par G_EMEA_* and G_K8_* sont reconnus par Rancher.

Utilisation de l'API

En utilisant l'API, c'est assez simple. Vous aurez d'abord besoin de quelques paramètres :

  • Obtenir l'ID du projet

Pour obtenir l'ID du projet, vous pouvez utiliser l'explorateur d'API en utilisant simplement le bouton "View in API".

curl --request GET \
 --url https://k8s-eb.cegedim.cloud/v3/projects \
 --header 'authorization: Bearer token-tttt:token-of-doom'
  • Obtenir l'ID du rôle

Pour obtenir l'ID du rôle, il se peut que vous ne soyez pas autorisé à l'afficher via l'interface utilisateur, mais vous l'obtiendrez via cette requête API :

curl --request GET \
--url https://rancher-staging.cegedim.cloud/v3/roleTemplates?name=Project%20Admin\
--header 'authorization: Bearer token-tttt:token-of-doom'
  • Donner des autorisations

En utilisant votre clé API, vous pouvez faire une demande POST pour créer le lien de rôle :

curl --request POST \
--url https://k8s-eb.cegedim.cloud/v3/projectRoleTemplateBindings \
--header 'authorization: Bearer token-tttt:token-of-doom' \
--header 'content-type: application/json' \
--data '{
"projectId": "c-6t7f4:p-d43l6",
"namespaceId":"",
"groupPrincipalId":"keycloakoidc_group_group://G_EMEA_DUPER_GROUP",
"roleTemplateId": "project-owner"
}'

Vérification de compatibilité avant une mise à jour de version Kubernetes

Contexte

Les version api de ressources Kubernetes peuvent être obsolètes, voire supprimés lors de la mise à jour de version Kubernetes.

Il y a une risque de cassure si vous avez des ressources avec une version api supprimé dans la nouvelle version de Kubernetes.

Pour éviter cela, une des solutions est d'utiliser l'outil "kubent" pour vérifier la compatibilité .

Kubent détecte les objets obsolètes du cluster Kubernetes. Vous devez migrer/modifier les ressources identifiés avant la mise à jour de version Kubernetes.

Démarrage rapide

Pour installer kubent :

sh -c "$(curl -sSL 'https://git.io/install-kubent')"

Pour identifier les objets obsolètes qui vont être supprimés dans la prochain version Kubernetes :

kubent [--context my-cluster]

Un exemple de l'output :

...
__________________________________________________________________________________________
>>> Deprecated APIs removed in 1.22 <<<
------------------------------------------------------------------------------------------
KIND                       NAMESPACE      NAME                                   API_VERSION                         REPLACE_WITH (SINCE)
Ingress                    <undefined>     toto                                 networking.k8s.io/v1beta1           networking.k8s.io/v1 (1.19.0)
...

Dans ce tutoriel, si votre cluster est planifié pour une mise à jour vers version Kubernetes 1.22, vous devez migrer votre resource ingress nommé "toto" de version api networking.k8s.io/v1beta1 vers networking.k8s.io/v1 avant la mise à jour.

Cette migration peut impliquer une modification des champs supplémentaires de la ressource. Veillez consulter la documentation officielle :

Kubent pourrait échouer de reporter certaine information, e.g. espace de nom de l'ingress, vous pouvez remonter l'issue à l'éditeur : https://github.com/doitintl/kube-no-trouble/issues

Configurer le transfert et la centralisation des logs vers un cluster OpenSearch

Contexte

Dans cet exemple, nous allons configurer le transfert de logs d'un cluster Kubernetes vers un cluster OpenSearch.

  • Le cluster OpenSearch est dans cet exemple my-cluster.es.cegedim.cloud

  • Le nom de la sortie du cluster est my-cluster-output.

Configuration du logging Banzai

Dans Rancher, sous Logging > ClusterOutput et Logging > Output, modifiez la configuration YAML et changez ceci :

    port: 443
    log_es_400_reason: true # useful to debug when no log is received in Opne Search / ELK
    suppress_type_name: true
    # Add this if the target is an Open Search cluster
    default_elasticsearch_version: "7"
    verify_es_version_at_startup: false

ClusterFlow/ClusterOutput présentent de nombreux problèmes lors de l'envoi de logs à OpenSearch / ELK cluster : Conflit de type de valeur attendue avec la même clé (par exemple, une valeur changée de "long" à "string" sera rejetée par OpenSearch / ELK Cluster).

Cela peut se produire isi vous avez activé Dynatrace.

Voici des exemples complets de la spécification ClusterOutput/Output pour ElasticSearch et OpenSearch :

Exemple pour OpenSearch
spec:
  elasticsearch:
    buffer:
      chunk_limit_size: 256m
      compress: gzip
      flush_at_shutdown: true
      flush_interval: 60s
      flush_mode: interval
      flush_thread_count: 2
      queue_limit_length: 96
      retry_forever: true
      type: file
    flatten_hashes: true
    host: {{ ELK URL }}
    include_tag_key: true
    log_es_400_reason: true
    logstash_format: true
    logstash_prefix: {{ prefix }}
    password:
      valueFrom:
        secretKeyRef:
          key: password
          name: {{ ELK credentials }}
    port: 443
    reconnect_on_error: true
    reload_connections: false
    reload_on_failure: true
    request_timeout: 30s
    scheme: https
    ssl_verify: false
    suppress_type_name: true
    user: {{ username }}
    default_elasticsearch_version: "7"
    verify_es_version_at_startup: false
Exemple pour ELK
spec:
  elasticsearch:
    buffer:
      chunk_limit_size: 256m
      compress: gzip
      flush_at_shutdown: true
      flush_interval: 60s
      flush_mode: interval
      flush_thread_count: 2
      queue_limit_length: 96
      retry_forever: true
      type: file
    flatten_hashes: true
    host: {{ ELK URL }}
    include_tag_key: true
    log_es_400_reason: true
    logstash_format: true
    logstash_prefix: {{ prefix }}
    password:
      valueFrom:
        secretKeyRef:
          key: password
          name: {{ ELK credentials }}
    port: 443
    reconnect_on_error: true
    reload_connections: false
    reload_on_failure: true
    request_timeout: 30s
    scheme: https
    ssl_verify: false
    suppress_type_name: true
    user: {{ username }}

Recommandations en matière de migration

Il y a deux options :

  • Migration vers Flow/ClusterOutput : poussera tous les logs des espaces de noms vers le même index OpenSearch.

  • Migration vers Flow/Output : poussera les logs des espaces de noms séparés vers des index OpenSearch dédiés.

La recommandation est de migrer vers "Flow/Output", et même d'avoir un index OpenSearch dédié pour les applications très importantes.

Migration de ClusterFlow/ClusterOutput vers Flow/ClusterOutput

Créer un fichier avec tous les espaces de noms :

Define namespaces
mkdir -p log-config
kubectl get ns --no-headers |grep -v kube-system|\
grep -v cattle|\
grep -v dynatrace|\
grep -v ceg-it|\
grep -v ingress-nginx|awk '{print $1}' > namespaces.txt
# review namespaces.txtD

Créer des fichiers K8s YAML pour configurer les logs sur tous les espaces de noms :

Create flow resources
while read LOG_NS
do
  cat <<EOF>> log-config/"configuration-"$LOG_NS".yaml"
apiVersion: logging.banzaicloud.io/v1beta1
kind: Flow
metadata:
  name: all-namespace-logs
  namespace: $LOG_NS
spec:
  filters:
  - dedot:
      de_dot_nested: true
      de_dot_separator: '-'
  globalOutputRefs:
  - my-cluster-output
EOF
done < namespaces.txt
# review content of folder log-config

Appliquer la configuration :

kubectl apply -f log-config

Migration de ClusterFlow/ClusterOutput vers Flow/Output

Créer un fichier avec tous les espaces de noms :

mkdir -p log-config
kubectl get ns --no-headers |grep -v kube-system|\
grep -v cattle|\
grep -v dynatrace|\
grep -v ceg-it|\
grep -v ingress-nginx|awk '{print $1}' > namespaces.txt
# review namespace.txt

Créer des fichiers K8S YAML :

while read LOG_NS
do
  kubectl -n cattle-logging-system get secret {{ ELK credentials }} -o json \
 | jq 'del(.metadata["namespace","creationTimestamp","resourceVersion","selfLink","uid"])' \
 | kubectl apply -n $LOG_NS -f -
  cat <<EOF>> log-config/"configuration-"$LOG_NS".yaml"
apiVersion: logging.banzaicloud.io/v1beta1
kind: Output
metadata:
  name: all-ns
  namespace: $LOG_NS
spec:
  elasticsearch:
    buffer:
      chunk_limit_size: 256m
      compress: gzip
      flush_at_shutdown: true
      flush_interval: 60s
      flush_mode: interval
      flush_thread_count: 2
      queue_limit_length: 96
      retry_forever: true
      type: file
    flatten_hashes: true
    host: my-cluster.es.cegedim.cloud
    include_tag_key: true
    log_es_400_reason: true
    logstash_format: true
    logstash_prefix: {{ prefix }}
    password:
      valueFrom:
        secretKeyRef:
          key: password
          name: {{ ELK credentials }}
    port: 443
    reconnect_on_error: true
    reload_connections: false
    reload_on_failure: true
    request_timeout: 30s
    scheme: https
    ssl_verify: false
    suppress_type_name: true
    user: {{ username }}
---
apiVersion: logging.banzaicloud.io/v1beta1
kind: Flow
metadata:
  name: all-namespace-logs
  namespace: $LOG_NS
spec:
  filters:
  - dedot:
      de_dot_nested: true
      de_dot_separator: '-'
  globalOutputRefs: []
  localOutputRefs:
  - all-ns
EOF
done < namespaces.txt
# review content of folder log-config

Appliquer la configuration :

kubectl apply -f log-config

Déboguer si la perte de logs persiste

Aucun tampon important ne devrait se produire si tout se passe bien. Vérifions le

kubectl -n cattle-logging-system get po -l app.kubernetes.io/name=fluentd -o name|awk '{print $1}'|xargs -I {} sh -c "kubectl -n cattle-logging-system exec {} -c fluentd -- du -hs /buffers"

Vérifions les 5 dernières lignes du journal de Fluentd :

kubectl -n cattle-logging-system get po -l app.kubernetes.io/name=fluentd -o name|awk '{print $1}'|xargs -I {} sh -c "kubectl -n cattle-logging-system exec {} -c fluentd -- tail -5  /fluentd/log/out"

Jetez un coup d'œil dans /fluentd/log/out à l'intérieur du pod fluentd, mais la plupart du temps, ce qui suit vous aidera :

kubectl -n cattle-logging-system get po -l app.kubernetes.io/component=fluentd --no-headers|awk '{print $1}'|xargs -I {} sh -c "kubectl -n cattle-logging-system exec -it  {} -c fluentd -- cat /fluentd/log/out|grep 'Rejected'"
2023-01-20 10:53:38 +0000 [warn]: #0 send an error event to @ERROR: error_class=Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchError error="400 - Rejected by Elasticsearch [error type]: mapper_parsing_exception [reason]: 'failed to parse field [stack_trace] of type [text] in document with id 'L7fQzoUBIs35W4-JCcJQ'. Preview of field's value: '{source=    at reconcileChildFibers (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:14348:23)}''" location=nil tag="kubernetes.var.log.containers.log-service-deployment-57747558f8-52jgx_my-application_log-service-6c560e016f7241b3231b96ed358390d8a2170b175833a695705c952183dcda5e.log" time=2023-01-20 10:52:33.431659917 +0000

Il est facile d'identifier le pod à l'origine du problème :

kubectl get po -A |grep log-service-deployment-57747558f8
                  my-application                         log-service-deployment-57747558f8-52jgx                          1/1     Running                 0          4d20h

Il faut comprendre que l'erreur n'est pas dans Kubernetes, c'est le conteneur qui produit des logs incohérents au format json. Ensuite, OpenSearch rejette les journaux envoyés. Banzai réessayera et tôt ou tard, le débordement arrivera.

Sources :

Une solution à court terme peut être choisie ci-dessous :

  • Retirer le pod du flux (exclusion du pod) ou désactiver l'ensemble du flux de l'espace de noms concerné.

  • Nettoyer l'index lié dans le serveur ES

Solution à long terme :

  • Adapter l'application pour produire un journal plus cohérent

  • Voir s'il est possible de configurer ES pour qu'il ignore gentiment, mais ne rejette pas, le paquet entier envoyé par Banzai.

Dernière mise à jour