0%

前言

docker0是Docker默认网络的核心组件, 通过虚拟网桥和NAT技术, 实现了容器间的通信以及容器与外部网络的交互。然而, docker0网段是固定的(通常是172.17.0.0/16), 为了更灵活地管理容器网络,Docker支持创建自定义网桥,允许用户指定网段。
例如, 在我以前做的一个单板仿真项目里, 每个容器用来模拟一块板, 单板的IP需要设置为172.16.0.0/16, 和docker0网段不一致。 由于这个项目部署在每个开发的工作机上, 我们决定不直接修改docker0配置, 选择了创建自定义网桥这种更灵活的方式。

Docker网桥的工作机制

Docker在主机上创建一个虚拟网桥(docker0), 每当启动一个容器,Docker会自动创建一对虚拟网卡(veth pair), 其中一端放在容器内部作为它的网络接口, 另一端则连接到主机上的这个虚拟网桥。 通过这种方式,容器之间可以通过网桥直接通信,数据包在网桥内转发,不经过主机的物理网络接口。
如果容器访问的是外部网络, 容器发出的数据包会先通过虚拟网桥到达主机, 然后主机通过NAT将容器的私有IP替换为自己的公网IP,从而让数据包能够顺利发送到外部网络。

阅读全文 »

前言

在我们的业务场景中,客户终端需要访问部署在云端的各种服务,这些云端服务分布在不同的域名下。 例如, 一个典型的客户需要访问数十个甚至上百个不同的FQDN来满足他的业务需求
然而, 许多客户的防火墙不支持通配符的FQDN白名单配置, 这意味者他们必须手动配置每个具体的FQDN,这种配置非常麻烦,而且一旦配置错误会导致网络不通,严重影响用户体验, 增加运维负担
为了解决这个问题,我设计了一个基于Stunnel的加密通信方案, 以简化客户的防火墙配置:

  • 我们在客户的网关设备上部署了Stunnel,用于将Squid代理的所有HTTP流量进行TLS加密
  • Stunnel作为透明加密层,接收来自Squid的流量,并将其封装到TLS隧道中,将加密后流量发送给云端的一个Cloud Proxy.
  • Cloud Proxy是一个HTTPS代理, 负责解密网关设备传来的TLS流量,将解密后的请求转发到真正的后端服务

这种方案下,客户只需在防火墙配置Cloud Proxy这一个FQDN即可,无需逐一配置所有目标服务的FQDN,这个方案大幅简化了客户的防火墙配置,同时有效减少了网络不通问题

Stunnel是什么, 被设计用来解决什么问题

Stunnel是一款开源软件,其主要功能是为应用程序或服务提供TLS/SSL加密支持。 它的设计初衷是为了增强那些本身不支持加密功能的传统应用程序或服务的安全性
通过Stunnel, 可以在严格的防火墙规则下实现安全的加密通信,同时有效绕过可能存在的网络访问限制。

阅读全文 »

Microk8s Ingress是什么

Ingress是k8s的一种资源对象,用于管理外部对集群内服务的访问, 它通过提供一个统一的入口点,将外部流量路由到集群内部的不同服务。

Microk8s Ingress用于解决什么问题

k8s集群中服务默认只能在集群内访问。 如果需要从外部访问服务,通常需要使用NodePort或LoadBalancer类型服务,这两个服务都存在一些问题

  • NodePort会占用节点端口,可能导致端口冲突
  • LoadBalancer需要云提供商支持, 不适合本地环境
  • Ingress提供一种灵活的方式暴露服务,允许通过域名或路径规则将流量路由到不同的服务

Microk8s Ingress基本原理

  • Microk8s内置了一个Nginx的Ingress Controller, 负责监听k8s中的Ingress资源,当检测到Ingress资源更新时, 动态更新Nginx配置文件
  • 外部流量先到达Nginx, 再基于域名和URL将请求转发到Service, Service再将流量分发到Pod
阅读全文 »

前言

在Linux双系统升级过程中, 需要先备份新系统的所有文件得到升级包, 然后在需要升级的机器上解压升级包, 完成升级. tar是Linux系统最常用的备份工具之一。
然而, 在这种跨系统的备份和迁移中, 如果没有正确地处理文件所有者信息, 就会导致权限混乱, 升级后出现一些严重问题, 例如用户无法登录。

我在实际项目中遇到了这个问题。 以下说明为什么使用tar备份Linux系统时需要添加--numeric-owner参数

tar的--numeric-owner参数是什么

--numeric-owner是tar的一个选项, 用于在打包或解包时, 保留文件的UID和GID, 而不是直接映射当前系统的用户名称和组名称

为什么需要--numeric-owner参数

因为在跨系统迁移时,源系统和目标系统的用户配置可能是不一致的,例如:

  • 目标系统有一个用户alice(UID=1002), 源系统虽然也有用户alice, 但UID=1000
  • 这种情况很常见, 比如说目标系统和原系统的OS不一致, 或者在目标系统上新增了一些用户, 造成这种不一致
  • 如果备份时没有使用--numeric-owner, 源系统解压了tar包后得到的文件UID是1000; 升级到目标系统后, alice(UID=1002)并不是UID=1000的文件所有者, 就会出现权限错误的问题

演示案例

以下通过演示, 说明备份系统时忽略--numeric-owner时存在的问题

阅读全文 »

背景

我们的客户有一些本地部署的网关设备(CentOS 7)需要做固件升级。 原有的单系统分区架构缺乏有效的回滚机制, 升级遇到故障后无法回滚, 导致服务中断, 用户体验差

目标

设计一种解决方案, 自动将客户的网关设备从单系统分区平滑升级到双系统,同时保证用户配置(IP, DNS, 登录口令)不丢失
整个升级过程对客户完全透明, 无需客户进行额外操作(比如添加磁盘, 创建新机器)

方案

设计如下方案:

方案 描述 优点 缺点
定制initramfs 通过定制initramfs进入紧急模式,预先加载升级包和配置文件到内存,再重建磁盘分区 用户无感知, 且备份了旧的配置 内存空间有限, 升级包+解压后系统文件需小于内存
安装ISO 下载并安装目标系统ISO 不需要单独出一个升级包 客户的配置很难同步, 升级后需要用户做一些手动配置
阅读全文 »

什么是消息队列

消息队列是在消息传输过程中保存消息的容器。 通常有生产者和消费者两个角色:

  • 生产者只负责发送数据到消息队列,谁消费他不管
  • 消费者只负责从消息队列中取数据处理,谁发送数据他不管

常见消息队列中间件

  • Kafka 高吞吐量, 实时日志采集
  • RabbitMQ Erlang语言, 灵活性和易用性,中小规模应用
  • RocketMQ 阿里出品, Java开发, 国内市场有很高知名度和应用案例

为什么使用消息队列

阅读全文 »

前言

Linux安装RabbitMQ
官方教程

1. Hello RabbitMQ

使用Python pika客户端, 写一个简单的生产者和消费者

1
Producer ------> Queue -----> Consumer

编写Producer(send.py)

先连接Broker, 建立connection和channel

1
2
3
4
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

接着声明一个队列; 在RabbitMQ中,消息不是直接发送到队列,而是先发送到交换机(exchange), 由交换机发送到队列。

1
channel.queue_declare(queue='hello')

使用basic_publish发送消息。 这里使用默认交换机(‘’), routing_key参数指定为队列名称

1
channel.basic_publish(exchange='', routing_key='hello', body='Hello World!')
阅读全文 »