I built a Raspberry Pi cluster and decided to look into getting OpenFaaS running on it.
OpenFaaS let’s you build and deploy serverless functions, which I think of as small containers that can scale to zero. They have a listener that is on standby ready for you to trigger the function via the API or from the OpenFaaS GUI.
I made the decision to also stand up a Kubernetes cluster for OpenFaaS to run on.
Was up pretty late getting these OpenFaas pods working. I learned that Tiller and Flannel don't always work very well on ARM systems. But hey... There is no better way to learn #K8s than to have to troubleshoot crashed pods. pic.twitter.com/EAJRsl1Mwz— Colin McCarthy (@Colinnation) July 8, 2019
*If I was starting over I would go with the more lightweight K3s by Rancher Labs over Kubeadm.
If you're interested in going that route there is a blog that Alex Ellis has written for using K3s that can be found here...
Using OpenFaaS Templates
After I got Kubernetes working and got OpenFaaS stood up I decided to create a function that would use Ansible to open a ServiceNow ticket. OpenFaaS has a collection of templates you can pick from to create your functions. I tried a few different ways and eventually settled on using a Dockerfile template. I have plans to also try out some Netmiko functions via the Python3 template and also some Nornir functions. Stay tuned for those in another upcoming blog post about auto-remediation with functions.
The Dockerfile I used is below. Now I’m also sourcing the container from a custom Docker image that I made named alpine-snow which has Ansible and the pysnow Python library installed. I pushed this up to Dockerhub and OpenFaaS grabbed it from there. After the first time the image is pulled down it's available locally after that. Doing this saved me from having to pull down Ansible during the actual function, which frankly would have taken a long time on my Raspberry Pi cluster.
The Ticketing Function That I built
FROM openfaas/classic-watchdog:0.13.4 as watchdog FROM cmccarth/alpine-snow:latest USER root RUN mkdir -p /app COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog RUN chmod +x /usr/bin/fwatchdog # Add SNOW ENV vars ENV SN_USERNAME "admin" ENV SN_PASSWORD "omitted" ENV SN_INSTANCE "omitted" # Add non root user RUN addgroup -S app && adduser app -S -G app RUN chown app /home/app WORKDIR /home/app USER app RUN git clone https://github.com/colin-mccarthy/env_vars WORKDIR /home/app/env_vars ENV fprocess="ansible-playbook create_ticket.yml -i hosts" # Set to true to see request in function logs ENV write_debug="false" EXPOSE 8080 EXPOSE 31112 EXPOSE 22 HEALTHCHECK --interval=3s CMD [ -e /tmp/.lock ] || exit 1 CMD ["fwatchdog"] ENV read_timeout="120" ENV write_timeout="120"
*The Ansible module being used is a fun project myself and a friend Luke Short worked on a while back to add the ability to use ENV vars with the snow_record module.
It can be found here on GitHub.
The OpenFaaS GUI
Here you can see a successful execution of my function from the OpenFaaS GUI.
Once I tested my function in the OpenFaaS GUI and saw that it was working it was time to automate the ticket creation. I stood up Zabbix an open source network monitoring tool in a Docker container and built a trigger and an action. The trigger is setup to alarm if my Cisco 3560 switch reboots. The action will curl the OpenFaaS function running on my Raspberry Pi cluster and should use Ansible to create a ticket in my free ServiceNow developers instance.
This was fairly easy as I just added a curl command to the Zabbix alarm
This worked fine to prove out my minimal solution but I plan to take it further and add the host into the curl when I revisit this project. That way the ticket can include some device specific info and probably use some of the pyATS playbooks I have blogged about before to gather facts. That may be better for other types of alarms where the device doesn’t lose connectivity.
You can see the size of my alpine-snow container compared to a typical alpine container. I think it would be fun to try and see how small I could get this and still have it function. I have considered creating a smaller version of Ansible by removing all of the modules in the Library directory. As well as any other plugins and what not that I’m not going to be using. It’s funny because while I was working on this Ansible announced a move to using collections, which sort of aligns with what I was thinking about. Remove a number of the modules for the main Ansible package and have people only install the collections they want.
If you're interested in building a similar Raspberry Pi cluster the case was purchased on Amazon from C4Labs.
I found this project to be very informative and fun. I learned about Containers, Docker, DockerHub, Kubernetes, K3s, and OpenFaaS, all of which were subjects I hadn't spent much time on before.
Stay tuned for more blogs
TheNetwork.Engineer - Aug 26 2019 - Colin McCarthy