THÔNG TIN
- Mục tiêu: Thực hiện thay đổi Public IP mà không gây downtime cho dịch vụ.
-
Hiện trạng:
-
Server CDN201 đang sử dụng IP
10.237.7.201và VIP10.237.7.203. - Server CDN202 đang sử dụng IP
10.237.7.202. -
Trạng thái sau thay đổi:
-
Server CDN201 sẽ chuyển sang IP
10.237.8.201và VIP10.237.8.203. - Server CDN202 sẽ chuyển sang IP
10.237.8.202. - VIP được quản lý bằng Keepalived.
- Domain hiện tại đang trỏ về VIP cũ
10.237.7.203. Sau khi chuyển đổi hoàn tất, domain sẽ được cập nhật trỏ về VIP mới10.237.8.203mà không làm gián đoạn dịch vụ. - Lý do: Hệ thống phải đón request liên tục, nên việc thay đổi IP cần được thực hiện theo quy trình đảm bảo không gây rớt gói, không downtime.
PRE-CHANGE`
Review cấu hình netplan trước khi change CDN201
cat > /etc/netplan/50-cloud-init.yaml << 'OEF'
network:
version: 2
ethernets:
eth0:
dhcp4: no
vlans:
eth0.101:
id: 101
link: eth0
addresses: [10.237.7.201/24]
routes:
- to: 0.0.0.0/0
via: 10.237.7.254
nameservers:
addresses: [8.8.8.8, 1.1.1.1]
OEF
Review cấu hình netplan trước khi change CDN202
cat > /etc/netplan/50-cloud-init.yaml << 'OEF'
network:
version: 2
ethernets:
eth0:
dhcp4: no
vlans:
eth0.101:
id: 101
link: eth0
addresses: [10.237.7.202/24]
routes:
- to: 0.0.0.0/0
via: 10.237.7.254
nameservers:
addresses: [8.8.8.8, 1.1.1.1]
OEF
Review cấu hình Keepalived trước khi change CDN201
cat > /etc/keepalived/keepalived.conf << 'OEF'
vrrp_instance INT {
state MASTER
interface eth0.101
virtual_router_id 11
priority 50
advert_int 5
unicast_src_ip 10.237.7.201
unicast_peer {
10.237.7.202
}
authentication {
auth_type PASS
auth_pass xAR8WZcp6wsUoKe
}
virtual_ipaddress {
10.237.7.203/24 dev eth0.101
}
garp_master_delay 1
}
OEF
Review cấu hình Keepalived trước khi change CDN202
cat > /etc/keepalived/keepalived.conf << 'OEF'
vrrp_instance INT {
state MASTER
interface eth0.101
virtual_router_id 11
priority 50
advert_int 5
unicast_src_ip 10.237.7.202
unicast_peer {
10.237.7.201
}
authentication {
auth_type PASS
auth_pass xAR8WZcp6wsUoKe
}
virtual_ipaddress {
10.237.7.203/24 dev eth0.101
}
garp_master_delay 1
}
OEF
Review thông tin ip CDN201, Lưu ý: node này đang nắm VIP 10.237.7.203.
root@CDN201:~# ip -br addr show
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP fe80::906f:1aff:fe48:e97f/64
ens19 DOWN
eth0.101@eth0 UP 10.237.7.201/24 10.237.7.203/24 fe80::906f:1aff:fe48:e97f/64
Review thông tin ip CDN202.
root@CDN202:~# ip -br addr show
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP fe80::6ce7:b9ff:fe1b:d478/64
ens19 DOWN
eth0.101@eth0 UP 10.237.7.202/24 fe80::6ce7:b9ff:fe1b:d478/64
Setup môi trường để test
apt update
apt install -y keepalived nginx net-tools
cat > /etc/nginx/conf.d/site.conf << 'OEF'
server {
listen 8099;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
charset utf-8;
}
server {
listen 80;
server_name _;
proxy_redirect off;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering on;
proxy_connect_timeout 3600s;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
send_timeout 3600s;
client_max_body_size 10m;
proxy_set_header X-Forwarded-Proto $scheme;
add_header Content-Security-Policy upgrade-insecure-requests;
proxy_pass http://127.0.0.1:8099;
}
}
OEF
cat > /etc/nginx/nginx.conf << 'OEF'
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
include /etc/nginx/conf.d/*.conf;
}
OEF
mkdir -p /var/www/html
echo "Webcome to webserver $(hostname)" > /var/www/html/index.html
nginx -t
nginx -s reload
TURNING (IMPORTAN)
Một số tham số sysctl cần bổ sung:
1. rp_filter
Tham số: net.ipv4.conf.*.rp_filter
- Đây là Reverse Path Filtering (lọc theo đường đi ngược). Kernel sẽ kiểm tra xem gói tin vào có thể route ngược trở lại theo cùng interface hay không.
-
Giá trị:
-
0= không lọc gì cả → gói vào interface nào cũng được, đi ra interface nào cũng không quan tâm, cho đi hết. 1= strict mode: gói vào interface nào thì kernel bắt buộc phải tính toán rằng nếu đi ngược lại thì cũng phải ra đúng interface đó.-
2= loose mode: chỉ cần hệ thống biết đường đi ngược lại, còn gói có vào interface nào cũng OK, không drop. -
Khuyến nghị nên dùng 2 (loose), vì:
-
Đảm bảo traffic hợp lệ không bị drop nhầm khi bạn chạy song song 2 subnet.
- Vẫn giữ được lớp lọc cơ bản, an toàn hơn 0.
- Đây cũng là best practice thường thấy khi triển khai Keepalived, VIP, hoặc routing phức tạp.
| Mode | Check source ngược? | Bắt buộc interface khớp? | Rủi ro spoofing | Ứng dụng |
|---|---|---|---|---|
0 |
❌ Không | ❌ Không | Cao nhất | Lab, routing rất phức tạp |
1 |
✅ Có | ✅ Bắt buộc | Thấp nhất | Single NIC/subnet, bảo mật cao |
2 |
✅ Có | ❌ Không | Trung bình | Multi-NIC, VIP, PBR (best practice) |
- Nếu chỉ test lab nội bộ, không quan ngại spoofing/ISP strict → để 0 và không dùng table 100 có thể “ổn” hơn, vì nhanh gọn, ít cấu hình.
- Nếu làm production, public service, có Keepalived VIP → nên đi theo hướng rp_filter=2 + policy routing (table 100). Đây mới là ổn định & an toàn lâu dài.
Xem giá trị toàn cục và mặc định cho interface mới
shell> sysctl net.ipv4.conf.all.rp_filter
net.ipv4.conf.all.rp_filter = 2
shell> sysctl net.ipv4.conf.default.rp_filter
net.ipv4.conf.default.rp_filter = 2
Xem giá trị cho interface cụ thể
shell> sysctl net.ipv4.conf.ens160.rp_filter
net.ipv4.conf.ens160.rp_filter = 2
2. arp_ignore
Tham số: net.ipv4.conf.*.arp_ignore xử lý khi trả lời ARP request.
Tức là khi ai đó hỏi: “MAC của IP X là gì?” Kernel quyết định có trả lời hay không và interface nào trả lời → giúp tránh interface này “trả lời hộ” IP của interface khác.
-
arp_ignore=0(mặc định) -
Bất kỳ IP nào gắn trên server đều có thể trả lời ARP, dù request đến từ interface khác.
-
Dẫn đến ARP flux: client học nhầm MAC → gói tin sau đó đi sai NIC.
-
arp_ignore=1 -
Chỉ interface đúng subnet/IP đó mới trả lời.
- Client hỏi IP nào thì chỉ IP đó (trên đúng NIC) trả lời.
-
Nhờ vậy MAC học được luôn khớp với NIC thực tế, gói tin đi đúng đường.
-
Ví dụ ở môi trường có VIP
10.237.8.203chạy bằng Keepalived: -
Khi VIP nhảy sang node khác, node cũ không được phép trả lời ARP cho IP này nữa.
- Nếu để
arp_ignore=0, node cũ đôi khi vẫn trả lời ARP nhầm (do vẫn có IP trong cấu hình hoặc cache) → client tiếp tục gửi gói sai node → mất kết nối. - Với
arp_ignore=1, node chỉ trả lời ARP nếu VIP thực sự đang gắn trên interface → đảm bảo failover VIP sạch sẽ.
3. arp_announce
Tham số: net.ipv4.conf.*.arp_announce xử lý khi server chủ động gửi ARP (announce), tức là Kernel gửi broadcast ARP chủ động (gratuitous ARP hoặc ARP probe khi thiết lập kết nối).
-
0(mặc định) -
Kernel có thể gửi ARP request/announce với bất kỳ địa chỉ source nào thuộc IP local (không nhất thiết là IP thuộc subnet của interface đó).
- → Dễ dẫn tới tình huống client/switch thấy ARP “lạ” (IP source không thuộc subnet) và có thể drop hoặc học sai MAC.
-
1(cẩn thận hơn một chút) -
Kernel sẽ cố gắng dùng IP gắn trên interface đó để gửi ARP.
- Tuy nhiên, nếu không có IP nào khớp subnet, nó vẫn có thể chọn IP khác.
- → Giảm ARP sai, nhưng chưa tuyệt đối.
-
2(strict – best practice trong multi-homed host, VIP) -
Kernel sẽ chỉ chọn IP thuộc subnet phù hợp nhất với interface đó để làm source ARP.
- Nếu không tìm thấy IP thuộc subnet, nó sẽ không bạ đâu xài đó.
- → Tránh hoàn toàn việc gửi ARP sai subnet.
-
Trong môi trường có Keepalived / VIP
-
Khi VIP 10.237.8.203 mới gắn vào eth0.100, kernel sẽ phát gratuitous ARP để quảng bá VIP này.
- Nếu arp_announce=0: có thể gratuitous ARP bị gửi với source IP khác VIP, gây nhầm lẫn ở client/L2 switch.
- Nếu arp_announce=2: luôn dùng đúng VIP/subnet khi announce → client học chính xác IP–MAC của VIP → failover mượt mà.
4. Vì sao phải cấu hình cho all, eth0.100, eth0.101?
all= giá trị áp dụng chung cho tất cả interface (nhưng đôi khi không override interface cụ thể).- Khai báo thêm cho từng sub-interface VLAN (
eth0.100,eth0.101) để chắc chắn rule áp dụng đúng.
Dưới đây là combo cấu hình khuyên dùng khi thực hiện change và kể cả trong môi trường Keepalived / VIP.
cat > /etc/sysctl.d/99-nodowntime.conf << 'EOF'
net.ipv4.conf.all.rp_filter=2
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net/ipv4/conf/eth0.100/rp_filter=2
net/ipv4/conf/eth0.100/arp_ignore=1
net/ipv4/conf/eth0.100/arp_announce=2
net/ipv4/conf/eth0.101/rp_filter=2
net/ipv4/conf/eth0.101/arp_ignore=1
net/ipv4/conf/eth0.101/arp_announce=2
EOF
Áp dụng config mới
sysctl --system
Trường hợp có **1 interface duy nhất có nên áp dụng 3 tùy chọn trên không.
- Trường hợp có 1 interface duy nhất:
eth0.101 -
Trên đó gắn 2 IP, mỗi IP thuộc 2 subnet khác nhau, ví dụ:
-
10.237.7.201/24 10.237.8.201/24
1. rp_filter=2
- Vẫn có tác dụng.
-
Nếu có gói đi vào interface này với source từ subnet “lạ”, kernel sẽ kiểm tra route ngược:
-
Nếu tồn tại route ngược (dù đi qua chính interface đó) → gói được chấp nhận.
- Nếu không tồn tại route ngược → drop.
- Trường hợp 1 interface nhiều IP thì nguy cơ asymmetric routing vẫn có (vì mỗi IP thuộc subnet khác nhau). → Nên để
2thay vì1để tránh drop oan.
2. arp_ignore=1
-
Vẫn có tác dụng, nhưng khác một chút:
-
Khi có ARP request trong subnet
10.237.7.0/24hỏi “ai có 10.237.8.201?”, interface sẽ không trả lời. - Ngược lại, nếu subnet
10.237.8.0/24hỏi về10.237.7.201→ cũng không trả lời. - Nhờ đó, tránh việc 1 IP trên cùng interface “trả lời hộ” IP của subnet khác.
- Rất quan trọng khi bạn gắn 2 subnet trên cùng 1 NIC.
3. arp_announce=2
- Vẫn có tác dụng.
- Khi kernel gửi ARP request/announce ra
eth0.101: - Nếu nó cần liên lạc với một host trong subnet
10.237.8.0/24, source ARP sẽ bắt buộc là10.237.8.201. - Nếu nó cần liên lạc với subnet
10.237.7.0/24, source ARP sẽ là10.237.7.201. - Như vậy không có chuyện ARP broadcast với source “sai subnet”.
IN-CHANGE
Bước 1 - Thêm tạm IP mới bằng command để tránh downtime
- Trên Server
CDN201
Tạo mới sub-interface VLAN 100 (vlan của ip mới)
ip link add link eth0 name eth0.100 type vlan id 100
ip link set dev eth0.100 up
Thêm IP mới vào sub-interface vừa tạo
ip addr add 10.237.8.201/24 dev eth0.100
Check lại đã có IP mới
root@CDN201:~# ip -br addr show
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP fe80::906f:1aff:fe48:e97f/64
ens19 DOWN
eth0.101@eth0 UP 10.237.7.201/24 10.237.7.203/24 fe80::906f:1aff:fe48:e97f/64
eth0.100@eth0 UP 10.237.8.201/24 fe80::906f:1aff:fe48:e97f/64
- Trên Server
CDN202
Tạo mới sub-interface VLAN 100 (vlan của ip mới)
ip link add link eth0 name eth0.100 type vlan id 100
ip link set dev eth0.100 up
Thêm IP mới vào sub-interface vừa tạo
ip addr add 10.237.8.202/24 dev eth0.100
Check lại đã có IP mới
root@CDN202:~# ip -br addr show
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP fe80::6ce7:b9ff:fe1b:d478/64
ens19 DOWN
eth0.101@eth0 UP 10.237.7.202/24 fe80::6ce7:b9ff:fe1b:d478/64
eth0.100@eth0 UP 10.237.8.202/24 fe80::6ce7:b9ff:fe1b:d478/64
Kết quả của bước này:
- Outbound: có thể đi internet được, vì router 101 vẫn chấp nhận source không thuộc đi ra gateway của nó, nhưng có thể bị chặn ở ngoài ISP vì có thể thiếu route.
- Inbound (client ngoài connect vào): không chắc chắn đi được, trừ khi hạ tầng router/ISP đã định tuyến đúng subnet 10.237.8.0/24 về interface VLAN100.
- Nếu khi có inbound, để đảm bảo reply đi đúng đường ra 10.237.8.254, cần policy-based routing, cấu hình tiếp ở bước 2.
Buóc 2 - Thêm default route kèm theo metric
Nếu bây giờ trỏ DNS từ VIP cũ sang VIP mới, vấn đề bây giờ DNS khách nào còn cache A-record cũ sẽ vẫn vào VIP cũ, khách đã cập nhật vào VIP mới thì sẽ đi vào VIP mới.
Lúc này để tránh gián đoạn khi endpoint gửi gói tin response cho client thì PBR sẽ đảm bảo đường về của mỗi kết nối đi đúng gateway theo VIP mà nó đi vào.
Cụ thể khi 2 luồng cùng tồn tại nó sẽ như sau:
Client còn cache → vào VIP cũ 10.237.7.203 → Kernel trả lời với source 10.237.7.254 và nếu giữ default main = 10.237.7.254, nó sẽ đi đúng GW 10.237.7.254.
Client đã cập nhật record → vào VIP mới 10.237.8.203 → Nhờ rule from 10.237.8.0/24 thuộc table 100 đã thêm, reply sẽ đi ra GW 10.237.8.254.
=> Hai luồng song song OK, PBR sẽ là để đảm bảo phần này không bị đi lộn gateway khi client request vào VIP mới.
- Trên Server
CDN201
Review metric gateway cũ là gì (không gán mặc định là 0)
root@CDN201:~# ip route show
default via 10.237.7.254 dev eth0.101 proto static
10.237.8.0/24 dev eth0.100 proto kernel scope link src 10.237.8.201
10.237.7.0/24 dev eth0.101 proto kernel scope link src 10.237.7.201
Thêm route với metric 100
ip route add default via 10.237.8.254 dev eth0.100 metric 100
Check lại default route mới được thêm vào có gắn metric 100. Traffic inbound client → VIP cũ lúc này vẫn ổn định, vì gói vào bằng subnet cũ thì reply vẫn đi ra GW cũ do metric thấp.
root@CDN201:~# ip route show
default via 10.237.7.254 dev eth0.101 proto static
default via 10.237.8.254 dev eth0.100 metric 100
10.237.8.0/24 dev eth0.100 proto kernel scope link src 10.237.8.201
10.237.7.0/24 dev eth0.101 proto kernel scope link src 10.237.7.201
- Trên Server
CDN202
Review metric gateway cũ là gì (không gán mặc định là 0)
root@CDN202:~# ip route show
default via 10.237.7.254 dev eth0.101 proto static
10.237.8.0/24 dev eth0.100 proto kernel scope link src 10.237.8.202
10.237.7.0/24 dev eth0.101 proto kernel scope link src 10.237.7.202
Thêm route với metric 100
ip route add default via 10.237.8.254 dev eth0.100 metric 100
Check lại default route mới được thêm vào có gắn metric 100.
root@CDN202:~# ip route show
default via 10.237.7.254 dev eth0.101 proto static
default via 10.237.8.254 dev eth0.100 metric 100
10.237.8.0/24 dev eth0.100 proto kernel scope link src 10.237.8.202
10.237.7.0/24 dev eth0.101 proto kernel scope link src 10.237.7.202
Traffic inbound client → VIP cũ lúc này vẫn ổn định, vì gói vào bằng subnet cũ thì reply vẫn đi ra GW cũ do metric thấp.
Tạo bảng định tuyến riêng, ví dụ table 100
Đầu tiên tạo bảng định tuyến nội bộ subnet 10.237.8.0/24 trong table 100
ip route add 10.237.8.0/24 dev eth0.100 scope link table 100
Set default cho bảng 100 đi qua GW mới
ip route add default via 10.237.8.254 dev eth0.100 table 100
Thêm rule sau sẽ giúp các request có source 10.237.8.0/24 dùng table 100
ip rule add from 10.237.8.0/24 table 100 priority 100
- Lúc này:
- Traffic vào VIP mới có địa chỉ 10.237.8.203/24 sẽ reply ra đúng 10.237.8.254.
- Tất cả lưu lượng khác vẫn dùng default cũ do có metric thấp hơn.
Bước 3 - Verify kết quả 2 bước trên
Kết quả cho server CDN201
Rule from 10.237.8.0/24 lookup 100 sẽ đảm bảo mọi gói có source 10.237.8.x dùng bảng route 100.
root@CDN201:~# ip rule
0: from all lookup local
100: from 10.237.8.0/24 lookup 100
32766: from all lookup main
32767: from all lookup default
Table 100 define default GW là 10.237.8.254, nên gói từ 10.237.8.201 sẽ đi ra đúng gateway này.
root@CDN201:~# ip route show table 100
default via 10.237.8.254 dev eth0.100
10.237.8.0/24 dev eth0.100 scope link
Kết quả dưới xác nhận dest 8.8.8.8 từ source 10.237.8.201 sẽ đi next-hop 10.237.8.254 qua eth0.100.
root@CDN201:~# ip route get 8.8.8.8 from 10.237.8.201
8.8.8.8 from 10.237.8.201 via 10.237.8.254 dev eth0.100 table 100 uid 0
cache
Traceroute hop 1 là 10.237.8.254 đã chứng minh traffic đi đúng gateway 100.
root@CDN201:~# traceroute -I -s 10.237.8.201 1.1.1.1
traceroute to 1.1.1.1 (1.1.1.1), 30 hops max, 60 byte packets
1 _gateway (10.237.8.254) 3.676 ms 3.851 ms 4.134 ms
2 10.56.123.1 (10.56.123.1) 2.476 ms 2.470 ms 2.468 ms
3 static.vnpt.vn (123.29.12.172) 3.499 ms * *
4 static.vnpt.vn (113.171.44.133) 3.820 ms * *
5 * * *
6 * * *
7 * * static.vnpt.vn (113.171.37.231) 29.463 ms
8 * * *
9 103.22.203.73 (103.22.203.73) 28.143 ms * *
10 one.one.one.one (1.1.1.1) 27.768 ms 27.797 ms 27.184 ms
Ping -I 10.237.8.201 tới 1.1.1.1 thành công, RTT thấp (~27 ms) → đường mạng qua gateway mới hoàn toàn hoạt động.
root@CDN201:~# ping -c 4 -I 10.237.8.201 1.1.1.1
PING 1.1.1.1 (1.1.1.1) from 10.237.8.201 : 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=58 time=27.4 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=58 time=27.3 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=58 time=27.1 ms
64 bytes from 1.1.1.1: icmp_seq=4 ttl=58 time=27.1 ms
--- 1.1.1.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 27.052/27.217/27.418/0.156 ms
Kết quả tương tự cho server CDN202
root@CDN202:~# ip rule
0: from all lookup local
100: from 10.237.8.0/24 lookup 100
32766: from all lookup main
32767: from all lookup default
root@CDN202:~# ip route show table 100
default via 10.237.8.254 dev eth0.100
10.237.8.0/24 dev eth0.100 scope link
root@CDN202:~# ip route get 8.8.8.8 from 10.237.8.202
8.8.8.8 from 10.237.8.202 via 10.237.8.254 dev eth0.100 table 100 uid 0
cache
root@CDN202:~# traceroute -I -s 10.237.8.202 1.1.1.1
traceroute to 1.1.1.1 (1.1.1.1), 30 hops max, 60 byte packets
1 _gateway (10.237.8.254) 8.419 ms 8.670 ms 8.812 ms
2 10.56.123.1 (10.56.123.1) 3.180 ms 3.178 ms 3.175 ms
3 10.208.231.87 (10.208.231.87) 5.794 ms * *
4 * * 10.208.232.71 (10.208.232.71) 10.367 ms
5 * * *
6 * * *
7 * * *
8 localhost (27.68.250.218) 4.166 ms * *
9 80.81.192.220 (80.81.192.220) 213.185 ms * *
10 * * *
11 * * *
12 * * *
13 91.185.5.253 (91.185.5.253) 245.056 ms * *
14 * gw-as41798.retn.net (87.245.238.51) 237.712 ms 237.036 ms
15 et541.rt1.int.stv.ovl.retn.net (87.245.238.50) 272.970 ms * 258.671 ms
16 ae0-1.sr.lim.waw.pl.retn.net (87.245.232.14) 251.897 ms 251.909 ms 252.104 ms
17 162.158.100.252 (162.158.100.252) 262.552 ms * *
18 162.158.100.23 (162.158.100.23) 234.892 ms 235.639 ms 235.233 ms
19 one.one.one.one (1.1.1.1) 234.341 ms 234.357 ms 233.486 ms
root@CDN202:~# ping -c 4 -I 10.237.8.202 1.1.1.1
PING 1.1.1.1 (1.1.1.1) from 10.237.8.202 : 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=48 time=240 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=48 time=239 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=48 time=240 ms
64 bytes from 1.1.1.1: icmp_seq=4 ttl=52 time=209 ms
--- 1.1.1.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 209.391/232.004/239.730/13.056 ms
Bước 4 - Thêm VIP và thay đổi config Keepalived.
Dùng command để thêm VIP mới 10.237.8.203 trên server hiện tại đang Active để giả lập VIP mới cũng nằm ở trên này.
ip addr add 10.237.8.203/24 dev eth0.100
Sửa file keepalived.conf trên server CDN201 (không restart Keeplalived)
cat > /etc/keepalived/keepalived.conf << 'OEF'
vrrp_instance INT {
state MASTER
interface eth0.100
virtual_router_id 11
priority 50
advert_int 5
unicast_src_ip 10.237.8.201
unicast_peer {
10.237.8.202
}
authentication {
auth_type PASS
auth_pass xAR8WZcp6wsUoKe
}
virtual_ipaddress {
10.237.8.203/24 dev eth0.100
}
garp_master_delay 1
}
OEF
Tương tự trên server CDN202 (không restart Keeplalived)
cat > /etc/keepalived/keepalived.conf << 'OEF'
vrrp_instance INT {
state MASTER
interface eth0.100
virtual_router_id 11
priority 50
advert_int 5
unicast_src_ip 10.237.8.202
unicast_peer {
10.237.8.201
}
authentication {
auth_type PASS
auth_pass xAR8WZcp6wsUoKe
}
virtual_ipaddress {
10.237.8.203/24 dev eth0.100
}
garp_master_delay 1
}
OEF
Bước 5 - Tự trỏ file host vào VIP mới và test.
Bước 6 - Đổi DNS từ VIP cũ sang VIP mới khi chắc chắn bài test ở bước 5 thành công.
- TTL (Time To Live) trong DNS là thời gian (giây) mà client hoặc DNS resolver được phép cache lại bản ghi trước khi phải hỏi lại authoritative DNS server.
Ví dụ:
domain.comcó TTL =621 giây(\~10 phút 21 giây).- Nếu một client lần đầu query lúc 10:00:00, nó sẽ nhận về IP cũ
10.237.7.203và cache lại trong đúng 621 giây. -
Trong khoảng 10:00:00 → 10:10:21, mọi request từ client đó sẽ dùng IP cũ (không cần hỏi lại DNS).
-
Nếu thay đổi record lúc 10:05, thì:
-
Các client đã query trước đó (ví dụ lúc 10:00) vẫn còn cache → tiếp tục dùng IP cũ đến khi TTL hết hạn (10:10:21).
-
Các client query sau khi update record (ví dụ 10:06, lần đầu hỏi) → sẽ nhận ngay IP mới.
-
Điều này nghĩa là:
-
Khoảng thời gian song song tồn tại: có client dùng IP cũ, có client dùng IP mới.
- Không phải ngay khi update DNS thì toàn bộ client lập tức thấy IP mới.
- Nếu client hỏi lúc 10h, đến 10h5 khi update thì nó sẽ còn giữ IP cũ thêm 5 phút 21 giây nữa trước khi phải hỏi lại và lấy IP mới.
→ Vì vậy, trong thực tế để tránh downtime khi đổi IP/VIP:
- Trước khi thực hiện thay đổi này cần giảm TTL xuống mức rất thấp (ví dụ 60 giây hoặc 30 giây) từ vài giờ → 1 ngày trước khi đổi, để đảm bảo client không cache quá lâu.
- Sau khi đổi xong, có thể tăng TTL lên lại để giảm số lượng query DNS.
Bước 7 - Xóa thông tin IP, Route Table của IP cũ.
- Khi chắc chắn không còn request vào VIP cũ thì có thể xoá IP cũ bằng command để không làm rớt gói (làm cả 2 server)
ip link set eth0.101 down
- Đảo default main sang 10.237.8.254 (làm cả 2 server)
ip route add default via 10.237.8.254 dev eth0.100 metric 0
ip route del default via 10.237.8.254 dev eth0.100 metric 100
- Giữ lại rule/table 100 nếu còn chạy song song 2 VIP; nếu chắc chắn chỉ còn VIP mới thì thực ra không cần PBR 100 nữa nên có thể xóa luôn (làm cả 2 server)
ip rule del from 10.237.8.0/24 table 100
ip route flush table 100
Cập nhật Netplan vĩnh viễn (chỉ thay đổi config không apply cấu hình lúc này)
Cấu hình netplan CDN201
cat > /etc/netplan/50-cloud-init.yaml << 'OEF'
network:
version: 2
ethernets:
eth0:
dhcp4: no
vlans:
eth0.100:
id: 100
link: eth0
addresses: [10.237.8.201/24]
routes:
- to: 0.0.0.0/0
via: 10.237.8.254
nameservers:
addresses: [8.8.8.8, 1.1.1.1]
OEF
Cấu hình netplan CDN202
cat > /etc/netplan/50-cloud-init.yaml << 'OEF'
network:
version: 2
ethernets:
eth0:
dhcp4: no
vlans:
eth0.100:
id: 101
link: eth0
addresses: [10.237.8.202/24]
routes:
- to: 0.0.0.0/0
via: 10.237.8.254
nameservers:
addresses: [8.8.8.8, 1.1.1.1]
OEF
ROLLBACK
Xoá default mới
ip route del default via 10.237.8.254 dev eth0.100
Xoá IP mới
ip addr del 10.237.8.201/24 dev eth0.100
ip addr del 10.237.8.202/24 dev eth0.100
Verify
tail -F /var/log/nginx/*.log
ss -ntp | grep '<VIP>'
tcpdump -ni eth0.101 host <OLD_VIP>