Merge branch 'pi-docker-swarm' into 'main'

Pi docker swarm

See merge request AHMZA/blog!5
This commit is contained in:
Hamza Ahmed
2021-12-23 00:36:38 +00:00
2 changed files with 278 additions and 4 deletions
+1
View File
@@ -25,6 +25,7 @@ Build:
only: only:
- main - main
Dockerize: Dockerize:
stage: dockerize stage: dockerize
image: image:
@@ -2,7 +2,7 @@
title: Building a Docker Swarm With Pi's title: Building a Docker Swarm With Pi's
date: 2021-12-12T17:23:32Z date: 2021-12-12T17:23:32Z
author: "ahmza" author: "ahmza"
draft: true draft: false
weight: weight:
tags: ["Homelab","Docker","Docker Swarm","Raspberry Pi","Pi4"] tags: ["Homelab","Docker","Docker Swarm","Raspberry Pi","Pi4"]
@@ -145,7 +145,7 @@ self explanitory. So go ahead and assemble the cluster 🛠
file system** file system**
### **Sort out the Network bits** ### **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 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 the device itself. Personally I prefer to set static IPs on the
device itself so I will cover that here. 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 To find the current ip of your Pis you can go to your DHCP server
and look for the DHCP leases for the Pis. 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 **SSH to the Pi** then open and edit the following files
* /etc/hosts * /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 * /etc/hostname
* edit this file with your hostname: ```mainpi``` * edit this file with your hostname: ```goob```
* /etc/dhcpcd.conf * /etc/dhcpcd.conf
* knowing we will be using only static IPs here I delete * knowing we will be using only static IPs here I delete
everything in the file add the following everything in the file add the following
@@ -169,4 +175,271 @@ and look for the DHCP leases for the Pis.
``` ```
**Now reboot the pi** ```sudo shutdown -r now``` **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.
> 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
---
- hosts: piCluster
become: yes
tasks:
- name: Configure SSH
block:
- name: Auth local SSH Keys
ansible.posix.authorized_key:
user: <pi_user>
state: present
key: "{{ item }}"
with_file:
- /home/<local_user>/.ssh/id_rsa.pub
- ./pi_rsa.pub
- name: Copy SSH Pi Intercoms Private Key
copy:
src: ./pi_rsa
dest: /home/<pi_user>/.ssh/id_rsa
mode: '0600'
owner: <pi_user>
group: <pi_user>
- name: Copy SSH Pi Intercoms Public Key
copy:
src: ./pi_rsa.pub
dest: /home/<pi_user>/.ssh/id_rsa.pub
mode: '0644'
owner: <pi_user>
group: <pi_user>
- 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: 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: <pi_user>
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: Install docker compose
command: sudo pip3 -v install docker-compose
when: dc_version.stdout.find('docker-compose 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
* Download the Docker Script
* Install Docker from script
* Enable the Docker service
* Add user to Docker group
6. Check if docker-compose is installed
* 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**
``` 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
**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`
* `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 manual and tedious so
this is something you could impliment into the ansible playbook using
multiple host groups.
**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 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 !!
### **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
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 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
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/<pi-user>/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", "<pi-address>: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.