在上一期,我们提到,flannel使用etcd作为分布式的控制平面,如下图所示:
在一个Pod入网的时候,flanneld会将pod的MAC地址,IP地址/子网掩码/默认网关,以及pod在bridge上连接的接口传递给etcd。
由于etcd全局同步的特性,其他node上的etcd也会有这些信息,因此在其他node上运行的flanneld实例,以IP地址为键,查询本node上的etcd,就可以查到对端pod的MAC地址、bridge地址、默认网关等信息,而不需要经过泛洪学习MAC和广播学习ARP。
这种方式看起来很美,但也有绕不开的问题——
让我们将kubernetes集群从3个node扩展到100个node,此时,集群中将运行100个flanneld实例。
问题来了:我们知道,无论是什么样的分布式系统,如果采用去中心化的设计,都必然面对信息同步时,算法的N平方复杂度问题。也就是说,如果节点数从10个增加到100个,每个节点的信息同步工作量会增加到原来的10倍,总的信息同步工作量会增加到原来的100倍。
当然,etcd不可能在100个节点上都部署,实践中一般用3-5个节点。
这又引入了另一个问题:
etcd的读写性能问题。
etcd本质上是一个数据库,数据库要遵循A,C,I,D四条铁律,其中A最为重要,它指的是操作的原子性(Atomic)。
什么是操作的原子性呢?
假设方老师的某某宝里面,有2000元,并且进行了在某多多上购买了1500元的二手DL360 G6服务器的操作。某多多判断:余额2000>价格1500,下单成功,发起扣款。
在某多多尚未完成扣款操作的时候,方老师又在某猫上下单购买了1500元的樱桃键盘操作,某猫判断:余额2000>价格1500,下单成功,发起扣款。
方老师卷走了价值3000的货物,只支付了某某宝中的余额2000元,剩余的1000元,将由某多多或某猫中比较倒霉的一个,向某乡村教师代言人发起法律诉讼追索。
当然,这个bug并不会发生,否则方老师将该bug扩散到羊毛群必然引发互联网行业惊天动地的的地震。
这是因为,所有涉及支付的数据库,它的操作是原子的(Atomic)。
虽然毛主席早在1937年著作的《矛盾论》中就雄辩指出,原子实际上是可以再分的,但在计算机领域依然使用这个词代表不可分割的操作。
所谓“原子操作”,指的是:
A在访问数据X时,B对数据X的访问将被推迟,直至A对数据X的访问完成。
原子操作依赖于CPU的原子指令,它可以在对内存的值进行操作时锁定总线,让其他试图修改该内存单元的CPU原地等待,本质上是事务需要进行排队。
既然在数据库中,操作的原子性是一条铁律,在分布式数据库的场景中,多个节点之间的同步也需要遵循这条铁律。排队与数据同步之间的叠加,会使得在节点数越多,每扩展一个节点付出的代价越大。
所以,在kubernetes flannel节点数大规模增加的情况下,etcd的节点数并不能同步增加。如果Kubernetes集群的节点数量超过500,pod数量达到5000个的数量级,etcd会逐渐成为瓶颈。
我们需要一个更适合的解决方案。
敬请期待下期。