git.iko.soy/typeable/nixpkgs
on master help sign in
Merge pull request #118898 from talyz/gitlab-memory-bloat

nixos/gitlab: Add options to tame GitLab's memory usage somewhat

commitfdd6ca8fce9dcf3f008de62214ccfd68c94069ca authorKim Lindberger <kim.lindberger@gmail.com> dateFri 30 Apr 2021, 16:58 (6 years ago) parent445c1146389170
1 file changed+115−3
nixos/modules/services/misc/gitlab.nix+115−3
nixos/modules/services/misc/gitlab.nix+115−3
@@ -155,6 +155,7 @@ let
155155 GITLAB_REDIS_CONFIG_FILE = pkgs.writeText "redis.yml" (builtins.toJSON redisConfig);
156156 prometheus_multiproc_dir = "/run/gitlab";
157157 RAILS_ENV = "production";
158+ MALLOC_ARENA_MAX = "2";
158159 };
159160
160161 gitlab-rake = pkgs.stdenv.mkDerivation {
@@ -652,6 +653,105 @@ in {
652653 description = "Extra configuration to merge into shell-config.yml";
653654 };
654655
656+ puma.workers = mkOption {
657+ type = types.int;
658+ default = 2;
659+ apply = x: builtins.toString x;
660+ description = ''
661+ The number of worker processes Puma should spawn. This
662+ controls the amount of parallel Ruby code can be
663+ executed. GitLab recommends <quote>Number of CPU cores -
664+ 1</quote>, but at least two.
665+
666+ <note>
667+ <para>
668+ Each worker consumes quite a bit of memory, so
669+ be careful when increasing this.
670+ </para>
671+ </note>
672+ '';
673+ };
674+
675+ puma.threadsMin = mkOption {
676+ type = types.int;
677+ default = 0;
678+ apply = x: builtins.toString x;
679+ description = ''
680+ The minimum number of threads Puma should use per
681+ worker.
682+
683+ <note>
684+ <para>
685+ Each thread consumes memory and contributes to Global VM
686+ Lock contention, so be careful when increasing this.
687+ </para>
688+ </note>
689+ '';
690+ };
691+
692+ puma.threadsMax = mkOption {
693+ type = types.int;
694+ default = 4;
695+ apply = x: builtins.toString x;
696+ description = ''
697+ The maximum number of threads Puma should use per
698+ worker. This limits how many threads Puma will automatically
699+ spawn in response to requests. In contrast to workers,
700+ threads will never be able to run Ruby code in parallel, but
701+ give higher IO parallelism.
702+
703+ <note>
704+ <para>
705+ Each thread consumes memory and contributes to Global VM
706+ Lock contention, so be careful when increasing this.
707+ </para>
708+ </note>
709+ '';
710+ };
711+
712+ sidekiq.memoryKiller.enable = mkOption {
713+ type = types.bool;
714+ default = true;
715+ description = ''
716+ Whether the Sidekiq MemoryKiller should be turned
717+ on. MemoryKiller kills Sidekiq when its memory consumption
718+ exceeds a certain limit.
719+
720+ See <link xlink:href="https://docs.gitlab.com/ee/administration/operations/sidekiq_memory_killer.html"/>
721+ for details.
722+ '';
723+ };
724+
725+ sidekiq.memoryKiller.maxMemory = mkOption {
726+ type = types.int;
727+ default = 2000;
728+ apply = x: builtins.toString (x * 1024);
729+ description = ''
730+ The maximum amount of memory, in MiB, a Sidekiq worker is
731+ allowed to consume before being killed.
732+ '';
733+ };
734+
735+ sidekiq.memoryKiller.graceTime = mkOption {
736+ type = types.int;
737+ default = 900;
738+ apply = x: builtins.toString x;
739+ description = ''
740+ The time MemoryKiller waits after noticing excessive memory
741+ consumption before killing Sidekiq.
742+ '';
743+ };
744+
745+ sidekiq.memoryKiller.shutdownWait = mkOption {
746+ type = types.int;
747+ default = 30;
748+ apply = x: builtins.toString x;
749+ description = ''
750+ The time allowed for all jobs to finish before Sidekiq is
751+ killed forcefully.
752+ '';
753+ };
754+
655755 extraConfig = mkOption {
656756 type = types.attrs;
657757 default = {};
@@ -993,7 +1093,11 @@ in {
9931093 ] ++ optional (cfg.databaseHost == "") "postgresql.service";
9941094 wantedBy = [ "gitlab.target" ];
9951095 partOf = [ "gitlab.target" ];
996− environment = gitlabEnv;
1096+ environment = gitlabEnv // (optionalAttrs cfg.sidekiq.memoryKiller.enable {
1097+ SIDEKIQ_MEMORY_KILLER_MAX_RSS = cfg.sidekiq.memoryKiller.maxMemory;
1098+ SIDEKIQ_MEMORY_KILLER_GRACE_TIME = cfg.sidekiq.memoryKiller.graceTime;
1099+ SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT = cfg.sidekiq.memoryKiller.shutdownWait;
1100+ });
9971101 path = with pkgs; [
9981102 postgresqlPackage
9991103 git
@@ -1005,13 +1109,15 @@ in {
10051109 # Needed for GitLab project imports
10061110 gnutar
10071111 gzip
1112+
1113+ procps # Sidekiq MemoryKiller
10081114 ];
10091115 serviceConfig = {
10101116 Type = "simple";
10111117 User = cfg.user;
10121118 Group = cfg.group;
10131119 TimeoutSec = "infinity";
1014− Restart = "on-failure";
1120+ Restart = "always";
10151121 WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab";
10161122 ExecStart="${cfg.packages.gitlab.rubyEnv}/bin/sidekiq -C \"${cfg.packages.gitlab}/share/gitlab/config/sidekiq_queues.yml\" -e production";
10171123 };
@@ -1145,7 +1251,13 @@ in {
11451251 TimeoutSec = "infinity";
11461252 Restart = "on-failure";
11471253 WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab";
1148− ExecStart = "${cfg.packages.gitlab.rubyEnv}/bin/puma -C ${cfg.statePath}/config/puma.rb -e production";
1254+ ExecStart = concatStringsSep " " [
1255+ "${cfg.packages.gitlab.rubyEnv}/bin/puma"
1256+ "-e production"
1257+ "-C ${cfg.statePath}/config/puma.rb"
1258+ "-w ${cfg.puma.workers}"
1259+ "-t ${cfg.puma.threadsMin}:${cfg.puma.threadsMax}"
1260+ ];
11491261 };
11501262
11511263 };