From a14ba1235a61375ecfd319e8f0fb8c24e354232d Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 4 Aug 2022 23:57:54 +0200 Subject: [PATCH] cluster/services/patroni: init --- cluster/services/patroni/default.nix | 49 +++++++++++ cluster/services/patroni/etcd.nix | 21 +++++ cluster/services/patroni/haproxy.nix | 41 ++++++++++ .../patroni/passwords/replication.age | Bin 0 -> 884 bytes cluster/services/patroni/passwords/rewind.age | Bin 0 -> 901 bytes .../services/patroni/passwords/superuser.age | Bin 0 -> 867 bytes cluster/services/patroni/worker.nix | 76 ++++++++++++++++++ secrets.nix | 3 + 8 files changed, 190 insertions(+) create mode 100644 cluster/services/patroni/default.nix create mode 100644 cluster/services/patroni/etcd.nix create mode 100644 cluster/services/patroni/haproxy.nix create mode 100644 cluster/services/patroni/passwords/replication.age create mode 100644 cluster/services/patroni/passwords/rewind.age create mode 100644 cluster/services/patroni/passwords/superuser.age create mode 100644 cluster/services/patroni/worker.nix diff --git a/cluster/services/patroni/default.nix b/cluster/services/patroni/default.nix new file mode 100644 index 0000000..7c21e7a --- /dev/null +++ b/cluster/services/patroni/default.nix @@ -0,0 +1,49 @@ +{ config, lib, ... }: + +let + inherit (config.vars) hosts; + + cfg = config.services.patroni; + + renameToLink = mode: n: v: lib.nameValuePair "patroni-etcd-node-${mode}-${n}" v; + + genLinks = mode: nodes: f: lib.mapAttrs' (renameToLink mode) (lib.genAttrs nodes f); + + getMeshIp = name: config.vars.mesh.${name}.meshIp; + + mkLink = name: { + ipv4 = getMeshIp name; + protocol = "http"; + }; +in +{ + vars.patroni = { + etcdNodes = lib.genAttrs cfg.nodes.etcd (name: config.links."patroni-etcd-node-peer-${name}"); + etcdNodesClient = lib.genAttrs cfg.nodes.etcd (name: config.links."patroni-etcd-node-client-${name}"); + etcdExtraNodes = [ "fly=http://10.1.1.151:2380" ]; + passwords = { + PATRONI_REPLICATION_PASSWORD = ./passwords/replication.age; + PATRONI_SUPERUSER_PASSWORD = ./passwords/superuser.age; + PATRONI_REWIND_PASSWORD = ./passwords/rewind.age; + }; + }; + links = genLinks "client" cfg.nodes.etcd mkLink + // genLinks "peer" cfg.nodes.etcd mkLink + // { + patroni-pg-internal.ipv4 = "0.0.0.0"; + patroni-api.ipv4 = "0.0.0.0"; + patroni-pg-access.ipv4 = "127.0.0.1"; + }; + services.patroni = { + nodes = { + worker = [ "VEGAS" "prophet" ]; + etcd = [ "VEGAS" "prophet" ]; + haproxy = [ "VEGAS" "prophet" ]; + }; + nixos = { + worker = ./worker.nix; + etcd = ./etcd.nix; + haproxy = ./haproxy.nix; + }; + }; +} diff --git a/cluster/services/patroni/etcd.nix b/cluster/services/patroni/etcd.nix new file mode 100644 index 0000000..8f1cb5f --- /dev/null +++ b/cluster/services/patroni/etcd.nix @@ -0,0 +1,21 @@ +{ cluster, lib, pkgs, ... }: + +let + inherit (cluster.config) vars; + + getEtcdUrl = name: vars.patroni.etcdNodes.${name}.url; + + mkMember = n: "${n}=${getEtcdUrl n}"; +in + +{ + services.etcd = { + enable = true; + dataDir = "/srv/storage/private/etcd"; + initialCluster = (map mkMember cluster.config.services.patroni.nodes.etcd) ++ vars.patroni.etcdExtraNodes; + listenPeerUrls = lib.singleton vars.patroni.etcdNodes.${vars.hostName}.url; + listenClientUrls = lib.singleton vars.patroni.etcdNodesClient.${vars.hostName}.url; + }; + # run on any architecture + systemd.services.etcd.environment.ETCD_UNSUPPORTED_ARCH = pkgs.go.GOARCH; +} diff --git a/cluster/services/patroni/haproxy.nix b/cluster/services/patroni/haproxy.nix new file mode 100644 index 0000000..6a4e7b8 --- /dev/null +++ b/cluster/services/patroni/haproxy.nix @@ -0,0 +1,41 @@ +{ cluster, ... }: + +let + inherit (cluster.config) vars; + + internalPort = cluster.config.links.patroni-pg-internal.portStr; + + checkPort = cluster.config.links.patroni-api.portStr; + + nodes = cluster.config.services.patroni.nodes.worker; + + getMeshIp = name: vars.mesh.${name}.meshIp; + + mkServerString = name: "server pg_ha_${name}_${internalPort} ${getMeshIp name}:${internalPort} maxconn 200 check port ${checkPort}"; +in + +{ + services.haproxy = { + enable = true; + config = '' + global + maxconn 200 + + defaults + log global + mode tcp + retries 2 + timeout client 30m + timeout connect 4s + timeout server 30m + timeout check 5s + + listen patroni + bind ${cluster.config.links.patroni-pg-access.tuple} + option httpchk + http-check expect status 200 + default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions + ${builtins.concatStringsSep " \n" (map mkServerString nodes)} + ''; + }; +} diff --git a/cluster/services/patroni/passwords/replication.age b/cluster/services/patroni/passwords/replication.age new file mode 100644 index 0000000000000000000000000000000000000000..431e3f4e9353e6d364573cfc0433dcc7ebf6c3f3 GIT binary patch literal 884 zcmZY4`)eC@0040D2WNvns1$sFdK01O%yM_RN1{W$BzMW>bxE7#a;H^t-%IXt$>ko& zU2<{V4=woY9Bh*@R-Gb)jn(O>1qIjr(BfmQvZ+JYL1%Ri6hyl*uvV=4>--Bod@4%S zUu^-~Gdp#owcW6lfQ$J2PeARq>aWTujw4|x%i#n{L2x2arlK{zY3Djd6$5U!Rp=L- zVze9z)$yh(M)C{+H$+@veeIYUw(BWH&*oU9L1B#%rf$flDJo9V^g5n`lLwgti1yDwNU7wh#sB%6et2w!v z7&fD9rL5UCMJNbLBiyW+LRo912sSH~=o>XT$j2QDlDaK!1n=XaqGn44i!~iC*Y^5F zx|Q_sLa<*m`rS@CB6wQchv>nkoHRwiQ4B#A%56Z3*+kwIu;G-5@OUmx#WNnBaq<6Y zgpg_W6o`)^0jAiD6|+*G2xHk;q?lAoMgVJ@GR;V&pt0LHkchK9>%)}>2uayEQ?_|M zMMyExGUcd|i=+db&ho}E&5V##-9y{Pe>c^y*wsqA3ZZ%xLekvM?qe;VT!OP2ZvhQU z)iF9)bTj=@74Rgdq-kJSu%?x%VW9>KPOGPfOfD)mGY0Jnx+DHu@cSVUcM+`>Bk}~6 z-j<`?3dyk!hL$}t?;(yP#b7EJVA(K88@}{!FDqO3HsOhL*W#BxIQ+m-#{b|@iv;V3 zK3{r!YU^U;%GlxF(%!T4?4tU@i>WV07iL}J=Z{a`HF)R7_FHC7Sg$_KoVq)?>#K*A z6YmdPVW&55RlL#r=4Kba{xrmb=O^lRj&skLX9MQ8WS(ueB{ z_kXl|*SVF6@8&l4J-!+)9fYup^*0Z^wdL~o+Mn{~m(T5guVbY008hR7U71gu2?2R8|PzacD+aL(xk%V^1938Ub#!IIf|M~F84@scgf{> zPR2l)#R>`qiP#UismK(O!5#=Ys#7aMZJE+pAIR(~8w@68#SKyX+TTC$D{3mJTBT;+ zX&JUPVK+6Xg8<+mpX=(NT1Igk3Hulp52A!GKOLKn)Fs!`WVB+_JZ~sinQXCjsfQY_ zz>`XuXe*sgJ&yr|9aDL+BJmg=sL}=A&H5orx8Q!BZW=;@OmR6nUV@pZ0q@*!$P?kN zk9PYZQRZ`;8tM5PZ8DqEVHwvT5=(gvagr2Mb~c74jkHbx0%E310#hT?3A|vi1kGWt z5MnYJy{S}0TG3lhBCKl7Zn?U1D+eU9P54MXA?X<;i)n10#iuJ~)k_wIQaAt==A?&;g38c}X%E>skTX&GsxU!57?$8%Y_kRWVCSVdoYs(6yfC z3ry-LUxa$N4A*)wH78JTT*H)VC)!Tbow(2oQE^lj`L2`%><&pLSSp=Y`YzO!!%i^G zX8N#YI-b)Y2rS$$>irtTqICTKjRm!)T69&w=u24&<%CSoZ8wQrF^jecFG5CSJ{%KD z3Zp?t+bfF*qUW-v+VFQJrl>L+;#M4`A8f>cRD;r4M?v`(r*mwL!$}+NMMEV31VNwI z2r(V8V+(|ol5i?y5{B(CcB_cNP9q>k^-@j5%#>-N1Tf@$i+uFs7`Qrgc5v&H*9N|^ z^^KnofvxR}=2U6ugVFtT{l*z`(SQcN7uVZoo>{u}#_-JM9n!|g;;zox{;PMr{Lkm~ z#lb=Nm+0+37f!;z&X5Hndj9%&@EwI%X&%}0<)-xmGEeL^K(yWOa80Ri#KN1 zE**H(G3Iv9tv>hNo|)pitJk(_95wR$Zn5^#`qEqHe+q5nJ{U!%anh<-{Ma&RgF<^5#RKy$cs6r`#8$$LHtoKJxYL ZU7yA;GZzj+`~LFkqf_I#oAa+z{{a>YQwjh8 literal 0 HcmV?d00001 diff --git a/cluster/services/patroni/passwords/superuser.age b/cluster/services/patroni/passwords/superuser.age new file mode 100644 index 0000000000000000000000000000000000000000..63a8259bea0d8e75b5428d8c1709693cef9a822c GIT binary patch literal 867 zcmZY4`-|HI0KoB~!mv6W_~Kw{7~Xax^xCvdnz%7ZUuoKFlQwPBbg*0VXp(DsX_GcD zJ=xq3L-YqxP92==1|9=qMJnvVXu}mvR*qK z$~eeaJf;Xi1~keYzSZ$iA1&&k^aO^4Y6dvjCM}iEx>&{Q7QqMsY-Q&Qq34tt;Y%tNF1_tuBXJ&d>r>EjRRf!g)X2d~iWQ=HV zp<;+mH7c+x)r1b&g7Biqh(su^*_iO(n?5=&v$S6}q`D~q!?q1zHDKSiWXnZ;pq*j( z97EZjjo?Acs6@n`#7U$V!7Bussu)r)=JWggz$A-;yx`{C9ZI!qk}` zS2i8iKUFsj=61b4d-empeVqpn9@zHSpVLo1^5{>)0r32#BO6!#8hPoP`N9KF&n{oz z`XR1dc>egp_Qk97U2XFdm&f^;7w>Yns~0cNJat2!{$tQn_SjSM`lauO-kqBuUR|~d zC#-|Nte-btxM%;DKOg$~*KbeLy9Ouq>Vb!L92%TsdZnAIRe1EBj&O0)iKXA~>pwjF zmKMBu