我们正在尝试构建HA Kubernetese集群,其中包含3个核心节点,每个节点都有完整的重要组件:ETCD + APIServer + Scheduller + ControllerManager和外部平衡器。由于ETCD可以自己创建集群,因此我们可以使用HA APIServers进行堆栈。几周之前看似显而易见的任务现在变成了一场灾难" ......
我们决定使用nginx作为3个独立APIServers的平衡器。我们群集中与APIServer(Kublets,Kube-Proxys,Schedulers,ControllerManagers ..)通信的所有其余部分都假设使用平衡器来访问它。在我们开始破坏"破坏性之前,一切都进展顺利。测试(我称之为),一些pod正在运行。 以下是使用HS拨打的APIServer配置部分:
.. --apiserver-count=3 --endpoint-reconciler-type=lease ..
这是我们的nginx.conf:
user nginx;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_processes auto;
events {
multi_accept on;
use epoll;
worker_connections 4096;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
gzip on;
underscores_in_headers on;
include /etc/nginx/conf.d/*.conf;
}
和apiservers.conf:
upstream apiserver_https {
least_conn;
server core1.sbcloud:6443; # max_fails=3 fail_timeout=3s;
server core2.sbcloud:6443; # max_fails=3 fail_timeout=3s;
server core3.sbcloud:6443; # max_fails=3 fail_timeout=3s;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 6443 ssl so_keepalive=1m:10s:3; # http2;
ssl_certificate "/etc/nginx/certs/server.crt";
ssl_certificate_key "/etc/nginx/certs/server.key";
expires -1;
proxy_cache off;
proxy_buffering off;
proxy_http_version 1.1;
proxy_connect_timeout 3s;
proxy_next_upstream error timeout invalid_header http_502; # non_idempotent # http_500 http_503 http_504;
#proxy_next_upstream_tries 3;
#proxy_next_upstream_timeout 3s;
proxy_send_timeout 30m;
proxy_read_timeout 30m;
reset_timedout_connection on;
location / {
proxy_pass https://apiserver_https;
add_header Cache-Control "no-cache";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header Authorization $http_authorization;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-SSL-CLIENT-CERT $ssl_client_cert;
}
}
经过一些测试后发现,Kubernetes似乎使用单一的长生活联系而不是传统的开放式关闭会议。这可能是SSL的露水。所以我们必须将proxy_send_timeout和proxy_read_timeout增加到荒谬的30m(APIServer的默认值是1800s)。如果此设置低于10米,则所有客户端(如Scheduler和ControllerManager)将因INTERNAL_ERROR流而产生吨数。
因此,对于碰撞测试,我只需将其中一个APIServers轻轻关闭即可。然后我重新启动另一个,所以nginx看到上游关闭并将所有当前连接切换到最后一个。几秒钟后重新启动APIserver返回,我们有2个APIServers工作。然后,我通过运行' systemctl stop network'将网络放在第三个APIServer上。在那台服务器上,所以它没有机会通知Kubernetes或者nginx它已经关闭了。
现在,集群完全坏了! nginx似乎认识到上游已经崩溃,但它不会重置已经死亡的上游已经令人兴奋的连接。我仍然可以用'ss -tnp'来看到它们。如果我重新启动Kubernetes服务,他们将重新连接并继续工作,如果我重新启动nginx也是如此 - 新的套接字将显示在ss输出中。
只有当我通过关闭网络使API服务器不可用(阻止它关闭与nginx的现有连接并通知Kubernetes它正在关闭)时,才会发生这种情况。如果我停止它 - 一切都像魅力一样。但这不是一个真实的案例。服务器可以在没有任何警告的情况下直接关闭 - 只是即时。
我们做错了什么?有没有办法强制nginx删除掉到上游的所有连接?在我们迁移到HAProxy或LVS之前要尝试的任何事情,并且在我们尝试使其平衡而不是破坏我们不那么HA群集的过程中毁掉一周的nginx。