Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.
Section
Painel
titlePipeline - SmartSRE

Atualmente temos três processos de integração/entrega que são gerenciados pelo time de SRE da Engenharia Protheus.

Temos os clientes de Produção do SmartERP, os clientes de Produção do Smart eSocial e os ambientes do Sistêmico.

O processo de geração dos artefatos é

...

automatizado,  Tudo ocorre devido a jobs autônomos disparados em cada processo do sistema. Como utilizamos JOBs para atualização, disparamos vários processos ao mesmo tempo, a fim de ganharmos tempo com a atualização do ambiente.

Dentre este jobs, temos:

  • Montagem do RPO
  • Montagem dos artefatos de implantação/atualização
  • Compilação/montagem das imagens

...

  • e charts.
Painel
titleProcesso de Montagem e Atualização

...

Montagem do chart da topologia
Deck of Cards
idfluxo
Card
id01
labelMontagem do RPO

As Tarefas de montagem do RPO (Repositório de fontes Protheus) para utilização das soluções smart (backoffice, sistemico/release, taf e etc.). Está salvo no repositório: https://code.engpro.totvs.com.br/smarterp/pipeline-rpo

Parâmetros

Os parâmetros de execução, ficam salvos no arquivo .config na raiz deste repositório. Nele é possível configurar os parâmetros de execução e montagem do RPO de acordo com cada necessidade.

Informações

Release de geração: $RELEASE
Origem do RPO: $RPOSOURCE
Aplica expedição continua: $EXPCONT
Aplica expediçoes da next: $EXPCONTNEXT
Expedições ignoradas do published: $MODULE_PUBLISH_BLACKLIST
Expedições aceitas do latest: $MODULE_LATEST_ALLOW
Aplica pacote pontuais: $PATCHPONTUAL
Gera RPO para Mercado Internacional: $GERAMI
Aplica fontes antigos no RPO

: $APPLYOLD
Realiza a geração do JITT: $JITT
Versão do APPSERVER do JITT: $APPVERSION
Versão do SO do JITT: $SOVERSION
Chama a geração das imagens ao termino do processo: $BUILDIMAGE

Gravação.

Após a geração do RPO, o mesmo fica salvo dentro do bucket do smartsre que fica atualmente dentro do arte/engenharia/bundle/apo.

Cron

O repositório esta configurado para ser executado automaticamente as quintas (backoffice) e sabados (taf e sistemico/release). Para configurar o cron, basta chamar via api:


Informações

curl --request POST \
--url https://drone

A geração do RPO é realizada atraves do JOB: https://james

.engpro.totvs.com.br/

view

api/

all/job

repos/smarterp/

job/smarterp-apis/job/master/

Após entrar no schedule, basta clicar em construir com Parâmetros e preencher os parâmetros conforme abaixo:

Ao término do job, será apresentado no LOG a mensagem:

pipeline-rpo/cron \
--header 'Authorization: Bearer xxxxxxxxxxxx' \
--header 'Content-Type: application/json' \
--data '{
"name": "master-cron",
"expr": "* 0 10 * * 4",
"branch": "master"
}'

Execução via API.

A execução via API, por enquanto está restrita somente aos parâmetros configurados no .config, sendo que somente é possível passar a versão a ser gerada.


Card
id02
labelMontagem dos artefatos de implantação/atualização

Tarefa utilizada para empacotar os artefatos utilizados nas imagens utilizadas pelas soluções SmartSRE. Está salvo no repositório: https://code.engpro.totvs.com.br/smarterp/pipeline-imagem

Parâmetros

Os parâmetros de execução, ficam salvos no arquivo .config na raiz deste repositório. Nele é possível configurar os parâmetros de execução e montagem dos artefatos de acordo com cada necessidade.

Informações

Release de geração: $RELEASE
Gera com UPDDISTR: $UPDDISTR
Gera com UPDDISTR com condicional?: $UPDDISTRCOND || Informar uma expressao logica para execução do flag de upddistr (Usado na automação do sistemico)
Local do dicionario padrão: ${DICIONARIO_PADRAO_PATH}
Local do dicionario Mercado Internacional: ${DICIONARIO_MI_PATH}
Gera dados do mercado internacional?: ${GERAMI}
Atualiza Web-Files (Published)?: ${UPDATE_WEBFILES}
Atualiza MeuRH (Published)?: ${UPDATE_MEURH}
Atualiza versão do SmartReports?: ${UPDATE_TREPORTS}
Executa o CI das Imagens (codeengpro)?: ${GERA_IMAGEM}
Repo (codeengpro) da Imagem a ser gerada: ${IMAGEM_REPO}
Branch (codeengpro) da Imagem a ser gerada: ${IMAGEM_BRANCH}
Executa o CI do Chart (cloud104)?: ${GERA_CHART}
Repo (cloud104) da Imagem a ser gerada: ${CHART_REPO}
Branch (cloud104) da Imagem a ser gerada: ${CHART_BRANCH}
Local do Arquivo de Values do chart: ${CHART_VALUES}

Gravação.

Após a geração dos artefatos, os mesmos são salvos dentro do bucket do smartsre que fica atualmente dentro do arte/engenharia/bundle/smartsre/espelho.

Cron

O repositorio esta configurado para ser executado automaticamente as quintas (backoffice). Para configurar o cron, basta chamar via api: 

Informações

curl --request POST \
  --url https://drone

Quando terminar, o RPO atualizado será disponibilizado no folder: https://arte

.engpro.totvs.com.br/

engenharia

api/

bundles

repos/smarterp/

base/topologia/rpo_smarterp/

A pasta: base_12.1.xx refere-se ao RPO ACUMULATIVO, ou seja, todas as aplicações de pacotes ficam salvos neste repositório.

A pasta: applypatch refere-se ao folder que armazena os pacotes que iremos aplicar no RPO do smarterp

Obs: Temos hoje no modelo dois RPOs, um para o Brasil e outro para o mercado internacional. Para diferenciamos os pacotes, adicionamos antes da extensão .ptm o _portuguese ou _spanish ou _multi, com isto, sabemos que aquele pacote é especifico para os RPOs

Card
id02
labelMontagem das imagens Docker

pipeline-imagem/cron \
  --header 'Authorization: Bearer xxxxxxxxxxxx' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "backoffice-cron",
  "expr": "* 0 11 * * 4",
  "branch": "backoffice"
  }'

Integração

Origem

Este repositório está integrado com o pipeline-rpo, sendo que algumas branchs são disparadas diretamente pelo pipeline-rpo. Devido a isto, não possuímos cron para todas as branchs

Imagens e charts

Após a conclusão do processo de empacotamento dos artefatos, este repositório pode ser configurado para disparar o CI/CD de outros repositórios, como das IMAGENS e CHARTS.

Execução via API.

A execução via API, por enquanto está restrita somente aos parâmetros configurados no .config, sendo que somente é possível passar a versão a ser gerada.

Card
id03
labelCompilação/montagem das imagens e charts.

Uma vez montado os artefatos, realizamos a atualização do repositório de imagem e do repositório de charts. Ambos repositórios irão variar em decorrência ao tipo do recurso que iremos atualizar. Atualmente controlamos:

ProdutoImagemChart
SmartERP - BackofficeGitea: SmartERP/Protheus (Develop/Master)GitHub: Cloud104/SmartERP (Develop/Master)
SmartERP - SistêmicoGitea: SmartERP/SmartERP (Develop/Master)GitHub: Cloud104/SmartERP (release/smarterp-sistemico)
SmartERP - ReleaseGitea: SmartERP/SmartERP (Develop/Master)GitHub: Cloud104/SmartERP (release/12.1.2x10)
SmarteSocial - Produção (TAF)Gitea: SmartERP/smartesocial (Develop/Master)GitHub: Cloud104/smartesocial (Develop/Master)
SmartTSS - ProduçãoGitea: SmartERP/tss (Develop/Master)Não tem REPO
SmartTransmiteGitea: SmartERP/tss (Develop/Master)GitHub: Cloud104/smarttransmite (Develop/Master)


Para todos os repositórios listados, seguimos o seguinte fluxo de trabalho:

Embed draw.io Diagram
diagramNameFluxo de Trabalho SRE
includedDiagram1
width997
pageId737572212

Card
id04
labelAtualização da topologia

A atualização das topologias variam em de acordo com a cada cluster. Dentro os modelos de atualização temos:

Deck of Cards
idAtualizacao
Card
id01
labelSmartERP - Produção

Ocorre após a homologação do SmartERP Backoffice de forma manual através do script:

Bloco de código
#!/bin/bash
set -f

desiredVersion=$1
needbackup=$2
environments=$3

function LauncherExternalId() {
	kubectl get namespace $i -o json | jq -r .metadata.labels.External_id
}

if [ "$desiredVersion" == " " ]; then
	echo Informe a versao desejada para atualização
	exit 1
fi

if [ "$needbackup" == " " ]; then
	needbackup="false"
fi

if [ "$environments" == " " ]; then
	environments='cfields\|ctecnologia\|cbul2o\|cj0u6a\|ckwcoi\|ctvey3'
fi

hlmbkp="/totvs/ambientes/helm/$(date '+%Y%m%d')"
mkdir -p $hlmbkp

function backupIsRunning() {
	kubectl -n $i get pods | grep protheus-backup-update | grep -iv 'completed\|failed\|error\|evicted' | wc -l
}

echo "iniciando atualização dos ambientes"

if [ ! -f "/totvs/ambientes/helm/smarterp-$desiredVersion.tgz" ]; then
	wget -O /totvs/ambientes/helm/smarterp-$desiredVersion.tgz http://smarterp-charts.storage.googleapis.com/smarterp-$desiredVersion.tgz
fi

for i in $(envs | grep -v $desiredVersion | grep -i $environments | grep -iv 'migratio\|canceled\|inactive' | cut -f1 -d ' '); do

	if [ ! -f "$hlmbkp/$i.yaml" ]; then
		echo backup to helm values
		helm get values $i >$hlmbkp/$i.yaml
	fi

	echo $i

	cStatus=$(kubectl -n $i get configmap protheus-updater-config -o json | jq -r '.data.UPDATER_STATUS')

	if [ "$cStatus" == "" ]; then
		cStatus="FAILED"
	fi

	# Possibilidade de executar varias vezes em paralelo
	baseVersion=$(kubectl get namespace $i -o json | jq -r .metadata.labels.BaseVersion)
	UpdateVersion=$(kubectl get namespace $i -o json | jq -r .metadata.labels.UpdaterDesiredVersion)

	if [ "$cStatus" == "OK" ] || [ "$cStatus" == "FAILED" ]; then

		if [ "$baseVersion" != "$desiredVersion" ] && [ "$baseVersion" == "$UpdateVersion" ]; then

			qtpod=$(kubectl -n $i get deploy -l base=false -o jsonpath='{range .items[?(@.status.availableReplicas>=1)]}{@.metadata.name}{"\n"}{end}' | wc -l)
			echo "$i | pods actives -> $qtpod"

			if [ "$qtpod" == "0" ]; then
				monitorId=$(curl --request POST 'https://api.uptimerobot.com/v2/getMonitors' --form 'api_key=u752568-980824d9145b401cc6b723da' --form 'search='$i' - Protheus' | jq '.monitors[].id')

				# STOP
				curl --request POST 'https://api.uptimerobot.com/v2/editMonitor' --form 'api_key=u752568-980824d9145b401cc6b723da' --form 'id='$monitorId --form 'status=0'

				kubectl label ns $i --overwrite UpdaterDesiredVersion=$desiredVersion
				kubectl -n $i patch configmap protheus-updater-config -p '{"data":{ "UPDATER_STATUS":"UPDATING" }}'

				echo $i | grep -i development
				if [ "$?" == 1 ]; then
					echo updating global values
					env="producao"
				else
					#	echo updating global values
					env="homologacao"
				fi

				if [ "$needbackup" == "true" ]; then
					kubectl -n $i create job --from=cronjob/protheus-daily-backup protheus-backup-update-$(date '+%Y%m%d')
					sleep 5s

					while [[ "$(backupIsRunning)" != "0" ]]; do
						echo "$i Waiting backup file..."
						sleep 10
					done
				fi

				chartfile="/totvs/ambientes/helm/smarterp-$desiredVersion.tgz"

				for pod in $(kubectl -n $i get deploy --no-headers -l base=false | awk '$3 != '0' {print $1}'); do
					kubectl -n $i scale deploy $pod --replicas=0
				done

				kubectl -n $i scale deploy protheus-sleeper --replicas=0
				kubectl -n $i scale deploy -l base=true --replicas=1
				kubectl -n $i delete pods --all --force --grace-period=0

				echo "$i | clean components topology"
				kubectl -n $i delete deploy --all
				# Descomentar os serviços que foram alterados no ultimo chart (HELM 2 somente)
				# kubectl -n $i delete configmap $(kubectl -n $i get configmap --no-headers | grep -i 'appserver\|config' | cut -f1 -d ' ')
				# kubectl -n $i delete configmap --all

				# excluido serviços criados recentemente para atualização.
				# kubectl -n $i delete ingress $(kubectl -n $i get ingress --no-headers | grep -i 'report\|pgadmin\|logserver' | cut -f1 -d ' ')
				# kubectl -n $i delete service $(kubectl -n $i get service --no-headers | grep -i 'report\|pgadmin\|logserver' | cut -f1 -d ' ')
				# exclui todos os services, tirando o nodeport
				# kubectl -n $i delete service $(kubectl -n $i get service --no-headers | grep -v $i | grep -iv 'np' | cut -f1 -d ' ')

				# kubectl -n $i delete cronjob --all
				# kubectl -n $i delete job --all

				# kubectl -n $i delete pvc pgsql-disk
				# kubectl -n $i delete PodDisruptionBudget --all
				# kubectl -n $i patch pvc protheus-data-claim -p '{"metadata":{"finalizers": null}}' &
				# kubectl -n $i delete PersistentVolume protheus-volume-$i &
				# kubectl patch pv protheus-volume-$i -p '{"metadata":{"finalizers": null}}'
				# kubectl -n $i delete uptimerobot --all

				setvalues=""
				# Informar os novos values aqui
				# exemplo:
				# setvalues=$setvalues' --set global.logserver.enabled=true --set global.logserver.secretAccessKey="'$secretLogServer'"'

				echo "$i | executing helm upgrade to $desiredVersion"
				eval helm upgrade $i $chartfile --namespace=$i --install --timeout 1800000 --debug --recreate-pods -f $hlmbkp/$i.yaml $setvalues
				# --no-hooks

				if [ "$?" == "0" ]; then
					echo "$i | updating kubectl values to $desiredVersion"

					kubectl label ns $i --overwrite BaseVersion="$desiredVersion"
					kubectl -n $i patch configmap protheus-updater-config -p '{"data":{ "UPDATER_STATUS":"OK" }}'
					kubectl -n $i patch configmap protheus-updater-config -p '{"data":{"HOOK_ENVIRONMENT_'$env'":""}}'
					kubectl -n $i patch configmap protheus-updater-config -p '{"data":{"HOOK_UPDATEDATA_'$env'":""}}'
					kubectl -n $i patch configmap protheus-updater-config -p '{"data":{"HOOK_UPDATEDATADICTONARY_'$env'":"" }}'

					# echo "$i | shutdown services"
					for pod in $(kubectl -n $i get deploy --no-headers | awk '$3 != '0' {print $1}'); do
						kubectl -n $i scale deploy $pod --replicas=0
					done

					for pod in $(kubectl -n $i get deploy --no-headers | grep -i "appserver\|config\|rest" | awk '$3 == '0' {print $1}'); do
						kubectl -n $i patch service ${pod}-svc -p '{"metadata":{"annotations":{"tks.sh/sleeper.user":""}}}'
					done

					for j in $(kubectl -n $i get deploy -l base=false --no-headers | grep -i 'config\|rest' | cut -d ' ' -f 1); do
						kubectl -n $i patch deploy $j -p '{"metadata":{"labels":{"base":"true" }}}'
						kubectl -n $i patch deploy $j -p '{"spec":{"template":{"metadata":{"labels":{"base":"true" }}}}}'
						kubectl -n $i patch deploy $j -p '{"metadata":{"annotations":{"tks.sh/sleeper.depends":"" }}}'
					done

					for j in $(kubectl -n $i get deploy -l base=false --no-headers | grep -iv 'config\|rest\|carol' | cut -d ' ' -f 1); do  
						depends=$(kubectl -n $i get deploy $j -o yaml | yq -r '.metadata.annotations."tks.sh/sleeper.depends"')",protheus-config-$env-all,protheus-rest-$env-all" 
						kubectl -n $i patch deploy $j -p '{"metadata":{"annotations":{"tks.sh/sleeper.depends":"'$depends'" }}}'
					done

					kubectl -n $i delete pods --all --force --grace-period=0

					# echo "$i | Start hypnus and license"
					# kubectl -n $i scale deploy protheus-license --replicas=1
					kubectl -n $i scale deploy protheus-sleeper --replicas=1

					topology=$(echo $i | cut -f1 -d '-')

					# START
					curl --request POST 'https://api.uptimerobot.com/v2/editMonitor' --form 'api_key=u752568-980824d9145b401cc6b723da' --form 'id='$monitorId --form 'status=1'

				else
					echo "$i HELM" >>/totvs/ambientes/erro.txt
					kubectl -n $i patch configmap protheus-updater-config -p '{"data":{ "UPDATER_STATUS":"FAILED" }}'
					exit 1
				fi

				#exit 0
			fi
			# sleep 5s
		fi
	else
		echo "$i status" >>/totvs/ambientes/erro.txt
	fi
done

echo "=) update finish!....."

spd-say -l "en-us" "     pay attention, it's done"

exit 0
Card
id02
labelSmartERP - BackOffice

Atualização ocorre de forma automática ao termino da publicação do chart no GCP para a branch develop

Bloco de código
#!/bin/bash

if [ "$1" == "" ]; then
   echo need to provide new version
   exit
fi

for i in $(kubectl get ns --no-headers --sort-by=.metadata.creationTimestamp | grep -i 'cbul2o' | cut -d ' ' -f 1); do
   echo $i

   kubectl patch ns $i -p '{"metadata":{"labels":{"UpdaterDesiredVersion":"'$1'", "UpdaterIgnoreUsing": "true"}}}'

   kubectl -n $i patch configmap protheus-updater-config -p '{"data":{ "UPDATER_STATUS":"OK" }}'
   kubectl -n $i patch configmap protheus-updater-config -p '{"data":{"HOOK_ENVIRONMENT_producao":""}}'
   kubectl -n $i patch configmap protheus-updater-config -p '{"data":{"HOOK_UPDATEDATA_producao":""}}'
   kubectl -n $i patch configmap protheus-updater-config -p '{"data":{"HOOK_UPDATEDATADICTONARY_producao":"" }}'

   kubectl -n $i scale deploy -l base=false --replicas=0
   kubectl -n $i scale deploy -l base=true --replicas=1

   kubectl -n $i delete pods --all --force --grace-period=0

   kubectl -n $i delete job force-update
   kubectl -n $i create job --from=cronjob/protheus-updater force-update
done
Card
id03
labelSmartERP - Release/Sistêmico

Atualização ocorre de forma automática ao termino da publicação do chart no GCP para a branch release ou sistêmico

Bloco de código
#!/bin/bash

if [ "$1" == "" ]; then
   echo need to provide new version
   exit
fi

for i in $(kubectl get ns --no-headers --sort-by=.metadata.creationTimestamp | grep -i 'cbul2o' | cut -d ' ' -f 1); do
   echo $i

   kubectl patch ns $i -p '{"metadata":{"labels":{"UpdaterDesiredVersion":"'$1'", "UpdaterIgnoreUsing": "true"}}}'

   kubectl -n $i patch configmap protheus-updater-config -p '{"data":{ "UPDATER_STATUS":"OK" }}'
   kubectl -n $i patch configmap protheus-updater-config -p '{"data":{"HOOK_ENVIRONMENT_producao":""}}'
   kubectl -n $i patch configmap protheus-updater-config -p '{"data":{"HOOK_UPDATEDATA_producao":""}}'
   kubectl -n $i patch configmap protheus-updater-config -p '{"data":{"HOOK_UPDATEDATADICTONARY_producao":"" }}'

   kubectl -n $i scale deploy -l base=false --replicas=0
   kubectl -n $i scale deploy -l base=true --replicas=1

   kubectl -n $i delete pods --all --force --grace-period=0

   kubectl -n $i delete job force-update
   kubectl -n $i create job --from=cronjob/protheus-updater force-update
done
Card
id03
label
Card
id04
labelSmart eSocial - Homologação

Atualização

ocorre de forma automática ao término da publicação do chart no GCP para a branch develop.

Aviso

Atualização utiliza o SmartUpdater do cluster e não do NS

Bloco de código
#!/bin/bash

if [ "$1" == "" ]; then
   echo need to provide new version
   exit
fi

for i in $(kubectl get ns --no-headers --sort-by=.metadata.creationTimestamp | grep -i 'c0fbc5' | cut -d ' ' -f 1); do
   kubectl patch ns $i -p '{"metadata":{"labels":{"UpdaterDesiredVersion":"'$1'", "UpdaterIgnoreUsing": "true"}}}'
done
Card
id05
labelSmart eSocial - Produção

Atualização ocorre de forma manual, através de script de atualização.

Bloco de código
#!/bin/bash
set -f

function updateIsRunning() {
  kubectl -n $i get pods | grep -i "protheus-appserver-" | grep -i 'Running' | grep -iv 'completed\|failed\|Init' | wc -l
}

function stopMonitor() {
  monitorId=$(curl --request POST 'https://api.uptimerobot.com/v2/getMonitors' --form 'api_key=u592805-9185b8fb1fd629c4b289786e' --form 'search='$i' Homolog Rest' | jq '.monitors[].id')
  postMonitor $monitorId '0'

  monitorId=$(curl --request POST 'https://api.uptimerobot.com/v2/getMonitors' --form 'api_key=u592805-9185b8fb1fd629c4b289786e' --form 'search='$i' Homolog Webapp' | jq '.monitors[].id')
  postMonitor $monitorId '0'

  monitorId=$(curl --request POST 'https://api.uptimerobot.com/v2/getMonitors' --form 'api_key=u592805-9185b8fb1fd629c4b289786e' --form 'search='$i' Prod Rest' | jq '.monitors[].id')
  postMonitor $monitorId '0'

  monitorId=$(curl --request POST 'https://api.uptimerobot.com/v2/getMonitors' --form 'api_key=u592805-9185b8fb1fd629c4b289786e' --form 'search='$i' Prod Webapp' | jq '.monitors[].id')
  postMonitor $monitorId '0'

}

function startMonitor() {
  monitorId=$(curl --request POST 'https://api.uptimerobot.com/v2/getMonitors' --form 'api_key=u592805-9185b8fb1fd629c4b289786e' --form 'search='$i' Homolog Rest' | jq '.monitors[].id')
  postMonitor $monitorId '1'

  monitorId=$(curl --request POST 'https://api.uptimerobot.com/v2/getMonitors' --form 'api_key=u592805-9185b8fb1fd629c4b289786e' --form 'search='$i' Homolog Webapp' | jq '.monitors[].id')
  postMonitor $monitorId '1'

  monitorId=$(curl --request POST 'https://api.uptimerobot.com/v2/getMonitors' --form 'api_key=u592805-9185b8fb1fd629c4b289786e' --form 'search='$i' Prod Rest' | jq '.monitors[].id')
  postMonitor $monitorId '1'

  monitorId=$(curl --request POST 'https://api.uptimerobot.com/v2/getMonitors' --form 'api_key=u592805-9185b8fb1fd629c4b289786e' --form 'search='$i' Prod Webapp' | jq '.monitors[].id')
  postMonitor $monitorId '1'
}

function postMonitor() {
  curl --request POST 'https://api.uptimerobot.com/v2/editMonitor' --form 'api_key=u592805-9185b8fb1fd629c4b289786e' --form 'id='$1 --form 'status='$2
}

desiredVersion=$1
environments=$2

if [ "$desiredVersion" == " " ]; then
  echo Informe a versao desejada para atualização
  exit 1
fi

if [ "$environments" == " " ]; then
  environments=$(kubectl get ns --no-headers --sort-by=.metadata.creationTimestamp | cut -d' ' -f1)
fi

hlmbkp="/totvs/ambientes/helm-taf/$(date '+%Y%m%d')"
mkdir -p $hlmbkp

cd $hlmbkp

echo "iniciando atualização dos ambientes"

for i in $(kubectl get ns --no-headers --sort-by=.metadata.creationTimestamp | grep -iv $desiredVersion | grep -i $environments | cut -f1 -d ' '); do

  qtpod=$(kubectl -n $i get deploy -o jsonpath='{range .items[?(@.status.availableReplicas>=1)]}{@.metadata.name}{"\n"}{end}' | grep 'appserver\|rest' | wc -l)
  echo "$i | pods actives -> $qtpod"

  if [ "$qtpod" == "0" ] || [ "$qtpod" == "4" ]; then

    sleep 3s
    # Possibilidade de executar varias vezes em paralelo
    baseVersion=$(kubectl get namespace $i -o json | jq -r .metadata.labels.BaseVersion)
    UpdateVersion=$(kubectl get namespace $i -o json | jq -r .metadata.labels.UpdaterDesiredVersion)

    if [ "$baseVersion" != "$desiredVersion" ] && [ "$baseVersion" == "$UpdateVersion" ]; then
      kubectl label ns $i --overwrite UpdaterDesiredVersion=$desiredVersion
      kubectl -n $i scale deploy protheus-sleeper --replicas=0

      stopMonitor $i >>/dev/null 2>&1

      if [ ! -f "$hlmbkp/$i.yaml" ]; then
        echo backup to helm values
        helm get values $i >$hlmbkp/$i.yaml
      fi

      if [ ! -f "/totvs/ambientes/helm/taf-standard-$desiredVersion.tgz" ]; then
        wget -O /totvs/ambientes/helm/taf-standard-$desiredVersion.tgz http://smartesocial-charts.storage.googleapis.com/taf-standard-$desiredVersion.tgz
      fi

      chartfile="/totvs/ambientes/helm/taf-standard-$desiredVersion.tgz"

      echo "$i | clean components topologie"
      kubectl -n $i delete pods --all --force --grace-period=0

      newHelmValues=""
	  # informar somente se tiver novos values
      # exemplo: newHelmValues=$newHelmValues' --set protheus-base.cloudProvider=aws'

      kubectl -n $i delete cronjob --all
      kubectl -n $i delete job --all
      kubectl -n $i delete configmap --all
      kubectl -n $i delete deploy --all
      kubectl -n $i delete ingress --all

      # exclui todos os services, tirando o nodeport
      # kubectl -n $i delete service $(kubectl -n $i get service --no-headers | grep -v $i | grep -iv 'np' | cut -f1 -d ' ')
      # helm delete $i --no-hooks --purge

      echo "$i | executing helm upgrade to $desiredVersion"
      helm upgrade $i $chartfile --namespace=$i --debug --install --recreate-pods --timeout 180000 -f $hlmbkp/$i.yaml $newHelmValues

      if [ "$?" == "0" ]; then
        echo "$i | updating kubectl values to $desiredVersion"
        kubectl label ns $i --overwrite BaseVersion="$desiredVersion"
      else
        echo "$i | error helm updating to $desiredVersion"
        exit 1
      fi

      echo "$i | Updating environment"
      kubectl -n $i scale deploy --all --replicas=0
      kubectl -n $i scale deploy -l base=true --replicas=1
      kubectl -n $i scale deploy protheus-appserver-producao-all --replicas=1
      kubectl -n $i scale deploy protheus-appserver-homologacao-all --replicas=1
      kubectl -n $i scale deploy protheus-sleeper --replicas=0

      sleep 10
      while [[ "$(updateIsRunning)" != "2" ]]; do
        echo "$i Waiting update... "
        sleep 10
      done

      startMonitor $i >>/dev/null 2>&1

      kubectl -n $i scale deploy --all --replicas=0
      kubectl -n $i scale deploy protheus-sleeper --replicas=1
    fi
  fi

done

spd-say -l "en-us" "     pay attention, it's done"

exit 0

Após a conclusão dos jobs supracitados, realizamos a atualização das topologias via Helm. Este processo para o cluster de produção é manual e controlado pelo SRE.