kubernetes 安装kube-router

前言

网上关于kubernetes网络部署的方案非常多,那为什么还要自己写这么一篇教程呢?因为这篇文章中将介绍一种较为少见的部署方式,使用kuberouter作为kubernetes系统网络组件,直接替换掉kubeproxy、flannel/calico等网络组件。使用这种部署方式的目的,是替换kube-proxy,减少iptables依赖,同时还能提供网络服务。

<!--more-->

替代分析

Kube-router替代kube-proxy

kube-proxy的作用主要是用于监听API server中 service 和 endpoint的变化情况,并通过iptables等来为服务配置负载均衡(仅支持TCP和UDP)。kube-proxy 可以直接运行在物理机上,也可以以 static pod 或者 daemonset 的方式运行。

Kube-proxy主要有以下技术特点:

  • 底层默认使用iptables进行流量的转发

  • 通过监听api server服务中的对象变化,实现service发现功能。

而kuberouter采用了基于相同技术但增加了更多负载均衡策略的IPVS来实现流量转发,服务发现的实现与kube-proxy一致。因此可以直接替代kube-proxy。

Kube-router代替flannel/Calico等网络组件

kubernetes 对网络的要求是:容器之间(包括同一台主机上的容器,和不同主机的容器)可以互相通信,容器和集群中所有的节点也能直接通信。

在kube-router出现之前,kubernetes长期以来使用第三方模块来负责网络模块配置,其中flannel是其中较为常用的一个,以flannel为例。

flannel在集群中的功能主要有以下两点:

能够给每个 Node 分配互不冲突的网段,意味着集群内每个容器有着互不冲突的 IP 地址;(指定 docker 启动参数的方式指定网段)

能够建立一个覆盖网络,通过这个覆盖网络,能将数据包原封不动传递到目标容器内。(这里传递通常是 UDP 数据包)

在实际运行过程中,每个节点需要部署一个flannel服务,部署成功后会生成一个flannel.0的虚拟设备,同时会运行flanneld的进程,用以链接flannel.0和物理网卡。传输过程中的数据包通过路由规则判断,如果是本网段的访问,就会走 docker0 网桥;如果是跨网段,也就是要跨宿主机访问,就会将数据发往 flannel0。flanneld将数据包封装成底层通信包,协议包括UDP、Vxlan等,这里往往用的是UDP,这个UDP 的packet 会根据 etcd 存放的路由表(一般会缓存到主机内存里)找到目的容器 IP 所承载的宿主机 IP,不借助第三方路由设备的前提下,数据包发送到了宿主机上。此时目标宿主机的 flanneld 进程会对 UDP 包进行解包操作,转化成数据包原本的协议,最终根据主机内部路由流入到目标容器中。

完成这一系列动作有两个核心的技术点:

flannel分配虚拟网卡是基于TUN/TAP虚拟网卡技术。

flannel是三层设备,利用backend对节点内的二层的数据包封包成UDP,再发送到目的节点的flanneld进行解包。

在kuberouter中,这种网络管理机制由CNI(容器网络接口)+BGP协议实现的。

Kube-router不像flannel一样采用子网管理的方式,而是利用kube-conroller-manager来做子网分配,每一个节点会根据cluster CIDR被分配到集群中独一无二的子网ip。Kube-router运行在集群中每个节点运行IBGP,同时自动将所有节点组成网络。所有的集群中的节点在集群中将组成可配置的私有自治网络。Kube-router将会广播pod CIDR,并且保存从同一个主机命名空间学习到的路由。

子网IP的管理是由CNI的brige插件配合IPAM的host-local插件完成。

部署kube-router

依赖

  • kube-router 能够访问apiserver

    这边提供kubeconfig方式

apiVersion: v1
clusters:
- cluster:
    certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    server: https://k8s.foxchan.com
  name: default
contexts:
- context:
    cluster: default
    namespace: default
    user: default
  name: default
current-context: default
users:
- name: default
  user:
    tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
  • controller-manager必要配置参数
--cluster-cidr=10.244.0.0/16 --allocate-node-cidrs=true \
  • 直接在主机运行需要有ipset命令
  • 以daemonseset 运行需要kube-apiserver 和kubelet 同时开启--allow-privileged=true
  • 如果选择pod-to-pod 网络模式,需要部署CNI插件

官方给的简单示例

wget -O /etc/cni/net.d/10-kuberouter.conf https://raw.githubusercontent.com/cloudnativelabs/kube-router/master/cni/10-kuberouter.conf

参数说明

  • 使用iptables实现网络策略限制. --run-firewall参数,可透传源IP。
  • 通过bgp实现路由策略.--run-router 参数
  • 通过lvs实现代理策略。 --run-service-proxy

--run-firewall, --run-router, --run-service-proxy可以有选择地只启用kube-router所需的功能

  • 只提供入口防火墙:--run-firewall=true --run-service-proxy=false --run-router=false
  • 仅仅替换kube-proxy: --run-service-proxy=true --run-firewall=false --run-router=false

查看现有集群nodeCIDR划分

kubectl get nodes -o json | jq ‘.items[] | .spec‘

命令行汉化

Usage of ./kube-router:
      --advertise-cluster-ip                将该服务的集群IP添加到RIB,以便通告给BGP peers.
      --advertise-external-ip               将服务的外部IP添加到RIB,以便将其通告给BGP peers.
      --cleanup-config                      清理iptables规则,ipvs,ipset配置并退出.
      --cluster-asn uint                    集群节点运行iBGP的ASN编号.
      --cluster-cidr string                 群集中的CIDR范围。它被用来识别pods的范围.
      --config-sync-period duration         apiserver配置同步之间的延迟(例如“5s”,“1m”)。必须大于0.(默认1m0s)
      --enable-overlay                      当enable-overlay设置为true时,IP-in-IP隧道将用于跨不同子网中节点的pod-pod联网。如果设置为false,则不使用隧道,并且路由基础架构预计为不同子网中的节点之间的pod-pod联网路由流量(默认值为true)
      --enable-pod-egress                   从Pod到群集外的SNAT流量。 (默认为true)
      --hairpin-mode                        为每个服务端点添加iptable规则以支持流量管控.
  -h, --help                                打印使用信息.
      --hostname-override string            覆盖节点的NodeName。如果kube-router无法自动确定您的NodeName,请设置此项.
      --iptables-sync-period duration       iptables规则同步之间的延迟(例如‘5s‘,‘1m‘)。必须大于0.(默认1m0s)
      --ipvs-sync-period duration           ipvs config同步之间的延迟(例如‘5s‘,‘1m‘,‘2h22m‘)。必须大于0.(默认1m0s)
      --kubeconfig string                   具有授权信息的kubeconfig文件的路径(主位置由主标志设置)。
      --masquerade-all                      SNAT所有流量到群集IP /节点端口。
      --master string                       Kubernetes API服务器的地址(覆盖kubeconfig中的任何值)。
      --nodeport-bindon-all-ip              对于NodePort类型的服务,创建监听节点的所有IP的IPVS服务.
      --nodes-full-mesh                     集群中的每个节点都将建立与其他节点的BGP对等关系。 (默认为true)
      --peer-router-asns uintSlice          集群节点将向其通告集群ip和节点的pid cidr的BGP peers的ASN编号。 (默认[])
      --peer-router-ips ipSlice             所有节点将对等的外部路由器的IP地址,并通告集群ip和pod cidr。 (默认[])
      --peer-router-passwords stringSlice   用“--peer-router-ips”定义的BGP peers进行认证的密码。
      --routes-sync-period duration         路线更新与广播之间的延迟(例如“5s”,“1m”,“2h22m”)。必须大于0.(默认1m0s)
      --run-firewall                        启用网络策略 - 设置iptables为pod提供入口防火墙。 (默认为true)
      --run-router                          启用Pod网络 - 通过iBGP发布并学习到Pod的路由。 (默认为true)
      --run-service-proxy                   启用服务代理 - 为Kubernetes服务设置IPVS。 (默认为true)```

安装

集群安装时没有选择kube-proxy插件

从k8s1.14开始,可以在kubeadm init的时候指定组件是否安装

先要创建kube-proxy configmap,然后修改yaml

kubectl create configmap kube-router --namespace=kube-system --from-file=kubeconfig
wget -o kubeadm-kuberouter-all-features.yaml https://raw.githubusercontent.com/cloudnativelabs/kube-router/master/daemonset/kubeadm-kuberouter-all-features.yaml

修改yaml,去访问之前生成的kubeconfig

...
        - name: cni-conf-dir
          mountPath: /etc/cni/net.d
        - name: kubeconfig
          mountPath: /var/lib/kube-router
          readOnly: true
        - name: xtables-lock
          mountPath: /run/xtables.lock
          readOnly: false
...
      volumes:
      - name: lib-modules
        hostPath:
          path: /lib/modules
      - name: cni-conf-dir
        hostPath:
          path: /etc/cni/net.d
      - name: kube-router-cfg
        configMap:
          name: kube-router-cfg
      - name: kubeconfig
        configMap:
          name: kube-router
      - name: xtables-lock
        hostPath:
          path: /run/xtables.lock
          type: FileOrCreate
...

集群已经有kube-proxy

只是进行替换

kubectl apply -f https://raw.githubusercontent.com/cloudnativelabs/kube-router/master/daemonset/kubeadm-kuberouter-all-features.yaml

安装完成后,清理iptables

kubectl -n kube-system delete ds kube-proxy
docker run --privileged -v /lib/modules:/lib/modules --net=host k8s.gcr.io/kube-proxy-amd64:v1.17.9 kube-proxy --cleanup

使用

负载均衡调度算法

Kube-router使用LVS作为服务代理。 LVS支持丰富的调度算法。您可以为该服务添加注释以选择一个调度算法。当一个服务没有注释时,默认情况下选择“轮询”调度策略

For least connection scheduling use:
kubectl annotate service my-service "kube-router.io/service.scheduler=lc"
For round-robin scheduling use:
kubectl annotate service my-service "kube-router.io/service.scheduler=rr"
For source hashing scheduling use:
kubectl annotate service my-service "kube-router.io/service.scheduler=sh"
For destination hashing scheduling use:
kubectl annotate service my-service "kube-router.io/service.scheduler=dh"

Direct server return

请阅读以下博客,了解如何结合使用DSR和“–advertise-external-ip”构建高度可扩展和可用的入口。 https://cloudnativelabs.github.io/post/2017-11-01-kube-high-available-ingress/
您可以为每个服务启用DSR(直接服务器返回)功能。当启用的服务端点将直接响应客户端通过签署服务代理。启用DSR时,Kube-router将使用LVS的隧道模式来实现此功能。
要启用DSR,您需要使用kube-router.io/service.dsr = tunnel注释来注释服务。例如,

kubectl annotate service my-service "kube-router.io/service.dsr=tunnel"

在当前的实现中,当在服务上应用注释时,DSR将仅适用于外部IP。
此外,当使用DSR时,当前的实现不支持端口重新映射。所以你需要使用相同的端口和目标端口的服务
你需要在kube-router守护进程清单中启用hostIPC:true和hostPID:true。并且必须将主路径/var/run/docker.sock设置为kube-router的一个volumemount。
上述更改需要kube-router输入pod namespace,并在pod中创建ipip隧道,并将外部IP分配给VIP。
对于示例清单,请查看启用DSR功能的manifest

暴露服务

  • svc clusterip
$ kubectl expose nginx --target-port=80 --port=80
$ kubectl get svc nginx -o template --template=‘{{.spec.clusterIP}}‘
10.254.116.179

在每台机器上查看lvs条目

ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.254.0.1:443 rr persistent 10800
  -> 172.26.6.1:6443              Masq    1      0          0
TCP  10.254.116.179:80 rr 10800
  -> 10.254.11.2:80               Masq    1      0          0

发现本机SVCIP代理后端真实podip,使用rr算法,通过ip addr s可以看到每添加一个服务node节点上面的kube-dummy-if网卡就会增加一个虚IP

  • svc session-affinity
kubectl delete svc nginx
kubectl expose deploy nginx --target-port=80 --port=80 --session-affinity=ClientIP
ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.254.0.1:443 rr persistent 10800
  -> 172.26.6.1:6443              Masq    1      0          0
TCP  10.254.191.234:80 rr persistent 10800
  -> 10.254.11.2:80               Masq    1      0          0
我们可以看到 多个persistent,既lvs里面的持久链接
  • svc NodePort
kubectl delete svc nginx
kubectl expose deploy nginx --target-port=80 --port=80 --type=NodePort
ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.26.6.3:31117 rr
  -> 10.254.11.2:80               Masq    1      0          0
TCP  10.254.0.1:443 rr persistent 10800
  -> 172.26.6.1:6443              Masq    1      0          0
TCP  10.254.102.188:80 rr
  -> 10.254.11.2:80               Masq    1      0          0
可以看到不仅有虚拟IP条目,还多了对应主机的lvs条目
  • 更改算法
kubectl annotate service nginx "kube-router.io/service.scheduler=dh"

network policy

kubectl annotate ns prod "net.beta.kubernetes.io/network-policy={\"ingress\":{\"isolation\":\"DefaultDeny\"}}" 

测试可以看到其他命名空间ping不通该命名空间

查看路由表

 ip route s

查看bgp新信息

#  kubectl --namespace=kube-system  exec -it  kube-router-pk7fs /bin/bash 
#  gobgp neighbor -u 172.26.6.3 #从哪些IP获得更新
Peer          AS  Up/Down State       |#Received  Accepted
172.26.6.2 64512 01:03:03 Establ      |        1         1
#  gobgp global rib -u 172.26.6.3 #global rib相当于路由表
   Network              Next Hop             AS_PATH              Age        Attrs
*> 10.254.0.0/24        172.26.6.2                                01:03:24   [{Origin: i} {LocalPref: 100}]
*> 10.254.2.0/24        172.26.6.3                                00:00:32   [{Origin: i}]

kubernetes 安装kube-router

上一篇:phpredis 扩展之操作 Redis,记下来记下来!


下一篇:HTML基础