k8s中service代理外部的服务(mysql\nginx)
K8s中Service、Endpoints、Pod之间的关系
一个 Service的目标Pod集合通常是由Label Selector 来决定的。
Endpoints 是一组实际服务的端点集合。一个 Endpoint 是一个可被访问的服务端点,即一个状态为 running 的 pod 的可访问端点。一般 Pod 都不是一个独立存在,所以一组 Pod 的端点合在一起称为 EndPoints。只有被 Service Selector 匹配选中并且状态为 Running 的才会被加入到和 Service 同名的 Endpoints 中。
注:只有配置了 selector 的 service 才会自动创建一个同名的 endpoints,没有配置 selector 的 service 不会产生 endpoints 资源对象。
Service工作原理
k8s在创建Service时,会根据标签选择器selector(lable selector)来查找Pod,据此创建与Service同名的endpoint对象,当Pod 地址发生变化时,endpoint也会随之发生变化,service接收前端client请求的时候,就会通过endpoint,找到转发到哪个Pod进行访问的地址。(至于转发到哪个节点的Pod,由负载均衡kube-proxy决定)
kubernetes集群中有三类IP地址
1、Node Network(节点网络),物理节点或者虚拟节点的网络,如ens33接口上的网路地址
2、Pod network(pod 网络),创建的Pod具有的IP地址
[root@k8s-master01 ~]# kubectl get pods -o wide NAME READY STATUS IP NODE frontend-h78gw 1/1 Running 10.244.187.76 node2
Node Network和Pod network这两种网络地址是我们实实在在配置的,其中节点网络地址是配置在节点接口之上,而pod网络地址是配置在pod资源之上的,因此这些地址都是配置在某些设备之上的,这些设备可能是硬件,也可能是软件模拟的。
3、Cluster Network(集群地址,也称为service network),这个地址是虚拟的地址(virtual ip),没有配置在某个接口上,只是出现在service的规则当中。
[root@k8s-master01 ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) kubernetes ClusterIP 10.96.0.1 <none> 443/TCP
创建一个service代理外部的服务nginx
创建一个没有标签选择器的service,这样的service就不会关联到任何pod,从而也不会自动创建endpoint。这时我们手动创建一个与service同名的endpoint,使用endpoint来定义外部服务的地址端口,service会自动关联该endpoint。
service是如何与endpoint关联的?需要特别注意一下几点:
1、endpoint的名称必须要与service的名称相同,这样两者才能关联; 2、service定义spec.ports的ports的时候,包含port端口、name端口名称、protocol协议; 3、endpoint中定义外部服务的IP和端口,endpoint的名称一定要与service的名称一样,协议也要一样,端口的name也要与service的端口的name一样,端口协议也要与service的端口协议一样,不然endpoint不能与service进行关联。
1 [root@k8s-master01 endpoint]# cat outside_agent_nginx.yaml 2 --- 3 apiVersion: v1 4 kind: Service 5 metadata: 6 name: outside-agent-svc #service的名称叫做outside-agent-svc 7 namespace: default 8 spec: 9 ports: 10 - name: out-agent-port #service端口的名称 11 port: 8056 #service的端口 12 protocol: TCP #端口协议 13 # targetPort: 80 #目标端口可以不定义,因为我们代理的不是pod,不定义targetPort,其默认等于port 14 sessionAffinity: None 15 type: ClusterIP 16 17 --- 18 apiVersion: v1 19 kind: Endpoints 20 metadata: 21 name: outside-agent-svc #endpoint的名称一定要与service的名称一致 22 namespace: default 23 subsets: 24 - addresses: 25 - ip: 192.168.118.129 #定义外部服务地址 26 ports: 27 - port: 80 #外部服务的端口 28 name: out-agent-port #端口的name,这个名称一定要与service端口的名称 29 protocol: TCP #端口协议,这个协议一定要与service的端口协议一致 30 [root@k8s-master01 endpoint]#
查看两者是否关联
1 [root@k8s-master01 endpoint]# kubectl describe -f outside_agent_nginx.yaml 2 Name: outside-agent-svc 3 Namespace: default 4 Labels: <none> 5 Annotations: <none> 6 Selector: <none> 7 Type: ClusterIP 8 IP Family Policy: SingleStack 9 IP Families: IPv4 10 IP: 10.111.9.114 11 IPs: 10.111.9.114 12 Port: out-agent-port 8056/TCP 13 TargetPort: 8056/TCP 14 Endpoints: 192.168.118.129:80 #可以发现,service已经与同名的endpoint关联起来了 15 Session Affinity: None 16 Events: <none> 17 18 19 Name: outside-agent-svc 20 Namespace: default 21 Labels: <none> 22 Annotations: <none> 23 Subsets: 24 Addresses: 192.168.118.129 25 NotReadyAddresses: <none> 26 Ports: 27 Name Port Protocol 28 ---- ---- -------- 29 out-agent-port 80 TCP 30 31 Events: <none> 32 [root@k8s-master01 endpoint]#
测试
1 #访问service,查看是否能正常访问外部服务 2 [root@ks8-master01 endpoint]# curl 10.111.9.114:8056 #访问service的ip和端口,能正常访问外部服务 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 4 <html> 5 <head> 6 <title>Welcome to CentOS</title> 7 <style rel="stylesheet" type="text/css"> 8 9 html { 10 background-image:url(img/html-background.png); 11 background-color: white; 12 font-family: "DejaVu Sans", "Liberation Sans", sans-serif; 13 font-size: 0.85em; 14 line-height: 1.25em; 15 margin: 0 4% 0 4%; 16 }
创建一个service代理外部的服务mysql
在 node2 上安装 mysql 数据库:
1 [root@k8s-node2 ~]# yum install mariadb-server.x86_64 -y 2 [root@k8s-node2 ~]# systemctl start mariadb 3 4 [root@k8s-master01 ~]# vim mysql_service.yaml 5 apiVersion: v1 6 kind: Service 7 metadata: 8 name: mysql 9 spec: 10 type: ClusterIP 11 ports: 12 - port: 3306 13 14 [root@k8s-master01 ~]# kubectl apply -f mysql_service.yaml 15 service/mysql created 16 17 [root@k8s-master01 ~]# kubectl get svc 18 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 19 client-svc ExternalName <none> nginx-svc.nginx-ns.svc.cluster.local 80/TCP 21m 20 kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 52d 21 mysql ClusterIP 10.101.57.164 <none> 3306/TCP 94s 22 23 # 关联不到任何 pod 24 [root@k8s-master01 ~]# kubectl describe svc mysql 25 Name: mysql 26 Namespace: default 27 Labels: <none> 28 Annotations: <none> 29 Selector: <none> 30 Type: ClusterIP 31 IP Family Policy: SingleStack 32 IP Families: IPv4 33 IP: 10.101.57.164 34 IPs: 10.101.57.164 35 Port: <unset> 3306/TCP 36 TargetPort: 3306/TCP 37 Endpoints: <none> # 还没有 endpoint 38 Session Affinity: None 39 Events: <none>
创建 endpoint 资源
# 查看帮助命令 [root@k8s-master01 ~]# kubectl explain endpoints [root@k8s-master01 ~]# kubectl explain endpoints.subsets [root@k8s-master01 ~]# kubectl explain endpoints.subsets.addresses [root@k8s-master01 ~]# kubectl explain endpoints.subsets.ports [root@k8s-master01 ~]# vim mysql_endpoint.yaml apiVersion: v1 kind: Endpoints metadata: name: mysql # 必须与前面创建的 service 名称一样 subsets: - addresses: - ip: 192.168.78.132 # node 节点的物理 ip ports: - port: 3306 [root@k8s-master01 ~]# kubectl apply -f mysql_endpoint.yaml endpoints/mysql created [root@k8s-master01 ~]# kubectl describe svc mysql Name: mysql Namespace: default Labels: <none> Annotations: <none> Selector: <none> Type: ClusterIP IP Family Policy: SingleStack IP Families: IPv4 IP: 10.101.57.164 IPs: 10.101.57.164 Port: <unset> 3306/TCP TargetPort: 3306/TCP Endpoints: 192.168.78.132:3306 # 这个就是定义的外部数据库 Session Affinity: None Events: <none>