From 8be83904406f630363acd659ad48f17476c1ef63 Mon Sep 17 00:00:00 2001 From: jasonawang Date: Thu, 13 Oct 2022 10:15:37 +0800 Subject: [PATCH] [ISSUE-48][FEATURE][FOLLOW UP] add docs for operator (#261) ### What changes were proposed in this pull request? For issue #48 I add docs about design and usage for operator. ### Why are the changes needed? Add doc for operator ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? Just doc --- README.md | 7 + .../operator/examples/configuration.yaml | 74 ++++++++++ .../operator/examples/full-restart/README.md | 33 +++++ .../full-restart/rss-full-restart.yaml | 2 +- .../operator/examples/full-upgrade/README.md | 38 +++++ .../full-upgrade/rss-full-upgrade.yaml | 2 +- .../examples/partition-upgrade/README.md | 42 ++++++ .../rss-partition-upgrade.yaml | 2 +- .../examples/specific-upgrade/README.md | 38 +++++ .../rss-specific-upgrade.yaml | 2 +- docs/asset/rss-crd-state-transition.png | Bin 0 -> 71668 bytes docs/operator/README.md | 35 +++++ docs/operator/design.md | 137 ++++++++++++++++++ docs/operator/examples.md | 31 ++++ docs/operator/install.md | 75 ++++++++++ 15 files changed, 514 insertions(+), 4 deletions(-) create mode 100644 deploy/kubernetes/operator/examples/configuration.yaml create mode 100644 deploy/kubernetes/operator/examples/full-restart/README.md create mode 100644 deploy/kubernetes/operator/examples/full-upgrade/README.md create mode 100644 deploy/kubernetes/operator/examples/partition-upgrade/README.md create mode 100644 deploy/kubernetes/operator/examples/specific-upgrade/README.md create mode 100644 docs/asset/rss-crd-state-transition.png create mode 100644 docs/operator/README.md create mode 100644 docs/operator/design.md create mode 100644 docs/operator/examples.md create mode 100644 docs/operator/install.md diff --git a/README.md b/README.md index f874ae381c..48585664ad 100644 --- a/README.md +++ b/README.md @@ -230,6 +230,13 @@ The jar for MapReduce is located in /jars/client/mr/rss-client-mr-XXXX Note that the RssMRAppMaster will automatically disable slow start (i.e., `mapreduce.job.reduce.slowstart.completedmaps=1`) and job recovery (i.e., `yarn.app.mapreduce.am.job.recovery.enable=false`) +### Deploy In Kubernetes + +We have provided operator of uniffle used for deploying it in kubernetes environments. + +For details, see the following document: + +[operator docs](docs/operator) ## Configuration diff --git a/deploy/kubernetes/operator/examples/configuration.yaml b/deploy/kubernetes/operator/examples/configuration.yaml new file mode 100644 index 0000000000..d7e9642b90 --- /dev/null +++ b/deploy/kubernetes/operator/examples/configuration.yaml @@ -0,0 +1,74 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: rss-configuration + namespace: kube-system +data: + coordinator.conf: |- + rss.coordinator.app.expired 60000 + rss.coordinator.exclude.nodes.file.path /data/rssadmin/rss/coo + rss.coordinator.server.heartbeat.timeout 30000 + rss.jetty.http.port 19996 + rss.rpc.server.port 19997 + log4j.properties: |- + log4j.rootCategory=INFO, RollingAppender + log4j.appender.console=org.apache.log4j.ConsoleAppender + log4j.appender.console.Threshold=INFO + log4j.appender.console.target=System.err + log4j.appender.console.layout=org.apache.log4j.PatternLayout + log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n + log4j.appender.RollingAppender=org.apache.log4j.RollingFileAppender + log4j.appender.RollingAppender.File=./logs/rss.log + log4j.appender.RollingAppender.MaxFileSize=50MB + log4j.appender.RollingAppender.MaxBackupIndex=10 + log4j.appender.RollingAppender.layout=org.apache.log4j.PatternLayout + log4j.appender.RollingAppender.layout.ConversionPattern=[%p] %d %t %c{1} %M - %m%n + server.conf: |- + rss.coordinator.quorum rss-coordinator-rss-demo-0:19997,rss-coordinator-rss-demo-1:19997 + rss.jetty.http.port 19996 + rss.rpc.executor.size 500 + rss.rpc.message.max.size 1073741824 + rss.rpc.server.port 19997 + rss.server.app.expired.withoutHeartbeat 120000 + rss.server.buffer.capacity 60g + rss.server.commit.timeout 600000 + rss.server.disk.capacity 3g + rss.server.event.size.threshold.l1 128m + rss.server.event.size.threshold.l2 192m + rss.server.event.size.threshold.l3 256m + rss.server.flush.cold.storage.threshold.size 128m + rss.server.flush.thread.alive 6 + rss.server.flush.threadPool.size 12 + rss.server.hadoop.dfs.client.socket-timeout 15000 + rss.server.hadoop.dfs.replication 2 + rss.server.hdfs.base.path hdfs://${your-hdfs-path} + rss.server.health.check.enable false + rss.server.heartbeat.interval 10000 + rss.server.heartbeat.timeout 60000 + rss.server.memory.shuffle.highWaterMark.percentage 70.0 + rss.server.memory.shuffle.lowWaterMark.percentage 10.0 + rss.server.pending.event.timeoutSec 600 + rss.server.preAllocation.expired 120000 + rss.server.read.buffer.capacity 5g + rss.server.shuffle.expired.timeout.ms 120000 + rss.server.write.retry.max 2 + rss.storage.basePath /data1/rssdata,/data10/rssdata,/data11/rssdata,/data12/rssdata,/data2/rssdata,/data3/rssdata,/data4/rssdata,/data5/rssdata,/data6/rssdata,/data7/rssdata,/data8/rssdata,/data9/rssdata + rss.storage.type MEMORY_LOCALFILE \ No newline at end of file diff --git a/deploy/kubernetes/operator/examples/full-restart/README.md b/deploy/kubernetes/operator/examples/full-restart/README.md new file mode 100644 index 0000000000..2180ce209d --- /dev/null +++ b/deploy/kubernetes/operator/examples/full-restart/README.md @@ -0,0 +1,33 @@ + + +# Fully Restart of Shuffle Servers + +If we want to restart shuffle server pods in full, we need to set `.spec.shuffleServer.sync` field to `true`, and +update `.spec.shuffleServer.upgradeStrategy.type` field to be `FullRestart`. + +```yaml +spec: +shuffleServer: + sync: true + upgradeStrategy: + type: "FullRestart" +``` + +Unlike full upgrade, full restart does not require configuration and image modification. + +We can refer to the [example](rss-full-restart.yaml). \ No newline at end of file diff --git a/deploy/kubernetes/operator/examples/full-restart/rss-full-restart.yaml b/deploy/kubernetes/operator/examples/full-restart/rss-full-restart.yaml index 4083fba65e..44fbde230a 100644 --- a/deploy/kubernetes/operator/examples/full-restart/rss-full-restart.yaml +++ b/deploy/kubernetes/operator/examples/full-restart/rss-full-restart.yaml @@ -22,7 +22,7 @@ metadata: name: rss-full-restart-demo namespace: kube-system spec: - configMapName: rss-full-restart-demo + configMapName: "${rss-configuration-name}" coordinator: image: "${rss-coordinator-image}" initContainerImage: "busybox:latest" diff --git a/deploy/kubernetes/operator/examples/full-upgrade/README.md b/deploy/kubernetes/operator/examples/full-upgrade/README.md new file mode 100644 index 0000000000..d8a46be9c9 --- /dev/null +++ b/deploy/kubernetes/operator/examples/full-upgrade/README.md @@ -0,0 +1,38 @@ + + +# Fully Upgrade of Shuffle Servers + +If we want to upgrade shuffle servers in full, we first need to update the configuration files in the configMap. + +Then, we need to edit the rss object as follows: + ++ update `.spec.shuffleServer.image` with new image version of shuffle server ++ set `.spec.shuffleServer.sync` field to `true` ++ update `.spec.shuffleServer.upgradeStrategy` field: + + set `.spec.shuffleServer.upgradeStrategy.type` to be `FullUpgrade` + +```yaml +spec: + shuffleServer: + image: "${rss-shuffle-server-image}" + sync: true + upgradeStrategy: + type: "FullUpgrade" +``` + +We can refer to the [example](rss-full-upgrade.yaml). \ No newline at end of file diff --git a/deploy/kubernetes/operator/examples/full-upgrade/rss-full-upgrade.yaml b/deploy/kubernetes/operator/examples/full-upgrade/rss-full-upgrade.yaml index a721557410..a34afbd7d6 100644 --- a/deploy/kubernetes/operator/examples/full-upgrade/rss-full-upgrade.yaml +++ b/deploy/kubernetes/operator/examples/full-upgrade/rss-full-upgrade.yaml @@ -22,7 +22,7 @@ metadata: name: rss-full-upgrade-demo namespace: kube-system spec: - configMapName: rss-full-upgrade-demo + configMapName: "${rss-configuration-name}" coordinator: image: "${rss-coordinator-image}" initContainerImage: "busybox:latest" diff --git a/deploy/kubernetes/operator/examples/partition-upgrade/README.md b/deploy/kubernetes/operator/examples/partition-upgrade/README.md new file mode 100644 index 0000000000..75cfe50cb8 --- /dev/null +++ b/deploy/kubernetes/operator/examples/partition-upgrade/README.md @@ -0,0 +1,42 @@ + + +# Specific Upgrade of Shuffle Servers + +If we want to upgrade shuffle servers in partition mode, we need to edit the rss object as follows: + ++ update `.spec.shuffleServer.image` with new image version of shuffle server ++ set `.spec.shuffleServer.sync` field to `true` ++ update `.spec.shuffleServer.upgradeStrategy` field: + + set `.spec.shuffleServer.upgradeStrategy.type` to be `PartitionUpgrade` + + update `.spec.shuffleServer.upgradeStrategy.partition` field, which has the same meaning + as `.spec.updateStrategy.rollingUpdate.partition` field + in [StatefulSet workload](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) (the replicas + whose index is less than this value will keep the old version, and the replicas whose index is greater than or + equal to this value will be updated to the new version) + +```yaml +spec: + shuffleServer: + image: "${rss-shuffle-server-image}" + sync: true + upgradeStrategy: + type: "PartitionUpgrade" + partition: 2 +``` + +We can refer to the [example](rss-partition-upgrade.yaml). \ No newline at end of file diff --git a/deploy/kubernetes/operator/examples/partition-upgrade/rss-partition-upgrade.yaml b/deploy/kubernetes/operator/examples/partition-upgrade/rss-partition-upgrade.yaml index fa4bf71cec..5f7912519e 100644 --- a/deploy/kubernetes/operator/examples/partition-upgrade/rss-partition-upgrade.yaml +++ b/deploy/kubernetes/operator/examples/partition-upgrade/rss-partition-upgrade.yaml @@ -22,7 +22,7 @@ metadata: name: rss-parition-upgrade-demo namespace: kube-system spec: - configMapName: rss-parition-upgrade-demo + configMapName: "${rss-configuration-name}" coordinator: image: "${rss-coordinator-image}" initContainerImage: "busybox:latest" diff --git a/deploy/kubernetes/operator/examples/specific-upgrade/README.md b/deploy/kubernetes/operator/examples/specific-upgrade/README.md new file mode 100644 index 0000000000..5ebc022622 --- /dev/null +++ b/deploy/kubernetes/operator/examples/specific-upgrade/README.md @@ -0,0 +1,38 @@ + + +# Specific Upgrade of Shuffle Servers + +If we want to upgrade shuffle servers by specifying replicas, we need to edit the rss object as follows: + +- update `.spec.shuffleServer.image` with new image version of shuffle server +- set `.spec.shuffleServer.sync` field to `true` +- update `.spec.shuffleServer.upgradeStrategy` field: + - set `.spec.shuffleServer.upgradeStrategy.type` to be `SpecificUpgrade` + - update `.spec.shuffleServer.upgradeStrategy.specificNames` field, which means the pod name we want to upgrade + +```yaml +spec: + shuffleServer: + image: "${rss-shuffle-server-image}" + sync: true + upgradeStrategy: + type: "SpecificUpgrade" + specificNames: [ "rss-shuffle-server-demo-0" ] +``` + +We can refer to the [example](rss-specific-upgrade.yaml). \ No newline at end of file diff --git a/deploy/kubernetes/operator/examples/specific-upgrade/rss-specific-upgrade.yaml b/deploy/kubernetes/operator/examples/specific-upgrade/rss-specific-upgrade.yaml index c2fca59c46..48c9b490fd 100644 --- a/deploy/kubernetes/operator/examples/specific-upgrade/rss-specific-upgrade.yaml +++ b/deploy/kubernetes/operator/examples/specific-upgrade/rss-specific-upgrade.yaml @@ -22,7 +22,7 @@ metadata: name: rss-specific-upgrade-demo namespace: kube-system spec: - configMapName: rss-specific-upgrade-demo + configMapName: "${rss-configuration-name}" coordinator: image: "${rss-coordinator-image}" initContainerImage: "busybox:latest" diff --git a/docs/asset/rss-crd-state-transition.png b/docs/asset/rss-crd-state-transition.png new file mode 100644 index 0000000000000000000000000000000000000000..f5329b8c46a0cb0451189af7d9bca876919a8059 GIT binary patch literal 71668 zcmbTd1yo#1&@ebiu;3n?L4qeFkOT`lFgOgZ!QEYhyAJM_Ay{w?PS9Y1!66U=!6mo` z_;22O-|n8X|2hAjozqvkZdG-6Rdsc>Oq7a}3?2>@4hRIolZ8sbKp;#g2!tMvg$6)U zit!jhAk;M#1$79J<>loS5*B&!;>GJXuPxjH+}+&;1YZX`IK34TZl<9DlC77W$XgMH zUt(Xy#zXkbVjP0SNGGrlz*k)qA+R zb2T+ zhWx*Z1K5USlx1dSzIydaNJz*()*oQ_DIVUj&?zD++PBsplM@pa6{VrCDK06Q9uU;B zboE9+pkd}%UEi#zYu+OwOAFsW?eRT}44z zL0n8My>_5#Y`d_zNKsw47I|RiGto8YQENbdU}TTU+d`T)F!1?4OF$Xw2YQi#K*@E3=AAy z-E?Hl>`rkaVKvuhfhB~U0VjMT*(clqz1Ao47|L!AiO9P>pq{PsOA}QC?-! zK!f|U$wh`-5DKZQtdzLA*W&(STbu+hNJ@3E1v_}IJ1g|Yt=61tqsPz4Q5O;CiiUbV40f8z! zYJWwua9Mx?-6PmO7kN3LgYZ7KY(!_v!$4MvYgwFCa14;q*juH~Yi4akpf_;T?w6hj z&;(w!2TC^$JIHT{()B&>k{vq8;{a7G?#DY&0fpLzC=3%IPhE2veV}<34n-+gep@7b zQZ0k67Y8zmG3bLGo?Z+87$IhT2Qtd8CJjjPlm^wz7|WUVWw27mfmTI`&_E0bP>m8m z`cwi31SG{!QjiZA@fSQH^}hxGsWBa71@(dm(Mm?|D-cST5M0zB+>C@IjE@3|86Saw zM^qxJ7;pt9qIUn~0bF8Gl-1BJOxWY@MxcPsPX?fELKp~08CdL~6yO4q0`Nr+xPZh8 z)P&{V3jLqh8i5hrBjdD7(zs}ByBzd2>C@4ZQ=VgXgYM88qH z$NIFJva-D>K!zKwTf_;Ae^F#^xnB|k-~6gL{~>Ry1isTLq)VBT0MJ`+Qs6FDwX{ZX z%mY$*_!sH+i03ek6jXJ&;nP=ON(Nv&93%o{KDj#b3T!j(6d>?8xmwl|52!uu2`CVd z|0OP9F~pKMpzxGu7rT`Fg$y{or6Vp`?MH?l?OabA}E` z|J(T=@sh2zWH8Xm5J%$`)YIO??+s##pYhSE{~scxGQc$8lU}^0ntgT}f&J^S<1?iJ z;?MTVZNFTShiiWw(;y2s^&?!N)$3RO2QR`%1Jj#%h>DAe1xzToi>ExH$yrS422@OQ z#QX-+Z2T_!Q;8oMhI&bnd-FNf1|^B8N4uT#ZJyKNL2Nj^I#GDLb=ln;c7u9EEhJXr zQv@G~)Udc2C;L00>?hm7Cjnu{yk3j+Bh`b&%SA3DD-#;_0oI-xUuVhAHyt=~H@FcR zF$)E|jB!6p`k4`+!1|a(e2bMn$kbazOu2~T`uHbn-+?zPY9~+okETqBVW92>2vq3h z2!|%DnZWw|%SG1M^%(*6PLCv2uX2nm6a{2S!Pq$Vsm(&D6Kv3)Gn1oSk;P@*ZZC}B z{nL;Eh}FqsFfm?kmw>UOLZoV=wMS^_t;Lj4n%;Thz|mA*@+H8c#Iv^Cy9Vqk+n-k_ zH#W;hpmA)a+M#7#XK0-nElpsJE6U9ZXfJ2EfA*t*gl?m@c9P~uJtFNxm7<(R@JpUrcF99geheF6|_(G@I<2G~d+ocH&YZu_Bt}x>n$80X-|HM&&Rz-!v8*J+E z0G6u}j2(yV=hbu7zx?hV0jAL%bcPE0+x~lNXlE)bO*9wh@0PFbcNq|I71T&Iy zmyu~?K>U~yq0IybsMAxle%7l_yoWhzwSEQwcso%Jq3Y0(#JnA8C=s%f7{*A3Bn>5H zT;^aTgE1U^mftQlGzrnO(89m9Itr(z_tw zVt>T()93iqnCU?5HUx(y3;{zV?X~D4sAx`YUy+J!Ypca9&~k`yYpcYFPR>%LG#KeF zO>5-78oX;PS3}f(@hBr~y4@lQxhO8KVnJP8F;vA1%RD?YDI0~{*fxFa3)$9E3{nVk z*NpZ7jn!CUv&tX4pcNW)Xbwxmnz|=WJ>@ zf|aFv;gSe$WwSR9CU&_^im7*j8ae`Rd(u2jI4rW8&u2#HNOo3}E`I+cQ7g+h^QfrK zcsf78r^J-r;wnfp)26L2@Oj6l&-7=!fcn@}7+ZLz=}6V7#VK2uRyb*ynf=%dSVLp$ zP@UbZfKp8GO8!Zpe+pNS?kHvt1F`^zn+avac=;ydcfr%1W z)07gA*vO$#(R`m0RU*Z>4474>CwPNYh+dd@ypkuK4#uF8D`i$!NkLy5)gy=&ixwP~ zfLAfw{=o2xG6=KfB+`hy4T zUX_N_H|y3ybM$zzYF&&{i!@nVPc2x&I#LTSi-cY#d>x)7vaiUYHk44bfyczVlh-=U z{pSBPN$L6NXR-MzQ}NqElEu2vPJza(Xv-JcqP?ekxX<3DPS(%L%o;JuQM=Sv?xI_{ zZb$%DY@*45q%DnVt;W)dl-qrZko+F;iqVYz00X5wN-BhugpDx5lo3W-jlNDG@?nZJ1okyIYaBOPa=)K!7O+$*W%c+MJRvB&vlP}>JCBtM1%wvu zdo!B!CO#Aol7cH`O8a2yVTMM6`h@JFx3rheHrwXn*6A^Vl{pjQe^i=E6m%Zs#>v?$ zDD9eNeQe+N=e)F-{=jr7-%bdLJcBCM8nCDR?N($ld_22t?f0BBN#pwIfh~mAa7QdR z!?ZAHOk#p`$UX5vJ|yK4{Kg+EtgN)6o&9S*oE3SE#x^QN6$0a$jH? z9!$s{^rTbg0Rp!mgd8vVDqX}*r*BBw!9N;@hf`i~Z5N=c2q9h$qBM=5^buAzK@)7d zuk2M3KM7F+UT{HLL$^eSKKRPtqiJ>cdY;R)>18C_7Vk2RM%p=RtkF@r!e6jo>}62b zzN9Ea&3SuqahwlXZ1yE6_!^?yB5;u`_b4_K^_kH?H@S5-XWd(7OA_Zsfp-Q%1k4xxe!l}W}$ zshhtKC%%dL4H;?p9-@+{WE#_e!vEH9uFz;eLnF-J2hVY~Wihw%dk%Ig%|5Gy1VX>c z*G~aVA6!JbL;Thcf7vwe)@cm#NgrWJH(ColmH6r$koO>qSPLb~mvrPoM!)VizG$eu z(?F=y@-|18v7=gq1s7Z^| zND0-pQ2hA`kz3&NYes3y34Eg7yy7hDni=K~PpI0AG3*PH z%ohPjYUzr#pHXN00jPIsCJ!De`!<+&Ld5rTv)_A%A&VFx6&x;6Prq9{o$xP$cHnr< zst7Zk$38c=6M(crte&EkLcQmG&|iN|(Zn#?7$Q$_;G8Jv{0J777myM>{*@8lamu+F z`|Y}ghGIt|1)n-SI_Kw(UB5kGZ@xN}P}N8lv!TF6qikvW2QfzD2q=ll_ZZ%OXEKXZ zK~jGSg!TNr^-Fx!5~!zo(lXb$lytLN!SJ)VJUU0ewi)ay;wW zBD7fM!(tN8d$5(_XV`v&o&whGD{(w^joAx9-+!3t`cPshom$c$&5d*@a0($I*#m)hfwv+-7Pag{)Pb1~R(e91ZS08nm)LJ4oz0IJz`~DrKFVvN! z$?4R=sqXLDgm!vCm)mAe3vSV*`PtDD0|L$)hygg3`h4=#OW3>E7b;=`<}z(EsaS;- z$^S$#Pb-!859j&cF@>iQuF~d)Qg?Q3OF^PNHboUjIcuMHbw#9cVrF(*BD)1gkem0LNlME0{F-PYP^mQE6Mh>7 z1VJDsE7Fp>ncP}a-u9k~-$=5eNCksb(G+6LitKF>eIID?tC4t`Z}|9J94w!Te~r*J zDfIVIohgDMKD7$OCCuvg`d?G=b09GTNy~uHv-6}z>gGOsdlnoQB5H_EENwkhq(Jni zQ8$j9io%*KB^bxNZ=t$OrF;?`;GZ}IEAD+Yl99TlyeS!q4jC@jJNoGRR-OaWO8VEc ze|`#v#69-`33I_a4ep+T$4=a+zDKd4WZlUSlUR>dA2Pg)>zjz>qM3U4_cgc5Qj4om4EfARe=Nv{ zNiG_m$g>*;cyaVrid~@e?ZKq;6RemNjn|f!A^gow@1$;?15$&+SG4F-prZF!%d!6R z>vOn$r6dcNsNxs0;L0zt9gpCK^vreY$FHdmCVCh%h{)J09C~Evt3LxVKFi-|J&tq- zSWE@`KfH8%iS$7Il|;`?w!_Li6?^0YAFo%(hO_<*Ops@Q5AAOHZDvIP0W2_?NNve# zBi_+K`%L{qgK{~1@F~)Ac-w**OF5Y+Y}5t*(K4TZwkj=J-K>llT1_q+Le{1c@gLJ=rKe;{D$4)hd%H%z-(24;sZDn=CSu%|!trl>0h95 z^q}DS>CFjc=IOf_V1Cij0!0YJ6-n1xtCpjnBnSk(9Gqu;s(Ix`Y3OXj)J@V4lLIsz zY*hw5u+!4@`V57naWKN%$S?!#x`DcH(sZ?Zc(%6yQ<(HBQtRRso4TTzy9bC5F|V!w zJM63f7YKMG%5IoYs?-OtiC#JhKu(aG^#sw*^PT4EqiljN+Zf+@djE_&pmIaZ%5)V< z$eaLc#rxUjw{+-BO-=pV!SAkUPioi|>y-}t<^eL?bqq+zC0{!Z3Tetz5;h6yqafa9y1g4p9+3HR!ne|39P*{JeG2jU8CnSR732+V6+ifLH z;5;5PVHr2KxA6|u&YXQU!or{FR5i@{X{G?7q53K3c&@xN6AGzm_(*ylNV<~{+x*^d zi!*JGEr<>jWjS|<&IsE?dX~v+u_3>^iLBK=Z)zt|<6UZC(WsUh7tCT#pdr|0kViFV6un~njsJN@;81Tlzq}W-;aPfM2u^e|$CS$F( zkL#a#g)iCMN5Kt)4)&Fsx z>(I?*(z5(j9z%w%ELej~>M(rO5pJQVjiQ}0OMe9+Ok!PxevE4u@mCUYVFw)QI{W() z_1aOcI$D1|>*0M7Kf0AfPa4-)2(@KVvGwhwGP7zCrYOVmP+*YqtrkO6f49wm+NZyN zAUiI^3`}VE1hmh)wfwE?%E=sj&XMLUj=Nu}K92XSkX58Yzu{RbKL5L4W@}-tqZxs7 zH5?S`2+ODT1e9xS4cW7gytr-U9*0CV2=IMV9+ktXP8fe$0w>M8dbULIr_JmpmFf3n zBL2$)CJSrH0Ac&3ik4S1d=hORNn0+}VB`dpP$CLeh|wQC2EsqH_N2WWV=w$82B7Pam?o7|Huu zSw93K)pneX=t@T==40O3YI{$LlwQeB$Iz=DuQEn5pp%CFVxa6}@F5aLC%{gTaOgNA z*zR~)pY3d#+#svaCcEWH>1nZ*>20{uoshen>rP2cROa9O%{WVVHz~i$1ApJ7bJ(zLDf)mM%r?fv zf1yv#tT-aj@N`|+{Au(v>}2=0m?uwO2$?Af{z7%j{lS4e4h_rCUw1WM=-KakQduIC z-r^F=o{Bv%gF;?U^JO9}%%4L6v*+cTcm+U*lYJ@9gbw|C?r2LA}Li%h<_#1gc$`?>X^BRR5HsJ zgcj+&W1nH*sUy~pnyy5J7=y`~pv{7ZayW+@EU#UC+Mr~sH0x(BxPz`aD9LF00;_9ulOOScMo29F zZG`Yy^OBkI7+@{H7s# zhlE85#ABZBukWOE&vk#Mj3c}Dy9;MjehR4Z`!w?ctq2x*e5?LOH0!r|E#VGFq0$_} zK5AOS0O1@Fqb~LB?v78A=RhuJU>&k+OWCw+(NaL1NY*yZ9JOYegj>jPkc@L{g@VTj z`}I^1IRZ3>((2Od4OpTtQfpxPkNINVEZ2+LlKwx?emjz~q21Td+4aE7n6HJ_fTp|^ z?c1STgp;y&@ZU_8SZs`t-)QmjxcypcY1gB7xWmMPpA5#n{c*JSZ0eO7{TO>h| zm+Z~is!MQ$#R#v3ejWC$6Pwgx*rQb4vu9xUxa-o>3y*}I>LjhFqe)BOU2x|Rf`b)0 z_&s@mqBv>}hPzo|@WhymQAPOXSNsGEwa9JU8b*rx24L(p7B)mUK<7QP8E*?|teOmL zTvWKEpt3UNEeGW$j?<|FncJY|56OP-w?+G|k3Z##s(Uz93-%c#_3WUWg+ixP zwMs-(@4-mioV5$s&ibh}wWqXNd#r`iRy)}6L|6?<9iyWFkLKD}GyaZ-tc_AFW$;mDoFh@o2RCOQsyGSvppMk~?MNCGOZP#kV}ki% zyRgz~tIj3iquIG2e z(?V5_mw;(Otqc&oHVv)z+y~LyoiXFSE5Lfq-{z5C_c^@$h^hCr(ZJ@+$Zv+%+jx7f zSI^n)rF4vRBq486?zsg#N`zaQ2$z{qXE}65mwI#RfQa zqSjp;JFQzP>{`JY_ngX@dPm!!wJa#I!U3I1evRDQsKoa_ZVS(Vbk}L;bI^(yBz!hk zf@g_LdNgx;zDjzNFy=rs1lg6s#bUxdDw2{D{cwR*mzAAH#9e0F*2cnbH=)~JnwC|~ zhqlqMpEoELrmln6e1)ytAr2Y7sb8+Q620)Okde#N7w0U%JgpP`APw1lqcp?kfeLsT zb|mJn88Q4-NYvTb+@vH?#lCUmo*0xD*M{cNu*$4hVW)!FlY)Mad^s`NLSP}_O9T7R z%?GTj5nm7<`2hjRqpWSB_WR8=$*X|KGp}IUAfQ9^fa97`hoUICW!lfKilkc4jmbqQ z+n|MkDtO>+GK3!+hCU+74w=q5i4B`5dg{t07RmQh(gEuON$FG7@26~V3(@Z`IN21| zT@kc0&2j(nO#PD}bu)8lA+>wSXeO4cY0?0!5-*CyUdb|IIyiqJX15oYg%(iJgU{LE zhwmFVNK2tC&3~8i`Ctf7Mu-o^?|_CU@Wa~HH5qqk9V-tKG-X9eskkR47s)4OtJ3^R zv`Rz{LEq7}K?-a#hye>LRtRW*=tCHkzOjiq7>k>q6_!fJTp0W14~r@RMOi|Atl9c# zGSwfY3g10&qaY#Pc^O3s-(&#Gk+(|@KLy;nHeB-pxfIL{;|*>PNO5wl*p{BL*6k1tLj^9 z$j7D~H_gmqG7pq!e0^SzWVZ8>YxG{KuN{#OG0-3AXd)?raxRBS>`0%VrMSF^^aAzZ zlT@g+w>lf@IYOM&Q#`~SUPS6etnxk-ino?w>G41dzj$$>`#$m^ZCIoZY{Wb0$(#E# zTlGjC3(0sX}MV$BA}w>wy;ZYYChgQN0h09QX}CBtCkbq3_w-uT7+z z29Sn z_UrS>vnV%uiMjH4qB8wO|L+wD?lYq^qriu5I-H~CqMJf-|~Lh~R3)^m#eQ9;@H-bH9P%T&o?*12q* zg<@w%+u6M)^2_p9E5C^kctV468)xKj5BhPa*W2r~Yc3&-&T>0TvNxd>iEpPibR zuU2k}hIqazLC!2wRcB5gkBF`!ZCiPY2TpK&2?yYSynsIy&b-qH603z>S3uP03j!5hhlC<52K2T|PJKq?_kk!FnAL#pM;Ik3p<<`7gCFYmB(>dzvp2zTtH12ECl5Zy_coc{X9^|nxG zOerpjo@LvV7LSe_{}0zp1v{{aQ9h|Mr}|X4g5Hx_c4$8S^CqcQMLm5}cx+?Ch}7`b zxD3Izf~1EM;H~`fG!aB>{CG=>sv?veY7T(`pk;NmtP1=XCB-9YqN3MwP;2+ULA*TT&+Asxw|3J(haBau&%yPN41>QOeJnP3^k#5=WZxR!rA9GE zt)F;@@zoYZFAhA~F_rFUJ{}nGu7%Il+B&t-BaO3OViboHX(_^W!xExnO!oxN z<|r^u_@TrbQqi9W+eIHGdhyD*dd2W!KqO$MM>-rx)-I~I67SbcJJqkBH=&RAnCyWY zZ$>zgzQ>zStGkG#zD2K6R|l*iFg?Pc`SCy`&Iie&8*81m0yZ18W>7enN@g-ykUSM% z$_UFMP28R`zr4JhiuG%?Mb<|(>?*pJe*8^Z2Hj+Z8z%9^{PmalB_!50VvXb%lc-c$ zn{F>5hEWXzRcy;D615_WjSzw)8I*G2{y{Eny(l*V-A~1lHoj+pIw|i2W*Z*=!X!aE zI3Afm>=H~=8HZjCJ7p+U%7j88sLpG~GwyKRyJG0?ufFg6uQxm$_qSHOFn$p``dx0M zzZ2NI*d~c-=vX$jDbD~KfT|6m+#+^3(9ncM))$Af!L-jO#kC^UrMUII9fomh?qhTW zB^AnF!CMDD<%~ZlA;6j0Qi~f}ZCgOxvUTbP=2qk7XVkLtS$%EutWrAW=xfCbwxLfJ zJ*T^=5_dbC>C0iHjqixS>fS22Gm%O9QGBRy?LOs73iL|n226gAb|)rODv77$f`TYX zwuk9I$y|9B2sY+-3g|D?XB?xZ)5P$j!>Dv9%4Xj29IWJ5cU`SEZuPX$`yHRBk$6+V zT>^5Ims(zC!FqBpPyJoOPt%#2KH+4(aOCb;fKq(D+_~Up89mdpr1&ONyiD zjO8$M?a^+RK3wkC#r-OY+4J&0qtTZp`!cPGJA0&3Yj6y>ML8e%CQ zO3*Z`L{N&vLCQ%;fRdSs{uS&Zy5VdLR&C z>7awg#5^S2-%@nt*r#ppFx&IF=vHkUXMh`73Q9mmo(71DdsM(V+6xoFl`6cy=d!Do zx;;0f=_Mp6n%Q+Lt#KXZ)xfz*z4i*6nzAA-fBaoz)6TkC5L|yDho~s6k1k5Irn@v? z#@RZchD84pX&?WHo=zLxz(USJqPMCRirZy4yfK7xq3{Hl*nM2-IR5-(b zb$t|A$7qeW!a~pLbZhDgHHQ;7y=TB$ zyG-OX0`yt42`k{ivAv@Uh&jmfqM-C3ik*OOwdun?nzc56jp?Kg68%MteRunJOXFXp zS3u;K5%yw{b*4%K*iU#vF&M=+5&c1i*zr-{F{E%p;?n3JX0Hrupi>6>=!?Bm5Gp+& zV9JSEm%1qeJelxgc&8r_1;P;D$bfY$(lVxh7PH@K{R0cAGaW3&#t^3rmyuvdT;b6E z*eK8PN>@8FZtttTeR~MzP&I~ZvWfVb!in%$o{`tWvqy{&XazAWl<)ul%j<~Vk6?g} z8X@d(XXi6wYUeZa+=z0X;T1#)E<}~u;9xJp!M^$|cWwLJU0tnPw3#x20!8?{1BDo5 zYW5?Fa89CxV*RU(M-%eUpn7v^F0^eHME61q-T=xOG0f=518+wUlp9J)Il9y@9H=CL zqn~cD#Dic!s7!hTqfC4s$N zX!D&OC}a!#l0f*}3xz$5GKnLVHWaKcwbG4ffw^N>S@16OarLxiz-GEhpSNB`vu z9IP~^s`ufjgTOIDeHCSQtp&7*IM8n__UB?j(Ax3Yz5GzpqxeKrG}6eSA6$CQcaM$| z{^p?Oxy}is&w)dwXzCGX&WcbJw7)c=q%|RlMc=rTK8%d8#aZG5hrYV;C88zkp+BS$ z(_jgld2#3@znpr0db7D|O7n>2jM*t*>}EN&cfD$^8q5`o-3XHrB2%s_ zCs~#yNGSW&j{rDuf5 z7f}n;7|YrK=U){V5LTIc68KzhheibdX0vvZ&%8{UY=NU`f4@e%KNazy63PIIAi-kK zB3_nD;Lb+;tv9+v^hfpIh(TH{S#B^Q5IdAq5uS$pFg?^mBZ1@P$xoMX+I|D9jeQ{7 z@znf>qS-m)cNo4`m-H|M8N`4H^b94-2eb=oY>g zS;dO{NJkw*1M%-# zTIA;`4I9&fgoUJ`ip%S0%At+3lwUO4NJwVTa0)(&Bngq-GlEW!L*1?x;CMO^n!g+_{iMaLofJoxvEMqq4tz2jdf6g0EmWz$aeJ<|k zzv`fSFR|!QZq;a0UaAN+$Fg>N@;TUBSJhj743*pc@s7~pfFqQegDQ@S1B?LNPf@H% z&;D2_W__Lx8xkf#)vg_;t{SQyohS`gn~Vn}AdhX0MTk6N`itzM#3?6_T_%BLeMJOg zm!RSvjP^+Xl5U=!MvN3?K=4XIi?OUj-;gawa@tw3GoHsL4iGY?f)T35r1hI#+*M6< z**dy%P?7&ZWk$GrL++Z@m2DXiRan-zf0>rQEh&;bt`2WVNxTpLk3L#RyaO;5d=|3S*%Ur@H4a-tb@e$=1Lu=atlQ8^No*Zv~u<^(m#}r!3i}=bVrP`FjsAz?|vo@G0X9^{mZ(Mrq(A2y`v*hrj z-B~Cu?FE977r`FOm^zTiT4~!{9nPLbugj-3+X+!EZ*VkJ%rC~ZhT{ImFUqE9dqXbL zgP&|W);fNG5`C*vAfh;3&5~V`idZu13nk1N*V?6(tg6%s)M4mRw=Ess5JN1Rr026I zVPgW7G=Zv7N^-<8DncbD6m|&aMNAr8<-ijVpn4Er(OWm1LS)LRrRi61wg#RZP-7kZKi?te2d{1F&#D=5W3+ zUIda78K(TPR2UN?I6Q4cS>CD4BK8c#-%(&9W~-tx7^r#9*r-3PJCr#+x#}_6mAqMh zwsxX7oEYAh`0;tTI+bMW{BkRshPojhIW2%bBpoC-!PWXWV_Hg43@5uZ2J}Cd3ll$ba*pSIDy>WOORY@zCn4kTbJRF{=n_z+m8DlF)l|S!ud79V+O_}kBYS5%y zGUAP5Eu5PJqY#h3fInkxH5H6c_WMgeDBk=U|N4;- zvO6~C0874FU%Pc2AGsy^(c#ZcT2%foPygFgSzSxio$cjT;^JmUGV>3|(9AYfQ-svM zfn?N-^m;0B{rP}UI3GJNqNK2NciuZ%gTkl7u9Sp;(`oRI?q-njV8N7vj2_AAveCxR zJ0x95oxwZ26yNHXmPdf8wJ|p}+*Fiw&Zw94!8h#cUZJ1D9 z`mPMKz%+Si9Az;hUVKqkqww-;#Pmbqr#IHcc{8ZV^T7~6n`&vH`LlLfVQTie zPSd^bjCZkGTcENC5l2&2gx>sFXD1QGZ*0j{C@gW^(I#?mMAcD?guD=#jIsQvP;Mv#DVy$S$ot6^2KgWJX9OW_I^{(We z^Qnb7gI=qe7CFcG7EMO$>93JDTj>{37%E!Osak+DLrHBKwb9U}!Ay zfTs~d4j2M^cCzWy#N^a!s#5)7Uh5t7-CH@C_@_u5)JCpxQSYUfTf(lJv9Cof1sk5S zV<2QyNTo#&EbiA;pbzVA0gGss1IPz*q}+?{ff%z2N*U;!gh|xVF7}Yg(6?PR_QhYI zonaOhJ)7kI<+Kh7>&$cCv7*=A7;E+}S>^|Z#zw;*LK^I0Y@f9~da~tlh-f?QX*Ywg zmR>PDVs&~+O#BO<;INM7dA97g0d?67x5?u9(SG~iR3mFYZ-i=OM3S z#3DW-marI)``vl%uA1lC=5IZ8Rn)QoP7{z(A@@7=f#$M`j|)2WHm@ZY(M0J|8>Az- zfnh#nN<5U*w#I4T5^pf<)I~7i?E&f7)>P&ym(2PZ_NuKo)KWph!ceO?zRB}rv0sMk zRb9*H?d$=jw8z1YEWq|zj8vzK;qa)l{_>3V*2GSI;5Uj7{)ZRjlYA7ciQ|^&Ke$RN z8x_9gcLIO2m}#U;qzk}>5>#$WJ``;4grw-+OgyPQ6Ag1SMe3XYq^G`^IgK<@z^3q#YOdD9RHoP28VM$R4{)($#z_+Dqo4`BrN;ynj;t9{urt z9gF$9Mlzjq=uD0s)Up5)aGh$H&Ztb4)<9r1$sLoJ_Fy2m-RBzW_82vPJdmM;1f=BRXDoszUUj(J;EHA8HDqRj$a8xb|hx# zwYD`FUA?w^LEM>gtg@(!3r!HgKtyPq;eC|7Zcnh5Td^uHe!c5r!%!T*%kYTe6)d?l zFJC(yN!HwhVPmsrq;?moQHEBLt}{!(b3R*@Ub+R3;o51?Vq7K%hd#|7#J^c^8jXE+ zR}*En7Rv6j3ch)4XvciJaF8%t!zeTVs3w^))a^x7oVoS~8RQnTq#%J#rO3#LmrhzB z*)-ew=3-&N$_#F>3VuYo5v?sc?*7$`MTU|*ooy7DEe~P-kT-GX%7(_)YM?}5Dd&p$0J5$ zBlt=io2_oC%T=a)qiHp3d%7XiG>ThR%6mb)EgGklC7O=y8uky)}Mrp_KPI?LJw4`|L31?x}) zt;0U3C1Kwa!R)y)5SV}_c^{E&(BGIu3Y=nrg>zDiB1Jr9mm5Tv5oaENgMBzt_oHp3Dc~ekwb)&nK|%r#Uf| z#N0s@O*LIGiHtkiC9}rgA6EDUy~(kH_O@@UIPQVTB8iexD#P5eb~g}nJ{uf}`b6iX zQ77y;^2S$V)f0@KPyHmVg1E!#$%ZOUN5}U`i8{B?wLf8&X=+d)#|0CcrZl)_401j2 zeV}mU4%bmV6=GM{mSJYrM9gQOm%%=|DC9>+?WOywXUM3mTxBr^0=+Vavb#cl1f7wP z@sa4{*r>D-2{jST6fvQ&6ttc0Ph?$o`D5#_7j1aQ9EkTmC~Y)Z42ioRB2wO;MA_{! z96;B93ZpT)2a}?5V?_Qkd?*VhEgs?sxJO1oGfQ8{pEKeSSA2gls>$g7*e`bdqoRCc zA~}|Zs#+pvuVAsW{O9~ud~fqSw)}ban{Z+FCH(8wL>rAQ$zkmF5LbjPV=<<}v|jE# zpr$H{ZQ5lB9?ZRxKhegP*WrN97Z>_aSyWA{Ir;mB@*~B{N=4{<%-+MZ4#%LM;(k3e zX!VlSg~gtR1;vwz_p`%Eo*vEUTYdZv7r&CY<39_J2i)W-TghghcfgvH%|^Ez;@33 zYi(+ZfE4;WcQR~5MN7SZ-Sxq^=i(vQs-4==S5g_XdQZ!^7+A zz|VtT@x{js*qs4S7lgz6&yY1CxyuF;3C1XEoz;Z`V|##%&mUffJ7uzdKNoH2 zj}V^lYtT`i(>D|b5tcM!s9t~_4We?cxzo>e>iwO0?{8H-l6&mp+PFA_ua#vQwx2~d zPp)2%|1Q1a-0wV|_dsTfF*4k!Sy#=-p++> z^uEBeE_G7VJIZk#Oy8fqm;DJpdJd{qcqebFJRaQspgEsC#@V^bxVooSXm&?$6K(9g zO`Ad0xI>>I7rLR*?uT;r-?J~^!j$PVu`!(JErzh`jh{g5_k1I3+Ye2 z^clBGdBy0+-+Gw?;&NOa_Y2u^`Kp|XjAwGYRJf0i^Xeui8gzlIRO>Wd>Hh|Yau2YybixC-Y8 z$-KM4LcBYfco`ldw-Q`?`K?C}0iz`QN%CF!SC26Mdg=36t7R{pTi)(1nNFTNh1#>| z@Qo*-XG=cvtGoIK}j9M`Q2JK?@g~S9Clu zF{P}21~MejKt4`hAIa5tM2yZLGaFu)IP|w`&rg*ZHmL^Y+PX z_=acbS!%vs7dY|#^5VoF{+|2ldgFv=ulGcI1}bhhVQ9#Z{=hT7fxw3M4y}KRVtzO< zBfQG41hnB_npgZUmkGomH#FL!v|l`TIZeX@Lfr`84%`_^MqB$B#|l2MpBY_Z`2{87 z!;B(YLu+##zSCRUNUd~U6^%G9Qq=A}xMLxz{eIk#1fBi(J=6Mtqx(=^Bb}AO)0ixz2d3s8!;NNFfi z+~KCr_r34^2kvjl%IxmU?3^=uWyT?!46Z4+qG&IK3v2j%2GKk-AP3HH2P*KQeODeT)rlI6^=41j8C$N!C$XJbx( zu_r*>mtZsDzK+)w?eTnzia;Rk zXy2!O=bSK{ZzqhPO~EtPcd3IG`#(4p9)DT@{2)-40=Y)BQY#z^4{huZ+nlGSx$)1j4mj-XwGnAC$cl7+^g`DwVM8QOCyFG@i6z%tDCUIv9vK@YW=rWtxuE4RyiKf9cgly*nx`f3z?SMqRGTr%?(Ok3%ge>Bes?!)YT7D2F$EZEC4n@edG(M)sF%7h&LH6YKPnz82?H@f$+u^3RT4&Etq;0!s z)_Bj_=N=E{w%f!~=uYSVv{ey_+o6&mpn8oNnq9SUY|d}ql=fACg8E>COqs4l?SN}Q z4`|f^JE-em`IEK^e%&wbvoWCjI+!eH*(y3`EJ170Q z(Nv{0utG5LC%s$IY&idtY)dOy&qM^dSP1`p11;Q(rF!Qlu!L)-dvp09XRjF4b-M7U zQ6YQ)bEg0C){vS;Dz9Q_GJn#`kfH**Q9FT%ZVT!Zi`7AcD4s%@sZ)6R_j#{Yg1ImNBtJT{B!y9}S!T`HqW>CfW>cNv!%eML!}C5OVD^3AFlR~$PZl`#FoCwf!ubSs`^ug ztWUw(#%g-O1$Z@9v26-J24ER(^ceTuwcyO}gORuudPOXazbNSQ&TUtop&{5mj>gre zDAywO&fwvB5=n^%lYD=`GBC6}^{ zLG#;tIfjY@E5P8*uxN%b03Em$Zu8^vupp?vq_VPn;){1ZZ5eyB`t#+UMBua`KopKz zDArh^+SX+%(s+%rotHHD#b0IMCo{~#|Hw&51Kh?YXX*`DNFaRZrAf>#$X2rJ-@ z_=q}Xp9#!Dt#@q7)*Oazb9G12s=q$#t}qrllQ(oNAHM92#vUlf(3Z31*h_VK?Cb;pk_>NNTM?k=^GOEEbw zsS}VyW(j~)9$?1Ft!mV2^W}B>B-IhdOIn)JP&?MFZ=eV=E-X;vk{)m|ZeO{U`Pq8i zd4lVQE7le{s9n`Ft#;I!f;<6`LVfbI5*7VTluGOZaCAlE-I@gZD?*q@WZLVsHVCf7 z9@L&>jSi*+C*LKPjPb!D9l1a|Y9UIJM*56Detcvb_11dcGk<-SE0R@E_$il$_?T%0 z-rX4dNAFkvgzMk@u(Lz{%E+6u`aehV+KJ+X;1`KVzs)K_(!z{Ve7PgiW;q3_W77_# zI;k~GsI%fvD!!ojLSZ39EypC|LCRvnrf}z4tLk~{5!41;7o~&k5w8ps+IMOL-A-PA zYaMTFmI_-O`kE4-($@CZdskOgkoRQy3zce?a^e{J2e08TgLcrX*J98&-cZQ9%wZZ2 ztwTrVqe>;Z-PrmHjJER90mO$0sE1Nt4;y525!#GVY{_v=)la%mXS9t^J8kO1EFjFZ zAy-?mDdh5K0Sf*>SZQ!`bilPD3t|<|n+2#bv879NoBEYGi$}Yg*?hUZ3p8+EU7lyb z{i2xoB`nF-%#ka-glmJKLX2hm+4uJUy9R+(K$}uR4hFtl+d403<0Eo2iqN7!tD4h4 zt8bJlNfSd(sVqi3=G_=U>&3F`@+dXQP-#3AK*&%H7l*BO zF-rT3R!-FG`WmtMfPhZaoW3)5mD5e-TcvV9=vi@Vbu|{`tTo4wKFsZ4{IVcy zqV+}1^1wFjt5nvqPZhuAh#;4)-=1D2>yHvTyO2U-neoFkSM_h@k=SHs= ze>N0>^=SDKO&EVjW{EkF2q6(+lhQFHiKNBA0US6 z8#bEL6iT6C*N-E1GkcTFFHq%a*uD&!dUlrn){JVqnFGjy9^XNkq;R z?Ay!stb()^UJ;RBxc&*YZK4kdYr`H^ildEfHh8p;IX5KH*o^j`{7XY@|KgW6Q_$BR z=)b&f?g^03=`I@r5FsdqK~Aqf!t^Ne;NR}iXg!bXZlr&@cZLqe6NnJ?P73xcO%WvG zAV$9n-rUU1ELwCQqk5#;E(0kT`;U(3ryI(i6hOqcBFICE@K$eydYx!gh7m)=2LQL^ zccq@7*D~innB%Z7SONlxh|Q`g{L&u{q+x$5z7WN+<#NN}Dte)Wy|+;zxWTCMnvB;R z>^jd|I0E}NRd7~y84px4Y;rg+3bbFM!xzpxH@|%de-S(oAc3jPe8jDtsj}jMD+Kix zI_vlOrNGJ<>dgUPR+P@Li5n_qogw4AZCXn#z=rfhEPRd-y&z((`V^n+Z`dlz1$!5> zud~|!Yb`lNJrvQtrWnL8;cL&`Wf7(pDJlyP69gDL{@~2`H5cu=xV{V^f>rH*zW~U+ z;IO|@3;DZ4VYArGqc@|`stq!E6Lv&tzbvYsXdP^uPXdj@fMH?5!px?9X^)-qJP~g! zwEKgp^NwNIHL_QhhxjJCu^M|VRYsIs+ibA<4hCGIgN9CHpHCKIss;c;Vh|w#$dGd& zCstO}eP3HnlsKUiYI2{EBedIshjuH1GpDoM5jj+27mK9>N4oWiX_~ zg#Z0d4!xg_9_PO=HQgoq_nvn8h$$KX_&|!a;fe*i?a)si!vUR6>De6>DP1B|v|@hy zgqi=hXE70Z-_+^7kiWkOqM^k{Zd!4!9em#47@$Z;2Bo8cRvP^dUn0C?y7CLx^wu_@ z0G0o@HU<}QzHx<3u$hfN*wCnq6RM8&Z|ae#5VP6}d&r1M*2uCV9pgU=$YQoyzpL~Q z0@6>VzsvZUOF5w))c>bu*To*9_pCa;Op%V~pNb$wrJef<5(lcIQ(*f@@cfV!$1@b{wKe^)w?%uz1v@|E<-6O`V9dn8V%m!-_$H> zI)|R5T<4JMZj!h>XTa8)p=i$KB;olYF<&hlDIOpFPsVcI;fCiQg7DQE#aBC!t+Q2PGQom-GblIUT3eUN)P(LW*&bFB}*W-j^Qt*afI?nz-y-Xqm1=ms<+*p{$WA1C@M zFKVNYc)+F~G*>HIy^s&m5};laT(|Z(OO*>-|sFy(4H~J1U2r;JV|NhHirD&k~?KgcRwM9ijC1HMFxdIAX0DydMI(BRbBh1 zxkupVtkrtXm6SouPK&@WcoHiNhpWggVya;=s8~1Nj8QITf#DYWCmOyr127if>liaK zepASFYB_Xk8IU-b;J4+q^&E88QdXSXf(+S&{k>^G+trHrLIR#osN`B?m##9Pk|u{Q zCc6Yy=$Ww~iQi-UD|vBzcEYKF?3`&Z&c=N5;EZLEB7<+f(Nr}CIU$y5n?S1Vc+}~Ygwn+2ZZ6&teY?C;zhY~v=8Us^<`I1 z0X`FK)jSd{64nY_kl`~O0Wk;9;r7- z)i8B2-!aIC6_#!NyJ4rXs}!7O^_l_6zJhtWhZuoq=wR;6tO=~Sk?0-y!)rQxYTgS< z#6+F+*Ou>=8Hw8@;Fxn!oSHg*7FZZ4B{mIOP~N3UZ!oC0-~5B)XB4;(u5LZr9K^fJ z{2$R04505fwius`=^9ce@|cA@XefLuOXUqG?2kLBE}vJ^Y@%6`2&n;2E&d}P2?zCQ zMuN%W7!r1a<&~$6Yb=NdM;&n0uz(~iYB*{PrKok99NI^A)@Kjw>gZ4P;bDQN@50;sG76*^@4$fJfZK-sAgo%N0iuaVn6|7F6z7A^F~qrTEE5 z1XlC?-P3FX)_aduQjcG!sq1bZU2}nQ;&Gx8z?7U_IErqf94x7b7H)KZl4~xF-)Q1{ z?M#2^2<83^#S((t29$mYy^~ql$Vq{s6*Z+v~gb5s)^B+FWJ$+=h zI7||O4MW3P{T1rpqQ7Jqx#J!$=?cYGqq=mz|1mJA3SuE2Wy|e#z`MiCkRY)mRt9o% zVz>Y`1U{X!s8Qv>4=auxURiAK7j!v2*@E8@=MhK^4@^)mOfD>;#+(}nl$D>nOSx>o zl5;s2mVza#nA>2Jz&(?yo^DQZ<+wHzsx&Q5dU)10P4Xqg!d#pWs6<@x zS?(@cAcecA(LXN>OH*v5sHna+zbB{|EDf8Z9QUQfv@nH?E-27K7DLEaXJa=2h#=@fb92J#!xLb z&SjYu&Yyj1DOZs`C(O6sC0a4%K81-Znh=rOyZDo9TgN3(NSzXy3lZ4;{)8xehS<^S z7mElxkbIp;$pGip-4K{`5_m;~kPnrWmyvPpy!d%tZ6IINVP1dc9V#ieLi&&Onj*?{ z^L%*nQmQu`N|735c^Q;pKT=UOlf#S@+BrcnG8&*9z#iK)6RrT> z7)hiO-h_-SJx@Gug>0gi4v|5p$_B^)n>C)m6R(~o?A0ETc_G#iN@{;Kz_0qpOO99u z_5gh^o>8JLHIjuP5hk)+DrFb+-W?XW1Ib^vQ_TGp6(vqaUj13+wBGX;i)EdAj4%|1 zh`@Q#b{%1J%SDOMu%?XO^$ow|Qw}|Cqf7;fHUd%YoVRh<1(7c(qkoTZ!sz|zvUv1% z6P%w?8QH$(r~)gX4eAL{^Xdmbx6nl&d~B3Z2IV1!zq7Y<&Jxzg7&c1xTXPL5J%Oe_ z5xxT|vPbQE>fMr9Gm7CIL&GE!D7rLo`0RY`KyOf0Er)uy0cheqeE{AMtW~k5FX8>D zA{1b}nvX|g>A}x=Ewmhx_}(gO0j*LZfQ)Eub3P1JgPEA_uhvG!pTSx$3Tn}>@qv7$ zR2%zDcELa8;2G1=2g5SYR93JfunMf0(P)7ef%PLORv#kXs*Fh0(2|rx!63}b5DOxA zg;#c5T3R6P7B&NrAq9SHR2hbZnmU;(4#KDH&kddFZ&U)WGCX(cPaZVz<*qn!jO0&H z^(6jO*)}*bE#h-#K)eHJYAP1rv}xA z)?Iz%0MFQ1gfalipo#Bj4QUseA41x&*JzEJg`7Lfpwr)c+lPnhrelpvTxDI@U6@`V z_2(E$P=j7{B&vUri(3;p9r17GXFn?#g2q%^+fN;Gl?zmXy%8k9!x{})w^ycT?9Fi3 z?^s^);&P%WpA(g(EwJe|l(wkUyWa(Fhlm1XU?)Tfpq!ttd{2G6HYo=y%tJE94=fenweAXxZcu?x|^{-91rN zL(4&ohe7L>I5pAgtseGr1dz#wP}*T&ia&@L!WIBcjI>cwXgC2(yfCQR=z+Hha*b@B3WtNX6fni*U6kuWnj`>B&K`K!Kf`y;V)!%;) zW~DLyc*6vjk!X|)dqSkp$cF?yU9U{Z@TP?|`^zgp*j}UflS>4zxcSS8E*C17Gu-J$?oPV|&`gjp_aLR5xwwn6%Z-yH-tf)L@& zBF6(Cf9LdxccWH@5J`GE_1X02j*a9S*l5GVuGv+!a_uy>&Zom?Y{DO|q-J!<8O!*; zI8h^ToiY2FWn-gWP^X(evk-lBe|x^iEaPO5DYSaBJ>$MLM+PD6LrsTQ1U!Fac5)hh z8gdoNwQEfh#S3%mxpAxDXOW9!O77=Me`Mh+XLq2*xYzv12B%99fZM>l;W0%?A1VHD z!ON?c+BM~z7r_Mw>z}hej{I!ikAge64@DurKNghLPYR`1%C`6=7`tcsr8z&6PhnZ> zJW0-}6(ldaH8T+Zq%{Mr?Jh60&{(v6uQ+YIqG} zEtu4br%smow%uBRIxka5_3ij)jfS567!N3oPc+Jj5)PQKFm#zFZ6x4tG%00PV+SV@ z%FEZ^bZj{D!FtYB7$I{OAL;FBCXMzw+{KrrhB4rPr-1yNRp zX1s8`abuQ|JM_yn>DmYZVMlXUWsNrqM?fmk>+~F(0dPdt2~8|zauUfdP?j|%WjDj@ zS38ZH&Hk@!qwL*C1~Gf6A4qcrD%7|?`sxQ)zv!<~`k`wQ;pecY0bFKZi3HQoF#q?z9J{`XZCgE-Tm2-u$eLL$t67!C<<)!{W~sgL}@(tE=Lu?wSg=lXV*x^Rs8 zm(pk`Isje##pm}`IEB|}zJ^#h8zc8tW$!3zFtA+MkiwW}OOODRL=9GWSZn&4QH@2* zoiaF~(qIF}>b8tjU5q1GMAA>M-34bc$Pi*9G{RHg1ziNcGAymcl>Jj!KDg^)-LUA) zy9})Dz;0XZW`364oh|E8ePWN_QOP5~)~V6;`1ggB4GeGocW{cv%)N-4qWpFbkb^|y*;lA z9(~rEgpYE1kM0oHUH(o-BB4R}{>xJPRhSETVh+d^&;bfxVPVg2K8|{}8K67a)b+UR zBeTOjgSLaeOy$=vBHywx)0_F`~#6D(_$$ zlSCo&jIyqyj)f4dxP(AG5NF0z$Z7Uvx!mG}QaDjn}VLgX%+3^6hP1Ui!J&!XbZD*lFIB&j|ieGzt6|(+5Qz2qW@%+lHl_ zbZ&l!AvB^Ia24RoGKtM9&6Pxy+m<#)1D_OYosw^smm^tZ!6*a7m4s#OWCnn@cL0485bSd zAD2p`gmL)bg}8PZhVS~Qi=`x;Iny&@OtqVJSuSLRjgSb+&Qcwv-l!NguX%+~0%BraBs}VQSr+3Jll*(c@@g98mEhUFKIruoFzX#tF__(8(+BkW zvQ&OAY73Ugr}xHtYY1nEFXC7=mJ5>-x;eH zPj~(w+g}vq*?;YH6h$Ke+%?Wzg<$I~#|e_2FwQbmJX|!90T2%f@O*Z}-v+V`4hK2j z{WUyz2Y=4MRv1nVD(YC<8Wr8trSf z9f~$vv7Kbhrr$R>wJY1TdQnfLAgbP&A!8(jw9R!jNB?Zi7t?5lUw>;K#a4eVI(!%} z0zEBP*P-V-(A+{J`O=DriyN({R+#`hM0~`l6QR`#ZA~9V*X{zsd}bMyiBFH>Z{oh{*Kd#&FaPF z=8S7}%YMck$}V4Li@hXFWo_lP@+43Ax4TIvwP(aFcNJO;D*hn!NTQ=~P_gzxzu$<7DHz__?Xzfbc^tGEwRSRT`hEhP6`d5oBrsR6tX_&5hXSqx`RUS;xGVBeY7xXaU!I5?PBM0L?BVHShGaw`7E*xzysCd*(~Z6LJhI-hb}7YopMg2h~Lm@=zY|A!w16?L39IOl{hL548R4N--zwt zGJ?jZ`;Kp2IQuYEx3cO>q}X}f%Yyv~xtySNLtyBGKFyWTa||(`N^DLjzuerP)F#5@ zGjh?p_VppmaPRW9c%LO}`)O4ksPzr4*j?V{Hfamg0^>#BRmt1Era=x1vuQLhGVTFY zZC6)!wtK5iy81}#Z^JLXLF*Go{^+nTB&V&8)@u{%1M02fUl>?e1m+l?RG-W=h>iws z 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 literal 0 HcmV?d00001 diff --git a/docs/operator/README.md b/docs/operator/README.md new file mode 100644 index 0000000000..d60e918e75 --- /dev/null +++ b/docs/operator/README.md @@ -0,0 +1,35 @@ + + +# Uniffle Operator + +The __[Uniffle Operator](https://github.com/apache/incubator-uniffle/tree/master/deploy/kubernetes/operator/)__ manages +Apache Uniffle Cluster within Kubernetes. + +The operator is currently in beta (`v1alpha1`), and while we do not anticipate changing the API in +backwards-incompatible ways there is no such guarantee yet. + +## Documentation + +Please visit the following pages for documentation on using and developing the Uniffle Operator: + +- [Installation](install.md): step-by-step instructions on how to get uniffle operator running on our cluster +- [Design & Usage](design.md): overview design of operator and detail usage of CRD + +### Examples + +Example uses of each CRD have been [provided](examples.md). diff --git a/docs/operator/design.md b/docs/operator/design.md new file mode 100644 index 0000000000..aeec45c3ac --- /dev/null +++ b/docs/operator/design.md @@ -0,0 +1,137 @@ + + +# Uniffle Operator Design + +## Summary + +The purpose is to develop an operator to facilitate the rapid deployment of Uniffle in kubernetes environments. + +## Motivation + +Using the advantages of kubernetes in container orchestration, elastic scaling, and rolling upgrades, uniffle can more +easily manage coordinator and shuffle server clusters. + +In addition, based on the operating characteristics of shuffle servers, we hope to achieve safe offline: + +1. Before a shuffle server is scaled down or upgraded, it should be added to the Coordinator's blacklist in advance. +2. After ensuring that the number of remaining applications is 0, allow its corresponding pod to be deleted and removed + from the blacklist. + +We don't just want to simply pull up the coordinators and shuffle servers, but also ensure that running jobs are not +affected. Therefore, we decided to develop an operator specifically. + +## Goals + +Operator will implement the following functions: + +1. Normally pull up two coordinator deployments (to ensure active-active) and a shuffle server statefulSet. +2. Supports replica expansion and upgrade of coordinators and shuffle servers, among which shuffle server also supports + grayscale upgrade. +3. Using the webhook mechanism, before a shuffle server is deleted, add its name to the coordinator's blacklist, and + check the number of applications remaining running, and then release the pod deletion request after ensuring safety. + +## Design Details + +This operator consists of two components: a crd controller and a webhook that admits crd and pod requests. + +The crd controller observes the status changes of the crd and controls the workload changes. + +The webhook verifies the changes of the crd, and admits the pod deletion request according to whether the number of +remaining applications is 0. + +The webhook will add the pod to be deleted to the coordinator's blacklist. When the pod is actually deleted, the +controller will remove it from the blacklist. + +## CRD Definition + +An example of a crd object is as follows: + +```yaml +apiVersion: uniffle.apache.org/v1alpha1 +kind: RemoteShuffleService +metadata: + name: rss-demo + namespace: kube-system +spec: + # ConfigMapName indicates configMap name stores configurations of coordinators and shuffle servers. + configMapName: rss-demo + # Coordinator represents the relevant configuration of the coordinators. + coordinator: + # Image represents the mirror image used by coordinators. + image: ${coordinator-image} + # InitContainerImage is optional, mainly for non-root users to initialize host path permissions. + initContainerImage: "busybox:latest" + # Count is the number of coordinator workloads to be generated. + # By default, we will deploy two coordinators to ensure active-active. + count: 2 + # RpcNodePort represents the port required by the rpc protocol of the coordinators, + # and the range is the same as the port range of the NodePort type service in kubernetes. + # By default, we will deploy two coordinators to ensure active-active. + rpcNodePort: + - 30001 + - 30011 + # httpNodePort represents the port required by the http protocol of the coordinators, + # and the range is the same as the port range of the NodePort type service in kubernetes. + # By default, we will deploy two coordinators to ensure active-active. + httpNodePort: + - 30002 + - 30012 + # XmxSize indicates the xmx size configured for coordinators. + xmxSize: "10G" + # ConfigDir records the directory where the configuration of coordinators reside. + configDir: "/data/rssadmin/rss/conf" + # Replicas field is the replicas of each coordinator's deployment. + replicas: 1 + # ExcludeNodesFilePath indicates exclude nodes file path in coordinators' containers. + excludeNodesFilePath: "/data/rssadmin/rss/coo/exclude_nodes" + # SecurityContext holds pod-level security attributes and common container settings. + securityContext: + # RunAsUser specifies the user ID of all processes in coordinator pods. + runAsUser: 1000 + # FsGroup specifies the group ID of the owner of the volume within coordinator pods. + fsGroup: 1000 + # LogHostPath represents the host path used to save logs of coordinators. + logHostPath: "/data/logs/rss" + # HostPathMounts field indicates host path volumes and their mounting path within coordinators' containers. + hostPathMounts: + /data/logs/rss: /data/rssadmin/rss/logs + # shuffleServer represents the relevant configuration of the shuffleServers + shuffleServer: + # Sync marks whether the shuffle server needs to be updated or restarted. + # When the user needs to update the shuffle servers, it needs to be set to true. + # After the update is successful, the controller will modify it to false. + sync: true + # Replicas field is the replicas of each coordinator's deployment. + replicas: 3 + # Image represents the mirror image used by shuffle servers. + image: ${shuffle-server-image} +``` + +After a user creates a rss object, the rss-controller component will create the corresponding workloads. + +For coordinators, the user directly modifies the rss object, and the controller synchronizes the corresponding state to +the workloads. + +For shuffle servers, only by changing the spec.shuffleServer.sync field to true, the controller will apply the +corresponding updates to the workloads. + +If you want more examples, please read more in [examples](examples.md). + +## State Transition + +![state transition](../asset/rss-crd-state-transition.png) diff --git a/docs/operator/examples.md b/docs/operator/examples.md new file mode 100644 index 0000000000..f9cf02cc7d --- /dev/null +++ b/docs/operator/examples.md @@ -0,0 +1,31 @@ + + +# Examples + +We need to create configMap first which saves coordinators, shuffleServers and log4j's configuration(we can refer +to [configuration](../../deploy/kubernetes/operator/examples/configuration.yaml)). + +Coordinator is a stateless service, when upgrading, we can directly update the configuration and then update the image. + +Shuffle server is a stateful service, and the upgrade operation is more complicated, so we show examples of different +upgrade modes. + +- [Full Upgrade](../../deploy/kubernetes/operator/examples/full-upgrade) +- [Full Restart](../../deploy/kubernetes/operator/examples/full-restart) +- [Partition Upgrade](../../deploy/kubernetes/operator/examples/partition-upgrade) +- [Specific Upgrade](../../deploy/kubernetes/operator/examples/specific-upgrade) diff --git a/docs/operator/install.md b/docs/operator/install.md new file mode 100644 index 0000000000..bfab345205 --- /dev/null +++ b/docs/operator/install.md @@ -0,0 +1,75 @@ + + +# Installation + +This section shows us how to install operator in our cluster. + +## Requirements + +1. Kubernetes 1.14+ +2. Kubectl 1.14+ + +Please make sure the kubectl is properly configured to interact with the Kubernetes environment. + +## Preparing Images of Coordinators and Shuffle Servers + +Run the following command: + +``` +cd /deploy/kubernetes/docker && sh build.sh --registry ${our-registry} +``` + +## Creating or Updating CRD + +We can refer +to [crd yaml file](../../deploy/kubernetes/operator/config/crd/bases/uniffle.apache.org_remoteshuffleservices.yaml). + +Run the following command: + +``` +kubectl apply -f ${crd-yaml-file} +``` + +## Setup or Update Uniffle Webhook + +We can refer to [webhook yaml file](../../deploy/kubernetes/operator/config/manager/rss-webhook.yaml). + +Run the following command: + +``` +kubectl apply -f ${webhook-yaml-file} +``` + +## Setup or Update Uniffle Controller + +We can refer to [controller yaml file](../../deploy/kubernetes/operator/config/manager/rss-controller.yaml). + +Run the following command: + +``` +kubectl apply -f ${controller-yaml-file} +``` + +## How To Use + +We can learn more details about usage of CRD +from [uniffle operator design](design.md). + +## Examples + +Example uses of CRD have been [provided](examples.md).