[英]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.
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.
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 = *
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
app
和name
- 我习惯于只有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.