Ngrok 内网穿透部署指南

自建内网穿透隧道,安全高效实现公网访问

Ngrok 内网穿透部署方案

📦 项目地址

代码仓库: git@github.com:blowizer/ngrok.git

git clone git@github.com:blowizer/ngrok.git
cd ngrok

🎯 场景使用

实现 ngrok 公网转发访问,用于内网穿透,将本地服务暴露到公网。

🖥️ 服务器环境准备

1. Ubuntu 系统依赖安装

apt-get -y install zlib-devel openssl-devel perl hg cpio expat-devel gettext-devel curl curl-devel perl-ExtUtils-MakeMaker hg wget gcc gcc-c++ git

2. Go 语言环境安装

推荐版本: go version go1.16.3 linux/amd64

# 删除旧版本 golang 依赖包(如果存在)
rpm -qa|grep golang|xargs rpm -e

# 下载安装包
wget https://golang.org/dl/go1.16.3.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.16.3.linux-amd64.tar.gz

# 配置环境变量
vim /etc/profile
# 在文件末尾添加以下内容:
# #go lang
# export GOROOT=/usr/local/go
# export PATH=$PATH:$GOROOT/bin

# 使配置生效
source /etc/profile

# 检测是否安装成功
go version

3. 防火墙端口配置

vim /etc/sysconfig/iptables
# 添加以下内容:
# -A INPUT -m state --state NEW -m tcp -p tcp --dport 4443 -j ACCEPT
# -A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
# -A INPUT -m state --state NEW -m tcp -p tcp --dport 8081 -j ACCEPT
# -A INPUT -m state --state NEW -m tcp -p tcp --dport 2222 -j ACCEPT

# 重新加载防火墙规则
/etc/init.d/iptables reload
/etc/init.d/iptables restart

# 查看开放的端口
iptables -nL

注意: 如果使用云服务器(如阿里云),还需要在安全组中开放相应端口。

Kubernetes 集群部署 - etcd 安装与配置

etcd 作为 Kubernetes 的数据存储核心,稳定可靠的部署至关重要

📋 概述

etcd 是 Kubernetes 集群的核心数据存储组件,负责存储集群的所有配置数据、状态信息和元数据。本文档提供 etcd 集群的完整安装、配置和部署方案。

架构说明

  • 集群模式: 建议至少 3 个节点(奇数个节点,避免脑裂)
  • 数据目录: /var/lib/etcd
  • 配置文件: /etc/etcd/etcd.conf
  • 服务文件: /etc/systemd/system/etcd.service
  • 端口:
    • 2379: 客户端通信端口
    • 2380: 节点间通信端口

🔧 环境准备

节点信息配置

根据实际环境修改以下节点信息:

# 节点格式: 主机名:IP地址:etcd节点名
NODES=(
    "k8s-master-01:192.168.1.100:etcd-01"
    "k8s-node-01:192.168.1.101:etcd-02"
    "k8s-master-02:192.168.1.102:etcd-03"
)

系统要求

  • 操作系统: CentOS 7+ / Ubuntu 18.04+
  • 内存: 至少 2GB(推荐 4GB+)
  • 磁盘: 至少 20GB 可用空间(SSD 推荐)
  • 网络: 节点间网络延迟 < 10ms

📦 安装 etcd

步骤 1: 下载 etcd 二进制文件

#!/bin/bash
# install-etcd.sh - etcd 安装脚本

set -e

ETCD_VERSION="v3.5.9"  # 根据 K8s 版本选择兼容的 etcd 版本
INSTALL_DIR="/usr/local/bin"
DATA_DIR="/var/lib/etcd"
CONFIG_DIR="/etc/etcd"

# 交互式确认
read -p "是否执行 etcd 安装步骤?(y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "已跳过 etcd 安装"
    exit 0
fi

echo "=== 开始安装 etcd ${ETCD_VERSION} ==="

# 创建必要目录
sudo mkdir -p ${INSTALL_DIR}
sudo mkdir -p ${DATA_DIR}
sudo mkdir -p ${CONFIG_DIR}

# 下载 etcd
cd /tmp
wget https://github.com/etcd-io/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz

# 解压并安装
tar -xzf etcd-${ETCD_VERSION}-linux-amd64.tar.gz
sudo cp etcd-${ETCD_VERSION}-linux-amd64/etcd* ${INSTALL_DIR}/
sudo chmod +x ${INSTALL_DIR}/etcd*

# 验证安装
${INSTALL_DIR}/etcd --version
${INSTALL_DIR}/etcdctl version

echo "✓ etcd 安装完成"

步骤 2: 配置 etcd 集群

#!/bin/bash
# configure-etcd.sh - etcd 集群配置脚本

set -e

NODES=(
    "k8s-master-01:192.168.1.100:etcd-01"
    "k8s-node-01:192.168.1.101:etcd-02"
    "k8s-master-02:192.168.1.102:etcd-03"
)

ETCD_VERSION="v3.5.9"
INSTALL_DIR="/usr/local/bin"
DATA_DIR="/var/lib/etcd"
CONFIG_DIR="/etc/etcd"
CERT_DIR="/etc/etcd/ssl"

# 交互式确认
read -p "是否执行 etcd 集群配置?(y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "已跳过 etcd 配置"
    exit 0
fi

echo "=== 开始配置 etcd 集群 ==="

# 生成集群初始成员列表
INITIAL_CLUSTER=""
for NODE_INFO in "${NODES[@]}"; do
    IFS=':' read -r HOSTNAME NODE_IP ETCD_NAME <<< "$NODE_INFO"
    INITIAL_CLUSTER+="${ETCD_NAME}=https://${NODE_IP}:2380,"
done
INITIAL_CLUSTER=${INITIAL_CLUSTER%,}

echo "集群成员列表: ${INITIAL_CLUSTER}"

# 为每个节点配置 etcd
for NODE_INFO in "${NODES[@]}"; do
    IFS=':' read -r HOSTNAME NODE_IP ETCD_NAME <<< "$NODE_INFO"
    
    echo "配置节点: ${HOSTNAME} (${ETCD_NAME})"
    
    ssh root@${NODE_IP} << EOF
        # 创建目录
        mkdir -p ${DATA_DIR}
        mkdir -p ${CONFIG_DIR}
        mkdir -p ${CERT_DIR}
        
        # 创建 etcd 配置文件
        cat > ${CONFIG_DIR}/etcd.conf << EOC
# 节点名称
ETCD_NAME=${ETCD_NAME}
# 数据目录
ETCD_DATA_DIR=${DATA_DIR}
# 监听客户端请求的地址
ETCD_LISTEN_CLIENT_URLS=https://${NODE_IP}:2379,https://127.0.0.1:2379
# 监听对等节点请求的地址
ETCD_LISTEN_PEER_URLS=https://${NODE_IP}:2380
# 客户端访问地址
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://${NODE_IP}:2380
ETCD_ADVERTISE_CLIENT_URLS=https://${NODE_IP}:2379
# 初始集群成员列表
ETCD_INITIAL_CLUSTER=${INITIAL_CLUSTER}
# 集群状态(new 表示新集群,existing 表示加入已有集群)
ETCD_INITIAL_CLUSTER_STATE=new
# 集群 token
ETCD_INITIAL_CLUSTER_TOKEN=k8s-etcd-cluster
# 客户端证书配置(如果使用 TLS)
ETCD_CLIENT_CERT_AUTH=true
ETCD_CERT_FILE=${CERT_DIR}/server.crt
ETCD_KEY_FILE=${CERT_DIR}/server.key
ETCD_TRUSTED_CA_FILE=${CERT_DIR}/ca.crt
# 对等节点证书配置
ETCD_PEER_CLIENT_CERT_AUTH=true
ETCD_PEER_CERT_FILE=${CERT_DIR}/peer.crt
ETCD_PEER_KEY_FILE=${CERT_DIR}/peer.key
ETCD_PEER_TRUSTED_CA_FILE=${CERT_DIR}/ca.crt
EOC
        
        # 设置权限
        chmod 644 ${CONFIG_DIR}/etcd.conf
        chown -R etcd:etcd ${DATA_DIR} ${CONFIG_DIR} 2>/dev/null || true
        
        echo "✓ ${HOSTNAME} 配置完成"
EOF
done

echo "✓ etcd 集群配置完成"

步骤 3: 创建 systemd 服务

#!/bin/bash
# setup-etcd-service.sh - 创建 etcd systemd 服务

set -e

NODES=(
    "k8s-master-01:192.168.1.100:etcd-01"
    "k8s-node-01:192.168.1.101:etcd-02"
    "k8s-master-02:192.168.1.102:etcd-03"
)

INSTALL_DIR="/usr/local/bin"
CONFIG_DIR="/etc/etcd"

# 交互式确认
read -p "是否创建 etcd systemd 服务?(y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "已跳过服务创建"
    exit 0
fi

echo "=== 创建 etcd systemd 服务 ==="

for NODE_INFO in "${NODES[@]}"; do
    IFS=':' read -r HOSTNAME NODE_IP ETCD_NAME <<< "$NODE_INFO"
    
    echo "为 ${HOSTNAME} 创建服务..."
    
    ssh root@${NODE_IP} << EOF
        cat > /etc/systemd/system/etcd.service << EOS
[Unit]
Description=Etcd Server
Documentation=https://github.com/coreos/etcd
After=network.target
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=-${CONFIG_DIR}/etcd.conf
ExecStart=${INSTALL_DIR}/etcd
Restart=on-failure
RestartSec=10
LimitNOFILE=65536
# 关键:增加启动超时时间,避免集群启动时超时
TimeoutStartSec=120

[Install]
WantedBy=multi-user.target
EOS
        
        # 重新加载 systemd
        systemctl daemon-reload
        systemctl enable etcd
        
        echo "✓ ${HOSTNAME} 服务创建完成"
EOF
done

echo "✓ etcd 服务创建完成"

🚀 启动 etcd 集群

步骤 4: 启动集群

#!/bin/bash
# start-etcd-cluster.sh - 启动 etcd 集群

set -e

NODES=(
    "k8s-master-01:192.168.1.100:etcd-01"
    "k8s-node-01:192.168.1.101:etcd-02"
    "k8s-master-02:192.168.1.102:etcd-03"
)

# 交互式确认
read -p "是否启动 etcd 集群?(y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "已跳过集群启动"
    exit 0
fi

echo "=== 启动 etcd 集群 ==="

# 按顺序启动节点(避免同时启动导致的问题)
for i in "${!NODES[@]}"; do
    NODE_INFO="${NODES[$i]}"
    IFS=':' read -r HOSTNAME NODE_IP ETCD_NAME <<< "$NODE_INFO"
    
    echo "启动节点 ${HOSTNAME} (第 $((i+1)) 个节点)..."
    
    ssh root@${NODE_IP} "systemctl start etcd"
    
    # 等待节点启动
    sleep 5
    
    # 检查节点状态
    if ssh root@${NODE_IP} "systemctl is-active --quiet etcd"; then
        echo "✓ ${HOSTNAME} 启动成功"
    else
        echo "✗ ${HOSTNAME} 启动失败,请检查日志: journalctl -u etcd -n 50"
    fi
done

echo "=== 检查集群状态 ==="
# 使用第一个节点检查集群状态
FIRST_NODE="${NODES[0]}"
IFS=':' read -r FIRST_HOST FIRST_IP FIRST_NAME <<< "$FIRST_NODE"

ssh root@${FIRST_IP} "/usr/local/bin/etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/etcd/ssl/ca.crt --cert=/etc/etcd/ssl/server.crt --key=/etc/etcd/ssl/server.key endpoint health" || echo "注意: 如果使用 TLS,请确保证书已正确配置"

echo "✓ etcd 集群启动完成"

✅ 验证和监控

检查集群状态

# 检查服务状态
systemctl status etcd

# 查看日志
journalctl -u etcd -f

# 检查集群健康(如果使用 TLS)
etcdctl --endpoints=https://127.0.0.1:2379 \
    --cacert=/etc/etcd/ssl/ca.crt \
    --cert=/etc/etcd/ssl/server.crt \
    --key=/etc/etcd/ssl/server.key \
    endpoint health

# 查看集群成员
etcdctl --endpoints=https://127.0.0.1:2379 \
    --cacert=/etc/etcd/ssl/ca.crt \
    --cert=/etc/etcd/ssl/server.crt \
    --key=/etc/etcd/ssl/server.key \
    member list

常用维护命令

# 备份 etcd 数据
etcdctl snapshot save /backup/etcd-snapshot-$(date +%Y%m%d).db

# 恢复 etcd 数据
etcdctl snapshot restore /backup/etcd-snapshot-20231229.db \
    --data-dir=/var/lib/etcd-restore

# 查看集群统计信息
etcdctl endpoint status --write-out=table

📝 注意事项

  1. 证书配置: 如果使用 TLS,确保所有节点的证书已正确配置
  2. 网络连通性: 确保所有节点间的 2379 和 2380 端口互通
  3. 数据备份: 定期备份 etcd 数据,防止数据丢失
  4. 资源监控: 监控 etcd 的 CPU、内存和磁盘使用情况
  5. 版本兼容: 确保 etcd 版本与 Kubernetes 版本兼容

🔗 相关资源

工单短信触达需求文档

基于DDD领域驱动设计,实现工单短信自动触达、手动回复、回访处理及统计报表功能

📋 需求概述

项目背景

投诉工单系统需要新增短信通知功能,实现工单受理、结案、回访的短信触达,并改造直通率统计报表。

核心目标

  1. 自动发送受理短信:新建工单后自动发送受理通知
  2. 手动短信回复:支持处理人员手动发送结案通知短信
  3. 短信回访:工单结案后自动发送回访短信,处理客户回复
  4. 统计报表改造:基于主办机构计算直通办理率

🏗️ 领域模型设计

核心领域(Core Domain)

1. 投诉工单实体(ComplaintOrder)

// 核心字段
- orderId: 工单ID
- orderType: 工单类型12378监管转办消保转送咨询等
- contactName: 联系人姓名
- contactPhone: 联系人电话
- complainantPhone: 投诉人电话
- mainOrg: 主办机构总行/信用卡中心/分行/其他
- mainOperator: 主办人员
- isSmsReply: 是否短信回复/
- smsReplyTime: 回复时间
- isSmsVisit: 是否短信回访/
- visitDate: 回访日期
- visitTime: 回访时间
- visitResult: 回访效果满意/不满意
- processNotifyType: 处理决定告知方式短信/其他
- processNotifyTime: 处理决定告知时间

2. 短信交互实体(SmsInteraction)

- smsId: 短信记录ID
- orderId: 关联工单
- smsType: 短信类型受理通知/结案通知/回访
- templateId: 短信模板
- phone: 发送手机号
- customerName: 客户姓名
- sendTime: 短信发送时间
- sendOperator: 发送人
- replyContent: 客户回复内容
- replyTime: 客户回复时间

3. 短信模板实体(SmsTemplate)

- templateId: 模板ID
- templateName: 模板名称
- templateContent: 模板内容
- templateType: 类型受理/结案/回访
- approvedStatus: 业务审核状态
- visibleRoles: 可见角色总行/分行
- enabled: 是否启用

🎯 功能需求与开发任务

功能一:新建工单自动发送受理短信

📌 功能描述

投诉工单新建成功后,系统自动发送受理短信给联系人。

工作台

快速访问常用应用和系统

第四章:规则入微 · 服务网格

即使在天庭管辖下,服务间通信的复杂性仍需更精细的法则来约束

楔子:通信的复杂性

掌握Kubernetes后,韩立在云上仙境中如鱼得水。他的韩门运行稳定,能够自动扩缩容、自愈、滚动更新,一切都显得那么完美。

然而,随着服务的不断增多,韩立发现了一个新的问题:服务间通信的复杂性。

在微服务架构中,服务之间的通信需要处理很多横切关注点(Cross-Cutting Concerns):

  • 服务发现:如何找到目标服务
  • 负载均衡:如何分发请求
  • 熔断降级:如何防止服务雪崩
  • 限流:如何控制流量
  • 重试:如何处理失败
  • 超时:如何设置超时时间
  • 安全:如何加密通信、认证授权
  • 监控:如何追踪请求链路
  • 日志:如何记录通信日志

这些逻辑如果都写在业务代码中,会导致:

  1. 代码耦合:业务逻辑与通信逻辑混合
  2. 重复代码:每个服务都要实现相同的逻辑
  3. 难以维护:修改通信逻辑需要修改所有服务
  4. 技术栈绑定:不同语言需要实现不同的逻辑

韩立想起了源界中流传的"服务网格"(Service Mesh)理论。这个理论说,可以将服务间通信的逻辑从业务代码中抽离出来,下沉为基础设施,由Sidecar代理来处理。

“这就是我需要的!“韩立眼中闪烁着兴奋的光芒。


第一节:本命剑灵——Sidecar模式

在服务网格中,每个服务都有一个"本命剑灵”——Sidecar代理。这个代理附着在服务身边,专职处理服务间通信,让服务本体能够专心处理业务逻辑。

Sidecar就像源界中的"护道傀儡”,它:

  • 与业务服务同生共死:Sidecar和业务服务运行在同一个Pod中
  • 代理所有通信:所有进出服务的流量都经过Sidecar
  • 透明代理:业务服务无需感知Sidecar的存在

在Istio中,Sidecar由Envoy实现。Envoy是一个高性能的代理,支持HTTP/1.1、HTTP/2、gRPC等协议。

当服务A调用服务B时:

  1. 服务A发送请求 → Envoy Sidecar A
  2. Envoy Sidecar A进行服务发现、负载均衡、熔断等处理
  3. 请求发送到 → Envoy Sidecar B
  4. Envoy Sidecar B进行认证、限流等处理
  5. 请求转发到 → 服务B
  6. 响应按原路返回

这样,所有的通信逻辑都在Sidecar中处理,业务服务只需要专注于业务逻辑。


第二节:天条律法司——Istio控制平面

Sidecar负责处理具体的通信,但谁来制定规则呢?

这就是Istio控制平面的作用。控制平面就像"天条律法司",负责制定所有服务间通信的规则,并下发到每个Sidecar执行。

Istio控制平面包含以下组件:

Pilot:服务发现和流量管理

  • 从Kubernetes等注册中心获取服务信息
  • 将路由规则、负载均衡策略等配置下发到Envoy

Citadel:安全和证书管理

  • 为服务间通信提供mTLS(双向TLS)加密
  • 管理证书的生成、分发和轮换

Galley:配置验证和分发

  • 验证Istio配置的正确性
  • 将配置转换为Envoy可理解的格式

Mixer(已废弃,功能合并到Envoy):策略和遥测

  • 访问控制策略
  • 指标收集和日志记录

韩立部署了Istio:

# 安装Istio
istioctl install --set profile=default

# 为命名空间启用自动注入Sidecar
kubectl label namespace default istio-injection=enabled

当在启用了自动注入的命名空间中创建Pod时,Istio会自动注入Envoy Sidecar: