zabbixのアクションでRedmineのissue登録をなんとかしてみた

ちょっと気軽に言われてためしてみたらけっこう手間取ったので備忘録です。

結論をいうと、zabbix4.0からならリモートコマンドでもめんどくさくないけどそれより下のバージョンだとissueのタイトルや説明のカスタマイズするにはトリガ数と同じ数分だけアクションを登録しなければならなくなるので刺身タンポポ撲滅したい勢としては不毛な感じがするという。[ansibleのzabbix_actionというモジュール](https://docs.ansible.com/ansible/devel/modules/zabbix_action_module.html#zabbix-action-module)はあるようですけど本末転倒っぽい。4.0より低いバージョンはメール通知連携でaliasでパイプでスクリプトに渡すという公式に載ってるやり方がいいのかなと思いました。

2通りやってみたのでいちおう載せられるとこをなんとなく書いときます。
環境は流用した関係でAmazonLinux1。

#### ★zabbix4.0以上でリモートコマンド＋redmine-pythonでWEB-APIで頑張るやつ

リモートコマンドで使えることを示すcommandsのカウント数の違いをマニュアルからctl+F検索してご覧いただくとわかるかと。
（必要そうなマクロはアクション登録画面のアクションタブの件名やメッセージでつかわれてる{TRIGGER.NAME}とか {ITEM.NAME1} ({HOST.NAME1}:{ITEM.KEY1}): {ITEM.VALUE1}とか）
https://www.zabbix.com/documentation/2.4/manual/appendix/macros/supported_by_location
https://www.zabbix.com/documentation/4.0/manual/appendix/macros/supported_by_location

で、以下は言われたzabbix2.4でテストしてみた履歴です。

###### コンテナでzabbixサーバを用意

```
# mkdir zabbix-test
# cd zabbix-test/

##DBコンテナを用意。
# docker run     -d     --name zabbix-db  \
   -v /backups:/backups  \
   -v /etc/localtime:/etc/localtime:ro  \
   --env="MARIADB_USER=zabbix"  \
   --env="MARIADB_PASS=*********" \
   --env="DB_innodb_buffer_pool_size=256M" \
   monitoringartist/zabbix-db-mariadb

##zabbixコンテナを用意。
# docker run \
>     -d \
>     --name zabbix \
>     -p 80:80 \
>     -p 10051:10051 \
>     -v /etc/localtime:/etc/localtime:ro \
>     --link zabbix-db:zabbix.db \
>     --env="ZS_DBHost=zabbix.db" \
>     --env="ZS_DBUser=zabbix" \
>     --env="ZS_DBPassword=*********" \
>     monitoringartist/zabbix-2.4
```

###### ホスト本体にzabbix-agentをansibleで入れリモートコマンドを許可設定

```roles/zabbix24/tasks/main.yml
---
- block:
  - name: import Zabbix RPM-GPG-KEY
    rpm_key: key=http://repo.zabbix.com/RPM-GPG-KEY-ZABBIX state=present
    tags: zabbix24

  - name: if ansible_distribution_major_version is null when amazonlinux1, set it.
    set_fact:
      ansible_distribution_major_version: 6
    when: ansible_distribution == 'Amazon' and ansible_service_mgr == 'upstart'

  - name: if ansible_distribution_major_version is null when amazonlinux2, set it.
    set_fact:
      ansible_distribution_major_version: 7
    when: ansible_distribution == 'Amazon' and ansible_service_mgr == 'systemd'

  - name: zabbix2.4 release install yum
    yum: name='http://repo.zabbix.com/zabbix/2.4/rhel/{{ ansible_distribution_major_version }}/x86_64/zabbix-release-2.4-1.el{{ ansible_distribution_major_version }}.noarch.rpm' state=present
    tags: zabbix24

  - name: zabbix2.4-agent install
    yum: name=zabbix-agent state=present enablerepo=zabbix
    tags: zabbix24
  when: ansible_os_family == 'RedHat'

- block:
  - name: import Zabbix Debian-Ubuntu-GPG-KEY
    apt_key: 
      url: 'http://repo.zabbix.com/zabbix-official-repo.key'
      state: present
    tags: zabbix24

  - name: zabbix2.4 release install apt
    apt_repository: 
      repo: 'deb http://repo.zabbix.com/zabbix/2.4/ubuntu {{ ansible_distribution_release }} main'
      state: present
    tags: zabbix24

  - name: zabbix2.4 agent install apt
    apt:
      pkg: zabbix-agent
      state: present
      update_cache: yes
      cache_valid_time: 0
    tags: zabbix24
  when:
    - ansible_distribution == "Ubuntu"
    - ansible_lsb.major_release < 16

- name: zabbix-agent.conf
  lineinfile: >-
    dest='/etc/zabbix/zabbix_agentd.conf'
    state=present
    backup=yes
    backrefs=yes
    regexp='{{ item.regexp }}'
    line='{{ item.line }}'
  with_items:
  - regexp: 'Hostname=Zabbix server'
    line: 'Hostname={{ inventory_hostname }}'
  - regexp: '^Server=127.0.0.1'
    line: 'Server={{ zabbix_server }}'
  - regexp: '^ListenIP=127.0.0.1'
    line: 'ListenIP=0.0.0.0'
  - regexp: '^# ServerActive='
    line: 'ServerActive={{ zabbix_server }}'
  - regexp: '^# Timeout=3'
    line: 'Timeout=30'
  - regexp: '^Include=/etc/zabbix/zabbix_agentd.d/'
    line: '#Include=/etc/zabbix/zabbix_agentd.d/'
  tags: zabbix24

- name: mkdir /etc/zabbix/zabbix_agentd.d/
  file: path=/etc/zabbix/zabbix_agentd.d/ state=directory owner=root group=root mode=0755
  tags: zabbix24

- name: start zabbix with chkconfig on
  service: name=zabbix-agent state=started enabled=yes
  tags: zabbix24
```
リモートコマンドは手動で変えてました


###### python-redmineを入れる、スクリプトを配置、コマンド単体テストしissue登録を確認

```
# easy_install python-redmine
# python
>>> from redminelib import Redmine
>>> quit()
# yum install git
# git clone https://github.com/ryumei/CZ201501.git
# cd CZ201501/
# vi issue_reporter.py
# git diff
--- a/issue_reporter.py
+++ b/issue_reporter.py
-from redmine import Redmine
+from redminelib import Redmine
# cat README.md
# python issue_reporter.py -u http
://<redmine-address> -k <apikey> -p <project-id> -s "(subject)auto-regist-test1" -d "mailbody（{HOSTNAME}などは使える"
```

###### 気軽にアラート出す用zabbixのアイテムとトリガとアクションを設定

nginxの適当にたてたコンテナのポートを監視する感じにテンプレートからアイテム複製してホストにテンプレートリンクさしてトリガも複製してアクションを設定
アイテムの間隔は10秒とかに短めにしとくとテスト時間が短くできる
そのトリガを作成
	HTTP service 8888 がダウンしました {HOST.NAME}
{Template App HTTP Service:net.tcp.service[http,,8888].max(#3)}=0

リモートcommandを実行するアクションを作成
（発動条件を障害だけにしたところ動いた）

```
ステップ,
開始１終了１間隔０、実行内容：リモートコマンド、ターゲット：現在のホスト、タイプ：カスタムスクリプト、次で実行：zabbixサーバ、
コマンド：
#/usr/local/bin/issue_reporter.py -u http://<my-redmine>/ -k <my-web-api-key> -p <my-project-id> -s "{TRRIGER.NAME}" -d "honbun"
アクションの実行条件：障害対応済み＝コメントなし
```
※{TRRIGER.NAME}はたぶん4.0以上じゃないと使えないのでそのまま登録されてしまう。

###### ポート落とすテスト用のコンテナを用意し落としてみてトリガの履歴が出たらissue登録を確認

いちおう使ったdockerfile置いときますがdocker runで気軽に起動するとかでもよいかと。

```
FROM centos:centos7.1.1503
ENV container docker
#RUN export http_proxy=http://<Proxy-server>:8080 && \
#    export https_proxy=http://<Proxy-server>:8080 && \
RUN yum swap -y fakesystemd systemd && \
    yum update -y && \
    yum install -y epel-release && \
    yum install -y nginx && \
    yum clean all && \
    ln -sf  /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
ADD nginx.conf /etc/nginx/
ADD default.conf /etc/nginx/conf.d/
#RUN systemctl enable nginx
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
#CMD ["/usr/sbin/nginx", "-g", "daemon off;, access_log syslog:server=logserver,facility=local1 main; error_log syslog:server=logserver,facility=local2 notice;"]
EXPOSE 80
#LABEL "com.datadoghq.ad.instances"='[{"nginx_status_url": "http://%%host%%:%%port%%/nginx_status"}]'
LABEL "com.datadoghq.ad.logs"='[{"source": "nginx", "service": "nginx-test-app"}]'
```
やりなおすばあいはdocker start して監視復活したらdocker stop

```
docker ps -a
docker stop <container-id>
```
ここまででzabbixのトリガ起因でのissue登録はできたが冒頭に書いた通り文面のカスタマイズに難あり。


#### ★zabbix4より下＋メールローカル配送＋aliasパイプ渡し＋rubyスクリプトでメールAPIで頑張るやつ

ちょっとメール関連の戦闘力が貧弱で苦労しました。送信はともかく受信が。
昨今は送信もクラウドベンダやプロバイダやキャリア等によるスパム対策的な制限もアレなのでローカル配送が手間がないなあと。外に出た瞬間に名前が引けないとダメとかSPFレコードがとか逆引きがとかなんか偽物じゃないスパムではないことを保証するための確認が色々入るので。

ロケーションの件にまつわる感想：
・zabbixのMTAをzabbixのローカルとしてそこにローカル配送するのが楽でした。
・コンテナからホストに送ろうとすると消耗するので気軽な気持ちでやるのはやめたほうがいいと思いました。
・gmailもテスト用に気軽に使える雰囲気はない気がしました。
・ドメインとメールの戦闘力がわりと必要な作業でした。
　（極力難易度を減らすやりかたがzabbixとmtaを同一サーバに載せてローカル配送する方法）
・メール受信のためのAPIはcurlするためのAPIではないようで設定とAPIキー用意を別に作業が要るので注意が必要。
・sendmailとssmtpに脱線したけどpostfixがやっぱり使いやすい気がしました。
・そもそもRedmine側でweb(port80,443等)のIP制限をしてたらそこも確認しないといけない。

公式のメールイッシュー登録は以下のかんじ。
http://guide.redmine.jp/RedmineReceivingEmails/

######メールコマンドでメールが届くかを確認

mailコマンド入ってないときは入れる

```
# yum install mailx
# echo hogehoge|mail -s 'redtest1' <my-mail-account-address>
# tail -f /var/log/maillog
```

######Postfixにする（alternativesで切り替える）

```
# yum install postfix
# cp /etc/postfix/main.cf{,.org}
# vi /etc/postfix/main.cf
# diff /etc/postfix/main.cf{,.org}
84c83
< mydomain = localhost.localdomain
---
> #mydomain = domain.tld
100c99
< myorigin = $mydomain
---
> #myorigin = $mydomain
114c113
< inet_interfaces = all
---
> #inet_interfaces = all
117c116
< #inet_interfaces = $mynetworks, $myhostname, localhost
---
> inet_interfaces = localhost
120c119
< inet_protocols = ipv4
---
> inet_protocols = all
165c164
< mydestination = $mydomain, $myhostname, localhost.$mydomain, localhost
---
> mydestination = $myhostname, localhost.$mydomain, localhost
268d266
< mynetworks = 10.0.0.0/8, 172.17.0.0/16, 192.168.0.0/24, 127.0.0.0/8
421c419
< home_mailbox = Maildir/
---
> #home_mailbox = Maildir/

# service postfix restart
# /usr/sbin/alternatives --config mta

There are 2 programs which provide 'mta'.

  Selection    Command
-----------------------------------------------
*+ 1           /usr/sbin/sendmail.sendmail
   2           /usr/sbin/sendmail.postfix

Enter to keep the current selection[+], or type selection number: 2

# netstat -lnpt
```

######zabbix側のアクションをメールに修正

アクションをメールに修正
開始１終了１間隔０、実行内容：メッセージの送信、ユーザに送信：Admin、次のメディアのみ使用：<設定したメディア名、
 デフォルトのメッセージ：チェック、アクションの実行条件：障害対応済み＝コメントなし

No media defined for user とか言われる場合はmailコマンドが実行できるのかから確認したりメール転送ができるのか確かめたりなどする。

ローカル配送の場合にはlocalhost.localdomainというのが/etc/hostsと/etc/postfix/main.confとzabbixのメディアのsmtpサーバの記述が合ってれば届くはず。
（MTAとしての設定がアレでAレコード引けない等々の理由で本文を確かめるために普通にメール転送で外部に送るテストするとたぶん迷惑フォルダに行く）

######コンテナ環境をdbだけ流用しzabbix-serverはホストに入れなおす

メールをローカル配送するためだけの措置としてこうする次第です。

DBコンテナにホストからつなげられるようにdocker runやdockerfileにexpose（ポートの公開）
してない場合に後から接続できるようにするコマンドを打っておく
https://www.scriptlife.jp/contents/programming/2016/09/07/docker-port-forward/

```
docker ps
docker inspect c9954c355dac
iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 3306 -j DNAT --to-destination 172.17.0.3:3306
```
zabbixそのたをansibleやコマンドなどで適当に入れる
（agentのroleしかなかったので適当に複製してchefレシピからserverのタスクをかいたがところどころ手動）

```
# /usr/local/bin/ansible-playbook -c local zbxserver-sample.yml -vvv -D -e "mysql_role=client"

# cat /root/default/ansible/zbxserver-sample.yml
- hosts: localhost
  become: yes
  roles:
    - { role: apache, tags: apache }
    - { role: mysql, tags: mysql }
    - { role: zabbix24-server, tags: zbx24 }
## playbook deploy sample command
# /usr/local/bin/ansible-playbook -c local zbxserver.yml -e "mysql_role=client" --syntax-check
# /usr/local/bin/ansible-playbook -c local zbxserver.yml -vvv -D -C -e "mysql_role=client"
# /usr/local/bin/ansible-playbook -c local zbxserver.yml -vvv -D -e "mysql_role=client"
```

phpはzabbixと一緒に勝手に入ってた

ちょっと失敗してたので手動でいれた（amazonlinux用の適切な分岐がなかったのとライブラリが違うとか）

```
# yum install --enablerepo=mysql57-community mysql-community-client
# yum install --enablerepo=mysql57-community mysql-community-libs mysql-community-devel
# yum install httpd httpd-devel mod_ssl openssl-devel
```
dbコンテナのidからipをしらべてホストから接続できることをmysqlコマンド打って接続確認

```
docker ps
docker inspect c9954c355dac
mysql -u zabbix -p -h 172.17.0.3
```
つながるのでOK

ちょっとzabbixのapache設定を2.4の書き方の問題だけでなおしたら動いた（dbの指定を初回に画面から実施）
https://tsunokawa.hatenablog.com/entry/2014/05/30/144249
https://blog.apar.jp/linux/334/

動いたあとアクションの内容とメディアタイプなどをローカル配送可能なようにhostsおよびmain.cfと合わせて修正するなどした
アイテムとトリガとアクションなどはdb流用してるのでそのまま使えていた

postfix側でのmydestinationを調整したらローカル転送ができるように
http://think-t.hatenablog.com/entry/20120930/p1

Redmineの管理からカスタムフィールドを作成（いちおう）
https://qiita.com/domonjo01/items/1729cddb0870b68c4015

######メール用のAPIキー生成して受信メール用のWebサービスを有効にする
公式マニュアルの記述どおりにする。
http://guide.redmine.jp/RedmineReceivingEmails/
このスクリプトを利用するためには、メール受信のためのAPIを有効にする必要があります: 「設定」→「受信メール」に移動し、 受信メール用のWebサービスを有効にする のチェックボックスをonにして、APIキーを入力するか生成してください。

というわけで生成したキーはaliasに書く

######メールaliasでパイプでスクリプトに渡す

```
# cd /usr/local/bin
# wget https://raw.githubusercontent.com/redmine/redmine/master/extra/mail_handler/rdm-mailhandler.rb
# chmod +x rdm-mailhandler.rb 

# rdm-mailhandler.rb -h

# vi /etc/aliases
# tail -2 /etc/aliases
#root: <my-mail-account-address>
root: "| /usr/local/bin/rdm-mailhandler.rb --url http://<my-redmine>/ --key <my-mail-api-key> --unknown-user accept --no-permission-check --project <my-project-name> --allow-override all "
# newaliases
```
newaliases忘れると更新が認識されないので注意。
ちなみにRedmine側に登録されてるユーザをfromにしないと普通にはじかれるらしいですが--unknown-user acceptとかつけるといけるらしい。


あとドメインが見つからないエラーの段階でzabbix搭載ホストのIPを変えてたのでRedmineからの接続制限でタイムアウトしていた。
キューの中身見るとエラーがそのうち書かれるのでそのメッセージから原因を推測できる。/var/log/maillogにもそのうち書かれるかもしれないけど。

```
# mailq
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
D0D1168A7F     1102 Fri Jan 18 07:38:33  <my-mail-account-address>
(temporary failure. Command output: An error occurred while contacting your Redmine server: Connection timed out - connect(2))
                                         root＠localhost.localdomain

-- 1 Kbytes in 1 Request.
```
失敗したときにキューを確認して丸ごと消す（dにid指定で個別に消せる）

```
# mailq
# postsuper -d ALL
```
https://qiita.com/pb_tmz08/items/60c760d71da00fcf5d9b

検証用のdockerを止めてたのを上げてzabbix側が復旧を認識したらまた止めてトリガの状態をみながらアラートを出す
（監視データ＞トリガ＞対象のトリガの時刻の部分を押下＞最近でたイベントの時間のリンクを押下＞メッセージアクションのステータスを確認する）
（アイテムから間隔は10秒等にしとくと待ちが短くなる。）

```
# docker start b21adda2caa7
# docker ps|grep 888
b21adda2caa7        centos:nginx-test                    "/usr/sbin/nginx -g …"   10 days ago         Up 3 minutes        0.0.0.0:8888->80/tcp   nginx-test

# docker stop b21adda2caa7 && tail -f /var/log/maillog
```
というわけで以下のようなmaillogがでてメールで届いたのと同様のチケット登録されてた。

```
Jan 18 07:49:34 ip-10-0-2-68 postfix/smtpd[9495]: connect from localhost[127.0.0.1]
Jan 18 07:49:34 ip-10-0-2-68 postfix/smtpd[9495]: 084D468A7F: client=localhost[127.0.0.1]
Jan 18 07:49:34 ip-10-0-2-68 postfix/cleanup[9498]: 084D468A7F: message-id=<20190118074934.084D468A7F＠ip-10-0-2-68.localhost.localdomain>
Jan 18 07:49:34 ip-10-0-2-68 postfix/qmgr[32706]: 084D468A7F: from=<my-mail-account-address>, size=1102, nrcpt=1 (queue active)
Jan 18 07:49:34 ip-10-0-2-68 postfix/smtpd[9495]: disconnect from localhost[127.0.0.1]
Jan 18 07:49:34 ip-10-0-2-68 postfix/local[9499]: 084D468A7F: to=<root＠localhost.localdomain>, relay=local, delay=0.53, delays=0.05/0.01/0/0.47, dsn=2.0.0, status=sent (delivered to command:  /usr/local/bin/rdm-mailhandler.rb --url http://<my-redmine>/ --key <my-mail-api-key> --unknown-user accept --no-permission-check --project <my-project-name> --allow-override all )
Jan 18 07:49:34 ip-10-0-2-68 postfix/qmgr[32706]: 084D468A7F: removed
```
証拠画像↓いちおう貼っておきます。
![redmine-mail-issue-regist-redmine.png](https://qiita-image-store.s3.amazonaws.com/0/25031/845d65ff-b695-6b61-cb20-c0a40a33dfbe.png)

というわけで以上。

#### slackとの連携
ついでなのでちょっとやってみました。

#####★zabbixからのslack通知連携テスト

https://github.com/bageljp/zabbix-slack
https://bitstar.jp/blog/2018/04/06/21023/
https://qiita.com/wapa5pow/items/2327561493015a833c97

path探してスクリプト置く

```
# rpm -qa|grep -i zabbix-server
zabbix-server-mysql-2.4.8-1.el6.x86_64
zabbix-server-2.4.8-1.el6.x86_64
# rpm -ql zabbix-server-2.4.8-1.el6.x86_64 |grep -i alertscripts
/usr/lib/zabbix/alertscripts
# grep -i AlertScript /etc/zabbix/zabbix_server.conf
### Option: AlertScriptsPath
# AlertScriptsPath=${datadir}/zabbix/alertscripts
AlertScriptsPath=/usr/lib/zabbix/alertscripts

# cd /usr/lib/zabbix/alertscripts
# wget https://raw.githubusercontent.com/bageljp/zabbix-slack/master/slack.sh
# chmod a+x slack.sh
```
browsタブからIncoming WebHooksをAddでconfig設定するかんじで適当に。
WebhookURLとチャンネル名を控える

```
# diff slack.sh{,.org}
4,5c4,5
< slack_url='https://hooks.slack.com/services/******/******/******'
< slack_username='zabbix-test'
---
> slack_url='https://hooks.slack.com/services/XXX/XXXX/XXXXX'
> slack_username='Zabbix'
9c9
< emoji=':space_invader:'
---
> emoji=':ghost:'
14,16c14,16
< zabbix_baseurl="http://<my-zabbix-server-url>/zabbix"
< zabbix_username="*****"
< zabbix_password="*****"
---
> zabbix_baseurl="http://zabbix.example.com"
> zabbix_username="yourzabbixusername"
> zabbix_password="zabbixpassword"
```
管理＞メディアタイプ
メディアタイプ作成
Slackにスクリプト指定

ユーザのメディアにSlack指定し通知先チャネルを登録

アクションの通知をSlackにする

アラート発生させてみる

通知されることを確認する

スクリプトをいじりながらやってみたものの
タイトル以外が通知されない感じだった

ので、やっぱ細かいの出したいんならzabbix3.2以上等にするといいのかなというところ。
2.4だとやっては見たもののトリガ名くらいしか通知できず。
（同じバージョンの例を見る限りはイベントIDは取れそうな気もするくらい）

#####★datadogからのslack通知連携

もはやzabbixは何の関係もないタイトル詐欺ですがついでにslackのテストをしたかっただけの備忘録です。

https://www.slack.com/plans
ワークスペースが統合限界に達しました。より多くの統合を可能にするために、あなたの計画をアップグレードしてください。
ということで10個以上インテグレーションしてるとdatadogの統合設定を会社のslack側に入れるにはslackを有料化する必要があるっぽい

じゃーしょうがないのでテスト用のワークスペースを適当につくってためしました

まずslack側で
適当な名前のワークスペースを作って#testというチャネルを作った
datadogのアプリを検索して追加してみた
でてきたwebhookURLを控えた

datadog側でIntegration＞Slack
Slack Account Nameのとこにslackのワークスペース名を入れた
Slack Account HookにwebhookのURLを入れた
Installを押した
するとチャネル名と宛先アカウント入れるとこが出てくるので
channel-nameとworkspace-name宛てに追加。

そこに送るモニタを画面から登録してExportしてみたところ以下のような感じに。

```
{
	"name": "Detect event docker kill on {{event.host.name}}",
	"type": "event alert",
	"query": "events('priority:all KILL status:error sources:docker').rollup('count').last('5m') > 1",
	"message": "event.id: {{event.id}},   \nevent.title: {{event.title}},   \nevent.text: {{event.text}},   \nevent.host.name: {{event.host.name}}   @slack-myworkspace1-test",
	"tags": [],
	"options": {
		"notify_audit": false,
		"locked": false,
		"timeout_h": 0,
		"silenced": {},
		"include_tags": true,
		"new_host_delay": 300,
		"notify_no_data": false,
		"renotify_interval": 0,
		"no_data_timeframe": 2
	}
}
```
しばらくすると以下のような感じに発報したデータがslackに飛んできていた。

```
Datadog アプリ [15:11]
Triggered: Detect event docker kill on i-xxxxxxxxx
event.id: 4764067214913445502,  
event.title: centos:nginx-test 3 stop 3 start 3 kill 3 die on i-xxxxxxxxx,  
event.text: %%% 
centos:nginx-test 3 stop 3 start 3 kill 3 die on i-xxxxxxxxx
&#x60;&#x60;&#x60;
 もっと表示する
Notified
@slack-myworkspace1-test
```