#postgresql #tomcat #kubernetes #kubernetes-service
#postgresql #tomcat #kubernetes #kubernetes-service
Вопрос:
В моем кластере K8 у меня есть два развертывания в одном пространстве имен. Одно развертывание предназначено для базы данных-Postgres, а другое — для Tomcat. Tomcat должен быть доступен извне, поэтому я настроил службу «NodePort», а для внутренней связи я создал службу «ClusterIP», предоставив порт Postgres (т.е. 5432). Как только все будет развернуто, я хочу, чтобы модуль Tomcat взаимодействовал с модулем Postgres. Но когда я «curl postgres-service: 5432» из модуля Tomcat, я получаю сообщение «отказано в подключении». Есть ли какие-либо неправильные настройки?
apiVersion: v1
kind: Service
metadata:
name: tomcat-service
namespace: application
labels:
app: application-tomcat
spec:
type: NodePort
ports:
- name: tomcat-port
targetPort: 80
port: 80
selector:
app: application-tomcat
---
apiVersion: v1
kind: Service
metadata:
name: postgres-service
namespace: application
labels:
app: application-postgres
spec:
ports:
- port: 5432
name: postgres-port
selector:
app: application-postgres
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: application-tomcat-deployment
namespace: application
labels:
app: application-tomcat
spec:
replicas: 1
selector:
matchLabels:
app: application-tomcat
template:
metadata:
labels:
app: application-tomcat
spec:
containers:
- name: application-container
image: tomcat
command:
- sleep
- "infinity"
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: application
name: application-postgres-deployment
labels:
app: application-postgres
spec:
replicas: 1
selector:
matchLabels:
app: application-postgres
template:
metadata:
labels:
app: application-postgres
spec:
containers:
- name: postgres
image: postgres
command:
- sleep
- "infinity"
ports:
- containerPort: 5432
name: postgredb
Модуль Postgres прослушивает порт ‘5432’, и база данных запущена.
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:5432 0.0.0.0:* LISTEN -
tcp6 0 0 :::5432 :::* LISTEN -
Ресурсы в пространстве имен
$ kubectl get all -n application
NAME READY STATUS RESTARTS AGE
pod/application-postgres-deployment-694869cd5d-wrhzr 1/1 Running 0 9m9s
pod/application-tomcat-deployment-6db75ffb6d-ds8fr 1/1 Running 0 9m9s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/postgres-service ClusterIP 10.32.0.207 <none> 5432/TCP 9m9s
service/tomcat-service NodePort 10.32.0.59 <none> 80:31216/TCP 9m9s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/application-postgres-deployment 1/1 1 1 9m9s
deployment.apps/application-tomcat-deployment 1/1 1 1 9m9s
NAME DESIRED CURRENT READY AGE
replicaset.apps/application-postgres-deployment-694869cd5d 1 1 1 9m9s
replicaset.apps/application-tomcat-deployment-6db75ffb6d 1 1 1 9m9s
Комментарии:
1. Вам не нужно создавать
Service
типClusterIP
of вручную / явно. СлужбаNodePort
создает службу внутриClusterIP
, которая может использоваться для внутренней связи.2. Я опустил службу типа ClusterIP, но тогда она создаст только службу NodePort. Итак, как я могу указать имя хоста в Tomcat для связи с модулем Postgres? Тогда какое имя я должен использовать для «curl» из модуля Tomcat?
3. вы можете получить доступ к модулям, используя имя службы как
curl http:servicename/
4. пожалуйста, отредактируйте вопрос, чтобы добавить туда подробности.
5. Почему ваши контейнеры запускаются
command: [sleep, infinity]
? Это определенно приведет к ошибке «отказано в подключении», поскольку процессы базы данных и веб-сервера фактически не выполняются.
Ответ №1:
Вы переопределили значение по умолчанию ENTRYPOINT
в образе postgresql, указав deployment.spec.template.containers[0].command
. Итак, теперь единственный процесс, который выполняется внутри модуля развертывания nginx-statefulset
sleep infinity
, — это postgres, и он не запущен. Удаление командного поля и добавление POSTGRES_PASSWORD
POSTGRES_HOST_AUTH_METHOD=trust
переменной среды или должно устранить проблему. Используйте следующий манифест для nginx-statefulset
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-statefulset
namespace: nginx
spec:
replicas: 1
selector:
matchLabels:
BIZID: nginx
template:
metadata:
labels:
BIZID: nginx
spec:
containers:
- name: postgres
image: postgres
env:
- name: POSTGRES_PASSWORD
value: admin
ports:
- containerPort: 5432
name: postgredb
Вы должны установить переменную env POSTGRES_PASSWORD
или POSTGRES_HOST_AUTH_METHOD=trust
. Без этого модуль завершит цикл сбоя со следующим сообщением об ошибке:
Error: Database is uninitialized and superuser password is not specified.
You must specify POSTGRES_PASSWORD to a non-empty value for the
superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run".
You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all
connections without a password. This is *not* recommended.
See PostgreSQL documentation about "trust":
https://www.postgresql.org/docs/current/auth-trust.html
Комментарии:
1. Я обновил вопрос. Не могли бы вы проверить еще раз?
2. Интересно. Я попытался использовать ваш манифест локально в своем кластере kind и заметил, что postgres не запущен. Где работает ваш кластер k8s? Можете ли вы поделиться командой, которую вы выполнили для вывода открытых подключений?
3. Я использую вычислительные механизмы GCP и установил там K8. Я использовал команду «netstat -tulpn» и для проверки запущенного процесса использовал «ps aux»
4. Служба состоит из 2 компонентов: запись dns, которая сопоставляет запрос postgres-service с IP-адресом кластера (в вашем случае 10.32.0.207), правила iptables на узле k8s, которые перехватывают трафик на ip-адрес кластера и выполняют dnat с фактическими IP-адресами pod. Вместо того, чтобы выполнять «curl postgres-service: 5432», попробуйте выполнить curl для фактического IP-адреса модуля postgres.
5. Я смог заставить это работать. Установленный пакет «ebtables» и загруженный модуль ядра — modprobe br_netfilter»
Ответ №2:
Глядя на ваши yamls, кажется, что ваше развертывание tomcat находится в пространстве имен с именем «test», тогда как ваше развертывание postgres находится в пространстве имен «по умолчанию».
Итак, чтобы обеспечить взаимодействие между пространствами имен, вам нужно будет добавить пространство имен к домену службы. Этот модуль — если он выполняется из модуля tomcat — должен работать:
curl http://postgres-service.default:5432
В качестве альтернативы просто разверните tomcat в пространство имен «по умолчанию».
Комментарии:
1. Но они находятся в одном пространстве имен
2. Если вы все еще используете те же yamls, которые вы опубликовали, tomcat развертывается в «тестовом» пространстве имен, а postgres — в пространстве имен по умолчанию. Если нет, то, пожалуйста, соответствующим образом обновите вопрос.
3. да, я пропустил пространство имен. Но когда я применяю файл Yaml, я явно использую команду —namespace . «kubectl create -f data.yml -n тест»
4. Таким образом, все они находятся в одном пространстве имен. Я отредактирую вопрос
5. К вашему СВЕДЕНИЮ: если я попытаюсь перезаписать пространство имен, определенное в yaml, с помощью kubectl, я получаю сообщение об ошибке «пространство имен не соответствует». Это связано с kubectl 1.20.