diff --git a/playbooks/loki.yml b/playbooks/loki.yml new file mode 100644 index 0000000..86f3da7 --- /dev/null +++ b/playbooks/loki.yml @@ -0,0 +1,6 @@ +--- +- name: Install loki + hosts: "{{ loki_hosts | default('loki') }}" + become: true + roles: + - role: finallycoffee.observability.loki diff --git a/roles/loki/README.md b/roles/loki/README.md new file mode 100644 index 0000000..5d69e64 --- /dev/null +++ b/roles/loki/README.md @@ -0,0 +1,14 @@ +# `finallycoffee.observability.loki` ansible role + +## Overview + +Runs [loki](https://github.com/grafana/loki) in a docker container. + +## Configuration + +Listens on `3100` per default, and can be changed using `loki_config_server_http_listen_port` / `loki_config_server_http_listen_addr`. + +### Required configuration + +Loki's storage config can be provided in `loki_config_storage_config`, +the schema configs can be provided in `loki_config_schema_config_configs`. diff --git a/roles/loki/defaults/main.yml b/roles/loki/defaults/main.yml new file mode 100644 index 0000000..d676d97 --- /dev/null +++ b/roles/loki/defaults/main.yml @@ -0,0 +1,45 @@ +--- +loki_user: loki +loki_version: "2.9.1" +loki_base_path: "/opt/loki" +loki_config_path: "{{ loki_base_path }}/config" +loki_config_file: "{{ loki_config_path }}/config.yml" +loki_state: present +loki_container_state: >- + {{ (loki_state == 'present') | ternary('started', 'absent') }} +loki_run_user: "{{ loki_user_info.uid | default(loki_user) }}" +loki_run_group: "{{ loki_user_info.group | default(loki_user) }}" +loki_all_host_directories: >- + {{ loki_required_host_directories + loki_host_directories | default([]) }} +loki_required_host_directories: + - path: "{{ loki_base_path }}" + - path: "{{ loki_config_path }}" + +loki_container_name: loki +loki_container_image_name: "loki" +loki_container_image_namespace: "grafana" +loki_container_image_registry: "docker.io" +loki_container_image_tag: ~ +loki_container_image: >- + {{ loki_container_image_registry + + (('/' + loki_container_image_namespace) + if loki_container_image_namespace | default(false, true) else '') + + '/' + loki_container_image_name + + ':' + (loki_container_image_tag | default(loki_version, true)) + }} +loki_container_env: {} +loki_container_base_volumes: + - "{{ loki_config_file }}:/etc/loki/local-config.yaml:ro" +loki_container_all_volumes: >-2 + {{ loki_container_base_volumes + loki_container_volumes | default([]) }} +loki_container_all_labels: >-2 + {{ loki_container_base_labels | combine(loki_container_labels | default({})) }} +loki_container_restart_policy: "unless-stopped" + +loki_config_target: "all" +loki_config_auth_enabled: false +loki_config_server_http_listen_port: 3100 +loki_config_server_http_listen_address: 127.0.0.1 +loki_config_storage_config: {} +loki_config_schema_config_configs: [] +loki_config_limits_config: [] diff --git a/roles/loki/handlers/main.yml b/roles/loki/handlers/main.yml new file mode 100644 index 0000000..cd3850c --- /dev/null +++ b/roles/loki/handlers/main.yml @@ -0,0 +1,10 @@ +--- +- name: Ensure loki is reloaded + listen: loki_reload + community.docker.docker_container: + name: "{{ loki_container_name }}" + state: "started" + restart: true + force_kill: true + kill_signal: "HUP" + when: "loki_container_state in ['started', 'present']" diff --git a/roles/loki/tasks/main.yml b/roles/loki/tasks/main.yml new file mode 100644 index 0000000..6c34132 --- /dev/null +++ b/roles/loki/tasks/main.yml @@ -0,0 +1,56 @@ +--- +- name: Ensure loki user '{{ loki_user }}' is {{ loki_state }} + ansible.builtin.user: + name: "{{ loki_user }}" + state: "{{ loki_state }}" + system: true + create_home: false + register: loki_user_info + +- name: Ensure loki host directories are {{ loki_state }} + ansible.builtin.file: + path: "{{ item.path }}" + state: >- + {{ (loki_state == 'present') | ternary('directory', 'absent') }} + owner: "{{ item.owner | default(loki_run_user) }}" + group: "{{ item.group | default(loki_run_group) }}" + mode: "{{ item.mode | default('0755') }}" + loop: "{{ loki_all_host_directories }}" + +- name: Ensure loki configuration file is templated + ansible.builtin.copy: + content: "{{ loki_final_config | to_nice_yaml(width=10000, indent=2) }}" + dest: "{{ loki_config_file }}" + owner: "{{ loki_run_user }}" + group: "{{ loki_run_group }}" + mode: "0640" + notify: loki_reload + +- name: Ensure loki container image '{{ loki_container_image }}' is {{ loki_state }} + community.docker.docker_image: + name: "{{ loki_container_image }}" + state: "{{ loki_state }}" + source: "pull" + force_source: >- + {{ loki_container_image_force_source + | default(loki_container_image_tag | default(false, true)) }} + register: loki_container_image_info + until: loki_container_image_info is success + retries: 3 + delay: 5 + +- name: Ensure loki container '{{ loki_container_name }}' is {{ loki_container_state }} + community.docker.docker_container: + name: "{{ loki_container_name }}" + image: "{{ loki_container_image }}" + env: "{{ loki_container_env }}" + user: "{{ loki_run_user }}:{{ loki_run_group }}" + ports: "{{ loki_container_ports | default(omit, true) }}" + labels: "{{ loki_container_all_labels }}" + volumes: "{{ loki_container_all_volumes }}" + networks: "{{ loki_container_networks | default(omit, true) }}" + purge_networks: "{{ loki_container_purge_networks | default(omit, true) }}" + etc_hosts: "{{ loki_container_etc_hosts | default(omit, true) }}" + hostname: "{{ loki_container_hostname | default(omit, true) }}" + restart_policy: "{{ loki_container_restart_policy }}" + state: "{{ loki_container_state }}" diff --git a/roles/loki/vars/main.yml b/roles/loki/vars/main.yml new file mode 100644 index 0000000..d825c6d --- /dev/null +++ b/roles/loki/vars/main.yml @@ -0,0 +1,14 @@ +loki_default_config: + target: "{{ loki_config_target }}" + auth_enabled: "{{ loki_config_auth_enabled }}" + server: + http_listen_address: "{{ loki_config_server_http_listen_address }}" + http_listen_port: "{{ loki_config_server_http_listen_port }}" + storage_config: "{{ loki_config_storage_config }}" + limits_config: "{{ loki_config_limits_config }}" + schema_config: + configs: "{{ loki_config_schema_config_configs }}" +loki_final_config: >- + {{ loki_default_config | combine(loki_config | default({}), recursive=True) }} +loki_container_base_labels: + version: "{{ loki_version }}"