一、Kafka的生产集群部署1.1 方案背景假设每天集群需要承载10亿数据。一天24小时，晚上12点到凌晨8点几乎没多少数据。使用二八法则估计，也就是80%的数据（8亿）会在16个小时涌入，而且8亿的80%的数据（6.4亿）会在这16个小时的20%时间（3小时）涌入。QPS计算公式：640000000 ÷ (3x60x60) = 60000，也就是说高峰期的时候Kafka集群要扛住每秒6万的并发。磁盘空间计算，每天10亿数据，每条50kb，也就是46T的数据。保存2个副本（在上一篇中也提到过其实两个副本会比较好，因为follower需要去leader那里同步数据，同步数据的过程需要耗费网络，而且需要磁盘空间，但是这个需要根据实际情况考虑），46 2 = 92T，保留最近3天的数据。故需要 92 3 = 276T1.2 QPS方面部署Kafka，Hadoop，MySQL···等核心分布式系统，一般建议直接采用物理机，抛弃使用一些低配置的虚拟机的想法。高并发这个东西，不可能是说，你需要支撑6万QPS，你的集群就刚好把这6万并发卡的死死的。加入某一天出一些活动让数据量疯狂上涨，那整个集群就会垮掉。但是，假如说你只要支撑6w QPS，单台物理机本身就能扛住4~5万的并发。所以这时2台物理机绝对绝对够了。但是这里有一个问题，我们通常是建议，公司预算充足，尽量是让高峰QPS控制在集群能承载的总QPS的30%左右（也就是集群的处理能力是高峰期的3~4倍这个样子），所以我们搭建的kafka集群能承载的总QPS为20万~30万才是安全的。所以大体上来说，需要5~7台物理机来部署，基本上就很安全了，每台物理机要求吞吐量在每秒4~5万条数据就可以了，物理机的配置和性能也不需要特别高。1.3 磁盘方面1.3.1 磁盘数量需要5台物理机的情况，需要存储276T的数据，平均下来差不多一台56T的数据。这个具体看磁盘数和盘的大小1.3.2 SAS还是SSD现在我们需要考虑一个问题：是需要SSD固态硬盘，还是普通机械硬盘？SSD就是固态硬盘，比机械硬盘要快，那么到底是快在哪里呢？其实SSD的快主要是快在磁盘随机读写，就要对磁盘上的随机位置来读写的时候，SSD比机械硬盘要快。比如说MySQL这种就应该使用SSD了（MySQL需要随机读写）。比如说我们在规划和部署线上系统的MySQL集群的时候，一般来说必须用SSD，性能可以提高很多，这样MySQL可以承载的并发请求量也会高很多，而且SQL语句执行的性能也会提高很多。因为写磁盘的时候kafka是顺序写的。机械硬盘顺序写的性能机会跟内存读写的性能是差不多的，所以对于Kafka集群来说其实使用机械硬盘就可以了。如果是需要自己创业或者是在公司成本不足的情况下，经费是能够缩减就尽量缩减的。1.4 内存角度JVM非常怕出现full gc的情况。kafka自身的jvm是用不了过多堆内存的，因为kafka设计就是规避掉用jvm对象来保存数据，避免频繁full gc导致的问题，所以一般kafka自身的jvm堆内存，分配个10G左右就够了，剩下的内存全部留给os cache。那服务器需要多少内存呢。我们估算一下，大概有100个topic，所以要保证有100个topic的leader partition的数据在操作系统的内存里。100个topic，一个topic有5个partition。那么总共会有500个partition。每个partition的大小是1G（在上一篇中的日志分段存储中规定了.log文件不能超过1个G），我们有2个副本，也就是说要把100个topic的leader partition数据都驻留在内存里需要1000G的内存。我们现在有5台服务器，所以平均下来每天服务器需要200G的内存，但是其实partition的数据我们没必要所有的都要驻留在内存里面，只需要25%的数据在内存就行，200G * 0.25 = 50G就可以了（因为在集群中的生产者和消费者几乎也算是实时的，基本不会出现消息积压太多的情况）。所以一共需要60G（附带上刚刚的10G Kafka服务）的内存，故我们可以挑选64G内存的服务器也行，大不了partition的数据再少一点在内存，当然如果能够提供128G内存那就更好。1.5 CPU coreCPU规划，主要是看你的这个进程里会有多少个线程，线程主要是依托多核CPU来执行的，如果你的线程特别多，但是CPU核很少，就会导致你的CPU负载很高，会导致整体工作线程执行的效率不太高，上一篇的Kafka的网络设计中讲过Kafka的Broker的模型。acceptor线程负责去接入客户端的连接请求，但是他接入了之后其实就会把连接分配给多个processor，默认是3个，但是一般生产环境建议大家还是多加几个，整体可以提升kafka的吞吐量比如说你可以增加到6个，或者是9个。另外就是负责处理请求的线程，是一个线程池，默认是8个线程，在生产集群里，建议大家可以把这块的线程数量稍微多加个2倍~3倍，其实都正常，比如说搞个16个工作线程，24个工作线程。后台会有很多的其他的一些线程，比如说定期清理7天前数据的线程，Controller负责感知和管控整个集群的线程，副本同步拉取数据的线程，这样算下来每个broker起码会有上百个线程。根据经验4个cpu core，一般来说几十个线程，在高峰期CPU几乎都快打满了。8个cpu core，也就能够比较宽裕的支撑几十个线程繁忙的工作。所以Kafka的服务器一般是建议16核，基本上可以hold住一两百线程的工作。当然如果可以给到32 cpu core那就最好不过了。1.6 网卡现在的网基本就是千兆网卡（1GB / s），还有万兆网卡（10GB / s）。kafka集群之间，broker和broker之间是会做数据同步的，因为leader要同步数据到follower上去，他们是在不同的broker机器上的，broker机器之间会进行频繁的数据同步，传输大量的数据。那每秒两台broker机器之间大概会传输多大的数据量？高峰期每秒大概会涌入6万条数据，约每天处理10000个请求，每个请求50kb，故每秒约进来488M数据，我们还有副本同步数据，故高峰期的时候需要488M * 2 = 976M/s的网络带宽，所以在高峰期的时候，使用千兆带宽，网络还是非常有压力的。综上描述10亿数据，6w/s的吞吐量，276T的数据，5台物理机 硬盘：11（SAS） * 7T，7200转 内存：64GB/128GB，JVM分配10G，剩余的给os cache CPU：16核/32核 网络：千兆网卡，万兆更好二、Kafka的集群搭建进到Kafka的config文件夹下，会发现有很多很多的配置文件，可是都不需要你来修改，你仅仅需要点开一个叫作server.properties的文件就够了。【broker.id】 每个broker都必须自己设置的一个唯一id，可以在0~255之间 【log.dirs】 这个极为重要，kafka的所有数据就是写入这个目录下的磁盘文件中的，如果说机器上有多块物理硬盘，那么可以把多个目录挂载到不同的物理硬盘上，然后这里可以设置多个目录，这样kafka可以数据分散到多块物理硬盘，多个硬盘的磁头可以并行写，这样可以提升吞吐量。ps：多个目录用英文逗号分隔 【zookeeper.connect】 连接kafka底层的zookeeper集群的 【Listeners】 broker监听客户端发起请求的端口号，默认是9092 【num.network.threads】默认值为3 【num.io.threads】默认值为8 细心的朋友们应该已经发现了，这就是上一篇我们在网络架构上提到的processor和处理线程池的线程数目。 所以说掌握Kafka网络架构显得尤为重要。 现在你看到这两个参数，就知道这就是Kafka集群性能的关键参数了 【unclean.leader.election.enable】 默认是false，意思就是只能选举ISR列表里的follower成为新的leader，1.0版本后才设为false，之前都是true，允许非ISR列表的follower选举为新的leader 【delete.topic.enable】 默认true，允许删除topic 【log.retention.hours】 可以设置一下，要保留数据多少个小时，这个就是底层的磁盘文件，默认保留7天的数据，根据自己的需求来就行了 【min.insync.replicas】 acks=-1（一条数据必须写入ISR里所有副本才算成功），你写一条数据只要写入leader就算成功了，不需要等待同步到follower才算写成功。但是此时如果一个follower宕机了，你写一条数据到leader之后，leader也宕机，会导致数据的丢失。因为实际的集群搭建说真的没有太大难度，所以搭建的过程就不详细展开了，网上应该很多相关资料三、Kafka的简单集群操作在操作Kafka集群的时候，不同的Kafka版本命令的写法是不一样的，所以其实如果需要了解一下，推荐直接到官网去查看上一篇时也有提到说Kafka在0.8版本以前存在比较大的问题，1.x的算是目前生产环境中使用较多的版本在quickStart就能看到相关的命令，比如① 创建主题bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test 将该命令修改一下 zookeeper localhost:2181 --replication-factor 2 --partitions 2 --topic tellYourDream 这时候就是zookeeper的地址为localhost:2181 两个分区，两个副本，一共4个副本，topic名称为“tellYourDream”了还得注意，一般来说设置分区数建议是节点的倍数，这是为了让服务节点分配均衡的举措。② 查看主题：bin/kafka-topics.sh --list --zookeeper localhost:2181③ 生产信息 bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test This is a message This is another message④ 消费信息 bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning This is a message This is another message这里有个细节需要提及一下，就是我们0.8版本的kafka找的是zookeeper，zookeeper上确实是也存在着元数据信息。不过这存在着一些问题，zookeeper本身有一个过半服务的特性，这是一个限制，过半服务是指任何的请求都需要半数节点同意才能执行。每次有写请求，它都要投票，因为它要保持数据的强一致性，做到节点状态同步，所以高并发写的性能不好。不适合做高并发的事。zookeeper是Kafka存储元数据和交换集群信息的工具，主要是处理分布式一致性的问题。⑤ 集群测试下面的命令就是生产50W条数据，每条数据200字节，这条命令一运行就会产生一条报告，可以很直观的看到集群性能，看不懂的情况搜索引擎也可以很好地帮助你解决问题测试生产数据 bin/kafka-producer-perf-test.sh --topic test-topic --num-records 500000 --record-size 200 --throughput -1 --producer-props bootstrap.servers=hadoop03:9092,hadoop04:9092,hadoop05:9092 acks=-1每次消费2000条，集群没跑挂那就稳妥了测试消费数据 bin/kafka-consumer-perf-test.sh --broker-list hadoop03:9092,hadoop04:9092,hadoop53:9092 --fetch-size 2000 --messages 500000 --topic test-topic 四、KafkaManagerKafkaManager使用scala写的项目。安装步骤可以参考kafka集群管理工具kafka-manager部署安装，非常不错。使用方法可以通过搜索引擎查找。安装好了之后可以使用jps命令查看一下，会多出一个名字叫做ProdServerStart的服务功能介绍1. 管理多个kafka集群 2. 便捷的检查kafka集群状态(topics,brokers,备份分布情况,分区分布情况) 3. 选择你要运行的副本 4. 基于当前分区状况进行 5. 可以选择topic配置并创建topic(0.8.1.1和0.8.2的配置不同) 6. 删除topic(只支持0.8.2以上的版本并且要在broker配置中设置delete.topic.enable=true) 7. Topic list会指明哪些topic被删除（在0.8.2以上版本适用） 8. 为已存在的topic增加分区 9. 为已存在的topic更新配置 10. 在多个topic上批量重分区 11. 在多个topic上批量重分区(可选partition broker位置)五、KafkaOffsetMonitorKafkaOffsetMonitor就是一个jar包而已，是一个针对于消费者的工具。它可以用于监控消费延迟的问题，不过对于重复消费和消息丢失等就无法解决，因为之后如果需要讲解SparkStreaming，flink这些用于消费者的实践的话，会使用到这个工具，所以现在先不展开，了解一下即可启动命令：java -cp KafkaOffsetMonitor-assembly-0.3.0-SNAPSHOT.jar \ com.quantifind.kafka.offsetapp.OffsetGetterWeb \ --offsetStorage kafka \ --zk xx:2181,xx:2181,xx:2181/kafka_cluster \ --port 8088 \ --refresh 60.seconds \ --retain 2.days还有一些跨机房同步数据的像MirrorMaker这些，酌情使用。转载自 https://juejin.im/post/5dd34f735188254efb3bd12b
Kubernetes CNI网络对比：Flannel、Calico、Canal和Weave
介绍网络架构是Kubernetes中较为复杂、让很多用户头疼的方面之一。Kubernetes网络模型本身对某些特定的网络功能有一定要求，但在实现方面也具有一定的灵活性。因此，业界已有不少不同的网络方案，来满足特定的环境和要求。CNI意为容器网络接口，它是一种标准的设计，为了让用户在容器创建或销毁时都能够更容易地配置容器网络。在本文中，我们将集中探索与对比目前最流行的CNI插件：Flannel、Calico、Weave和Canal（技术上是多个插件的组合）。这些插件既可以确保满足Kubernetes的网络要求，又能为Kubernetes集群管理员提供他们所需的某些特定的网络功能。背景容器网络是容器选择连接到其他容器、主机和外部网络（如Internet）的机制。容器的runtime提供了各种网络模式，每种模式都会产生不同的体验。例如，Docker默认情况下可以为容器配置以下网络：none：将容器添加到一个容器专门的网络堆栈中，没有对外连接。host：将容器添加到主机的网络堆栈中，没有隔离。default bridge：默认网络模式。每个容器可以通过IP地址相互连接。自定义网桥：用户定义的网桥，具有更多的灵活性、隔离性和其他便利功能。Docker还可以让用户通过其他驱动程序和插件，来配置更高级的网络（包括多主机覆盖网络）。CNI的初衷是创建一个框架，用于在配置或销毁容器时动态配置适当的网络配置和资源。下面链接中的CNI规范概括了用于配制网络的插件接口，这个接口可以让容器运行时与插件进行协调：https://github.com/containernetworking/cni/blob/master/SPEC.md插件负责为接口配置和管理IP地址，并且通常提供与IP管理、每个容器的IP分配、以及多主机连接相关的功能。容器运行时会调用网络插件，从而在容器启动时分配IP地址并配置网络，并在删除容器时再次调用它以清理这些资源。运行时或协调器决定了容器应该加入哪个网络以及它需要调用哪个插件。然后，插件会将接口添加到容器网络命名空间中，作为一个veth对的一侧。接着，它会在主机上进行更改，包括将veth的其他部分连接到网桥。再之后，它会通过调用单独的IPAM（IP地址管理）插件来分配IP地址并设置路由。在Kubernetes中，kubelet可以在适当的时间调用它找到的插件，来为通过kubelet启动的pod进行自动的网络配置。术语在对CNI插件们进行比较之前，我们可以先对网络中会见到的相关术语做一个整体的了解。不论是阅读本文，还是今后接触到其他和CNI有关的内容，了解一些常见术语总是非常有用的。一些最常见的术语包括：第2层网络： OSI（Open Systems Interconnections，开放系统互连）网络模型的“数据链路”层。第2层网络会处理网络上两个相邻节点之间的帧传递。第2层网络的一个值得注意的示例是以太网，其中MAC表示为子层。第3层网络： OSI网络模型的“网络”层。第3层网络的主要关注点，是在第2层连接之上的主机之间路由数据包。IPv4、IPv6和ICMP是第3层网络协议的示例。VXLAN：代表“虚拟可扩展LAN”。首先，VXLAN用于通过在UDP数据报中封装第2层以太网帧来帮助实现大型云部署。VXLAN虚拟化与VLAN类似，但提供更大的灵活性和功能（VLAN仅限于4096个网络ID）。VXLAN是一种封装和覆盖协议，可在现有网络上运行。Overlay网络：Overlay网络是建立在现有网络之上的虚拟逻辑网络。Overlay网络通常用于在现有网络之上提供有用的抽象，并分离和保护不同的逻辑网络。封装：封装是指在附加层中封装网络数据包以提供其他上下文和信息的过程。在overlay网络中，封装被用于从虚拟网络转换到底层地址空间，从而能路由到不同的位置（数据包可以被解封装，并继续到其目的地）。网状网络：网状网络（Mesh network）是指每个节点连接到许多其他节点以协作路由、并实现更大连接的网络。网状网络允许通过多个路径进行路由，从而提供更可靠的网络。网状网格的缺点是每个附加节点都会增加大量开销。BGP：代表“边界网关协议”，用于管理边缘路由器之间数据包的路由方式。BGP通过考虑可用路径，路由规则和特定网络策略，帮助弄清楚如何将数据包从一个网络发送到另一个网络。BGP有时被用作CNI插件中的路由机制，而不是封装的覆盖网络。了解了技术术语和支持各类插件的各种技术之后，下面我们可以开始探索一些最流行的CNI插件了。CNI比较Flannel链接：https://github.com/coreos/flannel由CoreOS开发的项目Flannel，可能是最直接和最受欢迎的CNI插件。它是容器编排系统中最成熟的网络结构示例之一，旨在实现更好的容器间和主机间网络。随着CNI概念的兴起，Flannel CNI插件算是早期的入门。与其他方案相比，Flannel相对容易安装和配置。它被打包为单个二进制文件flanneld，许多常见的Kubernetes集群部署工具和许多Kubernetes发行版都可以默认安装Flannel。Flannel可以使用Kubernetes集群的现有etcd集群来使用API存储其状态信息，因此不需要专用的数据存储。Flannel配置第3层IPv4 overlay网络。它会创建一个大型内部网络，跨越集群中每个节点。在此overlay网络中，每个节点都有一个子网，用于在内部分配IP地址。在配置pod时，每个节点上的Docker桥接口都会为每个新容器分配一个地址。同一主机中的Pod可以使用Docker桥接进行通信，而不同主机上的pod会使用flanneld将其流量封装在UDP数据包中，以便路由到适当的目标。Flannel有几种不同类型的后端可用于封装和路由。默认和推荐的方法是使用VXLAN，因为VXLAN性能更良好并且需要的手动干预更少。总的来说，Flannel是大多数用户的不错选择。从管理角度来看，它提供了一个简单的网络模型，用户只需要一些基础知识，就可以设置适合大多数用例的环境。一般来说，在初期使用Flannel是一个稳妥安全的选择，直到你开始需要一些它无法提供的东西。Calico链接：https://github.com/projectcalico/cni-pluginCalico是Kubernetes生态系统中另一种流行的网络选择。虽然Flannel被公认为是最简单的选择，但Calico以其性能、灵活性而闻名。Calico的功能更为全面，不仅提供主机和pod之间的网络连接，还涉及网络安全和管理。Calico CNI插件在CNI框架内封装了Calico的功能。在满足系统要求的新配置的Kubernetes集群上，用户可以通过应用单个manifest文件快速部署Calico。如果您对Calico的可选网络策略功能感兴趣，可以向集群应用其他manifest，来启用这些功能。尽管部署Calico所需的操作看起来相当简单，但它创建的网络环境同时具有简单和复杂的属性。与Flannel不同，Calico不使用overlay网络。相反，Calico配置第3层网络，该网络使用BGP路由协议在主机之间路由数据包。这意味着在主机之间移动时，不需要将数据包包装在额外的封装层中。BGP路由机制可以本地引导数据包，而无需额外在流量层中打包流量。除了性能优势之外，在出现网络问题时，用户还可以用更常规的方法进行故障排除。虽然使用VXLAN等技术进行封装也是一个不错的解决方案，但该过程处理数据包的方式同场难以追踪。使用Calico，标准调试工具可以访问与简单环境中相同的信息，从而使更多开发人员和管理员更容易理解行为。除了网络连接外，Calico还以其先进的网络功能而闻名。 网络策略是其最受追捧的功能之一。此外，Calico还可以与服务网格Istio集成，以便在服务网格层和网络基础架构层中解释和实施集群内工作负载的策略。这意味着用户可以配置强大的规则，描述pod应如何发送和接受流量，提高安全性并控制网络环境。如果对你的环境而言，支持网络策略是非常重要的一点，而且你对其他性能和功能也有需求，那么Calico会是一个理想的选择。此外，如果您现在或未来有可能希望得到技术支持，那么Calico是提供商业支持的。一般来说，当您希望能够长期控制网络，而不是仅仅配置一次并忘记它时，Calico是一个很好的选择。Canal链接：https://github.com/projectcalico/canalCanal也是一个有趣的选择，原因有很多。首先，Canal 是一个项目的名称，它试图将Flannel提供的网络层与Calico的网络策略功能集成在一起。然而，当贡献者完成细节工作时却发现，很明显，如果Flannel和Calico这两个项目的标准化和灵活性都已各自确保了话，那集成也就没那么大必要了。结果，这个官方项目变得有些“烂尾”了，不过却实现了将两种技术部署在一起的预期能力。出于这个原因，即使这个项目不复存在，业界还是会习惯性地将Flannel和Calico的组成称为“Canal”。由于Canal是Flannel和Calico的组合，因此它的优点也在于这两种技术的交叉。网络层用的是Flannel提供的简单overlay，可以在许多不同的部署环境中运行且无需额外的配置。在网络策略方面，Calico强大的网络规则评估，为基础网络提供了更多补充，从而提供了更多的安全性和控制。确保集群满足必要的系统要求（https://docs.projectcalico.org/v3.6/getting-started/kubernetes/requirements）后，用户需要应用两个manifest才能部署Canal，这使得其配置比单独的任何一个项目都困难。如果企业的IT团队计划改变他们的网络方案，且希望在实施改变之前能先对网络策略进行一些实验并获取一些经验，那么Canal是一个不错的选择。一般来说，如果你喜欢Flannel提供的网络模型，但发现Calico的一些功能很诱人，那么不妨尝试一下Canal。从安全角度来看，定义网络策略规则的能力是一个巨大的优势，并且在许多方面是Calico的杀手级功能。能够将该技术应用到熟悉的网络层，意味着您可以获得更强大的环境，且可以省掉大部分的过渡过程。Weave链接：https://www.weave.works/oss/net/Weave是由Weaveworks提供的一种Kubernetes CNI网络选项，它提供的模式和我们目前为止讨论的所有网络方案都不同。Weave在集群中的每个节点之间创建网状overlay网络，参与者之间可以灵活路由。这一特性再结合其他一些独特的功能，在某些可能导致问题的情况下，Weave可以智能地路由。为了创建网络，Weave依赖于网络中每台主机上安装的路由组件。然后，这些路由器交换拓扑信息，以维护可用网络环境的最新视图。当需要将流量发送到位于不同节点上的pod时，Weave路由组件会自动决定是通过“快速数据路径”发送，还是回退到“sleeve”分组转发的方法。快速数据路径依靠内核的本机Open vSwitch数据路径模块，将数据包转发到适当的pod，而无需多次移入和移出用户空间。Weave路由器会更新Open vSwitch配置，以确保内核层具有有关如何路由传入数据包的准确信息。相反，当网络拓扑不适合快速数据路径路由时，sleeve模式可用作备份。它是一种较慢的封装模式，在快速数据路径缺少必要的路由信息或连接的情况下，它可以来路由数据包。当流量通过路由器时，它们会了解哪些对等体与哪些MAC地址相关联，从而允许它们以更少的跳数、更智能地路由后续流量。当网络更改导致可用路由改变时，这一相同的机制可以帮助每个节点进行自行更正。与Calico一样，Weave也为Kubernetes集群提供网络策略功能。设置Weave时，网络策略会自动安装和配置，因此除了添加网络规则之外，用户无需进行其他配置。一个其他网络方案都没有、Weave独有的功能，是对整个网络的简单加密。虽然这会增加相当多的网络开销，但Weave可以使用NaCl加密(http://nacl.cr.yp.to)来为sleeve流量自动加密所有路由流量，而对于快速数据路径流量，因为它需要加密内核中的VXLAN流量，Weave会使用IPsec ESP来加密快速数据路径流量。对于那些寻求功能丰富的网络、同时希望不要增加大量复杂性或管理难度的人来说，Weave是一个很好的选择。它设置起来相对容易，提供了许多内置和自动配置的功能，并且可以在其他解决方案可能出现故障的场景下提供智能路由。网状拓扑结构确实会限制可以合理容纳的网络的大小，不过对于大多数用户来说，这也不是一个大问题。此外，Weave也提供收费的技术支持，可以为企业用户提供故障排除等等技术服务。结语Kubernetes采用的CNI标准，让Kubernetes生态系统中的网络解决方案百花齐放。更多样的选择，意味着大多数用户将能够找到适合其当前需求和部署环境的CNI插件，同时还可以在环境发生变化时也能找到新的解决方案。不同企业之间的运营要求差异很大，因此拥有一系列具有不同复杂程度和功能丰富性的成熟解决方案，大大有助于Kubernetes在满足不同用户独特需求的前提下，仍然能够提供一致的用户体验。[scode type="blue"]本文转载于公众号“RancherLabs”[/scode]