{"id":86902,"date":"2020-07-01T07:42:28","date_gmt":"2020-07-01T05:42:28","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/udalyaem-ustarevshuyu-feature-branch-v-kubernetes-klastere"},"modified":"2020-07-01T07:42:28","modified_gmt":"2020-07-01T05:42:28","slug":"udalyaem-ustarevshuyu-feature-branch-v-kubernetes-klastere","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/udalyaem-ustarevshuyu-feature-branch-v-kubernetes-klastere","title":{"rendered":"Eliminiamo il branch feature obsoleto nel cluster Kubernetes","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Eliminiamo il branch feature obsoleto nel cluster Kubernetes\" src=\"\/wp-content\/uploads\/2020\/07\/d97c0cce385c587e16f26f6d19b9d108.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Ciao! <b>Ramo funzionale<\/b> (aka deploy preview, review app) \u2014 \u00e8 quando vengono distribuite non solo la branch master, ma anche ogni pull request su un URL unico. Si pu\u00f2 verificare se il codice funziona nell'ambiente di produzione, e la funzionalit\u00e0 pu\u00f2 essere mostrata ad altri programmatori o product manager. Mentre si lavora nella pull request, ogni nuovo commit elimina il deploy attuale per il vecchio codice, e viene effettuato un nuovo deploy per il nuovo codice. Possono sorgere domande quando si \u00e8 fuso il pull request nella branch master. La feature branch non \u00e8 pi\u00f9 necessaria, ma le risorse di Kubernetes sono ancora nel cluster.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Ancora sulla feature branch<\/h2>\n<p><\/p>\n<p>Uno degli approcci per creare feature branch in Kubernetes \u00e8 utilizzare i namespace. In breve, la configurazione di produzione appare cos\u00ec:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">kind: Namespace\napiVersion: v1\nmetadata:\n  name: habr-back-end\n...\n\nkind: Deployment\napiVersion: apps\/v1\nmetadata:\n  namespace: habr-back-end\nspec:\n  replicas: 3\n...<\/code><\/pre>\n<p><\/p>\n<p>Per la feature branch viene creato un namespace con il suo identificatore (ad esempio, il numero della pull request) e un certo prefisso\/postfisso (ad esempio, <b>-pr-<\/b>):<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">kind: Namespace\napiVersion: v1\nmetadata:\n  name: habr-back-end-pr-17\n...\n\nkind: Deployment\napiVersion: apps\/v1\nmetadata:\n  namespace: habr-back-end-pr-17\nspec:\n  replicas: 1\n...<\/code><\/pre>\n<p><\/p>\n<p>In generale, ho scritto <b>Operatore Kubernetes<\/b> (un'applicazione che ha accesso alle risorse del cluster), <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dmytrostriletskyi\/stale-feature-branch-operator\">link al progetto su Github<\/a><\/noindex>. Rimuove i namespace che appartengono a vecchie feature branch. In Kubernetes, se si elimina un namespace, anche le altre risorse in quel namespace vengono eliminate automaticamente.<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl get pods --all-namespaces | grep -e \"-pr-\"\nNAMESPACE            ... AGE\nhabr-back-end-pr-264 ... 4d8h\nhabr-back-end-pr-265 ... 5d7h<\/code><\/pre>\n<p><\/p>\n<p>Su come implementare le feature branch nel cluster, si pu\u00f2 leggere <noindex><a rel=\"nofollow\" href=\"https:\/\/itnext.io\/feature-deployments-in-kubernetes-c74bdcff0d8e\">qui<\/a><\/noindex> e <noindex><a rel=\"nofollow\" href=\"https:\/\/codefresh.io\/kubernetes-tutorial\/dynamically-creating-k8s-namespaces-every-branch-pull-request-2\">qui<\/a><\/noindex>.<\/p>\n<p><\/p>\n<h2>Motivazione<\/h2>\n<p><\/p>\n<p>Diamo un'occhiata al ciclo di vita tipico di una pull request con integrazione continua (<code>continuous integration<\/code>):<\/p>\n<p><\/p>\n<ol>\n<li>Pushiamo un nuovo commit nella branch.<\/li>\n<li>Durante la build, vengono eseguiti linters e\/o test.<\/li>\n<li>Le configurazioni di Kubernetes della pull request vengono create al volo (ad esempio, il suo numero viene inserito in un modello pronto).<\/li>\n<li>Utilizzando kubectl apply, le configurazioni vengono caricate nel cluster (distribuzione).<\/li>\n<li>Il pull request viene unito nella branch master.<\/li>\n<\/ol>\n<p><\/p>\n<p>Mentre si lavora nella pull request, ogni nuovo commit elimina il deploy attuale per il vecchio codice, e viene effettuato un nuovo deploy per il nuovo codice. Ma quando il pull request viene fuso nella branch master, verr\u00e0 costruita solo la branch master. Alla fine, si dimentica il pull request, ma le sue risorse Kubernetes sono ancora nel cluster.<\/p>\n<p><\/p>\n<h2>Come utilizzare<\/h2>\n<p><\/p>\n<p>Installa il progetto con il comando seguente:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl apply -f https:\/\/raw.githubusercontent.com\/dmytrostriletskyi\/stale-feature-branch-operator\/master\/configs\/production.yml<\/code><\/pre>\n<p><\/p>\n<p>Crea un file con il seguente contenuto e installalo tramite <code>kubectl apply -f<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">apiVersion: feature-branch.dmytrostriletskyi.com\/v1\nkind: StaleFeatureBranch\nmetadata:\n  name: stale-feature-branch\nspec:\n  namespaceSubstring: -pr-\n  afterDaysWithoutDeploy: 3<\/code><\/pre>\n<p><\/p>\n<p>Parametro <b>namespaceSubstring<\/b> necessario per filtrare i namespace delle pull request da altri namespace. Ad esempio, se nel cluster ci sono i seguenti namespace: <code>habr-back-end<\/code>, <code>habr-front-end<\/code>, <code>habr-back-end-pr-17<\/code>, <code>habr-back-end-pr-33<\/code>, allora i candidati per la rimozione saranno <code>habr-back-end-pr-17<\/code>, <code>habr-back-end-pr-33<\/code>.<\/p>\n<p><\/p>\n<p>Parametro <b>afterDaysWithoutDeploy<\/b> necessario per eliminare i vecchi namespace. Ad esempio, se il namespace \u00e8 stato creato <code>3 giorni 1 ora<\/code> fa, e nel parametro \u00e8 specificato <code>3 giorni<\/code>, questo namespace verr\u00e0 rimosso. Funziona anche al contrario, se un namespace \u00e8 stato creato <code>2 giorni 23 ore<\/code> fa, e nel parametro \u00e8 specificato <code>3 giorni<\/code>, questo namespace non verr\u00e0 rimosso.<\/p>\n<p><\/p>\n<p>C'\u00e8 un altro parametro, che determina la frequenza con cui scansionare tutti i namespace e controllare i giorni senza deploy \u2014 <b>checkEveryMinutes<\/b>. Per impostazione predefinita \u00e8 uguale a <code>30 minuti<\/code>.<\/p>\n<p><\/p>\n<h2>Come funziona<\/h2>\n<p><\/p>\n<p>Nella pratica, servir\u00e0:<\/p>\n<p><\/p>\n<ol>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/docs.docker.com\/get-docker\">Docker<\/a><\/noindex> per lavorare in un ambiente isolato.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/tasks\/tools\/install-minikube\">Minikube<\/a><\/noindex> alzer\u00e0 il cluster Kubernetes localmente.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/tasks\/tools\/install-kubectl\">kubectl<\/a><\/noindex> \u2014 interfaccia della riga di comando per gestire il cluster.<\/li>\n<\/ol>\n<p><\/p>\n<p>Alziamo il cluster Kubernetes localmente:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ minikube start --vm-driver=docker\nminikube v1.11.0 su Darwin 10.15.5\nUtilizzando il driver docker basato sul profilo esistente.\nAvviando il nodo del piano di controllo minikube nel cluster minikube.<\/code><\/pre>\n<p><\/p>\n<p>Specifichiamo <code>kubectl<\/code> utilizzare il cluster locale per impostazione predefinita:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl config use-context minikube\nSwitched to context \"minikube\".<\/code><\/pre>\n<p><\/p>\n<p>Scarichiamo le configurazioni per l'ambiente di produzione:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ curl https:\/\/raw.githubusercontent.com\/dmytrostriletskyi\/stale-feature-branch-operator\/master\/configs\/production.yml &gt; stale-feature-branch-production-configs.yml<\/code><\/pre>\n<p><\/p>\n<p>Poich\u00e9 le configurazioni di produzione sono impostate per controllare i vecchi namespace, e nel nostro nuovo cluster non ce ne sono, sostituiamo la variabile di ambiente <code>IS_DEBUG<\/code> in <code>true<\/code>. Con questo valore, il parametro <code>afterDaysWithoutDeploy<\/code> non viene considerato e i namespace non vengono controllati per i giorni senza deploy, solo per la presenza della sottostringa (<code>-pr-<\/code>).<\/p>\n<p><\/p>\n<p>Se sei su <code>Linux<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ sed -i 's|false|true|g' stale-feature-branch-production-configs.yml<\/code><\/pre>\n<p><\/p>\n<p>Se sei su <code>macOS<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ sed -i \"\" 's|false|true|g' stale-feature-branch-production-configs.yml<\/code><\/pre>\n<p><\/p>\n<p>Installiamo il progetto:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl apply -f stale-feature-branch-production-configs.yml<\/code><\/pre>\n<p><\/p>\n<p>Controlliamo che nel cluster sia apparso il risorsa <code>StaleFeatureBranch<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl api-resources | grep stalefeaturebranches\nNOME                 ... APIGROUP                             ... TYPE\nstalefeaturebranches ... feature-branch.dmytrostriletskyi.com ... StaleFeatureBranch<\/code><\/pre>\n<p><\/p>\n<p>Controlliamo che nel cluster sia apparso l'operatore:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl get pods --namespace stale-feature-branch-operator\nNOME                                           ... STATO  ... ET\u00c0\nstale-feature-branch-operator-6bfbfd4df8-m7sch ... In esecuzione ... 38s<\/code><\/pre>\n<p><\/p>\n<p>Se si guarda nei suoi log, \u00e8 pronto a gestire le risorse <code>StaleFeatureBranch<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator\n... \"msg\":\"Versione dell'operatore: 0.0.1\"\n...\n... \"msg\":\"Avvio di EventSource\", ... , \"source\":\"tipo sorgente: \/, Tipo=\"}\n... \"msg\":\"Avvio del Controller\", ...}\n... \"msg\":\"Avvio dei lavoratori\", ..., \"numero di lavoratori\":1}<\/code><\/pre>\n<p><\/p>\n<p>Installiamo i pronti <code>fixtures<\/code> (configurazioni pronte per la modellazione delle risorse del cluster) per la risorsa <code>StaleFeatureBranch<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl apply -f https:\/\/raw.githubusercontent.com\/dmytrostriletskyi\/stale-feature-branch-operator\/master\/fixtures\/stale-feature-branch.yml<\/code><\/pre>\n<p><\/p>\n<p>\u00c8 specificato di cercare namespace contenenti la sottostringa <code>-pr-<\/code> ogni <code>1 minuto<\/code>.:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">apiVersion: feature-branch.dmytrostriletskyi.com\/v1\nkind: StaleFeatureBranch\nmetadata:\n  name: stale-feature-branch\nspec:\n  namespaceSubstring: -pr-\n  afterDaysWithoutDeploy: 1 \n  checkEveryMinutes: 1<\/code><\/pre>\n<p><\/p>\n<p>L'operatore ha risposto ed \u00e8 pronto a controllare i namespace:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator\n... \"msg\":\"La feature branch obsoleta \u00e8 in fase di elaborazione.\",\"namespaceSubstring\":\"-pr-\",\"afterDaysWithoutDeploy\":1,\"checkEveryMinutes\":1,\"isDebug\":\"true\"}<\/code><\/pre>\n<p><\/p>\n<p>Installiamo <code>fixtures<\/code>, contenente due namespace (<code>project-pr-1<\/code>, <code>project-pr-2<\/code>) e i loro <code>deployments<\/code>, <code>servizi<\/code>, <code>ingress<\/code>, e cos\u00ec via:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl apply -f https:\/\/raw.githubusercontent.com\/dmytrostriletskyi\/stale-feature-branch-operator\/master\/fixtures\/first-feature-branch.yml -f https:\/\/raw.githubusercontent.com\/dmytrostriletskyi\/stale-feature-branch-operator\/master\/fixtures\/second-feature-branch.yml\n...\nnamespace\/project-pr-1 created\ndeployment.apps\/project-pr-1 created\nservice\/project-pr-1 created\nhorizontalpodautoscaler.autoscaling\/project-pr-1 created\nsecret\/project-pr-1 created\nconfigmap\/project-pr-1 created\ningress.extensions\/project-pr-1 created\nnamespace\/project-pr-2 created\ndeployment.apps\/project-pr-2 created\nservice\/project-pr-2 created\nhorizontalpodautoscaler.autoscaling\/project-pr-2 created\nsecret\/project-pr-2 created\nconfigmap\/project-pr-2 created\ningress.extensions\/project-pr-2 created<\/code><\/pre>\n<p><\/p>\n<p>Verifichiamo che tutte le risorse sopra siano state create con successo:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 &amp;&amp; kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2\n...\nNAME                              ... READY ... STATUS  ... AGE\npod\/project-pr-1-848d5fdff6-rpmzw ... 1\/1   ... Running ... 67s\n\nNAME                         ... READY ... AVAILABLE ... AGE\ndeployment.apps\/project-pr-1 ... 1\/1   ... 1         ... 67s\n...<\/code><\/pre>\n<p><\/p>\n<p>Poich\u00e9 abbiamo attivato <code>debug<\/code>, namespace <code>project-pr-1<\/code> e <code>project-pr-2<\/code>, di conseguenza tutte le altre risorse, dovranno essere eliminate immediatamente senza considerare il parametro <code>afterDaysWithoutDeploy<\/code>. Nei log dell'operatore questo \u00e8 visibile:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator\n... \"msg\":\"Il namespace deve essere eliminato poich\u00e9 la modalit\u00e0 debug \u00e8 abilitata.\",\"namespaceName\":\"project-pr-1\"}\n... \"msg\":\"Il namespace \u00e8 in fase di elaborazione.\",\"namespaceName\":\"project-pr-1\",\"namespaceCreationTimestamp\":\"2020-06-16 18:43:58 +0300 EEST\"}\n... \"msg\":\"Il namespace \u00e8 stato eliminato.\",\"namespaceName\":\"project-pr-1\"}\n... \"msg\":\"Il namespace deve essere eliminato poich\u00e9 la modalit\u00e0 debug \u00e8 abilitata.\",\"namespaceName\":\"project-pr-2\"}\n... \"msg\":\"Il namespace \u00e8 in fase di elaborazione.\",\"namespaceName\":\"project-pr-2\",\"namespaceCreationTimestamp\":\"2020-06-16 18:43:58 +0300 EEST\"}\n... \"msg\":\"Il namespace \u00e8 stato eliminato.\",\"namespaceName\":\"project-pr-2\"}<\/code><\/pre>\n<p><\/p>\n<p>Se controlliamo la presenza delle risorse, saranno in stato <code>Terminating<\/code> (in fase di eliminazione) o gi\u00e0 eliminate (l'output del comando \u00e8 vuoto).<\/p>\n<p><\/p>\n<pre><code class=\"bash\">$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 &amp;&amp; kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2\n...<\/code><\/pre>\n<p><\/p>\n<p>Puoi ripetere il processo di creazione <code>fixtures<\/code> pi\u00f9 volte e assicurarti che vengano eliminate entro un minuto.<\/p>\n<p><\/p>\n<h2>Alternative<\/h2>\n<p><\/p>\n<p>Cosa si pu\u00f2 fare al posto dell'operatore che lavora in un cluster? Ci sono diversi approcci, tutti imperfetti (e i loro svantaggi sono soggettivi), e ciascuno decide cosa si adatta meglio al progetto specifico:<\/p>\n<p><\/p>\n<ol>\n<li>\n<p>Eliminare il branch feature durante la build del branch master di integrazione continua.<\/p>\n<p><\/p>\n<ul>\n<li>Per questo \u00e8 necessario sapere quale pull request \u00e8 associata al commit che viene costruito. Poich\u00e9 il namespace della feature branch contiene l'identificatore della pull request \u2014 il suo numero o nome della branch, l'identificatore deve sempre essere specificato nel commit.<\/li>\n<li>Le build dei branch master falliscono. Ad esempio, avete le seguenti fasi: scaricare il progetto, eseguire i test, compilare il progetto, fare il rilascio, inviare notifiche, pulire la feature branch dell'ultimo pull request. Se la build fallisce durante l'invio della notifica, dovrete eliminare tutte le risorse nel cluster manualmente.<\/li>\n<li>Senza un contesto adeguato, l'eliminazione della feature branch nella build master non \u00e8 ovvia.<\/li>\n<\/ul>\n<p>\n<\/li>\n<li>\n<p>Utilizzo dei webhook (<noindex><a rel=\"nofollow\" href=\"https:\/\/github.community\/t\/trigger-jenkins-job-when-a-pull-request-is-merged-to-a-branch\/1169\">un esempio<\/a><\/noindex>).<\/p>\n<p><\/p>\n<ul>\n<li>Potrebbe non essere il tuo approccio. Ad esempio, in <noindex><a rel=\"nofollow\" href=\"https:\/\/www.jenkins.io\">Jenkins<\/a><\/noindex>, solo un tipo di pipeline supporta la possibilit\u00e0 di salvare le sue configurazioni nel codice sorgente. Quando si utilizzano i webhook, \u00e8 necessario scrivere uno script per elaborarli. Questo script dovr\u00e0 essere collocato nell'interfaccia di Jenkins, il che \u00e8 difficile da mantenere.<\/li>\n<\/ul>\n<p>\n<\/li>\n<li>\n<p>Scrivere <noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/workloads\/controllers\/cron-jobs\/\">Cronjob<\/a><\/noindex> e aggiungere il cluster Kubernetes.<\/p>\n<p><\/p>\n<ul>\n<li>Spesa di tempo per la scrittura e il supporto.<\/li>\n<li>L'operatore gi\u00e0 funziona in uno stile simile, \u00e8 documentato e supportato.<\/li>\n<\/ul>\n<p>\n<\/li>\n<\/ol>\n<p><\/p>\n<p>Grazie per l'attenzione all'articolo. <strong><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dmytrostriletskyi\/stale-feature-branch-operator\">Link al progetto su Github<\/a><\/noindex><\/strong>.<\/p>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/508534\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442! Feature branch (aka deploy preview, review app) \u2014 \u044d\u0442\u043e \u043a\u043e\u0433\u0434\u0430 \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u0441\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e master \u0432\u0435\u0442\u043a\u0430, \u043d\u043e \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 pull request \u043d\u0430 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 URL. \u041c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043b\u0438 \u043a\u043e\u0434 \u0432 production-\u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438, \u0444\u0438\u0447\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430\u043c \u0438\u043b\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u043b\u043e\u0433\u0430\u043c. \u041f\u043e\u043a\u0430 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0432 pull request&#8217;\u0435, \u043a\u0430\u0436\u0434\u044b\u0439 \u043d\u043e\u0432\u044b\u0439 commit \u0442\u0435\u043a\u0443\u0449\u0438\u0439 deploy \u0434\u043b\u044f \u0441\u0442\u0430\u0440\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f, \u0430 \u043d\u043e\u0432\u044b\u0439 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":86903,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-86902","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442!\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/udalyaem-ustarevshuyu-feature-branch-v-kubernetes-klastere\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0443\u044e feature branch \u0432 Kubernetes \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442!\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/udalyaem-ustarevshuyu-feature-branch-v-kubernetes-klastere\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-07-01T05:42:28+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-07-01T05:42:28+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Eliminare il branch feature obsoleto nel cluster Kubernetes | ProHoster","description":"Ciao!","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/udalyaem-ustarevshuyu-feature-branch-v-kubernetes-klastere","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0443\u044e feature branch \u0432 Kubernetes \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 | ProHoster","og:description":"\u041f\u0440\u0438\u0432\u0435\u0442!","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/udalyaem-ustarevshuyu-feature-branch-v-kubernetes-klastere","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-07-01T05:42:28+00:00","article:modified_time":"2020-07-01T05:42:28+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"86902","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 14:03:55","updated":"2022-10-03 08:48:02","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/86902","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=86902"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/86902\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/86903"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=86902"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=86902"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=86902"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}