spacemanspiff2007 / HABApp

Easy home automation with MQTT and/or openHAB
Apache License 2.0
54 stars 23 forks source link

Kubernetes Deployment Using Docker Image #456

Open RichieRogers opened 3 weeks ago

RichieRogers commented 3 weeks ago

Hi, I've been running OpenHab & HabApp for a few years now - first on Windows, currently on Raspberry Pi and soon moving to Kubernetes. I've managed to get the HabApp Docker deployment to deploy to my Kubernetes cluster, but I'm having issues trying to get the config.yml file (stored as a ConfigMap) to replace the default config file. I've tried the following:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pv-habapp
  namespace: openhab
spec:
  storageClassName: rook-ceph-block
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

apiVersion: apps/v1
kind: Deployment
metadata:
  name: habapp
  namespace: openhab
  labels:
    app: habapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: habapp
  template:
    metadata:
      labels:
        app: habapp
    spec:
      hostNetwork: true
      containers:
      - name: habapp
        image: spacemanspiff2007/habapp:latest
        volumeMounts:
        - name: habapp-config   # issue with this overwriting the config - how do we replace default config????????
          mountPath: /habapp/config
          readOnly: false
      volumes:
      - name: habapp
        persistentVolumeClaim:
          claimName: pv-habapp
      - name: habapp-config
        configMap:
          name: habapp-config

However, if I set it to read only, the deployment fails, setting read only to false and the config gets overwritten by the default config. I'm pretty new to both Docker and Kubernetes, so any help would be much appreciated.

Thanks, Richie

RichieRogers commented 16 hours ago

I managed to resolve this by editing the Dockerfile to remove the config mapping and building my own image from that. I can now use ConfigMap to pass in my config.yml & logging.yml.

Thanks, Richie

spacemanspiff2007 commented 15 hours ago

Can you describe or provide an example of what you did. Maybe I then can add it to the docs?

RichieRogers commented 14 hours ago

Hi, Sure. I downloaded the source and edited Dockerfile:

FROM python:3.11 as buildimage

COPY . /tmp/app_install

RUN set -eux; \
# wheel all packages for habapp
    cd /tmp/app_install; \
    pip wheel --wheel-dir=/root/wheels .

FROM python:3.11

COPY --from=buildimage /root/wheels /root/wheels
COPY container/entrypoint.sh /entrypoint.sh

ENV HABAPP_HOME=/habapp \
    USER_ID=9001 \
    GROUP_ID=${USER_ID}

RUN set -eux; \
# Install required dependencies
    apt-get update; \
    DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
        gosu \
        tini; \
    ln -s -f $(which gosu) /usr/local/bin/gosu; \
    apt-get clean; \
    rm -rf /var/lib/apt/lists/*; \
    mkdir -p ${HABAPP_HOME}; \
    mkdir -p ${HABAPP_HOME}/config; \   <---- deleted this line
# install HABApp
    pip3 install \
        --no-index \
        --find-links=/root/wheels \
        habapp; \
# prepare entrypoint script
    chmod +x /entrypoint.sh; \
# clean up
    rm -rf ${HABAPP_HOME}/config; \  <---- added this line
    rm -rf /root/wheels

WORKDIR ${HABAPP_HOME}
VOLUME ["${HABAPP_HOME}/config"]  <---- deleted this line
ENTRYPOINT ["/entrypoint.sh"]

CMD ["gosu", "habapp", "tini", "--", "python", "-m", "HABApp", "--config", "./config"]

entrypoint.sh:

#!/bin/bash -x

set -euo pipefail

NEW_USER_ID=${USER_ID}
NEW_GROUP_ID=${GROUP_ID:-$NEW_USER_ID}

echo "Starting with habapp user id: $NEW_USER_ID and group id: $NEW_GROUP_ID"
if ! id -u habapp >/dev/null 2>&1; then
  if [ -z "$(getent group $NEW_GROUP_ID)" ]; then
    echo "Create group habapp with id ${NEW_GROUP_ID}"
    groupadd -g $NEW_GROUP_ID habapp
  else
    group_name=$(getent group $NEW_GROUP_ID | cut -d: -f1)
    echo "Rename group $group_name to habapp"
    groupmod --new-name habapp $group_name
  fi
  echo "Create user habapp with id ${NEW_USER_ID}"
  adduser -u $NEW_USER_ID --disabled-password --gecos '' --home "${HABAPP_HOME}" --gid ${NEW_GROUP_ID} habapp
fi

chown -R habapp:habapp "${HABAPP_HOME}/config"   <---- remove the "/config"
sync

exec "$@"

My Kubernetes deployment file looks like:

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pv-habapp
  namespace: openhab
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: habapp
  namespace: openhab
  labels:
    app: habapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: habapp
  template:
    metadata:
      labels:
        app: habapp
    spec:
      hostNetwork: true
      containers:
      - name: habapp
        image: my_modifiedimage/repository:habapp-24.8.1
        volumeMounts:
        - name: habapp-config
          mountPath: /habapp/config/config.yml
          subPath: config.yml
          readOnly: false
        - name: habapp-logging
          mountPath: /habapp/config/logging.yml
          subPath: logging.yml
          readOnly: false
        - name: habapp-rule-test
          mountPath: /habapp/rules/habapp-rule-test.py
          subPath: habapp-rule-test.py
          readOnly: false

      imagePullSecrets:
      - name: regcred
      volumes:
      - name: habapp
        persistentVolumeClaim:
          claimName: pv-habapp
      - name: habapp-config
        configMap:
          name: habapp-config
      - name: habapp-logging
        configMap:
          name: habapp-logging
      - name: habapp-rule-test
        configMap:
          name: habapp-rule-test

It's probably not the best way to do it, as I'll have to re-apply the deployment every time I create/update/delete a rule, but it should work well enough for my purposes. A possibly better option might be to map the rules to an NFS share, where they can be easily edited - presumably the folder watcher would still pickup those changes?

Thanks, Richie