nixos/hbase: add thrift and rest servers

This commit is contained in:
illustris 2023-02-11 19:47:13 +05:30
parent 5d4dea59c1
commit 8f1c823ab0
No known key found for this signature in database
GPG key ID: 56C8FC0B899FEFA3
2 changed files with 141 additions and 104 deletions

View file

@ -5,11 +5,89 @@ let
cfg = config.services.hadoop; cfg = config.services.hadoop;
hadoopConf = "${import ./conf.nix { inherit cfg pkgs lib; }}/"; hadoopConf = "${import ./conf.nix { inherit cfg pkgs lib; }}/";
mkIfNotNull = x: mkIf (x != null) x; mkIfNotNull = x: mkIf (x != null) x;
# generic hbase role options
hbaseRoleOption = name: extraOpts: {
enable = mkEnableOption (mdDoc "HBase ${name}");
openFirewall = mkOption {
type = types.bool;
default = false;
description = mdDoc "Open firewall ports for HBase ${name}.";
};
restartIfChanged = mkOption {
type = types.bool;
default = false;
description = mdDoc "Restart ${name} con config change.";
};
extraFlags = mkOption {
type = with types; listOf str;
default = [];
description = mdDoc "Extra flags for the ${name} service.";
};
environment = mkOption {
type = with types; attrsOf str;
default = {};
description = mdDoc "Environment variables passed to ${name}.";
};
} // extraOpts;
# generic hbase role configs
hbaseRoleConfig = name: ports: (mkIf cfg.hbase."${name}".enable {
services.hadoop.gatewayRole = {
enable = true;
enableHbaseCli = mkDefault true;
};
systemd.services."hbase-${toLower name}" = {
description = "HBase ${name}";
wantedBy = [ "multi-user.target" ];
path = with cfg; [ hbase.package ] ++ optional
(with cfg.hbase.master; enable && initHDFS) package;
preStart = mkIf (with cfg.hbase.master; enable && initHDFS)
(concatStringsSep "\n" (
map (x: "HADOOP_USER_NAME=hdfs hdfs --config /etc/hadoop-conf ${x}")[
"dfsadmin -safemode wait"
"dfs -mkdir -p ${cfg.hbase.rootdir}"
"dfs -chown hbase ${cfg.hbase.rootdir}"
]
));
inherit (cfg.hbase."${name}") environment;
script = concatStringsSep " " (
[
"hbase --config /etc/hadoop-conf/"
"${toLower name} start"
]
++ cfg.hbase."${name}".extraFlags
++ map (x: "--${toLower x} ${toString cfg.hbase.${name}.${x}}")
(filter (x: hasAttr x cfg.hbase.${name}) ["port" "infoPort"])
);
serviceConfig = {
User = "hbase";
SyslogIdentifier = "hbase-${toLower name}";
Restart = "always";
};
};
services.hadoop.hbaseSiteInternal."hbase.rootdir" = cfg.hbase.rootdir;
networking = {
firewall.allowedTCPPorts = mkIf cfg.hbase."${name}".openFirewall ports;
hosts = mkIf (with cfg.hbase.regionServer; enable && overrideHosts) {
"127.0.0.2" = mkForce [ ];
"::1" = mkForce [ ];
};
};
});
in in
{ {
options.services.hadoop = { options.services.hadoop = {
gatewayRole.enableHbaseCli = mkEnableOption (lib.mdDoc "HBase CLI tools"); gatewayRole.enableHbaseCli = mkEnableOption (mdDoc "HBase CLI tools");
hbaseSiteDefault = mkOption { hbaseSiteDefault = mkOption {
default = { default = {
@ -21,7 +99,7 @@ in
"hbase.cluster.distributed" = "true"; "hbase.cluster.distributed" = "true";
}; };
type = types.attrsOf types.anything; type = types.attrsOf types.anything;
description = lib.mdDoc '' description = mdDoc ''
Default options for hbase-site.xml Default options for hbase-site.xml
''; '';
}; };
@ -30,7 +108,7 @@ in
type = with types; attrsOf anything; type = with types; attrsOf anything;
example = literalExpression '' example = literalExpression ''
''; '';
description = lib.mdDoc '' description = mdDoc ''
Additional options and overrides for hbase-site.xml Additional options and overrides for hbase-site.xml
<https://github.com/apache/hbase/blob/rel/2.4.11/hbase-common/src/main/resources/hbase-default.xml> <https://github.com/apache/hbase/blob/rel/2.4.11/hbase-common/src/main/resources/hbase-default.xml>
''; '';
@ -39,7 +117,7 @@ in
default = {}; default = {};
type = with types; attrsOf anything; type = with types; attrsOf anything;
internal = true; internal = true;
description = lib.mdDoc '' description = mdDoc ''
Internal option to add configs to hbase-site.xml based on module options Internal option to add configs to hbase-site.xml based on module options
''; '';
}; };
@ -50,11 +128,11 @@ in
type = types.package; type = types.package;
default = pkgs.hbase; default = pkgs.hbase;
defaultText = literalExpression "pkgs.hbase"; defaultText = literalExpression "pkgs.hbase";
description = lib.mdDoc "HBase package"; description = mdDoc "HBase package";
}; };
rootdir = mkOption { rootdir = mkOption {
description = lib.mdDoc '' description = mdDoc ''
This option will set "hbase.rootdir" in hbase-site.xml and determine This option will set "hbase.rootdir" in hbase-site.xml and determine
the directory shared by region servers and into which HBase persists. the directory shared by region servers and into which HBase persists.
The URL should be 'fully-qualified' to include the filesystem scheme. The URL should be 'fully-qualified' to include the filesystem scheme.
@ -68,7 +146,7 @@ in
default = "/hbase"; default = "/hbase";
}; };
zookeeperQuorum = mkOption { zookeeperQuorum = mkOption {
description = lib.mdDoc '' description = mdDoc ''
This option will set "hbase.zookeeper.quorum" in hbase-site.xml. This option will set "hbase.zookeeper.quorum" in hbase-site.xml.
Comma separated list of servers in the ZooKeeper ensemble. Comma separated list of servers in the ZooKeeper ensemble.
''; '';
@ -76,107 +154,36 @@ in
example = "zk1.internal,zk2.internal,zk3.internal"; example = "zk1.internal,zk2.internal,zk3.internal";
default = null; default = null;
}; };
master = { } // (let
enable = mkEnableOption (lib.mdDoc "HBase Master"); ports = port: infoPort: {
initHDFS = mkEnableOption (lib.mdDoc "initialization of the hbase directory on HDFS"); port = mkOption {
type = types.int;
openFirewall = mkOption { default = port;
type = types.bool; description = mdDoc "RPC port";
default = false; };
description = lib.mdDoc '' infoPort = mkOption {
Open firewall ports for HBase master. type = types.int;
''; default = infoPort;
description = mdDoc "web UI port";
}; };
}; };
regionServer = { in mapAttrs hbaseRoleOption {
enable = mkEnableOption (lib.mdDoc "HBase RegionServer"); master.initHDFS = mkEnableOption (mdDoc "initialization of the hbase directory on HDFS");
regionServer.overrideHosts = mkOption {
overrideHosts = mkOption {
type = types.bool; type = types.bool;
default = true; default = true;
description = lib.mdDoc '' description = mdDoc ''
Remove /etc/hosts entries for "127.0.0.2" and "::1" defined in nixos/modules/config/networking.nix Remove /etc/hosts entries for "127.0.0.2" and "::1" defined in nixos/modules/config/networking.nix
Regionservers must be able to resolve their hostnames to their IP addresses, through PTR records Regionservers must be able to resolve their hostnames to their IP addresses, through PTR records
or /etc/hosts entries. or /etc/hosts entries.
''; '';
}; };
thrift = ports 9090 9095;
openFirewall = mkOption { rest = ports 8080 8085;
type = types.bool; });
default = false;
description = lib.mdDoc ''
Open firewall ports for HBase master.
'';
};
};
};
}; };
config = mkMerge [ config = mkMerge ([
(mkIf cfg.hbase.master.enable {
services.hadoop.gatewayRole = {
enable = true;
enableHbaseCli = mkDefault true;
};
systemd.services.hbase-master = {
description = "HBase master";
wantedBy = [ "multi-user.target" ];
preStart = mkIf cfg.hbase.master.initHDFS ''
HADOOP_USER_NAME=hdfs ${cfg.package}/bin/hdfs --config ${hadoopConf} dfsadmin -safemode wait
HADOOP_USER_NAME=hdfs ${cfg.package}/bin/hdfs --config ${hadoopConf} dfs -mkdir -p ${cfg.hbase.rootdir}
HADOOP_USER_NAME=hdfs ${cfg.package}/bin/hdfs --config ${hadoopConf} dfs -chown hbase ${cfg.hbase.rootdir}
'';
serviceConfig = {
User = "hbase";
SyslogIdentifier = "hbase-master";
ExecStart = "${cfg.hbase.package}/bin/hbase --config ${hadoopConf} " +
"master start";
Restart = "always";
};
};
services.hadoop.hbaseSiteInternal."hbase.rootdir" = cfg.hbase.rootdir;
networking.firewall.allowedTCPPorts = mkIf cfg.hbase.master.openFirewall [
16000 16010
];
})
(mkIf cfg.hbase.regionServer.enable {
services.hadoop.gatewayRole = {
enable = true;
enableHbaseCli = mkDefault true;
};
systemd.services.hbase-regionserver = {
description = "HBase RegionServer";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = "hbase";
SyslogIdentifier = "hbase-regionserver";
ExecStart = "${cfg.hbase.package}/bin/hbase --config /etc/hadoop-conf/ " +
"regionserver start";
Restart = "always";
};
};
services.hadoop.hbaseSiteInternal."hbase.rootdir" = cfg.hbase.rootdir;
networking = {
firewall.allowedTCPPorts = mkIf cfg.hbase.regionServer.openFirewall [
16020 16030
];
hosts = mkIf cfg.hbase.regionServer.overrideHosts {
"127.0.0.2" = mkForce [ ];
"::1" = mkForce [ ];
};
};
})
(mkIf cfg.gatewayRole.enable { (mkIf cfg.gatewayRole.enable {
@ -192,5 +199,10 @@ in
isSystemUser = true; isSystemUser = true;
}; };
}) })
]; ] ++ (mapAttrsToList hbaseRoleConfig {
master = [ 16000 16010 ];
regionServer = [ 16020 16030 ];
thrift = with cfg.hbase.thrift; [ port infoPort ];
rest = with cfg.hbase.rest; [ port infoPort ];
}));
} }

View file

@ -53,6 +53,24 @@ with pkgs.lib;
}; };
}; };
}; };
thrift = { ... }:{
services.hadoop = {
inherit coreSite;
hbase = {
inherit zookeeperQuorum;
thrift = defOpts;
};
};
};
rest = { ... }:{
services.hadoop = {
inherit coreSite;
hbase = {
inherit zookeeperQuorum;
rest = defOpts;
};
};
};
}; };
testScript = '' testScript = ''
@ -80,5 +98,12 @@ with pkgs.lib;
assert "1 active master, 0 backup masters, 1 servers" in master.succeed("echo status | HADOOP_USER_NAME=hbase hbase shell -n") assert "1 active master, 0 backup masters, 1 servers" in master.succeed("echo status | HADOOP_USER_NAME=hbase hbase shell -n")
regionserver.wait_until_succeeds("echo \"create 't1','f1'\" | HADOOP_USER_NAME=hbase hbase shell -n") regionserver.wait_until_succeeds("echo \"create 't1','f1'\" | HADOOP_USER_NAME=hbase hbase shell -n")
assert "NAME => 'f1'" in regionserver.succeed("echo \"describe 't1'\" | HADOOP_USER_NAME=hbase hbase shell -n") assert "NAME => 'f1'" in regionserver.succeed("echo \"describe 't1'\" | HADOOP_USER_NAME=hbase hbase shell -n")
rest.wait_for_open_port(8080)
assert "${hbase.version}" in regionserver.succeed("curl http://rest:8080/version/cluster")
thrift.wait_for_open_port(9090)
''; '';
meta.maintainers = with maintainers; [ illustris ];
}) })