Quando seu sistema de "Infraestrutura como código" cresce além do exemplo "Hello World" sem planejamento, o código tende a ficar desestruturado. Configurações não planejadas são fixadas no código. A capacidade de manutenção cai drasticamente.
Use este documento e o exemplo de código que acompanha esse documento para estruturar suas implantações com mais eficiência e em escala.
Além disso, faça com que todas as equipes apliquem a convenção de nomenclatura e as práticas recomendadas internas. Este documento é destinado a um público tecnicamente avançado e pressupõe que você tenha um conhecimento básico de Python, infraestrutura do Google Cloud, Deployment Manager e, geralmente, infraestrutura como código.
Antes de começar
- Para usar os exemplos de linha de comando deste guia, instale a ferramenta de linha de comando "gcloud".
- Para usar os exemplos de API deste guia, configure o acesso de API.
Vários ambientes com uma única base de código
Em grandes implantações com mais de uma dúzia de recursos, as práticas recomendadas padrão exigem o uso de uma quantidade significativa de propriedades externas (parâmetros de configuração). Assim você evita a fixação de strings e lógica no código de modelos genéricos. Muitas dessas propriedades são parcialmente duplicadas em serviços e ambientes semelhantes (como os de desenvolvimento, testes ou produção). Por exemplo, todos os serviços padrão estão sendo executados em uma pilha LAMP semelhante. Seguir estas práticas recomendadas gera um grande conjunto de propriedades de configuração, muitas delas duplicadas, que pode ser difícil de manter e aumenta a chance de erro humano.
A tabela a seguir apresenta um exemplo de código para demonstrar as diferenças entre uma configuração hierárquica e uma configuração única por implantação. A tabela destaca uma duplicação comum na configuração única. Ao usar a configuração hierárquica, a tabela mostra como mover seções repetidas para um nível mais alto na hierarquia para evitar repetição e diminuir as chances de erro humano.
Modelo | Configuração hierárquica sem redundância | Configuração única com redundância |
---|---|---|
|
|
N/A |
|
|
|
|
|
|
|
|
|
Para lidar melhor com uma base de código grande, use um layout hierárquico estruturado e combine as propriedades de configuração em cascata. Para fazer isso, use vários arquivos de configuração, em vez de apenas um. Além disso, você trabalhará com funções auxiliares e compartilhará parte da base de código com sua organização.
O exemplo de código que acompanha este documento,
Organization_with_departments
,
contém uma base de código com estrutura predefinida que pode ser personalizada, um script auxiliar
para combinar configurações, funções auxiliares para nomenclatura e um conjunto completo de
configurações de exemplo. É possível encontrar este exemplo de trabalho no
repositório do GitHub de amostras do Deployment Manager.
Estruturar e colocar seu código em cascata de forma hierárquica oferece vários benefícios:
- Ao dividir a configuração em vários arquivos, você melhora a estrutura e a legibilidade das propriedades, além de evitar duplicá-las.
- A combinação hierárquica é feita de modo a colocar os valores em cascata de forma lógica, criando arquivos de configuração de nível superior que podem ser reutilizados em outros projetos ou componentes.
- Cada propriedade é definida apenas uma vez (exceto as substituições), evitando a necessidade de lidar com a atribuição de namespace em nomes de propriedades.
- Seus modelos não precisam distinguir o ambiente, já que a configuração adequada é carregada com base nas variáveis apropriadas.
Como estruturar sua base de código hierarquicamente
Uma implantação do Deployment Manager contém um arquivo de configuração YAML ou de esquema e vários arquivos Python. Juntos, eles formam a base de código de uma implantação. Os arquivos Python podem ter várias finalidades. É possível usá-los como modelos de implantação, arquivos de código geral (classes auxiliares) ou como arquivos de código que armazenam propriedades de configuração.
Para estruturar a base de código hierarquicamente, alguns arquivos Python são usados como arquivos de configuração no lugar do arquivo de configuração padrão. Essa abordagem é mais flexível do que vincular a implantação a um único arquivo YAML.
Como tratar a infraestrutura como código real
É importante seguir o princípio Não se repita (DRY, na sigla em inglês) para manter o código limpo. Defina tudo apenas uma vez. Essa abordagem torna a base de código mais limpa, mais fácil de revisar, de validar e de manter. Quando uma propriedade precisa ser modificada em apenas um lugar, o risco de erro humano diminui.
Use estas diretrizes para estruturar suas configurações seguindo o princípio DRY e manter uma base de código mais leve com arquivos de configuração menores e duplicação mínima.
Organizações, departamentos, ambientes e módulos
Organizações, departamentos, ambientes e módulos são os princípios fundamentais para estruturar sua base de código de forma limpa e hierárquica. Eles são opcionais e extensíveis. Veja em hierarquia de configuração um diagrama da hierarquia da base de código de exemplo, que segue esses princípios.
No diagrama a seguir, um módulo é implantado em um ambiente. A combinação de configurações seleciona os arquivos de configuração adequados em cada nível de acordo com o contexto de uso. Ela também define automaticamente o sistema e o departamento.
Na lista a seguir, os números representam a ordem de substituição:
Propriedades de organização
O nível mais alto da sua estrutura. Nesse nível, é possível armazenar propriedades de configuração, como
organization_name
,organization_abbreviation
, que você usa na convenção de nomenclatura e funções auxiliares que quer compartilhar e aplicar em todas as equipes.Propriedades de departamento
Organizações contêm departamentos, caso você tenha departamentos na estrutura. No arquivo de configuração de cada departamento, compartilhe propriedades que não são usadas por outros departamentos, como
department_name
oucost_center
.Propriedades de sistema (projeto)
Cada departamento contém sistemas. Um sistema representa uma pilha de software bem definida, como uma plataforma de comércio eletrônico. Não é um projeto do Google Cloud, e sim um ecossistema de serviços em funcionamento.
No nível do sistema, sua equipe tem muito mais autonomia do que nos níveis acima. Aqui, você pode definir funções auxiliares (como
project_name_generator()
,instance_name_generator()
ouinstance_label_generator()
) para os parâmetros de toda a equipe e de todo o sistema (comosystem_name
,default_instance_size
ounaming_prefix
).Propriedades de ambiente
Seu sistema provavelmente tem vários ambientes, como
Dev
,Test
ouProd
e, opcionalmente,QA
eStaging
, todos bem semelhantes entre si. O ideal é que eles usem a mesma base de código e apenas as configurações sejam diferentes. No nível do ambiente, é possível substituir propriedades comodefault_instance_size
nas configurações deProd
eQA
.Propriedades de módulo
Caso seu sistema seja grande, divida-o em vários módulos em vez de mantê-lo como um grande bloco monolítico. É possível, por exemplo, transferir a base de rede e de segurança para blocos separados, assim como as camadas de back-end, front-end e banco de dados. Os módulos são modelos desenvolvidos por terceiros em que você adiciona apenas a configuração adequada. Defina no nível do módulo as propriedades relevantes apenas para módulos específicos, incluindo as propriedades que devem substituir aquelas herdadas do nível do sistema. Os níveis de ambiente e módulo são divisões paralelas de um sistema, mas os módulos vêm depois dos ambientes no processo de combinação.
Propriedades de módulo específicas para um ambiente
Algumas das suas propriedades de módulo também podem variar de acordo com o ambiente, como o tamanho das instâncias, imagens, endpoints. Propriedades de módulo específicas para um ambiente são o nível mais específico e representam o último ponto na combinação em cascata para substituir valores definidos anteriormente.
Classe auxiliar para combinar configurações
A classe auxiliar config_merger
automaticamente carrega os arquivos de configuração adequados e combina o conteúdo deles em um único dicionário.
Para usar a classe config_merger
, você precisa fornecer as seguintes informações:
- nome do módulo
- contexto global, incluindo o nome do ambiente
Chamar a função estática ConfigContext
retorna o dicionário de configuração combinado.
O código a seguir mostra como usar essa classe:
- O
module = "frontend"
especifica o contexto em que os arquivos de propriedade são carregados. - O ambiente é escolhido automaticamente com base em
context.properties["envName"]
. A configuração global.
cc = config_merger.ConfigContext(context.properties, module) print cc.configs['ServiceName']
Nos bastidores, essa classe auxiliar precisa se alinhar com as estruturas de configuração, carregar todos os níveis na ordem correta e substituir os valores de configuração adequados. Para alterar os níveis ou a ordem de substituição, modifique a classe de combinação de configurações.
Normalmente, não será necessário modificar a classe no uso cotidiano. Você geralmente edita os modelos e os arquivos de configuração adequados e, em seguida, usa o dicionário resultante com todas as configurações.
A base de código de exemplo inclui três arquivos de configuração fixados no código:
org_config.py
department_config.py
system_config.py
Crie os arquivos de configuração de organização e de departamento como links simbólicos durante a inicialização do repositório. Esses arquivos podem ficar em outro repositório de código, já que na prática não fazem parte da base de código de uma equipe de projeto, mas são compartilhados com toda a organização e todos os departamentos.
A combinação de configurações também procura arquivos que correspondam aos outros níveis da estrutura:
envs/[environment name].py
[environment name]/[module name].py
modules/[module name].py
Arquivo de configuração
O Deployment Manager usa um único arquivo de configuração para cada implantação específica. Ele não pode ser compartilhado entre implantações.
Quando você usa a classe config-merger
, as propriedades de configuração são completamente desanexadas deste arquivo de configuração porque você não a está usando.
Em vez de usá-lo, você usa uma coleção de arquivos Python, algo que oferece muito mais flexibilidade em uma implantação. Também é possível compartilhar esses arquivos entre implantações.
Qualquer arquivo Python pode conter variáveis, o que permite armazenar sua configuração de maneira estruturada e distribuída. A melhor abordagem é usar dicionários com uma estrutura predefinida. A fusão de configurações procura um dicionário chamado configs
em todos os arquivos na cadeia de mesclagem. Os configs
separados são combinados em um só.
A combinação de configurações substitui as propriedades com o mesmo caminho e nome que aparecem nos dicionários várias vezes. Em alguns casos, esse comportamento é útil, como ao substituir um valor padrão por um valor específico para o contexto. No entanto, existem muitos outros casos em que é preferível evitar a substituição da propriedade. Para fazer isso, adicione um namespace separado para tornar a propriedade exclusiva. Ao adicionar um namespace no exemplo a seguir, você cria um nível adicional no dicionário de configuração, o que gera um subdicionário.
config = { 'Zip_code': '1234' 'Count': '3' 'project_module': { 'admin': 'Joe', } } config = { 'Zip_code': '5555' 'Count': '5' 'project_module_prod': { 'admin': 'Steve', } }
Classes auxiliares e convenções de nomenclatura
As convenções de nomenclatura são a melhor maneira de manter sua infraestrutura do
Deployment Manager sob controle. Evite usar nomes vagos ou genéricos,
como my project
ou test instance
.
O exemplo a seguir apresenta uma convenção de nomenclatura para as instâncias de toda a organização:
def getInstanceName(self, name): return '-'.join(self.configs['Org_level_configs']['Org_Short_Name'], self.configs['Department_level_configs']['Department_Short_Name'], self.configs['System_short_name'], name, self.configs["envName"])
Fornecer uma função auxiliar facilita a definição do nome de cada instância de acordo com a convenção predefinida. Isso também facilita a revisão do código, já que nenhum nome de instância é gerado de qualquer outra forma. A função seleciona automaticamente os nomes de configurações dos níveis superiores. Essa abordagem ajuda a evitar entradas desnecessárias.
É possível aplicar essas convenções de nomenclatura na maioria dos recursos do Google Cloud e para rótulos. Funções mais complexas podem até mesmo gerar um conjunto de rótulos padrão.
Estrutura de pastas da base de código de exemplo
A estrutura de pastas da base de código de exemplo é flexível e pode ser personalizada. No entanto, ela foi parcialmente fixada no código da combinação de configurações e do arquivo de esquema do Deployment Manager. Isso significa que, ao fazer uma modificação, você precisará refleti-la nos arquivos da combinação de configurações e nos arquivos de esquema.
├── global │ ├── configs │ └── helper └── systems └── my_ecom_system ├── configs │ ├── dev │ ├── envs │ ├── modules │ ├── prod │ └── test ├── helper └── templates
A pasta global contém arquivos compartilhados com diferentes equipes de projeto. Para simplificar, a pasta de configuração contém a configuração da organização e os arquivos de configuração de todos os departamentos. Neste exemplo, não há uma classe auxiliar separada para departamentos. É possível adicionar qualquer classe auxiliar no nível da organização ou do sistema.
A pasta global pode ser armazenada em um repositório Git separado. É possível fazer referência aos arquivos a partir de sistemas individuais. Também é possível usar links simbólicos, mas eles podem criar confusão ou falhas em determinados sistemas operacionais.
├── configs │ ├── Department_Data_config.py │ ├── Department_Finance_config.py │ ├── Department_RandD_config.py │ └── org_config.py └── helper ├── config_merger.py └── naming_helper.py
A pasta de sistemas contém um ou mais sistemas diferentes. Os sistemas são separados uns dos outros e não compartilham configurações.
├── configs │ ├── dev │ ├── envs │ ├── modules │ ├── prod │ └── test ├── helper └── templates
A pasta de configuração contém todos os arquivos de configuração exclusivos de um sistema, além de fazer referência às configurações globais por links simbólicos.
├── department_config.py -> ../../../global/configs/Department_Data_config.py ├── org_config.py -> ../../../global/configs/org_config.py ├── system_config.py ├── dev │ ├── frontend.py │ └── project.py ├── prod │ ├── frontend.py │ └── project.py ├── test │ ├── frontend.py │ └── project.py ├── envs │ ├── dev.py │ ├── prod.py │ └── test.py └── modules ├── frontend.py └── project.py Org_config.py: config = { 'Org_level_configs': { 'Org_Name': 'Sample Inc.', 'Org_Short_Name': 'sampl', 'HQ_Address': { 'City': 'London', 'Country': 'UK' } } }
Adicione na pasta da classe auxiliar outras classes auxiliares e faça referência às classes globais.
├── config_merger.py -> ../../../global/helper/config_merger.py └── naming_helper.py -> ../../../global/helper/naming_helper.py
Na pasta de modelos, armazene ou faça referência aos modelos do Deployment Manager. Links simbólicos também funcionam aqui.
├── project_creation -> ../../../../../../examples/v2/project_creation └── simple_frontend.py
Como usar a base de código de exemplo
A melhor maneira de começar a aplicar a prática hierárquica na base da sua infraestrutura como código é clonar a base de código de exemplo. Em seguida, copie o conteúdo da pasta hierarchical_configuration.
Confira o repositório de exemplo.
git clone https://github.com/GoogleCloudPlatform/deploymentmanager-samples.git cd deploymentmanager-samples/community/hierarchical_configuration/Organization_with_departments/systems/my_ecom_system gcloud config set deployment_manager/glob_imports True
Use os seguintes links simbólicos para fazer referência aos arquivos globais e configurar o sistema no contexto local.
ln -sf ../../../global/helper/config_merger.py helper/config_merger.py ln -sf ../../../global/helper/naming_helper.py helper/naming_helper.py ln -sf ../../../global/configs/org_config.py configs/org_config.py
Selecione o departamento adequado na lista global.
ln -sf ../../../global/configs/Department_Data_config.py configs/department_config.py
Para definir o contexto de ambiente correto, use o sinalizador
--properties
para especificar a propriedadeenvName
. Essa propriedade permite executar o mesmo código segmentando diferentes ambientes no mesmo comando.[MY-PROJECT-ID]
representa o ID do projeto do Google Cloud.[MY-PROJECT-ID] gcloud deployment-manager deployments create hierarchy-org-example-dev --template env_demo_project.py --properties=envName:dev gcloud deployment-manager deployments create hierarchy-org-example-test --template env_demo_project.py --properties=envName:test gcloud deployment-manager deployments create hierarchy-org-example-prod --template env_demo_project.py --properties=envName:prod
Práticas recomendadas
As práticas recomendadas a seguir podem ajudar a estruturar seu código hierarquicamente.
Arquivos de esquema
O Deployment Manager exige que o arquivo de esquema inclua uma lista de todos os arquivos usados de alguma forma durante a implantação. Adicionar uma pasta inteira deixa seu código mais curto e genérico.
- Classes auxiliares:
- path: helper/*.py
- Arquivos de configuração:
- path: configs/*.py - path: configs/*/*.py
- Importações em massa (estilo glob)
gcloud config set deployment_manager/glob_imports True
Várias implantações
É recomendável que um sistema contenha várias implantações, o que significa que elas usam os mesmos conjuntos de configurações, mesmo de módulos diferentes. Por exemplo, rede, firewalls, back-end, front-end. Pode ser necessário acessar a saída dessas implantações de outra implantação. É possível consultar a saída da implantação depois que ela está pronta e salvá-la na pasta de configurações. Adicione esses arquivos de configuração durante o processo de combinação.
Links simbólicos
Os links simbólicos são compatíveis com os comandos gcloud deployment-manager
, e os arquivos vinculados são carregados corretamente. No entanto, links simbólicos não são compatíveis com todos os sistemas operacionais.
Hierarquia de configurações
O diagrama a seguir apresenta uma visão geral dos diferentes níveis e as relações entre eles. Cada retângulo representa um arquivo de propriedades, conforme indicado pelo nome do arquivo em vermelho.
Ordem de combinação com base no contexto
A combinação de configurações seleciona os arquivos de configuração adequados em cada nível de acordo com o contexto de uso de cada arquivo. O contexto representa um módulo que você está implantando em um ambiente. Ele define o sistema e o departamento automaticamente.
No diagrama a seguir, os números representam a ordem de substituição na hierarquia:
A seguir
- Veja mais exemplos de implantação no repositório do GitHub do Deployment Manager.
- Leia mais sobre modelos e implantações.