Trucs et astuces Kubernetes: déplacement des ressources de cluster vers Helm 2



Le besoin de récupérer les ressources du cluster Kubernetes peut survenir dans des conditions de combat lorsque vous ne pouvez pas simplement les recréer avec des outils Helm. On peut distinguer deux raisons principales:

  • Ce sera simple, que vous ayez un nuage ou du métal nu.
  • Lors de la suppression, les services dans les nuages ​​peuvent être perdus, ainsi que les équilibreurs de charge associés dans Kubernetes.

Dans notre cas, une solution était nécessaire pour capturer les entrées-nginx actives tout en intégrant notre opérateur Kubernetes.

Il est strictement inacceptable pour Helm que les ressources qu'il gère ne soient pas créées par lui.

"Si les ressources de publication de votre équipe peuvent être modifiées manuellement, préparez-vous à rencontrer les problèmes décrits dans la section: [BOGUE] Après le déploiement, l'état des ressources de publication dans le cluster ne correspond pas au graphique de barre décrit ." (de notre dernier article )

Comme indiqué précédemment, Helm fonctionne comme suit:

  1. À chaque installation (installation de helm install , helm upgrade ), Helm stocke le manifeste de version généré dans le backend de stockage . Par défaut, ConfigMaps est utilisé: pour chaque révision d'une version, ConfigMap est créé dans le même espace de noms dans lequel Tiller est exécuté.
  2. Lors de déploiements répétés ( helm upgrade Helm), Helm compare le nouveau manifeste généré avec l'ancien manifeste de la dernière révision de version DEPLOYED de ConfigMap et applique la différence résultante dans Kubernetes.

Sur la base de ces fonctionnalités, nous sommes arrivés à la conclusion qu'il suffit de patcher ConfigMap (version de backend de stockage) pour récupérer , c'est-à-dire adopter les ressources existantes dans le cluster.

Tiller fait référence à ConfigMap au format suivant: %RELEASE_NAME.v%REVISION . Pour obtenir les entrées existantes, vous devez exécuter la commande kubectl get cm -l OWNER=TILLER --namespace kube-system (par défaut, Tiller est installé dans le namespace kube-system - sinon vous devez spécifier celui utilisé).

 $ kubectl get cm -l OWNER=TILLER -n kube-system NAME DATA AGE release_name_1.v618 1 5d release_name_1.v619 1 1d release_name_2.v1 1 2d release_name_2.v2 1 3d 

Chaque ConfigMap est présenté dans ce format:

 apiVersion: v1 data: release: H4sIAHEEd1wCA5WQwWrDMAyG734Kwc52mtvwtafdAh27FsURjaljG1kp5O3nNGGjhcJ21M/nT7+stVZvcEozO7LAFAgLnSNOdG4boSkHFCpNIb55R2bBKSjM/ou4+BQt3Fp19XGwcNoINZHggIJWAayaH6leJ/24oTIBewplpQEwZ3Ode+JIdanxqXkw/D4CGClMpoyNG5HlmdAH05rDC6WPRTC6p2Iv4AkjXmjQ/WLh04dArEomt9aVJVfHMcxFiD+6muTEsl+i74OF961FpZEvJN09HEXyHmdOklwK1X7s9my7eYdK7egk8b8/6M+HfwNgE0MSAgIAAA== kind: ConfigMap metadata: creationTimestamp: 2019-02-08T11:12:38Z labels: MODIFIED_AT: "1550488348" NAME: release_name_1 OWNER: TILLER STATUS: DEPLOYED VERSION: "618" name: release_name_1.v618 namespace: kube-system resourceVersion: "298818981" selfLink: /api/v1/namespaces/kube-system/configmaps/release_name_1.v618 uid: 71c3e6f3-2b92-11e9-9b3c-525400a97005 de apiVersion: v1 data: release: H4sIAHEEd1wCA5WQwWrDMAyG734Kwc52mtvwtafdAh27FsURjaljG1kp5O3nNGGjhcJ21M/nT7+stVZvcEozO7LAFAgLnSNOdG4boSkHFCpNIb55R2bBKSjM/ou4+BQt3Fp19XGwcNoINZHggIJWAayaH6leJ/24oTIBewplpQEwZ3Ode+JIdanxqXkw/D4CGClMpoyNG5HlmdAH05rDC6WPRTC6p2Iv4AkjXmjQ/WLh04dArEomt9aVJVfHMcxFiD+6muTEsl+i74OF961FpZEvJN09HEXyHmdOklwK1X7s9my7eYdK7egk8b8/6M+HfwNgE0MSAgIAAA== kind: ConfigMap metadata: creationTimestamp: 2019-02-08T11:12:38Z labels: MODIFIED_AT: "1550488348" NAME: release_name_1 OWNER: TILLER STATUS: DEPLOYED VERSION: "618" name: release_name_1.v618 namespace: kube-system resourceVersion: "298818981" selfLink: /api/v1/namespaces/kube-system/configmaps/release_name_1.v618 uid: 71c3e6f3-2b92-11e9-9b3c-525400a97005 OU4 + BQt3Fp19XGwcNoINZHggIJWAayaH6leJ / 24oTIBewplpQEwZ3Ode + JIdanxqXkw / D4CGClMpoyNG5HlmdAH05rDC6WPRTC6p2Iv4AkjXmjQ / WLh04dArEomt9aVJVfHMcxFiD + 6muTEsl + i74OF961FpZEvJN09HEXyHmdOklwK1X7s9my7eYdK7egk8b8 / 6M + HfwNgE0MSAgIAAA == apiVersion: v1 data: release: H4sIAHEEd1wCA5WQwWrDMAyG734Kwc52mtvwtafdAh27FsURjaljG1kp5O3nNGGjhcJ21M/nT7+stVZvcEozO7LAFAgLnSNOdG4boSkHFCpNIb55R2bBKSjM/ou4+BQt3Fp19XGwcNoINZHggIJWAayaH6leJ/24oTIBewplpQEwZ3Ode+JIdanxqXkw/D4CGClMpoyNG5HlmdAH05rDC6WPRTC6p2Iv4AkjXmjQ/WLh04dArEomt9aVJVfHMcxFiD+6muTEsl+i74OF961FpZEvJN09HEXyHmdOklwK1X7s9my7eYdK7egk8b8/6M+HfwNgE0MSAgIAAA== kind: ConfigMap metadata: creationTimestamp: 2019-02-08T11:12:38Z labels: MODIFIED_AT: "1550488348" NAME: release_name_1 OWNER: TILLER STATUS: DEPLOYED VERSION: "618" name: release_name_1.v618 namespace: kube-system resourceVersion: "298818981" selfLink: /api/v1/namespaces/kube-system/configmaps/release_name_1.v618 uid: 71c3e6f3-2b92-11e9-9b3c-525400a97005 

Les manifestes générés sont stockés sous forme binaire (dans l'exemple ci-dessus avec la clé .data.release ), nous avons donc décidé de créer la version à l'aide des outils standard de Helm, mais avec un talon spécial, qui sera ensuite remplacé par les manifestes des ressources sélectionnées.

Implémentation


L'algorithme de solution est le suivant:

  1. Nous préparons un fichier manifest.yaml avec des manifestes de ressources pour adoption (cet élément sera discuté plus en détail ci-dessous).
  2. Nous créons un graphique dans lequel il existe un seul modèle avec un ConfigMap temporaire, car Helm ne peut pas créer de version sans ressources.
  3. Nous créons un templates/stub.yaml avec un stub dont la longueur sera égale au nombre de caractères dans manifest.yaml (au cours des expériences, il s'est avéré que le nombre d'octets devait correspondre). En tant que stub, un jeu de caractères reproductibles doit être sélectionné, qui restera après la génération et stocké dans le backend de stockage. Pour plus de simplicité et de clarté, # utilisé, à savoir:

     {{ repeat ${manifest_file_length} "#" }} 
  4. Installez le tableau: helm install et helm upgrade --install .
  5. Nous remplaçons le stub dans la version de backend de stockage par les manifest.yaml de ressources de manifest.yaml qui ont été sélectionnés pour adoption dans la première étape:

     stub=$(printf '#%.0s' $(seq 1 ${manifest_file_length})) release_data=$(kubectl get -n ${tiller_namespace} cm/${release_name}.v1 -o json | jq .data.release -r) updated_release_data=$(echo ${release_data} | base64 -d | zcat | sed "s/${stub}/$(sed -z 's/\n/\\n/g' ${manifest_file_path} | sed -z 's/\//\\\//g')/" | gzip -9 | base64 -w0) kubectl patch -n ${tiller_namespace} cm/${release_name}.v1 -p '{"data":{"release":"'${updated_release_data}'"}}' 
  6. Nous vérifions que Tiller est disponible et avons repris nos modifications.
  7. Supprimez le ConfigMap temporaire (de la deuxième étape).
  8. De plus, le travail avec la version n'est pas différent de la version régulière.

Gist avec l'implémentation décrite ci-dessus est disponible à:

 $ ./script.sh Example: ./script.sh foo bar-prod manifest.yaml Usage: ./script.sh CHART_NAME RELEASE_NAME MANIFEST_FILE_TO_ADOPT [TILLER_NAMESPACE] 

À la suite du script, la version de RELEASE_NAME est créée. Il s'associe aux ressources dont les manifestes sont décrits dans le fichier MANIFEST_FILE_TO_ADOPT . Un graphique CHART_NAME est également généré, qui peut être utilisé pour accompagner davantage les manifestes et les versions en particulier.

Lors de la préparation du manifeste avec des ressources, il est nécessaire de supprimer les champs de service utilisés par Kubernetes (ce sont des données de service dynamiques, il est donc incorrect de les versionner dans Helm). Dans un monde idéal, la formation se résume à une seule commande: kubectl get RESOURCE -o yaml --export . Après tout, la documentation dit:

  --export=false: If true, use 'export' for the resources. Exported resources are stripped of cluster-specific information. 

... mais, comme la pratique l'a montré, l'option --export toujours --export , donc un formatage manifeste supplémentaire sera nécessaire. Dans le service/release-name-habr ci-dessous, vous devez supprimer les selfLink creationTimestamp et selfLink .

version kubectl
 $ kubectl version Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.3", GitCommit:"721bfa751924da8d1680787490c54b9179b1fed0", GitTreeState:"clean", BuildDate:"2019-02-01T20:08:12Z", GoVersion:"go1.11.5", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.3", GitCommit:"721bfa751924da8d1680787490c54b9179b1fed0", GitTreeState:"clean", BuildDate:"2019-02-01T20:00:57Z", GoVersion:"go1.11.5", Compiler:"gc", Platform:"linux/amd64"} 

kubectl get service / release-name-habr -o yaml --export
 apiVersion: v1 kind: Service metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app.kubernetes.io/instance":"release-name","app.kubernetes.io/managed-by":"Tiller","app.kubernetes.io/name":"habr","helm.sh/chart":"habr-0.1.0"},"name":"release-name-habr","namespace":"default"},"spec":{"ports":[{"name":"http","port":80,"protocol":"TCP","targetPort":"http"}],"selector":{"app.kubernetes.io/instance":"release-name","app.kubernetes.io/name":"habr"},"type":"ClusterIP"}} creationTimestamp: null labels: app.kubernetes.io/instance: release-name app.kubernetes.io/managed-by: Tiller app.kubernetes.io/name: habr helm.sh/chart: habr-0.1.0 name: release-name-habr selfLink: /api/v1/namespaces/default/services/release-name-habr spec: ports: - name: http port: 80 protocol: TCP targetPort: http selector: app.kubernetes.io/instance: release-name app.kubernetes.io/name: habr sessionAffinity: None type: ClusterIP status: loadBalancer: {} 

Voici des exemples d'utilisation du script. Les deux montrent comment utiliser le script pour adopter des ressources travaillant dans le cluster et les supprimer ensuite à l'aide des outils Helm.

Exemple 1




Exemple 2




Conclusion


La solution décrite dans l'article peut être finalisée et utilisée non seulement pour adopter les ressources Kubernetes à partir de zéro, mais également pour les ajouter aux versions existantes.

Pour le moment il n'y a pas de solutions permettant de saisir les ressources existantes dans le cluster, de les transférer à la direction de Helm. Il est possible que dans Helm 3 une solution soit mise en œuvre pour couvrir ce problème (au moins il y a une proposition à ce sujet).

PS


Autres du cycle de trucs et astuces de K8:


Lisez aussi dans notre blog:

Source: https://habr.com/ru/post/fr441964/


All Articles