After setting up Jenkins to auto build and deploy my IRC bots, I decided to add the next component of a CI/CD stack, automated testing. This was to use ant to run the tests, and JUnit for the testing framework for the application. I’ll be setting this up in both of my Jenkins projects, I have one that just builds my applications, and a second that builds the docker containers and pushes them to the repository.
My Jenkins setup includes 2 builds for each of my projects:
Builds the java application
This is just a general Jenkins project that uses ant to build
Builds the docker container, tags it, and pushes it to my local docker repository
This uses Jenkins pipelines to perform the build, tag, push
The docker build pushes my production code and is used by my docker-swarm to update my locally built containers. This is the important build. The general java build is just me experimenting with Jenkins builds following the non-pipeline route.
After my initial jenkins setup, I thought my system would be good to go for a long time, however I encountered a problem with permissions after my docker cluster reboot. After all my nodes were back up, and jenkins was running, it could no longer access the docker.sock that it used to handle building and pushing containers. I tried a few things, rebuilding the container, updating it, changing some groups, and found quite a few threads on the topic. Some people had chmod’d the docker.sock to 777 (BAD) or had given jenkins root (ALSO BAD). I ended up finding the solution in using a specific entrypoint script that would determine the group to add to the jenkins user, then launch jenkins using the jenkins user from root.
Most of my additions are from sudo-bmitch’s jenkins-docker repository on GitHub. These include the dockerfile changes and the entrypoint.sh script (as well as the healthcheck mentioned later on).
Due to unforeseen events, I ended up having to shutdown all of my servers. Due to this, my docker VM cluster ended up getting its first chance to reboot the entire stack of all nodes. This ended up showing some problems in my configuration sadly, as well as a docker issue I had previously encountered in my raspberry pi cluster.
I’ve always wanted to experiment with clustering technologies, I tried setting up a kubernetes cluster however that ended in failure. For this next experiment, I went with something simpler to deal with, docker swarm. Since docker and swarm are supported on raspberry pi’s, and since i had a number of raspberry pi’s not in use, I decided to use them for the cluster.
I printed a 2U rack mount kit for raspberry pis. I felt like this would be the perfect time to make use of it. I racked up 2 raspberry pi 3B+ units with POE hats (more on that later) and went to use those for the docker cluster. I added Samsung 32GB micro sd cards for storage.
I was originally running a home assistant VM using a script that loaded HASS into proxmox, however the HASS.io image didn’t have the tooling that I like having on a machine for general management of the system. I started researching and took a few turns around to find the right installation script, but I did and included the commands below. The following shell commands and script install Home Assistant Supervised on a general X86 machine. This worked fine on Ubuntu 18.04 LTS.
The default port for HASS is 8123, so go to the server IP:8123 to finish configuration. This will give you all the benefits of the HASSio images for raspberry pi and intel nucs but with your own preferred operating system rather than using the build thats included with the home assistant built images (which are very limited).
While using MotionEyeOS on a raspberry pi 3 worked for a while, eventually I began to need a bit more hardware to handle some of the security camera goals I had. For this, since I already had my hand crafted 19in rack, I wanted to find a decent rack mount server for it, preferably SuperMicro.
I ended up finding a Redwood Director RDIR-1G on ebay for a good price. After doing some research, it l found out that it was a SuperMicro box, specifically it was a 5018D-MF. This is a solid little 1U half depth box with an E3 server processor on it. The listing claimed it had 32GB of RAM, however I found out later that it only had 8GB ram. This was still a pretty decent deal and I went with it.
Of course, once it arrived whats the first thing we do, open it up.
Why not? In reality, I always wanted to play with clustering, originally with proxmox and ceph, but I never had enough hardware to do so. I do however have a proxmox node with enough ram that I can host multiple lightweight nodes.
Docker swarm is lightweight enough that I can virtualize the entire cluster on my single proxmox host. While this isn’t fault tolerant like a cluster across multiple nodes, it does mean I can reboot cluster nodes for kernel updates and maintain my uptime. I also am able to add additional docker swarm nodes on separate hardware if I get additional hardware, and there is the benefit of having the cluster load balance itself for which software is running on which node.
Each node in the cluster is identical, each can be replaced by following the exact same process and while I don’t have automated deployment of new nodes, they are still closer to cattle than many of my other virtual machines. Due to the goal of replicated storage between the nodes, I should also be able to take a single node and rebuild the entire cluster if needed, since it would have the entire clusters configuration.
I’ve been trying to come up with a way to handle storing and version controlling my 3D models (both from thingiverse, and models I create myself), however i ran into quite a few deadends when looking for software built for this purpose (PLM/PDM), so I’ve figured it would easiest to build a folder structure with some metadata alongside it to go on top of GIT, and allow GIT to deal with version control. While STL files are text, a majority of my models are in proprietary binary formats, but GIT can still at least store the files and provide a history. I figure the repository would have 3 primary folders, parts, products, 3rd party (more or less unstructured). Each part/product would also have an export folder which will store a copy of STLs, and metadata to go with for a specific published version of a model (might be duplicate data, maybe use some type of tag in GIT to represent each officially published version).
Parts: not very useful as a single component, but used to create products, or as spare components to some item
Products: a grouping of parts to encompass a single object, or a single piece that makes up the object (think one piece phone stand, vs a multi-piece assembly). While these may seem separate in their usage, they will be the final product of whatever is created.
3rd party: these may or may not follow the data policies, things like the ultimaker 2 models/plans and the backblaze storage pod models which are neat to have, but we won’t be applying our policies to those large assemblies. These can also include the innumerable thingiverse models we all acquire, eventually the goal will be to incorporate all thingiverse metadata into the dataset as well to provide details locally for all models herin.
Exports: Each part or product can have versioned exports as well, these will be one specific version of the STL, assembly, and tags, allowing a product to reference the version of the export until both are updated to support newer versions or varients.
I wrote a number of IRC bots a number of years ago, hosting them on my infrastructure. Since building a 3 node docker swarm, I decided that these would be good candidates to use in learning Jenkins for both auto building the software, and building containers. I hadn’t made my own dockerfiles before, nor had I setup proper builds outside of my IDE for these bots before.
Like many, I had issues with sqlite database corruption on Unraid. I found while researching it that it had to do with file locks in the fuse file system unraid uses to merge disks. I found the best way to circumvent this is to use the cache disk for those databases and map them directly. My docker mappings now point to /mnt/cache/share instead of going /mnt/user/share. This solved the issue better than the 6.8.0rc5 fixes. This avoids the system in question completely and solved the stability issues for me.