Este documento irá guiá-lo na configuração do seu gerenciador de tarefas Sintético , mostrando como:
- Use variáveis de ambiente para configurar seu gerenciador de tarefas Sintético.
- Configure módulos personalizados para API com script ou monitor de navegador com script .
- Forneça variáveis definidas pelo usuário em sua configuração.
Configuração usando variáveis de ambiente
As variáveis ambientais permitem ajustar a configuração do gerenciador de tarefas Sintético para atender às suas necessidades ambientais e funcionais específicas.
As variáveis são fornecidas na inicialização usando o argumento -e, --env .
A tabela a seguir mostra todas as variáveis de ambiente suportadas pelo gerenciador de tarefas Sintético. PRIVATE_LOCATION_KEY é obrigatório e todas as outras variáveis são opcionais.
Nome | Descrição |
|---|---|
| Required. chave de localização privada, conforme encontrada na lista entidade privada de localização. |
| Formato: Padrão: |
| Aponta o gerenciador de tarefas Sintético para um determinado |
| Para contas baseadas nos EUA, o endpoint é: Para contas baseadas na UE , o endpoint é: Certifique-se de que seu gerenciador de tarefas Sintético possa se conectar ao endpoint apropriado para atender seu monitor. |
| O domínio Docker Registry onde as imagens de tempo de execução estão hospedadas. Use isto para substituir |
| O docker repositório ou organização onde as imagens de tempo de execução estão hospedadas. Use isto para substituir |
| Host do servidor proxy usado para comunicação da Horda. Formato: |
| Porta do servidor proxy usada para comunicação da Horda. Formato: |
| Nome de usuário do servidor proxy usado para comunicação da Horda. Formato: |
| Senha do servidor proxy usada para comunicação da Horda. Formato: |
| Aceita certificados proxy autoassinados para a conexão do servidor proxy usada para comunicação do Horde? Valores aceitáveis: |
| A quantidade máxima de segundos que as verificações do seu monitor podem ser executadas. Este valor deve ser um número inteiro entre 0 segundos (excluído) e 900 segundos (incluído) (por exemplo, de 1 segundo a 15 minutos). Padrão: 180 segundos |
| Padrão: Opções adicionais: |
| O número de trabalhos pesados simultâneos (navegador/navegador com script e API com script) que podem ser executados ao mesmo tempo. Padrão: CPUs disponíveis - 1. |
| Uma matriz que pode ser usada para executar imagens de tempo de execução específicas. Formato: ['newrelic/Sintético-ping-runtime:latest','newrelic/Sintético-node-API-runtime:latest','newrelic/Sintético-node-navegador-runtime:latest'] Padrão: todos os tempos de execução mais recentes. |
| Se definido, ativa verified script execution e usa esse valor como passphrase. |
| Um conjunto hospedado localmente de pares de valores principais definidos pelo usuário. |
| Se definido, habilita o webassembly para o tempo de execução do navegador do nó. Para usar o webassembly, a versão mínima do seu gerenciador de tarefas Sintético deve ser release-367 ou superior e a versão do tempo de execução do navegador do nó deve ser 2.3.21 ou superior. |
As variáveis são fornecidas na inicialização usando o argumento -e, --env .
A tabela a seguir exibe todas as variáveis de ambiente que o gerenciador de tarefas Sintéticos suporta. PRIVATE_LOCATION_KEY é obrigatório e todas as outras variáveis são opcionais. Para executar o gerenciador de tarefas Sintéticos em um ambiente Podman, a versão mínima deve ser release-418 ou superior.
Nome | Descrição |
|---|---|
| Required. chave de localização privada, conforme encontrada na lista entidade privada de localização. |
| Para contas baseadas nos EUA, o endpoint é: Para contas baseadas na UE , o endpoint é: Certifique-se de que seu gerenciador de tarefas Sintético possa se conectar ao endpoint apropriado para atender seu monitor. |
| A entrada do host adicionada ao pod criado onde o SJM será executado. Use isto para substituir |
| A porta na qual o serviço Podman LibPod RESTful API está sendo executado na instância. Use isto para substituir |
| A versão específica da API RESTful do Podman LibPod que está sendo usada. Use isto para substituir |
| O nome do pod no qual o contêiner SJM é executado. Use isto para substituir |
| O domínio Docker Registry onde as imagens de tempo de execução estão hospedadas. Use isto para substituir |
| O docker repositório ou organização onde as imagens de tempo de execução estão hospedadas. Use isto para substituir |
| Host do servidor proxy usado para comunicação da Horda. Formato: |
| Porta do servidor proxy usada para comunicação da Horda. Formato: |
| Nome de usuário do servidor proxy usado para comunicação da Horda. Formato: |
| Senha do servidor proxy usada para comunicação da Horda. Formato: |
| Aceita certificados proxy autoassinados para a conexão do servidor proxy usada para comunicação do Horde? Valores aceitáveis: |
| A quantidade máxima de segundos que as verificações do seu monitor podem ser executadas. Este valor deve ser um número inteiro entre 0 segundos (excluído) e 900 segundos (incluído) (por exemplo, de 1 segundo a 15 minutos). Padrão: 180 segundos |
| Padrão: Opções adicionais: |
| O número de trabalhos pesados simultâneos (navegador/navegador com script e API com script) que podem ser executados ao mesmo tempo. Padrão: CPUs disponíveis - 1. |
| Uma matriz que pode ser usada para executar imagens de tempo de execução específicas. Formato: ['newrelic/Sintético-ping-runtime:latest','newrelic/Sintético-node-API-runtime:latest','newrelic/Sintético-node-navegador-runtime:latest'] Padrão: todos os tempos de execução mais recentes. |
| Se definido, ativa verified script execution e usa esse valor como passphrase. |
| Um conjunto hospedado localmente de pares de valores principais definidos pelo usuário. |
| Se definido, habilita o webassembly para o tempo de execução do navegador do nó. Para usar o webassembly, a versão mínima do seu gerenciador de tarefas Sintético deve ser release-367 ou superior e a versão do tempo de execução do navegador do nó deve ser 2.3.21 ou superior. |
As variáveis são fornecidas na inicialização usando o argumento --set .
A lista a seguir mostra todas as variáveis de ambiente suportadas pelo gerenciador de tarefas Sintético. synthetics.privateLocationKey é obrigatório e todas as outras variáveis são opcionais.
Uma série de configurações avançadas adicionais estão disponíveis e totalmente documentadas em nosso README do gráfico do Helm
Nome | Descrição |
|---|---|
| Required if |
| Required if |
| O nome do objeto secreto usado para extrair uma imagem de um registro de contêiner especificado. |
| Substituição de nome usada para sua implantação, substituindo o padrão. |
| Versão de lançamento do Sintético-job-manager para usar em vez da versão especificada em chart.yml. |
| Padrão: Opções adicionais: |
| Para contas baseadas nos EUA, o endpoint é: Para contas baseadas na UE , o endpoint é: Certifique-se de que seu gerenciador de tarefas Sintético possa se conectar ao endpoint apropriado para atender seu monitor. |
| O registro e organização Docker onde a imagem do minion Runner está hospedada. Use isto para substituir |
| Se definido, ele ativa verified script execution e usa esse valor como passphrase. |
| Se definido, permite a execução verificada do script e usa esse valor para recuperar a senha de um segredo do Kubernetes com uma chave chamada |
| Se definido, habilita o webassembly para o tempo de execução do navegador do nó. Para usar o webassembly, a versão mínima do seu gerenciador de tarefas Sintético deve ser release-367 ou superior e a versão do tempo de execução do navegador do nó deve ser 2.3.21 ou superior. |
| Servidor proxy usado para comunicação da Horda. Formato: |
| Porta do servidor proxy usada para comunicação da Horda. Formato: |
| Aceite certificados autoassinados ao usar um servidor proxy para comunicação do Horde. Valores aceitáveis: |
| Nome de usuário do servidor proxy para comunicação da Horda. Formatar: |
| Senha do servidor proxy para comunicação da Horda. Formato: |
| Uma string JSON de variáveis definidas pelo usuário. O usuário pode acessar essas variáveis em seu script. Formato: |
| Um caminho local para o usuário para um arquivo JSON contendo variáveis definidas pelo usuário. Isso é transmitido por meio de |
| Um caminho no PersistentVolume fornecido pelo usuário para o arquivo user_defined_variables.json. O usuário deverá fornecer um PersistentVolume ou PersistentVolumeClaim se esta variável for preenchida. |
| Se estiver montando um volume, o usuário poderá fornecer um nome para um PersistentVolumeClaim que já existe no cluster. Pressupõe a existência de um PersistentVolume correspondente. |
| Se estiver montando um volume e não fornecer um PersistentVolumeClaim, o usuário deverá fornecer, no mínimo, um nome PersistentVolume. Helm irá gerar um PersistentVolumeClaim. |
| O nome do StorageClass para o PersistentVolumeClaim gerado. Isso deve corresponder ao StorageClassName no PV existente. Caso contrário, o Kubernetes usará a classe de armazenamento padrão, se presente. |
| O tamanho do volume do PersistentVolumeClaim gerado. Formato: |
| A quantidade máxima de segundos que as verificações do seu monitor podem ser executadas. Este valor deve ser um número inteiro entre 0 segundos (excluído) e 900 segundos (incluído) (por exemplo, de 1 segundo a 15 minutos). Padrão: 180 segundos |
| O contêiner a ser puxado. Padrão: |
| A política de puxar. Padrão: |
| Configure um contexto de segurança customizado para o pod Sintético-job-manager. |
| Se o tempo de execução do ping persistente deve ou não ser implantado. Isso pode ser desativado se você não usar o monitor de ping. Padrão: |
| O número de contêineres de tempo de execução de ping a serem implantados. Aumente o replicaCount para dimensionar a implantação com base nas suas necessidades de monitoramento de ping. Padrão: |
| A imagem do contêiner a ser extraída para o tempo de execução do ping. Padrão: |
| A política pull para o contêiner de tempo de execução de ping. Padrão: |
| Se o tempo de execução da API Node.js deve ou não ser implantado. Isso pode ser desativado se você não usar o monitor de API com script. Padrão: |
| O número de ambientes de execução da API Node.js Padrão: |
| O número de ambientes de execução da API Node.js Padrão: |
| A imagem do contêiner a ser extraída para o ambiente de execução da API Node.js. Padrão: |
| A política pull para o contêiner de tempo de execução da API Node.js. Padrão: |
| Se o tempo de execução do navegador Node.js deve ou não ser implantado. Isso pode ser desativado se você não usar o script com simples ou monitor do navegador. Padrão: |
| O número de tempos de execução do navegador Chrome Padrão: |
| O número de tempos de execução do navegador Chrome Padrão: |
| A imagem do contêiner a ser extraída para o tempo de execução do navegador Node.js. Padrão: |
| A política pull para o contêiner de tempo de execução do navegador Node.js. Padrão: |
As variáveis são fornecidas na inicialização usando o argumento --set .
A lista a seguir mostra todas as variáveis de ambiente suportadas pelo gerenciador de tarefas Sintético. synthetics.privateLocationKey é obrigatório e todas as outras variáveis são opcionais.
Uma série de configurações avançadas adicionais estão disponíveis e totalmente documentadas em nosso README do gráfico do Helm
Nome | Descrição |
|---|---|
| Required. localização privada key, conforme encontrado na lista localização privada entidade. |
| O nome do objeto secreto usado para extrair uma imagem de um registro de contêiner especificado. |
| Substituição de nome usada para sua implantação, substituindo o padrão. |
| Versão de lançamento do Sintético-job-manager para usar em vez da versão especificada em chart.yml. |
| Padrão: Opções adicionais: |
| Para contas baseadas nos EUA, o endpoint é: Para contas baseadas na UE , o endpoint é: Certifique-se de que seu gerenciador de tarefas Sintético possa se conectar ao endpoint apropriado para atender seu monitor. |
| Se definido, ele ativa verified script execution e usa esse valor como passphrase. |
| Se definido, permite a execução verificada do script e usa esse valor para recuperar a senha de um segredo do Kubernetes com uma chave chamada |
| Se definido, habilita o webassembly para o tempo de execução do navegador do nó. Para usar o webassembly, a versão mínima do seu gerenciador de tarefas Sintético deve ser release-367 ou superior e a versão do tempo de execução do navegador do nó deve ser 2.3.21 ou superior. |
| Servidor proxy usado para comunicação da Horda. Formato: |
| Porta do servidor proxy usada para comunicação da Horda. Formato: |
| Aceite certificados autoassinados ao usar um servidor proxy para comunicação do Horde. Valores aceitáveis: |
| Nome de usuário do servidor proxy para comunicação da Horda. Formatar: |
| Senha do servidor proxy para comunicação da Horda. Formato: |
| Uma string JSON de variáveis definidas pelo usuário. O usuário pode acessar essas variáveis em seu script. Formato: |
| Um caminho local para o usuário para um arquivo JSON contendo variáveis definidas pelo usuário. Isso é transmitido por meio de |
| Um caminho fornecido pelo usuário |
| Ao montar um volume, o usuário pode fornecer um nome para um |
| Se estiver montando um volume e não fornecer um |
| O nome do |
| O tamanho do volume para o |
| A quantidade máxima de segundos que as verificações do seu monitor podem ser executadas. Este valor deve ser um número inteiro entre 0 segundos (excluído) e 900 segundos (incluído) (por exemplo, de 1 segundo a 15 minutos). Padrão: 180 segundos |
| O contêiner a ser puxado. Padrão: |
| A política de puxar. Padrão: |
| Defina um contexto de segurança personalizado para o pod |
| Se o tempo de execução do ping persistente deve ou não ser implantado. Isso pode ser desativado se você não usar o monitor de ping. Padrão: |
| O número de contêineres de tempo de execução de ping a serem implantados. Aumente o Padrão: |
| A imagem do contêiner a ser extraída para o tempo de execução do ping. Padrão: |
| A política pull para o contêiner de tempo de execução de ping. Padrão: |
| Se o tempo de execução da API Node.js deve ou não ser implantado. Isso pode ser desativado se você não usar o monitor de API com script. Padrão: |
| O número de ambientes de execução da API Node.js Padrão: |
| O número de ambientes de execução da API Node.js Padrão: |
| A imagem do contêiner a ser extraída para o ambiente de execução da API Node.js. Padrão: |
| A política pull para o contêiner de tempo de execução da API Node.js. Padrão: |
| Se o tempo de execução do navegador Node.js deve ou não ser implantado. Isso pode ser desativado se você não usar o script com simples ou monitor do navegador. Padrão: |
| O número de tempos de execução do navegador Chrome Padrão: |
| O número de tempos de execução do navegador Chrome Padrão: |
| A imagem do contêiner a ser extraída para o tempo de execução do navegador Node.js. Padrão: |
| A política pull para o contêiner de tempo de execução do navegador Node.js. Padrão: |
Variáveis definidas pelo usuário para monitor com script
Os gerenciadores de tarefas Private Sintético permitem configurar variáveis de ambiente para monitor com script. Essas variáveis são gerenciadas localmente no SJM e podem ser acessadas via $env.USER_DEFINED_VARIABLES. Você pode definir variáveis definidas pelo usuário de duas maneiras. Você pode montar um arquivo JSON ou fornecer uma variável de ambiente ao SJM no lançamento. Se ambos forem fornecidos, o SJM utilizará apenas valores fornecidos pelo ambiente.
O usuário pode criar um arquivo no formato JSON e montar o volume onde o arquivo está localizado em um caminho de destino especificado no contêiner SJM.
O arquivo deve ter permissões de leitura e conter um mapa formatado em JSON. Exemplo de arquivo de variáveis definidas pelo usuário:
{ "KEY": "VALUE", "user_name": "MINION", "my_password": "PASSW0RD123", "my_URL": "https://newrelic.com/", "ETC": "ETC"}Coloque o arquivo no diretório de origem do host. O SJM espera que o nome do arquivo seja user_defined_variables.json
Exemplo de Docker :
O diretório de destino esperado é: /var/lib/newrelic/synthetics/variables/
$docker run ... -v /variables:/var/lib/newrelic/synthetics/variables:rw ...Exemplo de Podman:
No caso do SELinux, monte o volume adicionalmente com :z ou :Z. Para mais informações, consulte a documentação do Podman. O diretório de destino esperado é: /var/lib/newrelic/synthetics/variables/
$podman run ... -v /variables:/var/lib/newrelic/synthetics/variables:rw,z ...Exemplo de Kubernetes:
O usuário tem duas opções ao fornecer um arquivo ao pod SJM no Kubernetes. Eles podem:
- Passe um arquivo local.
- Forneça um PersistentVolume que inclua o
user_defined_variables.json.
Passe um arquivo local
Esta opção cria um recurso ConfigMap Kubernetes e o monta no pod SJM.
$helm install newrelic/synthetics-job-manager ... --set-file "synthetics.userDefinedVariables.userDefinedFile=[local-path]/user_defined_variables.json" ...Monte um PersistentVolume
Esta opção exige que o usuário forneça um PersistentVolume que inclua o arquivo user_defined_variables.json ou um PersistentVolumeClaim para o mesmo. Para obter mais detalhes sobre a instalação do helm chart usando um PersistentVolume, siga as instruções em armazenamento permanente de dados.
Depois que o usuário tiver preparado um PersistentVolume conforme descrito abaixo, inicie o SJM, definindo o caminho onde o arquivo user_defined_variables.json está localizado e defina quaisquer outras variáveis synthetics.persistence conforme necessário.
$helm install newrelic/synthetics-job-manger ... --set synthetics.userDefinedVariables.userDefinedPath="variables"As variáveis poderão ser passadas para seu respectivo sistema contêiner via variável de ambiente.
Exemplo de Docker :
Use a sinalização -e para configurar uma variável de ambiente chamada USER_DEFINED_VARIABLES e atribua a ela o valor de uma string de mapa formatada em JSON.
$docker run ... -e USER_DEFINED_VARIABLES='{"key":"value","name":"sjm"}' ...Exemplo de Podman:
Use a sinalização -e para configurar uma variável de ambiente chamada USER_DEFINED_VARIABLES e atribua a ela o valor de uma string de mapa formatada em JSON.
$podman run ... -e USER_DEFINED_VARIABLES='{"key":"value","name":"sjm"}' ...Exemplo de Kubernetes:
Use a sinalização --set-literal para transmitir a string formatada em JSON.
$helm install newrelic/synthetics-job-manager ... --set-literal synthetics.userDefinedVariables.userDefinedJson='{"key":"value","name":"sjm"}' ...Acessando variáveis de ambiente definidas pelo usuário a partir do script
Para fazer referência a uma variável de ambiente definida pelo usuário configurada, use o $env.USER_DEFINED_VARIABLES reservado seguido do nome de uma determinada variável com notação de ponto (por exemplo, $env.USER_DEFINED_VARIABLES.MY_VARIABLE).
Cuidado
Variáveis de ambiente definidas pelo usuário não são limpas do log. Considere usar o recurso de credenciais seguras para informações confidenciais.
Módulos de nós personalizados
Módulos de nó personalizados são fornecidos no SJM. Eles permitem criar um conjunto personalizado de módulos do Node e usá-los em monitores com script (API com script e navegador com script) para monitoramento sintético.
Configure seu diretório de módulos personalizados
Crie um diretório com um arquivo package.json seguindo as diretrizes oficiais do npm na pasta raiz. O SJM instalará qualquer dependência listada no arquivo package.json campo dependencies . Essas dependências estarão disponíveis ao executar o monitor no gerenciador de tarefas Sintético privado. Veja um exemplo disso abaixo.
Exemplo
Neste exemplo, um diretório de módulo customizado é usado com a seguinte estrutura:
/example-custom-modules-dir/ ├── counter │ ├── index.js │ └── package.json └── package.json ⇦ the only mandatory fileO package.json define dependencies como um módulo local (por exemplo, counter) e qualquer módulo hospedado (por exemplo, smallest versão 1.0.1):
{ "name": "custom-modules", "version": "1.0.0", ⇦ optional "description": "example custom modules directory", ⇦ optional "dependencies": { "smallest": "1.0.1", ⇦ hosted module "counter": "file:./counter" ⇦ local module }}Adicione seu diretório de módulos personalizados ao SJM para Docker, Podman ou Kubernetes
Para docker, lance o SJM montando o diretório em /var/lib/newrelic/synthetics/modules. Por exemplo:
$docker run ... -v /example-custom-modules-dir:/var/lib/newrelic/synthetics/modules:rw ...Para podman, inicie o SJM montando o diretório em /var/lib/newrelic/synthetics/modules. No caso do SELinux, monte o volume adicionalmente com :z ou :Z. Para mais informações, consulte a documentação do Podman. Por exemplo:
$podman run ... -v /example-custom-modules-dir:/var/lib/newrelic/synthetics/modules:rw,z ...Para Kubernetes, o diretório em /var/lib/newrelic/synthetics/modules precisa existir em um PV antes de iniciar o SJM com módulos customizados habilitados.
Dica
O modo de acesso PV deverá ser ReadWriteMany se você precisar compartilhar o armazenamento entre vários pods.
Um método é criar um pod que monte o PV apenas com a finalidade de copiar o diretório de módulos personalizados para o PV. O exemplo a seguir usa Amazon EFS com Amazon EKS:
Criar o namespace, o volume persistente e a declaração de volume persistente
Certifique-se de já ter configurado seu sistema de arquivos EFS e instalado o driver EFS CSI em seu cluster. Você também precisará do ID do sistema de arquivos EFS para os PVs
spec.csi.volumeHandle.bash$kubectl apply -f - <<EOF$apiVersion: v1$kind: Namespace$metadata:$name: newrelic$$---$kind: StorageClass$apiVersion: storage.k8s.io/v1$metadata:$name: efs-sc$provisioner: efs.csi.aws.com$$---$apiVersion: v1$kind: PersistentVolume$metadata:$name: custom-modules-pvc$spec:$capacity:$storage: 5Gi$volumeMode: Filesystem$accessModes:$- ReadWriteMany$persistentVolumeReclaimPolicy: Retain$storageClassName: efs-sc$csi:$driver: efs.csi.aws.com$volumeHandle: <your-efs-filesystem-id>$$---$apiVersion: v1$kind: PersistentVolumeClaim$metadata:$name: custom-modules-pvc$namespace: newrelic$spec:$accessModes:$- ReadWriteMany$storageClassName: efs-sc$resources:$requests:$storage: 5Gi$EOFMude para o namespace
newrelicem seu~/.kube/config.bash$kubectl config get-contexts$kubectl config set-context YOUR_CONTEXT --namespace=newrelic$kubectl config view --minify | grep namespace:Neste ponto, o PVC deve estar vinculado ao PV com modo de acesso RWX.
bash$kubectl get pv,pvcNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGEpersistentvolume/custom-modules-pvc 5Gi RWX Retain Bound newrelic/custom-modules-pvc efs-sc <unset> 4m46sNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGEpersistentvolumeclaim/custom-modules-pvc Bound custom-modules-pvc 5Gi RWX efs-sc <unset> 4m10sCrie
mount-custom-mods-podpara copiar seu diretório de módulos personalizadosbash$kubectl apply -f - <<EOF$apiVersion: v1$kind: Pod$metadata:$name: mount-custom-mods-pod$spec:$containers:$- name: mount-custom-mods-pod$image: nginx$resources:$requests:$memory: "64Mi"$cpu: "250m"$limits:$memory: "128Mi"$cpu: "500m"$volumeMounts:$- mountPath: "/var/lib/newrelic/synthetics/modules"$name: custom-modules-storage$volumes:$- name: custom-modules-storage$persistentVolumeClaim:$claimName: custom-modules-pvc$EOFNeste ponto, o
mount-custom-mods-poddeve ser criado e configurado para usar o volume.bash$kubectl describe po mount-custom-mods-pod | grep -A4 Volumes:Volumes:custom-modules-storage:Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)ClaimName: custom-modules-pvcReadOnly: falseVerifique se há algum aviso relacionado ao PV, PVC ou
mount-custom-mods-pod.bash$kubectl get events --field-selector type=Warning --sort-by='.lastTimestamp'Copie seu diretório de módulos personalizados para o PV
Não é necessário copiar
node_modulespois ele será gerado pelo SJM emnpm install.bash$cd custom-modules$rm -rf node_modules && cd ..Verifique se o
mount-custom-mods-podestá em execução.bash$kubectl get poNAME READY STATUS RESTARTS AGEmount-custom-mods-pod 1/1 Running 0 5m43sCopie para o PV.
bash$kubectl cp custom-modules newrelic/mount-custom-mods-pod:/var/lib/newrelic/synthetics/modulesVerifique se
/var/lib/newrelic/synthetics/modules/custom-modules/package.jsonexiste no PV.bash$kubectl exec -it mount-custom-mods-pod -- bashroot@mount-custom-mods-pod:/# cd /var/lib/newrelic/synthetics/modules/root@mount-custom-mods-pod:/var/lib/newrelic/synthetics/modules# ls -ltotal 4drwxr-xr-x 2 root root 6144 Jun 29 03:49 custom-modulesroot@mount-custom-mods-pod:/var/lib/newrelic/synthetics/modules# ls -l custom-modules/total 4-rw-r--r-- 1 501 staff 299 Jun 29 03:49 package.jsonlançar o SJM com recurso de módulos customizados habilitado
Configure valores para
persistence.existingClaimNameecustomNodeModules.customNodeModulesPathna linha de comando ou em um arquivo YAML durante a instalação. O valorcustomNodeModules.customNodeModulesPathdeve especificar o subcaminho no Volume Persistente onde existem seus arquivos de módulos personalizados. Por exemplo:bash$helm upgrade --install synthetics-job-manager newrelic/synthetics-job-manager -n newrelic --set global.persistence.existingClaimName=custom-modules-pvc --set global.customNodeModules.customNodeModulesPath=custom-modules --set synthetics.privateLocationKey=YOUR_PRIVATE_LOCATION_KEYRelease "synthetics-job-manager" does not exist. Installing it now.NAME: synthetics-job-managerLAST DEPLOYED: Fri Jun 28 16:53:28 2024NAMESPACE: newrelicSTATUS: deployedREVISION: 1TEST SUITE: NoneO diretório
custom-modulesagora deve conter os pacotes instalados emnode_modules.bash$kubectl exec -it mount-custom-mods-pod -- bashroot@mount-custom-mods-pod:/# cd /var/lib/newrelic/synthetics/modules/root@mount-custom-mods-pod:/var/lib/newrelic/synthetics/modules# ls -l custom-modules/total 16-rw-r--r-- 1 root root 836 Jun 29 03:51 READMEdrwxr-xr-x 18 root root 6144 Jun 29 03:51 node_modules-rw-r--r-- 1 501 staff 299 Jun 29 03:49 package.json-rw-r--r-- 1 root root 190 Jun 29 03:51 package.json.shasumSe os módulos de nós customizados não forem detectados, ajuste as permissões no diretório
custom-modulese no arquivopackage.json.bash$kubectl exec -it mount-custom-mods-pod -- bashroot@mount-custom-mods-pod:/# cd /var/lib/newrelic/synthetics/modules/root@mount-custom-mods-pod:/var/lib/newrelic/synthetics/modules# chmod -R 777 custom-modulesroot@mount-custom-mods-pod:/var/lib/newrelic/synthetics/modules# chown -R 2000:2000 custom-modules
Para verificar se os módulos foram instalados corretamente ou se ocorreu algum erro, procure as seguintes linhas no synthetics-job-manager contêiner ou log pod :
2024-06-29 03:51:28,407{UTC} [main] INFO c.n.s.j.p.options.CustomModules - Detected mounted path for custom node modules2024-06-29 03:51:28,408{UTC} [main] INFO c.n.s.j.p.options.CustomModules - Validating permission for custom node modules package.json file2024-06-29 03:51:28,409{UTC} [main] INFO c.n.s.j.p.options.CustomModules - Installing custom node modules...2024-06-29 03:51:44,670{UTC} [main] INFO c.n.s.j.p.options.CustomModules - Custom node modules installed successfully.Agora você pode adicionar "require('smallest');" ao script de monitor que você envia para esta localização privada.
Mudar package.json
Além dos módulos locais e hospedados, você também pode utilizar módulos Node.js. Para atualizar os módulos customizados usados pelo seu SJM, faça alterações no arquivo package.json e reinicie o SJM. Durante o processo de reinicialização, o SJM reconhecerá a alteração na configuração e executará automaticamente as operações de limpeza e reinstalação para garantir que os módulos atualizados sejam aplicados.
Cuidado
Módulos locais: embora seu package.json possa incluir qualquer módulo local, esses módulos devem residir na árvore no diretório do módulo personalizado. Se armazenado fora da árvore, o processo de inicialização falhará e você verá uma mensagem de erro no log docker após iniciar o SJM.
Armazenamento permanente de dados
O usuário pode querer usar o armazenamento permanente de dados para fornecer o arquivo user_defined_variables.json ou oferecer suporte a módulos de nós personalizados.
Para definir o armazenamento permanente de dados no Docker:
Crie um diretório no host onde você está iniciando o Job Manager. Este é o seu diretório de origem.
inicie o Job Manager, montando o diretório de origem no diretório de destino
/var/lib/newrelic/synthetics.Exemplo:
bash$docker run ... -v /sjm-volume:/var/lib/newrelic/synthetics:rw ...
Para definir o armazenamento permanente de dados no Podman:
Crie um diretório no host onde você está iniciando o Job Manager. Este é o seu diretório de origem.
inicie o Job Manager, montando o diretório de origem no diretório de destino
/var/lib/newrelic/synthetics.Exemplo:
bash$podman run ... -v /sjm-volume:/var/lib/newrelic/synthetics:rw,z ...
Kubernetes
Para definir o armazenamento permanente de dados no Kubernetes, o usuário tem duas opções:
Forneça um PersistentVolumeClaim (PVC) existente para um PersistentVolume (PV) existente, definindo o valor de configuração
synthetics.persistence.existingClaimName. Exemplo:bash$helm install ... --set synthetics.persistence.existingClaimName=sjm-claim ...Forneça um nome PersistentVolume (PV) existente, definindo o valor de configuração
synthetics.persistence.existingVolumeName. Helm irá gerar um PVC para o usuário. O usuário também pode definir opcionalmente os seguintes valores:
synthetics.persistence.storageClass: A classe de armazenamento do PV existente. Se não for fornecido, o Kubernetes usará a classe de armazenamento padrão.synthetics.persistence.size: O tamanho da reivindicação. Se não for definido, o padrão atualmente é 2Gi.bash$helm install ... --set synthetics.persistence.existingVolumeName=sjm-volume --set synthetics.persistence.storageClass=standard ...
Considerações de dimensionamento
Para garantir que sua localização privada seja executada com eficiência, você deve provisionar recursos de CPU suficientes em seu host para lidar com sua workload de monitoramento. Muitos fatores influenciam o dimensionamento, mas você pode estimar rapidamente suas necessidades. Você precisará de 1 núcleo de CPU para cada monitor pesado (por exemplo, navegador simples, navegador com script ou monitor de API com script). Abaixo estão duas fórmulas para ajudar você a calcular o número de núcleos necessários, seja para diagnosticar uma configuração atual ou planejar uma futura.
Fórmula 1: Diagnosticando um Local Existente
Se sua localização privada atual estiver com dificuldades para acompanhar e você suspeitar que há trabalhos na fila, use esta fórmula para descobrir quantos núcleos você realmente precisa. Baseia-se no desempenho observável do seu sistema.
$$ C_{est} = (R_{proc} + R_{growth}) \cdot D_{avg,m} $$
C\_\{est} = Núcleos de CPU Estimados.
R\_\{proc} = A taxa de trabalhos pesados sendo processados por minuto.
R\_\{growth} = A taxa em que sua fila
jobManagerHeavyweightJobsestá crescendo por minuto.D\_\{avg,m} = A duração média de trabalhos pesados em minutos.
Esta fórmula calcula a sua taxa real de chegada de tarefas, somando as tarefas que o seu sistema está processando às tarefas que estão se acumulando na fila. Multiplicar essa carga total pela duração média da tarefa indica exatamente quantos núcleos são necessários para concluir todo o trabalho sem enfileiramento.
Fórmula 2: Previsão de um local novo ou futuro
Se você estiver configurando uma nova localização privada ou planejando adicionar mais monitores, use esta fórmula para prever suas necessidades com antecedência.
$$ C_{est} = N_{mon} \cdot D_{avg,m} \cdot \frac{1}P_{avg,m} $$
C\_\{est} = Núcleos de CPU Estimados.
N\_\{mon} = O número total de monitores pesados que você planeja executar.
D\_\{avg,m} = A duração média de uma tarefa pesada em minutos.
P\_\{avg,m} = O período médio para monitores pesados em minutos (por exemplo, um monitor que é executado a cada 5 minutos tem P\_\{avg,m} = 5).
Este cálculo parte dos princípios básicos para determinar a sua workload esperada: quantos monitores você tem, com que frequência eles são executados e quanto tempo levam para serem concluídos.
Fatores importantes de dimensionamento
Ao usar essas fórmulas, lembre-se de levar em conta estes fatores:
Duração do job (D\_\{avg,m}): Sua média deve incluir jobs que excedem o tempo limite (geralmente 3 minutos), pois eles ocupam um núcleo durante toda a sua duração.
Falhas e novas tentativas de trabalho: quando um monitor falha, ele é automaticamente repetido. Essas tentativas são trabalhos adicionais que aumentam a carga total. Um monitor que falha consistentemente e tenta novamente multiplica efetivamente seu período, impactando significativamente as taxas de transferência.
Escalonamento: além de adicionar mais núcleos a um host (escalonamento vertical), você pode implantar gerenciadores de tarefas adicionais da Sintéticos com a mesma chave de localização privada para balancear a carga de tarefas em vários ambientes (escalonamento horizontal).
É importante observar que um único Sintéticos Job Manager (SJM) tem um limite de taxas de transferência de aproximadamente 15 trabalhos pesados por minuto. Isso se deve a uma estratégia de segmentação interna que favorece a competição eficiente de trabalhos entre vários SJMs em relação ao número bruto de trabalhos processados por SJM. Se seus cálculos indicarem a necessidade de taxas de transferência mais altas, você deverá expandir implantando SJMs adicionais. Você pode verificar se sua fila de tarefas está crescendo para determinar se mais SJMs são necessários.
Adicionar mais SJMs com a mesma chave de localização privada oferece diversas vantagens:
Balanceamento de carga: Os trabalhos para localização privada são distribuídos em todos os SJMs disponíveis.
Proteção contra failover: se uma instância do SJM ficar inativa, outras poderão continuar processando trabalhos.
Taxas totais de transferência maiores: as taxas totais de transferência para sua localização privada se tornam a soma das taxas de transferência de cada SJM (p. ex., dois SJMs fornecem até 30 trabalhos/minuto).
Consulta NRQL para diagnóstico
Você pode executar essas consultas no criador de consultas para obter as entradas para a fórmula de diagnóstico. Certifique-se de definir o intervalo de tempo para um período longo o suficiente para obter uma média estável.
1. Encontre a taxa de jobs processados por minuto (R\_\{proc}): Esta consulta conta o número de jobs não-ping (pesados) concluídos no último dia e mostra a taxa média por minuto.
FROM SyntheticCheckSELECT rate(uniqueCount(id), 1 minute) AS 'job rate per minute'WHERE location = 'YOUR_PRIVATE_LOCATION' AND type != 'SIMPLE'SINCE 1 day ago2. Encontre a taxa de crescimento da fila por minuto (R\_\{growth}): Esta consulta calcula o crescimento médio por minuto da fila
jobManagerHeavyweightJobsem um gráfico de série temporal. Uma linha acima de zero indica que a fila está aumentando, enquanto uma linha abaixo de zero significa que ela está diminuindo.FROM SyntheticsPrivateLocationStatusSELECT derivative(jobManagerHeavyweightJobs, 1 minute) AS 'queue growth rate per minute'WHERE name = 'YOUR_PRIVATE_LOCATION'TIMESERIES SINCE 1 day agoDica
Certifique-se de selecionar a conta onde existe a localização privada. É melhor visualizar essa consulta como uma série temporal porque a função derivada pode variar muito. O objetivo é obter uma estimativa da taxa de crescimento da fila por minuto. Play diferentes intervalos de tempo para ver o que funciona melhor.
3. Encontre o número total de monitores pesados (N\_\{mon}): Esta consulta encontra a contagem única de monitores pesados.
FROM SyntheticCheckSELECT uniqueCount(monitorId) AS 'monitor count'WHERE location = 'YOUR_PRIVATE_LOCATION' AND type != 'SIMPLE'SINCE 1 day ago4. Encontre a duração média do job em minutos (D\_\{avg,m}): Esta consulta encontra a duração média de execução de jobs não-ping concluídos e converte o resultado de milissegundos para minutos.
executionDurationrepresenta o tempo que o job levou para executar no host.FROM SyntheticCheckSELECT average(executionDuration)/60e3 AS 'avg job duration (m)'WHERE location = 'YOUR_PRIVATE_LOCATION' AND type != 'SIMPLE'SINCE 1 day ago5. Encontre o período médio do monitor heavyweight (P\_\{avg,m}): Se a fila de
jobManagerHeavyweightJobsda localização privada estiver aumentando, não é exato calcular o período médio do monitor a partir dos resultados existentes. Isso precisará ser estimado a partir da lista de monitores na página Monitores sintéticos. Certifique-se de selecionar a conta New Relic correta e pode ser necessário filtrar porprivateLocation.Dica
Monitores Sintéticos podem existir em múltiplas subcontas. Se você tiver mais subcontas do que as que podem ser selecionadas no criador de consulta, escolha as contas com mais monitores.
Nota sobre monitores de ping e a fila
pingJobsOs monitores de ping são diferentes. São trabalhos leves que não consomem um núcleo de CPU completo cada. Em vez disso, eles usam uma fila separada (
pingJobs) e são executados em um pool de threads de trabalho.Embora consumam menos recursos, um alto volume de tarefas de ping, especialmente aquelas com falhas, ainda pode causar problemas de desempenho. Tenha estes pontos em mente:
Modelo de recursos: os trabalhos de ping utilizam threads de trabalho, não núcleos de CPU dedicados. O cálculo de núcleo por trabalho não se aplica a eles.
Tempo limite e nova tentativa: uma tarefa de ping com falha pode ocupar um thread de trabalho por até 60 segundos. Primeiro, ele tenta uma solicitação HTTP HEAD (tempo limite de 30 segundos). Se isso falhar, ele tenta imediatamente com uma solicitação HTTP GET (outro tempo limite de 30 segundos).
Dimensionamento: embora a fórmula de dimensionamento seja diferente, os mesmos princípios se aplicam. Para lidar com um grande volume de trabalhos de ping e evitar que a fila
pingJobscresça, talvez seja necessário aumentar e/ou diminuir a escala. Aumentar a escala significa aumentar os recursos de CPU e memória por host ou namespace. Escalar significa adicionar mais instâncias do tempo de execução do ping. Isso pode ser feito implantando mais gerenciadores de tarefas em mais hosts, em mais namespaces ou até mesmo dentro do mesmo namespace. Como alternativa, oping-runtimeno Kubernetes permite que você defina um número maior de réplicas por implantação.
Cada tempo de execução usado pelo gerenciador de tarefas Kubernetes e do OpenShift Sintético pode ser dimensionado independentemente definindo valores no gráfico do helm. O node-api-runtime e o node-browser-runtime são dimensionados independentemente usando uma combinação das configurações parallelism e completions.
A configuração
parallelismcontrola quantos pods de um determinado runtime são executados simultaneamente.A configuração
completionscontrola quantos pods devem ser concluídos antes que oCronJobinicie outro Job Kubernetes para esse runtime.Melhores práticas para o dimensionamento da sua implantação
Muitas vezes não é possível calcular com precisão os valores de paralelismo e conclusões necessários porque a duração média vista no New Relic pode não ser precisa, especialmente se o local privado existente não estiver funcionando bem. Siga esta abordagem prática para ajustar o paralelismo e as conclusões. As equações abaixo podem ser usadas para obter valores aproximados como ponto de partida.
1. Estimar conclusões e paralelismo
Faça o possível para estimar a duração média de execução e o número de jobs por 5 minutos. Isso fornece um ponto de partida aproximado para a próxima etapa, que envolverá tentativa e erro para ajustar os valores de paralelismo e conclusões em um cluster em funcionamento. Certifique-se de escalá-los proporcionalmente, por exemplo, indo dos padrões de 1 e 6 para 10 e 60.
Conclusões Estimadas: Isso determina quanto tempo sua carga de jobs de 5 minutos levará para ser concluída.
-- Get average execution duration in minutesFROM SyntheticCheckSELECT average(executionDuration / 60e3) AS 'Avg Duration (min)'WHERE type != 'SIMPLE' AND location = 'YOUR_PRIVATE_LOCATION'SINCE 1 hour ago$$ Completions = \frac{5}D_{avg,m} $$
Onde D\_\{avg,m} é a sua duração média de execução do job em minutos.
Paralelismo Estimado: Isso determina quantos workers (pods) você precisa executar simultaneamente para lidar com sua carga de trabalho de 5 minutos.
-- Get jobs per 5 minutesFROM SyntheticCheckSELECT rate(uniqueCount(id), 5 minutes) AS 'Number of monitor jobs per 5 minutes'WHERE type != 'SIMPLE' AND location = 'YOUR_PRIVATE_LOCATION'SINCE 1 hour ago$$ P_{est} = \frac{N_m}{Completions} $$
Onde N_m é o seu número de jobs por 5 minutos. Este valor P\_\{est} é o seu paralelismo estimado.
2. Execute um deploy do Helm
Execute um deploy do Helm com valores estimados de paralelismo e conclusões, e sua melhor estimativa para
ping-runtime.replicaCountconsiderando o número de núcleos de CPU por nó e o número de monitores de ping que precisam ser executados por minuto.3. Monitore o crescimento da fila
Com os monitores sintéticos configurados para enviar tarefas para o local privado, verifique o crescimento da fila em um gráfico de linha de série temporal para
pingJobsejobManagerHeavyweightJobs.Se a fila
pingJobstiver uma inclinação positiva, aumenteping-runtime.replicaCounte reimplante.Se a fila
jobManagerHeavyweightJobstiver uma inclinação positiva, aumenteparallelismecompletionsproporcionalmente até que a fila pare de crescer (inclinação negativa).Uma inclinação negativa indica que o gerenciador de jobs tem paralelismo suficiente para lidar com a demanda do job. Eventualmente atingirá zero com uma inclinação negativa.
FROM SyntheticsPrivateLocationStatusSELECT average(jobManagerHeavyweightJobs) AS 'Heavyweight Queue Growth', average(pingJobs) AS 'Ping Queue Growth'WHERE name = 'YOUR_PRIVATE_LOCATION'SINCE 1 day ago TIMESERIES4. Ajuste com base no estado de execução do pod
Com a fila diminuindo ou zerada, verifique se há pods
node-api-runtimeenode-browser-runtimeque estejam em um estado "running" há mais de 10 minutos. Isso indica que o paralelismo está definido muito alto e há mais pods do que o necessário.Para evitar o desperdício desnecessário de recursos, diminua
parallelismecompletionspara reduzir a idade de cada pod de runtime "em execução". Se o objetivo for uma idade de job do Kubernetes de 5 minutos, os pods de runtime devem estar em estado de execução por menos de 5 minutos, o que significa que o pod foi criado, recebeu rapidamente um job para executar e foi concluído.5. Escale horizontalmente se necessário
Se a fila não estiver diminuindo, mas houver muitos pods em um estado "running" por mais de 10 minutos, é provável que o gerenciador de jobs esteja atingindo seu gargalo de desempenho. A próxima etapa é reduzir o paralelismo e escalar horizontalmente com uma ou mais implantações adicionais.
Por exemplo, com
parallelism: 100,completions: 600a fila ainda está crescendo, mas há muitos pods em um estado "running" há mais de 10 minutos, e a idade do Job do Kubernetes é de 20 minutos ... definaparallelism: 50,completions: 200e escale horizontalmente (out) adicionando 2 deployments adicionais. Isso resulta em um total de 150 pods paralelos e deve reduzir a duração do job do K8s para menos de 20 minutos, reduzindo também o número de pods "running" de longa duração. Busque uma idade de job do K8s de 5 a 10 minutos.Para mais informações sobre como adicionar implantações, consulte Escalonamento horizontal com múltiplas implantações do SJM.
Dica
Você pode usar a seguinte consulta para ajudar a determinar se precisa escalar horizontalmente.
Observação: Monitores podem existir em várias subcontas.
-- monitors per minute per SJMFROM SyntheticCheck SELECTround(rate(uniqueCount(id), 1 minute)/uniqueCount(minionId),0.1) AS 'heavy jobs per minute per SJM',uniqueCount(minionId) AS 'number of SJMs (namespaces)',round(rate(uniqueCount(id), 1 minute),0.1) AS 'heavy jobs per minute total'WHERE minionContainerSystem = 'KUBERNETES' AND minionDeploymentMode = 'private' AND location = 'YOUR_PRIVATE_LOCATION' AND type != 'SIMPLE' FACET location SINCE 1 hour ago TIMESERIESDica
Reduzir o número de ciclos de jobs do K8s também pode melhorar o desempenho. À medida que cada ciclo atinge o número definido de conclusões, há cada vez menos pods "em execução" para assumir novos jobs do Synthetics. Por exemplo, com completions definido como 200 e parallelism definido como 50, temos inicialmente 50 pods em execução, mas isso começa a diminuir à medida que passamos de 150 completions. Com 199 conclusões, resta apenas 1 pod em execução.
Definir um valor maior para completions não é uma má ideia, mas pode levar a eventos de aviso no K8s sobre
TooManyMissedTimespara o cronjob.Expandindo com múltiplas implantações SJM
Para escalar além das taxas de transferência de 15 jobs/minuto de um único SJM, você deve instalar várias versões separadas do SJM Helm.
Importante
Não use réplicas para escalar o pod do job manager. A arquitetura SJM requer uma relação 1:1 entre um pod de runtime e seu pod SJM pai. Se os pods de runtime enviarem resultados de volta para a réplica do SJM incorreta (por exemplo, por meio de um serviço do Kubernetes), esses resultados serão perdidos. No entanto, ping-runtime.replicaCount pode ser usado.
A estratégia correta é implantar múltiplos SJMs instância, cada um como sua própria versão Helm. Cada SJM competirá por trabalhos da mesma localização privada, fornecendo balanceamento de carga, proteção contra failover e um aumento nas taxas de transferência totais de trabalho.
Estratégia de escalonamento horizontal
Se você precisar escalar horizontalmente, pode simplificar a manutenção tratando cada implantação do SJM como uma unidade de capacidade fixa.
Definir Paralelismo: Para cada SJM, defina
parallelismpara o mesmo máximo que um único SJM pode suportar sem criar muitos pods de runtime "em execução" de longa duração. Isso maximiza o throughput potencial de cada SJM sem desperdiçar recursos.Definir Conclusões: Para cada SJM, defina
completionspara o mesmo valor fixo também. Ajuste conforme necessário para atingir uma idade de job do Kubernetes de 5 minutos por runtime, ou seja, node-browser-runtime e node-api-runtime.Instalar Releases: Instale quantas releases do Helm separadas forem necessárias para lidar com sua demanda total de jobs, ou seja, zerar a fila ou obter uma inclinação negativa no gráfico de linha.
Monitore e adicione: Monitore a fila de tarefas da localização privada. Se começar a aumentar (inclinação positiva), basta instalar outra release do Helm (por exemplo,
sjm-delta) usando a mesma configuração fixa.Ao fixar o paralelismo e as conclusões em valores estáticos, aumentar ou diminuir a capacidade torna-se um processo mais simples de adicionar ou remover releases do Helm. Isso ajuda a evitar o desperdício de recursos do cluster com um valor de paralelismo superior ao que o SJM pode utilizar efetivamente.
Exemplo de instalação
Ao instalar várias versões do SJM, você deve fornecer um nome exclusivo para cada versão. Todas as instâncias devem ser configuradas com a mesma chave de localização privada.
É altamente recomendável definir o
fullnameOverridepara criar nomes de recursos mais curtos e fáceis de gerenciar. Por exemplo, para instalar dois SJMs chamadossjm-alphaesjm-betano namespacenewrelic(ambos usando o mesmovalues.yamlcom seu paralelismo e autocompletares fixos):bash$# Install the first SJM deployment$helm upgrade --install sjm-alpha newrelic/synthetics-job-manager \>-n newrelic \>-f values.yaml \>--set fullnameOverride=sjm-alpha \>--set ping-runtime.fullnameOverride=sjm-alpha-ping \>--set node-api-runtime.fullnameOverride=sjm-alpha-api \>--set node-browser-runtime.fullnameOverride=sjm-alpha-browserbash$# Install the second SJM deployment to add capacity$helm upgrade --install sjm-beta newrelic/synthetics-job-manager \>-n newrelic \>-f values.yaml \>--set fullnameOverride=sjm-beta \>--set ping-runtime.fullnameOverride=sjm-beta-ping \>--set node-api-runtime.fullnameOverride=sjm-beta-api \>--set node-browser-runtime.fullnameOverride=sjm-beta-browserVocê pode continuar este padrão (
sjm-charlie,sjm-delta, etc.) para quantos SJMs forem necessários para impedir que a fila de trabalho cresça.