{"id":354180,"date":"2024-05-20T22:43:18","date_gmt":"2024-05-20T22:43:18","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=354180"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=354180","title":{"rendered":"<span>\u041c\u043e\u0439 \u043e\u043f\u044b\u0442 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 Grafana \u043f\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 Terraform \u0438\u043b\u0438 \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0441\u043b\u0438 \u043d\u0430\u0434\u043e\u0435\u043b\u043e \u0442\u044b\u043a\u0430\u0442\u044c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0438 \u0432 GUI<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412\u0430\u043c \u0441\u043a\u0430\u0437\u0430\u043b\u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430, \u0432\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 \u0441\u0432\u044f\u0437\u043a\u0443 Prometheus + Grafana. \u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u043b\u0438 Grafana \u043d\u0430 \u0441\u0432\u043e\u0438\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u0445 (VM\/Docker\/Kubernetes) \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 Data Source Prometheus (\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u0430\u043c \u0435\u0449\u0435 \u0441\u043a\u0430\u0437\u0430\u043b\u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 Grafana Loki) \u0438 \u0434\u0430\u043b\u0435\u0435 \u043f\u043e \u0433\u0430\u0439\u0434\u0430\u043c \u0438\u0437 \u044e\u0442\u0443\u0431\u0430 \u043d\u0430\u0447\u0430\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b \u0438 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0430\u043b\u0435\u0440\u0442\u044b.<\/p>\n<p>\u0412\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e, \u043d\u043e \u0432 \u043e\u0434\u0438\u043d \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0435 \u0434\u0443\u043c\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 Grafana \u0432 \u043a\u043e\u0434\u0435, \u0447\u0442\u043e\u0431\u044b \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043b\u0435\u0433\u043a\u043e \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u0442\u0435\u0440\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043b\u0438 \u0436\u0435 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0439 \u0441\u0440\u0435\u0434\u044b (dev\/prod). \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b \u043d\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0442\u0440\u0443\u0434\u0430, \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438 \u0447\u0435\u0440\u0435\u0437 GUI, \u043d\u043e \u043a\u0430\u043a \u0436\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0438, contact points \u0438 \u0441\u0430\u043c\u0438 \u0430\u043b\u0435\u0440\u0442\u044b?<br \/> \u0417\u043d\u0430\u043a\u043e\u043c\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f? \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0447\u0442\u043e \u043d\u0435\u0442. \u0410 \u0443 \u043c\u0435\u043d\u044f \u0434\u0430!<\/p>\n<h3>\u041f\u0435\u0440\u0435\u0434 \u043f\u0440\u043e\u0447\u0442\u0435\u043d\u0438\u0435\u043c<\/h3>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0438 \u043a\u043e\u043c\u0430\u043d\u0434. \u042f \u0431\u043e\u043b\u044c\u0448\u0435 \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0441\u0432\u043e\u0435\u043c \u043e\u043f\u044b\u0442\u0435 \u0438 \u043d\u0435 \u043f\u0440\u0435\u0441\u043b\u0435\u0434\u0443\u044e \u0446\u0435\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0431\u0443\u0447\u0430\u044e\u0449\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e, \u043d\u043e \u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u043a\u043e\u043c\u0443-\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442, \u0442\u043e \u044d\u0442\u043e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e!<\/p>\n<h3>\u0427\u0442\u043e \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c<\/h3>\n<p>\u0417\u0430\u0434\u0430\u0447\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430 &#8212; \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0443\u044e Grafana \u043f\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 terraform (\u043e\u0431\u043e\u0436\u0430\u044e \u0435\u0433\u043e!). \u041d\u043e \u043f\u0435\u0440\u0435\u0434 \u044d\u0442\u0438\u043c \u0438\u0437\u0443\u0447\u0438\u0432 \u0435\u0451 API \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0432 \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<h3>\u0421 \u0447\u0435\u043c \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c<\/h3>\n<p>\u0423 \u043c\u0435\u043d\u044f \u0432 \u0440\u0430\u0441\u043f\u043e\u0440\u044f\u0436\u0435\u043d\u0438\u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044b\u0439 Prometheus \u0438 Grafana Loki, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0435 \u043a Grafana (\u0432\u0441\u0435 \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f \u0432 Kubernetes). \u0418\u043c\u0435\u0435\u0442\u0441\u044f \u0434\u0432\u0430 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430: \u043f\u0435\u0440\u0432\u044b\u0439 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043d\u044b\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438 \u0432\u0442\u043e\u0440\u043e\u0439 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u043b\u043e\u0433\u043e\u0432. \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u0432 \u044d\u0442\u0438\u0445 \u0434\u0432\u0443\u0445 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u0441\u0432\u043e\u0439 \u0430\u043b\u0435\u0440\u0442. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u0430\u043b\u0435\u0440\u0442\u0430\u043c\u0438 \u0432 \u043f\u0435\u0440\u0432\u043e\u043c \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0435, \u0432 \u0434\u0438\u0441\u043a\u043e\u0440\u0434 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f, \u0435\u0441\u043b\u0438 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 resolved \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u0432\u043d\u043e\u0432\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d.  \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u0430\u043b\u0435\u0440\u0442\u0430\u043c\u0438 \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0435, \u0432 \u0434\u0438\u0441\u043a\u043e\u0440\u0434 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f, \u0435\u0441\u043b\u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e ERROR \u043b\u043e\u0433\u043e\u0432 \u0432 \u043c\u0438\u043d\u0443\u0442\u0443 \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u043b\u043e 25 \u0435\u0434\u0438\u043d\u0438\u0446. <\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/q6\/xg\/gh\/q6xgghtplfnhpnhachro4qfbi3y.png\" data-src=\"https:\/\/habrastorage.org\/webt\/q6\/xg\/gh\/q6xgghtplfnhpnhachro4qfbi3y.png\"\/><\/figure>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ih\/vu\/as\/ihvuasqtck41-1sfrfify-3cegc.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ih\/vu\/as\/ihvuasqtck41-1sfrfify-3cegc.png\"\/><\/figure>\n<h3>Grafana API<\/h3>\n<h4>API-\u043a\u043b\u044e\u0447<\/h4>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c API \u043a\u043b\u044e\u0447, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a API \u0433\u0440\u0430\u0444\u0430\u043d\u044b. \u0417\u0430\u0439\u0434\u0435\u043c \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0443 &#171;Service accounts&#187; <\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/9o\/4b\/b6\/9o4bb6ltfbrucb5h25wjjaavdpm.png\" data-src=\"https:\/\/habrastorage.org\/webt\/9o\/4b\/b6\/9o4bb6ltfbrucb5h25wjjaavdpm.png\"\/><\/figure>\n<p> \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0439 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0441 \u0440\u043e\u043b\u044c\u044e Admin \u0438 \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e terraform: <\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/fi\/uf\/ys\/fiufyss6v6vlcnsxrpc2ifmb_ik.png\" data-src=\"https:\/\/habrastorage.org\/webt\/fi\/uf\/ys\/fiufyss6v6vlcnsxrpc2ifmb_ik.png\"\/><\/figure>\n<p> \u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0433\u043e \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 \u0438 \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u043c \u0434\u0430\u0442\u0443 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430: <\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ob\/fh\/u0\/obfhu0khts3sv3p8_lfpxl1cxyu.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ob\/fh\/u0\/obfhu0khts3sv3p8_lfpxl1cxyu.png\"\/><\/figure>\n<p> \u0421\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u0435\u0433\u043e \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f: <\/p>\n<pre><code class=\"bash\">$ export GRAFANA_TOKEN=&lt;token_itself> <\/code><\/pre>\n<h4>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 ID \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432<\/h4>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043a REST API \u0433\u0440\u0430\u0444\u0430\u043d\u044b \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u0432\u044b\u0448\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u043c:<\/p>\n<pre><code class=\"bash\">$ curl -H \"Authorization: Bearer $GRAFANA_TOKEN\" https:\/\/&lt;grafana_host>\/api\/dashboards\/home | jq {   \"meta\": {     \"isHome\": true,     \"canSave\": false,     \"canEdit\": true,     \"canAdmin\": false, &lt;other_content_is_hidden> } <\/code><\/pre>\n<p>\u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e Grafana v10.0.5, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0435 \u0442\u043e\u0447\u043a\u0438 <a href=\"https:\/\/grafana.com\/docs\/grafana\/v10.0\/developers\/http_api\/\" rel=\"noopener noreferrer nofollow\">\u043e\u0442\u0441\u044e\u0434\u0430<\/a>. \u0418 \u0442\u0430\u043a, \u043f\u043e\u043b\u0443\u0447\u0438\u043c ID \u0432\u0441\u0435\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 terraform. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"bash\">curl --location 'https:\/\/&lt;grafana_host>\/api\/datasources' \\  --header \"Authorization: Bearer $GRAFANA_TOKEN\" | jq [   {     \"id\": 5,     \"uid\": \"FeVw13D2\",     \"orgId\": 1,     \"name\": \"Loki\",     \"type\": \"loki\", &lt;other_content_is_hidden>   },   {     \"id\": 1,     \"uid\": \"d4V1dDwe\",     \"orgId\": 1,     \"name\": \"Prometheus\",     \"type\": \"prometheus\",     &lt;other_content_is_hidden>   } ] <\/code><\/pre>\n<p>\u0421\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u043e\u0432:<\/p>\n<pre><code class=\"bash\">$ curl --location \"https:\/\/&lt;grafana_host>\/api\/search?query=%\" \\        --header \"Authorization: Bearer $GRAFANA_TOKEN\" | jq [   {     \"id\": 9,     \"uid\": \"FvDw34Dq\",     \"title\": \"Kubernetes deployment running status\", &lt;other_content_is_hidden>   },   {     \"id\": 12,     \"uid\": \"3Cw21Sqwr\",     \"title\": \"Kubernetes logging\",     &lt;other_content_is_hidden>   } ] <\/code><\/pre>\n<p>\u0421\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u043f\u0430\u043f\u043e\u043a:<\/p>\n<pre><code class=\"bash\">$ curl --location \"https:\/\/&lt;grafana_host>\/api\/folders\" \\  --header \"Authorization: Bearer $GRAFANA_TOKEN\" | jq [   {     \"id\": 11,     \"uid\": \"8Dve31Xcs\",     \"title\": \"Discord Alerting\"   },   {     \"id\": 14,     \"uid\": \"cDq3s12Zs\",     \"title\": \"Discord Alerting Loki\"   } ] <\/code><\/pre>\n<p>\u0421\u043f\u0438\u0441\u043e\u043a contact points:<\/p>\n<pre><code class=\"bash\">$ curl --location \"https:\/\/&lt;grafana_host>\/api\/v1\/provisioning\/contact-points\" \\ --header \"Authorization: Bearer $GRAFANA_TOKEN\" | jq [   {     \"uid\": \"cMux1S3cS\",     \"name\": \"Discord\",     \"type\": \"discord\",   &lt;other_content_is_hidden>     \"disableResolveMessage\": false   },   {     \"uid\": \"BqgE23vD\",     \"name\": \"Discord (without Resolved)\",     \"type\": \"discord\",     &lt;other_content_is_hidden>     \"disableResolveMessage\": true   } ] <\/code><\/pre>\n<p>\u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0432\u044b \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438 \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0430\u043b\u0435\u0440\u0442\u043e\u0432. \u042f \u0434\u043e\u043b\u0433\u043e \u0438\u0441\u043a\u0430\u043b \u0438 \u043d\u0430\u0448\u0435\u043b \u043d\u0430 \u0444\u043e\u0440\u0443\u043c\u0435 \u0433\u0440\u0430\u0444\u0430\u043d\u044b \u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443:<\/p>\n<pre><code class=\"bash\">curl --location \"https:\/\/&lt;grafana_host>\/api\/ruler\/grafana\/api\/v1\/rules\" \\  --header \"Authorization: Bearer $GRAFANA_TOKEN\" | jq {   \"Discord Alerting\": [     {       \"name\": \"default\",       \"interval\": \"30s\",       \"rules\": [         {           \"expr\": \"\",           \"for\": \"3m\",           \"labels\": {             \"discord\": \"channel\"           },           \"annotations\": {             &lt;other_content_is_hidden>             \"description\": \"site-api status available\"           },           \"grafana_alert\": {             \"id\": 9,             \"orgId\": 1,             \"title\": \"site-api status available\",             \"condition\": \"B\",             \"data\": [               {                 &lt;other_content_is_hidden>                 \"datasourceUid\": \"d4V1dDwe\",                 \"model\": {                   \"datasource\": {                     \"type\": \"prometheus\",                     \"uid\": \"d4V1dDwe\"                   },                   \"editorMode\": \"builder\",                   \"expr\": \"kube_deployment_status_replicas_available{namespace=\\\"development\\\", deployment=\\\"site-api\\\"}\",                   &lt;other_content_is_hidden>                 }               }             ],             \"intervalSeconds\": 30,             \"uid\": \"fW3vDw31S\",             &lt;other_content_is_hidden>           }         },       ]     }   ],   \"Discord Alerting Loki\": [     {       \"name\": \"default\",       \"interval\": \"30s\",       \"rules\": [         {           \"expr\": \"\",           \"for\": \"30s\",           \"labels\": {             \"discord\": \"channel_resolved_0\",           },           \"annotations\": {         &lt;other_content_is_hidden>             \"description\": \"office-api ERROR logs count MORE THAN 25 for one minute!\"           },           \"grafana_alert\": {             \"id\": 17,             \"orgId\": 1,             \"title\": \"office-api ERROR logs count\",             \"condition\": \"B\",             \"data\": [               {                 &lt;other_content_is_hidden>                 \"datasourceUid\": \"FeVw13D2\",                 \"model\": {                   \"datasource\": {                     \"type\": \"loki\",                     \"uid\": \"FeVw13D2\"                   },                   \"editorMode\": \"code\",                   \"expr\": \"count_over_time(({namespace=\\\"development\\\", app=\\\"office-api\\\"} |= \\\"ERROR\\\")[1m])\",                   &lt;other_content_is_hidden>                 },                 {                   &lt;other_content_is_hidden>                 }               }             ],             \"intervalSeconds\": 20,                         \"uid\": \"-vFw2ZdwW\",             &lt;other_content_is_hidden>           }         }       ]     }   ] } <\/code><\/pre>\n<p>\u0412 &#171;rules&#187; \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0430\u043b\u0435\u0440\u0442\u043e\u0432 \u0438 \u0438\u0445 id. \u0423 \u043c\u0435\u043d\u044f \u0438\u0445 \u043c\u043d\u043e\u0433\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0430\u043f\u043a\u0438.<\/p>\n<h3>Terraform<\/h3>\n<h4>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443<\/h4>\n<p>\u041a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 Git \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0430\u0436\u043d\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0430\u043f\u043e\u043a \u0438 \u0444\u0430\u0439\u043b\u043e\u0432.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0430\u043f\u043e\u043a:<\/p>\n<pre><code class=\"bash\">$ tree -a . \u251c\u2500\u2500 .env.example \u251c\u2500\u2500 environments \u2502   \u2514\u2500\u2500 development \u2502       \u251c\u2500\u2500 .env \u2502       \u251c\u2500\u2500 main.tf \u2502       \u2514\u2500\u2500 variables.tf \u251c\u2500\u2500 .gitignore \u2514\u2500\u2500 modules     \u251c\u2500\u2500 grafana_alerting     \u2502   \u251c\u2500\u2500 main.tf     \u2502   \u251c\u2500\u2500 outputs.tf     \u2502   \u2514\u2500\u2500 variables.tf     \u2514\u2500\u2500 grafana_oss         \u251c\u2500\u2500 main.tf         \u251c\u2500\u2500 outputs.tf         \u2514\u2500\u2500 variables.tf <\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 .gitignore \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432 git \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u0444\u0430\u0439\u043b\u044b, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 terraform \u0438 \u0444\u0430\u0439\u043b\u044b, \u0445\u0440\u0430\u043d\u044f\u0449\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code># file: .\/.gitignore *terraform* .env <\/code><\/pre>\n<p>\u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u0432\u043e\u0439 .env \u0444\u0430\u0439\u043b \u0441\u043e \u0441\u0432\u043e\u0438\u043c\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. \u0422\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u0438 \u0444\u0430\u0439\u043b\u044b \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 git, \u0442\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0444\u0430\u0439\u043b .env.example, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u0443\u0441\u0442\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438:<\/p>\n<pre><code class=\"bash\"># file: .\/.env.example export GRAFANA_AUTH= export GRAFANA_URL= <\/code><\/pre>\n<p>\u042d\u0442\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u0432 terraform. GRAFANA_AUTH \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c API \u0442\u043e\u043a\u0435\u043d \u0438\u043b\u0438 login\/password \u0432 base64. \u0427\u0435\u0440\u0435\u0437 GRAFANA_URL \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0430\u0434\u0440\u0435\u0441 \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u0430 \u0433\u0440\u0430\u0444\u0430\u043d\u0430.<\/p>\n<p>\u0421\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b \u0432 \u043f\u0430\u043f\u043a\u0443 .\/environments\/development \u0438 \u0443\u043a\u0430\u0436\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">$ cp .\/.env.example .\/environments\/development\/.env <\/code><\/pre>\n<pre><code class=\"bash\"># file: .\/environments\/development\/.env export GRAFANA_AUTH=$GRAFANA_TOKEN export GRAFANA_URL=\"https:\/\/&lt;grafana_host>\/\" <\/code><\/pre>\n<h4>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430<\/h4>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 <a href=\"https:\/\/docs.comcloud.xyz\/providers\/grafana\/grafana\/latest\" rel=\"noopener noreferrer nofollow\">Grafana<\/a> \u0438 \u043d\u0430\u0448\u0438 \u0431\u0443\u0434\u0443\u0449\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0438:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/development\/main.tf  terraform {   required_providers {     grafana = {       source = \"grafana\/grafana\"       version = \"2.1.0\"     }   } }  provider \"grafana\" { }  module \"grafana_oss\" {   source = \"..\/..\/modules\/grafana_oss\" }  module \"grafana_alerting\" {   source = \"..\/..\/modules\/grafana_alerting\" } <\/code><\/pre>\n<p>\u0412 <a href=\"http:\/\/main.tf\" rel=\"noopener noreferrer nofollow\">main.tf<\/a> \u0444\u0430\u0439\u043b \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043c\u043e\u0434\u0443\u043b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c Grafana \u0432 required_providers:<\/p>\n<pre><code class=\"json\">\/\/ files: .\/modules\/grafana_oss\/main.tf &amp;&amp; .\/modules\/grafana_alerts\/main.tf  terraform {   required_providers {     grafana = {       source = \"grafana\/grafana\"       version = \"2.1.0\"     }   } } <\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c .env \u0444\u0430\u0439\u043b \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">$ . .\/environments\/development\/.env <\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c terraform init \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430:<\/p>\n<pre><code class=\"bash\">$ terraform -chdir=.\/environments\/development init  Initializing the backend... Initializing modules... - grafana_alerting in ..\/..\/modules\/grafana_alerting - grafana_oss in ..\/..\/modules\/grafana_oss  Initializing provider plugins... - Finding grafana\/grafana versions matching \"2.1.0\"... - Installing grafana\/grafana v2.1.0... - Installed grafana\/grafana v2.1.0 (unauthenticated) <\/code><\/pre>\n<h4>\u0418\u043c\u043f\u043e\u0440\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438<\/h4>\n<p>Terraform \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u0441 \u043d\u0435\u0434\u0430\u0432\u043d\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 HQL. \u0417\u0430\u0442\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0438 \u0441\u0430\u043c\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c \u0432 \u043c\u043e\u0434\u0443\u043b\u044c \u0441\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0430\u043c\u0438 Terraform.<\/p>\n<h3>grafana_folder<\/h3>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0443 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0432 \u0435\u0451 UID \u0438\u043b\u0438 ID. \u0412\u0435\u0437\u0434\u0435 \u0433\u0434\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c UID. \u0423 \u043c\u0435\u043d\u044f \u0434\u0432\u0435 \u043f\u0430\u043f\u043a\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0438\u0445 \u043e\u0431\u0435. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043a\u043e\u043d\u0435\u0446 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0433\u043e <a href=\"http:\/\/main.tf\" rel=\"noopener noreferrer nofollow\">main.tf<\/a> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/main.tf &lt;other_content_is_hidden>  import {   id = \"8Dve31Xcs\"   to = grafana_folder.discord-alerting }  import {   id = \"cDq3s12Zs\"   to = grafana_folder.discord-alerting-loki } <\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 terraform plan \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c -generate-out-config \u0438 \u0443\u043a\u0430\u0437\u0430\u0432 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430:<\/p>\n<pre><code class=\"bash\">terraform -chdir=.\/environments\/development plan -generate-config-out folder.tf grafana_folder.discord-alerting: Preparing import... [id=8Dve31Xcs] grafana_folder.discord-alerting-loki: Preparing import... [id=cDq3s12Zs] grafana_folder.discord-alerting-loki: Refreshing state... [id=cDq3s12Zs] grafana_folder.discord-alerting: Refreshing state... [id=8Dve31Xcs]  Terraform will perform the following actions:    # grafana_folder.discord-alerting will be imported   # (config will be generated)     resource \"grafana_folder\" \"discord-alerting\" {         id     = \"0:11\"         org_id = \"0\"         title  = \"Discord Alerting\"         uid    = \"8Dve31Xcs\"         url    = \"https:\/\/&lt;grafana_host>\/dashboards\/f\/8Dve31Xcs\/discord-alerting\"     }    # grafana_folder.discord-alerting-loki will be imported   # (config will be generated)     resource \"grafana_folder\" \"discord-alerting-loki\" {         id     = \"0:14\"         org_id = \"0\"         title  = \"Discord Alerting Loki\"         uid    = \"cDq3s12Zs\"         url    = \"https:\/\/&lt;grafana_host>\/dashboards\/f\/cDq3s12Zs\/discord-alerting-loki\"     }  Plan: 2 to import, 0 to add, 0 to change, 0 to destroy. <\/code><\/pre>\n<p>terraform \u0432\u044b\u0432\u0435\u043b \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043b \u0444\u0430\u0439\u043b <a href=\"http:\/\/folder.tf\" rel=\"noopener noreferrer nofollow\">folder.tf<\/a> \u0441 \u0433\u043e\u0442\u043e\u0432\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439. \u041f\u0440\u0438\u043c\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435:<\/p>\n<pre><code class=\"bash\">$ terraform -chdir=.\/environments\/development apply            Terraform will perform the following actions: &lt;imported_resources> Plan: 2 to import, 0 to add, 0 to change, 0 to destroy.  Do you want to perform these actions?   Terraform will perform the actions described above.   Only 'yes' will be accepted to approve.    Enter a value: yes  grafana_folder.discord-alerting: Importing... [id=8Dve31Xcs] grafana_folder.discord-alerting: Import complete [id=8Dve31Xcs] grafana_folder.discord-alerting-loki: Importing... [id=cDq3s12Zs] grafana_folder.discord-alerting-loki: Import complete [id=cDq3s12Zs]  Apply complete! Resources: 2 imported, 0 added, 0 changed, 0 destroyed. <\/code><\/pre>\n<p>terraform \u043f\u0440\u043e\u0441\u0438\u0442 \u0432\u0432\u0435\u0441\u0442\u0438 yes, \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u0438\u043d\u044f\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u041e\u043d \u0442\u0430\u043a\u0436\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u0432 \u0445\u043e\u0434\u0435 terraform apply \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0434\u0432\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u0430.<\/p>\n<p>\u0423\u0434\u0430\u043b\u0438\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u044b import \u0438\u0437 <a href=\"http:\/\/main.tf\" rel=\"noopener noreferrer nofollow\">main.tf<\/a> \u0444\u0430\u0439\u043b\u0430. \u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0438 \u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438\u0437 root \u043c\u043e\u0434\u0443\u043b\u044f \u0432 grafana_oss. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b:<\/p>\n<pre><code class=\"bash\">$ mv .\/environments\/development\/folder.tf .\/modules\/grafana_oss  <\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c terraform plan, \u0442\u043e terraform \u0443\u0432\u0438\u0434\u0438\u0442, \u0447\u0442\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0438\u0441\u0447\u0435\u0437\u043b\u0430 \u0438 \u0437\u0430\u0445\u043e\u0447\u0435\u0442 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0440\u0435\u0441\u0443\u0440\u0441\u044b. \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u0441\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c, \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u043c \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0432 \u043c\u043e\u0434\u0443\u043b\u044c:<\/p>\n<pre><code class=\"bash\">$ terraform -chdir=.\/environments\/development state mv grafana_folder.discord-alerting module.grafana_oss.grafana_folder.discord-alerting Move \"grafana_folder.discord-alerting\" to \"module.grafana_oss.grafana_folder.discord-alerting\" Successfully moved 1 object(s).  $ terraform -chdir=.\/environments\/development state mv grafana_folder.discord-alerting-loki module.grafana_oss.grafana_folder.discord-alerting-loki Move \"grafana_folder.discord-alerting-loki\" to \"module.grafana_oss.grafana_folder.discord-alerting-loki\" Successfully moved 1 object(s). <\/code><\/pre>\n<p>\u0423\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0438\u043c\u043f\u043e\u0440\u0442 \u043f\u0440\u043e\u0448\u0435\u043b \u0443\u0441\u043f\u0435\u0448\u043d\u043e:<\/p>\n<pre><code class=\"bash\">$ terraform -chdir=.\/environments\/development plan  module.grafana_oss.grafana_folder.discord-alerting-loki: Refreshing state... [id=0:14] module.grafana_oss.grafana_folder.discord-alerting: Refreshing state... [id=0:11]  No changes. Your infrastructure matches the configuration.  Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed. <\/code><\/pre>\n<p>Terraform \u043d\u0435 \u0432\u0438\u0434\u0438\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0438 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442, \u0447\u0442\u043e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438.<br \/> \u041f\u0440\u043e\u0432\u0435\u0440\u043d\u0435\u043c \u0442\u0435 \u0436\u0435 \u0441\u0430\u043c\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c\u0438.<\/p>\n<h3>grafana_data_source<\/h3>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u044b import \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/main.tf &lt;other_content_is_hidden>  import {   id = \"d4V1dDwe\"   to = grafana_data_source.prometheus }  import {   id = \"FeVw13D2\"   to = grafana_data_source.loki } <\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c terraform plan:<\/p>\n<pre><code class=\"bash\">terraform -chdir=.\/environments\/development plan -generate-config-out data_source.tf Terraform will perform the following actions:    # grafana_data_source.loki will be imported   # (config will be generated)     resource \"grafana_data_source\" \"loki\" {         access_mode        = \"proxy\"         basic_auth_enabled = false         id                 = \"1:5\"         is_default         = false         json_data_encoded  = jsonencode(             {                 manageAlerts = false             }         )         name               = \"Loki\"         org_id             = \"1\"         type               = \"loki\"         uid                = \"FeVw13D2\"         url                = \"http:\/\/loki-stack:3100\"     }    # grafana_data_source.prometheus will be imported   # (config will be generated)     resource \"grafana_data_source\" \"prometheus\" {         access_mode        = \"proxy\"         basic_auth_enabled = false         id                 = \"1:1\"         is_default         = true         json_data_encoded  = jsonencode(             {                 httpMethod    = \"POST\"                 tlsSkipVerify = true             }         )         name               = \"Prometheus\"         org_id             = \"1\"         type               = \"prometheus\"         uid                = \"d4V1dDwe\"         url                = \"http:\/\/prometheus-kube-prometheus-prometheus:9090\"     }  Plan: 2 to import, 0 to add, 0 to change, 0 to destroy. <\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c terraform apply \u0438 \u043f\u0435\u0440\u0435\u0434 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u043a\u043e\u0434\u0430 \u0432 \u043c\u043e\u0434\u0443\u043b\u044c, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e, \u0443\u0434\u0430\u043b\u0438\u0432 \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/development\/data_source.tf resource \"grafana_data_source\" \"loki\" {   json_data_encoded        = \"{\\\"manageAlerts\\\":false}\"   name                     = \"Loki\"   org_id                   = \"1\"   type                     = \"loki\"   uid                      = \"FeVw13D2\"   url                      = \"http:\/\/loki-stack:3100\" }  resource \"grafana_data_source\" \"prometheus\" {   is_default               = true   json_data_encoded        = \"{\\\"httpMethod\\\":\\\"POST\\\",\\\"tlsSkipVerify\\\":true}\"   name                     = \"Prometheus\"   org_id                   = \"1\"   type                     = \"prometheus\"   uid                      = \"d4V1dDwe\"   url                      = \"http:\/\/prometheus-kube-prometheus-prometheus:9090\" } <\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u043c \u0432\u0441\u0451 \u0432 \u043c\u043e\u0434\u0443\u043b\u044c:<\/p>\n<pre><code class=\"bash\">$ mv .\/environments\/development\/data_source.tf .\/modules\/grafana_oss   $ terraform -chdir=.\/environments\/development state mv grafana_data_source.loki module.grafana_oss.grafana_data_source.loki                  Move \"grafana_data_source.loki\" to \"module.grafana_oss.grafana_data_source.loki\" Successfully moved 1 object(s).  $ terraform -chdir=.\/environments\/development state mv grafana_data_source.prometheus module.grafana_oss.grafana_data_source.prometheus Move \"grafana_data_source.prometheus\" to \"module.grafana_oss.grafana_data_source.prometheus\" Successfully moved 1 object(s). <\/code><\/pre>\n<p>\u0412\u044b\u043d\u0435\u0441\u0435\u043c url \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 terraform \u0434\u043b\u044f \u0433\u0438\u0431\u043a\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u043e\u043c <a href=\"http:\/\/variables.tf\" rel=\"noopener noreferrer nofollow\">variables.tf<\/a> \u0441\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e &#8212; \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044b \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 Grafana \u0432 Kubernetes \u0438\u043b\u0438 docker-compose, \u0442\u043e \u043e\u043d\u0438 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u0442\u0430\u043a\u0438\u043c\u0438:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/modules\/grafana_oss\/variables.tf variable \"loki_data_source_url\" {   type = string   default = \"http:\/\/loki-stack:3100\" }  variable \"prometheus_data_source_url\" {   type = string   default = \"http:\/\/prometheus-kube-prometheus-prometheus:9090\" } <\/code><\/pre>\n<p>\u0423\u0434\u0430\u043b\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0438 \u0432\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u0443\u043a\u0430\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/modules\/grafana_oss\/data_source.tf resource \"grafana_data_source\" \"loki\" {   &lt;other_content_is_hidden>   url                      = var.loki_data_source_url }  resource \"grafana_data_source\" \"prometheus\" {   &lt;other_content_is_hidden>   url                      = var.prometheus_data_source_url } <\/code><\/pre>\n<h3>grafana_dashboard<\/h3>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b. \u041f\u043e\u043c\u0438\u043c\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0432 Terraform, \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430 \u0432 Grafana \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u044f JSON \u0441\u0445\u0435\u043c\u0430. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b \u0432 Terraform:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/development\/main.tf &lt;other_content_is_hidden>  import {   id = \"FvDw34Dq\"   to = grafana_dashboard.k8s-deployment-running-status }  import {   id = \"3Cw21Sqwr\"   to = grafana_dashboard.k8s-logging } <\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c terraform plan \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"bash\">$ terraform -chdir=.\/environments\/development plan -generate-config-out=dashboard.tf  &lt;other_content_is_hidden> Plan: 2 to import, 0 to add, 0 to change, 0 to destroy. <\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u043c \u0432\u0441\u0451 \u0432 \u043c\u043e\u0434\u0443\u043b\u044c:<\/p>\n<pre><code class=\"bash\">$ terraform -chdir=.\/environments\/development apply  &lt;other_content_is_hidden> Plan: 2 to import, 0 to add, 0 to change, 0 to destroy.  Do you want to perform these actions?   Terraform will perform the actions described above.   Only 'yes' will be accepted to approve.    Enter a value: yes  grafana_dashboard.k8s-logging: Importing... [id\"3Cw21Sqwr] grafana_dashboard.k8s-logging: Import complete [id\"3Cw21Sqwr] grafana_dashboard.k8s-deployment-running-status: Importing... [id=FvDw34Dq] grafana_dashboard.k8s-deployment-running-status: Import complete [id=FvDw34Dq]  Apply complete! Resources: 2 imported, 0 added, 0 changed, 0 destroyed.  $ mv .\/environments\/development\/dashboard.tf .\/modules\/grafana_oss   $ terraform -chdir=.\/environments\/development state mv grafana_dashboard.k8s-deployment-running-status module.grafana_oss.grafana_dashboard.k8s-deployment-running-status  Move \"grafana_dashboard.k8s-deployment-running-status\" to \"module.grafana_oss.grafana_dashboard.k8s-deployment-running-status\" Successfully moved 1 object(s).  $ terraform -chdir=.\/environments\/development state mv grafana_dashboard.k8s-logging module.grafana_oss.grafana_dashboard.k8s-logging Move \"grafana_dashboard.k8s-logging\" to \"module.grafana_oss.grafana_dashboard.k8s-logging\" Successfully moved 1 object(s). <\/code><\/pre>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/modules\/grafana_oss\/dashboard.tf resource \"grafana_dashboard\" \"k8s-logging\" {   config_json = \"&lt;huge_json_content>\"   folder      = null   message     = null   org_id      = \"0\"   overwrite   = null }  resource \"grafana_dashboard\" \"k8s-deployment-running-status\" {   config_json = \"&lt;huge_json_content>\"   folder      = null   message     = null   org_id      = \"0\"   overwrite   = null } <\/code><\/pre>\n<p>\u0412 config_json \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f JSON \u0441\u0445\u0435\u043c\u0430 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430. \u0422\u0430\u043a \u043a\u0430\u043a \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0447\u0435\u043d\u044c \u0434\u043b\u0438\u043d\u043d\u043e\u0435, \u0442\u043e \u044f \u0440\u0435\u0448\u0438\u043b \u0435\u0433\u043e \u043d\u0435 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c. \u0425\u0440\u0430\u043d\u0438\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u044f\u043c\u043e \u0432 \u043a\u043e\u0434\u0435 \u043f\u043b\u043e\u0445\u0430\u044f \u0438\u0434\u0435\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b\u043d\u0435\u0441\u0435\u043c JSON \u0441\u0445\u0435\u043c\u0443 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0430\u043f\u043a\u0443 \u0433\u0434\u0435 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0441\u0445\u0435\u043c\u044b \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u043e\u0432:<\/p>\n<pre><code class=\"bash\">$ mkdir dasboard_schemas <\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0434 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u043e\u043c JSON \u0438\u0437 config_json \u0432 \u0444\u0430\u0439\u043b, \u0435\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0435\u0436\u0434\u0435 \u0434\u0435\u0437\u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u0414\u043b\u044f \u0434\u0435\u0437\u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u043a \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 Python, \u0430 \u0437\u0430\u0442\u0435\u043c \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432\u044b\u0432\u043e\u0434 echo \u0432 \u0443\u0442\u0438\u043b\u0438\u0442\u0443 jq. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b \u0431\u043e\u043b\u0435\u0435 \u043b\u0435\u0433\u043a\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c &#8212; \u0447\u0435\u0440\u0435\u0437 GUI \u0413\u0440\u0430\u0444\u0430\u043d\u044b.<\/p>\n<p>\u0417\u0430\u0439\u0434\u0435\u043c \u0432 \u0434\u0430\u0448\u0431\u043e\u0440\u0434 Kubernetes logging \u0438 \u043d\u0430\u0436\u043c\u0435\u043c \u043d\u0430 Export: <\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/6u\/kp\/ew\/6ukpewn9rkvd518lbcwl7hncgww.png\" data-src=\"https:\/\/habrastorage.org\/webt\/6u\/kp\/ew\/6ukpewn9rkvd518lbcwl7hncgww.png\"\/><\/figure>\n<p> \u041d\u0430\u0436\u043c\u0435\u043c Save to file \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u043c \u0444\u0430\u0439\u043b \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u0443\u044e \u0440\u0430\u043d\u0435\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e dasboard_schemas. \u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0435\u043c \u0435\u0433\u043e \u0432 k8s-logging.json. \u0422\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043d\u0435\u043c \u0441 \u0434\u0440\u0443\u0433\u0438\u043c \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u043e\u043c. <\/p>\n<p>\u0412 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0438\u0442\u043e\u0433\u0435 \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0442\u0430\u043a\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<pre><code class=\"bash\">$ tree . \u251c\u2500\u2500 dashboard_schemas \u2502   \u251c\u2500\u2500 k8s-deployment-running-status.json \u2502   \u2514\u2500\u2500 k8s-logging.json \u251c\u2500\u2500 environments \u2502   \u2514\u2500\u2500 development \u2502       \u251c\u2500\u2500 main.tf \u2502       \u2514\u2500\u2500 variables.tf \u2514\u2500\u2500 modules     \u251c\u2500\u2500 grafana_alerting     \u2502   \u251c\u2500\u2500 main.tf     \u2502   \u251c\u2500\u2500 outputs.tf     \u2502   \u2514\u2500\u2500 variables.tf     \u2514\u2500\u2500 grafana_oss         \u251c\u2500\u2500 dashboard.tf         \u251c\u2500\u2500 data_source.tf         \u251c\u2500\u2500 folder.tf         \u251c\u2500\u2500 main.tf         \u251c\u2500\u2500 outputs.tf         \u2514\u2500\u2500 variables.tf <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443\u0434\u0430\u043b\u0438\u043c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 config_json \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 file() \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/modules\/grafana_oss\/dashboard.tf resource \"grafana_dashboard\" \"k8s-logging\" {   config_json = \"${file(\"..\/..\/dashboard_schemas\/k8s-logging.json\")}\"   org_id      = \"0\" }  resource \"grafana_dashboard\" \"k8s-deployment-running-status\" {   config_json = \"${file(\"..\/..\/dashboard_schemas\/k8s-deployment-running-status.json\")}\"   org_id      = \"0\" } <\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c terraform plan \u0438 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u0431\u044b\u043b\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0430:<\/p>\n<pre><code class=\"bash\">$ terraform -chdir=.\/environments\/development plan  No changes. Your infrastructure matches the configuration.  Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed. <\/code><\/pre>\n<p>\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0432 \u0441\u0445\u0435\u043c\u044b \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u043e\u0432, \u044f \u0437\u0430\u043c\u0435\u0442\u0438\u043b, \u0447\u0442\u043e \u0442\u0430\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f UID \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445. \u0412 k8s-logging.json, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, UID \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 Loki \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f 12 \u0440\u0430\u0437:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/dashboard_schemas\/k8s-logging.json &lt;other_content_is_hidden> \"datasource\": { \"type\": \"loki\", \"uid\": \"FeVw13D2\" } &lt;other_content_is_hidden> <\/code><\/pre>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445 \u0443 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u0432\u043e\u0439 UID, \u0442\u043e \u043b\u0443\u0447\u0448\u0438\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 \u043a\u043e\u0434\u0435 UID, \u0430 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0435\u0433\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f Terraform.<\/p>\n<p>\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <a href=\"https:\/\/developer.hashicorp.com\/terraform\/language\/functions\/templatefile\" rel=\"noopener noreferrer nofollow\">templatefile<\/a>. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u0444\u0430\u0439\u043b \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u0437\u0430\u0442\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445. \u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u044e\u0442\u0441\u044f \u0442\u0430\u043a\u0436\u0435 \u043a\u0430\u043a \u0438 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u0430\u0445 terraform \u0447\u0435\u0440\u0435\u0437 ${}. \u0417\u0430\u043c\u0435\u043d\u0438\u043c \u0432\u0435\u0437\u0434\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 UID \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/dashboard_schemas\/k8s-logging.json &lt;other_content_is_hidden> \"datasource\": {   \"type\": \"loki\",   \"uid\": \"${loki_data_source_id}\" } &lt;other_content_is_hidden> <\/code><\/pre>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 k8s-deployment-running-status.json:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/dashboard_schemas\/k8s-deployment-running-status.json \"datasource\": {   \"type\": \"prometheus\",   \"uid\": \"${prometheus_data_source_uid}\" } <\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u043c\u0435\u0441\u0442\u043e ${} \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0445 \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 templatefile. \u041f\u0435\u0440\u0432\u044b\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u0442\u044c \u0434\u043e \u0444\u0430\u0439\u043b\u0430, \u0432\u0442\u043e\u0440\u044b\u043c &#8212; \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"json\">resource \"grafana_dashboard\" \"k8s-logging\" {   config_json = templatefile(\"..\/..\/dashboard_schemas\/k8s-logging.json\", {     loki_data_source_uid = grafana_data_source.loki.uid   })   org_id      = \"0\" }  resource \"grafana_dashboard\" \"k8s-deployment-running-status\" {   config_json = templatefile(\"..\/..\/dashboard_schemas\/k8s-deployment-running-status.json\", {     prometheus_data_source_uid = grafana_data_source.prometheus.uid   })   org_id      = \"0\" } <\/code><\/pre>\n<h3>grafana_contact_point<\/h3>\n<p>\u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u043c\u043e\u0434\u0443\u043b\u044e grafana_alerting. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c contact point-\u044b:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/development\/main.tf &lt;other_content_is_hidden>  import {   id = \"Discord\"   to = grafana_contact_point.discord }  import {   id = \"Discord (without Resolved)\"   to = grafana_contact_point.discord-without-resolved } <\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u0438\u043c\u043f\u043e\u0440\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"bash\">$ terraform -chdir=.\/environments\/development plan -generate-config-out=contact-point.tf  Planning failed. Terraform encountered an error while generating this plan.  \u2577 \u2502 Error: Missing required argument \u2502  \u2502   with grafana_contact_point.discord, \u2502   on contact-point.tf line 7: \u2502   (source code not available) \u2502  \u2502 The argument \"discord.0.url\" is required, but no definition was found. \u2575 \u2577 \u2502 Error: Missing required argument \u2502  \u2502   with grafana_contact_point.discord-without-resolved, \u2502   on contact-point.tf line 7: \u2502   (source code not available) \u2502  \u2502 The argument \"discord.0.url\" is required, but no definition was found. <\/code><\/pre>\n<p>\u041e\u0448\u0438\u0431\u043a\u0430! \u041d\u043e \u0444\u0430\u0439\u043b <a href=\"http:\/\/contact-point.tf\" rel=\"noopener noreferrer nofollow\">contact-point.tf<\/a> \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/development\/contact-point.tf  resource \"grafana_contact_point\" \"discord\" {   name = \"Discord\"   discord {     avatar_url              = \"https:\/\/logowik.com\/content\/uploads\/images\/prometheus-monitoring-system4911.logowik.com.webp\"     disable_resolve_message = false     message                 = null     settings                = null # sensitive     url                     = null # sensitive     use_discord_username    = false   } }  resource \"grafana_contact_point\" \"discord-without-resolved\" {   name = \"Discord (without Resolved)\"   discord {     avatar_url              = \"https:\/\/logowik.com\/content\/uploads\/images\/prometheus-monitoring-system4911.logowik.com.webp\"     disable_resolve_message = true     message                 = null     settings                = null # sensitive     url                     = null # sensitive     use_discord_username    = false   } } <\/code><\/pre>\n<p>\u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 discord.0.url (Webhook URL Discord \u0431\u043e\u0442\u0430) \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u0438 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 terraform \u043d\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0435\u0433\u043e. \u0421\u043b\u0435\u0434\u0443\u0435\u0442 \u0435\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0430\u043c\u0438\u043c. \u0425\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u0432 \u043a\u043e\u0434\u0435 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u0431\u0443\u0434\u0435\u043c \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0442\u044c \u0438\u0445 \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0432 .env \u0444\u0430\u0439\u043b\u0435. \u041d\u043e \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u043a\u0430\u0436\u0435\u043c URL Webhook \u0431\u043e\u0442\u0430 \u043f\u0440\u044f\u043c\u043e \u0432 \u043a\u043e\u0434\u0435, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0434\u0430\u043b\u0438\u043c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u043e\u043b\u044f:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/development\/contact-point.tf  resource \"grafana_contact_point\" \"discord\" {   name = \"Discord\"   discord {     avatar_url              = \"https:\/\/logowik.com\/content\/uploads\/images\/prometheus-monitoring-system4911.logowik.com.webp\"     disable_resolve_message = false     url                     = \"https:\/\/discord.com\/api\/webhooks\/&lt;other_url_part>\"   } }  resource \"grafana_contact_point\" \"discord-without-resolved\" {   name = \"Discord (without Resolved)\"   discord {     avatar_url              = \"https:\/\/logowik.com\/content\/uploads\/images\/prometheus-monitoring-system4911.logowik.com.webp\"     disable_resolve_message = true     url                     = \"https:\/\/discord.com\/api\/webhooks\/&lt;other_url_part>\"   } } <\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c terraform apply. \u042f \u0434\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437 \u043f\u043e\u043a\u0430\u0437\u0430\u043b \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438\u0437 root \u043c\u043e\u0434\u0443\u043b\u044f \u0432 \u0434\u0440\u0443\u0433\u043e\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u043e\u0439\u0434\u0435\u043c\u0441\u044f \u0431\u0435\u0437 \u043a\u043e\u043c\u0430\u043d\u0434.<br \/> \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 (discord.0.url) \u0438\u0437 \u043a\u043e\u0434\u0430 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432 \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u043e\u043c <a href=\"http:\/\/variables.tf\" rel=\"noopener noreferrer nofollow\">variables.tf<\/a> \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/modules\/grafana_alerting\/variables.tf  variable \"discord_webhook_url\" {   type = string } <\/code><\/pre>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u044d\u0442\u043e\u0433\u043e, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0432 &#171;\u0440\u0443\u0442\u043e\u0432\u043e\u043c&#187; \u043c\u043e\u0434\u0443\u043b\u0435:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/development\/variables.tf  variable \"discord_webhook_url\" {   type = string } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0438\u0437 root \u043c\u043e\u0434\u0443\u043b\u044f \u0432 \u043c\u043e\u0434\u0443\u043b\u044c grafana_alerting:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/development\/main.tf &lt;other_content_is_hidden>  module \"grafana_alerting\" {   source = \"..\/..\/modules\/grafana_alerting\"    discord_webhook_url = var.discord_webhook_url } <\/code><\/pre>\n<p>\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0442\u044c\u0441\u044f \u043f\u0443\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u0430\u0441\u044c \u0441 TF_VAR_:<\/p>\n<pre><code class=\"bash\"># file: .\/.env.example  export GRAFANA_AUTH= export GRAFANA_URL=  export TF_VAR_discord_webhook_url= <\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0430\u043a\u0436\u0435 \u0434\u0430\u043d\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0432 .env, \u043d\u043e \u0443\u0436\u0435 \u0441\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c:<\/p>\n<pre><code class=\"bash\"># file: .\/environments\/development\/.env  &lt;other_content_is_hidden>  export TF_VAR_discord_webhook_url=\"https:\/\/discord.com\/api\/webhooks\/&lt;other_url_part>\" <\/code><\/pre>\n<p>\u0412 <a href=\"http:\/\/contact-point.tf\" rel=\"noopener noreferrer nofollow\">contact-point.tf<\/a> \u0434\u043b\u044f discord.0.url \u0443\u043a\u0430\u0436\u0435\u043c \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/modules\/grafana_alerting\/contact-point.tf  resource \"grafana_contact_point\" \"discord\" {   ...   discord {     ...     url = var.discord_webhook_url    } }  resource \"grafana_contact_point\" \"discord-without-resolved\" {   ...   discord {     ...     url = var.discord_webhook_url    } }  <\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c terraform plan, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0441 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u0432\u0441\u0451 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435.<\/p>\n<h3>grafana_notification_policy<\/h3>\n<p>\u0412 Terraform \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 (notification policy) \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432 \u043e\u0434\u043d\u043e\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0435. \u041a\u0430\u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0432 <a href=\"https:\/\/docs.comcloud.xyz\/providers\/grafana\/grafana\/latest\/docs\/resources\/notification_policy\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 grafana \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430<\/a>, grafana_notification_policy \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u0442 \u0434\u0435\u0440\u0435\u0432\u043e \u043f\u043e\u043b\u0438\u0442\u0438\u043a \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0438. \u0422\u0430\u043a\u0436\u0435, \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 &#171;Import&#187; \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e id \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0440\u0430\u0432\u0435\u043d &#171;policy&#187;.  \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0441\u0443\u0440\u0441:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/development\/contact-point.tf  import {   id = \"policy\"   to = grafana_notification_policy.policy-tree } <\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c terraform plan, terraform apply, \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432 \u043c\u043e\u0434\u0443\u043b\u044c grafana_alerting \u0438 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u0443\u0434\u0430\u043b\u0438\u043c \u043b\u0438\u0448\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \u0438 \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f contact_point \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u0438\u0437 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/modules\/grafana_alerting\/notification-policy.tf  resource \"grafana_notification_policy\" \"policy-tree\" {   contact_point   = \"grafana-default-email\"   group_by        = [\"grafana_folder\", \"alertname\"]    policy {     contact_point   = grafana_contact_point.discord.name     group_by        = []     matcher {       label = \"discord\"       match = \"=\"       value = \"channel\"     }   }    policy {     contact_point   = grafana_contact_point.discord-without-resolved.name     group_by        = []     matcher {       label = \"discord\"       match = \"=\"       value = \"channel_resolved_0\"     }   } } <\/code><\/pre>\n<h3>grafana_rule_group<\/h3>\n<p>\u0418 \u0432\u043e\u0442 \u043c\u044b \u0434\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u0434\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e &#8212; \u0430\u043b\u0435\u0440\u0442\u043e\u0432! \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0443 \u043c\u0435\u043d\u044f \u0438\u0445 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e, \u043d\u043e \u0434\u043b\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u044e \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0432\u0430 &#8212; \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e contact point-\u0430. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 id \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f uid \u043f\u0430\u043f\u043a\u0438 \u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u0430\u043b\u0435\u0440\u0442\u043e\u0432. \u0412 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0433\u0440\u0443\u043f\u043f\u044b \u0430\u043b\u0435\u0440\u0442\u043e\u0432 \u0432\u0435\u0437\u0434\u0435 default: <\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/j3\/j1\/g6\/j3j1g6qcrds1nnk4grh1tojll1q.png\" data-src=\"https:\/\/habrastorage.org\/webt\/j3\/j1\/g6\/j3j1g6qcrds1nnk4grh1tojll1q.png\"\/><\/figure>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u043c\u043f\u043e\u0440\u0442\u044b:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/development\/main.tf  import {   id = \"8Dve31Xcs;default\"   to = grafana_rule_group.discord-alerting }  import {   id = \"cDq3s12Zs;default\"   to = grafana_rule_group.discord-alerting-loki } <\/code><\/pre>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0432 \u0444\u0430\u0439\u043b <a href=\"http:\/\/rule-group.tf\" rel=\"noopener noreferrer nofollow\">rule-group.tf<\/a> \u0438 \u0441\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043c \u0435\u0451 \u0432 \u043c\u043e\u0434\u0443\u043b\u044c grafana_alerting.<\/p>\n<p>\u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0430\u043b\u0435\u0440\u0442\u0430 \u0432 \u0433\u0440\u0443\u043f\u043f\u0435 \u0430\u043b\u0435\u0440\u0442\u043e\u0432 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u0435\u0439. \u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0440\u0430\u043d\u0435\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/modules\/grafana_alerting\/rule-group.tf  resource \"grafana_rule_group\" \"discord-alerting\" {   folder_uid       = \"8Dve31Xcs\"   interval_seconds = 30   name             = \"default\"   org_id           = \"1\"   rule {     annotations = {       description      = \"site-api status available\"     }     condition      = \"B\"     exec_err_state = \"Alerting\"     for            = \"3m\"     is_paused      = false     labels = {       discord = \"channel\"     }     name          = \"site-api status available\"     no_data_state = \"NoData\"     data {       datasource_uid = \"d4V1dDwe\"       model          = \"{\\\"datasource\\\":{\\\"type\\\":\\\"prometheus\\\",\\\"uid\\\":\\\"d4V1dDwe\\\"},\\\"editorMode\\\":\\\"builder\\\",\\\"expr\\\":\\\"kube_deployment_status_replicas_available{namespace=\\\\\\\"development\\\\\\\", deployment=\\\\\\\"site-api\\\\\\\"}\\\",\\\"interval\\\":\\\"\\\",\\\"intervalMs\\\":15000,\\\"legendFormat\\\":\\\"{{deployment}}\\\",\\\"range\\\":true,\\\"refId\\\":\\\"A\\\"}\"       query_type     = null       ref_id         = \"A\"       relative_time_range {         from = 300         to   = 0       }     }     data {       datasource_uid = \"-100\"       model          = \"{\\\"conditions\\\":[{\\\"evaluator\\\":{\\\"params\\\":[1],\\\"type\\\":\\\"lt\\\"},\\\"operator\\\":{\\\"type\\\":\\\"and\\\"},\\\"query\\\":{\\\"params\\\":[\\\"A\\\"]},\\\"reducer\\\":{\\\"params\\\":[],\\\"type\\\":\\\"last\\\"},\\\"type\\\":\\\"query\\\"}],\\\"datasource\\\":{\\\"type\\\":\\\"__expr__\\\",\\\"uid\\\":\\\"-100\\\"},\\\"expression\\\":\\\"A\\\",\\\"hide\\\":false,\\\"refId\\\":\\\"B\\\",\\\"type\\\":\\\"classic_conditions\\\"}\"       query_type     = null       ref_id         = \"B\"       relative_time_range {         from = 0         to   = 0       }     }   } }  resource \"grafana_rule_group\" \"discord-alerting-loki\" {   folder_uid       = \"cDq3s12Zs\"   interval_seconds = 20   name             = \"default\"   org_id           = \"1\"   rule {     annotations = {       description      = \"office-api ERROR logs count MORE THAN 25 for one minute!\"     }     condition      = \"B\"     exec_err_state = \"OK\"     for            = \"30s\"     is_paused      = false     labels = {       discord          = \"channel_resolved_0\"     }     name          = \"office-api ERROR logs count\"     no_data_state = \"OK\"     data {       datasource_uid = \"FeVw13D2\"       model          = \"{\\\"datasource\\\":{\\\"type\\\":\\\"loki\\\",\\\"uid\\\":\\\"FeVw13D2\\\"},\\\"editorMode\\\":\\\"code\\\",\\\"expr\\\":\\\"count_over_time(({namespace=\\\\\\\"development\\\\\\\", app=\\\\\\\"office-api\\\\\\\"} |= \\\\\\\"ERROR\\\\\\\")[1m])\\\",\\\"legendFormat\\\":\\\"{{app}}\\\",\\\"queryType\\\":\\\"range\\\",\\\"refId\\\":\\\"A\\\"}\"       query_type     = \"range\"       ref_id         = \"A\"       relative_time_range {         from = 21600         to   = 0       }     }     data {       datasource_uid = \"-100\"       model          = \"{\\\"conditions\\\":[{\\\"evaluator\\\":{\\\"params\\\":[25],\\\"type\\\":\\\"gt\\\"},\\\"operator\\\":{\\\"type\\\":\\\"and\\\"},\\\"query\\\":{\\\"params\\\":[\\\"A\\\"]},\\\"reducer\\\":{\\\"params\\\":[],\\\"type\\\":\\\"last\\\"},\\\"type\\\":\\\"query\\\"}],\\\"datasource\\\":{\\\"type\\\":\\\"__expr__\\\",\\\"uid\\\":\\\"-100\\\"},\\\"expression\\\":\\\"A\\\",\\\"hide\\\":false,\\\"refId\\\":\\\"B\\\",\\\"type\\\":\\\"classic_conditions\\\"}\"       query_type     = null       ref_id         = \"B\"       relative_time_range {         from = 0         to   = 0       }     }   } } <\/code><\/pre>\n<p>\u041a\u0430\u043a \u0438 \u0441 JSON \u0441\u0445\u0435\u043c\u0430\u043c\u0438 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u043e\u0432, \u0434\u043b\u044f \u0433\u0440\u0443\u043f\u043f \u0430\u043b\u0435\u0440\u0442\u043e\u0432 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 terraform. \u0422\u0430\u043a \u043a\u0430\u043a \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043f\u0430\u043f\u043e\u043a \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043c\u043e\u0434\u0443\u043b\u0435 grafana_oss \u0438\u0445 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432 \u043c\u043e\u0434\u0443\u043b\u044c grafana_alerting \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c output \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 grafana_oss:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/modules\/grafana_oss\/outputs.tf  output \"discord_alerting_folder_uid\" {   value = grafana_folder.discord-alerting.uid }  output \"discord_alerting_loki_folder_uid\" {   value = grafana_folder.discord-alerting-loki.uid }  output \"prometheus_data_source_uid\" {   value = grafana_data_source.prometheus.uid }  output \"loki_data_source_uid\" {   value = grafana_data_source.loki.uid } <\/code><\/pre>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c input \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 grafana_alerting:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/modules\/grafana_alerting\/variables.tf  ... variable \"discord_alerting_folder_uid\" {   type = string }  variable \"discord_alerting_loki_folder_uid\" {   type = string }  variable \"prometheus_data_source_uid\" {   type = string }  variable \"loki_data_source_uid\" {   type = string } <\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u0437 grafana_oss \u0432 grafana_alerting:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/development\/main.tf  &lt;other_content_is_hidden>  module \"grafana_alerting\" {   source = \"..\/..\/modules\/grafana_alerting\"    discord_webhook_url = var.discord_webhook_url    discord_alerting_folder_uid      = module.grafana_oss.discord_alerting_folder_uid   discord_alerting_loki_folder_uid = module.grafana_oss.discord_alerting_loki_folder_uid   prometheus_data_source_uid       = module.grafana_oss.prometheus_data_source_uid   loki_data_source_uid             = module.grafana_oss.loki_data_source_uid } <\/code><\/pre>\n<p>\u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u0433\u0440\u0443\u043f\u043f\u0430\u043c \u0430\u043b\u0435\u0440\u0442\u043e\u0432. \u041e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b \u0441 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/modules\/grafana_alerting\/rule-group.tf  resource \"grafana_rule_group\" \"discord-alerting\" {   folder_uid = var.discord_alerting_folder_uid   ...   rule {     ...     data {       datasource_uid = var.prometheus_data_source_uid       model          = \"{\\\"datasource\\\":{\\\"type\\\":\\\"prometheus\\\",\\\"uid\\\":\\\"${var.prometheus_data_source_uid}\\\"},\\\"editorMode\\\":\\\"builder\\\",\\\"expr\\\":\\\"kube_deployment_status_replicas_available{namespace=\\\\\\\"development\\\\\\\", deployment=\\\\\\\"site-api\\\\\\\"}\\\",\\\"interval\\\":\\\"\\\",\\\"intervalMs\\\":15000,\\\"legendFormat\\\":\\\"{{deployment}}\\\",\\\"range\\\":true,\\\"refId\\\":\\\"A\\\"}\"       ...     }     data {       ...     }   } }  resource \"grafana_rule_group\" \"discord-alerting-loki\" {   folder_uid = var.discord_alerting_loki_folder_uid   ...   rule {     ...     data {       datasource_uid = var.loki_data_source_uid       model          = \"{\\\"datasource\\\":{\\\"type\\\":\\\"loki\\\",\\\"uid\\\":\\\"${var.loki_data_source_uid}\\\"},\\\"editorMode\\\":\\\"code\\\",\\\"expr\\\":\\\"count_over_time(({namespace=\\\\\\\"development\\\\\\\", app=\\\\\\\"office-api\\\\\\\"} |= \\\\\\\"ERROR\\\\\\\")[1m])\\\",\\\"legendFormat\\\":\\\"{{app}}\\\",\\\"queryType\\\":\\\"range\\\",\\\"refId\\\":\\\"A\\\"}\"       ...     }     data {       ...     }   } } <\/code><\/pre>\n<p>\u042f \u0437\u0430\u043c\u0435\u043d\u0438\u043b folder_uuid, rule.datasource_uid, \u0430 \u0442\u0430\u043a\u0436\u0435 uid \u0432 rule.data.model.<\/p>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u0431\u044b\u043b\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432\u0441\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0438\u0437 Grafana \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0434. \u042d\u0442\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442 \u0435\u0451 \u0441\u043e\u0445\u0440\u0430\u043d\u043d\u043e\u0441\u0442\u044c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0438 \u0442\u0440\u0430\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\u0445. \u0412 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0438\u0442\u043e\u0433\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>. \u251c\u2500\u2500 dashboard_schemas \u2502   \u251c\u2500\u2500 k8s-deployment-running-status.json \u2502   \u2514\u2500\u2500 k8s-logging.json \u251c\u2500\u2500 environments \u2502   \u2514\u2500\u2500 development \u2502       \u251c\u2500\u2500 main.tf \u2502       \u251c\u2500\u2500 terraform.tfstate \u2502       \u2514\u2500\u2500 variables.tf \u2514\u2500\u2500 modules     \u251c\u2500\u2500 grafana_alerting     \u2502   \u251c\u2500\u2500 contact-point.tf     \u2502   \u251c\u2500\u2500 main.tf     \u2502   \u251c\u2500\u2500 notification-policy.tf     \u2502   \u251c\u2500\u2500 outputs.tf     \u2502   \u251c\u2500\u2500 rule-group.tf     \u2502   \u2514\u2500\u2500 variables.tf     \u2514\u2500\u2500 grafana_oss         \u251c\u2500\u2500 dashboard.tf         \u251c\u2500\u2500 data_source.tf         \u251c\u2500\u2500 folder.tf         \u251c\u2500\u2500 main.tf         \u251c\u2500\u2500 outputs.tf         \u2514\u2500\u2500 variables.tf <\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/759348\/\"> https:\/\/habr.com\/ru\/articles\/759348\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412\u0430\u043c \u0441\u043a\u0430\u0437\u0430\u043b\u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430, \u0432\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 \u0441\u0432\u044f\u0437\u043a\u0443 Prometheus + Grafana. \u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u043b\u0438 Grafana \u043d\u0430 \u0441\u0432\u043e\u0438\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u0445 (VM\/Docker\/Kubernetes) \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0438 Data Source Prometheus (\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u0430\u043c \u0435\u0449\u0435 \u0441\u043a\u0430\u0437\u0430\u043b\u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 Grafana Loki) \u0438 \u0434\u0430\u043b\u0435\u0435 \u043f\u043e \u0433\u0430\u0439\u0434\u0430\u043c \u0438\u0437 \u044e\u0442\u0443\u0431\u0430 \u043d\u0430\u0447\u0430\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b \u0438 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0430\u043b\u0435\u0440\u0442\u044b.<\/p>\n<p>\u0412\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e, \u043d\u043e \u0432 \u043e\u0434\u0438\u043d \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0435 \u0434\u0443\u043c\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 Grafana \u0432 \u043a\u043e\u0434\u0435, \u0447\u0442\u043e\u0431\u044b \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043b\u0435\u0433\u043a\u043e \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u0442\u0435\u0440\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043b\u0438 \u0436\u0435 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0439 \u0441\u0440\u0435\u0434\u044b (dev\/prod). \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b \u043d\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0442\u0440\u0443\u0434\u0430, \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438 \u0447\u0435\u0440\u0435\u0437 GUI, \u043d\u043e \u043a\u0430\u043a \u0436\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0438, contact points \u0438 \u0441\u0430\u043c\u0438 \u0430\u043b\u0435\u0440\u0442\u044b?<br \/> \u0417\u043d\u0430\u043a\u043e\u043c\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f? \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0447\u0442\u043e \u043d\u0435\u0442. \u0410 \u0443 \u043c\u0435\u043d\u044f \u0434\u0430!<\/p>\n<h3>\u041f\u0435\u0440\u0435\u0434 \u043f\u0440\u043e\u0447\u0442\u0435\u043d\u0438\u0435\u043c<\/h3>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0438 \u043a\u043e\u043c\u0430\u043d\u0434. \u042f \u0431\u043e\u043b\u044c\u0448\u0435 \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0441\u0432\u043e\u0435\u043c \u043e\u043f\u044b\u0442\u0435 \u0438 \u043d\u0435 \u043f\u0440\u0435\u0441\u043b\u0435\u0434\u0443\u044e \u0446\u0435\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0431\u0443\u0447\u0430\u044e\u0449\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e, \u043d\u043e \u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u043a\u043e\u043c\u0443-\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442, \u0442\u043e \u044d\u0442\u043e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e!<\/p>\n<h3>\u0427\u0442\u043e \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c<\/h3>\n<p>\u0417\u0430\u0434\u0430\u0447\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430 &#8212; \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0443\u044e Grafana \u043f\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 terraform (\u043e\u0431\u043e\u0436\u0430\u044e \u0435\u0433\u043e!). \u041d\u043e \u043f\u0435\u0440\u0435\u0434 \u044d\u0442\u0438\u043c \u0438\u0437\u0443\u0447\u0438\u0432 \u0435\u0451 API \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0432 \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<h3>\u0421 \u0447\u0435\u043c \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c<\/h3>\n<p>\u0423 \u043c\u0435\u043d\u044f \u0432 \u0440\u0430\u0441\u043f\u043e\u0440\u044f\u0436\u0435\u043d\u0438\u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044b\u0439 Prometheus \u0438 Grafana Loki, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0435 \u043a Grafana (\u0432\u0441\u0435 \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f \u0432 Kubernetes). \u0418\u043c\u0435\u0435\u0442\u0441\u044f \u0434\u0432\u0430 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430: \u043f\u0435\u0440\u0432\u044b\u0439 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043d\u044b\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438 \u0432\u0442\u043e\u0440\u043e\u0439 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u043b\u043e\u0433\u043e\u0432. \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u0432 \u044d\u0442\u0438\u0445 \u0434\u0432\u0443\u0445 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u0441\u0432\u043e\u0439 \u0430\u043b\u0435\u0440\u0442. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u0430\u043b\u0435\u0440\u0442\u0430\u043c\u0438 \u0432 \u043f\u0435\u0440\u0432\u043e\u043c \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0435, \u0432 \u0434\u0438\u0441\u043a\u043e\u0440\u0434 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f, \u0435\u0441\u043b\u0438 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 resolved \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u0432\u043d\u043e\u0432\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d.  \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u0430\u043b\u0435\u0440\u0442\u0430\u043c\u0438 \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0435, \u0432 \u0434\u0438\u0441\u043a\u043e\u0440\u0434 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f, \u0435\u0441\u043b\u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e ERROR \u043b\u043e\u0433\u043e\u0432 \u0432 \u043c\u0438\u043d\u0443\u0442\u0443 \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u043b\u043e 25 \u0435\u0434\u0438\u043d\u0438\u0446. <\/p>\n<figure class=\"\"><\/figure>\n<figure class=\"\"><\/figure>\n<h3>Grafana API<\/h3>\n<h4>API-\u043a\u043b\u044e\u0447<\/h4>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c API \u043a\u043b\u044e\u0447, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a API \u0433\u0440\u0430\u0444\u0430\u043d\u044b. \u0417\u0430\u0439\u0434\u0435\u043c \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0443 &#171;Service accounts&#187; <\/p>\n<figure class=\"\"><\/figure>\n<p> \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0439 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u0441 \u0440\u043e\u043b\u044c\u044e Admin \u0438 \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e terraform: <\/p>\n<figure class=\"\"><\/figure>\n<p> \u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0433\u043e \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 \u0438 \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u043c \u0434\u0430\u0442\u0443 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430: <\/p>\n<figure class=\"\"><\/figure>\n<p> \u0421\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u0435\u0433\u043e \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f: <\/p>\n<pre><code class=\"bash\">$ export GRAFANA_TOKEN=&lt;token_itself> <\/code><\/pre>\n<h4>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 ID \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432<\/h4>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043a REST API \u0433\u0440\u0430\u0444\u0430\u043d\u044b \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u0432\u044b\u0448\u0435 \u0442\u043e\u043a\u0435\u043d\u043e\u043c:<\/p>\n<pre><code class=\"bash\">$ curl -H \"Authorization: Bearer $GRAFANA_TOKEN\" https:\/\/&lt;grafana_host>\/api\/dashboards\/home | jq {   \"meta\": {     \"isHome\": true,     \"canSave\": false,     \"canEdit\": true,     \"canAdmin\": false, &lt;other_content_is_hidden> } <\/code><\/pre>\n<p>\u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e Grafana v10.0.5, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0435 \u0442\u043e\u0447\u043a\u0438 <a href=\"https:\/\/grafana.com\/docs\/grafana\/v10.0\/developers\/http_api\/\" rel=\"noopener noreferrer nofollow\">\u043e\u0442\u0441\u044e\u0434\u0430<\/a>. \u0418 \u0442\u0430\u043a, \u043f\u043e\u043b\u0443\u0447\u0438\u043c ID \u0432\u0441\u0435\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 terraform. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"bash\">curl --location 'https:\/\/&lt;grafana_host>\/api\/datasources' \\  --header \"Authorization: Bearer $GRAFANA_TOKEN\" | jq [   {     \"id\": 5,     \"uid\": \"FeVw13D2\",     \"orgId\": 1,     \"name\": \"Loki\",     \"type\": \"loki\", &lt;other_content_is_hidden>   },   {     \"id\": 1,     \"uid\": \"d4V1dDwe\",     \"orgId\": 1,     \"name\": \"Prometheus\",     \"type\": \"prometheus\",     &lt;other_content_is_hidden>   } ] <\/code><\/pre>\n<p>\u0421\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u043e\u0432:<\/p>\n<pre><code class=\"bash\">$ curl --location \"https:\/\/&lt;grafana_host>\/api\/search?query=%\" \\        --header \"Authorization: Bearer $GRAFANA_TOKEN\" | jq [   {     \"id\": 9,     \"uid\": \"FvDw34Dq\",     \"title\": \"Kubernetes deployment running status\", &lt;other_content_is_hidden>   },   {     \"id\": 12,     \"uid\": \"3Cw21Sqwr\",     \"title\": \"Kubernetes logging\",     &lt;other_content_is_hidden>   } ] <\/code><\/pre>\n<p>\u0421\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u043f\u0430\u043f\u043e\u043a:<\/p>\n<pre><code class=\"bash\">$ curl --location \"https:\/\/&lt;grafana_host>\/api\/folders\" \\  --header \"Authorization: Bearer $GRAFANA_TOKEN\" | jq [   {     \"id\": 11,     \"uid\": \"8Dve31Xcs\",     \"title\": \"Discord Alerting\"   },   {     \"id\": 14,     \"uid\": \"cDq3s12Zs\",     \"title\": \"Discord Alerting Loki\"   } ] <\/code><\/pre>\n<p>\u0421\u043f\u0438\u0441\u043e\u043a contact points:<\/p>\n<pre><code class=\"bash\">$ curl --location \"https:\/\/&lt;grafana_host>\/api\/v1\/provisioning\/contact-points\" \\ --header \"Authorization: Bearer $GRAFANA_TOKEN\" | jq [   {     \"uid\": \"cMux1S3cS\",     \"name\": \"Discord\",     \"type\": \"discord\",   &lt;other_content_is_hidden>     \"disableResolveMessage\": false   },   {     \"uid\": \"BqgE23vD\",     \"name\": \"Discord (without Resolved)\",     \"type\": \"discord\",     &lt;other_content_is_hidden>     \"disableResolveMessage\": true   } ] <\/code><\/pre>\n<p>\u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0432\u044b \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438 \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0430\u043b\u0435\u0440\u0442\u043e\u0432. \u042f \u0434\u043e\u043b\u0433\u043e \u0438\u0441\u043a\u0430\u043b \u0438 \u043d\u0430\u0448\u0435\u043b \u043d\u0430 \u0444\u043e\u0440\u0443\u043c\u0435 \u0433\u0440\u0430\u0444\u0430\u043d\u044b \u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443:<\/p>\n<pre><code class=\"bash\">curl --location \"https:\/\/&lt;grafana_host>\/api\/ruler\/grafana\/api\/v1\/rules\" \\  --header \"Authorization: Bearer $GRAFANA_TOKEN\" | jq {   \"Discord Alerting\": [     {       \"name\": \"default\",       \"interval\": \"30s\",       \"rules\": [         {           \"expr\": \"\",           \"for\": \"3m\",           \"labels\": {             \"discord\": \"channel\"           },           \"annotations\": {             &lt;other_content_is_hidden>             \"description\": \"site-api status available\"           },           \"grafana_alert\": {             \"id\": 9,             \"orgId\": 1,             \"title\": \"site-api status available\",             \"condition\": \"B\",             \"data\": [               {                 &lt;other_content_is_hidden>                 \"datasourceUid\": \"d4V1dDwe\",                 \"model\": {                   \"datasource\": {                     \"type\": \"prometheus\",                     \"uid\": \"d4V1dDwe\"                   },                   \"editorMode\": \"builder\",                   \"expr\": \"kube_deployment_status_replicas_available{namespace=\\\"development\\\", deployment=\\\"site-api\\\"}\",                   &lt;other_content_is_hidden>                 }               }             ],             \"intervalSeconds\": 30,             \"uid\": \"fW3vDw31S\",             &lt;other_content_is_hidden>           }         },       ]     }   ],   \"Discord Alerting Loki\": [     {       \"name\": \"default\",       \"interval\": \"30s\",       \"rules\": [         {           \"expr\": \"\",           \"for\": \"30s\",           \"labels\": {             \"discord\": \"channel_resolved_0\",           },           \"annotations\": {         &lt;other_content_is_hidden>             \"description\": \"office-api ERROR logs count MORE THAN 25 for one minute!\"           },           \"grafana_alert\": {             \"id\": 17,             \"orgId\": 1,             \"title\": \"office-api ERROR logs count\",             \"condition\": \"B\",             \"data\": [               {                 &lt;other_content_is_hidden>                 \"datasourceUid\": \"FeVw13D2\",                 \"model\": {                   \"datasource\": {                     \"type\": \"loki\",                     \"uid\": \"FeVw13D2\"                   },                   \"editorMode\": \"code\",                   \"expr\": \"count_over_time(({namespace=\\\"development\\\", app=\\\"office-api\\\"} |= \\\"ERROR\\\")[1m])\",                   &lt;other_content_is_hidden>                 },                 {                   &lt;other_content_is_hidden>                 }               }             ],             \"intervalSeconds\": 20,                         \"uid\": \"-vFw2ZdwW\",             &lt;other_content_is_hidden>           }         }       ]     }   ] } <\/code><\/pre>\n<p>\u0412 &#171;rules&#187; \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0430\u043b\u0435\u0440\u0442\u043e\u0432 \u0438 \u0438\u0445 id. \u0423 \u043c\u0435\u043d\u044f \u0438\u0445 \u043c\u043d\u043e\u0433\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0430\u043f\u043a\u0438.<\/p>\n<h3>Terraform<\/h3>\n<h4>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443<\/h4>\n<p>\u041a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 Git \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0430\u0436\u043d\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0430\u043f\u043e\u043a \u0438 \u0444\u0430\u0439\u043b\u043e\u0432.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0430\u043f\u043e\u043a:<\/p>\n<pre><code class=\"bash\">$ tree -a . \u251c\u2500\u2500 .env.example \u251c\u2500\u2500 environments \u2502   \u2514\u2500\u2500 development \u2502       \u251c\u2500\u2500 .env \u2502       \u251c\u2500\u2500 main.tf \u2502       \u2514\u2500\u2500 variables.tf \u251c\u2500\u2500 .gitignore \u2514\u2500\u2500 modules     \u251c\u2500\u2500 grafana_alerting     \u2502   \u251c\u2500\u2500 main.tf     \u2502   \u251c\u2500\u2500 outputs.tf     \u2502   \u2514\u2500\u2500 variables.tf     \u2514\u2500\u2500 grafana_oss         \u251c\u2500\u2500 main.tf         \u251c\u2500\u2500 outputs.tf         \u2514\u2500\u2500 variables.tf <\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 .gitignore \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432 git \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u0444\u0430\u0439\u043b\u044b, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 terraform \u0438 \u0444\u0430\u0439\u043b\u044b, \u0445\u0440\u0430\u043d\u044f\u0449\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code># file: .\/.gitignore *terraform* .env <\/code><\/pre>\n<p>\u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u0432\u043e\u0439 .env \u0444\u0430\u0439\u043b \u0441\u043e \u0441\u0432\u043e\u0438\u043c\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f. \u0422\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u0438 \u0444\u0430\u0439\u043b\u044b \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 git, \u0442\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0444\u0430\u0439\u043b .env.example, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u0443\u0441\u0442\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438:<\/p>\n<pre><code class=\"bash\"># file: .\/.env.example export GRAFANA_AUTH= export GRAFANA_URL= <\/code><\/pre>\n<p>\u042d\u0442\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u0432 terraform. GRAFANA_AUTH \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c API \u0442\u043e\u043a\u0435\u043d \u0438\u043b\u0438 login\/password \u0432 base64. \u0427\u0435\u0440\u0435\u0437 GRAFANA_URL \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0430\u0434\u0440\u0435\u0441 \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u0430 \u0433\u0440\u0430\u0444\u0430\u043d\u0430.<\/p>\n<p>\u0421\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b \u0432 \u043f\u0430\u043f\u043a\u0443 .\/environments\/development \u0438 \u0443\u043a\u0430\u0436\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">$ cp .\/.env.example .\/environments\/development\/.env <\/code><\/pre>\n<pre><code class=\"bash\"># file: .\/environments\/development\/.env export GRAFANA_AUTH=$GRAFANA_TOKEN export GRAFANA_URL=\"https:\/\/&lt;grafana_host>\/\" <\/code><\/pre>\n<h4>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430<\/h4>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 <a href=\"https:\/\/docs.comcloud.xyz\/providers\/grafana\/grafana\/latest\" rel=\"noopener noreferrer nofollow\">Grafana<\/a> \u0438 \u043d\u0430\u0448\u0438 \u0431\u0443\u0434\u0443\u0449\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0438:<\/p>\n<pre><code class=\"json\">\/\/ file: .\/environments\/development\/main.tf  terraform {   required_providers {     grafana = {       source = \"grafana\/grafana\"       version = \"2.1.0\"     }   } }  provider \"grafana\" { }  module \"grafana_oss\" {   source = \"..\/..\/modules\/grafana_oss\" }  module \"grafana_alerting\" {   source = \"..\/..\/modules\/grafana_alerting\" } <\/code><\/pre>\n<p>\u0412 <a href=\"http:\/\/main.tf\" rel=\"noopener noreferrer nofollow\">main.tf<\/a> \u0444\u0430\u0439\u043b \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043c\u043e\u0434\u0443\u043b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c Grafana \u0432 required_providers:<\/p>\n<pre><code class=\"json\">\/\/ files: .\/modules\/grafana_oss\/main.tf &amp;&amp; .\/modules\/grafana_alerts\/main.tf  terraform {   required_providers {     grafana = {       source = \"grafana\/grafana\"       version = \"2.1.0\"     }   } } <\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c .env \u0444\u0430\u0439\u043b \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">$ . .\/environments\/development\/.env <\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c terraform init \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430:<\/p>\n<pre><code class=\"bash\">$ terraform -chdir=.\/environments\/development init  Initializing the backend... Initializing modules... - grafana_alerting in ..\/..\/modules\/grafana_alerting - grafana_oss in ..\/..\/modules\/grafana_oss  Initializing provider plugins... - Finding grafana\/grafana versions matching \"2.1.0\"... - Installing grafana\/grafana v2.1.0... - Installed grafana\/grafana v2.1.0 (unauthenticated) <\/code><\/pre>\n<h4>\u0418\u043c\u043f\u043e\u0440\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438<\/h4>\n<p>Terraform \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u0441 \u043d\u0435\u0434\u0430\u0432\u043d\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 HQL. \u0417\u0430\u0442\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0438 \u0441\u0430\u043c\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c \u0432 \u043c\u043e\u0434\u0443\u043b\u044c \u0441\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0430\u043c\u0438 Terraform.<\/p>\n<h3>grafana_folder<\/h3>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-354180","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/354180","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=354180"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/354180\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=354180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=354180"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=354180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}