1. Kubernetes 网络模型

在 Kubernetes 的网络模型中,最小的网络单位是 Pod。Pod 的网络设计原则是 IP-per-Pod,即 Pod 中 container 共享同一套网络协议栈,具有相同的网络命名空间。Pod 内的 container 通过 localhost + port 访问,类似于 Liunx 中进程访问的方式。构建 Kubernetes 的 Pod 网络模型如下:
 
Kubernetes 对集群网络的设计原则有:
  • 所有容器都可以不用 NAT 和别的容器通信。
  • 所有节点都可以不用 NAT 和所有容器通信,反之亦然。
  • 容器的地址和外部看到的地址是同一个地址。
 
回顾前面文章,容器在 Docker 环境下访问外网是通过 NAT 的,NAT 会增加端口管理的复杂性,而且在外部看不到实际容器的 ip。这里的设计原则避开了这些点,它使得 Pod 可以被看作独立的“虚拟机”,从而较好的进行服务发现,域名解析,负载均衡等。

2. 单节点 Pod 访问

单节点构建 pod,实现 pod 内 container 的相互访问。
 
创建 pod:
  1. $ cat deployment.yaml
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. name: deployment
  6. spec:
  7. replicas: 1
  8. selector:
  9. matchLabels:
  10. app: web_server
  11. template:
  12. metadata:
  13. labels:
  14. app: web_server
  15. spec:
  16. containers:
  17. - name: httpd-test
  18. image: httpd
  19. - name: bootcamp-test
  20. image: bootcamp:v1
  21.  
  22. $ kubectl apply -f deployment.yaml
  23. deployment.apps/deployment created
  24.  
  25. $ kubectl get pods
  26. NAME READY STATUS RESTARTS AGE
  27. deployment-595bb7bd6c-6jxwr 2/2 Running 0 44s
 
pod 包括两个 container httpd 和 bootcamp。其中,httpd 监听在 80 端口,bootcamp 监听在 8080 端口:
  1. $ netstat -ntlp | grep 80
  2. tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 10204/httpd
  3. tcp6 0 0 :::8080 :::* LISTEN 10077/node
  4.  
  5. $ ps aux | grep 10077 | grep -v grep
  6. root 10077 0.0 0.9 708220 23720 ? Sl 09:32 0:00 node server.js
  7. $ ps aux | grep 10204 | grep -v grep
  8. root 10204 0.0 0.1 5940 4360 ? Ss 09:32 0:00 httpd -DFOREGROUND
 
进入 pod ,从 pod 中访问 container:
  1. $ kubectl exec -it deployment-595bb7bd6c-6jxwr /bin/bash
  2. Defaulting container name to bootcamp-test.
  3. Use 'kubectl describe pod/deployment-595bb7bd6c-6jxwr -n default' to see all of the containers in this pod.
  4. root@deployment-595bb7bd6c-6jxwr:/# ip a
  5. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
  6. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  7. inet 127.0.0.1/8 scope host lo
  8. valid_lft forever preferred_lft forever
  9. 10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
  10. link/ether 02:42:ac:12:00:05 brd ff:ff:ff:ff:ff:ff
  11. inet 172.18.0.5/24 brd 172.18.0.255 scope global eth0
  12. valid_lft forever preferred_lft forever
  13.  
  14. root@deployment-595bb7bd6c-6jxwr:/# curl 172.18.0.5:8080
  15. Hello Kubernetes bootcamp! | Running on: deployment-595bb7bd6c-6jxwr | v=1
  16. root@deployment-595bb7bd6c-6jxwr:/# curl 172.18.0.5:80
  17. <html><body><h1>It works!</h1></body></html>
可以看到,进入 pod 实际上进入的是 pod 内的 container,在 continer 内通过 ip + port 实现 httpd 和 bootcamp 的访问。 
 
同理,直接在 node 上访问 pod:
  1. $ curl 172.18.0.5:8080
  2. Hello Kubernetes bootcamp! | Running on: deployment-595bb7bd6c-6jxwr | v=1
  3. $ curl 172.18.0.5:80
  4. <html><body><h1>It works!</h1></body></html>
  5. $ curl 172.18.0.5:8081
  6. curl: (7) Failed to connect to 172.18.0.5 port 8081: Connection refused

3. Pod 网络模型

上节实现了 pod 内 container 的相互访问,那么 container 是怎么访问到“外网”的呢?
 
带着这个问题我们查看和 deployment 相关的 container:
  1. $ docker ps | grep deployment
  2. 24adb2a738f4 httpd "httpd-foreground" Up 6 minutes k8s_httpd-test_deployment-..
  3. 1339d17223d8 8fafd8af70e9 "/bin/sh -c 'node se…" Up 7 minutes k8s_bootcamp-test_deployment-..
  4. c86a97fff88b k8s.gcr.io/pause:3.1 "/pause" Up 7 minutes k8s_POD_deployment-...
 
和期望的不一样,多了一个“pause”类型的 container。查看这三个容器的网络命名空间:
  1. $ mkdir -p /var/run/netns
  2. $ docker inspect --format '{{ .State.Pid }}' 24adb2a738f4
  3. 8349
  4. $ docker inspect --format '{{ .State.Pid }}' 1339d17223d8
  5. 8189
  6. $ docker inspect --format '{{ .State.Pid }}' c86a97fff88b
  7. 8100
  8.  
  9. $ ln -s /proc/8349/ns/net /var/run/netns/httpd
  10. $ ln -s /proc/8189/ns/net /var/run/netns/bootcamp
  11. $ ln -s /proc/8100/ns/net /var/run/netns/pause
  12.  
  13. $ ip netns list
  14. pause (id: 3)
  15. bootcamp (id: 3)
  16. httpd (id: 3)
  17.  
  18. $ ip netns exec httpd ls -la /proc/self/ns/
  19. lrwxrwxrwx 1 root root 0 Jan 17 08:37 net -> 'net:[4026532636]'
  20. ...
  21. $ ip netns exec bootcamp ls -la /proc/self/ns/
  22. lrwxrwxrwx 1 root root 0 Jan 17 08:37 net -> 'net:[4026532636]'
  23. ...
  24. $ ip netns exec pause ls -la /proc/self/ns/
  25. lrwxrwxrwx 1 root root 0 Jan 17 08:37 net -> 'net:[4026532636]'
  26. ...
 
它们具有相同的网络命名空间,进一步的查看容器对应的网络类型:
  1. $ docker inspect 24adb2a738f4 | grep NetworkMode
  2. "NetworkMode": "container:c86a97fff88bd73d221dfbe56e209e868f4479671bca9d01c14fd07ba1f03a4d",
  3. $ docker inspect 1339d17223d8 | grep NetworkMode
  4. "NetworkMode": "container:c86a97fff88bd73d221dfbe56e209e868f4479671bca9d01c14fd07ba1f03a4d",
  5. $ docker inspect c86a97fff88b | grep NetworkMode
  6. "NetworkMode": "default"
 
到这里我们大体知道了,容器 pause 的网络模式是默认(网桥)模式,容器 httpd 和 bootcamp 是 container 模式。pause 容器是作为 httpd 和 bootcamp 的“挂载点”存在的,它的存在保证了多个容器可以使用同一个 ip,同一个网络协议栈,即满足 IP-per-Pod 模型。
 
那么,我们查看网络命名空间的 veth 设备即能知道 Pod 的网络结构了。
  1. $ brctl show
  2. bridge name bridge id STP enabled interfaces
  3. docker0 8000.0242ed103e29 no vethd2c436f
  4.  
  5. $ ip a
  6. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
  7. 2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
  8. 3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
  9. 11: veth4132daf@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
  10. link/ether 7a:db:25:ff:27:85 brd ff:ff:ff:ff:ff:ff link-netnsid 3
  11. inet6 fe80::78db:25ff:feff:2785/64 scope link
  12. valid_lft forever preferred_lft forever
  13.  
  14. root@deployment-595bb7bd6c-6jxwr:/# ip a
  15. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
  16. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  17. inet 127.0.0.1/8 scope host lo
  18. valid_lft forever preferred_lft forever
  19. 10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
  20. link/ether 02:42:ac:12:00:05 brd ff:ff:ff:ff:ff:ff
  21. inet 172.18.0.5/24 brd 172.18.0.255 scope global eth0
  22. valid_lft forever preferred_lft forever
 
构建网络示意图如下:
 
 
那么,如果网络容器 pause 因故障销毁了会出现什么情况呢?
首先,绑定到网络容器中的原 network namespace 还是会存在的。当网络容器销毁时 replicaSet 会触发 kubelet 对网络容器进行重建,重建的网络容器归属于新的 network namespace,而相应的原来“桥接”在网络容器上的容器也被重建,并且“桥接”到新的网络容器上。
 
 

Kubernetes 网络:Pod 和 container 的那点猫腻的更多相关文章

  1. kubernetes 的pod控制器

    转载于网络   pod是kubernetes的最小单元,自主式创建的pod删除就没有了,但是通过资源控制器创建的pod如果删除还会重建.pod控制器就是用于实现代替我们去管理pod的中间层,并帮我们确 ...

  2. Kubernetes网络的4种解决方案

    一.Kubernetes + Flannel Kubernetes的网络模型假定了所有Pod都在一个可以直接连通的扁平的网络空间中,这在GCE(Google Compute Engine)里面是现成的 ...

  3. Kubernetes探索学习004--深入Kubernetes的Pod

    深入研究学习Pod 首先需要认识到Pod才是Kubernetes项目中最小的编排单位原子单位,凡是涉及到调度,网络,存储层面的,基本上都是Pod级别的!官方是用这样的语言来描述的: A Pod is ...

  4. 深入解读docker网络与kubernetes网络

    前言:你是否学习使用k8s很久很久了可是对于网络这块仍旧似懂非懂呢? 您是否对网上一堆帖子有如下的抱怨: 打开多个博客,然后发现有区别么? 明显是直译过来的,越看越迷糊 “因为xxx,所以yyy”,. ...

  5. 从零开始入门 K8s | Kubernetes 网络概念及策略控制

    作者 | 阿里巴巴高级技术专家  叶磊 一.Kubernetes 基本网络模型 本文来介绍一下 Kubernetes 对网络模型的一些想法.大家知道 Kubernetes 对于网络具体实现方案,没有什 ...

  6. Kubernetes之Pod使用

    一.什么是Podkubernetes中的一切都可以理解为是一种资源对象,pod,rc,service,都可以理解是 一种资源对象.pod的组成示意图如下,由一个叫”pause“的根容器,加上一个或多个 ...

  7. Kubernetes网络之Flannel工作原理

    目录 1.Docker网络模式 1.1 bridge网络的构建过程 1.2 外部访问 2.Kubernetes网络模式 2.1 同一个Pod中容器之间的通信 2.2 不同Pod中容器之间的通信 2.3 ...

  8. kubernetes concepts -- Pod Overview

    This page provides an overview of Pod, the smallest deployable object in the Kubernetes object model ...

  9. 超长干货丨Kubernetes网络快速入门完全指南

    Kubernetes网络一直是一个非常复杂的主题.本文将介绍Kubernetes实际如何创建网络以及如何为Kubernetes集群设置网络. 本文不包括如何设置Kubernetes集群.这篇文章中的所 ...

  10. DevOps专题|玩转Kubernetes网络

    Kubernetes无疑是当前最火热的容器编排工具,网络是kubernetes中非常重要的一环, 本文主要介绍一些相应的网络原理及术语,以及kubernetes中的网络方案和对比. Kubernete ...

随机推荐

  1. Head First Java学习:第八章-接口和抽象类

    第八章:接口和抽象类 深入多态 1.抽象类:有些类不应该被初始化 在类声明前面加上抽象类的关键字,abstract. 防止类被初始化,即不能被"new"创建该类的实例(要求) 还是 ...

  2. Kernel Memory 入门系列: Embedding 简介

    Kernel Memory 入门系列: Embedding 简介 在 RAG模式 其实留了一个问题. 我们对于的用户问题的理解和文档的检索并没有提供合适的方法. 当然我们可以通过相对比较传统的方法. ...

  3. 安装了华企盾DSC防泄密,所有进程的加密文件都无法打开

    用pchunter等工具查看系统回调中是否有文件厂商不存在的(system目录的除外),在恢复模式删除掉,或者用360系统急救箱查杀一下

  4. 用CloudDrive将阿里云、天翼云、115挂载为电脑本地硬盘

    用CloudDrive将阿里云.天翼云.115挂载为电脑本地硬盘 写在前面 它可以把各大在线网盘,直接变成电脑本地硬盘,俗称"网盘挂载".这在一定程度上,确实能缓解存储紧张问题,瞬 ...

  5. PersistenceException、ReflectionException、IllegalArgumentException、wrapException持久性异常 反射异常 非法参数异常 包装异常

    PersistenceException.ReflectionException.IllegalArgumentException.wrapException wrapException 持久性异常 ...

  6. 三个月我迁移了100PB数据

    2023年马上结束,这一年做了不少事情,有一项我可以吹好几年,忍不住和大家分享一下啊. 需求 去年底收到一项需求,要求2个月内从某云存储迁移100PB数据到微软云存储,包含几百亿个文件.当时听到这个数 ...

  7. 使用 PostgreSQL 实现 PageRank

    PageRank 算法 ​ 作为 Google 最早的一个网页排名算法,该算法在早期的搜索引擎中是搜索结果最为准确的,同时也是 Google 发家的一个重要算法.尽管这些年来该算法不再是 Google ...

  8. QT OpenGLWidget高分屏适配时出现的问题

    参考官方文档,为了解决4K屏幕显示QT界面时出现窗口变小分辨率不匹配的问题,我们可以在 QApplication a(argc, argv); 这句之前添加: #if (QT_VERSION > ...

  9. Flutter Getx 状态管理 --- (依赖管理) GetxController

    Flutter Getx 简单的状态管理(依赖管理) GetxController Getx 依赖管理简介 Get有一个简单而强大的依赖管理器,它允许你只用1行代码就能检索到与你的Bloc或Contr ...

  10. 6、Flutter 列表组件 滑动

    列表有以下分类: 1.垂直列表 class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget bui ...