keepalivedのインストール

# 1. はじめに
keepalivedを使って、GW冗長構成のシステム構築と動作確認をする。
あくまでも忘れっぽい自分向けに書いてる資料となりますので、読みづらい部分があるかもしれません。

# 2. 環境
- CentOS 7.8 と Cisco 841m を用いて構成する

```bash:centos7
[~]$ cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)

[~]$ keepalived --version
Keepalived v2.0.20 (01/22,2020)
```

```bash:cisco841m
#show ver
Cisco IOS Software, C800M Software (C800M-UNIVERSALK9-M), Version 15.5(3)M4a, RELEASE SOFTWARE (fc1)

#show inv
NAME: "C841M-4X-JSEC/K9", DESCR: "C841M-4X-JSEC/K9 chassis, Hw Serial#: FGLxxxxxxxx, Hw Revision: 1.0"
```

- ホストのIPアドレスは以下の通り

| H/N | IPv4 |
| --- | ---- |
| centos7 | 192.168.30.250 |
| c841m | 192.168.30.240 |
| vrrp grp ip | 192.168.30.254 |

```
+----------------------------------------------+
|                                              |
| M/C                                          |
|                                              |
+-- wlan0 --------------------------- eth0 ----+
      |                                |
      |                                |
+-- wlan0 --+                    +--- eth0/5 --+
|           |                    |             |
| centos7   | === Virtual IP === | cisco841m   |
|           | = 192.168.30.254 = |             |
|           | ================== |             |
+-- eth0 ---+                    +--- eth0/0 --+
      |                                | (vlan1)
      | .30.250                        | .30.240
      |                                |
+----------------------------------------------+
|                                              |
| LAN                                          |
| 192.168.30.0/24                              |
|                                              |
+----------------------------------------------+
```

# 3. 事前準備
## 3.1. パッケージのインストール

```bash:centos7
yum install -y keepalived
```

## 3.2. 設定ファイル作成

サンプルは /usr/local/etc/keepalived/keepalived.conf 

```bash:【centos7】/etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
}

vrrp_instance VI_30 {
    state BACKUP
    interface eth0
    virtual_router_id 30
    priority 90
    preempt
    preempt_delay 3
    advert_int 3
    virtual_ipaddress {
        192.168.30.254/24
    }
    track_interface {
        wlan0 weight 15
    }
}
```

- `state BACKUP` サービス起動時や再起動した際に、まず MASTER として動作するのか SLAVE として動作するのかを指定する
- `interface eth0` VRRP 有効化するI/F
- `virtual_router_id` VRRP Group ID
- `priority 90` プライオリティ。高いほうが最終的に MASTER になる。普通は 100 前後。track 監視する場合は `priority + track_weight` の値になる。← 105
- `preempt` preempt の有効化
- `preempt_delay 3` preempt の有効化遅延。← 多分 3s
- `advert_int 3` advertise timer は 同じのVRRPグループ内で 共通 にする。← 3s
- `virtual_ipaddress{}` vrrp virtual ip。なぜ複数かけそうなのかはわからない。多分 /24 略すと /32 になるんじゃないかな と思ったけど [REDHAT のページ](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/load_balancer_administration/ch-initial-setup-vsa#s2-initial-setup-conf-file-VSA) 見たら /24 書いてなかった
- `track_interface{}` `{I/F名} weight {数字}` の書式でいれる。ここで指定した I/F が up/up ではないとき priority の値が変わる

```bash:cisco841m
conf t
!
interface vlan 1
vrrp 30 ip 192.168.30.254 ! ← grp 30 の値はルータ内部であっていれば 1~255 内ならなんでも良い
vrrp 30 priority 100 ! ← Default priority 100
vrrp 30 timers advertise 3 ! ← advertise timer は 同じのVRRPグループ内で 共通 にする
vrrp 30 preempt delay minimum 10 ! ← preempt を設定して MASTER がダウンした際 自動で SLAVE -> MASTER になるように
vrrp 30 track 30 decrement 15 ! ← Gi0/5 を監視して 落ちたら自動でプライオリティを下げる(SLAVEになろうとする)
!
track 30 interface GigabitEthernet0/5 line-protocol
 delay up 30
!
```

## 3.3. 設定ファイル検証

```bash:centos7
# typo バージョン
# state BACKUP を state MasTer に変えてみた
[~]$ keepalived --config-test
(Line 7) (VI_30) unknown state 'MasTer', defaulting to BACKUP
[~]$

# 問題なし バージョン
[~]$ keepalived --config-test
[~]$
```

- `keepalived --config-test` で何も出てこなければOK
- 問題や typo があれば 親切に教えてくれる。そしてデフォルトがあるものはデフォルトになるっぽい

```bash:cisco841m
(config-if)#vrrp 30 praioriti 90
                      ^
% Invalid input detected at '^' marker.

(config-if)#
```

- Cisco 機器の場合は typo はスグ教えてくれる。

## 3.4. ルーティング有効化

```bash:centos7
[~]$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
[~]$ cat /etc/sysctl.d/99-sysctl.conf
# sysctl settings are defined through files in
# /usr/lib/sysctl.d/, /run/sysctl.d/, and /etc/sysctl.d/.
#
# Vendors settings live in /usr/lib/sysctl.d/.
# To override a whole file, create a new file with the same in
# /etc/sysctl.d/ and put new settings there. To override
# only specific settings, add a file with a lexically later
# name in /etc/sysctl.d/ and put new settings there.
#
# For more information, see sysctl.conf(5) and sysctl.d(5).
#
[~]$
[~]$ sudo sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
[~]$ sudo echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.d/99-sysctl.conf
[~]$ cat /etc/sysctl.d/99-sysctl.conf
# sysctl settings are defined through files in
# /usr/lib/sysctl.d/, /run/sysctl.d/, and /etc/sysctl.d/.
#
# Vendors settings live in /usr/lib/sysctl.d/.
# To override a whole file, create a new file with the same in
# /etc/sysctl.d/ and put new settings there. To override
# only specific settings, add a file with a lexically later
# name in /etc/sysctl.d/ and put new settings there.
#
# For more information, see sysctl.conf(5) and sysctl.d(5).
#
net.ipv4.ip_forward=1
[~]$
```

- sysctl だけでは サーバ再起動後に設定が消えるので /etc/sysctl.d/*.conf にも追記する

## 3.5. ファイアウォール設定

### firewall-cmd

```bash:centos7
[~]$ sudo firewall-cmd --permanent --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

[~]$ sudo firewall-cmd --permanent --add-masquerade
success
[~]$ sudo firewall-cmd --permanent --add-protocol=vrrp
success
[~]$ sudo firewall-cmd --reload
success
[~]$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0 wlan0
  sources:
  services: dhcpv6-client ssh 
  ports: 
  protocols: vrrp
  masquerade: yes
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

[~]$
```

- `sudo firewall-cmd --permanent --list-all` 恒久設定(保存されている)の F/W の設定を確認する
- `sudo firewall-cmd --permanent --add-masquerade` NAPT 有効化 → 恒久設定
- `sudo firewall-cmd --permanent --add-protocol=vrrp` VRRPパケットの送受信を許可 → 恒久設定
- `sudo firewall-cmd --reload` F/W のpolicy を再読み込みし、恒久設定 を 現在の設定に置き換える
- `sudo firewall-cmd --list-all` 現在の F/W の設定を確認する

### selinux

- [SELinux とは - 仕組み、使い方、エラーへの対処 | Red Hat](https://www.redhat.com/ja/topics/linux/what-is-selinux)
- [5.4. SELinux の有効化および無効化 Red Hat Enterprise Linux 6 | Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/security-enhanced_linux/sect-security-enhanced_linux-working_with_selinux-enabling_and_disabling_selinux)

> SELinux (Security-Enhanced Linux) とは、システムにアクセス可能なユーザーをより詳細に制御できるようにする、Linux® システム 用のセキュリティ・アーキテクチャです。
SELinux は、システム上のアプリケーション、プロセス、ファイルのアクセス制御を定義します。アクセス制御にはセキュリティポリシーを使用します。セキュリティポリシーは一連のルールで構成されており、アクセス可能なものとそうでないものを SELinux が識別できるようにします。

- [【ざっくりと理解する】SELinuxとは？ | エンジニアの入り口](https://eng-entrance.com/linux-selinux)

> アクセス制御に使う
SELinuxを利用すると細かいアクセス制御が可能になる。例えば、サービス毎に最小限の権限を与え管理することなどが可能になる。
root権限ですら制限をかけることも可能となっており、redhat系のディストリビューションであるCentOSやFedoraの場合はデフォルトで導入されているシステムだ。



```bash:centos7
[~]$ getenforce
Enforcing
[~]$ sudo setenforce Permissive
[~]$ getenforce
Permissive
[~]$ sudo sed -ie "s/SELINUX=enforcing/SELINUX=permissive/i" /etc/selinux/config
```

- `getenforce` SELinuxの状態の確認
    - enforcing ... SELinux 有効でありアクセス制御が有効となる
    - permissive ... アクセス制御は無効だが警告メッセージを表示する
    - disabled ... SELinux 無効

- `sudo setenforce Permissive` SELinuxの状態を permissive にする
- `sudo sed -ie "expression" file` 再起動後も設定を保持するよう 設定ファイルの変更

# 4. 動作確認
## centos7

```bash:centos7
[~]$ sudo systemctl enable keepalived
Created symlink from /etc/systemd/system/multi-user.target.wants/keepalived.service to /usr/lib/systemd/system/keepalived.service.
[~]$ sudo systemctl start keepalived
[~]$
```

- systemctl enable → systemctl start して起動させる
- 既に起動してしまっている場合は systemctl enable → systemctl restart
- 起動しているかどうかは `journalctl -xf -u keepalived` 叩けばわからなくもない(↓再起動のログ)

```bash:centos7
[~]$ journalctl -xe -u keepalived
-- Logs begin at Sun 2020-07-19 09:55:08 JST. --
Jul 23 07:18:33 prod01.local systemd[1]: Started LVS and VRRP High Availability Monitor.
-- Subject: Unit keepalived.service has finished start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit keepalived.service has finished starting up.
--
-- The start-up result is done.
Jul 23 07:18:33 prod01.local Keepalived_vrrp[7209]: Registering Kernel netlink command channel
Jul 23 07:18:33 prod01.local Keepalived_vrrp[7209]: Opening file '/etc/keepalived/keepalived.conf'.
Jul 23 07:18:33 prod01.local Keepalived_vrrp[7209]: Assigned address 192.168.30.250 for interface eth0
Jul 23 07:18:33 prod01.local Keepalived_vrrp[7209]: Assigned address fe80::250:30:168:192 for interface eth0
Jul 23 07:18:33 prod01.local Keepalived_vrrp[7209]: (VI_30) Changing effective priority from 90 to 105
Jul 23 07:18:33 prod01.local Keepalived_vrrp[7209]: Registering gratuitous ARP shared channel
Jul 23 07:18:33 prod01.local Keepalived_vrrp[7209]: (VI_30) removing VIPs.
Jul 23 07:18:33 prod01.local Keepalived_vrrp[7209]: (VI_30) Entering BACKUP STATE (init)
Jul 23 07:18:33 prod01.local Keepalived_vrrp[7209]: VRRP sockpool: [ifindex(2), family(IPv4), proto(112), unicast(0), fd(11,12)]
Jul 23 07:18:36 prod01.local Keepalived_vrrp[7209]: (VI_30) start preempt delay (3.000000)



Jul 23 07:18:41 prod01.local Keepalived_vrrp[7209]: (VI_30) received lower priority (100) advert from 192.168.30.240 - discarding
Jul 23 07:18:48 prod01.local Keepalived_vrrp[7209]: (VI_30) Receive advertisement timeout
Jul 23 07:18:48 prod01.local Keepalived_vrrp[7209]: (VI_30) Entering MASTER STATE
Jul 23 07:18:48 prod01.local Keepalived_vrrp[7209]: (VI_30) setting VIPs.
Jul 23 07:18:48 prod01.local Keepalived_vrrp[7209]: Sending gratuitous ARP on eth0 for 192.168.30.254
Jul 23 07:18:48 prod01.local Keepalived_vrrp[7209]: (VI_30) Sending/queueing gratuitous ARPs on eth0 for 192.168.30.254
Jul 23 07:18:48 prod01.local Keepalived_vrrp[7209]: Sending gratuitous ARP on eth0 for 192.168.30.254
Jul 23 07:18:53 prod01.local Keepalived_vrrp[7209]: (VI_30) Sending/queueing gratuitous ARPs on eth0 for 192.168.30.254
Jul 23 07:18:53 prod01.local Keepalived_vrrp[7209]: Sending gratuitous ARP on eth0 for 192.168.30.254
```

あとは `ip a` で Secondary addr がアサインされていればいいらしい

```bash:centos7
[~]$ ip a show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 70:85:c2:ff:01:23 brd ff:ff:ff:ff:ff:ff
    inet 192.168.30.250/24 brd 192.168.30.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet 192.168.30.254/24 scope global secondary eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::250:30:168:192/128 scope link noprefixroute
       valid_lft forever preferred_lft forever```
```

## cisco841m

```bash:cisco841m
000179: Jul 23 07:06:20.021 JST: %IP-4-DUPADDR: Duplicate address 192.168.30.254 on Vlan83, sourced by 7085.c2ff.0123
000180: Jul 23 07:06:20.021 JST: %VRRP-6-STATECHANGE: Vl30 Grp 30 state Master -> Backup
```

- centos7 側で サービス起動させるとCiscoルータ側は メッセージが出てくる(terminal monitor しないとでてこない)
- Cisco 側でメッセージが 表示されない場合は ter mon していないか、そもそも設定が間違ってる

- `show logg` でも同じのが出てくるので、まずはログ見てみる
    - `show vrrp all`
    - `show vrrp brief`

```bash:cisco841m
#show vrrp brief
Interface          Grp Pri Time  Own Pre State   Master addr     Group addr
Vl30               30  100 9609       Y  Backup  192.168.30.250  192.168.30.254
```

- 両方とも MASTER になっている場合は 以下が可能性としてある
    - SELinux を Disable もしくは Permissive にしていない。もしくは Enforce で polocy 許可していない
    - firewalld で VRRP Hello packet を許可していない
    - VRRP Hello timer の 相違

他にも理由があるかもしれないが環境と構成とconfigで変わってくるのでこれが原因っていうのは挙げきれない

# 5. 最後に
とりあえず動くっていうものを構築しました。
普段 HSRP（Cisco) ばっか使ってて、Linux でも HSRP 組みたいなぁどうやるんだろうってのをまじで2~3時間悩んでた。
そもそも HSRP ってCisco独自の規格だから標準のやつ探さないかんかったのに。。。

IPTables → Firewalld とか service → systemctl、 chkconfig → systemctl にしたので おそらく centos8 系でも動くんじゃないかな…
そう言えば [centos8 での主な仕様変更の中に Quagga 廃止][notable-changes-to-particular-components_infrastructure-services] って書いてあったなぁ。OSPF の DR としても使ってたからそのまま centos8 にできなくてぴえん :;(∩´﹏`∩);: 🥺



[notable-changes-to-particular-components_infrastructure-services]:https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html-single/considerations_in_adopting_rhel_8/index#notable-changes-to-particular-components_infrastructure-services