Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7d7042dc1 | ||
|
|
39f5fe3683 |
@@ -0,0 +1,80 @@
|
||||
# ComfyUI — GPU-accelerated image generation on worker-1.
|
||||
# Uses 1x V100 32GB (sm70). Freed by scaling ornith 2→1.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: comfyui
|
||||
namespace: comfyui
|
||||
labels:
|
||||
app: comfyui
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: comfyui
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: comfyui
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: worker-1
|
||||
runtimeClassName: nvidia
|
||||
containers:
|
||||
- name: comfyui
|
||||
image: ghcr.io/ai-dock/comfyui:v2-cuda-12.1.1-base-22.04
|
||||
ports:
|
||||
- containerPort: 8188
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: NVIDIA_VISIBLE_DEVICES
|
||||
value: "all"
|
||||
- name: COMFYUI_FLAGS
|
||||
value: "--listen 0.0.0.0 --port 8188"
|
||||
resources:
|
||||
requests:
|
||||
cpu: "4"
|
||||
memory: 8Gi
|
||||
nvidia.com/gpu: "1"
|
||||
limits:
|
||||
cpu: "8"
|
||||
memory: 16Gi
|
||||
nvidia.com/gpu: "1"
|
||||
volumeMounts:
|
||||
- mountPath: /workspace/ComfyUI/models
|
||||
name: models
|
||||
- mountPath: /workspace/ComfyUI/output
|
||||
name: output
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8188
|
||||
periodSeconds: 10
|
||||
initialDelaySeconds: 30
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8188
|
||||
failureThreshold: 60
|
||||
periodSeconds: 10
|
||||
volumes:
|
||||
- name: models
|
||||
persistentVolumeClaim:
|
||||
claimName: comfyui-models
|
||||
- name: output
|
||||
emptyDir: {}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: comfyui-models
|
||||
namespace: comfyui
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: longhorn
|
||||
resources:
|
||||
requests:
|
||||
storage: 50Gi
|
||||
@@ -0,0 +1,25 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: comfyui
|
||||
namespace: comfyui
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
||||
# WebSocket support for ComfyUI's live preview
|
||||
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
|
||||
nginx.ingress.kubernetes.io/proxy-set-headers: "Upgrade"
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
rules:
|
||||
- host: comfy.riotpiao.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: comfyui
|
||||
port:
|
||||
number: 80
|
||||
@@ -0,0 +1,7 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: comfyui
|
||||
namespace: comfyui
|
||||
labels:
|
||||
app: comfyui
|
||||
spec:
|
||||
selector:
|
||||
app: comfyui
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8188
|
||||
protocol: TCP
|
||||
@@ -14,6 +14,7 @@ resources:
|
||||
- ornith.yaml
|
||||
- reasoning.yaml
|
||||
- reranker.yaml
|
||||
- qwen-cpu.yaml
|
||||
- networkpolicy.yaml
|
||||
# No namespace transformer: every file sets its own, and the transformer would
|
||||
# rewrite metadata.namespace on anything cross-namespace added later.
|
||||
|
||||
@@ -33,12 +33,8 @@ spec:
|
||||
|
||||
ollama pull ornith:35b
|
||||
|
||||
ollama pull qwen2.5:3b-instruct
|
||||
|
||||
ollama run ornith:35b "ok" >/dev/null 2>&1 || true
|
||||
|
||||
ollama run qwen2.5:3b-instruct "ok" >/dev/null 2>&1 || true
|
||||
|
||||
wait $SERVE_PID
|
||||
|
||||
'
|
||||
@@ -54,7 +50,7 @@ spec:
|
||||
- name: OLLAMA_NUM_PARALLEL
|
||||
value: '1'
|
||||
- name: OLLAMA_MAX_LOADED_MODELS
|
||||
value: '2'
|
||||
value: '1'
|
||||
image: ollama/ollama:0.32.9@sha256:1685741456770df6e3cceb2a945a5f75e020f658d1701509668d6f4688f1dd3f
|
||||
name: kserve-container
|
||||
ports:
|
||||
@@ -65,8 +61,7 @@ spec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- ollama ps 2>/dev/null | grep -q ornith && ollama ps 2>/dev/null |
|
||||
grep -q qwen2.5
|
||||
- ollama ps 2>/dev/null | grep -q ornith
|
||||
periodSeconds: 10
|
||||
resources:
|
||||
limits:
|
||||
@@ -82,8 +77,7 @@ spec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- ollama ps 2>/dev/null | grep -q ornith && ollama ps 2>/dev/null |
|
||||
grep -q qwen2.5
|
||||
- ollama ps 2>/dev/null | grep -q ornith
|
||||
failureThreshold: 120
|
||||
periodSeconds: 15
|
||||
volumeMounts:
|
||||
@@ -91,13 +85,10 @@ spec:
|
||||
name: models
|
||||
deploymentStrategy:
|
||||
type: Recreate
|
||||
# 2 replicas -- each its own GPU, each loading both ornith:35b and
|
||||
# qwen2.5:3b-instruct -- so 2 concurrent implementer-style calls each
|
||||
# get an independent instance instead of contending on one, at the
|
||||
# cost of judge/qwen traffic still sharing whichever replica an
|
||||
# implementer call also lands on.
|
||||
maxReplicas: 2
|
||||
minReplicas: 2
|
||||
# 1 replica -- ornith:35b only. qwen2.5:3b moved to CPU on cp-2.
|
||||
# Frees 1 GPU for ComfyUI.
|
||||
maxReplicas: 1
|
||||
minReplicas: 1
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: worker-1
|
||||
runtimeClassName: nvidia
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
# qwen2.5:3b-instruct on CPU (talos-cp-2, 144GB RAM, 24 cores).
|
||||
# Moved off GPU to free a V100 for ComfyUI. Latency ~10x slower
|
||||
# than GPU but sufficient for lightweight tasks (summarization,
|
||||
# classification, quick answers).
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: qwen-cpu
|
||||
namespace: llm-serving
|
||||
labels:
|
||||
app: qwen-cpu
|
||||
app.kubernetes.io/name: qwen-cpu
|
||||
app.kubernetes.io/part-of: llm-serving
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: qwen-cpu
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: qwen-cpu
|
||||
app.kubernetes.io/name: qwen-cpu
|
||||
app.kubernetes.io/part-of: llm-serving
|
||||
spec:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: talos-cp-2
|
||||
tolerations:
|
||||
- key: node-role.kubernetes.io/control-plane
|
||||
operator: Exists
|
||||
effect: NoSchedule
|
||||
containers:
|
||||
- name: ollama
|
||||
image: ollama/ollama:0.32.9@sha256:1685741456770df6e3cceb2a945a5f75e020f658d1701509668d6f4688f1dd3f
|
||||
command: ["/bin/sh", "-c"]
|
||||
args:
|
||||
- |
|
||||
ollama serve &
|
||||
SERVE_PID=$!
|
||||
until ollama list >/dev/null 2>&1; do sleep 2; done
|
||||
ollama pull qwen2.5:3b-instruct
|
||||
ollama run qwen2.5:3b-instruct "ok" >/dev/null 2>&1 || true
|
||||
wait $SERVE_PID
|
||||
env:
|
||||
- name: OLLAMA_HOST
|
||||
value: "0.0.0.0:8080"
|
||||
- name: OLLAMA_MODELS
|
||||
value: /root/.ollama/models
|
||||
- name: OLLAMA_CONTEXT_LENGTH
|
||||
value: "32768"
|
||||
- name: OLLAMA_KEEP_ALIVE
|
||||
value: "-1"
|
||||
- name: OLLAMA_MAX_LOADED_MODELS
|
||||
value: "1"
|
||||
- name: OLLAMA_NUM_PARALLEL
|
||||
value: "2"
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
protocol: TCP
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: ["/bin/sh", "-c", "ollama ps 2>/dev/null | grep -q qwen2.5"]
|
||||
periodSeconds: 10
|
||||
startupProbe:
|
||||
exec:
|
||||
command: ["/bin/sh", "-c", "ollama ps 2>/dev/null | grep -q qwen2.5"]
|
||||
failureThreshold: 60
|
||||
periodSeconds: 10
|
||||
resources:
|
||||
requests:
|
||||
cpu: "4"
|
||||
memory: 4Gi
|
||||
limits:
|
||||
cpu: "8"
|
||||
memory: 8Gi
|
||||
volumeMounts:
|
||||
- mountPath: /root/.ollama
|
||||
name: ollama-data
|
||||
volumes:
|
||||
- name: ollama-data
|
||||
persistentVolumeClaim:
|
||||
claimName: qwen-cpu-data
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: qwen-cpu
|
||||
namespace: llm-serving
|
||||
labels:
|
||||
app: qwen-cpu
|
||||
app.kubernetes.io/part-of: llm-serving
|
||||
spec:
|
||||
selector:
|
||||
app: qwen-cpu
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
---
|
||||
# Small PVC for qwen2.5:3b model weights (~1.9GB).
|
||||
# Separate from llm-models PVC which is pinned to worker-1.
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: qwen-cpu-data
|
||||
namespace: llm-serving
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: longhorn
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
@@ -0,0 +1,32 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: comfyui
|
||||
namespace: argocd
|
||||
labels:
|
||||
app.kubernetes.io/name: comfyui
|
||||
app.kubernetes.io/component: image-generation
|
||||
annotations:
|
||||
argocd.argoproj.io/sync-wave: "8"
|
||||
spec:
|
||||
project: homelab
|
||||
revisionHistoryLimit: 3
|
||||
source:
|
||||
repoURL: https://forgejo.riotpiao.com/rock/homelab.git
|
||||
targetRevision: main
|
||||
path: k8s/apps/comfyui
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: comfyui
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
retry:
|
||||
limit: 5
|
||||
backoff:
|
||||
duration: 5s
|
||||
factor: 2
|
||||
maxDuration: 3m
|
||||
@@ -1,178 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# End-to-end auth flow tests for api-gateway.
|
||||
# Validates: JWT auth, identity headers, token exchange, error handling.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/test-auth-e2e.sh
|
||||
#
|
||||
# Requires: kubectl access to cluster, curl, jq
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
API="https://api.riotpiao.com"
|
||||
TOKEN_URL="https://authentik.riotpiao.com/application/o/token/"
|
||||
PASS=0
|
||||
FAIL=0
|
||||
SKIP=0
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
check() {
|
||||
local name="$1" expected="$2" actual="$3"
|
||||
if [ "$expected" = "$actual" ]; then
|
||||
echo -e " ${GREEN}✓${NC} $name"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
echo -e " ${RED}✗${NC} $name (expected $expected, got $actual)"
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
skip() {
|
||||
echo -e " ${YELLOW}○${NC} $1 (skipped: $2)"
|
||||
SKIP=$((SKIP + 1))
|
||||
}
|
||||
|
||||
# --- Load credentials ---
|
||||
echo "Loading credentials from cluster..."
|
||||
P_SECRET=$(kubectl get secret -n portfolio portfolio-agent-oidc -o jsonpath='{.data.CLIENT_SECRET}' | base64 -d 2>/dev/null) || true
|
||||
M_SECRET=$(kubectl get secret -n poimen memory-agent-oidc -o jsonpath='{.data.CLIENT_SECRET}' | base64 -d 2>/dev/null) || true
|
||||
|
||||
if [ -z "$P_SECRET" ] || [ -z "$M_SECRET" ]; then
|
||||
echo "ERROR: Cannot read service account secrets. Check kubectl context."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Get tokens ---
|
||||
echo ""
|
||||
echo "=== Acquiring tokens ==="
|
||||
|
||||
P_TOKEN=$(curl -s -X POST "$TOKEN_URL" \
|
||||
-d "grant_type=client_credentials&client_id=portfolio-agent&client_secret=$P_SECRET&scope=openid roles" \
|
||||
| jq -r '.access_token')
|
||||
|
||||
M_TOKEN=$(curl -s -X POST "$TOKEN_URL" \
|
||||
-d "grant_type=client_credentials&client_id=memory-agent&client_secret=$M_SECRET&scope=openid roles" \
|
||||
| jq -r '.access_token')
|
||||
|
||||
if [ "$P_TOKEN" = "null" ] || [ -z "$P_TOKEN" ]; then
|
||||
echo "ERROR: Failed to get portfolio-agent token"
|
||||
exit 1
|
||||
fi
|
||||
echo " portfolio-agent: token acquired"
|
||||
echo " memory-agent: token acquired"
|
||||
|
||||
# --- Scenario 1: LLM inference ---
|
||||
echo ""
|
||||
echo "=== Scenario 1: LLM inference (llm:inference) ==="
|
||||
|
||||
CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$API/v1/chat/completions" \
|
||||
-H "Authorization: Bearer $P_TOKEN" -H "Content-Type: application/json" \
|
||||
-d '{"model":"qwen2.5:3b-instruct","messages":[{"role":"user","content":"ok"}],"max_tokens":2}')
|
||||
check "portfolio-agent -> qwen chat" "200" "$CODE"
|
||||
|
||||
CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$API/v1/chat/completions" \
|
||||
-H "Authorization: Bearer $M_TOKEN" -H "Content-Type: application/json" \
|
||||
-d '{"model":"reasoning","messages":[{"role":"user","content":"ok"}],"max_tokens":2}')
|
||||
check "memory-agent -> reasoning chat" "200" "$CODE"
|
||||
|
||||
CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$API/v1/embeddings" \
|
||||
-H "Authorization: Bearer $P_TOKEN" -H "Content-Type: application/json" \
|
||||
-d '{"model":"nomic-ai/nomic-embed-text-v2-moe","input":"test"}')
|
||||
check "portfolio-agent -> embeddings" "200" "$CODE"
|
||||
|
||||
CODE=$(curl -s -o /dev/null -w "%{http_code}" "$API/v1/models")
|
||||
check "GET /v1/models (no auth)" "200" "$CODE"
|
||||
|
||||
# --- Scenario 2: Auth enforcement ---
|
||||
echo ""
|
||||
echo "=== Scenario 2: Auth enforcement ==="
|
||||
|
||||
CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$API/v1/chat/completions" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"model":"qwen2.5:3b-instruct","messages":[{"role":"user","content":"ok"}]}')
|
||||
check "no token -> 401" "401" "$CODE"
|
||||
|
||||
CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$API/v1/chat/completions" \
|
||||
-H "Authorization: Bearer garbage-token" -H "Content-Type: application/json" \
|
||||
-d '{"model":"qwen2.5:3b-instruct","messages":[{"role":"user","content":"ok"}]}')
|
||||
check "bad token -> 403" "403" "$CODE"
|
||||
|
||||
# --- Scenario 3: Token claims ---
|
||||
echo ""
|
||||
echo "=== Scenario 3: Token claims ==="
|
||||
|
||||
decode_jwt() { python3 -c "import base64,json,sys; p=sys.argv[1].split('.')[1]; p+='='*(4-len(p)%4); print(json.dumps(json.loads(base64.urlsafe_b64decode(p))))" "$1"; }
|
||||
|
||||
P_CLAIMS=$(decode_jwt "$P_TOKEN")
|
||||
P_ROLES=$(echo "$P_CLAIMS" | jq -r '.roles | join(",")')
|
||||
check "portfolio-agent has llm:inference" "true" "$(echo "$P_ROLES" | grep -q 'llm:inference' && echo true || echo false)"
|
||||
check "portfolio-agent has s3:read" "true" "$(echo "$P_ROLES" | grep -q 's3:read' && echo true || echo false)"
|
||||
check "portfolio-agent has sqs:read" "true" "$(echo "$P_ROLES" | grep -q 'sqs:read' && echo true || echo false)"
|
||||
|
||||
M_CLAIMS=$(decode_jwt "$M_TOKEN")
|
||||
M_ROLES=$(echo "$M_CLAIMS" | jq -r '.roles | join(",")')
|
||||
check "memory-agent has memory:write" "true" "$(echo "$M_ROLES" | grep -q 'memory:write' && echo true || echo false)"
|
||||
check "memory-agent has s3:write" "true" "$(echo "$M_ROLES" | grep -q 's3:write' && echo true || echo false)"
|
||||
|
||||
# --- Scenario 4: X-Service dispatch ---
|
||||
echo ""
|
||||
echo "=== Scenario 4: X-Service dispatch ==="
|
||||
|
||||
CODE=$(curl -s -o /dev/null -w "%{http_code}" "$API/" \
|
||||
-H "X-Service: s3" -H "X-Resource: list-objects" \
|
||||
-H "Authorization: Bearer $P_TOKEN")
|
||||
check "portfolio-agent -> S3 list (reaches MinIO)" "403" "$CODE"
|
||||
# 403 = MinIO reached but rejects JWT (needs SigV4). Not a gateway auth issue.
|
||||
|
||||
# Memory service might be down
|
||||
CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "$API/" \
|
||||
-H "X-Service: memory" -H "X-Resource: skills" \
|
||||
-H "Authorization: Bearer $P_TOKEN" 2>/dev/null)
|
||||
if [ "$CODE" = "200" ]; then
|
||||
check "portfolio-agent -> memory skills" "200" "$CODE"
|
||||
elif [ "$CODE" = "502" ]; then
|
||||
skip "portfolio-agent -> memory skills" "poimen-memory pods down"
|
||||
else
|
||||
check "portfolio-agent -> memory skills" "200" "$CODE"
|
||||
fi
|
||||
|
||||
# --- Scenario 5: Auth endpoints ---
|
||||
echo ""
|
||||
echo "=== Scenario 5: Auth endpoints ==="
|
||||
|
||||
# /auth/token — may return 400 if password grant not working, but endpoint should respond
|
||||
CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$API/auth/token" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"rock","password":"wrong"}')
|
||||
# Should get 400 (bad creds forwarded from Authentik) or 502 (upstream issue), not 404
|
||||
if [ "$CODE" != "404" ] && [ "$CODE" != "405" ]; then
|
||||
check "/auth/token endpoint exists" "true" "true"
|
||||
else
|
||||
check "/auth/token endpoint exists" "not-404" "$CODE"
|
||||
fi
|
||||
|
||||
CODE=$(curl -s -o /dev/null -w "%{http_code}" -X GET "$API/auth/token")
|
||||
check "GET /auth/token -> 405" "405" "$CODE"
|
||||
|
||||
CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$API/auth/refresh" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"refresh_token":"invalid"}')
|
||||
if [ "$CODE" != "404" ] && [ "$CODE" != "405" ]; then
|
||||
check "/auth/refresh endpoint exists" "true" "true"
|
||||
else
|
||||
check "/auth/refresh endpoint exists" "not-404" "$CODE"
|
||||
fi
|
||||
|
||||
# --- Summary ---
|
||||
echo ""
|
||||
echo "========================================="
|
||||
TOTAL=$((PASS + FAIL + SKIP))
|
||||
echo -e "Results: ${GREEN}$PASS passed${NC}, ${RED}$FAIL failed${NC}, ${YELLOW}$SKIP skipped${NC} / $TOTAL total"
|
||||
echo "========================================="
|
||||
|
||||
[ "$FAIL" -eq 0 ] && exit 0 || exit 1
|
||||
@@ -36,6 +36,7 @@
|
||||
rewrite name paperless.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
|
||||
rewrite name img.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
|
||||
rewrite name api.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
|
||||
rewrite name comfy.riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
|
||||
rewrite name riotpiao.com ingress-nginx-controller.ingress-nginx.svc.cluster.local
|
||||
|
||||
kubernetes cluster.local in-addr.arpa ip6.arpa {
|
||||
|
||||
Reference in New Issue
Block a user