明锐有光 - 运维
type: channel
link: https://www.xiaohetao.xyz/category/default/
description: 运维相关
items: K8s五大核心组件详解
items: Linux性能分析神器sar介绍
items: Kafka集群优化指南
items: 批量服务器管理指南
items: kafka详细介绍
items: API网关之apisix介绍
items: sudo提权的门道
items: 基于OpenResty的版本灰度发布方案
items: 使用nginx进行灰度发布的几种方式介绍
items: ssh常见故障排查及解决措施

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会把空闲内存用作缓存，真正需要关注的是当应用程序需要内存时，系统能否快速回收这些缓存。因此一般…

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…

ssh常见故障排查及解决措施
type: item
date: 2025-12-08T14:01:00+08:00
description: 关键排查方法客户端调试: 使用 ssh -v 参数查看详细连接过程服务器日志: 检查 /var/log/secure 或 journalctl -u sshd 获取服务器端错误权限验证: 系统性检查文件和目录权限密钥验证: 使用 ssh-keygen -y 验证密钥对匹配性预防措施定期备份密钥: 避免密钥丢失导致无法访问使用现代密钥算法: 推荐使用 ED25519 而非 RSA保持权限正确: 使用自动化脚本定期检查关键文件权限启用多种认证方式: 配置密码认证作为备用方案监控 SSH 日志: 及时发现异常登录尝试常见 SSH 认证失败原因问题类型错误信息解决方法私钥权限过开放UNPROTECTED PRIVATE KEY FILEchmod 400 私钥文件主目录权限错误bad ownership or modeschmod 755 ~ + chown user:user ~.ssh 目录权限错误Authentication refusedchmod 700 ~/.sshauthorized_keys 权限错误认证失败无明确提示chmod 600 ~/.ssh/authorized_keys密钥算法不支持key type not in PubkeyAcceptedAlgorithms修改 sshd_config 启用算法密钥不匹配认证失败验证并更换正确的密钥对私钥文件权限问题错误信息: WARNING: UNPROTECTED PRIVATE KEY FILE! Permissions 0644 for 'xxxxx.pem' are too open. 问题分析:私钥文件权限为 0644（所有用户可读）SSH 安全机制要求私钥文件仅所有者可访问解决措施: chmod 400 /home/test/xxxx.pem密钥匹配性验证排查步骤:确认正确的私钥文件路径验证私钥与服务器公钥是否匹配验证命令:# 本地生成公钥指纹 ssh-keygen -y -f /home/test/xxxx.pem ​ # 服务器端查看授权公钥 cat /home/ec2-user/.ssh/authorized_keys服务器端配置问题定位查看服务器 SSH 日志 (/var/log/secure)，可以发现的两个关键错误：目录权限错误: Authentication refused: bad ownership or modes for directory /home/ec2-user 密钥算法不支持: userauth_pubkey: key type ssh-rsa not in PubkeyAcceptedAlgorithms [preauth]原因1：用户主目录权限配置错误 问题详情:/home/ec2-user 目录的所有权或权限不符合 SSH 安全要求。SSH 要求用户主目录及 .ssh 目录必须有严格的权限控制。SSH 权限要求:用户主目录: 755 权限，所有者为用户本人.ssh 目录: 700 权限，所有者为用户本人authorized_keys 文件: 600 权限，所有者为用户本人原因2：SSH 服务器禁用了 RSA 算法 问题详情:服务器 SSH 配置中未包含 ssh-rsa 算法客户端使用的是 RSA 类型的密钥版本 OpenSSH (8.8+) 默认禁用了 SHA-1 相关的 RSA 算法解决方案#在服务器端以 root 用户执行： # 1. 修复 ec2-user 主目录权限 chown ec2-user:ec2-user /home/ec2-user chmod 755 /home/ec2-user ​ # 2. 修复 .ssh 目录权限 chmod 700 /home/ec2-user/.ssh chmod 600 /home/ec2-user/.ssh/authorized_keys chown -R ec2-user:ec2-user /home/ec2-user/.ssh ​ # 3. 启用 ssh-rsa 算法支持 echo "PubkeyAcceptedAlgorithms +ssh-rsa" >> /etc/ssh/sshd_config ​ # 4. 重启 SSH 服务 systemctl restart sshd