kubernetes网络 – 网络插件 – flannel

flannel支持host-gw,vxlan,ipip,ipsec模式和VPC路由模式。 部署 使用下面命令对部署flannel到集群中,会在集群中创建flannel的daemonset和一个flannel的配置文件。 kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml 其中默认配置文件内容如下,主要包含了cni配置和网络配置。其中cni配置为采用flannel cni,指定网桥名称为cbr0,打开网桥接口的haripin模式,并将网桥设置为默认的网关。这些参数的含义可参考后面cni部分。 默认也指定了集群的网络模式为vxlan,使用flannel cni,并配置了整个网络的网段。 kind: ConfigMap apiVersion: v1 metadata: name: kube-flannel-cfg namespace: kube-system labels: tier: node app: flannel data: cni-conf.json: | { "name": "cbr0", "cniVersion": "0.3.1", "plugins": [ { "type": "flannel", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true } } ] } net-conf.json: | { "Network": "10.248.0.0/13", "Backend": { "Type": "vxlan" } } cni插件 cni要解决的问题是本机如何访问pod以及外部主机进来的数据包怎么进入pod。使用flannel作为网络插件的话,可选两种cni插件,其一是flannel…

kubernetes网络 – ingress资源

ingress主要用来将集群内的http服务暴露到集群外。ingress提供负载均衡,ssl/tls终结和基于名称的虚拟服务器功能。 下图是ingress架构图: ingress用来暴露http和https服务,如果是其他的服务协议,无法通过ingress进行暴露,需要使用nodeport或者loadbalancer类型的服务。 ingress控制器 要使用配置ingress,需要集群内存在ingress控制器,ingress控制器负责将ingress的定义配置到具体的控制器服务上。kubernetes支持的ingress控制器参考: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/ 此处我们使用nginx-ingress进行配置和演示,参考下面文档进行安装配置: https://github.com/kubernetes/ingress-nginx/tree/main/charts/ingress-nginx kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.3/deploy/static/provider/baremetal/deploy.yaml kubectl annotate ingressclasses nginx ingressclass.kubernetes.io/is-default-class=true # 改成LoadBalancer类型 kubectl edit svc -n ingress-nginx ingress-nginx-controller # 修改deployment # - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller # - --enable-ssl-passthrough kubectl edit deployments.apps -n ingress-nginx ingress-nginx-controller # 创建测试应用 kubectl apply -f https://github.com/istio/istio/blob/1.11.3/samples/helloworld/helloworld.yaml ingress 创建ingress资源进行测试。 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: minimal-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - http: paths: - path: /hello pathType: Prefix backend: service: name:…

kubernetes网路 – 服务与DNS

kubernetes会为每个service对象创建dns记录,这个操作是由dns插件完成的,基本上所有集群都会使用coredns作为dns插件。 kubernetes中的服务是区分命名空间的,nginx这个域名在默认情况下是使用本pod所在namespace解析的,如pod所在的namespace为default,则默认解析为nginx.default。下列是一个示例pod的resolv文件配置 [root@master1 ~]# kubectl exec -it nginx-deployment-66b6c48dd5-95c7f -- cat /etc/resolv.confnameserver 172.17.0.10search default.svc.cluster.local svc.cluster.local cluster.localoptions ndots:5 服务对象分为普通服务和无头服务,无头服务是指spec.clusterIP=None的,其他服务则为普通服务。 如果service是一个普通服务对象,则会为其创建一个dns A记录(ipv6则为AAAA记录),该记录的ip地址是在kube-controller-manager的--service-cluster-ip-range参数指定的网段内,该网段和pod网段以及节点网段都不在一个网段内。 如果service是一个无头服务,则会创建一些列dns A记录,记录的ip地址是pod的ip。 k8s还会为服务对象的每个命名端口创建srv记录。如_my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster-domain.example。对于普通服务,解析到my-svc.my-namespace.svc.cluster-domain.exampl加端口号。对于无头服务会为每个pod创建一个类似的记录。auto-generated-name.my-svc.my-namespace.svc.cluster-domain.example加端口号。 通常情况下,会为所有pod创建如下类型的dns解析: pod-ip-address.my-namespace.pod.cluster-domain.example -> pod-ip kubectl run aaaa --image=nginx [root@master1 ~]# nslookup 10-248-5-2.default.pod.cluster.local 172.17.0.10 Server: 172.17.0.10 Address: 172.17.0.10#53 ​ Name: 10-248-5-2.default.pod.cluster.local Address: 10.248.5.2 通常情况下,会为deployment和daemonset的pod,且通过service进行暴露的话,则会创建下列dns解析: pod-ip-address.deployment.my-namespace.svc.cluster.local -> pod-ip 针对deployment进行测试 kubectl create deployment nginx --image=nginx kubectl expose deployment nginx --port 80 [root@master3 ~]# nslookup nginx.default.svc.cluster.local 172.17.0.10 Server: 172.17.0.10 Address: 172.17.0.10#53 ​…

kubernetes网络 – 服务概念

kubernetes中服务主要用来进行服务发现和负载均衡。 在集群中我们的工作负载是不稳定的,ip地址可能随着pod重启,升级和扩容等不断发生变化,为了能够让其他工作负载可以稳定访问到这个工作负载,我们需要为其创建一个服务对象。 服务对象也是一个api资源对象,和其他api对象定义方法相同,下面是一个服务对象的定义: apiVersion: v1 kind: Service metadata: name: nginx spec: selector: # 根据标签选择pod app: nginx # type: ClusterIP # clusterIP: 192.168.3.251 ports: # TCP, UDP, SCTP - protocol: TCP appProtocol: http name: nginx-http port: 80 targetPort: 80 # 支持多个端口配置 - name: https protocol: TCP port: 443 targetPort: 9377 externalTrafficPolicy: Cluster 这个服务对象会创建一个service资源,服务控制器会根据我们的selector选择对应的pod,创建endpoint后endpointslice资源关联到这个服务。服务控制器还会为我们的服务自动创建一个虚拟ip地址,其他工作负载使用这个虚拟ip地址访问这个服务。endpoint资源代表后端真正的服务实例,它关联到pod,访问到虚拟ip的流量会转到对应的后端pod对应的端口上。 通过selector可以让kunbernetes根据标签自动选择pod并创建endpoint关联到service。有些场景我们也可以不使用selector,例如: 引用已有服务的ip列表 apiVersion: v1 kind: Service metadata: name: my-service spec: ports: - protocol: TCP port: 443 targetPort: 6443…

kubernetes网络 – 集群网络原理分析

vxlan网络 vxlan是一种基于3层网络实现的2层overlay网络。vxlan网络可以使用VNI划分出多个彼此隔离的网络,可应用于多租户场景。 vxlan可以结合bridge一起来使用,相当于使用vxlan将多个主机上的bridge连接起来形成一个大的逻辑上的bridge设备。也可以不使用bridge,而是结合路由使用。下图是结合路由或bridge使用的场景示例: 在kubernetes环境中,可以使用简单的路由方式。内核在vxlan数据包解包后将原始二层数据给到了vxlan设备去接收,vxlan设备将数据包送入到上层网络协议栈。网络协议栈根据主机上的路由表配置,将包发给相应pod的网卡。 在这种路由模式下,节点上不需要知道其他所有pod的mac地址,只需要节点上对应的网关的地址的mac。数据包通过vxlan设备发送和接收的大致流程如下: 数据发送: 数据包从pod1发出,进入peer网卡的接收队列,然后到达node1的协议栈,经过路由判决,走node1的forward链。 forward时,要去的pod2的IP为172.16.2.1,主机路由匹配到应该走vxlan设备,下一跳为172.16.2.0。 数据包到达vxlan设备,查询路由表得知网关地址为172.16.2.0,于是通过arp协议查找网关的mac地址,在arp表中找到了匹配的记录后完成mac头封装,准备发送。 vxlan设备发送数据包并不是提交到发送队列,而是调用udp隧道相关接口将数据包封装成一个udp数据包,接着会查询fdb表查找要将数据从那个VTEP接口发出,经过查找后得到的VTEP接口为192.168.56.2,从而将数据包发送node2节点 。 数据接收: node2接收后,走主机协议栈,判断这是发往本机的udp包,于是走INPUT方向,最终发到UDP隧道层处理。 当创建vxlan创建udp隧道时,会将其接收数据包方法覆盖为vxlan的接收方法,所以在收到vxlan的UDP数据包后,进行对vxlan包解包,之后调用网卡的接收数据包方法进行接收原始二层数据包,此时如果vxlan设备被加入到了bridge设备,那么这个数据包会由bridge设备收到,bridge设备决定进行二层抓发或是送入上层网络协议栈。如果没有加入bridge中,那么如果目的mac地址是自己的也会送入上层网络协议栈。 进入上层网络协议栈后,就会根据主机的路由判断是入站还是转发,发现目标地址是172.16.2.1,经过路由判决时,发现不是本机地址,进行转发,找到相应的路由通过veth-pairhost端发出,从而进入pod。 下面,我们通过一些列命令手动创建和管理vxlan设备,进行测试vxlan相关功能,此处我们采用纯路由方式。 首先在第一台主机上先创建vxlan设备,配置路由: set -ux sysctl -w net.ipv4.ip_forward=1 sysctl -w net.ipv4.conf.all.proxy_arp=1 sysctl -w net.ipv4.conf.all.rp_filter=0 iptables -A FORWARD -d 172.16.0.0/16 -j ACCEPT iptables -A FORWARD -s 172.16.0.0/16 -j ACCEPT ​ ip link add vxlan.1 type vxlan vni 1 ip link set vxlan.1 up ip addr add 172.16.1.0/32 dev vxlan.1 ip route add 172.16.2.0/24 via 172.16.2.0 dev vxlan.1…

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,…

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…