소개하다
다음과 같은 부하 분산 구성이 있습니다.
10.0.1.31 - lb
10.0.1.35 - virtual IP
10.0.1.32 - node1 (tomcat + mysql)
10.0.1.33 - node2 (tomcat + mysql)
나는 keepalived
이를 사용하여 패킷을 활성 노드로 리디렉션합니다. 공유 IP 주소는 10.0.1.35입니다. lb에는 구성이 필요합니다.
echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf
들어오는 패킷을 적절하게 처리하려면 node1과 node2가 10.0.1.35를 열어야 합니다.lo
[root@lb-node1 ~]# ip addr list dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet 10.0.1.35/32 scope global lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
질문
lo
로케일 Tomcat이 lb를 통해 mysql에 연결을 시도하는 경우 포트는 10.0.1.35이므로 연결은 로컬 인스턴스에 설정됩니다 .
lo
나가는 패킷을 건너뛰고 싶습니다.
시험
mysql 서비스가 비활성화되고 lo
인터페이스의 ip가 10.0.1.35인 node1에서 node2의 mysql에 연결을 시도합니다. 안타깝게도 결과는
[root@lb-node1 ~]# telnet 10.0.1.35 3306
Trying 10.0.1.35...
telnet: connect to address 10.0.1.35: Connection refused
물론 lo 인터페이스에서 10.0.1.35 IP를 제거하면 node2의 mysql 인스턴스에 연결할 수 있습니다.
해결책(?)
적절한 측정항목을 사용하여 경로를 추가해 보았지만 도움이 되지 않았습니다./
[root@lb-node1 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.1.0 0.0.0.0 255.255.255.255 UH 0 0 0 eth0
10.0.1.0 0.0.0.0 255.255.255.255 UH 100 0 0 lo
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
0.0.0.0 10.0.1.1 0.0.0.0 UG 0 0 0 eth0
@패트릭 솔루션
vip=10.0.1.35
ip route add local $vip dev lo table 10 proto kernel scope host
ip rule add to $vip lookup 10 prio 1
ip route del local $vip dev lo table local
ip rule add to $vip iif lo lookup main prio 0
@Patrick 솔루션 문제
초기 상태
VIP+IP 라우팅 구성, mysql은 두 노드 모두에서 작동합니다.
P Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.0.1.35:http rr persistent 6
TCP 10.0.1.35:mysql rr persistent 6
-> 10.0.1.32:mysql Route 10 0 0
-> 10.0.1.33:mysql Route 10 0 2
UDP 10.0.1.35:snmptrap rr persistent 6
-> 10.0.1.32:snmptrap Route 10 0 0
-> 10.0.1.33:snmptrap Route 10 0 1
root@lb-node1 ~]# mysql -h 10.0.1.35 -u test -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 126
Server version: 5.5.36-MariaDB-wsrep-log MariaDB Server, wsrep_25.9.r3961
Copyright (c) 2000, 2014, Oracle, Monty Program Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> SHOW VARIABLES WHERE Variable_name = 'hostname';
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| hostname | lb-node2 |
+---------------+----------+
1 row in set (0.00 sec)
MariaDB [(none)]>
[root@lb-node2 ~]# mysql -h 10.0.1.35 -u test -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 133
Server version: 5.5.36-MariaDB-wsrep-log MariaDB Server, wsrep_25.9.r3961
Copyright (c) 2000, 2014, Oracle, Monty Program Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
ariaDB [(none)]> ;
ERROR: No query specified
MariaDB [(none)]> SHOW VARIABLES WHERE Variable_name = 'hostname';
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| hostname | lb-node2 |
+---------------+----------+
1 row in set (0.00 sec)
MariaDB [(none)]>
보시다시피 모든 것이 잘 작동합니다.
질문
그러나 현재 활성화된 mysql 서버를 종료하면:
[root@lb-node2 ~]# service mysql stop
Shutting down MySQL.... SUCCESS!
[root@lb-node2 ~]#
Every 2.0s: ipvsadm -l Fri May 9 10:20:49 2014
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.0.1.35:http rr persistent 6
TCP 10.0.1.35:mysql rr persistent 6
-> 10.0.1.32:mysql Route 10 0 0
UDP 10.0.1.35:snmptrap rr persistent 6
-> 10.0.1.32:snmptrap Route 10 0 0
-> 10.0.1.33:snmptrap Route 10 0 1
두 노드에서 mysql에 연결할 수 없습니다
[root@lb-node2 ~]# mysql -h 10.0.1.35 -u test -p
Enter password:
.....
로드 밸런서가 패킷을 올바르게 리디렉션하기 때문에 node1이 들어오는 패킷을 수락하지 않는 것 같습니다.
[root@lb-node1 ~]# tcpdump -i eth0 'port 3306' and src 10.0.1.33 or dst 10.0.1.33
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
10:35:26.915640 ARP, Reply 10.0.1.35 is-at 52:54:00:30:a3:4b (oui Unknown), length 28
10:35:26.915987 IP 10.0.1.33.38517 > 10.0.1.35.mysql: Flags [S], seq 2024730796, win 14600, options [mss 1460,sackOK,TS val 1298907 ecr 0,nop,wscale 7], length 0
10:35:27.914788 IP 10.0.1.33.38517 > 10.0.1.35.mysql: Flags [S], seq 2024730796, win 14600, options [mss 1460,sackOK,TS val 1299907 ecr 0,nop,wscale 7], length 0
10:35:29.914784 IP 10.0.1.33.38517 > 10.0.1.35.mysql: Flags [S], seq 2024730796, win 14600, options [mss 1460,sackOK,TS val 1301907 ecr 0,nop,wscale 7], length 0
VIP 액세스 권한이 아직 있는데 뭐가 이상한가요?
[root@lb-node1 ~]# ip addr list dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet 10.0.1.35/32 scope global lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
[root@lb-node1 ~]# ip route
10.0.1.0/24 dev eth0 proto kernel scope link src 10.0.1.32
169.254.0.0/16 dev eth0 scope link metric 1002
default via 10.0.1.1 dev eth0
답변1
나는 당신이 달성하려는 것과 비슷한 일을 하는 아주 오래된 코드를 찾아냈습니다. 원하는 효과를 얻으려면 다음을 수행할 수 있습니다.
vip=10.0.1.35
ip route add local $vip dev lo table 10 proto kernel scope host
ip rule add to $vip lookup 10 prio 1
ip route del local $vip dev lo table local
ip rule add to $vip iif lo lookup main prio 0
이렇게 하면 상자가 모든 트래픽을 10.0.1.35
네트워크(따라서 해당 IP에 대한 ARP 요청에 응답하는 로드 밸런서)로 전송하게 됩니다. 그러나 상자는 로드 밸런서가 제공하는 모든 트래픽을 계속 허용합니다.
설명하다
더 이해하기 쉽기 때문에 순서대로 설명하겠습니다.
ip route del local $vip dev lo table local
10.0.1.35
이렇게 하면 모든 트래픽을 localhost 로 보내 표시되는 경로가 제거됩니다 lo
.
ip route add local $vip dev lo table 10 proto kernel scope host
그러면 방금 삭제한 테이블이 대체되지만 완전히 새로운 테이블( 10
)에 배치됩니다.
ip rule add to $vip iif lo lookup main prio 0
iif lo
이는 로컬 박스( )에서 트래픽을 보낼 때 10.0.1.35
"로컬" 경로 대신 기본 경로를 사용하도록 시스템에 지시합니다 . 이렇게 하면 10.0.1.35
트래픽이 10.0.1.0/24
서브넷(또는 그렇지 않은 경우 로컬 서브넷 /24
)으로 라우팅됩니다.
ip rule add to $vip lookup 10 prio 1
이 규칙은 나중에 일치하도록 위의 규칙보다 낮은 우선순위(높은 숫자)로 추가됩니다. 트래픽이 위의 규칙과 일치하지 않는 경우(아님 ) 테이블에 일치하는 경로가 있는지 iif lo
확인 하고 이전에 추가한 경로를 선택합니다. 이 규칙(및 우리가 표에 추가한 경로 )의 이유는 로드 밸런서가 이 상자로 전송한(따라서 전송되지 않은 ) 모든 트래픽이 거부되지 않기 때문입니다. 기본적으로 이는 커널에 "예, 이 IP는 내 것입니다"라고 알려줍니다.10
10
iif lo
"로컬" 경로를 테이블로 옮기는 이유 는 규칙이 일치하기를 10
원하기 때문입니다 . iif lo lookup main prio 0
그러나 "로컬" 테이블은 우선순위가 가장 높으므로 항상 먼저 일치합니다.
규칙을 순서대로 추가하는 이유는 방해를 방지하기 위해서입니다. 지침에 표시된 순서대로 추가하면 간격이 생기고 라우팅이 없어 로컬 상자로 전송되는 모든 트래픽이 거부됩니다 10.0.1.35
.10.0.1.35