fix(devops): resolve 4 P2 DevOps improvements (Wave 3 — TEC-263)
- DEVOPS-W-01: Add oliver006/redis_exporter to docker-compose.yml so the existing prometheus.yml scrape job (redis-exporter:9121) resolves - DEVOPS-W-04: Add redis-sentinel.yaml with Redis Sentinel HA setup (1 master StatefulSet + 2 replica StatefulSet + 3 sentinel pods) replacing the single-instance SPOF redis.yaml in staging K8s - DEVOPS-W-05: Add network-policy.yaml with default-deny-all NetworkPolicy + explicit allow rules for inter-service, Traefik ingress, Redis access, Prometheus scrape, and external egress (Neon PostgreSQL, AMQP) - DEVOPS-M-01: Add aquasecurity/trivy-action to docker-build.yml to scan every built image for CRITICAL/HIGH CVEs; results uploaded to GitHub Security tab via SARIF Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
19
.github/workflows/docker-build.yml
vendored
19
.github/workflows/docker-build.yml
vendored
@@ -112,3 +112,22 @@ jobs:
|
||||
tags: ${{ steps.tags.outputs.tags }}
|
||||
cache-from: type=registry,ref=${{ matrix.image }}:buildcache
|
||||
cache-to: type=registry,ref=${{ matrix.image }}:buildcache,mode=max
|
||||
|
||||
# EN: Scan image for vulnerabilities with Trivy (DEVOPS-M-01)
|
||||
# VI: Quet lo hong bao mat image bang Trivy (DEVOPS-M-01)
|
||||
- name: Scan ${{ matrix.service }} image for vulnerabilities
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
image-ref: ${{ matrix.image }}:${{ github.sha }}
|
||||
format: 'sarif'
|
||||
output: 'trivy-results-${{ matrix.service }}.sarif'
|
||||
severity: 'CRITICAL,HIGH'
|
||||
exit-code: '1'
|
||||
ignore-unfixed: true
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
if: always()
|
||||
with:
|
||||
sarif_file: 'trivy-results-${{ matrix.service }}.sarif'
|
||||
category: 'trivy-${{ matrix.service }}'
|
||||
|
||||
@@ -68,6 +68,22 @@ services:
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# Redis Exporter - Prometheus metrics for Redis (DEVOPS-W-01)
|
||||
redis-exporter:
|
||||
image: oliver006/redis_exporter:latest
|
||||
container_name: redis-exporter-local
|
||||
environment:
|
||||
REDIS_ADDR: "redis://redis:6379"
|
||||
REDIS_PASSWORD: "goodgo-redis-local"
|
||||
ports:
|
||||
- "9121:9121"
|
||||
networks:
|
||||
- microservices-network
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
|
||||
# MinIO - Object Storage (S3-compatible)
|
||||
minio:
|
||||
image: minio/minio:latest
|
||||
|
||||
370
deployments/staging/kubernetes/network-policy.yaml
Normal file
370
deployments/staging/kubernetes/network-policy.yaml
Normal file
@@ -0,0 +1,370 @@
|
||||
# EN: Kubernetes NetworkPolicy — default-deny + explicit allow rules (DEVOPS-W-05)
|
||||
# VI: Kubernetes NetworkPolicy — tu choi mac dinh + cho phep tuong minh (DEVOPS-W-05)
|
||||
#
|
||||
# Strategy:
|
||||
# 1. Default-deny all ingress and egress in staging namespace
|
||||
# 2. Allow DNS resolution (kube-dns)
|
||||
# 3. Allow inter-service communication via explicit rules
|
||||
# 4. Allow ingress from Traefik (API gateway)
|
||||
# 5. Allow Prometheus scraping metrics from all services
|
||||
# 6. Allow Redis access only from application services
|
||||
|
||||
# =============================================================================
|
||||
# Default Deny — block all ingress + egress by default
|
||||
# =============================================================================
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: default-deny-all
|
||||
namespace: staging
|
||||
labels:
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
spec:
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
|
||||
---
|
||||
# =============================================================================
|
||||
# Allow DNS (kube-dns) — required for all pods to resolve service names
|
||||
# =============================================================================
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-dns-egress
|
||||
namespace: staging
|
||||
labels:
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
spec:
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- ports:
|
||||
- port: 53
|
||||
protocol: UDP
|
||||
- port: 53
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
# =============================================================================
|
||||
# Allow Traefik ingress → microservices (port 8080)
|
||||
# EN: Traefik runs in kube-system namespace (or traefik namespace).
|
||||
# VI: Traefik chay trong namespace kube-system (hoac traefik namespace).
|
||||
# =============================================================================
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-traefik-ingress
|
||||
namespace: staging
|
||||
labels:
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
spec:
|
||||
podSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- iam-service
|
||||
- merchant-service
|
||||
- order-service
|
||||
- fnb-engine
|
||||
- inventory-service
|
||||
- wallet-service
|
||||
- catalog-service
|
||||
- storage-service
|
||||
- booking-service
|
||||
- pos-web
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: kube-system
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: traefik
|
||||
ports:
|
||||
- port: 8080
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
# =============================================================================
|
||||
# Allow microservices to egress to each other (port 8080)
|
||||
# EN: Services communicate internally via REST (HTTP/8080).
|
||||
# VI: Cac service giao tiep noi bo qua REST (HTTP/8080).
|
||||
# =============================================================================
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-inter-service-egress
|
||||
namespace: staging
|
||||
labels:
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
spec:
|
||||
podSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- iam-service
|
||||
- merchant-service
|
||||
- order-service
|
||||
- fnb-engine
|
||||
- inventory-service
|
||||
- wallet-service
|
||||
- catalog-service
|
||||
- storage-service
|
||||
- booking-service
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- iam-service
|
||||
- merchant-service
|
||||
- order-service
|
||||
- fnb-engine
|
||||
- inventory-service
|
||||
- wallet-service
|
||||
- catalog-service
|
||||
- storage-service
|
||||
- booking-service
|
||||
ports:
|
||||
- port: 8080
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
# =============================================================================
|
||||
# Allow Redis access — only from app services (port 6379)
|
||||
# EN: Redis is accessed only by application pods (not pos-web frontend).
|
||||
# VI: Redis chi duoc truy cap boi cac pod ung dung (khong phai pos-web frontend).
|
||||
# =============================================================================
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-redis-ingress
|
||||
namespace: staging
|
||||
labels:
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
spec:
|
||||
podSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- redis-master
|
||||
- redis-replica
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- iam-service
|
||||
- merchant-service
|
||||
- order-service
|
||||
- fnb-engine
|
||||
- inventory-service
|
||||
- wallet-service
|
||||
- catalog-service
|
||||
- storage-service
|
||||
- booking-service
|
||||
ports:
|
||||
- port: 6379
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
# Allow Redis master → replica replication egress
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-redis-replication
|
||||
namespace: staging
|
||||
labels:
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
spec:
|
||||
podSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- redis-master
|
||||
- redis-replica
|
||||
- redis-sentinel
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- redis-master
|
||||
- redis-replica
|
||||
- redis-sentinel
|
||||
ports:
|
||||
- port: 6379
|
||||
protocol: TCP
|
||||
- port: 26379
|
||||
protocol: TCP
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- redis-master
|
||||
- redis-replica
|
||||
- redis-sentinel
|
||||
ports:
|
||||
- port: 6379
|
||||
protocol: TCP
|
||||
- port: 26379
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
# =============================================================================
|
||||
# Allow microservices to reach Redis (egress)
|
||||
# =============================================================================
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-app-to-redis-egress
|
||||
namespace: staging
|
||||
labels:
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
spec:
|
||||
podSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- iam-service
|
||||
- merchant-service
|
||||
- order-service
|
||||
- fnb-engine
|
||||
- inventory-service
|
||||
- wallet-service
|
||||
- catalog-service
|
||||
- storage-service
|
||||
- booking-service
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- to:
|
||||
- podSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- redis-master
|
||||
- redis-replica
|
||||
- redis-sentinel
|
||||
ports:
|
||||
- port: 6379
|
||||
protocol: TCP
|
||||
- port: 26379
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
# =============================================================================
|
||||
# Allow Prometheus scrape — port 8080 metrics from all app pods
|
||||
# EN: Prometheus runs in monitoring namespace and scrapes /metrics.
|
||||
# VI: Prometheus chay trong namespace monitoring va thu thap /metrics.
|
||||
# =============================================================================
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-prometheus-scrape
|
||||
namespace: staging
|
||||
labels:
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
spec:
|
||||
podSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- iam-service
|
||||
- merchant-service
|
||||
- order-service
|
||||
- fnb-engine
|
||||
- inventory-service
|
||||
- wallet-service
|
||||
- catalog-service
|
||||
- storage-service
|
||||
- booking-service
|
||||
- pos-web
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: monitoring
|
||||
ports:
|
||||
- port: 8080
|
||||
protocol: TCP
|
||||
|
||||
---
|
||||
# =============================================================================
|
||||
# Allow microservices to reach external services (Neon PostgreSQL, etc.)
|
||||
# EN: Egress to external HTTPS/PostgreSQL (Neon cloud DB, SMTP, etc.)
|
||||
# VI: Egress ra ngoai HTTPS/PostgreSQL (Neon cloud DB, SMTP, v.v.)
|
||||
# =============================================================================
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-external-egress
|
||||
namespace: staging
|
||||
labels:
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
spec:
|
||||
podSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- iam-service
|
||||
- merchant-service
|
||||
- order-service
|
||||
- fnb-engine
|
||||
- inventory-service
|
||||
- wallet-service
|
||||
- catalog-service
|
||||
- storage-service
|
||||
- booking-service
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
- ports:
|
||||
- port: 443
|
||||
protocol: TCP
|
||||
- port: 5432
|
||||
protocol: TCP
|
||||
- port: 5671
|
||||
protocol: TCP
|
||||
- port: 5672
|
||||
protocol: TCP
|
||||
427
deployments/staging/kubernetes/redis-sentinel.yaml
Normal file
427
deployments/staging/kubernetes/redis-sentinel.yaml
Normal file
@@ -0,0 +1,427 @@
|
||||
# EN: Redis HA with Sentinel — replaces single-instance redis.yaml (DEVOPS-W-04)
|
||||
# VI: Redis HA voi Sentinel — thay the redis.yaml don le (DEVOPS-W-04)
|
||||
#
|
||||
# Architecture:
|
||||
# - redis-master: 1 pod StatefulSet (read/write)
|
||||
# - redis-replica: 2 pod StatefulSet (read-only replicas)
|
||||
# - redis-sentinel: 3 pod StatefulSet (monitors master, auto-failover)
|
||||
#
|
||||
# EN: Apply this file AND remove (or stop applying) redis.yaml to avoid conflicts.
|
||||
# VI: Apply file nay VA xoa (hoac ngung apply) redis.yaml de tranh conflict.
|
||||
|
||||
# =============================================================================
|
||||
# ConfigMap — Sentinel configuration template
|
||||
# =============================================================================
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: redis-sentinel-config
|
||||
namespace: staging
|
||||
labels:
|
||||
app: redis-sentinel
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
data:
|
||||
sentinel.conf: |
|
||||
sentinel resolve-hostnames yes
|
||||
sentinel announce-hostnames yes
|
||||
sentinel monitor goodgo-master redis-master-0.redis-master.staging.svc.cluster.local 6379 2
|
||||
sentinel auth-pass goodgo-master $(REDIS_PASSWORD)
|
||||
sentinel down-after-milliseconds goodgo-master 5000
|
||||
sentinel failover-timeout goodgo-master 60000
|
||||
sentinel parallel-syncs goodgo-master 1
|
||||
replica.conf: |
|
||||
replicaof redis-master-0.redis-master.staging.svc.cluster.local 6379
|
||||
masterauth $(REDIS_PASSWORD)
|
||||
requirepass $(REDIS_PASSWORD)
|
||||
maxmemory 256mb
|
||||
maxmemory-policy allkeys-lru
|
||||
appendonly yes
|
||||
|
||||
---
|
||||
# =============================================================================
|
||||
# StatefulSet — Redis Master (1 replica)
|
||||
# =============================================================================
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: redis-master
|
||||
namespace: staging
|
||||
labels:
|
||||
app: redis-master
|
||||
role: master
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
tier: infrastructure
|
||||
spec:
|
||||
serviceName: redis-master
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: redis-master
|
||||
role: master
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: redis-master
|
||||
role: master
|
||||
environment: staging
|
||||
spec:
|
||||
containers:
|
||||
- name: redis
|
||||
image: redis:7-alpine
|
||||
command:
|
||||
- redis-server
|
||||
- "--requirepass"
|
||||
- "$(REDIS_PASSWORD)"
|
||||
- "--maxmemory"
|
||||
- "256mb"
|
||||
- "--maxmemory-policy"
|
||||
- "allkeys-lru"
|
||||
- "--appendonly"
|
||||
- "yes"
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: goodgo-secrets
|
||||
key: Redis__Password
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "250m"
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- redis-cli -a "$REDIS_PASSWORD" ping
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- redis-cli -a "$REDIS_PASSWORD" ping
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
volumeMounts:
|
||||
- name: redis-master-data
|
||||
mountPath: /data
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: redis-master-data
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
|
||||
---
|
||||
# Service — Redis Master (headless for StatefulSet DNS)
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: redis-master
|
||||
namespace: staging
|
||||
labels:
|
||||
app: redis-master
|
||||
role: master
|
||||
environment: staging
|
||||
spec:
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: redis-master
|
||||
role: master
|
||||
ports:
|
||||
- name: redis
|
||||
port: 6379
|
||||
targetPort: 6379
|
||||
|
||||
---
|
||||
# Service — Redis write endpoint (used by apps)
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: redis
|
||||
namespace: staging
|
||||
labels:
|
||||
app: redis-master
|
||||
role: master
|
||||
environment: staging
|
||||
spec:
|
||||
selector:
|
||||
app: redis-master
|
||||
role: master
|
||||
ports:
|
||||
- name: redis
|
||||
port: 6379
|
||||
targetPort: 6379
|
||||
type: ClusterIP
|
||||
|
||||
---
|
||||
# =============================================================================
|
||||
# StatefulSet — Redis Replicas (2 replicas for HA)
|
||||
# =============================================================================
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: redis-replica
|
||||
namespace: staging
|
||||
labels:
|
||||
app: redis-replica
|
||||
role: replica
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
tier: infrastructure
|
||||
spec:
|
||||
serviceName: redis-replica
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: redis-replica
|
||||
role: replica
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: redis-replica
|
||||
role: replica
|
||||
environment: staging
|
||||
spec:
|
||||
initContainers:
|
||||
- name: init-replica-conf
|
||||
image: busybox:1.36
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
sed "s/\$(REDIS_PASSWORD)/$REDIS_PASSWORD/g" /config/replica.conf > /data/redis.conf
|
||||
env:
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: goodgo-secrets
|
||||
key: Redis__Password
|
||||
volumeMounts:
|
||||
- name: redis-config
|
||||
mountPath: /config
|
||||
- name: redis-replica-data
|
||||
mountPath: /data
|
||||
containers:
|
||||
- name: redis
|
||||
image: redis:7-alpine
|
||||
command:
|
||||
- redis-server
|
||||
- /data/redis.conf
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: goodgo-secrets
|
||||
key: Redis__Password
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "250m"
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- redis-cli -a "$REDIS_PASSWORD" ping
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- redis-cli -a "$REDIS_PASSWORD" ping
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
volumeMounts:
|
||||
- name: redis-replica-data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: redis-config
|
||||
configMap:
|
||||
name: redis-sentinel-config
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: redis-replica-data
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
|
||||
---
|
||||
# Service — Redis Replicas (headless)
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: redis-replica
|
||||
namespace: staging
|
||||
labels:
|
||||
app: redis-replica
|
||||
role: replica
|
||||
environment: staging
|
||||
spec:
|
||||
clusterIP: None
|
||||
selector:
|
||||
app: redis-replica
|
||||
role: replica
|
||||
ports:
|
||||
- name: redis
|
||||
port: 6379
|
||||
targetPort: 6379
|
||||
|
||||
---
|
||||
# =============================================================================
|
||||
# StatefulSet — Redis Sentinel (3 nodes — quorum = 2)
|
||||
# =============================================================================
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: redis-sentinel
|
||||
namespace: staging
|
||||
labels:
|
||||
app: redis-sentinel
|
||||
role: sentinel
|
||||
environment: staging
|
||||
platform: goodgo
|
||||
tier: infrastructure
|
||||
spec:
|
||||
serviceName: redis-sentinel
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: redis-sentinel
|
||||
role: sentinel
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: redis-sentinel
|
||||
role: sentinel
|
||||
environment: staging
|
||||
spec:
|
||||
initContainers:
|
||||
- name: init-sentinel-conf
|
||||
image: busybox:1.36
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
sed "s/\$(REDIS_PASSWORD)/$REDIS_PASSWORD/g" /config/sentinel.conf > /data/sentinel.conf
|
||||
env:
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: goodgo-secrets
|
||||
key: Redis__Password
|
||||
volumeMounts:
|
||||
- name: sentinel-config
|
||||
mountPath: /config
|
||||
- name: sentinel-data
|
||||
mountPath: /data
|
||||
containers:
|
||||
- name: sentinel
|
||||
image: redis:7-alpine
|
||||
command:
|
||||
- redis-sentinel
|
||||
- /data/sentinel.conf
|
||||
ports:
|
||||
- containerPort: 26379
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: goodgo-secrets
|
||||
key: Redis__Password
|
||||
resources:
|
||||
requests:
|
||||
memory: "64Mi"
|
||||
cpu: "50m"
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- redis-cli
|
||||
- -p
|
||||
- "26379"
|
||||
- ping
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- redis-cli
|
||||
- -p
|
||||
- "26379"
|
||||
- ping
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
volumeMounts:
|
||||
- name: sentinel-data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: sentinel-config
|
||||
configMap:
|
||||
name: redis-sentinel-config
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: sentinel-data
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Mi
|
||||
|
||||
---
|
||||
# Service — Redis Sentinel (headless + ClusterIP)
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: redis-sentinel
|
||||
namespace: staging
|
||||
labels:
|
||||
app: redis-sentinel
|
||||
role: sentinel
|
||||
environment: staging
|
||||
spec:
|
||||
selector:
|
||||
app: redis-sentinel
|
||||
role: sentinel
|
||||
ports:
|
||||
- name: sentinel
|
||||
port: 26379
|
||||
targetPort: 26379
|
||||
type: ClusterIP
|
||||
Reference in New Issue
Block a user