Skip to content

Commit

Permalink
Redis traffic management
Browse files Browse the repository at this point in the history
Signed-off-by: huabing zhao <zhaohuabing@gmail.com>
  • Loading branch information
zhaohuabing committed May 6, 2023
1 parent 93d2110 commit 0655496
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 124 deletions.
124 changes: 0 additions & 124 deletions content/zh/docs/v1.x/tutorials/redis.md

This file was deleted.

8 changes: 8 additions & 0 deletions content/zh/docs/v1.x/tutorials/redis/_index.md
@@ -0,0 +1,8 @@
---
title: Redis 流量管理
weight: 2000
---

Redis 是一种高性能的键值数据库,通常被用作缓存、会话存储和消息代理等用途。Redis 可以部署为单机模式或者 Cluster 模式,但不同模式的客户端访问方式不同,这增加了应用使用 Redis 的开发成本。通过采用 Aeraki Mesh 的 Redis 流量管理功能,我们可以在不修改客户端代码的前提下切换后端的 Redis 部署模式,实现客户端无感知的 Redis Cluster 数据分片,并提供读写分离、流量镜像等高级流量管理功能。

比如您在测试集群使用一个小型的单实例的 Redis ,而在生产环境使用一个复杂而稳定的多副本实例的集群模式的Redis,通过 Aeraki Mesh,您将无需修改您应用的代码/配置,从而尽可能的保证了开发,预发布,线上环境相同([Dev/prod parity](https://12factor.net/dev-prod-parity))。
43 changes: 43 additions & 0 deletions content/zh/docs/v1.x/tutorials/redis/cluster.md
@@ -0,0 +1,43 @@
---
title: 屏蔽 Redis 的部署模式差异
description:
weight: 03
---


例如,当我们通过 Redis 客户端访问 demo 中部署的 Redis cluster,会出现下面的访问错误:

```bash
kubectl exec -it `kubectl get pod -l app=redis-client -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-client -n redis -- redis-cli -h redis-cluster

redis-cluster:6379> set foo bar
(error) MOVED 15495 10.244.0.23:6379
```

这是因为 Redis 客户端采用了普通模式的 API,而 redis-cluster 服务则是一个 Redis Cluster,该 Cluster 由6台 Redis 服务器组成。通过配置 [RdisDestination](https://aeraki.net/zh/docs/v1.x/reference/redis/#RedisDestination),Aeraki Mesh 可以屏蔽掉这种差异。

```yaml
kubectl apply -f- <<EOF
apiVersion: redis.aeraki.io/v1alpha1
kind: RedisDestination
metadata:
name: redis-cluster
namespace: redis
spec:
host: redis-cluster.redis.svc.cluster.local
trafficPolicy:
connectionPool:
redis:
mode: CLUSTER
EOF
```

此时再通过客户端访问 redis-cluster 服务,就可以正常访问了。

```bash
kubectl exec -it `kubectl get pod -l app=redis-client -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-client -n redis -- redis-cli -h redis-cluster

redis-cluster:6379> set foo bar
OK
```

38 changes: 38 additions & 0 deletions content/zh/docs/v1.x/tutorials/redis/install.md
@@ -0,0 +1,38 @@
---
title: 安装示例程序
description:
weight: 01
---


从 github 下载 Aeraki。

```bash
git clone https://github.com/aeraki-mesh/aeraki.git
```

安装 Istio 和 Aeraki。

```bash
make demo
```

在 aerkai 代码目录下执行 redis demo 的安装脚本,该脚本会创建一个 redis namespace,并在其中部署 redis demo 应用。

```bash
./demo/redis/install.sh
```

demo 应用中包含一个 redis cluster(statefulset),一个单机模式的 redis,和一个 redis 客户端。后面我们将使用该 demo 来演示 Aeraki Mesh 对 Redis 的流量管理相关功能。
```bash
kubectl -n redis get pod
NAME READY STATUS RESTARTS AGE
redis-client-c4db4746c-dzcdr 2/2 Running 0 4m26s
redis-cluster-0 1/1 Running 0 4m26s
redis-cluster-1 1/1 Running 0 4m24s
redis-cluster-2 1/1 Running 0 4m22s
redis-cluster-3 1/1 Running 0 4m21s
redis-cluster-4 1/1 Running 0 4m20s
redis-cluster-5 1/1 Running 0 4m19s
redis-single-5bf9d77d69-qh7f4 1/1 Running 0 95s
```
92 changes: 92 additions & 0 deletions content/zh/docs/v1.x/tutorials/redis/password.md
@@ -0,0 +1,92 @@
---
title: 设置 Redis 访问密码
description:
weight: 02
---

## 为 Redis 服务设置访问密码

demo 中部署的 redis-single 服务设置了访问密码,此时如果通过客户端去访问该服务,redis 服务器会提示需要用户认证,拒绝访问请求。

```bash
kubectl exec -it `kubectl get pod -l app=redis-client -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-client -n redis -- redis-cli -h redis-single
redis-single:6379> set a a
(error) NOAUTH Authentication required.
```

在未使用 Aeraki Mesh 对 Redis 进行流量管理时,客户端代码需要从配置中得知其运行环境中访问的 Redis 服务是否需要进行认证,以及认证的用户名和密码。然后根据配置和 Redis 服务器进行认证,这增加了客户端代码及配置管理的复杂度。

通过采用 Aeraki Mesh 的 [RdisDestination](https://aeraki.net/zh/docs/v1.x/reference/redis/#RedisDestination) ,可以设置访问 Redis 的密码,由 Sidecar Proxy 来替客户端和 Redis 服务器进行认证。这样 Redis Client 就无需再关注 Redis 服务的密码信息。

```yaml
kubectl apply -f- <<EOF
apiVersion: v1
kind: Secret
metadata:
name: redis-service-secret
namespace: redis
type: Opaque
data:
password: dGVzdHJlZGlzCg==
---
apiVersion: redis.aeraki.io/v1alpha1
kind: RedisDestination
metadata:
name: redis-single
namespace: redis
spec:
host: redis-single.redis.svc.cluster.local
trafficPolicy:
connectionPool:
redis:
auth:
secret:
name: redis-service-secret
EOF
```

此时再通过客户端访问 redis-single 服务,就可以正常访问了。

```bash
kubectl exec -it `kubectl get pod -l app=redis-client -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-client -n redis -- redis-cli -h redis-single

redis-single:6379> set foo bar
OK
```


## 为客户端设置独立的访问密码

在某些情况下,您可能希望客户端使用的访问密码与 Redis 服务的真实密码不同。这样会带来一些好处,比如可以在不影响客户端的情况下更换 Redis 服务密码。这样也减少了 Redis 服务密码暴露的风险。通过配置 [RedisService](https://aeraki.net/zh/docs/v1.x/reference/redis/#RedisService) ,您可以单独设置客户端的访问密码。

```yaml
kubectl apply -f- <<EOF
apiVersion: redis.aeraki.io/v1alpha1
kind: RedisService
metadata:
name: redis-single
namespace: redis
spec:
host:
- redis-single.redis.svc.cluster.local
settings:
auth:
plain:
password: testredis123!
EOF
```

此时访问 redis-single 服务,需要使用 RedisService 中设置的新密码。

```bash
kubectl exec -it `kubectl get pod -l app=redis-client -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-client -n redis -- redis-cli -h redis-single

redis-single:6379> AUTH testredis
(error) ERR invalid password
redis-single:6379> AUTH testredis123!
OK
redis-single:6379> get foo
"bar"
```

> 备注:RedisDestination 和 RedisService 中的 auth 字段均支持两种密钥获取的途径:secret 与 plain。secret 代表所需要的用户名、密码信息存在于 secret 配置中。默认情况下,将使用所引用 secret 中定义的 username 的值作为 auth 使用的用户名,password 或 token 作为 auth 时使用的密码。通过配置 passwordField 和 usernameField 您可以指定做为auth时使用的密码和用户名的 secret 配置的字段。
58 changes: 58 additions & 0 deletions content/zh/docs/v1.x/tutorials/redis/routing.md
@@ -0,0 +1,58 @@
---
title: Redis 流量路由
description:
weight: 04
---

采用 [RedisService](https://aeraki.net/zh/docs/v1.x/reference/redis/#RedisService) ,我们可以根据请求 key 的前缀将流量路由到不同的 Redis 服务上。

例如下面的 RedisService 将以 `cluster` 开头的 key 路由到 redis-cluster 服务,其它 key 路由到 redis-single 服务。

```yaml
kubectl apply -f- <<EOF
apiVersion: redis.aeraki.io/v1alpha1
kind: RedisService
metadata:
name: redis-cluster
namespace: redis
spec:
host:
- redis-cluster.redis.svc.cluster.local
redis:
- match:
key:
prefix: cluster
route:
host: redis-cluster.redis.svc.cluster.local
- route:
host: redis-single.redis.svc.cluster.local
EOF
```

此时通过客户端访问 redis-cluster 服务,分别设置 `test-route``cluster-test-route` 两个 key 的值。然后这两个 key 的值也可以通过 get 命令获取到。

```bash
kubectl exec -it `kubectl get pod -l app=redis-client -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-client -n redis -- redis-cli -h redis-cluster

redis-cluster:6379> set test-route "this key goes to redis-single"
OK
redis-cluster:6379> set cluster-test-route "this key goes to redis-cluster"
OK
redis-cluster:6379> get test-route
"this key goes to redis-single"
redis-cluster:6379> get cluster-test-route
"this key goes to redis-cluster
```
再通过客户端访问 redis-single 服务,可以看到 redis-single 服务中只有 `test-route` 这个 key,而 `cluster-test-route` 这个 key 的值为 nil。这说明 `test-route` 被路由到 redis-single 服务,而 `cluster-test-route` 被路由到 redis-cluster 服务。
```bash
kubectl exec -it `kubectl get pod -l app=redis-client -n redis -o jsonpath="{.items[0].metadata.name}"` -c redis-client -n redis -- redis-cli -h redis-single
redis-single:6379> AUTH testredis123!
OK
redis-single:6379> get test-route
"this key goes to redis-single"
redis-single:6379> get cluster-test-route
(nil)
```

0 comments on commit 0655496

Please sign in to comment.