[kubernetes] Endpoint 和 Service介绍与应用

听闻少年二字,当与平庸相斥。这篇文章主要讲述[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
NAMEREADYSTATUSRESTARTSAGEIPNODENOMINATED NODEREADINESS GATES
nginx-7848d4b86f-mdql81/1Running06m45s10.244.4.140wokayou< none> < none>
nginx-7848d4b86f-t5zmt1/1Running06m45s10.244.4.139wokayou< none> < none>
nginx-7848d4b86f-zt7jj1/1Running06m45s10.244.4.141wokayou< 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
NAMEENDPOINTSAGE
nginx-svc10.244.4.139:80,10.244.4.140:80,10.244.4.141:8018m


        访问:

        查看???IPVS???规则:



??0x03 Service类型和应用??
        ???Service???支持4种类型:
  1. ???ClusterIP???(默认模式)
  2. ???NodePort???:主机端口模式
  3. ???Headless ClusterIP???:无头模式
  4. ???LoadBalancer???:使用外部负载均衡
  5. ???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
NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE
nginx-svcNodePort10.104.215.99< none> 80:31321/TCP3m23s

        随便登录一台主机,查看端口监听情况

    集群外访问测试:

【[kubernetes] Endpoint 和 Service介绍与应用】        ???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
NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE
nginx-svcClusterIPNone< none> 80/TCP48s


        获取集群内???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

        集群内访问:



??0x??03.4  ExternalName 将外部流量引入集群内部??
        ???ExternalName???类型的???Service???通过???CNAM????E???和它的值,可以将服务映射到???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???进行访问



??0x??03.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]#

        访问:



--结束。

    推荐阅读