k8s的nodePort在物理机上不工作

有天,领导告知IAAS组新有一批空闲的物理机可以给我们用,希望扩容到k8s集群中,提升性能并降低云主机的成本,于是在IAAS组将系统重做之后就给到了我们。 部署测试时发现物理机上的其他应用都正常,但我们自己的一个使用Nodeport的应用却连接不上。。

检查ipvs规则,发现nodeport的对应规则是缺失的,预期: ipvsadm –list中能查到:

宿主机ip:nodeport:rr
-> podIp:cbt
clusterIp:rr
-> podIp:cbt

pkg/proxy/ipvs/proxier.go负责相关规则的创建,具体是:

//pkg/proxy/ipvs/proxier.go#929
func (proxier *Proxier) syncProxyRules() {
  if svcInfo.nodePort != 0 {
      ...
      nodeIPs, err := proxier.ipGetter.NodeIPs()
			if err != nil {
				glog.Errorf("Failed to get node IP, err: %v", err)
			} else {
				for _, nodeIP := range nodeIPs {
					// ipvs call
  }
}
//pkg/proxy/ipvs/proxier.go#176
func (r *realIPGetter) NodeIPs() (ips []net.IP, err error) {
	interfaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	for i := range interfaces {
		name := interfaces[i].Name
		// We assume node ip bind to eth{x}
		if !strings.HasPrefix(name, "eth") {
			continue
		}

关键在这里:

if !strings.HasPrefix(name, "eth") {
  continue
}

发现问题,代码中只过滤eth相关网卡,但dell物理机centos系统的网卡默认都是em开头的,而且这批机器因性能考虑,做了多网卡绑定:

具体如:

# cat ifcfg-em1
TYPE=Ethernet
BOOTPROTO=none
DEVICE=em1
ONBOOT=yes
MASTER=bond0
SLAVE=yes

解决办法两个:

  1. 改网卡名
  2. 改过滤规则或取消该规则

再后来发现这个bug已经在1.10修复了,见commit