├── .gitignore ├── LICENSE.txt ├── README.md ├── aks ├── service-solr-cluster.yml ├── service-zookeeper-ensemble.yml ├── storageclass-azurefile.yml ├── storageclass-solrcluster.yml └── storageclass-zkensemble.yml ├── aws ├── storageclass-solrcluster.yml └── storageclass-zkensemble.yml ├── configmap ├── solr-cluster-config.properties ├── solr-config-multi.properties ├── solr-config.properties ├── solr.xml ├── zookeeper-config.properties └── zookeeper-ensemble-config.properties ├── debug └── busybox.yml ├── docker-for-desktop ├── service-solr.yml ├── service-zookeeper.yml ├── storageclass-solrcluster.yml └── storageclass-zkensemble.yml ├── docker-image ├── Dockerfile ├── Readme.md └── docker-entrypoint.sh ├── google-cloud └── README.md ├── ingress ├── certificates.yaml ├── cluster-issuer.yaml └── ingress.yml ├── minikube ├── service-solr.yml ├── service-zookeeper.yml ├── storageclass-solrcluster.yml └── storageclass-zkensemble.yml ├── service-account └── rbac-config.yml ├── services ├── service-solr-cluster.yml ├── service-solr.yml ├── service-zookeeper-ensemble.yml └── service-zookeeper.yml ├── start-aks-multi.sh ├── start-aks-solr-cluster.sh ├── start-aks-zookeeper-ensemble.sh ├── start-aws-solr-cluster.sh ├── start-aws-zookeeper-ensemble.sh ├── start-minikube.sh ├── start.sh ├── statefulsets ├── pod-disruption-budget.yml ├── statefulset-solr-cluster.yml ├── statefulset-solr.yml ├── statefulset-zookeeper-ensemble.yml └── statefulset-zookeeper.yml ├── stop-and-delete-aks-solr-cluster.sh ├── stop-and-delete-aks-zookeeper-ensemble.sh └── stop-and-delete.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | 204 | 205 | 206 | Some code in core/src/java/org/apache/lucene/util/UnicodeUtil.java was 207 | derived from unicode conversion examples available at 208 | http://www.unicode.org/Public/PROGRAMS/CVTUTF. Here is the copyright 209 | from those sources: 210 | 211 | /* 212 | * Copyright 2001-2004 Unicode, Inc. 213 | * 214 | * Disclaimer 215 | * 216 | * This source code is provided as is by Unicode, Inc. No claims are 217 | * made as to fitness for any particular purpose. No warranties of any 218 | * kind are expressed or implied. The recipient agrees to determine 219 | * applicability of information provided. If this file has been 220 | * purchased on magnetic or optical media from Unicode, Inc., the 221 | * sole remedy for any claim will be exchange of defective media 222 | * within 90 days of receipt. 223 | * 224 | * Limitations on Rights to Redistribute This Code 225 | * 226 | * Unicode, Inc. hereby grants the right to freely use the information 227 | * supplied in this file in the creation of products supporting the 228 | * Unicode Standard, and to make copies of this file in any form 229 | * for internal or external distribution as long as this notice 230 | * remains attached. 231 | */ 232 | 233 | 234 | Some code in core/src/java/org/apache/lucene/util/ArrayUtil.java was 235 | derived from Python 2.4.2 sources available at 236 | http://www.python.org. Full license is here: 237 | 238 | http://www.python.org/download/releases/2.4.2/license/ 239 | 240 | Some code in core/src/java/org/apache/lucene/util/UnicodeUtil.java was 241 | derived from Python 3.1.2 sources available at 242 | http://www.python.org. Full license is here: 243 | 244 | http://www.python.org/download/releases/3.1.2/license/ 245 | 246 | Some code in core/src/java/org/apache/lucene/util/automaton was 247 | derived from Brics automaton sources available at 248 | www.brics.dk/automaton/. Here is the copyright from those sources: 249 | 250 | /* 251 | * Copyright (c) 2001-2009 Anders Moeller 252 | * All rights reserved. 253 | * 254 | * Redistribution and use in source and binary forms, with or without 255 | * modification, are permitted provided that the following conditions 256 | * are met: 257 | * 1. Redistributions of source code must retain the above copyright 258 | * notice, this list of conditions and the following disclaimer. 259 | * 2. Redistributions in binary form must reproduce the above copyright 260 | * notice, this list of conditions and the following disclaimer in the 261 | * documentation and/or other materials provided with the distribution. 262 | * 3. The name of the author may not be used to endorse or promote products 263 | * derived from this software without specific prior written permission. 264 | * 265 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 266 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 267 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 268 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 269 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 270 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 271 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 272 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 273 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 274 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275 | */ 276 | 277 | The levenshtein automata tables in core/src/java/org/apache/lucene/util/automaton 278 | were automatically generated with the moman/finenight FSA package. 279 | Here is the copyright for those sources: 280 | 281 | # Copyright (c) 2010, Jean-Philippe Barrette-LaPierre, 282 | # 283 | # Permission is hereby granted, free of charge, to any person 284 | # obtaining a copy of this software and associated documentation 285 | # files (the "Software"), to deal in the Software without 286 | # restriction, including without limitation the rights to use, 287 | # copy, modify, merge, publish, distribute, sublicense, and/or sell 288 | # copies of the Software, and to permit persons to whom the 289 | # Software is furnished to do so, subject to the following 290 | # conditions: 291 | # 292 | # The above copyright notice and this permission notice shall be 293 | # included in all copies or substantial portions of the Software. 294 | # 295 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 296 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 297 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 298 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 299 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 300 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 301 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 302 | # OTHER DEALINGS IN THE SOFTWARE. 303 | 304 | Some code in core/src/java/org/apache/lucene/util/UnicodeUtil.java was 305 | derived from ICU (http://www.icu-project.org) 306 | The full license is available here: 307 | https://github.com/unicode-org/icu/blob/main/icu4c/LICENSE 308 | 309 | /* 310 | * Copyright (C) 1999-2010, International Business Machines 311 | * Corporation and others. All Rights Reserved. 312 | * 313 | * Permission is hereby granted, free of charge, to any person obtaining a copy 314 | * of this software and associated documentation files (the "Software"), to deal 315 | * in the Software without restriction, including without limitation the rights 316 | * to use, copy, modify, merge, publish, distribute, and/or sell copies of the 317 | * Software, and to permit persons to whom the Software is furnished to do so, 318 | * provided that the above copyright notice(s) and this permission notice appear 319 | * in all copies of the Software and that both the above copyright notice(s) and 320 | * this permission notice appear in supporting documentation. 321 | * 322 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 323 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 324 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 325 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE 326 | * LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR 327 | * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 328 | * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 329 | * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 330 | * 331 | * Except as contained in this notice, the name of a copyright holder shall not 332 | * be used in advertising or otherwise to promote the sale, use or other 333 | * dealings in this Software without prior written authorization of the 334 | * copyright holder. 335 | */ 336 | 337 | The following license applies to the Snowball stemmers: 338 | 339 | Copyright (c) 2001, Dr Martin Porter 340 | Copyright (c) 2002, Richard Boulton 341 | All rights reserved. 342 | 343 | Redistribution and use in source and binary forms, with or without 344 | modification, are permitted provided that the following conditions are met: 345 | 346 | * Redistributions of source code must retain the above copyright notice, 347 | * this list of conditions and the following disclaimer. 348 | * Redistributions in binary form must reproduce the above copyright 349 | * notice, this list of conditions and the following disclaimer in the 350 | * documentation and/or other materials provided with the distribution. 351 | * Neither the name of the copyright holders nor the names of its contributors 352 | * may be used to endorse or promote products derived from this software 353 | * without specific prior written permission. 354 | 355 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 356 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 357 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 358 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 359 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 360 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 361 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 362 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 363 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 364 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 365 | 366 | The following license applies to the KStemmer: 367 | 368 | Copyright © 2003, 369 | Center for Intelligent Information Retrieval, 370 | University of Massachusetts, Amherst. 371 | All rights reserved. 372 | 373 | Redistribution and use in source and binary forms, with or without modification, 374 | are permitted provided that the following conditions are met: 375 | 376 | 1. Redistributions of source code must retain the above copyright notice, this 377 | list of conditions and the following disclaimer. 378 | 379 | 2. Redistributions in binary form must reproduce the above copyright notice, 380 | this list of conditions and the following disclaimer in the documentation 381 | and/or other materials provided with the distribution. 382 | 383 | 3. The names "Center for Intelligent Information Retrieval" and 384 | "University of Massachusetts" must not be used to endorse or promote products 385 | derived from this software without prior written permission. To obtain 386 | permission, contact info@ciir.cs.umass.edu. 387 | 388 | THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF MASSACHUSETTS AND OTHER CONTRIBUTORS 389 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 390 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 391 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE 392 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 393 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 394 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 395 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 396 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 397 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 398 | SUCH DAMAGE. 399 | 400 | The following license applies to the Morfologik project: 401 | 402 | Copyright (c) 2006 Dawid Weiss 403 | Copyright (c) 2007-2011 Dawid Weiss, Marcin Miłkowski 404 | All rights reserved. 405 | 406 | Redistribution and use in source and binary forms, with or without modification, 407 | are permitted provided that the following conditions are met: 408 | 409 | * Redistributions of source code must retain the above copyright notice, 410 | this list of conditions and the following disclaimer. 411 | 412 | * Redistributions in binary form must reproduce the above copyright notice, 413 | this list of conditions and the following disclaimer in the documentation 414 | and/or other materials provided with the distribution. 415 | 416 | * Neither the name of Morfologik nor the names of its contributors 417 | may be used to endorse or promote products derived from this software 418 | without specific prior written permission. 419 | 420 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 421 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 422 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 423 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 424 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 425 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 426 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 427 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 428 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 429 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 430 | 431 | --- 432 | 433 | The dictionary comes from Morfologik project. Morfologik uses data from 434 | Polish ispell/myspell dictionary hosted at http://www.sjp.pl/slownik/en/ and 435 | is licenced on the terms of (inter alia) LGPL and Creative Commons 436 | ShareAlike. The part-of-speech tags were added in Morfologik project and 437 | are not found in the data from sjp.pl. The tagset is similar to IPI PAN 438 | tagset. 439 | 440 | --- 441 | 442 | The following license applies to the Morfeusz project, 443 | used by org.apache.lucene.analysis.morfologik. 444 | 445 | BSD-licensed dictionary of Polish (SGJP) 446 | http://sgjp.pl/morfeusz/ 447 | 448 | Copyright © 2011 Zygmunt Saloni, Włodzimierz Gruszczyński, 449 | Marcin Woliński, Robert Wołosz 450 | 451 | All rights reserved. 452 | 453 | Redistribution and use in source and binary forms, with or without 454 | modification, are permitted provided that the following conditions are 455 | met: 456 | 457 | 1. Redistributions of source code must retain the above copyright 458 | notice, this list of conditions and the following disclaimer. 459 | 460 | 2. Redistributions in binary form must reproduce the above copyright 461 | notice, this list of conditions and the following disclaimer in the 462 | documentation and/or other materials provided with the 463 | distribution. 464 | 465 | THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS “AS IS” AND ANY EXPRESS 466 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 467 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 468 | DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS BE 469 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 470 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 471 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 472 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 473 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 474 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 475 | IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 476 | 477 | --- 478 | 479 | core/src/java/org/apache/lucene/util/compress/LZ4.java is a Java 480 | implementation of the LZ4 (https://github.com/lz4/lz4/tree/dev/lib) 481 | compression format for Lucene's DataInput/DataOutput abstractions. 482 | 483 | LZ4 Library 484 | Copyright (c) 2011-2016, Yann Collet 485 | All rights reserved. 486 | 487 | Redistribution and use in source and binary forms, with or without modification, 488 | are permitted provided that the following conditions are met: 489 | 490 | * Redistributions of source code must retain the above copyright notice, this 491 | list of conditions and the following disclaimer. 492 | 493 | * Redistributions in binary form must reproduce the above copyright notice, this 494 | list of conditions and the following disclaimer in the documentation and/or 495 | other materials provided with the distribution. 496 | 497 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 498 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 499 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 500 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 501 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 502 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 503 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 504 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 505 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 506 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 507 | 508 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SolrCloud Zookeeper Kubernetes 2 | ============================== 3 | 4 | # Introduction 5 | 6 | This project aims to help developers and newbies that would try latest version of SolrCloud (and Zookeeper) in a Kubernetes environment. 7 | 8 | Here you'll find basically two different configuration: 9 | 10 | * one (or more) Solr instance and one Zookeeper configured as Standalone node 11 | * one (or more) Solr instance and a Zookeeper Ensemble (which means a cluster) 12 | 13 | The Zookeeper configuration (and interaction with Solr) is the hardest part of the project. 14 | It is important to point out that Zookeeper has two different configuration: Standalone and Ensemble. 15 | 16 | * Standalone has only one node 17 | * Ensemble is a cluster and has always an odd number of nodes starting from 3 (i.e. 3, 5, 7, etc.). 18 | 19 | Here we need two different configuration (StatefulSet) for Zookeeper, depending if you want have Standalone or Ensemble. Of course if you need to deploy an high availablity configuration, there are no ways, you can't have a single point of failure so you need to start an Ensemble. 20 | 21 | Solr on the other hand can run one or more instances transparentely from the zookeeper configuration, it just need to have one or more Zookeeper correctly configured and running a version compatible with the Sor version you choose. 22 | 23 | # Kubernetes Deployment Envs 24 | 25 | Here are described following Kubernetes Deployment Envs: 26 | 27 | * Kubernetes with Docker for Desktop (local) 28 | * Azure Kubernetes Services (AKS) 29 | * Amazon Elastic Kubernetes Service (EKS) 30 | * Google Container Engine (GKE) (this part of the project should be updated) 31 | * Minikube (local) 32 | 33 | At end of installation Solr (port 8983) and Zookeeper (port 2181) are reachable via kubernetes services that acts as TCP [LoadBalancer](https://kubernetes.io/docs/concepts/services-networking/#loadbalancer). 34 | 35 | Note: Use CloudSolrClient in your Java client application only inside the Kubernetes Cluster, from outside better if you use HttpSolrClient via the loadbalancer. 36 | 37 | ## Prerequisite for Kubernetes with Docker for Desktop 38 | 39 | * [install Docker for Desktop lastest](https://www.docker.com/community-edition) version aka Community edition. 40 | 41 | ## Prerequisite for Google Cloud installation 42 | 43 | * Install Google Cloud SDK - https://cloud.google.com/sdk/downloads 44 | * Follow the Kubernetes Engine Quickstart - https://cloud.google.com/kubernetes-engine/docs/quickstart 45 | 46 | ## Prerequisite for Azure AKS installation 47 | 48 | * Install [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) 49 | * Then run: `az aks install-cli` 50 | 51 | ## Prerequisite for Minikube installation 52 | 53 | * [install Docker lastest](https://docs.docker.com/engine/installation/) version or Docker for Desktop 54 | * [install Minikube latest](https://github.com/kubernetes/minikube#minikube) version 55 | * install a [VM driver](https://github.com/kubernetes/minikube#quickstart) compatible with your environment (MacOS, Linux, Windows). 56 | 57 | ## Quick start 58 | 59 | If you want try a light configuration with 1 SolrCloud container and 1 Zookeeper container, start with: 60 | 61 | git clone https://github.com/freedev/solrcloud-zookeeper-kubernetes.git 62 | cd solrcloud-zookeeper-kubernetes 63 | 64 | ## Kubernetes with Docker for Desktop quick start 65 | 66 | ./start.sh 67 | 68 | Then run the command `kubectl get pods` and `kubectl get service` to ensure that pods and services were created 69 | correctly: 70 | 71 | $ kubectl get pods 72 | NAME READY STATUS RESTARTS AGE 73 | solr-0 1/1 Running 0 2m26s 74 | zk-0 1/1 Running 1 2m31s 75 | 76 | $ kubectl get service 77 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 78 | kubernetes ClusterIP 10.96.0.1 443/TCP 4d 79 | solr-service LoadBalancer 10.100.213.138 localhost 8983:30955/TCP 1s 80 | solrcluster ClusterIP None 1s 81 | zk-service LoadBalancer 10.109.138.223 localhost 2181:30063/TCP 1s 82 | zkensemble ClusterIP None 1s 83 | 84 | So you'll find the SorlCloud cluster at: http://localhost:8983/solr/#/ 85 | 86 | ## Azure AKS quickstart 87 | 88 | * You need a Kubernetes Cluster - [Azure Kubernetes Service (AKS) quickstart](https://docs.microsoft.com/en-us/azure/aks/) 89 | 90 | If you already have an existing eks cluster and only need to get the credentials: 91 | 92 | az aks get-credentials --resource-group myResourceGroup --name MyManagedCluster 93 | 94 | Now you can start your cluster: 95 | 96 | start.sh 97 | 98 | To find the services load balancer just run: 99 | 100 | $ kubectl get services 101 | 102 | ## Amazon Elastic Kubernetes Service (Amazon 103 | EKS) quickstart 104 | 105 | * You need a Kubernetes Cluster - [Creating an Amazon EKS Cluster](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html) 106 | 107 | ``` 108 | $ eksctl create cluster --name solr-dev --nodegroup-name standard-workers --node-type t3a.medium --nodes 4 --node-ami auto --nodes-min 1 --nodes-max 4 109 | ``` 110 | 111 | Now you can start your cluster: 112 | 113 | start.sh 114 | 115 | To find the services load balancer just run: 116 | 117 | $ kubectl get services 118 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 119 | kubernetes ClusterIP 10.100.0.1 443/TCP 13m 120 | solr-service LoadBalancer 10.100.115.145 a50c0fe32b57211e9a3fc0ae1e2f29a2-134001589.eu-west-1.elb.amazonaws.com 8983:30107/TCP 107s 121 | solrcluster ClusterIP None 107s 122 | zk-service LoadBalancer 10.100.134.160 a502a5087b57211e9a3fc0ae1e2f29a2-301817188.eu-west-1.elb.amazonaws.com 2181:32609/TCP 108s 123 | zkensemble ClusterIP None 108s 124 | 125 | ## Google Cloud quick start 126 | 127 | First set default compute/region and compute/zone where create your Kubernetes cluster, for example: 128 | 129 | gcloud config set compute/region europe-west4 130 | 131 | gcloud config set compute/zone europe-west4-b 132 | 133 | I've choosen `europe-west4` because is near to me, in your case may be better if you a region/zone near you. 134 | 135 | Then create the Kubernetes cluster `cluster-solr`, note that in this tutorial I've choosen a machine-type `n1-standard-4` with 4 cores and 15 GB RAM. 136 | 137 | gcloud container clusters create cluster-solr --num-nodes 1 --machine-type n1-standard-4 --disk-size=50 --scopes storage-rw,compute-rw 138 | 139 | Now you can start your cluster: 140 | 141 | start.sh 142 | 143 | When your cluster is successfully started, you need to understand how to reach the Solr instance. 144 | You can use `kubectl` and `jq`: 145 | 146 | $ kubectl get svc solr-service -o json | jq ".spec.ports[0] | .nodePort" 147 | 8983 148 | $ kubectl get nodes -o json | jq '.items[0] | .status.addresses[] | select(.type | contains("ExternalIP")) | .address' 149 | 123.123.123.123 150 | 151 | If your node is still not reachable, probably it's because of Google cloud default network firewall rules. 152 | 153 | gcloud compute firewall-rules create allow-8983-from-everywhere --allow=TCP:8983 --direction=INGRESS 154 | gcloud compute firewall-rules create allow-2181-from-everywhere --allow=TCP:2181 --direction=INGRESS 155 | gcloud compute instances add-tags $(kubectl get node -o json | jq -r '.items[0] | .metadata.name ') --tags=allow-8983-from-everywhere,allow-2181-from-everywhere 156 | 157 | ## Minikube quick start 158 | 159 | Execute this to create and configure a virtual machine that runs a single-node Kubernetes cluster. 160 | 161 | minikube start --extra-config=apiserver.ServiceNodePortRange=1-50000 162 | 163 | Note: Minikube normally does not handle [LoadBalancer Services](https://kubernetes.io/docs/concepts/services-networking/#loadbalancer). I've choose LoadBalancer services to expose externally solr and zookeeper. 164 | only for Minikube you need to use [NodePort Service Type](https://kubernetes.io/docs/concepts/services-networking/#nodeport) 165 | 166 | This command also configures your kubectl installation to communicate with this cluster. 167 | 168 | After that you can finally start (create) your SolrCloud cluster with 1 Solr instance and 1 Zookeeper instance: 169 | 170 | ./start-minikube.sh 171 | 172 | Then run the command `kubectl get pods` to ensure that the pods were created correctly: 173 | 174 | $ kubectl get pods 175 | NAME READY STATUS RESTARTS AGE 176 | solr-0 1/1 Running 0 2m26s 177 | zk-0 1/1 Running 1 2m31s 178 | 179 | Then run the command `minikube service` to see where the services are (which port and ip address): 180 | 181 | minikube service list 182 | 183 | |-------------|----------------------|----------------------------| 184 | | NAMESPACE | NAME | URL | 185 | |-------------|----------------------|----------------------------| 186 | | default | kubernetes | No node port | 187 | | default | solr-service | http://192.168.99.101:8983 | 188 | | default | solrcluster | No node port | 189 | | default | zk-service | http://192.168.99.101:2181 | 190 | | default | zkensemble | No node port | 191 | | kube-system | kube-dns | No node port | 192 | | kube-system | kubernetes-dashboard | No node port | 193 | |-------------|----------------------|----------------------------| 194 | 195 | As you can imagine, this is an example of the returned output, there is the ip address and the port for `solr-service` and `zk-service`. 196 | So you'll find the SorlCloud cluster at: http://192.168.99.101:8983 197 | 198 | Note: The ip address 192.168.99.101 allocated with minikube will change from environment to environment. 199 | 200 | ## Shutdown 201 | 202 | If you want shutdown Solr and Zookeeper just run: 203 | 204 | ./stop.sh 205 | 206 | ## Looking at the logs 207 | 208 | kubectl exec -t -i zk-0 -- tail -100f /store/logs/zookeeper.log 209 | 210 | ### Introduction to Stateful application in Kubernetes 211 | 212 | Before to deploy Solr or Zookeeper in Kubernetes, it is important understand what's the difference between Stateless and Stateful applications in Kubernetes. 213 | 214 | > Stateless applications 215 | > 216 | > A stateless application does not preserve its state and saves no data to persistent storage — all user and session data stays with the client. 217 | > 218 | > Some examples of stateless applications include web frontends like Nginx, web servers like Apache Tomcat, and other web applications. 219 | > 220 | > You can create a Kubernetes Deployment to deploy a stateless application on your cluster. Pods created by Deployments are not unique and do not preserve their state, which makes scaling and updating stateless applications easier. 221 | > 222 | > Stateful applications 223 | > 224 | >A stateful application requires that its state be saved or persistent. Stateful applications use persistent storage, such as persistent volumes, to save data for use by the server or by other users. 225 | > 226 | >Examples of stateful applications include databases like MongoDB and message queues like Apache ZooKeeper. 227 | > 228 | >You can create a Kubernetes StatefulSet to deploy a stateful application. Pods created by StatefulSets have unique identifiers and can be updated in an ordered, safe way. 229 | 230 | So a Solrcloud Cluster matches exactly the kind of Stateful application previously described. 231 | And we have to create the environment following these steps: 232 | 233 | 1. create configmap where store the cluster configuration 234 | 2. create statefulsets for Solr and Zookeeper that can write their data on persistent volumes 235 | 3. map solr and zookeeper as network services (loadbalancer or nodeport) 236 | -------------------------------------------------------------------------------- /aks/service-solr-cluster.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: solrcluster 5 | labels: 6 | app: solr-app 7 | spec: 8 | clusterIP: None 9 | selector: 10 | app: solr-app 11 | --- 12 | apiVersion: v1 13 | kind: Service 14 | metadata: 15 | name: solr-service 16 | annotations: 17 | service.beta.kubernetes.io/azure-load-balancer-internal: "true" 18 | labels: 19 | app: solr-app 20 | spec: 21 | ports: 22 | - protocol: TCP 23 | port: 8983 24 | targetPort: 8983 25 | type: LoadBalancer 26 | selector: 27 | app: solr-app 28 | -------------------------------------------------------------------------------- /aks/service-zookeeper-ensemble.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: zkensemble 5 | labels: 6 | app: zookeeper-app 7 | spec: 8 | clusterIP: None 9 | selector: 10 | app: zookeeper-app 11 | --- 12 | apiVersion: v1 13 | kind: Service 14 | metadata: 15 | name: zk-service 16 | annotations: 17 | service.beta.kubernetes.io/azure-load-balancer-internal: "true" 18 | labels: 19 | app: zookeeper-app 20 | spec: 21 | ports: 22 | - protocol: TCP 23 | port: 2181 24 | targetPort: 2181 25 | type: LoadBalancer 26 | selector: 27 | app: zookeeper-app 28 | -------------------------------------------------------------------------------- /aks/storageclass-azurefile.yml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | name: azurefile 5 | provisioner: kubernetes.io/azure-file 6 | allowVolumeExpansion: true 7 | mountOptions: 8 | - dir_mode=0777 9 | - file_mode=0777 10 | - uid=1000 11 | - gid=1000 12 | parameters: 13 | skuName: Standard_LRS 14 | -------------------------------------------------------------------------------- /aks/storageclass-solrcluster.yml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | name: store-solrcluster 5 | provisioner: kubernetes.io/azure-disk 6 | reclaimPolicy: Delete 7 | allowVolumeExpansion: true 8 | parameters: 9 | skuName: Premium_LRS 10 | kind: Managed 11 | storageaccounttype: Premium_LRS 12 | # fsType: xfs 13 | # location: eastus 14 | -------------------------------------------------------------------------------- /aks/storageclass-zkensemble.yml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | name: store-zkensemble 5 | provisioner: kubernetes.io/azure-disk 6 | reclaimPolicy: Delete 7 | allowVolumeExpansion: true 8 | parameters: 9 | skuName: Premium_LRS 10 | kind: Managed 11 | storageaccounttype: Premium_LRS 12 | # fsType: xfs 13 | # location: eastus 14 | # storageAccount: azure_storage_account_name 15 | -------------------------------------------------------------------------------- /aws/storageclass-solrcluster.yml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | name: store-solrcluster 5 | provisioner: kubernetes.io/aws-ebs 6 | reclaimPolicy: Delete 7 | allowVolumeExpansion: true 8 | parameters: 9 | fsType: ext4 10 | type: gp2 11 | volumeBindingMode: WaitForFirstConsumer 12 | -------------------------------------------------------------------------------- /aws/storageclass-zkensemble.yml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | name: store-zkensemble 5 | provisioner: kubernetes.io/aws-ebs 6 | reclaimPolicy: Delete 7 | allowVolumeExpansion: true 8 | parameters: 9 | fsType: ext4 10 | type: gp2 11 | volumeBindingMode: WaitForFirstConsumer 12 | -------------------------------------------------------------------------------- /configmap/solr-cluster-config.properties: -------------------------------------------------------------------------------- 1 | solrHome=/store/data 2 | solrPort=8983 3 | zkHost=zk-0.zkensemble:2181,zk-1.zkensemble:2181,zk-2.zkensemble:2181 4 | solrLogsDir=/store/logs 5 | solrHeap=1g 6 | -------------------------------------------------------------------------------- /configmap/solr-config-multi.properties: -------------------------------------------------------------------------------- 1 | solrHome=/store/data 2 | solrPort=32080 3 | zkHost=zk-0.zk-hs.default.svc.cluster.local,zk-1.zk-hs.default.svc.cluster.local,zk-2.zk-hs.default.svc.cluster.local 4 | solrLogsDir=/store/logs 5 | -------------------------------------------------------------------------------- /configmap/solr-config.properties: -------------------------------------------------------------------------------- 1 | solrHome=/store/data 2 | solrPort=8983 3 | zkHost=zk-0.zkensemble:2181 4 | solrHost=solr-service 5 | solrLogsDir=/store/logs 6 | solrHeap=512m -------------------------------------------------------------------------------- /configmap/solr.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 28 | 29 | 30 | 31 | 32 | 33 | ${host:} 34 | ${jetty.port:8983} 35 | ${hostContext:solr} 36 | 37 | ${genericCoreNodeNames:true} 38 | 39 | ${zkClientTimeout:30000} 40 | ${distribUpdateSoTimeout:600000} 41 | ${distribUpdateConnTimeout:60000} 42 | ${zkCredentialsProvider:org.apache.solr.common.cloud.DefaultZkCredentialsProvider} 43 | ${zkACLProvider:org.apache.solr.common.cloud.DefaultZkACLProvider} 44 | 45 | 46 | 47 | 49 | ${socketTimeout:600000} 50 | ${connTimeout:60000} 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /configmap/zookeeper-config.properties: -------------------------------------------------------------------------------- 1 | zooMyId=1 2 | zooLogDir=/store/logs 3 | zooDataLogDir=/store/datalog 4 | zooPort=2181 5 | zooDataDir=/store/data 6 | zooStandaloneEnabled=true 7 | zooAdminServerEnabled=true 8 | zooLog4jProp=INFO,ROLLINGFILE 9 | -------------------------------------------------------------------------------- /configmap/zookeeper-ensemble-config.properties: -------------------------------------------------------------------------------- 1 | zooLogDir=/store/logs 2 | zooDataLogDir=/store/datalog 3 | zooDataDir=/store/data 4 | zooStandaloneEnabled=false 5 | zooAdminServerEnabled=true 6 | zooServers=server.1=zk-0.zkensemble:2888:3888 server.2=zk-1.zkensemble:2888:3888 server.3=zk-2.zkensemble:2888:3888 7 | zooLog4jProp=INFO,ROLLINGFILE 8 | -------------------------------------------------------------------------------- /debug/busybox.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: busybox 5 | namespace: default 6 | spec: 7 | containers: 8 | - name: busybox 9 | image: busybox:1.28 10 | command: 11 | - sleep 12 | - "3600" 13 | imagePullPolicy: IfNotPresent 14 | restartPolicy: Always 15 | hostNetwork: true 16 | dnsPolicy: ClusterFirstWithHostNet 17 | -------------------------------------------------------------------------------- /docker-for-desktop/service-solr.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: solrcluster 5 | labels: 6 | app: solr-app 7 | spec: 8 | clusterIP: None 9 | selector: 10 | app: solr-app 11 | --- 12 | apiVersion: v1 13 | kind: Service 14 | metadata: 15 | name: solr-service 16 | annotations: 17 | service.beta.kubernetes.io/azure-load-balancer-internal: "true" 18 | labels: 19 | app: solr-app 20 | spec: 21 | ports: 22 | - protocol: TCP 23 | port: 8983 24 | targetPort: 8983 25 | type: LoadBalancer 26 | selector: 27 | app: solr-app 28 | -------------------------------------------------------------------------------- /docker-for-desktop/service-zookeeper.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: zkensemble 5 | labels: 6 | app: zookeeper-app 7 | spec: 8 | clusterIP: None 9 | selector: 10 | app: zookeeper-app 11 | --- 12 | apiVersion: v1 13 | kind: Service 14 | metadata: 15 | name: zk-service 16 | annotations: 17 | service.beta.kubernetes.io/azure-load-balancer-internal: "true" 18 | labels: 19 | app: zookeeper-app 20 | spec: 21 | ports: 22 | - protocol: TCP 23 | port: 2181 24 | targetPort: 2181 25 | type: LoadBalancer 26 | selector: 27 | app: zookeeper-app 28 | -------------------------------------------------------------------------------- /docker-for-desktop/storageclass-solrcluster.yml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1beta1 3 | metadata: 4 | name: store-solrcluster 5 | provisioner: docker.io/hostpath -------------------------------------------------------------------------------- /docker-for-desktop/storageclass-zkensemble.yml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1beta1 3 | metadata: 4 | name: store-zkensemble 5 | provisioner: docker.io/hostpath -------------------------------------------------------------------------------- /docker-image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM zookeeper:3.4.14 2 | 3 | RUN set -eux; \ 4 | apt-get update; \ 5 | DEBIAN_FRONTEND=noninteractive \ 6 | apt-get install -y --no-install-recommends \ 7 | iputils-ping \ 8 | dnsutils \ 9 | net-tools \ 10 | telnet ;\ 11 | rm -rf /var/lib/apt/lists/*; 12 | 13 | COPY docker-entrypoint.sh / 14 | 15 | # ENTRYPOINT [ "/custom-entrypoint.sh" ] 16 | -------------------------------------------------------------------------------- /docker-image/Readme.md: -------------------------------------------------------------------------------- 1 | OpenShift example template 2 | ========================== 3 | 4 | https://github.com/engapa/zookeeper-k8s-openshift/tree/master/openshift -------------------------------------------------------------------------------- /docker-image/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [ "$ZOO_SERVERS" != "" ] 6 | then 7 | echo $ZOO_SERVERS | sed "s/$(hostname).zkensemble/0.0.0.0/g" > /conf/zooservers.txt 8 | cat /conf/zooservers.txt 9 | export ZOO_SERVERS="$( cat /conf/zooservers.txt )" 10 | fi 11 | 12 | # Allow the container to be started with `--user` 13 | if [[ "$1" = 'zkServer.sh' && "$(id -u)" = '0' ]]; then 14 | chown -R "$ZOO_USER" "$ZOO_DATA_DIR" "$ZOO_DATA_LOG_DIR" "$ZOO_LOG_DIR" "$ZOO_CONF_DIR" 15 | exec gosu "$ZOO_USER" "$0" "$@" 16 | fi 17 | 18 | # Generate the config only if it doesn't exist 19 | if [[ ! -f "$ZOO_CONF_DIR/zoo.cfg" ]]; then 20 | CONFIG="$ZOO_CONF_DIR/zoo.cfg" 21 | 22 | echo "clientPort=$ZOO_PORT" >> "$CONFIG" 23 | echo "dataDir=$ZOO_DATA_DIR" >> "$CONFIG" 24 | echo "dataLogDir=$ZOO_DATA_LOG_DIR" >> "$CONFIG" 25 | 26 | echo "tickTime=$ZOO_TICK_TIME" >> "$CONFIG" 27 | echo "initLimit=$ZOO_INIT_LIMIT" >> "$CONFIG" 28 | echo "syncLimit=$ZOO_SYNC_LIMIT" >> "$CONFIG" 29 | 30 | echo "autopurge.snapRetainCount=$ZOO_AUTOPURGE_SNAPRETAINCOUNT" >> "$CONFIG" 31 | echo "autopurge.purgeInterval=$ZOO_AUTOPURGE_PURGEINTERVAL" >> "$CONFIG" 32 | echo "maxClientCnxns=$ZOO_MAX_CLIENT_CNXNS" >> "$CONFIG" 33 | 34 | for server in $ZOO_SERVERS; do 35 | echo "$server" >> "$CONFIG" 36 | done 37 | fi 38 | 39 | # Write myid only if it doesn't exist 40 | if [[ ! -f "$ZOO_DATA_DIR/myid" ]]; then 41 | echo "${ZOO_MY_ID:-1}" > "$ZOO_DATA_DIR/myid" 42 | fi 43 | 44 | exec "$@" 45 | -------------------------------------------------------------------------------- /google-cloud/README.md: -------------------------------------------------------------------------------- 1 | gcloud config set compute/region europe-west4 2 | 3 | gcloud config set compute/zone europe-west4-b 4 | 5 | gcloud container clusters create cluster1 --num-nodes 1 --machine-type n1-standard-4 --disk-size=50 --scopes storage-rw,compute-rw 6 | 7 | gcloud compute disks create --size 50 --type pd-standard pd-disk-zookeeper 8 | 9 | gcloud compute disks create --size 50 --type pd-standard pd-disk-solr 10 | 11 | -------------------------------------------------------------------------------- /ingress/certificates.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: certmanager.k8s.io/v1alpha1 2 | kind: Certificate 3 | metadata: 4 | name: tls-secret-prod 5 | spec: 6 | secretName: tls-secret-prod 7 | dnsNames: 8 | - nobby-a4aedadfe4.northeurope.cloudapp.azure.com 9 | acme: 10 | config: 11 | - http01: 12 | ingressClass: nginx 13 | domains: 14 | - nobby-a4aedadfe4.northeurope.cloudapp.azure.com 15 | issuerRef: 16 | name: letsencrypt-prod 17 | kind: ClusterIssuer 18 | -------------------------------------------------------------------------------- /ingress/cluster-issuer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: certmanager.k8s.io/v1alpha1 2 | kind: ClusterIssuer 3 | metadata: 4 | name: letsencrypt-prod 5 | spec: 6 | acme: 7 | server: https://acme-v02.api.letsencrypt.org/directory 8 | email: antony.briggs@gmail.com 9 | privateKeySecretRef: 10 | name: letsencrypt-prod 11 | http01: {} -------------------------------------------------------------------------------- /ingress/ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: nobby-ingress 5 | annotations: 6 | kubernetes.io/ingress.class: nginx 7 | certmanager.k8s.io/cluster-issuer: letsencrypt-prod 8 | nginx.ingress.kubernetes.io/rewrite-target: / 9 | spec: 10 | tls: 11 | - hosts: 12 | - nobby-a4aedadfe4.northeurope.cloudapp.azure.com 13 | secretName: tls-secret-prod 14 | rules: 15 | - host: nobby-a4aedadfe4.northeurope.cloudapp.azure.com 16 | http: 17 | paths: 18 | - path: / 19 | backend: 20 | serviceName: nobby-service 21 | servicePort: 3000 22 | - path: /solr 23 | backend: 24 | serviceName: solr-service 25 | servicePort: 8983 26 | -------------------------------------------------------------------------------- /minikube/service-solr.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: solrcluster 5 | labels: 6 | app: solr-app 7 | spec: 8 | clusterIP: None 9 | selector: 10 | app: solr-app 11 | --- 12 | apiVersion: v1 13 | kind: Service 14 | metadata: 15 | name: solr-service 16 | labels: 17 | app: solr-app 18 | spec: 19 | ports: 20 | - port: 8983 21 | targetPort: 8983 22 | nodePort: 8983 23 | protocol: TCP 24 | selector: 25 | app: solr-app 26 | type: NodePort 27 | -------------------------------------------------------------------------------- /minikube/service-zookeeper.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: zkensemble 5 | labels: 6 | app: zookeeper-app 7 | spec: 8 | clusterIP: None 9 | selector: 10 | app: zookeeper-app 11 | --- 12 | apiVersion: v1 13 | kind: Service 14 | metadata: 15 | name: zk-service 16 | labels: 17 | app: zookeeper-app 18 | spec: 19 | ports: 20 | - port: 2181 21 | targetPort: 2181 22 | nodePort: 2181 23 | protocol: TCP 24 | selector: 25 | app: zookeeper-app 26 | type: NodePort 27 | -------------------------------------------------------------------------------- /minikube/storageclass-solrcluster.yml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1beta1 3 | metadata: 4 | name: store-solrcluster 5 | provisioner: k8s.io/minikube-hostpath 6 | -------------------------------------------------------------------------------- /minikube/storageclass-zkensemble.yml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1beta1 3 | metadata: 4 | name: store-zkensemble 5 | provisioner: k8s.io/minikube-hostpath 6 | -------------------------------------------------------------------------------- /service-account/rbac-config.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: tiller 5 | namespace: kube-system 6 | --- 7 | apiVersion: rbac.authorization.k8s.io/v1 8 | kind: ClusterRoleBinding 9 | metadata: 10 | name: tiller 11 | roleRef: 12 | apiGroup: rbac.authorization.k8s.io 13 | kind: ClusterRole 14 | name: cluster-admin 15 | subjects: 16 | - kind: ServiceAccount 17 | name: tiller 18 | namespace: kube-system -------------------------------------------------------------------------------- /services/service-solr-cluster.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: solrcluster 5 | labels: 6 | app: solr-app 7 | spec: 8 | clusterIP: None 9 | selector: 10 | app: solr-app 11 | --- 12 | apiVersion: v1 13 | kind: Service 14 | metadata: 15 | name: solr-service 16 | labels: 17 | app: solr-app 18 | spec: 19 | ports: 20 | - protocol: TCP 21 | port: 8983 22 | targetPort: 8983 23 | type: LoadBalancer 24 | selector: 25 | app: solr-app 26 | -------------------------------------------------------------------------------- /services/service-solr.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: solr-service-nodeport 5 | spec: 6 | ports: 7 | - port: 8983 8 | targetPort: 8983 9 | protocol: TCP 10 | selector: 11 | app: solr-app 12 | type: NodePort 13 | -------------------------------------------------------------------------------- /services/service-zookeeper-ensemble.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: zkensemble 5 | labels: 6 | app: zookeeper-app 7 | spec: 8 | clusterIP: None 9 | selector: 10 | app: zookeeper-app 11 | --- 12 | apiVersion: v1 13 | kind: Service 14 | metadata: 15 | name: zk-service 16 | labels: 17 | app: zookeeper-app 18 | spec: 19 | ports: 20 | - protocol: TCP 21 | port: 2181 22 | targetPort: 2181 23 | type: LoadBalancer 24 | selector: 25 | app: zookeeper-app 26 | -------------------------------------------------------------------------------- /services/service-zookeeper.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: zookeeper-service-nodeport 5 | spec: 6 | ports: 7 | - port: 2181 8 | targetPort: 2181 9 | protocol: TCP 10 | selector: 11 | app: zookeeper-app 12 | type: NodePort 13 | -------------------------------------------------------------------------------- /start-aks-multi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # build zookeeper ensenble from k8s repo 4 | kubectl apply -f https://kubernetes.io/examples/application/zookeeper/zookeeper.yaml 5 | 6 | kubectl create configmap solr-config --from-env-file=configmap/solr-config-multi.properties 7 | 8 | kubectl get configmap 9 | 10 | # I think the headless service needs creating before the stateful set 11 | kubectl create -f services/service-solr.yml 12 | kubectl create -f statefulsets/pod-disruption-budget.yml 13 | kubectl create -f statefulsets/statefulset-solr.yml 14 | 15 | # init helm 16 | # 1. create service account called tiller 17 | # kubectl create -f service-account/rbac-config.yaml 18 | # 2. init 19 | # helm init --service-account tiller 20 | 21 | # create ingress controller (helm) 22 | helm install stable/nginx-ingress --namespace kube-system --set controller.replicaCount=2 --set rbac.create=false 23 | 24 | # get eternal ip of ingress controller 25 | kubectl get service -l app=nginx-ingress --namespace kube-system 26 | 27 | # create dns for ip address created by ingress controller 28 | 29 | ##!/bin/bash 30 | ## Public IP address of your ingress controller 31 | #IP="138.91.55.80" 32 | ## Get the resource-id of the public ip 33 | #PUBLICIPID=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[id]" --output tsv) 34 | ## Update public ip address with DNS name 35 | #az network public-ip update --ids $PUBLICIPID --dns-name "nobby-a4aedadfe4" 36 | 37 | 38 | # create cert-manager 39 | # This is a 2-step process as a work-around for some issues with CRDs 40 | kubectl apply \ 41 | -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.6/deploy/manifests/00-crds.yaml 42 | helm repo update 43 | helm install stable/cert-manager \ 44 | --namespace kube-system \ 45 | --set ingressShim.defaultIssuerName=letsencrypt-prod \ 46 | --set ingressShim.defaultIssuerKind=ClusterIssuer \ 47 | --set rbac.create=false \ 48 | --set serviceAccount.create=false \ 49 | --set createCustomResource=false 50 | 51 | # create cert issuer (not sure on dependency on above) 52 | kubectl apply -f ingress/cluster-issuer.yaml 53 | 54 | # create cert 55 | kubectl apply -f ingress/certificates.yaml 56 | 57 | # create ingress - it takes a few minutes for the certificate to be visible on the https site 58 | kubectl apply -f ingress/ingress.yml 59 | 60 | kubectl get pod 61 | kubectl get statefulset 62 | kubectl get service 63 | kubectl get certificate 64 | kubectl get ingress 65 | -------------------------------------------------------------------------------- /start-aks-solr-cluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl create configmap solr-cluster-config --from-env-file=configmap/solr-cluster-config.properties 4 | 5 | kubectl get configmap 6 | 7 | kubectl apply -f aks/storageclass-solrcluster.yml 8 | 9 | kubectl get storageclass 10 | 11 | kubectl apply -f aks/service-solr-cluster.yml 12 | 13 | kubectl get service 14 | 15 | kubectl apply -f statefulsets/statefulset-solr-cluster.yml 16 | 17 | kubectl get statefulsets 18 | -------------------------------------------------------------------------------- /start-aks-zookeeper-ensemble.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl create configmap zookeeper-ensemble-config --from-env-file=configmap/zookeeper-ensemble-config.properties 4 | 5 | kubectl get configmap 6 | 7 | kubectl apply -f aks/storageclass-zkensemble.yml 8 | 9 | kubectl get storageclass 10 | 11 | kubectl apply -f aks/service-zookeeper-ensemble.yml 12 | 13 | kubectl get service 14 | 15 | kubectl apply -f statefulsets/statefulset-zookeeper-ensemble.yml 16 | 17 | kubectl get statefulsets 18 | -------------------------------------------------------------------------------- /start-aws-solr-cluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl create configmap solr-cluster-config --from-env-file=configmap/solr-cluster-config.properties 4 | 5 | kubectl get configmap 6 | 7 | kubectl apply -f aws/storageclass-solrcluster.yml 8 | 9 | kubectl get storageclass 10 | 11 | kubectl apply -f services/service-solr-cluster.yml 12 | 13 | kubectl get service 14 | 15 | kubectl apply -f statefulsets/statefulset-solr-cluster.yml 16 | 17 | kubectl get statefulsets 18 | -------------------------------------------------------------------------------- /start-aws-zookeeper-ensemble.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl create configmap zookeeper-ensemble-config --from-env-file=configmap/zookeeper-ensemble-config.properties 4 | 5 | kubectl get configmap 6 | 7 | kubectl apply -f aws/storageclass-zkensemble.yml 8 | 9 | kubectl get storageclass 10 | 11 | kubectl apply -f services/service-zookeeper-ensemble.yml 12 | 13 | kubectl get service 14 | 15 | kubectl apply -f statefulsets/statefulset-zookeeper-ensemble.yml 16 | 17 | kubectl get statefulsets 18 | -------------------------------------------------------------------------------- /start-minikube.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl create configmap solr-config --from-env-file=configmap/solr-config.properties 4 | kubectl create configmap zookeeper-config --from-env-file=configmap/zookeeper-config.properties 5 | 6 | kubectl get configmap 7 | 8 | kubectl apply -f minikube/storageclass-solrcluster.yml 9 | kubectl apply -f minikube/storageclass-zkensemble.yml 10 | 11 | kubectl apply -f statefulsets/statefulset-zookeeper.yml 12 | 13 | sleep 5 14 | 15 | kubectl apply -f minikube/service-zookeeper.yml 16 | 17 | kubectl apply -f statefulsets/statefulset-solr.yml 18 | 19 | sleep 5 20 | 21 | kubectl apply -f minikube/service-solr.yml 22 | 23 | kubectl get pod 24 | kubectl get deployment 25 | kubectl get service 26 | 27 | echo "created solr and zookeeper statefulsets" 28 | echo "created solr and zookeeper services" 29 | echo "" 30 | 31 | -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl create configmap solr-config --from-env-file=configmap/solr-config.properties 4 | kubectl create configmap zookeeper-config --from-env-file=configmap/zookeeper-config.properties 5 | 6 | kubectl create -f statefulsets/statefulset-zookeeper.yml 7 | kubectl create -f services/service-zookeeper-ensemble.yml 8 | 9 | sleep 15 10 | 11 | kubectl create -f statefulsets/statefulset-solr.yml 12 | kubectl create -f services/service-solr-cluster.yml 13 | 14 | kubectl get pod 15 | kubectl get deployment 16 | kubectl get service 17 | 18 | -------------------------------------------------------------------------------- /statefulsets/pod-disruption-budget.yml: -------------------------------------------------------------------------------- 1 | apiVersion: policy/v1beta1 2 | kind: PodDisruptionBudget 3 | metadata: 4 | name: solr-pdb 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: solr-app 9 | maxUnavailable: 1 -------------------------------------------------------------------------------- /statefulsets/statefulset-solr-cluster.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: solr 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: solr-app # has to match .spec.template.metadata.labels 9 | serviceName: "solrcluster" 10 | replicas: 2 # by default is 1 11 | template: 12 | metadata: 13 | labels: 14 | app: solr-app # has to match .spec.selector.matchLabels 15 | spec: 16 | terminationGracePeriodSeconds: 60 17 | restartPolicy: Always 18 | containers: 19 | - name: solr 20 | image: solr:8.8.1 21 | imagePullPolicy: IfNotPresent 22 | # resources: 23 | # requests: 24 | # cpu: 1000m 25 | # limits: 26 | # cpu: 1000m 27 | readinessProbe: 28 | tcpSocket: 29 | port: 8983 30 | initialDelaySeconds: 5 31 | periodSeconds: 10 32 | livenessProbe: 33 | tcpSocket: 34 | port: 8983 35 | initialDelaySeconds: 15 36 | periodSeconds: 20 37 | volumeMounts: 38 | - name: volsolr 39 | mountPath: /store 40 | ports: 41 | - name: solrport 42 | containerPort: 8983 43 | env: 44 | - name: MY_POD_NAME 45 | valueFrom: 46 | fieldRef: 47 | fieldPath: metadata.name 48 | - name: MY_POD_NAMESPACE 49 | valueFrom: 50 | fieldRef: 51 | fieldPath: metadata.namespace 52 | - name: MY_POD_IP 53 | valueFrom: 54 | fieldRef: 55 | fieldPath: status.podIP 56 | - name: SOLR_HOME 57 | valueFrom: 58 | configMapKeyRef: 59 | name: solr-cluster-config 60 | key: solrHome 61 | - name: ZK_HOST 62 | valueFrom: 63 | configMapKeyRef: 64 | name: solr-cluster-config 65 | key: zkHost 66 | - name: POD_HOST_NAME 67 | valueFrom: 68 | fieldRef: 69 | fieldPath: metadata.name 70 | - name: SOLR_HOST 71 | value: "$(POD_HOST_NAME).solrcluster" 72 | - name: SOLR_LOGS_DIR 73 | valueFrom: 74 | configMapKeyRef: 75 | name: solr-cluster-config 76 | key: solrLogsDir 77 | - name: SOLR_HEAP 78 | valueFrom: 79 | configMapKeyRef: 80 | name: solr-cluster-config 81 | key: solrHeap 82 | initContainers: 83 | - name: init-solr-data 84 | image: busybox 85 | command: 86 | - "/bin/sh" 87 | - "-c" 88 | - "if [ ! -d $SOLR_HOME/lib ] ; then mkdir -p $SOLR_HOME/lib && chown -R 8983:8983 $SOLR_HOME ; else true; fi" 89 | env: 90 | - name: SOLR_HOME 91 | valueFrom: 92 | configMapKeyRef: 93 | name: solr-cluster-config 94 | key: solrHome 95 | volumeMounts: 96 | - name: volsolr 97 | mountPath: /store 98 | - name: init-solr-logs 99 | image: busybox 100 | command: 101 | - "/bin/sh" 102 | - "-c" 103 | - "if [ ! -d $SOLR_LOGS_DIR ] ; then mkdir -p $SOLR_LOGS_DIR && chown 8983:8983 $SOLR_LOGS_DIR ; else true; fi" 104 | env: 105 | - name: SOLR_LOGS_DIR 106 | valueFrom: 107 | configMapKeyRef: 108 | name: solr-cluster-config 109 | key: solrLogsDir 110 | volumeMounts: 111 | - name: volsolr 112 | mountPath: /store 113 | - name: init-solr-xml 114 | image: solr:8.1.1 115 | command: 116 | - "/bin/sh" 117 | - "-c" 118 | - "if [ ! -f $SOLR_HOME/solr.xml ] ; then cp /opt/solr/server/solr/solr.xml $SOLR_HOME/solr.xml;\ 119 | sed -i \"s//\\/store\\/data\\/lib<\\/str>/g\" $SOLR_HOME/solr.xml ; else true; fi " 120 | env: 121 | - name: SOLR_HOME 122 | valueFrom: 123 | configMapKeyRef: 124 | name: solr-cluster-config 125 | key: solrHome 126 | volumeMounts: 127 | - name: volsolr 128 | mountPath: /store 129 | volumeClaimTemplates: 130 | - metadata: 131 | name: volsolr 132 | spec: 133 | storageClassName: store-solrcluster 134 | accessModes: [ "ReadWriteOnce" ] 135 | resources: 136 | requests: 137 | storage: 32Gi 138 | -------------------------------------------------------------------------------- /statefulsets/statefulset-solr.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: solr 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: solr-app # has to match .spec.template.metadata.labels 9 | serviceName: "solrcluster" 10 | replicas: 1 # by default is 1 11 | template: 12 | metadata: 13 | labels: 14 | app: solr-app # has to match .spec.selector.matchLabels 15 | spec: 16 | terminationGracePeriodSeconds: 10 17 | restartPolicy: Always 18 | containers: 19 | - name: solr 20 | image: solr:8.1.1 21 | imagePullPolicy: IfNotPresent 22 | readinessProbe: 23 | tcpSocket: 24 | port: 8983 25 | initialDelaySeconds: 5 26 | periodSeconds: 10 27 | livenessProbe: 28 | tcpSocket: 29 | port: 8983 30 | initialDelaySeconds: 15 31 | periodSeconds: 20 32 | volumeMounts: 33 | - name: volsolr 34 | mountPath: /store 35 | ports: 36 | - name: solrport 37 | containerPort: 8983 38 | env: 39 | - name: MY_POD_NAME 40 | valueFrom: 41 | fieldRef: 42 | fieldPath: metadata.name 43 | - name: MY_POD_NAMESPACE 44 | valueFrom: 45 | fieldRef: 46 | fieldPath: metadata.namespace 47 | - name: MY_POD_IP 48 | valueFrom: 49 | fieldRef: 50 | fieldPath: status.podIP 51 | - name: SOLR_HOME 52 | valueFrom: 53 | configMapKeyRef: 54 | name: solr-config 55 | key: solrHome 56 | - name: ZK_HOST 57 | valueFrom: 58 | configMapKeyRef: 59 | name: solr-config 60 | key: zkHost 61 | - name: POD_HOST_NAME 62 | valueFrom: 63 | fieldRef: 64 | fieldPath: metadata.name 65 | - name: SOLR_HOST 66 | value: "$(POD_HOST_NAME).solrcluster" 67 | - name: SOLR_LOGS_DIR 68 | valueFrom: 69 | configMapKeyRef: 70 | name: solr-config 71 | key: solrLogsDir 72 | - name: SOLR_HEAP 73 | valueFrom: 74 | configMapKeyRef: 75 | name: solr-config 76 | key: solrHeap 77 | initContainers: 78 | - name: init-solr-data 79 | image: busybox 80 | command: 81 | - "/bin/sh" 82 | - "-c" 83 | - "if [ ! -d $SOLR_HOME/lib ] ; then mkdir -p $SOLR_HOME/lib && chown -R 8983:8983 $SOLR_HOME ; else true; fi" 84 | env: 85 | - name: SOLR_HOME 86 | valueFrom: 87 | configMapKeyRef: 88 | name: solr-config 89 | key: solrHome 90 | volumeMounts: 91 | - name: volsolr 92 | mountPath: /store 93 | - name: init-solr-logs 94 | image: busybox 95 | command: 96 | - "/bin/sh" 97 | - "-c" 98 | - "if [ ! -d $SOLR_LOGS_DIR ] ; then mkdir -p $SOLR_LOGS_DIR && chown 8983:8983 $SOLR_LOGS_DIR ; else true; fi" 99 | env: 100 | - name: SOLR_LOGS_DIR 101 | valueFrom: 102 | configMapKeyRef: 103 | name: solr-config 104 | key: solrLogsDir 105 | volumeMounts: 106 | - name: volsolr 107 | mountPath: /store 108 | - name: init-solr-xml 109 | image: solr:8.1.1 110 | command: 111 | - "/bin/sh" 112 | - "-c" 113 | - "if [ ! -f $SOLR_HOME/solr.xml ] ; then cp /opt/solr/server/solr/solr.xml $SOLR_HOME/solr.xml;\ 114 | sed -i \"s//\\/store\\/data\\/lib<\\/str>/g\" $SOLR_HOME/solr.xml ; else true; fi " 115 | env: 116 | - name: SOLR_HOME 117 | valueFrom: 118 | configMapKeyRef: 119 | name: solr-config 120 | key: solrHome 121 | volumeMounts: 122 | - name: volsolr 123 | mountPath: /store 124 | volumeClaimTemplates: 125 | - metadata: 126 | name: volsolr 127 | spec: 128 | accessModes: [ "ReadWriteOnce" ] 129 | resources: 130 | requests: 131 | storage: 32Gi 132 | -------------------------------------------------------------------------------- /statefulsets/statefulset-zookeeper-ensemble.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: zk 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: zookeeper-app # has to match .spec.template.metadata.labels 9 | serviceName: "zkensemble" 10 | replicas: 3 # by default is 1 11 | template: 12 | metadata: 13 | labels: 14 | app: zookeeper-app # has to match .spec.selector.matchLabels 15 | spec: 16 | terminationGracePeriodSeconds: 10 17 | restartPolicy: Always 18 | containers: 19 | - name: zookeeper 20 | image: zookeeper:3.4.14 21 | imagePullPolicy: IfNotPresent 22 | command: 23 | - "/bin/sh" 24 | - "-c" 25 | - "if [ ! -d $ZOO_DATA_DIR ] ; then mkdir -p $ZOO_DATA_DIR ; chmod 777 $ZOO_DATA_DIR ; else touch /conf/test; fi && \ 26 | if [ ! -d $ZOO_LOG_DIR ] ; then mkdir -p $ZOO_LOG_DIR ; chmod 777 $ZOO_LOG_DIR ; else touch /conf/test; fi && \ 27 | if [ ! -d $ZOO_DATA_LOG_DIR ] ; then mkdir -p $ZOO_DATA_LOG_DIR ; chmod 777 $ZOO_DATA_LOG_DIR ; else touch /conf/test; fi && \ 28 | if [ ! -f $ZOO_DATA_DIR/myid ] ; then $(echo $((${HOSTNAME##*-}+1)) > $ZOO_DATA_DIR/myid ) else touch /conf/test; fi && \ 29 | $(echo $ZOO_SERVERS | sed \"s/$(hostname).zkensemble/0.0.0.0/g\" > /conf/zooservers.txt) && \ 30 | export ZOO_SERVERS=\"$( cat /conf/zooservers.txt )\" && \ 31 | /docker-entrypoint.sh zkServer.sh start-foreground" 32 | readinessProbe: 33 | tcpSocket: 34 | port: 2181 35 | initialDelaySeconds: 5 36 | periodSeconds: 10 37 | livenessProbe: 38 | tcpSocket: 39 | port: 2181 40 | initialDelaySeconds: 15 41 | periodSeconds: 20 42 | volumeMounts: 43 | - name: volzookeeper 44 | mountPath: /store 45 | ports: 46 | - name: zkport 47 | containerPort: 2181 48 | - name: zkportpeers 49 | containerPort: 2888 50 | - name: zkportelection 51 | containerPort: 3888 52 | env: 53 | - name: MY_POD_NAME 54 | valueFrom: 55 | fieldRef: 56 | fieldPath: metadata.name 57 | - name: MY_POD_NAMESPACE 58 | valueFrom: 59 | fieldRef: 60 | fieldPath: metadata.namespace 61 | - name: MY_POD_IP 62 | valueFrom: 63 | fieldRef: 64 | fieldPath: status.podIP 65 | - name: ZOO_LOG_DIR 66 | valueFrom: 67 | configMapKeyRef: 68 | name: zookeeper-ensemble-config 69 | key: zooLogDir 70 | - name: ZOO_DATA_DIR 71 | valueFrom: 72 | configMapKeyRef: 73 | name: zookeeper-ensemble-config 74 | key: zooDataDir 75 | - name: ZOO_DATA_LOG_DIR 76 | valueFrom: 77 | configMapKeyRef: 78 | name: zookeeper-ensemble-config 79 | key: zooDataLogDir 80 | - name: ZOO_SERVERS 81 | valueFrom: 82 | configMapKeyRef: 83 | name: zookeeper-ensemble-config 84 | key: zooServers 85 | - name: ZOO_LOG4J_PROP 86 | valueFrom: 87 | configMapKeyRef: 88 | name: zookeeper-ensemble-config 89 | key: zooLog4jProp 90 | - name: ZOO_STANDALONE_ENABLED 91 | valueFrom: 92 | configMapKeyRef: 93 | name: zookeeper-ensemble-config 94 | key: zooStandaloneEnabled 95 | - name: ZOO_ADMINSERVER_ENABLED 96 | valueFrom: 97 | configMapKeyRef: 98 | name: zookeeper-ensemble-config 99 | key: zooAdminServerEnabled 100 | volumeClaimTemplates: 101 | - metadata: 102 | name: volzookeeper 103 | spec: 104 | storageClassName: store-zkensemble 105 | accessModes: [ "ReadWriteOnce" ] 106 | resources: 107 | requests: 108 | storage: 32Gi 109 | -------------------------------------------------------------------------------- /statefulsets/statefulset-zookeeper.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: zk 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: zookeeper-app # has to match .spec.template.metadata.labels 9 | serviceName: "zkensemble" 10 | replicas: 1 # by default is 1 11 | template: 12 | metadata: 13 | labels: 14 | app: zookeeper-app # has to match .spec.selector.matchLabels 15 | spec: 16 | terminationGracePeriodSeconds: 60 17 | restartPolicy: Always 18 | containers: 19 | - name: zookeeper 20 | image: zookeeper:3.4.14 21 | imagePullPolicy: IfNotPresent 22 | command: 23 | - "/bin/sh" 24 | - "-c" 25 | - "if [ ! -d $ZOO_DATA_DIR ] ; then mkdir -p $ZOO_DATA_DIR ; chmod 777 $ZOO_DATA_DIR ; else touch /conf/test; fi && \ 26 | if [ ! -d $ZOO_LOG_DIR ] ; then mkdir -p $ZOO_LOG_DIR ; chmod 777 $ZOO_LOG_DIR ; else touch /conf/test; fi && \ 27 | if [ ! -d $ZOO_DATA_LOG_DIR ] ; then mkdir -p $ZOO_DATA_LOG_DIR ; chmod 777 $ZOO_DATA_LOG_DIR ; else touch /conf/test; fi && \ 28 | if [ ! -f $ZOO_DATA_DIR/myid ] ; then $(echo $((${HOSTNAME##*-}+1)) > $ZOO_DATA_DIR/myid ) else touch /conf/test; fi && \ 29 | /docker-entrypoint.sh zkServer.sh start-foreground" 30 | readinessProbe: 31 | tcpSocket: 32 | port: 2181 33 | initialDelaySeconds: 5 34 | periodSeconds: 10 35 | livenessProbe: 36 | tcpSocket: 37 | port: 2181 38 | initialDelaySeconds: 15 39 | periodSeconds: 20 40 | volumeMounts: 41 | - name: volzookeeper 42 | mountPath: /store 43 | ports: 44 | - name: zkport 45 | containerPort: 2181 46 | - name: zkportpeers 47 | containerPort: 2888 48 | - name: zkportelection 49 | containerPort: 3888 50 | env: 51 | - name: MY_POD_NAME 52 | valueFrom: 53 | fieldRef: 54 | fieldPath: metadata.name 55 | - name: MY_POD_NAMESPACE 56 | valueFrom: 57 | fieldRef: 58 | fieldPath: metadata.namespace 59 | - name: MY_POD_IP 60 | valueFrom: 61 | fieldRef: 62 | fieldPath: status.podIP 63 | - name: ZOO_LOG_DIR 64 | valueFrom: 65 | configMapKeyRef: 66 | name: zookeeper-config 67 | key: zooLogDir 68 | - name: ZOO_DATA_DIR 69 | valueFrom: 70 | configMapKeyRef: 71 | name: zookeeper-config 72 | key: zooDataDir 73 | - name: ZOO_DATA_LOG_DIR 74 | valueFrom: 75 | configMapKeyRef: 76 | name: zookeeper-config 77 | key: zooDataLogDir 78 | - name: ZOO_LOG4J_PROP 79 | valueFrom: 80 | configMapKeyRef: 81 | name: zookeeper-config 82 | key: zooLog4jProp 83 | volumeClaimTemplates: 84 | - metadata: 85 | name: volzookeeper 86 | spec: 87 | accessModes: [ "ReadWriteOnce" ] 88 | resources: 89 | requests: 90 | storage: 32Gi 91 | -------------------------------------------------------------------------------- /stop-and-delete-aks-solr-cluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl delete statefulset solr 4 | 5 | kubectl delete service solrcluster 6 | kubectl delete service solr-service 7 | 8 | kubectl delete pvc volsolr-solr-0 9 | kubectl delete pvc volsolr-solr-1 10 | # kubectl delete pvc volsolr-solr-2 11 | 12 | PV=$(kubectl get pv | grep "default/volsolr-solr-" | awk '{ print $1}') 13 | if [ "$PV" == "" ] 14 | then 15 | echo "persistent volume not found" 16 | else 17 | kubectl delete pv $PV 18 | fi 19 | 20 | kubectl delete configmap solr-cluster-config 21 | kubectl delete sc store-solrcluster 22 | 23 | -------------------------------------------------------------------------------- /stop-and-delete-aks-zookeeper-ensemble.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl delete statefulset zk 4 | 5 | kubectl delete service zkensemble 6 | kubectl delete service zk-service 7 | 8 | kubectl delete pvc volzookeeper-zk-0 9 | kubectl delete pvc volzookeeper-zk-1 10 | kubectl delete pvc volzookeeper-zk-2 11 | 12 | PV=$(kubectl get pv | grep "default/volzookeeper-zk-" | awk '{ print $1}') 13 | if [ "$PV" == "" ] 14 | then 15 | echo "persistent volume not found" 16 | else 17 | kubectl delete pv $PV 18 | fi 19 | 20 | kubectl delete configmap zookeeper-ensemble-config 21 | 22 | kubectl delete storageclass store-zkensemble 23 | -------------------------------------------------------------------------------- /stop-and-delete.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl delete statefulset solr 4 | kubectl delete statefulset zk 5 | 6 | kubectl delete svc solr-service 7 | kubectl delete svc solrcluster 8 | kubectl delete svc zk-service 9 | kubectl delete svc zkensemble 10 | 11 | kubectl delete configmap solr-config 12 | kubectl delete configmap solr-cluster-config 13 | kubectl delete configmap zookeeper-config 14 | kubectl delete configmap zookeeper-ensemble-config 15 | 16 | 17 | PVC=$(kubectl get pvc | grep -E "volzookeeper-zk-\d+|volsolr-solr-\d+" | awk '{ print $1}') 18 | if [ "$PVC" == "" ] 19 | then 20 | echo "persistent volume claim not found" 21 | else 22 | kubectl delete pvc $PVC 23 | fi 24 | 25 | PV=$(kubectl get pv | grep "default/volsolr-solr-" | awk '{ print $1}') 26 | if [ "$PV" == "" ] 27 | then 28 | echo "persistent volume not found" 29 | else 30 | kubectl delete pv $PV 31 | fi 32 | 33 | PV=$(kubectl get pv | grep "default/volzookeeper-zk-" | awk '{ print $1}') 34 | if [ "$PV" == "" ] 35 | then 36 | echo "persistent volume not found" 37 | else 38 | kubectl delete pv $PV 39 | fi 40 | 41 | kubectl delete storageclass store-solrcluster 42 | kubectl delete storageclass store-zkensemble 43 | 44 | --------------------------------------------------------------------------------