Se a sua infraestrutura de TI crescer muito rapidamente, mais cedo ou mais tarde você se deparará com uma escolha: aumentar linearmente os recursos humanos para apoiá-la ou iniciar a automação. Até certo ponto, vivíamos no primeiro paradigma, e então começou o longo caminho para a Infraestrutura como Código.
Claro que a NSPK não é uma startup, mas tal clima reinou na empresa nos primeiros anos de sua existência, e foram anos muito interessantes. Meu nome é
De forma geral podemos dizer que nossa equipe fornece 2 produtos para a empresa. O primeiro é a infraestrutura. O correio deve funcionar, o DNS deve funcionar e os controladores de domínio devem permitir que você acesse servidores que não devem travar. O cenário de TI da empresa é enorme! Estes são sistemas de negócios e de missão crítica, os requisitos de disponibilidade para alguns são 99,999. O segundo produto são os próprios servidores, físicos e virtuais. Os existentes precisam ser monitorados e os novos devem ser entregues regularmente aos clientes de vários departamentos. Neste artigo quero focar em como desenvolvemos a infraestrutura responsável pelo ciclo de vida do servidor.
Início de uma jornada
No início de nossa jornada, nossa pilha de tecnologia era assim:
SO CentOS 7
Controladores de domínio FreeIPA
Automação - Ansible(+Torre), Sapateiro
Tudo isso localizado em 3 domínios, espalhados por diversos data centers. Em um data center existem sistemas de escritório e locais de teste, no restante existe PROD.
A criação de servidores em um determinado momento ficou assim:
No modelo de VM, o CentOS é mínimo e o mínimo necessário é como o /etc/resolv.conf correto, o resto vem através do Ansible.
CMDB-Excel.
Se o servidor for físico, em vez de copiar a máquina virtual, o sistema operacional foi instalado nela usando o Cobbler - os endereços MAC do servidor de destino são adicionados à configuração do Cobbler, o servidor recebe um endereço IP via DHCP e, em seguida, o sistema operacional Está adicionado.
No começo até tentamos fazer algum tipo de gerenciamento de configuração no Cobbler. Mas com o tempo, isso começou a trazer problemas de portabilidade de configurações tanto para outros data centers quanto para o código Ansible para preparação de VMs.
Naquela época, muitos de nós considerávamos o Ansible uma extensão conveniente do Bash e não economizávamos em designs usando shell e sed. No geral Bashsível. Em última análise, isso levou ao fato de que, se o manual por algum motivo não funcionasse no servidor, seria mais fácil excluir o servidor, consertar o manual e executá-lo novamente. Essencialmente, não havia controle de versão de scripts, nem portabilidade de configurações.
Por exemplo, queríamos alterar algumas configurações em todos os servidores:
- Alteramos a configuração nos servidores existentes no segmento lógico/data center. Às vezes, não num dia – os requisitos de acessibilidade e a lei dos grandes números não permitem que todas as alterações sejam aplicadas de uma só vez. E algumas mudanças são potencialmente destrutivas e exigem a reinicialização de algo – desde serviços até o próprio sistema operacional.
- Corrigindo no Ansible
- Nós consertamos no Cobbler
- Repita N vezes para cada segmento lógico/data center
Para que todas as mudanças ocorressem sem problemas, muitos fatores tiveram que ser levados em consideração, e as mudanças ocorrem constantemente.
- Refatorando código ansible, arquivos de configuração
- Mudando as melhores práticas internas
- Alterações com base nos resultados da análise de incidentes/acidentes
- Mudança dos padrões de segurança, tanto internos quanto externos. Por exemplo, o PCI DSS é atualizado com novos requisitos todos os anos
Crescimento da infraestrutura e o início da jornada
Cresceu o número de servidores/domínios lógicos/data centers e com eles o número de erros de configuração. Em algum momento, chegamos a três direções nas quais o gerenciamento de configuração precisa ser desenvolvido:
- Automação. O erro humano em operações repetitivas deve ser evitado tanto quanto possível.
- Repetibilidade. É muito mais fácil gerenciar a infraestrutura quando ela é previsível. A configuração dos servidores e as ferramentas para sua preparação devem ser as mesmas em todos os lugares. Isso também é importante para equipes de produto - após o teste, é necessário garantir que o aplicativo terminará em um ambiente de produção configurado de forma semelhante ao ambiente de teste.
- Simplicidade e transparência na realização de alterações no gerenciamento de configuração.
Resta adicionar algumas ferramentas.
Escolhemos o GitLab CE como nosso repositório de código, principalmente por seus módulos CI/CD integrados.
Cofre de segredos - Hashicorp Vault, incl. para a excelente API.
Testando configurações e funções ansible – Molecule+Testinfra. Os testes são muito mais rápidos se você se conectar ao mitógeno ansible. Ao mesmo tempo, começamos a escrever nosso próprio CMDB e orquestrador para implantação automática (na foto acima do Cobbler), mas esta é uma história completamente diferente, que meu colega e principal desenvolvedor desses sistemas contará no futuro.
Nossa escolha:
Molécula + Testinfra
Ansible + Torre + AWX
Mundo dos Servidores + DITNET (Desenvolvimento próprio)
Sapateiro
Gitlab + executor GitLab
Cofre Hashicorp
A propósito, sobre papéis ansible. No início havia apenas um, mas depois de várias refatorações havia 17 deles. Eu recomendo fortemente dividir o monólito em papéis idempotentes, que podem então ser iniciados separadamente; além disso, você pode adicionar tags. Dividimos as funções por funcionalidade – rede, registro, pacotes, hardware, molécula etc. Em geral, seguimos a estratégia abaixo. Não insisto que esta seja a única verdade, mas funcionou para nós.
- Copiar servidores da “imagem dourada” é um mal!A principal desvantagem é que você não sabe exatamente em que estado as imagens estão agora e que todas as alterações ocorrerão em todas as imagens em todos os farms de virtualização.
- Use o mínimo de arquivos de configuração padrão e combine com outros departamentos que você é responsável pelos principais arquivos do sistema, Por exemplo:
- Deixe /etc/sysctl.conf vazio, as configurações devem estar apenas em /etc/sysctl.d/. Seu padrão em um arquivo, personalizado para o aplicativo em outro.
- Use arquivos de substituição para editar unidades do systemd.
- Modele todas as configurações e inclua-as inteiramente; se possível, nenhum sed ou seus análogos nos playbooks
- Refatorando o código do sistema de gerenciamento de configuração:
- Divida as tarefas em entidades lógicas e reescreva o monólito em funções
- Use linters! Ansible-lint, yaml-lint, etc.
- Mude sua abordagem! Não é ridículo. É necessário descrever o estado do sistema
- Para todas as funções do Ansible, você precisa escrever testes em moléculas e gerar relatórios uma vez por dia.
- No nosso caso, após a preparação dos testes (que são mais de 100), foram encontrados cerca de 70000 erros. Demorou vários meses para consertar.
Nossa implementação
Assim, os papéis ansible estavam prontos, modelados e verificados por linters. E até idiotas são criados em todos os lugares. Mas a questão da entrega confiável de código para diferentes segmentos permaneceu em aberto. Decidimos sincronizar com scripts. Parece com isso:
Depois que a mudança chega, o CI é lançado, um servidor de teste é criado, as funções são implementadas e testadas pela molécula. Se tudo estiver bem, o código vai para o branch prod. Mas não aplicamos novo código aos servidores existentes na máquina. É uma espécie de rolha necessária para a alta disponibilidade dos nossos sistemas. E quando a infraestrutura se torna enorme, a lei dos grandes números entra em ação - mesmo que você tenha certeza de que a mudança é inofensiva, ela pode levar a consequências terríveis.
Existem também muitas opções para criar servidores. Acabamos escolhendo scripts Python personalizados. E para CI ansible:
- name: create1.yml - Create a VM from a template
vmware_guest:
hostname: "{{datacenter}}".domain.ru
username: "{{ username_vc }}"
password: "{{ password_vc }}"
validate_certs: no
cluster: "{{cluster}}"
datacenter: "{{datacenter}}"
name: "{{ name }}"
state: poweredon
folder: "/{{folder}}"
template: "{{template}}"
customization:
hostname: "{{ name }}"
domain: domain.ru
dns_servers:
- "{{ ipa1_dns }}"
- "{{ ipa2_dns }}"
networks:
- name: "{{ network }}"
type: static
ip: "{{ip}}"
netmask: "{{netmask}}"
gateway: "{{gateway}}"
wake_on_lan: True
start_connected: True
allow_guest_control: True
wait_for_ip_address: yes
disk:
- size_gb: 1
type: thin
datastore: "{{datastore}}"
- size_gb: 20
type: thin
datastore: "{{datastore}}"
É a isso que chegamos, o sistema continua a viver e a se desenvolver.
- 17 Funções Ansible para configurar o servidor. Cada uma das funções é projetada para resolver uma tarefa lógica separada (registro, auditoria, autorização de usuário, monitoramento, etc.).
- Teste de função. Molécula + TesteInfra.
- Desenvolvimento próprio: CMDB + Orchestrator.
- O tempo de criação do servidor é de aproximadamente 30 minutos, automatizado e praticamente independente da fila de tarefas.
- O mesmo estado/nomeação da infraestrutura em todos os segmentos – playbooks, repositórios, elementos de virtualização.
- Verificação diária do status do servidor com geração de relatórios sobre discrepâncias com o padrão.
Espero que minha história seja útil para aqueles que estão no início de sua jornada. Qual pilha de automação você usa?
Fonte: habr.com