Post Tags

Running Hubot on Kubernetes

Introduction

 

In this blog we’re going to create a Hubot installation in Kubernetes with a Slack adapter. We’re assuming you have nothing but an interest in running Hubot within your organization, so we’ll be working through the entire process of setting up a Hubot Repo, configuring Slack, getting a Docker container for Hubot, and hosting it in Kubernetes. 

 

This guide will cover creating a basic Hubot installation, but I highly recommend configuring a brain for Hubot. A Hubot brain is a storage layer so Hubot has persistence. The most common brain is Redis so I will cover configuring Hubot for using Redis; however, I will not be covering how to setup Redis itself.

 

Creating the repository

 

To begin, you must have Git, Node, and NPM installed on your computer. Next we’re going to start by generating a Hubot repository. This will be the central location for all of your Hubot scripts. It will also host the Dockerfile for running Hubot. To generate the hubot repository run the following commands:

 

npm install -g yo generator-hubot
mkdir <Clever name for your bot>
cd <Clever name for your bot>
yo hubot


# The `yo hubot` command is going to have some configuration options you must fill out:

 

Option

Description

--owner="Bot Wrangler <bw@example.com>"

Bot owner, e.g. “Bot Wrangler bw@example.com”

--name="Hubot"

Bot name, e.g. “Hubot”

--description="Delightfully aware robot"

Bot description, e.g. “Delightfully aware robot”

--adapter=slack

Bot adapter, e.g. “slack”

 

Next, let’s get git initialized:

 

git init
git add .
git commit -m "Initial commit"

 

Great! This repository will be the basis for creating your very own Hubot scripts for your organization. By default, Hubot has no scripts enabled. Let’s take a look at the example.coffee script in the scripts direction of the repository you just created. The beginning of the file should look something like this:

 

# Description:
#   Example scripts for you to examine and try out.
#
# Notes:
#   They are commented out by default, because most of them are pretty silly and
#   wouldn't be useful and amusing enough for day to day huboting.
#   Uncomment the ones you want to try and experiment with.
#
#   These are from the scripting documentation: https://github.com/github/hubot/blob/master/docs/scripting.md

module.exports = (robot) ->

  # robot.hear /badger/i, (res) ->
  #   res.send "Badgers? BADGERS? WE DON'T NEED NO STINKIN BADGERS"

 

We are going to uncomment the following two lines:

 

# robot.hear /badger/i, (res) ->
#   res.send "Badgers? BADGERS? WE DON'T NEED NO STINKIN BADGERS"

 

With these two lines uncommented, Hubot will respond with "Badgers? BADGERS? WE DON'T NEED NO STINKIN BADGERS" anytime it sees the word “badger”. Not the most useful script, but it’s a start!

 

(Optional) Installing Third Party Scripts

 

With Hubot there is an abundance of scripts already available from the open source community. In your terminal you should be able to run a specific command to search for and then add these scripts to your Hubot. I am going to give an example of how to search for and then install scripts but this section is not required to get hubot running. As an example, if I were interesting in a Jenkins script I could do the following:

 

$ npm search hubot-scripts jenkins
NAME                      | DESCRIPTION | AUTHOR          | DATE | VERSION | KEYWORDS
hubot-jenkins-notify-stat | Notify if jenkins...   | =danpoltawski   | 2019-02-04 | 0.1.3    | hubot hubot-scripts
uschanges                 | |               | | |
hubot-jenkins-gof         | Jenkins support for... | =gabealmer      | 2016-09-16 | 0.0.1   | hubot hubot-scripts
hubot-jenkins-connector   | Jenkins integration... | =oltruong       | 2019-10-28 | 1.2.1 | hubot hubot-scripts
hubot-jenkins-optimised   | Jenkins integration... | =rohitjmathew   | 2019-05-31 | 1.0.6 | hubot hubot-scripts hubot-jenkins
hubot-sbueringer-jenkins  | Jenkins Integration... | =sbueringer     | 2017-05-28 | 1.1.4 | hubot hubot-scripts
hubot-jenkins-notifier    | Notifies about... | =halkeye        | 2017-04-25 | 1.1.0 | hubot hubot-scripts jenkins
hubot-jenkins-userauth    | Interact with... | =benwtr         | 2017-11-16 | 0.0.5 | hubot hubot-scripts jenkins
hubot-jenkins-enhanced    | Jenkins integration... | =wintondeshong  | 2018-10-04 | 1.2.2 | hubot hubot-scripts
hubot-jenkins             | Jenkins Integration... | =balbeko        | 2014-07-30 | 1.0.2 | hubot hubot-scripts
hubot-jenkins-x           | Jenkins Integration... | =zhanyi         | 2018-07-20 | 1.0.3 | hubot hubot-scripts hubot-jenkins
hubot-jenkins-enhanced-im | Jenkins integration... | =zack-hable     | 2018-07-27 | 1.0.0 | hubot hubot-scripts
proved                    | |               | | |
hubot-yardmaster          | Hubot Script for...    | =riveramj       | 2016-06-08 | 1.0.30   | hubot hubot-scripts jenkins git branch CI
hubot-waiter              | A hubot integration... | =andremw        | 2016-08-24 | 0.0.16 | hubot hubot-scripts jenkins ci
hubot-scripts-deploy      | A Hubot script to... | =marianitadn    | 2017-11-24 | 0.3.0 | hubot deploy ci
bitbucket2jenkins         | hubot scripts:... | =im-ikeda       | 2016-01-13 | 0.0.9 | hubot hubot-scripts bitbucket jenkins

 

After looking through the options I decide on the hubot-jenkins-optimized script. To add this to my Hubot all I need to do is run:

 

npm install hubot-jenkins-optimised --save

 

And then add hubot-jenkins-optimized to my external-scripts.json file in the repository like so:

 

[
  "hubot-jenkins-optimised"
]

 

If there are other scripts in the file, just add hubot-jenkins-optimized to the array. Scripts may require additional configuration to work, so please read the author’s documentation.

 

Getting Slack configured

 

Next we need to perform some configuration in Slack. You will need to be an admin in order to perform the next steps. If you’re not a Slack admin, you can still perform the steps and Slack will send a request for approval to existing admins but you will need to wait for their approval before the integration will work. While there are a couple of ways to get Slack and Hubot working together, a Slack App is the recommended way.

 

Slack apps are a container for many capabilities in the Slack platform, and let you access those capabilities in a single place. To begin, you just need a Bot User.

  1. Create a new app at the app management page. Pick a clever name and choose the workspace you want Hubot installed in.
  2. Navigate to the Bot User page and add a bot user. The display name is the name your team will use to mention your Hubot in Slack.
  3. Navigate to the Install App page and install the app into the workspace. Once you’ve authorized the installation, you’ll be taken back to the Install App page, but this time you’ll have a Bot OAuth Access Token. Copy that value and store it for later, it will be your Slack token.

You’ll be using this Bot OAuth Access Token in the HUBOT_SLACK_TOKEN environment variable later. The hubot_slack script was installed as part of choosing your adapter earlier and will respond to this variable.

(Optional) A brain for the bot!

A Hubot brain is a mechanism for persistence in Hubot. You may need this if you use scripts such as hubot-auth where you can specify which users can take certain actions. In order to give the bot a Redis brain we need to install the hubot-redis-brain external script. Follow the process from the Installing Third Party Scripts section. The script will respond to the REDIS_URL environment variable, which we will be setting in the next section.

Creating the Dockerfile, building, and testing

 

For the next step, we will be creating a container to run Hubot in. You will need Docker installed, so please follow the documentation here to get Docker set up. Shoutout to hubot-rocketchat which the following Dockerfile is based on. Create a file named Dockerfile in the root of your hubot repository and enter these lines into it:

# Hubot needs node to run.
FROM node:13

# Environment variables:
# Forces non-interactive mode for apt commands.
ENV DEBIAN_FRONTEND "noninteractive"
# A placeholder for the Bot OAuth Access Token.
ENV HUBOT_SLACK_TOKEN "nope-1234-5678-91011-00e4dd"
# The clever name you came up with earlier.
ENV HUBOT_NAME "<The clever name you came up with>"
# The person to contact if Hubot breaks.
ENV HUBOT_OWNER "<Some email address>"
# A description for the bot if you want one. This is more
# important if you have multiple bots.
ENV HUBOT_DESCRIPTION "A simple helpful robot for <Your Organization>"
# (Optional) the URL for hubot-redis-brain.
ENV REDIS_URL "redis://<Your Redis URL:PORT>/hubot"

# Create a user to run Hubot as.
RUN useradd hubot -m
# Copy this repository to the user's home directory.
COPY . /home/hubot
# And make sure that the files have the right owner and group.
RUN chown -R hubot:hubot /home/hubot

# Use the new user for running commands.
USER hubot
# Set the working directory to be the user's home directory.
WORKDIR /home/hubot
# Install dependencies.
RUN npm install

# Set a default command to run Hubot!
CMD ./bin/hubot -n $HUBOT_NAME -a slack

 

Great! We now have a Dockerfile that can run Hubot. Please note, I do not recommend placing secrets in your Dockerfile. We will be using configmaps in Kubernetes later to hold the secrets. To build the container run this command:

 

docker build . --no-cache -t <The clever name you came up with>:latest

 

Now you can run Hubot for the very first time! To run your container enter this command:

 

docker run -it -e "HUBOT_SLACK_TOKEN=<Your Bot OAuth Token>" <The clever name you came up with>

 

The container should start without a problem. Now create a channel in Slack and invite your bot by running /invite @<The clever name you came up with> and type @<The clever name you came up with> ping. You should receive the word PONG in response:

Screen Shot 2019-12-31 at 10.09.06 AM

Nice! We have the bot working! Before moving on to the Kubernetes configuration, we will need to push the container to a container repository.  Docker Hub is a popular and easy choice. Go ahead and create an account on Docker Hub and then create a repository for your bot that is named with the clever name you came up with. You can log into your account via the command line by running docker login and following the prompts. After that, upload your container by running:

 

docker push <Your Docker Hub username>/<The clever name you came up with>:latest

 

Kubernetes Configuration

 

Now that we have a working bot, let’s get it running in Kubernetes. This is actually a fairly simple process but you will need to have kubectl installed with the appropriate level of access to create deployments and configmaps. I am going to be using the default namespace here, but feel free to change to any other you prefer. I am also going to assume that your bot is available publicly, if you want to host your bot’s container privately please see the documentation here. Let’s start the deployment process by creating the configmap. To do this, create a file name hubot.properties with the following line in it:

 

HUBOT_SLACK_TOKEN=<Your Bot OAuth Token>

 

To add the configmap to Kubernetes we need to run this command:

 

kubectl create configmap hubot --from-file=hubot.properties

 

By creating the configmap you can avoid having to keep secrets in the container or the Dockerfile. This will be particularly useful as you develop more scripts for Hubot that need access to more tools such as Jenkins or Spinnaker. Next we are going to create a deployment. This will describe what container for Kubernetes to run and more information about the configuration for this container, like the configmap. I am not going to go into detail about the deployment but extensive documentation can be found here. Create a file called hubot_deployment.yml and enter the following text:

 

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: hubot
  namespace: default
spec:
  revisionHistoryLimit: 1
  replicas: 1
  selector:
    matchLabels:
      app: hubot
  template:
    metadata:
      labels:
        app: hubot
    spec:
      containers:
        - name: hubot
          image: <Your Docker Hub username>/<The clever name you came up with>:latest
          imagePullPolicy: Always
          envFrom:
            - configMapRef:
                name: hubot

 

Once the hubot_deployment.yml file is created, you can send the deployment to Kubernetes via this kubectl command:

 

kubectl apply -f hubot_deployment.yml

 

You can check on the status of the deployment by running:

 

kubectl describe deployment hubot

 

You’ll be looking for a line that says something like:

 

Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable

 

If you see that zero are unavailable then Hubot should be up and running! Go back to your test channel and run @<Your clever name> ping and see if you get a PONG and that’s it! You;ve got Hubot up and running in Kubernetes. Now you can add more functionality to your bot. At iSeatz, we use our to Hubot to run Jenkins jobs, lookup configuration settings, and more! ChatOps is definitely a huge convenience that your organization will love! There is so much you can do with Hubot and for more information about Hubot please see Hubot’s documentation here.

Loyalty Integrated Food Delivery
Food delivery usage has grown 300% during COVID-19. Connect your members with delicious, convenient rewards.