From 0 to Kubernetes – Step 5, actually doing something with it

Let’s deploy something useful now.

How about rundeck? Rundeck is a remote management tool (not completely unlike Ansible Tower) that basically lets you remotely run commands on nodes.

Let’s deploy that in our K3s instance.

Rundeck does not need all that much to run in K3s.

First, we need a namespace to put it in:

apiVersion: v1
kind: Namespace
metadata:
  name: rundeck

Rundeck needs a place to keep its data. Lets create storage space – in Kubernetes (amd k3s) that needs a PersistentVolumeClaim:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: rundeck-pvc
  namespace: rundeck
  labels:
    app: rundeck-app
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

Another thing we need is a service, to tell Kubernetes that there’s something listening on some port for communication from the outside – otherwise the app would not be reachable at all. The service definition looks like this:

apiVersion: v1
kind: Service
metadata:
  namespace: rundeck
  name: rundeck-svc
  labels:
  app: rundeck-app
spec:
  ports:
    - port: 4440
  selector:
    app: rundeck-app

Now we need a Deployment to tie it all together:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rundeck-app
  namespace: rundeck
  labels:
    app: rundeck-app
spec:
  selector:
    matchLabels:
      app: rundeck-app
  template:
  metadata:
  labels:
    app: rundeck-app
  spec:
    containers:
    - name: rundeck-app
      image: rundeck/rundeck:3.3.10
      env:
      - name: RUNDECK_GRAILS_URL
        value: https://rundeck.apps.my.lan
      - name: EXTERNAL_SERVER_URL
        value: https://rundeck.apps.my.lan
      ports:
      - containerPort: 4440
      volumeMounts:
      - name: rundeck-persistent-storage
        mountPath: /home/rundeck/server/data
    volumes:
    - name: rundeck-persistent-storage
      persistentVolumeClaim:
        claimName: rundeck-pvc

Note the two environment variables here. Without $RUNDECK_GRAILS_URL and $RUNDECK_SERVER_URL all urls generated inside the app would point at 127.0.0.1 which would be less than useful…

So the last thing would be to create a route in traefik that uses the name we put into these two variables, and points at the service we have defined:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: ingressroutetls
  namespace: rundeck
spec:
  entryPoints:
  - websecure
  routes:
  - match: Host(`rundeck.apps.my.lan`)
    kind: Rule
    services:
    - name: rundeck-svc
      port: 4440
  tls: {}

Again, the line tls: {} tells traefik to use the default certificate we have set up.

When you tie it all into one yaml file, don’t forget to put the separators in. The final deployment is here.

After applying it with kubectl apply -f (filename) you should see this in your K3s:

lemmy@akari:~> kubectl get all -n rundeck
NAME READY STATUS RESTARTS AGE
pod/rundeck-app-5b9dc4d485-jkwqv 1/1 Running 0 4d20h

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/rundeck-svc ClusterIP 10.43.15.90 <none> 4440/TCP 4d20h

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/rundeck-app 1/1 1 1 4d20h

NAME DESIRED CURRENT READY AGE
replicaset.apps/rundeck-app-5b9dc4d485 1 1 1 4d20h

You should also be able to access rundeck on https://rundeck.apps.my.lan and see a log in prompt where you login with the username admin and the password admin.

Continued here.

1 thought on “From 0 to Kubernetes – Step 5, actually doing something with it

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: