Skip to content

Kubernetes Deployment

Overview

Kubernetes is the recommended deployment platform for CoSky in production environments. The project ships with ready-to-use manifest files for both single-replica and clustered Redis setups, a Kubernetes Service for stable network access, and OpenTelemetry annotations for automatic observability instrumentation. CoSky's lightweight resource footprint (250m CPU / 1024Mi memory requests) makes it well-suited for shared cluster environments.

Deployment Manifest (Single Node Redis)

The base deployment manifest creates a single CoSky replica connected to a standalone Redis instance:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cosky
  labels:
    app: cosky
spec:
  replicas: 1
  selector:
    matchLabels:
      app: cosky
  template:
    metadata:
      labels:
        app: cosky
      annotations:
        instrumentation.opentelemetry.io/inject-java: "true"
    spec:
      containers:
        - name: cosky
          image: registry.cn-shanghai.aliyuncs.com/ahoo/cosky:5.3.5
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          env:
            - name: SPRING_DATA_REDIS_HOST
              value: redis-uri:6379
            - name: SPRING_DATA_REDIS_PASSWORD
              value: redis-pwd
            - name: TZ
              value: Asia/Shanghai
          startupProbe:
            httpGet:
              port: http
              path: /actuator/health
          readinessProbe:
            httpGet:
              port: http
              path: /actuator/health/readiness
          livenessProbe:
            httpGet:
              port: http
              path: /actuator/health/liveness
          resources:
            limits:
              cpu: "1"
              memory: 1280Mi
            requests:
              cpu: 250m
              memory: 1024Mi
          volumeMounts:
            - mountPath: /etc/localtime
              name: volume-localtime
      volumes:
        - hostPath:
            path: /etc/localtime
            type: ""
          name: volume-localtime

Clustered Redis Deployment

For production environments with Redis Cluster, use the cluster manifest which reads connection details from a Kubernetes Secret:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cosky
  labels:
    app: cosky
spec:
  replicas: 1
  selector:
    matchLabels:
      app: cosky
  template:
    metadata:
      labels:
        app: cosky
      annotations:
        instrumentation.opentelemetry.io/inject-java: "true"
    spec:
      containers:
        - name: cosky
          image: registry.cn-shanghai.aliyuncs.com/ahoo/cosky:5.3.5
          env:
            - name: SPRING_DATA_REDIS_CLUSTER_NODES
              valueFrom:
                secretKeyRef:
                  name: redis-secret
                  key: nodes
            - name: SPRING_DATA_REDIS_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: redis-secret
                  key: password
            - name: SPRING_DATA_REDIS_CLUSTER_MAX_REDIRECTS
              value: "3"
            - name: SPRING_DATA_REDIS_LETTUCE_CLUSTER_REFRESH_ADAPTIVE
              value: "true"
            - name: SPRING_DATA_REDIS_LETTUCE_CLUSTER_REFRESH_PERIOD
              value: 30s
            - name: TZ
              value: Asia/Shanghai
          # ... same probes, resources, and volumes as above

Kubernetes Service

The Service exposes CoSky on port 80, forwarding to the container port 8080:

yaml
apiVersion: v1
kind: Service
metadata:
  name: cosky
  labels:
    app: cosky
spec:
  selector:
    app: cosky
  ports:
    - name: rest
      port: 80
      protocol: TCP
      targetPort: 8080

Architecture Overview

The following diagram shows the Kubernetes deployment topology for a single-replica setup:

mermaid
flowchart TB
    subgraph Kubernetes Cluster
        style Kubernetes Cluster fill:#161b22,stroke:#30363d,color:#e6edf3
        subgraph cosky namespace
            style cosky namespace fill:#161b22,stroke:#30363d,color:#e6edf3
            LB["Ingress / LB"] --> SVC["Service: cosky<br>port 80 -> 8080"]
            SVC --> POD["Pod: cosky<br>CPU: 250m-1<br>Mem: 1024-1280Mi"]
            POD --> R["Redis<br>(standalone or cluster)"]
            POD --> OT["OpenTelemetry<br>Collector"]
        end
    end

    LB:::node
    SVC:::node
    POD:::node
    R:::node
    OT:::node

    classDef node fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

Clustered Redis Topology

When using Redis Cluster, CoSky connects through the Lettuce client with adaptive topology refres```mermaid flowchart TB subgraph Kubernetes Cluster style Kubernetes Cluster fill:#161b22,stroke:#30363d,color:#e6edf3 subgraph cosky pods style cosky pods fill:#161b22,stroke:#30363d,color:#e6edf3 P1["CoSky Pod 1"] P2["CoSky Pod 2"] end subgraph redis-secret style redis-secret fill:#161b22,stroke:#30363d,color:#e6edf3 S["K8s Secret
redis-secret"] end subgraph Redis Cluster style Redis Cluster fill:#161b22,stroke:#30363d,color:#e6edf3 N1["Redis Node 1"] N2["Redis Node 2"] N3["Redis Node 3"] N1 --- N2 N2 --- N3 N3 --- N1 end P1 -->|"SPRING_DATA_REDIS_CLUSTER_NODES
from secret"| N1 P2 -->|"SPRING_DATA_REDIS_CLUSTER_NODES
from secret"| N2 S -.->|"valueFrom.secretKeyRef"| P1 S -.->|"valueFrom.secretKeyRef"| P2 end

P1:::node
P2:::node
S:::node
N1:::node
N2:::node
N3:::node

classDef node fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

Pod Startup Sequence

mermaid
sequenceDiagram
    autonumber
    participant K as Kubelet
    participant C as CoSky Container
    participant R as Redis
    participant SP as Startup Probe
    participant RP as Readiness Probe
    participant LP as Liveness Probe

    K->>C: create container
    C->>R: connect via env config
    R-->>C: connection OK
    C->>C: Spring Boot initialization
    C->>C: load bootstrap.yaml + application.yaml
    C->>C: init CoSec / CosID / Simba
    loop startup probe
        SP->>C: GET /actuator/health
        C-->>SP: 503 until ready
        SP->>C: GET /actuator/health
        C-->>SP: 200 OK
    end
    K->>C: mark pod as Started
    loop readiness probe
        RP->>C: GET /actuator/health/readiness
        C-->>RP: 200 OK
    end
    K->>C: add pod to Service endpoints
    loop liveness probe
        LP->>C: GET /actuator/health/liveness
        C-->>LP: 200 OK
    end

Resource Configuration

ResourceRequestsLimitsNotes
CPU250m1 coreSuitable for moderate traffic
Memory1024Mi1280MiIncludes JVM heap + off-heap
Startup Probe/actuator/health-Allows up to failureThreshold * periodSeconds for cold start
Readiness Probe/actuator/health/readiness-Controls traffic routing
Liveness Probe/actuator/health/liveness-Restarts unhealthy pods

Environment Variables

Standalone Redis

VariableSourceDescription
SPRING_DATA_REDIS_HOSTDirect valueRedis host and port (e.g. redis-uri:6379)
SPRING_DATA_REDIS_PASSWORDDirect value or SecretRedis authentication password
TZDirect valueContainer timezone
LANGDirect valueLocale setting

Clustered Redis

VariableSourceDescription
SPRING_DATA_REDIS_CLUSTER_NODESSecret (redis-secret.nodes)Comma-separated cluster node addresses
SPRING_DATA_REDIS_PASSWORDSecret (redis-secret.password)Cluster authentication password
SPRING_DATA_REDIS_CLUSTER_MAX_REDIRECTSDirect value (3)Maximum cluster redirect hops
SPRING_DATA_REDIS_LETTUCE_CLUSTER_REFRESH_ADAPTIVEDirect value (true)Enable adaptive topology refresh
SPRING_DATA_REDIS_LETTUCE_CLUSTER_REFRESH_PERIODDirect value (30s)Topology refresh interval
TZDirect valueContainer timezone

Health Probes

CoSky exposes three Spring Boot Actuator health endpoints used by Kubernetes probes:

Probe TypeEndpointConfiguration
StartupGET /actuator/healthDefault failureThreshold and periodSeconds
ReadinessGET /actuator/health/readinessDefault settings
LivenessGET /actuator/health/livenessDefault settings

The startup probe prevents Kubernetes from killing the pod before Spring Boot finishes initializing. Once the startup probe succeeds, the readiness and liveness probes take over.

OpenTelemetry Integration

The deployment manifests include the annotation instrumentation.opentelemetry.io/inject-java: "true", which enables automatic Java instrumentation by an OpenTelemetry operator sidecar. This provides distributed tracing, metrics, and log correlation without code changes.

Volume Mounts

VolumeMount PathTypePurpose
volume-localtime/etc/localtimehostPathSynchronize container clock with host

Applying the Manifests

bash
# Create the Redis secret (for cluster mode)
kubectl create secret generic redis-secret \
  --from-literal=nodes="redis-node-1:6379,redis-node-2:6379,redis-node-3:6379" \
  --from-literal=password="your-redis-password"

# Deploy CoSky
kubectl apply -f k8s/deployment/cosky.yml

# Or deploy with cluster Redis
kubectl apply -f k8s/deployment/cosky-cluster.yml

# Create the Service
kubectl apply -f k8s/deployment/cosky-service.yaml

# Verify deployment
kubectl get pods -l app=cosky
kubectl get svc cosky

Observabilit```mermaid

flowchart LR subgraph Observability Pipeline style Observability Pipeline fill:#161b22,stroke:#30363d,color:#e6edf3 P["CoSky Pod
OTel annotation"] -->|"auto-inject"| I["OTel Agent
sidecar"] I -->|"traces + metrics"| O["OTel Collector"] O --> J["Jaeger / Tempo"] O --> M["Prometheus"] O --> G["Grafana"] end

P:::node
I:::node
O:::node
J:::node
M:::node
G:::node

classDef node fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
edf3

References

Released under the Apache License 2.0.