容器有四大特性:
该文章从容器与 Linux 系统之间的关系,主要从Namespace,Cgroups等LInux特性以及容器的实践以及Docker 的进一步创新,分析了四大特性的由来。
容器的发展并不是空中花园,一蹴而就,而是站在了Linux 这个巨人的肩膀上,它是对笨重的虚拟技术的不满,而进一步的创新,Docker 的基于分层的文件系统管理整个容器镜像,更是将容器技术推上了浪潮,同时也让Docker 从那个容器争霸的时代获胜,统一霸主地位。
如今机器部署早已成为了历史的产物,容器编排技术k8s的出现,更是将容器技术的发展推上了顶峰。
这里对自己学习的容器的核心技术做个总结,主要包括以下方面:
Namespace 技术并不是Docker 本身提出的,而是 Linux 内核自带的, Linux 内核中描述进程的一个结构体如下:
struct task_struct{
...
/*namespace*/
struct nsproxy *nsproxy;
}
struct nsproxy {
atomic_t count; // 引用计数
struct uts_namespace *uts_ns; // 主机名与NIS域名
struct ipc_namespace *ipc_ns; // System V IPC和POSIX message queue
struct mnt_namespace *mnt_ns; // 文件系统挂载点
struct pid_namespace *pid_ns_for_children; // 进程号
struct net *net_ns; // 网络设备、网络栈、端口号等
struct time_namespace *time_ns; // 系统单调时间及REAL_TIME
struct cgroup_namespace *cgroup_ns; // cgroup资源
};
task_struct
为描述进程的一个结构体,其中包括一个描述进程命名空间的一个嵌套结构体nsproxy
namespace 类型隔离资源IPCSystem V IPC 和 POSIX 消息队列Network网络设备、网络协议栈、网络端口等PID进程Mount挂载点UTS主机名和域名USR用户和用户组
这就是为什么在使用Linux的时候感受不到namespace的存在
Linux 系统预留了用户对进程namespace的操作
clone
setns
unshare
Pid namespace
但是相同namespace 中容器内部的pid和外部的ps 看到的pid 是不一样的,容器会维护内部pid 与 主机pid的映射关系,容器在启动的时候会有一个ENTRYPOINT进程,这个就是容器自身在主机上的进程,容器内的所有进程都是通过该进程fork 出来的
这样就做到了容器间的进程隔离
net namespace
这样就做到了容器间的网络隔离
ipc namespace
而只有相同IPC namespace 的进程才可以相互通信
容器在进程间通信上与Linux 进程间通信方式保持一致,因此需要在IPC资源申请的时候加入namespace 信息,才能保证容器间进程通信
mnt namespace
uts namespace
使其在网络上可以被视为一个独立的节点而非host上的一个进程
user namespace
lsns -t
## 不指定类型将查询出当前用户已有的所有类型的net ns
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ lsns
NS TYPE NPROCS PID USER COMMAND
4026531836 pid 8 729087 admin /home/admin/.minikube/cache/linux/amd64/v1.25.3/kubectl --context minikube proxy --port 0
4026531837 user 8 729087 admin /home/admin/.minikube/cache/linux/amd64/v1.25.3/kubectl --context minikube proxy --port 0
4026531838 uts 8 729087 admin /home/admin/.minikube/cache/linux/amd64/v1.25.3/kubectl --context minikube proxy --port 0
4026531839 ipc 8 729087 admin /home/admin/.minikube/cache/linux/amd64/v1.25.3/kubectl --context minikube proxy --port 0
4026531840 mnt 8 729087 admin /home/admin/.minikube/cache/linux/amd64/v1.25.3/kubectl --context minikube proxy --port 0
4026531956 net 8 729087 admin /home/admin/.minikube/cache/linux/amd64/v1.25.3/kubectl --context minikube proxy --port 0
## 查看root 用户下的 ns
## 可以发现systemd的ns 为1,为系统启动时的第一个进程,其他所有进程的ns都是继承于它
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo lsns
NS TYPE NPROCS PID USER COMMAND
4026531836 pid 141 1 root /usr/lib/systemd/systemd --system --deserialize 23
4026531837 user 252 1 root /usr/lib/systemd/systemd --system --deserialize 23
4026531838 uts 153 1 root /usr/lib/systemd/systemd --system --deserialize 23
4026531839 ipc 141 1 root /usr/lib/systemd/systemd --system --deserialize 23
4026531840 mnt 139 1 root /usr/lib/systemd/systemd --system --deserialize 23
4026531856 mnt 1 28 root kdevtmpfs
4026531956 net 245 1 root /usr/lib/systemd/systemd --system --deserialize 23
4026532185 mnt 1 1055 chrony /usr/sbin/chronyd
4026532186 mnt 92 1431166 1000 [celeryd: celery@ali-jkt-dc-bnc-airflow-test02:MainProcess] -active- (worker
4026532187 uts 92 1431166 1000 [celeryd: celery@ali-jkt-dc-bnc-airflow-test02:MainProcess] -active- (worker
4026532188 ipc 92 1431166 1000 [celeryd: celery@ali-jkt-dc-bnc-airflow-test02:MainProcess] -active- (worker
ls -la /proc/
每一个进程在/proc 目录下都有对应的pid 目录
## 打印出PID 1271557 对应的每个ns的id
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo ls -la /proc/1271557/ns/
total 0
dr-x--x--x 2 root root 0 Dec 7 05:25 .
dr-xr-xr-x 9 root root 0 Nov 28 17:33 ..
lrwxrwxrwx 1 root root 0 Dec 7 05:25 ipc -> ipc:[4026532494]
lrwxrwxrwx 1 root root 0 Dec 7 05:25 mnt -> mnt:[4026532492]
lrwxrwxrwx 1 root root 0 Dec 7 05:25 net -> net:[4026532497]
lrwxrwxrwx 1 root root 0 Dec 7 05:25 pid -> pid:[4026532495]
lrwxrwxrwx 1 root root 0 Dec 7 05:25 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Dec 7 05:25 uts -> uts:[4026532493]
nsenter -t -n ip addr
## 查看net ns 发现启动了一个go 程序
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo lsns -t net
NS TYPE NPROCS PID USER COMMAND
4026531956 net 245 1 root /usr/lib/systemd/systemd --system --deserialize 23
4026532227 net 2 1433135 65535 /pause
4026532300 net 2 1433134 65535 /pause
4026532497 net 3 1271557 root /bin/sh -c `go mod tidy`\x0a`go run main.go`\x0a
## 进入该go 程序的net ns 中执行查询ip 命令
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo nsenter -t 1271557 -n ip a
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
462: eth0@if463: mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:15:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.21.0.2/16 brd 172.21.255.255 scope global eth0
valid_lft forever preferred_lft forever
unshare -f -
# 在一个新的net namespace中执行一个sleep 180 命令
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo unshare -fn sleep 180
# 另开 一个窗口查看发现有新的net namespace 生成
# 该ns id为4026532595 包含的新执行命令的PID 3904433
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo lsns -t net
NS TYPE NPROCS PID USER COMMAND
4026531956 net 247 1 root /usr/lib/systemd/systemd --system --deserialize 23
4026532227 net 2 1433135 65535 /pause
4026532300 net 2 1433134 65535 /pause
4026532497 net 3 1271557 root /bin/sh -c `go mod tidy`\x0a`go run main.go`\x0a
4026532595 net 2 3904433 root unshare -fn sleep 180
# 当进程执行完后,/proc/ 下对应的文件会被删除
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo nsenter -t 3904433 -n ip a
nsenter: cannot open /proc/3904433/ns/net: No such file or directory
上图展示了容器与操作系统之间的关系,以及操作系统与系统硬件之间的关系
操作系统为运行在硬件上的一个软件,它实现了对硬件各个模块的操作接口,以提供给运行在操系统的上进程调用
操作系统启动运行的第一个进程就是systemd PID1,其他的所有进程都是通过该父进程fork 出来的,不同的进程间通过namespace 实现隔离,容器也是systemd fork 出来的子进程,也通过namespace 实现容器间的隔离
LInux 上通过Cgroups 实现进程对资源的限额配置,同样的容器也是通过Cgroups实现对资源大小的限制
Cgroups (Control groups), 一个cgroups 可以包含多个子系统,每个子系统就是对应一种资源的配额或者显示
Cgroup 会对其绑定的所有进程执行已有的子系统逻辑,所以想要对进程进行资源限制或者显示资源使用情况,只要和对应cgroup 绑定即可
LInux 资源分为可压榨资源与不可压榨资源
可压榨资源:比如说cpu
当对一个进程的CPU进行限制时,进程可以继续正常运行,只是运行的比较慢而已
不可压榨资源:比如说内存memory
当对一个进程的内存进行限制时,进程可能就无法启动,运行中的进程也可能被OOM KILLER
Linux的CPU子系统位于/sys/fs/cgroup/cpu
目录下
当需要使用到CPU子系统对进程进行CPU限制或者查询CPU使用状况时,只需要在该目录下创建子目录,在创建完子目录后,Linux会自动将对应的配置文件复制一份至该子目录下:
然后需要做什么样的CPU配额,只要在对应的配置文件中配置就行了
配置文件说明
上图为使用相对时间划分CPU限制,Cgroup A 绑定的进程使用33%的CPU, Cgroup B 绑定的进程使用66%的CPU
但是并不是说Cgroup A永远只能使用33%的CPU,当 Cgroup B 的进程执行完毕后,此时如果A中的进程还没有执行完毕,那么A中的进程就可以利用100%的CPU(假设只有A和B两个CGroup的进程)
上图为使用时间周期(period)与 绝对时间限额(quota)来控制CPU使用:
该Cgroup下的进程在100000us内使用的CPU时间加起来不能超过40000us
用于统计 Cgroup 及其子 Cgroup 下进程的CPU的使用情况
用于统计 Cgroup 及其子 Cgroup 下进程的内存的使用情况
内核默认提供5个调度器,Linux 内核使用struct sched_class来对调度器进行抽象
Stop调度器,stop_sched_class: 优先级最高的调度类,可以抢占其他所有进程,不能被其他进程抢占
Deadline调度器,dl_sched_class: 使用红黑树,把进程按照绝对截止期限进行排序,选择最小进程进行调度运行
RT调度器,rt_sched_class: 实时调度器,为每个优先级维护一个队列
CFS调度器,cfs_sched_class: 完全公平调度器,采用完全公平算法,引入虚拟运行时间概念
IDLE-Task调度器,idle_sched_class: 空闲调度器,每个CPU都会有一个idle线程,当没有其他进程可以调度时,调度运行idle线程
CFS调度器与红黑树
红黑树特点:
查询速度快log(n),自平衡, 稳定(层级差不超过2)
Linux把 vruntime 最小的进程放在最左边,vruntime 最大的进程放在**最右边,**CFS调度器每次选取树的最左边的节点运行
进程优先级越高的进程,vruntime 越小,这样就保证了优先级高的进程先运行
package main
// 主程序阻塞,将消耗一个CPU
// 主程序中启动一个goroutine 阻塞,将消耗一个CPU
// 加起来将消耗两个CPU
func main() {
go func() {
for {
}
}()
for {
}
}
运行后,再开一个窗口通过top
查看该进程消耗的CPU,发现稳定消耗在2个CPU,对应的PID为 4129204 :
在CPU子系统中,对该进程(PID 4129204)进行CPU限额(root 用户才有权限操作)
将该进程添加进刚才在CPU子系统下创建的cpudemo目录下的cgroup.porcs
文件中:
[root@ali-jkt-dc-bnc-airflow-test02 cpudemo]# echo 4129204 > cgroup.procs
默认下是没有对CPU限额的:
[root@ali-jkt-dc-bnc-airflow-test02 cpudemo]# cat cpu.cfs_period_us 100000 ## -1 表示不限额 [root@ali-jkt-dc-bnc-airflow-test02 cpudemo]# cat cpu.cfs_quota_us -1
修改在周期内的绝对时间cpu.cfs_quota_us
达到限额:
## 修改为和 cpu.cfs_period_us 一样 ## 通过公式CPU = quota/period 计算出最多消耗1个CPU
[root@ali-jkt-dc-bnc-airflow-test02 cpudemo]# echo 100000 > cpu.cfs_quota_us
top 查看发现确实只消耗了一个CPU:
上边总结的Namespace
和Cgroups
都是Linux 本身就有的,如果说Docker仅仅实现了这些功能,还不能足以说明Docker的强大
在那个容器化大战的时代,使Docker 真正能够横扫六合的是开创了OverlayFS
的创举:
Union FS
Docker 的文件系统利用了Union FS
技术:
有了 Union FS 技术,就可以将不同来源的不同子目录联合,并且目录都有自己的权限控制,这样就模拟了一个完整的文件系统
容器镜像
Docker 利用 Union FS 技术的实现产物就是容器镜像,同时这也是 Docker 成功的重大原因
Docker 规定可以通过 Dockerfile 这种源代码的方式来创建容器镜像,运行开发人员定义一个面向应用的容器镜像构建的源代码
可以说这是打破了运维与开发边界的第一步,Dockerfile 的简单易上手,迅速吸引了大批的用户
Union FS 在 Dockerfile 中的体现
这样在同一台 Linux 主机上多次通过 Dockerfile 构建的时候,会先查找主机上是否已经有相同的层级构建过,如果构建过就会使用已有的,然后继续下一层的构建
Linux 文件系统
Linux 文件系统主要由两部分组成:
Bootfs(boot file system)
rootfs (root file system)
Docker 启动
Linux
Docker 启动
当启动完成之后,就只有最上层是writeable的,下边的层级就都是 readonly
可以发现 Docker 的启动模仿了Linux的启动方式,不过 Docker 妙就妙在可以分层多次构建,在通过Dockerfile 暴露出需要构建的层级,以及每个层级需要构建的内容,这样就实现了配置化构建,根据程序所需的环境依赖,来构建出不同的文件系统,命名为容器镜像
写操作
由于镜像具有共享特性,所以对容器可写层的操作需要依赖存储驱动提供的写时复制和用时分配机制,来支持对容器可写层的修改,进而提高对存储和内存资源的利用率
写时复制
当一个镜像被多个容器使用,在主机上不需要保存该镜像的多个副本。在需要对镜像提供的文件进行修改时,该文件会从镜像的文件系统被复制到容器的可写层的文件系统进行修改,而镜像里边的文件不会改变。不同容器对文件的修改都相互独立、互不影响
用时分配
按需分配空间,而非提前分配,即当一个文件被创建出来后,才会分配空间
容器存储驱动
OverlayFS 文件存储驱动
上图的基础镜像层FS包括文件1,2,3
现在有一个容器引用了该镜像并且需要修改可写层,修改镜像的文件2 并且添加文件4
使用overlay 存储驱动就会将Lower 层(基础镜像层)upper 层(容器层)合并为新的FS,这样就保证了基础镜像的FS没有变更,又保证了新的FS(可写层)同时包含基础镜像的文件以及修改后的文件
Open Container Initiative
OCI 组织与2015年创建,是一个致力于定义容器镜像标准和运行时标准的开放式组织
Docker daemon
Docker 服务本身的后台程序,对外提供REST API
Docker Commond
输入docker 命令,发送到Docker daemon 中去
containerd
Docker 新版都支持了OCI容器标准,Docker daemon 收到commond的命令后通过GRPC发送至containerd
containerd 负责给需要操作的容器进程启动一个父进程shim,将commond 需要操作的进程控制权完全交给shim 进程,然后将shim 进程的管理交给操作系统的init 进程 systemd,这样containerd 就会很轻量级,无需管理大量的进程,只需要创建shim 进程就行了
这样containerd的升级和修改就可以非常简单
containerd 可以独立出为单独的组件,这样就保证了当我们升级Docker 版本的时候,只需要升级Docker daemon 即可,只要containerd 正常运行,在升级的时候就不会影响容器中运行中的进程
shim
由 containerd 创建的进程,控制着运行时进程runc的整个生命周期
Docker 支持的几种网络模式
Null(–net=None)
Host
Conrtainer
Bridge(–net=bridge)
跨主机网络通信
如果将网络分为容器网络与基础架构网络(主机本身网络) ,容器内的网络是没办法直接在基础架构网络间通信的。
上边几种网络模式都是单机的网络模式,也就是实现了容器间网络与所在主机本身网络间的通信,但是跨主机之间的容器网络通信仅仅依赖于上边的是不够的,下边为两个常用的跨主机间的容器网络通信方式:
Overlay(libnetwork, libkv)
Underlay
使用现有底层网络,为每一个容器配置可路由的网络IP
优点
实现简单直接利用主机IP间通信,不需要封包,解包,网络访问效率相对于 Overlay 较高
缺点
需要自己规划对应IP, 需要一定的管理成本,管理不当容易造成IP失效
容器启动后,会在主机上启动一个 docker0 的网络,容器的所有内部网络都是通过docker0 去分配与管理的,现在要配置一个容器内的网络与主机网络互通,流程如下:
# 1. 创建一个目录保存新建的net namespace信息
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ mkdir -p /var/run/netns
# 2. 启动一个不指定网络的 nginx 容器
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ docker run --network=none -d nginx
# 3. 查看容器的进程号
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ docker ps | grep nginx
b3653a372d31 nginx "/docker-entrypoint.…" About a minute ago Up 58 seconds keen_hawking
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ docker inspect b3653a372d31 | grep -i pid
"Pid": 752524,
"PidMode": "",
"PidsLimit": null,
# 3. 进入ns中查看该进程ip 信息
# 目前只有lo回环ip,因为还没有配置相关网络
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo nsenter -t 752524 -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
# 4. 建立进程与新建网络ns 之间的关联关系
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ export pid=752524
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ ll /var/run/netns/$pid
lrwxrwxrwx 1 root root 19 Dec 11 07:33 /var/run/netns/752524 -> /proc/752524/ns/net
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ ip netns list
752524
cni-10a27892-3539-fbae-48ce-479c9ec72496 (id: 1)
cni-be8d609e-00db-c086-d971-b5ce84486e43 (id: 0)
# 5. 确认docker0 网络正常
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ ip a | grep docker0
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
inet 172.17.0.1/16 scope global docker0
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ brctl show | grep docker0
docker0 8000.0242a5c49e4d no
# 6. 建立一根ip网线 veth pair
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo ip link add A type veth peer name B
# 7. 为docker0 网络添加interface A
# 将网线A端连接网络doker0
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo brctl addif docker0 A
# 查看下docker0的信息,发现多了个A, 但是此时该接口还无效,需要up
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ brctl show docker0
bridge name bridge id STP enabled interfaces
docker0 8000.0242a5c49e4d no A
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo ip link set A up
# 8. 配置容器内ip 并且与网线B端相连
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ SETIP=172.17.0.10
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ SETMASK=16
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ GATEWAY=172.17.0.1
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo ip link set B netns $pid
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo ip netns exec $pid ip link set dev B name eth0
# 查看下 netns 中该进程的ip信息,发现多了一个网络eth0 和主机上的465网络相连
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo nsenter -t $pid -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
464: eth0@if465: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 9e:94:44:8c:d3:f8 brd ff:ff:ff:ff:ff:ff link-netnsid 0
# 查看主机ip发现465网络与docker0相连
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ ip a | grep 465
465: A@if464: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue master docker0 state LOWERLAYERDOWN group default qlen 1000
# 9. 为容器内eth0 网络添加ip并且up
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo ip netns exec $pid ip link set eth0 up
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ ip netns exec $pid ip addr add $SETIP/$SETMASK dev eth0
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo ip netns exec $pid ip addr add $SETIP/$SETMASK dev eth0
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo ip netns exec $pid ip route add default via $GATEWAY
# 查看容器内网络,发现有了ip并且处于up 状态
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ sudo nsenter -t $pid -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
464: eth0@if465: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 9e:94:44:8c:d3:f8 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.10/16 scope global eth0
valid_lft forever preferred_lft forever
# 最后curl 请求验证容器内网络是否与主机网络互通
[admin@ali-jkt-dc-bnc-airflow-test02 ~]$ curl 172.17.0.10
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
当使用docker run 命令使用默认网络配置的时候,docker 会使用桥接模式为每一个容器配置一个eth0的网络并且与docker0网络相连,也就是上边我们自己通过Null 模式操作的流程步骤
这样做的好处就是配置简单,但是增加了对ip 的管理成本,否则容易造成ip 浪费,导致ip 不够的问题
Docker overlay 网络驱动原生支持多主机网络,Libnetwork 是一个内置的基于VXLAN 的网络驱动
假设如上一台虚拟机A(ip 为10.1.1.100 )运行在主机A上(IP为165.123.1.1),现在需要发送网络请求到主机B(IP为140.123.1.1)的虚拟机B上(IP为10.1.1.101)
Flannel 为k8s的一个网络插件是overlay网络的一种实现方式,将多个主机间Pod网络通信相连
如上有两台机器一台运行着两个前端应用Pod,一台运行着两个后端服务Pod,现在前端需要访问后端地址
Ping 命令网络抓包