>> Apresentação e considerações

Nesse post vamos brincar um pouco com o Puppet Autônomo que trabalha no modo ServerLess, ou seja, teremos em nosso Lab instalado somente o client do puppet, o intuito é o estudo para que possamos conhecer alguns dos principais resources que o puppet disponibiliza para que possamos começar a entender como eles trabalham de forma ainda bem básica.

Let’s go!!!

>> Pre-requisitos:

  • Sistema Operacional Linux
    No meu caso estou usando o Linux Mint 18 (Sarah), mais você pode usar qualquer distro.
  • Puppet agent instalado

>> Basicamente, o que é Puppet?

Criado em 2005, o Puppet é um utilitário de gerenciamento de configuração de software. O desenvolvimento do Puppet é coordenado pela Puppet Labs.

De acordo com a Puppet Labs, com o Puppet você define o estado que deseja sua infraestrutura de TI, e o Puppet forçará esse estado nela automaticamente, ou seja, de forma simplista criamos módulos e templates descrevendo todas as configurações que desejamos ter em nosso ambiente, e o Puppet garante que tudo estará de acordo com a “receita” que definimos.

O meu intuíto não é ir a fundo na teoria ou ir em detalhes mais específicos, mais sim apresentar de forma prática alguns resources para que possamos iniciar nossos estudos com Puppet

>> Instalação do Puppet Agent

No meu caso, como já possuia o pocote no repositório, executei o comando:

~# apt-get install puppet -y

Para mais detalhes a respeito da instalação do agent em outras distros, veja:
https://docs.puppet.com/puppet/4.10/install_linux.html

>> Gerenciando usuários e grupos – Resource user e group

O comando “puppet resource [user|group]” lista todos os usuários e grupos respectivamente mostrando os detalhes de configuração.

Aqui estou listando um grupo que existe que é o grupo “rodrigo” como podemos ver ele está “present” e temos a informação do gid do grupo

~# puppet  resource group rodrigo
  group { 'rodrigo':
  ensure => 'present',
  gid    => '1000',
}

Nesse comando estou listando o usuário “rodrigo” que é um usuário existente, inclusive o usuário que utilizo no meu sistema operacional, e como podemos ver temos diversas informações a respeito do meu usuário como home, shell, grupos, comentário entre outras coisas

~# puppet resource user rodrigo
user { 'rodrigo':
  ensure           => 'present',
  comment          => 'Rodrigo Floriano de Souza,,,',
  gid              => '1000',
  groups           => ['adm', 'cdrom', 'sudo', 'dip', 'plugdev', 'lpadmin', 'sambashare'],
  home             => '/home/rodrigo',
  password         => '$6$UjSJv8Sn$L/G4uM.5Xg8zGRCs7KxoNObXuVgwAi13QvAN7wPiiKKz7j5maX2v2GlzLDEkaANGHLTflgi31hhIj9M5yFQnq0',
  password_max_age => '99999',
  password_min_age => '0',
  shell            => '/bin/bash',
  uid              => '1000',
}

Nesse outro exemplo estou listando o usuário “daemon” que é um usuário de sistema e não possui login no shell

~# puppet resource user daemon
user { 'daemon':
  ensure           => 'present',
  comment          => 'daemon',
  gid              => '1',
  home             => '/usr/sbin',
  password         => '*',
  password_max_age => '99999',
  password_min_age => '0',
  shell            => '/usr/sbin/nologin',
  uid              => '1',
}

>> Criando o grupo e usuário “devops”

Aqui podemos ver que ao listar, o estado está como “absent”, ou seja, nem o grupo e nem o usuário não existe

~# puppet resource group devops
group { 'devops':
  ensure => 'absent',
}

~# puppet resource user devops
user { 'devops':
  ensure => 'absent',
}

Na criação do grupo definimos a garantia do estado com o “ensure” e definimos um “gid” para o grupo

~# puppet resource group ensure=present gid=5000
Notice: /Group[ensure=present]/ensure: created
group { 'ensure=present':
  ensure => 'present',
  gid    => '5000',
}

Na linha de comando criei o usuário “devops” garantindo que esteja presente com home e shell definido

Como o usuário foi criado, na saída do comando recebemos uma notificação:
“Notice: /User[devops]/ensure: created”, como o puppet é idempotente se executarmos o comando novamente ele não ira criar o usuário novamente

~# puppet resource user devops ensure=present comment="DevOps Admin" gid=5000 shell=/bin/bash home=/home/devops managehome=true
Notice: /User[devops]/ensure: created
user { 'devops':
  ensure  => 'present',
  comment => 'DevOps Admin',
  gid     => '5000',
  home    => '/home/devops',
  shell   => '/bin/bash',
}

Agora para remover o usuário trocamos o ensure de present para absent, com isso temos uma “Notice” informando que o usuário foi removido

~# puppet resource user devops ensure=absent
Notice: /User[devops]/ensure: removed
user { 'devops':
  ensure => 'absent',
}

Da mesma forma acontece com o grupo quando inserimos o ensure como “absent”

~# puppet resource user devops ensure=absent
Notice: /User[devops]/ensure: removed
user { 'devops':
  ensure => 'absent',
}

Para ver todas as opções possíveis para a manipulação de usuários e grupos no puppet segue o link das documentações oficiais:

https://docs.puppet.com/puppet/latest/types/user.html
https://docs.puppet.com/puppet/4.10/types/group.html

>> Gerenciando arquivos e diretórios – Resource file

Com o Puppet podemos gerenciar arquivos e diretórios de diferentes formas onde podemos garantir o seu estado, seja um arquivo ou diretório comum, link simbólico, Hard Link, dispositivo de bloco, dispositivo de caractere, enfim toda essa gerência pode ser realizar com o resource “file”.

Da mesma forma que no resource user, no resource file podemos visualizar o estado somente para ver seus atributos e configurações de acordo com a syntax do Puppet

Abaixo estou exibindo respectivamente o diretório, um arquivo comum e um link simbólico:

~# puppet  resource file /etc
file { '/etc':
  ensure => 'directory',
  ctime  => '2017-04-25 22:59:45 -0300',
  group  => '0',
  mode   => '755',
  mtime  => '2017-04-25 22:59:45 -0300',
  owner  => '0',
  type   => 'directory',
}

~# puppet  resource file /etc/hosts
file { '/etc/hosts':
  ensure  => 'file',
  content => '{md5}18b60a28c4f5020e431a181142d2fa15',
  ctime   => '2017-02-04 19:15:51 -0200',
  group   => '0',
  mode    => '644',
  mtime   => '2017-02-04 19:15:51 -0200',
  owner   => '0',
  type    => 'file',
}

~# puppet  resource file /etc/resolv.conf
file { '/etc/resolv.conf':
  ensure => 'link',
  ctime  => '2017-02-04 19:15:51 -0200',
  group  => '0',
  mode   => '777',
  mtime  => '2017-02-04 19:15:51 -0200',
  owner  => '0',
  target => '../run/resolvconf/resolv.conf',
  type   => 'link',
}

Agora que vimos como é a saída, vamos criar nosso diretório, nosso arquivo e nosso link simbólico.

~# puppet resource file /root/rdglinux ensure=directory owner=root group=root mode=755
Notice: /File[/root/rdglinux]/ensure: created
file { '/root/rdglinux':
  ensure => 'directory',
  group  => '0',
  mode   => '755',
  owner  => '0',
}

~# puppet resource file /root/rdglinux/arquivoteste.txt ensure=file owner=root group=root mode=755Notice: /File[/root/rdglinux/arquivoteste.txt]/ensure: created
file { '/root/rdglinux/arquivoteste.txt':
  ensure => 'file',
  group  => '0',
  mode   => '755',
  owner  => '0',
}

~# puppet resource file /root/rdglinux/linkteste.txt ensure=link target=/root/rdglinux/arquivoteste.txt
Notice: /File[/root/rdglinux/linkteste.txt]/ensure: created
file { '/root/rdglinux/linkteste.txt':
  ensure => 'link',
  target => '/root/rdglinux/arquivoteste.txt',
}

Conseguimos ver que o que criamos está ok através do comando ls e o comando tree.

~# ls -lhtr /root/rdglinux/
total 0
-rwxr-xr-x 1 root root  0 Abr 28 13:31 arquivoteste.txt
lrwxrwxrwx 1 root root 31 Abr 28 13:32 linkteste.txt -> /root/rdglinux/arquivoteste.txt

~# tree /root/rdglinux
/root/rdglinux
├── arquivoteste.txt
└── linkteste.txt -> /root/rdglinux/arquivoteste.txt

0 directories, 2 files

Removendo os recursos criados:

~# puppet resource file /root/rdglinux/linkteste.txt ensure=absent
Notice: /File[/root/rdglinux/linkteste.txt]/ensure: removed
file { '/root/rdglinux/linkteste.txt':
  ensure => 'absent',
}

~# puppet resource file /root/rdglinux/arquivoteste.txt ensure=absent
Notice: /File[/root/rdglinux/arquivoteste.txt]/ensure: removed
file { '/root/rdglinux/arquivoteste.txt':
  ensure => 'absent',
}

~# puppet resource file /root/rdglinux ensure=absent
Notice: /File[/root/rdglinux]: Not removing directory; use 'force' to override
Notice: /File[/root/rdglinux]/ensure: removed
file { '/root/rdglinux':
  ensure => 'directory',
}

Para maiores informações desse resource, acesse:

https://docs.puppet.com/puppet/latest/types/file.html

>> Gerenciando pacotes – Resource Package

O Resource Package serve para garantir o estado dos pacotes em um sistema, geralmente o puppet já entende qual será o gerenciador de pacotes a ser utilizado, ao executar uma instalação ele já reconhece os providers (gerenciadores de pacotes), com isso você pode executar a instalação em sistemas da família Debian, da família RHEL, da Família SuSE, entre muitas outras que podem ser vistas na documentação

Temos aqui como exemplo a listagem de 4 pacotes, e podemos ver que os dois primeiros estão com o estado “purged”, ou seja, não estão instalados, e os outros 2 estão com o ensure definido com a versão que está instalada do respectivo software

~# puppet resource package htop
package { 'htop':
  ensure => 'purged',
}

~# puppet resource package nmap
package { 'nmap':
  ensure => 'purged',
}

~# puppet resource package multitail
package { 'multitail':
  ensure => '6.4.2-1build1',
}

~# puppet resource package telnet
package { 'telnet':
  ensure => '0.17-40',
}

Abaixo segue um exemplo da instalação do pacote “htop”, ao executar sua instalação temos uma mensagem de “Notice” informando que o estado do pactote foi alterado de “purged” para “latest”, nesse caso estamos pedindo para que o pacote seja instalado em sua última versão de acordo com o repositório configurado

~# puppet resource package htop ensure=latest
Notice: /Package[htop]/ensure: ensure changed 'purged' to 'latest'
package { 'htop':
  ensure => '2.0.1-1ubuntu1',
}

Podemos também especificar a versão do pacotes que queremos que esteja instalada, essa pode ser uma opção mais segura em um ambiente produtivo pois uma atualização de determinados pacotes sem a devida verificação pode ser um risco

~# puppet resource package nginx ensure=1.10.0-0ubuntu0.16.04.4
Notice: /Package[nginx]/ensure: ensure changed 'purged' to '1.10.0-0ubuntu0.16.04.4'
package { 'nginx':
  ensure => '1.10.0-0ubuntu0.16.04.4',
}

Pra fechar abaixo estamos garantindo que o pacote nginx não esteja instalado em nosso sistema, no caso o pacote foi removido!

~# puppet resource package nginx ensure=absent
Notice: /Package[nginx]/ensure: removed
package { 'nginx':
  ensure => 'purged',
}

Para maiores informações do Resource Package veja o link abaixo:

https://docs.puppet.com/puppet/latest/types/package.html

>> Conclusão

Bom, é isso ae! …esse post é mais destinado aos iniciantes e aqueles que desejam conhecer um pouquinho de Puppet! …assim como nos outros posts, pretendo evoluir nessa sequência de Puppet conforme meus estudos disponibilizarei mais conteúdo! …

Elogios, críticas e sugestões serão bem vindas, se gostou compartilhe!

Muito obrigado a todos, abraço galera!