kubernetes网络 – kube-proxy详解

kube-proxy是kubernetes中网络核心组件,实现了服务暴露和转发等网络功能。如前面章节讲到,kube-proxy支持用户空间模式,ipvs和iptables三种代理模式。用户空间模式性能问题较严重,基本不再使用,应用最多的是iptables和ipvs模式。如果启动时不指定具体使用哪种模式,当前版本kube-proxy会优先使用iptables模式,如果探测到系统不支持则回滚到用户空间模式。当然,如果指定了ipvs模式,但是系统不支持的话也会回滚到iptables模式。 kube-proxy通过apiserver监听service和endpoint资源的变化,并动态更新网络配置规则。当前iptables应该是应用较多的模式,因此本节主要针对iptables规则进行分析。对于ipvs模式来说也并不是不需要iptables规则,在下列情况的时候还是会依赖iptables的规则实现相关功能:参考这里。在本节对iptables规则进行分析之后,可以按照这种方式再去分析ipvs相关规则配置,在分析ipvs规则时也需要要求我们熟悉ipvs和ipset等。 在kubernetes网络中,还有其他网络插件实现了和kube-proxy相同的功能,若kube-router,cilium,他们都支持kube-proxy实现的功能,因此在使用上述网络插件时,集群里可以不部署kube-proxy。 kube-proxy在同步iptables规则时是通过iptables-save方式获取当前的规则,然后根据集群内的service状态动态对已有规则进行更新,最后使用iptables-save将规则在配置到系统上。kube-proxy重启不会影响到新建链接和已有链接的状态。在删除已有service,kube-proxy还会释放相关的链接,以及对不同协议的额外处理操作,这里不做太多分析。 下面是一个固定nginx的service的来进行分析iptables规则。 [root@master1 ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 172.17.0.1 <none> 443/TCP 79d nginx LoadBalancer 172.17.45.122 192.168.64.1,4.3.2.1 80:30935/TCP 3d5h [root@master1 ~]# kubectl edit svc nginx Edit cancelled, no changes made. [root@master1 ~]# kubectl get svc nginx -oyaml apiVersion: v1 kind: Service metadata: creationTimestamp: "2021-10-16T05:55:09Z" labels: app: nginx name: nginx namespace: default resourceVersion: "619828" uid: 58ad25b5-6ee0-4a10-8c60-3a4371db1bbc spec: clusterIP: 172.17.45.122 clusterIPs: - 172.17.45.122…

kubernetes网络 – iptables讲解

iptables命令用来管理ip数据包的过滤。iptables由命令行工具和一系列内核模块组成,iptables命令行工具用来管理规则配置,内核模块负责执行具体的规则。iptables内核模块依托于linux的netfilter网络框架,netfilter框架提供了一系列的网络钩子,ip数据包在经过网络协议栈的时候会触发这些钩子以执行注册到这些钩子上的函数。iptables内核模块会在这些钩子上注册处理函数来实现对ip数据包的过滤等。 netfilter中提供了ip钩子,ipv6钩子,arp钩子和bridge钩子等,都有对应的命令行工具和内核模块,如ip6tables,ebtables等,可以为不同网络层提供过滤功能,关于这些不同的功能,可以参考对应的文档查看。我们主要关心iptables,来看下netfilter中包含的ip钩子: NF_IP_PRE_ROUTING ip数据包达到网络协议栈后最先触发的是这个钩子,在还未执行路由决策之前触发。 NF_IP_LOCAL_IN 在linux对ip数据包执行了路由之后,如果目的地是给本地系统时触发。 NF_IP_FORWARD 在linux对ip数据包执行了路由之后,如果需要转发给其他主机时触发。 NF_IP_LOCAL_OUT 本地数据包将要从本地发出时触发。 NF_IP_POST_ROUTING 在任何本地发出的或本地进行转发的数据包将要在网络设备发发出时触发。 ip数据包在netfilter框架中会经过上面的钩子进行处理,iptables内核模块在这些钩子上注册了不同的处理函数,可以对数据包进行处理。iptables中包含这几种对数据包的处理功能: 包过滤,主要用来实现防火墙功能 包修改,修改数据包中的信息 网络地址转换,实现网络地址转换功能 表、链和目标 iptables中有不同类型的表:默认的filter表,nat表,mangle表raw表,每张表里存放不同类型的规则。 不同的表中还包含不同的链,可以是内置的链或用户自定义的链,内置的链包括:INPUT,PREROUTING,FORWARD,POSTROUTING,OUTPUT,这些是和netfilter中的钩子相对应的,是执行我们规则的入口。 每个链中又包含不同的规则,规则定义如何对数据包进行匹配,以及匹配之后要执行的目标动作,这些动作可以是跳转到用户的自定义链或者是内置的ACCEPT,DROP,RETURN,还可以是扩展模块中的,如REJECT,MARK等。这些目标可以分为终结和非终结型,终结型规则在执行完之后不会再匹配接下来规则,如ACCEPT,DROP,REJECT,MASQUERADE(nat的都是),而非终结类型再执行完当前规则后还会继续匹配后面的规则,如MARK,LOG。链中的规则匹配是按照顺序机型匹配执行的,如果当前规则不匹配则会一直匹配下一条规则,直到终结或匹配结束。 ACCEPT是允许数据包通过。DROP是丢弃数据包。RETURN是从当前链返回到调用该链的上层链中的下一条继续匹配。如果是内置链,则当匹配结束,或有规则使用了RETURN作为目标动作时,则使用这个内置链的策略决定是否允许通过。 关注Network Layer,以及注意图中包的路径,表的先后顺序。 命令行工具 iptables规则表,链和规则的关系为:table <-> chain -> rule。 指定表 -t, --table table 指定要操作的表,如果不指定这个参数则操作默认的filter表,针对所有命令生效。 默认策略 -P, --policy chain target 指定内置表的默认策略,target必须是ACCEPT或DROP。 链操作 -L, --list [chain]列出指定链内的规则,如果chain未指定,则列出该表下的所有规则。可以和-n选项结合使用,来讲ip地址和端口以数字形式显示。可以和--line-numbers结合使用,显示行号。 -S, --list-rules [chain]列出指定链内的规则,如果chain未指定,则列出该表下的所有规则。该命令以定义规则所使用的命令方式展示。 -F, --flush [chain]清空指定链内的规则(链仍然保留),如果chain未指定,则清空该表下的所有规则。 -N, --new-chain chain创建新的链。 -X, --delete-chain [chain]删除用户自定义链。被删除的链不能有其他链引用,被删除的链必须为空,即里面没有规则。如果不指定chain的话将会尝试删除所有的用户自定义链。 -E, --rename-chain old-chain new-chain修改链的名称。 规则操作 -A, --append chain rule-specification添加规则到链中。 -C, --check chain rule-specification测试指定规则是否存在 -D,…

golang中的单向channel和nil值channel

在阅读client-go代码时发现源码对channel的部分使用方式不太理解,一个是单项channel的使用,一个是nil值channel的使用,于是搜索总结一下。 在golang中可以定义channel为双向的,也可以将channel定义为只能接收或只能发送类型的,如下面所示: // You can edit this code! // Click here and start typing. package main func main() { // 普通双向的 var normalCh chan interface{} // 只能发送 var sendOnlyCh chan<- interface{} // 只能接收 var receiveOnlyCh <-chan interface{} <-sendOnlyCh receiveOnlyCh <- 1 } 编译上述代码,将会得到下列错误: ./prog.go:12:2: invalid operation: <-sendOnlyCh (receive from send-only type chan<- interface {}) ./prog.go:13:16: invalid operation: receiveOnlyCh <- 1 (send to receive-only type <-chan interface {}) Go build failed.…

haproxy+keepalived配置示例

在非云环境中,要实现服务的高可用和负载功能一般会使用haproxy+keepalived方案,通过使用vrrp管理vip地址的的自动漂移,以及通过haproxy实现服务的负载功能。除了vrrp协议,还需要确保我们的主机网络中支持无偿arp,以保证我们的路由器或其他主机能够正确的将vip地址解析到正确的mac地址。在下图中,采用两个服务器安装keepalived+haproxy进行主备部署,后面有三台独立的RS服务器,当然keepalived本身也可以和RS服务部署在同一台服务器上。 下面是针对haproxy的配置,我们要配置haproxy直接绑定的虚拟vip地址的话,需要开启ip_nonlocal_bind这个配置项,如果监听的是0.0.0.0地址的话就无所谓: [root@master3 ~]# echo net.ipv4.ip_nonlocal_bind=1 /etc/sysctl.d/haproxy-keepalived.conf [root@master3 ~]# sysctl -p /etc/sysctl.d/haproxy-keepalived.conf [root@master3 ~]# cat /etc/haproxy/haproxy.cfg #--------------------------------------------------------------------- # Example configuration for a possible web application. See the # full configuration options online. # # http://haproxy.1wt.eu/download/1.4/doc/configuration.txt # #--------------------------------------------------------------------- #--------------------------------------------------------------------- # Global settings #--------------------------------------------------------------------- global # to have these messages end up in /var/log/haproxy.log you will # need to: # # 1) configure syslog to accept network log events. This is done…

bpg协议简要介绍

边界网关协议(英语:Border Gateway Protocol,缩写:BGP)是互联网上一个核心的去中心化自治路由协议。它通过维护IP路由表或“前缀”表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议。 大多数互联网服务提供商必须使用BGP来与其他ISP创建路由连接(尤其是当它们采取多宿主连接时)。因此,即使大多数互联网用户不直接使用它,但是与7号信令系统——即通过PSTN的跨供应商核心响应设置协议相比,BGP仍然是互联网最重要的协议之一。特大型的私有IP网络也可以使用BGP。例如,当需要将若干个大型的OSPF(开放最短路径优先)网络进行合并,而OSPF本身又无法提供这种可扩展性时。使用BGP的另一个原因是其能为多宿主的单个或多个ISP网络提供更好的冗余。 AS就是一个独立管理的网络。大公司或者组织的网络一般是由一到多个AS组成,小的公司或者个人是通常会接入到ISP(Internet Service Provider)的AS。不管怎么样,如果设备在互联网上,那么必定是属于某一个AS。EBGP是用来连接各个AS,这样互联网上的设备的才能够彼此互连。AS之间的连接协议,目前在用的,有且仅有EBGP一种。 在bgp网络中,具有相同AS号的peer称为IBGP(internal peer),而具有不同AS号的peer称为EBGP(external peer)。IBGP应用在AS内部,作为IGP的一种。一般的IGP,例如OSPF,EIGRP,用来在邻接路由器之间传递路由。而IBGP可以用来在edge router之间同步路由,edge router并不需要邻接。Edge router是指在AS边缘,用来连接其他AS的router,那么edge router肯定是运行了EBGP。同时这个edge router也会有对端AS的路由。通过IBGP,edge router会将学习到的对端AS的路由,传递给其他的edge router。这样,可以实现跨AS的连通。 bgp使用使用tcp 179端口就行通信,消息格式按照TLV形式构成,其中T是消息类型,L是消息长度,V是具体的消息。bgp-4(针对ipv4路由,参考rfc2858查看ipv6和其他协议路由)中一共定义了4个核心消息类型,分别为OPEN,UPDATE,KEEPALIVE,NOTIFICATION。其中OPEN用来在建立peer链接时使用,此处还有一个扩展协议rfc2842定义了基于OPEN消息的扩展属性,给双方提供的协商自身能力的能力;UPDATE用来更新和撤销路由信息,KEEPALIVE用来维护peer链接的心跳,NOTIFICATION用来在出错时进行通知,在rfc2918中还定义了一个ROUTE-REFRESH类型的消息,用来实现路由的全量刷新。 UPDATE用来在peer之间进行路由的更新和撤销操作,其中最重要的是UPDATE消息,其消息的格式参考如下: UPDATE消息用来向peer端公布(advertise)可行的具有相同路径属性的路由,或者撤销不再 可行的路由。单条UPDATE消息既可以公布路由,也可撤销之前公布的路由。 +-----------------------------------------------------+ | 撤销的路由信息长度(2字节) | +-----------------------------------------------------+ | 撤销的路由信息(变长) | +-----------------------------------------------------+ | 路径属性信息长度(2字节) | +-----------------------------------------------------+ | 路径属性(变长) | +-----------------------------------------------------+ | 网络层可达性信息(NLRI)(变长) | +-----------------------------------------------------+ 撤销的路由信息长度: 两字节无符号整形,标识撤销的路由信息的数据总长度。通过该值可以定位到NLRI 在数据流中的位置。 0值意味着没有路由信息被撤销,那么撤销的路由信息不包含在这条消息中。 撤销的路由信息: 可变长度的字段,包含了正在被撤回的IP地址前缀列表。每个IP地址前缀使用二元组 <长度,前缀表示,含义如下: +---------------------------+ | 长度(1字节) | +---------------------------+ | 前缀(变长) | +---------------------------+ 这两个字段的含义如下: a) 长度: 表示IP地址前缀的bit位是多少,0值表示匹配所有IP地址。 b) 前缀: IP地址前缀,后面跟随着一些bit位用来进行字节对其,这些用来补齐的bit没有 实际用途,值无所谓。 路径属性信息长度: 这是一个两字节编码的无符号证书表示路径属性信息的数据总长度,通过该值可以定位…

eBPF技术介绍

最近在看cilium和calico关于eBPF功能,发现有许多不理解的地方,比如概念原理等,因此花费了一定的时间进行了学习和整理,翻了不少文档和博客,最后发现还是cilium社区的这篇文章讲解的最通透,希望后来人可以静下心来把这篇文章慢慢读下来并理解。开始方向错了,其实主要两条线,一个是基于llvm的c语言编写eBPF程序,涉及到一些宏,段定义,maps定义,btf等,llvm按照一定规范为我们编译和生成elf格式的文件,另一个是iproute2/bpftool等加载器将eBPF程序加载到内核,加载工具会读取elf中的各种段信息,将其加载到内核中,此处也会涉及段名称的约定,加载工具与编译器对于btf之间的约定。明白这两块之后再看内核提供的相关辅助函数和不同的map就可以做一些特定功能的bpf程序开发了。 简介 BPF(Berkeley Packet Filter ),中文翻译为伯克利包过滤器,是类 Unix 系统上数据链路层的一种原始接口,提供原始链路层封包的收发。1992 年,Steven McCanne 和 Van Jacobson 写了一篇名为《BSD数据包过滤:一种新的用户级包捕获架构》的论文。在文中,作者描述了他们如何在 Unix 内核实现网络数据包过滤,这种新的技术比当时最先进的数据包过滤技术快 20 倍。BPF 在数据包过滤上引入了两大革新: 一个新的虚拟机 (VM) 设计,可以有效地工作在基于寄存器结构的 CPU 之上; 应用程序使用缓存只复制与过滤数据包相关的数据,不会复制数据包的所有信息。这样可以最大程度地减少BPF 处理的数据; 由于这些巨大的改进,所有的 Unix 系统都选择采用 BPF 作为网络数据包过滤技术,直到今天,许多 Unix 内核的派生系统中(包括 Linux 内核)仍使用该实现。 2014 年初,Alexei Starovoitov 实现了 eBPF(extended Berkeley Packet Filter)。经过重新设计,eBPF 演进为一个通用执行引擎,可基于此开发性能分析工具、网络数据包过滤、系统调用过滤,系统观测和分析等诸多场景。eBPF 最早出现在 3.18 内核中,此后原来的 BPF 就被称为经典 BPF,缩写 cBPF(classic BPF),cBPF 现在已经基本废弃。现在,Linux 内核只运行 eBPF,内核会将加载的 cBPF 字节码透明地转换成 eBPF 再执行。 eBPF 新的设计针对现代硬件进行了优化,所以 eBPF 生成的指令集比旧的 BPF 解释器生成的机器码执行得更快。扩展版本也增加了虚拟机中的寄存器数量,将原有的 2 个 32 位寄存器增加到 10…

kubernetes基础 – 使用kubeadm部署kubernetes集群

环境信息 ​ 主机名 内网ip 公网ip 负载均衡器 master1 192.168.3.29 x.x.x.x 192.168.3.33:6443 *:6443 master2 192.168.3.30 n/a master3 192.168.3.31 n/a node1 192.168.3.27 n/a n/a node2 192.168.3.32 n/a n/a node3 192.168.3.28 n/a n/a 主机操作系统版本为CentOS 7.9。 配置基础环境 cat /etc/hosts ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ​ 192.168.3.29 master1 192.168.3.30 master2 192.168.3.31 master3 192.168.3.27 node1 192.168.3.32 node2 192.168.3.28 node3 # 生成known_hosts ssh-keyscan -t rsa -f /etc/hosts >> ~/.ssh/known_hosts 配置master1节点到其他节点的免密登录 ssh-keygen yum install -y…

kubernetes网络 – linux网络基础设施

在介绍之前,先来熟悉一下linux给我们提供的一些基础设备。回顾一下之前cni与pod网络中的测试用例。 [root@localhost ~]# ip link add name testbr type bridge [root@localhost ~]# ip link add name veth1 type veth peer name br-veth1 [root@localhost ~]# ip link add name veth2 type veth peer name br-veth2 [root@localhost ~]# ip netns add test1 [root@localhost ~]# ip netns add test2 [root@localhost ~]# ip link set netns test1 dev veth1 [root@localhost ~]# ip link set netns test2 dev veth2 [root@localhost ~]# ip link set master…

linux的proxy_arp和arp_filter参数解释

proxy_arp和arp_filter用来控制是否对arp请求作出响应,在正常情况下,如果收到arp请求,且请求的ip地址为网卡自身的ip地址时都会回复。那么当ip地址不是网卡自身的ip地址时是否进行回复则取决于这两个参数的配置,使用网卡自身的mac地址回复。两个参数的官方文档解释如下: arp_filter 1 – 允许主机上拥有同一个子网的多个网卡,对于每个接口上收到的arp请求是否进行回复取决于当本机向发出arp请求的那个客户端的源ip发数据包时,这个数据包是否会从当前接收到请求的接口发出。如果是则回复,否则不回复。 0 – 本机有那个ip地址的话则会回复(其实是看路由,网卡配置ip地址后再local表里自动创建一条路由)。 proxy_arp 是否开启arp代理,开启arp代理的话则会以自己的mac地址回复arp请求,0为不开启,1则开启。 在开启了proxy_arp的情况下,如果请求中的ip地址不是本机网卡接口的地址:但是有该地址的路由,则会以自己的mac地址进行回复;如果没有该地址的路由,不回复。 如果开启了arp_filter,请求中的ip地址是本机接口的地址:如果且当我们向发起arp请求的客户端回复的包也通过当前网卡出去的话则进行回复;如果回包时不走当前网卡则不会进行回复。 下面通过一小段命令来测试,首先准备一个veth-pair和netns。 ip netns add test1 ip link add name veth0 type veth peer name host-veth0 ip link set host-veth0 up ip link set veth0 netns test1 ip netns exec test1 ip link set veth0 up ip netns exec test1 ip addr add 10.0.0.1 dev veth0 ip netns exec test1 ip route add default dev veth0 ip link add…

kubernetes网络 – cni与pod网络

pod网络 kubernetes中每个pod都拥有自己的ip地址,pod内的所有容器实例都共享同一个网络命名空间,因此容器实例之间可以通过localhost地址进行通信,并且他们都可以看到同样的ip地址和mac地址。 kubernetes对于pod的网络定制了下列三个要求,所有网络插件支持这几个要求即可: 所有节点上所有的pod可以互相通信,并且不依赖NAT 节点上的进程可以和该节点上的所有pod通信 运行在主机网络空间下的pod可以和所有节点上的所有pod互相通信,并且不依赖NAT 网络插件 cni代表容器网络接口,是CNCF社区下的一个项目,定义了一系列的接口格式,来规范容器的网络接口的配置。 kubernetes支持两种网络插件配置模式,分别为 cni kubenet kubenet 其中kubenet是一个非常简单的网络插件,并且只支持linux。本身不提供跨节点的网络通信以及网络策略功能。通常是要和云控制器结合起来去使用的。kubenet模式下,kubelet会创建一个叫做cbr0的网桥设备,并未每个pod创建一个veth-pair(虚拟接口对),一端在容器内,一端在容器外,在容器外的接口加入到这个网桥(二层)中。节点上所有的pod都通过主机上的接口连接到网桥,因此针对单个节点上的pod是可以互相通信的。 可以通过以下示例进行简单测试验证: echo 1 > /proc/sys/net/ipv4/conf/all/accept_local echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter echo 1 > /proc/sys/net/ipv4/conf/default/accept_local echo 0 > /proc/sys/net/ipv4/conf/default/rp_filter echo 0 > /proc/sys/net/bridge/bridge-nf-call-iptables ip link add testbr type bridge ip link set testbr promisc on ip link set testbr up ip netns add test1 ip netns add test2 ip link add veth1 type veth peer br-veth1 ip link add…