前面讲解了Pod和deployment等多个核心对象,了解了可以通过这些对象来创建一些pod对象,并且提供内部的访问,但是在实际生产中,肯定是想将pod中的服务对外网提供服务,让外网用户能通过IP:Port的方式来访问到集群后端的服务。
实现的方法有很多,比如:1,已知Node可以通过pod的IP:Port来访问pod中的服务,那只要在Node上面安装一个nginx,通过这个nginx来转发即可;2.创建一个ingress服务来转发,这个后面会讲解;3.创建一个service服务对象,通过service的一些特性来对外提供服务。本章节,讲解的就是service服务对象。
什么是Kubernetes Service?
Service是K8s中的一种抽象,它定义了一组Pod的逻辑集合,并为这组Pod提供一个稳定的访问点(Endpoint)。这个访问点可以是一个固定的虚拟IP地址或者一个DNS名称,通过这个访问点,其他的应用或服务可以方便地访问到这组Pod,实现服务发现和负载均衡。
在K8s中,Pod是最小的可部署单元,而Service则提供了对这些Pod的抽象。使用Service,我们可以将后端Pod组织成一个逻辑单元,而不用担心它们的具体部署细节。这种抽象使得我们可以更加灵活地进行应用的扩展和维护。
Service的类型
K8s中的Service有四种类型,分别是ClusterIP、NodePort、LoadBalancer和ExternalName。接下来,我们将详细介绍每种类型的Service以及它们的用途。
ClusterIP:使用集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的ServiceType。
NodePort:通过每个 Node 节点上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 ,可以从集群的外部访问一个 NodePort 服务。
LoadBalancer:使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务,这个需要结合具体的云厂商进行操作。
ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如, mydb.baidu.com)。
了解Service之前,我们先大概了解下k8s种的3种IP类型 和 3种Port类型。一会在后面的yaml文件举例中再来具体讲解。
3种IP类型
Node IP: Node节点的IP地址
Pod IP: Pod的IP地址
ClusterIP: Service的IP地址
3种Port类型
Port: service的端口号
targetPort: 后端Pod的端口号
NodePort: Node节点的端口
下面来对service的4中类型分别举例说明。
首先先创建一个nginx的pod。
# cat nginx_dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
labels:
k8s-app: nginx-demo
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: m.daocloud.io/docker.io/library/nginx
ports:
- containerPort: 80
# kubectl apply -f nginx_dep.yaml
deployment.apps/nginx-deploy created
ClusterIP类型:
ClusterIP,默认方式,集群内访问
创建一个ClusterIP类型的yaml文件
# cat nginx_svc_clusterIP.yaml
apiVersion: v1
kind: Service
metadata:
name: nginxservice
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 8080
targetPort: 80
name: service-cip
# kubectl apply -f nginx_svc_clusterIP.yaml
service/nginxservice created
①kind类型为Service
②service选择选择pod的标签为 app:nginx,刚好和上面创建的pod对应上了
③转发的协议为TCP
④service的port为8080
⑤选择的pod的端口为80
最后2个加起来的意思是将service的8080端口转发到后端pod的80端口。
查看pod和service
访问测试发现不管是PodIP:PORT还是ServiceIP:PORT访问,返回内容一样,这说明通过ServiceIP转发成功。
# curl 10.20.213.29
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
....
通过service的IP和端口来访问
# curl 10.10.188.174:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
....
NodePort 类型:
NodePort 集群外访问
创建一个NodePort 类型的yaml文件
# cat nginx_svc_nodePort.yaml
apiVersion: v1
kind: Service
metadata:
name: nginxservicenp
spec:
selector:
app: nginx
type: NodePort
ports:
- protocol: TCP
port: 8081
targetPort: 80
nodePort: 30080 #从api-server.conf中配置的端口范围来选取(通常是30000-32767)
name: svc-nodeport
注意这里增加了一个字段 spec.type: NodePort。为和上面例子区分开,这里的端口用的是8081.
从下图可以看到新创建的service的类型为NodePort,并且出现了2个端口,8081是service的端口,而30080是node服务器的端口。
访问测试
# curl 10.20.213.29
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
....
通过service的IP和端口来访问
# curl 10.10.207.250:8081
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
....
通过Node服务器的IP和端口来访问,这里使用的是master的IP,也可以使用node节点的IP
# curl 172.21.176.3:30080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
....
通过测试可知,这时候已经可以通过NodeIP:port的方式来访问内部pod服务了。