1. Tổng quan.
Redis là một hệ thống cơ sở dữ liệu chất lượng cao được sử dụng để lưu trữ và truy xuất dữ liệu. Redis (viết tắt của REmote DIctionary Server) là một hệ thống lưu trữ dữ liệu trên RAM (in-memory data store), còn được gọi là cơ sở dữ liệu trên bộ nhớ. Nó được phát triển dựa trên kiến trúc key-value, trong đó dữ liệu được lưu trữ dưới dạng cặp key-value, giúp tạo ra một bộ nhớ cache nhanh và hỗ trợ nhiều kiểu dữ liệu khác nhau. Redis thường được sử dụng cho các tác vụ như lưu trữ phi cấu trúc, lấy và cập nhật dữ liệu tại tốc độ cao, xử lý hàng triệu yêu cầu mỗi giây, và nhiều ứng dụng khác.
Redis Stack là một sự mở rộng của Redis, mà nói cách khác là một phiên bản mở rộng của Redis, với khả năng thêm các mô hình dữ liệu và công cụ xử lý hiện đại để cung cấp một trải nghiệm phát triển hoàn chỉnh hơn
Bài viết này cung cấp một cách tiếp cận để triển khai Redis Stack Server trong Kubernetes bằng cách sử dụng Bitnami Helm chart, giúp bạn tận dụng các tính năng mở rộng của Redis Stack cho các ứng dụng của mình.
- Lý do sử dụng Redis Stack:Redis Stack là một sự mở rộng của Redis, mà nói cách khác là một phiên bản mở rộng của Redis, với khả năng thêm các mô hình dữ liệu và công cụ xử lý hiện đại để cung cấp một trải nghiệm phát triển hoàn chỉnh hơn. Ngoài tất cả các tính năng của OSS Redis (Redis phiên bản mã nguồn mở), Redis Stack hỗ trợ các tính năng bổ sung sau:
- RedisJSON: Cho phép bạn lưu trữ và truy vấn các tài liệu JSON.
- RediSearch: Cung cấp tìm kiếm toàn văn bản (full-text search).
- RedisTimeSeries: Hỗ trợ dữ liệu chuỗi thời gian, bao gồm việc ghi và truy vấn dữ liệu chuỗi thời gian.
- RedisGraph: Cho phép bạn lưu trữ và truy vấn dữ liệu đồ thị bằng cách sử dụng ngôn ngữ truy vấn Cypher.
- RedisBloom: Hỗ trợ các cấu trúc dữ liệu xác suất.
- Triển khai Redis Stack trong Kubernetes:Bài viết này tập trung vào việc triển khai Redis Stack Server trong môi trường Kubernetes bằng cách sử dụng Bitnami Helm chart. Bitnami Helm chart là một cách tiện lợi để triển khai ứng dụng trong Kubernetes, và trong trường hợp này, nó đã được cấu hình để triển khai Redis Stack thay vì Redis thông thường.
- Cấu hình Linh hoạt bằng Helm Chart:Một điểm quan trọng mà bài viết nhấn mạnh là tính linh hoạt của Bitnami Helm chart cho phép bạn cấu hình triển khai Redis Stack Server một cách dễ dàng bằng một lệnh Helm duy nhất. Bitnami Helm chart cho phép bạn đặt cấu hình các tính năng mở rộng của Redis Stack (ví dụ: RedisJSON, RediSearch, RedisTimeSeries, RedisGraph, RedisBloom) thông qua các tùy chọn cấu hình.
- Nhược điểm và Cảnh báo:Bài viết cũng nhắc đến rằng tác giả đã tập trung vào việc đảm bảo việc triển khai thành công và đã thực hiện một số kiểm tra đơn giản để xác minh rằng các tính năng mở rộng của Redis Stack hoạt động. Tuy nhiên, tác giả cũng lưu ý rằng điều này không phải là một môi trường sản xuất và cần phải có nhiều kiểm tra và thử nghiệm hơn nếu bạn định sử dụng nó trong môi trường sản xuất.
Dưới đây là sơ đồ mô tả ngắn gọn về Redis Stack mô hình mô hình Setinel.
2. Cách triển khai.
Đầu tiên hãy tạo một namespace cho dự án này.
kubectl create ns redis-stack
Dùng lệnh helm search repo <tên repo>
để tìm các version của Redis.
$ helm search repo redis
NAME CHART VERSION APP VERSION DESCRIPTION
bitnami/redis 17.15.6 7.2.0 Redis(R) is an open source, advanced key-value ...
bitnami/redis-cluster 8.7.2 7.2.0 Redis(R) is an open source, scalable, distribut...
Hãy tải repo này về bằng lệnh helm fetch <tên repo> --version=<số version>
.
helm fetch bitnami/redis --version=17.15.6
Sau khi tải thành công, bạn sẽ nhận được 1 file nén như dưới.
$ ls -al *.tgz
-rw-r--r-- 1 root root 93195 Aug 21 09:19 redis-17.15.6.tgz
Giải nén nó và di chuyển vào thư mục vừa giải nén.
tar -zxvf redis-17.15.6.tgz
cd redis/
Hãy dùng lệnh kubectl get storageclass
để tìm các storageclass có sẵn trong hệ thống của bạn. Ví dụ của mình đã có sẵn 1 storage longhorn.
$ kubectl get storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
longhorn (default) driver.longhorn.io Delete Immediate true 96d
Hãy mở file values.yaml và chỉnh sửa một số tham số sau:
global:
storageClass: "longhorn"
redis:
password: "Hoanghd164"
password: "Hoanghd164" <- tất cả các tham số password
master:
count: 1
replica:
replicaCount: 3
storageClass: "<tên storageclass của bạn>"
sentinel:
enabled: true
Dưới đây là file đầy đủ của mình https://wiki.hoanghd.com/wp-content/uploads/codes/redis-stack-values-17.15.6.yaml
.
Sau khi thay đổi các tham số của values.yaml xong, hãy chạy lệnh helm upgrade -i
sau:
helm upgrade -i \
redis-stack-server /home/redis \
--atomic \
--repo https://charts.bitnami.com/bitnami \
--version 17.15.6 \
--namespace redis-stack \
--values - <<EOF
global:
redis:
password: "Hoanghd164"
image:
repository: "redis/redis-stack-server"
tag: "6.2.4-v2"
master:
args:
- -c
- /opt/bitnami/scripts/merged-start-scripts/start-master.sh
extraVolumes:
- name: merged-start-scripts
configMap:
name: bitnami-redis-stack-server-merged
defaultMode: 0755
extraVolumeMounts:
- name: merged-start-scripts
mountPath: /opt/bitnami/scripts/merged-start-scripts
replica:
args:
- -c
- /opt/bitnami/scripts/merged-start-scripts/start-replica.sh
extraVolumes:
- name: merged-start-scripts
configMap:
name: bitnami-redis-stack-server-merged
defaultMode: 0755
extraVolumeMounts:
- name: merged-start-scripts
mountPath: /opt/bitnami/scripts/merged-start-scripts
extraDeploy:
- apiVersion: v1
kind: ConfigMap
metadata:
name: bitnami-redis-stack-server-merged
data:
start-master.sh: |
#!/usr/bin/dumb-init /bin/bash
### docker entrypoint script, for starting redis stack
BASEDIR=/opt/redis-stack
cd \${BASEDIR}
CMD=\${BASEDIR}/bin/redis-server
if [ -z "\${REDISEARCH_ARGS}" ]; then
REDISEARCH_ARGS="MAXSEARCHRESULTS 10000 MAXAGGREGATERESULTS 10000"
fi
if [ -z "\${REDISGRAPH_ARGS}" ]; then
REDISGRAPH_ARGS="MAX_QUEUED_QUERIES 25 TIMEOUT 1000 RESULTSET_SIZE 10000"
fi
[[ -f \$REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="\$(< "\${REDIS_PASSWORD_FILE}")"
if [[ -f /opt/bitnami/redis/mounted-etc/master.conf ]];then
cp /opt/bitnami/redis/mounted-etc/master.conf /opt/bitnami/redis/etc/master.conf
fi
if [[ -f /opt/bitnami/redis/mounted-etc/redis.conf ]];then
cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf
fi
\${CMD} \
--port "\${REDIS_PORT}" \
--requirepass "\${REDIS_PASSWORD}" \
--masterauth "\${REDIS_PASSWORD}" \
--include "/opt/bitnami/redis/etc/redis.conf" \
--include "/opt/bitnami/redis/etc/master.conf" \
--loadmodule /opt/redis-stack/lib/redisearch.so \${REDISEARCH_ARGS} \
--loadmodule /opt/redis-stack/lib/redisgraph.so \${REDISGRAPH_ARGS} \
--loadmodule /opt/redis-stack/lib/redistimeseries.so \${REDISTIMESERIES_ARGS} \
--loadmodule /opt/redis-stack/lib/rejson.so \${REDISJSON_ARGS} \
--loadmodule /opt/redis-stack/lib/redisbloom.so \${REDISBLOOM_ARGS}
start-replica.sh: |
#!/usr/bin/dumb-init /bin/bash
BASEDIR=/opt/redis-stack
cd \${BASEDIR}
CMD=\${BASEDIR}/bin/redis-server
get_port() {
hostname="\$1"
type="\$2"
port_var=\$(echo "\${hostname^^}_SERVICE_PORT_\$type" | sed "s/-/_/g")
port=\${!port_var}
if [ -z "\$port" ]; then
case \$type in
"SENTINEL")
echo 26379
;;
"REDIS")
echo 6379
;;
esac
else
echo \$port
fi
}
get_full_hostname() {
hostname="\$1"
echo "\${hostname}.\${HEADLESS_SERVICE}"
}
REDISPORT=\$(get_port "\$HOSTNAME" "REDIS")
[[ -f \$REDIS_PASSWORD_FILE ]] && export REDIS_PASSWORD="\$(< "\${REDIS_PASSWORD_FILE}")"
[[ -f \$REDIS_MASTER_PASSWORD_FILE ]] && export REDIS_MASTER_PASSWORD="\$(< "\${REDIS_MASTER_PASSWORD_FILE}")"
if [[ -f /opt/bitnami/redis/mounted-etc/replica.conf ]];then
cp /opt/bitnami/redis/mounted-etc/replica.conf /opt/bitnami/redis/etc/replica.conf
fi
if [[ -f /opt/bitnami/redis/mounted-etc/redis.conf ]];then
cp /opt/bitnami/redis/mounted-etc/redis.conf /opt/bitnami/redis/etc/redis.conf
fi
echo "" >> /opt/bitnami/redis/etc/replica.conf
echo "replica-announce-port \$REDISPORT" >> /opt/bitnami/redis/etc/replica.conf
echo "replica-announce-ip \$(get_full_hostname "\$HOSTNAME")" >> /opt/bitnami/redis/etc/replica.conf
\${CMD} \
--port "\${REDIS_PORT}" \
--requirepass "\${REDIS_PASSWORD}" \
--masterauth "\${REDIS_PASSWORD}" \
--include "/opt/bitnami/redis/etc/redis.conf" \
--include "/opt/bitnami/redis/etc/replica.conf" \
--loadmodule /opt/redis-stack/lib/redisearch.so \${REDISEARCH_ARGS} \
--loadmodule /opt/redis-stack/lib/redisgraph.so \${REDISGRAPH_ARGS} \
--loadmodule /opt/redis-stack/lib/redistimeseries.so \${REDISTIMESERIES_ARGS} \
--loadmodule /opt/redis-stack/lib/rejson.so \${REDISJSON_ARGS} \
--loadmodule /opt/redis-stack/lib/redisbloom.so \${REDISBLOOM_ARGS}
EOF
Thông báo dưới cho biết redis-stack-server chưa tồn tại nên với tham số helm upgrade -i nó sẽ tự động cài đặt.
Release "redis-stack-server" does not exist. Installing it now.
Lệnh Helm trên dùng để triển khai ứng dụng Redis Stack Server trong Kubernetes. Dưới đây là phân tích tác dụng của từng lệnh:
helm upgrade -i
là một cách rút gọn để thực hiện lệnhhelm install
nếu phiên bản chưa tồn tại (được sử dụng để cài đặt) vàhelm upgrade
nếu phiên bản đã tồn tại (được sử dụng để cập nhật).redis-stack-server
là tên của chart./home/redis
là đường dẫn lưu trữ của bản Helm chart.--repo https://charts.bitnami.com/bitnami
là địa chỉ webserver Bitnami sử dụng để lưu trữ các bản Helm chart của họ.--atomic
sẽ tự động chờ cho toàn bộ quá trình triển khai hoàn thành và thực hiện rollback (quay trở lại phiên bản trước đó) nếu bất kỳ thành phần nào thất bại.--version 17.5.6
là phiên bản chart Redis của Bitnami.--values -
cho phép bạn truyền giá trị vào Helm chart.global.redis.password: "Hoanghd164"
đặt một mật khẩu cho tất cả các node Redis (master và replica).image.repository
vàimage.tag
cho phép sử dụng một image và trong trường hợp này chúng ta muốn sử dụng imageredis-stack-server
và tag “latest” từ Docker Hub.master.args
vàreplica.args
là cần thiết để thực thi các script khởi động.master.extraVolumes
,replica.extraVolumes
,master.extraVolumeMounts
, vàreplica.extraVolumeMounts
cần thiết để mount ConfigMap với script thực thi bên dưới.extraDeploy
là một cách để Helm chart này tạo một ConfigMap có tênbitnami-redis-stack-server-merged
được mount ở trên. ConfigMap này kết hợp script khởi động từ imageredis-stack-server
và các script khởi động từ Helm chart Bitnami cho cả node master và replica.
Hãy verify các cài đặt của bạn.
$ kubectl get pod,svc,pvc -n redis-stack
NAME READY STATUS RESTARTS AGE
pod/redis-stack-server-node-0 2/2 Running 0 24m
pod/redis-stack-server-node-1 2/2 Running 0 24m
pod/redis-stack-server-node-2 2/2 Running 0 16h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/redis-stack-server NodePort 10.96.86.175 <none> 6379:32205/TCP,26379:31983/TCP 16h
service/redis-stack-server-headless ClusterIP None <none> 6379/TCP,26379/TCP 16h
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/redis-data-redis-stack-server-node-0 Bound pvc-bceb338e-91c4-4098-b0bc-4f4f6d6c4f10 8Gi RWO longhorn 16h
persistentvolumeclaim/redis-data-redis-stack-server-node-1 Bound pvc-f712c29a-8572-4442-adc1-c87ff9f11877 8Gi RWO longhorn 16h
persistentvolumeclaim/redis-data-redis-stack-server-node-2 Bound pvc-4a403ecf-8874-4499-81e6-38874a6ded05 8Gi RWO longhorn 16
Kết quả pvc trên Longhorn.
Bạn có thể vào một pod để xem
$ kubectl exec -it -n redis-stack pod/redis-stack-server-node-0 bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
Defaulted container "redis" out of: redis, sentinel
groups: cannot find name for group ID 1001
I have no name!@redis-stack-server-node-0:/$ redis-cli -a Hoanghd164
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> INFO
Bạn gõ INFO và kéo xuống phần Replication bạn sẽ nhìn thấy cluster đã nhìn thấy 2 slave như dưới.
# Replication
role:master
connected_slaves:2
slave0:ip=redis-stack-server-node-1.,port=6379,state=online,offset=5014304,lag=0
slave1:ip=redis-stack-server-node-2.,port=6379,state=online,offset=5014304,lag=0
master_failover_state:no-failover
master_replid:6b1d2cd944b7653edbc585aee580deb5e46c994e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:5014304
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:3965729
repl_backlog_histlen:1048576
Do service/redis-stack-server đang ở chế độ ClusterIP nên mình sẽ edit nó để chuyển sang NodePort ở port 32205.
(lý do mình sử dụng NodePort 32205 kà vì cụm Kubernetes của mình có node Loadbalancer chạy Haproxy đang listen Port 32205 từ các node Worker để chuyển nó thành port 6379 cho các client ngoài kết nối.
kubectl edit service/redis-stack-server -n redis-stack
Mình chỉnh sửa 2 tham số như dưới.
Kết quả.
$ kubectl get service/redis-stack-server -n redis-stack
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
redis-stack-server NodePort 10.105.172.140 <none> 6379:32205/TCP,26379:32420/TCP 7m21s
Mình sử dụng Redisinsight để kiểm tra kết quả.
Truyền IP Loadbalancer và mật khẩu vào.
Kết quả.
Bận giờ bạn có thể thoải mái xoá pod (chỉ cần dư 1 pod) thì hệ thống của bạn không downtime nhé.