Цель статьи: Показать на практическом примере, как использовать один Load Balancer для приёма TLS-соединений и маршрутизации бинарного трафика к разным backend‑приложениям с терминацией (расшифровкой) TLS на Gateway — например, к Redis и другим TCP‑сервисам.
Как это работает:
Клиент устанавливает TLS‑соединение с Gateway.
Gateway расшифровывает TLS (режим
Terminate) трафик.После расшифровки остаётся бинарный TCP‑трафик.
TCPRouteмаршрутизирует расшифрованный TCP‑трафик к нужному backend‑сервису.Backend‑сервис получает обычный TCP‑трафик без TLS.
Предварительные требования
Kubernetes‑кластер создан и доступен.
kubectlнастроен и подключён к кластеру.Helm установлен.
DNS‑зона настроена (например,
apatsev.org.ru).Выделен статический IP‑адрес для Envoy Gateway.
Обе внешние DNS‑записи для Redis указывают на этот IP‑адрес.
Схема маршрутизации трафика
Красная линия — путь прохождения трафика от приложения до Redis.
Синяя линия — зашифрованный трафик.
Зелёная линия — незашифрованный трафик.

Маршрутизация по FQDN
Важно: В данной конфигурации каждый FQDN маршрутизируется строго на свой backend:
Трафик с
redis1.apatsev.org.ruидёт только на backendredis1(черезTCPRouteсsectionName: tls-terminate-redis1).Трафик с
redis2.apatsev.org.ruидёт только на backendredis2(черезTCPRouteсsectionName: tls-terminate-redis2).
Маршрутизация определяется на уровне Gateway listener‑ов:
listenertls-terminate-redis1сhostname: "redis1.apatsev.org.ru"→TCPRouteсsectionName: tls-terminate-redis1→ backendredis1.listenertls-terminate-redis2сhostname: "redis2.apatsev.org.ru"→TCPRouteсsectionName: tls-terminate-redis2→ backendredis2.
TCPRoute не поддерживает поле hostnames. Маршрутизация по hostname происходит на уровне Gateway listener‑а через sectionName, что обеспечивает строгую изоляцию трафика между разными FQDN.
1. Установка Envoy Gateway
Установка Envoy Gateway через Helm:
helm upgrade --install envoy-gateway oci://docker.io/envoyproxy/gateway-helm \
--version v1.6.2 \
-n envoy-gateway \
--create-namespace \
--wait2. Применение EnvoyProxy конфигурации
После установки Envoy Gateway применяем EnvoyProxy ресурс для настройки LoadBalancer со статическим IP.
kind: EnvoyProxy нужен для настройки общего “data-plane” прокси для нескольких Gateway — в частности, включается mergeGateways: true, чтобы Envoy Gateway сливал конфигурации нескольких Gateway в один общий Envoy и, как следствие, держал один Service типа LoadBalancer с одним статическим IP (а значит и один входной адрес для нескольких FQDN/listener‑ов). Без EnvoyProxy вы обычно получите отдельный Service/LoadBalancer на каждый Gateway.
Создаём файл envoyproxy.yaml:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
name: merged-proxy
namespace: envoy-gateway
spec:
mergeGateways: true
provider:
type: Kubernetes
kubernetes:
envoyService:
patch:
type: StrategicMerge
value:
spec:
type: LoadBalancer
loadBalancerIP: <STATIC_IP> # IP, на который указывают обе внешние DNS‑записи RedisПрименяем:
kubectl apply -f envoyproxy.yaml3. Генерация TLS сертификатов
Скрипт генерирует Root CA и обычный (leaf) TLS‑сертификат, подписанный этим Root CA. Также он создаёт два секрета:
gateway-tls-cert(типkubernetes.io/tls) — ключ+сертификат для TLS Terminate (Terminate) на Gatewaygateway-root-ca(типOpaque) —ca.crtдля клиентов (app1/app2)
Содержимое скрипта:
#!/bin/bash
set -e
echo "Генерация Root CA и TLS сертификата для Gateway..."
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT
CA_KEY="/tmp/gateway-ca.key"
CA_CRT="/tmp/gateway-ca.crt"
TLS_KEY="/tmp/gateway-tls.key"
TLS_CSR="$TMP_DIR/gateway-tls.csr"
TLS_CRT_LEAF="/tmp/gateway-tls-leaf.crt"
TLS_CRT_CHAIN="/tmp/gateway-tls.crt"
DOMAIN="apatsev.org.ru"
WILDCARD="*.$DOMAIN"
# 1) Root CA (самоподписанный корневой сертификат)
openssl genrsa -out "$CA_KEY" 2048
openssl req -x509 -new -nodes -days 3650 -sha256 \
-key "$CA_KEY" \
-out "$CA_CRT" \
-subj "/CN=Gateway Root CA ($DOMAIN)" \
-addext "basicConstraints=critical,CA:TRUE,pathlen:0" \
-addext "keyUsage=critical,keyCertSign,cRLSign" \
-addext "subjectKeyIdentifier=hash"
# 2) Leaf сертификат для Gateway, подписанный Root CA
cat > "$TMP_DIR/leaf.cnf" <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = v3_req
[ dn ]
CN = $WILDCARD
[ v3_req ]
basicConstraints = critical,CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = $WILDCARD
DNS.2 = redis1.$DOMAIN
DNS.3 = redis2.$DOMAIN
EOF
openssl genrsa -out "$TLS_KEY" 2048
openssl req -new -key "$TLS_KEY" -out "$TLS_CSR" -config "$TMP_DIR/leaf.cnf"
openssl x509 -req -in "$TLS_CSR" -days 365 -sha256 \
-CA "$CA_CRT" -CAkey "$CA_KEY" -CAcreateserial \
-out "$TLS_CRT_LEAF" \
-extfile "$TMP_DIR/leaf.cnf" -extensions v3_req
# 3) Цепочка (leaf + root CA) для отдачи клиентам при handshake (на всякий случай)
cat "$TLS_CRT_LEAF" "$CA_CRT" > "$TLS_CRT_CHAIN"
# 4) Secret для Gateway (TLS keypair)
kubectl create secret tls gateway-tls-cert \
--cert="$TLS_CRT_CHAIN" \
--key="$TLS_KEY" \
--dry-run=client -o yaml | kubectl apply -f -
# 5) Secret с Root CA для клиентов (app1/app2)
kubectl create secret generic gateway-root-ca \
--from-file=ca.crt="$CA_CRT" \
--dry-run=client -o yaml | kubectl apply -f -
echo "Готово:"
echo "- Root CA: $CA_CRT"
echo "- Gateway TLS key: $TLS_KEY"
echo "- Gateway TLS cert chain: $TLS_CRT_CHAIN"
echo "- Secrets: gateway-tls-cert, gateway-root-ca применены в кластер."Запуск:
./scripts/generate-tls-certs.sh4. Создание GatewayClass
GatewayClass ссылается на EnvoyProxy конфигурацию через parametersRef:
Содержимое manifests/gatewayclass.yaml:
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: envoy
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
parametersRef:
group: gateway.envoyproxy.io
kind: EnvoyProxy
name: merged-proxy
namespace: envoy-gatewayПрименяем:
kubectl apply -f manifests/gatewayclass.yamlПроверка статуса:
kubectl get gatewayclass envoyОжидаемый результат: GatewayClass создан со статусом ACCEPTED: True.
5. Развертывание ресурсов Gateway API
Создание Gateway‑ресурсов с TLS Terminate (Terminate)
Важно: Убедитесь, что GatewayClass envoy создан перед созданием Gateway ресурса.
Файл manifests/gateway-redis1.yaml:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg-redis1
namespace: default
spec:
gatewayClassName: envoy
listeners:
- name: tls-terminate-redis1
protocol: TLS
port: 443
hostname: "redis1.apatsev.org.ru"
tls:
mode: Terminate
certificateRefs:
- name: gateway-tls-cert
kind: Secret
allowedRoutes:
namespaces:
from: AllФайл manifests/gateway-redis2.yaml:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg-redis2
namespace: default
spec:
gatewayClassName: envoy
listeners:
- name: tls-terminate-redis2
protocol: TLS
port: 443
hostname: "redis2.apatsev.org.ru"
tls:
mode: Terminate
certificateRefs:
- name: gateway-tls-cert
kind: Secret
allowedRoutes:
namespaces:
from: AllВажно: Для маршрутизации по разным hostname нужны отдельные listener‑ы (по одному на hostname). Детали привязки TCPRoute к listener‑у (через parentRefs[].sectionName) и того, почему TCPRoute не ограничивается по hostnames, — в разделе «Создание TCPRoute» ниже.
Применение:
kubectl apply -f manifests/gateway-redis1.yaml
kubectl apply -f manifests/gateway-redis2.yaml
# Проверка статуса Gateway
kubectl get gateway eg-redis1 eg-redis2 -n default | grep -C 1 PROGRAMMED
kubectl describe gateway eg-redis1 -n default | grep -C 1 Accepted
kubectl describe gateway eg-redis2 -n default | grep -C 1 AcceptedОжидаемый результат: Gateway‑ресурсы созданы, статус PROGRAMMED: True (в выводе kubectl get), условие Accepted: True (в условиях Gateway), адрес назначен (статический IP из Terraform).
Создание тестовых backend‑приложений (Redis 1 и Redis 2)
Redis выбран как наиболее простой вариант для тестирования:
Легко развернуть
Минимальные требования к ресурсам
Простой бинарный протокол для тестирования
Быстрая проверка работоспособности
Созданы два отдельных Redis backend‑а для демонстрации маршрутизации по hostname.
Файл manifests/redis1-deployment.yaml:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis1
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: redis1
template:
metadata:
labels:
app: redis1
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
name: redis
command:
- redis-server
- --port
- "6379"
---
apiVersion: v1
kind: Service
metadata:
name: redis1
namespace: default
spec:
ports:
- name: redis
port: 6379
targetPort: 6379
protocol: TCP
selector:
app: redis1Файл manifests/redis2-deployment.yaml аналогичен, но использует redis2 вместо redis1.
Применение манифестов:
kubectl apply -f manifests/redis1-deployment.yaml
kubectl apply -f manifests/redis2-deployment.yaml
# Проверка
kubectl get pods -l 'app in (redis1,redis2)'
kubectl get svc redis1 redis2Создание TCPRoute
В режиме tls.mode: Terminate TLS завершается на уровне Gateway listener‑а (выбор listener‑а идёт по SNI/hostname), а TCPRoute маршрутизирует уже расшифрованный TCP‑трафик к backend.
Важно:
TCPRouteне поддерживает полеhostnames— маршрутизация поhostnameпроисходит на уровне Gatewaylistener‑а.Поэтому для каждого
hostnameнужен отдельныйlistenerв Gateway, а соответствующийTCPRouteдолжен ссылаться на него черезparentRefs[].sectionName.
Файл manifests/redis1-tcproute.yaml:
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: redis1-tcproute
namespace: default
spec:
parentRefs:
- name: eg-redis1
namespace: default
sectionName: tls-terminate-redis1
rules:
- backendRefs:
- name: redis1
port: 6379
weight: 100Файл manifests/redis2-tcproute.yaml:
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: redis2-tcproute
namespace: default
spec:
parentRefs:
- name: eg-redis2
namespace: default
sectionName: tls-terminate-redis2
rules:
- backendRefs:
- name: redis2
port: 6379
weight: 100Примечание: parentRefs[].sectionName должен совпадать с именем listener‑а в Gateway (tls-terminate-redis1 или tls-terminate-redis2).
Применение:
kubectl apply -f manifests/redis1-tcproute.yaml
kubectl apply -f manifests/redis2-tcproute.yaml
# Проверка статуса
kubectl get tcproute redis1-tcproute redis2-tcproute -n default
kubectl describe tcproute redis1-tcproute -n default
kubectl describe tcproute redis2-tcproute -n defaultОжидаемый результат: TCPRoute‑ресурсы созданы, статус Accepted: True, привязаны к Gateway.
Тестирование TLS‑соединения (через openssl)
# Получение IP‑адреса (из Gateway status)
GATEWAY_IP=$(kubectl get gateway eg-redis1 -n default -o jsonpath='{.status.addresses[0].value}')
# Тест 1: TLS handshake + SNI (сертификат отдаётся Gateway, TLS терминируется на Gateway)
openssl s_client -connect $GATEWAY_IP:443 \
-servername redis1.apatsev.org.ru \
-showcerts
# Тест 2: Redis 1 через TLS терминацию на Gateway (отправляем Redis RESP поверх TLS до Gateway)
(echo -e "PING\r\n"; sleep 1) | openssl s_client -connect $GATEWAY_IP:443 \
-servername redis1.apatsev.org.ru \
-CAfile /tmp/gateway-ca.crt \
-quiet 2>/dev/null
# Тест 3: Redis 2 через TLS терминацию на Gateway
(echo -e "PING\r\n"; sleep 1) | openssl s_client -connect $GATEWAY_IP:443 \
-servername redis2.apatsev.org.ru \
-CAfile /tmp/gateway-ca.crt \
-quiet 2>/dev/null
# Ожидаемый ответ: +PONG (Redis протокол)
# Если получен ответ PONG, это подтверждает:
# - TLS расшифровывается на Gateway
# - SNI `hostname` правильно извлекается
# - `TCPRoute` маршрутизирует трафик к правильному Redis backend на основе `hostname`
# - Redis отвечает на запросыОжидаемый результат:
TLS handshake успешен
SNI правильно передаётся и используется для маршрутизации
Трафик расшифровывается на Gateway
Бинарный трафик маршрутизируется к соответствующему Redis backend на основе
hostnameRedis 1 и Redis 2 отвечают на запросы при использовании соответствующих
hostname
Тестирование через Go‑приложение
main.go:
package main
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"net"
"os"
"path/filepath"
"time"
"github.com/redis/go-redis/v9"
)
func main() {
// Получение адреса Redis из переменной окружения
redisHost := os.Getenv("REDIS_HOST")
if redisHost == "" {
fmt.Fprintln(os.Stderr, "REDIS_HOST не установлен")
os.Exit(1)
}
redisPort := os.Getenv("REDIS_PORT")
if redisPort == "" {
redisPort = "443"
}
redisAddr := fmt.Sprintf("%s:%s", redisHost, redisPort)
fmt.Printf("Подключение к Redis через Gateway: %s\n", redisAddr)
// Проверка DNS разрешения
fmt.Printf("Проверка DNS для %s...\n", redisHost)
ips, err := net.LookupHost(redisHost)
if err != nil {
fmt.Fprintf(os.Stderr, "Ошибка DNS разрешения: %v\n", err)
os.Exit(1)
}
fmt.Printf("DNS разрешен: %v\n", ips)
// TLS конфигурация: по умолчанию проверяем сертификат через Root CA,
// который передается в контейнер через k8s Secret.
//
// - REDIS_CA_CERT: путь к ca.crt (по умолчанию /etc/redis-ca/ca.crt)
// - REDIS_INSECURE_SKIP_VERIFY=true: отключить проверку (не рекомендуется)
caPath := os.Getenv("REDIS_CA_CERT")
if caPath == "" {
caPath = "/etc/redis-ca/ca.crt"
}
insecure := os.Getenv("REDIS_INSECURE_SKIP_VERIFY") == "true"
tlsCfg := &tls.Config{
MinVersion: tls.VersionTLS12,
ServerName: redisHost,
}
if insecure {
tlsCfg.InsecureSkipVerify = true
fmt.Fprintln(os.Stderr, "Внимание: включен REDIS_INSECURE_SKIP_VERIFY=true (проверка TLS отключена)")
} else {
caBytes, err := os.ReadFile(filepath.Clean(caPath))
if err != nil {
fmt.Fprintf(os.Stderr, "Не удалось прочитать CA сертификат (%s): %v\n", caPath, err)
fmt.Fprintln(os.Stderr, "Смонтируйте Secret с ca.crt или установите REDIS_INSECURE_SKIP_VERIFY=true")
os.Exit(1)
}
pool := x509.NewCertPool()
if ok := pool.AppendCertsFromPEM(caBytes); !ok {
fmt.Fprintf(os.Stderr, "Не удалось распарсить CA сертификат (%s)\n", caPath)
os.Exit(1)
}
tlsCfg.RootCAs = pool
}
// Настройка Redis клиента с TLS
rdb := redis.NewClient(&redis.Options{
Addr: redisAddr,
TLSConfig: &tls.Config{
MinVersion: tlsCfg.MinVersion,
ServerName: tlsCfg.ServerName,
RootCAs: tlsCfg.RootCAs,
InsecureSkipVerify: tlsCfg.InsecureSkipVerify,
},
DialTimeout: 5 * time.Second,
ReadTimeout: 3 * time.Second,
WriteTimeout: 3 * time.Second,
})
defer rdb.Close()
// Контекст с таймаутом для всех операций
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Получение аргументов командной строки
if len(os.Args) > 1 {
// Проверка подключения с выводом статуса
fmt.Println("Проверка подключения к Redis...")
_, err := rdb.Ping(ctx).Result()
if err != nil {
fmt.Fprintf(os.Stderr, "Ошибка подключения к Redis: %v\n", err)
os.Exit(1)
}
fmt.Println("Подключение успешно!")
// Выполнение команды Redis
cmd := os.Args[1]
args := os.Args[2:]
var result interface{}
switch cmd {
case "PING":
result, err = rdb.Ping(ctx).Result()
case "SET":
if len(args) < 2 {
fmt.Println("Использование: SET <key> <value>")
os.Exit(1)
}
err = rdb.Set(ctx, args[0], args[1], 0).Err()
if err == nil {
result = "OK"
}
case "GET":
if len(args) < 1 {
fmt.Println("Использование: GET <key>")
os.Exit(1)
}
result, err = rdb.Get(ctx, args[0]).Result()
case "DEL":
if len(args) < 1 {
fmt.Println("Использование: DEL <key>")
os.Exit(1)
}
result, err = rdb.Del(ctx, args...).Result()
case "KEYS":
pattern := "*"
if len(args) > 0 {
pattern = args[0]
}
result, err = rdb.Keys(ctx, pattern).Result()
case "FLUSHDB":
err = rdb.FlushDB(ctx).Err()
if err == nil {
result = "OK"
}
default:
fmt.Fprintf(os.Stderr, "Неизвестная команда: %s\n", cmd)
fmt.Println("Поддерживаемые команды: PING, SET, GET, DEL, KEYS, FLUSHDB")
os.Exit(1)
}
if err != nil {
fmt.Fprintf(os.Stderr, "Ошибка выполнения команды: %v\n", err)
os.Exit(1)
}
fmt.Println(result)
} else {
// Интерактивный режим (простой)
fmt.Println("Интерактивный режим. Для выхода используйте Ctrl+C")
fmt.Println("Примеры команд:")
fmt.Println(" SET key value")
fmt.Println(" GET key")
fmt.Println(" DEL key")
fmt.Println(" KEYS *")
// Простой цикл для выполнения команд
for {
var input string
fmt.Print("redis> ")
fmt.Scanln(&input)
if input == "quit" || input == "exit" {
break
}
}
}
}
go.mod:
module redis-client
go 1.21
require github.com/redis/go-redis/v9 v9.7.0
require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
)
go.sum
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
Dockerfile:
# Многостадийная сборка
FROM golang:1.21-alpine AS builder
# Установка необходимых инструментов
RUN apk add --no-cache git ca-certificates tzdata
WORKDIR /build
# Копирование go.mod и go.sum (если есть)
COPY go.mod go.sum* ./
# Загрузка зависимостей
RUN go mod download
# Копирование исходного кода
COPY main.go .
# Обновление зависимостей после копирования кода
RUN go mod tidy
# Сборка приложения
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o redis-client main.go
# Финальный образ
FROM alpine:latest
# Установка CA сертификатов для TLS
RUN apk --no-cache add ca-certificates
WORKDIR /app
# Копирование бинарника из builder
COPY --from=builder /build/redis-client .
# Переменная окружения для выбора Redis хоста
# REDIS_HOST может быть redis1.apatsev.org.ru или redis2.apatsev.org.ru или любой другой
ENV REDIS_HOST=redis1.apatsev.org.ru
ENV REDIS_PORT=443
# Исполняемый файл
ENTRYPOINT ["/app/redis-client"]
CMD []
Для тестирования используется готовый Docker‑образ ghcr.io/patsevanton/gateway-api-tcproute-redis:1.0.0.
Установка app1/app2 (клиенты) с Root CA из Kubernetes Secret
app1 и app2 подключаются к Redis через TLS (до Gateway) и проверяют сертификат по Root CA из Kubernetes Secret gateway-root-ca (ключ ca.crt).
Secret gateway-root-ca создаётся на шаге «Генерация TLS‑сертификатов» командой ./scripts/generate-tls-certs.sh.
Если Root CA уже есть и нужно создать Secret вручную:
kubectl create secret generic gateway-root-ca \
--from-file=ca.crt=/path/to/ca.crt \
--dry-run=client -o yaml | kubectl apply -f -Запись данных в Redis
Запись в redis1.apatsev.org.ru:
kubectl delete pod redis1-test --ignore-not-found
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: redis1-test
spec:
restartPolicy: Never
volumes:
- name: gateway-root-ca
secret:
secretName: gateway-root-ca
items:
- key: ca.crt
path: ca.crt
containers:
- name: redis1-test
image: ghcr.io/patsevanton/gateway-api-tcproute-redis:1.0.0
env:
- name: REDIS_HOST
value: redis1.apatsev.org.ru
- name: REDIS_CA_CERT
value: /etc/redis-ca/ca.crt
volumeMounts:
- name: gateway-root-ca
mountPath: /etc/redis-ca
readOnly: true
args: ["SET", "redis1key", "redis1"]
EOF
sleep 5
kubectl logs -f pod/redis1-test
kubectl delete pod redis1-test --wait=falseВ выводе будет надпись
Подключение успешно!
Запись в redis2.apatsev.org.ru:
kubectl delete pod redis2-test --ignore-not-found
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: redis2-test
spec:
restartPolicy: Never
volumes:
- name: gateway-root-ca
secret:
secretName: gateway-root-ca
items:
- key: ca.crt
path: ca.crt
containers:
- name: redis2-test
image: ghcr.io/patsevanton/gateway-api-tcproute-redis:1.0.0
env:
- name: REDIS_HOST
value: redis2.apatsev.org.ru
- name: REDIS_CA_CERT
value: /etc/redis-ca/ca.crt
volumeMounts:
- name: gateway-root-ca
mountPath: /etc/redis-ca
readOnly: true
args: ["SET", "redis2key", "redis2"]
EOF
sleep 5
kubectl logs -f pod/redis2-test
kubectl delete pod redis2-test --wait=falseВ выводе будет надпись
Подключен��е успешно!
Чтение данных из Redis
Чтение всех ключей из redis1.apatsev.org.ru:
kubectl delete pod redis1-test --ignore-not-found
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: redis1-test
spec:
restartPolicy: Never
volumes:
- name: gateway-root-ca
secret:
secretName: gateway-root-ca
items:
- key: ca.crt
path: ca.crt
containers:
- name: redis1-test
image: ghcr.io/patsevanton/gateway-api-tcproute-redis:1.0.0
env:
- name: REDIS_HOST
value: redis1.apatsev.org.ru
- name: REDIS_CA_CERT
value: /etc/redis-ca/ca.crt
volumeMounts:
- name: gateway-root-ca
mountPath: /etc/redis-ca
readOnly: true
args: ["KEYS", "*"]
EOF
sleep 5
kubectl logs -f pod/redis1-test
kubectl delete pod redis1-test --wait=falseВ выводе будет надпись
Подключение успешно!
[redis1key]
Чтение всех ключей из redis2.apatsev.org.ru:
kubectl delete pod redis2-test --ignore-not-found
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: redis2-test
spec:
restartPolicy: Never
volumes:
- name: gateway-root-ca
secret:
secretName: gateway-root-ca
items:
- key: ca.crt
path: ca.crt
containers:
- name: redis2-test
image: ghcr.io/patsevanton/gateway-api-tcproute-redis:1.0.0
env:
- name: REDIS_HOST
value: redis2.apatsev.org.ru
- name: REDIS_CA_CERT
value: /etc/redis-ca/ca.crt
volumeMounts:
- name: gateway-root-ca
mountPath: /etc/redis-ca
readOnly: true
args: ["KEYS", "*"]
EOF
sleep 5
kubectl logs -f pod/redis2-test
kubectl delete pod redis2-test --wait=falseВ выводе будет надпись
Подключение успешно!
[redis2key]
Удаление всех ключей из Redis
Удаление всех ключей из redis1.apatsev.org.ru:
kubectl delete pod redis1-test --ignore-not-found
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: redis1-test
spec:
restartPolicy: Never
volumes:
- name: gateway-root-ca
secret:
secretName: gateway-root-ca
items:
- key: ca.crt
path: ca.crt
containers:
- name: redis1-test
image: ghcr.io/patsevanton/gateway-api-tcproute-redis:1.0.0
env:
- name: REDIS_HOST
value: redis1.apatsev.org.ru
- name: REDIS_CA_CERT
value: /etc/redis-ca/ca.crt
volumeMounts:
- name: gateway-root-ca
mountPath: /etc/redis-ca
readOnly: true
args: ["FLUSHDB"]
EOF
sleep 5
kubectl logs -f pod/redis1-test
kubectl delete pod redis1-test --wait=falseУдаление всех ключей из redis2.apatsev.org.ru:
kubectl delete pod redis2-test --ignore-not-found
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: redis2-test
spec:
restartPolicy: Never
volumes:
- name: gateway-root-ca
secret:
secretName: gateway-root-ca
items:
- key: ca.crt
path: ca.crt
containers:
- name: redis2-test
image: ghcr.io/patsevanton/gateway-api-tcproute-redis:1.0.0
env:
- name: REDIS_HOST
value: redis2.apatsev.org.ru
- name: REDIS_CA_CERT
value: /etc/redis-ca/ca.crt
volumeMounts:
- name: gateway-root-ca
mountPath: /etc/redis-ca
readOnly: true
args: ["FLUSHDB"]
EOF
sleep 5
kubectl logs -f pod/redis2-test
kubectl delete pod redis2-test --wait=false