MySQL kubernetes 中的路由器即服务
MySQL router in kubernetes as a service
我想在 Kubernetes 中部署 MySQL-路由器作为服务。
我的计划..
- 在 k8 中部署 MySQL-router 并使用
LoadBalancer
(MetalLB) 将 MySQL-router 作为服务公开
- k8 中的应用程序 运行 将
mysql-router
服务视为其数据库。
- MySQL-路由器将应用程序数据发送到外部 InnoDB 集群。
我尝试使用以下方式进行部署:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-router
namespace: mysql-router
spec:
replicas: 1
selector:
matchLabels:
app: mysql-router
template:
metadata:
labels:
app: mysql-router
version: v1
spec:
containers:
- name: mysql-router
image: mysql/mysql-router
env:
- name: MYSQL_HOST
value: "192.168.123.130"
- name: MYSQL_PORT
value: "3306"
- name: MYSQL_USER
value: "root"
- name: MYSQL_PASSWORD
value: "root@123"
imagePullPolicy: Always
ports:
- containerPort: 6446
192.168.123.130
是 MySQL 集群主 IP。
apiVersion: v1
kind: Service
metadata:
name: mysql-router-service
namespace: mysql-router
labels:
app: mysql-router
spec:
selector:
app: mysql-router
ports:
- protocol: TCP
port: 6446
type: LoadBalancer
loadBalancerIP: 192.168.123.123
当我检查 mysql-router
容器日志时,我看到类似这样的内容:
Waiting for mysql server 192.168.123.130 (0/12)
Waiting for mysql server 192.168.123.130 (1/12)
Waiting for mysql server 192.168.123.130 (2/12)
....
在部署中设置外部 MySQL 集群信息后,出现以下错误:
Successfully contacted mysql server at 192.168.123.130. Checking for cluster state.
Can not connect to database. Exiting.
如果不指定 MYSQL_HOST
,我无法部署 mysql-router
。我在这里错过了什么?
我的理想部署
当然你必须提供 MySQL 主机。您可以使用在服务中设置的 k8s DNS
来执行此操作。
MySQL 路由器是在您的应用程序和任何后端 MySQL 服务器之间提供透明路由的中间件。它可用于各种用例,例如通过有效地将数据库流量路由到适当的后端 MySQL 服务器来提供高可用性和可扩展性。
例子
在下面的示例中,我使用 dynamic volume provisioning
作为数据,使用 openebs-hostpath
并使用 StatefulSet
作为 MySQL 服务器。
部署
MySQL 路由器:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-router
namespace: mysql-router
spec:
replicas: 1
selector:
matchLabels:
app: mysql-router
template:
metadata:
labels:
app: mysql-router
version: v1
spec:
containers:
- name: mysql-router
image: mysql/mysql-router
env:
- name: MYSQL_HOST
value: "mariadb-galera.galera-cluster"
- name: MYSQL_PORT
value: "3306"
- name: MYSQL_USER
value: "root"
- name: MYSQL_PASSWORD
value: "root@123"
imagePullPolicy: Always
ports:
- containerPort: 3306
MySQL 服务器
apiVersion: apps/v1
kind: StatefulSet
metadata:
namespace: galera-cluster
name: mariadb-galera
spec:
podManagementPolicy: OrderedReady
replicas: 1
selector:
matchLabels:
app: mariadb-galera
serviceName: mariadb-galera
template:
metadata:
labels:
app: mariadb-galera
spec:
restartPolicy: Always
securityContext:
fsGroup: 1001
runAsUser: 1001
containers:
- command:
- bash
- -ec
- |
# Bootstrap from the indicated node
NODE_ID="${MY_POD_NAME#"mariadb-galera-"}"
if [[ "$NODE_ID" -eq "0" ]]; then
export MARIADB_GALERA_CLUSTER_BOOTSTRAP=yes
export MARIADB_GALERA_FORCE_SAFETOBOOTSTRAP=no
fi
exec /opt/bitnami/scripts/mariadb-galera/entrypoint.sh /opt/bitnami/scripts/mariadb-galera/run.sh
env:
- name: MY_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: BITNAMI_DEBUG
value: "false"
- name: MARIADB_GALERA_CLUSTER_NAME
value: galera
- name: MARIADB_GALERA_CLUSTER_ADDRESS
value: gcomm://mariadb-galera.galera-cluster
- name: MARIADB_ROOT_PASSWORD
value: root@123
- name: MARIADB_DATABASE
value: my_database
- name: MARIADB_GALERA_MARIABACKUP_USER
value: mariabackup
- name: MARIADB_GALERA_MARIABACKUP_PASSWORD
value: root@123
- name: MARIADB_ENABLE_LDAP
value: "no"
- name: MARIADB_ENABLE_TLS
value: "no"
image: docker.io/bitnami/mariadb-galera:10.4.13-debian-10-r23
imagePullPolicy: IfNotPresent
livenessProbe:
exec:
command:
- bash
- -ec
- |
exec mysqladmin status -uroot -p$MARIADB_ROOT_PASSWORD
failureThreshold: 3
initialDelaySeconds: 120
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: mariadb-galera
ports:
- containerPort: 3306
name: mysql
protocol: TCP
- containerPort: 4567
name: galera
protocol: TCP
- containerPort: 4568
name: ist
protocol: TCP
- containerPort: 4444
name: sst
protocol: TCP
readinessProbe:
exec:
command:
- bash
- -ec
- |
exec mysqladmin status -uroot -p$MARIADB_ROOT_PASSWORD
failureThreshold: 3
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
volumeMounts:
- mountPath: /opt/bitnami/mariadb/.bootstrap
name: previous-boot
- mountPath: /bitnami/mariadb
name: data
- mountPath: /opt/bitnami/mariadb/conf
name: mariadb-galera-config
volumes:
- emptyDir: {}
name: previous-boot
- configMap:
defaultMode: 420
name: my.cnf
name: mariadb-galera-config
volumeClaimTemplates:
- apiVersion: v1
metadata:
name: data
spec:
storageClassName: openebs-hostpath
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
服务
MySQL 路由器服务
apiVersion: v1
kind: Service
metadata:
name: mysql-router-service
namespace: mysql-router
labels:
app: mysql-router
spec:
selector:
app: mysql-router
ports:
- protocol: TCP
port: 3306
type: LoadBalancer
loadBalancerIP: 192.168.123.123
MySQL 服务
apiVersion: v1
kind: Service
metadata:
namespace: galera-cluster
name: mariadb-galera
labels:
app: mariadb-galera
spec:
type: ClusterIP
ports:
- name: mysql
port: 3306
selector:
app: mariadb-galera
---
apiVersion: v1
kind: Service
metadata:
namespace: galera-cluster
name: mariadb-galera-headless
labels:
app: mariadb-galera
spec:
type: ClusterIP
ports:
- name: galera
port: 4567
- name: ist
port: 4568
- name: sst
port: 4444
selector:
app: mariadb-galera
你需要它从 App1-x 到 Mysql 路由器的 #1 通信和从 MysqlRoutere 到外部 mysql 实例的 #2 VIP/LB。
我们从 Mysql 实例 VIP 的 #2 配置开始。您将需要 service without selector.
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
ports:
- name: mysql
port: 3306
protocol: TCP
targetPort: 3306
sessionAffinity: None
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
name: mysql-service
subsets:
- addresses:
- ip: 192.168.123.130
- ip: 192.168.123.131
- ip: 192.168.123.132
ports:
- name: mysql
port: 3306
protocol: TCP
您不需要 LoadBalancer
因为您只会在集群内部进行连接。因此,请改用 ClusterIp
。
#1 创建Mysql路由器部署。
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-router
namespace: mysql-router
spec:
replicas: 1
selector:
matchLabels:
app: mysql-router
template:
metadata:
labels:
app: mysql-router
version: v1
spec:
containers:
- name: mysql-router
image: mysql/mysql-router
env:
- name: MYSQL_HOST
value: "mysql-service"
- name: MYSQL_PORT
value: "3306"
- name: MYSQL_USER
value: "root"
- name: MYSQL_PASSWORD
value: "root@123"
imagePullPolicy: Always
ports:
- containerPort: 6446
要通过 VIP/ClusterIP 连接到外部 MySQL 实例,请使用 mysql-service
服务,如果部署和服务在同一个命名空间中,请使用 mysql-service
作为主机名或在其中放置一个 CLusterIP
来自 kubectl get service mysql-service
apiVersion: v1
kind: Service
metadata:
name: mysql-router-service
namespace: mysql-router
labels:
app: mysql-router
spec:
selector:
app: mysql-router
ports:
- name: mysql
port: 6446
protocol: TCP
targetPort: 6446
type: ClusterIP
您可以在 kubernetes 集群内连接到同一命名空间中的 mysql-router-service
主机名,在外部命名空间连接到 mysql-router-service.namespace.svc
或在 kubernetes 集群外部使用 NodePort
或 LoadBalancer
.
我想在 Kubernetes 中部署 MySQL-路由器作为服务。
我的计划..
- 在 k8 中部署 MySQL-router 并使用
LoadBalancer
(MetalLB) 将 MySQL-router 作为服务公开
- k8 中的应用程序 运行 将
mysql-router
服务视为其数据库。 - MySQL-路由器将应用程序数据发送到外部 InnoDB 集群。
我尝试使用以下方式进行部署:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-router
namespace: mysql-router
spec:
replicas: 1
selector:
matchLabels:
app: mysql-router
template:
metadata:
labels:
app: mysql-router
version: v1
spec:
containers:
- name: mysql-router
image: mysql/mysql-router
env:
- name: MYSQL_HOST
value: "192.168.123.130"
- name: MYSQL_PORT
value: "3306"
- name: MYSQL_USER
value: "root"
- name: MYSQL_PASSWORD
value: "root@123"
imagePullPolicy: Always
ports:
- containerPort: 6446
192.168.123.130
是 MySQL 集群主 IP。
apiVersion: v1
kind: Service
metadata:
name: mysql-router-service
namespace: mysql-router
labels:
app: mysql-router
spec:
selector:
app: mysql-router
ports:
- protocol: TCP
port: 6446
type: LoadBalancer
loadBalancerIP: 192.168.123.123
当我检查 mysql-router
容器日志时,我看到类似这样的内容:
Waiting for mysql server 192.168.123.130 (0/12)
Waiting for mysql server 192.168.123.130 (1/12)
Waiting for mysql server 192.168.123.130 (2/12)
....
在部署中设置外部 MySQL 集群信息后,出现以下错误:
Successfully contacted mysql server at 192.168.123.130. Checking for cluster state. Can not connect to database. Exiting.
如果不指定 MYSQL_HOST
,我无法部署 mysql-router
。我在这里错过了什么?
我的理想部署
当然你必须提供 MySQL 主机。您可以使用在服务中设置的 k8s DNS
来执行此操作。
MySQL 路由器是在您的应用程序和任何后端 MySQL 服务器之间提供透明路由的中间件。它可用于各种用例,例如通过有效地将数据库流量路由到适当的后端 MySQL 服务器来提供高可用性和可扩展性。
例子
在下面的示例中,我使用 dynamic volume provisioning
作为数据,使用 openebs-hostpath
并使用 StatefulSet
作为 MySQL 服务器。
部署
MySQL 路由器:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-router
namespace: mysql-router
spec:
replicas: 1
selector:
matchLabels:
app: mysql-router
template:
metadata:
labels:
app: mysql-router
version: v1
spec:
containers:
- name: mysql-router
image: mysql/mysql-router
env:
- name: MYSQL_HOST
value: "mariadb-galera.galera-cluster"
- name: MYSQL_PORT
value: "3306"
- name: MYSQL_USER
value: "root"
- name: MYSQL_PASSWORD
value: "root@123"
imagePullPolicy: Always
ports:
- containerPort: 3306
MySQL 服务器
apiVersion: apps/v1
kind: StatefulSet
metadata:
namespace: galera-cluster
name: mariadb-galera
spec:
podManagementPolicy: OrderedReady
replicas: 1
selector:
matchLabels:
app: mariadb-galera
serviceName: mariadb-galera
template:
metadata:
labels:
app: mariadb-galera
spec:
restartPolicy: Always
securityContext:
fsGroup: 1001
runAsUser: 1001
containers:
- command:
- bash
- -ec
- |
# Bootstrap from the indicated node
NODE_ID="${MY_POD_NAME#"mariadb-galera-"}"
if [[ "$NODE_ID" -eq "0" ]]; then
export MARIADB_GALERA_CLUSTER_BOOTSTRAP=yes
export MARIADB_GALERA_FORCE_SAFETOBOOTSTRAP=no
fi
exec /opt/bitnami/scripts/mariadb-galera/entrypoint.sh /opt/bitnami/scripts/mariadb-galera/run.sh
env:
- name: MY_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: BITNAMI_DEBUG
value: "false"
- name: MARIADB_GALERA_CLUSTER_NAME
value: galera
- name: MARIADB_GALERA_CLUSTER_ADDRESS
value: gcomm://mariadb-galera.galera-cluster
- name: MARIADB_ROOT_PASSWORD
value: root@123
- name: MARIADB_DATABASE
value: my_database
- name: MARIADB_GALERA_MARIABACKUP_USER
value: mariabackup
- name: MARIADB_GALERA_MARIABACKUP_PASSWORD
value: root@123
- name: MARIADB_ENABLE_LDAP
value: "no"
- name: MARIADB_ENABLE_TLS
value: "no"
image: docker.io/bitnami/mariadb-galera:10.4.13-debian-10-r23
imagePullPolicy: IfNotPresent
livenessProbe:
exec:
command:
- bash
- -ec
- |
exec mysqladmin status -uroot -p$MARIADB_ROOT_PASSWORD
failureThreshold: 3
initialDelaySeconds: 120
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: mariadb-galera
ports:
- containerPort: 3306
name: mysql
protocol: TCP
- containerPort: 4567
name: galera
protocol: TCP
- containerPort: 4568
name: ist
protocol: TCP
- containerPort: 4444
name: sst
protocol: TCP
readinessProbe:
exec:
command:
- bash
- -ec
- |
exec mysqladmin status -uroot -p$MARIADB_ROOT_PASSWORD
failureThreshold: 3
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
volumeMounts:
- mountPath: /opt/bitnami/mariadb/.bootstrap
name: previous-boot
- mountPath: /bitnami/mariadb
name: data
- mountPath: /opt/bitnami/mariadb/conf
name: mariadb-galera-config
volumes:
- emptyDir: {}
name: previous-boot
- configMap:
defaultMode: 420
name: my.cnf
name: mariadb-galera-config
volumeClaimTemplates:
- apiVersion: v1
metadata:
name: data
spec:
storageClassName: openebs-hostpath
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
服务
MySQL 路由器服务
apiVersion: v1
kind: Service
metadata:
name: mysql-router-service
namespace: mysql-router
labels:
app: mysql-router
spec:
selector:
app: mysql-router
ports:
- protocol: TCP
port: 3306
type: LoadBalancer
loadBalancerIP: 192.168.123.123
MySQL 服务
apiVersion: v1
kind: Service
metadata:
namespace: galera-cluster
name: mariadb-galera
labels:
app: mariadb-galera
spec:
type: ClusterIP
ports:
- name: mysql
port: 3306
selector:
app: mariadb-galera
---
apiVersion: v1
kind: Service
metadata:
namespace: galera-cluster
name: mariadb-galera-headless
labels:
app: mariadb-galera
spec:
type: ClusterIP
ports:
- name: galera
port: 4567
- name: ist
port: 4568
- name: sst
port: 4444
selector:
app: mariadb-galera
你需要它从 App1-x 到 Mysql 路由器的 #1 通信和从 MysqlRoutere 到外部 mysql 实例的 #2 VIP/LB。
我们从 Mysql 实例 VIP 的 #2 配置开始。您将需要 service without selector.
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
ports:
- name: mysql
port: 3306
protocol: TCP
targetPort: 3306
sessionAffinity: None
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
name: mysql-service
subsets:
- addresses:
- ip: 192.168.123.130
- ip: 192.168.123.131
- ip: 192.168.123.132
ports:
- name: mysql
port: 3306
protocol: TCP
您不需要 LoadBalancer
因为您只会在集群内部进行连接。因此,请改用 ClusterIp
。
#1 创建Mysql路由器部署。
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-router
namespace: mysql-router
spec:
replicas: 1
selector:
matchLabels:
app: mysql-router
template:
metadata:
labels:
app: mysql-router
version: v1
spec:
containers:
- name: mysql-router
image: mysql/mysql-router
env:
- name: MYSQL_HOST
value: "mysql-service"
- name: MYSQL_PORT
value: "3306"
- name: MYSQL_USER
value: "root"
- name: MYSQL_PASSWORD
value: "root@123"
imagePullPolicy: Always
ports:
- containerPort: 6446
要通过 VIP/ClusterIP 连接到外部 MySQL 实例,请使用 mysql-service
服务,如果部署和服务在同一个命名空间中,请使用 mysql-service
作为主机名或在其中放置一个 CLusterIP
来自 kubectl get service mysql-service
apiVersion: v1
kind: Service
metadata:
name: mysql-router-service
namespace: mysql-router
labels:
app: mysql-router
spec:
selector:
app: mysql-router
ports:
- name: mysql
port: 6446
protocol: TCP
targetPort: 6446
type: ClusterIP
您可以在 kubernetes 集群内连接到同一命名空间中的 mysql-router-service
主机名,在外部命名空间连接到 mysql-router-service.namespace.svc
或在 kubernetes 集群外部使用 NodePort
或 LoadBalancer
.