k8s集群内部服务发现的方式有两种:
1、通过变量发现
只能获取相同namespace里的变量
变量的获取有先后顺序,引用的变量必须要先创建
2、通过DNS的方式发现
在kube-system里有dns,可以自动发现所有命名空间里的服务的clusterIP
所以,在同一个命名空间里,一个服务访问另外一个服务的时候,可以直接通过服务名来访问
只要创建了一个服务(不管在哪个ns里创建的),都会自动向kube-system里的DNS注册
如果是不同的命名空间,可以通过 服务名.命名空间名 来访问
Service是一种抽象的对象,它定义了一组Pod的逻辑集合和一个用于访问它们的策略。
service主要实现集群内部通信,以及基于四层的内外通信(如端口)。
service用于为pod提供一个固定,统一的访问接口及负载均衡的能力,并借助新一代DNS的服务发现功能,解决客户端发现并访问容器化应用的难题。
service的地址是不会发生改变的,它通过标签选择器和后端的pod关联。
k8s集群中的3种ip:
1、Node IP:Node节点的IP地址
2、Pod IP: Pod的IP地址
3、Cluster IP: Service的IP地址,不能ping通
k8s集群中的service类型
$ kubectl explain svc.spec.type
Defaults to ClusterIP. Valid options are ExternalName, ClusterIP, NodePort, and LoadBalancer.
不使用type字段的话,默认就是ClusterIP类型
1、ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的ServiceType。
k8s集群内部流量走向:
内部客户端--service(ClussterIp:Port)--endpoint(ip和port列表)--应用pod(port)
2、NodePort:通过每个 Node 节点上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 :,可以从集群的外部访问一个 NodePort 服务。
NodePort类型的service数据流向:
外部用户--外部LB--nodePort(集群入口)--service--endpoint--应用pod
3、LoadBalancer类型的service应用在公有云环境中
4、ExternalName类型的service用于实现集群内部pod访问集群外部的服务
数据流向:内部pod--service--外部服务
该类型的service没有serviceIP,没有nodeport,没有标签选择器,需要CNAME解析记录
完成内部流量转发工作的是各工作节点的kube-proxy
proxy工作模式有3种:
1、userspace代理模式
2、iptables代理模式
3、ipvs代理模式
ipvs模式和iptables模式的区别仅仅是:请求流量的调度功能由ipvs完成,其他功能仍由iptables完成
创建service的两种方式:
1、使用kubectl expose命令
2、定义资源清单文件
$ kubectl explain svc.metadata
FIELDS:
labels
name #svc的名字
namespace
$ kubectl explain svc.spec
FIELDS:
clusterIP #svc的ip地址
ports
selector
type
$ kubectl explain svc.spec.clusterIP
clusterIP is the IP address of the service and is usually assigned randomly by the master.
Valid values are "None", empty string (""), or a valid IP address.
"None" can be specified for headless services when proxying is not required.
Only applies to types ClusterIP, NodePort, and LoadBalancer. Ignored if type is ExternalName.
clusterIP表示svc的ip地址,一般自动获取,不用手动指定。如果不使用该字段或者指定其值为空,都表示自动获取ip地址。
如果指定其值为None,表示该svc是无头服务。
当svc的type是ExternalName时,不能使用该字段。
$ kubectl explain svc.spec.ports
FIELDS:
1、port:
指该service暴露的端口,用yaml文件创建svc时是必选项,用命令创建时可以不指定,如果不指定,会继承pod中的containerPort。
2、nodePort:
指node节点端口(只有当type为NodePort或LoadBalancer时才需要该参数,一般自动生成),用于对外通信。
3、targetPort:
指后端pod暴露的端口,就是pod中的containerPort。
如果既不指定port又不指定targetPort,那么port和targetPort都会继承pod中的containerPort。
如果指定了port而没有指定targetPort,那么targetPort会继承port值,所以此时必须指定targetPort值为pod中的containerPort,不能随便指定端口号,除非port值和pod中的containerPort相同(这种情况可以不指定targetPort)。
当type为ClusterIP时,流量经过的端口走向是:
svc端口(port)----pod端口(targetPort)----容器端口(containerPort)
当type为NodePort时,流量经过的端口走向是:
节点端口(NodePort)----svc端口(port)----pod端口(targetPort)----容器端口(containerPort)
使用命令创建svc(containerPort是8080)
$ kubectl get deploy
$ kubectl expose deploy deploy_name1
$ kubectl get svc
$ kubectl delete svc svc_name
$ kubectl expose deploy deploy_name2 --port=8080
$ kubectl expose deploy deploy_name3--port=80 --target-port=8080
$ kubectl expose deploy deploy_name4 --port=80 --target-port=8080 --type=NodePort
$ kubectl get svc svc_name -o yaml
spec:
clusterIP: 10.97.153.130
externalTrafficPolicy: Cluster
ports:
- nodePort: 30693
port: 80
protocol: TCP
targetPort: 8080
$ curl http://10.97.153.130$ curl http://192.168.1.243:30693 #243是master地址
$ kubectl delete svc svc_name
用yaml文件创建svc
apiVersion: v1
kind: Service
metadata:
labels:
ame: mysvc
name: mysvc
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: mysvc #匹配标签为app: mysvc的后端pod
type: NodePort
Headless无头类型的service:
该service没有IP,客户端不经过service,而是直接访问后端的pod
无头服务的type不能是NodePort。
kind: Service
spec:
clusterIP: None #(该参数设置为None即可成为无头service)
查看某个服务下有哪些pod:
$ kubectl get svc
$ kubectl get svc svc_name -o yaml
$ kubectl describe svc svc_name
Selector: run=nginx1
$ kubectl get pod -l run=nginx1
验证通过DNS发现服务
$ kubectl get pod -n kube-system |grep dns
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP
$ yum install bind-utils -y
$ dig -t A svc_name.default.svc.cluster.local. @10.96.0.10
$ kubectl get svc svc_name -o yaml
在pod中验证dns服务发现
$ kubectl run busybox --rm -it --image=busybox sh
/ # cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local example.com