Puppet: como usar dados de uma tabela MySQL em modelos do Puppet 3.0?

3

Eu tenho alguns dados cuja fonte de verdade está em um banco de dados MySQL, o tamanho é esperado para o máximo no intervalo de algumas milhares de linhas (na pior das hipóteses) e eu gostaria de usar fantoche para configurar arquivos em alguns servidores com esses dados (principalmente iterando por essas linhas em um modelo).

Atualmente estou usando o Puppet 3.0.x, e não posso mudar o fato de que o MySQL será a fonte oficial desses dados. Por favor, note que os dados vêm de fontes externas e não de fantoches ou dos nós gerenciados.

Quais abordagens possíveis existem? Qual você recomendaria?

Os classificadores de nós externos seriam úteis aqui?

Meu "último recurso" seria despejar a tabela regularmente em um arquivo YAML e ler isso por meio do Hiera para um modelo Puppet, ou para despejar diretamente a tabela em um ou mais arquivos de texto pré-formatados prontos para serem copiados para os nós.

Há uma pergunta não respondida sobre SF sobre os usuários do sistema, mas o problema fundamental é provavelmente semelhante ao meu - ele está tentando obter dados do MySQL.

    
por Luke404 27.11.2012 / 11:52

2 respostas

3

Eu vou ainda mais longe e tenho um banco de dados MySQL que é autoritário para todos dados do servidor (na verdade, é um aplicativo django). Veja como eu os integro:

Definições de nós

Existem duas possibilidades. Atualmente, usamos um manifesto gerado, incluído no site.pp, contendo entradas como:

node "avrdb.prod.example.com" {
    $sdb_status="live"
    $sdb_db_type="slave"
    $sdb_db_version="mysql_55"
    $sdb_os="co56"
    include "s_db::avrdb"

}

Mas em breve, precisamos mudar isso para um ENC como fantoche não suporta mais isso. O ENC já está escrito e usa quase o mesmo modelo.

Dados do servidor

Algumas receitas, como nossa receita mestre de DNS, precisam de dados extras sobre servidores. Como você sugere, isso é feito em modelos. Aqui está um exemplo de um desses modelos: named.conf, que precisa conhecer todos os servidores de nomes secundários. Ele simplesmente usa a gem mysql para chegar ao banco de dados. A estrutura do banco de dados é irrelevante, é claro, mas um exemplo completo geralmente é bom:)

<%   
require 'rubygems'
require 'mysql'

dbh = Mysql.real_connect('serverdb.prod.example.com', 'user', 'pass', 'serverdb')
int_slaves = dbh.query("SELECT ip_address, name FROM network_vip WHERE name LIKE 'idns%' ORDER BY name")
int_hosts = dbh.query("SELECT i.ip_address, a.name FROM servers_interface as i LEFT JOIN servers_asset as a ON i.asset_id=a.id WHERE a.name regexp '^idns-' and i.name='eth0'");
ext_slaves = dbh.query("SELECT ip_address, name FROM network_vip WHERE name LIKE 'edns%' ORDER BY name")
ext_hosts = dbh.query("SELECT i.ip_address, a.name FROM servers_interface as i LEFT JOIN servers_asset as a ON i.asset_id=a.id WHERE a.name regexp '^edns-*' and i.name='eth0'");
%>

options {
    directory "/var/named";
    dump-file "/var/named/data/cache_dump.db";
    statistics-file "/var/named/data/named_stats.txt";
    allow-recursion { none; };
    allow-transfer { any; };
    allow-query { any; };
    // default for transfers-in and transfers-out is 10
    transfers-in 128;
    transfers-out 128;
    // default for transfers-per-ns is 2
    transfers-per-ns 8;
    //  serial-query-rate on a master has undocumented side-effects
    //  of notifying slaves much faster for many zones
    serial-query-rate 4096;
    // resolvers or authoritatives
    also-notify {
        // Internal slaves
        <% int_slaves.each{|slave| -%>
        // <%= slave[1] %>
        <%= slave[0] %>;
        <% } 
        int_slaves.data_seek(0) -%>

        // Internal dns hosts
        // Needed as we move all the boxes over to HA, where they
        // query from eth0, not vip
        <% int_hosts.each{|slave| -%>
        // <%= slave[1] %>
        <%= slave[0] %>;
        <% }
        int_hosts.data_seek(0) -%>

        // External slaves
        <% ext_slaves.each{|slave| -%>
        // <%= slave[1] %>
        <%= slave[0] %>;
        <% } -%>
        <% ext_hosts.each{|slave| -%>
        // <%= slave[1] %>
        <%= slave[0] %>;
        <% }
        ext_hosts.data_seek(0) -%>


    };
};
include "/etc/rndc.key";

// logging
logging {
    channel default_file { file "/var/log/named/named.log"    versions 10 size 100m;  print-time yes; print-category yes; };
    channel security_file { file "/var/log/named/security.log" versions 10 size 100m;  print-time yes; print-category yes; };
    channel query_file { file "/var/log/named/query.log"    versions 10 size 100m;  print-time yes; print-category yes; };
    channel debug_default { file "/var/log/named/debug.log"    versions 10 size 100m;  print-time yes; print-category yes; };

    category general  { default_file; default_debug; };
    category security { security_file; };
    category default  { default_file; };
    category queries  { query_file; };
    category edns-disabled  { null; };
};

statistics-channels {
    inet 127.0.0.1 port 8080;
};

// Do not put any zone declarations here unless they differ between views
// Put zones with data common to all views in commonzones.conf

// This view goes to all the internal nameservers
view "internal" {
    match-clients {
        // Internal slaves
        <% int_slaves.each{|slave| -%>
        // <%= slave[1] %>
        <%= slave[0] %>;
        <% } -%>

        // Internal ds hosts
        // Safety catch in case they request an AXFR on their eth0 ip
        <% int_hosts.each{|slave| -%>
        // <%= slave[1] %>
        <%= slave[0] %>;
        <% } -%>

    };
    zone "example.com" IN {
        type master;
        file "master/example.com-internal.zone";
    };
    // This path relative to chroot
    include "/etc/commonzones.conf";
    include "/etc/zones.rfc1918";
};

// This view goes to everyone else
view "others" {
    match-clients { any; };
    // Special zones that differ between views
    zone "example.com" IN {
        type master;
        file "master/example.com-external.zone";
    };
    // This path relative to chroot
    include "/etc/commonzones.conf";
    include "/etc/zones.rfc1918";
};
    
por 27.11.2012 / 22:02
2

Você também pode usar o backend hiera-mysql . Se você vir a fonte desse back-end, será fácil criar uma nova ou personalizá-la. Usando hiera assim, irá tornar o seu modelo / manifesto código mais limpo, do que usando a abordagem sugerida por Dennis (que também funciona finel)

    
por 27.11.2012 / 22:34