# Redis 用户名查找和认证配置指南

**问题日期：** 2026年2月22日  
**环境：** juwan namespace  
**Redis 版本：** 7.0.12  
**部署模式：** RedisReplication (OpsTree Operator)

---

## 📋 目录

1. [问题背景](#问题背景)
2. [Redis 认证机制演进](#redis-认证机制演进)
3. [诊断过程](#诊断过程)
4. [用户名发现结果](#用户名发现结果)
5. [各语言连接配置](#各语言连接配置)
6. [常见问题解答](#常见问题解答)
7. [安全建议](#安全建议)

---

## 🎯 问题背景

### 问题描述
在配置应用连接 Redis 时，发现只有密码信息（存储在 Kubernetes Secret `user-redis` 中），但不清楚：
- Redis 是否需要用户名？
- 如果需要，用户名是什么？
- 如何查找 Redis 的用户名配置？

### 初始已知信息
```yaml
Secret: user-redis
Namespace: juwan
Key: password
Value: (base64 编码的密码)
```

### 疑问
- 使用 RedisInsight 等管理工具时，Username 字段应该填什么？
- 应用代码中是否需要配置 Username？
- 不同 Redis 版本的认证方式是否有差异？

---

## 📚 Redis 认证机制演进

### Redis 6.0 之前：传统密码认证

**特点：**
- ❌ 不支持多用户
- ✅ 只需配置一个全局密码
- 🔧 配置项：`requirepass`
- 👤 隐式用户名：`default`（客户端不需要指定）

**配置示例：**
```conf
# redis.conf
requirepass mypassword
```

**连接方式：**
```bash
# 只需要密码
redis-cli -h host -p 6379 -a mypassword

# 或使用 AUTH 命令
redis-cli -h host -p 6379
> AUTH mypassword
```

**优点：**
- ✅ 配置简单
- ✅ 向后兼容

**缺点：**
- ❌ 所有客户端共享同一密码
- ❌ 无法区分不同应用的访问权限
- ❌ 无法限制特定命令
- ❌ 审计困难

---

### Redis 6.0+：ACL（访问控制列表）

**引入时间：** Redis 6.0 (2020年5月)

**新特性：**
- ✅ 支持多用户
- ✅ 每个用户有独立的密码
- ✅ 细粒度权限控制（命令、key、channel）
- ✅ 默认用户 `default` 兼容旧版本
- ✅ 支持运行时动态修改

**架构对比：**
```
传统模式：
┌─────────────┐
│  所有客户端  │
└──────┬──────┘
       │ (一个密码)
       ↓
┌─────────────┐
│    Redis    │
│  (全权限)   │
└─────────────┘

ACL 模式：
┌────────┐  ┌────────┐  ┌────────┐
│ App A  │  │ App B  │  │ Admin  │
└───┬────┘  └───┬────┘  └───┬────┘
    │ user1     │ user2     │ admin
    │ (读写)    │ (只读)    │ (全部)
    ↓           ↓           ↓
┌───────────────────────────────┐
│           Redis ACL           │
│  user1: +@write +@read       │
│  user2: +@read ~cache:*      │
│  admin: +@all ~*             │
└───────────────────────────────┘
```

**ACL 规则语法：**
```
user <username> on <password> ~<keypattern> +<command>

示例：
user alice on >secret123 ~* +@all        # 全部权限
user bob on >pass456 ~cache:* +get +set  # 只能操作 cache:* 的 key
user readonly on >readonly ~* +@read -@write  # 只读权限
```

---

## 🔍 诊断过程

### 步骤 1：确认 Pod 容器名称

**目的：** 找到 Redis 容器的正确名称，以便执行命令

**命令：**
```bash
kubectl get pod user-redis-0 -n juwan -o jsonpath='{.spec.containers[*].name}'
```

**输出：**
```
user-redis redis-exporter
```

**分析：**
- ✅ Pod 中有 2 个容器
- 📦 `user-redis`：Redis 主容器
- 📊 `redis-exporter`：Prometheus 监控容器
- 🎯 **需要连接到 `user-redis` 容器**

**关键信息：**
```yaml
Pod: user-redis-0
Containers:
  - name: user-redis      # ← Redis 服务容器
    image: quay.io/opstree/redis:v7.0.12
    port: 6379
  - name: redis-exporter  # ← 监控容器
    image: quay.io/opstree/redis-exporter
    port: 9121
```

---

### 步骤 2：获取 Redis 密码

**目的：** 从 Kubernetes Secret 中提取密码，用于认证

**命令：**
```bash
kubectl get secret user-redis -n juwan -o jsonpath='{.data.password}' | base64 -d
```

**输出：**
```
<密码内容>  # 实际密码已隐藏
```

**说明：**
- Secret 中的数据以 base64 编码存储
- 需要解码才能得到明文密码
- `base64 -d` 在 Linux/Mac 上；Windows PowerShell 需要用其他方法

**Windows PowerShell 解码方法：**
```powershell
$encoded = kubectl get secret user-redis -n juwan -o jsonpath='{.data.password}'
[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($encoded))
```

---

### 步骤 3：检查 ACL 配置（关键步骤）

**目的：** 查询 Redis 的用户配置，确认是否启用 ACL 以及有哪些用户

**命令：**
```bash
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a $(kubectl get secret user-redis -n juwan -o jsonpath='{.data.password}' | base64 -d) \
  ACL LIST
```

**命令解析：**
```bash
kubectl exec -it user-redis-0 \     # 在 user-redis-0 Pod 中执行命令
  -n juwan \                         # 命名空间
  -c user-redis \                    # 指定容器
  -- \                               # 分隔符
  redis-cli \                         # Redis 命令行工具
  -a $(kubectl get secret ...) \     # 使用密码认证
  ACL LIST                           # 列出所有 ACL 用户
```

**输出：**
```
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
1) "user default on #e3e7d4b9413497efc274c747b2ee88023e00e6416080db92c7bdd49a73f32d3d ~* &* +@all"
```

**输出分析：**

#### 警告信息
```
Warning: Using a password with '-a' option on the command line interface may not be safe.
```
- ⚠️ 安全提醒：命令行中的密码可能被历史记录或进程列表泄露
- 💡 生产环境建议：使用配置文件或环境变量传递密码

#### ACL 规则详解
```
user default on #e3e7d4b...73f32d3d ~* &* +@all
|    |       |  |                    |  |  |
|    |       |  |                    |  |  └─ 权限：所有命令
|    |       |  |                    |  └──── 所有 Pub/Sub channel
|    |       |  |                    └─────── 所有 key pattern
|    |       |  └──────────────────────────── 密码哈希（SHA256）
|    |       └─────────────────────────────── 状态：已启用
|    └─────────────────────────────────────── 用户名
└──────────────────────────────────────────── 类型：用户
```

**权限标识含义：**

| 标识 | 含义 | 说明 |
|-----|------|------|
| `on` | 用户已启用 | 可以登录 |
| `off` | 用户已禁用 | 无法登录 |
| `~*` | Key Pattern | `*` = 所有 key；`~cache:*` = 只能访问 cache 开头的 key |
| `&*` | Pub/Sub Pattern | `*` = 所有 channel |
| `+@all` | 命令权限 | `@all` = 所有命令；`+get +set` = 只能用 GET/SET |
| `-@dangerous` | 禁止命令组 | 禁止危险命令（FLUSHDB, KEYS 等）|
| `#hash` | 密码哈希 | SHA256 哈希值，不存储明文 |

**命令组示例：**
- `@read`：只读命令（GET, HGET, LRANGE 等）
- `@write`：写入命令（SET, HSET, LPUSH 等）
- `@admin`：管理命令（CONFIG, SHUTDOWN 等）
- `@dangerous`：危险命令（FLUSHALL, KEYS 等）
- `@all`：所有命令

**结论：**
- ✅ Redis 启用了 ACL 模式
- 👤 **用户名是：`default`**
- 🔑 密码已配置（存储为 SHA256 哈希）
- 🔓 权限：完全访问（所有命令、所有 key、所有 channel）

---

### 步骤 4：验证用户名配置

**目的：** 确认 `default` 用户可以正常工作

**方法 1：使用密码（不指定用户名）**
```bash
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a <password> PING
```

**预期输出：**
```
Warning: Using a password with '-a' option on the command line interface may not be safe.
PONG
```

✅ **说明：只提供密码可以正常连接（默认使用 default 用户）**

---

**方法 2：显式指定用户名**
```bash
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli --user default --pass <password> PING
```

**预期输出：**
```
PONG
```

✅ **说明：显式指定 default 用户也可以正常连接**

---

**方法 3：测试错误的用户名**
```bash
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli --user wronguser --pass <password> PING
```

**预期输出：**
```
(error) WRONGPASS invalid username-password pair or user is disabled.
```

❌ **说明：不存在的用户名会认证失败**

---

### 步骤 5：查看完整的 ACL 信息

**目的：** 了解 `default` 用户的详细权限配置

**命令：**
```bash
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a <password> ACL GETUSER default
```

**输出：**
```
 1) "flags"
 2) 1) "on"
    2) "allkeys"
    3) "allchannels"
    4) "allcommands"
 3) "passwords"
 4) 1) "e3e7d4b9413497efc274c747b2ee88023e00e6416080db92c7bdd49a73f32d3d"
 5) "commands"
 6) "+@all"
 7) "keys"
 8) 1) "*"
 9) "channels"
10) 1) "*"
11) "selectors"
12) (empty array)
```

**详细分析：**

| 字段 | 值 | 含义 |
|-----|---|------|
| `flags` | `on, allkeys, allchannels, allcommands` | 用户已启用，可访问所有资源 |
| `passwords` | `e3e7d4b...` (SHA256) | 密码哈希 |
| `commands` | `+@all` | 允许所有命令组 |
| `keys` | `*` | 可访问所有 key |
| `channels` | `*` | 可访问所有 Pub/Sub channel |

**权限总结：**
- ✅ 用户状态：启用（on）
- ✅ 命令权限：所有命令（+@all）
- ✅ Key 权限：所有 key（~*）
- ✅ Channel 权限：所有 channel（&*）
- 🔒 密码：已设置且加密存储

---

## 🎯 用户名发现结果

### 最终结论

#### ✅ 当前 Redis 配置
```yaml
认证模式: ACL (Redis 6.0+)
用户名: default
密码: (存储在 Secret user-redis 中)
权限: 完全访问（超级用户）
状态: 已启用
```

#### 📝 连接参数汇总

| 参数 | 值 | 备注 |
|-----|---|------|
| **用户名** | `default` | 可省略，客户端默认使用 |
| **密码** | `kubectl get secret user-redis -n juwan -o jsonpath='{.data.password}' \| base64 -d` | 必需 |
| **Host (集群内)** | `user-redis-master.juwan.svc.cluster.local` | 写操作 |
| **Host (集群内)** | `user-redis-replica.juwan.svc.cluster.local` | 读操作 |
| **Host (Sentinel)** | `user-redis-sentinel-sentinel.juwan.svc.cluster.local` | 推荐 |
| **Port** | `6379` | Redis 数据端口 |
| **Sentinel Port** | `26379` | Sentinel 端口 |

---

### 为什么大多数情况不需要指定用户名？

#### Redis 客户端的默认行为

1. **向后兼容**
   ```
   Redis 6.0+ 保持了与旧版本的兼容性
   当客户端只提供密码时，自动使用 'default' 用户
   ```

2. **客户端实现**
   ```go
   // go-redis 内部逻辑（伪代码）
   if password != "" && username == "" {
       username = "default"  // 自动补全
   }
   ```

3. **AUTH 命令演进**
   ```bash
   # Redis 5.x 及之前
   AUTH password              # 只有密码
   
   # Redis 6.0+（向后兼容）
   AUTH password              # 等价于 AUTH default password
   AUTH username password     # 新格式
   ```

#### 何时需要显式指定用户名？

| 场景 | 是否需要 | 原因 |
|-----|---------|------|
| 使用 `default` 用户 | ❌ 不需要 | 客户端自动使用 |
| 创建了自定义用户 | ✅ 需要 | 必须明确指定 |
| 多应用共享 Redis | ✅ 推荐 | 权限隔离 |
| 审计需求 | ✅ 推荐 | 区分访问来源 |
| 管理工具连接 | ⚠️ 可选 | 有些工具要求填写 |

---

## 💻 各语言连接配置

### Go (go-redis)

#### 方式 1：只用密码（推荐）
```go
import "github.com/redis/go-redis/v9"

// 不指定 Username，自动使用 default
rdb := redis.NewClient(&redis.Options{
    Addr:     "user-redis-master.juwan.svc.cluster.local:6379",
    Password: os.Getenv("REDIS_PASSWORD"),  // 只需密码
    DB:       0,
})
```

#### 方式 2：显式指定用户名
```go
// 显式指定 Username（效果相同）
rdb := redis.NewClient(&redis.Options{
    Addr:     "user-redis-master.juwan.svc.cluster.local:6379",
    Username: "default",                    // 明确指定
    Password: os.Getenv("REDIS_PASSWORD"),
    DB:       0,
})
```

#### Sentinel 模式（生产推荐）
```go
// Sentinel 模式也支持用户名
rdb := redis.NewFailoverClient(&redis.FailoverOptions{
    MasterName:    "mymaster",
    SentinelAddrs: []string{
        "user-redis-sentinel-sentinel.juwan.svc.cluster.local:26379",
    },
    // Username 可省略（默认 default）
    Password: os.Getenv("REDIS_PASSWORD"),
    DB:       0,
})
```

---

### Go-Zero 框架

#### 配置文件
```yaml
# app/users/rpc/etc/pb.yaml
Redis:
  Type: sentinel
  MasterName: mymaster
  SentinelAddrs:
    - user-redis-sentinel-sentinel.juwan.svc.cluster.local:26379
  Pass: ${REDIS_PASSWORD}  # 只需密码，不需要用户名
```

#### 如果需要自定义用户
```yaml
Redis:
  Type: sentinel
  MasterName: mymaster
  SentinelAddrs:
    - user-redis-sentinel-sentinel.juwan.svc.cluster.local:26379
  Username: default  # 可选：显式指定
  Pass: ${REDIS_PASSWORD}
```

---

### Python (redis-py)

#### 只用密码
```python
import redis

# 不指定 username
r = redis.Redis(
    host='user-redis-master.juwan.svc.cluster.local',
    port=6379,
    password=os.getenv('REDIS_PASSWORD'),  # 只需密码
    db=0
)
```

#### 显式指定用户名（redis-py 4.3+）
```python
# 显式指定 username
r = redis.Redis(
    host='user-redis-master.juwan.svc.cluster.local',
    port=6379,
    username='default',  # 明确指定
    password=os.getenv('REDIS_PASSWORD'),
    db=0
)
```

#### Sentinel 模式
```python
from redis.sentinel import Sentinel

sentinel = Sentinel([
    ('user-redis-sentinel-sentinel.juwan.svc.cluster.local', 26379)
])

# 获取主节点（不指定 username）
master = sentinel.master_for(
    'mymaster',
    password=os.getenv('REDIS_PASSWORD')
)

# 或显式指定
master = sentinel.master_for(
    'mymaster',
    username='default',
    password=os.getenv('REDIS_PASSWORD')
)
```

---

### Java (Spring Data Redis)

#### application.yml（只用密码）
```yaml
spring:
  redis:
    password: ${REDIS_PASSWORD}  # 只需密码
    sentinel:
      master: mymaster
      nodes:
        - user-redis-sentinel-sentinel.juwan.svc.cluster.local:26379
```

#### 显式指定用户名（Spring Boot 2.6+）
```yaml
spring:
  redis:
    username: default           # 可选
    password: ${REDIS_PASSWORD}
    sentinel:
      master: mymaster
      nodes:
        - user-redis-sentinel-sentinel.juwan.svc.cluster.local:26379
```

#### Java 代码（Jedis）
```java
// 只用密码
JedisPoolConfig poolConfig = new JedisPoolConfig();
JedisPool pool = new JedisPool(
    poolConfig,
    "user-redis-master.juwan.svc.cluster.local",
    6379,
    2000,
    "password"  // 只需密码
);

// 显式指定用户名（Jedis 4.0+）
JedisPool pool = new JedisPool(
    poolConfig,
    "user-redis-master.juwan.svc.cluster.local",
    6379,
    2000,
    "default",   // 用户名
    "password"   // 密码
);
```

---

### Node.js (ioredis)

#### 只用密码
```javascript
const Redis = require('ioredis');

// 不指定 username
const redis = new Redis({
  host: 'user-redis-master.juwan.svc.cluster.local',
  port: 6379,
  password: process.env.REDIS_PASSWORD,  // 只需密码
});
```

#### 显式指定用户名（ioredis 4.0+）
```javascript
// 显式指定 username
const redis = new Redis({
  host: 'user-redis-master.juwan.svc.cluster.local',
  port: 6379,
  username: 'default',  // 明确指定
  password: process.env.REDIS_PASSWORD,
});
```

#### Sentinel 模式
```javascript
const redis = new Redis({
  sentinels: [
    { 
      host: 'user-redis-sentinel-sentinel.juwan.svc.cluster.local', 
      port: 26379 
    }
  ],
  name: 'mymaster',
  password: process.env.REDIS_PASSWORD,  // username 可省略
});
```

---

### redis-cli 命令行

#### 只用密码
```bash
# 方式 1：命令行参数
redis-cli -h user-redis-master.juwan.svc.cluster.local -p 6379 -a <password>

# 方式 2：交互式登录
redis-cli -h user-redis-master.juwan.svc.cluster.local -p 6379
> AUTH <password>
OK
```

#### 显式指定用户名
```bash
# 方式 1：命令行参数
redis-cli -h host -p 6379 --user default --pass <password>

# 方式 2：交互式登录
redis-cli -h host -p 6379
> AUTH default <password>
OK
```

---

## 🛠️ 管理工具配置

### RedisInsight

**配置示例：**
```
Name: juwan-user-redis
Host: localhost (使用 kubectl port-forward)
Port: 6379
Username: default  ← 填这个（或留空）
Password: <从 Secret 获取>
```

**说明：**
- ✅ Username 可以填 `default`
- ✅ Username 也可以留空（某些版本支持）
- 🔧 建议先 port-forward：`kubectl port-forward -n juwan svc/user-redis-master 6379:6379`

---

### Redis Commander

**Docker 运行：**
```bash
docker run -d \
  -e REDIS_HOSTS=juwan:user-redis-master.juwan.svc.cluster.local:6379:0:password \
  -p 8081:8081 \
  rediscommander/redis-commander
```

**URL 格式：**
```
# 不带用户名
redis://:<password>@host:6379

# 带用户名
redis://default:<password>@host:6379
```

---

### Another Redis Desktop Manager

**连接配置：**
```json
{
  "name": "juwan-redis",
  "host": "localhost",
  "port": 6379,
  "auth": "password",      // 只需密码
  "username": ""           // 留空（或填 "default"）
}
```

---

## ❓ 常见问题解答

### Q1: 为什么有些地方说 Redis 不需要用户名？

**A:** 这取决于 Redis 版本：

```
Redis 5.x 及之前:
└─ ❌ 不支持用户名，只有全局密码
   └─ 配置：requirepass password

Redis 6.0+:
└─ ✅ 支持 ACL 多用户
   └─ 但保持向后兼容
      └─ 如果只提供密码，自动使用 'default' 用户
```

### Q2: 我的 Redis 是哪个版本？

**查看方法：**
```bash
kubectl exec -it user-redis-0 -n juwan -c user-redis -- redis-cli -v
# 或
kubectl exec -it user-redis-0 -n juwan -c user-redis -- redis-server --version
```

**你的环境：**
```
Redis 7.0.12 (quay.io/opstree/redis:v7.0.12)
✅ 支持 ACL
✅ 用户名: default
```

### Q3: 如何创建自定义用户？

**场景：** 为不同应用创建独立的用户账号

#### 创建只读用户
```bash
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a <password> ACL SETUSER readonly on \
  '>readonly_password' \
  ~* \
  +@read -@write -@dangerous
```

**验证：**
```bash
# 使用新用户登录
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli --user readonly --pass readonly_password GET somekey

# 尝试写操作（应该失败）
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli --user readonly --pass readonly_password SET somekey value
# (error) NOPERM User has no permissions to run the 'set' command
```

#### 创建应用专用用户
```bash
# 只能访问 app:* 开头的 key
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a <password> ACL SETUSER app_user on \
  '>app_password' \
  ~app:* \
  +@all
```

#### 保存 ACL 配置
```bash
# 持久化到配置文件
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a <password> ACL SAVE
```

⚠️ **注意：** 在 Kubernetes 环境中，Pod 重启可能丢失 ACL 配置。建议：
1. 使用 ConfigMap 存储 ACL 配置
2. 在 StatefulSet 启动脚本中加载配置
3. 或使用 Redis Operator 的 ACL 管理功能

### Q4: 如何查看所有用户？

```bash
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a <password> ACL LIST
```

### Q5: 如何重置用户密码？

#### 重置 default 用户密码
```bash
# 1. 生成新密码
NEW_PASSWORD=$(openssl rand -base64 32)

# 2. 在 Redis 中更新
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a <old_password> ACL SETUSER default ">$NEW_PASSWORD"

# 3. 更新 Kubernetes Secret
kubectl create secret generic user-redis \
  --from-literal=password=$NEW_PASSWORD \
  --dry-run=client -o yaml | kubectl apply -f -

# 4. 重启应用 Pods（使新密码生效）
kubectl rollout restart deployment/user-rpc -n juwan
```

### Q6: 客户端报错 "WRONGPASS invalid username-password pair"

**可能原因：**

1. **密码错误**
   ```bash
   # 验证密码
   kubectl get secret user-redis -n juwan -o jsonpath='{.data.password}' | base64 -d
   ```

2. **用户名错误**
   ```bash
   # 检查用户是否存在
   kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
     redis-cli -a <admin_password> ACL LIST
   ```

3. **用户被禁用**
   ```bash
   # 启用用户
   kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
     redis-cli -a <admin_password> ACL SETUSER default on
   ```

4. **网络连接到了错误的 Redis 实例**
   ```bash
   # 确认连接的主机
   kubectl get svc -n juwan | grep redis
   ```

### Q7: 在 Kubernetes 中如何安全地传递密码？

**推荐方案：环境变量 + Secret**

```yaml
# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-rpc
spec:
  template:
    spec:
      containers:
      - name: user-rpc
        env:
          - name: REDIS_PASSWORD
            valueFrom:
              secretKeyRef:
                name: user-redis
                key: password
```

**应用代码：**
```go
// 从环境变量读取
password := os.Getenv("REDIS_PASSWORD")

rdb := redis.NewClient(&redis.Options{
    Addr:     "user-redis-master.juwan.svc.cluster.local:6379",
    Password: password,
})
```

**❌ 不推荐：**
```yaml
# 不要在配置文件中硬编码密码
Redis:
  Password: "hardcoded_password"  # ❌ 不安全
```

---

## 🔒 安全建议

### 1. 密码强度

**检查当前密码强度：**
```bash
PASSWORD=$(kubectl get secret user-redis -n juwan -o jsonpath='{.data.password}' | base64 -d)
echo "密码长度: ${#PASSWORD}"
```

**推荐：**
- ✅ 至少 32 字符
- ✅ 包含大小写字母、数字、特殊字符
- ✅ 使用密码生成器：`openssl rand -base64 32`

### 2. 权限最小化

**不要所有应用都用 default 超级用户！**

```bash
# 为不同应用创建独立用户
# 用户 A：只能读写自己的 key
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a <password> ACL SETUSER app_a on \
  '>password_a' ~app_a:* +@all

# 用户 B：只读
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a <password> ACL SETUSER app_b on \
  '>password_b' ~* +@read
```

### 3. 禁止危险命令

**即使是 default 用户，也应该限制危险命令：**

```bash
# 禁止 FLUSHALL, FLUSHDB, KEYS 等命令
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a <password> ACL SETUSER default -flushall -flushdb -keys

# 查看限制后的权限
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a <password> ACL GETUSER default
```

### 4. 审计日志

**启用 ACL 日志记录：**
```bash
# 查看最近的 ACL 事件
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a <password> ACL LOG 10

# 输出示例：
# 1) reason: auth
#    username: default
#    timestamp: 1234567890
```

### 5. 定期轮换密码

**建议：每 90 天轮换一次**

```bash
#!/bin/bash
# rotate-redis-password.sh

# 1. 生成新密码
NEW_PWD=$(openssl rand -base64 32)

# 2. 更新 Redis
kubectl exec -it user-redis-0 -n juwan -c user-redis -- \
  redis-cli -a "$OLD_PWD" ACL SETUSER default ">$NEW_PWD"

# 3. 更新 Secret
kubectl create secret generic user-redis \
  --from-literal=password="$NEW_PWD" \
  -n juwan --dry-run=client -o yaml | kubectl apply -f -

# 4. 滚动重启应用
kubectl rollout restart deployment/user-rpc -n juwan

echo "密码已轮换，新密码: $NEW_PWD"
```

### 6. 网络隔离

**NetworkPolicy 限制访问：**
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: redis-access-policy
  namespace: juwan
spec:
  podSelector:
    matchLabels:
      app: user-redis
  policyTypes:
    - Ingress
  ingress:
    # 只允许 user-rpc 访问
    - from:
      - podSelector:
          matchLabels:
            app: user-rpc
      ports:
      - protocol: TCP
        port: 6379
```

---

## 📝 总结

### 核心发现

| 项目 | 值 |
|-----|---|
| 认证模式 | ✅ ACL (Redis 6.0+) |
| 用户名 | `default` |
| 密码位置 | Secret `user-redis` in namespace `juwan` |
| 权限级别 | 超级用户（+@all ~* &*） |
| 是否必须指定用户名 | ❌ 不必须（客户端默认使用 default） |

### 最佳实践

1. **开发/测试环境**
   ```yaml
   # 简单配置即可
   Password: <from_secret>
   # Username 省略
   ```

2. **生产环境（推荐）**
   ```yaml
   # 为每个应用创建独立用户
   Username: app_user
   Password: <dedicated_password>
   # 限制权限和 key 范围
   ```

3. **连接方式**
   ```
   ⭐⭐⭐ Sentinel 模式（推荐）
   - 自动故障转移
   - 高可用
   - 只需密码（username 可省略）
   ```

---

**文档版本：** 1.0  
**创建日期：** 2026年2月22日  
**维护者：** DevOps Team  
**下次审查：** 2026年3月22日
