笔者的环境中有这样的情况:本单位部署了k8s环境,对外暴露了一个网关地址,相关单位通过这个IP进行调用。
外部对k8s的服务调用一般有几种方式:
- ingress方式:这需要本地建设DNS服务器,而本单位刚好没有;
- EXTERNAL-IP方式:可以虚拟出一个不同的子网地址,但这需要网管在路由器上做一些配置;
- loadbalancer模式,一般在公有云上使用,不适合;
- NodePort方式:把pod的端口映射到node上,供外部访问,这也是我们采用的方式。
但在使用中,开发人员提出这样一种可能:NodePort的调用是采用k8s集群中任意一个node+映射端口号的方式,如果pod没有落在这台node上,它可以把请求转发出去;但如果提供的这个node刚好宕机/相关k8s服务宕机/网卡宕机的情况下,这个请求就没办法转发到了,这就造成这个服务实际可用时但外部却无法调用的情况。
所以这时候我们采用了nginx+keepalive的方法来实现nodeport的高可用。具体原理是:使用keepalive虚拟出VIP,再用nginx配置ip池,通过nginx来管理ip地址,实现高可用。以下为配置过程。
我们把这两个服务安装在k8s的node1/2上。
安装配置nginx反向代理
# node0/1两台机都要做(先自行下载nginx安装包)
$ rpm -ivh nginx-1.18.0-1.el7.ngx.x86_64.rpm
# 以Eureka服务为例,它映射到了宿主机的30211端口
$ kc get svc -n dc-test-ns
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
......
dc-service-support-eureka NodePort 10.96.51.210 192.168.66.201 31211:30211/TCP 132
$ vi /etc/nginx/nginx.conf # 内容如下:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
upstream gateway_pools { # ip池,把k8s所有的机器都配上
server 192.168.53.121:30211;
server 192.168.53.122:30211;
server 192.168.53.123:30211;
server 192.168.53.124:30211;
server 192.168.53.125:30211;
server 192.168.53.126:30211;
}
server {
listen 8080; # 这里要注意不要和已启动的端口冲突
location / {
proxy_pass http://gateway_pools;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
access_log logs/access_www.log main;
}
}
$ systemctl enable nginx && service nginx start
安装配置keepalived服务
$ yum install -y keepalived.x86_64
$ vi /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id k8s
}
vrrp_script chk_nginx
{
script "/etc/keepalived/nginx_check.sh" #监控脚本
interval 2 # 2秒一次
weight -20 # keepalived部署了两台所以设为20,如果三台就设为30
}
vrrp_instance VI_1 {
state BACKUP # 两台主机都设为backup非抢占模式
interface ens33 # 网卡接口,可用ip a 命令查看
virtual_router_id 33 # virtual_router_id不要与本网段中已有的冲突
priority 100
advert_int 1 # VRRP Multicast广播周期秒数
nopreempt # 设置为非抢占模式必须要该参数
authentication {
auth_type PASS # VRRP认证方式,主备必须一致
auth_pass xxxx
}
track_script {
chk_nginx
}
virtual_ipaddress {
192.168.53.120/32 # HA虚拟地址,子掩一定要用32位,因为有外网要访问
}
}
$ mkdir -p /etc/nginx/logs
$ systemctl enable keepalived && service keepalived start
# node1上跟上机一样配置,但要修改router_id、priority!
# nginx检查脚本
$ cat /etc/keepalived/nginx_check.sh
#!/bin/bash
stat=` ps aux |grep -v grep|grep /usr/sbin/nginx |wc -l`
if [ $stat -eq 0 ];then
systemctl restart nginx
sleep 3
if [ ` ps aux |grep -v grep|grep /usr/sbin/nginx |wc -l` -eq 0 ];then
systemctl stop keepalived
fi
fi
$ chmod +x /etc/keepalived/nginx_check.sh
现在VIP与反向代理都配好了,可以直接访问 http://你的VIP:8080/
网友评论