[kubernetes] Endpoint 和 Service介绍与应用
Posted 运维少年
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[kubernetes] Endpoint 和 Service介绍与应用相关的知识,希望对你有一定的参考价值。
0x01 介绍
每个Pod都有独有的IP地址,而每次Pod重建后IP地址都会发生变化,那我们如何长期对一个Pod进行访问呢?答案就是Service,Servcie可以理解为一组Pod的四层代理,Service作为kubernets一种标准的资源,它可以通过节点的kube-proxy从apiserver中获取每个Pod的地址,从而实现代理功能。由下图可见,每一个Service资源都有一个endpoints,endpoints主要记录了每个pod的IP地址信息,当Pod的IP发生变化时,endpoints会进行更新。
Service常见的代理模式有两种,一种是IPVS,一种是iptables;还有比较新的cni:ebpf、nftables。本篇使用的是IPVS,启用IPVS可以通过以下方式进行设置:
1、使用kubeadm安装的集群配置
# kubectl edit configmap kube-proxy -n kube-system
...
mode: “ipvs“
...、
# kubectl delete pod kube-proxy-btz4p -n kube-system
注:1、kube-proxy配置文件以configmap方式存储
2、如果让所有节点生效,需要重建所有节点kube-proxy pod
2、二进制安装的集群配置
# vi kube-proxy-config.ymlmode: ipvsipvs:scheduler: "rr“
# systemctl restart kube-proxy
注:参考不同资料,文件名可能不同。
值得注意的是:当 kube-proxy 以 IPVS 代理模式启动时,它将验证 IPVS 内核模块是否可用。如果未检测到 IPVS 内核模块,则 kube-proxy 将退回到以 iptables 代理模式运行。
0x02 Service快速入门
定义一个deployment资源
[root@aliyun168-37 nginx]# cat dp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
namespace: test
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
定义一个service资源
[root@aliyun168-37 nginx]# cat svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: test
spec:
selector:
app: nginx # 选择的pod
ports:
- port: 8080 # service端口
targetPort: 80 # container端口
protocol: TCP # 协议类型
应用:
kubectl apply -f dp.yaml
kubectl apply -f svc.yaml
至此一个Service资源就创建好了,Service的endpoint为labels app:nginx的pod.
查看Pod
[root@aliyun168-37 nginx]# kubectl get pod -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-7848d4b86f-mdql8 1/1 Running 0 6m45s 10.244.4.140 wokayou <none> <none>
nginx-7848d4b86f-t5zmt 1/1 Running 0 6m45s 10.244.4.139 wokayou <none> <none>
nginx-7848d4b86f-zt7jj 1/1 Running 0 6m45s 10.244.4.141 wokayou <none> <none>
查看Service
[root@aliyun168-37 nginx]# kubectl describe svc/nginx-svc -n test
Name: nginx-svc
Namespace: test
Labels: <none>
Annotations: Selector: app=nginx
Type: ClusterIP
IP: 10.109.58.23
Port: <unset> 8080/TCP # 代理后的端口
TargetPort: 80/TCP # Container的端口
Endpoints: 10.244.4.139:80,10.244.4.140:80,10.244.4.141:80
Session Affinity: None
Events: <none>
查看Endpoints(创建Service后会自动创建一个同名的endpoints)
[root@aliyun168-37 nginx]# kubectl get endpoints nginx-svc -n test
NAME ENDPOINTS AGE
nginx-svc 10.244.4.139:80,10.244.4.140:80,10.244.4.141:80 18m
访问:
查看IPVS规则:
0x03 Service类型和应用
Service支持4种类型:
ClusterIP(默认模式)
NodePort:主机端口模式
Headless ClusterIP:无头模式
LoadBalancer:使用外部负载均衡
ExternalName:将外部服务引入集群内部
0x03.1 ClusterIP
不指定Service类型时,默认类型为ClusterIP,而这个ClusterIP的地址段在安装集群的时已经配置好了,ClusterIP一般只能在集群内访问,集群外是无法访问的。
配置位置:
cat kube-controller-manager.yaml
...
- --service-cluster-ip-range=10.96.0.0/12
...
ClusterIP类型使用:
[root@aliyun168-37 nginx]# cat svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: test
spec:
selector:
app: nginx
ports:
- port: 8080 # service端口
targetPort: 80 # container Port
protocol: TCP
type: ClusterIP
也可以指定ClusterIP
...
spec:
...
type: ClusterIP
clusterIP: 10.100.100.100
...
0x03.2 NodePort
NodePort类型的Service应用后,每个Node都会监听该端口。我们可以通过任意一个NodeIP:Port来访问。
创建一个NodePort类型的Service
...
spec:
...
ports:
- port: 80
protocol: TCP
type: NodePort
...
查看Service,可以看到已经将80端口映射为31321端口了
[root@aliyun168-37 nginx]# kubectl get svc -n test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc NodePort 10.104.215.99 <none> 80:31321/TCP 3m23s
随便登录一台主机,查看端口监听情况
集群外访问测试:
NodePort类型的Service在不指定Port的情况下,将随机分配一个Port,而分配的访问默认为30000-32767,可以通过以下配置文件进行修改:
vim kube-apiserver.yaml
增加:
- --service-node-port-range=1-65535
也可以指定NodePort
...
spec:
...
ports:
- port: 80
protocol: TCP
nodePort: 1023
type: NodePort
...
0x03.3 Headless ClusterIP无头服务
无头服务是一种特殊ClusterIP类型的Service,但是没有ClusterIP,只能通过域名进行访问,无头服务一般在StatfulSet中使用。
定义一个Headless ClusterIP资源
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: test
spec:
selector:
app: nginx
ports:
- port: 80
protocol: TCP
clusterIP: "None" # 此处定义为Node,即为Headless
查看Service
[root@aliyun168-37 nginx]# kubectl get svc -n test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc ClusterIP None <none> 80/TCP 48s
获取集群内DNS地址
解析地址,域名组成为servicename.namespace.svc.cluster.local:
[root@aliyun168-37 nginx]# nslookup nginx-svc.test.svc.cluster.local 10.96.0.10
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: nginx-svc.test.svc.cluster.local
Address: 10.244.4.140
Name: nginx-svc.test.svc.cluster.local
Address: 10.244.4.141
Name: nginx-svc.test.svc.cluster.local
Address: 10.244.4.139
集群内访问:
0x03.4 ExternalName 将外部流量引入集群内部
ExternalName类型的Service通过CNAME和它的值,可以将服务映射到externalName字段的内容引入外部服务到内部流量,即使用DNS CNAME机制把自己CNAME到你指定的另外一个域名上。
定义一个externalName类型Service:
[root@aliyun168-37 nginx]# cat svc3.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: test
spec:
type: ExternalName
externalName: mysql.51yunwei.top
pod使用mysql进行访问
0x03.5 LoadBalancer使用外部负载均衡
LoadBalancer需要使用外部Balancer(负载均衡器)来实现,我的环境无法演示。
0x04 使用endpoint代理集群外部服务
通过上面的例子,我们知道service是依靠endpoint实现的,而这个endpoint也是一种kuberntes资源,支持自定义,这就意味着我们也可以使用service实现集群外部的资源代理访问。
定义endpoints:
apiVersion: v1
kind: Endpoints
metadata:
name: mysql-svc
namespace: test
subsets:
- addresses:
- ip: 1.1.1.1
ports:
- port: 3306
定义service(名字和endpoints一样就可以自动关联起来了):
apiVersion: v1
kind: Service
metadata:
name: mysql-svc
namespace: test
spec:
ports:
- port: 3306
targetPort: 3306
protocol: TCP
查看:
[root@aliyun168-37 nginx]# kubectl describe svc mysql-svc -n test
Name: mysql-svc
Namespace: test
Labels: <none>
Annotations: Selector: <none>
Type: ClusterIP
IP: 10.103.36.61
Port: <unset> 3306/TCP
TargetPort: 3306/TCP
Endpoints: 1.1.1.1:3306
Session Affinity: None
Events: <none>
[root@aliyun168-37 nginx]#
访问:
--结束。
以上是关于[kubernetes] Endpoint 和 Service介绍与应用的主要内容,如果未能解决你的问题,请参考以下文章