vault使用agent验证approle生成.env环境变量

Vault是个很厉害的 secret 引擎了,不多说了,主要用于集中管理各种密码、密钥。 用来管理Kubernetes的凭据相当好,但是我们通常是自己开发的程序,然后需要读各种配置文件,比如连接DB的用户名,密码等等,最后连接到数据库。 那么这种情况下,如果管理好配置项呢? 方法如下,用approle读取Vault的配置信息: 一、启动vault引擎测试环境 首先启动vault引擎,测试,用Docker,方便创建和销毁 # 启动容器 # 我们手动指定了ROOT_TOKEN是root,这只用于测试环境 docker run -d --rm \ --add-host host.docker.internal:host-gateway \ --cap-add=IPC_LOCK \ --name vault \ -p 8200:8200 \ -e VAULT_DEV_ROOT_TOKEN_ID=root \ -e VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200 \ hashicorp/vault --add-host host.docker.internal:host-gateway 这个个参数的作用是在容器的 /etc/hosts 文件中添加一个主机名和 IP 地址的映射。 --add-host: 这是 docker run 的一个选项,用来在容器的 /etc/hosts 文件中添加一个自定义的主机条目。 host.docker.internal: 这是主机名。在 Docker Desktop(macOS 和 Windows)中,host.docker.internal 是一个特殊的 DNS 名称,它会被解析为宿主机的内部 IP 地址。 host-gateway: 这是 docker 在较新版本中引入的一个特殊关键字。它代表了宿主机与 Docker 网络之间的网关 IP 地址。在许多 Linux 环境中,这个关键字会指向 Docker 的网桥 IP(例如 172.17.0.1)。 综合起来,--add-host host.docker.internal:host-gateway 的作用是: ...

2025年8月6日

上难度---->内网vps用lego申请route53 DNS证书并更新到BT宝塔

上一篇我们说了 Aws的EC2服务器用lego获得免费证书并更新到ACM,这下又来了个更加有难度的挑战: DNS解析是放在了AWS Route 53上,然后vps上跑着BT宝塔,用来代理转发开发环境的https证书 这个环境如何用lego来安全的申请到证书并配置宝塔呢?这回可不像EC2那样可以自动附加IAM角色了 我们先来看看lego的用法吧: https://go-acme.github.io/lego/dns/route53/ 语法如下: 继续看,看来必须需要IAM的凭据才可以,继续下拉,有使用IAM的policy,那我们必须创建一个Role角色,然后再建立一个代理用户,gen出key,通过这个代理用户的凭据来间接进行访问 步骤如下: 一、去route53,拿到arn 我们要拿到具体域名的zone ID,就是Z0打头的那一串 二、建立IAM实际工作的Role 首先建立一个Policy,route53AcmeCert { "Version": "2012-10-17 "Statement": [ "Effect": "Allow", "Action": "route53:GetChange", "Resource": "arn:aws:route53:::change/*" }, { "Effect": "Allow", "Action": "route53:ListHostedZonesByName", }, { "Effect": "Allow", "Action": [ "route53:ListResourceRecordSets" ], "Resource": [ "arn:aws:route53:::hostedzone/Z01111111111111111111" ] }, { "Effect": "Allow", "Action": [ "route53:ChangeResourceRecordSets" ], "Resource": [ "arn:aws:route53:::hostedzone/Z01111111111111111111" ], "Condition": { "ForAllValues:StringEquals": { "route53:ChangeResourceRecordSetsNormalizedRecordNames": [ "_acme-challenge.example.com" ], "route53:ChangeResourceRecordSetsRecordTypes": [ "TXT" ] } } } ] } 然后建立一个Role,RealUpdateCertRole,绑定上面的策略 ...

2025年7月29日

Postgres的wal和PITR时间点恢复

研究了Postgres的库数据恢复和转移,再来研究一下PITR按时间点恢复 类比到MySQL,因为我们是运维,不是专业的DBA,所以恢复到正确数据即可 那跟阿里云以及自建的MySQL恢复一样,首先都要有一个每天的基础备份,然后类比MySQL的Binlog,Postgres这里就相当于wal。 这么类比就对了,那么恢复过程的思路是一样的: 首先建立一个新的实例 第二步把每天的基础物理全备给恢复上去 第三步把之后的wal日志传到新实例,恢复到指定时间点 第四步最后把表或库Dump下来,灌入到旧实例的新表或新库 那我们一步一步来解释: 一、每天建立一个基础备份,这样在Base基础上,只需恢复当天的wal,速度够快 建立每天的Base基础物理备份 pg_basebackup -Ft -Pv -Xf -z -Z5 -U postgres -h localhost -p 5432 -D /pg_backup 解释一下: -Ft: 指定备份格式为 tar。 如果使用 tar 格式,备份会输出 tar 文件,并且不需要直接访问 PostgreSQL 数据目录。 -Pv: -P:显示备份进度。 -v:启用详情模式(verbose),显示更多日志。 -Xf: -X:控制 WAL 日志的处理方式,f 表示在备份中包含 WAL 文件(Write Ahead Logs),确保备份可以用于恢复到完整的一致状态。 -z: 启用压缩功能。 -Z5: 设置压缩级别为 5(压缩级别从 0 到 9,9 为最高压缩)。 -U postgres: 使用 postgres 用户来连接数据库。 -h localhost: 指定数据库主机为当前机器(localhost)。 -p 5432: 指定 PostgreSQL 监听端口为 5432(默认端口)。 -D /pg_backup: 将备份文件保存到指定路径 /pg_backup 中。 这样我们就在 /pg_backup 中有了备份文件,包括一个backup_manifest的文件清单,以及一个压缩包 ...

2025年7月28日

单机部署kafka用kraft不依赖zookeeper

上一篇说了用Docker部署kafka,后端不用zookeeper,改用kraft。 这一篇说说不用Docker,直接单机部署kafka用kraft的方法。 一、准备,虚机的话需要4cpu 8G内存 # 装好java java --version 建3个目录 # 放kafka的2进制可执行文件 mkdir -p /opt/kafka # 放kafka的日志文件 mkdir -p /var/log/kafka # 放kafka的数据文件 mkdir -p /var/lib/kafka 二、下载并配置kafka # 释放到指定目录 tar -xzf kafka_2.13-3.5.0.tgz -C /opt/kafka # 修改/opt/kafka/config/server.properties process.roles=broker,controller node.id=1 controller.quorum.voters=1@localhost:9093 listeners=PLAINTEXT://localhost:9092,CONTROLLER://localhost:9093 log.dirs=/var/lib/kafka # 然后需要再追加到server.properties的部分 metadata.log.dir=/var/lib/kafka/metadata num.replica.fetchers=1 offsets.topic.replication.factor=1 transaction.state.log.replication.factor=1 transaction.state.log.min.isr=1 三、初始化kafka集群 # 生成一个uuid uuidgen dc66bcb0-758e-4360-843d-5ccb1da2ee74 # 初始化 cd /opt/kafka bin/kafka-storage.sh format -t <UUID> -c config/server.properties # 启动 bin/kafka-server-start.sh config/server.properties # 检查一下代理的状态 bin/kafka-broker-api-versions.sh --bootstrap-server localhost:9092 四、推送数据验证 ...

2025年7月28日

用Docker部署kafka且不依赖zookeeper

用redpanda居然还要每隔30天更新一下License文件,叔可忍婶不可忍啊。 换掉换掉,直接用Docker部署kafka,后端不用zookeeper,用kraft,天下苦zk也久矣! 方法很简单,用docker-compose,编辑docker-compose.yml文件 name: 'stream' services: kafka: image: confluentinc/cp-kafka:latest hostname: kafka container_name: kafka ports: - 9092:9092 - 9093:9093 environment: KAFKA_KRAFT_MODE: true # This enables KRaft mode in Kafka. KAFKA_PROCESS_ROLES: controller,broker # Kafka acts as both broker and controller. KAFKA_NODE_ID: 1 # A unique ID for this Kafka instance. KAFKA_CONTROLLER_QUORUM_VOTERS: 1@10.8.1.119:9093 # Defines the controller voters. KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://10.8.1.119:9092 KAFKA_LOG_DIRS: /var/lib/kafka/data # Where Kafka stores its logs. KAFKA_AUTO_CREATE_TOPICS_ENABLE: true # Kafka will automatically create topics if needed. KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 # Since we’re running one broker, one replica is enough. KAFKA_LOG_RETENTION_HOURS: 168 # Keep logs for 7 days. KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0 # No delay for consumer rebalancing. CLUSTER_ID: Mk3OEYBSD34fcwNTJENDM2Qk # A unique ID for the Kafka cluster. volumes: - /var/run/docker.sock:/var/run/docker.sock - ./data:/var/lib/kafka/data # Store Kafka logs on your local machine. 注意以上的文件,暴露了2个端口,9092和9093,9092用于客户端连接,9093用于集群通讯;KAFKA_KRAFT_MODE: true用kraft不用zk. ClUSTER_ID可以换个不同的。 ...

2025年7月28日

aws的EC2服务器用lego获得免费证书并更新到ACM

交代一下背景: 公司在AWS上用的是EKS+Fargate,还有一个跳板机,证书呢就不太想用aws收费的了,干脆用免费的证书好了。 那问题就来了,Let‘s encrypt的证书90天到期,已经手动更新过3次了,实在太麻烦了,能不能自动申请并更新到ACM呢? 答案是可以的,原理是:利用EC2可以携带IAM角色的原理,就可以无凭证更新免费证书到AWS Certificate Manager了 做法如下: 一、首先去ACM中拿到证书的ARN,要确保IAM权限不外泄,避免更新错证书 二、生成一个IAM的policy,命名为AllowUpdateCertificate,只允许更新这两个特定的证书 具体策略内容如下: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "acm:ImportCertificate" ], "Resource": [ "arn:aws:acm:ap-southeast-1:111111111111:certificate/arn01", "arn:aws:acm:ap-southeast-1:111111111111:certificate/arn02" ] } ] } 三、IAM生成一个role角色,命名为Ec2UpdateCertificateRole,把AllowUpdateCertificate策略给附上 四、到EC2的实例详细信息中,操作–>安全–>修改IAM角色 附上Ec2UpdateCertificateRole这个角色 五、在EC2的机器上,装好AWS CLI,还有lego(申请Let’s encrypt证书的软件) 先写好获得证书的脚本 get_cert.sh,域名DNS解析是托管到cloudflare的,所以也直接用API TOKEN来处理 #!/bin/bash CLOUDFLARE_DNS_API_TOKEN=######## /usr/local/bin/lego --path /usr/local/bin/certs --email zhangranrui@rendoumi.com --dns cloudflare --domains *.rendoumi.com --domains rendoumi.com renew --renew-hook="/usr/local/bin/update_aws_cert.sh" 参数--renew-hook如果有新证书,就调用后面的脚本。如果没有新证书,就无操作,避免无用功。 然后再写好 update_aws_cert.sh,这就是个千字文了,由gemini生成的: 由于lego生成的crt是证书+证书链,所以第一步要把证书部分给单独拆出来 #!/bin/bash cd /usr/local/bin/certs/certificates #首先把证书单独拆出来 awk '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/ {print} /-----END CERTIFICATE-----/ {exit}' _.rendoumi.com.crt > _.rendoumi.com.only # --- 配置部分 --- # 您要更新的现有 ACM 证书的 ARN # 示例:CERTIFICATE_ARN="arn:aws:acm:ap-southeast-1:123456789012:certificate/abcdefab-1234-5678-abcd-1234567890ab" CERTIFICATE_ARN="arn:aws:acm:ap-southeast-1:111111111111:certificate/11111111-1111-1111-1111-111111111111" # 新证书文件的路径(例如:/opt/certs/new_certificate.crt) # 确保这个路径在您的EC2实例上是正确的 CERTIFICATE_BODY_PATH="_.rendoumi.com.only" # 新私钥文件的路径(例如:/opt/certs/private.key) # 确保这个路径在您的EC2实例上是正确的 PRIVATE_KEY_PATH="_.rendoumi.com.key" # 证书链文件的路径(可选) # 如果没有证书链,请将此变量留空或注释掉 # 示例:CERTIFICATE_CHAIN_PATH="/opt/certs/ca_bundle.crt" CERTIFICATE_CHAIN_PATH="_.rendoumi.com.issuer.crt" # 如果没有链,请将其留空 "" # ACM 证书所在的 AWS 区域 # 这个区域应该与 CERTIFICATE_ARN 中的区域匹配 # 示例:AWS_REGION="ap-southeast-1" AWS_REGION="ap-southeast-1" # --- 配置部分结束 --- echo "--- 开始使用实例角色重新导入 ACM 证书 ---" echo "证书 ARN: ${CERTIFICATE_ARN}" echo "区域: ${AWS_REGION}" # 检查文件是否存在 if [ ! -f "${CERTIFICATE_BODY_PATH}" ]; then echo "错误:证书文件 '${CERTIFICATE_BODY_PATH}' 不存在。" exit 1 fi if [ ! -f "${PRIVATE_KEY_PATH}" ]; then echo "错误:私钥文件 '${PRIVATE_KEY_PATH}' 不存在。" exit 1 fi if [ -n "${CERTIFICATE_CHAIN_PATH}" ] && [ ! -f "${CERTIFICATE_CHAIN_PATH}" ]; then echo "警告:证书链文件 '${CERTIFICATE_CHAIN_PATH}' 已指定但不存在。将不包含证书链进行导入。" CERTIFICATE_CHAIN_PATH="" # 如果文件不存在,则清空路径 fi # 构造 AWS CLI 命令。AWS CLI 会自动使用实例角色提供的凭证。 IMPORT_CMD="aws acm import-certificate \ --certificate-arn ${CERTIFICATE_ARN} \ --certificate fileb://${CERTIFICATE_BODY_PATH} \ --private-key fileb://${PRIVATE_KEY_PATH} \ --region \"${AWS_REGION}\"" # 如果有证书链,则添加到命令中 if [ -n "${CERTIFICATE_CHAIN_PATH}" ]; then IMPORT_CMD="${IMPORT_CMD} --certificate-chain fileb://${CERTIFICATE_CHAIN_PATH}" fi echo "正在执行命令:" echo "$IMPORT_CMD" echo "--------------------------" # 执行命令 # 注意:这里我们不指定 --profile 或任何凭证,AWS CLI 会自动使用实例IAM角色。 eval $IMPORT_CMD # 检查命令执行结果 if [ $? -eq 0 ]; then echo "--- 证书重新导入成功!---" echo "ACM 证书 ${CERTIFICATE_ARN} 已更新。" else echo "--- 证书重新导入失败!---" echo "请检查错误消息,确保:" echo "1. EC2 实例已正确附加了具有 acm:ImportCertificate 权限的 IAM 角色。" echo "2. 证书、私钥和链文件路径正确且可读。" echo "3. 证书/私钥/链的格式正确。" fi echo "--- 脚本执行完毕 ---" 看起来真的是又臭又长,废话连篇。注意:gemini 生成的代码有问题,aws acm import-certificate 的参数中,证书文件的前缀是fileb://,gemini给的是file://,调试了半天,最后去aws看了文档才发现。 ...

2025年7月25日

Redpanda到期后如何续License

上回我们在 Kafka的测试替代品-Redpanda 中说了怎么搭建,结果用了一个月,问题就来了 license过期了,擦的,只允许用30天,需要续费了。 方法如下: 一、打开网站,申请30天的免费license https://cloud.redpanda.com/try-enterprise 打开网站,然后填入姓名和邮箱,就会得到一个长字符串xyz,拷贝下来 二、去机器上 我们是用docker compose启动的,所以需要进入容器,导入license docker exec -it redpanda-0 /bin/sh rpk cluster license set xyz 三、重启容器 按道理上一步弄完,就应该好了的,可惜这产品做的稀烂。还必须重启容器才起作用 docker compose restart 就ok了,但是30天就更新一次license,而且必须要重启容器,这谁受得了啊。 下周就抽空装一个不依赖Zookeeper,用Rraft的Kafka来用,彻底去掉这个不伦不类的软件。

2025年7月25日

Postgres不同实例、不同用户直接的数据导出导入

公司生产环境在AWS使用了 Aurora Postgres Serveless 的数据库。 测试环境是在内网搭建了一个postgres 13数据库。 那测试和生产的实例不同,数据库不同,用户名也不同,需要把测试环境的A库的schema.public迁移到生产B库的schema.public。 普及一下概念,PG的权限分三层,数据库、schema、schema中的对象。 那么用pg_dump的话,如果不带任何参数,那会把权限也给带上,那就麻烦大了去了! 所以正确的导出、导入步骤如下: 一、首先要观察源库,看看都有什么extention,在schema.public有什么Functions 如上图所示,看到uuid_generate # 看看服务器版本 select version(); PostgreSQL 13.14 那就很奇怪,extension 只有一个plpgsql,functions却有一堆uuid_generate 那十有八九需要用到extension uuid-oosp 先去目的库建一个吧 create extension "uuid-ossp"; 二、dump数据 这里要注意,不要把任何权限的东西带进来 pg_dump -h 172.16.8.1 -U postgres -d source --schema=public --no-owner --no-privileges --file=export.sql # 全备份的命令 # export PGPASSWORD="xxxxxxxx" # pg_dump -U bbc -h localhost -p 5432 bbc > dc_system.sql 然后要编辑看看这个导入的文件 发现有create schema的语句,如果目的数据库已经有了,那需要去掉。 再看下面: 建立了一个FUNCTION,如果已经建立了extension,那也会报错,不过这2种错误我们都可以直接不用管,直接执行试试 三、导入目标库 跑一跑,看一看: psql -h 10.8.0.1 -U dest -d dest -f export.sql 报了不少错 ...

2025年7月23日

内网kubernetes+cloudflare+cert-manager自动签发证书

这个场景非常的有意思: 公司内部有若干个kubernetes集群,属于测试环境,研发搭建了一套SAAS的环境,这个环境需要xxx.abc.com的域名来访问,域名解析记录全都是192.168.0.x,供内部访问,域名会动态生成,需要证书也随之生成,且dns域名托管在cloudflare上。 基本环境如上,麻烦的是 cert-manager 不可能签发私网的证书,只能曲线救国,用dns验证的方式来签发证书了,如果配上 external-dns,那dns解析也不用做了;只要发布一个ingress,就直接生成dns解析记录和对应的https证书。 具体做法如下: 一、配置 cloudflare API token 登录cloudflare,去生成API Token,路径是:User Profile > API Tokens > API Tokens. Permissions: Zone - DNS - Edit Zone Resources: Include - All Zones cert-manager的官方文档居然是错的,https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/ 推荐的 Zone - Zone - Read 是加不上的,有Edit就足够了 然后获得Token的字符串xxxxxx 二、安装cert-manager 这个简单,直接用helm安装 现在这个时间节点,2025.07.09,cert-manager 是 v1.18.2,所以用新命令执行安装 helm repo add jetstack https://charts.jetstack.io helm repo update #老版本比如1.0 helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set installCRDs=true #新版本v1.18.2 helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set crds.enabled=true 三、准备签发机构Issuer ...

2025年7月9日

CORS跨域在不同环境中的配置

Cross-Origin Resource Sharing (CORS) 跨域,一个网站引用了另外一个网站的资源,就需要跨域了。 最通俗点,就是服务器的返回头上要加上三行: Access-Control-Allow-Origin", "*" Access-Control-Allow-Methods", "GET, POST, OPTIONS" Access-Control-Allow-Headers", "DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization" 说白点:就是允许的来源站,允许的方法,允许的头信息 那在不同的地方配置又不相同: 一、Nginx server { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; 二、openresty中的lua脚本 location /pg/nginit { rewrite_by_lua_block { ngx.log(ngx.ERR, "Environment configuration update, about to get configuration information from redis") -- 添加跨域 CORS 头 ngx.header["Access-Control-Allow-Origin"] = "*" -- 允许所有域名请求 ngx.header["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS" -- 允许的方法 ngx.header["Access-Control-Allow-Headers"] = "DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization" -- 允许的请求头 三、AWS的S3 <CORSConfiguration> <CORSRule> <AllowedOrigin>http://example.com</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedHeader>*</AllowedHeader> </CORSRule> </CORSConfiguration> 四、AWS Lambda 或者 API Gateway headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': true, } 最后,AWS的ALB不支持配置CORS!!!,必须在后端的 application 中设置。 ...

2025年6月17日