GitLab
Ansible
GoogleCloudPlatform
GitLab-CI
stackdriver
0

Stackdriver+Gitlab-CI+Ansibleで自動復旧の仕組みを構築する

はじめに

GCE上のプロセスをStackdriverで監視していて、プロセスが落ちたらSlackにアラートを飛ばす・・・・

ちゃうねん!アラートが飛ばすことが目的じゃなくて、サービスをいち早く復旧させるのが目的やねん!

どうせAlert飛んだあとにやることは、systemctl status XXXXXでステータス確認して、sudo systemctl start XXXXXをするだけじゃん。

ということで、Stackdriver+Gitlab-CI+Ansibleを連携させて、アラートを飛ばすだけじゃなく、サービスを復旧させる仕組みを構築してみようと思う。

チームのメンバーがSlack botでもいい感じに自動復旧の仕組みを作ってる記事があるので、Slack botでやりたいんだよ!俺は!っていう人は↓を参考にすると幸せになれる。
Stackdriverとslackbotでサービス自動復旧させる
https://qiita.com/andromeda/items/fcb2ea02e9bb32e329e4

全体構成

autohealing (2).png

補足

後述もしているが、proxy経由でStackdriverのwebhookをしている理由は、SourceIPが固定化出来ないのでGitLabのFirewallルールにSourceIPを追加出来ないため。
一定のセキュリティを担保するためにBasic認証付きにしている。

前提

  • gitlab自体はすでにインストール(稼働)済みとする
  • GCPプロジェクトが利用可能な状態である

Gitlab-runner+Ansibleサーバを構築

適当にGCEインスタンスを作成する。
今回はCentOS7のイメージを使用。

Ansibleのインストール

適当にインストール

sudo yum install ansible

ansibleの設定ファイル

すごく単純でこんな構成

$ tree
.
├── inventories
│   └── hosts
├── roles
│   └── nginx
│       └── tasks
│           └── main.yml
└── site_test.yml

hosts
[nginx]
XXX.XXX.XXX.XXX
main.yml
- name: start nginx
  systemd:
    name: nginx
    state: started
site_test.yml
- name: start nginx
  hosts: nginx
  become: yes
  roles: 
    - nginx

.gilab-ci.ymlの設定

ansibleというユーザーを作って、ansibleユーザーで実行する。
また、ansibleユーザーの公開鍵は、監視対象となるNginxサーバがあるGCPプロジェクトに登録しておく。

.gitlab-ci.yml
stages:
  - start-service

start-service:
  stage: start-service
  tags:
    - autohealing
  script:
    - sudo ansible-playbook -i ./ansible/inventories/hosts -u ansible --private-key=/home/ansible/.ssh/id_rsa ./ansible/site_test.yml

GitLab-Runnerのインストール

公式ドキュメントを参考にインストール

$ sudo curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash

$ sudo yum install gitlab-runner

# 起動確認
$ systemctl status gitlab-runner
● gitlab-runner.service - GitLab Runner
   Loaded: loaded (/etc/systemd/system/gitlab-runner.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2018-10-20 01:04:37 JST; 11h ago
 Main PID: 25635 (gitlab-runner)
   CGroup: /system.slice/gitlab-runner.service
           └─25635 /usr/lib/gitlab-runner/gitlab-runner run --working-directory /home/gitlab-runner --config /etc/gitlab-runner/config.toml --service gitla...

gitlab-runnerにsudo権限を与える

$ sudo visudo
# 以下を末尾に追加
gitlab-runner ALL=(ALL) NOPASSWD: ALL

GitLab-Runnerを登録する

公式ドキュメント通り対話形式で以下のようにRegisterする

$ sudo gitlab-runner register
Running in system-mode.                            

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://example.gitlab.com/
Please enter the gitlab-ci token for this runner:
XXXXXXXXXXXXXXX
Please enter the gitlab-ci description for this runner:
[ansible-server] : autohealing
Please enter the gitlab-ci tags for this runner (comma separated):
autohealing
Registering runner... succeeded                     runner=yJC3cma3
Please enter the executor: docker+machine, docker-ssh+machine, kubernetes, docker, virtualbox, shell, ssh, docker-ssh, parallels:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! 

こんな感じでrunnerが登録される
CI : CD Settings · CI : CD · blcloud-infra : blcloud-autohealing · GitLab 2018-10-20 14-13-28.png

.netrcを作成する

git pullとかするときにアカウント情報聞かれてめんどいので、 .netrcを作っておく

$ su - gitlab-runner
$ vi .netrc
machine gitlab.com
login ci-user(適当)
password ci-password(適当)

Pipeline triggerを設定

GitLabにてtriggerを設定して、webhookで使用するtokenを取得する。

スクリーンショット 2018-10-20 22.28.13.png

gitlab-proxyサーバの作成

Stackdriver AlertのWebhookはGIPが一定ではない(Googleサポートにも問合せたけど、左記の回答)。
GitlabにIPでFireWallがあった場合は、Webhookが通知できない。
なので、Nginxでproxyとなるサーバを用意して、GIPを固定化する。
そして、NginxにBasic認証を用いることで、一定のセキュリティを担保するようにする。

IPを固定できるようにしてーというissuesが上がっているので、ここをウォッチしていくと、このgitlab-proxyが不要になったら分かるようになる。
是非、スターつけてください!

nginxのインストール

$ sudo yum install -y nginx

basic認証を設定する

$ sudo yum install -y httpd-tools
$ htpasswd -c /etc/nginx/.htpasswd なんか適当にID
New password: なんか適当にPW
Re-type new password: なんか適当にPW

$ vi /etc/nginx/nginx.conf

       auth_basic "Restricted";
       auth_basic_user_file /etc/nginx/.htpasswd;

        location / {
            proxy_pass https://gitlabのアドレス/;
        }

監視対象のサーバ作成

今回、監視される側となるサーバを作成する。
このNginxがダウンしたら、stackdriverが検知して、gitlabに通知後にgitlab-runnerを発火する。

Nginxのインストール

適当にGCEにNginxをインストールしておく

$ sudo install -y nginx
$ systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: active (running) since Sat 2018-10-20 04:29:30 UTC; 42min ago
  Process: 1726 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
  Process: 1723 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
  Process: 1722 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
 Main PID: 1728 (nginx)
   CGroup: /system.slice/nginx.service
           ├─1728 nginx: master process /usr/sbin/nginx
           └─1729 nginx: worker process

StackdriverAgentのインストール

プロセスのメトリクスを取得するにはStackdriverMonitoringAgentのインストールがいる。

$ curl -sSO https://dl.google.com/cloudagents/install-monitoring-agent.sh
$ sudo bash install-monitoring-agent.sh

# 起動確認
$ systemctl status stackdriver-agent
● stackdriver-agent.service - LSB: start and stop Stackdriver Agent
   Loaded: loaded (/etc/rc.d/init.d/stackdriver-agent; bad; vendor preset: disabled)
   Active: active (running) since Sat 2018-10-20 11:27:42 UTC; 37s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 9464 ExecStart=/etc/rc.d/init.d/stackdriver-agent start (code=exited, status=0/SUCCESS)
 Main PID: 9495 (stackdriver-col)
   CGroup: /system.slice/stackdriver-agent.service
           └─9495 /opt/stackdriver/collectd/sbin/stackdriver-collectd -C /etc/stackdriver/collectd.conf -P /var/run/stackdriver-agent.pid

Stackdriverのアラート設定

webhookの設定

スクリーンショット 2018-10-25 9.46.41.png

alertの設定

スクリーンショット 2018-10-25 9.43.51.png

notificationの設定

スクリーンショット 2018-10-25 9.53.01.png

いざ実践

Nginxを落とす

$ sudo systemctl stop nginx
$ systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: inactive (dead)

Oct 25 05:05:39 web-test systemd[1]: Started The nginx HTTP and reverse proxy server.
Oct 25 05:36:07 web-test systemd[1]: Stopping The nginx HTTP and reverse proxy server...
Oct 25 05:36:07 web-test systemd[1]: Stopped The nginx HTTP and reverse proxy server.
Oct 25 05:44:40 web-test systemd[1]: Starting The nginx HTTP and reverse proxy server...
Oct 25 05:44:40 web-test nginx[13630]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Oct 25 05:44:40 web-test nginx[13630]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Oct 25 05:44:40 web-test systemd[1]: Failed to read PID from file /run/nginx.pid: Invalid argument
Oct 25 05:44:40 web-test systemd[1]: Started The nginx HTTP and reverse proxy server.
Oct 26 08:33:01 web-test systemd[1]: Stopping The nginx HTTP and reverse proxy server...
Oct 26 08:33:01 web-test systemd[1]: Stopped The nginx HTTP and reverse proxy server.

Stackdriverで障害を検知!
スクリーンショット 2018-10-26 17.41.43.png

すると・・・パイプラインが動き出す

Pipelines · blcloud-infra : blcloud-autohealing · GitLab 2018-10-25 13-24-57.png

Running with gitlab-runner 11.3.1 (0aa5179e)
  on autohealing 2cd3b42d
Using Shell executor...
Running on ansible-server...
Fetching changes...
HEAD is now at 324102c 改装を変更
Checking out 324102c4 as master...
Skipping Git submodules setup
$ sudo ansible-playbook -i ./ansible/inventories/hosts -u ansible --private-key=/home/ansible/.ssh/id_rsa ./ansible/site_test.yml

PLAY [start nginx] *************************************************************

TASK [Gathering Facts] *********************************************************
ok: [XXX.XXX.XXX.XXX]

TASK [nginx : start nginx] *****************************************************
changed: [XXX.XXX.XXX.XXX]

PLAY RECAP *********************************************************************
XXX.XXX.XXX.XXX             : ok=2    changed=1    unreachable=0    failed=0   

Job succeeded

Nginxのステータスを見てみると・・・復活している!

$ systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: active (running) since Fri 2018-10-26 08:41:40 UTC; 1min 16s ago
  Process: 15845 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
  Process: 15842 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
  Process: 15841 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
 Main PID: 15847 (nginx)
   CGroup: /system.slice/nginx.service
           ├─15847 nginx: master process /usr/sbin/nginx
           └─15848 nginx: worker process

Oct 26 08:41:39 web-test systemd[1]: Starting The nginx HTTP and reverse proxy server...
Oct 26 08:41:40 web-test nginx[15842]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Oct 26 08:41:40 web-test nginx[15842]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Oct 26 08:41:40 web-test systemd[1]: Failed to read PID from file /run/nginx.pid: Invalid argument
Oct 26 08:41:40 web-test systemd[1]: Started The nginx HTTP and reverse proxy server.

スクリーンショット 2018-10-26 18.08.07.png

今後やりたいこと

gitlabの通知をする際に、variablesを付加してansibleで使用するplaybookを動的に変更出来るようにしておきたい。