[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会进行更新。

[kubernetes]


    ​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

[kubernetes]

    访问:

[kubernetes]

    查看​IPVS​规则:

[kubernetes]


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​来访问。

[kubernetes]

    创建一个​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

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

[kubernetes]

    集群外访问测试:

[kubernetes]

    ​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

[kubernetes]

    获取集群内​DNS​地址

[kubernetes]

    解析地址,域名组成为​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

    集群内访问:

[kubernetes]


0x03.4 ExternalName 将外部流量引入集群内部

    ​ExternalName​类型的​Service​通过​CNAME​和它的值,可以将服务映射到​externalName​字段的内容引入外部服务到内部流量,即​使用DNS CNAME机制把自己CNAME到你指定的另外一个域名上。

[kubernetes]

    定义一个​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​进行访问

[kubernetes]


0x03.5 LoadBalancer使用外部负载均衡

    ​LoadBalancer​需要使用外部​Balancer​(负载均衡器)来实现,我的环境无法演示。

[kubernetes]


0x04 使用endpoint代理集群外部服务

     通过上面的例子,我们知道service是依靠endpoint实现的,而这个endpoint也是一种kuberntes资源,支持自定义,这就意味着我们也可以使用service实现集群外部的资源代理访问。

[kubernetes]

    定义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]



--结束。

以上是关于[kubernetes] Endpoint 和 Service介绍与应用的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes 中的“端点”是啥?

浅谈kubernetes:master节点和node节点

Kubernetes kube-proxy 详解

Kubernetes 部署 Mysql 8

kubernetes-003

Terraform data.google_container_cluster.cluster.endpoint 为空