沪江黄凯:Kuberneters 的 Fannel 有一种模式是 Vxlan,它的封装折包是做内核里做的,效率会高一点。容器多就会效率会低是因为,在 Kubernetes 1.2 的时候,走这样的一种模式,数据先到内核态中,然后把数据拉回到用户态,用 Proxy的方式分发给各个容器当中的。其实在Kubernetes 1.3以后,它直接在iptables里设规则,相当于用户数据不用跑到用户态,在内核直接分发出去了,这种效率会非常高。所以可以研究一下Kubernetes新版本。
扇贝丁彦:我们碰到过网络方面的问题。默认的Docker engine的启动参数里面有个iptables,不知道大家有没有定制化过,如果不定制化这个参数,它默认会帮你建iptables的转发规则,并会开启内核的网络追踪的模块。一开始我们没有注意这件事情,当我们的Nginx迁到Docker的时候,Nginx服务瞬间会挂。后来查原因,是因为这些参数会开启网络追踪模块。因为我们的Nginx流量非常大,当时只有3台Linux云主机,分发Http请求的,然后会导致3台Linux宿主机,内存会被刷破,网络会出现堵塞。所以我们关掉了 iptables 参数,并采用Host的网络模型。所以它的容器拿到的IP就是Host的IP。我们一开始也想上一些Kubernetes这些东西,然后发现简单跑个模型根本跑不起来,所以一开始就放弃了这一套东西,直接搞了个裸的Docker。
主持人:关于跨数据中心容器集群的使用,大家有经验么?
沪江黄凯:我们跨数据中心主要是IP分配上的问题,我们现在也在尝试使用Calico,如果Host网络是通的话,那么它的内部网络也就通了,可以自由划Vlan,这样你就可以解决跨Data center的问题。还有一个问题就在跨Data center时,服务注册与发现的问题。这个问题也困扰我们很久了,我们现在使用Consul做服务注册与发现。虽然Consul它是官方支持跨Data center,但是我们在使用当中的话会发现注册的IP,在另外一个注册中心,它会发现的比较慢,甚至有时候出现IP冲突的时候。
我们的做法是把 Host 的 IP 地址直接用 Environment 的形式注到 Docker 镜像内部,接下 来 Docker 镜像要注册,它就会读取 app 的 IP,然后发送给 Consul,只要保证 Host 的 IP 和 Docker内部容器的 IP 能够互通的就行了。如果不能通的话,比如说完全和 Host IP 隔离,那么起码有几台机器要暴露出去,又比如说,Consul 它本身自己要暴露出去才能访问到。Host 的 IP 是容器启动之后注进去的,启动命令中把 Host 的 IP 地址加在 -e 的后面,容器在启动之后,它的环境就会有这么一个 IP。我们用 Mesos 就没这个问题,但是用 Kubernetes 就有这个问题。Mesos 会自动帮你把这些东西注入容器中去。
滴滴田智伟:其实 Kubernetes 本身也是可以解决这个问题,我们现在在做线下持续交付的时候。定义完 Service 之后,容器会同一个 Namespace 默认加一个系统环境变量。
沪江黄凯:我们试过,在 Pod 启动之后,Pod 里容器想访问 host 的 IP 地址,是没有办法做到的。
蘑菇街张振华:因为我们之前也遇到这个问题,然后我们业务方,他们可能有一些程序会获取本机 IP 地址,如果是内部的 IP 地址,他们程序可能会出现问题,于是我们当时没有用 Docker 默认的网络,而是采用 Vlan。
主持人:我们提到好多 Mesos、Kubernetes、网络,发现没有提自动伸缩,有没有项目涉及到容器的自动伸缩?
沪江黄凯:我们沪江是基于 Mesos+Marathon 做了自己的一个服务,它这个服务是干嘛的呢,就是监测,不停的监测每一个 Docker 的 CPU 和内存的利用率,一旦超过百分之多少以后,就向Marathon发一个命令,说我要扩容,它还可以支持时间点,比如 15 分钟监测一次,如果在 15 分钟发现它超过阈值了,就马上扩容出来,但是缩的话,不是适用于频繁监控,如果小于 20% 的话就会缩,一旦缩的话会影响线上用户的请求。怎么办呢?我们在缩的时候可以规定它的时间点,比如半夜里2-3点,访问量少于多少点时候把它缩掉。我们监测的是 Docker 内部的 CPU 的使用率。就是监测一个服务,它可以监控所有同一服务的 Container,比如一个服务有100个容器,那么这一百多个 CPU 利用率加起来除于一百,相当于平均的利用率。如果平均利用率超过 80%了,那说明这个集群到了扩展程度了,它会以一种比例来扩展。针对单个容器,可以设置内存的限制。我们给每一个容器呢,比如它只能用 4 个 CPU,只能用 8G 的内存,或者更小一点的内存,这些都设好,设好之后它自动扩展相同规格的容器。这么做是因为 Cgroup 有个问题,当利用率到达了启动的限制,Cgroup 会把这个容器 kill 掉。这个是不可理喻的问题,所以我们想到用 Load scale 来扩容,不让他直接死掉。