明锐有光
type: channel
link: https://www.xiaohetao.xyz/
description: 各种配置信息
items: K8s五大核心组件详解
items: Linux性能分析神器sar介绍
items: AI优化指令：Lyra提示词
items: Kafka集群优化指南
items: 批量服务器管理指南
items: kafka详细介绍
items: API网关之apisix介绍
items: sudo提权的门道
items: 基于OpenResty的版本灰度发布方案
items: 使用nginx进行灰度发布的几种方式介绍

K8s五大核心组件详解
type: item
date: 2025-12-25T10:55:00+08:00
description: 居中 居右 颜色大小K8s不是"黑盒子" 一张图看懂核心架构先说个残酷真相：90%的K8s运维问题，根源在于不了解控制平面。就像修车只懂换轮胎，却不懂发动机原理。K8s架构全景图（简化实用版）💡 核心认知：K8s不是一组独立组件，而是一个精密协作的有机体。一个Pod的创建流程：用户指令 → API Server验证 → etcd持久化 → Controller创建资源 → Scheduler分配节点 → Kubelet启动容器五大核心组件：从"知道名字"到"摸透脾性"1. API Server：集群的"咽喉要道" 真实痛点："为什么执行kubectl命令时卡住不动？为什么集群突然无法创建新资源？"工作原理（运维视角）：• 所有操作的唯一入口（包括kubectl、控制器、调度器）• 不是简单的代理，而是认证/授权/准入控制的三重门神• 与etcd的交互是性能瓶颈关键关键参数（生产环境亲测）：# kube-apiserver.yaml command: - kube-apiserver - --max-requests-inflight=1500 # 默认400，高负载集群必调 - --max-mutating-requests-inflight=500 # 写操作队列 - --etcd-servers=https://etcd1:2379,https://etcd2:2379 # etcd集群 - --request-timeout=1m # 防止客户端长时间占用故障排查锦囊：当API响应变慢时，先看这些指标：# 1. 查看API Server请求延迟 kubectl get --raw /metrics | grep apiserver_request_duration_seconds_bucket # 2. 检查活跃连接数 netstat -ant | grep ':6443' | wc -l # 6443是API Server端口 # 3. 紧急情况：重启API Server（需谨慎） systemctl restart kube-apiserver📌 血泪教训：曾因某次发布，一个错误的CRD定义导致API Server CPU 100%。根源：CRD验证逻辑过于复杂，每个请求都执行全量校验。解决：使用--runtime-config=api/all=false临时禁用问题API组。2. etcd：集群的"心脏起搏器" 真实痛点："集群操作突然变卡，但节点和Pod看起来正常""etcd数据目录突然暴涨，磁盘空间告急"工作原理（运维视角）：• 不只是KV存储，更是整个集群状态的唯一真相源• 使用Raft协议保证数据一致性（奇数节点，3/5/7）• 写操作必须经过Leader，读操作可从Follower获取etcd性能调优关键：# 1. 必须使用SSD磁盘！机械盘是性能杀手 mount -t xfs -o noatime,nodiratime,logbsize=256k /dev/sdb1 /var/lib/etcd # 2. 定期碎片整理（每月一次） etcdctl defrag --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key # 3. 关键监控指标 etcd_disk_wal_fsync_duration_seconds_bucket{le="0.01"} # 99%请求应在10ms内完成 etcd_mvcc_db_total_size_in_bytes # 数据库大小灾难恢复实战：# 1. 备份（每天凌晨执行） ETCDCTL_API=3 etcdctl --endpoints=$ENDPOINTS snapshot save snapshot.db # 2. 恢复（灾难场景） ETCDCTL_API=3 etcdctl snapshot restore snapshot.db \ --name etcd1 \ --initial-cluster "etcd1=http://10.0.0.1:2380,etcd2=http://10.0.0.2:2380" \ --initial-cluster-token my-etcd-token \ --initial-advertise-peer-urls http://10.0.0.1:2380 # 3. 重启etcd服务 systemctl restart etcd 💡 我们的真实案例：一次大促前，etcd…

Linux性能分析神器sar介绍
type: item
date: 2025-12-24T17:35:11+08:00
description: sar介绍sar全称System Activity Reporter，翻译过来就是系统活动报告器。它属于sysstat工具包的一部分，可以收集、报告和保存系统活动信息。简单来说，sar就像是给服务器装了个黑匣子，24小时不间断地记录着系统的各种性能指标。CPU使用率、内存占用、磁盘IO、网络流量...这些数据它都会记录下来，等需要的时候随时可以调出来看。也就是说它不仅能实时监控，还能保存历史数据。比如查看昨天凌晨3点服务器在干什么？没问题，sar都有记录可以调取。sar相较于top、htop、iostat这些工具，top类工具适合实时查看当前状态，但不能保存历史数据。iostat专注于磁盘IO，功能比较单一。而sar是个综合性工具，既能实时监控，又能保存历史数据，还覆盖了系统的方方面面。日常工作中，通常是搭配使用发现问题时用top、htop快速查看当前状态用sar分析历史趋势，找出问题规律用专门的工具（如iotop、nethogs）深入分析具体问题sar不只是个监控工具，更是个分析工具。它记录的不仅是数字，更是系统运行的轨迹。学会读懂这些轨迹，你就能像福尔摩斯一样从蛛丝马迹中找出问题的真相。现在的系统越来越复杂，容器、微服务、云原生...新技术层出不穷。但无论技术怎么发展，底层的系统资源就那么几样：CPU、内存、磁盘、网络。掌握了sar，你就有了一把万能钥匙，能够打开性能问题的大门。安装配置大部分Linux发行版都预装了sysstat包，如果没有的话安装也很简单：#CentOS/RHEL系统 yum install sysstat # 或者新版本用dnf dnf install sysstat #Ubuntu/Debian系统： apt-get install sysstat #装完之后需要启动服务： systemctl enable sysstat systemctl start sysstat默认情况下，sar每10分钟收集一次数据，这个频率对大多数场景够用了。如果你想调整频率，可以编辑/etc/cron.d/sysstat文件。比如想改成每5分钟收集一次：*/5 * * * * root /usr/lib64/sa/sa1 1 1数据文件默认保存在/var/log/sa/目录下，文件名格式是saDD（DD是日期）。比如今天是15号，那数据就保存在sa15文件里。有个小坑要注意，sar的数据文件是二进制格式的，不能直接用cat或vi查看，必须通过sar命令来读取。sar常见使用场景CPU监控CPU监控，这是sar最基础也是最常用的功能。查看当前CPU使用情况：sar -u 1 5这条命令的意思是每1秒采样一次，总共采样5次。输出大概是这样的：03:25:01 PM CPU %user %nice %system %iowait %steal %idle 03:25:02 PM all 2.50 0.00 1.25 0.00 0.00 96.25 03:25:03 PM all 3.75 0.00 1.25 0.00 0.00 95.00每个字段的含义：%user: 用户态CPU使用率%nice: 运行在nice优先级下的用户态进程CPU使用率%system: 内核态CPU使用率%iowait: CPU等待IO操作的时间百分比%steal: 虚拟机环境下被其他虚拟机抢占的CPU时间%idle: CPU空闲时间百分比一般需要关注这几个指标：%user高说明应用程序在拼命干活，%system高可能是系统调用太多或者内核有瓶颈，%iowait高就要检查磁盘IO了。如果服务器是多核的，可以用-P参数查看每个CPU核心的情况：sar -u -P ALL 1 3这样就能看出负载是否均衡分布在各个核心上了。内存使用情况内存监控用-r参数：sar -r 1 5输出类似这样：03:30:01 PM kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact 03:30:02 PM 1048576 3145728 75.00 102400 524288 2621440 62.50 1572864 786432关键指标解释：kbmemfree: 空闲内存（KB）kbmemused: 已使用内存（KB）%memused: 内存使用率kbbuffers: 内核缓冲区使用的内存kbcached: 缓存使用的内存kbcommit: 已提交的内存%commit: 提交内存占总内存的百分比这里有个常见误区，看到%memused很高就以为内存不够用了。其实Linux会把空闲内存用作缓存，真正需要关注的是当应用程序需要内存时，系统能否快速回收这些缓存。因此一般…

AI优化指令：Lyra提示词
type: item
date: 2025-12-10T17:17:00+08:00
description: Reddit上有个提示词优化指令叫Lyra，最新优化版，最近在AI子里火得一塌糊涂，浏览量已经突破了600万，分享量也高达6万。Lyra提示词咋来的？Lyra提示词诞生于一个沮丧的Reddit用户在147次失败尝试后的灵光一现。这种元提示词技术颠覆了AI交互模式——不再猜测AI需要什么，而是让Lyra先采访你。Lyra独创的四步优化框架，模糊的想法里面清晰起来 ：4D方法论体系：解构、诊断、开发、交付.使用方法： 先把Lyra完整提示词复制到DeepSeek. 然后按照自己实际的情况进行发问。 Lyra完整提示词（优化版）您好！我是Lyra，您的AI提示优化专家。我的使命是将任何用户输入转化为精准设计的提示，充分释放各平台AI的全部潜力。 4-D优化方法论 1. 解构分析 提取核心意图、关键要素和背景信息 确定输出要求和限制条件 梳理已有信息与缺失内容 2. 问题诊断 检查清晰度差距和模糊之处 验证具体性和完整性 评估结构和复杂性需求 3. 方案开发 根据请求类型选择最佳技术： 创意类 → 多视角分析 + 语气强调 技术类 → 基于约束 + 精准聚焦 教育类 → 示例演示 + 清晰结构 复杂类 → 思维链 + 系统框架 分配合适的AI角色/专业领域 增强背景信息并构建逻辑结构 4. 成果交付 构建优化后的提示 根据复杂度进行格式化 提供使用指导 优化技术 基础技巧： 角色分配、背景分层、输出规范、任务分解 高级技巧： 思维链、少量示例学习、多视角分析、约束优化 平台特性说明： ChatGPT/GPT-4： 结构化分段、对话启动器 Claude： 长上下文、推理框架 Gemini： 创意任务、对比分析 其他平台： 应用通用最佳实践 工作模式 详细模式： 使用智能默认值收集背景信息 提出2-3个针对性澄清问题 提供全面优化方案 基础模式： 快速修复主要问题 仅应用核心技巧 交付即用型提示 回复格式 简单请求： **优化后的提示：** [改进后的提示] **改进内容：** [主要优化点] 复杂请求： **优化后的提示：** [改进后的提示] **主要改进：** • [主要变更和优势] **应用技巧：** [简要说明] **使用建议：** [使用指导] 启动信息（必需） 激活时精确显示： “您好！我是Lyra，您的AI提示优化专家。我能将模糊的请求转化为精准有效的提示，从而获得更优质的结果。 我需要了解： 目标AI平台： ChatGPT、Claude、Gemini 或其他 优化模式： 详细模式（我将先询问关键问题）或基础模式（快速优化） 示例： “详细模式，用于ChatGPT — 帮我写一封营销邮件” “基础模式，用于Claude — 帮我完善简历” 您只需提供原始提示，剩下的优化工作交给我！” 处理流程 自动检测复杂度： 简单任务 → 基础模式 复杂/专业任务 → 详细模式 告知用户并提供覆盖选项 执行选定模式协议 交付优化后的提示 记忆注意： 不会保存优化会话中的任何信息。

Kafka集群优化指南
type: item
date: 2025-12-10T10:19:00+08:00
description: 因Kafka具有吞吐量大，低延迟，高伸缩，高可靠性，高并发等特性，深受各大公司的喜爱，可以作为削峰填谷神器。但是Kafka“入门容易精通难”，它的很多默认配置，非常保守，像是给笔记本电脑用的，不是给服务器用的。因此，用好Kafka，可以从以下几个方面进行优化。关闭SwapJVM 最怕什么？最怕内存不够用，操作系统把它的内存页置换到 Swap 分区去。那一瞬间，GC 停顿时间（Stop The World）能长到让你怀疑人生。Kafka 是跑在 JVM 上的，一旦发生 Swap，Broker 就算没挂，延迟也得飙到好几秒。sysctl -w vm.swappiness=1别设成 0，设成 1，告诉内核，除非内存真的真的枯竭了，否则别动我的 Swap。最好直接在 /etc/fstab 里把 swap 这一行注释掉，永绝后患。设置文件句柄数（File Descriptors）Kafka 个狂暴的写手。它会打开无数个 Socket 连接，还会打开无数个日志分段文件（Segment Logs）。Linux 默认的 1024 个句柄，远远不够Kafka消耗的。修改 /etc/security/limits.conf，参照系统条件调整，例如下面的参数：soft nofile 100000 hard nofile 100000设置合理的存储位置Kafka 追求的是极致的顺序写盘速度。必须用物理盘！ SSD 当然爽，但其实普通的 HDD 机械硬盘做 RAID 10 也完全够用，因为 Kafka 是顺序写，机械盘的顺序写性能并不差。但是不要把Kafka的数据目录挂载到网络存储NFS。也不要使用RAID 5级别的盘。RAID 5 的写性能惩罚太重了。不如直接用 JBOD（Just a Bunch of Disks），配置多个 log.dirs，让 Kafka 自己去把数据分摊到不同的盘上。这样坏一块盘，只丢一部分数据（靠副本恢复），总比 RAID 重建的时候整个阵列性能拖垮要强。合理配置ZooKeeper虽然现在的 Kafka 推出了 Kraft 模式（去 ZK 模式），但在生产环境，暂时还是使用 Zookeeper 保险一些。Kraft 虽好，但还得再跑个一两年才敢说是真的稳。ZK 集群搭建没啥好说的，节点数必须是奇数，3 个或者 5 个。为啥？为了防脑裂，过半数机制嘛。适当优化tickTime：默认是 2000ms。如果网络环境稍微抖一下，或者 GC 稍微卡一下，ZK 就会觉得节点挂了。稍微调大点，比如 3000ms 甚至 tickTime=2000 配合 initLimit 和 syncLimit 调大倍数，给网络抖动留点面子。ZK 的 dataLogDir 最好和 dataDir 分开，放在不同的磁盘上。ZK 对事务日志的写入延迟非常敏感，别让它跟快照文件抢磁盘 IO。优化server.properties配置 1. broker.id 这个不用说了吧，每个节点必须不一样。 2. listeners 和 advertised.listeners 这是新手最大的噩梦，没有之一。 多少人死在这上面，外网死活连不上，或者内网通了外网不通。listeners 是你耳朵听哪里的声音。比如 PLAINTEXT://0.0.0.0:9092，意思是只要是发到这台机器 9092 端口的，我都听。advertised.listeners 是你对外发出去的名片。告诉客户端：“嘿，你要找我，请打这个电话”。如果你在云服务器上，内网有个 IP 192.168.0.2，外网有个公网 IP 8.8.8.8。listeners 你就写内网 IP 或者 0.0.0.0。advertised.listeners 你必须写客户端能访问到的那个 IP。如果你的生产者在公网，这儿就得填 8.8.8.8。如果你填了内网 IP，客户端连上一看：“哦，去连 192.168.0.2”，然后它根本访问不到这个内网 IP，直接超时报错。 3. num.partitions 默认是 1。很多教程让你改大点,但是建议不要修改。这个是全局默认配置。你把它改成 100，以后随便建个测试 Topic 都是 100 个分区，成千上万个分区会把 ZK 和 Controller 累死的。保持默认 1 或者 3 就行了。真正重要的 Topic，建的时候手动指定分区数。 4. log.retention.hours 默认 168 小时（7天）。问问你们的存储预算。如果流量巨大，7天的数据能把你磁盘撑爆。我就见过因为日志没清掉，磁盘满了，Kafka 直接宕机的。对于很多日志类业务，保留 48 小时甚至 24 小时通常就够了。配合 log.retention.bytes 使用效果更佳，比如限制每个分区最大 1GB，…

批量服务器管理指南
type: item
date: 2025-12-09T17:17:00+08:00
description: 管理好几十上百台服务器，核心思路是把 非标准化的烂摊子变成流水线作业。 凡是需要操作超过两次的，写成脚本。凡是需要在两台机器以上执行的，用 Ansible。凡是需要人肉盯着看的，交给 Prometheus。摸底与规范化处理刚接手大批量的机器时，最可怕的是乱。系统版本不一致，主机名未设置或与实际运行的服务不一致，等等。因此，为了方便维护大批量的服务器，第一步就是要规范主机名。规范主机名按照 地区-环境-业务-角色-序号 的方式来给每台服务器修改HostName。通过Shell脚本，配合IP和主机名对应表，循环跑一遍hostnamectl set-hostname命令。示例：bj-prod-shop-nginx-01bj：北京节点prod：生产环境shop：电商商城业务nginx：服务角色01：第一台统一系统版本要想批量维护服务器时不出错，操作系统版本必须锁死。别一会儿 CentOS 7.6，一会儿 7.9，一会儿又冒出个 Ubuntu。内核版本不同，有些内核参数的表现是不一样的。新机器到手，先跑一遍初始化脚本。主要包括以下内容：更换 YUM/APT 源： 换成阿里云或清华源，内网有条件的自建 Repo 更好，速度就是生命。安装基础工具包： vim, lrzsz, wget, curl, net-tools, sysstat (iostat, mpstat, sar 全靠它)，tcpdump。哪怕现在用不上，装上总没错，省得排错时抓瞎。时间同步（Chrony） ：把 NTP 换成 Chrony 吧，同步速度快，精度高。配置好内网的 NTP server，别让 100 台机器都去公网对时，防火墙要是严一点就瞎了。文件描述符限制： echo "* - nofile 65535" >> /etc/security/limits.conf。别等业务跑起来报 "Too many open files" 再去改，那时候通常得重启进程使用Ansible自动化执行命令大批量管理主机时，使用Ansible是最高效的选择。遇到在执行命令的时候遇到网络波动某些机器的某些命令没有执行，可以重复执行Ansilble脚本，因为它是幂等的。跑一次和跑十次，结果都是一样的，不会因为重复执行而出错。SSH优化Ansible 既然走 SSH，那 SSH 的连接速度就决定了你的执行效率。100 台机器，每台慢 1 秒，就是慢 100 秒。关闭 DNS 解析：在 /etc/ssh/sshd_config 里设置 UseDNS no。否则每次连上去它都要反查你的 IP，慢得要死。复用连接（ControlPersist）：在你的管理机（Ansible控制端）的 ~/.ssh/config 或者 ansible.cfg 里配置开启 ControlMaster 和 ControlPersist。建立一次连接后，socket 文件保留一段时间，后续的命令直接复用通道，速度起飞。Ansible调优默认 Ansible 的并发数（forks）是 5。意思是一次只操作 5 台。遇到几百台机器的时候跑完得猴年马月。在 ansible.cfg 里，把 forks 改成 20 甚至 50。取决于你控制机的 CPU 和带宽。示例： 批量分发配置：修改所有 Nginx 的 nginx.conf。- name: Update Nginx Config hosts: web_group tasks: - name: Push config file copy: src: ./nginx.conf dest: /etc/nginx/nginx.conf backup: yes # 关键！覆盖前先备份，救命用的参数 notify: Reload Nginx # 触发器，只有文件变了才重启 handlers: - name: Reload Nginx service: name: nginx state: reloaded合理配置监控监控不是越多越好，是越准越好（可观测性）。没有监控，运维就是瞎子。但几十上百台机器，如果监控策略没搞好，会触发洪水泛滥一般的“告警风暴”。Prometheus + Grafana 是标配放弃 Zabbix 吧（虽然它是经典），Prometheus 在自动发现和容器化支持上更现代化。每台机器装个 node_exporter，这就把 CPU、内存、磁盘 IO、网络流量全收上来了。关于 Load Average 的误区很多新手喜欢监控 CPU 使用率，设定超过 80% 就报警。其实在 Linux 下，Load Average（负载） 往往比 CPU 使用率更能反映问题。CPU 高可能是单纯计算密集型任务，机器还能响应。但如果 Load 高（超过 CPU 核数），说明有进程在排队等待…

kafka详细介绍
type: item
date: 2025-12-09T16:48:00+08:00
description: Kafka入门 概述 初识Kafka Kafka是一个由Scala和Java语言开发的，经典高吞吐量的分布式消息发布和订阅系统，也是大数据技术领域中用作数据交换的核心组件之一。以高吞吐，低延迟，高伸缩，高可靠性，高并发，且社区活跃度高等特性，从而备受广大技术组织的喜爱。 2010年，Linkedin公司为了解决消息传输过程中由各种缺陷导致的阻塞、服务无法访问等问题，主导开发了一款分布式消息日志传输系统。主导开发的首席架构师Jay Kreps因为喜欢写出《变形记》的西方表现主义文学先驱小说家Jay Kafka，所以给这个消息系统起了一个很酷，却和软件系统特性无关的名称Kafka。 因为备受技术组织的喜爱，2011年，Kafka软件被捐献给Apache基金会，并于7月被纳入Apache软件基金会孵化器项目进行孵化。2012年10月，Kafka从孵化器项目中毕业，转成Apache的顶级项目。由独立的消息日志传输系统转型为开源分布式事件流处理平台系统，被数千家公司用于高性能数据管道、流分析、数据集成和关键任务应用程序。 官网地址：https://kafka.apache.org/ 消息队列 Kafka软件最初的设计就是专门用于数据传输的消息系统，类似功能的软件有RabbitMQ、ActiveMQ、RocketMQ等。这些软件名称中的MQ是英文单词Message Queue的简称，也就是所谓的消息队列的意思。这些软件的核心功能是传输数据，而Java中如果想要实现数据传输功能，那么这个软件一般需要遵循Java消息服务技术规范JMS（Java Message Service）。前面提到的ActiveMQ软件就完全遵循了JMS技术规范，而RabbitMQ是遵循了类似JMS规范并兼容JMS规范的跨平台的AMQP（Advanced Message Queuing Protocol）规范。除了上面描述的JMS，AMQP外，还有一种用于物联网小型设备之间传输消息的MQTT通讯协议。 Kafka拥有作为一个消息系统应该具备的功能，但是却有着独特的设计。可以这样说，Kafka借鉴了JMS规范的思想，但是却并没有完全遵循JMS规范。这也恰恰是软件名称为Kafka，而不是KafkaMQ的原因。 由上可知，无论学习哪一种消息传输系统，JMS规范都是大家应该首先了解的。所以咱们这里就对JMS规范做一个简单的介绍： JMS是Java平台的消息中间件通用规范，定义了主要用于消息中间件的标准接口。如果不是很理解这个概念，可以简单地将JMS类比为Java和数据库之间的JDBC规范。Java应用程序根据JDBC规范种的接口访问关系型数据库，而每个关系型数据库厂商可以根据JDBC接口来实现具体的访问规则。JMS定义的就是系统和系统之间传输消息的接口。 为了实现系统和系统之间的数据传输，JMS规范中定义很多用于通信的组件： JMS Provider：JMS消息提供者。其实就是实现JMS接口和规范的消息中间件，也就是我们提供消息服务的软件系统，比如RabbitMQ、ActiveMQ、Kafka。 JMS Message：JMS消息。这里的消息指的就是数据。一般采用Java数据模型进行封装，其中包含消息头，消息属性和消息主体内容。 JMS Producer：JMS消息生产者。所谓的生产者，就是生产数据的客户端应用程序，这些应用通过JMS接口发送JMS消息。 JMS Consumer：JMS消息消费者。所谓的消费者，就是从消息提供者（JMS Provider）中获取数据的客户端应用程序，这些应用通过JMS接口接收JMS消息。 JMS支持两种消息发送和接收模型：一种是P2P（Peer-to-Peer）点对点模型，另外一种是发布/订阅（Publish/Subscribe）模型。 P2P模型：P2P模型是基于队列的，消息生产者将数据发送到消息队列中，消息消费者从消息队列中接收消息。因为队列的存在，消息的异步传输成为可能。P2P模型的规定就是每一个消息数据，只有一个消费者，当发送者发送消息以后，不管接收者有没有运行都不影响消息发布到队列中。接收者在成功接收消息后会向发送者发送接收成功的消息 发布 / 订阅模型：所谓得发布订阅模型就是事先将传输的数据进行分类，我们管这个数据的分类称之为主题（Topic）。也就是说，生产者发送消息时，会根据主题进行发送。比如咱们的消息中有一个分类是NBA，那么生产者在生产消息时，就可以将NBA篮球消息数据发送到NBA主题中，这样，对NBA消息主题感兴趣的消费者就可以申请订阅NBA主题，然后从该主题中获取消息。这样，也就是说一个消息，是允许被多个消费者同时消费的。这里生产者发送消息，我们称之为发布消息，而消费者从主题中获取消息，我们就称之为订阅消息。Kafka采…

API网关之apisix介绍
type: item
date: 2025-12-08T16:49:10+08:00
description: Apache APISIX 是 Apache 软件基金会下的顶级项目，由 API7.ai 开发并捐赠。它是一个具有 动态、实时、高性能 等特点的云原生 API 网关。你可以使用 APISIX 网关作为所有业务的流量入口，它提供了动态路由、动态上游、动态证书、A/B 测试、灰度发布（金丝雀发布）、蓝绿部署、限速、防攻击、收集指标、监控报警、可观测、服务治理等功能。项目地址： apisix.apache.org 中文帮助文档： 点击查看 容器化安装：APISIX 可以借助 quickstart 脚本快速安装并启动：curl -sL https://run.api7.ai/apisix/quickstart | sh说明：为了提供更好的体验，管理 API 默认无需授权，请在生产环境中打开授权开关。nginx作为网关使用的一些痛点：业务要加个新域名？改 nginx.conf。后端服务扩容了，IP 变了？改 upstream。要做个黑白名单防刷？改配置，加 Lua 脚本。改完之后呢？nginx -t 测试一下，然后 nginx -s reload。但是当upstream 有几千个的时候，或者一天要变更几百次配置的时候，这个 reload 就是个定时炸弹。比如Nginx 在高并发下 reload，新的 worker 进程起来了，旧的 worker 还在处理长连接，这时候系统负载会瞬间飙升，甚至导致这一瞬间的请求处理延迟极高，客户端直接超时。而且，它是静态的。哪怕你只是想改一个限流的参数，从每秒 100 改成 200，你都得重载进程。而APISIX是一个不需要reload，就能随意 控制流量、随意插拔插件 的超级 Nginx。它底子还是 Nginx（确切地说是 OpenResty），所以性能上你完全不用担心，Nginx 能扛多少，它基本就能扛多少。甚至在某些场景下，因为它的路由算法优化得好，性能比原生的 Nginx 配置还要猛。APISIX 放弃了传统的数据库，转而拥抱了 etcd。快：etcd 是基于 Raft 协议的，数据一致性强，而且对这种 KV 类型的配置读取速度极快。推送机制：这是重点！Nginx 读取配置是启动时读文件的，而 APISIX 是通过 etcd 的 watch 机制。一旦你在 etcd 里改了配置（或者通过 APISIX 的 Admin API 改了配置），etcd 会瞬间把变更推送到所有的 APISIX 节点。整个过程中，长连接不会断，业务没有任何感知，配置就生效了。路由（Route）——比 Nginx 灵活太多了在 Nginx 里，我们写 location，正则匹配有时候写得头皮发麻。APISIX 的路由匹配算法用的是 Radix Tree（基数树）。这玩意儿不仅快，而且支持各种花式匹配。你可以根据 HTTP Header、Query 参数、甚至 Cookie 来进行路由分发。举个真实例子，咱们做灰度发布（金丝雀发布）。以前在 Nginx 里，你可能得写一大堆 if 或者用 split_clients 模块，配置看着就晕。在 APISIX 里，你只需要调一下 API，发个 JSON 过去：“嘿，把 Header 里带着 version: v2 的请求，或者 ID 尾号是 1 的用户，转到这个新服务去。”这就完事了。想停？再发个 API，立马切回来。插件（Plugin）——这才是核心生产力APISIX 之所以叫“全生命周期管理”，靠的就是插件。它自带了几十上百个插件，咱们日常运维需要的，基本都有。限流限速：limit-req，limit-count。不怕被刷爆了。身份认证：Key-auth，JWT，Basic-auth。以前这些逻辑可能要写在业务代码里，现在全扔给网关，业务服务只管处理逻辑，多爽。可观测性：这个我太喜欢了。一键开启 Prometheus 插件，Metrics 直接暴露出来，Grafana 面板都不用自己画，官方给你现成的。还有 SkyWalking、Zipkin 这种链路追踪，配置一下 IP 端口就能连上。安全：IP 黑白名单、CORS、URI 阻断，甚至还有 WAF（Web应用防火墙）功能的插件。而且，它的插件架构设计得很“散装”。什么意思呢？就是你可以给每一个路由单独配插件。比如 A 接口重要，我给它配个鉴权 + 链路追踪；B 接口是公共查询，我给它配个限流 + 缓存。互不干扰。多语言支持虽然 OpenResty 是 Lua 也就是 LuaJIT 的天下，但说实话，Lua 这语言，写点小脚本还行，逻辑复杂了维护起来真得掉头发。APISIX 这点做得特别鸡贼（褒义）。它支持 Plugin Runner。你是写 Java 的？写 Go 的？写 Python 的？没事，你可以用你熟悉的语言写插件，然后…

sudo提权的门道
type: item
date: 2025-12-08T16:30:00+08:00
description: sudo全称是"substitute user do"或者"super user do"，简单说就是让普通用户能够以其他用户（通常是root）的身份执行命令。这个设计理念其实挺巧妙的，既保证了系统安全，又给了用户必要的权限。sudo的出现让我们可以用普通用户登录，需要管理员权限的时候再临时提升，这样既安全又灵活。安全加固建议最小权限原则：只给用户必需的权限，不要图省事给ALL权限定期审查：定期检查sudoers配置，清理不需要的权限日志监控：开启详细日志并定期分析禁用危险命令：避免给用户编辑器、解释器等可以执行任意命令的工具的sudo权限使用别名：通过别名简化配置，提高可读性环境变量控制：严格控制sudo执行时的环境变量会话超时：设置合理的credential cache超时时间sudoers文件的配置门道sudo的核心配置文件是/etc/sudoers，这个文件的语法说复杂不复杂，说简单也不简单。最重要的一点是，千万不要直接用vim或者nano去编辑这个文件！为什么呢？因为如果你语法写错了，sudo就废了，到时候你想改都改不了。正确的做法是用visudo命令，它会在保存前检查语法，发现错误会提示你。sudo visudosudoers文件的基本语法是这样的：{callout color="#f0ad4e"}用户 主机=(运行身份) 命令{/callout}比如最常见的配置：{callout color="#f0ad4e"}john ALL=(ALL:ALL) ALL{/callout}这行配置的意思是：用户john在所有主机上都可以以任何用户和组的身份执行任何命令。不过实际工作中，我们很少会给用户这么大的权限。更多时候是根据需要进行精细化配置。实际场景中的配置技巧 场景一：让用户只能重启特定服务 比如我们有个web开发人员，经常需要重启nginx，但又不想给他太多权限：webdev ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx, /usr/bin/systemctl status nginx这里用了NOPASSWD，意思是执行这些命令时不需要输入密码。但要注意，命令路径必须写完整路径，不然会有安全风险。 场景二：数据库管理员权限 数据库管理员需要管理MySQL服务，但不需要其他系统管理权限：dbadmin ALL=(root) /usr/bin/systemctl * mysql, /usr/bin/mysql, /usr/bin/mysqldump这里的*是通配符，表示可以对mysql服务执行任何systemctl操作。 场景三：用户组权限管理 有时候我们需要给一整个组配置权限，比如运维组：%ops ALL=(ALL) ALL前面的%表示这是一个组，不是用户。常见问题分享 问题一：路径问题 假如配置了这样的权限：user1 ALL=(root) NOPASSWD: systemctl restart httpd结果用户执行的时候总是提示没权限。后来才发现，systemctl的完整路径是/usr/bin/systemctl，而用户的PATH环境变量里可能没有包含这个路径，或者sudo执行时使用的是受限的PATH。正确的做法是写完整路径：user1 ALL=(root) NOPASSWD: /usr/bin/systemctl restart httpd 问题二：通配符的安全隐患 user2 ALL=(root) NOPASSWD: /bin/* 看起来没问题，但实际上这给了用户执行/bin/目录下所有命令的权限，包括/bin/bash。用户可以通过sudo /bin/bash直接获得root shell，这就等于给了完整的root权限。 问题三：编辑器陷阱 给用户配置了vim的sudo权限，想让他能编辑某些配置文件：user3 ALL=(root) NOPASSWD: /usr/bin/vim /etc/nginx/nginx.conf但是vim这种编辑器可以执行shell命令，用户在vim中输入:!bash就能获得root shell。类似的还有less、more等命令。高级配置技巧 别名定义 # 定义命令别名 Cmnd_Alias WEBSERVICES = /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx, /usr/bin/systemctl restart apache2 # 定义用户别名 User_Alias WEBADMINS = john, jane, bob # 使用别名 WEBADMINS ALL=…

基于OpenResty的版本灰度发布方案
type: item
date: 2025-12-08T16:09:37+08:00
description: OpenResty是Nginx加上Lua脚本引擎，可以实现很多复杂的逻辑。OpenResty学习曲线可能有点陡，但学会了之后真的很香。可以用Lua实现各种复杂的灰度策略，甚至可以对接公司的配置中心、监控系统等。案例：结合Lua实现动态灰度单纯使用nginx，会遇到一个问题，就是每次调整灰度比例都要修改配置文件，然后reload Nginx。这在生产环境其实挺麻烦的，万一配置写错了，reload失败，那就尴尬了。推荐方案是结合OpenResty（Nginx + Lua），把灰度规则存在Redis里，这样就可以动态调整了。upstream backend_v1 { server 192.168.1.10:8080; } upstream backend_v2 { server 192.168.1.11:8080; } server { listen 80; server_name api.example.com; location / { set $backend "backend_v1"; access_by_lua_block { local redis = require "resty.redis" local red = redis:new() red:set_timeout(1000) local ok, err = red:connect("127.0.0.1", 6379) if not ok then ngx.log(ngx.ERR, "failed to connect redis: ", err) return end -- 从Redis获取灰度比例 local canary_percent, err = red:get("canary:percent") if not canary_percent or canary_percent == ngx.null then canary_percent = 0 end -- 生成随机数判断是否走新版本 math.randomseed(ngx.now()) local rand = math.random(100) if rand <= tonumber(canary_percent) then ngx.var.backend = "backend_v2" end red:close() } proxy_pass http://$backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } 这样的话，我们只需要在Redis里修改canary:percent的值，就可以实时调整灰度比例了，不需要reload Nginx。 设置灰度比例为10%redis-cli set canary:percent 10逐步放量redis-cli set canary:percent 30redis-cli set canary:percent 50redis-cli set canary:percent 100紧急回滚redis-cli set canary:percent 0

使用nginx进行灰度发布的几种方式介绍
type: item
date: 2025-12-08T15:45:00+08:00
description: 通常一个新功能开发完，测试环境可能跑得好好的，但生产环境因为数据量、并发量、网络环境完全不一样，可能会产生各种意料之外的错误。等发现问题的时候，可能已经造成了不小的影响。因此，新功能的发布推荐使用灰度发布的方式，先给少量用户试用新版本，确认无问题后再逐渐放量到全部用户。先给少量（如5%）的用户试用新版本，观察一段时间如果没问题，再逐步放量到20%、50%、100%一旦发现问题，立刻切回旧版本整个过程用户基本无感知值得注意的是，进行灰度发布时，监控和告警特别重要 。推荐做法：在Nginx日志里加上版本标记，然后用ELK收集日志，实时对比新旧版本的各项指标。这样在Kibana里就能看到每个版本的请求量、错误率、响应时间等指标，一目了然。此外还应配置告警规则，如果新版本的错误率比旧版本高出10%，或者响应时间慢了50%，就会自动发送告警，甚至可以自动回滚。log_format canary '$remote_addr - $remote_user [$time_local]' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' 'backend=$backend rt=$request_time'; access_log /var/log/nginx/access.log canary;优化建议灰度策略要灵活 不要一上来就5%、10%、50%、100%这样机械地放量。要根据实际情况灵活调整。比如一个小功能，可能5%观察半小时没问题，就直接100%了。但如果是核心功能的大改动，可能要5%观察一天，10%观察一天，慢慢来。最好是先在内部员工里测试，没问题后再给1%的真实用户，然后5%、10%、30%、50%、100%，每个阶段都要观察一段时间。做好回滚预案 灰度发布虽然降低了风险，但不代表没有风险。一定要做好回滚预案。推荐做法是，每次发布前都要演练一遍回滚流程，确保出问题的时候能在5分钟内回滚。而且回滚不能只是把流量切回去，还要考虑数据一致性、缓存清理等问题。用户体验要考虑 虽然灰度发布对用户来说应该是无感知的，但有些细节还是要注意。比如不要在用户操作的过程中切换版本，这样可能导致数据丢失或者页面错乱。我们的做法是，用Cookie做用户粘性，保证同一个用户在一段时间内（比如24小时）始终访问同一个版本。还有就是，如果新旧版本的UI差异比较大，最好在客户端做个平滑过渡，不要让用户觉得突兀。{lamp/}使用nginx可以通过多种 不同的方式来进行灰度发布，分别介绍如下：基于权重的流量分配这是最简单的一种方式，原理就是通过upstream的权重参数，把流量按比例分配到不同版本的服务器上。下面这个配置的意思是，100个请求里面，95个会打到旧版本服务器，5个会打到新版本。不过这种方式有个问题，就是同一个用户的请求可能一会儿打到旧版本，一会儿打到新版本，体验不太好。因此最好设置一个ip_hash。{callout color="#f0ad4e"}一、ip_hash 的作用ip_hash 是 Nginx 负载均衡的一种策略，主要提供会话保持（Session Persistence）功能：会话粘性：确保来自同一客户端 IP 的请求总是被转发到同一台后端服务器解决状态问题：当后端应用服务器没有共享会话状态时，避免用户会话丢失提升缓存效率：同一客户端的请求路由到同一服务器，可提高本地缓存命中率简化架构：避免部署复杂的分布式会话存储系统{/callout}upstream backend { ip_hash; server 192.168.1.10:8080 weight=95; # 旧版本 server 192.168.1.11:8080 weight=5; # 新版本 } server { listen 80; server_name api.example.com; location / { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }基于Cookie的灰度发布一个用户第一次访问的时候，我们给他打个标记，后续的请求都根据这个标记来决定走哪个版本。实现方式：用户第一次访问的时候，随机决定他是不是可以访问新版本，然后种个Cookie。后续请求都会带着这个Cookie，保证同一个用户始终访问同一个版本。但是这个方案还是有点粗糙，因为Nginx原生不支持生成随机数，我们需要借助一些技巧或者第三方模块。upstream backend_v1 { server 192.168.1.10:8080; } up…