Rex is a cluster configuration management system based on SSH links written by Perl, which is syntactically similar to Puppet DSL. See the Chinese version of the official website. This article is only an introduction document written by me on the department’s wiki.
Common command parameters
The rex command has many parameters, but because our environment is krb certified, some parameters can only be written in Rexfile. Therefore, if you usually execute commands under /etc/puppet/webui with Rexfile, many configurations will be automatically loaded. Then there are basically only the following command parameters:
-Tv:Check which Task tasks are defined in the current Rexfile and the server group.
-H:Specifies which hosts the Task will be executed. The more convenient part here is that it supports the writing method of 10.5.16.[95..110].
-G:Specifies on which groups the Task will be executed. There are many ways to define Group. Rex supports defaults: directly specified in Rexfile through group instructions, setting through ini configuration files, etc. Currently I have implemented a groups_db directive to get it from our sqlite. groups_db('cdnbj::nginx') will automatically generate a server group called 'cdnbj::nginx', including all servers in cdnbj that have nginx deployed.
-e:Specify a temporary task. It is usually a simple command form such as 'say run "ipconfig". If you need complex logic, just write a Task in Rexfile.
-q:Specify the run log level, with -q and -qq.
-d:Specifies the run log level, with -d and -dd.
Rexfile Introduction
Parameter setting part:
set connection => "OpenSSH";
user "root";
krb5_auth;
parallelism 10;
These four lines specify that kerberos authentication is used and 10 processes execute the ssh command.
desc "install puppet agent";
task "puppet_install", sub {
}
before "puppet_install", sub {
}
after "puppet_install", sub {
}
These lines are the Rexfile task definition body format. The task directive defines a task, and the task will be executed on a specific -H or -G server. The others are optional, and the desc content will be displayed when -Tv; the tasks defined by before and after will be executed before or after the corresponding task will be executed at the '''rex command execution, that is, 10.4.1.21 local '''.
Introduction to common instructions
run
Run the command. If there is a callback function, then stdout and stderr will be passed to the callback function; if not, stdout will be used as the return value.
for example:
say run "uptime";
run "nginx -v", sub { my ($out, $err) = @_; say $err };
file
Distribute files. The syntax is similar to Puppet's file. Supports source, template, ensure, on_change and other operations. Note: rex executes Rexfiles in sequence, so there is no need to set the Puppet require command.
for example:
file "/etc//",
source => "repos/";
file "/etc/nginx/",
content => template("templates/etc/nginx/"),
owner => "nginx",
group => "nginx",
mode => 644,
ensure => 'file',
on_change => sub { service nginx => "restart"; };
file "/etc/nginx/",
ensure => "directory",
pkg
Install the software package, write the command in the early version of the command install package => "nginx" , and it has recently been changed to pkg , which is more like the Puppet syntax.
Passing arrays as pkg content is also supported. In addition, rex also provides an update_package_db directive to execute yum clean all or apt-get update operations. This is something Puppet lacks.
for example:
update_package_db();
my $packages = case operating_system,
Debian => ["apache2", "libphp5-apache2"],
CentOS => ["httpd", "php5"],
pkg $packages,
ensure => "present";
ensure also supports several meanings such as present, absent, and latest. Same as Puppet.
account
User management used the create_user and create_group instructions, and recently updated the create_user to the account instruction.
for example:
create_group 'puppet';
account "puppet",
ensure => "present",
uid => 509,
home => '/home/puppet',
comment => 'Puppet Account',
expire => '2015-05-30',
groups => ['puppet'],
password => 'puppet',
system => 1,
no_create_home => TRUE,
ssh_key => "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChUw...";
tail
Used to observe the latest addition of logs of multiple hosts at the same time. It should be a relatively useful small function. The code is as follows:
tail "/var/log/syslog", sub {
my ($data) = @_;
my $server = Rex->get_current_connection()->{'server'};
print "$server>> $data\n";
};
Remote host details related variables
Puppet has a special Facts variable to determine the details of the remote host. Because Rex uses SSH connection, it will not run an agent on the remote host to collect this information, so it still provides relevant content by remotely executing commands. Several commonly used functions (can also be considered variables) are:
is_redhat
This is used to determine whether the operating system is the RedHat series. Before, because there were a batch of Debian machines, there was always such an operation logic in the Rexfile:
if ( is_debian ) {
} elsif ( is_redhat ) {
} else {
}
operating_system_version
This is used to determine the specific operating system version number. For example, the operations that should be applied by CentOS5 and CentOS6 are different, and even CentOS6.5 and CentOS6.2 may be inconsistent.
For example, the 1w10 task in Rexfile:
if ( is_redhat and operating_system_version >= 64 )
}
route
Rex can collect much more information than puppet, such as network-related, sysctl-related, etc. The 1w10 task in Rexfile uses route information to obtain the default gateway and network card interface.
my ($default_route) = grep {
$_->{"flags"} =~ m/UG/ && (
$_->{"destination"} eq "0.0.0.0" ||
$_->{"destination"} eq "default" )
} route;
if ($default_route) {
my $default_gw = $default_route->{"gateway"};
my $default_if = $default_route->{"iface"};
run "ip route change default via ${default_gw} dev ${default_if} initcwnd 10 initrwnd 10";
};
connection
When multiple hosts perform tasks, most people want to see which host returns a certain result when outputting. I used the tail task before, but it looks very complicated to write. In fact, rex provides a more concise way of writing. That is connection->server.
task 'tellmewhoyouare', sub {
say connection->server;
}
The entire information of the currently connected server can also be obtained through the get_system_information command, which are actually equivalent. However, according to the literal meaning, it is generally used in different contexts.
If you want to view this information in full, you can view it through the dump_system_information directive. This command is different from print Dumper get_system_information() in that it will use each key as a separate variable. And these variables are embedded variables that can be directly used in the template of rex. for example:
listen <%= $eth0_ip %>:80;
visible_hostname <%= $hostname %>
Variables that are not in the dump_system_information list and want to be used in template must be explicitly passed. This is inconsistent with Puppet. Puppet can obtain variables set in any pp class through the () directive in template, which completely ignores the existence of the lexical scope ==!
for example:
file '/etc/elasticsearch/',
content => template('files/', conf => {
clustername => 'logstash'
});
Corresponding writing:
clustername: <%= $conf->{'clustername'} %>
That's all.