diff --git a/changelogs/fragments/feature_kubernetes.yml b/changelogs/fragments/feature_kubernetes.yml
new file mode 100644
index 00000000..4e09589f
--- /dev/null
+++ b/changelogs/fragments/feature_kubernetes.yml
@@ -0,0 +1,4 @@
+---
+major_changes:
+ - Add a role for the installation and configuration of `Icinga for Kubernetes `_.
+ - Add tasks to role :code:`icingaweb2` to install and configure `Icinga for Kubernetes Web `_.
\ No newline at end of file
diff --git a/doc/role-icinga_kubernetes/role-icinga_kubernetes.md b/doc/role-icinga_kubernetes/role-icinga_kubernetes.md
new file mode 100644
index 00000000..70c0a894
--- /dev/null
+++ b/doc/role-icinga_kubernetes/role-icinga_kubernetes.md
@@ -0,0 +1,75 @@
+# Role icinga.icinga.icinga_kubernetes
+
+This role installs and configures the Icinga Kubernetes Daemon. In addition it can also import the schema into the database.
+More information about this package can be found [in the official documentation](https://icinga.com/docs/icinga-for-kubernetes/latest/doc/01-About/).
+
+## Database
+
+Icinga Kubernetes relies on a relational database to persist received data. This database **won't** be created by this role - you need to deploy and configure one in advance. For more information, see the [Databases](../getting-started.md#databases) section in the getting started guide.
+
+## Variables
+
+The following variables define the configuration for Icinga Kubernetes. Some variables got predefined [defaults](../../roles/kubernetes/defaults/main.yml), others are purely opt-in.
+
+For more information on the respective settings please see [the official documentation](https://icinga.com/docs/icinga-for-kubernetes/latest/doc/03-Configuration/).
+
+### Database Configuration
+
+| Variable | Type | Description | Default |
+|----------|------|-------------|---------|
+| `icinga_kubernetes_database_host` | `String` | Defines database address to connect to. | `127.0.0.1` |
+| `icinga_kubernetes_database_import_schema` | `bool` | Defines whether to import the schema into the database or not. **Needs `icinga_kubernetes_database_type` to be set**. | `false` |
+| `icinga_kubernetes_database_name` | `String` | Defines the database to connect to. | `kubernetes` |
+| `icinga_kubernetes_database_password` | `String` | Defines the database password to connect with. | `kubernetes` |
+| `icinga_kubernetes_database_port` | `int` | Defines the database port to connect to. | **n/a** |
+| `icinga_kubernetes_database_type` | `mysql` | Defines database type set in `config.yml`. | `mysql` |
+| `icinga_kubernetes_database_user` | `String` | Defines database user set in `config.yml`. | `kubernetes` |
+
+### Icinga Kubernetes Configuration
+
+The following variables are used for the Icinga Kubernetes setup. Normally, you can rely on the defaults to work and should **not** change them unless you know what you are doing.
+
+| Variable | Type | Description | Default |
+|----------|------|-------------|---------|
+| `icinga_kubernetes_config_dir` | `String` | Defines the directory where the Icinga Kubernetes configuration is stored. | `/etc/icinga-kubernetes` |
+| `icinga_kubernetes_database_schema` | `String` | Defines the path to the schema file. | `"/usr/share/icinga-kubernetes/schema/{{ icinga_kubernetes_database_type }}/schema.sql"` |
+| `icinga_kubernetes_group` | `String` | Defines the group membership for the Icinga Kubernetes user. | `icinga-kubernetes` |
+| `icinga_kubernetes_packages` | `List` | Defines the packages to install for Icinga Kubernetes. | `[icinga-kubernetes]` |
+| `icinga_kubernetes_service_name` | `String` | Defines the name of the Icinga Kubernetes service. | `icinga-kubernetes` |
+| `icinga_kubernetes_user` | `String` | Defines the user for the Icinga Kubernetes service. | `icinga-kubernetes` |
+| `icinga_kubernetes_kubeconfig_path` | `String` | Defines the path for the kubeconfig file, if not in standard path defined by KUBECONFIG env | |
+
+## Examples
+
+This play installs Icinga Kubernetes with on the same host as its connected MySQL database. It also imports the schema into the database.
+
+```yaml
+- name: Install Icinga Kubernetes
+ hosts: icingakubernetes
+ become: true
+ vars:
+ icinga_kubernetes_database_import_schema: true # Import the schema into the database
+ icinga_kubernetes_database_type: mysql # needed by the schema import
+
+ roles:
+ - role: icinga.icinga.icinga_kubernetes
+```
+
+This example installs Icinga Kubernetes and connects it to a **remote** MySQL database. It also imports the schema into the database and set a custom kubeconfig path.
+
+```yaml
+- name: Install Icinga Kubernetes
+ hosts: icingadb
+ become: true
+ vars:
+ icinga_kubernetes_database_type: mysql
+ icinga_kubernetes_database_host: mysql.example.com
+ icinga_kubernetes_database_port: 3306
+ icinga_kubernetes_database_user: kube_user
+ icinga_kubernetes_database_password: hellokube$123
+ icinga_kubernetes_database_import_schema: true
+ icinga_kubernetes_kubeconfig_path: /opt/kube/config
+
+ roles:
+ - role: icinga.icinga.icinga_kubernetes
+```
diff --git a/doc/role-icingaweb2/module-kubernetes.md b/doc/role-icingaweb2/module-kubernetes.md
new file mode 100644
index 00000000..77876512
--- /dev/null
+++ b/doc/role-icingaweb2/module-kubernetes.md
@@ -0,0 +1,24 @@
+## Module Kubernetes
+
+### Variables and Configuration
+
+The general module parameter like `enabled` and `source` can be applied here.
+
+| Variable | Value |
+|----------|------------|
+| enabled | true/false |
+| source | package |
+
+#### Section configuration
+
+The backend database for the module needs to be available and configured at the `icingaweb2_resources` variable.
+
+```yaml
+icingaweb2_modules:
+ kubernetes:
+ enabled: true
+ source: package
+ config:
+ database:
+ resource: kubernetes_db
+```
diff --git a/roles/icinga_kubernetes/defaults/main.yml b/roles/icinga_kubernetes/defaults/main.yml
new file mode 100644
index 00000000..aec56976
--- /dev/null
+++ b/roles/icinga_kubernetes/defaults/main.yml
@@ -0,0 +1,19 @@
+---
+# Database Settings
+icinga_kubernetes_database_import_schema: false
+icinga_kubernetes_database_type: mysql
+icinga_kubernetes_database_host: 127.0.0.1
+icinga_kubernetes_database_name: kubernetes
+icinga_kubernetes_database_user: kubernetes
+icinga_kubernetes_database_password: kubernetes
+# icinga_kubernetes_database_port:
+
+# Variables for kubernetes role
+icinga_kubernetes_config_dir: /etc/icinga-kubernetes
+icinga_kubernetes_service_name: icinga-kubernetes
+icinga_kubernetes_group: icinga-kubernetes
+icinga_kubernetes_user: icinga-kubernetes
+icinga_kubernetes_database_schema: "/usr/share/icinga-kubernetes/schema/{{ icinga_kubernetes_database_type }}/schema.sql"
+icinga_kubernetes_packages:
+ - icinga-kubernetes
+# icinga_kubernetes_kubeconfig_path:
diff --git a/roles/icinga_kubernetes/handlers/main.yml b/roles/icinga_kubernetes/handlers/main.yml
new file mode 100644
index 00000000..f7630776
--- /dev/null
+++ b/roles/icinga_kubernetes/handlers/main.yml
@@ -0,0 +1,9 @@
+---
+- name: Systemd reload
+ ansible.builtin.systemd:
+ daemon_reload: true
+
+- name: Kubernetes-restart
+ ansible.builtin.service:
+ name: "{{ icinga_kubernetes_service_name }}"
+ state: restarted
diff --git a/roles/icinga_kubernetes/meta/main.yml b/roles/icinga_kubernetes/meta/main.yml
new file mode 100644
index 00000000..1b6cbe3a
--- /dev/null
+++ b/roles/icinga_kubernetes/meta/main.yml
@@ -0,0 +1,27 @@
+galaxy_info:
+ author: |
+ - Gianmarco Mameli
+ description: Role to install, configure or manage Icinga Kubernetes.
+ license: Apache-2.0
+ min_ansible_version: '2.9'
+ platforms:
+ - name: opensuse
+ versions: ['15.5']
+ - name: SLES
+ versions: ['15']
+ - name: EL
+ versions: ['7']
+ - name: Debian
+ versions: ['buster','bullseye','bookworm']
+ - name: Ubuntu
+ versions: ['jammy']
+ galaxy_tags:
+ - icinga
+ - monitoring
+ - satellite
+ - agent
+ - server
+ - master
+ - icinga2
+ - kubernetes
+dependencies: []
diff --git a/roles/icinga_kubernetes/tasks/install_on_debian.yml b/roles/icinga_kubernetes/tasks/install_on_debian.yml
new file mode 100644
index 00000000..a47970ea
--- /dev/null
+++ b/roles/icinga_kubernetes/tasks/install_on_debian.yml
@@ -0,0 +1,4 @@
+- name: Debian - Install Kubernetes packages
+ ansible.builtin.apt:
+ name: "{{ icinga_kubernetes_packages }}"
+ state: present
diff --git a/roles/icinga_kubernetes/tasks/install_on_redhat.yml b/roles/icinga_kubernetes/tasks/install_on_redhat.yml
new file mode 100644
index 00000000..ffa86a8c
--- /dev/null
+++ b/roles/icinga_kubernetes/tasks/install_on_redhat.yml
@@ -0,0 +1,4 @@
+- name: RedHat - Install Kubernetes packages
+ ansible.builtin.yum:
+ name: "{{ icinga_kubernetes_packages }}"
+ state: present
diff --git a/roles/icinga_kubernetes/tasks/install_on_suse.yml b/roles/icinga_kubernetes/tasks/install_on_suse.yml
new file mode 100644
index 00000000..405e52a2
--- /dev/null
+++ b/roles/icinga_kubernetes/tasks/install_on_suse.yml
@@ -0,0 +1,4 @@
+- name: Suse - Install Kubernetes packages
+ community.general.zypper:
+ name: "{{ icinga_kubernetes_packages }}"
+ state: present
diff --git a/roles/icinga_kubernetes/tasks/main.yml b/roles/icinga_kubernetes/tasks/main.yml
new file mode 100644
index 00000000..119f8c09
--- /dev/null
+++ b/roles/icinga_kubernetes/tasks/main.yml
@@ -0,0 +1,32 @@
+---
+- name: Include OS specific vars
+ ansible.builtin.include_vars: "{{ lookup('first_found', params) }}"
+ vars:
+ params:
+ files:
+ - "{{ ansible_os_family }}-{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml"
+ - "{{ ansible_os_family }}-{{ ansible_distribution_major_version }}.yml"
+ - "{{ ansible_os_family }}-{{ ansible_distribution }}.yml"
+ - "{{ ansible_os_family }}.yml"
+ - default.yml
+ paths:
+ - "{{ role_path }}/vars"
+
+- name: Check supported operatingsystems
+ block:
+ - name: Include OS specific installation
+ ansible.builtin.include_tasks: "install_on_{{ ansible_os_family | lower }}.yml"
+ rescue:
+ - name: "OS family not supported!"
+ ansible.builtin.fail:
+ msg: "The OS {{ ansible_os_family }} is not supported!"
+
+- name: Include Tasks to configure Icinga Kubernetes
+ ansible.builtin.include_tasks: manage_config.yml
+
+- name: Include Tasks to import DB Schema
+ ansible.builtin.include_tasks: "manage_schema_{{ icinga_kubernetes_database_type | lower }}.yml"
+ when: icinga_kubernetes_database_import_schema and icinga_kubernetes_database_type is defined
+
+- name: Include Tasks to manage Kubernetes Service
+ ansible.builtin.include_tasks: manage_service.yml
diff --git a/roles/icinga_kubernetes/tasks/manage_config.yml b/roles/icinga_kubernetes/tasks/manage_config.yml
new file mode 100644
index 00000000..5da34111
--- /dev/null
+++ b/roles/icinga_kubernetes/tasks/manage_config.yml
@@ -0,0 +1,9 @@
+---
+- name: Write configuration to {{ icinga_kubernetes_config_dir }}/config.yml
+ ansible.builtin.template:
+ src: kubernetes.yml.j2
+ dest: "{{ icinga_kubernetes_config_dir }}/config.yml"
+ owner: "{{ icinga_kubernetes_user }}"
+ group: "{{ icinga_kubernetes_group }}"
+ mode: 0640
+ notify: Kubernetes-restart
diff --git a/roles/icinga_kubernetes/tasks/manage_schema_mysql.yml b/roles/icinga_kubernetes/tasks/manage_schema_mysql.yml
new file mode 100644
index 00000000..c05ce5e8
--- /dev/null
+++ b/roles/icinga_kubernetes/tasks/manage_schema_mysql.yml
@@ -0,0 +1,31 @@
+- name: MySQL import Kubernetes schema
+ when: icinga_kubernetes_database_import_schema | default(False)
+ block:
+ - name: Build mysql command
+ ansible.builtin.set_fact:
+ mysqlcmd: >-
+ mysql {% if icinga_kubernetes_database_host | default('localhost') != 'localhost' %} -h "{{ icinga_kubernetes_database_host }}" {%- endif %}
+ {% if icinga_kubernetes_database_port is defined %} -P {{ icinga_kubernetes_database_port }} {%- endif %}
+ {% if icinga_kubernetes_database_ca is defined %} --ssl-ca "{{ icinga_kubernetes_database_ca }}" {%- endif %}
+ {% if icinga_kubernetes_database_cert is defined %} --ssl-cert "{{ icinga_kubernetes_database_cert }}" {%- endif %}
+ {% if icinga_kubernetes_database_key is defined %} --ssl-key "{{ icinga_kubernetes_database_key }}" {%- endif %}
+ -u "{{ icinga_kubernetes_database_user | default('kubernetes') }}"
+ -p"{{ icinga_kubernetes_database_password }}"
+ "{{ icinga_kubernetes_database_name | default('kubernetes') }}"
+
+ - name: MySQL check for Kubernetes schema
+ ansible.builtin.shell: >
+ {{ mysqlcmd }}
+ -Ns -e "select version from kubernetes_schema"
+ failed_when: false
+ changed_when: false
+ check_mode: false
+ register: _db_schema
+
+ - name: MySQL import Kubernetes schema
+ ansible.builtin.shell: >
+ {{ mysqlcmd }}
+ < {{ icinga_kubernetes_database_schema }}
+ when: _db_schema.rc != 0
+ check_mode: false
+ run_once: true
diff --git a/roles/icinga_kubernetes/tasks/manage_schema_pgsql.yml b/roles/icinga_kubernetes/tasks/manage_schema_pgsql.yml
new file mode 100644
index 00000000..07079629
--- /dev/null
+++ b/roles/icinga_kubernetes/tasks/manage_schema_pgsql.yml
@@ -0,0 +1,36 @@
+# temporarily disabled, pgsql at the moment is not available for icinga kubernetes
+
+# - name: PgSQL import Kubernetes schema
+# when: icinga_kubernetes_database_import_schema| default(False)
+# block:
+# - name: Build pgsql command
+# ansible.builtin.set_fact:
+# _tmp_pgsqlcmd: >-
+# PGPASSWORD="{{ icinga_kubernetes_database_password }}"
+# psql
+# "{% if icinga_kubernetes_database_host %} host="{{ icinga_kubernetes_database_host }}" {%- endif %}
+# {% if icinga_kubernetes_database_port is defined %} port={{ icinga_kubernetes_database_port }} {%- endif %}
+# user={{ icinga_kubernetes_database_user | default('kubernetes') }}
+# dbname={{ icinga_kubernetes_database_name | default('kubernetes') }}
+# {% if icinga_kubernetes_database_sslmode is defined %} sslmode={{ icinga_kubernetes_database_sslmode }} {%- endif %}
+# {% if icinga_kubernetes_database_ca is defined %} sslrootcert={{ icinga_kubernetes_database_ca }} {%- endif %}
+# {% if icinga_kubernetes_database_cert is defined %} sslcert={{ icinga_kubernetes_database_cert }} {%- endif %}
+# {% if icinga_kubernetes_database_key is defined %} sslkey={{ icinga_kubernetes_database_key }} {%- endif %}
+# {% if icinga_kubernetes_database_ssl_extra_options is defined %} {{ icinga_kubernetes_database_ssl_extra_options }} {%- endif %}"
+
+# - name: PgSQL check for Kubernetes schema
+# ansible.builtin.shell: >
+# {{ _tmp_pgsqlcmd }}
+# -w -c "select version from kubernetes_schema"
+# failed_when: false
+# changed_when: false
+# check_mode: false
+# register: _db_schema
+
+# - name: PgSQL import Kubernetes schema
+# ansible.builtin.shell: >
+# {{ _tmp_pgsqlcmd }}
+# -w -f {{ icinga_kubernetes_database_schema }}
+# when: _db_schema.rc != 0
+# check_mode: false
+# run_once: true
diff --git a/roles/icinga_kubernetes/tasks/manage_service.yml b/roles/icinga_kubernetes/tasks/manage_service.yml
new file mode 100644
index 00000000..93681f93
--- /dev/null
+++ b/roles/icinga_kubernetes/tasks/manage_service.yml
@@ -0,0 +1,27 @@
+---
+- name: Override KUBECONFIG path if defined
+ when: icinga_kubernetes_kubeconfig_path is defined
+ block:
+ - name: Create service override directory
+ ansible.builtin.file:
+ path: /etc/systemd/system/{{ icinga_kubernetes_service_name }}.service.d
+ state: directory
+ mode: '0755'
+ notify:
+ - Systemd reload
+ - Kubernetes-restart
+
+ - name: Create service override configuration file
+ ansible.builtin.template:
+ src: icinga-kubernetes-override.conf.j2
+ dest: "/etc/systemd/system/{{ icinga_kubernetes_service_name }}.service.d/override.conf"
+ mode: '0640'
+ notify:
+ - Systemd reload
+ - Kubernetes-restart
+
+- name: Ensure Kubernetes Service is running
+ ansible.builtin.service:
+ state: started
+ enabled: yes
+ name: "{{ icinga_kubernetes_service_name }}"
diff --git a/roles/icinga_kubernetes/templates/icinga-kubernetes-override.conf.j2 b/roles/icinga_kubernetes/templates/icinga-kubernetes-override.conf.j2
new file mode 100644
index 00000000..504ecec7
--- /dev/null
+++ b/roles/icinga_kubernetes/templates/icinga-kubernetes-override.conf.j2
@@ -0,0 +1,20 @@
+### Editing /etc/systemd/system/icinga-kubernetes.service.d/override.conf
+### Anything between here and the comment below will become the new contents of the file
+
+[Service]
+Environment="KUBECONFIG={{ icinga_kubernetes_kubeconfig_path }}"
+
+### Lines below this comment will be discarded
+
+### /lib/systemd/system/icinga-kubernetes.service
+# [Unit]
+# Description=Icinga for Kubernetes
+# After=syslog.target network-online.target mariadb.service postgresql.service
+#
+# [Service]
+# Type=simple
+# ExecStart=/usr/sbin/icinga-kubernetes --config /etc/icinga-kubernetes/config.yml
+# User=icinga-kubernetes
+#
+# [Install]
+# WantedBy=multi-user.target
\ No newline at end of file
diff --git a/roles/icinga_kubernetes/templates/kubernetes.yml.j2 b/roles/icinga_kubernetes/templates/kubernetes.yml.j2
new file mode 100644
index 00000000..3080acb1
--- /dev/null
+++ b/roles/icinga_kubernetes/templates/kubernetes.yml.j2
@@ -0,0 +1,18 @@
+# {{ ansible_managed | comment }}
+
+database:
+{% if icinga_kubernetes_database_type is defined %}
+ type: {{ icinga_kubernetes_database_type }}
+{% endif %}
+ host: {{ icinga_kubernetes_database_host | default('localhost') }}
+{% if icinga_kubernetes_database_port is defined %}
+ port: {{ icinga_kubernetes_database_port }}
+{% endif %}
+ database: {{ icinga_kubernetes_database_name | default('kubernetes') }}
+ user: {{ icinga_kubernetes_database_user | default('kubernetes') }}
+ password: {{ icinga_kubernetes_database_password | default('kubernetes') }}
+
+prometheus:
+{% if icinga_kubernetes_prometheus_url is defined %}
+ url: {{ icinga_kubernetes_prometheus_url }}
+{% endif %}
diff --git a/roles/icinga_kubernetes/vars/default.yml b/roles/icinga_kubernetes/vars/default.yml
new file mode 100644
index 00000000..ed97d539
--- /dev/null
+++ b/roles/icinga_kubernetes/vars/default.yml
@@ -0,0 +1 @@
+---
diff --git a/roles/icingaweb2/tasks/modules/kubernetes.yml b/roles/icingaweb2/tasks/modules/kubernetes.yml
new file mode 100644
index 00000000..1537d179
--- /dev/null
+++ b/roles/icingaweb2/tasks/modules/kubernetes.yml
@@ -0,0 +1,18 @@
+- name: Module Icinga Kubernetes | Ensure config directory
+ ansible.builtin.file:
+ state: directory
+ dest: "{{ icingaweb2_modules_config_dir }}/{{ item.key }}"
+ owner: "{{ icingaweb2_httpd_user }}"
+ group: "{{ icingaweb2_group }}"
+ mode: "2770"
+
+- name: Module Icinga Kubernetes | Manage config files
+ ansible.builtin.include_tasks: manage_module_config.yml
+ loop: "{{ _files }}"
+ loop_control:
+ loop_var: _file
+ when: vars['icingaweb2_modules'][_module][_file] is defined
+ vars:
+ _module: "{{ item.key }}"
+ _files:
+ - config
diff --git a/roles/icingaweb2/vars/main.yml b/roles/icingaweb2/vars/main.yml
index 588f0d6d..18e3ec10 100644
--- a/roles/icingaweb2/vars/main.yml
+++ b/roles/icingaweb2/vars/main.yml
@@ -4,3 +4,4 @@ icingaweb2_module_packages:
director: icinga-director
x509: icinga-x509
businessprocess: icinga-businessprocess
+ kubernetes: icinga-kubernetes-web