├── LICENSE ├── README.md ├── Ubuntu └── container_toolkit.sh ├── cert-manager ├── README.md ├── letsencrypt-prod-issuer.yaml ├── letsencrypt-staging-issuer.yaml └── selfsigned-cluster-issuer.yaml ├── docker-registry ├── README.md └── full_deployment.yaml ├── metallb ├── layer2-conf.yaml ├── metallb-notes.txt └── nginx-metallb.yaml ├── notes └── docker-containers-to-k8s-pods.txt ├── prometheus_grafana └── README.md ├── raspberry_pi ├── example_yaml_deployment.yaml ├── rpi_container_toolkit.sh ├── secure_pi.sh └── traefik.yaml ├── traefik └── README.md └── user_administration └── authenticate_users.sh /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Automate the install of Kubernetes and Docker. 2 | Calico networking is here to stay. 3 | 4 | 5 | # Help Menu Ubuntu 22.04 6 | 7 | 8 | ``` 9 | ./container_toolkit.sh -h 10 | [*] Help Menu: 11 | 12 | [*] --master-calico Install Kubernetes MASTER NODE Calico and Docker. 13 | ./container_toolkit.sh --master-calico 14 | 15 | [*] --worker-node Install Kubernetes WORKER NODE and Docker 16 | ./container_toolkit.sh --worker-node 17 | 18 | [*] --docker Install ONLY Docker. 19 | ./container_toolkit.sh --docker 20 | 21 | [*] --rancher Install a ONLY Rancher constainer. 22 | ./container_toolkit.sh --rancher 23 | 24 | [*] --helm Apply this option to install helm. 25 | ./container_toolkit.sh --helm 26 | 27 | [*] --clean Clean up Kubernetes WORKER NODES. Typically we should not need this. 28 | ./container_toolkit.sh --clean 29 | ``` 30 | 31 | 32 | # Deploy Kubernetes Master With The Calico Network: 33 | 34 | * Run on a Ubuntu 22.04 hosts or VM that you want dedicated as Master 35 | 36 | ```./container_toolkit.sh --master-calico``` 37 | 38 | * Once done, check your pods: 39 | 40 | ``` 41 | kubectl get pods --all-namespaces 42 | 43 | NAMESPACE NAME READY STATUS RESTARTS AGE 44 | kube-system calico-kube-controllers-7b9dcdcc5-dsm52 1/1 Running 0 74s 45 | kube-system calico-node-q9g9f 1/1 Running 0 75s 46 | kube-system coredns-5644d7b6d9-k5z7x 1/1 Running 0 75s 47 | kube-system coredns-5644d7b6d9-q2464 1/1 Running 0 75s 48 | kube-system etcd-container-host 1/1 Running 0 15s 49 | kube-system kube-apiserver-container-host 1/1 Running 0 23s 50 | kube-system kube-controller-manager-container-host 1/1 Running 0 17s 51 | kube-system kube-proxy-z4fqq 1/1 Running 0 75s 52 | kube-system kube-scheduler-container-host 1/1 Running 0 19s 53 | ``` 54 | 55 | 56 | # Deploy Kubernetes Workers: 57 | 58 | * Run on a Ubunutu 22.04 hosts or VM that you want dedicated as a Worker 59 | 60 | ```./container_toolkit.sh --worker-node``` 61 | 62 | * Obtain your secret from master and add to each worker node. 63 | * You can verify all is working by running on Master: 64 | 65 | ``` 66 | kubectl get nodes 67 | NAME STATUS ROLES AGE VERSION 68 | container-host Ready master 5m57s v1.16.2 69 | k8-node1 Ready 2m58s v1.16.2 70 | k8-node2 Ready 2m55s v1.16.2 71 | k8-node3 Ready 2m55s v1.16.2 72 | ``` 73 | 74 | # Side note 75 | We have found Ubuntu 22.04 doesn't always disable swap after a reboot. You most likely will need to ssh into the nodes and disable swap, then restart kubernetes to get the services working: 76 | ``` 77 | sudo /sbin/swapoff -av 78 | sudo systemctl restart kubelet.service 79 | ``` 80 | 81 | 82 | ## Install Dockerfile 83 | ``` 84 | docker build -t container_toolkit . 85 | docker run --rm -it container_toolkit /opt/container_toolkit/Ubuntu/container_toolkit.sh -h 86 | ``` 87 | 88 | 89 | # Help Menu - Raspberry Pi 90 | 91 | ``` 92 | bash rpi_container_toolkit.sh 93 | [*] Help Menu: 94 | 95 | [*] --rancherk3s-master The generic k3s install for Master. 96 | bash rpi_container_toolkit.sh --rancherk3s-master 97 | 98 | [*] --rancherk3s-worker The generic k3s install for Worker. 99 | bash rpi_container_toolkit.sh --rancherk3s-worker 100 | 101 | 102 | ###### FOR THE DOCKER USERS - use below options to install Docker instead of containerd ###### 103 | 104 | 105 | [*] --rancherk3s-master-docker K3s install for Master but with Docker instead of containerd. 106 | bash rpi_container_toolkit.sh --rancherk3s-master-docker 107 | 108 | [*] --rancherk3s-worker-docker K3s install for Worker but with Docker instead of containerd. 109 | bash rpi_container_toolkit.sh --rancherk3s-worker-docker 110 | 111 | 112 | >>> Use below to install frameworks known to work on k3s. 113 | 114 | [*] --helm-master Install Helm3 to Master 115 | bash rpi_container_toolkit.sh --helm 116 | 117 | [*] --openfaas-master Install on master - openfaas repo and cli tools. 118 | bash rpi_container_toolkit.sh --openfaas-master 119 | 120 | [*] --arkade-master Install on master - arkade repo and cli tools. 121 | bash rpi_container_toolkit.sh --arkade-master 122 | ``` 123 | 124 | * Check your nodes 125 | 126 | ``` 127 | kubectl get nodes 128 | NAME STATUS ROLES AGE VERSION 129 | pi-master Ready master 37m v1.18.2+k3s1 130 | pi-worker1 Ready 27m v1.18.2+k3s1 131 | pi-worker2 Ready 25m v1.18.2+k3s1 132 | ``` 133 | 134 | * Check your pods: 135 | ``` 136 | kubectl get pods --all-namespaces 137 | NAMESPACE NAME READY STATUS RESTARTS AGE 138 | kube-system helm-install-traefik-b5mzb 0/1 Completed 2 37m 139 | kube-system metrics-server-7566d596c8-5nqdn 1/1 Running 1 37m 140 | kube-system local-path-provisioner-6d59f47c7-blj9l 1/1 Running 1 37m 141 | kube-system svclb-traefik-kxhxw 2/2 Running 2 36m 142 | kube-system traefik-758cd5fc85-shcm2 1/1 Running 1 36m 143 | kube-system coredns-8655855d6-xh8p9 1/1 Running 1 37m 144 | kube-system svclb-traefik-ftjzq 2/2 Running 2 27m 145 | kube-system svclb-traefik-59p4l 2/2 Running 0 25m 146 | openfaas nats-b988ccbfd-5zddw 1/1 Running 0 22m 147 | openfaas queue-worker-5ffdf7b57-zssj6 1/1 Running 1 22m 148 | openfaas alertmanager-65fd77874c-xrmxx 1/1 Running 0 22m 149 | openfaas prometheus-9c9c8447b-dwnfz 1/1 Running 0 22m 150 | openfaas gateway-76fd4f4cf8-thdhb 2/2 Running 0 22m 151 | openfaas-fn certinfo-68f7b4f848-db8nq 1/1 Running 0 21m 152 | openfaas-fn figlet-54647f7fc6-r789k 1/1 Running 0 21m 153 | openfaas-fn nodeinfo-768577f7b5-6fg7x 1/1 Running 0 21m 154 | openfaas faas-idler-7579b574df-bzj66 1/1 Running 3 22m 155 | ``` 156 | 157 | ## Test openfaas 158 | 159 | * figlet 160 | ``` 161 | echo 'Got eem' | faas-cli invoke figlet --gateway http://127.0.0.1:31112 162 | ____ _ 163 | / ___| ___ | |_ ___ ___ _ __ ___ 164 | | | _ / _ \| __| / _ \/ _ \ '_ ` _ \ 165 | | |_| | (_) | |_ | __/ __/ | | | | | 166 | \____|\___/ \__| \___|\___|_| |_| |_| 167 | 168 | ``` 169 | 170 | * certinfo 171 | ``` 172 | curl http://127.0.0.1:31112/function/certinfo -d "google.com" 173 | Host 172.217.1.206 174 | Port 443 175 | Issuer GTS CA 1O1 176 | CommonName *.google.com 177 | NotBefore 2020-04-28 07:43:41 +0000 UTC 178 | NotAfter 2020-07-21 07:43:41 +0000 UTC 179 | SANs [*.google.com *.android.com *.appengine.google.com *.bdn.dev *.cloud.google.com *.crowdsource.google.com *.g.co *.gcp.gvt2.com *.gcpcdn.gvt1.com *.ggpht.cn *.gkecnapps.cn *.google-analytics.com *.google.ca *.google.cl *.google.co.in *.google.co.jp *.google.co.uk *.google.com.ar *.google.com.au *.google.com.br *.google.com.co *.google.com.mx *.google.com.tr *.google.com.vn *.google.de *.google.es *.google.fr *.google.hu *.google.it *.google.nl *.google.pl *.google.pt *.googleadapis.com *.googleapis.cn *.googlecnapps.cn *.googlecommerce.com *.googlevideo.com *.gstatic.cn *.gstatic.com *.gstaticcnapps.cn *.gvt1.com *.gvt2.com *.metric.gstatic.com *.urchin.com *.url.google.com *.wear.gkecnapps.cn *.youtube-nocookie.com *.youtube.com *.youtubeeducation.com *.youtubekids.com *.yt.be *.ytimg.com android.clients.google.com android.com developer.android.google.cn developers.android.google.cn g.co ggpht.cn gkecnapps.cn goo.gl google-analytics.com google.com googlecnapps.cn googlecommerce.com source.android.google.cn urchin.com www.goo.gl youtu.be youtube.com youtubeeducation.com youtubekids.com yt.be] 180 | ``` 181 | 182 | * nodeinfo 183 | ``` 184 | echo -n verbose | faas-cli invoke nodeinfo --gateway 127.0.0.1:31112 185 | Hostname: nodeinfo-768577f7b5-6fg7x 186 | 187 | Arch: arm 188 | CPUs: 4 189 | Total mem: 3823MB 190 | Platform: linux 191 | Uptime: 1721 192 | [ 193 | { 194 | .. 195 | .. 196 | ``` 197 | -------------------------------------------------------------------------------- /Ubuntu/container_toolkit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # https://linuxconfig.org/how-to-install-kubernetes-on-ubuntu-20-04-focal-fossa-linux 4 | 5 | ######################################################################### 6 | # Automate the container install process. # 7 | # # 8 | # Install Kubernetes, Docker, and Rancher # 9 | ######################################################################### 10 | 11 | function _run_as_root() { 12 | # Run as root 13 | if [[ $(id -u) != 0 ]]; then 14 | echo 'Must be ran as root.' 15 | exit 16 | fi 17 | } 18 | 19 | function _help_menu() { 20 | # Help menu 21 | echo '[*] Help Menu:' 22 | echo '' 23 | echo '[*] --master-calico Install Kubernetes MASTER NODE Calico and Docker.' 24 | echo ' bash container_toolkit.sh --master-calico' 25 | echo '' 26 | echo '[*] --worker-node Install Kubernetes WORKER NODE and Docker' 27 | echo ' bash container_toolkit.sh --worker-node' 28 | echo '' 29 | echo '[*] --docker Install ONLY Docker.' 30 | echo ' bash container_toolkit.sh --docker' 31 | echo '' 32 | echo '[*] --rancher Install a ONLY Rancher constainer.' 33 | echo ' bash container_toolkit.sh --rancher' 34 | echo '' 35 | echo '[*] --helm Apply this option to install helm.' 36 | echo ' bash container_toolkit.sh --helm' 37 | echo '' 38 | echo '[*] --clean Clean up Kubernetes WORKER NODES. Typically we should not need this.' 39 | echo ' bash container_toolkit.sh --clean' 40 | echo '' 41 | exit 42 | } 43 | 44 | 45 | function cleanup_docker() { 46 | # Cleanup any currently installed docker package. 47 | echo '[*] Removing old Docker packages.' 48 | sudo apt remove docker docker-engine docker.io containerd runc -y 49 | } 50 | 51 | function install_dependencies() { 52 | # Setup packages for docker. 53 | echo '[*] Installing packages to support Docker.' 54 | sudo apt update -y 55 | sudo apt install apt-transport-https ca-certificates curl gnupg gnupg2 software-properties-common nfs-common -y 56 | } 57 | 58 | function docker_install_script(){ 59 | curl -fsSL https://get.docker.com -o get-docker.sh 60 | sudo sh ./get-docker.sh --dry-run 61 | } 62 | 63 | function set_hostname() { 64 | echo "$(ip a | grep enp -A1 | grep inet | awk '{print $2}' | sed 's/\/24//g')" "$(hostnamectl --static)" >> /etc/hosts 65 | } 66 | 67 | function disable_swap() { 68 | # Disable swap and comment out from /etc/fstab 69 | echo '[*] Disabling SWAP and commenting out fstab.' 70 | /sbin/swapoff -av 71 | edit_swap=$(cat /etc/fstab | awk '{print $1}' | grep swap) 72 | sed -i "s|$edit_swap|#$edit_swap|g" /etc/fstab 73 | cat /etc/fstab | grep swap 74 | } 75 | 76 | function load_kernel_modules() { 77 | sudo tee /etc/modules-load.d/containerd.conf < /dev/null 99 | sudo apt-get update -y 100 | } 101 | 102 | function install_docker_packages(){ 103 | sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y 104 | sudo docker run hello-world 105 | } 106 | 107 | function install_containerd(){ 108 | sudo apt update -y 109 | sudo apt install -y containerd.io 110 | } 111 | 112 | function containerd_use_systemd(){ 113 | containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1 114 | sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml 115 | } 116 | 117 | function restart_enable_containerd(){ 118 | sudo systemctl restart containerd 119 | sudo systemctl enable containerd 120 | } 121 | 122 | function add_kubernetes_repo(){ 123 | curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg 124 | sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg 125 | echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list 126 | sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list 127 | } 128 | 129 | function install_kube_commands(){ 130 | sudo apt update -y 131 | sudo apt install -y kubelet kubeadm kubectl 132 | sudo apt-mark hold kubelet kubeadm kubectl 133 | } 134 | 135 | function restart_kubelet_services(){ 136 | sudo systemctl restart kubelet.service 137 | sudo systemctl enable kubelet.service 138 | } 139 | 140 | function init_kubernetes_images(){ 141 | sudo kubeadm config images pull 142 | } 143 | 144 | function api_server_master_calico() { 145 | # Beginning of Master node setup. 146 | echo '[*] Starting Master node.' 147 | #kubeadm init --pod-network-cidr=192.168.0.0/16 148 | kubeadm init --pod-network-cidr=10.96.0.0/16 149 | mkdir -p $HOME/.kube 150 | sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config 151 | sudo chown $(id -u):$(id -g) $HOME/.kube/config 152 | } 153 | 154 | function install_calico_network_policy() { 155 | # Install the calico pod network. 156 | #curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml -O 157 | #sed -i -e "s?192.168.0.0?10.96.0.0?g" calico.yaml 158 | #kubectl apply -f calico.yaml 159 | #echo '[*] Check pods with "kubectl get pods --all-namespaces". Once done, install --helm.' 160 | #kubectl get pods --all-namespaces 161 | curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.3/manifests/tigera-operator.yaml -O 162 | curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.3/manifests/custom-resources.yaml -O 163 | kubectl create -f tigera-operator.yaml 164 | sed -i 's/cidr: 192\.168\.0\.0\/16/cidr: 10.96.0.0\/16/g' custom-resources.yaml 165 | kubectl create -f custom-resources.yaml 166 | } 167 | 168 | function install_calicoctl() { 169 | echo '[*] Installing calicoctl as a pod' 170 | # etcd: 171 | #kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.3/manifests/calicoctl-etcd.yaml 172 | # K8s API datastore: 173 | kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.3/manifests/calicoctl.yaml 174 | kubectl exec -ti -n kube-system calicoctl -- /calicoctl get profiles -o wide 175 | } 176 | 177 | function set_felix_loose_true() { 178 | echo '[*] Ignoring loose RPF for Felix.' 179 | kubectl -n kube-system set env daemonset/calico-node FELIX_IGNORELOOSERPF=true 180 | } 181 | 182 | function install_rancher() { 183 | # Install Rancher on master kubernetes host. 184 | sudo docker run --privileged -d --restart=unless-stopped -p 80:80 -p 443:443 rancher/rancher 185 | } 186 | 187 | function cleanup_workers() { 188 | # Cleanup workers for Rancher. 189 | docker rm -f $(docker ps -qa) 190 | docker volume rm $(docker volume ls -q) 191 | cleanupdirs="/var/lib/etcd /etc/kubernetes /etc/cni /opt/cni /var/lib/cni /var/run/calico /opt/rke" 192 | for dir in $cleanupdirs; do 193 | echo "Removing $dir" 194 | rm -rf $dir 195 | done 196 | } 197 | 198 | function install_helm_three(){ 199 | curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null 200 | sudo apt-get install apt-transport-https -y 201 | echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list 202 | sudo apt-get update -y 203 | sudo apt-get install helm -y 204 | } 205 | 206 | ################################ 207 | # ***Notes 208 | # Patch a Service to external Node port like so: (Good for on prem) 209 | # kubectl patch service nginx-ingress-controller -p '{"spec":{"externalIPs":["192.168.1.101"]}}' 210 | # This will not be HA though 211 | 212 | ############################ 213 | # Functions to be executed # 214 | ############################ 215 | 216 | 217 | case "$1" in 218 | --docker) 219 | _run_as_root 220 | cleanup_docker 221 | install_dependencies 222 | docker_install_script 223 | ;; 224 | --master-calico) 225 | _run_as_root 226 | cleanup_docker 227 | install_dependencies 228 | set_hostname 229 | disable_swap 230 | load_kernel_modules 231 | update_bridge 232 | enable_docker_repo 233 | install_docker_packages 234 | install_containerd 235 | containerd_use_systemd 236 | restart_enable_containerd 237 | add_kubernetes_repo 238 | install_kube_commands 239 | restart_kubelet_services 240 | init_kubernetes_images 241 | api_server_master_calico 242 | install_calico_network_policy 243 | install_calicoctl 244 | set_felix_loose_true 245 | ;; 246 | --worker-node) 247 | _run_as_root 248 | cleanup_docker 249 | install_dependencies 250 | set_hostname 251 | disable_swap 252 | load_kernel_modules 253 | update_bridge 254 | enable_docker_repo 255 | install_docker_packages 256 | install_containerd 257 | containerd_use_systemd 258 | restart_enable_containerd 259 | add_kubernetes_repo 260 | install_kube_commands 261 | ;; 262 | --helm) 263 | _run_as_root 264 | install_helm_three 265 | ;; 266 | --rancher) 267 | _run_as_root 268 | cleanup_docker 269 | install_dependencies 270 | set_hostname 271 | docker_install_script 272 | install_rancher 273 | ;; 274 | --clean) 275 | echo 'Needs Testing' 276 | exit 277 | _run_as_root 278 | cleanup_workers 279 | ;; 280 | -h) 281 | _help_menu 282 | ;; 283 | --help) 284 | _help_menu 285 | ;; 286 | *) 287 | _help_menu 288 | ;; 289 | esac 290 | -------------------------------------------------------------------------------- /cert-manager/README.md: -------------------------------------------------------------------------------- 1 | Install Metallb, then Traefik first, then move forward with cert-manager 2 | 3 | helm repo add jetstack https://charts.jetstack.io --force-update 4 | 5 | helm install \ 6 | cert-manager jetstack/cert-manager \ 7 | --namespace cert-manager \ 8 | --create-namespace \ 9 | --version v1.16.2 \ 10 | --set crds.enabled=true 11 | 12 | Now define cluster issuers for certs: 13 | 14 | kubectl apply -f selfsigned-cluster-issuer.yaml 15 | kubectl apply -f letsencrypt-staging-issuer.yaml 16 | kubectl apply -f letsencrypt-prod-issuer.yaml 17 | 18 | 19 | If using on AWS, expect this to fail if using a custom CNI (anything other than AWS' CNI). Just use AWS CNI if you need Let's Encrypt 20 | -------------------------------------------------------------------------------- /cert-manager/letsencrypt-prod-issuer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: ClusterIssuer 3 | metadata: 4 | name: letsencrypt-prod 5 | spec: 6 | acme: 7 | # You must replace this email address with your own. 8 | # Let's Encrypt will use this to contact you about expiring 9 | # certificates, and issues related to your account. 10 | email: user@gmail.com 11 | server: https://acme-v02.api.letsencrypt.org/directory 12 | privateKeySecretRef: 13 | # Secret resource that will be used to store the account's private key. 14 | name: prod-issuer-account-key 15 | # Add a single challenge solver, HTTP01 using nginx 16 | solvers: 17 | - http01: 18 | ingress: 19 | class: traefik 20 | 21 | -------------------------------------------------------------------------------- /cert-manager/letsencrypt-staging-issuer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: ClusterIssuer 3 | metadata: 4 | name: letsencrypt-staging 5 | spec: 6 | acme: 7 | # You must replace this email address with your own. 8 | # Let's Encrypt will use this to contact you about expiring 9 | # certificates, and issues related to your account. 10 | email: user@gmail.com 11 | server: https://acme-staging-v02.api.letsencrypt.org/directory 12 | privateKeySecretRef: 13 | # Secret resource that will be used to store the account's private key. 14 | name: staging-issuer-account-key 15 | # Add a single challenge solver, HTTP01 using nginx 16 | solvers: 17 | - http01: 18 | ingress: 19 | class: traefik 20 | 21 | -------------------------------------------------------------------------------- /cert-manager/selfsigned-cluster-issuer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: Issuer 3 | metadata: 4 | name: selfsigned-issuer 5 | namespace: sandbox 6 | namespace: cert-manager 7 | spec: 8 | selfSigned: {} 9 | --- 10 | apiVersion: cert-manager.io/v1 11 | kind: ClusterIssuer 12 | metadata: 13 | name: selfsigned-cluster-issuer 14 | spec: 15 | selfSigned: {} 16 | --- 17 | apiVersion: v1 18 | kind: Namespace 19 | metadata: 20 | name: sandbox 21 | --- 22 | apiVersion: cert-manager.io/v1 23 | kind: ClusterIssuer 24 | metadata: 25 | name: selfsigned-issuer 26 | spec: 27 | selfSigned: {} 28 | --- 29 | apiVersion: cert-manager.io/v1 30 | kind: Certificate 31 | metadata: 32 | name: my-selfsigned-ca 33 | namespace: sandbox 34 | spec: 35 | isCA: true 36 | commonName: my-selfsigned-ca 37 | secretName: root-secret 38 | privateKey: 39 | algorithm: ECDSA 40 | size: 256 41 | issuerRef: 42 | name: selfsigned-issuer 43 | kind: ClusterIssuer 44 | group: cert-manager.io 45 | --- 46 | apiVersion: cert-manager.io/v1 47 | kind: Issuer 48 | metadata: 49 | name: my-ca-issuer 50 | namespace: sandbox 51 | spec: 52 | ca: 53 | secretName: root-secret 54 | 55 | -------------------------------------------------------------------------------- /docker-registry/README.md: -------------------------------------------------------------------------------- 1 | * Required for htpasswd 2 | sudo apt install apache2-utils -y 3 | 4 | * get your password and base64 5 | htpasswd -Bc htpasswd registry 6 | echo username:password | base64 7 | -------------------------------------------------------------------------------- /docker-registry/full_deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: docker-registry-ns 5 | --- 6 | apiVersion: v1 7 | data: 8 | htpasswd: {{ Get this from README.md }} 9 | kind: Secret 10 | metadata: 11 | name: docker-registry-htpasswd 12 | namespace: docker-registry-ns 13 | type: Opaque 14 | --- 15 | # Create PersistentVolume 16 | # change the ip of NFS server 17 | apiVersion: v1 18 | kind: PersistentVolume 19 | metadata: 20 | name: docker-registry-storage-pv 21 | namespace: docker-registry-ns 22 | labels: 23 | type: local 24 | spec: 25 | storageClassName: manual 26 | capacity: 27 | storage: 50Gi 28 | accessModes: 29 | - ReadWriteOnce 30 | hostPath: 31 | path: /mnt/kubernetes/docker-registry/registry 32 | --- 33 | apiVersion: v1 34 | kind: PersistentVolumeClaim 35 | metadata: 36 | name: docker-registry-storage-pvc 37 | namespace: docker-registry-ns 38 | spec: 39 | storageClassName: manual 40 | accessModes: 41 | - ReadWriteOnce 42 | resources: 43 | requests: 44 | storage: 50Gi 45 | --- 46 | apiVersion: apps/v1 47 | kind: Deployment 48 | metadata: 49 | name: docker-registry 50 | namespace: docker-registry-ns 51 | labels: 52 | app: docker-registry 53 | spec: 54 | replicas: 1 55 | selector: 56 | matchLabels: 57 | app: docker-registry 58 | template: 59 | metadata: 60 | labels: 61 | app: docker-registry 62 | spec: 63 | containers: 64 | - name: docker-registry 65 | image: registry 66 | ports: 67 | - containerPort: 5000 68 | volumeMounts: 69 | - name: docker-registry-storage-pv 70 | mountPath: /var/lib/registry 71 | - name: htpasswd 72 | mountPath: /mnt/kubernetes/docker-registry/auth 73 | readOnly: true 74 | env: 75 | - name: REGISTRY_AUTH 76 | value: htpasswd 77 | - name: REGISTRY_AUTH_HTPASSWD_REALM 78 | value: Docker Registry 79 | - name: REGISTRY_AUTH_HTPASSWD_PATH 80 | value: /mnt/kubernetes/docker-registry/auth/htpasswd 81 | - name: REGISTRY_STORAGE_DELETE_ENABLED 82 | value: "true" 83 | volumes: 84 | - name: docker-registry-storage-pv 85 | persistentVolumeClaim: 86 | claimName: docker-registry-storage-pvc 87 | - name: htpasswd 88 | secret: 89 | secretName: docker-registry-htpasswd 90 | restartPolicy: Always 91 | --- 92 | apiVersion: v1 93 | kind: Service 94 | metadata: 95 | name: docker-registry-service 96 | namespace: docker-registry-ns 97 | spec: 98 | selector: 99 | app: docker-registry 100 | ports: 101 | - protocol: TCP 102 | port: 5000 103 | --- 104 | #apiVersion: extensions/v1beta1 105 | apiVersion: networking.k8s.io/v1 106 | kind: Ingress 107 | metadata: 108 | name: docker-registry-ingress 109 | namespace: docker-registry-ns 110 | annotations: 111 | #kubernetes.io/ingress.class: "traefik" 112 | acme.cert-manager.io/http01-edit-in-place: "true" 113 | #cert-manager.io/cluster-issuer: letsencrypt-prod 114 | cert-manager.io/cluster-issuer: letsencrypt-staging 115 | traefik.ingress.kubernetes.io/frontend-entry-points: http, https 116 | traefik.ingress.kubernetes.io/redirect-entry-point: https 117 | spec: 118 | ingressClassName: "traefik" 119 | rules: 120 | - host: registry.yourdomain.com 121 | http: 122 | paths: 123 | - path: / 124 | pathType: Prefix 125 | backend: 126 | service: 127 | name: docker-registry-service 128 | port: 129 | number: 5000 130 | tls: 131 | - hosts: 132 | - registry.yourdomain.com 133 | secretName: docker-registry-tls 134 | --- 135 | apiVersion: traefik.io/v1alpha1 136 | kind: IngressRoute 137 | metadata: 138 | name: registry-ingressroute 139 | namespace: docker-registry-ns 140 | spec: 141 | entryPoints: 142 | - websecure 143 | routes: 144 | - match: Host(`registry.yourdomain.com`) 145 | kind: Rule 146 | services: 147 | - name: docker-registry-service 148 | port: 5000 149 | tls: 150 | certResolver: letsencrypt 151 | -------------------------------------------------------------------------------- /metallb/layer2-conf.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: metallb.io/v1beta1 2 | kind: IPAddressPool 3 | metadata: 4 | name: first-pool 5 | namespace: metallb-system 6 | spec: 7 | addresses: 8 | - 192.168.1.240-192.168.1.250 9 | --- 10 | apiVersion: metallb.io/v1beta1 11 | kind: L2Advertisement 12 | metadata: 13 | name: example 14 | namespace: metallb-system 15 | -------------------------------------------------------------------------------- /metallb/metallb-notes.txt: -------------------------------------------------------------------------------- 1 | https://metallb.universe.tf/installation/ 2 | Create the deployment 3 | kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml 4 | kubectl apply -f layer2-conf.yaml 5 | -------------------------------------------------------------------------------- /metallb/nginx-metallb.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: nginx-test-deployment 5 | --- 6 | apiVersion: apps/v1 7 | kind: Deployment 8 | metadata: 9 | name: nginx-deployment 10 | namespace: nginx-test-deployment 11 | labels: 12 | app: nginx 13 | spec: 14 | replicas: 1 15 | selector: 16 | matchLabels: 17 | app: nginx 18 | template: 19 | metadata: 20 | labels: 21 | app: nginx 22 | spec: 23 | containers: 24 | - name: nginx 25 | image: nginx:1.14.2 26 | ports: 27 | - containerPort: 80 28 | --- 29 | apiVersion: v1 30 | kind: Service 31 | metadata: 32 | name: example-service 33 | namespace: nginx-test-deployment 34 | spec: 35 | selector: 36 | app: nginx 37 | ports: 38 | - port: 80 39 | targetPort: 80 40 | type: LoadBalancer 41 | -------------------------------------------------------------------------------- /notes/docker-containers-to-k8s-pods.txt: -------------------------------------------------------------------------------- 1 | >>> Visual instructions: 2 | https://www.youtube.com/watch?v=r15S2tBevoE 3 | 4 | 5 | >>> Prerequisits 6 | 7 | [*] docker-compose must be installed on Master 8 | yum install epel-release -y 9 | yum update -y 10 | yum install docker-compose -y 11 | 12 | [*] docker-compose files for private registry 13 | https://github.com/justmeandopensource/docker/tree/master/docker-compose-files/docker-registry 14 | 15 | 16 | [*] Install Apache for the htttpd option: 17 | yum install httpd -y 18 | 19 | [*] Create directories on kube-master and worker nodes 20 | mkdir -p /mnt/docker-registry/certs 21 | 22 | If you have Ansible, run this to push to all of your k8s hosts, Master and Workers: 23 | ansible -m shell -a "mkdir -p /mnt/docker-registry/certs" k8s-lab-hosts 24 | 25 | [*] Create the auth directory: 26 | mkdir -p /mnt/docker-registry/auth 27 | 28 | If you have Ansible, run this to push to all of your k8s hosts, Master and Workers: 29 | ansible -m shell -a "mkdir -p /mnt/docker-registry/auth" k8s-lab-hosts 30 | 31 | [*] You need the following in your /etc/docker/daemon.json file on Master and Worker nodes 32 | {"insecure-registries": ["host-OR-ip:port"]} 33 | 34 | Example: 35 | { 36 | "exec-opts": ["native.cgroupdriver=systemd"], 37 | "log-driver": "json-file", 38 | "log-opts": { 39 | "max-size": "100m" 40 | }, 41 | "storage-driver": "overlay2", 42 | "storage-opts": [ 43 | "overlay2.override_kernel_check=true" 44 | ], 45 | "insecure-registries": ["192,168.1.200:5000"] 46 | } 47 | 48 | [*] Create the openssl.conf file in any directory that you want, Update as needed: 49 | 50 | [ req ] 51 | distinguished_name = req_distinguished_name 52 | x509_extensions = req_ext 53 | default_md = sha256 54 | prompt = no 55 | encrypt_key = no 56 | 57 | [ req_distinguished_name ] 58 | countryName = "GB" 59 | localityName = "London" 60 | organizationName = "Just Me and Opensource" 61 | organizationalUnitName = "YouTube" 62 | commonName = "" 63 | emailAddress = "test@example.com" 64 | 65 | [ req_ext ] 66 | subjectAltName = @alt_names 67 | 68 | [alt_names] 69 | DNS = "" 70 | 71 | 72 | [*] Generate a certificate: 73 | openssl req -x509 -newkey rsa:4096 -days 365 -config openssl.conf -keyout /mnt/docker-registry/certs/domain.key -out /mnt/docker-registry/certs/domain.crt 74 | 75 | [*] Verify your cert: 76 | openssl x509 -text -noout -in /mnt/docker-registry/certs/domain.crt 77 | 78 | [*] Create user and password for access to docker registry: 79 | htpasswd -Bbn docker-user docker-password > /mnt/docker-registry/auth/htpasswd # USE your own user and password!! 80 | 81 | [*] Enable port 5000 in firewalld. 82 | firewall-cmd --permanent --add-port=5000/tcp 83 | firewall-cmd --reload 84 | 85 | 86 | >>> Rough Guidelines on creating an internal registry 87 | 88 | ** Side note, you can run this in a separate terminal to watch for failues. Great for debugging: 89 | kubectl get events -w 90 | 91 | [*] Use the correct docker-compose file you need (Use 03 for TLS and authentication). 92 | Change the file name to: 93 | "docker-compose.yaml" 94 | On the master node, run the following to create your registry: 95 | "docker-compose up -d" 96 | You now have a running registry. 97 | 98 | [*] Login to your registry: 99 | docker login 192.168.1.200:5000 100 | Username: docker-user 101 | Password: 102 | WARNING! Your password will be stored unencrypted in /root/.docker/config.json. 103 | Configure a credential helper to remove this warning. See 104 | https://docs.docker.com/engine/reference/commandline/login/#credentials-store 105 | 106 | Login Succeeded 107 | 108 | If you do not login, you should see: 109 | docker pull 192.168.1.200:5000/mydebian:v1 110 | Error response from daemon: Get http://192.168.1.200:5000/v2/: net/http: HTTP/1.x transport connection broken: malformed HTTP response "\x15\x03\x01\x00\x02\x02" 111 | 112 | [*] Pull your image: 113 | docker pull 192.168.1.200:5000/mydebian:v1 114 | v1: Pulling from mydebian 115 | 7e2b2a5af8f6: Already exists 116 | Digest: sha256:810e68a830ba42daa245ad973d516222c6c8256b7e82f3a70274deb67b4b5238 117 | Status: Downloaded newer image for 192.168.1.200:5000/mydebian:v1 118 | 192.168.1.200:5000/mydebian:v1 119 | 120 | 121 | [*] To use an image from this registry to create a pod, add an image like so: 122 | Build the image and push to registry: 123 | docker build -t :5000/mydebian:v1 . 124 | docker push :5000/mydebian:v1 125 | 126 | [*] Log into the registry from kuberenetes by creating a secret: 127 | kubectl create secret docker-registry mydockercredentials --docker-server 192.168.1.200:5000 --docker-username docker-username --docker-password docker-password 128 | 129 | [*] Generate the yaml for editing: 130 | kubectl run mytest --image 192.168.1.200:5000/mydebian:v2 --image-pull-policy Always --dry-run -o yaml > /tmp/mydebian.yaml 131 | Add your secret, example: 132 | vi /tmp/mydebian.yaml 133 | apiVersion: v1 134 | kind: Pod 135 | metadata: 136 | creationTimestamp: null 137 | labels: 138 | run: mytest 139 | name: mytest 140 | spec: 141 | containers: 142 | - image: 192.168.1.200:5000/mydebian:v2 143 | imagePullPolicy: Always 144 | name: mytest 145 | resources: {} 146 | imagePullSecrets: 147 | - name: mydockercredentials 148 | dnsPolicy: ClusterFirst 149 | restartPolicy: Always 150 | status: {} 151 | 152 | [*] Create the pod: 153 | kubectl create -f /tmp/mydebian.yaml 154 | 155 | [*] Congrats! Pod Deployed! 156 | -------------------------------------------------------------------------------- /prometheus_grafana/README.md: -------------------------------------------------------------------------------- 1 | After Traefik is up and running, clone and install prometheus with grafana. Make sure to update the service file to route through Traefik 2 | 3 | git clone https://github.com/prometheus-operator/kube-prometheus.git 4 | 5 | 6 | New service file kube-prometheus/manifests/grafana-service.yaml 7 | 8 | apiVersion: v1 9 | kind: Service 10 | metadata: 11 | labels: 12 | app.kubernetes.io/component: grafana 13 | app.kubernetes.io/name: grafana 14 | app.kubernetes.io/part-of: kube-prometheus 15 | app.kubernetes.io/version: 10.2.0 16 | name: grafana 17 | namespace: monitoring 18 | spec: 19 | ports: 20 | - name: http 21 | port: 3000 22 | targetPort: http 23 | selector: 24 | app.kubernetes.io/component: grafana 25 | app.kubernetes.io/name: grafana 26 | app.kubernetes.io/part-of: kube-prometheus 27 | --- 28 | apiVersion: networking.k8s.io/v1 29 | kind: Ingress 30 | metadata: 31 | name: grafana-ingress 32 | namespace: monitoring 33 | annotations: 34 | kubernetes.io/ingress.class: "traefik" 35 | acme.cert-manager.io/http01-edit-in-place: "true" 36 | #cert-manager.io/cluster-issuer: letsencrypt-prod 37 | cert-manager.io/cluster-issuer: letsencrypt-staging 38 | traefik.ingress.kubernetes.io/frontend-entry-points: http, https 39 | traefik.ingress.kubernetes.io/redirect-entry-point: https 40 | spec: 41 | rules: 42 | - host: grafana.example.com 43 | http: 44 | paths: 45 | - path: / 46 | pathType: Prefix 47 | backend: 48 | service: 49 | name: grafana 50 | port: 51 | number: 3000 52 | tls: 53 | - hosts: 54 | - grafana.example.com 55 | secretName: grafana-example-com-tls 56 | --- 57 | apiVersion: traefik.containo.us/v1alpha1 58 | kind: IngressRoute 59 | metadata: 60 | name: grafana-ingress-route 61 | namespace: monitoring 62 | spec: 63 | entryPoints: 64 | - websecure 65 | routes: 66 | - match: Host(`grafana.example.com`) 67 | kind: Rule 68 | services: 69 | - name: grafana 70 | port: 3000 71 | tls: 72 | certResolver: traefik 73 | 74 | 75 | View the README for most recent way to install: 76 | https://github.com/prometheus-operator/kube-prometheus 77 | 78 | TL;DR: 79 | kubectl apply --server-side -f manifests/setup 80 | kubectl wait \ 81 | --for condition=Established \ 82 | --all CustomResourceDefinition \ 83 | --namespace=monitoring 84 | kubectl apply -f manifests/ 85 | 86 | -------------------------------------------------------------------------------- /raspberry_pi/example_yaml_deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: project-namespace 5 | --- 6 | //Private Docker Registry Secret 7 | apiVersion: v1 8 | kind: Secret 9 | metadata: 10 | name: myregistrykey 11 | namespace: project-namespace 12 | data: 13 | .dockerconfigjson: {{ BASE64 OUTPUT OF ~/.docker/config.json }} 14 | type: kubernetes.io/dockerconfigjson 15 | --- 16 | // SQL Root Password 17 | apiVersion: v1 18 | kind: Secret 19 | metadata: 20 | name: mysql-root-secret 21 | namespace: project-namespace 22 | type: Opaque 23 | data: 24 | password: {{ BASE64 OUTPUT OF PASSWORD }} 25 | --- 26 | // SQL db's, user, and password 27 | apiVersion: v1 28 | kind: Secret 29 | metadata: 30 | name: mysql-db-secret 31 | namespace: project-namespace 32 | type: Opaque 33 | data: 34 | username: {{ BASE64 OUTPUT OF DB USERNAME }} 35 | password: {{ BASE64 OUTPUT OF DB PASSWORD }} 36 | database-one: {{ BASE64 OUTPUT OF DATABASE NAME 1 }} 37 | database-two: {{ BASE64 OUTPUT OF DATABASE NAME 2 }} 38 | --- 39 | apiVersion: v1 40 | kind: Service 41 | metadata: 42 | name: first-db-service # MARK B 43 | namespace: project-namespace 44 | spec: 45 | type: ClusterIP 46 | ports: 47 | - port: 3306 48 | targetPort: 3306 49 | protocol: TCP 50 | selector: 51 | app: mariadb-first-db-deploy # Must match with `MARK A` 52 | --- 53 | apiVersion: v1 54 | kind: PersistentVolume 55 | metadata: 56 | name: mariadb-storage-db-one 57 | namespace: project-namespace 58 | labels: 59 | type: local 60 | spec: 61 | storageClassName: manual 62 | capacity: 63 | storage: 10Gi 64 | accessModes: 65 | - ReadWriteOnce 66 | hostPath: 67 | path: /path/to/nfs/mount 68 | --- 69 | apiVersion: v1 70 | kind: PersistentVolumeClaim 71 | metadata: 72 | name: mariadb-storage-db-one 73 | namespace: project-namespace 74 | spec: 75 | storageClassName: manual 76 | accessModes: 77 | - ReadWriteOnce 78 | resources: 79 | requests: 80 | storage: 8Gi 81 | --- 82 | apiVersion: apps/v1 83 | kind: Deployment 84 | metadata: 85 | namespace: project-namespace 86 | name: mariadb-first-db-deploy # MARK A 87 | labels: 88 | app: mariadb-first-db-deploy # MARK A 89 | spec: 90 | replicas: 1 91 | selector: 92 | matchLabels: 93 | app: mariadb-first-db-deploy # MARK A 94 | template: 95 | metadata: 96 | labels: 97 | app: mariadb-first-db-deploy # MARK A 98 | spec: 99 | containers: 100 | - name: mariadb-first-db-deploy 101 | image: example-private.registry.com/mariadb:latest 102 | env: 103 | - name: MYSQL_ROOT_PASSWORD 104 | valueFrom: 105 | secretKeyRef: 106 | name: mysql-root-secret # MARK P 107 | key: password 108 | - name: MYSQL_DATABASE 109 | valueFrom: 110 | secretKeyRef: 111 | name: mysql-db-secret 112 | key: database-one 113 | - name: MYSQL_USER 114 | valueFrom: 115 | secretKeyRef: 116 | name: mysql-db-secret 117 | key: username 118 | - name: MYSQL_PASSWORD 119 | valueFrom: 120 | secretKeyRef: 121 | name: mysql-db-secret 122 | key: password 123 | imagePullPolicy: IfNotPresent 124 | ports: 125 | - containerPort: 3306 126 | volumeMounts: 127 | - name: mariadb-persistent-storage-db-one 128 | mountPath: /var/lib/mysql 129 | imagePullPolicy: IfNotPresent 130 | restartPolicy: Always 131 | volumes: 132 | - name: mariadb-persistent-storage-db-one 133 | persistentVolumeClaim: 134 | claimName: mariadb-storage-db-one # MARK Z 135 | imagePullSecrets: 136 | - name: myregistrykey 137 | --- 138 | apiVersion: v1 139 | kind: Service 140 | metadata: 141 | name: second-db-service # MARK B 142 | namespace: project-namespace 143 | spec: 144 | type: ClusterIP 145 | ports: 146 | - port: 3306 147 | targetPort: 3306 148 | protocol: TCP 149 | selector: 150 | app: mariadb-second-db-deploy # Must match with `MARK A` 151 | --- 152 | apiVersion: v1 153 | kind: PersistentVolume 154 | metadata: 155 | name: mariadb-storage-db-two 156 | namespace: project-namespace 157 | labels: 158 | type: local 159 | spec: 160 | storageClassName: manual 161 | capacity: 162 | storage: 10Gi 163 | accessModes: 164 | - ReadWriteOnce 165 | hostPath: 166 | path: /path/to/nfs/mount 167 | --- 168 | apiVersion: v1 169 | kind: PersistentVolumeClaim 170 | metadata: 171 | name: mariadb-storage-db-two 172 | namespace: project-namespace 173 | spec: 174 | storageClassName: manual 175 | accessModes: 176 | - ReadWriteOnce 177 | resources: 178 | requests: 179 | storage: 8Gi 180 | --- 181 | apiVersion: apps/v1 182 | kind: Deployment 183 | metadata: 184 | namespace: project-namespace 185 | name: mariadb-second-db-deploy # MARK A 186 | labels: 187 | app: mariadb-second-db-deploy # MARK A 188 | spec: 189 | replicas: 1 190 | selector: 191 | matchLabels: 192 | app: mariadb-second-db-deploy # MARK A 193 | template: 194 | metadata: 195 | labels: 196 | app: mariadb-second-db-deploy # MARK A 197 | spec: 198 | containers: 199 | - name: mariadb-second-db-deploy 200 | image: example-private.registry.com/mariadb:latest 201 | env: 202 | - name: MYSQL_ROOT_PASSWORD 203 | valueFrom: 204 | secretKeyRef: 205 | name: mysql-root-secret # MARK P 206 | key: password 207 | - name: MYSQL_DATABASE 208 | valueFrom: 209 | secretKeyRef: 210 | name: mysql-db-secret 211 | key: database-two 212 | - name: MYSQL_USER 213 | valueFrom: 214 | secretKeyRef: 215 | name: mysql-db-secret 216 | key: username 217 | - name: MYSQL_PASSWORD 218 | valueFrom: 219 | secretKeyRef: 220 | name: mysql-db-secret 221 | key: password 222 | imagePullPolicy: IfNotPresent 223 | ports: 224 | - containerPort: 3306 225 | volumeMounts: 226 | - name: mariadb-persistent-storage-db-two 227 | mountPath: /var/lib/mysql 228 | imagePullPolicy: IfNotPresent 229 | restartPolicy: Always 230 | volumes: 231 | - name: mariadb-persistent-storage-db-two 232 | persistentVolumeClaim: 233 | claimName: mariadb-storage-db-two # MARK Z 234 | imagePullSecrets: 235 | - name: myregistrykey 236 | --- 237 | apiVersion: v1 238 | kind: Service 239 | metadata: 240 | name: project-website-loadbalancer 241 | namespace: project-namespace 242 | spec: 243 | selector: 244 | app: project-namespace 245 | clusterIP: {{ IPV4 WITHIN KUBERNETES /16 NETWORK }} 246 | externalTrafficPolicy: Cluster 247 | ports: 248 | - name: http 249 | nodePort: 31105 250 | port: 80 251 | protocol: TCP 252 | targetPort: 80 253 | - name: https 254 | nodePort: 31106 255 | port: 443 256 | protocol: TCP 257 | targetPort: 443 258 | sessionAffinity: None 259 | type: NodePort 260 | status: 261 | loadBalancer: {} 262 | --- 263 | apiVersion: extensions/v1beta1 264 | kind: Ingress 265 | metadata: 266 | name: project-website-ingress 267 | namespace: project-namespace 268 | annotations: 269 | kubernetes.io/ingress.class: "nginx" 270 | cert-manager.io/cluster-issuer: {{ NAMESPACE OF CERT-MANAGER DEPLOYMENT }} 271 | spec: 272 | rules: 273 | - host: {{ your.domain.com }} 274 | http: 275 | paths: 276 | - path: / 277 | backend: 278 | serviceName: project-website 279 | servicePort: 80 280 | tls: 281 | - hosts: 282 | - your.domain.com 283 | secretName: your-domain-com-tls 284 | --- 285 | apiVersion: v1 286 | kind: Service 287 | metadata: 288 | name: project-website 289 | namespace: project-namespace 290 | spec: 291 | type: ClusterIP 292 | ports: 293 | - port: 80 294 | targetPort: 80 295 | selector: 296 | app: project-website 297 | --- 298 | apiVersion: apps/v1 299 | kind: Deployment 300 | metadata: 301 | name: project-website 302 | namespace: project-namespace 303 | spec: 304 | replicas: 1 305 | selector: 306 | matchLabels: 307 | app: project-website 308 | template: 309 | metadata: 310 | labels: 311 | app: project-website 312 | spec: 313 | containers: 314 | - name: project-website 315 | image: example-private.registry.com/website:latest 316 | env: 317 | - name: MYSQL_DB_HOST 318 | value: mariadb-first-db-deploy 319 | - name: MYSQL_ROOT_PASSWORD 320 | valueFrom: 321 | secretKeyRef: 322 | name: mysql-root-secret # MARK P 323 | key: password 324 | - name: MYSQL_DATABASE 325 | valueFrom: 326 | secretKeyRef: 327 | name: mysql-db-secret 328 | key: database-one 329 | - name: MYSQL_USER 330 | valueFrom: 331 | secretKeyRef: 332 | name: mysql-db-secret 333 | key: username 334 | - name: MYSQL_PASSWORD 335 | valueFrom: 336 | secretKeyRef: 337 | name: mysql-db-secret 338 | key: password 339 | imagePullPolicy: IfNotPresent 340 | ports: 341 | - containerPort: 80 342 | imagePullSecrets: 343 | - name: myregistrykey 344 | -------------------------------------------------------------------------------- /raspberry_pi/rpi_container_toolkit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ############################################ 4 | # Prepare and install k8's on raspberry pi # 5 | # Tested on Pi4b # 6 | ############################################ 7 | 8 | function run_as_root() { # Best to run as root 9 | if [[ $(/usr/bin/id -u) != 0 ]]; then 10 | /bin/echo '[*] Must be ran as root.' 11 | exit 12 | fi 13 | } 14 | 15 | function _help_menu() { 16 | # Help menu 17 | echo '[*] Help Menu:' 18 | echo '' 19 | #echo '[*] --init Run first on every pi! Then move on to --master OR --worker. TURNED OFF FOR NOW.' 20 | #echo ' bash rpi_container_toolkit.sh --init' 21 | # echo '' 22 | # echo '[*] --master Install full Kubernetes k8s MASTER NODE Calico and Docker. DOES NOT WORK' 23 | # echo ' bash rpi_container_toolkit.sh --master' 24 | # echo '' 25 | # echo '[*] --worker Install full Kubernetes k8s WORKER NODE and Docker. DOES NOT WORK' 26 | # echo ' bash rpi_container_toolkit.sh --worker' 27 | # echo '' 28 | echo '[*] --rancherk3s-master The generic k3s install for Master.' 29 | echo ' bash rpi_container_toolkit.sh --rancherk3s-master' 30 | echo '' 31 | echo '[*] --rancherk3s-worker The generic k3s install for Worker.' 32 | echo ' bash rpi_container_toolkit.sh --rancherk3s-worker' 33 | echo '' 34 | echo '' 35 | echo ' ###### FOR THE DOCKER USERS - use below options to install Docker instead of containerd ######' 36 | echo '' 37 | echo '' 38 | echo '[*] --rancherk3s-master-docker K3s install for Master but with Docker instead of containerd.' 39 | echo ' bash rpi_container_toolkit.sh --rancherk3s-master-docker' 40 | echo '' 41 | echo '[*] --rancherk3s-worker-docker K3s install for Worker but with Docker instead of containerd.' 42 | echo ' bash rpi_container_toolkit.sh --rancherk3s-worker-docker' 43 | echo '' 44 | echo '' 45 | echo ' >>> Use below to install frameworks known to work on k3s.' 46 | echo '' 47 | echo '[*] --helm-master Install Helm3 to Master' 48 | echo ' bash rpi_container_toolkit.sh --helm' 49 | echo '' 50 | echo '[*] --openfaas-master Install on master - openfaas repo and cli tools.' 51 | echo ' bash rpi_container_toolkit.sh --openfaas-master' 52 | echo '' 53 | echo '[*] --arkade-master Install on master - arkade repo and cli tools.' 54 | echo ' bash rpi_container_toolkit.sh --arkade-master' 55 | echo '' 56 | exit 57 | } 58 | 59 | function update_apt() { # Update apt repo for up to date packaging 60 | /usr/bin/sudo apt-get update -y 61 | /usr/bin/sudo apt-get upgrade -y 62 | /usr/bin/sudo apt-get dist-upgrade -y 63 | /usr/bin/sudo apt-get autoclean -y 64 | /usr/bin/sudo apt-get autoremove -y 65 | } 66 | 67 | function enable_traffic_forwarding() { 68 | /bin/echo "[*] Allowing traffic forwarding." 69 | /bin/sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' /etc/sysctl.conf 70 | /bin/sed -i '/^net.ipv4.ip_forward=1/a net.ipv4.ip_nonlocal_bind=1' /etc/sysctl.conf 71 | } 72 | 73 | function disable_swap() { 74 | /bin/echo "[*] Disabling Swap" 75 | /sbin/swapoff -av 76 | /usr/bin/free 77 | } 78 | 79 | function install_docker() { # Use docker's shell script to install. 80 | /bin/echo "[*] Installing Docker" 81 | /usr/bin/curl -sSL get.docker.com | /bin/sh && /usr/sbin/usermod node -aG docker 82 | } 83 | 84 | function ufw_ports_allowed() { # Enable NAT forwarding, masquerade, and reqired ports. 85 | /bin/echo "[*] Enabling required ports." 86 | /usr/bin/sudo apt-get install ufw -y 87 | /usr/bin/sudo /usr/sbin/ufw enable 88 | /bin/sed -i 's/DEFAULT_FORWARD_POLICY="DROP"/DEFAULT_FORWARD_POLICY="ACCEPT"/g' /etc/default/ufw 89 | /bin/sed -i 's@#net/ipv4/ip_forward=1@net/ipv4/ip_forward=1@g' /etc/ufw/sysctl.conf 90 | # sed -i '/^*filter/i # NAT table rules 91 | # *nat 92 | # :PREROUTING ACCEPT [0:0] 93 | # :POSTROUTING ACCEPT [0:0] 94 | 95 | # # Port Forwardings 96 | # -A PREROUTING -i eth0 -p tcp --dport 22 -j DNAT --to-destination 10.96.0.0 97 | 98 | # # Forward traffic through eth0 - Change to match you out-interface 99 | # -A POSTROUTING -s 10.96.0.0/16 -o eth0 -j MASQUERADE 100 | 101 | # # don't delete the 'COMMIT' line or these nat table rules won't 102 | # # be processed 103 | # COMMIT' /etc/ufw/before.rules 104 | /usr/bin/sudo /usr/sbin/ufw allow 22/tcp 105 | /usr/bin/sudo /usr/sbin/ufw allow 80/tcp 106 | /usr/bin/sudo /usr/sbin/ufw allow 443/tcp 107 | /usr/bin/sudo /usr/sbin/ufw allow 2376/tcp 108 | /usr/bin/sudo /usr/sbin/ufw allow 2379/tcp 109 | /usr/bin/sudo /usr/sbin/ufw allow 2380/tcp 110 | /usr/bin/sudo /usr/sbin/ufw allow 4789/udp 111 | /usr/bin/sudo /usr/sbin/ufw allow 6443/tcp 112 | /usr/bin/sudo /usr/sbin/ufw allow 6783:6784/udp 113 | /usr/bin/sudo /usr/sbin/ufw allow 8472/udp 114 | /usr/bin/sudo /usr/sbin/ufw allow 9099/tcp 115 | /usr/bin/sudo /usr/sbin/ufw allow 10250/tcp 116 | /usr/bin/sudo /usr/sbin/ufw allow 10251/tcp 117 | /usr/bin/sudo /usr/sbin/ufw allow 10252/tcp 118 | /usr/bin/sudo /usr/sbin/ufw allow 10254/tcp 119 | /usr/bin/sudo /usr/sbin/ufw allow 10255/tcp 120 | /usr/bin/sudo /usr/sbin/ufw allow 30000:32767/tcp 121 | /usr/bin/sudo /usr/sbin/ufw allow 30000:32767/udp 122 | /usr/bin/sudo /usr/sbin/ufw reload 123 | } 124 | 125 | function install_kubernetes() { # Install Kubernetes 126 | curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | \ 127 | /usr/bin/sudo apt-key add - && echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | \ 128 | /usr/bin/sudo tee /etc/apt/sources.list.d/kubernetes.list && /usr/bin/sudo apt-get update -q 129 | /usr/bin/sudo apt-get -y install kubelet kubectl kubeadm 130 | } 131 | 132 | # function set_cgroup_driver() { 133 | # # Update cgroup driver for kubernetes 134 | # echo '[*] Verify Docker cgroupfs' 135 | # docker info | grep -i cgroup 136 | # echo '[*] Updating Docker to use same cgroup.' 137 | # cat > /etc/docker/daemon.json <>> " keyValue 73 | /bin/echo "$keyValue" >> /home/node/.ssh/authorized_keys 74 | 75 | /bin/chmod 700 /home/node/.ssh 76 | /bin/chmod 600 /home/node/.ssh/authorized_keys 77 | /bin/chown -R node:node /home/node 78 | } 79 | 80 | function create_root_password() { # Ask for the users new root password 81 | /bin/echo '[*] Type in user "root" password.' 82 | read -sp "Password: " password_root_variable 83 | } 84 | 85 | function set_root_password() { # Set the new password for the root user. 86 | /bin/echo -e '[*] Changing user "root" password' 87 | /bin/echo -e "$password_root_variable\n$password_root_variable\n" | /usr/bin/sudo /usr/bin/passwd root 88 | } 89 | 90 | function config_root_ssh_keys() { # Create Admin User Secure File Structure SSH 91 | if [ ! -d /root/.ssh ]; then 92 | /bin/mkdir /root/.ssh 93 | /usr/bin/touch /root/.ssh/authorized_keys 94 | fi 95 | 96 | if [ ! -f /root/.ssh/authorized_keys ]; then 97 | /usr/bin/touch /root/.ssh/authorized_keys 98 | fi 99 | /bin/echo "Please copy/paste your authorized key for 'root' user:" 100 | read -r -p ">>> " keyValue 101 | /bin/echo "$keyValue" >> /root/.ssh/authorized_keys 102 | 103 | /bin/chmod 700 /root/.ssh 104 | /bin/chmod 600 /root/.ssh/authorized_keys 105 | /bin/chown -R root:root /root 106 | } 107 | 108 | function ask_for_hostname() { # Ask for the users new root password 109 | /bin/echo '[*] Changing hostname for this pi.' 110 | read -r -p "New Hostname: " user_requested_hostname 111 | } 112 | 113 | function set_hostname() { # Request hostname. 114 | /bin/echo "[*] Setting hostname to "$user_requested_hostname"" 115 | /usr/bin/hostnamectl set-hostname $user_requested_hostname 116 | } 117 | 118 | function cleanup_etc_hosts() { # Remove the raspberrypi hostname from /etc/hosts 119 | /bin/sed -i '/raspberrypi/d' /etc/hosts 120 | } 121 | 122 | function set_etc_hosts_manually() { # Add new hostname to /etc/hosts. 123 | /bin/echo "$(ifconfig | grep eth0 -A1 | grep inet | awk '{print $2}')" "$(hostnamectl --static)" >> /etc/hosts 124 | } 125 | 126 | function secure_sudo_raspbian() { # Require password when using /usr/bin/sudo for pi and node users. 127 | /bin/sed -i 's/NOPASSWD/PASSWD/g' /etc/sudoers.d/010_pi-nopasswd 128 | mv /etc/sudoers.d/010_pi-nopasswd /etc/sudoers.d/010_pi-passwd 129 | /usr/bin/touch /etc/sudoers.d/010_node-passwd 130 | cat /etc/sudoers.d/010_pi-passwd > /etc/sudoers.d/010_node-passwd 131 | /bin/sed -i 's/pi/node/g' /etc/sudoers.d/010_node-passwd 132 | } 133 | 134 | function secure_sudo_ubuntu() { # Require password when using /usr/bin/sudo for ubuntu or node users. 135 | /bin/sed -i 's/NOPASSWD/PASSWD/g' /etc/sudoers.d/90-cloud-init-users 136 | /bin/echo "# User rules for node" >> /etc/sudoers.d/90-cloud-init-users 137 | /bin/echo "node ALL=(ALL) PASSWD:ALL" >> /etc/sudoers.d/90-cloud-init-users 138 | } 139 | 140 | function configure_sshd() { # Add a Banner to ssh requiring permission to get into the Pi. 141 | /bin/echo "" > /etc/issue.net 142 | /bin/echo " #####################################################" >> /etc/issue.net 143 | /bin/echo " # Unauthorized access to this machine is prohibited #" >> /etc/issue.net 144 | /bin/echo " # Speak with the owner first to obtain Permission #" >> /etc/issue.net 145 | /bin/echo " #####################################################" >> /etc/issue.net 146 | /bin/echo "" >> /etc/issue.net 147 | /bin/echo "" >> /etc/issue.net 148 | /bin/echo "" >> /etc/issue.net 149 | /bin/echo "" >> /etc/issue.net 150 | /bin/sed -i 's/#Banner\ none/Banner\ \/etc\/issue.net/g' /etc/ssh/sshd_config 151 | /bin/sed -i 's/#PermitRootLogin\ prohibit-password/PermitRootLogin\ yes/g' /etc/ssh/sshd_config 152 | /bin/sed -i 's/#PasswordAuthentication\ yes/PasswordAuthentication\ no/g' /etc/ssh/sshd_config 153 | /bin/sed -i 's/#AuthorizedKeysFile/AuthorizedKeysFile/g' /etc/ssh/sshd_config 154 | #/bin/echo -e "AllowUsers node" >> /etc/ssh/sshd_config 155 | } 156 | 157 | function deny_default_user() { # If default users exist, blacklist them from ssh. 158 | if [ $(/bin/cat /etc/passwd | /bin/grep pi | /usr/bin/wc -l) -eq 1 ]; then 159 | /bin/echo -e "DenyUsers pi" >> /etc/ssh/sshd_config 160 | elif [ $(/bin/cat /etc/passwd | /bin/grep ubuntu | /usr/bin/wc -l) -eq 1 ]; then 161 | /bin/echo -e "DenyUsers ubuntu" >> /etc/ssh/sshd_config 162 | fi 163 | } 164 | 165 | function enable_restart_ssh() { # Enable and restart ssh. 166 | /usr/bin/sudo systemctl enable ssh 167 | /usr/bin/sudo systemctl restart ssh 168 | } 169 | 170 | function update_apt() { # Update apt repo for up to date packaging 171 | /usr/bin/sudo apt-get update -y 172 | /usr/bin/sudo apt-get upgrade -y 173 | /usr/bin/sudo apt-get dist-upgrade -y 174 | /usr/bin/sudo apt-get autoclean -y 175 | /usr/bin/sudo apt-get autoremove -y 176 | } 177 | 178 | function install_iptables() { # Install persisent iptables 179 | /usr/bin/sudo apt-get install iptables-persistent -y 180 | } 181 | 182 | function cgroup_to_bootfile() { # Must use cgroup memory, needed in boot file 183 | sed -i 's/$/\ cgroup_enable=cpuset\ cgroup_memory=1\ cgroup_enable=memory/' /boot/firmware/cmdline.txt 184 | } 185 | 186 | function enable_iptables_for_k3s() { 187 | /usr/bin/sudo /usr/sbin/iptables -F 188 | /usr/bin/sudo /usr/bin/update-alternatives --set iptables /usr/sbin/iptables-legacy 189 | /usr/bin/sudo /usr/bin/update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy 190 | } 191 | 192 | function install_firewall() { # Install the firewall and allow port 22 193 | /usr/bin/sudo apt-get install ufw -y 194 | /usr/bin/sudo ufw enable 195 | /usr/bin/sudo ufw allow 22/tcp 196 | /usr/bin/sudo ufw status 197 | } 198 | 199 | function reboot_pi() { # Reboot the pi 200 | /bin/echo '[*] Rebooting the pi in 5 seconds.' 201 | sleep 5 202 | reboot 203 | } 204 | 205 | ################################ 206 | # Functions to run on execute. # 207 | ################################ 208 | 209 | ############################ 210 | # Functions to be executed # 211 | ############################ 212 | 213 | 214 | case "$1" in 215 | --ubuntu) 216 | run_as_root 217 | create_node_password 218 | create_node_user 219 | ubuntu_node_user_groups 220 | config_node_ssh_keys 221 | create_root_password 222 | set_root_password 223 | config_root_ssh_keys 224 | ask_for_hostname 225 | set_hostname 226 | set_etc_hosts_manually 227 | secure_sudo_ubuntu 228 | configure_sshd 229 | deny_default_user 230 | enable_restart_ssh 231 | enable_iptables_for_k3s 232 | cgroup_to_bootfile 233 | update_apt 234 | reboot_pi 235 | ;; 236 | --raspbian) 237 | run_as_root 238 | set_keyboard_english 239 | create_pi_password 240 | set_pi_password 241 | create_node_password 242 | create_node_user 243 | raspbian_node_user_groups 244 | config_node_ssh_keys 245 | create_root_password 246 | set_root_password 247 | config_root_ssh_keys 248 | ask_for_hostname 249 | set_hostname 250 | cleanup_etc_hosts 251 | set_etc_hosts_manually 252 | secure_sudo_raspbian 253 | configure_sshd 254 | deny_default_user 255 | enable_restart_ssh 256 | update_apt 257 | install_iptables 258 | install_firewall 259 | reboot_pi 260 | ;; 261 | -h) 262 | _help_menu 263 | ;; 264 | --help) 265 | _help_menu 266 | ;; 267 | *) 268 | _help_menu 269 | ;; 270 | esac -------------------------------------------------------------------------------- /raspberry_pi/traefik.yaml: -------------------------------------------------------------------------------- 1 | # Example for harded certificates 2 | apiVersion: helm.cattle.io/v1 3 | kind: HelmChart 4 | metadata: 5 | name: traefik 6 | namespace: kube-system 7 | spec: 8 | chart: https://%{KUBERNETES_API}%/static/charts/traefik-1.81.0.tgz 9 | valuesContent: |- 10 | rbac: 11 | enabled: true 12 | ssl: 13 | enabled: true 14 | enforced: true 15 | tlsMinVersion: "VersionTLS12" 16 | cipherSuites: ["TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"] 17 | metrics: 18 | prometheus: 19 | enabled: true 20 | kubernetes: 21 | ingressEndpoint: 22 | useDefaultPublishedService: true 23 | image: "rancher/library-traefik" 24 | #dashboard.enabled: "true" # <-- add this line 25 | #dashboard.domain: "traefik.internal" # <-- and this one with a resolvable DNS name 26 | tolerations: 27 | - key: "CriticalAddonsOnly" 28 | operator: "Exists" 29 | - key: "node-role.kubernetes.io/master" 30 | operator: "Exists" 31 | effect: "NoSchedule" 32 | -------------------------------------------------------------------------------- /traefik/README.md: -------------------------------------------------------------------------------- 1 | helm repo add traefik https://traefik.github.io/charts 2 | kubectl create ns traefik-v2 3 | helm install --namespace=traefik-v2 traefik traefik/traefik 4 | 5 | # Use this to access the dashboard. If on a remote host, just ssh port forward to your local machine 6 | ssh -i ~/.ssh/id_rsa -L 9000:127.0.0.1:9000 user@master-ip -N 7 | kubectl port-forward $(kubectl -n traefik-v2 get pods --selector "app.kubernetes.io/name=traefik" --output=name) 9000:9000 8 | # Now visit 127.0.0.1:9000/dashboard/ 9 | 10 | 11 | 12 | Create unsigned certs: 13 | openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=traefik-ui.minikube" 14 | Creat base64 and add them to the traefik-deployment.yaml: 15 | cat tls.crt | base64 16 | cat tls.key | base64 17 | rm tls.crt 18 | rm tls.key 19 | 20 | These can be used for self signed certs. Let use letsencrypt for CA signed certs 21 | 22 | Just add ingress and ingressroutes to your deployment files 23 | 24 | 25 | TODO: 26 | * Update with middleware, the below does not work with newer versions of Traefik and Let's Encrypt 27 | * Found that the apiVersion needs to be updated (under IngressRoute): 28 | 29 | 30 | --- 31 | apiVersion: v1 32 | kind: Service 33 | metadata: 34 | name: docker-registry-service 35 | namespace: docker-registry-namespace 36 | spec: 37 | selector: 38 | app: docker-registry 39 | ports: 40 | - protocol: TCP 41 | port: 5000 42 | --- 43 | apiVersion: networking.k8s.io/v1 44 | kind: Ingress 45 | metadata: 46 | name: docker-registry-ingress 47 | namespace: docker-registry-namespace 48 | annotations: 49 | kubernetes.io/ingress.class: "traefik" 50 | acme.cert-manager.io/http01-edit-in-place: "true" 51 | # cert-manager.io/cluster-issuer: letsencrypt-prod 52 | cert-manager.io/cluster-issuer: letsencrypt-staging 53 | traefik.ingress.kubernetes.io/frontend-entry-points: http, https 54 | traefik.ingress.kubernetes.io/redirect-entry-point: https 55 | spec: 56 | rules: 57 | - host: registry.example.com 58 | http: 59 | paths: 60 | - path: / 61 | pathType: Prefix 62 | backend: 63 | service: 64 | name: docker-registry-service 65 | port: 66 | number: 5000 67 | tls: 68 | - hosts: 69 | - registry.example.com 70 | secretName: docker-registry-tls 71 | --- 72 | #apiVersion: traefik.containo.us/v1alpha1 73 | apiVersion: traefik.io/v1alpha1 74 | kind: IngressRoute 75 | metadata: 76 | name: registry-example-ingressroute 77 | namespace: docker-registry-namespace 78 | spec: 79 | entryPoints: 80 | - websecure 81 | routes: 82 | - match: Host(`registry.example.com`) 83 | kind: Rule 84 | services: 85 | - name: docker-registry-service 86 | port: 5000 87 | tls: 88 | certResolver: letsencrypt 89 | 90 | -------------------------------------------------------------------------------- /user_administration/authenticate_users.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################# 4 | # Authenticate Users and Create Their Namespace # 5 | ################################################# 6 | 7 | USER=$2 8 | 9 | function check_user_input() { 10 | if [[ $USER == '' ]]; then 11 | echo '[*] Please provide a user name.' 12 | exit 13 | fi 14 | } 15 | 16 | 17 | function _run_as_root() { # Run as root 18 | if [[ $(id -u) != 0 ]]; then 19 | echo 'Must be ran as root.' 20 | exit 21 | fi 22 | } 23 | 24 | 25 | function _help_menu() { # Help menu 26 | echo '[*] Help Menu:' 27 | echo '' 28 | echo "[*] -u Authenticate a user, parse the user\'s name." 29 | echo ' bash authenticate_user.sh -u iamauser' 30 | echo '' 31 | echo '[*] -d Delete a RoleBind to revoke user access.' 32 | echo ' bash authenticate_user -d iamauser-admin' 33 | echo '' 34 | echo '' 35 | exit 36 | } 37 | 38 | 39 | function create_key_and_csr() { # Generate key and csr for user 40 | echo '[*] Creating key and csr' 41 | openssl req -new -newkey rsa:4096 -nodes -keyout $USER-k8s.key -out $USER-k8s.csr -subj "/CN="$USER"/O=devops" 42 | } 43 | 44 | 45 | function kube_apply_csr_yaml() { # Create yaml file to request CA approval and apply the yaml 46 | echo "[*] Applying the "$USER"-k8s-csr.yaml" 47 | users_base64_csr=$(cat $USER-k8s.csr | base64 | tr -d '\n') 48 | cat < $USER-k8s-csr.yaml 49 | apiVersion: certificates.k8s.io/v1beta1 50 | kind: CertificateSigningRequest 51 | metadata: 52 | name: $USER-k8s-access 53 | spec: 54 | groups: 55 | - system:authenticated 56 | request: "$users_base64_csr" 57 | usages: 58 | - client auth 59 | EOF 60 | kubectl create -f $USER-k8s-csr.yaml 61 | } 62 | 63 | 64 | function kube_get_csr() { # Get the pending or approved csr waiting for CA approval 65 | echo '[*] Get csr from kubectl' 66 | kubectl get csr 67 | } 68 | 69 | 70 | function kube_approve_csr() { # Approve the pending csr 71 | echo '[*] Approve the pending csr' 72 | kubectl certificate approve $USER-k8s-access 73 | } 74 | 75 | 76 | function kube_retreive_signed_csr() { # Retrieve the signed CSR and print to file 77 | echo '[*] Retreive the CA signed crt' 78 | sleep 2 79 | kubectl get csr $USER-k8s-access -o jsonpath='{.status.certificate}' | base64 --decode > $USER-k8s-access.crt 80 | } 81 | 82 | 83 | function print_the_csr() { # Print the User's crt file 84 | echo "[*] Printing "$USER"-k8s-access.crt" 85 | cat $USER-k8s-access.crt 86 | } 87 | 88 | 89 | function retreive_users_signed_ca() { # Pull the Users CA signed file 90 | echo '[*] Retreiving the signed CA crt' 91 | kubectl config view -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' --raw | base64 --decode - > $USER-k8s-ca.crt 92 | } 93 | 94 | 95 | function kube_create_users_config() { # Create users kubeconfig file. 96 | echo '[*] Creating the users kubeconfig file' 97 | kubectl config set-cluster $(kubectl config view -o jsonpath='{.clusters[0].name}') --server=$(kubectl config view -o jsonpath='{.clusters[0].cluster.server}') --certificate-authority=$USER-k8s-ca.crt --kubeconfig=$USER-k8s-config --embed-certs 98 | } 99 | 100 | 101 | function print_users_kubeconfig() { # Print the kubeconfig file 102 | echo '[*] Print the User kubeconfig file' 103 | cat $USER-k8s-config 104 | } 105 | 106 | 107 | function create_user_into_kubeconfig() { # Fill in the users for the kubeconfig file 108 | echo '[*] Import user into kubeconfig file' 109 | kubectl config set-credentials $USER --client-certificate=$USER-k8s-access.crt --client-key=$USER-k8s.key --embed-certs --kubeconfig=$USER-k8s-config 110 | } 111 | 112 | 113 | function create_context_into_kubeconfig() { # Fill in the context for the kubeconfig file 114 | echo '[*] Import context into the user kubeconfig file' 115 | kubectl config set-context $USER --cluster=$(kubectl config view -o jsonpath='{.clusters[0].name}') --namespace=$USER --user=$USER --kubeconfig=$USER-k8s-config 116 | } 117 | 118 | 119 | function kube_create_user_namespace() { # Create the User's namespace 120 | echo '[*] Creating the User namespace' 121 | kubectl create ns $USER 122 | } 123 | 124 | 125 | function specify_context_for_user() { # Specify the context for User to use with kubectl commands. 126 | echo '[*] Specifying the user context for kubectl' 127 | kubectl config use-context $USER --kubeconfig=$USER-k8s-config 128 | } 129 | 130 | 131 | function kube_test_users_kubeconfig() { # Test User's kubeconfig file 132 | echo '[*] Test user kubeconfig file' 133 | kubectl version --kubeconfig=$USER-k8s-config 134 | } 135 | 136 | 137 | function kube_test_user_pods() { # See the running pods for user 138 | echo '[*] Print the user pods for the user namespace' 139 | kubectl get pods --kubeconfig=$USER-k8s-config 140 | } 141 | 142 | 143 | function kube_create_user_admin_role_to_user_pods() { # Create admin RoleBind for User to User namespace 144 | # If you want to also bump up root privs: 145 | # kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root 146 | echo '[*] Create admin RoleBind for user namespace' 147 | kubectl create rolebinding $USER-admin --namespace=$USER --clusterrole=admin --user=$USER 148 | } 149 | 150 | function give_user_their_files() { # Print to Admin they need to send files to user 151 | echo "[*] That's it! Send the following files to the user in a SECURED setting." 152 | echo " - "$USER"-k8s-config" 153 | echo "[*] Have them place this file in ~/.kube/config and make sure kubectl is installed on their client." 154 | } 155 | 156 | 157 | function kube_delete_user_rolebinding() { # Delete the RoleBind user-admin 158 | echo "[*] Deleting RoleBind "$USER"-admin" 159 | kubectl delete rolebinding $USER-admin 160 | } 161 | 162 | 163 | function kube_delete_approved_csr() { # Delete the CA signed csr 164 | echo "[*] Deleting CA Signed csr for "$USER"" 165 | kubectl delete csr $USER-k8s-access 166 | } 167 | 168 | 169 | function kube_delete_user_namespace() { 170 | echo "[*] Deleting Namespace for "$USER"" 171 | kubectl delete namespaces $USER 172 | } 173 | 174 | 175 | function delete_user_conf_files() { 176 | echo "[*] Deleting files:" 177 | echo $(ls $USER-k8s*) 178 | rm -rf $(ls $USER-k8s*) 179 | } 180 | 181 | ############################ 182 | # Functions to be executed # 183 | ############################ 184 | 185 | case "$1" in 186 | -u) 187 | _run_as_root 188 | check_user_input 189 | create_key_and_csr 190 | kube_apply_csr_yaml 191 | kube_get_csr 192 | kube_approve_csr 193 | kube_retreive_signed_csr 194 | kube_get_csr 195 | #print_the_csr 196 | retreive_users_signed_ca 197 | kube_create_users_config 198 | #print_users_kubeconfig 199 | create_user_into_kubeconfig 200 | create_context_into_kubeconfig 201 | kube_create_user_namespace 202 | specify_context_for_user 203 | kube_test_users_kubeconfig 204 | kube_test_user_pods # This one should fail since we are Forbidden 205 | kube_create_user_admin_role_to_user_pods 206 | kube_test_user_pods # This should now show no pods, we are in! 207 | give_user_their_files 208 | ;; 209 | -d) 210 | _run_as_root 211 | check_user_input 212 | kube_delete_user_rolebinding 213 | kube_delete_approved_csr 214 | kube_delete_user_namespace 215 | delete_user_conf_files 216 | ;; 217 | -h) 218 | _help_menu 219 | ;; 220 | *) 221 | _help_menu 222 | ;; 223 | esac 224 | --------------------------------------------------------------------------------