无法在 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 服务?

如何从 kubernetes pod 连接到本地网络

Kubernetes node.js 容器无法连接到 MongoDB Atlas

无法从 kubernetes pod 内部连接到外部数据库