Chef-workstation, Chef-server, Chef-client via bootstrap

Seguindo o modelo DevOps o Chef é mais uma ferramenta presente no mercado, assim como Puppet, Ansible, SaltStack, para gerência de configuração, orquestração, manutenção e automatização da infraestrutura computacional. Grandes empresas ao redor do mundo como Facebook, Google, IBM, Microsoft, Yahoo entre muitas outras utilizam Chef para orquestração de seu ambiente.

Para este artigo iremos:

– Configurar o Chef-Workstation;
– Instalar o Chef DK no Chef-Workstatison;
– Configurar o Chef-server;
– Criar uma receita;
– Fazer o upload da receita no Chef-server;
– Conectar um Node no Chef-server;
– Fazer o deploy do Cookbook do Chef-server para os Nodes;

AMBIENTE

Chef-Workstation: Ubuntu 17.04 (zesty)
Chef-Server: Linux CentOS 7.3.1611 (Core)
Chef-Nodes: Linux CentOS 7.3.1611 (Core)

CHEF-WORKSTATION

No nosso Chef-Workstation (no caso meu notebook) vamos baixar e instalar o Chef-DK:

# wget https://packages.chef.io/files/stable/chefdk/2.4.17/ubuntu/14.04/chefdk_2.4.17-1_amd64.deb

Para o seu S.O procure a versão em: https://downloads.chef.io/chefdk

# dpkg -i chefdk_1.4.3-1_amd64.deb 
A seleccionar pacote anteriormente não seleccionado chefdk.
(Lendo banco de dados ... 312974 ficheiros e directórios actualmente instalados.)
A preparar para desempacotar chefdk_1.4.3-1_amd64.deb ...
A descompactar chefdk (1.4.3-1) ...
Configurando chefdk (1.4.3-1) ...
Thank you for installing Chef Development Kit!

Geramos o chef-repo, que é o nosso repositório, o local onde vamos guardar nossas receitas, metadados e etc:

# chef generate repo chef-repo

Ele cria a seguinte estrutura:

# ls -lStrh chef-repo/
total 32K
-rw-r--r-- 1 root root   70 out 16 23:33 LICENSE
-rw-r--r-- 1 root root 1,5K out 16 23:33 README.md
-rw-r--r-- 1 root root 1,2K out 16 23:33 chefignore
drwxr-xr-x 3 root root 4,0K out 16 23:33 data_bags
drwxr-xr-x 2 root root 4,0K out 16 23:33 roles
drwxr-xr-x 2 root root 4,0K out 16 23:33 environments
drwx------ 2 root root 4,0K out 21 22:04 nodes
drwxr-xr-x 5 root root 4,0K nov 19 10:26 cookbooks

Vamos criar um diretório oculto (.chef) para armazenarmos as chaves criptográficas que iremos criar para o nosso Chef-server.

# mkdir .chef

Feito isso agora vamos para o Chef-server.

CHEF-SERVER

Vamos baixar o pacote chef-server-core e efetuar sua instalação:

# wget https://packages.chef.io/files/stable/chef-server/12.15.7/el/7/chef-server-core-12.15.7-1.el7.x86_64.rpm

# rpm -ivh chef-server-core-12.15.7-1.el7.x86_64.rpm  

Feito isso vamos executar o seguinte comando:

# chef-server-ctl reconfigure

Este comando irá configurar todo o ambiente do Chef e levará vários minutos. Vamos criar aqui também um diretório oculto:

# mkdir .chef

Criamos um usuário administrativo para administrar o Chef com a senha mais difícil do mundo:

[root@chefserver .chef]# chef-server-ctl user-create tadeu Tadeu Bernacchi tbernacchi@gmail.com '123456' -f /root/.chef/tadeu.pem

E criamos uma organização associando o usuário criado no passo anterior:

[root@chefserver2 .chef]# chef-server-ctl org-create tabajara 'Tabajara Ltda' --association_user tadeu -f /root/.chef/tabajara.pem

Agora copiamos as chaves para o nosso Chef-Workstation:

[root@chefserver2 .chef]# scp *.pem tadeu@notebook:~
tadeu@notebook's password: 

E no Chef-Workstation movemos as chaves para o diretório do chef-repo:

[root@notebook tadeu]# mv *.pem /home/tadeu/Downloads/chef/chef-repo/.chef/

Com as chaves inseridas vamos configurar o Knife:

[root@notebook .chef]# knife configure 
Overwrite /root/.chef/knife.rb? (Y/N) y
Please enter the chef server URL: [https://notebook/organizations/myorg] https://chefserver2/organizations/tabajara
Please enter an existing username or clientname for the API: [tadeu] tadeu
Please enter the validation clientname: [chef-validator] tabajara-validator
Please enter the location of the validation key: [/etc/chef-server/chef-validator.pem] /home/tadeu/Downloads/chef/chef-repo/.chef/tabajara.pem
Please enter the path to a chef repository (or leave blank): /home/tadeu/Downloads/chef/chef-repo/
*****

You must place your client key in:
  /root/.chef/tadeu.pem
Before running commands with Knife

*****

You must place your validation key in:
  /home/tadeu/Downloads/chef/chef-repo/.chef/tabajara.pem
Before generating instance data with Knife

*****
Configuration file written to /root/.chef/knife.rb

O chef-server URL é possível obtê-lo no chef-server com o comando:

[root@chefserver2 .chef]# chef-server-ctl org-show 
tabajara: https://127.0.0.1/organizations/tabajara

A configuração do nosso Knife ficou assim:

[root@notebook tadeu]# cat /root/.chef/knife.rb 
log_level                :info
log_location             STDOUT
node_name                'tadeu'
client_key               '/root/.chef/tadeu.pem'
validation_client_name   'tabajara-validator'
validation_key           '/home/tadeu/Downloads/chef/chef-repo/.chef/tabajara.pem'
chef_server_url          'https://chefserver2/organizations/tabajara'
syntax_check_cache_path  '/root/.chef/syntax_check_cache'

Lembrando que precisamos também definir o path dos nossos cookbooks, vamos fazer isso adicionando a seguinte diretiva no knife.rb:

cookbook_path [ '/home/tadeu/Downloads/chef/chef-repo/cookbooks' ] 

E Voilá, terminos de configurar o knife. Também podemos setar o editor de texto que vai ser utilizado para configurar os nodes.

Exportando para o sistema:

[root@notebook:~]# export "EDITOR=vim"

Ou editando o knife.rb adicionando a seguinte linha:

knife[:editor]="vim"

Feito isso agora vamos garantir que a conexão entre o nosso Chef-Workstation e o nosso Chef-server seja feita de forma segura utilizando SSL:

[root@notebook .chef]# knife ssl fetch 
WARNING: Certificates from 192.168.30.102 will be fetched and placed in your trusted_cert
directory (/root/.chef/trusted_certs).

Knife has no means to verify these are the correct certificates. You should
verify the authenticity of these certificates after downloading.

Adding certificate for chefserver in /root/.chef/trusted_certs/chefserver.crt

https://www.chef.io/customers/
https://downloads.chef.io/chef-server 

E verificamos se foi validado com o comando:

[root@notebook chef-repo]# knife client list 
tabajara-validator
NODES

Agora vamos instalar nos nossos nodes o chef-client. Como estou utilizando um ambiente com Vagrant, o nome de usuário e senha são vagrant, mas para esse procedimento precisaremos de um usuário nos nodes com permissão de sudo.

[root@notebook tadeu]# knife bootstrap chefteste -x vagrant -P vagrant --sudo
Doing old-style registration with the validation key at /home/tadeu/Downloads/chef/chef-repo/.chef/tabajara.pem...
Delete your validation key in order to use your user credentials instead

Connecting to chefteste
chefteste -----> Installing Chef Omnibus (-v 12)
chefteste downloading https://omnitruck-direct.chef.io/chef/install.sh
chefteste   to file /tmp/install.sh.12936/install.sh
chefteste trying wget...
chefteste el 7 x86_64
chefteste Getting information for chef stable 12 for el...
chefteste downloading https://www.chef.io/stable/chef/metadata?v=12&p=el&pv=7&m=x86_64
chefteste   to file /tmp/install.sh.12941/metadata.txt
chefteste trying wget...
chefteste sha1	2d78a2f463c0d3d7ed867a50a9460650b196e251
chefteste sha256	b2b8c16b92d65d003ee07f1f30a456b573a8cdddf6ba66e4afba42d44060492a
chefteste url	https://packages.chef.io/files/stable/chef/12.20.3/el/7/chef-12.20.3-1.el7.x86_64.rpm
chefteste version	12.20.3
chefteste downloaded metadata file looks valid...
chefteste downloading https://packages.chef.io/files/stable/chef/12.20.3/el/7/chef-12.20.3-1.el7.x86_64.rpm
chefteste   to file /tmp/install.sh.12941/chef-12.20.3-1.el7.x86_64.rpm
chefteste trying wget...
chefteste Comparing checksum with sha256sum...
chefteste Installing chef 12
chefteste installing with rpm...
chefteste aviso: /tmp/install.sh.12941/chef-12.20.3-1.el7.x86_64.rpm: Cabeçalho V4 DSA/SHA1 Signature, ID da chave 83ef826a: NOKEY
chefteste Preparando...                         ################################# [100%]
chefteste Updating / installing...
chefteste    1:chef-12.20.3-1.el7               ################################# [100%]
chefteste Thank you for installing Chef!
...
...
...
chefteste Chef Client finished, 0/0 resources updated in 05 seconds

Obs: Após o final da instalação percebemos algumas mensagens de “HTTP Request Returned 404 Not Found”, isso é normal por não estarmos utilizando o Chef-Automate na nossa infra.

Instalação terminada agora vamos verificar se o nosso Chef-Workstation consegue “enxergar” nosso node “chefteste”:

[root@notebook tadeu]# knife node list
chefteste

Para mais informações:

[root@notebook tadeu]# knife node show chefteste
1 items found

Node Name:   chefteste
Environment: _default
FQDN:        chefteste
IP:          10.0.2.15
Run List:    
Roles:       
Recipes:     
Platform:    centos 7.3.1611
Tags: 

Tudo OK, lindo. Agora vamos criar nosso primeiro cookbook:

[root@notebook tadeu]# cd Downloads/chef/chef-repo/cookbooks
[root@notebook cookbooks]# chef generate cookbook editors
Generating cookbook editors
- Ensuring correct cookbook file content
- Ensuring delivery configuration
- Ensuring correct delivery build cookbook content

Your cookbook is ready. Type `cd editors` to enter it.

There are several commands you can run to get started locally developing and testing your cookbook.
Type `delivery local --help` to see a full list.

Why not start by writing a test? Tests for the default recipe are stored at:

test/smoke/default/default_test.rb

If you'd prefer to dive right in, the default recipe can be found at:

recipes/default.rb

Vamos verificar a sua estrutura:

[root@notebook cookbooks]# tree .  
.
└── editors
    ├── Berksfile
    ├── chefignore
    ├── LICENSE
    ├── metadata.rb
    ├── README.md
    ├── recipes
    │   └── default.rb
    ├── spec
    │   ├── spec_helper.rb
    │   └── unit
    │       └── recipes
    │           └── default_spec.rb
    └── test
        └── smoke
            └── default
                └── default_test.rb

8 directories, 9 files

No diretório do cookbook vamos criar três receitas para o cookbook “editors”.

[root@notebook: recipes]# touch vim.rb emacs.rb nano.rb

Cada uma com o seguinte conteúdo:

[root@notebook: recipes]# cat *.rb 
#
# Cookbook:: editors
# Recipe:: default
#
# Copyright:: 2017, The Authors, All Rights Reserved.
package 'emacs'do 
  action :install 
end

package 'nano' do 
  action :install 
end 

package 'vim' do 
  action :install
end 

Podemos verificar a sintaxe do cookbook com o comando:

[root@notebook: cookbooks]# cookstyle editors/recipes/* 
Inspecting 4 files
....

4 files inspected, no offenses detected

Sintaxe ok, agora vamos fazer o upload desse cookbook para o nosso Chef-server:

[root@notebook: editors]# knife cookbook upload editors
Uploading editors      [0.1.0]
Uploaded 1 cookbook.

No nosso node que será aplicado o cookbook podemos verificar que ainda não há nenhuma run_list:

[root@notebook: editors]# knife node show cheftest
Node Name:   cheftest
Environment: _default
FQDN:        chefnode1
IP:          10.0.2.15
Run List:    
Roles:       
Recipes:     
Platform:    centos 7.3.1611
Tags: 

Vamos inserir uma receita desse cookbook para ser executa (run_list) nesse node:

[root@notebook: editors]# knife node run_list add chefnode1 "recipe[editors::vim]" 
chefnode1:
  run_list: recipe[editors::vim]

Estamos dizendo para o chef incluir o cookbook “editors” com a receita “vim” para ser executada nesse host. Verificamos:

[root@notebook recipes]# knife node show chefteste
Node Name:   cheftest
Environment: _default
FQDN:        cheftest
IP:          10.0.2.15
Run List:    recipe[editors::vim]
Roles:       
Recipes:     
Platform:    centos 7.3.1611
Tags:

Para verificar os cookbooks disponíveis:

[root@notebook: editors]# knife cookbook list 
editors   0.1.0

Para remover um “run_list” de um node:

[root@notebook: editors]# knife node run_list remove chefnode1 "recipe[editors::nano]" 
chefnode1:
  run_list: recipe[editors::vim]

Para remover um cookbook:

[root@notebook cookbooks]# knife cookbook delete tcpdump
Do you really want to delete tcpdump version 0.1.0? (Y/N) y
Deleted cookbook[tcpdump version 0.1.0]
CHEF-CLIENT

Agora no nosso node chefteste:

[root@chefteste ~]# which vim 
/usr/bin/which: no vim in (/sbin:/bin:/usr/sbin:/usr/bin)

Nenhum pacote vim está instalado, vamos executar o chef-client com a opção -W (que simula o chef-client e mostra quais as alterações que serão feitas no node):

[root@chefnode1 ~]# chef-client -W
Starting Chef Client, version 13.6.0
resolving cookbooks for run list: ["editors::vim"]
Synchronizing Cookbooks:
  - editors (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 1 resources
Recipe: editors::vim
  * yum_package[vim] action install
    - Would install version 7.4.160-2.el7 of package vim-enhanced
[2017-11-06T00:04:44+00:00] WARN: In why-run mode, so NOT performing node save.

Running handlers:
Running handlers complete
Chef Client finished, 1/1 resources would have been updated

A saída do comando mostra que o editor de textos vim seria instalado com sucesso. Um outro exemplo bacana do conceito de recipes é a instalação de somente uma determinada receita de um cookbook.

[root@chefnode1 ~]# chef-client -r "recipe[editors::nano]" 
Starting Chef Client, version 13.6.0
resolving cookbooks for run list: ["editors::nano"]
Synchronizing Cookbooks:
  - editors (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 1 resources
Recipe: editors::nano
  * yum_package[nano] action install
    - install version 2.3.1-10.el7 of package nano

Running handlers:
Running handlers complete
Chef Client finished, 1/1 resources updated in 17 seconds

Verificamos:

[root@chefnode1 ~]# which nano 
/bin/nano

Também podemos criar uma receita com o comando:

[root@notebook: editors]# chef generate recipe teste
Recipe: code_generator::recipe
  * directory[/home/tadeu/chef/chef-repo/cookbooks/editors/spec/unit/recipes] action create (up to date)
  * cookbook_file[/home/tadeu/chef/chef-repo/cookbooks/editors/spec/spec_helper.rb] action create_if_missing (up to date)
  * template[/home/tadeu/chef/chef-repo/cookbooks/editors/spec/unit/recipes/teste_spec.rb] action create_if_missing
    - create new file /home/tadeu/chef/chef-repo/cookbooks/editors/spec/unit/recipes/teste_spec.rb
    - update content in file /home/tadeu/chef/chef-repo/cookbooks/editors/spec/unit/recipes/teste_spec.rb from none to a9da73
    (diff output suppressed by config)
  * directory[/home/tadeu/chef/chef-repo/cookbooks/editors/test/smoke/default] action create (up to date)
  * template[/home/tadeu/chef/chef-repo/cookbooks/editors/test/smoke/default/teste_test.rb] action create_if_missing
    - create new file /home/tadeu/chef/chef-repo/cookbooks/editors/test/smoke/default/teste_test.rb
    - update content in file /home/tadeu/chef/chef-repo/cookbooks/editors/test/smoke/default/teste_test.rb from none to 9124ab
    (diff output suppressed by config)
  * template[/home/tadeu/chef/chef-repo/cookbooks/editors/recipes/teste.rb] action create
    - create new file /home/tadeu/chef/chef-repo/cookbooks/editors/recipes/teste.rb
    - update content in file /home/tadeu/chef/chef-repo/cookbooks/editors/recipes/teste.rb from none to 9a0d47
    (diff output suppressed by config)

Para criar receitas com este comando é preciso estar dentro do respectivo cookbook. Podemos utilizar também do método include_recipe, que é a chamada das receitas dentro do nosso arquivo default.rb. Ex:

[root@notebook: editors]# cat recipes/default.rb 
#
# Cookbook:: editors
# Recipe:: default
#
# Copyright:: 2017, The Authors, All Rights Reserved.
include_recipe 'editors::vim'
include_recipe 'editors::nano'
include_recipe 'editors::emacs'

Subimos o cookbook e no nosso node executamos:

[root@chefnode1 ~]# chef-client -r "recipe[editors]" 
Starting Chef Client, version 13.6.0
resolving cookbooks for run list: ["editors"]
Synchronizing Cookbooks:
  - editors (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 3 resources
Recipe: editors::vim
  * yum_package[vim] action install
    - install version 7.4.160-2.el7 of package vim-enhanced
Recipe: editors::nano
  * yum_package[nano] action install
    - install version 2.3.1-10.el7 of package nano
Recipe: editors::emacs
  * yum_package[emacs] action install
    - install version 24.3-20.el7_4 of package emacs

Running handlers:
Running handlers complete
Chef Client finished, 3/3 resources updated in 02 minutes 54 seconds

Que é a chamada do cookbook editors com a receita default. Terminado o chef-client verificamos os pacotes instalados:

[root@chefnode1 ~]# which vim 
/bin/vim
[root@chefnode1 ~]# which nano
/bin/nano
[root@chefnode1 ~]# which emacs
/bin/emacs

Para adicionarmos um host para ser gerenciado pelo nosso Chef-server:

[root@notebook: editors]# knife node create chefteste

Para removermos um host do Chef-server:

[root@notebook: editors]# knife node delete chefteste

CONCLUSÃO

Como ainda estou me aventurando nesse mundo das ferramentas DevOps, conheci o Chef através do canal LinuxTips no YouTube, o Chef me pareceu um pouco mais complicado em relação ao Ansible, (Minha primeira ferramenta de CM que tive contato) sua instalação, e também sua estrutura, Chef-server, Chef-Automate me pareceram mais complexas e me deixaram com algumas dúvidas, mas como foi meu primeiro contato com esse software e pretendo estudá-lo mais a fundo com o passar no tempo foi bem legal poder interagir com a ferramenta e poder conhecer sua estrutura de funcionamento, sua configuração, comandos e etc. Futuramente pretendo colocar aqui mais coisas sobre o Chef, como a instalação e configuração do Data Collector (Chef-Automate), o Chef-Manage (API do Chef) assim como utilizar o Supermarket do Chef, seu repositório oficial de receitas.

Referências:
https://www.chef.io
https://docs.chef.io/workstation.html
https://docs.chef.io/server_components.html
https://docs.chef.io/errors.html
https://downloads.chef.io/chefdk
https://downloads.chef.io/chef-server
https://www.youtube.com/watch?v=0Mp3iJSYXlY