k8s 如何使用 ClusterIP + ingress 从集群外部访问内部的 mysql?
我搭建了一个 minikube 环境
pod 和 service、ingress 的声明如下:
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/data/mysql-data" # Change this path to your desired host path
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql8
spec:
replicas: 1
selector:
matchLabels:
app: mysql8
template:
metadata:
labels:
app: mysql8
spec:
containers:
- name: mysql8
image: mysql:8.0.34
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
- name: custom-config
mountPath: /etc/mysql/conf.d
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "250m"
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
- name: custom-config
configMap:
name: mysql-custom-config # Create a ConfigMap with your custom configuration
---
apiVersion: v1
kind: Service
metadata:
name: mysql8-service
spec:
selector:
app: mysql8
ports:
- protocol: TCP
port: 3306
targetPort: 3306
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mysql8-ingress
spec:
rules:
- host: mysql.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: mysql8-service
port:
number: 3306
然后应用他们
minikube kubectl -- apply -f application/stateful/mysql.yaml
查看 pod 状态正常
─➤ minikube kubectl get pods 130 ↵
NAME READY STATUS RESTARTS AGE
mysql8-5db94fb5d5-22nhc 1/1 Running 2 (3d16h ago) 53d
查看 services 状态正常
╰─➤ minikube kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 53d
mysql8-service ClusterIP 10.110.118.91 <none> 3306/TCP 53d
查看 ingress 状态正常
─➤ minikube kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
mysql8-ingress <none> mysql.example.com 80 33m
修改本地的 /etc/hosts
╰─➤ cat /etc/hosts 1 ↵
127.0.0.1 localhost
127.0.1.1 vobiler740
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.49.2 mysql.example.com
我的 minikube 的 ip 就是 192.168.49.2
╭─pon@T4GPU ~/code/me/k8s-console ‹master*› ╰─➤ minikube ip 192.168.49.2
然后从宿主机访问, 但是连接失败
╰─➤ mycli -uroot -p123456 -hmysql.example.com -P3306
(2003, "Can't connect to MySQL server on 'mysql.example.com' ([Errno 111] Connection refused)")
然后我把 ClusterIP 改成 NodePort 却可以
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/data/mysql-data" # Change this path to your desired host path
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql8
spec:
replicas: 1
selector:
matchLabels:
app: mysql8
template:
metadata:
labels:
app: mysql8
spec:
containers:
- name: mysql8
image: mysql:8.0.34
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
- name: custom-config
mountPath: /etc/mysql/conf.d
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "250m"
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
- name: custom-config
configMap:
name: mysql-custom-config # Create a ConfigMap with your custom configuration
---
apiVersion: v1
kind: Service
metadata:
name: mysql8-service
spec:
selector:
app: mysql8
ports:
- protocol: TCP
port: 3306
targetPort: 3306
nodePort: 30001
type: NodePort
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mysql8-ingress
spec:
rules:
- host: mysql.example.com # 设置你想要的域名
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: mysql8-service # 这里填写你的 Service 名称
port:
number: 3306 # 这里填写 Service 的端口号
然后应用
minikube kubectl -- apply -f application/stateful/mysql.yaml
再次从宿主机连接 mysql, 就成功了
─➤ mycli -uroot -p123456 -hmysql.example.com -P30001 1 ↵
MySQL
mycli 1.27.0
Home: http://mycli.net
Bug tracker: https://github.com/dbcli/mycli/issues
Thanks to the contributor - chainkite
MySQL root@mysql.example.com:(none)>
所以为什么呢?为什么 ClusterIP 不行,但是 NodePort 却可以呢?
我看懂了,这样的,你使用Ingress其实已经是已经把80端口映射到3306了 ( mysql.example.com:80 => mysql8-service:3306 )
, 所以如果这样方案能行的话,正确的访问应该是 mycli -uroot -p123456 -hmysql.example.com -P80
(不过这样理论也也不能用,一个是http协议一个是tcp协议, Ingress实现tcp的转发是要额外配置的)
至于为什么NodePort可以使用, 因为你使用 NodePort 已经把 3306 的端口映射到宿主机的30001了,你使用 mycli -uroot -p123456 -hmysql.example.com -P30001
通过 ip 访问到数据库了,根本没有通过 Ingress 进行访问, 也就是 -hmysql.example.com
是把域名解析成 ip 也就是你宿主机 ip , mysql 客户端再通过 ip+端口 访问到数据库,不知道我说清楚了没
至于你想通过 Ingress 来转发tcp协议 我没玩过,不过可以参考一下这篇文章 https://blog.csdn.net/w851685279/article/details/115911686
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容