├── .drone.yml ├── .github └── workflows │ ├── ansible-lint.yml │ ├── ci-docker.yml │ ├── ci-extended.yml │ ├── ci.yml │ ├── flake8.yml │ ├── galaxy.yml │ └── yaml-lint.yml ├── .yamllint ├── LICENSE ├── Makefile ├── README.md ├── defaults └── main.yml ├── handlers └── main.yml ├── meta └── main.yml ├── molecule ├── default │ ├── converge.yml │ ├── molecule.yml │ ├── prepare.yml │ └── tests │ │ ├── test_default.py │ │ └── test_promtail.py ├── promtail-docker │ ├── converge.yml │ ├── molecule.yml │ ├── prepare.yml │ ├── requirements.yml │ └── tests │ │ └── test_default.py ├── promtail │ ├── converge.yml │ ├── molecule.yml │ ├── prepare.yml │ └── tests │ │ └── test_default.py └── update │ ├── converge.yml │ ├── molecule.yml │ ├── prepare.yml │ └── tests │ ├── test_default.py │ └── test_promtail.py ├── tasks ├── loki.yml ├── main.yml ├── preflight-loki.yml ├── preflight-promtail.yml ├── preflight.yml ├── promtail-config.yml ├── promtail-docker.yml └── promtail.yml ├── templates ├── loki.yml.j2 ├── promtail.yml.j2 ├── systemd-loki.j2 ├── systemd-promtail-docker.j2 └── systemd-promtail.j2 └── vars └── main.yml /.drone.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: pipeline 3 | name: default 4 | 5 | volumes: 6 | - name: docker 7 | host: 8 | path: /var/run/docker.sock 9 | 10 | workspace: 11 | base: /ansible-loki 12 | 13 | steps: 14 | - name: molecule test 15 | image: quay.io/ansible/molecule:2.22 16 | volumes: 17 | - name: docker 18 | path: /var/run/docker.sock 19 | environment: 20 | MOLECULE_NO_LOG: no 21 | NETRC: "" # drone automatically sets up .netrc for github login 22 | # but that breaks the loki/promtail release downloads 23 | commands: 24 | - molecule test 25 | -------------------------------------------------------------------------------- /.github/workflows/ansible-lint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: ansible-lint 3 | 4 | on: 5 | push: 6 | 7 | jobs: 8 | lint: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: checkout 12 | uses: actions/checkout@v2 13 | - name: ansible-lint 14 | uses: ansible/ansible-lint-action@master 15 | with: 16 | targets: "." 17 | -------------------------------------------------------------------------------- /.github/workflows/ci-docker.yml: -------------------------------------------------------------------------------- 1 | --- 2 | on: 3 | pull_request: 4 | 5 | name: molecule-promtail 6 | 7 | jobs: 8 | molecule-promtail-docker: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | with: 13 | path: "${{ github.repository }}" 14 | - name: molecule test 15 | uses: robertdebock/molecule-action@2.6.1 16 | with: 17 | scenario: promtail-docker 18 | image: centos 19 | tag: 7 20 | -------------------------------------------------------------------------------- /.github/workflows/ci-extended.yml: -------------------------------------------------------------------------------- 1 | --- 2 | on: 3 | pull_request: 4 | 5 | name: molecule-extended 6 | 7 | jobs: 8 | molecule-promtail: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | with: 13 | path: "${{ github.repository }}" 14 | - name: molecule test 15 | uses: robertdebock/molecule-action@2.6.1 16 | with: 17 | scenario: promtail 18 | image: centos 19 | tag: 7 20 | molecule-update: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v2 24 | with: 25 | path: "${{ github.repository }}" 26 | - name: molecule test 27 | uses: robertdebock/molecule-action@2.6.1 28 | with: 29 | scenario: update 30 | image: centos 31 | tag: 7 32 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | on: 3 | pull_request: 4 | 5 | name: molecule 6 | 7 | jobs: 8 | molecule: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | with: 13 | path: "${{ github.repository }}" 14 | - name: molecule test 15 | uses: robertdebock/molecule-action@2.4.0 16 | with: 17 | image: centos 18 | tag: 7 19 | -------------------------------------------------------------------------------- /.github/workflows/flake8.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: flake8 3 | 4 | on: 5 | pull_request: 6 | 7 | jobs: 8 | lint: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Setup flake8 annotations 13 | uses: rbialon/flake8-annotations@v1 14 | - name: Flake8 Code Linter 15 | uses: jonasrk/flake8-action@master 16 | -------------------------------------------------------------------------------- /.github/workflows/galaxy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: galaxy 3 | 4 | on: 5 | push: 6 | tags: 7 | - '*' 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: checkout 14 | uses: actions/checkout@v2 15 | - name: galaxy 16 | uses: robertdebock/galaxy-action@1.0.3 17 | with: 18 | galaxy_api_key: ${{ secrets.GALAXY_API_KEY }} 19 | -------------------------------------------------------------------------------- /.github/workflows/yaml-lint.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: yaml-lint 3 | 4 | on: 5 | pull_request: 6 | 7 | jobs: 8 | lint: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: yaml-lint 13 | uses: ibiqlik/action-yamllint@v1 14 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | # Based on ansible-lint config 3 | extends: default 4 | 5 | rules: 6 | braces: 7 | max-spaces-inside: 1 8 | level: error 9 | brackets: 10 | max-spaces-inside: 1 11 | level: error 12 | colons: 13 | max-spaces-after: -1 14 | level: error 15 | commas: 16 | max-spaces-after: -1 17 | level: error 18 | comments: disable 19 | comments-indentation: disable 20 | document-start: disable 21 | empty-lines: 22 | max: 3 23 | level: error 24 | hyphens: 25 | level: error 26 | indentation: disable 27 | key-duplicates: enable 28 | line-length: disable 29 | new-line-at-end-of-file: disable 30 | new-lines: 31 | type: unix 32 | trailing-spaces: disable 33 | truthy: disable 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Luzilla Capital GmbH 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are 4 | permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list 7 | of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or other 11 | materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 14 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 16 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 17 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 18 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 19 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 20 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 21 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 22 | DAMAGE. 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL=/bin/bash 2 | 3 | IMAGE:=quay.io/ansible/molecule:3.0.4 4 | ANSIBLE_ROLE:=ansible-loki 5 | OPTS?=--all 6 | 7 | .PHONY: test-local 8 | test-local: 9 | docker run --rm -it \ 10 | -v "$(CURDIR)":/tmp/$(ANSIBLE_ROLE):ro \ 11 | -v /var/run/docker.sock:/var/run/docker.sock \ 12 | -w /tmp/$(ANSIBLE_ROLE) \ 13 | --env MOLECULE_NO_LOG=no \ 14 | $(IMAGE) \ 15 | molecule test $(OPTS) 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![ansible-lint](https://github.com/hostwithquantum/ansible-loki/workflows/ansible-lint/badge.svg) ![flake8](https://github.com/hostwithquantum/ansible-loki/workflows/flake8/badge.svg) ![yaml-lint](https://github.com/hostwithquantum/ansible-loki/workflows/yaml-lint/badge.svg) ![molecule](https://github.com/hostwithquantum/ansible-loki/workflows/molecule/badge.svg) 2 | 3 | # ansible-loki 4 | 5 | An Ansible role to install Grafana Loki and Promtail. 6 | 7 | ## Requirements 8 | 9 | For the standard (from binary) install of loki/promtail: 10 | 11 | - `unzip` on the hosts 12 | 13 | For the dockerized promtail: 14 | 15 | - Python: `docker==4.3.1` 16 | - `docker-cli` 17 | 18 | ## Role Variables 19 | 20 | See `defaults/main.yml` to customize this role. 21 | 22 | ## Dependencies 23 | 24 | _None._ 25 | 26 | ## Example Playbook 27 | 28 | This role is driven by inventory groups: 29 | 30 | ```yaml 31 | all: 32 | hosts: 33 | monitoring.host.example.org: 34 | children: 35 | loki: 36 | monitoring.host.example.org: 37 | promtail: 38 | monitoring.host.example.org: 39 | ``` 40 | 41 | And the playbook: 42 | 43 | ```yaml 44 | - hosts: all 45 | roles: 46 | - role: hostwithquantum.loki 47 | ``` 48 | 49 | ## License 50 | 51 | BSD-2-Clause 52 | 53 | ## Author Information 54 | 55 | An optional section for the role authors to include contact information, or a website (HTML is not allowed). 56 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | loki_version: 1.6.1 3 | 4 | loki_config_directory: /etc/loki 5 | loki_config_auth: true 6 | loki_config_store: /var/lib/loki 7 | loki_config_retention: 336h 8 | loki_config_period: 168h 9 | loki_config_http_address: 127.0.0.1 10 | loki_config_http_port: 3100 11 | loki_config_log_level: debug 12 | 13 | # install a containerized promtail 14 | promtail_use_docker: false 15 | promtail_docker_image: "grafana/promtail:{{ loki_version }}" 16 | 17 | promtail_config_directory: /etc/promtail 18 | promtail_config_log_level: info 19 | promtail_config_server_listen: 127.0.0.1 20 | promtail_config_server_port: 9080 21 | promtail_config_client_loki_address: 127.0.0.1 22 | promtail_config_client_loki_port: 3100 23 | promtail_config_client_loki_path: /loki/api/v1/push 24 | promtail_config_client_tenant_id: luzilla 25 | promtail_config_client_set_tenant_id: true 26 | promtail_config_client_external_labels: 27 | node: "{{ inventory_hostname }}" 28 | 29 | promtail_config_scrape_journald_path: /run/log/journal 30 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: reload systemd loki 3 | systemd: 4 | name: "loki" 5 | daemon_reload: yes 6 | enabled: Yes 7 | 8 | - name: restart systemd loki 9 | service: 10 | name: "loki" 11 | state: restarted 12 | 13 | - name: reload systemd promtail 14 | systemd: 15 | name: "promtail" 16 | daemon_reload: yes 17 | enabled: Yes 18 | 19 | - name: restart systemd promtail 20 | service: 21 | name: "promtail" 22 | state: restarted 23 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | role_name: loki 3 | author: Till Klampaeckel 4 | description: Install Grafana Loki 5 | company: Planetary Quantum GmbH 6 | license: BSD-2-Clause 7 | 8 | min_ansible_version: 2.8 9 | # platforms: 10 | # - name: Fedora 11 | # versions: 12 | # - all 13 | # - 25 14 | # - name: SomePlatform 15 | # versions: 16 | # - all 17 | # - 1.0 18 | # - 7 19 | # - 99.99 20 | 21 | platforms: 22 | - name: el 23 | versions: 24 | - 7 25 | - name: FreeBSD 26 | versions: 27 | - all 28 | 29 | galaxy_tags: 30 | - promtail 31 | - loki 32 | - grafana 33 | - logging 34 | dependencies: [] 35 | -------------------------------------------------------------------------------- /molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: loki 4 | roles: 5 | - role: ansible-loki 6 | 7 | - name: Converge 8 | hosts: promtail 9 | roles: 10 | - role: ansible-loki 11 | -------------------------------------------------------------------------------- /molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | platforms: 7 | - name: instance 8 | image: geerlingguy/docker-centos7-ansible:latest 9 | pre_build_image: True 10 | command: /sbin/init 11 | env: 12 | MOLECULE_DEBUG: "1" 13 | privileged: True 14 | tmpfs: 15 | - /run 16 | - /tmp 17 | volumes: 18 | - /sys/fs/cgroup:/sys/fs/cgroup:ro 19 | groups: 20 | - promtail 21 | - loki 22 | provisioner: 23 | name: ansible 24 | options: 25 | diff: false 26 | v: true 27 | verifier: 28 | name: testinfra 29 | lint: 30 | name: flake8 31 | -------------------------------------------------------------------------------- /molecule/default/prepare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Prepare hosts 3 | hosts: all 4 | tasks: 5 | - name: Install unzip 6 | package: 7 | disablerepo: epel 8 | name: 9 | - unzip 10 | -------------------------------------------------------------------------------- /molecule/default/tests/test_default.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pytest 3 | import testinfra.utils.ansible_runner 4 | 5 | testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( 6 | os.environ['MOLECULE_INVENTORY_FILE'] 7 | ).get_hosts('all') 8 | 9 | 10 | def test_hosts_file(host): 11 | f = host.file('/etc/hosts') 12 | 13 | assert f.exists 14 | assert f.user == 'root' 15 | assert f.group == 'root' 16 | 17 | 18 | @pytest.mark.parametrize("name", [ 19 | ("loki"), 20 | ("promtail"), 21 | ]) 22 | def test_promtail_configuration(host, name): 23 | f = host.file('/etc/' + name + '/' + name + '.yml') 24 | 25 | assert f.exists 26 | assert f.user == 'root' 27 | assert f.group == 'root' 28 | 29 | 30 | @pytest.mark.parametrize("name", [ 31 | ("loki"), 32 | ("promtail"), 33 | ]) 34 | def test_services_enabled(host, name): 35 | svc = host.service(name) 36 | assert svc.is_running 37 | assert svc.is_enabled 38 | -------------------------------------------------------------------------------- /molecule/default/tests/test_promtail.py: -------------------------------------------------------------------------------- 1 | import os 2 | import testinfra.utils.ansible_runner 3 | 4 | testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( 5 | os.environ['MOLECULE_INVENTORY_FILE'] 6 | ).get_hosts('promtail') 7 | 8 | 9 | def test_external_labels(host): 10 | f = host.file('/etc/promtail/promtail.yml') 11 | 12 | assert f.exists 13 | assert f.user == 'root' 14 | assert f.group == 'root' 15 | 16 | assert f.contains("tenant_id: luzilla") 17 | assert f.contains("node: instance") 18 | -------------------------------------------------------------------------------- /molecule/promtail-docker/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | roles: 5 | - role: ansible-loki 6 | vars: 7 | loki_version: 2.1.0 8 | promtail_use_docker: true 9 | promtail_config_server_listen: 0.0.0.0 10 | promtail_config_server_port: 9080 11 | -------------------------------------------------------------------------------- /molecule/promtail-docker/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | platforms: 7 | - name: instance 8 | image: geerlingguy/docker-centos7-ansible:latest 9 | pre_build_image: True 10 | command: /sbin/init 11 | env: 12 | MOLECULE_DEBUG: "1" 13 | privileged: True 14 | tmpfs: 15 | - /run 16 | - /tmp 17 | volumes: 18 | - /sys/fs/cgroup:/sys/fs/cgroup:ro 19 | groups: 20 | - promtail 21 | provisioner: 22 | name: ansible 23 | options: 24 | diff: false 25 | v: false 26 | verifier: 27 | name: testinfra 28 | lint: 29 | name: flake8 30 | -------------------------------------------------------------------------------- /molecule/promtail-docker/prepare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Prepare hosts 3 | hosts: all 4 | roles: 5 | # install a docker in docker 6 | - role: atosatto.docker-swarm 7 | vars: 8 | docker_daemon_config: 9 | storage-driver: vfs 10 | docker_service_override: | 11 | [Service] 12 | ExecStart= 13 | ExecStart=/usr/bin/dockerd -H unix:// 14 | skip_cli: False 15 | skip_containerd: False 16 | skip_docker_compose: True 17 | skip_docker_py: True 18 | skip_engine: False 19 | skip_group: True 20 | skip_swarm: True 21 | - role: geerlingguy.pip 22 | vars: 23 | pip_install_packages: 24 | - name: docker 25 | version: 4.3.1 26 | -------------------------------------------------------------------------------- /molecule/promtail-docker/requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: atosatto.docker-swarm 3 | version: v2.3.0 4 | - name: geerlingguy.pip 5 | src: https://github.com/geerlingguy/ansible-role-pip 6 | version: 1.3.0 7 | -------------------------------------------------------------------------------- /molecule/promtail-docker/tests/test_default.py: -------------------------------------------------------------------------------- 1 | import os 2 | import testinfra.utils.ansible_runner 3 | 4 | testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( 5 | os.environ['MOLECULE_INVENTORY_FILE'] 6 | ).get_hosts('all') 7 | 8 | 9 | def test_only_promtail_is_present(host): 10 | promtail = host.service("promtail") 11 | assert promtail.is_running 12 | assert promtail.is_enabled 13 | 14 | 15 | def test_promtail_version(host): 16 | version_output = host.check_output("docker images grafana/promtail") 17 | assert "2.1.0" in version_output 18 | 19 | 20 | def test_promtail_port_binding(host): 21 | metrics_output = host.check_output("curl http://127.0.0.1:9080/metrics") 22 | assert len(metrics_output) > 0 23 | assert "cortex_deprecated_flags_inuse_total 0" in metrics_output 24 | -------------------------------------------------------------------------------- /molecule/promtail/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | roles: 5 | - role: ansible-loki 6 | vars: 7 | loki_version: 1.6.1 8 | -------------------------------------------------------------------------------- /molecule/promtail/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | platforms: 7 | - name: instance 8 | image: geerlingguy/docker-centos7-ansible:latest 9 | pre_build_image: True 10 | command: /sbin/init 11 | env: 12 | MOLECULE_DEBUG: "1" 13 | privileged: True 14 | tmpfs: 15 | - /run 16 | - /tmp 17 | volumes: 18 | - /sys/fs/cgroup:/sys/fs/cgroup:ro 19 | groups: 20 | - promtail 21 | provisioner: 22 | name: ansible 23 | options: 24 | diff: false 25 | v: true 26 | verifier: 27 | name: testinfra 28 | lint: 29 | name: flake8 30 | -------------------------------------------------------------------------------- /molecule/promtail/prepare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Prepare hosts 3 | hosts: all 4 | pre_tasks: 5 | - name: Install unzip 6 | package: 7 | disablerepo: epel 8 | name: 9 | - unzip 10 | -------------------------------------------------------------------------------- /molecule/promtail/tests/test_default.py: -------------------------------------------------------------------------------- 1 | import os 2 | import testinfra.utils.ansible_runner 3 | 4 | testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( 5 | os.environ['MOLECULE_INVENTORY_FILE'] 6 | ).get_hosts('all') 7 | 8 | 9 | def test_only_promtail_is_present(host): 10 | promtail = host.service("promtail") 11 | assert promtail.is_running 12 | assert promtail.is_enabled 13 | 14 | 15 | def test_promtail_version(host): 16 | version_output = host.check_output("/usr/local/bin/promtail -version") 17 | assert "1.6.1" in version_output 18 | 19 | 20 | def test_loki_is_not_install(host): 21 | loki = host.service("loki") 22 | assert not loki.is_running 23 | assert not loki.is_enabled 24 | assert not host.file("/usr/local/bin/loki").exists 25 | -------------------------------------------------------------------------------- /molecule/update/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | roles: 5 | - role: ansible-loki 6 | vars: 7 | loki_version: 2.1.0 8 | -------------------------------------------------------------------------------- /molecule/update/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | platforms: 7 | - name: instance 8 | image: geerlingguy/docker-centos7-ansible:latest 9 | pre_build_image: True 10 | command: /sbin/init 11 | env: 12 | MOLECULE_DEBUG: "1" 13 | privileged: True 14 | tmpfs: 15 | - /run 16 | - /tmp 17 | volumes: 18 | - /sys/fs/cgroup:/sys/fs/cgroup:ro 19 | groups: 20 | - promtail 21 | - loki 22 | provisioner: 23 | name: ansible 24 | options: 25 | diff: false 26 | v: true 27 | verifier: 28 | name: testinfra 29 | lint: 30 | name: flake8 31 | -------------------------------------------------------------------------------- /molecule/update/prepare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Prepare hosts 3 | hosts: all 4 | roles: 5 | - role: ansible-loki 6 | vars: 7 | loki_version: 1.6.1 8 | pre_tasks: 9 | - name: Install unzip 10 | package: 11 | disablerepo: epel 12 | name: 13 | - unzip 14 | -------------------------------------------------------------------------------- /molecule/update/tests/test_default.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pytest 3 | import testinfra.utils.ansible_runner 4 | 5 | testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( 6 | os.environ['MOLECULE_INVENTORY_FILE'] 7 | ).get_hosts('all') 8 | 9 | 10 | def test_hosts_file(host): 11 | f = host.file('/etc/hosts') 12 | 13 | assert f.exists 14 | assert f.user == 'root' 15 | assert f.group == 'root' 16 | 17 | 18 | @pytest.mark.parametrize("name", [ 19 | ("loki"), 20 | ("promtail"), 21 | ]) 22 | def test_promtail_configuration(host, name): 23 | f = host.file('/etc/' + name + '/' + name + '.yml') 24 | 25 | assert f.exists 26 | assert f.user == 'root' 27 | assert f.group == 'root' 28 | 29 | 30 | @pytest.mark.parametrize("name", [ 31 | ("loki"), 32 | ("promtail"), 33 | ]) 34 | def test_services_enabled(host, name): 35 | svc = host.service(name) 36 | assert svc.is_running 37 | assert svc.is_enabled 38 | 39 | 40 | @pytest.mark.parametrize("name", [ 41 | ("loki"), 42 | ("promtail"), 43 | ]) 44 | def test_version(host, name): 45 | version_output = host.check_output("/usr/local/bin/" + name + " -version") 46 | assert "2.1.0" in version_output 47 | -------------------------------------------------------------------------------- /molecule/update/tests/test_promtail.py: -------------------------------------------------------------------------------- 1 | import os 2 | import testinfra.utils.ansible_runner 3 | 4 | testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( 5 | os.environ['MOLECULE_INVENTORY_FILE'] 6 | ).get_hosts('promtail') 7 | 8 | 9 | def test_external_labels(host): 10 | f = host.file('/etc/promtail/promtail.yml') 11 | 12 | assert f.exists 13 | assert f.user == 'root' 14 | assert f.group == 'root' 15 | 16 | assert f.contains("tenant_id: luzilla") 17 | assert f.contains("node: instance") 18 | -------------------------------------------------------------------------------- /tasks/loki.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install systemd-unit 3 | template: 4 | src: "systemd-loki.j2" 5 | dest: "/etc/systemd/system/loki.service" 6 | mode: '0644' 7 | register: unit_tpl 8 | notify: 9 | - reload systemd loki 10 | when: "__loki_go_os == 'linux'" 11 | 12 | - name: Create config directories for loki 13 | file: 14 | mode: '0755' 15 | path: "{{ item }}" 16 | state: directory 17 | with_items: 18 | - "{{ loki_config_directory }}" 19 | - "{{ loki_config_store }}" 20 | 21 | - name: Setup configuration 22 | template: 23 | src: "loki.yml.j2" 24 | dest: "/etc/loki/loki.yml" 25 | mode: '0644' 26 | register: conf_tpl 27 | notify: 28 | - restart systemd loki 29 | 30 | - block: 31 | - name: Download loki release 32 | get_url: 33 | url: "{{ __loki_download }}" 34 | dest: "/tmp/{{ __loki_archive }}" 35 | checksum: "sha256:{{ __loki_download_github }}/v{{ loki_version }}/SHA256SUMS" 36 | mode: '0644' 37 | register: _download_release 38 | until: _download_release is succeeded 39 | retries: 5 40 | delay: 2 41 | 42 | - name: Unpack loki release 43 | unarchive: 44 | src: "/tmp/{{ __loki_archive }}" 45 | dest: "/tmp" 46 | creates: "/tmp/loki-{{ __loki_go_os }}-{{ __loki_go_arch }}" 47 | remote_src: true 48 | mode: '0644' 49 | 50 | - name: Copy loki to /usr/local/bin 51 | copy: 52 | src: "/tmp/loki-{{ __loki_go_os }}-{{ __loki_go_arch }}" 53 | dest: "/usr/local/bin/loki" 54 | mode: 0755 55 | owner: root 56 | group: root 57 | remote_src: true 58 | notify: restart systemd loki 59 | check_mode: false 60 | when: 61 | - __loki_version != loki_version 62 | 63 | - name: Clean-up 64 | file: 65 | path: "/tmp/{{ item }}" 66 | state: absent 67 | loop: 68 | - "{{ __loki_archive }}" 69 | - "loki-{{ __loki_go_os }}-{{ __loki_go_arch }}" 70 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - import_tasks: preflight.yml 3 | 4 | - name: Install loki 5 | include_tasks: loki.yml 6 | when: __install_loki 7 | 8 | - name: Install promtail 9 | include_tasks: promtail.yml 10 | when: 11 | - __install_promtail 12 | - not promtail_use_docker 13 | 14 | - name: Install promtail [Docker] 15 | include_tasks: promtail-docker.yml 16 | when: 17 | - __install_promtail 18 | - promtail_use_docker 19 | -------------------------------------------------------------------------------- /tasks/preflight-loki.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Is it installed? 3 | stat: 4 | path: /usr/local/bin/loki 5 | register: __loki_stat 6 | - name: Get version 7 | command: /usr/local/bin/loki -version 8 | changed_when: false 9 | register: __loki_version_out 10 | when: __loki_stat.stat.exists 11 | - name: Set version 12 | set_fact: 13 | __loki_version: "{{ __loki_version_out.stdout_lines[0].split(' ')[2] | replace('v', '') }}" 14 | when: __loki_stat.stat.exists 15 | -------------------------------------------------------------------------------- /tasks/preflight-promtail.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Is it installed? 3 | stat: 4 | path: /usr/local/bin/promtail 5 | register: __promtail_stat 6 | - name: Get version 7 | command: /usr/local/bin/promtail -version 8 | changed_when: false 9 | register: __promtail_version_out 10 | when: __promtail_stat.stat.exists 11 | - name: Set version 12 | set_fact: 13 | __promtail_version: "{{ __promtail_version_out.stdout_lines[0].split(' ')[2] | replace('v', '') }}" 14 | when: __promtail_stat.stat.exists 15 | -------------------------------------------------------------------------------- /tasks/preflight.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check targets 3 | assert: 4 | that: __install_loki or __install_promtail 5 | 6 | - name: Check version 7 | assert: 8 | that: not loki_version.startswith('v') 9 | fail_msg: "loki_version must be '1.2.0', and not 'v1.2.0'" 10 | 11 | - name: "Preflight: loki" 12 | include_tasks: preflight-loki.yml 13 | when: __install_loki 14 | 15 | - name: Empty version 16 | set_fact: 17 | __loki_version: "" 18 | when: 19 | - __install_loki 20 | - __loki_version is not defined 21 | 22 | - name: "Preflight: promtail" 23 | include_tasks: preflight-promtail.yml 24 | when: 25 | - __install_promtail 26 | - __promtail_version is not defined 27 | 28 | - name: Empty version 29 | set_fact: 30 | __promtail_version: "" 31 | when: not __promtail_stat.stat.exists 32 | -------------------------------------------------------------------------------- /tasks/promtail-config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create config directories for promtail 3 | file: 4 | mode: '0755' 5 | path: "{{ item }}" 6 | state: directory 7 | with_items: 8 | - "{{ promtail_config_directory }}" 9 | - /var/lib/promtail 10 | 11 | - name: Setup configuration 12 | template: 13 | src: "promtail.yml.j2" 14 | dest: "/etc/promtail/promtail.yml" 15 | mode: '0644' 16 | register: conf_tpl 17 | notify: 18 | - restart systemd promtail 19 | -------------------------------------------------------------------------------- /tasks/promtail-docker.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Configure 3 | import_tasks: promtail-config.yml 4 | 5 | - name: Download/pre-seed promtail image 6 | docker_image: 7 | name: "{{ promtail_docker_image }}" 8 | source: pull 9 | 10 | - name: Install systemd service 11 | template: 12 | src: systemd-promtail-docker.j2 13 | dest: /etc/systemd/system/promtail.service 14 | mode: '0644' 15 | notify: 16 | - reload systemd promtail 17 | - restart systemd promtail 18 | when: "__loki_go_os == 'linux'" 19 | -------------------------------------------------------------------------------- /tasks/promtail.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install systemd-unit 3 | template: 4 | src: "systemd-promtail.j2" 5 | dest: "/etc/systemd/system/promtail.service" 6 | mode: '0644' 7 | notify: 8 | - reload systemd promtail 9 | when: "__loki_go_os == 'linux'" 10 | 11 | - name: Configure 12 | import_tasks: promtail-config.yml 13 | 14 | - block: 15 | - name: Download promtail release 16 | get_url: 17 | url: "{{ __promtail_download }}" 18 | dest: "/tmp/{{ __promtail_archive }}" 19 | checksum: "sha256:{{ __loki_download_github }}/v{{ loki_version }}/SHA256SUMS" 20 | mode: '0644' 21 | register: _download_binary 22 | until: _download_binary is succeeded 23 | retries: 5 24 | delay: 2 25 | 26 | - name: Unpack promtail release 27 | unarchive: 28 | src: "/tmp/{{ __promtail_archive }}" 29 | dest: "/tmp" 30 | creates: "/tmp/promtail-{{ __loki_go_os }}-{{ __loki_go_arch }}" 31 | mode: '0644' 32 | remote_src: true 33 | 34 | - name: Copy promtail to /usr/local/bin 35 | copy: 36 | src: "/tmp/promtail-{{ __loki_go_os }}-{{ __loki_go_arch }}" 37 | dest: "/usr/local/bin/promtail" 38 | mode: 0755 39 | owner: root 40 | group: root 41 | remote_src: true 42 | notify: restart systemd promtail 43 | check_mode: false 44 | when: 45 | - (__promtail_version != loki_version) 46 | 47 | - name: Clean-up 48 | file: 49 | path: "/tmp/{{ item }}" 50 | state: absent 51 | when: 52 | - (__promtail_version != loki_version) 53 | loop: 54 | - "{{ __promtail_archive }}" 55 | - "promtail-{{ __loki_go_os }}-{{ __loki_go_arch }}" 56 | -------------------------------------------------------------------------------- /templates/loki.yml.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | 3 | auth_enabled: {{ loki_config_auth }} 4 | 5 | server: 6 | http_listen_address: {{ loki_config_http_address }} 7 | http_listen_port: {{ loki_config_http_port }} 8 | grpc_listen_address: 127.0.0.1 9 | log_level: {{ loki_config_log_level }} 10 | 11 | ingester: 12 | lifecycler: 13 | address: 127.0.0.1 14 | ring: 15 | kvstore: 16 | store: inmemory 17 | replication_factor: 1 18 | final_sleep: 0s 19 | chunk_idle_period: 5m 20 | chunk_retain_period: 30s 21 | 22 | schema_config: 23 | configs: 24 | - from: 2018-04-15 25 | store: boltdb 26 | object_store: filesystem 27 | schema: v9 28 | index: 29 | prefix: loki_index_ 30 | period: {{ loki_config_period }} 31 | 32 | storage_config: 33 | boltdb: 34 | directory: {{ loki_config_store }}/index 35 | 36 | filesystem: 37 | directory: {{ loki_config_store }}/chunks 38 | 39 | limits_config: 40 | enforce_metric_name: false 41 | reject_old_samples: true 42 | reject_old_samples_max_age: {{ loki_config_period }} 43 | 44 | chunk_store_config: 45 | max_look_back_period: {{ loki_config_retention }} 46 | 47 | table_manager: 48 | chunk_tables_provisioning: 49 | inactive_read_throughput: 0 50 | inactive_write_throughput: 0 51 | provisioned_read_throughput: 0 52 | provisioned_write_throughput: 0 53 | index_tables_provisioning: 54 | inactive_read_throughput: 0 55 | inactive_write_throughput: 0 56 | provisioned_read_throughput: 0 57 | provisioned_write_throughput: 0 58 | retention_deletes_enabled: true 59 | retention_period: {{ loki_config_retention }} 60 | -------------------------------------------------------------------------------- /templates/promtail.yml.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | server: 3 | http_listen_address: {{ promtail_config_server_listen }} 4 | http_listen_port: {{ promtail_config_server_port }} 5 | grpc_listen_address: {{ promtail_config_server_listen }} 6 | grpc_listen_port: 0 7 | log_level: {{ promtail_config_log_level }} 8 | 9 | # Positions 10 | positions: 11 | filename: /var/lib/promtail/positions.yaml 12 | 13 | # Loki Server URL 14 | clients: 15 | - url: http://{{ promtail_config_client_loki_address }}:{{ promtail_config_client_loki_port }}{{ promtail_config_client_loki_path }} 16 | {% if promtail_config_client_set_tenant_id %} 17 | tenant_id: {{ promtail_config_client_tenant_id }} 18 | {% endif %} 19 | external_labels: 20 | {% for label_key in promtail_config_client_external_labels %} 21 | {{ label_key }}: {{ promtail_config_client_external_labels[label_key] }} 22 | {% endfor %} 23 | 24 | {% if __loki_go_os == 'linux' %} 25 | scrape_configs: 26 | - job_name: journal 27 | journal: 28 | path: {{ promtail_config_scrape_journald_path }} 29 | labels: 30 | job: journal 31 | relabel_configs: 32 | - source_labels: ['__journal__systemd_unit'] 33 | target_label: 'unit' 34 | {% endif %} 35 | -------------------------------------------------------------------------------- /templates/systemd-loki.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Loki Log Aggregator 3 | Documentation=https://github.com/grafana/loki 4 | After=network.target 5 | 6 | [Service] 7 | Type=simple 8 | ExecStart=/usr/local/bin/loki -config.file /etc/loki/loki.yml 9 | Restart=always 10 | RestartSec=10 11 | StandardOutput=journal 12 | StandardError=journal 13 | Environment=SYSTEMD_LOG_LEVEL=debug 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /templates/systemd-promtail-docker.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Promtail Loki Agent 3 | Documentation=https://github.com/grafana/loki 4 | After=docker.service 5 | PartOf=docker.service 6 | Requires=docker.service 7 | 8 | [Service] 9 | TimeoutStartSec=0 10 | ExecStartPre=-/usr/bin/docker stop %n 11 | ExecStartPre=-/usr/bin/docker rm -f %n 12 | ExecStart=/usr/bin/docker run \ 13 | --rm \ 14 | -v {{ promtail_config_directory }}:{{ promtail_config_directory }}:ro \ 15 | -v {{ promtail_config_scrape_journald_path }}:{{ promtail_config_scrape_journald_path }} \ 16 | -v /var/lib/promtail:/var/lib/promtail \ 17 | -p 127.0.0.1:{{ promtail_config_server_port }}:{{ promtail_config_server_port }} \ 18 | --name %n {{ promtail_docker_image }} \ 19 | -config.file={{ promtail_config_directory }}/promtail.yml 20 | Restart=always 21 | RestartSec=10s 22 | SyslogIdentifier=%n 23 | 24 | [Install] 25 | WantedBy=docker.service 26 | -------------------------------------------------------------------------------- /templates/systemd-promtail.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Promtail Loki Agent 3 | Documentation=https://github.com/grafana/loki 4 | After=loki.service 5 | 6 | [Service] 7 | Type=simple 8 | User=root 9 | ExecStart=/usr/local/bin/promtail -config.file {{ promtail_config_directory }}/promtail.yml 10 | Restart=always 11 | RestartSec=10 12 | StandardOutput=journal 13 | StandardError=journal 14 | Environment=SYSTEMD_LOG_LEVEL=debug 15 | 16 | [Install] 17 | WantedBy=multi-user.target 18 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | __loki_go_os_map: 3 | alpine: linux 4 | archlinux: linux 5 | darwin: darwin 6 | debian: linux 7 | freebsd: freebsd 8 | # 'hp-ux' 9 | mandrake: linux 10 | redhat: linux 11 | # solaris 12 | suse: linux 13 | 14 | __loki_go_os: "{{ __loki_go_os_map[ansible_os_family | lower] | default('linux') }}" 15 | 16 | __loki_go_arch_map: 17 | i386: '386' 18 | x86_64: 'amd64' 19 | aarch64: 'arm64' 20 | armv7l: 'armv7' 21 | armv6l: 'armv6' 22 | 23 | __loki_go_arch: "{{ __loki_go_arch_map[ansible_architecture] | default(ansible_architecture) }}" 24 | 25 | __loki_download_github: "https://github.com/grafana/loki/releases/download" 26 | 27 | __loki_archive: "loki-{{ __loki_go_os }}-{{ __loki_go_arch }}.zip" 28 | __loki_download: "{{ __loki_download_github }}/v{{ loki_version }}/{{ __loki_archive }}" 29 | 30 | __promtail_archive: "promtail-{{ __loki_go_os }}-{{ __loki_go_arch }}.zip" 31 | __promtail_download: "{{ __loki_download_github }}/v{{ loki_version }}/{{ __promtail_archive }}" 32 | 33 | __install_loki: "{{ inventory_hostname in groups['loki'] | default([]) }}" 34 | __install_promtail: "{{ inventory_hostname in groups['promtail'] | default([]) }}" 35 | --------------------------------------------------------------------------------