Hero Image

从底层技术角度看,Pod内不同容器之间共享存储和一些namespace。 PID namespace: Pod中不同应用程序看拿到的其他进程的ID。Sidecar 模式下只能看到一个进程? Network Namespace: Pod 中的多个容器具有相同的网络配置,共享一个端口范围。 IPC Namespace: Pod中的多个容器能够使用SystemV IPC 或 POSIX消息队列进行通信。 UTS Namespace: Pod中的多个容器共享一个主机名。 在Kubernetes的网络模型中,每台服务器上的容器有自己独立的IP段。 为了实现这一目标,重点解决一下两点: 各台服务器上的容器IP段不能重叠,所以需要某种IP段分配机制,为各台机器分配独立的IP段。 从某个Pod发出的流量到达所在的机器的Host上时,机器网络层应当根据目标IP地址,将流量转发到目标机器的能力。 综上,两个能力: IP地址分配和Route. 容器之间直接通信,不需要额外的NAT。 Pod to Pod 所有的Pod之间要保证3层网络的联通性 Pod to Service Servcie 总共有4种类型,其中组常用的就是Cluster IP. 这种类型的Service会分配一个仅集群内可以访问的虚拟IP。 Kubernetes通过kube-proxy组件实现Service Cluster IP的功能。kube-proxy 是一个daemonset,通过复杂的iptables/IPVS 规则在Pod和Service之间进行各种过滤和NAT. Pod到集群外 从Pod内部到集群外的流量,Kubernetes会通过SNAT来处理。 Kubernets 默认的组网方案是bridge,CNI主要是用来解决容器的跨机通信。典型的跨机通信方案有bridge和overlay。 创建Pod时候,首先会创建一个pause容器。占用一个 linux的network namespace。Pod内的其他容器共享这个network namespace。此时,只有一个lo设备。 CNI负责初始化pause container 中的网络设备。 kubernetes主机内组网&跨节点组网 kubernetes 经典的主机内组网模型是veth pair+bridge。 跨机通信一般是bridge + overlay。 vxlan downward API 通过HostAlias修改pod中的/etc/host(Pod在host network下不支持) Pod的隔离中 network namspce 是最先创建的,如果ns使用了host模式,则uts也会使用host模式。 Pause扮演PID 1的角色,并在子进程成为“孤儿进程”时,通过wait() 收割这些僵尸子进程。

Hero Image
K8s network

容器网络 每一个容器都可以有一个自己独立的网络栈,这个独立的网络栈是基于Linux的Network Namespace实现的。 这个独立的网络栈包含了: Network Interface、Loopback Device、Routing Table和IPtables规则。对于一个进程来说,这些要素就构成了它发起和响应网络请求的基本环境。 容器可以使用自己独立的网络栈(创建属于自己的Network Namespace),也可以直接使用Host的网络栈(不创建Network Namespace)。 1# Uset -net=host to share the host network 2docker run -d -net=host --name nginx-host nginx 直接使用Host的网络栈可以提供良好的网络性能,但是不可避免的会引入网络资源共享的问题,比如端口冲突。大多数应用场景下,我们希望容器能够有自己独立的IP地址和端口,即有自己独立的Namespace。 这个时候,就会出现一个问题,在这个被隔离的容器进程中如何与其他的Network Namespace里的容器进程进行交互呢。 一般我们如果希望两台主机之间的通信,直接用网线把这两台主机连接起来即可;而如果是多台主机之间通信我们可以将其连接在同一台交换机上。 在Linux系统中,能够起到虚拟交换机作用的虚拟网络设备是Bridge,是二层网络设备。主要功能是根据MAC地址来将数据包转发到网桥的不同Port上。 为了实现上述目的,docker项目会在Host上创建一个docker0的网桥,凡是连接在docker0网桥上的容器,就相当于在同一个二层网络。 接下来就是如何把容器连接到docker0网桥上,这就需要veth pair的虚拟设备了。veth pair创建出来以后总是以两张虚拟网卡veth peer的形式成对出现的。并且从其中一个peer发出的数据包可以直接出现在与之对应的另一个peer上,即使veth pair的两端不在同一个Network Namespace 中。因此,veth pair常常用作连接不同Network Namespace的网线。

Hero Image
怎么成为K8s的Contributor

Important Doc Contributor Cheat Sheet 加入SIG SIG(Special Interest Groups) 是Kubernetes社区中关注特定模块的永久组织。 作为刚参与社区的开发者,可以从sig/app, sig/node, sig/scheduling 这几个SIG开始。 KEP KEP(Kubernetes Enhancement Proposal)。对于功能和API的修改都需要先在kubernetes/enhancements仓库对应SIG的目录下提交Proposal才能实施。所有的Proposal都必须经过讨论,通过社区SIG Leader的批准。 很多不熟悉Kubernetes工作流的开发者会在社区中直接提交一个包含API改动的commit,但是如果这类commit没有对应的KEP 是不会被社区合入的。 项目设计 所有进入开发状态的功能都会有一个非常详细的KEP。KEP有一个详细的模板,设计是非常规范的。我们再日常的开发中也可以使用类似的格式写设计文档或者技术文档。 最近几年新实现的功能都会有着比较详细的KEP文档 分布式协作 Kubernetes 中所有的社区会议都会使用Zoom录制,并上传到Youtube。大多数的讨论和交流也对会再对应的issue和PR中。 每个提交的PR都要通过2K以上的成员的review以及几千个单元测试、集成测试、端到端测试以及扩展性测试,这些测定共同保证了项目的稳定性。 kubernetes/test-infra 项目中包含了Kubernetes的测试基础配置。 很多端到端的测试都会启动Kubernetes集群,并在真实的环境中测试代码的逻辑,这些测试可能一次会执行几十分钟,并且有一定概率出现Flaky。 影响力 提高个人和公司在开源社区的影响力,也是参与社区的重要目的。 对个人来说,参与开源项目可以快速理解项目的实现原理以及工作流程。如果想要在未来从事相关的工作,参与开源项目一定是加分项。 对公司来说,参与开源项目可以提高公司在开源社区的话语权,提高公司的技术影响力。足够的话语权也会让开源社区在关键需求上有较快的支持,减少与社区代码的分叉,降低维护成本,并满足公司内部的需求。 操作指南 参与开源项目并不一定要从非常复杂的功能或者Proposal开始。任何一个对代码库有利的PR都是值得提交的。修复代码中的typo 或者静态检查错误,作为最开始的工作是没有任何问题的。这能够帮我们快速热身。不过在熟悉了kubernetes的提交流程之后就没有必要做类似的提交了,以为所有的提交都需要Reviewer和Approver的批准,我们应该尽可能的做有意义的变动,减少他们的工作量。 从阅读源码开始 我们可以从自己熟悉的模块入手,了解该模块的实现原理,在阅读代码的过程中,我们很容易发现源代码中的一些typo和缺陷,这个时候就可以提交PR修复这些问题。 从静态检查开始 .golint_failures 文件中忽略了几百个Package中的静态检查,你可以在其中选择合适的Package作为成为Kubernetes贡献者的而第一步。 从项目管理开始 也可以选择Kubernetes的项目管理, sig/release. 选取第一个kubernetes问题 issue 列表 使用tag过滤问题 “good first issue” “help wanted” 这些标签表明了对新手非常友好。有时候问题也会被打上错误标签,也许是技术难度被低估了。 TODO 搜索代码库里的TODO。 Go 语言的开发规范、分布式社区的治理方式 代码需要每天都看,留出专门的时间来查看Kubernetes的源码,对它的核心组件的实现看看,构建一下, 测试一下,修一下Bug,typo等。 一般半年之后,你就可以熟悉基础项目,并且开始贡献代码。 当你已经和团队协作的很熟悉,就会自然承接一些子任务,然后团队就会赋予你写的权限,这样就可以顺理成章的成为Kubernetes的committer。这个时候你就是这个子项目的maintainer了 TODO 加入 Kubenetes Slack Channle 加入邮件列表 加入SIG 参加社区会议 提issue 如何提交PR