简体   繁体   English

无法通过 Kubernetes 集群中的主机名连接到 MariaDB

[英]Can't connect to MariaDB by hostname within a Kubernetes cluster

If I set up MariaDB form the official image within a Docker Compose configuration, I can access it by its host name - for example if in a bash shell within the MariaDB container:如果我在 Docker Compose 配置中从官方镜像中设置 MariaDB,我可以通过它的主机名访问它 - 例如,如果在 MariaDB 容器内的 bash shell 中:

# host db
db has address 172.21.0.2


# curl telnet://db:3306
Warning: Binary output can mess up your terminal. Use "--output -" to tell 
Warning: curl to output it to your terminal anyway, or consider "--output 
Warning: <FILE>" to save to a file.
  • no connection refused issue here这里没有连接被拒绝的问题

But if have MariaDB deployed from the official image within a Kubernetes cluster (tried both MicroK8s and GKE), I can connect to it via localhost but not by its host name:但是,如果从 Kubernetes 集群中的官方镜像部署了 MariaDB(尝试了 MicroK8s 和 GKE),我可以通过localhost连接到它,但不能通过主机名连接到它:

# host db
db.my-namspace.svc.cluster.local has address 10.152.183.124

# curl telnet://db:3306
curl: (7) Failed to connect to db port 3306: Connection refused

# curl telnet://localhost:3306
Warning: Binary output can mess up your terminal. Use "--output -" to tell 
Warning: curl to output it to your terminal anyway, or consider "--output 
Warning: <FILE>" to save to a file.
  • connection is refused for the service host name, but localhost responds服务主机名的连接被拒绝,但本地主机响应

I've tried to replace the included my.cnf with a simplified version like:我试图用简化版本替换包含的my.cnf ,例如:

[mysqld]
skip-grant-tables
skip-networking=0
#### Unix socket settings (making localhost work)
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock

#### TCP Socket settings (making all remote logins work)
port         = 3306
bind-address = *
  • with no luck没有运气

The MariaDB Kubernetes deployment is like: MariaDB Kubernetes 部署如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: db
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      name: db
  template:
    metadata:
      labels:
        name: db
    spec:
      containers:
      - env:
        - name: MYSQL_PASSWORD
          value: template
        - name: MYSQL_ROOT_PASSWORD
          value: root
        - name: MYSQL_USER
          value: template
        image: mariadb:10.4
        name: db
        ports:
        - containerPort: 3306
        resources: {}
        volumeMounts:
        - mountPath: /var/lib/mysql
          name: dbdata
      restartPolicy: Always
      volumes:
      - name: dbdata
        persistentVolumeClaim:
          claimName: dbdata
status: {}

and the corresponding Persistent Volume Claim:和相应的持久卷声明:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    io.kompose.service: dbdata
  name: dbdata
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi
status: {}

It baffles me that the same configuration works with Docker Compose but not within a Kubernetes cluster.令我感到困惑的是,相同的配置适用于 Docker Compose,但不适用于 Kubernetes 集群。

Any ideas what may be going on?任何想法可能会发生什么?

Update 2020-03-18 I forgot to include the service declaration for the database and add it here: 2020 年 3 月 18 日更新我忘记包含数据库的服务声明并在此处添加:

apiVersion: v1
kind: Service
metadata:
  labels:
    app: db
  name: db
spec:
  ports:
  - name: "3306"
    port: 3306
    targetPort: 3306
  selector:
    app: db
    name: db
  type: ClusterIP
status:
  loadBalancer: {}

...am including both app and name for the spec.selector - am used to having only name but @Al-waleed Shihadeh's example includes app so I'll include that also, just in case - but without success. ...我包括了spec.selector appname - 我习惯于只有name但@Al-waleed Shihadeh 的示例包括app所以我也会包括它,以防万一 - 但没有成功。

Here are outputs from a couple of kubectl listing commands:以下是几个 kubectl 列表命令的输出:

$ sudo microk8s.kubectl get svc db -n my-namespace
NAME   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
db     ClusterIP   10.152.183.246   <none>        3306/TCP   35m
$ sudo microk8s.kubectl get pods -owide -n my-namespace
NAME                           READY   STATUS             RESTARTS   AGE   IP            NODE          NOMINATED NODE   READINESS GATES
db-77cbcf87b6-l44lm            1/1     Running            0          34m   10.1.48.118   microk8s-vm   <none>           <none>

Solution Comparing the service declaration posted by KoopaKiller, which proved to work, I finally noticed that setting the protocol attribute to "TCP" in the ports declaration was missing - this part:解决方案比较了 KoopaKiller 发布的服务声明,它被证明是有效的,我终于注意到在端口声明中将protocol属性设置为“TCP”是缺失的——这部分:

spec:
  ports:
  - protocol: TCP
...

Since you are using Kubernetes Deployment, the name of your pods will be generated dinamically based on the name you gave in spec file, in your example, the pods will be create with the name db-xxxxxxxxxx-xxxxx .由于您使用的是 Kubernetes 部署,因此您的 pod 的名称将根据您在规范文件中提供的名称动态生成,在您的示例中,将使用名称db-xxxxxxxxxx-xxxxx创建 pod。

In order to make a 'fixed' hostname, you need to create a service for reach your pods, example:为了创建“固定”主机名,您需要创建一个服务来访问您的 pod,例如:

apiVersion: v1
kind: Service
metadata:
  name: db
spec:
  selector:
    name: db
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306
  type: ClusterIP

And to check if was successfully deployed:并检查是否已成功部署:

$ kubectl get svc db
NAME   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
db     ClusterIP   10.96.218.18   <none>        3306/TCP   89s

The fullname of your service will be: <name>.<namespace>.cluster.local in this case using default namespace will be db.default.cluster.local pointing to ip 10.96.218.18 as showed in example above.您的服务的全名将是: <name>.<namespace>.cluster.local在这种情况下,使用default命名空间将是db.default.cluster.local指向 ip 10.96.218.18如上例所示。

To reach your service you need to configure your /etc/hosts with his information:要获得您的服务,您需要使用他的信息配置您的 /etc/hosts:

echo -ne "10.96.218.18\tdb.default.cluster.local db db.default" >> /etc/hosts

After that you will be able to reach your service by dns:之后,您将能够通过 dns 访问您的服务:

$ dig +short db
10.96.218.18

$ mysql -h db -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 5.5.5-10.4.12-MariaDB-1:10.4.12+maria~bionic mariadb.org binary distribution

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

Just for you know, you could also use HELM template to setup a mariadb with replication.众所周知,您还可以使用 HELM 模板来设置带有复制功能的 mariadb。 See this article看这篇文章

References:参考:

https://kubernetes.io/docs/concepts/services-networking/service/ https://kubernetes.io/docs/concepts/services-networking/service/

https://kubernetes.io/docs/concepts/workloads/controllers/deployment/ https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

to be able to access the service from the host node you need to define a service object in Kubernetes为了能够从主机节点访问服务,您需要在 Kubernetes 中定义一个服务对象

so the complete k8s objects should look like the below snippet PersistentVolumeClaim所以完整的 k8s 对象应该看起来像下面的代码片段 PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  creationTimestamp: null
  labels:
    io.kompose.service: db-data
  name: db-data
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi
status: {}

Service服务

apiVersion: v1
kind: Service
metadata:
  labels:
    app: mysql
  name: mysql
spec:
  ports:
  - port: 3306
    targetPort: 3306
  selector:
    app: mysql
  type: ClusterIP

Deployment部署

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: mysql
  name: mysql
spec:
  replicas: 1
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: dummy
        - name: MYSQL_DATABASE
          value: community_db
        resources: {}
        volumeMounts:
          - mountPath: /var/lib/mysql
            name: db-data
        image: mysql:5.7
        ports:
        - containerPort: 3306
      volumes:
      - name: db-data
        persistentVolumeClaim:
          claimName: db-data
      restartPolicy: Always

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM