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.