Build

We'll begin at the site.pp again, and model our application from the endpoint. I have added two additional service lines that ensure that firewalls are disabled for the purpose of this lesson. We could consider using puppetlabs/firewall to manage our firewall as well, and even produce and consume FQDNs for our firewall. In the following sample, you will notice a few things:

  • We're passing a dbpass variable to the application. This could be stored in Hiera and encrypted with EYAML.
  • We have two wordpress nodes and two haproxy nodes that each have their own unique name in the appserver:
# For the purposes of this demo, the next two lines can be used to ensure firewalls
# are off for all CentOS nodes.

service {'iptables': ensure => stopped }
service {'firewalld': ensure => stopped }

site {
myapp { 'myapp':
dbpass => 'rarypass',
nodes => {
Node['mysql'] => [ Myapp::Db['myapp']],
Node['wordpress'] => [ Myapp::Web['myapp-1']],
Node['wordpress-2'] => [ Myapp::Web['myapp-2']],
Node['haproxy'] => [ Myapp::Lb['myapp-1']],
Node['haproxy-2'] => [ Myapp::Lb['myapp-2']],
}
}
}

After our application is declared, we can model our init.pp to declare the entire application. There is a lot going on in this application, so note the following:

  • Five variables are made available, and the db variables are used in both the DB and the App.
  • Myapp::Db produces a database.
  • Myapp::Web consumes a database and produces an HTTP service resource.
  • We use the collect_component_titles function from puppetlabs/app_modeling to provide an array that we can iterate over. We're collecting the nodes via $nodes that are attached to Myapp::Web and Myapp::Lb. These values are named allwebs and alllbs.
  • We use a map function from puppetlabs/stdlib against $allwebs. In this map function, we turn each node name into the value Http["web-${wordpress_name}"], where $wordpress_name is the name of each node attached to the Myapp::Web application. We use this value as our export on each MyApp::Web declaration.
  • We provide the value of $http (Http["web-${wordpress_name}"]) back to the array of $https, so that we can use these values on the load balancer.
  • Our load balancer uses an each statement in place of a map statement, because we don't need to transform any of this data:
application myapp (
$dbuser = 'wordpress',
$dbpass = 'w0rdpr3ss!',
$dbname = 'wordpress',
$webpath = '/var/www/wordpress',
$webport = '80'
) {

myapp::db { $name:
dbuser => $dbuser,
dbpass => $dbpass,
dbname => $dbname,
export => Database["db-${name}"],
}

# This section can be confusing, but here is essentially what's going on
# $allwebs is an array full of every node assigned to Myapp::Web in our application
# $https takes that $allwebs array of every node, creates a service resource,
# adds myapp::web to each node providing values for that service resource, and then
# returns all transformed service resource names back to the array.

# We're transforming each node listed in our site.pp into an array of Http[<nodename>]
# resource calls. And on each node we'll apply our defined type inside of the
# same map.

$allwebs = collect_component_titles($nodes, Myapp::Web)

$https = $allwebs.map |$wordpress_name| {

$http = Http["web-${wordpress_name}"]

myapp::web { "$wordpress_name":
dbuser => $dbuser,
dbpass => $dbpass,
dbname => $dbname,
webport => $webport,
webpath => $webpath,
consume => Database["db-${name}"],
export => $http,
}

$http

}

# We'll use an each statement here instead of a map, because we don't need
# any Load balancer values returned. They're the end of the chain. Our each
# statement covers each node, and $https from before is used to add nodes
# to the load balancer

$alllbs = collect_component_titles($nodes, Myapp::Lb)

$alllbs.each |$load_balancer| {

myapp::lb { "${load_balancer}":
balancermembers => $https,
require => $https,
port => '80',
balance_mode => 'roundrobin',
}

}

}

Our myapp::db produces a MySQL server, and a single database meant to serve our application. We use the values of dbuser, dbpass, and dbname from our application at init.pp. Pay special attention to the produces line, using the app_modeling service resource for databases at the bottom of the manifest:

  • Produces a host from the FQDN of the machine to be consumed by the web application.
  • Produces a port which is not used by our web manifest, but provides an availability test to our application orchestration nodes. The application orchestration for the web will not trigger until the node can reach a database at the FQDN on port 3306. Without this declaration, it will default to 5432, which is the default port of a postgres server:
define myapp::db (
$dbuser,
$dbpass,
$dbname,
){

class {'::mysql::server':
root_password => 'Sup3rp@ssword!',
override_options => {
'mysqld' => {
'bind-address' => '0.0.0.0'
}
}
}

mysql::db { $dbname:
user => $dbuser,
password => $dbpass,
host => '%',
grant => ['ALL'],
}
}
# This produces line is producing 2 values: host and port. We'll use host directly
# on Myapp::Web, but the port designator is used to pass the Resource Type test for
# Database using puppetlabs/app_modeling. Without the port, the test will fail to find
# the upstream Database and won't finish the agent run.
Myapp::Db produces Database {
host => $::fqdn,
port => '3306',

}

Our Myapp::Web call will make use of five variables from our initial application, but receive its database host from the consumed resources. Pay attention to the following:

  • The value for $dbhost is filled by consuming the database. At the bottom, we explicitly map the value of $dbhost to the consumed $host value in the Myapp::Web consumes Myapp::Db.
  • We pass $dbhost, provided by the consume to class wordpress, providing an automatic connection to a remote DB.
  • Myapp::Web produces an HTTP resource that provides host, port, IP, and status codes. We'll use the host, port, and IP for our load balancer, but the status_codes is another availability test to ensure that the website served by the haproxy is up with a status code of 302 or 200:
define myapp::web (
$webpath,
$webport,
$dbuser,
$dbpass,
$dbhost,
$dbname,
) {

package {['php','mysql','php-mysql','php-gd']:
ensure => installed,
}

class {'apache':
default_vhost => false
}

include ::apache::mod::php

apache::vhost { $::fqdn:
port => $webport,
docroot => $webpath,
require => [File[$webpath]],
}

file { $webpath:
ensure => directory,
owner => 'apache',
group => 'apache',
require => Package['httpd'],
}

class { '::wordpress':
db_user => $dbuser,
db_password => $dbpass,
db_host => $dbhost,
db_name => $dbname,
create_db => false,
create_db_user => false,
install_dir => $webpath,
wp_owner => 'apache',
wp_group => 'apache',
}
}
Myapp::Web consumes Database {
dbhost => $host,
}
Myapp::Web produces Http {
host => $::clientcert,
port => $webport,
ip => $::networking['interfaces']['enp0s8']['ip'],
# Like the port parameter in the Database provider, we'll need to send the status_codes
# flag to the Http provider to ensure we don't only accept a 302 status code.
# A new wordpress application sends status code 200, so we'll let it through as well.
status_codes => ['302','200'],
}

Myapp::Lb doesn't actually consume or export any resources. We build a haproxy::listen service, and then for every balancermember, we import the aforementioned values. In our application declaration, we ran each statement against every member of the $https array, and the following code transforms that data into a relevant load balancer. We take the host, port, and IP produced from every myapp::web, and add it as a member to our haproxy::listen:

define myapp::lb (
$balancermembers,
String $ipaddress = '0.0.0.0',
String $balance_mode = 'roundrobin',
String $port = '80',
) {

include haproxy

haproxy::listen {"wordpress-${name}":
collect_exported => false,
ipaddress => $::networking['interfaces']['enp0s8']['ip'],
mode => 'http',
options => {
'balance' => $balance_mode,
},
ports => $port,
}

$balancermembers.each |$member| {
haproxy::balancermember { $member['host']:
listening_service => "wordpress-${name}",
server_names => $member['host'],
ipaddresses => $member['ip'],
ports => $member['port'],
}
}

}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.59.145.158