无法在 Kubernetes 中从工作连接到服务
Posted
技术标签:
【中文标题】无法在 Kubernetes 中从工作连接到服务【英文标题】:Can't connect from job to service in kubernetes 【发布时间】:2021-11-07 14:27:28 【问题描述】:我正在尝试为 dotnet 实体框架设置数据库迁移作业。 似乎我无法从 kubernetes 作业连接到 mysql 数据库服务,但是当我转发端口时,我可以从桌面连接。
这是我工作的 MySql 部署 + 服务:
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
targetPort: 3306
selector:
app: mysql
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:8.0
name: mysql
env:
- name: MYSQL_DATABASE
value: myDatabase
- name: MYSQL_USER
value: myUser
- name: MYSQL_PASSWORD
value: myPassword
- name: MYSQL_ROOT_PASSWORD
value: myRootPassword
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
为简洁起见,我不会粘贴持久性卷声明。
这很有效,因为我可以在我这样做之后从我的桌面连接到 mysql:
kubectl port-forward deployment/mysql 3306:3306
并通过 MySQL Workbench 连接。
我不能做的是从使用 Dockerfile 的作业中运行迁移,该作业具有带有 dbContext 的 C# 数据库项目,以便运行 db 迁移。
工作:
apiVersion: batch/v1
kind: Job
metadata:
name: candles-downloader-db-migration
spec:
backoffLimit: 0
template:
spec:
containers:
- name: candles-service-migration
image: migration
imagePullPolicy: Never
env:
- name: CONNECTION_STRING
value: server=mysql.default.svc.cluster.local:3306;uid=myUser;pwd=myPassword;database=myDatabase
restartPolicy: Never
如您所见,我通过环境变量 CONNECTION_STRING 传递连接字符串
然后是作业的 Dockerfile:
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env
RUN dotnet tool install --global dotnet-ef --version 5.0.9
ENV PATH $PATH:/root/.dotnet/tools
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj .
RUN dotnet restore
# Copy everything else and build
COPY ./ .
ENTRYPOINT dotnet ef database update -v --connection $CONNECTION_STRING
我在我的 minikube 集群上构建了映像。 作业开始时,dockerfile 容器获取连接字符串。对于调试,我使用 -v 标志来进行详细输出。
这是失败作业的输出(为简洁起见,不重要的部分被截断):kubectl logs candles-downloader-db-migration-gqndm
Finding IDesignTimeServices implementations in assembly 'Infrastructure.Persistence.Sql'...
No design-time services were found.
Migrating using database 'myDatabase' on server 'mysql.default.svc.cluster.local:3306'.
'CandlesServiceDbContext' disposed.
System.InvalidOperationException: An exception has been raised that is likely due to a transient failure. Consider enabling transient error resiliency by adding 'EnableRetryOnFailure()' to the 'UseMySql' call.
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Unable to connect to any of the specified MySQL hosts.
我怀疑连接字符串有问题。
我用server=mysql.default.svc.cluster.local:3306;uid=myUser;pwd=myPassword;database=myDatabase
但我也尝试过使用不同的服务器值:
mysql.default.svc.cluster.local:3306
mysql.default.cluster.local:3306
mysql.svc.cluster.local:3306
mysql:3306
甚至是我的mysql服务的本地集群IP10.97.213.180:3306
它们都不起作用。我总是在作业日志中收到此错误:
无法连接到任何指定的 MySQL 主机。
我在不同 pod 上的作业/容器是否应该通过 kubernetes 服务看到其他 pod 上的 mysql 服务器?我是这么想的,但它看起来像“隐形”。
【问题讨论】:
创建一个 busybox pod 并尝试使用 pod 中的这些服务名称 ping。这应该给你正确的价值。服务的全名可以根据job和mysql所在的命名空间而改变。 【参考方案1】:我在阅读 kubernetes 文档后想通了: https://kubernetes.io/docs/tasks/administer-cluster/dns-debugging-resolution/
我已使用以下命令安装了 DNS 实用程序:
kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
然后我可以测试我的“mysql”服务是否可以通过名称发现:
kubectl exec -i -t dnsutils -- nslookup mysql
确实如此。输出是:
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: mysql.default.svc.cluster.local
Address: 10.97.213.180
但是在使用端口指定名称后,它失败了:
kubectl exec -i -t dnsutils -- nslookup mysql:3306
Server: 10.96.0.10
Address: 10.96.0.10#53
** server can't find mysql:3306: NXDOMAIN
command terminated with exit code 1
正如我所料,错误出在连接字符串中。 我不得不改变
server=mysql:3306; ...
到
server=mysql;port=3306; ...
我的迁移在工作中运行。
【讨论】:
以上是关于无法在 Kubernetes 中从工作连接到服务的主要内容,如果未能解决你的问题,请参考以下文章
Kubernetes - 无法从服务的 pod 连接到服务 IP
无法通过 Spring Boot 将 Docker Desktop Kubernetes (Windows) 服务连接到本地 Postgres db
如何在 Docker 中从 Docker 连接到 SQL Server 服务?