前言
公司早期的K8S集群是基于flannel分配网段后,并没有在kubelet中启动cni插件功能,而是利用docker本身的网络管理功能,如下所示dockerd的启动命令为:
./dockerd --bip=10.236.51.1/25 ...
这利用了docker的自身的网络管理能力,我们知道docker本身是具备端口映射的功能,可以把容器中的服务通过端口映射的方式,如下所示,我们启动一个容器,把容器中的80端口映射到宿主机的8000端口上:
docker run -p 8000:80 -it ubuntu /bin/bash
有些老业务为了让容器与外部系统互通,把容器的端口映射到了宿主机的端口上,通过对宿主机的端口进行管理,来防止容器调度的冲突,这种方式一定层度上解决了业务上的问题。
近期,我们对K8S的网络模型进行了升级,通过自定义的网络CNI插件,实现三层网络模型,可以让容器网络与主机网络系统打通,为了统一K8S集群方便管理,我们需要把一些老的业务迁移到新的K8S集群中来。
我们又不希望管理多个K8S集群,但是新集群中的CNI插件本身,不具备这种端口映射的能力,所以碰到了旧的业务无法迁移的难题。
额外话题:
从这个问题本身来看,其实业务方并没有使用端口映射功能的必要性,既然业务自己管理分配的主机节点和端口号,那么我们完全可以基于Host网络部署Pod来达到相同的目的。
这里我们先不考虑方案替代性上来说,端口映射功能也是一个比较有意思的点,剖析一下如何在我们新的K8S集群中来支撑这种端口映射功能。
K8S中的端口映射
K8S在框架层面是支撑了端口映射的功能,我们可以看看下面这个Pod的定义:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
hostPort: 8080
这个Pod要求把容器中80端口映射到宿主机的8080端口中,虽然我们能够这样申明,但是究竟能不能做到,就跟我们指定的网络模式有很大关系了。
如果按照我们老集群中,采用None的模式,让docker进程去管理网络,那么docker自身具备这种端口映射的能力,所以他就能够支持,而在我们新集群中应用的时候,发现不能达到目的,映射根本没有完成。
应用CNI portmap插件实现对端口映射的支持
我们首先来看看我们自定义的插件配置:
root@herrypc:/etc/cni/net.d# cat 11-flannel.conf
{
"cniVersion": "0.3.0",
"name": "mynet",
"type": "flannel",
"ipMasq": false,
"delegate": {
"type": "bridge",
"forceAddress": false,
"ipMasq": false,
"hairpinMode": true,
"isDefaultGateway": true
}
}
基础插件自身是不具备端口映射的能力的,所以基于上述配置无法实现端口映射,但是CNI本身支持级联插件的功能,可以在配置中指定portmap作为级联插件来支持端口映射能力。
为了支持级联插件,我们配置不能采用前面的配置格式,而是基于conflist的配置,文件名改为:11-flannel.conflist,内容如下:
root@herrypc:/etc/cni/net.d# cat 11-flannel.conflist
{
"cniVersion": "0.3.0",
"name": "mynet",
"plugins": [
{
"type": "flannel",
"ipMasq": false,
"delegate": {
"type": "bridge",
"forceAddress": false,
"ipMasq": false,
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {"portMappings": true},
"snat": true
},
}
}
网友评论