Gustavo Soares

tecnologia, infraestrutura web, mobile e afins

Browsing Posts in infraestrutura

Aconteceu em março de 2012, no cinemark Downtown Barra a premiação da primeira edição do Javali de Ouro Awards. Trata-se de uma premiação anual da Globo.com para premiar os melhores projetos em diferentes categorias, a saber: Projeto do Ano, Inovação, Melhor Experiência Social, Melhor Engenharia de Software, Melhor Solução em Infraestrutura, Melhor Solução de UX, Colaboração entre times e Disseminação do Conhecimento.

E na categoria melhor solução em Infraestrutura “the Javali de Outro goes to…”

Recebendo a premiação das mãos do Diretor de Operações e Datacenter.

Não tinha a menor expectativa de ganhar, mas acabei vencendo com o projeto Automação com Puppet. Sala do cinema lotada… tive que descer lá para receber o prêmio e depois fazer um discurso. Obviamente eu não tinha planejado e treinado discurso nenhum e ele não saiu bem como eu gostaria. :)

Quem trabalha com infraestrutura em TI sabe o quão difícil é inovar nesta área. Os profissionais dessa área costumam ser muito resistentes a mudança, principalmente para um projeto como este. Este projeto quebrou muitos paradigmas e mudou a forma que os Sysadmin’s da Globo.com trabalham/enxergam infraestrutura. Trouxe mais agilidade para o dia a dia das pessoas e eu arrisco dizer que ele aproximou Dev’s de Op’s. Antes a configuração dos servidores era uma caixa preta para os desenvolvedores . Com o puppet a configuração, mais do que nunca, passa a ser enxergada como código (Infrastructure as A Code). Além disso, houve uma grande difusão de conhecimento sobre esta tecnologia. Foram feitos inúmeros workshops, treinamentos, techtalks… tudo para “evangelizar”, difundir e consolidar o uso do Puppet dentro da organização.

Premiação Javali de Ouro Awards - Discurso

Até a presente data, mais de 1000 servidores (físicos e virtuais) foram puppetizados na empresa. E mais estão por vir!!

e galera…. inovar é preciso!!

Share

Foi tudo decidido em cima da hora e cá estou eu para participar da primeira conferência voltada para o Puppet: PuppetConf. Para vocês terem idéia, eu fiquei sabendo que iria vir na sexta-feira, dia 16/09/2011 e depois disso foi aquela correria para fazer inscrição, arrumar as passagens, hospedagem e o adiantamento. Cheguei hoje (quarta-feira, dia 21/09/2011) em Portland e amanhã já começa. Ainda bem que costumo me adaptar rápido ao fuso horário, espero que dessa vez não seja diferente.

Comecei a usar o puppet em 2009, e hoje 2 anos depois, é com muito entusiasmo que fico em poder assistir uma série de palestras dessa tecnologia que mudou a forma com que os servidores são instalados, configurados e mantidos na empresa que trabalho atualmente. Realmente considero o puppet uma ferramenta fantástica e juntamente com o Chef, eles são os big players do mercado para sistemas de gerência de configuração. Já escrevi alguns artigos aqui no blog sobre puppet.

A programação das palestras você encontra aqui. Pela descrição de algumas, vai ter momento que vou querer me dividir em 2!!

Para finalizar este post uma coincidência que aconteceu… Meu aniversário é no dia 6/11, o número do quarto que fiquei é o 611. E eu com isso, certo!? Você deve estar pensando… :) ))))

Share

Resolvi escrever sobre uma dica MUITO útil para quem está utilizando o puppet e que com certeza irá evitar alguns problemas no futuro. Trata-se de uma forma para automatizar o teste de sintaxe dos seus arquivos puppet (*.pp) e os templates ERB antes que tais arquivos sejam enviados para o seu puppetmaster. Para fazer isso, você deve utilizar os hooks que tanto quanto o SVN quanto o GIT oferecem. Resumindo, hooks são mecanismos que tais sistemas de controle de versão oferecem para execução de qualquer comando antes ou após a atualização de código no repositório.

git-hooks e puppet

Como utilizo o git como repositório, daqui para frente vou me concentrar apenas nele. O git oferece hooks do tipo pre-commit, post-commit e update. Os primeiros dois hook são do tipo cliente, enquanto que último atua no lado do servidor, isto é, sempre que é feito um git push. Para configurar os hooks do tipo cliente, basta criar o diretório hooks dentro do diretório .git na raiz do projeto e criar os arquivos pre-commit e post-commit. Para habilitar ou desabilitar um determinado tipo de hook, basta adicionar ou remover a permissão de execução do script. Como estamos interessados em rodar um teste de sintaxe nos arquivos puppet e template o hook mais indicado seria o pre-commit, para evitar que sejam comitados códigos com o potencial de quebrar a execução do puppetmaster. O trecho abaixo é o conteúdo do arquivo que venho utilizando.


#!/bin/sh

syntax_errors=0
error_msg=$(mktemp /tmp/error_msg.XXXXXX)

if git rev-parse --quiet --verify HEAD > /dev/null
then
    against=HEAD
else
    # Initial commit: diff against an empty tree object
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

# Get list of new/modified manifest and template files to check (in git index)
cmd="git diff-index --diff-filter=AM --name-only --cached $against | egrep '\.(pp|erb)'"
echo "cmd: $cmd"
for indexfile in `git diff-index --diff-filter=AM --name-only --cached $against | egrep '\.(pp|erb)'`
do
    # Don't check empty files
    if [ `git cat-file -s :0:$indexfile` -gt 0 ]
    then
        echo "Arquivo alterado: $indexfile"
        case $indexfile in
            *.pp )
                # Check puppet manifest syntax
                git cat-file blob :0:$indexfile | puppet --color=false --parseonly --ignoreimport > $error_msg ;;
            *.erb )
                # Check ERB template syntax
                git cat-file blob :0:$indexfile | erb -x -T - | ruby -c 2> $error_msg > /dev/null ;;
        esac
        if [ "$?" -ne 0 ]
        then
            echo -n "$indexfile: "
            cat $error_msg
            syntax_errors=`expr $syntax_errors + 1`
        fi
    fi
done

rm -f $error_msg

if [ "$syntax_errors" -ne 0 ]
then
    echo "Error: $syntax_errors syntax errors found, aborting commit."
    exit 1
fi

O script acima irá rodar o teste de sintaxe apenas nos arquivos com extensão pp e erb, que são as extensões mais utilizadas para os arquivos puppet e os arquivos de template do puppet. É necessário ter o puppet instalado na sua máquina. Para isso, veja qual a versão do puppet que o seu servidor puppetmaster está rodando e instale-a com o comando: sudo gem install puppet -v [VERSÃO]

O exemplo de instalação do puppet que dei anteriormente, foi via rubygems, mas ela poderia ser feita de outras formas. (yum/macports/rpm/apt-get e etc).

É isso! Espero ter ajudado!

Share

Fuçando a Internet (AKA Google :) ) dia desses achei um site que agrega os principais blogs sobre o puppet. Achei a idéia muito interessante e resolvi compartilhar o link aqui no blog. Segue o link: http://www.planetpuppet.org/

Share

Scribe

O scribe é uma aplicação criada e utilizada pelo Facebook para centralização de logs. Existem outras soluções que focam neste mesmo assunto como por exemplo o Splunk e diversas outras com o já conhecido Syslog, ou até o mesmo o Spread. Ainda sobre o syslog, existe um projeto bem legal, o php-syslog ou logZilla, que fornece uma interface web para apresentar as mensagens de log processadas pelo syslog. Essas mensagens são armazenada em um banco de dados MySql.

Já testei o splunk e achei ele excepcional.. com apenas uma ressalva: é pago! O php-syslog também é legal, e dependendo da sua necessidade ele pode atender bem. Para início de conversa acho que uma solução de centralização de logs em um ambiente web e para aplicações que já estão no ar e funcionando, deveria ser não intrusiva na aplicação. Independente da tecnologia que se vá utilizar. O que quero dizer com isso é que deveria-se tentar evitar qualquer alteração na aplicação para que ela enviasse os seus logs para o servidor central A ou B. Se a aplicação já está gerando log em arquivos no filesystem, é bom deixar assim e um outro “processo” por fora se encarrega de enviar o log para o lugar correto.

Bem, voltemos ao scribe… segue a descrição no repositório do próprio facebook.

Scribe is a server for aggregating log data streamed in real time from a large number of servers. It is designed to be scalable, extensible without client-side modification, and robust to failure of the network or any specific machine.

Sua arquitetura é do tipo client-server. Temos um servidor central, ou master, que é responsável por agregar (centralizar) as mensagens enviadas pelos clientes.

Funcionamento básico do Scribe

No arquivo de configuração, que fica no servidor master, definimos uma série de informações como por exemplo:

  • o diretório onde as mensagens serão salvas
  • se queremos criar um diretório com o nome do hostname que a mensagem foi enviada
  • se vamos querer enviar a mensagem para um outro servidor master
  • se vamos querer rotacionar o log
  • frequência de rotacionamento
  • e etc..etc..etc..

Para saber todos os parâmetros de configuração a melhor forma é consultar o link http://wiki.github.com/facebook/scribe/scribe-configuration

Instalação

A instalação do scribe é meio complicada… ele tem uma série de dependências. Na empresa que trabalho precisei gerar uma série de pacotes rpm para adequar algumas coisas particulares a nossa infra-estrutura. Se você tiver sorte, pode ser que já tenha algum pacote pronto dependendo do SO que você queira instalar o scribe. As principais dependências, na ordem que devem ser instaladas, são:

Caso precise compilar alguns desses pacotes, é bom dar uma olhada nos argumentos que o ./configure recebe ;)

Configuração do scribe master

A configuração do scribe não é muito complicada (complicado é instalar e compilar as deps). A seguir coloco um exemplo de um arquivo de configuração.

##
## Sample Scribe configuration
##

# This file configures Scribe to listen for messages on port 1463 and write
# them to /tmp/scribetest

port=1463
max_msg_per_second=2000000
check_interval=3

# DEFAULT

category=default

#file
type=file
fs_type=std
file_path=/tmp/scribetest
use_hostname_sub_directory=yes
rotate_period=daily
rotate_hour=23
rotate_minute=59
write_meta=yes
base_filename=test_scribe
max_size=1000000000
add_newlines=0

Acho que o arquivo é autoexplicativo. Copie o conteúdo e salve o arquivo em algum lugar da sua máquina. Em seguida, inicie o daemon do scribe no master com o seguinte comando:

scribed -c [CAMINHO PARA O ARQUIVO]

Configuração do scribe client

Beleza, você já tem o scribe master escutando na porta 1463. Agora precisa enviar mensagens para ele. Aqui vem o pulo do gato. Para enviar mensagens para o master, você deve utilizar a api do scribe para isso. Se você procurar no google vai achar alguns exemplos. Uma solução é criar um script python utilizando uma classe python para tail e a própria api em python do scribe. Desta forma, você poderia utilizar o script como se fosse o comando tail do unix. A medida que novas linhas vão sendo escritas no arquivo elas vão sendo enviadas diretamente para o scribe server.

Ao enviar as mensagens para o scribe master, você precisará especificar no cliente qual categoria no master você estará enviando. O scribe permite você agrupar os logs em categorias. Desta forma logs de um servidor apache poderiam ser enviadas para uma categoria apache por exemplo. Desta forma, quando o master receber mensagens da sua categoria apache, ele vai salvá-las dentro da pasta apache. Isso permite uma melhor organização e estruturação da informação no seu servidor central.

A seguir listo um exemplo de utilização da api python, obtido do próprio repositório do scribe.

#!/usr/bin/python

##  Copyright (c) 2007-2008 Facebook
##
##  Licensed 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.
##
## See accompanying file LICENSE or visit the Scribe site at:
## http://developers.facebook.com/scribe/

'''scribe_cat: A simple script for sending messages to scribe.'''

import sys
from scribe import scribe
from thrift.transport import TTransport, TSocket
from thrift.protocol import TBinaryProtocol

if len(sys.argv) == 2:
  category = sys.argv[1]
  host = '127.0.0.1'
  port = 1463
elif len(sys.argv) == 4 and sys.argv[1] == '-h':
  category = sys.argv[3]
  host_port = sys.argv[2].split(':')
  host = host_port[0]
  if len(host_port) > 1:
    port = int(host_port[1])
  else:
    port = 1463
else:
  sys.exit('usage (message is stdin): scribe_cat [-h host[:port]] category')

log_entry = scribe.LogEntry(category=category, message=sys.stdin.read())

socket = TSocket.TSocket(host=host, port=port)
transport = TTransport.TFramedTransport(socket)
protocol = TBinaryProtocol.TBinaryProtocol(trans=transport, strictRead=False, strictWrite=False)
client = scribe.Client(iprot=protocol, oprot=protocol)

transport.open()
result = client.Log(messages=[log_entry])
transport.close()

if result == scribe.ResultCode.OK:
  sys.exit()
elif result == scribe.ResultCode.TRY_LATER:
  print >> sys.stderr, "TRY_LATER"
  sys.exit(84)  # 'T'
else:
  sys.exit("Unknown error code.")

Uma vez o log centralizado, fica mais fácil para você tratar o dado bruto armazenado e extrair informações e métricas importantes para a regra de negócio da empresa. Para mais informações, consulte as referências que listo logo a seguir.

Referências

  1. http://wiki.github.com/facebook/scribe
  2. http://groups.google.com/group/scribe-server/
  3. http://github.com/facebook/scribe
Share

Gerência de configuração automatizada com alguma ferramenta (puppet, chef, cfengine, bcfg2) criada para tal propósito é uma atividade que (aposto) poucas empresas no Brasil utilizam, ao passo que lá fora está virando praticamente commodity, assim como soluções e/ou tecnologias utilizando hadoop.

A seguir vou listar algumas situações bem comuns de qualquer empresa de TI que não esteja terceirizando a sua infraestrutura e a minha resposta *provável* para a pergunta.

  1. Preciso editar o meu /etc/hosts no servidor para adicionar um mapeamento para o apache funcionar, como faço?
    1. Essa é fácil! Para quem é “macho”, dá um vi no /etc/hosts ou então um gedit
  2. Preciso instalar uma pacote rpm ou gem no meu servidor?
    1. Logo no servidor ou então uso o capistrano ou o fabric para rodar um yum install [PACOTE]
  3. Minha aplicação roda com o usuário XPTO e por isso preciso criá-lo em todos os servidores envolvidos com o mesmo uid e gid, como faço?
    1. Hummm… ou posso logar em cada servidor e rodar o comando de criação de usuário, ou novamente, utilizar alguma solução com capistrano ou fabric para automatizar isso. Repare que esta solução, só cria o usuário. Se por um acaso, alguém der uma mãozada no servidor e alterar o uid do usuário, provavelmente você só vai tomar conhecimento disso quando sua aplicação tomar algum erro de escrita, execução ou leitura de algum arquivo.
  4. Preciso garantir que a configuração dos meus servidores estejam íntegras ou que são equivalente aos servidores de desenvolvimento e qa, e aí, como faço?
    1. Bem, talvez essa questão seja a mais complicada. O mais comum é colocar as configurações em um diretório compartilhado entre os servidores, assim todos os servidores terão a mesma configuração. No entanto, novamente, isto não resolve o problema de você ficar sabendo  quando um determinado arquivo foi alterado. Normalmente, você vai ficar sabendo disso da pior forma possível…

Bem, as perguntas que eu poderia fazer, são praticamente infinitas, mas acho que já deu para ter uma idéia para que serve e qual o benefício de um sistema de gerência de configuração. Os mais utilizados hoje em dia são o puppetchef, ambos escritos em ruby. A seguir mostro um exemplo de como instalar um pacote com o puppet o chef.

puppet

package { postfix: ensure => latest }

O recurso acima é bem intuitivo e bem claro. Ele está instalando a última versão do pacote postfix. Caso o pacote já esteja instalado, ele irá verificar se a versão instalada é a última versão. Obviamente, que este comportamento pode ser alterado. Uma observação… ao rodar o comando acima o puppet irá fazer uma inspeção do sistema operacional em uso, caso seja CentOS por exemplo, irá usar o yum ou o rpm para instalar o pacote. É possível, utilizar a definição package para gerenciar outros tipos de pacotes, como pacotes ruby por exemplo, ou seja, gem.

A definição do próprio puppet para um recurso é a seguinte:

The fundamental unit of modelling in Puppet is a resource. Resources describe some aspect of a system; it might be a file, a service, a package, or perhaps even a custom resource that you have developed. We’ll show later how resources can be aggregrated together with “defines” and “classes”, and even show how to organize things with “modules”, but resources are what we should start with first.

Each resource has a type, a title, and a list of attributes – each resource in Puppet can support various attributes, though many of them will have reasonable defaults and you won’t have to specify all of them.

chef

package “tar” do
version “1.16.1-1″
action :install
end
Pelos exemplos dados, podemos ver claramente que a “linguagem” utilizada pelo puppet é declarativa e procura abstrair a linguagem no qual ele foi implementado (ruby). Já o chef,  utiliza um pouco da estrutura de linguagem do próprio ruby. Quem já viu um arquivo do capistrano, irá perceber a semelhança entre os dois. Por isso, que na minha opinião, há uma TENDÊNCIA maior de pessoas da área de desenvolvimento preferirem o chef e pessoas da área de infra preferirem o puppet. Pessoas da área de infra estão bastante acostumadas a trabalhar com arquivos de configuração do apache por exemplo, daí uma outra justificativa para a preferência do puppet. Isto não é nenhuma crítica pejorativa, apenas que cada tipo de profissional tem suas preferências. Preferências a parte, o importante é que seja utilizado algum tipo de sistema de gerência de configuração para automatizar e facilitar o provisionamento de servidores.

continue reading…

Share

Muitas pessoas quando precisam utilizar um proxy pensam logo no squid

No entanto, caso a aplicação por trás do squid faça uso de ajax e/ou utilize serviços REST, é possível que você tenha alguns problemas. O squid retorna um status de erro quando o POST ou PUT é feito com content-length 0 (zero). Mas calma! Existem outras opções open source disponíveis no mercado. É possível utilizar o apache como um proxy. Basta utilizar os módulos de proxy que já estão mais maduros na versão 2.2.x, na versão 2.0.x do apache não é muito recomendado utilizar estes módulos.

A configuração é bem simples. Basta dar o load dos módulos abaixo:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Depois, basta adicionar a configuração abaixo no seu httpd.conf.
ProxyRequests On
ProxyVia On
ProxyBadHeader Ignore
ProxyStatus On
ProxyPreserveHost Off
E pronto! Seu apache estará funcionando como um proxy. Se quiser pode alterar a porta de bind dele na diretiva Listen.
Share

Estou usando o apache 2.2.x em alguns projetos novos que estou envolvido na empresa que trabalho. Achei que seria interessante explicar como é feita a configuração para encaminhar as requisições dinâmicas, sejam elas para jsp’s, servelts, ssp’s e etc, para um servidor no backend, podendo ser o Jboss (tomcat) ou o Weblogic utilizando o mod_proxy.

No apache 2.2.x é muito simples e fácil fazer isso, não necessitando nenhum módulo de terceiros como o mod_jk ou o módulo da bea. Podemos usar dois módulos para isso:

  1. mod_proxy_http
  2. mod_proxy_ajp

Particularmente, prefiro usar o mod_proxy para encaminhar requisições para o Jboss/Tomcat. O mod_jk é cheio de burocracia com aqueles seus dois arquivos (worker.properties e jk.conf). :)

Para encaminhar requisições para o jboss podemos usar o mod_proxy_http ou o mod_proxy_ajp. Já para o weblogic, nossa única opção é o mod_proxy_http, visto que o weblogic não suporta o protocolo AJP.

Sugiro que a configuração seja feita no arquivo httpd-vhosts.conf (ou num arquivo a parte) e depois dar um include dele no arquivo httpd.conf, apenas para deixar as coisas mais organizadas.

Segue um exemplo simples utilizando o mod_proxy_http:

ProxyPreserveHost On
ProxyPass /ghi !
ProxyPass /abc http://localhost:8080/abc min=256 smax=512 max=1024 timeout=10 ttl=10
ProxyPass /xyz http://localhost:8080/xyz min=256 smax=512 max=1024 timeout=10 ttl=10

A cláusula ProxyPreserveHost On faz com que o proxy preserve (como o prório nome sugere) o host enviado na requisição. O mapeamento para o Jboss ou Weblogic é feita usando a diretiva ProxyPass, que contém a seguinte sintaxe:

ProxyPass [path] !|url [key=value key=value ...]]

Caso se queira negar uma determinada uri, basta adicionar o sinal de ! no final, caso contrário será necessário especificar para onde será encaminhado a requisição. Lembrando que as urls negadas, e que portanto não deverão ser processadas pelo backend, devem ser definidas primeiro. No exemplo dado, a uri /ghi nao será processada pelo backend. Caso fóssems usar o mod_proxy_ajp basta substituir o http:// por ajp:// e substituir o LoadModule do mod_proxy_http para mod_proxy_ajp.

A partir do Apache 2.2.6 uma nova cláusula foi criada, chamada ProxyPassMatch, permitindo especificar uma expressão regular na definação dos paths que serão jogados para o backend.

Espero que tenha ficado claro…qualquer dúvida, deixe seu comentário.

Ahh!! Mais uma coisa… o módulo mod_proxy existe no apache 2.0.x, porém ele ainda está meio bugado. :)

Share

Switch to our mobile site