Puppet – Instalação e configuração do Mcollective, plugins e orquestração de clientes

Como instalar o Mcollective para fazer a orquestração de clientes.

1. Introdução

Para este tutorial você precisa ter Puppet Server funcionando.
Como instalar o Puppet Server e Puppet cliente

O puppet-agent é all-in-one, ele já contém o Mcollective, Hiera, Facter, e Puppet, sendo assim você não precisa instalar os pacotes mcollective-* como acontecia nas versões < Puppet 4.x.x. O Mcollective precisa de um serviço de mensageria, que é uma camada middleware para troca mensagens entre aplicações conhecido como “Broker”; neste caso vamos utilizar o serviço de mensageria Apache ActiveMQ, ou simplesmente ActiveMQ.
Também tem como opção o RabbitMQ, porém não será abordado neste tutorial.

2. Infraestrutura e pré-requisitos

Segue abaixo a infraestrutura utilizada neste lab, para que você utilize como exemplo.

Puppet Server: puppetserver-01.devopslab.com.br
Nodes/Clientes: puppetclient-01.devopslab.com.br, puppetclient-02.devopslab.com.br
S.O: Centos 7 – 64 bits instalação mínima.
Aplicações: puppetserver 2.2.1
puppet 4.3.2
puppet-agent 1.3.5

3. Instalação do ActiveMQ

No servidor do Puppet Server instale o repositório:

#rpm -hiv https://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm

Instale o ActiveMQ.

# yum install activemq

Configuração. Definição de usuário e senha.

# vi /etc/activemq/credentials.properties
activemq.username=mcollective
activemq.password=marionette

O usuário e senha pode ser a que você quiser ok, aqui vou seguir o padrão do mcollective.

Crie um nome para a fila de mensagens do ActiveMQ.
Neste caso criei como: ‘brokerName=”puppetserver-01.devopslab.com.br”‘.

# vi /etc/activemq/activemq.xml

<broker xmlns="http://activemq.apache.org/schema/core" brokerName="puppetserver-01.devopslab.com.br" dataDirectory="${activemq.data}"> 

Ainda no arquivo activemq.xml altere as configurações de memória e storage. O ActiveMQ vem configurado para utilizar 100GB de armazenamento, e para arquivos temporários ele pede 50GB de espaço, não convém utilizar tudo isto para um lab, então deixe mais ou menos assim:

# vi /etc/activemq/activemq.xml

<systemUsage>
            <systemUsage>
                <memoryUsage>
                    <memoryUsage percentOfJvmHeap="40" />
                </memoryUsage>
                <storeUsage>
                    <storeUsage limit="1 gb"/>
                </storeUsage>
                <tempUsage>
                    <tempUsage limit="500 mb"/>
                </tempUsage>
            </systemUsage>
        </systemUsage>

Segue todo meu arquivo activemq.xml.

<!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    this work for additional information regarding copyright ownership.
    The ASF licenses this file to You under the Apache License, Version 2.0
    (the "License"); you may not use this file except in compliance with
    the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<!-- START SNIPPET: example -->
<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">

    <!-- Allows us to use system properties as variables in this configuration file -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <value>file:${activemq.conf}/credentials.properties</value>
        </property>
    </bean>

    <!--
        The <broker> element is used to configure the ActiveMQ broker.
    -->
    <broker xmlns="http://activemq.apache.org/schema/core" brokerName="puppetserver-01.devopslab.com.br" dataDirectory="${activemq.data}">

        <destinationPolicy>
            <policyMap>
              <policyEntries>
                <policyEntry topic=">" >
                    <!-- The constantPendingMessageLimitStrategy is used to prevent
                         slow topic consumers to block producers and affect other consumers
                         by limiting the number of messages that are retained
                         For more information, see:

                         http://activemq.apache.org/slow-consumer-handling.html

                    -->
                  <pendingMessageLimitStrategy>
                    <constantPendingMessageLimitStrategy limit="1000"/>
                  </pendingMessageLimitStrategy>
                </policyEntry>
              </policyEntries>
            </policyMap>
        </destinationPolicy>


        <!--
            The managementContext is used to configure how ActiveMQ is exposed in
            JMX. By default, ActiveMQ uses the MBean server that is started by
            the JVM. For more information, see:

            http://activemq.apache.org/jmx.html
        -->
        <managementContext>
            <managementContext createConnector="false"/>
        </managementContext>

        <!--
            Configure message persistence for the broker. The default persistence
            mechanism is the KahaDB store (identified by the kahaDB tag).
            For more information, see:

            http://activemq.apache.org/persistence.html
        -->
        <persistenceAdapter>
            <kahaDB directory="${activemq.data}/kahadb"/>
        </persistenceAdapter>


          <!--
            The systemUsage controls the maximum amount of space the broker will
            use before disabling caching and/or slowing down producers. For more information, see:
            http://activemq.apache.org/producer-flow-control.html
          -->
          <systemUsage>
            <systemUsage>
                <memoryUsage>
                    <memoryUsage percentOfJvmHeap="40" />
                </memoryUsage>
                <storeUsage>
                    <storeUsage limit="1 gb"/>
                </storeUsage>
                <tempUsage>
                    <tempUsage limit="500 mb"/>
                </tempUsage>
            </systemUsage>
        </systemUsage>

        <!--
            The transport connectors expose ActiveMQ over a given protocol to
            clients and other brokers. For more information, see:

            http://activemq.apache.org/configuring-transports.html
        -->
        <transportConnectors>
            <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
        </transportConnectors>

        <!-- destroy the spring context on shutdown to stop jetty -->
        <shutdownHooks>
            <bean xmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.hooks.SpringContextHook" />
        </shutdownHooks>

    </broker>

    <!--
        Enable web consoles, REST and Ajax APIs and demos
        The web consoles requires by default login, you can disable this in the jetty.xml file

        Take a look at ${ACTIVEMQ_HOME}/conf/jetty.xml for more details
    -->
    <import resource="jetty.xml"/>

</beans>
<!-- END SNIPPET: example -->

Firewall
Libere a porta do ActiveMQ 61613/tcp no Firewall.

# firewall-cmd --permanent --add-port=61613/tcp
# systemctl reload firewalld

Inicie e habilite o ActiveMQ.

# systemctl enable activemq.service
# systemctl start activemq.service

Verificação dos logs do ActiveMQ.
# tail -f /var/log/activemq/activemq.log

2016-02-26 22:30:02,416 [main           ] INFO  XBeanBrokerFactory$1           - Refreshing org.apache.activemq.xbean.XBeanBrokerFactory$1@36f6e879: startup date [Fri Feb 26 22:30:02 BRT 2016]; root of context hierarchy
2016-02-26 22:30:03,395 [main           ] INFO  PListStoreImpl                 - PListStore:[/usr/share/activemq/data/puppetserver-01.devopslab.com.br/tmp_storage] started
2016-02-26 22:30:03,435 [main           ] INFO  BrokerService                  - Using Persistence Adapter: KahaDBPersistenceAdapter[/usr/share/activemq/data/kahadb]
2016-02-26 22:30:03,767 [main           ] INFO  MessageDatabase                - KahaDB is version 5
2016-02-26 22:30:03,789 [main           ] INFO  MessageDatabase                - Recovering from the journal ...
2016-02-26 22:30:03,803 [main           ] INFO  MessageDatabase                - Recovery replayed 355 operations from the journal in 0.024 seconds.
2016-02-26 22:30:03,951 [main           ] INFO  BrokerService                  - Apache ActiveMQ 5.9.1 (puppetserver-01.devopslab.com.br, ID:puppetserver-01-39882-1456536603823-0:1) is starting
2016-02-26 22:30:04,021 [main           ] INFO  TransportServerThreadSupport   - Listening for connections at: tcp://puppetserver-01:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600
2016-02-26 22:30:04,022 [main           ] INFO  TransportConnector             - Connector openwire started
2016-02-26 22:30:04,025 [main           ] INFO  TransportServerThreadSupport   - Listening for connections at: amqp://puppetserver-01:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600
2016-02-26 22:30:04,026 [main           ] INFO  TransportConnector             - Connector amqp started
2016-02-26 22:30:04,029 [main           ] INFO  TransportServerThreadSupport   - Listening for connections at: stomp://puppetserver-01:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600
2016-02-26 22:30:04,030 [main           ] INFO  TransportConnector             - Connector stomp started
2016-02-26 22:30:04,035 [main           ] INFO  TransportServerThreadSupport   - Listening for connections at: mqtt://puppetserver-01:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600
2016-02-26 22:30:04,035 [main           ] INFO  TransportConnector             - Connector mqtt started
2016-02-26 22:30:04,130 [main           ] INFO  Server                         - jetty-7.6.9.v20130131
2016-02-26 22:30:04,160 [main           ] INFO  ContextHandler                 - started o.e.j.s.ServletContextHandler{/,null}
2016-02-26 22:30:04,191 [main           ] INFO  AbstractConnector              - Started SelectChannelConnector@0.0.0.0:61614
2016-02-26 22:30:04,191 [main           ] INFO  WSTransportServer              - Listening for connections at ws://puppetserver-01:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600
2016-02-26 22:30:04,192 [main           ] INFO  TransportConnector             - Connector ws started
2016-02-26 22:30:04,193 [main           ] INFO  BrokerService                  - Apache ActiveMQ 5.9.1 (puppetserver-01.devopslab.com.br, ID:puppetserver-01-39882-1456536603823-0:1) started
2016-02-26 22:30:04,193 [main           ] INFO  BrokerService                  - For help or more information please see: http://activemq.apache.org
2016-02-26 22:30:04,350 [main           ] INFO  Server                         - jetty-7.6.9.v20130131
2016-02-26 22:30:04,578 [main           ] INFO  ContextHandler                 - started o.e.j.w.WebAppContext{/admin,file:/var/lib/activemq/webapps/admin/}
2016-02-26 22:30:04,710 [main           ] INFO  /admin                         - Initializing Spring FrameworkServlet 'dispatcher'
2016-02-26 22:30:04,761 [main           ] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/createDestination.action] onto handler '/createDestination.action'
2016-02-26 22:30:04,762 [main           ] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/deleteDestination.action] onto handler '/deleteDestination.action'
2016-02-26 22:30:04,762 [main           ] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/createSubscriber.action] onto handler '/createSubscriber.action'
2016-02-26 22:30:04,762 [main           ] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/deleteSubscriber.action] onto handler '/deleteSubscriber.action'
2016-02-26 22:30:04,762 [main           ] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/sendMessage.action] onto handler '/sendMessage.action'
2016-02-26 22:30:04,762 [main           ] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/purgeDestination.action] onto handler '/purgeDestination.action'
2016-02-26 22:30:04,763 [main           ] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/deleteMessage.action] onto handler '/deleteMessage.action'
2016-02-26 22:30:04,763 [main           ] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/copyMessage.action] onto handler '/copyMessage.action'
2016-02-26 22:30:04,763 [main           ] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/moveMessage.action] onto handler '/moveMessage.action'
2016-02-26 22:30:04,763 [main           ] INFO  ndingBeanNameUrlHandlerMapping - Mapped URL path [/deleteJob.action] onto handler '/deleteJob.action'
2016-02-26 22:30:04,885 [main           ] INFO  WebAppContext                  - ActiveMQ Console at http://0.0.0.0:8161/admin
2016-02-26 22:30:04,893 [main           ] INFO  ContextHandler                 - started o.e.j.w.WebAppContext{/camel,file:/var/lib/activemq/webapps/camel}
2016-02-26 22:30:04,897 [main           ] INFO  WebAppContext                  - WebApp@5395829 at http://0.0.0.0:8161/camel
2016-02-26 22:30:04,905 [main           ] INFO  ContextHandler                 - started o.e.j.w.WebAppContext{/demo,file:/var/lib/activemq/webapps/demo}
2016-02-26 22:30:04,907 [main           ] INFO  WebAppContext                  - WebApp@5395829 at http://0.0.0.0:8161/demo
2016-02-26 22:30:04,914 [main           ] INFO  ContextHandler                 - started o.e.j.w.WebAppContext{/fileserver,file:/var/lib/activemq/webapps/fileserver}
2016-02-26 22:30:04,918 [main           ] INFO  WebAppContext                  - WebApp@5395829 at http://0.0.0.0:8161/fileserver
2016-02-26 22:30:04,922 [main           ] INFO  AbstractConnector              - Started SelectChannelConnector@0.0.0.0:8161

Veja nos logs que o ActiveMQ foi iniciado com sucesso “starded”.

Verifique o bind da porta 61613, tem que estar escutando.

# netstat -tnpau| grep 61613
tcp6       0      0  :::61613		:::*	LISTEN	5075/java

4. Configuração do Mcollective Server e Cliente

Para a configuração do Mcollective Server e client basta fazer os devidos ajustes nos arquivos client.cfg e server.cfg do Mcollective.

Fique atento as linhas:

plugin.activemq.pool.1.host = puppetserver-01.devopslab.com.br
plugin.activemq.pool.1.port = 61613
plugin.activemq.pool.1.user = mcollective
plugin.activemq.pool.1.password = marionette

# vi /etc/puppetlabs/mcollective/server.cfg

main_collective = mcollective
collectives = mcollective

libdir = /opt/puppetlabs/mcollective/plugins

# consult the "classic" libdirs too
libdir = /usr/share/mcollective/plugins
libdir = /usr/libexec/mcollective

logfile = /var/log/puppetlabs/mcollective.log
loglevel = info
daemonize = 1

# Plugins
securityprovider = psk
plugin.psk = unset

connector = activemq
plugin.activemq.pool.size = 1
plugin.activemq.pool.1.host = puppetserver-01.devopslab.com.br
plugin.activemq.pool.1.port = 61613
plugin.activemq.pool.1.user = mcollective
plugin.activemq.pool.1.password = marionette
#plugin.activemq.pool.1.ssl = false

# Facts
factsource = yaml
plugin.yaml = /etc/puppetlabs/mcollective/facts.yaml

Configuração do Mcollective cliente.
# vi /etc/puppetlabs/mcollective/client.cfg

main_collective = mcollective
collectives = mcollective

libdir = /opt/puppetlabs/mcollective/plugins

# consult the "classic" libdirs too
libdir = /usr/share/mcollective/plugins
libdir = /usr/libexec/mcollective

logger_type = console
loglevel = warn

# Plugins
securityprovider = psk
plugin.psk = unset

connector = activemq
plugin.activemq.pool.size = 1
plugin.activemq.pool.1.host = puppetserver-01.devopslab.com.br
plugin.activemq.pool.1.port = 61613
plugin.activemq.pool.1.user = mcollective
plugin.activemq.pool.1.password = marionette

connection_timeout = 3

Reinicie o Mcollective.

# systemctl start mcollective.service
# systemctl enable mcollective.service

O Log do Mcollective tem que ter uma saída parecida a esta:
#tail –f /var/log/puppetlabs/mcollective.log

^[[AI, [2016-02-26T22:47:36.675684 #5211]  INFO -- : config.rb:167:in `loadconfig' The Marionette Collective version 2.8.7 started by /opt/puppetlabs/puppet/bin/mcollectived using config file /etc/puppetlabs/mcollective/server.cfg
I, [2016-02-26T22:47:36.675875 #5211]  INFO -- : mcollectived:64:in `<main>' The Marionette Collective 2.8.7 started logging at info level
I, [2016-02-26T22:47:36.679816 #5218]  INFO -- : activemq.rb:211:in `initialize' ActiveMQ connector initialized.  Using stomp-gem 1.3.3
I, [2016-02-26T22:47:36.681132 #5218]  INFO -- : activemq.rb:313:in `connection_headers' Connecting without STOMP 1.1 heartbeats, if you are using ActiveMQ 5.8 or newer consider setting plugin.activemq.heartbeat_interval
I, [2016-02-26T22:47:36.681669 #5218]  INFO -- : activemq.rb:114:in `on_connecting' TCP Connection attempt 0 to stomp://mcollective@puppetserver-01.devopslab.com.br:61613
I, [2016-02-26T22:47:36.690413 #5218]  INFO -- : activemq.rb:119:in `on_connected' Connected to stomp://mcollective@puppetserver-01.devopslab.com.br:61613

Veja que o Mcollective se conecta no ActiveMQ.

4.1 Configuração dos nodes/clientes da Rede

Copie o arquivo “client.cfg” e “server.cfg” para a pasta “/etc/puppetlabs/mcollective” de todos os seus clientes e reinicie o mcollective.

# systemctl start mcollective.service
# systemctl enable mcollective.service

5. Teste de funcionamento do Mcollective

Configurado o Mcollective no servidor do Puppet Server e configurados todos os clientes da rede, faça o Login no servidor Puppet Server e teste o Mcollective com o comando mco.

[root@puppetserver-01 ~]# mco find
puppetserver-01
puppetclient-02
puppetclient-01

[root@puppetserver-01 ~]# mco ping 
puppetserver-01                          time=23.88 ms
puppetclient-02                          time=64.69 ms
puppetclient-01                          time=65.56 ms
---- ping statistics ----
3 replies max: 65.56 min: 23.88 avg: 51.37

Foram descobertos 3 clientes Mcollective. Este é o funcionamento básico do Mcollective, que é o teste de comunicação “ping”, porém isto ainda não é a orquestração, ou seja, ainda não é possível executar comandos nos hosts, gerenciar o puppet e etc, para isto necessita-se da instalação de plug-ins.

6. Instalação de Plugins Mcollective – Plugin Puppet

Existem vários plug-ins que controlam vários aspectos do sistema.
Consulte aqui os tipos de plug-ins do Mcollective:
https://docs.puppetlabs.com/mcollective/deploy/plugins.html#about-plugins–available-plugin-types

Existem duas formas de instalar os plug-ins do Mcollective.
A primeira é através dos repositórios da PuppetLabs, que é o que vamos utilizar aqui, simplesmente rodando o comando “yum install plugin***”.

A segunda forma é copiando os arquivos os arquivos de configurações e executáveis (.erb, .rb, .dll) para as pastas das bibliotecas do Mcollective. Esta é a forma mais difícil, porém alguns plugins só podem ser instalados desta forma.

Vamos começar instalando os plug-ins para o gerenciamento remoto do Puppet.

Instale o repositório abaixo tanto no Puppet Server como nos nodes/clientes.

# rpm -hiv https://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm

Puppet Server
No Puppet Server instale os Plugins: mcollective-puppet-client e mcollective-puppet-common.

[root@puppetserver-01 /]# yum install mcollective-puppet-client mcollective-puppet-common

No pacote “mcollective-puppet-client” entenda o “client” como se fosse a máquina que vai executar os comandos de orquestração, neste caso o Puppet Server vai executar a orquestração dos clientes.

Nodes/Clientes
Nos nodes/clientes instale os plug-ins: mcollective-puppet-agent e mcollective-puppet-common.

[root@puppetclient-01 /]# yum install mcollective-puppet-agent mcollective-puppet-common

No pacote “mcollective-puppet-agent” entenda o “agent” como sendo os hosts que vão receber os comandos de orquestração, sendo assim o “agent” vai ficar esperando os comandos de orquestração do cliente (Puppet Server).

Após ter instalado os plug-ins, reinicie o Mcollective.

# systemctl restart mcollective.service

6.1 Teste de Orquestração via Mcollective

Acabamos de configurar o Puppet Server e todos os clientes, sendo assim vamos testar, faça o login no Puppet Server para realizarmos alguns testes.

A. Consultar o status do Puppet nos clientes.

[root@puppetserver-01 ~]# mco puppet status -I puppetclient-01
 * [ ============================================================> ] 1 / 1
   puppetclient-01: Currently idling; last completed run 22 minutes 39 seconds ago
Summary of Applying:
   false = 1
Summary of Daemon Running:
   running = 1
Summary of Enabled:
   enabled = 1
Summary of Idling:
   true = 1
Summary of Status:
   idling = 1
Finished processing 1 / 1 hosts in 21.67 ms

B. Re-executar o Puppet em um cliente para que ele verifique o server por novas alterações.
Imagine que você criou uma nova configuração no Puppet Server, por exemplo a edição do arquivo de hosts dos clientes, e quer forçar a aplicação das alterações, para isto você vai executar um “runonce”. Veja:

[root@puppetserver-01 ~]# mco puppet runonce -I puppetclient-01 -I puppetclient-02
 * [ ============================================================> ] 2 / 2
Finished processing 2 / 2 hosts in 125.00 ms

Para saber todas as opções do comando “mco puppet” consulte o help.

# mco help puppet

Finalizamos a orquestração com Mcollective.
Para resumir o funcionamento do Mcollective você precisa ter instalado o ActiveMQ, configurado os arquivos server.cfg e client.cfg e instalação dos Plugins.

Atente-se para a diferença entre “mcollective-puppet-client” e “mcollective-puppet-agent”.

Conforme mencionado neste tutorial, existem vários plugins, por exemplo tem um Plugin que permite a execução de comandos via shell, muito legal este, pois é possível executar comandos do Linux via Mcollective.

Tem também um plugin do Facter, que permite consultar dados do sistema, fazer um inventário, como por exemplo verificar quantas CPUs, Memória, quais os IPs, interface de rede, versão de S.O, qualquer informação sobre o sistema operacional.

Leia: Tutorial Instalação e utilização do plugin Facter

Até a próxima.

Leonardo Macedo Cerqueira

Flannel+Etcd+Docker – Como criar e configurar uma sub-rede para fazer a comunicação entre containers Docker utilizando o Flannel

O objetivo deste tutorial é criar uma sub-rede utilizando o Flannel para fazer a comunicação entre os containers e consecutivamente entre aplicações, bancos de dados e etc.
E tem mais, se você vai criar um cluster com Kubernetes, CoreOS ou Docker Swarm+Compose é fundamental ter uma sub-rede para comunicação, e o Flannel é uma excelente opção; para não dizer a melhor.

Rede-Flannel

1. Introdução

Flannel é uma rede virtual (overlay network) utilizada para provisionar uma sub-rede para cada host do cluster; no nosso caso são hosts Docker.
Esta sub-rede vai permitir a alocação de ips para os containeres da rede.
O objetivo ao utilizar uma rede com Flannel é fazer a comunicação entre os containeres.

Quando você instala o Docker ele cria uma rede interna isolada, geralmente é uma rede 172.17.X.X. Se você tiver outros hosts Docker na rede os containeres não conseguirão se comunicar, por isto que precisamos do Flannel.

O Flannel utiliza como backend o Etcd para fazer o armazenamento das informações de rede. O Etcd é um sistema distribuído de armazenamento do tipo key=valor.

Então neste tutorial vamos utilizar o Flannel para fazer a comunição entre os containeres e o Etcd para o armazenamento das informações de rede.

2. Infraestrutura e pré-requisitos

Pré-requisitos.
* Docker instalado. Se preferir pode seguir este tutorial de instalação do Docker.
* 1 servidor para o Etcd.
* X servidores rodando o Docker. X são quantos hosts Docker você quiser.
* Sistema Operacional Centos 7 X86_64.

Infraestrutura deste Lab.

Etcd
etcd-01.devopslab.com.br

Hosts Docker
docker-engine-01.devopslab.com.br
docker-engine-02.devopslab.com.br
docker-engine-03.devopslab.com.br

3. Instalação do Etcd e definição de rede

Instalar o Etcd é fácil, você precisa apenas ter o repositório “extras” ativo no seu CentOS 7. O repositório extras já vem configurado mas de qualquer forma segue abaixo.

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

Instalação do Etcd.

# yum install etcd

Altere o Bind do etcd para 0.0.0.0. Segue meu arquivo de configuração do etcd.

# cat /etc/etcd/etcd.conf |grep -v ^#

ETCD_NAME=default
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"

Habilite o startup e inicie o Etcd.

systemctl enable etcd.service
systemctl start.service

Libera a porta 2379/tcp no firewall.

# firewall-cmd –add-port=2379/tcp
# firewall-cmd --permanent --add-port=2379/tcp

3.1 – Definição de rede

Crie um arquivo .json em qualquer pasta e defina sua rede.
#vi flannel-config.json

{
    "Network": "10.0.0.0/16",
    "SubnetLen": 24,
    "Backend": {
        "Type": "vxlan",
        "VNI": 1
     }
}

Agora crie uma chave (key=valor) no etcd com as informações da rede.

# etcdctl set /redeinternadevopslab.com.br/network/config < flannel-config.json

Key – /redeinternadevopslab.com.br/network/config
Valor – Conteúdo do arquivo flannel-config.json

Faça um “get” para verificar a criação da key=valor.

# etcdctl get /redeinternadevopslab.com.br/network/config
{
    "Network": "10.0.0.0/16",
    "SubnetLen": 24,
    "Backend": {
        "Type": "vxlan",
        "VNI": 1
     }
}

Seu Etcd já está com a rede definida, o próximo passo é configurar o Flannel nos clientes.

4. Instalação e configuração do Flannel nos hosts Docker

Agora precisamos instalar o agente Flannel em todos os hosts Docker. O repositório é o “extras”, o mesmo utilizado na instalação do Etcd, que provavelmente já exista no seu Centos 7.

# yum install flannel

Configuração do Flannel.
Edite o arquivo “/etc/sysconfig/flanneld” e altere as variáveis
FLANNEL_ETCD = Servidor do Etcd.
FLANNEL_ETCD_KEY = Key definida no Etcd.

Segue meu arquivo.

# cat  /etc/sysconfig/flanneld | grep -v ^#
FLANNEL_ETCD="http://etcd-01.devopslab.com.br:2379"
FLANNEL_ETCD_KEY="/redeinternadevopslab.com.br/network"

Habilite o startup e inicie o Flanneld.

# systemctl enable flanneld
# systemctl start flanneld

Se tudo correu bem, você vai ter uma nova interface de rede no seu host.

# ip addr | grep flannel
4: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN 
    inet 10.0.82.0/16 scope global flannel.1

Verifique se foi criado o arquivo “/run/flannel/subnet.env”, pois nele consta as definições de rede que serão cosultadas pelo Docker.

# cat /run/flannel/subnet.env 
FLANNEL_NETWORK=10.0.0.0/16
FLANNEL_SUBNET=10.0.82.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=false

4.1 – Configuração do Docker para a utilização do Flannel

Vamos editar o arquivo de definição do serviço Docker e informar para utilizar a rede Flannel.
Você pode consultar o arquivo docker.service com o comando “systemctl status docker”.
O que precisa ser alterado são estes 2 campos:
EnvironmentFile=-/run/flannel/subnet.env

ExecStart=/usr/bin/docker daemon -H fd:// $OPTIONS $DOCKER_STORAGE_OPTIONS –bip=${FLANNEL_SUBNET} –mtu=${FLANNEL_MTU}

Segue meu arquivo “/usr/lib/systemd/system/docker.service”.
# cat /usr/lib/systemd/system/docker.service

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target docker.socket
Requires=docker.socket

[Service]
Type=notify
EnvironmentFile=-/run/flannel/subnet.env
ExecStart=/usr/bin/docker daemon -H fd:// $OPTIONS $DOCKER_STORAGE_OPTIONS --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU}
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target

Agora reinicie o Docker para ele pegar a nova rede.

# systemctl restart docker

Eu tive que reiniciar o Docker umas 3 ou 4 vezes para ele assumir a nova rede.
Ou se você preferir reinicie todo o host Docker.

# ip addr | grep docker
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN 
    inet 10.0.82.1/24 scope global docker0

Veja que agora existe a internface “docker0“.

5. Teste de comunicação entre containeres

Com o Flannel configurado, crie alguns containeres em hosts diferentes e faça teste de ping e telnet.
Cuidado com Firewall ativo nos hosts Docker pois pode bloquear sua comunicação. Crie as regras de Firewall ou simplesmente desative.

Teste 1.
Origem
Host Docker 1: 10.0.2.201
Container 1: 10.0.82.2

Destino:
Host Docker 2: 10.0.2.202
Container 2: 10.0.24.3

root@31bf8abfa529:/# ip a l eth0| grep inet' '
    inet 10.0.82.2/24 scope global eth0

root@31bf8abfa529:/# ping 10.0.24.3
PING 10.0.24.3 (10.0.24.3) 56(84) bytes of data.
64 bytes from 10.0.24.3: icmp_seq=1 ttl=62 time=6.25 ms
64 bytes from 10.0.24.3: icmp_seq=2 ttl=62 time=0.810 ms
64 bytes from 10.0.24.3: icmp_seq=3 ttl=62 time=1.72 ms

Teste 2.
Origem
Host Docker 2: 10.0.2.202
Container 2: 10.0.24.3

Destino:
Host Docker 1: 10.0.2.201
Container 1: 10.0.82.2

root@8b43f759f5d2:/# ip a l eth0| grep inet' '
    inet 10.0.24.3/24 scope global eth0

root@8b43f759f5d2:/# ping 10.0.82.2
PING 10.0.82.2 (10.0.82.2) 56(84) bytes of data.
64 bytes from 10.0.82.2: icmp_seq=1 ttl=62 time=4.77 ms
64 bytes from 10.0.82.2: icmp_seq=2 ttl=62 time=1.11 ms
64 bytes from 10.0.82.2: icmp_seq=3 ttl=62 time=1.18 ms

Teste 3.
Origem:
Host Docker 3: 10.0.2.203
Container 3: 10.0.81.3

Destino:
Host Docker 1: 10.0.2.201
Container 1: 10.0.82.2

root@c9c0a823ddf0:/# ip a l eth0| grep inet' '
    inet 10.0.81.3/24 scope global eth0

root@c9c0a823ddf0:/# ping 10.0.82.2
PING 10.0.82.2 (10.0.82.2) 56(84) bytes of data.
64 bytes from 10.0.82.2: icmp_seq=1 ttl=62 time=1.79 ms
64 bytes from 10.0.82.2: icmp_seq=2 ttl=62 time=1.15 ms
64 bytes from 10.0.82.2: icmp_seq=3 ttl=62 time=1.17 ms

Pronto! A comunicação entre seus containeres está funcionando, as aplicações vão alcançar umas às outras e sucesso.

Qualquer coisa estamos aí.

Leonardo Macedo Cerqueira

Como gerar pacotes .RPM – gere seu próprio pacote rpm

Uma excelente utilidade ao gerar seus próprios pacotes é a possibilidade de fazer upgrade e downgrade de aplicações com facilidade e agilizar as entregas em Dev, Qa, e Produção.
Hoje em dia com CI e CD é imprescindível que ao executar um deploy se tenha a possibilidade de rollback, isto é o básico.
Então neste tutorial vou demonstrar como gerar pacotes rpms, assim como o processo de instalação, upgrade e downgrade dos pacotes.

1. Criação de um usuário para gerar pacotes RPM
É opcional mas recomendo criar um usuário dedicado para o build de pacotes .rpm, neste tutorial eu criei o usuário “buildrpm”.

2. Instale os pacotes rpmdevtools e rpm-build

# yum -y install rpmdevtools rpm-build

3. Crie a árvore de diretórios para gerar o pacote

$ rpmdev-setuptree
$ ls -R rpmbuild/
rpmbuild/:
BUILD  RPMS  SOURCES  SPECS  SRPMS

Ou pode ser criado na mão.

$ mkdir rpmbuild
$ cd rpmbuild
$ mkdir BUILD RPMS SOURCES SPECS SRPMS

4. Vou criar um arquivo de repositório .repo, no caso é o “MEU-REPO.repo”

$ cd rpmbuild/SOURCES
$ mkdir -p repo-versao-1/etc/yum.repos.d
$ cp -v ~/MEU-REPO.repo repo-versao-1/etc/yum.repos.d

Foi criado um repositório qualquer no caso “MEU-REPO.repo”, mas poderia ser qualquer arquivo.
Criei uma pasta versionada “repo-versao-1”, sendo assim sugiro que a cada modificação altere a versão da pasta (repo-versao-1.1, repo-versao-1.2, repo-versao-2.0, …).

5. Gere o tarball da pasta “repo-versao-1”

$ cd rpmbuild/SOURCES
$ # tar cvzf repo-versao-1.tar.gz repo-versao-1

$ tar cvzf repo-versao-1.tar.gz repo-versao-1
repo-versao-1/
repo-versao-1/etc/
repo-versao-1/etc/yum.repos.d/
repo-versao-1/etc/yum.repos.d/MEU-REPO.repo

Este pacote .tar.gz será utilizado na definição do .spec logo abaixo.

6. Criação do arquivo .Spec
O arquivo .spec é onde serão definidas as informações para a gerar o pacote .rpm.

$ cd rpmbuild/SPECS
$ rpmdev-newspec  repo-versao-1.spec
$ cat repo-versao-1.spec
Name:           repo-versao
Version:        1
Release:        0
Summary:        Resumo Este e um repositorio repo devopslab bla bla bla

License:        GPL
URL:            http://repo.devopslab.com.br/repo/CentOS/
Source0:        repo-versao-1.tar.gz

BuildArch:	noarch
BuildRoot:	%{_tmppath}/%{name}-buildroot

%description
Escreva uma descricao para o pacote
Este e um novo repositorio bla bla bla

%prep
%setup -q

%install
mkdir -p $RPM_BUILD_ROOT
cp -R * $RPM_BUILD_ROOT

%files
%defattr(-,root,root,-)
/etc/yum.repos.d/MEU-REPO.repo

7. Gere o pacote utilizando as definições do arquivo .spec

$ cd rpmbuild/SPECS/
$ # rpmbuild -v -bb repo-versao-1.spec

buildrpm@rpmbuild-01 SPECS]$ rpmbuild -v -bb repo-versao-1.spec
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.DowMqD
+ umask 022
+ cd /home/buildrpm/rpmbuild/BUILD
+ cd /home/buildrpm/rpmbuild/BUILD
+ rm -rf repo-versao-1
+ /usr/bin/gzip -dc /home/buildrpm/rpmbuild/SOURCES/repo-versao-1.tar.gz
+ /usr/bin/tar -xf -
+ STATUS=0
+ '[' 0 -ne 0 ']'
+ cd repo-versao-1
+ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ exit 0
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.xb3qI7
+ umask 022
+ cd /home/buildrpm/rpmbuild/BUILD
+ '[' /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64 '!=' / ']'
+ rm -rf /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
++ dirname /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
+ mkdir -p /home/buildrpm/rpmbuild/BUILDROOT
+ mkdir /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
+ cd repo-versao-1
+ mkdir -p /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
+ cp -R etc /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
+ '[' noarch = noarch ']'
+ case "${QA_CHECK_RPATHS:-}" in
+ /usr/lib/rpm/check-buildroot
+ /usr/lib/rpm/redhat/brp-compress
+ /usr/lib/rpm/redhat/brp-strip /usr/bin/strip
+ /usr/lib/rpm/redhat/brp-strip-comment-note /usr/bin/strip /usr/bin/objdump
+ /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip
+ /usr/lib/rpm/brp-python-bytecompile /usr/bin/python 1
+ /usr/lib/rpm/redhat/brp-python-hardlink
+ /usr/lib/rpm/redhat/brp-java-repack-jars
Processing files: repo-versao-1-0.noarch
Provides: repo-versao = 1-0
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
Wrote: /home/buildrpm/rpmbuild/RPMS/noarch/repo-versao-1-0.noarch.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.lNfmk8
+ umask 022
+ cd /home/buildrpm/rpmbuild/BUILD
+ cd repo-versao-1
+ /usr/bin/rm -rf /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
+ exit 0
#

8. Verifique o pacote criado na pasta RPMS

$ ls rpmbuild/RPMS/noarch/ 
rpmbuild/RPMS/noarch/repo-versao-1-0.noarch.rpm

$ rpm -qpl rpmbuild/RPMS/noarch/repo-versao-1-0.noarch.rpm
/etc/yum.repos.d/MEU-REPO.repo

9. Instale o pacote e veja se foi criado o arquivo “/etc/yum.repos.d/MEU-REPO.repo”

$ sudo rpm -hiv repo-versao-1-0.noarch.rpm

$ ls -l /etc/yum.repos.d/MEU-REPO.repo 
-rw-r--r--. 1 root root 202 Apr 14 13:10 /etc/yum.repos.d/MEU-REPO.repo

10. Teste de remoção de pacote
Remova o pacote repo-versao-1-0. Após a remoção o arquivo “/etc/yum.repos.d/MEU-REPO.repo” terá que ser removido.

$ sudo yum remove repo-versao-1-0.noarch
$ ls -l /etc/yum.repos.d/MEU-REPO.repo 
ls: cannot access /etc/yum.repos.d/MEU-REPO.repo: No such file or directory

11. Teste de Upgrade e Downgrade
Vou gerar algumas versões para fazer o teste de upgrade e downgrade.
Primeiramente crie novos arquivos “.spec” e altere a versão e o source0.

SPECS/repo-versao-1.1.spec
Name: repo-versao
Version: 1.1
Release: 0
Source0: repo-versao-1.1.tar.gz

SPECS/repo-versao-1.2.spec
Name: repo-versao
Version: 1.2
Release: 0
Source0: repo-versao-1.2.tar.gz

Agora crie novas pastas dentro do SOURCES com as respectivas versões.
SOURCES/repo-versao-1.1
SOURCES/repo-versao-1.2

Altere os arquivos que você quiser, e gere um novo tarball tar.gz.
tar -cvzf repo-versao-1.1.tar.gz repo-versao-1.1
tar -cvzf repo-versao-1.2.tar.gz repo-versao-1.2

Por fim gere os novos pacotes.
$ rpmbuild -v -bb SPECS/repo-versao-1.1.spec
$ rpmbuild -v -bb SPECS/repo-versao-1.2.spec

Verifique os pacotes rpms gerados.
$ cd /home/buildrpm/rpmbuild/RPMS/noarch
$ ls
repo-versao-1-0.noarch.rpm
repo-versao-1.1-0.noarch.rpm
repo-versao-1.2-0.noarch.rpm

Instalação do pacote versão 1.1 repo-versao-1.1-0.noarch.rpm

$ sudo rpm -hiv repo-versao-1.1-0.noarch.rpm
Preparing...                          ################################# [100%]
Updating / installing...
   1:repo-versao-1.1-0                ################################# [100%]
$ cat /etc/yum.repos.d/MEU-REPO.repo | grep Versao
name=Versao 1.1 - Repositorio Teste Meu Repo - DevOpsLab

Upgrade para a versão 1.2 repo-versao-1.2-0.noarch.rpm

$ sudo rpm -Uvh repo-versao-1.2-0.noarch.rpm
Preparing...                          ################################# [100%]
Updating / installing...
   1:repo-versao-1.2-0                ################################# [ 50%]
Cleaning up / removing...
   2:repo-versao-1.1-0                ################################# [100%]
$ cat /etc/yum.repos.d/MEU-REPO.repo | grep Versao
name=Versao 1.2 - Repositorio Teste Meu Repo - DevOpsLab
$ rpm -qa | grep repo-versao
repo-versao-1.2-0.noarch

Downgrade para a versão 1.0 repo-versao-1-0.noarch.rpm

$ sudo rpm -Uvh --oldpackage repo-versao-1-0.noarch.rpm
Preparing...                          ################################# [100%]
Updating / installing...
   1:repo-versao-1-0                  ################################# [ 50%]
Cleaning up / removing...
   2:repo-versao-1.2-0                ################################# [100%]
$ cat /etc/yum.repos.d/MEU-REPO.repo | grep Versao
name=Versao 1.0 - Repositorio Teste Meu Repo - DevOpsLab
$ rpm -qa | grep repo-versao
repo-versao-1-0.noarch

Remoção do pacote repo-versao-1-0.noarch.rpm

$ sudo rpm -e repo-versao-1-0.noarch
$ ls  /etc/yum.repos.d/MEU-REPO.repo
ls: cannot access /etc/yum.repos.d/MEU-REPO.repo: No such file or directory
$ rpm -qa | grep repo-versao
$ 

É isto aí, novidades só chamar.

Leonardo Macedo

Centralização e análise de logs com Graylog, MongoDB e Elasticsearch

“Open source log management that actually works” – www.graylog.org
Neste tutorial vamos instalar e configurar o Graylog para a centralização e análise de logs.

É fundamental ter uma ferramenta para análise de logs na sua infraestrutura, isto te possibilita um debug mais apurado do ambiente, melhora a segurança, ajuda a compartilhar informações com os times, auxilia na monitoração com o uso de triggers, centralização de logs, enfim é uma ferramenta estratégica que oferece vários recursos para uma boa análise da sua infraestrutura.

Graylog é uma excelente alternativa ao Splunk e Kibana+Logstash.

1.Infraestrutura e pré-requisitos

Sistema operacional: Centos 7 x86_64.

Componentes:
Graylog Server – Análise e coleta de logs. Insere os logs no Elasticsearch.
Graylog Web – Interface Web para o Graylog Server.
MongoDB– Armazenamento de configurações e metadados.
Elasticsearch – Armazenamento de logs e ferramenta de busca.
graylog-Diagram

Versões utilizadas neste tutorial:
graylog-web-1.3.4-1.noarch
graylog-server-1.3.4-1.noarch

mongodb-org-server-3.2.4-1.el7.x86_64
mongodb-org-3.2.4-1.el7.x86_64

elasticsearch-1.7.5-1.noarch

Servidores:
Graylog Server e interface Web:
10.0.2.100 graylog-webeserver-01.devopslab.com.br

MongoDB:
10.0.2.101 graylog-mongodb-01.devopslab.com.br

Elasticsearch
10.0.2.102 graylog-elasticsearch-01.devopslab.com.br

2. Instalação do Elasticsearch

Faça o login no servidor do Elasticsearch graylog-elasticsearch-01.devopslab.com.br
Recomendo 1GB de RAM.
Até o presente momento o Graylog funciona apenas com o Elasticsearch 1.7.

Desative o Firewall e Selinux.

# systemctl stop firewalld.service
# systemctl disable firewalld.service
# sed -i s/SELINUX=enforcing/SELINUX=disabled/g /etc/selinux/config
# setenforce 0

Tuning do Sistema Operacional – Aumente a quantidade de Openfiles

# vi /etc/security/limits.conf
*                soft   nofile     64000
*                hard  nofile      64000
# ulimit -n 64000

Verifique o fs.file-max, pois ele tem que ser maior que 64000.

# sysctl -a | grep fs.file-max
fs.file-max = 98929

Instalação do Java
Versões suportadas: OpenJDK ou Java Oracle
Java 8 update 20 ou posterior.
Java 7 update 55 ou posterior.

# yum -y install java-1.8.0-openjdk.x86_64
# java -version
openjdk version "1.8.0_77"

Repositório – Importação da chave pública do repositório

# rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch

Crie o arquivo do repositório do Elasticsearch.
#vi /etc/yum.repos.d/elasticsearch.repo

[elasticsearch-1.7]
name=Elasticsearch repository for 1.7.x packages
baseurl=http://packages.elastic.co/elasticsearch/1.7/centos
gpgcheck=1
gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1

Instale o Elasticsearch 1.7

# yum -y install elasticsearch

Configuração do Elasticsearch
Todas as configurações serão executadas no arquivo /etc/elasticsearch/elasticsearch.yml
# vi /etc/elasticsearch/elasticsearch.yml

Defina um nome qualquer para o cluster.
cluster.name: graylog-lab

Desabilitando a descoberta automática de nodes Elasticsearch e definindo o servidor do Elasticsearch.
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: [“graylog-elasticsearch-01.devopslab.com.br:9300”]

Desabilitando a execução remota de scripts.
Adicione ao final do arquivo elasticsearch.yml
script.disable_dynamic: true

Arquivo completo elasticsearch.yml.
# cat  /etc/elasticsearch/elasticsearch.yml| grep -v ^#| grep -v ^$
cluster.name: graylog-lab
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: ["graylog-elasticsearch-01.devopslab.com.br:9300"]
script.disable_dynamic: true

Reinicie o Elasticsearch.

# systemctl enable elasticsearch.service
# systemctl restart elasticsearch.service

Verificando a saúde do cluster de Elasticsearch.
Status 200 está ok.

curl -X GET http://localhost:9200
# curl -X GET 'http://localhost:9200'
{
  "status" : 200,
  "name" : "Hydro",
  "cluster_name" : "graylog-lab",
  "version" : {
    "number" : "1.7.5",
    "build_hash" : "00f95f4ffca6de89d68b7ccaf80d148f1f70e4d4",
    "build_timestamp" : "2016-02-02T09:55:30Z",
    "build_snapshot" : false,
    "lucene_version" : "4.10.4"
  },
  "tagline" : "You Know, for Search"
}

Status ‘green’ está ok.

# curl -XGET 'http://localhost:9200/_cluster/health?pretty=true'
# curl -XGET 'http://localhost:9200/_cluster/health?pretty=true'
{
  "cluster_name" : "graylog-lab",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 1,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 0,
  "active_shards" : 0,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0
}

3. Instalação do MongoDB

Servidor graylog-mongodb-01.devopslab.com.br
Recomendo 1GB de RAM.
Desative o Firewall e Selinux.

Tuning do S.O – Aumente a quantidade de Openfiles e Max process

# vi /etc/security/limits.conf
*                soft   nofile      64000
*                hard  nofile      64000
*                soft   nproc      64000
*                hard  nproc      64000
# ulimit -n 64000
# ulimit -u 64000

Verifique o fs.file-max. O valor tem que ser maior que 64000.

# sysctl -a | grep fs.file-max
fs.file-max = 98929

Repositório – Crie o arquivo do repositório do MongoDB

[mongodb-org-3.2]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.2/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.2.asc

Instale a última versão do MongoDB.

# yum install -y mongodb-org

Comente a linha ‘bindIp: 127.0.0.1’ no arquivo ‘/etc/mongod.conf’ para que o MongoDB escute em todas as interfaces de rede.

# sed -i s/bindIp:/#bindIp:/g /etc/mongod.conf 

Inicie o MongoDB.

# systemctl enable mongod.service
# systemctl start mongod.service

4. Instalação do Graylog Server

Servidor graylog-webeserver-01.devopslab.com.br
Desative o Firewall e Selinux.
Instale o java. Utilize o mesmo passo descrito na instalação do Elasticsearch.

Repositório – Instalação do pacote graylog-1.3-repository-el7_latest.rpm

# rpm -hiv https://packages.graylog2.org/repo/packages/graylog-1.3-repository-el7_latest.rpm

Instalação do Graylog server.

# yum -y install graylog-server

Instale o repositório Epel. Ele é dependencia para a instalação do pacote pwgen.

# yum -y install epel-release.noarch

Configuração do Graylog Server.
# vi /etc/graylog/server/server.conf
Define este node como master.
is_master = true

Gere uma senha de segurança para proteger o armazenamento das senhas dos usuários.

# pwgen -N 1 -s 96
bD9QUDQMjkd0JZ5S205p3mJDtcLAjH61K0jP48wGxcETvcPV8zI7kgRSB5KJwzxpw6CSAelzILFr9zxMXt0wXhOqnKGCkdNA

Configure a senha em password_secret

password_secret =U2UAb7rBEvc0Q1CLRiSaANdaQcEMWYALoN8TuNCph1nCUcII1oyNFtLXZrC4yoBQ3BVWMUSg8WoVRnvo4mURElJjeoC653LQ

Rest API para a conexão do Graylog Web e outros Graylog Server.

rest_listen_uri = http://127.0.0.1:12900/

Crie uma senha para o usuário Administrativo ‘admin’.

# echo -n minha_senha | sha256sum
f9b88ac71caec840be639a8eb18e68728744252316456ce9b3cf6b58d82bb7cd  -
root_password_sha2 = f9b88ac71caec840be639a8eb18e68728744252316456ce9b3cf6b58d82bb7cd

Quantidade de nodes e replicas do Elasticsearch

elasticsearch_shards = 1
elasticsearch_replicas = 0

Nome do Cluster Elasticsearch. É o mesmo definido em no arquivo elasticsearch.yml do servidor do Elasticsearch.

elasticsearch_cluster_name = graylog-lab

Desabilitando a descoberta automática e definindo o servidor do Elasticsearch.

elasticsearch_discovery_zen_ping_multicast_enabled = false
elasticsearch_discovery_zen_ping_unicast_hosts = graylog-elasticsearch-01.devopslab.com.br:9300

Desativando a autenticação e definindo a string de conexão com o banco MongoDB.

mongodb_useauth = false
mongodb_uri = mongodb://graylog-mongodb-01.devopslab.com.br:27017/graylog2

Arquivo server.conf completo.

# cat server.conf | grep -v ^# |grep -v ^$
is_master = true
node_id_file = /etc/graylog/server/node-id
password_secret = bD9QUDQMjkd0JZ5S205p3mJDtcLAjH61K0jP48wGxcETvcPV8zI7kgRSB5KJwzxpw6CSAelzILFr9zxMXt0wXhOqnKGCkdNA
root_password_sha2 = 8b7baf6899f95c2f4723ef35f4cb10ac678221ac2d63ae8901f63151d243881e
plugin_dir = /usr/share/graylog-server/plugin
rest_listen_uri = http://127.0.0.1:12900/
rotation_strategy = count
elasticsearch_max_docs_per_index = 20000000
elasticsearch_max_number_of_indices = 20
retention_strategy = delete
elasticsearch_shards = 1
elasticsearch_replicas = 0
elasticsearch_index_prefix = graylog2
allow_leading_wildcard_searches = false
allow_highlighting = false
elasticsearch_cluster_name = graylog-lab
elasticsearch_discovery_zen_ping_multicast_enabled = false
elasticsearch_discovery_zen_ping_unicast_hosts = graylog-elasticsearch-01.devopslab.com.br:9300
elasticsearch_analyzer = standard
output_batch_size = 500
output_flush_interval = 1
output_fault_count_threshold = 5
output_fault_penalty_seconds = 30
processbuffer_processors = 5
outputbuffer_processors = 3
processor_wait_strategy = blocking
ring_size = 65536
inputbuffer_ring_size = 65536
inputbuffer_processors = 2
inputbuffer_wait_strategy = blocking
message_journal_enabled = true
message_journal_dir = /var/lib/graylog-server/journal
dead_letters_enabled = false
lb_recognition_period_seconds = 3
mongodb_useauth	= false
mongodb_uri = mongodb://graylog-mongodb-01.devopslab.com.br:27017/graylog2
mongodb_max_connections = 100
mongodb_threads_allowed_to_block_multiplier = 5
content_packs_dir = /usr/share/graylog-server/contentpacks
content_packs_auto_load = grok-patterns.json

Inicie o Graylog Server

# systemctl enable graylog-server.service
# systemctl start graylog-server.service

5. Instalação do Graylog Web

O Graylog Web vai ficar no mesmo servidor do Graylog Server, então Java, Firewall e Selinux já estão ok.
Recomendo pelo menos 2GB de RAM.
Servidor graylog-webeserver-01.devopslab.com.br

Instalação do graylog-web.

# yum -y install graylog-web

Configuração do Graylog Web
# vi /etc/graylog/web/web.conf

Gere uma chave para criptografia de funções do graylog com o comando ‘pwgen -N 1 -s 96’ e cole no campo:
application.secret=””

Configure a conexão com a API do Server em graylog2-server.uris=””
graylog2-server.uris=”http://127.0.0.1:12900/”

Veja como ficou a configuração do greylog web.

# cat web.conf| grep -v ^#| grep -v ^$
graylog2-server.uris="http://127.0.0.1:12900/"

application.secret="OGBIrIC2eCOGqc3P621rIXFbGFF0DP6l1FU4A5FN8Zu4RATafF6y2EEdpHIvytkiCG8G2n7C18eUoQxGlJzHd5KHaJE3Sc20"

field_list_limit=100

application.global=lib.Global

Inicie o Graylog Web.

# systemctl enable graylog-web
# systemctl start graylog-web

Faça o login na interface Web (http://ip-webserver:9000):
http://graylog-webeserver-01.devopslab.com.br:9000/

Usuário: admin
Senha: Foi definida na instalação do graylog-server, lembra?.
home-graylog1

6. Configuração dos clientes e envio de Log

O Graylog aceita logs nos formatos RFC-5424 e RFC-3164, que são os utilizados pelo syslog-ng e rsyslog.

Equipamentos e aplicações com logs fora do padrão precisam de plugins, como por exemplo roteadores Cisco e Fortigate ou app Java e Web servers.

Visite o Marketplace para checar todos os plugins disponíveis: https://marketplace.graylog.org/

É possível você desenvolver seu próprio padrão de log com a ferramenta Graylog Extractor ou enviar o log via API.

6.1 – Configuração do Input de logs

Antes de começar a receber logs no Graylog é necessário criar uma configuração de Input, que basicamente diz quais tipos de logs serão aceitos. Os tipos de logs aceitos podem ser estendidos com plugins próprios ou de terceiros (veja o o site graylog markeplace).
Logue na interface Web e vá para:
System/Inputs → Inputs → Launch New Input
Selecione Syslog UDP.
Selecione Syslog TCP.
Clique em Lauch.

Escolha uma porta acima de 1024. Portas <1024 apenas o usuário root pode manipular. Eu escolhi a porta 1030/tcp e 1030/udp para o recebimento de logs do syslog. graylog-input

6.2 – Configuração do Firewall

Eu quero que meus servidores enviem o log para a porta 514/tcp e 514/udp. Simplesmente pois é um padrão, é comum enviar logs para estas portas.
Você também pode enviar direto para a porta definida no Input, no meu caso 1030.

Se você quer usar o padrão, crie uma regra de firewall que redirecione todo o tráfego em vier pela porta 514/tcp e 514/udp para a porta 1030.

# iptables -t nat -A PREROUTING -i enp0s3 -p udp -m udp --dport 514 -j REDIRECT --to-ports 1030
# iptables -t nat -A PREROUTING -i enp0s3 -p tcp -m tcp --dport 514 -j REDIRECT --to-ports 1030

6.3 – Configuração em envio de logs

Vou configurar os próprios servidores do Cluster do Graylog para o envio de log.
Hoje em dia todos os Linux estão utilizando o rsyslog, então vou configurar o rsyslog da seguinte forma.

# vi /etc/rsyslog.conf
*.*	@graylog-webeserver-01.devopslab.com.br:514;RSYSLOG_SyslogProtocol23Format

graylog-webeserver-01.devopslab.com.br:514 – Meu servidor do Graylog ouvindo na porta 514. poderia ser a porta definida no Input 1030tcp/udp.
*.* – Todos os logs e facilidades.
@ – Protocolo UDP.
@@ – Protocolo TCP.

Reinicie o rsyslog para que o logs comecem a ser enviados para o graylog.

# systemctl restart rsyslog

Obs: Este template ‘RSYSLOG_SyslogProtocol23Format’ funciona apenas caso a versão do rsyslog seja maior que 5.

# rsyslogd -version
rsyslogd 7.4.7, compiled with:
	FEATURE_REGEXP:				Yes
	FEATURE_LARGEFILE:			No
	GSSAPI Kerberos 5 support:		Yes
	FEATURE_DEBUG (debug build, slow code):	No
	32bit Atomic operations supported:	Yes
	64bit Atomic operations supported:	Yes
	Runtime Instrumentation (slow code):	No
	uuid support:				Yes
See http://www.rsyslog.com for more information.

Se seu rsyslog for menor 5, utilize apenas a linha:

# vi /etc/rsyslog.conf
*.*	@graylog-webeserver-01.devopslab.com.br:514

7. Verificação dos logs na interface Web

Logue na interface web e entre na abas sources e search que será possível ver os logs e a origem dos logs.

Aba SOURCES.
dashboard-sources

Aba SEARCH.
dashboard-search
Se você chegou até aqui seu Graylog está funcionando e recebendo logs, agora basta você explorar a ferramenta, clicar nas várias opções, integrar com Ldap, criar logins para seus times, criar triggers de monitoramento, criar Dashboards, fazer filtros específicos e etc.

8. Graylog via proxy com o Nginx

Este passo é opcional.
Digitar a url com a porta no navegador não é algo muito legal, então vamos configurar um proxy reverso com Nginx para não ter que digitar http://x.x.x.x:porta/

No servidor Graylog Server e Web instale o Nginx.

# yum -y install nginx

Altere estes campos:

server {
        listen       80 default_server;
        server_name  graylog.devopslab.com.br;
        location / {
	proxy_pass http://localhost:9000;
        }

E reinicie o nginx. Agora você pode simplesmente digitar http://graylog.devopslab.com.br/ sem ter que digitar porta.

Segue todo o arquivo nginx.conf, basta copiar e colar ;). O restante do arquivo está padrão, conforme veio instalado.

# cat nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        server_name  graylog.devopslab.com.br;
        location / {
	proxy_pass http://localhost:9000;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}

Referência:
Graylog
http://docs.graylog.org/en/1.3/

Elasticssearch
https://www.elastic.co/guide/en/elasticsearch/reference/1.7/index.html

MongoDB
https://docs.mongodb.org/manual/

Qualquer dúvida, sugestão e etc, só chamar.

[]’s

Leonardo Macedo Cerqueira