背景介绍
业务说明:微服务message通过K8S部署在linux服务器上,它需要把短信验证码,通过https请求推到第三方系统(域名是sms.yunpian.com),并在接收到成功的响应后,将验证码写入数据库(此时才生效)。
要做的事:拦截message发送到第三方系统的https请求,并返回成功的响应
实现概述
- 部署Mockoon服务模拟第三方系统,对请求进行响应(默认是http协议,监听3000接口)
- 在Nginx中配置反代理,将https请求转到Mockoon服务提供的http服务上
- 在message中配置/etc/hosts,把域名sms.yunpian.com映射为Nginx服务所在的IP
这样message发送到sms.yunpian.com的https请求,会发送到Nginx,Nginx再把请求转发到Mockoon服务,Mockoon服务返回发送成功的响应,完成模拟
详细实现步骤
1. Mockoon 服务部署和配置
- 首先保证服务器上安装有node.js工具,没有安装的可自行安装。node.js的版本和mockoon版本要对应,安装了node的直接查询版本
node --version
- 因为服务器上node.js版本是16,所以Mockoon要选择较低的5.0.0版本,使用 npm 全局安装 @mockoon/cli,
npm install -g @mockoon/cli@5.0.0
安装完成后,运行以下命令检查是否成功:
mockoon-cli --help
能看到输出的帮助信息,说明安装成功

- 编写一个简单的配置文件sms-mock.json,用于对请求进行响应
# 创建 Mockoon 配置文件 (sms-mock.json)
{
"name": "SMS Mock Service",
"port": 3000,
"routes": [
{
"method": "POST",
"path": "/v2/sms/single_send.json",
"responses": [
{
"statusCode": 200,
"body": "{\"code\":0,\"msg\":\"success\",\"count\":1}"
}
]
}
]
}
- 切换到配置文件目录下,启动Mockoon 服务
mockoon-cli start --data sms-mock.json --y
- 用另一个服务器发送请求进行测试
curl -X POST http://10.0.31.51:3000/v2/sms/single_send.json
成功返回配置文件中的响应体,Mockoon服务部署和配置完成
2. Nginx 反向代理配置
2.1 生成证书
因为https请求,需要证书,因此使用openssl命令生成自签名证书:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout private-key.key \
-out certificate.crt \
-subj "/CN=sms.yunpian.com"
2.2 配置Nginx反代理
说明:nginx支持配置多个域名,新增一个server即可
server {
listen 443 ssl http2;
server_name sms.yunpian.com;
# 证书位置
ssl_certificate /root/mocks/certificate.crt;
ssl_certificate_key /root/mocks/private-key.key;
# 短信发送接口代理
location /v2/sms/single_send.json {
proxy_pass http://10.0.31.51:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
3. Kubernetes 容器证书信任配置
3.1 生成证书的 ConfigMap
将第二步生成的证书复制一份到容器所在的服务器,生成 ConfigMap
kubectl create configmap sms-certificate --from-file=certificate.crt=./certificate.crt -n $NAMESPACE
其中sms-certificate 为起的别名,$NAMESPACE为pod部署的空间名称
3.2 编写pod资源配置文件
spec:
template:
spec:
initContainers:
- name: import-certificate
image: $CURRENT_IMAGE
command: ["sh", "-c"]
args:
- |-
set -e
echo "开始导入 SSL 证书..."
# 复制原始信任库
cp /opt/java/openjdk/lib/security/cacerts /truststore-volume/cacerts
# 导入证书到 Java 信任库
/opt/java/openjdk/bin/keytool -import -noprompt -trustcacerts \
-alias sms.yunpian.com \
-file /cert/certificate.crt \
-keystore /truststore-volume/cacerts \
-storepass changeit
echo "证书成功导入 Java 信任库"
volumeMounts:
- name: cert-volume
mountPath: /cert
readOnly: true
- name: truststore-volume
mountPath: /truststore-volume
containers:
- name: $CONTAINER_NAME
command: ["sh", "-c"]
args:
- |
cp /truststore-volume/cacerts \$JAVA_HOME/lib/security/cacerts
# 添加 hosts 条目
echo '10.0.31.51 sms.yunpian.com' >> /etc/hosts
echo "Hosts 条目添加成功"
# 以下是原pod文件中的内容
[ -d /opt/logs/\${HOSTNAME} ] || mkdir -p /opt/logs/\${HOSTNAME}
ln -sf /opt/logs/\${HOSTNAME} /opt/acx/acx-message/logs
[ -d /opt/sensor/\${HOSTNAME} ] || mkdir -p /opt/sensor/\${HOSTNAME}
ln -sf /opt/sensor/\${HOSTNAME} /opt/acx/acx-message/sensor
bash /opt/acx/acx-message/script/start.sh
volumeMounts:
- name: truststore-volume
mountPath: /truststore-volume
readOnly: true
volumes:
- name: cert-volume
configMap:
name: sms-certificate-itos2
- name: truststore-volume
emptyDir: {}
脚本中2个的变量获取
CURRENT_IMAGE=$(kubectl get deployment $DEPLOYMENT_NAME -n $NAMESPACE -o jsonpath='{.spec.template.spec.containers[0].image}')
CONTAINER_NAME=$(kubectl get deployment $DEPLOYMENT_NAME -n $NAMESPACE -o jsonpath='{.spec.template.spec.containers[0].name}')
实现说明:
- initContainers: 初始化容器,在主容器启动前执行一次性任务
把 JDK 原始 /opt/java/openjdk/lib/security/cacerts 复制到 /truststore-volume/cacerts。 用 keytool -import … 把/cert/certificate.crt 以别名 sms.yunpian.com导入/truststore-volume/cacerts,生成“官方库 + 自定义证书”的新信任库。此时truststore-volume里已有主容器可直接使用的 cacerts。
- containers: 主应用容器
使用命令 cp /truststore-volume/cacerts$JAVA_HOME/lib/security/cacerts,用 init 容器准备好的文件覆盖 JVM 默认信任库。 后续 JVM进程启动时,整个运行时环境天然信任这张证书,无需再指定 -Djavax.net.ssl.trustStore 等参数,完成“自定义证书对 Java 应用透明生效”。同时将在/etc/hosts文件中,添加映射,强制将sms.yunpian.com解析到内网IP。
- volumes: 定义存储卷
把第一步中自定义证书(certificate.crt)的ConfigMap(sms-certificate)挂进 Pod,同时声明一个 emptyDir 卷truststore-volume,供 init 容器与主容器共享。
3.3 将pod配置文件合并到当前的配置中
kubectl patch deployment $DEPLOYMENT_NAME -n $NAMESPACE --type='strategic' --patch-file="$PATCH_FILE"
其中,$PATCH_FILE为第二步中配置文件的名称
至此完成了Mockoon + Nginx + K8S 的整个方案的部署,系统发送短信后,会被成功的拦截并返回成功
3.4 包装成一个shell脚本
- 为了方便后面的执行,将第三步内容写进shell脚本,备份原有的配置文件,完成新增部分配置文件的编写和合并,并对执行情况进行检查
#!/bin/bash
set -e
# 配置变量
NAMESPACE="k8s-wyf"
DEPLOYMENT_NAME="acx-message-v1-server"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
echo "步骤 1: 备份当前 Deployment 配置"
kubectl get deployment $DEPLOYMENT_NAME -n $NAMESPACE -o yaml > deployment-backup-${TIMESTAMP}.yaml
echo "步骤 2: 动态获取当前镜像版本和容器名称"
CURRENT_IMAGE=$(kubectl get deployment $DEPLOYMENT_NAME -n $NAMESPACE -o jsonpath='{.spec.template.spec.containers[0].image}')
CONTAINER_NAME=$(kubectl get deployment $DEPLOYMENT_NAME -n $NAMESPACE -o jsonpath='{.spec.template.spec.containers[0].name}')
echo "当前镜像版本: $CURRENT_IMAGE"
echo "容器名称: $CONTAINER_NAME"
echo "步骤 3: 创建 Strategic Merge Patch 文件并应用"
PATCH_FILE=$(mktemp)
cat > "$PATCH_FILE" <<EOF
spec:
template:
spec:
initContainers:
- name: import-certificate
image: $CURRENT_IMAGE
command: ["sh", "-c"]
args:
- |-
set -e
echo "开始导入 SSL 证书..."
# 复制原始信任库
cp /opt/java/openjdk/lib/security/cacerts /truststore-volume/cacerts
# 导入证书到 Java 信任库
/opt/java/openjdk/bin/keytool -import -noprompt -trustcacerts \
-alias sms.yunpian.com \
-file /cert/certificate.crt \
-keystore /truststore-volume/cacerts \
-storepass changeit
echo "证书成功导入 Java 信任库"
volumeMounts:
- name: cert-volume
mountPath: /cert
readOnly: true
- name: truststore-volume
mountPath: /truststore-volume
containers:
- name: $CONTAINER_NAME
command: ["sh", "-c"]
volumeMounts:
- name: truststore-volume
mountPath: /truststore-volume
readOnly: true
- name: startup-script
mountPath: /scripts
volumes:
- name: cert-volume
configMap:
name: sms-certificate
- name: truststore-volume
emptyDir: {}
EOF
echo "应用 Strategic Merge Patch..."
kubectl patch deployment $DEPLOYMENT_NAME -n $NAMESPACE --type='strategic' --patch-file="$PATCH_FILE"
# 清理临时文件
rm -f "$PATCH_FILE"
echo "步骤 4: 等待 Pod 重启..."
echo "等待 10 秒让 Deployment 开始更新..."
sleep 10
# 等待 Pod 就绪
echo "等待新 Pod 就绪..."
for i in {1..30}; do
if kubectl get deployment $DEPLOYMENT_NAME -n $NAMESPACE -o jsonpath='{.status.readyReplicas}' | grep -q 1; then
echo "Pod 已就绪"
break
fi
echo "等待中... ($i/30)"
sleep 5
done
echo "步骤 6: 验证部署"
NEW_POD=$(kubectl get pods -n $NAMESPACE -l app=message-v1 -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
if [ -n "$NEW_POD" ] && kubectl get pod $NEW_POD -n $NAMESPACE >/dev/null 2>&1; then
echo "新 Pod 名称: $NEW_POD"
POD_STATUS=$(kubectl get pod $NEW_POD -n $NAMESPACE -o jsonpath='{.status.phase}')
echo "Pod 状态: $POD_STATUS"
if [ "$POD_STATUS" = "Running" ]; then
echo "检查 initContainer 日志:"
kubectl logs $NEW_POD -n $NAMESPACE -c import-certificate --tail=50 || echo "无法获取 initContainer 日志"
echo "检查证书是否已导入 Java 信任库:"
kubectl exec $NEW_POD -n $NAMESPACE -- /opt/java/openjdk/bin/keytool -list -cacerts -storepass changeit | grep "sms.yunpian.com" && echo "Java 信任库中找到证书" || echo "Java 信任库中未找到证书"
echo "检查 /etc/hosts 文件:"
kubectl exec $NEW_POD -n $NAMESPACE -- grep "sms.yunpian.com" /etc/hosts && echo "找到 hosts 条目" || echo "未找到 hosts 条目"
echo "检查应用日志:"
kubectl logs $NEW_POD -n $NAMESPACE --tail=10 || echo "无法获取应用日志"
else
echo "Pod 未处于 Running 状态,检查详情:"
kubectl describe pod $NEW_POD -n $NAMESPACE
fi
else
echo "未找到运行中的 Pod"
echo "检查 Deployment 状态:"
kubectl get deployment $DEPLOYMENT_NAME -n $NAMESPACE
fi
echo "自动化配置完成!"
echo "备份文件已保存: deployment-backup-${TIMESTAMP}.yaml"
733

被折叠的 条评论
为什么被折叠?



