One place for hosting & domains

      Gerenciamento

      Uma Introdução ao Gerenciamento de Configuração


      Introdução

      Em um aspecto mais amplo, o gerenciamento de configuração (GC) refere-se ao processo de manipular sistematicamente as alterações em um sistema, de maneira a manter a integridade ao longo do tempo. Embora esse processo não tenha sido originado no setor de TI, o termo é amplamente usado para se referir ao gerenciamento de configuração de servidor.

      A automação desempenha um papel essencial no gerenciamento de configuração de servidor. É o mecanismo usado para fazer o servidor alcançar um estado desejável, definido anteriormente por scripts de provisionamento usando a linguagem e os recursos específicos de uma ferramenta. A automação é, de fato, o coração do gerenciamento de configurações de servidores, e é por isso que é comum também se referir às ferramentas de gerenciamento de configuração como Ferramentas de Automação ou Ferramentas de Automação de TI.

      Outro termo comum usado para descrever os recursos de automação implementados pelas ferramentas de gerenciamento de configuração é Orquestração de Servidor ou Orquestração de TI, uma vez que essas ferramentas geralmente são capazes de gerenciar de um a centenas de servidores a partir de uma máquina controladora central.

      Existem várias ferramentas de gerenciamento de configuração disponíveis no mercado. Puppet, Ansible, Chef e Salt são escolhas populares. Embora cada ferramenta tenha suas próprias características e funcione de maneiras ligeiramente diferentes, todas elas são orientadas pelo mesmo propósito: garantir que o estado do sistema corresponda ao estado descrito pelos seus scripts de provisionamento.

      Benefícios do Gerenciamento de Configuração para Servidores

      Embora o uso do gerenciamento de configuração geralmente exija mais planejamento e esforço iniciais do que a administração manual do sistema, todas as infraestruturas de servidor, exceto as mais simples, serão aprimoradas pelos benefícios que ele oferece. Para citar alguns:

      Provisionamento Rápido de Novos Servidores

      Sempre que um novo servidor precisa ser deployado, uma ferramenta de gerenciamento de configuração pode automatizar a maior parte, se não todo, do processo de provisionamento para você. A automação torna o provisionamento muito mais rápido e eficiente, pois permite que tarefas tediosas sejam executadas com mais rapidez e precisão do que qualquer ser humano poderia. Mesmo com a documentação adequada e completa, o deployment manual de um servidor web, por exemplo, pode levar horas em comparação a alguns minutos com o gerenciamento/automação da configuração.

      Recuperação Rápida de Eventos Críticos

      Com o provisionamento rápido, vem outro benefício: recuperação rápida de eventos críticos. Quando um servidor fica offline devido a circunstâncias desconhecidas, pode levar várias horas para se auditar adequadamente o sistema e descobrir o que realmente aconteceu. Em cenários como esse, fazer o deploy de um servidor substituto geralmente é a maneira mais segura de colocar seus serviços online novamente enquanto uma inspeção detalhada é feita no servidor afetado. Com o gerenciamento e a automação da configuração, isso pode ser feito de maneira rápida e confiável.

      Não mais Servidores Snowflake

      À primeira vista, a administração manual do sistema pode parecer uma maneira fácil de fazer deploy e corrigir rapidamente os servidores, mas isso geralmente tem um preço. Com o tempo, pode se tornar extremamente difícil saber exatamente o que está instalado em um servidor e quais alterações foram feitas quando o processo não é automatizado. Os hotfixes manuais, os ajustes de configuração e as atualizações de software podem transformar os servidores em snowflakes exclusivos, difíceis de gerenciar e ainda mais difíceis de replicar. Usando uma ferramenta de GC, o procedimento necessário para lançar um novo servidor ou atualizar um existente estará documentado nos scripts de provisionamento.

      Controle de Versão para o Ambiente do Servidor

      Depois de ter sua configuração do servidor traduzida em um conjunto de scripts de provisionamento, você poderá aplicar ao ambiente do seu servidor muitas das ferramentas e fluxos de trabalho que você normalmente usa para o código-fonte de software.

      Ferramentas de controle de versão como o Git, podem ser usadas para acompanhar as alterações feitas no provisionamento e manter ramificações separadas para as versões antigas dos scripts. Você também pode usar o controle de versão para implementar uma política de code review para os scripts de provisionamento, onde todas as alterações devem ser submetidas como um pull request e aprovadas pelo líder do projeto antes de serem aceitas. Essa prática adicionará consistência extra à sua configuração de infraestrutura.

      Ambientes Replicados

      O gerenciamento de configuração torna trivial replicar ambientes com exatamente o mesmo software e as mesmas configurações. Isso permite que você crie efetivamente um ecossistema de vários estágios, com servidores de produção, desenvolvimento e teste. Você pode até usar máquinas virtuais locais para desenvolvimento, criadas com os mesmos scripts de provisionamento. Essa prática minimizará os problemas causados por discrepâncias no ambiente que ocorrem com frequência quando as aplicações são deployadas na produção ou compartilhadas entre colegas de trabalho com diferentes configurações de máquina (sistema operacional diferente, versões de software e/ou configurações).

      Visão Geral das Ferramentas de Gerenciamento de Configuração

      Embora cada ferramenta de GC tenha seus próprios termos, filosofia e ecossistema, elas geralmente compartilham muitas características e têm conceitos semelhantes.

      A maioria das ferramentas de gerenciamento de configuração usa um modelo de controlador/mestre e node/agente. Essencialmente, o controlador direciona a configuração dos nodes, com base em uma série de instruções ou tasks definidas em seus scripts de provisionamento.

      Abaixo, você encontra os recursos mais comuns presentes na maioria das ferramentas de gerenciamento de configuração para servidores:

      Framework de Automação

      Cada ferramenta de gerenciamento de configuração fornece uma sintaxe específica e um conjunto de recursos que você pode usar para escrever scripts de provisionamento. A maioria das ferramentas possui recursos que tornam sua linguagem semelhante às linguagens de programação convencionais, mas de maneira simplificada. Variáveis, loops e condicionais são recursos comuns fornecidos para facilitar a criação de scripts de provisionamento mais versáteis.

      Comportamento Idempotente

      As ferramentas de gerenciamento de configuração controlam o estado dos recursos para evitar a repetição de tarefas que foram executadas anteriormente. Se um pacote já estiver instalado, a ferramenta não tentará instalá-lo novamente. O objetivo é que, após cada execução de provisionamento, o sistema atinja (ou mantenha) o estado desejado, mesmo que você o execute várias vezes. É isso que caracteriza essas ferramentas como tendo um comportamento idempotente. Esse comportamento não é necessariamente imposto em todos os casos, no entanto.

      Fatos do Sistema (Facts)

      As ferramentas de gerenciamento de configuração geralmente fornecem informações detalhadas sobre o sistema que está sendo provisionado. Esses dados estão disponíveis através de variáveis globais, conhecidas como facts. Eles incluem coisas como interfaces de rede, endereços IP, sistema operacional e distribuição. Cada ferramenta fornecerá um conjunto diferente de facts. Eles podem ser usados para tornar os scripts e templates de provisionamento mais adaptáveis a vários sistemas.

      Sistema de Templates

      A maioria das ferramentas de GC fornecerá um sistema de templates interno que pode ser usado para facilitar a criação de arquivos e serviços de configuração. Os templates geralmente suportam variáveis, loops e condicionais que podem ser usados para maximizar a versatilidade. Por exemplo, você pode usar um template para configurar facilmente um novo virtual host no Apache, enquanto reutiliza o mesmo template para várias instalações de servidores. Em vez de ter apenas valores estáticos codificados, um template deve conter espaços reservados (placeholders) para valores que podem mudar de host para host, como NameServer e DocumentRoot.

      Extensibilidade

      Embora os scripts de provisionamento possam ser muito especializados para as necessidades e demandas de um servidor específico, há muitos casos em que você tem configurações semelhantes de servidor ou partes de uma configuração que podem ser compartilhadas entre vários servidores. A maioria das ferramentas de provisionamento fornecerá maneiras pelas quais você pode reutilizar e compartilhar facilmente pequenos blocos de sua configuração de provisionamento como módulos ou plugins.

      Módulos e plugins de terceiros geralmente são fáceis de encontrar na Internet, especialmente para configurações comuns de servidores, como a instalação de um servidor web PHP. As ferramentas de GC tendem a ter uma comunidade forte criada em torno delas e os usuários são incentivados a compartilhar suas extensões personalizadas. O uso de extensões fornecidas por outros usuários pode economizar muito tempo, além de servir como uma excelente maneira de aprender como outros usuários resolveram problemas comuns usando a ferramenta de sua escolha.

      Escolhendo uma Ferramenta de Gerenciamento de Configuração

      Existem muitas ferramentas de GC disponíveis no mercado, cada uma com um conjunto diferente de recursos e diferentes níveis de complexidade. As escolhas populares incluem Chef, Ansible e Puppet. O primeiro desafio é escolher uma ferramenta que seja adequada às suas necessidades.

      Há algumas coisas que você deve levar em consideração antes de fazer uma escolha:

      Complexidade da Infraestrutura

      A maioria das ferramentas de gerenciamento de configuração requer uma hierarquia mínima composta por uma máquina controladora e um node que será gerenciado por ela. O Puppet, por exemplo, exige que uma aplicação agent seja instalada em cada node e um aplicação master seja instalada na máquina do controlador. O Ansible, por outro lado, possui uma estrutura descentralizada que não requer instalação de software adicional nos nodes, mas depende do SSH para executar as tarefas de provisionamento. Para projetos menores, uma infraestrutura simplificada pode parecer melhor, no entanto, é importante levar em consideração aspectos como escalabilidade e segurança, que podem não ser impostos pela ferramenta.

      Algumas ferramentas podem ter mais componentes e partes móveis, o que pode aumentar a complexidade da sua infraestrutura, impactando na curva de aprendizado e possivelmente aumentando o custo geral de implementação.

      Curva de Aprendizado

      Como mencionado anteriormente neste artigo, as ferramentas de GC fornecem uma sintaxe personalizada, às vezes usando uma linguagem de domínio específico (DSL) e um conjunto de recursos que compõem seu framework de automação. Como nas linguagens de programação convencionais, algumas ferramentas exigem uma curva de aprendizado mais alta para serem dominadas. Os requisitos de infraestrutura também podem influenciar a complexidade da ferramenta e a rapidez com que você poderá ver um retorno do investimento.

      Custo

      A maioria das ferramentas de GC oferece versões gratuitas ou open source, com assinaturas pagas para recursos e serviços avançados. Algumas ferramentas terão mais limitações que outras, portanto, dependendo de suas necessidades específicas e de como sua infraestrutura cresce, você pode acabar tendo que pagar por esses serviços. Você também deve considerar o treinamento como um custo extra em potencial, não apenas em termos monetários, mas também em relação ao tempo necessário para atualizar sua equipe com a ferramenta que você acabou escolhendo.

      Ferramentas Avançadas

      Como mencionado anteriormente, a maioria das ferramentas oferece serviços pagos que podem incluir suporte, extensões e ferramentas avançadas. É importante analisar suas necessidades específicas, o tamanho da sua infraestrutura e se há ou não a necessidade de usar esses serviços. Os painéis de gerenciamento, por exemplo, são um serviço comum oferecido por essas ferramentas e podem facilitar muito o processo de gerenciamento e monitoramento de todos os seus servidores a partir de um ponto central. Mesmo que você ainda não precise desses serviços, considere as opções para uma possível necessidade futura.

      Comunidade e Suporte

      Uma comunidade forte e acolhedora pode ser extremamente útil em termos de suporte e documentação, pois os usuários geralmente ficam felizes em compartilhar seu conhecimento e suas extensões (módulos, plugins e scripts de provisionamento) com outros usuários. Isso pode ser útil para acelerar sua curva de aprendizado e evitar custos extras com suporte ou treinamento pagos.

      Visão Geral das Ferramentas Populares

      A tabela abaixo deve lhe fornecer uma rápida visão geral das principais diferenças entre as três ferramentas de gerenciamento de configuração mais populares disponíveis no mercado atualmente: Ansible, Puppet e Chef.

      Ansible Puppet Chef
      Linguagem do Script YAML DSL personalizada baseada em Ruby Ruby
      Infraestrutura A máquina controladora aplica a configuração nos nodes via SSH O Puppet Master sincroniza a configuração nos Puppet Nodes As Workstations do Chef enviam a configuração para o Chef Server, a partir do qual os nodes do Chef serão atualizados
      Requer software especializado para os nodes Não Sim Sim
      Fornece ponto de controle centralizado Não. Qualquer computador pode ser um controlador Sim, via Puppet Master Sim, via Chef Server
      Terminologia do script Playbook / Roles Manifests / Modules Recipes / Cookbooks
      Ordem de Execução das Tarefas Sequencial Não-sequencial Sequencial

      Próximos Passos

      Até agora, vimos como o gerenciamento de configuração funciona para servidores e o que considerar ao escolher uma ferramenta para criar sua infraestrutura de gerenciamento de configuração. Nos guias subsequentes desta série, teremos uma experiência prática com três ferramentas populares de gerenciamento de configuração: Ansible, Puppet e Chef.

      Para que você possa comparar essas ferramentas por si mesmo, usaremos um exemplo simples de configuração de servidor que deve ser totalmente automatizado por cada ferramenta. Essa configuração consiste em um servidor Ubuntu 18.04 executando o Apache para hospedar uma página web simples.

      Conclusão

      O gerenciamento de configuração pode melhorar drasticamente a integridade dos servidores ao longo do tempo, fornecendo um framework para automatizar processos e acompanhar as alterações feitas no ambiente do sistema. No próximo guia dessa série, veremos como implementar uma estratégia de gerenciamento de configuração na prática usando Ansible como ferramenta.



      Source link

      Gerenciamento de Configuração 101: Escrevendo Receitas do Chef


      Introdução

      Em poucas palavras, o gerenciamento de configuração de servidor (também conhecido como IT Automation) é uma solução para transformar a sua administração de infraestrutura em uma base de código, descrevendo todos os processos necessários para fazer o deploy de um servidor em um conjunto de scripts de provisionamento que podem ser versionados e facilmente reutilizados. Isso pode melhorar muito a integridade de qualquer infraestrutura de servidor ao longo do tempo.

      Em um guia anterior, falamos sobre os principais benefícios da implementação de uma estratégia de gerenciamento de configuração para a infraestrutura de servidor, como as ferramentas de gerenciamento de configuração funcionam e o que essas ferramentas têm em comum normalmente.

      Esta parte da série o guiará pelo processo de automatização do provisionamento de servidores usando o Chef, uma poderosa ferramenta de gerenciamento de configuração que aproveita a linguagem de programação Ruby para automatizar a administração e o provisionamento da infraestrutura. Vamos nos concentrar na terminologia da linguagem, sintaxe e recursos necessários para criar um exemplo simplificado para automatizar completamente o deployment de um servidor web Ubuntu 18.04 usando o Apache.

      Esta é a lista de passos que precisamos automatizar para alcançar nosso objetivo:

      1. Atualizar o cache do apt
      2. Instalar o Apache
      3. Criar um diretório raiz de documentos personalizado (document root)
      4. Colocar um arquivo index.html no document root personalizado
      5. Aplicar um template para configurar nosso virtual host personalizado
      6. Reiniciar o Apache

      Começaremos examinando a terminologia usada pelo Chef, seguida de uma visão geral dos principais recursos da linguagem que podem ser usados para escrever recipes ou receitas. No final deste guia, compartilharemos o exemplo completo para que você possa experimentar sozinho.

      Nota: este guia pretende apresentar a linguagem do Chef e como escrever receitas para automatizar o provisionamento de servidor. Para uma visão mais introdutória do Chef, incluindo as etapas necessárias para instalar e começar com esta ferramenta, consulte a documentação oficial do Chef.

      Começando

      Antes de podermos avançar para uma visão mais prática do Chef, é importante nos familiarizarmos com importantes terminologias e conceitos introduzidos por esta ferramenta.

      Termos do Chef

      • Chef Server: um servidor central que armazena informações e gerencia o provisionamento dos nodes
      • Chef Node: um servidor individual que é gerenciado por um Chef Server
      • Chef Workstation: uma máquina controladora na qual os provisionamentos são criados e carregados para o Chef Server
      • Recipe (receita): um arquivo que contém um conjunto de instruções (recursos) a serem executados. Uma receita deve estar contida dentro de um Cookbook
      • Resource (recurso): uma parte do código que declara um elemento do sistema e que ação deve ser executada. Por exemplo, para instalar um pacote, declaramos um recurso package com a ação install
      • Cookbook (livro de receitas): uma coleção de receitas e outros arquivos relacionados organizados de forma predefinida para facilitar o compartilhamento e a reutilização de partes de um provisionamento
      • Attributes (atributos): detalhes sobre um node específico. Os Attributes (atributos) podem ser automáticos (veja a próxima definição) e também podem ser definidos nas receitas
      • Automatic Attributes: variáveis globais que contêm informações sobre o sistema, como interfaces de rede e sistema operacional (conhecidos como facts em outras ferramentas). Esses atributos automáticos são coletados por uma ferramenta chamada Ohai
      • Services: usado para acionar alterações de status do serviço, como reiniciar ou parar um serviço

      Formato da Receita

      As receitas do Chef são escritas usando Ruby. Uma receita é basicamente uma coleção de definições de recursos que criarão um conjunto passo a passo de instruções a serem executadas pelos nodes. Essas definições de recursos podem ser combinadas com o código Ruby para maior flexibilidade e modularidade.

      Abaixo você pode encontrar um exemplo simples de uma receita que irá executar o apt-get update e instalar o vim posteriormente:

      execute "apt-get update" do
       command "apt-get update"
      end
      
      apt_package "vim" do
       action :install
      end
      
      

      Escrevendo Receitas

      Trabalhando com Variáveis

      As variáveis locais podem ser definidas nas receitas como variáveis locais regulares do Ruby. O exemplo abaixo mostra como criar uma variável local que é usada posteriormente dentro de uma definição de recurso:

      package  = "vim"
      
      apt_package package do
       action :install
      end
      

      Essas variáveis, no entanto, têm um escopo limitado, sendo válidas apenas dentro do arquivo em que foram definidas. Se você deseja criar uma variável e disponibilizá-la globalmente, para poder usá-la em qualquer um dos seus cookbooks ou receitas, você precisa definir um atributo personalizado.

      Usando Atributos

      Os atributos representam detalhes sobre um node. O Chef possui atributos automáticos, que são os atributos coletados por uma ferramenta chamada Ohai e contêm informações sobre o sistema (como plataforma, nome do host e endereço IP padrão), mas também permitem definir seus próprios atributos personalizados.

      Os atributos têm níveis de precedência diferentes, definidos pelo tipo de atributo que você cria. Os atributos default são a escolha mais comum, pois ainda podem ser sobrescritos por outros tipos de atributos quando desejado.

      O exemplo a seguir mostra como o exemplo anterior seria com um atributo de node default em vez de uma variável local:

      node.default['main']['package'] = "vim"
      
      apt_package node['main']['package'] do
       action :install
      end
      

      Há dois detalhes a serem observados neste exemplo:

      A prática recomendada ao definir variáveis de node é organizá-las como hashes usando o cookbook atual em uso como chave. Nesse caso, usamos main, porque temos um cookbook com o mesmo nome. Isso evita confusão se você estiver trabalhando com vários cookbooks que podem ter atributos com nomes semelhantes.
      Observe que usamos node.default ao definir o atributo, mas ao acessar seu valor posteriormente, usamos node diretamente. O uso do node.default define que estamos criando um atributo do tipo default. Esse atributo pode ter seu valor sobrescrito por outro tipo com precedência mais alta, como atributos normal ou override.

      A precedência dos atributos pode ser um pouco confusa no início, mas você se acostumará com isso depois de alguma prática. Para ilustrar o comportamento, considere o seguinte exemplo:

      node.normal['main']['package']  = "vim"
      
      node.override['main']['package'] = "git"
      
      node.default['main']['package'] = "curl"
      
      apt_package node['main']['package'] do
       action :install
      end
      

      Você sabe qual pacote será instalado neste caso? Se você achou que é o git, adivinhou corretamente. Independentemente da ordem em que os atributos foram definidos, a maior precedência do tipo override fará com que o node['main']['package'] seja avaliado como git.

      Usando Loops

      Os loops são normalmente usados para repetir uma tarefa usando diferentes valores de entrada. Por exemplo, em vez de criar 10 tarefas para instalar 10 pacotes diferentes, você pode criar uma única tarefa e usar um loop para repetir a tarefa com todos os pacotes diferentes que deseja instalar.

      O Chef suporta todas as estruturas de loop Ruby para criar loops dentro de receitas. Para uso simples, each é uma escolha comum:

      ['vim', 'git', 'curl'].each do |package|
       apt_package package do
         action :install
       end
      end
      

      Em vez de usar um array inline, você também pode criar uma variável ou atributo para definir os parâmetros que deseja usar dentro do loop. Isso manterá as coisas mais organizadas e fáceis de ler. Abaixo, o mesmo exemplo agora usando uma variável local para definir os pacotes que devem ser instalados:

      packages = ['vim', 'git', 'curl']
      
      packages.each do |package|
       apt_package package do
         action :install
       end
      end
      

      Usando Condicionais

      Condicionais podem ser usadas para decidir dinamicamente se um bloco de código deve ou não ser executado, com base em uma variável ou em uma saída de um comando, por exemplo.

      O Chef suporta todos as condicionais do Ruby para criar instruções condicionais nas receitas. Além disso, todos os tipos de recursos suportam duas propriedades especiais que avaliarão uma expressão antes de decidir se a tarefa deve ser executada ou não: if_only e not_if.

      O exemplo abaixo verificará a existência do php antes de tentar instalar a extensão php-pear. Ele usará o comando which para verificar se existe um executável php atualmente instalado neste sistema. Se o comando which php retornar falso, esta tarefa não será executada:

      apt_package "php-pear" do
       action :install
       only_if "which php"
      end
      

      Se quisermos fazer o oposto, executando um comando o tempo todo exceto quando uma condição é avaliada como verdadeira, usamos not_if. Este exemplo instalará o php5, a menos que o sistema seja o CentOS:

      apt_package "php5" do
       action :install
       not_if { node['platform'] == 'centos' }
      end
      

      Para realizar avaliações mais complexas, ou se você desejar executar várias tarefas sob uma condição específica, você pode usar qualquer uma das condicionais padrão do Ruby. O exemplo a seguir só executará apt-get update quando o sistema for Debian ou Ubuntu:

      if node['platform'] == 'debian' || node['platform'] == 'ubuntu'
       execute "apt-get update" do
         command "apt-get update"
       end
      end
      

      O atributo node['platform'] é um atributo automático do Chef. O último exemplo foi apenas para demonstrar uma construção condicional mais complexa, no entanto, pode ser substituída por um teste simples usando o atributo automático node['platform_family'], que retornaria “debian” para os sistemas Debian e Ubuntu.

      Trabalhando com Templates

      Os templates geralmente são usados para definir arquivos de configuração, permitindo o uso de variáveis e outros recursos destinados a tornar esses arquivos mais versáteis e reutilizáveis.

      O Chef usa templates Embedded Ruby (ERB), que é o mesmo formato usado pelo Puppet. Eles suportam condicionais, loops e outros recursos do Ruby.

      Abaixo está um exemplo de um modelo de ERB para configurar um virtual host no Apache, usando uma variável para definir o document root para esse host:

      <VirtualHost *:80>
          ServerAdmin webmaster@localhost
          DocumentRoot <%= @doc_root %>
      
          <Directory <%= @doc_root %>>
              AllowOverride All
              Require all granted
          </Directory>
      </VirtualHost>
      

      Para aplicar o template, precisamos criar um recurso template. É assim que você aplicaria esse template para substituir o virtual host padrão do Apache:

      template "/etc/apache2/sites-available/000-default.conf" do
       source "vhost.erb"
       variables({ :doc_root => node['main']['doc_root'] })
       action :create
      end 
      

      O Chef faz algumas suposições ao lidar com arquivos locais, a fim de reforçar a organização e a modularidade. Nesse caso, o Chef procuraria um arquivo de template vhost.erb dentro de uma pasta templates que deveria estar no mesmo cookbook em que esta receita está localizada.

      Ao contrário das outras ferramentas de gerenciamento de configuração que vimos até agora, o Chef tem um escopo mais estrito para variáveis. Isso significa que você precisará fornecer explicitamente todas as variáveis que planeja usar dentro de um template, ao definir o recurso template. Neste exemplo, usamos o método variables para passar adiante o atributo doc_root que precisamos no modelo de virtual host.

      Definindo e Acionando Serviços

      Os recursos de serviço são usados para garantir que os serviços sejam inicializados e ativados. Eles também são usados para acionar a reinicialização do serviço.

      No Chef, os recursos de serviço precisam ser declarados antes de você tentar notificá-los, caso contrário, você receberá um erro.

      Vamos levar em consideração o nosso exemplo anterior de uso de templates, onde configuramos um virtual host no Apache. Se você deseja garantir que o Apache seja reiniciado após uma mudança no virtual host, primeiro crie um recurso service para o serviço Apache. É assim que esse recurso é definido no Chef:

      service "apache2" do
        action [ :enable, :start ]
      end
      

      Agora, ao definir o recurso template, você precisa incluir uma opção notify para acionar uma reinicialização:

      template "/etc/apache2/sites-available/000-default.conf" do
       source "vhost.erb"
       variables({ :doc_root => node['main']['doc_root'] })
       action :create
       notifies :restart, resources(:service => "apache2")
      end
      

      Exemplo de Receita

      Agora, vamos dar uma olhada em uma receita que automatizará a instalação de um servidor Web Apache em um sistema Ubuntu 14.04, conforme discutido na introdução deste guia.

      O exemplo completo, incluindo o arquivo de template para configurar o Apache e um arquivo HTML para ser servido pelo servidor web, pode ser encontrado no Github. A pasta também contém um arquivo Vagrant que permite testar a receita em uma configuração simplificada, usando uma máquina virtual gerenciada pelo Vagrant.

      Abaixo você pode encontrar a receita completa:

      • node.default['main']['doc_root'] = "/vagrant/web"
      • execute "apt-get update" do
      • command "apt-get update"
      • end
      • apt_package "apache2" do
      • action :install
      • end
      • service "apache2" do
      • action [ :enable, :start ]
      • end
      • directory node['main']['doc_root'] do
      • owner 'www-data'
      • group 'www-data'
      • mode '0644'
      • action :create
      • end
      • cookbook_file "#{node['main']['doc_root']}/index.html" do
      • source 'index.html'
      • owner 'www-data'
      • group 'www-data'
      • action :create
      • end
      • template "/etc/apache2/sites-available/000-default.conf" do
      • source "vhost.erb"
      • variables({ :doc_root => node['main']['doc_root'] })
      • action :create
      • notifies :restart, resources(:service => "apache2")
      • end

      Receita Explicada

      linha 1

      A receita começa com uma definição de atributo, node['main']['doc_root']. Poderíamos ter usado uma variável local simples aqui, no entanto, na maioria dos cenários de casos de uso, as receitas precisam definir variáveis globais que serão usadas nas receitas incluídas ou em outros arquivos. Para essas situações, é necessário criar um atributo em vez de uma variável local, pois a última possui um escopo limitado.

      linhas 3-5

      Esse recurso execute executa um apt-get update.

      linhas 7-10

      Este recurso apt_package instala o pacote apache2.

      linhas 12-15

      Este recurso service ativa e inicia o serviço apache2. Posteriormente, precisaremos notificar esse recurso para reiniciar o serviço. É importante que a definição de serviço venha antes de qualquer recurso que tente notificar um serviço, caso contrário, você receberá um erro.

      linhas 17-22

      Este recurso directory usa o valor definido pelo atributo personalizado node['main']['doc_root'] para criar um diretório que servirá como nosso document root

      linhas 24-29

      Um recurso cookbook_file é usado para copiar um arquivo local em um servidor remoto. Este recurso copiará nosso arquivo index.html e o colocará dentro do document root que criamos em uma tarefa anterior.

      linhas 31-36

      Por fim, esse recurso template aplica nosso template de virtual host do Apache e notifica o serviço apache2 para uma reinicialização.

      Conclusão

      O Chef é uma poderosa ferramenta de gerenciamento de configuração que utiliza a linguagem Ruby para automatizar o provisionamento e o deployment de servidores. Ele lhe oferece liberdade para usar os recursos de linguagem padrão para obter o máximo de flexibilidade, além de oferecer DSLs personalizadas para alguns recursos.



      Source link

      Gerenciamento de Configuração 101: Escrevendo Manifests do Puppet


      Introdução

      Em poucas palavras, o gerenciamento de configuração de servidor (também conhecido como IT Automation) é uma solução para transformar a sua administração de infraestrutura em uma base de código, descrevendo todos os processos necessários para fazer o deploy de um servidor em um conjunto de scripts de provisionamento que podem ser versionados e facilmente reutilizados. Isso pode melhorar muito a integridade de qualquer infraestrutura de servidor ao longo do tempo.

      Em um guia anterior, falamos sobre os principais benefícios da implementação de uma estratégia de gerenciamento de configuração para a infraestrutura de servidor, como as ferramentas de gerenciamento de configuração funcionam e o que essas ferramentas têm em comum normalmente.

      Esta parte da série o guiará pelo processo de automatização do provisionamento de servidores usando o Puppet, uma ferramenta popular de gerenciamento de configuração capaz de gerenciar infraestruturas complexas de maneira transparente, usando um servidor mestre ou master para orquestrar a configuração dos nodes. Vamos nos concentrar na terminologia da linguagem, sintaxe e recursos necessários para criar um exemplo simplificado para automatizar completamente o deployment de um servidor web Ubuntu 18.04 usando o Apache.

      Esta é a lista de passos que precisamos automatizar para alcançar nosso objetivo:

      1. Atualizar o cache do apt
      2. Instalar o Apache
      3. Criar um diretório raiz de documentos personalizado (document root)
      4. Colocar um arquivo index.html no document root personalizado
      5. Aplicar um modelo para configurar nosso virtual host personalizado
      6. Reiniciar o Apache

      Começaremos examinando a terminologia usada pelo Puppet, seguida de uma visão geral dos principais recursos da linguagem que podem ser usados para escrever manifests. No final deste guia, compartilharemos o exemplo completo para que você possa experimentar sozinho.

      Nota: este guia pretende apresentar a linguagem do Puppet e como escrever manifests para automatizar o provisionamento de servidor. Para uma visão mais introdutória do Puppet, incluindo as etapas necessárias para instalar e começar com esta ferramenta, consulte a documentação oficial do Puppet.

      Começando

      Antes de podermos avançar para uma visão mais prática do Puppet, é importante nos familiarizarmos com importantes terminologias e conceitos introduzidos por esta ferramenta.

      Termos do Puppet

      • Puppet Master: o servidor principal que controla a configuração nos nodes
      • Puppet Agent Node: um node controlado por um Puppet Master
      • Manifest: um arquivo que contém um conjunto de instruções a serem executadas
      • Resource (recurso): uma parte do código que declara um elemento do sistema e como seu estado deve ser alterado. Por exemplo, para instalar um pacote, precisamos definir um recurso package e garantir que seu estado esteja definido como installed
      • Module: uma coleção de manifests e outros arquivos relacionados organizados de uma forma predefinida para facilitar o compartilhamento e a reutilização de partes de um provisionamento
      • Class: Assim como nas linguagens de programação regulares, as classes são usadas no Puppet para organizar melhor o provisionamento e facilitar a reutilização de partes do código
      • Facts: variáveis globais que contêm informações sobre o sistema, como interfaces de rede e sistema operacional
      • Services: usado para disparar alterações de status do serviço, como reiniciar ou parar um serviço

      O provisionamento no Puppet é escrito usando uma DSL (linguagem específica de domínio) personalizada baseada em Ruby.

      Recursos

      Com o Puppet, as tarefas ou etapas são definidas declarando recursos. Os recursos podem representar pacotes, arquivos, serviços, usuários e comandos. Eles podem ter um estado, que acionará uma alteração no sistema caso o estado de um recurso declarado seja diferente do que está atualmente no sistema. Por exemplo, um recurso package definido como installed no seu manifest acionará uma instalação do pacote no sistema se o pacote não tiver sido instalado anteriormente.

      É assim que um recurso package se parece:

      package { 'nginx':
          ensure  => 'installed'
      }
      

      Você pode executar qualquer comando arbitrário declarando um recurso exec, como o seguinte:

      exec { 'apt-get update':
          command => '/usr/bin/apt-get update'
      }
      

      Observe que a parte apt-get update na primeira linha não é a declaração de comando real, mas um identificador para este recurso exclusivo. Frequentemente, precisamos fazer referência a outros recursos de dentro de um recurso e usamos o identificador deles para isso. Nesse caso, o identificador é apt-get update, mas poderia ser qualquer outra string.

      Dependência de Recurso

      Ao escrever manifests, é importante ter em mente que o Puppet não avalia os recursos na mesma ordem em que eles são definidos. Essa é uma fonte comum de confusão para quem está começando com o Puppet. Os recursos devem definir explicitamente a dependência entre si, caso contrário, não há garantia de qual recursos será avaliado e, consequentemente, executado primeiro.

      Como um exemplo simples, digamos que você queira executar um comando, mas você precisa garantir que uma dependência seja instalada primeiro:

      package { 'python-software-properties':
          ensure => 'installed'
      }
      
      exec { 'add-repository':
          command => '/usr/bin/add-apt-repository ppa:ondrej/php5 -y'
          require => Package['python-software-properties']
      }
      

      A opção require recebe como parâmetro uma referência a outro recurso. Neste caso, estamos nos referindo ao recurso Package identificado como python-software-properties.

      É importante notar que, enquanto usamos exec, package, e assim por diante para declarar recurso (com letras minúsculas), quando nos referimos a recurso definidos anteriormente, usamos Exec, Package e assim por diante (em maiúsculas).

      Agora, digamos que você precise garantir que uma tarefa seja executada antes de outra. Para um caso como este, podemos usar a opção before:

      package { 'curl':
          ensure => 'installed'
          before => Exec['install script']
      }
      
      exec { 'install script':
          command => '/usr/bin/curl http://example.com/some-script.sh'
      

      Formato do Manifest

      Os manifests são basicamente uma coleção de declarações de recursos, usando a extensão .pp. Abaixo você pode encontrar um exemplo de um playbook simples que executa duas tarefas: atualiza o cache do apt e instala o vim posteriormente:

      exec { 'apt-get update':
          command => '/usr/bin/apt-get update'
      }
      
      package { 'vim':
          ensure => 'installed'
          require => Exec['apt-get update']
      }
      

      Antes do final deste guia, veremos um exemplo mais real de um manifest, explicado em detalhes. A próxima seção fornecerá uma visão geral dos elementos e recursos mais importantes que podem ser usados para escrever manisfests do Puppet.

      Escrevendo Manifests

      Trabalhando com Variáveis

      As variáveis podem ser definidas em qualquer ponto em um manifest. Os tipos mais comuns de variáveis são strings e matrizes ou arrays de strings, mas outros tipos também são suportados, como booleanos e hashes.

      O exemplo abaixo define uma variável string que é usada posteriormente dentro de um recurso:

      $package = "vim"
      
      package { $package:
         ensure => "installed"
      }
      

      Usando Loops

      Os loops são normalmente usados para repetir uma tarefa usando diferentes valores de entrada. Por exemplo, em vez de criar 10 tarefas para instalar 10 pacotes diferentes, você pode criar uma única tarefa e usar um loop para repetir a tarefa com todos os pacotes diferentes que deseja instalar.

      A maneira mais simples de repetir uma tarefa com valores diferentes no Puppet é usando arrays, como no exemplo abaixo:

      $packages = ['vim', 'git', 'curl']
      
      package { $packages:
         ensure => "installed"
      }
      

      A partir da versão 4, o Puppet suporta maneiras adicionais de iterar as tarefas. O exemplo abaixo faz a mesma coisa que o exemplo anterior, mas desta vez usando o iterador each. Esta opção oferece mais flexibilidade para fazer um loop pelas definições de recursos:

      $packages.each |String $package| {
        package { $package:
          ensure => "installed"
        }
      }
      

      Usando Condicionais

      Condicionais podem ser usadas para decidir dinamicamente se um bloco de código deve ou não ser executado, com base em uma variável ou em uma saída de um comando, por exemplo.

      O Puppet suporta a maioria das estruturas condicionais que você pode encontrar nas linguagens de programação tradicionais, como as instruções if/else e case. Além disso, alguns recursos como o exec suportam atributos que funcionam como condicionais, mas aceitam apenas uma saída de comando como condição.

      Digamos que você queira executar um comando com base em um fact. Nesse caso, como você deseja testar o valor de uma variável, é necessário usar uma das estruturas condicionais suportadas, como if/else:

      if $osfamily != 'Debian' {
       warning('This manifest is not supported on this OS.')
      }
      else {
       notify { 'Good to go!': }
      }
      

      Outra situação comum é quando você deseja condicionar a execução de um comando com base na saída de outro comando. Para casos como esse, você pode usar onlyif ou unless, como no exemplo abaixo. Este comando será executado apenas quando a saída de /bin/which php for bem-sucedida, ou seja, o comando sair com o status 0:

      exec { "Test":
       command => "/bin/echo PHP is installed here > /tmp/test.txt",
       onlyif => "/bin/which php"
      }
      

      Da mesma forma, unless irá executar o comando o tempo todo, exceto quando o comando sob unless sair com êxito:

      exec { "Test":
       command => "/bin/echo PHP is NOT installed here > /tmp/test.txt",
       unless => "/bin/which php"
      }
      

      Trabalhando com Templates

      Os templates geralmente são usados para definir arquivos de configuração, permitindo o uso de variáveis e outros recursos destinados a tornar esses arquivos mais versáteis e reutilizáveis. O Puppet suporta dois formatos diferentes para templates: Embedded Puppet (EPP) e Embedded Ruby (ERB). O formato EPP, no entanto, funciona apenas com versões recentes do Puppet (a partir da versão 4.0).

      Abaixo está um exemplo de um template ERB para configurar um virtual host no Apache, usando uma variável para configurar o document root para este host:

      <VirtualHost *:80>
          ServerAdmin webmaster@localhost
          DocumentRoot <%= @doc_root %>
      
          <Directory <%= @doc_root %>>
              AllowOverride All
              Require all granted
          </Directory>
      </VirtualHost>
      

      Para aplicar o template, precisamos criar um recurso file que processe o conteúdo do template com o método template. É assim que você aplicaria esse template para substituir o virtual host padrão do Apache:

      file { "/etc/apache2/sites-available/000-default.conf":
          ensure => "present",
          content => template("apache/vhost.erb") 
      }    
      

      O Puppet faz algumas suposições ao lidar com arquivos locais, a fim de reforçar a organização e a modularidade. Nesse caso, o Puppet procuraria um arquivo de template vhost.erb dentro de uma pasta apache/templates, dentro do seu diretório de módulos.

      Definindo e Acionando Serviços

      Os recursos de serviço são usados para garantir que os serviços sejam inicializados e ativados. Eles também são usados para acionar a reinicialização do serviço.

      Vamos levar em consideração o nosso exemplo anterior de uso de template, onde configuramos um virtual host no Apache. Se você deseja garantir que o Apache seja reiniciado após uma mudança no virtual host, primeiro crie um recurso service para o serviço Apache. É assim que esse recurso é definido no Puppet:

      service { 'apache2':
          ensure => running,
          enable => true
      }
      

      Agora, ao definir o recurso, você precisa incluir uma opção notify para acionar uma reinicialização:

      file { "/etc/apache2/sites-available/000-default.conf":
          ensure => "present",
          content => template("vhost.erb"),
          notify => Service['apache2'] 
      } 
      

      Manifest de Exemplo

      Agora, vamos dar uma olhada em um manifest que automatizará a instalação de um servidor Web Apache em um sistema Ubuntu 14.04, conforme discutido na introdução deste guia.

      O exemplo completo, incluindo o arquivo de template para configurar o Apache e um arquivo HTML para ser servido pelo servidor web, pode ser encontrado no Github. A pasta também contém um arquivo Vagrant que permite testar o manifest em uma configuração simplificada, usando uma máquina virtual gerenciada pelo Vagrant.

      Abaixo você pode encontrar o manifest completo:

      default.pp

      • $doc_root = "/var/www/example"
      • exec { 'apt-get update':
      • command => '/usr/bin/apt-get update'
      • }
      • package { 'apache2':
      • ensure => "installed",
      • require => Exec['apt-get update']
      • }
      • file { $doc_root:
      • ensure => "directory",
      • owner => "www-data",
      • group => "www-data",
      • mode => 644
      • }
      • file { "$doc_root/index.html":
      • ensure => "present",
      • source => "puppet:///modules/main/index.html",
      • require => File[$doc_root]
      • }
      • file { "/etc/apache2/sites-available/000-default.conf":
      • ensure => "present",
      • content => template("main/vhost.erb"),
      • notify => Service['apache2'],
      • require => Package['apache2']
      • }
      • service { 'apache2':
      • ensure => running,
      • enable => true
      • }

      Manifest Explicado

      linha 1

      O manifest começa com uma definição de variável, $doc_root. Essa variável é usada posteriormente em uma declaração de recurso.

      linhas 3-5

      Este recurso exec executa um comando apt-get update.

      linhas 7-10

      Este recurso package instala o pacote apache2, definindo que o recurso apt-get update é um requisito, o que significa que ele só será executado após a avaliação do recurso necessário.

      linhas 12-17

      Utilizamos um recurso file aqui para criar um novo diretório que servirá como document root. O recurso file pode ser usado para criar diretórios e arquivos, e também é usado para aplicar templates e copiar arquivos locais no servidor remoto. Esta tarefa pode ser executada em qualquer ponto do provisionamento, portanto, não precisamos definir nenhum require aqui.

      linhas 19-23

      Usamos outro recurso file aqui, desta vez para copiar nosso arquivo index.html local para o document root dentro do servidor. Usamos o parâmetro source para permitir que o Puppet saiba onde encontrar o arquivo original. Essa nomenclatura é baseada na maneira como o Puppet lida com arquivos locais; se você der uma olhada no repositório de exemplo do Github, você verá como a estrutura de diretórios deve ser criada para permitir que o Puppet encontre esse recurso. O diretório document root precisa ser criado antes da execução do recurso, e é por isso que incluímos uma opção require que faz referência ao recurso anterior.

      linhas 25-30

      Um novo recurso file é usado para aplicar o template do Apache e notificar o serviço para uma reinicialização. Neste exemplo, nosso provisionamento é organizado em um módulo chamado main, e é por isso que a origem do template é main/vhost.erb. Usamos uma instrução require para garantir que o recurso do template seja executado apenas após a instalação do pacote apache2, caso contrário, a estrutura de diretórios usada pelo Apache ainda não estará presente.

      linhas 32-35

      Finalmente, o recurso service declara o serviço apache2, que notificamos para reiniciar a partir do recurso que aplica o template de virtual host.

      Conclusão

      O Puppet é uma poderosa ferramenta de gerenciamento de configuração que usa uma DSL expressiva e personalizada para gerenciar recursos do servidor e automatizar tarefas. Sua linguagem oferece recursos avançados que podem dar flexibilidade extra às suas configurações de provisionamento; é importante lembrar que os recursos não são avaliados na mesma ordem em que são definidos e, por esse motivo, você precisa ter cuidado ao definir dependências entre os recursos para estabelecer a sequência de execução correta.

      No próximo guia desta série, veremos o Chef, outra ferramenta poderosa de gerenciamento de configuração que aproveita a linguagem de programação Ruby para automatizar a administração e o provisionamento da infraestrutura.



      Source link