什么是Overlay网络, 用于解决什么问题 ?
Overlay网络通过在现有网络之上创建一个虚拟网络层, 解决不同主机的容器之间相互通信的问题
如果没有Overlay网络,实现跨主机的容器通信通常需要以下方法:
- 端口映射
- 使用宿主机网络模式
这些方法牺牲了容器网络隔离的优势, 并且可能导致端口冲突问题
以下搭建一个简易的Docker Swarm 集群(一主一从), 探究 Overlay 网络下不同节点上的容器间互相通信的原理
早期,客户的On-premises网关设备(基于CentOS 7)采用增量升级方案进行固件更新。 这种方案存在两个主要问题:
为了解决这些问题,需要为客户网关设备设计一种新的升级方案。
A/B分区升级机制允许设备在不同分区上安装和运行系统的不同版本,从而实现无缝更新。这种方法常用于移动设备、物联网设备以及其他需要高可用性和减少停机时间的场景中。例如,Android系统、Chrome OS及许多嵌入式和IoT设备都采用了A/B系统升级方法。其主要优点包括:
我们的客户有一些本地部署的网关设备(CentOS 7)需要做固件升级。 原有的单系统分区架构缺乏有效的回滚机制, 升级遇到故障后无法回滚, 导致服务中断, 用户体验差
设计一种解决方案, 自动将客户的网关设备从单系统分区平滑升级到双系统,同时保证用户配置(IP, DNS, 登录口令)不丢失
整个升级过程对客户完全透明, 无需客户进行额外操作(比如添加磁盘, 创建新机器)
设计如下方案:
方案 | 描述 | 优点 | 缺点 |
---|---|---|---|
定制initramfs | 通过定制initramfs进入紧急模式,预先加载升级包和配置文件到内存,再重建磁盘分区 | 用户无感知, 且备份了旧的配置 | 内存空间有限, 升级包+解压后系统文件需小于内存 |
安装ISO | 下载并安装目标系统ISO | 不需要单独出一个升级包 | 客户的配置很难同步, 升级后需要用户做一些手动配置 |
我们在企业客户网络中部署了一些On-Premises的服务网关, 服务网关上部署了Squid代理软件, 为客户本地终端访问云服务提供正向代理
然而,对于使用较旧防火墙的客户来说,这些防火墙不支持基于FQDN(完全合格域名)的通配符匹配。这意味着当本地终端尝试访问云端资源时,用户必须逐一配置FQDN, 这种配置过程不仅繁琐,而且容易因为遗漏某些FQDN导致连接被防火墙阻止,造成网络中断,严重影响用户体验。
针对这个问题, 我们设计了一种基于Stunnel的加密通信方案, 绕过客户防火墙限制。 客户仅需配置Stunnel服务器的FQDN, 无需为每个目标服务器的FQDN进行单独设置, 从而简化了防火墙配置流程,提升了用户体验。
Stunnel是一款开源软件,其主要功能是为应用程序或服务提供TLS/SSL加密支持。 它的设计初衷是为了增强那些本身不支持加密功能的传统应用程序或服务的安全性
通过Stunnel, 可以在严格的防火墙规则下实现安全的加密通信,同时有效绕过可能存在的网络访问限制。
Ingress是k8s的一种资源对象,用于管理外部对集群内服务的访问, 它通过提供一个统一的入口点,将外部流量路由到集群内部的不同服务。
k8s集群中服务默认只能在集群内访问。 如果需要从外部访问服务,通常需要使用NodePort或LoadBalancer类型服务,这两个服务都存在一些问题
在我之前做的项目里,我们对Microk8s微服务的更新是通过自制tar包的方式做的, tar包存储了镜像和YAML文件。 每次升级时,我们需要先删除所有的YAML资源,然后重新创建新的资源。 这种方式存在以下问题:
了解到Helm可以有效解决以上问题, Helm是Kubernetes 的包管理工具,方便用户快速发现、 共享和使用Kubernetes构建的应用。 以下举例演示如何使用Helm实现安装、升级、回滚操作
docker0是Docker默认网络的核心组件, 通过虚拟网桥和NAT技术, 实现了容器间的通信以及容器与外部网络的交互。然而, docker0网段是固定的(通常是172.17.0.0/16), 为了更灵活地管理容器网络,Docker支持创建自定义网桥,允许用户指定网段。
例如, 在我以前做的一个单板仿真项目里, 每个容器用来模拟一块板, 单板的IP需要设置为172.16.0.0/16, 和docker0网段不一致。 由于这个项目部署在每个开发的工作机上, 我们决定不直接修改docker0配置, 选择了创建自定义网桥这种更灵活的方式。
Docker在主机上创建一个虚拟网桥(docker0), 每当启动一个容器,Docker会自动创建一对虚拟网卡(veth pair), 其中一端放在容器内部作为它的网络接口, 另一端则连接到主机上的这个虚拟网桥。 通过这种方式,容器之间可以通过网桥直接通信,数据包在网桥内转发,不经过主机的物理网络接口。
如果容器访问的是外部网络, 容器发出的数据包会先通过虚拟网桥到达主机, 然后主机通过NAT将容器的私有IP替换为自己的公网IP,从而让数据包能够顺利发送到外部网络。
8台Linux虚拟机, Rocky Linux 9.5 x86_64
各个机器IP、主机名、角色如下
1 | 192.168.52.91 k8s-master1 主节点1 |
以下分步搭建kubernetes集群
在 Docker 中,默认情况下容器无法直接与外部网络通信。 为了使外部网络能够访问容器内的服务,Docker 提供了端口映射功能,通过将宿主机的端口映射到容器内的端口,外部可以通过宿主机的IP和端口访问容器内的服务
以下通过动手演示, 安装一个Flask容器, 解释端口映射从外部访问容器的原理
1 | . |
Dockerfile
1 | FROM rockylinux:9.3 |
app.py
1 | from flask import Flask |
构建镜像
1 | docker build -t flask-app:1.0 . |
启动容器, 进行端口映射
1 | docker run -d -p 80:5000 flask-app:1.0 |
从外部访问 (192.168.52.203是我的虚拟机IP)
1 | # curl 192.168.52.203 |
Docker 多阶段构建是一种通过在单个 Dockerfile 中定义多个构建阶段的技术。 每个阶段可以使用不同的基础镜像和依赖项,允许开发人员在构建过程中分离应用程序的编译环境与运行环境。 最终生成的镜像只包含运行应用程序所需的文件,而无需携带编译工具链或其他不必要的依赖
通过多阶段构建,可以有效减少镜像体积,提升部署效率
下面通过一个简单的 Go 程序,分别用传统方式和多阶段构建两种方法演示如何构建 Docker 镜像,并观察多阶段构建对镜像大小的显著优化效果
1 | package main |