У меня есть приложение, которое я пытаюсь развернуть в Kubernetes (используя Docker Desktop).
В приложении есть два модуля, каждый из которых состоит из одного компонента:
модуль API
ВЕБ-модуль
Идея состоит в том, что я хочу, чтобы WEB-модуль был доступен внешнему миру, но я не хочу, чтобы другие модули были доступны кому-либо, кроме других модулей в кластере. В конце концов я добавлю базу данных, рабочие компоненты, очередь и Redis, которые должны быть скрыты в кластере от внешнего мира. Ничего особенного в архитектуре.
Веб-страница обслуживается нормально, и вызов API на веб-сервере тоже работает отлично.
Вызов модуля WEB в модуль API вызывает у меня проблемы:
URL-адрес, который я пытаюсь использовать: http://localhost:8000.
Я получаю следующую ошибку:
TypeError: fetch failed
at node:internal/deps/undici/undici:12618:11
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async /app/server.js:51:17 {
cause: Error: connect ECONNREFUSED 10.107.140.254:8000
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1605:16) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '10.107.140.254',
port: 8000
В дополнение к localhost я пробовал:
Я нашел страницу, на которой говорилось, что, возможно, веб-узл.js разрешается в ipv6, поэтому я безуспешно добавил это в верхнюю часть своего веб-приложения nodejs:
var dns = require('node:dns');
dns.setDefaultResultOrder('ipv4first');
Я могу успешно свернуть API (с хоста MacOS) с помощью:
curl -d '{"x": 1}' -H "Content-Type: application/json" -X POST http://localhost:8000
Поэтому я уверен, что API работает.
Вот код в API WEB nodejs, который пытается получить модуль API:
await fetch('http://localhost:8000', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
body: JSON.stringify({}}) })
.then(r => Promise.all([r, r.status !== 200 ? r.text() : r.json()]))
.then(([r, json]) => {
if (r.status !== 200) {
console.info(r); console.info(json);
}
})
.catch(e => {
console.info(e);
}
);
Вот мои файлы манифеста:
API.deployment.yml:
apiVersion: v1
kind: Service
metadata:
name: k8s-api
labels:
app: k8s-api
spec:
type: LoadBalancer
ports:
- port: 8000
name: "api"
targetPort: 8000
selector:
app: k8s-api
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-api-deployment
spec:
replicas: 1
minReadySeconds: 10
selector:
matchLabels:
app: k8s-api
template:
metadata:
labels:
app: k8s-api
yada: booyah
spec:
containers:
- image: k8s-sample-api
name: k8s-api
imagePullPolicy: Never
веб.развертывание.yml:
apiVersion: v1
kind: Service
metadata:
name: k8s-web
labels:
app: k8s-web
spec:
type: LoadBalancer
ports:
- port: 8080
name: "web"
targetPort: 8080
selector:
app: k8s-web
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-web-deployment
spec:
replicas: 1
minReadySeconds: 10
selector:
matchLabels:
app: k8s-web
template:
metadata:
labels:
app: k8s-web
yada: booyah
spec:
containers:
- image: k8s-sample-web
name: k8s-web
imagePullPolicy: Never
Я также попытался объединить их в службе кластеров (с селектором на основе метки yada: booyah), используя кластер.deployment.yml
apiVersion: v1
kind: Service
metadata:
name: server-cluster-ip-service
spec:
type: ClusterIP
selector:
yada: booyah
ports:
- name: "8000"
port: 8000
targetPort: 8000
- name: "8080"
port: 8080
targetPort: 8080
Вот что показывает kubectl get all
:
NAME READY STATUS RESTARTS AGE
pod/k8s-api-deployment-8cf4dcd8c-p7gbz 1/1 Running 0 2m38s
pod/k8s-web-deployment-7cdf999d48-mx76j 1/1 Running 0 4s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/k8s-api LoadBalancer 10.108.64.186 localhost 8000:30825/TCP 2m38s
service/k8s-web LoadBalancer 10.106.86.200 localhost 8080:32391/TCP 4s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 36h
service/server-cluster-ip-service ClusterIP 10.109.42.57 <none> 8000/TCP,8080/TCP 4s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/k8s-api-deployment 1/1 1 1 2m38s
deployment.apps/k8s-web-deployment 1/1 1 0 4s
NAME DESIRED CURRENT READY AGE
replicaset.apps/k8s-api-deployment-8cf4dcd8c 1 1 1 2m38s
replicaset.apps/k8s-web-deployment-7cdf999d48 1 1 1 4s
Какие-либо предложения?
Вы добавили localhost:8000 с внешнего сервера, вместо этого вам следует определить исходные значения службы, которые в вашем случае http://k8s-api:8000
, также для внутреннего подключения используйте ClusterIP.
Кроме того, проверьте, дает ли серверная служба ответ 200, открыв хост-порт.
Более того, вы можете создать сервис DNS, который будет статичным навсегда:
serviceName.namespaceName.svc.cluster.local
вы можете использовать сетевые политики Kubernetes, чтобы ограничить входящий и исходящий трафик определенными модулями/развертываниями. Вы можете обратиться: kubernetes.io/docs/concepts/services-networking/…
Спасибо, использование k8s-api сработало! Однако я по-прежнему могу получить доступ к внутреннему API через Curl с моего хост-терминала MacOS. Как мне изменить свои развертывания, чтобы сделать API недоступным для хоста, но все еще доступным для WEB-модуля?