> For the complete documentation index, see [llms.txt](https://thorstenkramm.gitbook.io/saltstack/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://thorstenkramm.gitbook.io/saltstack/salt-mine.md).

# Salt-Mine

### In die Mine speichern

Die Salt-Mine erlaubt es Minions, auf Daten andere Minions zuzugreifen.

Dabei bestimmt jeder Minion, welche Daten er in der Mine ablegt und damit "freigibt". Eine Standard-Konfiguration für die Mine existiert nicht. Legen Sie mit folgendem Inhalt an:

{% code title="/etc/salt/minion.d/mine.conf" %}

```yaml
mine_interval: 2
mine_functions:
    network.ip_addrs: []
```

{% endcode %}

Nach dem Restart des Minions hinterlegt dieser nun all 2 Minuten seine IP-Adressen in der Mine.

> The Salt Mine functions are executed when the Minion starts and at a given interval by the scheduler. The default interval is every 60 minutes 📖 [Salt Doku](https://docs.saltproject.io/en/latest/topics/mine/)

Sie können mit `salt '*' mine.update` ein Update erzwingen.

Testen Sie, was in der Mine abgelegt wurde:

```
salt <MINION> config.get mine_functions
salt <MINION> mine.get '*' <FUNCTION>
```

{% hint style="warning" %}
**Achtung:** Daten, welche in der Mine liegen, können von allen Minions gelesen werden! `salt-call mine.get '*' network.ip_addrs`
{% endhint %}

Als Mine-Funktion können alle Salt-Module verwendet werden. Beispiel für eine `mine.conf`:

```
mine_functions:
  network.ip_addrs: []
  test.ping: []
  file.read: [/etc/hosts]
  cmd.run: [/bin/date]
```

### Mine zentral vom Master auf den Minion aktivieren

{% code title="/srv/salt/mine/activate.sls" %}

```yaml
/etc/salt/minion.d/mine.conf:
  file.managed:
    - contents: |
        mine_interval: 2
        mine_functions:
          network.ip_addrs: []
minion-restart:
  cmd.run:
    - name: salt-call service.restart salt-minion
    - bg: true
```

{% endcode %}

### Aus der Mine lesen <a href="#aus-der-mine-lesen" id="aus-der-mine-lesen"></a>

Nachdem Restart des Minions kann man testen, was in der Mine liegt:

```
salt <MINION> config.get mine_functions

minion1:
    ----------
    cmd.run:
        - /bin/date
    file.read:
        - /etc/hosts
    network.ip_addrs:
    test.ping:
    
salt <MINION> mine.get '*' cmd.run
<MINION>:
    ----------
    <MINION>:
        Thu Nov  8 09:10:45 UTC 2018
```

Daten aus der Mine können nun wie folgt in States verwendet werden:

{% code title="/srv/salt/exmaples/mine-read.sls" %}

```yaml
/tmp/mine-data.txt:
    file.managed:
        - contents: |
                IP Adressen:
                {% for minion, ip_addr in salt['mine.get']('*', 'network.ip_addrs', tgt_type='glob') | dictsort() %}
                    minion: {{ minion }}, ip: {{ ip_addr[0] }}
                {% endfor %}
                Datum:
                {% for minion, date in salt['mine.get']('*', 'cmd.run', tgt_type='glob') | dictsort() %}
                    minion: {{ minion }}, date: {{ date }}
                {% endfor %}
```

{% endcode %}

### In die Mine hereinschauen

```
salt '*' mine.get '*' network.ip_addrs
```

### Beispiel 1: Namensauflösung ohne DNS <a href="#beispiel-1-webserver-cluster-und-loadbalancer" id="beispiel-1-webserver-cluster-und-loadbalancer"></a>

Im nachfolgenden Beispiel werden sich all Minions gegenseitig in die lokale `/etc/hosts` Datei eintragen. Die Minions können sich dann per Namen erreichen, ohne dass diese in einen DNS Server eingetragen werden müssen.

{% code title="/srv/salt/network/hosts.sls" %}

```yaml
#
# Read all minion ids from the mine and add them to the hosts file
#
{% for minion_id, addrs in salt['mine.get']('*', 'network.ip_addrs', tgt_type='glob') | dictsort() %}
{{ minion_id }}:
  host.present:
    - ip: {{ addrs[0] }}
    - clean: True
    - names:
      - {{ minion_id }}
      - {{ minion_id }}.local
{% endfor %}
```

{% endcode %}

### Beispiel 2: Webserver-Cluster und Loadbalancer <a href="#beispiel-1-webserver-cluster-und-loadbalancer" id="beispiel-1-webserver-cluster-und-loadbalancer"></a>

Ein klassischer Anwendungsfall ist die Konfiguration von Loadbalancern. Diese müssen wissen, über welche Server die Last verteilt werden soll.

Über die Salt Mine können sich Server registrieren und der Minion des Loadbalancers hat Zugriff auf eine Serverliste, welche aus der Salt Mine generiert wird.

#### Schritt 1: Salt Mine auf den Minions aktivieren <a href="#schritt-1-salt-mine-auf-den-minions-aktivieren" id="schritt-1-salt-mine-auf-den-minions-aktivieren"></a>

Die Salt Mine kann auf den Minions zentral vom Salt Master mit dem nachfolgenden State aktiviert werden:

#### Schritt 2: Loadbalancer mit Mine-Daten konfigurieren <a href="#schritt-2-loadbalancer-mit-mine-daten-konfigurieren" id="schritt-2-loadbalancer-mit-mine-daten-konfigurieren"></a>

Und der Loadbalancer kann wie folgt auf die Liste zugreifen:

```
/tmp/loadbalancer.conf:
    file.managed:
        - contents: |
{% for server, addrs in salt['mine.get']('roles:web', 'network.ip_addrs', tgt_type='grain') | dictsort() %}
            server {{ server }} ip {{ addrs[0] }}
{% endfor %}
```

> Das Beispiel setzt voraus, dass die Backend-Minions ein Grain `roles:web` gesetzt haben.

{% code title="/srv/salt/caddy/loadbalancer.sls" %}

```yaml
{% if 'loadbalancer' not in pillar.get('roles',[]) %}
always-fails:
  test.fail_without_changes:
    - name: Requirement not met. Your role does not allow to become a loadbalancer 
    - failhard: True
{% else %}
include:
  - caddy

extend:
  /etc/caddy/Caddyfile:
    file.managed:
        - contents: |
            :80 {
                reverse_proxy * {% for server, addrs in salt['mine.get']('roles:php-backend', 'network.ip_addrs', tgt_type='pillar') | dictsort() -%}
                 {{ addrs[0]+" " }}
                {%- endfor %} {
                  lb_policy round_robin
              }
            }
{% endif %}
```

{% endcode %}

🧩 **Aufgabe:** Starten Sie einen neuen LXD Container und rollen Sie alle nötigen States aus, damit das neue System als Backend dem Cluster beitritt.&#x20;

<details>

<summary>Optimierung der Loadbalancer Konfiguration</summary>

```sls
include:
  - .init

<div data-gb-custom-block data-tag="set"></div>

<div data-gb-custom-block data-tag="for" data-0='mine.get' data-1='mine.get' data-2='mine.get' data-3='](' data-4='roles:webserver' data-5='network.ip_addrs' data-6=', tgt_type='>

<div data-gb-custom-block data-tag="set" data-0='0' data-1='0' data-2='0' data-3='0' data-4='0' data-5='0' data-6='0' data-7='0' data-8='0' data-9='0' data-10='0' data-11='0' data-12='0' data-13='0' data-14='0' data-15='0' data-16='0' data-17='0' data-18='0' data-19='0' data-20='0' data-21='0' data-22='0' data-23='0' data-24='0' data-25='0' data-26='0'></div>

</div>

extend:
    /etc/caddy/Caddyfile:
      file.managed:
        - contents: |
            # This is a loadbalancer config
            :80 {
              reverse_proxy * {{ backends | join(" ") }} {
                  lb_policy round_robin
              }
            }
```

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://thorstenkramm.gitbook.io/saltstack/salt-mine.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
