Ingress 생성하기
클러스터에 설치한 프로메테우스와 알럿매니저 그리고 그라파라를 쿠버네티스 클러스터 외부에서 쉽게 접근할 수 있도록 Ingress
리소스를 생성하겼습니다. Ingress
리소스를 사용하기 위해서는 쿠버네티스 클러스터에 IngressController
가 설치되어 있어야 합니다.
사용할 각 도메인들을 DNS 서버에 등록하고 다음과 같이 Ingress
리소스를 생성해 줍니다. 일반적으로 도메인과 IngressController
가 묶여 있는 로드밸런서의 주소를 연결해 줍니다.
prometheus-k8s 를 위한 Ingress 생성하기
다음 파일명으로 Ingress
리소스 매니페스트 파일을 작성합니다.
prometheus-k8s-ingress.yaml
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: prometheus-k8s spec: rules: - host: prometheus.my-domain.com http: paths: - backend: serviceName: prometheus-k8s servicePort: 9090 path: /
작성한 매니페스트 파일을 kubectl
을 이용하여 생성합니다.
kubectl -n monitoring apply -f prometheus-k8s-ingress.yaml
적용이 완료되면, 웹 브라우저에서 http://prometheus.my-domain.com 으로 프로메테우스 서버에 접속할 수 있습니다.
alertmanager-main 를 위한 Ingress 생성하기
다음 파일명으로 Ingress
리소스 매니페스트 파일을 작성합니다.
alertmanager-main-ingress.yaml
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: alertmanager-main spec: rules: - host: alertmanager.my-domain.com http: paths: - backend: serviceName: alertmanager-main servicePort: 9093 path: /
작성한 매니페스트 파일을 kubectl
을 이용하여 생성합니다.
kubectl -n monitoring apply -f alertmanager-main-ingress.yaml
적용이 완료되면, 웹 브라우저에서 http://alertmanager.my-domain.com 으로 알럿매니저 서버에 접속할 수 있습니다.
grafana 를 위한 Ingress 생성하기
다음 파일명으로 Ingress
리소스 매니페스트 파일을 작성합니다.
grafana-ingress.yaml
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: grafana spec: rules: - host: grafana.my-domain.com http: paths: - backend: serviceName: grafana servicePort: 3000 path: /
작성한 매니페스트 파일을 kubectl
을 이용하여 생성합니다.
kubectl -n monitoring apply -f grafana-ingress.yaml
적용이 완료되면, 웹 브라우저에서 http://grafana.my-domain.com 으로 그라파너 서버에 접속할 수 있습니다.
AlertManager 에 노티피케이션 설정하기
기본적으로 alertmanager-main
라는 알럿 매니저가 설치되어 있습니다. 하지만 노티피케이션 설정이 없기 때문에, 알럿이 발생해도 노티피케이션을 받을 수가 없습니다.
알럿이 발생할 때 슬랙으로 노티피케이션을 받을 수 있도록 알럿매니저 설정을 변경해 보겠습니다.
alertmanager-main
라는 알럿 매니저는 prometheus-operator
를 이용하여 설치되어 있기 때문에 설정을 변경하려면 alertmanager-main
이라는 Secret
리소스를 수정해줘야 합니다. 해당 Secret
리소스의 data
필드에 “파일명: BASE64로 인코딩된 설정내용”으로 저장되어 있습니다. 직접 리소스를 수정해줘도 되지만, 편의를 위해서 삭제하고 다시 만들도록 하겠습니다.
슬랙 템플릿 파일 만들기
노티피케이션을 슬랙으로 받을 때 사용할 템플릿 파일을 먼저 작성하겠습니다.
이 템플릿은 https://gist.github.com/milesbxf/e2744fc90e9c41b47aa47925f8ff6512 을 약간 수정한 것입니다. 용도에 맞게 수정해서 사용하실 수 있습니다.
다음 파일명으로 슬랙 템플릿 파일을 작성합니다.
slack-templates.tmpl
# This builds the silence URL. We exclude the alertname in the range # to avoid the issue of having trailing comma separator (%2C) at the end # of the generated URL {{ define "__alert_silence_link" -}} {{ .ExternalURL }}/#/silences/new?filter=%7B {{- range .CommonLabels.SortedPairs -}} {{- if ne .Name "alertname" -}} {{- .Name }}%3D"{{- .Value -}}"%2C%20 {{- end -}} {{- end -}} alertname%3D"{{ .CommonLabels.alertname }}"%7D {{- end }} {{ define "__alert_severity_prefix" -}} {{ if ne .Status "firing" -}} :lgtm: {{- else if eq .Labels.severity "critical" -}} :fire: {{- else if eq .Labels.severity "warning" -}} :warning: {{- else -}} :question: {{- end }} {{- end }} {{ define "__alert_severity_prefix_title" -}} {{ if ne .Status "firing" -}} :lgtm: {{- else if eq .CommonLabels.severity "critical" -}} :fire: {{- else if eq .CommonLabels.severity "warning" -}} :warning: {{- else if eq .CommonLabels.severity "info" -}} :information_source: {{- else -}} :question: {{- end }} {{- end }} {{/* First line of Slack alerts */}} {{ define "slack.monzo.title" -}} [{{ .Status | toUpper -}} {{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{- end -}} ] {{ template "__alert_severity_prefix_title" . }} {{ .CommonLabels.alertname }} {{- end }} {{/* Color of Slack attachment (appears as line next to alert )*/}} {{ define "slack.monzo.color" -}} {{ if eq .Status "firing" -}} {{ if eq .CommonLabels.severity "warning" -}} warning {{- else if eq .CommonLabels.severity "critical" -}} danger {{- else -}} #439FE0 {{- end -}} {{ else -}} good {{- end }} {{- end }} {{/* Emoji to display as user icon (custom emoji supported!) */}} {{ define "slack.monzo.icon_emoji" }}:prometheus:{{ end }} {{/* The test to display in the alert */}} {{ define "slack.monzo.text" -}} {{ range .Alerts }} {{- if .Annotations.message }} {{ .Annotations.message }} {{- end }} {{- if .Annotations.description }} {{ .Annotations.description }} {{- end }} {{- end }} {{- end }} {{- /* If none of the below matches, send to #monitoring-no-owner, and we can then assign the expected code_owner to the alert or map the code_owner to the correct channel */ -}} {{ define "__get_channel_for_code_owner" -}} {{- if eq . "platform-team" -}} platform-alerts {{- else if eq . "security-team" -}} security-alerts {{- else -}} monitoring-no-owner {{- end -}} {{- end }} {{- /* Select the channel based on the code_owner. We only expect to get into this template function if the code_owners label is present on an alert. This is to defend against us accidentally breaking the routing logic. */ -}} {{ define "slack.monzo.code_owner_channel" -}} {{- if .CommonLabels.code_owner }} {{ template "__get_channel_for_code_owner" .CommonLabels.code_owner }} {{- else -}} monitoring {{- end }} {{- end }} {{ define "slack.monzo.link_button_text" -}} {{- if .CommonAnnotations.link_text -}} {{- .CommonAnnotations.link_text -}} {{- else -}} Link {{- end }} :link: {{- end }}
알럿매니저 설정 파일 만들기
알럿매니저에서 노티피케이션을 슬랙으로 보낼 수 있게 설정 파일을 작성하겠습니다.
슬랙을 보낼 수 있도록 slack_api_url
필드에 사용할 URL 주소를 입력합니다. 그리고 templates
필드를 사용해서 템플릿 파일들을 읽어오도록 설정하였습니다.
다음 파일명으로 알럿매니저 설정 파일을 작성합니다.
alertmanager.yaml
global: resolve_timeout: 5m slack_api_url: '<https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX>' templates: - '*.tmpl' route: group_by: [alertname, job] group_interval: 5m group_wait: 30s receiver: 'slack-alert' repeat_interval: 12h routes: - match: alertname: 'Watchdog' receiver: 'null' receivers: - name: 'null' - name: 'slack-alert' slack_configs: - channel: '#{{- template "slack.monzo.code_owner_channel" . -}}' send_resolved: true title: '{{ template "slack.monzo.title" . }}' icon_emoji: '{{ template "slack.monzo.icon_emoji" . }}' color: '{{ template "slack.monzo.color" . }}' text: '{{ template "slack.monzo.text" . }}' actions: - type: button text: 'Runbook :green_book:' url: '{{ (index .Alerts 0).Annotations.runbook_url }}' - type: button text: 'Query :mag:' url: '{{ (index .Alerts 0).GeneratorURL }}' - type: button text: 'Dashboard :grafana:' url: '{{ (index .Alerts 0).Annotations.dashboard }}' - type: button text: 'Silence :no_bell:' url: '{{ template "__alert_silence_link" . }}' - type: button text: '{{ template "slack.monzo.link_button_text" . }}' url: '{{ .CommonAnnotations.link_url }}'
alertmanager-main Secret
리소스 생성하기
앞서 생성한 alertmanager.yaml
파일과 slack-templates.tmpl
파일을 사용하여 alertmanager-main
라는 Secret
리소스 생성해 보겠습니다. 편의를 위해 기존에 있던 리소스는 삭제하였습니다.
kubectl -n monitoring delete secret alertmanager-main kubectl -n monitoring create secret generic alertmanager-main --from-file=alertmanager.yaml --from-file=slack-templates.tmpl
다음 명령어를 실행하면 생성한 Secret
리소스 조회할 수 있습니다.
kubectl -n monitoring get secret alertmanager-main -o yaml
정상적으로 조회되면, 다음과 같은 결과를 확인 할 수 있습니다.
apiVersion: v1 data: alertmanager.yaml: Z2xvYmFsOgogIHJlc29sdmVfdGltZW91dDogNW0KICBzbGFja19hcGlfdXJsOiAnaHR0cHM6Ly9ob29rcy5zbGFjay5jb20vc2VydmljZXMvVDAwMDAwMDAwL0IwMDAwMDAwMC9YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFgnCgp0ZW1wbGF0ZXM6CiAgLSAnKi50bXBsJwoKcm91dGU6CiAgZ3JvdXBfYnk6IFthbGVydG5hbWUsIGpvYl0KICBncm91cF9pbnRlcnZhbDogNW0KICBncm91cF93YWl0OiAzMHMKICByZWNlaXZlcjogJ3NsYWNrLWFsZXJ0JwogIHJlcGVhdF9pbnRlcnZhbDogMTJoCiAgcm91dGVzOgogICAgLSBtYXRjaDoKICAgICAgICBhbGVydG5hbWU6ICdXYXRjaGRvZycKICAgICAgcmVjZWl2ZXI6ICdudWxsJwpyZWNlaXZlcnM6CiAgLSBuYW1lOiAnbnVsbCcKICAtIG5hbWU6ICdzbGFjay1hbGVydCcKICAgIHNsYWNrX2NvbmZpZ3M6CiAgICAgIC0gY2hhbm5lbDogJyN7ey0gdGVtcGxhdGUgInNsYWNrLm1vbnpvLmNvZGVfb3duZXJfY2hhbm5lbCIgLiAtfX0nCiAgICAgICAgc2VuZF9yZXNvbHZlZDogdHJ1ZQogICAgICAgIHRpdGxlOiAne3sgdGVtcGxhdGUgInNsYWNrLm1vbnpvLnRpdGxlIiAuIH19JwogICAgICAgIGljb25fZW1vamk6ICd7eyB0ZW1wbGF0ZSAic2xhY2subW9uem8uaWNvbl9lbW9qaSIgLiB9fScKICAgICAgICBjb2xvcjogJ3t7IHRlbXBsYXRlICJzbGFjay5tb256by5jb2xvciIgLiB9fScKICAgICAgICB0ZXh0OiAne3sgdGVtcGxhdGUgInNsYWNrLm1vbnpvLnRleHQiIC4gfX0nCiAgICAgICAgYWN0aW9uczoKICAgICAgICAgIC0gdHlwZTogYnV0dG9uCiAgICAgICAgICAgIHRleHQ6ICdSdW5ib29rIDpncmVlbl9ib29rOicKICAgICAgICAgICAgdXJsOiAne3sgKGluZGV4IC5BbGVydHMgMCkuQW5ub3RhdGlvbnMucnVuYm9va191cmwgfX0nCiAgICAgICAgICAtIHR5cGU6IGJ1dHRvbgogICAgICAgICAgICB0ZXh0OiAnUXVlcnkgOm1hZzonCiAgICAgICAgICAgIHVybDogJ3t7IChpbmRleCAuQWxlcnRzIDApLkdlbmVyYXRvclVSTCB9fScKICAgICAgICAgIC0gdHlwZTogYnV0dG9uCiAgICAgICAgICAgIHRleHQ6ICdEYXNoYm9hcmQgOmdyYWZhbmE6JwogICAgICAgICAgICB1cmw6ICd7eyAoaW5kZXggLkFsZXJ0cyAwKS5Bbm5vdGF0aW9ucy5kYXNoYm9hcmQgfX0nCiAgICAgICAgICAtIHR5cGU6IGJ1dHRvbgogICAgICAgICAgICB0ZXh0OiAnU2lsZW5jZSA6bm9fYmVsbDonCiAgICAgICAgICAgIHVybDogJ3t7IHRlbXBsYXRlICJfX2FsZXJ0X3NpbGVuY2VfbGluayIgLiB9fScKICAgICAgICAgIC0gdHlwZTogYnV0dG9uCiAgICAgICAgICAgIHRleHQ6ICd7eyB0ZW1wbGF0ZSAic2xhY2subW9uem8ubGlua19idXR0b25fdGV4dCIgLiB9fScKICAgICAgICAgICAgdXJsOiAne3sgLkNvbW1vbkFubm90YXRpb25zLmxpbmtfdXJsIH19JwoKCg== slack-templates.tmpl: IyBUaGlzIGJ1aWxkcyB0aGUgc2lsZW5jZSBVUkwuICBXZSBleGNsdWRlIHRoZSBhbGVydG5hbWUgaW4gdGhlIHJhbmdlCiMgdG8gYXZvaWQgdGhlIGlzc3VlIG9mIGhhdmluZyB0cmFpbGluZyBjb21tYSBzZXBhcmF0b3IgKCUyQykgYXQgdGhlIGVuZAojIG9mIHRoZSBnZW5lcmF0ZWQgVVJMCnt7IGRlZmluZSAiX19hbGVydF9zaWxlbmNlX2xpbmsiIC19fQogICAge3sgLkV4dGVybmFsVVJMIH19LyMvc2lsZW5jZXMvbmV3P2ZpbHRlcj0lN0IKICAgIHt7LSByYW5nZSAuQ29tbW9uTGFiZWxzLlNvcnRlZFBhaXJzIC19fQogICAgICAgIHt7LSBpZiBuZSAuTmFtZSAiYWxlcnRuYW1lIiAtfX0KICAgICAgICAgICAge3stIC5OYW1lIH19JTNEInt7LSAuVmFsdWUgLX19IiUyQyUyMAogICAgICAgIHt7LSBlbmQgLX19CiAgICB7ey0gZW5kIC19fQogICAgYWxlcnRuYW1lJTNEInt7IC5Db21tb25MYWJlbHMuYWxlcnRuYW1lIH19IiU3RAp7ey0gZW5kIH19CgoKCnt7IGRlZmluZSAiX19hbGVydF9zZXZlcml0eV9wcmVmaXgiIC19fQogICAge3sgaWYgbmUgLlN0YXR1cyAiZmlyaW5nIiAtfX0KICAgIDpsZ3RtOgogICAge3stIGVsc2UgaWYgZXEgLkxhYmVscy5zZXZlcml0eSAiY3JpdGljYWwiIC19fQogICAgOmZpcmU6CiAgICB7ey0gZWxzZSBpZiBlcSAuTGFiZWxzLnNldmVyaXR5ICJ3YXJuaW5nIiAtfX0KICAgIDp3YXJuaW5nOgogICAge3stIGVsc2UgLX19CiAgICA6cXVlc3Rpb246CiAgICB7ey0gZW5kIH19Cnt7LSBlbmQgfX0KCnt7IGRlZmluZSAiX19hbGVydF9zZXZlcml0eV9wcmVmaXhfdGl0bGUiIC19fQogICAge3sgaWYgbmUgLlN0YXR1cyAiZmlyaW5nIiAtfX0KICAgIDpsZ3RtOgogICAge3stIGVsc2UgaWYgZXEgLkNvbW1vbkxhYmVscy5zZXZlcml0eSAiY3JpdGljYWwiIC19fQogICAgOmZpcmU6CiAgICB7ey0gZWxzZSBpZiBlcSAuQ29tbW9uTGFiZWxzLnNldmVyaXR5ICJ3YXJuaW5nIiAtfX0KICAgIDp3YXJuaW5nOgogICAge3stIGVsc2UgaWYgZXEgLkNvbW1vbkxhYmVscy5zZXZlcml0eSAiaW5mbyIgLX19CiAgICA6aW5mb3JtYXRpb25fc291cmNlOgogICAge3stIGVsc2UgLX19CiAgICA6cXVlc3Rpb246CiAgICB7ey0gZW5kIH19Cnt7LSBlbmQgfX0KCgp7ey8qIEZpcnN0IGxpbmUgb2YgU2xhY2sgYWxlcnRzICovfX0Ke3sgZGVmaW5lICJzbGFjay5tb256by50aXRsZSIgLX19CiAgICBbe3sgLlN0YXR1cyB8IHRvVXBwZXIgLX19CiAgICB7eyBpZiBlcSAuU3RhdHVzICJmaXJpbmciIH19Ont7IC5BbGVydHMuRmlyaW5nIHwgbGVuIH19e3stIGVuZCAtfX0KICAgIF0ge3sgdGVtcGxhdGUgIl9fYWxlcnRfc2V2ZXJpdHlfcHJlZml4X3RpdGxlIiAuIH19IHt7IC5Db21tb25MYWJlbHMuYWxlcnRuYW1lIH19Cnt7LSBlbmQgfX0KCgp7ey8qIENvbG9yIG9mIFNsYWNrIGF0dGFjaG1lbnQgKGFwcGVhcnMgYXMgbGluZSBuZXh0IHRvIGFsZXJ0ICkqL319Cnt7IGRlZmluZSAic2xhY2subW9uem8uY29sb3IiIC19fQogICAge3sgaWYgZXEgLlN0YXR1cyAiZmlyaW5nIiAtfX0KICAgICAgICB7eyBpZiBlcSAuQ29tbW9uTGFiZWxzLnNldmVyaXR5ICJ3YXJuaW5nIiAtfX0KICAgICAgICAgICAgd2FybmluZwogICAgICAgIHt7LSBlbHNlIGlmIGVxIC5Db21tb25MYWJlbHMuc2V2ZXJpdHkgImNyaXRpY2FsIiAtfX0KICAgICAgICAgICAgZGFuZ2VyCiAgICAgICAge3stIGVsc2UgLX19CiAgICAgICAgICAgICM0MzlGRTAKICAgICAgICB7ey0gZW5kIC19fQogICAge3sgZWxzZSAtfX0KICAgIGdvb2QKICAgIHt7LSBlbmQgfX0Ke3stIGVuZCB9fQoKCnt7LyogRW1vamkgdG8gZGlzcGxheSBhcyB1c2VyIGljb24gKGN1c3RvbSBlbW9qaSBzdXBwb3J0ZWQhKSAqL319Cnt7IGRlZmluZSAic2xhY2subW9uem8uaWNvbl9lbW9qaSIgfX06cHJvbWV0aGV1czp7eyBlbmQgfX0KCnt7LyogVGhlIHRlc3QgdG8gZGlzcGxheSBpbiB0aGUgYWxlcnQgKi99fQp7eyBkZWZpbmUgInNsYWNrLm1vbnpvLnRleHQiIC19fQogICAge3sgcmFuZ2UgLkFsZXJ0cyB9fQogICAgICAgIHt7LSBpZiAuQW5ub3RhdGlvbnMubWVzc2FnZSB9fQogICAgICAgICAgICB7eyAuQW5ub3RhdGlvbnMubWVzc2FnZSB9fQogICAgICAgIHt7LSBlbmQgfX0KICAgICAgICB7ey0gaWYgLkFubm90YXRpb25zLmRlc2NyaXB0aW9uIH19CiAgICAgICAgICAgIHt7IC5Bbm5vdGF0aW9ucy5kZXNjcmlwdGlvbiB9fQogICAgICAgIHt7LSBlbmQgfX0KICAgIHt7LSBlbmQgfX0Ke3stIGVuZCB9fQoKCgp7ey0gLyogSWYgbm9uZSBvZiB0aGUgYmVsb3cgbWF0Y2hlcywgc2VuZCB0byAjbW9uaXRvcmluZy1uby1vd25lciwgYW5kIHdlIApjYW4gdGhlbiBhc3NpZ24gdGhlIGV4cGVjdGVkIGNvZGVfb3duZXIgdG8gdGhlIGFsZXJ0IG9yIG1hcCB0aGUgY29kZV9vd25lcgp0byB0aGUgY29ycmVjdCBjaGFubmVsICovIC19fQp7eyBkZWZpbmUgIl9fZ2V0X2NoYW5uZWxfZm9yX2NvZGVfb3duZXIiIC19fQogICAge3stIGlmIGVxIC4gInBsYXRmb3JtLXRlYW0iIC19fQogICAgICAgIHBsYXRmb3JtLWFsZXJ0cwogICAge3stIGVsc2UgaWYgZXEgLiAic2VjdXJpdHktdGVhbSIgLX19CiAgICAgICAgc2VjdXJpdHktYWxlcnRzCiAgICB7ey0gZWxzZSAtfX0KICAgICAgICBtb25pdG9yaW5nLW5vLW93bmVyCiAgICB7ey0gZW5kIC19fQp7ey0gZW5kIH19Cgp7ey0gLyogU2VsZWN0IHRoZSBjaGFubmVsIGJhc2VkIG9uIHRoZSBjb2RlX293bmVyLiBXZSBvbmx5IGV4cGVjdCB0byBnZXQKaW50byB0aGlzIHRlbXBsYXRlIGZ1bmN0aW9uIGlmIHRoZSBjb2RlX293bmVycyBsYWJlbCBpcyBwcmVzZW50IG9uIGFuIGFsZXJ0LgpUaGlzIGlzIHRvIGRlZmVuZCBhZ2FpbnN0IHVzIGFjY2lkZW50YWxseSBicmVha2luZyB0aGUgcm91dGluZyBsb2dpYy4gKi8gLX19Cnt7IGRlZmluZSAic2xhY2subW9uem8uY29kZV9vd25lcl9jaGFubmVsIiAtfX0KICAgIHt7LSBpZiAuQ29tbW9uTGFiZWxzLmNvZGVfb3duZXIgfX0KICAgICAgICB7eyB0ZW1wbGF0ZSAiX19nZXRfY2hhbm5lbF9mb3JfY29kZV9vd25lciIgLkNvbW1vbkxhYmVscy5jb2RlX293bmVyIH19CiAgICB7ey0gZWxzZSAtfX0KICAgICAgICBtb25pdG9yaW5nCiAgICB7ey0gZW5kIH19Cnt7LSBlbmQgfX0KCnt7IGRlZmluZSAic2xhY2subW9uem8ubGlua19idXR0b25fdGV4dCIgLX19CiAgICB7ey0gaWYgLkNvbW1vbkFubm90YXRpb25zLmxpbmtfdGV4dCAtfX0KICAgICAgICB7ey0gLkNvbW1vbkFubm90YXRpb25zLmxpbmtfdGV4dCAtfX0KICAgIHt7LSBlbHNlIC19fQogICAgICAgIExpbmsKICAgIHt7LSBlbmQgfX0gOmxpbms6Cnt7LSBlbmQgfX0= kind: Secret metadata: name: alertmanager-main namespace: monitoring type: Opaque
변경된 설정은 알럿매니저 웹 화면에서 확인할 수 있습니다. 메뉴의 Status
를 클릭하면, 설정 내용응 확인할 수 있습니다.


참고
- https://juliusv.com/promslack/
- https://gist.github.com/milesbxf/e2744fc90e9c41b47aa47925f8ff6512
- https://api.slack.com/messaging/webhooks