在 kubernetes 中联系服务

Contacting service in kubernetes

我以为我了解 kubernetes 服务是如何工作的,并且一直认为它们是一种将多个 pods“分组”的方式,以使其能够联系服务而不是单个 [=45] =].但是,看来我错了。我创建了一个 mysql 部署(只有一个 pod)和一个服务,以便在我想使用来自其他 pods(其他微服务)的 mysql 连接时访问该服务。这是我做的服务:

apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    run: mysql
spec:
  ports:
  - port: 3306
    targetPort: 3306
    protocol: TCP
  selector:
    run: mysql

我希望这能让我通过到达 <clusterIp>:<targetPort> 连接到 mysql pod,但是每当我尝试连接时连接都被拒绝。我尝试在线阅读,最初认为 nodeport 服务类型是个好主意,但 kubernetes 网站告诉我该服务比 <NodeIP>:<NodePort> 更可达,所以这让我感到困惑。 MySQL 只能在集群内被其他节点访问。我怎样才能做到这一点?

备注:
service = api.read_namespaced_service(name="mysql", namespace="default")

mydb = mysql.connector.connect(host=service.spec.cluster_ip, user="root",
                                 password="password", database="db_name",
                                 auth_plugin='mysql_native_password')

这是我得到的错误:

Traceback (most recent call last):
  File "/init/db_init.py", line 10, in <module>
    mydb = mysql.connector.connect(host=service.spec.cluster_ip, user="root",
  File "/usr/local/lib/python3.9/site-packages/mysql/connector/__init__.py", line 272, in connect
    return CMySQLConnection(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/mysql/connector/connection_cext.py", line 85, in __init__
    self.connect(**kwargs)
  File "/usr/local/lib/python3.9/site-packages/mysql/connector/abstracts.py", line 1028, in connect
    self._open_connection()
  File "/usr/local/lib/python3.9/site-packages/mysql/connector/connection_cext.py", line 241, in _open_connection
    raise errors.get_mysql_exception(msg=exc.msg, errno=exc.errno,
mysql.connector.errors.DatabaseError: 2003 (HY000): Can't connect to MySQL server on '10.107.203.112:3306' (111)

更新

根据要求,这是 mysql pod 的完整日志:

2022-01-27 17:57:14+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.28-1debian10 started.
2022-01-27 17:57:15+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2022-01-27 17:57:15+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.28-1debian10 started.
2022-01-27 17:57:15+00:00 [Note] [Entrypoint]: Initializing database files
2022-01-27T17:57:15.090697Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.28) initializing of server in progress as process 43
2022-01-27T17:57:15.105399Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2022-01-27T17:57:16.522380Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2022-01-27T17:57:20.805814Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
2022-01-27 17:57:29+00:00 [Note] [Entrypoint]: Database files initialized
2022-01-27 17:57:29+00:00 [Note] [Entrypoint]: Starting temporary server
2022-01-27T17:57:29.868217Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.28) starting as process 92
2022-01-27T17:57:29.892649Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2022-01-27T17:57:30.100941Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2022-01-27T17:57:30.398700Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2022-01-27T17:57:30.398743Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2022-01-27T17:57:30.419293Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2022-01-27T17:57:30.430833Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: /var/run/mysqld/mysqlx.sock
2022-01-27T17:57:30.430879Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.28'  socket: '/var/run/mysqld/mysqld.sock'  port: 0  MySQL Community Server - GPL.
2022-01-27 17:57:30+00:00 [Note] [Entrypoint]: Temporary server started.
Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
2022-01-27 17:57:32+00:00 [Note] [Entrypoint]: Creating database football

2022-01-27 17:57:32+00:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/SQL.sql


2022-01-27 17:57:33+00:00 [Note] [Entrypoint]: Stopping temporary server
2022-01-27T17:57:33.143178Z 12 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.0.28).
2022-01-27T17:57:36.222404Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.28)  MySQL Community Server - GPL.
2022-01-27 17:57:37+00:00 [Note] [Entrypoint]: Temporary server stopped

2022-01-27 17:57:37+00:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up.

2022-01-27T17:57:37.329690Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.28) starting as process 1
2022-01-27T17:57:37.336444Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2022-01-27T17:57:37.525143Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2022-01-27T17:57:37.738175Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2022-01-27T17:57:37.738216Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2022-01-27T17:57:37.745722Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2022-01-27T17:57:37.757638Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
2022-01-27T17:57:37.757679Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.28'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.

此外,这是我使用的部署:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: repo/football-mysql
        name: mysql
        env:
          # Use secret in real usage
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim

Service 和 Pod 之间存在标签不匹配:

# service
spec:
  selector:
    run: mysql  # <- this

# deployment
spec:
  template:
    metadata:
      labels:
        app: mysql  # <- and this

因此,Service 的目标是其他 Pod,而不是 Deployment 创建的 Pod。换句话说,该服务查找 Pods 且 run 标签值等于 mysql,而您的 MySQL Pod 具有 app 标签且 mysql在里面。

要使其工作,至少一对标签必须在服务和 Pod 的两侧完全相等。在这种情况下,将 run 替换为 app 应该就足够了:

apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    run: mysql  # changing here isn't mandatory, up to you
spec:
  ports:
  - port: 3306
    targetPort: 3306
    protocol: TCP
  selector:
    app: mysql  # here is the required change