У меня загрузочное приложение Java Spring, развернутое на локальном кластере Minikube, работающем на моем компьютере.
Приложение Java подключается к базе данных mysql и принимает конфигурацию во время выполнения, используя конфигурацию источника данных.Это класс конфигурации БД:
public class DatasourceConfig {
@Bean
@Primary
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(System.getProperty("mysql_user"));
dataSource.setUsername(System.getProperty("mysql_user"));
dataSource.setPassword(System.getProperty("mysql_pass"));
return dataSource;
}
}
Я передаю значения для mysql_url
, mysql_pass
, mysql_user
во время выполнения, как это (из Dockerfile
):
ENTRYPOINT java -Dmysql_url=$mysql_url \
-Dmysql_user=$mysql_user \
-Dmysql_pass=$mysql_pass \
-jar myapp.jar
Я создал другой модуль pod / развертывание для локального образа контейнера MySQL и открыл его через службу локально.
Это файл mysql.yml
для kubernetes:
apiVersion: v1
kind: Service
metadata:
name: mysql-svc
labels:
app: mysql
spec:
ports:
- port: 3306
nodePort: 30306
targetPort: mysql-port
protocol: TCP
selector:
app: mysql
type: NodePort
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
labels:
app: mysql
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-deployment
labels:
app: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
tier: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
tier: mysql
spec:
containers:
- name: mysql
image: mysql
imagePullPolicy: Never
ports:
- name: mysql-port
containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: pass
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
Итак, теперьУ меня есть две из них: pods + deploy + services, работающие на Minikube, одна для моего приложения и другая для контейнера mysql: (ниже вывод kubectl get all
NAME READY STATUS RESTARTS AGE
pod/mysql-deployment-8464d4875d-jlszz 1/1 Running 0 168m
pod/myapp-deployment-6469d8554b-4sbhz 1/1 Running 0 38m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d
service/mysql-svc NodePort 10.105.186.178 <none> 3306:30306/TCP 168m
service/myapp-svc NodePort 10.96.243.6 <none> 8080:31001/TCP 41m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mysql-deployment 1/1 1 1 168m
deployment.apps/myapp-deployment 1/1 1 1 41m
NAME DESIRED CURRENT READY AGE
replicaset.apps/mysql-deployment-8464d4875d 1 1 1 168m
replicaset.apps/myapp-deployment-6469d8554b 1 1 1 41m
Я могу правильно запустить приложение java с хостамашина, выполнив это:
minikube service myapp-svc
, и я также могу подключиться к Mysql с хост-машины, выполнив это:
run minikube service mysql-svc --url
, что дает мне: http://<mysql-ip>:30306
и затем я могу подключиться к нему следующим образом (с хост-компьютера):
mysql -h <mysql-ip> -P 30306 -u root -p
.
Это правильно соединяет меня с MySQL, работающим налокальный кластер kubernetes через Minikube.
Я даже могу подключиться к службе MySQL изнутри JAVконтейнер, работающий на миникубе:
сначала я подключаюсь к java-модулю следующим образом:
kubectl exec -it myapp-deployment-6469d8554b-4sbhz /bin/bash
, а затем запускаю mysql -h <mysql-ip> -P 30306 -u root -p
внутри модуля.Это также правильно связывает меня с mysql, работающим внутри другого модуля.
Единственная проблема заключается в следующем:
Изнутри модуля Java при проверке журналов приложений, Я вижу это:
ОШИБКА 1 --- [main] com.zaxxer.hikari.pool.HikariPool: HikariPool-1 - исключение при инициализации пула.
com.mysql.cj.jdbc.exceptions.CommunicationsException: сбой линии связи
Последний пакет, успешно отправленный на сервер, был 0 миллисекунд назад.Драйвер не получил никаких пакетов от сервера.
, а также, когда я пытаюсь вызвать любой из API, в котором есть операции с базой данных, я получаю следующую ошибку: Unable to acquire JDBC Connection; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
Это означает, что мой код Java фактически не может подключиться к MySql, развернутому на другом модуле.
Я проверил, что модуль Java успешно может подключиться к модулю Mysql, тогда почемумой Java-код не может подключиться ??
Я даже подтвердил, что могу запускать Java-образ Docker локально, передавая URL-адрес mysql модуля, развернутого в minikube, следующим образом:
docker run -e mysql_url=jdbc:mysql://<mysql-ip>:<mysql-port>/my_db \
-e mysql_user=root \
-e mysql_pass=pass \
--rm -p 8081:8080 --name myApp -it me/myapp
Это подтверждает, что мой Java-код правильно настроен для подключения к MySQL (даже тот, который развернут на модуле), когда я запускаю его локально.
Итак, мне кажется, что в основном все настроено правильно..
- Сам модуль mysql работает правильно, что я проверил, сначала подключившись к нему с помощью локального клиента mysql.
- Java code iможет подключиться к MySQL, запущенному на Minikube, когда я запускаю образ Docker локально.
- Модуль Java на Minikube может подключаться к модулю mysql, что я проверил, подключившись к модулю mysql из модуля java с помощью клиента mysql из bash.
- Код Java такжевыполняется (без подключения к базе данных).
Единственное, что не работает, - это то, что приложение Java, развернутое внутри Minikube, не может подключиться к mysql, развернутому в другом модуле.
Для этого единственная точка отказа, о которой я могу думать, - это способ, которым Kubernetes передает переменные ENV в образ докера во время его запуска. Но я даже подтвердил это, запустив env
внутриBash работает на моем модуле Java.который показал, что все необходимые переменные среды установлены там правильно.
Это мой файл развертывания для Java:
myapp.deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: me/myapp
imagePullPolicy: Never
env:
- name: mysql_url
value: jdbc:mysql://<mysql-ip>:30306/my_db
- name: mysql_user
value: root
- name: mysql_pass
value: pass
ports:
- name: java-port
containerPort: 8080
Должен ли я также определить определение модуля и предоставить там переменные ENV?
Есть ли здесь что-то еще, что мне нужно сделать?
Как я могу это исправить?
PS : я уже запустил eval $(minikube docker-env)
в моем текущем окне терминала, чтобы локальные образы док-станции были доступны для Minikube.