kube-apiserver 高可用之本地 Proxy 方案

kublet、kube-proxy 的配置文件中静态指定了某个 kube-apiserver IP,如果该 apiserver 实例挂掉,可能会引起服务异常。

本文档讲解使用 nginx 4 层透明代理功能实现 K8S 节点访问 kube-apiserver 服务时高可用的方案。

另一种高可用方案是通过 VIP 实现的,参考:06-1.部署高可用组件-keepalived.md

基于 nginx proxy 的 kube-apiserver 高可用架构

nginx-proxy-ha.png

  • 控制节点的 kube-controller-manager、kube-scheduler 是多实例部署,且都访问本地的 kube-apiserver,所以只要有一个控制节点工作正常,就可以保证高可用;
  • 集群内的 Pod 使用域名 kubernetes 访问 kube-apiserver 时也是高可用的:因为 kube-dns 会自动解析出多个 kube-apiserver 节点的 IP。
  • 工作节点上的 kubelet、kube-proxy 通过本地的 kube-nginx (监听 127.0.0.1)访问 kube-apiserver,从而实现 kube-apiserver 的高可用。
  • kube-nginx 会对所有 kube-apiserver 实例做健康检查和负载均衡;

为何要重新编译 nginx ?

官方发布的 nginx 软件包功能完整,但在安装时还需要在线安装依赖的其它软件包。而场内一般没有外网和 YUM 源,所以我们需要重新编译一个最小功能集、最低依赖的 nginx 二进制程序,部署时不需要安装额外软件包。

下载和编译 nginx

下载源码:

  1. cd /opt/k8s/work
  2. wget http://nginx.org/download/nginx-1.15.3.tar.gz
  3. tar -xzvf nginx-1.15.3.tar.gz

配置编译参数:

  1. cd /opt/k8s/work/nginx-1.15.3
  2. mkdir nginx-prefix
  3. ./configure --with-stream --without-http --prefix=$(pwd)/nginx-prefix --without-http_uwsgi_module --without-http_scgi_module --without-http_fastcgi_module
  • --with-stream:开启 4 层透明转发(TCP Proxy)功能;
  • --without-xxx:关闭所有其他功能,这样生成的动态链接二进制程序依赖最小;

输出:

  1. Configuration summary
  2. + PCRE library is not used
  3. + OpenSSL library is not used
  4. + zlib library is not used
  5. nginx path prefix: "/root/tmp/nginx-1.15.3/nginx-prefix"
  6. nginx binary file: "/root/tmp/nginx-1.15.3/nginx-prefix/sbin/nginx"
  7. nginx modules path: "/root/tmp/nginx-1.15.3/nginx-prefix/modules"
  8. nginx configuration prefix: "/root/tmp/nginx-1.15.3/nginx-prefix/conf"
  9. nginx configuration file: "/root/tmp/nginx-1.15.3/nginx-prefix/conf/nginx.conf"
  10. nginx pid file: "/root/tmp/nginx-1.15.3/nginx-prefix/logs/nginx.pid"
  11. nginx error log file: "/root/tmp/nginx-1.15.3/nginx-prefix/logs/error.log"
  12. nginx http access log file: "/root/tmp/nginx-1.15.3/nginx-prefix/logs/access.log"
  13. nginx http client request body temporary files: "client_body_temp"
  14. nginx http proxy temporary files: "proxy_temp"

编译和安装:

  1. cd /opt/k8s/work/nginx-1.15.3
  2. make && make install

验证编译的 nginx

  1. cd /opt/k8s/work/nginx-1.15.3
  2. ./nginx-prefix/sbin/nginx -v

输出:

  1. nginx version: nginx/1.15.3

查看 nginx 动态链接的库:

  1. $ ldd ./nginx-prefix/sbin/nginx
  2. linux-vdso.so.1 => (0x00007ffc945e7000)
  3. libdl.so.2 => /lib64/libdl.so.2 (0x00007f4385072000)
  4. libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f4384e56000)
  5. libc.so.6 => /lib64/libc.so.6 (0x00007f4384a89000)
  6. /lib64/ld-linux-x86-64.so.2 (0x00007f4385276000)
  • 由于只开启了 4 层透明转发功能,所以除了依赖 libc 等操作系统核心 lib 库外,没有对其它 lib 的依赖(如 libz、libssl 等),这样可以方便部署到各版本操作系统中;

安装和部署 nginx

创建目录结构:

  1. mkdir -p /opt/k8s/kube-nginx/{conf,logs,sbin}

拷贝二进制程序:

  1. cp /opt/k8s/work/nginx-1.15.3/nginx-prefix/sbin/nginx /opt/k8s/kube-nginx/sbin/kube-nginx
  2. chmod a+x /opt/k8s/kube-nginx/sbin/*
  • 进程重命名为 kube-nginx;

配置 nginx,开启 4 层透明转发功能:

  1. cat > /opt/k8s/kube-nginx/conf/kube-nginx.conf <<EOF
  2. worker_processes 1;
  3. events {
  4. worker_connections 1024;
  5. }
  6. stream {
  7. upstream backend {
  8. hash $remote_addr consistent;
  9. server 172.27.128.8:6443 max_fails=3 fail_timeout=30s;
  10. server 172.27.128.51:6443 max_fails=3 fail_timeout=30s;
  11. server 172.27.128.118:6443 max_fails=3 fail_timeout=30s;
  12. }
  13. server {
  14. listen 127.0.0.1:8443;
  15. proxy_connect_timeout 1s;
  16. proxy_pass backend;
  17. }
  18. }
  19. EOF
  • 需要根据集群 kube-apiserver 的实际情况,替换 backend 中 server 列表;

配置 systemd unit 文件,启动服务

配置 kube-nginx systemd unit 文件:

  1. cat > /etc/systemd/system/kube-nginx.service <<EOF
  2. [Unit]
  3. Description=kube-apiserver nginx proxy
  4. After=network.target
  5. After=network-online.target
  6. Wants=network-online.target
  7. [Service]
  8. Type=forking
  9. ExecStartPre=/opt/k8s/kube-nginx/sbin/kube-nginx -c /opt/k8s/kube-nginx/conf/kube-nginx.conf -p /opt/k8s/kube-nginx -t
  10. ExecStart=/opt/k8s/kube-nginx/sbin/kube-nginx -c /opt/k8s/kube-nginx/conf/kube-nginx.conf -p /opt/k8s/kube-nginx
  11. ExecReload=/opt/k8s/kube-nginx/sbin/kube-nginx -c /opt/k8s/kube-nginx/conf/kube-nginx.conf -p /opt/k8s/kube-nginx -s reload
  12. PrivateTmp=true
  13. Restart=always
  14. RestartSec=5
  15. StartLimitInterval=0
  16. LimitNOFILE=65536
  17. [Install]
  18. WantedBy=multi-user.target
  19. EOF

启动 kube-nginx 服务:

  1. systemctl daemon-reload && systemctl enable kube-nginx && systemctl restart kube-nginx

检查 kube-nginx 服务运行状态

  1. systemctl status kube-nginx |grep 'Active:'

确保状态为 active (running),否则到 master 节点查看日志,确认原因:

  1. journalctl -u kube-nginx

修改 kubelet、kube-proxy 配置,使用本地 nginx proxy

修改 /etc/kubernetes/kubelet.kubeconfig/etc/kubernetes/kubelet-bootstrap.kubeconfig 文件中的 cluster server 值为 server: https://127.0.0.1:8443

重启 kubelet 服务:systemctl restart kubelet

修改 /etc/kubernetes/kube-proxy.kubeconfig 文件中的 cluster server 值为 server: https://127.0.0.1:8443

重启 kube-proxy 服务: systemctl restart kube-proxy