Coder Social home page Coder Social logo

tuxmea / puppetlabs-haproxy Goto Github PK

View Code? Open in Web Editor NEW

This project forked from puppetlabs/puppetlabs-haproxy

0.0 1.0 0.0 1.03 MB

Puppet module to dynamically configure haproxy on Redhat family OSes using storeconfigs

License: Apache License 2.0

Ruby 64.88% Puppet 34.93% Shell 0.09% Dockerfile 0.10%

puppetlabs-haproxy's Introduction

haproxy

Table of Contents

  1. Overview
  2. Module Description - What the module does and why it is useful
  3. Setup - The basics of getting started with haproxy
  4. Usage - Configuration options and additional functionality
  5. Reference - An under-the-hood peek at what the module is doing and how
  6. Limitations - OS compatibility, etc.
  7. Development - Guide for contributing to the module

Overview

The haproxy module lets you use Puppet to install, configure, and manage HAProxy.

Module Description

HAProxy is a daemon for load-balancing and proxying TCP- and HTTP-based services. This module lets you use Puppet to configure HAProxy servers and backend member servers.

Setup

Beginning with haproxy

The simplest HAProxy configuration consists of a server that listens on a port and balances against some other nodes:

node 'haproxy-server' {
  include ::haproxy
  haproxy::listen { 'puppet00':
    collect_exported => false,
    ipaddress        => $facts['networking']['ip'],
    ports            => '8140',
  }
  haproxy::balancermember { 'server00':
    listening_service => 'puppet00',
    server_names      => 'server00.example.com',
    ipaddresses       => '10.0.0.10',
    ports             => '8140',
    options           => 'check',
  }
  haproxy::balancermember { 'server01':
    listening_service => 'puppet00',
    server_names      => 'server01.example.com',
    ipaddresses       => '10.0.0.11',
    ports             => '8140',
    options           => 'check',
  }
}

Usage

Configure HAProxy options

The main haproxy class has many options for configuring your HAProxy server:

class { 'haproxy':
  global_options   => {
    'log'     => "${facts['networking']['ip']} local0",
    'chroot'  => '/var/lib/haproxy',
    'pidfile' => '/var/run/haproxy.pid',
    'maxconn' => '4000',
    'user'    => 'haproxy',
    'group'   => 'haproxy',
    'daemon'  => '',
    'stats'   => 'socket /var/lib/haproxy/stats',
  },
  defaults_options => {
    'log'     => 'global',
    'stats'   => 'enable',
    'option'  => [
      'redispatch',
    ],
    'retries' => '3',
    'timeout' => [
      'http-request 10s',
      'queue 1m',
      'connect 10s',
      'client 1m',
      'server 1m',
      'check 10s',
    ],
    'maxconn' => '8000',
  },
}

The above shown values are the module's defaults for platforms like Debian and RedHat (see haproxy::params for details). If you wish to override or add to any of these defaults set merge_options => true (see below) and set global_options and/or defaults_options to a hash containing just the option => value pairs you need changed or added. In case of duplicates your supplied values will "win" over the default values (this is especially noteworthy for arrays -- they cannot be merged easily). If you want to completely remove a parameter set it to the special value undef:

class { 'haproxy':
  global_options   => {
    'maxconn' => undef,
    'user'    => 'root',
    'group'   => 'root',
    'stats'   => [
      'socket /var/lib/haproxy/stats',
      'timeout 30s'
    ]
  },
  defaults_options => {
    'retries' => '5',
    'option'  => [
      'redispatch',
      'http-server-close',
      'logasap',
    ],
    'timeout' => [
      'http-request 7s',
      'connect 3s',
      'check 9s',
    ],
    'maxconn' => '15000',
  },
}

HAProxy and Software Collections

To use this module with a software collection such as rh-haproxy18 you will need to set a few extra parameters like so:

class { 'haproxy':
  package_name        => 'rh-haproxy18',
  config_dir          => '/etc/opt/rh/rh-haproxy18/haproxy',
  config_file         => '/etc/opt/rh/rh-haproxy18/haproxy/haproxy.cfg',
  config_validate_cmd => '/bin/scl enable rh-haproxy18 "haproxy -f % -c"',
  service_name        => 'rh-haproxy18-haproxy',
}

Configure HAProxy daemon listener

To export the resource for a balancermember and collect it on a single HAProxy load balancer server:

haproxy::listen { 'puppet00':
  ipaddress => $facts['networking']['ip'],
  ports     => '8140',
  mode      => 'tcp',
  options   => {
    'option'  => [
      'tcplog',
    ],
    'balance' => 'roundrobin',
  },
}

Configure multi-network daemon listener

If you need a more complex configuration for the listen block, use the $bind parameter:

haproxy::listen { 'puppet00':
  mode    => 'tcp',
  options => {
    'option'  => [
      'tcplog',
    ],
    'balance' => 'roundrobin',
  },
  bind    => {
    '10.0.0.1:443'             => ['ssl', 'crt', 'puppetlabs.com'],
    '168.12.12.12:80'          => [],
    '192.168.122.42:8000-8100' => ['ssl', 'crt', 'puppetlabs.com'],
    ':8443,:8444'              => ['ssl', 'crt', 'internal.puppetlabs.com']
  },
}

Note: $ports and $ipaddress cannot be used in combination with $bind.

Configure HAProxy load-balanced member nodes

First export the resource for a balancermember:

@@haproxy::balancermember { 'haproxy':
  listening_service => 'puppet00',
  ports             => '8140',
  server_names      => $facts['networking']['hostname'],
  ipaddresses       => $facts['networking']['ip'],
  options           => 'check',
}

Then collect the resource on a load balancer:

Haproxy::Balancermember <<| listening_service == 'puppet00' |>>

Then create the resource for multiple balancermembers at once:

haproxy::balancermember { 'haproxy':
  listening_service => 'puppet00',
  ports             => '8140',
  server_names      => ['server01', 'server02'],
  ipaddresses       => ['192.168.56.200', '192.168.56.201'],
  options           => 'check',
}

This example assumes a single-pass installation of HAProxy where you know the members in advance. Otherwise, you'd need a first pass to export the resources.

Configure a load balancer with exported resources

Install and configure an HAProxy service listening on port 8140 and balanced against all collected nodes:

node 'haproxy-server' {
  include ::haproxy
  haproxy::listen { 'puppet00':
    ipaddress => $facts['networking']['ip'],
    ports     => '8140',
  }
}

node /^server\d+/ {
  @@haproxy::balancermember { $facts['networking']['fqdn']:
    listening_service => 'puppet00',
    server_names      => $facts['networking']['hostname'],
    ipaddresses       => $facts['networking']['ip'],
    ports             => '8140',
    options           => 'check',
  }
}

The resulting HAProxy service uses storeconfigs to collect and realize balancermember servers, and automatically collects configurations from backend servers. The backend nodes export their HAProxy configurations to the Puppet Server, which then distributes them to the HAProxy server.

Set up a frontend service

This example routes traffic from port 8140 to all balancermembers added to a backend with the title 'puppet_backend00':

haproxy::frontend { 'puppet00':
  ipaddress     => $facts['networking']['ip'],
  ports         => '8140',
  mode          => 'tcp',
  bind_options  => 'accept-proxy',
  options       => {
    'default_backend' => 'puppet_backend00',
    'timeout client'  => '30s',
    'option'          => [
      'tcplog',
      'accept-invalid-http-request',
    ],
  },
}

If option order is important, pass an array of hashes to the options parameter:

haproxy::frontend { 'puppet00':
  ipaddress     => $facts['networking']['ip'],
  ports         => '8140',
  mode          => 'tcp',
  bind_options  => 'accept-proxy',
  options       => [
    { 'default_backend' => 'puppet_backend00' },
    { 'timeout client'  => '30s' },
    { 'option'          => [
        'tcplog',
        'accept-invalid-http-request',
      ],
    }
  ],
}

This adds the frontend options to the configuration block in the same order as they appear within your array.

Set up a backend service

haproxy::backend { 'puppet00':
  options => {
    'option'  => [
      'tcplog',
    ],
    'balance' => 'roundrobin',
  },
}

If option order is important, pass an array of hashes to the options parameter:

haproxy::backend { 'puppet00':
  options => [
    { 'option'  => [
        'tcplog',
      ]
    },
    { 'balance' => 'roundrobin' },
    { 'cookie'  => 'C00 insert' },
  ],
}

Set up a resolver

Note: This is only available on haproxy 1.6+

# Need to start with an init-addr parameter set to none and enable runtime DNS resolution.
class { 'haproxy':
...
  defaults_options => {
    'default-server' => 'init-addr none',
...
  },
}

# Declare the resolver
haproxy::resolver { 'puppet00':
  nameservers           => {
    'dns1' => '192.168.56.1:53',
    'dns2' => '192.168.56.2:53'
  },
  hold                  => {
    'nx'    => '30s',
    'valid' => '10s'
  },
  resolve_retries       => 3,
  timeout               => {
    'retry' => '1s'
  },
  accepted_payload_size => 512,
}

# Setup the balancermember to use the resolver for DNS resolution
haproxy::balancermember { 'haproxy':
  listening_service => 'puppet00',
  ports             => '8140',
  server_names      => ['server01', 'server02'],
  ipaddresses       => ['server01', 'server02'],
  options           => 'check resolvers puppet00 resolve-prefer ipv4',
}

Set up stick-tables for a frontend (or a backend)

haproxy::backend { 'backend01':
  options => [
    { 'stick-table' => 'type ip size 1 nopurge peers LB' },
    { 'stick'       => 'on dst' },
  ],
}

This adds the backend options to the configuration block in the same order as they appear within the array.

Configure multiple haproxy instances on one machine

This is an advanced feature typically only used at large sites.

It is possible to run multiple haproxy processes ("instances") on the same machine. This has the benefit that each is a distinct failure domain, each can be restarted independently, and each can run a different binary.

In this use case, instead of using Class['haproxy'], each process is started using haproxy::instance{'inst'} where inst is the name of the instance. It assumes there is a matching Service['inst'] that will be used to manage service. Different sites may have different requirements for how the Service[] is constructed. However, haproxy::instance_service exists as an example of one way to do this, and may be sufficient for most sites.

In this example, two instances are created. The first uses the standard class and uses haproxy::instance to add an additional instance called beta.

   include ::haproxy
   haproxy::listen { 'puppet00':
     instance         => 'haproxy',
     collect_exported => false,
     ipaddress        => $facts['networking']['ip'],
     ports            => '8800',
   }

   haproxy::instance { 'beta': }
   ->
   haproxy::instance_service { 'beta':
     haproxy_package     => 'custom_haproxy',
     haproxy_init_source => "puppet:///modules/${module_name}/haproxy-beta.init",
   }
   ->
   haproxy::listen { 'puppet00':
     instance         => 'beta',
     collect_exported => false,
     ipaddress        => $facts['networking']['ip'],
     ports            => '9900',
   }

In this example, two instances are created called group1 and group2. The second uses a custom package.

   haproxy::instance { 'group1': }
   ->
   haproxy::instance_service { 'group1':
     haproxy_init_source => "puppet:///modules/${module_name}/haproxy-group1.init",
   }
   ->
   haproxy::listen { 'group1-puppet00':
     section_name     => 'puppet00',
     instance         => 'group1',
     collect_exported => false,
     ipaddress        => $facts['networking']['ip'],
     ports            => '8800',
   }
   haproxy::instance { 'group2': }
   ->
   haproxy::instance_service { 'group2':
     haproxy_package     => 'custom_haproxy',
     haproxy_init_source => "puppet:///modules/${module_name}/haproxy-group2.init",
   }
   ->
   haproxy::listen { 'group2-puppet00':
     section_name     => 'puppet00',
     instance         => 'group2',
     collect_exported => false,
     ipaddress        => $facts['networking']['ip'],
     ports            => '9900',
   }

Manage a map file

haproxy::mapfile { 'domains-to-backends':
  ensure   => 'present',
  mappings => [
    { 'app01.example.com' => 'bk_app01' },
    { 'app02.example.com' => 'bk_app02' },
    { 'app03.example.com' => 'bk_app03' },
    { 'app04.example.com' => 'bk_app04' },
    'app05.example.com bk_app05',
    'app06.example.com bk_app06',
  ],
}

This creates a file /etc/haproxy/domains-to-backends.map containing the mappings specified in the mappings array.

The map file can then be used in a frontend to map Host: values to backends, implementing name-based virtual hosting:

frontend ft_allapps
  [...]
  use_backend %[req.hdr(host),lower,map(/etc/haproxy/domains-to-backends.map,bk_default)]

Or expressed using haproxy::frontend:

haproxy::frontend { 'ft_allapps':
  ipaddress => '0.0.0.0',
  ports     => '80',
  mode      => 'http',
  options   => {
    'use_backend' => '%[req.hdr(host),lower,map(/etc/haproxy/domains-to-backends.map,bk_default)]'
  }
}

Reference

For information on the classes and types, see the REFERENCE.md

Limitations

For an extensive list of supported operating systems, see metadata.json

Development

Acceptance tests for this module leverage puppet_litmus. To run the acceptance tests follow the instructions here. You can also find a tutorial and walkthrough of using Litmus and the PDK on YouTube.

If you run into an issue with this module, or if you would like to request a feature, please file a ticket. Every Monday the Puppet IA Content Team has office hours in the Puppet Community Slack, alternating between an EMEA friendly time (1300 UTC) and an Americas friendly time (0900 Pacific, 1700 UTC).

If you have problems getting this module up and running, please contact Support.

If you submit a change to this module, be sure to regenerate the reference documentation as follows:

puppet strings generate --format markdown --out REFERENCE.md

puppetlabs-haproxy's People

Contributors

hunner avatar david22swan avatar pmcmaw avatar davids avatar tphoney avatar sheenaajay avatar lionce avatar lukasaud avatar daianamezdrea avatar jordanbreen28 avatar bmjen avatar eimlav avatar adrianiurca avatar sanfrancrisko avatar antaflos avatar chelnak avatar eputnam avatar ramesh7 avatar michaeltlombardi avatar gspatton avatar anesterova avatar michaelkoettenstorfer avatar justinstoller avatar cmurphy avatar malikparvez avatar jonnytdevops avatar bastelfreak avatar tlimoncelli avatar praj1001 avatar acidprime avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.