在k8s中,我们的应用会以pod的形式被调度到各个node节点上,在设计集群如何处理容器之间的网络时是一个不小的挑战,今天我们会从pod(应用)通信来展开关于k8s网络的讨论。

小作文包含如下内容:

  • k8s网络模型与实现方案
  • pod内容器通信
  • pod与pod通信
  • pod与service通信
  • 外网与service通信

k8s网络模型与实现方案

k8s集群中的每一个Pod(最小调度单位)都有自己的IP地址,即ip-per-pod模型

ip-per-pod模型中每一个pod在集群中保持唯一性,我们不需要显式地在每个 Pod 之间创建链接, 不需要处理容器端口到主机端口之间的映射。从端口分配、命名、服务发现、 负载均衡、应用配置和迁移的角度来看,Pod 可以被视作独立虚拟机或者物理主机。

如下图,从表面上来看两个容器在docker网络与k8s网络中与client通信形式。

k8s是一套庞大的分布式系统,为了保持核心功能的精简(模块化)以及适应不同业务用户的网络环境,k8s通过CNI(Container Network Interface)即容器网络接口集成各种网络方案。这些网络方案必须符合k8s网络模型要求:

  • 节点上的 Pod 可以不通过 NAT 和其他任何节点上的 Pod 通信
  • 节点上的代理(比如:系统守护进程、kubelet)可以和节点上的所有Pod通信

备注:仅针对那些支持 Pods 在主机网络中运行的平台(比如:Linux):

  • 那些运行在节点的主机网络里的 Pod 可以不通过 NAT 和所有节点上的 Pod 通信

如此操作,是不是有点像美团?将配送业务外包(CNI)给三方公司(实现方案),骑手是通过哪种飞机大炮(网络)送餐的我不管,只要符合准时、不撒漏(模型要求)等相关规矩这就是一次合格的配送。

CNI 做两件事,容器创建时的网络分配,和当容器被删除时释放网络资源。 常用的 CNI 实现方案有 Flannel、Calico、Weave以及各种云厂商根据自身网络推出的CNI插件如华为的 CNI-Genie、阿里云Terway。关于各实现方案的原理不是本次讨论重点,有机会单独写一篇。


pod内容器通信

Pod内容器非常简单,在同一个 Pod 内,所有容器共享存储、网络即使用同一个 IP 地址和端口空间,并且可以通过 localhost 发现对方。Pod 使用了一个中间容器 Infra,Infra 在 Pod 中首先被创建,而其他容器则通过 Join Network Namespace 的方式与 Infra 容器关联在一起。

我们有一个pod包含busybox、nginx这两个容器

kubectl get pod -n training
NAME READY STATUS RESTARTS AGE
pod-localhost-765b965cfc-8sh76 2/2 Running 0 2m56s

在busybox中使用telnet连接nginx容器的 80端口看看。

kubectl exec -it  pod-localhost-765b965cfc-8sh76 -c container-si1nrb -n training -- /bin/sh

# telnet localhost 80
Connected to localhost

一个pod有多个容器时可以通过-c指定进入的容器名(通过describe查看容器名称),显然通过localhost就可以轻松访问到同一个pod中的nginx容器80端口。这也是在许多关系密切的应用中通常会部署在同一个pod中。


pod与pod通信

  1. pod在同一主机

我们通过node选择器将两个pod调度到同一个node中

 ...
nodeSelector:
kubernetes.io/hostname: node2
...

两个容器分别获得一个IP地址,同样通过IP地址双方网络正常互通。

# kubectl get pod -o wide -n training
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-to-pod-64444686ff-w7c4g 1/1 Running 0 6m53s 100.82.98.206 node2 <none> <none>
pod-to-pod-busybox-7b9db67bc6-tl27c 1/1 Running 0 5m3s 100.82.98.250 node2 <none> <none>
# kubectl exec -it pod-to-pod-busybox-7b9db67bc6-tl27c -n training -- /bin/sh
/# telnet 100.82.98.206 80
Connected to 100.82.98.206

同一主机网络的pod互通和我们之前学习的docker bridge相似,通过linux网桥添加虚拟设备对veth pair连接容器和主机主机命名空间。具体可查看文章《docker容器网络bridge》。

我们把之前的图拿过来,在k8s中只不过把灰色部分替换成CNI方案实现。

  1. pod在不同主机

此时我们的pod分布如下:

kubectl get pod -o wide -n training
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod-to-pod-64444686ff-w7c4g 1/1 Running 0 104m 100.82.98.206 node2 <none> pod-to-pod-busybox-node2-6476f7b7f9-mqcw9 1/1 Running 0 42s 100.91.48.208 node3 <none> # kubectl exec -it pod-to-pod-busybox-node2-6476f7b7f9-mqcw9 -n training -- /bin/sh
/ # telnet 100.82.98.206 80
Connected to 100.82.98.206

pod在不同主机的通信依赖于CNI插件,这里我们以Calico为例的做简单了解,从Calico架构图中可以看到每个node节点的自身依然采用容器网络模式,Calico在每个节点都利用Linux 内核实现了一个高效的虚拟路由器vRouter来负责数据转发。每个虚拟路由器将路由信息广播到网络中,并添加路由转发规则。同时基于iptables还提供了丰富的网络策略,实现k8s的Network Policy策略,提供容器间网络可达性限制的功能。

简单理解就是通过在主机上启动虚拟路由器(calico node),将每个主机作为路由器使用实现互联互通的网络拓扑。

Calico节点组网时可以直接利用数据中心的网络结构(L2或者L3),不需要额外的NAT、隧道或者Overlay Network,没有额外的封包解包,能够节约CPU运算,提高网络效率。


pod与service通信

我们知道在k8s中容器随时可能被摧毁,pod的IP显然不是持久的,会随着扩展或缩小应用规模、或者应用程序崩溃以及节点重启等而消失和出现。service 设计就是来处理这个问题。service可以管理一组 Pod 的状态,允许我们跟踪一组随时间动态变化的 Pod IP 地址。而客户端只需要知道service这个不变的虚拟IP就可以了。

我们先来看看典型的service与pod使用,我们创建了一个service,标签选择器为app:nginx,将会路由到app=nginx标签的Pod上。

# kubectl get service -n training
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
training-service ClusterIP 10.96.229.238 <none> 8881/TCP 10m

Service对外暴露的端口8881,这样在集群的中的pod即可通过8881访问到与service 绑定的label为app=nginx的pod

kubectl run -it --image nginx:alpine curl --rm /bin/sh
/ # curl 10.96.229.238:8881
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
...

其实大多数时候在自动化部署服务时并不知道service ip,所以另一种常见方式通过DNS进行域名解析后,可以使用“ServiceName:Port”访问Service,可以自己尝试一下。

service 是如何做到服务发现的?

Endpoints是k8s中的一种资源对象,k8s通过Endpoints监控到Pod的IP,service又关联Endpoints从而实现Pod的发现。大致如下图所示,service的发现机制我们会在后面文章中做深入了解。


外网与service通信

其实所谓外网通信也是service的表现形式。

service几种类型和不同用途。

  • ClusterIP:用于在集群内部互相访问的场景,通过ClusterIP访问Service,即我们上面所说的pod与service。
  • NodePort:用于从集群外部访问的场景,通过节点上的端口访问Service。
  • LoadBalancer:用于从集群外部访问的场景,其实是NodePort的扩展,通过一个特定的LoadBalancer访问Service,这个LoadBalancer将请求转发到节点的NodePort,而外部只需要访问LoadBalancer。
  • None:用于Pod间的互相发现,这种类型的Service又叫Headless Service。

我们先来看NodePort:

我们在service中指定type: NodePort创建出的service将会包含一个在所有node 开放的端口30678,这样我们访问任意节点IP:30678即可访问到我们的pod

# kubectl get service -n training
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
training-service NodePort 10.96.229.238 <none> 8881:30678/TCP 55m # curl 192.168.1.86:30678
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
....

LoadBalancer类型和它名字一样,为负载均衡而生。它的结构如下图所示,

LoadBalancer本身不是属于Kubernetes的组件,如果使用云厂商的容器服务。通常会提供一套他们的负载均衡服务比如阿里云ACK的SLB、华为云的ELB等等。Service是基于四层TCP和UDP协议转发的,而k8s 另外一种资源对象Ingress可以基于七层的HTTP和HTTPS协议转发,可通过域名和路径做到更细粒度的划分,这是后话。


希望小作文对你有些许帮助,如果内容有误请指正。

您可以随意转载、修改、发布本文,无需经过本人同意。 通过博客阅读:iqsing.github.io

k8s网络模型与集群通信的更多相关文章

  1. kubeadm实现k8s高可用集群环境部署与配置

    高可用架构 k8s集群的高可用实际是k8s各核心组件的高可用,这里使用主备模式,架构如下: 主备模式高可用架构说明: 核心组件 高可用模式 高可用实现方式 apiserver 主备 keepalive ...

  2. 【葵花宝典】lvs+keepalived部署kubernetes(k8s)高可用集群

    一.部署环境 1.1 主机列表 主机名 Centos版本 ip docker version flannel version Keepalived version 主机配置 备注 lvs-keepal ...

  3. 日志分析系统 - k8s部署ElasticSearch集群

    K8s部署ElasticSearch集群 1.前提准备工作 1.1 创建elastic的命名空间 namespace编排文件如下: elastic.namespace.yaml --- apiVers ...

  4. 集群通信组件Tribes之整体介绍

    接下来一系列文章会对集群通信框架tribes进行源码级别的分析,欢迎讨论. 把若干机器组合成一个集群,集群为了能协同工作,成员之间的通信是必不可少的,当然可以说这也是集群实现中重点需要解决的核心问题, ...

  5. 集群通信组件tribes之使用方法

    上面已经对tribes的内部实现机制及原理进行了深入的剖析,在理解它的设计原理后看看如何使用tribes,整个使用相当简单便捷,只需要四步: ① 定义一个消息对象,由于这个消息对象是要在网络之间传递的 ...

  6. 集群通信组件tribes之用法

    上面已经对tribes的内部实现机制及原理进行了深入的剖析.在理解它的设计原理后看看怎样使用tribes.整个使用相当简单便捷,仅仅须要四步: ① 定义一个消息对象,因为这个消息对象是要在网络之间传递 ...

  7. .Net Core2.1 秒杀项目一步步实现CI/CD(Centos7.2)系列一:k8s高可用集群搭建总结以及部署API到k8s

    前言:本系列博客又更新了,是博主研究很长时间,亲自动手实践过后的心得,k8s集群是购买了5台阿里云服务器部署的,这个集群差不多搞了一周时间,关于k8s的知识点,我也是刚入门,这方面的知识建议参考博客园 ...

  8. k8s 使本地集群支持 LoadBalancer 服务

    k8s 使本地集群支持 LoadBalancer 服务 为了使本地集群支持 LoadBalancer 服务,可以参考以下两种实现方案: keepalived-cloud-provider metalL ...

  9. Envoy 基础教程:使用 Unix Domain Socket(UDS) 与上游集群通信

    Envoy Proxy 在大多数情况下都是作为 Sidecar 与应用部署在同一网络环境中,每个应用只需要与 Envoy(localhost)交互,不需要知道其他服务的地址.然而这并不是 Envoy ...

随机推荐

  1. 深入浅出WPF-02.WPF系列目录

    WPF系列目录 2. XAML认识 3. XAML语法 4. x名称空间详解 5. 控件与布局 6. 绑定Binding-01 6. 绑定Binding-02 6. 绑定Binding-03 7. 属 ...

  2. 智汀家庭云-开发指南Golang:设备模块

    1.品牌 品牌指的是智能设备的品牌,SA通过插件的形式对该品牌下的设备进行发现控制.理论上来说一个品牌对应一个插件服务.您可以通过项目 根目录下的品牌查看SA支持的品牌.关于插件服务的详细信息可以参考 ...

  3. OpenStack创建Win10实例

    直接用Windows的iso文件创建实例是创建不出来的,需要先在kvm下创建qcow2格式的虚拟机,然后用已经创建好的虚拟机文件当做OpenStack的镜像来创建实例就好了. 首先第一点是需要有一台L ...

  4. Proxychains完成Linux命令行代理

    前言 Proxychains是一个Linux和类Unix平台非常流行的命令行代理工具,它支持强制应用的TCP 连接通过代理,支持 Tor.HTTP与 Socks 代理.与 sshuttle 不同的是, ...

  5. 【数学】快速傅里叶变换(FFT)

    快速傅里叶变换(FFT) FFT 是之前学的,现在过了比较久的时间,终于打算在回顾的时候系统地整理一篇笔记,有写错的部分请指出来啊 qwq. 卷积 卷积.旋积或褶积(英语:Convolution)是通 ...

  6. 【Docker】(11)---Docker的网络概念

    一.实现原理 1.实现原理 Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为C ...

  7. 初始HTML03

    **------------恢复内容开始------------** HTML 页面标签组成 一个完整的页面仅有一个html元素,在这个元素之下,包含head和body元素,前者负责说明页面结构,后者 ...

  8. Scrum Meeting 0522

    零.说明 日期:2021-5-22 任务:简要汇报两日内已完成任务,计划后两日完成任务 备注:由于在Beta冲刺阶段的最后一周中团队成员需要准备必修课程计算机网络的相关考试,所以为了保证Beta功能的 ...

  9. [软工顶级理解组] Beta阶段项目展示

    目录 团队成员 软件介绍 项目简介 预期典型用户 功能描述 预期目标用户数 用户反馈 团队管理 分工协作 项目管理 取舍平衡 代码管理 程序测试 代码规范 文档撰写 继续开发指导性 用户沟通 需求分析 ...

  10. 2020BUAA软工个人博客作业

    2020BUAA软工个人博客作业 17373010 杜博玮 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人博客作业 我在这个课程的目标是 学 ...