github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/production/nomad/README.md (about)

     1  # Loki Nomad examples
     2  
     3  ## Requirements
     4  
     5  ### Hard requirements
     6  
     7  - recent version of Nomad [installed](https://www.nomadproject.io/docs/install) with healthy Docker driver
     8  - [Consul integration](https://www.nomadproject.io/docs/integrations/consul-integration)
     9    is enabled in Nomad
    10  - access to S3 storage
    11  
    12  ### Optional requirements
    13  
    14  - [Vault integration](https://www.nomadproject.io/docs/integrations/vault-integration)
    15    for providing S3 credentials securely
    16  - Traefik configured to use
    17    [Consul provider](https://doc.traefik.io/traefik/providers/consul-catalog/) to
    18    loadbalance between Loki instances
    19  
    20  ### Production use
    21  
    22  For use in production it is recommended to:
    23  
    24  - secure HTTP endpoints with
    25    [Consul Connect](https://www.nomadproject.io/docs/integrations/consul-connect)
    26  - setup authentication - can be achieved with
    27    [Traefik](https://doc.traefik.io/traefik/middlewares/http/basicauth/)
    28  - secure GRPC communication with mTLS - can be achived with Vault's
    29    [PKI secret engine](https://www.vaultproject.io/docs/secrets/pki)
    30  
    31  See [loki-distributed](./loki-distributed) README for more info.
    32  
    33  ## Service discovery when scaling
    34  
    35  When using multiple Loki instances memberlist advertises wrong address (see this
    36  [issue](https://github.com/grafana/loki/issues/5610)), that is why these
    37  examples are using Consul ring for service discovery.
    38  
    39  Is you are using Nomad then you are probably also using Consul, so this
    40  shouldn't be an issue.
    41  
    42  ## Run Loki behind loadbalancer
    43  
    44  When running multiple instances of Loki incoming requests should be
    45  loadbalanced.
    46  
    47  Register Loki in Traefik:
    48  
    49  ```hcl
    50  tags = [
    51    "traefik.enable=true",
    52    "traefik.http.routers.loki.entrypoints=https",
    53    "traefik.http.routers.loki.rule=Host(`loki.service.consul`)",
    54  ]
    55  ```
    56  
    57  ## Setup basicauth
    58  
    59  Generate basicauth credentials:
    60  
    61  ```shell
    62  > docker run --rm httpd:alpine htpasswd -nb promtail password123
    63  promtail:$apr1$Lr55BanK$BV/rE2POaOolkFz8kIfY4/
    64  ```
    65  
    66  Register Loki in Traefik:
    67  
    68  ```hcl
    69  tags = [
    70    "traefik.enable=true",
    71    "traefik.http.routers.loki.entrypoints=https",
    72    "traefik.http.routers.loki.rule=Host(`loki.service.consul`)",
    73    "traefik.http.middlewares.loki.basicauth.users=promtail:$apr1$Lr55BanK$BV/rE2POaOolkFz8kIfY4/",
    74    "traefik.http.routers.loki.middlewares=loki@consulcatalog",
    75  ]
    76  ```
    77  
    78  Update Promtail config:
    79  
    80  ```yaml
    81  clients:
    82    - url: https://loki.service.consul/loki/api/v1/push
    83      basic_auth:
    84        username: promtail
    85        password_file: password123
    86  ```
    87  
    88  ## Use HashiCorp Vault to provide S3 credentials
    89  
    90  To provide static credentials:
    91  
    92  ```hcl
    93  template {
    94    data = <<-EOH
    95    {{ with secret "secret/minio/loki" }}
    96    S3_ACCESS_KEY_ID={{ .Data.data.access_key }}
    97    S3_SECRET_ACCESS_KEY={{ .Data.data.secret_key }}
    98    {{- end }}
    99    EOH
   100  
   101    destination = "secrets/s3.env"
   102    env         = true
   103  }
   104  ```
   105  
   106  Is is better to provide dynamic credentials using
   107  [AWS secret engine](https://www.vaultproject.io/docs/secrets/aws) when using AWS
   108  S3:
   109  
   110  ```hcl
   111  template {
   112    data = <<-EOH
   113    {{ with secret "aws/creds/loki" -}}
   114    S3_ACCESS_KEY_ID={{ .Data.access_key }}
   115    S3_SECRET_ACCESS_KEY={{ .Data.secret_key }}
   116    {{- end }}
   117    EOH
   118  
   119    destination = "secrets/s3.env"
   120    env         = true
   121  }
   122  ```
   123  
   124  ## Supply alerting rules to Loki ruler with `local` ruler storage
   125  
   126  ### Using [`artifact` stanza](https://www.nomadproject.io/docs/job-specification/artifact)
   127  
   128  Alert rules can be downloaded from remote storage using artifact stanza. It
   129  supports:
   130  
   131  - Git
   132  - Mercurial
   133  - HTTP
   134  - Amazon S3
   135  - Google GCP
   136  
   137  Example with git:
   138  
   139  ```hcl
   140  artifact {
   141    source      = "git::github.com/<someorg>/<repo>//<subdirectory_with_loki_rules>"
   142    destination = "local/rules/"
   143  }
   144  ```
   145  
   146  ### Using local files
   147  
   148  Alert rules can be stored locally (beside job definition) and provided to Loki
   149  ruler container with
   150  [`template`](https://www.nomadproject.io/docs/job-specification/template) stanza
   151  and some HCL magic, namely:
   152  
   153  - [fileset](https://www.nomadproject.io/docs/job-specification/hcl2/functions/file/fileset) -
   154    to generate a list of files
   155  - [file](https://www.nomadproject.io/docs/job-specification/hcl2/functions/file/file) -
   156    to get the content of a file
   157  - [dynamic](https://www.nomadproject.io/docs/job-specification/hcl2/expressions#dynamic-blocks) -
   158    to dynamically generate `template` stanza for each file found
   159  
   160  Example:
   161  
   162  ```shell
   163  > tree rules/
   164  rules/
   165  └── fake
   166      └── some-alerts.yml
   167  
   168  1 directory, 1 file
   169  ```
   170  
   171  ```hcl
   172  dynamic "template" {
   173    for_each = fileset(".", "rules/**")
   174  
   175    content {
   176      data            = file(template.value)
   177      destination     = "local/${template.value}"
   178      left_delimiter  = "[["
   179      right_delimiter = "]]"
   180    }
   181  }
   182  ```
   183  
   184  Each file will end up in `/local/rules/` inside ruler container.
   185  
   186  ### Using Consul K/V and Terraform
   187  
   188  ```shell
   189  > tree loki-rules/
   190  loki-rules/
   191  └── fake
   192      └── some-alerts.yml
   193  
   194  1 directory, 1 file
   195  ```
   196  
   197  Using Terraform
   198  [Consul provider](https://registry.terraform.io/providers/hashicorp/consul/latest/docs/resources/keys)
   199  put all files in `loki-rules/` to Consul K/V
   200  
   201  ```hcl
   202  resource "consul_keys" "loki-rules" {
   203    dynamic "key" {
   204      for_each = fileset("${path.module}/loki-rules", "**")
   205      content {
   206        path   = "configs/loki-rules/${trimsuffix(key.value, ".yml")}"
   207        value  = file("${file.module}/loki-rules/${key.value}")
   208        delete = true
   209      }
   210    }
   211  }
   212  ```
   213  
   214  Provide rules from K/V to Loki ruler container inside Nomad with
   215  [`safeTree`](https://github.com/hashicorp/consul-template/blob/main/docs/templating-language.md#safetree)
   216  
   217  ```hcl
   218  template {
   219    data = <<-EOF
   220    {{- range safeTree "configs/loki-rules" }}
   221    ---
   222    {{ .Value | indent 2 }}
   223    {{ end -}}
   224    EOF
   225  
   226    destination   = "local/rules/fake/rules.yml"
   227    change_mode   = "signal"
   228    change_signal = "SIGINT"
   229  }
   230  ```
   231  
   232  When updated in Consul K/V rules will be automatically updated in Loki ruler.