From 95cdcc860afffd25e17aa440e73c3aa1f94630ed Mon Sep 17 00:00:00 2001 From: AHMZA Date: Fri, 17 Dec 2021 19:15:08 +0000 Subject: [PATCH 01/11] added back pi-docker-swam branch --- .../posts/building-a-docker-swarm-with-pis.md | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/content/posts/building-a-docker-swarm-with-pis.md b/content/posts/building-a-docker-swarm-with-pis.md index 72cb47b..0798b8f 100644 --- a/content/posts/building-a-docker-swarm-with-pis.md +++ b/content/posts/building-a-docker-swarm-with-pis.md @@ -145,7 +145,7 @@ self explanitory. So go ahead and assemble the cluster 🛠 file system** ### **Sort out the Network bits** -This is the easy part, there are two methods we can use to set a +This is the easy part, there are two methods you can use to set a static IP address, one is on your DHCP server and the other is on the device itself. Personally I prefer to set static IPs on the device itself so I will cover that here. @@ -153,11 +153,17 @@ device itself so I will cover that here. To find the current ip of your Pis you can go to your DHCP server and look for the DHCP leases for the Pis. +> there are naming conventions for naming primary and secondary +things but this is your cluster so be creative with it, I have my +primary node named ```Goob``` and the secondary nodes named ```Doris1``` +```Doris2``` and ```Doris3``` +[reference](https://www.youtube.com/watch?v=oFb7FVe8sdQ) + **SSH to the Pi** then open and edit the following files * /etc/hosts - * edit this line with your hostname: ```127.0.1.1 mainpi``` + * edit this line with your hostname: ```127.0.1.1 goob``` * /etc/hostname - * edit this file with your hostname: ```mainpi``` + * edit this file with your hostname: ```goob``` * /etc/dhcpcd.conf * knowing we will be using only static IPs here I delete everything in the file add the following @@ -169,4 +175,40 @@ and look for the DHCP leases for the Pis. ``` **Now reboot the pi** ```sudo shutdown -r now``` +**Once the Pis are back up log into each one and change the default +passwords** you may also want to create a new user for yourself but +thats totally optional. + +### **Provision with** ***Ansible*** +you want to **create an _Ansible_ control node** and that is as simple as +installing a package onto your machine. Ansible is built using python +which makes it easy to install as **we can use the python pip package +manger.** To check you have it installed do ```pip --version``` if +it's not installed do the following + + +```curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py``` + +```python get-pip.py --user``` + +**once you have pip installed proceed to installing _Ansible_** + +[Docs](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) + +```pip install ansible``` + +Now that ansible is installed we can create a runbok that defines the +steps ansible needs to take on the remote machine to correctly +provision it. This playbook is written in yaml so get ready to make +sure your indents are correct 😬 + +**Creating the playbook** +now you can copy what I have and it should work - after changing a +thing or two - which is fine however I encourage you to copy what I +have, read the [Docs](https://docs.ansible.com/ansible/latest/user_guide/index.html) +and make any changes you feel are necessary. + +```yaml + +``` From 644e375d2bd1d69d69e43d95ab474383c2f924d0 Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Date: Fri, 17 Dec 2021 19:18:15 +0000 Subject: [PATCH 02/11] Update .gitlab-ci.yml --- .gitlab-ci.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 75cf827..d95bb50 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,6 +22,10 @@ Build: artifacts: paths: - public + only: + - main + + Dockerize: stage: dockerize @@ -33,3 +37,7 @@ Dockerize: - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:latest + only: + - main + + From a1138a52cf13c123eb2a950dc4254bd967f14533 Mon Sep 17 00:00:00 2001 From: AHMZA Date: Fri, 17 Dec 2021 20:42:10 +0000 Subject: [PATCH 03/11] new post --- content/posts/you-need-to-learn-linux.md | 90 +++++++++++++++++++++++ static/img/learn-linux/learn-linux.gif | Bin 0 -> 6947 bytes 2 files changed, 90 insertions(+) create mode 100644 content/posts/you-need-to-learn-linux.md create mode 100755 static/img/learn-linux/learn-linux.gif diff --git a/content/posts/you-need-to-learn-linux.md b/content/posts/you-need-to-learn-linux.md new file mode 100644 index 0000000..04bb8e1 --- /dev/null +++ b/content/posts/you-need-to-learn-linux.md @@ -0,0 +1,90 @@ +--- +title: You Need to Learn Linux 🐧 +date: 2021-12-17T19:16:50Z +author: "ahmza" +draft: true +weight: + +tags: ["Linux"] +description: "Ever wanted to learn Linux ? Well no better time than now to learn" +canonicalURL: "https://blog.ahmza.com/Page%28/posts/you-need-to-learn-linux.md%29" + +cover: + image: "/img/learn-linux/learn-linux.gif" # image path/url + alt: "learn-linux" # alt text + caption: "" # display caption under cover + relative: false # when using page bundles set this to true +showtoc: true +searchHidden: false +--- +## **Introduction** +I say you need to learn _Linux_ because really there is no reason not +to. If you are pursuing a career in IT then you will without a doubt +come across _Linux_ and having even basic knowledge of _Linux_ will get +you far simply because it is everywhere. Many people struggle with the +OS simply because it's fundamentally different compared to the other +operating systems but give it a bit of time, you will master the +basics and understand how much control over the system it gives you. + + +## **But Why** +As mentioned before, there isn't reason not to. **Linux is everywhere**, +from data centres to your phone. **Understanding how to use _Linux_ is +great if you in or looking at a career in IT** because not many people +-relatively speaking- know how to use it, it sets you apart from others. +**I also believe _Linux_ gives you a deeper understanding of how your +system works** at a lower level which can be great when it comes to +troubleshooting. I think the most important factor is that **Linux is +open source** and so you have the ability to look at the code you are +running and with this comes full customisability of the system. + +If you consider yourself a power user then _Linux_ is the perfect +operating system due to the aforementioned customisability but also the +command line. Many people are scared away from _Linux_ as they are +intimidated by the fact that they have to use the terminal, however if +you can overcome this "fear" then you have unlocked a great power and +from my experience will start finding GUI's cumbersome. + + +## **How can you start** +There are many ways you can start using _Linux_ and a lot of them don't +require you to use _Linux_ as your main operating system. You do need +to be committed to using Linux. Try not to fall back to Windows or +MacOS if you cant figure something out, **search for solutions.** +**Lastly try to get comfortable with the terminal.** + +### **Install Linux as your main OS** +This is the **Full Send** option. This is a great option if you know +a move to Linux is something you want to commit to. I think this is the +best option as you have to start learning Linux to get things done so +you have incentive to keep going. + + +**Choosing a distro** is fun but a huge time investment, you will hear the +term `distro hopping` which is installing different distributions of +_Linux_ and with the number of distros out there this can be daunting +for new users. A great Distribution that I recommend is +[Manjaro with KDE Plasma](https://manjaro.org/downloads/official/kde/) +as it offers a heavily customisable desktop environment `KDE Plasma` +and Manjaro itself is a great as it is based on Arch Linux so it can +leverage the power of the AUR (Arch User Repository) + +### ***MacOS*** **Terminal** +_MacOS_ is actually _UNIX_ based and so **if you have an _apple Mac/MacBook_ +all you need is to open the Terminal** application and start playing +around. I used this option for a while on my work machine and it works +great. You get the best of both worlds with this option so if you have +a MacOS device then this is a solid option. Not recommended if you +don't have one of these devices simply due to cost 💸 + +### ***Windows WSL*** +The _Windows Subsystem for Linux_ is another great option to get started +with _Linux_ as it installs the _Linux Kernel_ natively in windows and +allows you to play around with a real _Linux_ environment, before doing +a full send on my main machine this is the option I used. + +### **Virtual Machines** +If there is a specific Distribution of _Linux_ you want to try without +doing a Full Send then this is a great option however if you want to +simply get to know the _Linux_ then choose the _MacOS_ terminal or _WSL_ +methods as they are a lot lighter. diff --git a/static/img/learn-linux/learn-linux.gif b/static/img/learn-linux/learn-linux.gif new file mode 100755 index 0000000000000000000000000000000000000000..11dae8c83b683caafb63d1938ef1dcd461c001b8 GIT binary patch literal 6947 zcmeI#>08nXvn8W));n+LgY?DaRVH zV0LGicr~KI2g-V~4+af40|(0c@~vZ+SHTBa&x-7bTaOVAvR^QrbC1SB4siz9ZWW#_ zghLgtt1dUitU(S}4&A>l%sECpTs2%5Jkl7aZdv`dAwn|TLbT+*YeBCpuc^cDjkn{} z^=wG+`yU>Y^sM4Fj?_#DXvSWxq$3YL_2yZ{{?s^HD|%k)lxssiS~vBo(yJ+6)2e>@ zO>NLfE7|Jd>}YfB%1=#e-k0~CL_J%Ib;H-mo?I)8Rz3?W9;oo*Q;s$Ln0Z|iE7N+X zxG*;%L_(=HEm7a5N2r&ew((&L^O6yUnJqv5^}@=E>~pI(R>^F^J7HK8?~_=q+vO7l zu>tKuXu232$8EU^(o5F#>+(&#i|8s$-Axhc;#Ke9{Rj!!?u7)iR=hS*)^2}|oFou2 z$VX=bwoumQK-bf5EG-tKo!RkbbGpKA!S%athNyzO=UsF+(dPdG{4cqS(chVQ@sPl*916sfwVC1<$l>^%4Xnt|cI@WVR8Iv~ zWw#TiDjO36gSf3fA;I@Lw48$PKiNSHuIZMU34*{I*Fec|GCv+ng(;?4Tu5aG>- z@8Z=%cpoTEAq}4jh#`$r)xwab*;aLA^VdEnWXq3tL}csotPsin`BVK?n-bLdR=cV` z=~f2>)^qETmaRr;=SElO(8pW6Nuf`+B6~ug?!ah-b?v4)hY9{*kixo+xIJM)GrmT6 zk43+8c<47ru`~5!l-SuuX-`qAI|Y@u=UFI-*YzQ5*@ zB;SXnch-Kq8>x{Lj8UPEiwSqAt$%#d&xv1YjgZE#GTUI7wc2M$%+K6$E=HF5Maoy` zgSjc0`0P~(Xj2JON`M59@6-{sftD2$H&%`-EBd!<1Nvnom&*~Crx&%zSiD*c4sIM zVd2N8cNw{!2qoBs?dG%Gx7*8nLWw3dA6oG&J2OJ)$*Tj}I(qw`94ugwf`d!+#z0Tu z-Jz6-%98C;{8Q_xP%3)5L|+E#It~d-!b3;kj?8%PjfezFUOwya|)? zBmF>M1SdRyI=I|w4BQ{x9bPbBS$<3k^rNT38LQLfwleTDEF_{(#gugdN_d7diYU^! z$vUMEd5(9CkQHyLVx5K&o|6J2O190g&e}p=q!A)Y_n5LBTnR5|oCv1LO}3LaN5`y7(+GH)uP+e)WDiqtl(8A`f!H;aVL% zQ-tY1!!OU9)Nx*U-0%|K8|=8~Ta$0v5g6o^^#1Te=HxEq>H3i|RTEyvnsz90#cpi3 zjYE)8I*)Yu1j%qUIN)xrOe%Q`!>JGXZ8*1LN!wVLB z)?l+_Q3jcBC zna=LR7wsq*G;_OE=~F~C@QO^>?Wfs9wA_2$&}US!IHd@1R(wFK3Vo_)ZOX^4)i$2`NC z)yj&XWRab5%yUvmZHd07*xo7T1+BW42_uW0gJNFh&DNINYEJ!0j2S33t7E&8r`#%H zUR8$FRd{Pk+=Vf(Ypd(3kYveaNz7pLY#kS)Iqjn!JJe}bf1gU8zHS`*rYEHS0Yh^p zz$tckpt`<}OP&c1iXC}7TmO)+IeUv3`*yuE&d5>X~IZ_b%<2EVp zsjb%6G$MLp53E7pO8H8wKu?+=8-(6k-{?a0r-R&vUL@sPo&^2bTH4T$k!j5rs>g}! zV2#hIl=)KQII%Ob@g+m+JIg6<%8lFjic9%k85AeEENvX*YyG%KjGMj=YkJd9`B7UD zHxrC(8X41C;0fbqBe+eYQp!TJBu`auGHm$iumu9$QFq=bY(~w|D%@MGJ~Y9 zyp_Z+G)r5g80hM_I%csG);dR}u1*+ZmU@t_-x$y}krQTlfZO_=OI@1|!mPZNwl46Y zKfe$$s}nH(Qa|kvEfU??>x1=0f{JV zqG7a}aaUsGcp?n0cK(l~g5ybthW_!wC6(PuvZ8~JiITDua3`XVU$(;)o8!(JfE`#k z&+E8z0UG;3$@}&sUWkUA4@maCnCzir?A4WQFG}`yxA8SdIc%TePfubbrf{&yK_Io8 zq7+Ys)KL7oaQoDYKB-am>rkxJ^KGedpmi7!-s<|5q(yLI0Nx3U2NqA>=)(KD;i)Ve ziUDA`1;{YK(eQwC8IT(QB8q?$3WOrrqH>8n;g}Dhd{KqXA{=QWR7ERuLBvBli4Wk) zbpgcvSYpGXQd1YvbezcNDYYAr43Co@vxp1HBqtV0D8kK8lG4|EKgXZxwI`Fz$%CS6 zuUX{NPspQi|1l6HIgR`=Ix#3wY{=Lh8z* z!kUPxsgO1dPg7(otV5)MuxVg~g1R70D?4pHB5k8?+9ok|O9NF$K-}s<-DXJLu|(M^ zpzO}3>_JfeI6^T1Q;gn_O~im1ifrycw$LRX6q61&kl+C6s0Yc~kYuw&Jnn#VUQ~4vg;z z#=<>-vBYMq2pDT(h74S&XjG`|Shy~*P>oOs<`k-T7ivxwLLo&PjEa79EZQ7cq)jN& zUq;Lej?BLUnU@Gm4-V6-n|Wo5 z=?y9KH7dL2SmqyCc7src;FMW={wL@xIwF|e_FIdYIU!p$%7#KA zfvn!>n0!`QfujantGGL`qPi6lR9VyK7*tjNju2GcINSX%=>Gda*Zh)m@e=y$!)>nl zU;FwyR^$3z`400x{-Un!eLa{Jx6tG+jaw|i!s3@|(vb1X*@fKr71}*H=sup6gO1uJ z2VKrD&?Wo=-B(4dlF7JC!M{yqOUIvb&}|3FLC5(8Iv-twfOZWF#iXs%<6Gcz&_RBI z&Ue!<(1oPM%U@-Xha7YT>*b)^1+I_Ut2gyb6+Zn!3uBP9g966eMJPgu_)hI@`vK?R z;@=pc#|Dm}1h>lK&0PFr6Ioy=@$z)BHXroFoDfR7Zc?J#kAHHI6H5LUbpP|9%gGd7 zOlm(=t&(eeW!*o6O-d%*nD1HZUk+U2|EzOKm>Ki|dkw{HzwHYAJ?#g5<(@WosAeI@ z#9!k7M%ZWkAcw4d!^-Mje`5WW;_WkyjzPl_MThG?dzuD)n;agb7}wWmYTpc6sT%oE z@6|Xu(-b2a30Ab^4Q@3Ht?+;Q(Z#r-TQ<5yIakk9<)k+EMgHv7il8g)Q-)1H{LG>< zCP$^ajhjCl+JX`~RemcT{CnyO?B1~Cs&~6(YjX}PF4BK&CB%roT(=ps;#471a=)mw z!@Lp_>|?hJ-d^cxp5!_?u0}NK*r>WW*|?|l>B%jR1TSvU;2Kw_zV}K`XZ|T z1>OG>(8&&Lzb1nYkHzaZO4p8IZC6n`woCfaAHR)stWK3HuZ+M_7vvQF%HZp{HT%g{ zQk7&CFJ$``sn$Q$APPg)N{bj3_g$(YFo=$Ybb&QQ*nEYA4erN4_6eKqvDyY2-^&yH zVp!m?o9l>Yn>c)o^sIP*U3S5Q4Tu$b^8sH&dWh(uWE@;aw$x*;+^dIn6#1= ze}ZRo${sg-4R_WZe2j%V(}p`|ui^?yhN<8#4E+L~EjHO>NLda#tMO!Sy0RQ}md8{4 z-IZ_PQw|iS1nDTtLFY)rh4O6Wpu;JoM)8#7pfi+%E?P+ry1hH`NpPj)0Q|0Bpi?Av z;kS?DsrLAxy#Vpc<%}*+79JoJ0=allz6eP91v-2x&7Q#IT`7+Sm9Pj{Ip{?3w?RbY zdfH;$BqZKH!cv%GwxERa;6n7bII`Cm%#4A3l-{2PYpD-#I3}YYV2GFr=Mw zpq)n0&H^+CHqA*uJ0}y5s^~ z0c0ZBnL&cgo8n9)I4jgJE8HO~5|I@JWTDtuv4X5PaTW$lPcWn>Ina|4^i+Tju<1kr zoh+tP!P)7C*>@eX<&?_;va{LQxq|F`akiXtMTR*g4mnIj&i@+d*8f+~d4#P~P_X(B D5a2Ob literal 0 HcmV?d00001 From 688e5f40519afce3092abd58f3653c04f11240f0 Mon Sep 17 00:00:00 2001 From: AHMZA Date: Sun, 19 Dec 2021 15:54:11 +0000 Subject: [PATCH 04/11] updated post --- content/posts/you-need-to-learn-linux.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/posts/you-need-to-learn-linux.md b/content/posts/you-need-to-learn-linux.md index 04bb8e1..3cdd848 100644 --- a/content/posts/you-need-to-learn-linux.md +++ b/content/posts/you-need-to-learn-linux.md @@ -2,7 +2,7 @@ title: You Need to Learn Linux 🐧 date: 2021-12-17T19:16:50Z author: "ahmza" -draft: true +draft: false weight: tags: ["Linux"] @@ -60,7 +60,7 @@ best option as you have to start learning Linux to get things done so you have incentive to keep going. -**Choosing a distro** is fun but a huge time investment, you will hear the +**Choosing a distro is fun but a huge time investment, you will hear the term `distro hopping` which is installing different distributions of _Linux_ and with the number of distros out there this can be daunting for new users. A great Distribution that I recommend is From 43ba0dbecface20bd4f530b99120f69caf575d18 Mon Sep 17 00:00:00 2001 From: AHMZA Date: Tue, 14 Dec 2021 01:07:17 +0000 Subject: [PATCH 05/11] dissabled categories in favour of using only tags --- config.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/config.yml b/config.yml index 05bb549..663f0fc 100644 --- a/config.yml +++ b/config.yml @@ -107,10 +107,6 @@ params: keys: ["title", "permalink", "summary", "content"] menu: main: - - identifier: categories - name: categories - url: /categories/ - weight: 10 - identifier: tags name: tags url: /tags/ From 6ae44a02e9a744b6083339af5c9f7f84540807bb Mon Sep 17 00:00:00 2001 From: AHMZA Date: Tue, 14 Dec 2021 01:10:10 +0000 Subject: [PATCH 06/11] only build for changes made to main --- .gitlab-ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d95bb50..195343f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -24,8 +24,11 @@ Build: - public only: - main +<<<<<<< HEAD +======= +>>>>>>> f07b1f2 (only build for changes made to main) Dockerize: stage: dockerize @@ -39,5 +42,8 @@ Dockerize: - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:latest only: - main +<<<<<<< HEAD +======= +>>>>>>> f07b1f2 (only build for changes made to main) From f9e7af96354ba4e2c36e8530ba28186b14f4f45e Mon Sep 17 00:00:00 2001 From: ahmza Date: Sun, 19 Dec 2021 16:59:34 +0000 Subject: [PATCH 07/11] added ansible section of the guide --- .../posts/building-a-docker-swarm-with-pis.md | 157 +++++++++++++++++- 1 file changed, 153 insertions(+), 4 deletions(-) diff --git a/content/posts/building-a-docker-swarm-with-pis.md b/content/posts/building-a-docker-swarm-with-pis.md index 0798b8f..d300124 100644 --- a/content/posts/building-a-docker-swarm-with-pis.md +++ b/content/posts/building-a-docker-swarm-with-pis.md @@ -182,7 +182,7 @@ thats totally optional. ### **Provision with** ***Ansible*** you want to **create an _Ansible_ control node** and that is as simple as -installing a package onto your machine. Ansible is built using python +installing a package onto your machine. _Ansible_ is built using python which makes it easy to install as **we can use the python pip package manger.** To check you have it installed do ```pip --version``` if it's not installed do the following @@ -198,8 +198,8 @@ it's not installed do the following ```pip install ansible``` -Now that ansible is installed we can create a runbok that defines the -steps ansible needs to take on the remote machine to correctly +Now that _Ansible_ is installed we can create a runbok that defines the +steps _Ansible_ needs to take on the remote machine to correctly provision it. This playbook is written in yaml so get ready to make sure your indents are correct 😬 @@ -209,6 +209,155 @@ thing or two - which is fine however I encourage you to copy what I have, read the [Docs](https://docs.ansible.com/ansible/latest/user_guide/index.html) and make any changes you feel are necessary. -```yaml +> Check the [git repo](https://gitlab.com/AHMZA/pi-docker-swarm-ansible-deploy/-/tree/main) for the most up to date yaml file im using. +**Create the deploy.yml** + +```yaml +--- +- hosts: piCluster + become: yes + tasks: + - name: Auth local SSH Keys + ansible.posix.authorized_key: + user: + state: present + key: "{{ item }}" + with_file: + - /home//.ssh/id_rsa.pub + - ./pi_rsa.pub + + - name: Copy SSH Pi Intercoms Private Key + copy: + src: ./pi_rsa + dest: /home//.ssh/id_rsa + mode: '0600' + + + - name: Copy SSH Pi Intercoms Public Key + copy: + src: ./pi_rsa.pub + dest: /home//.ssh/id_rsa.pub + mode: '0644' + + - name: Check for any updates and install them + apt: + update_cache: true + upgrade: dist + + - name: Install Required build dependencies + apt: + update_cache: true + pkg: + - python3 + - python3-pip + - vim + - curl + + - name: Check Docker is installed + shell: "docker --version" + register: docker_version + + - name: check Docker compose is installed + shell: "docker-compose --version" + register: dc_version + + - name: Download Docker script + command: curl -fsSL https://get.docker.com -o get-docker.sh + when: docker_version.stdout.find('Docker version') + + - name: Run Docker install script + command: sudo sh get-docker.sh + when: docker_version.stdout.find('Docker version') + + - name: Install docker compose + command: sudo pip3 -v install docker-compose + when: dc_version.stdout.find('docker-compose version') + + - name: Enable docker service + service: + name: "{{ item }}" + enabled: true + state: started + loop: + - docker + - containerd + when: docker_version.stdout.find('Docker version') + + - name: Add user to docker group + user: + name: + groups: docker + append: yes + when: docker_version.stdout.find('Docker version') + + - name: wait for network on boot + command: raspi-config nonint do_boot_wait 0 + + - name: Reboot + reboot: ``` + +The steps this playbook takes are as follows: +1. Copy your SSH keys to the pi authorized_keys +2. Copy same Pi ssh key between the Pis for intercommunication +3. Check for and Install updates +4. Install any build dependancies +5. Check if Docker is Installed +6. Check if docker-compose is installed + * Check this because if they are already installed we can skip these steps and save time +7. Download the Docker Script +8. Install Docker from script +9. Install docker-compose (This will take a while on each pi so be patient, grab a coffee) +10. Enable the Docker service +11. Add user to Docker group +12. Change raspi config to wait for network before boot +13. Reboot + +take some time to read through the playbook, read the docs and try to +understand whats going on. Change the usernames to your username. + +Make the hosts file in the same directory as the deploy.yml +``` yaml +[piCluster] +10.10.10.20 +10.10.10.21 +10.10.10.22 +``` + +* `[piCluster]` - specifies a group of hosts +* `10.10.10.xx` - specifies the Pis IP + +heres the command to run the playbook. + +`ansible-playbook -i hosts -kK deploy.yml -c paramiko` + +* `ansible-playbook` - the command to run the playbook +* `-i hosts` - specifies the host/inventory file +* `-kK` - asks you for password for the SSH connection(-k) and the sudo password(-K) +* `deploy.yml` - the _Ansible_ playbook +* `-c paramiko` - Use the paramiko connection method, I found this works best with ssh keys + +You can do so much with _Ansible_, for example mount network shares etc, +if you can do it in the cli you can do it in _Ansible_ !! + +Now that the ansible script is done we can go ahead and actually +configure all the Pis into the cluster. + +### **Creating/Joining the swarm ** +Creating and joining the cluster is easy - It is a bit manual so this +is something you could impliment into the ansible playbook using +multiple host groups. Keep an eye out on the git repo as I may +implement this myself. + +**Follow the steps below to create the swarm:** +1. ssh to the main swarm node, this will be the manager node. +2. run `docker swarm init` + * This will return a command and token. Make sure to copy this token to your clipboard +3. exit the main swarm node +4. ssh to one of the worker nodes +5. paste and run the copied command +6. do the same on the remaining worker nodes + +You should now have a correctly configured cluster !! + From 77d45c6115cf474d653da5d8651a56e4bf2b343d Mon Sep 17 00:00:00 2001 From: ahmza Date: Thu, 23 Dec 2021 00:06:13 +0000 Subject: [PATCH 08/11] added more sections to the post --- .../posts/building-a-docker-swarm-with-pis.md | 214 ++++++++++++------ 1 file changed, 149 insertions(+), 65 deletions(-) diff --git a/content/posts/building-a-docker-swarm-with-pis.md b/content/posts/building-a-docker-swarm-with-pis.md index d300124..c4b6c04 100644 --- a/content/posts/building-a-docker-swarm-with-pis.md +++ b/content/posts/building-a-docker-swarm-with-pis.md @@ -211,6 +211,10 @@ and make any changes you feel are necessary. > Check the [git repo](https://gitlab.com/AHMZA/pi-docker-swarm-ansible-deploy/-/tree/main) for the most up to date yaml file im using. +**This script assumes you are using SSH keys, which you should but if +not you can skip the whole "Configure SSH" block,** +***I RECCOMEND YOU USE SSH KEYS*** - [read this](https://blog.ahmza.com/posts/securing-ssh/) + **Create the deploy.yml** ```yaml @@ -218,27 +222,35 @@ and make any changes you feel are necessary. - hosts: piCluster become: yes tasks: - - name: Auth local SSH Keys - ansible.posix.authorized_key: - user: - state: present - key: "{{ item }}" - with_file: - - /home//.ssh/id_rsa.pub - - ./pi_rsa.pub - - name: Copy SSH Pi Intercoms Private Key - copy: - src: ./pi_rsa - dest: /home//.ssh/id_rsa - mode: '0600' + - name: Configure SSH + block: + - name: Auth local SSH Keys + ansible.posix.authorized_key: + user: + state: present + key: "{{ item }}" + with_file: + - /home//.ssh/id_rsa.pub + - ./pi_rsa.pub + + - name: Copy SSH Pi Intercoms Private Key + copy: + src: ./pi_rsa + dest: /home//.ssh/id_rsa + mode: '0600' + owner: + group: + + - name: Copy SSH Pi Intercoms Public Key + copy: + src: ./pi_rsa.pub + dest: /home//.ssh/id_rsa.pub + mode: '0644' + owner: + group: - - name: Copy SSH Pi Intercoms Public Key - copy: - src: ./pi_rsa.pub - dest: /home//.ssh/id_rsa.pub - mode: '0644' - name: Check for any updates and install them apt: @@ -254,42 +266,46 @@ and make any changes you feel are necessary. - vim - curl + - name: Check Docker is installed shell: "docker --version" register: docker_version - + + - name: Install Docker + block: + + - name: Download Docker script + command: curl -fsSL https://get.docker.com -o get-docker.sh + + - name: Run Docker install script + command: sudo sh get-docker.sh + + - name: Enable docker service + service: + name: "{{ item }}" + enabled: true + state: started + loop: + - docker + - containerd + + - name: Add user to docker group + user: + name: + groups: docker + append: yes + + when: docker_version.stdout.find('Docker version') + + - name: check Docker compose is installed shell: "docker-compose --version" register: dc_version - - name: Download Docker script - command: curl -fsSL https://get.docker.com -o get-docker.sh - when: docker_version.stdout.find('Docker version') - - - name: Run Docker install script - command: sudo sh get-docker.sh - when: docker_version.stdout.find('Docker version') - - name: Install docker compose command: sudo pip3 -v install docker-compose when: dc_version.stdout.find('docker-compose version') - - name: Enable docker service - service: - name: "{{ item }}" - enabled: true - state: started - loop: - - docker - - containerd - when: docker_version.stdout.find('Docker version') - - - name: Add user to docker group - user: - name: - groups: docker - append: yes - when: docker_version.stdout.find('Docker version') - name: wait for network on boot command: raspi-config nonint do_boot_wait 0 @@ -304,31 +320,36 @@ The steps this playbook takes are as follows: 3. Check for and Install updates 4. Install any build dependancies 5. Check if Docker is Installed + * Download the Docker Script + * Install Docker from script + * Enable the Docker service + * Add user to Docker group 6. Check if docker-compose is installed - * Check this because if they are already installed we can skip these steps and save time -7. Download the Docker Script -8. Install Docker from script -9. Install docker-compose (This will take a while on each pi so be patient, grab a coffee) -10. Enable the Docker service -11. Add user to Docker group -12. Change raspi config to wait for network before boot -13. Reboot + * Install docker-compose (This will take a while on each pi so be patient, grab a coffee) +9. Change raspi config to wait for network before boot +10. Reboot take some time to read through the playbook, read the docs and try to understand whats going on. Change the usernames to your username. -Make the hosts file in the same directory as the deploy.yml +**Make the hosts file in the same directory as the deploy.yml** ``` yaml [piCluster] 10.10.10.20 10.10.10.21 10.10.10.22 ``` - * `[piCluster]` - specifies a group of hosts * `10.10.10.xx` - specifies the Pis IP -heres the command to run the playbook. +**create the Pi Intercommunication keys** +``` bash +ssh-keygen +Enter file in which to save the key (/home/ahmza/.ssh/id_rsa): .pi_rsa +``` +* save the keys in the same directory the deploy.yml file is + +**heres the command to run the playbook.** `ansible-playbook -i hosts -kK deploy.yml -c paramiko` @@ -341,23 +362,86 @@ heres the command to run the playbook. You can do so much with _Ansible_, for example mount network shares etc, if you can do it in the cli you can do it in _Ansible_ !! -Now that the ansible script is done we can go ahead and actually +Now that the _Ansible_ script is done we can go ahead and actually configure all the Pis into the cluster. -### **Creating/Joining the swarm ** -Creating and joining the cluster is easy - It is a bit manual so this -is something you could impliment into the ansible playbook using -multiple host groups. Keep an eye out on the git repo as I may -implement this myself. +### **Creating/Joining the swarm** +Creating and joining the cluster is easy - It is manual and tedious so +this is something you could impliment into the ansible playbook using +multiple host groups. -**Follow the steps below to create the swarm:** -1. ssh to the main swarm node, this will be the manager node. +**Follow these steps to create the swarm:** +1. ssh to the main Pi, this will be the manager node. 2. run `docker swarm init` - * This will return a command and token. Make sure to copy this token to your clipboard -3. exit the main swarm node + * This will return a command and token. Make sure to copy them +3. exit the main Pi 4. ssh to one of the worker nodes 5. paste and run the copied command 6. do the same on the remaining worker nodes -You should now have a correctly configured cluster !! +You should now have a correctly configured cluster !! From here there +are multiple ways to go about managing your cluster. I'll demonstrate +one here but will link others too for further reading. +### **Portainer** +Portainer is a webgui that will allow us to manage the cluster, it will +make deploying and destroying containers across the cluster a breeze. +I do understand that all of what portainer does can simply be accomplished +in the command line, however portainer just makes it less hastle to manage. + +**Install Portainer** + +Firstly we want to download the yaml file that will be used to deploy +the portainer contiainer on our cluster. + +`curl -L https://downloads.portainer.io/portainer-agent-stack.yml -o portainer-agent-stack.yml` + +Now we can actually deploy portainer to the cluster using the following +command: + +`docker stack deploy -c portainer-agent-stack.yml portainer` + +Once the stack is up and running navigate to: + +`https://raspberry-ip:9443` + +where raspberry-ip is the IP address of the manager node in the swarm. + +### **Optional last step** + +If you intend to build any of your own docker images then it may be useful +to create a private repository to host any images that you need to run +across the cluster. + +to create this private repository create a file called docker-compose.yml +in a folder called repository or whatever and enter the following. +``` yaml + +version: '3.9' +services: + registry: + image: registry:2 + ports: + - 5000:5000 + volumes: + - /home//docker/registry/data:/var/lib/registry +``` + +**Be sure to change pi-user to your pi user** + +**create a file /etc/docker/daemon.json and eter the following** +``` json +{ + "insecure-registries": ["localhost:5000", ":5000"] +} +``` +where `pi-address` is the ip address of the main swarm node. + +**restart the docker service with `sudo systemctl restart docker`** + +now we need to deploy the registry to the stack like we did with portainer + +`docker stack deploy -c docker-compose.yml registry` + +and we should have a private registry setup that we can use to push our +custom docker images to. From 01ee1418203a408247f139ec23058be3c8d426b8 Mon Sep 17 00:00:00 2001 From: AHMZA Date: Thu, 23 Dec 2021 00:23:39 +0000 Subject: [PATCH 09/11] finished post ?? --- content/posts/building-a-docker-swarm-with-pis.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/content/posts/building-a-docker-swarm-with-pis.md b/content/posts/building-a-docker-swarm-with-pis.md index c4b6c04..4efedbc 100644 --- a/content/posts/building-a-docker-swarm-with-pis.md +++ b/content/posts/building-a-docker-swarm-with-pis.md @@ -2,7 +2,7 @@ title: Building a Docker Swarm With Pi's date: 2021-12-12T17:23:32Z author: "ahmza" -draft: true +draft: false weight: tags: ["Homelab","Docker","Docker Swarm","Raspberry Pi","Pi4"] @@ -379,11 +379,9 @@ multiple host groups. 5. paste and run the copied command 6. do the same on the remaining worker nodes -You should now have a correctly configured cluster !! From here there -are multiple ways to go about managing your cluster. I'll demonstrate -one here but will link others too for further reading. +You should now have a correctly configured cluster !! -### **Portainer** +### **Optional Step - Portainer** Portainer is a webgui that will allow us to manage the cluster, it will make deploying and destroying containers across the cluster a breeze. I do understand that all of what portainer does can simply be accomplished @@ -407,7 +405,7 @@ Once the stack is up and running navigate to: where raspberry-ip is the IP address of the manager node in the swarm. -### **Optional last step** +### **Optional Step - Private Registry** If you intend to build any of your own docker images then it may be useful to create a private repository to host any images that you need to run From dc7e0a646a12a144493ddfe2d0aece61d8dd7409 Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Date: Thu, 23 Dec 2021 00:27:25 +0000 Subject: [PATCH 10/11] Update .gitlab-ci.yml --- .gitlab-ci.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 195343f..c6e84ff 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -24,12 +24,8 @@ Build: - public only: - main -<<<<<<< HEAD -======= ->>>>>>> f07b1f2 (only build for changes made to main) - Dockerize: stage: dockerize image: @@ -42,8 +38,3 @@ Dockerize: - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:latest only: - main -<<<<<<< HEAD - - -======= ->>>>>>> f07b1f2 (only build for changes made to main) From 805c90a0b2f6a08dc1cf9b18722fb84d4862b0e0 Mon Sep 17 00:00:00 2001 From: AHMZA Date: Thu, 23 Dec 2021 00:32:35 +0000 Subject: [PATCH 11/11] removed learn linux from branch --- content/posts/you-need-to-learn-linux.md | 90 ----------------------- static/img/learn-linux/learn-linux.gif | Bin 6947 -> 0 bytes 2 files changed, 90 deletions(-) delete mode 100644 content/posts/you-need-to-learn-linux.md delete mode 100755 static/img/learn-linux/learn-linux.gif diff --git a/content/posts/you-need-to-learn-linux.md b/content/posts/you-need-to-learn-linux.md deleted file mode 100644 index 3cdd848..0000000 --- a/content/posts/you-need-to-learn-linux.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: You Need to Learn Linux 🐧 -date: 2021-12-17T19:16:50Z -author: "ahmza" -draft: false -weight: - -tags: ["Linux"] -description: "Ever wanted to learn Linux ? Well no better time than now to learn" -canonicalURL: "https://blog.ahmza.com/Page%28/posts/you-need-to-learn-linux.md%29" - -cover: - image: "/img/learn-linux/learn-linux.gif" # image path/url - alt: "learn-linux" # alt text - caption: "" # display caption under cover - relative: false # when using page bundles set this to true -showtoc: true -searchHidden: false ---- -## **Introduction** -I say you need to learn _Linux_ because really there is no reason not -to. If you are pursuing a career in IT then you will without a doubt -come across _Linux_ and having even basic knowledge of _Linux_ will get -you far simply because it is everywhere. Many people struggle with the -OS simply because it's fundamentally different compared to the other -operating systems but give it a bit of time, you will master the -basics and understand how much control over the system it gives you. - - -## **But Why** -As mentioned before, there isn't reason not to. **Linux is everywhere**, -from data centres to your phone. **Understanding how to use _Linux_ is -great if you in or looking at a career in IT** because not many people --relatively speaking- know how to use it, it sets you apart from others. -**I also believe _Linux_ gives you a deeper understanding of how your -system works** at a lower level which can be great when it comes to -troubleshooting. I think the most important factor is that **Linux is -open source** and so you have the ability to look at the code you are -running and with this comes full customisability of the system. - -If you consider yourself a power user then _Linux_ is the perfect -operating system due to the aforementioned customisability but also the -command line. Many people are scared away from _Linux_ as they are -intimidated by the fact that they have to use the terminal, however if -you can overcome this "fear" then you have unlocked a great power and -from my experience will start finding GUI's cumbersome. - - -## **How can you start** -There are many ways you can start using _Linux_ and a lot of them don't -require you to use _Linux_ as your main operating system. You do need -to be committed to using Linux. Try not to fall back to Windows or -MacOS if you cant figure something out, **search for solutions.** -**Lastly try to get comfortable with the terminal.** - -### **Install Linux as your main OS** -This is the **Full Send** option. This is a great option if you know -a move to Linux is something you want to commit to. I think this is the -best option as you have to start learning Linux to get things done so -you have incentive to keep going. - - -**Choosing a distro is fun but a huge time investment, you will hear the -term `distro hopping` which is installing different distributions of -_Linux_ and with the number of distros out there this can be daunting -for new users. A great Distribution that I recommend is -[Manjaro with KDE Plasma](https://manjaro.org/downloads/official/kde/) -as it offers a heavily customisable desktop environment `KDE Plasma` -and Manjaro itself is a great as it is based on Arch Linux so it can -leverage the power of the AUR (Arch User Repository) - -### ***MacOS*** **Terminal** -_MacOS_ is actually _UNIX_ based and so **if you have an _apple Mac/MacBook_ -all you need is to open the Terminal** application and start playing -around. I used this option for a while on my work machine and it works -great. You get the best of both worlds with this option so if you have -a MacOS device then this is a solid option. Not recommended if you -don't have one of these devices simply due to cost 💸 - -### ***Windows WSL*** -The _Windows Subsystem for Linux_ is another great option to get started -with _Linux_ as it installs the _Linux Kernel_ natively in windows and -allows you to play around with a real _Linux_ environment, before doing -a full send on my main machine this is the option I used. - -### **Virtual Machines** -If there is a specific Distribution of _Linux_ you want to try without -doing a Full Send then this is a great option however if you want to -simply get to know the _Linux_ then choose the _MacOS_ terminal or _WSL_ -methods as they are a lot lighter. diff --git a/static/img/learn-linux/learn-linux.gif b/static/img/learn-linux/learn-linux.gif deleted file mode 100755 index 11dae8c83b683caafb63d1938ef1dcd461c001b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6947 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 D5a2Ob