一、Kubernetes资源管理Service的使用定义
1.1 介绍说明
- 防止Pod失联
- 定义一组Pod的访问策略
- 支持ClusterIP、NodePort以及LoadBalance三种类型
- Service的底层实现主要有Iptables和IPVS两种网络模型
- Pod与service关系
- 通过lable-selector相关联
- 通过Service实现Pod的负载均衡(TCP/UDP 4层)
1.2 service定义
# 版本
apiVersion: v1
# 资源对象
kind: Service
# 元数据
metadata:
指定service名称
name: my-service
命名空间
namespace: default
spec:
分配IP
clusterIP: 10.0.0.1
指定端口
ports:
端口名称
- name: http
指定service端口
port: 80
service使用协议
protocol: TCP
容器端口,转发后端容器端口
targetPort: 80
标签选择器,通过标签匹配关联的pod
selector:
标签
app: nginx
实例 [1] 创建service yml文件
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: default
spec:
clusterIP: 10.0.0.123
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
[2] 创建service
kubectl apply -f service.yaml
[3] 查看创建的service
kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-service ClusterIP 10.0.0.123 <none> 80/TCP
[4] 动态感知查看分配的Node
kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.1.108:6443,192.168.1.109:6443 2d16h
my-service <none> 2m54s
nginx-service 172.17.1.2:80,172.17.1.3:80,172.17.1.6:80 44h
nginx-service2 <none> 17h
注:每个service对应一个ENDPOINTS控制器,service则用来关联pod
[5] 查看ENDPOINTS详细信息
kubectl describe service my-service
Name: my-service
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"my-service","namespace":"default"},"spec":{"clusterIP":"10.0.0.12...
Selector: app=nginx
Type: ClusterIP
IP: 10.0.0.123
Port: http 80/TCP
TargetPort: 80/TCP
Endpoints: <none>
Session Affinity: None
Events: <none>
二、Service代理k8s外部应用
希望在生产环境中使用某个固定的名称而非IP地址进行访问外部中间件服务
希望Service指向一个Namespace中或其他集群中的服务
某个项目正在迁移至k8s集群,但是一部分服务任然在集群外部,此时可以使用Service代理至k8s集群外部的服务。
[1] 常见代理service服务
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-svc-external
name: nginx-svc-external
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
sessionAffinity: None
type: ClusterIP
[2] 常见外部服务的endpoint服务
apiVersion: v1
kind: Endpoints
metadata:
labels:
app: nginx-svc-external
name: nginx-svc-external
namespace: default
subsets:
- addresses:
- ip: 42.236.78.232 外部服务的IP地址
ports:
- name: http
port: 80
protocol: TCP
三、Kubernetes资源管理service类型
- ClusterIP:默认,分配一个集群内部可以访问的虚拟IP(VIP)
- NodePort:在每个Node上分配一个端口作为外部访问入口
- LoadBalancer:工作在特定的cloud Provider上,例如Google Cloud,AWS,OpenStack
- ExternalName:通过返回定义的CNAME别名
3.1 ClusterIP
3.2 NodePort
3.3 LoadBalancer
3.4 二、NodePort端口固定
# 固定范围在kube-apiserver配置文件下参数
--service-node-port-range=30000-50000
实例
# 通过配置yaml文件固定端口
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: A
ports:
- protocol: TCP
port: 80
targetPort: 8080
固定端口数值,必须是配置文件范围内
nodePort: 30001
网络类型
type: NodePort
四、Kubernetes资源管理service代理模式
底层流量转发与负载均衡实现:
- Iptables(默认)
- IPVS
4.1 IPVS
了解代理模式之IPVS工作原理
LVS基于IPVS内核调度模块实现的负载均衡。
# 查看路由对应关系,需要先下载ipvsadm工具
Ipvsadm -ln
注:内核态处理
IPVS:
工作在内核态,有更好的性能
调度算法丰富:rr\wrr\lc\wlc\ip hash …
[1]安装IPVS
yum -y install ipvsadm
开启使用IPVS模式
[2] Node:启动IPVS模式,修改配置文件
vim /opt/kubernetes/cfg/kube-proxy
KUBE_PROXY_OPTS="--logtostderr=true \
--v=4 \
--hostname-override=192.168.1.110 \
--cluster-cidr=10.0.0.0/24 \
--proxy-mode=ipvs \
--masquerade-all=true \
# 指定默认调度算法
--ipvs-scheduler=wrr \
--kubeconfig=/opt/kubernetes/cfg/kube-proxy.kubeconfig"
[3] 重启kube-proxy
systemctl restart kube-proxy
4.2 Iptables
iptables实现是通过linux内核,实现linux内核级防火墙。
查看所有规则:iptables-save more
原理:通过iptables为访问来源创建许多规则,所有规则从上到下进行匹配。
问题:
1、 创建很多iptables规则(更新,非增量式);
2、 iptables规则从上到下逐条匹配(延时大);
3、 用户态处理;
Iptables:
- 灵活,功能强大(可以在数据包不同阶段对包进行操作)
- 规则遍历匹配和更新,呈线性时延
五、Kubernetes资源管理service案例
5.1 创建简单service
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp ## 使用选择器选择所有Pod
# type: ClusterIPtype很重要,不写默认是ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 9376
- Service 创建完成后,会对应一组EndPoint。可以kubectl get ep 进行查看
- type有四种,每种对应不同服务发现机制
- Servvice可以利用Pod的就绪探针机制,只负载就绪了的Pod。自动剔除没有就绪的Pod
5.2 创建无Selector的Service
- 我们可以创建Service不指定Selector
- 然后手动创建EndPoint,指定一组Pod地址。
- 此场景用于我们负载均衡其他中间件场景。
# 无selector的svc
apiVersion: v1
kind: Service
metadata:
name: my-service-no-selector
spec:
ports:
- protocol: TCP
name: http ###一定注意,name可以不写,
但是这里如果写了name,那么endpoint里面的ports必须有同名name才能绑定
port: 80 # service 80
targetPort: 80 #目标80
---
apiVersion: v1
kind: Endpoints
metadata:
name: my-service-no-selector ### ep和svc的绑定规则是:和svc同名同名称空间,port同名或同端口
namespace: default
subsets:
- addresses:
- ip: 220.181.38.148
- ip: 39.156.69.79
- ip: 192.168.169.165
ports:
- port: 80
name: http ## svc有name这里一定要有
protocol: TCP
## 实验
apiVersion: v1
kind: Service
metadata:
name: cluster-service-no-selector
namespace: default
spec:
不选中Pod而在下面手动定义可以访问的EndPoint
type: ClusterIP
ports:
- name: abc
port: 80 ## 访问当前service 的 80
targetPort: 80 ## 派发到Pod的 80
---
apiVersion: v1
kind: Endpoints
metadata:
name: cluster-service-no-selector ## 和service同名
namespace: default
subsets:
- addresses:
- ip: 192.168.169.184
- ip: 192.168.169.165
- ip: 39.156.69.79
ports:
- name: abc ## ep和service要是一样的
port: 80
protocol: TCP
场景:pod要访问Mysql。Mysql单独部署到很多机器,每次记ip麻烦
集群内创建一个service,实时的可以剔除EP信息。反向代理集群的东西。
5.3 ClusterIP
type: ClusterIP
ClusterIP: 手动指定/None/""
- 手动指定的ClusterIP必须在合法范围内
- None会创建出没有ClusterIP的headless service(无头服务),Pod需要用服务的域名访问
5.4 NodePort
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: default
type: NodePort
ports:
- protocol: TCP
port: 80 # service 80
targetPort: 80 #目标80
nodePort: 32123 #自定义
- 如果将 type 字段设置为 NodePort ,则 Kubernetes 将在 --service-node-port-range 标志指定的范围内分配端口(默认值:30000-32767)
- k8s集群的所有机器都将打开监听这个端口的数据,访问任何一个机器,都可以访问这个service对应的Pod
- 使用 nodePort 自定义端口
5.5 ExternalName
apiVersion: v1
kind: Service
metadata:
name: my-service-05
namespace: default
spec:
type: ExternalName
externalName: baidu.com
- 其他的Pod可以通过访问这个service而访问其他的域名服务
- 但是需要注意目标服务的跨域问题
5.6 LoadBalancer
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/name: load-balancer-example
name: my-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app.kubernetes.io/name: load-balancer-example
type: LoadBalancer
5.7 扩展-externalIP
在Service 的定义中,externalIPs 可以和任何类型的 .spec.type 一通使用。在下面的例子中,
客户端可通过 80.11.12.10:80 (externalIP:port) 访问 my-service
apiVersion: v1
kind: Service
metadata:
name: my-service-externalip
spec:
selector:
app: canary-nginx
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
externalIPs: 定义只有externalIPs指定的地址才可以访问这个service
- 10.170.0.111
5.8 扩展-Pod的DNS
apiVersion: v1
kind: Service
metadata:
name: default-subdomain
spec:
selector:
name: busybox
clusterIP: None
ports:
- name: foo 实际上不需要指定端口号
port: 1234
targetPort: 1234
---
apiVersion: v1
kind: Pod
metadata:
name: busybox1
labels:
name: busybox
spec:
hostname: busybox-1
subdomain: default-subdomain
指定必须和svc名称一样,才可以 podName.subdomain.名称空间.svc.cluster.local访问。否则访问不同指定Pod
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
name: busybox
---
apiVersion: v1
kind: Pod
metadata:
name: busybox2
labels:
name: busybox
spec:
hostname: busybox-2
subdomain: default-subdomain
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
name: busybox
-
访问 busybox-1. default-subdomain .default. svc.cluster.local 可以访问到busybox-1。
-
访问Service
-
同名称空间
- ping service-name 即可
-
不同名称空间
- ping service-name.namespace 即可
-
访问Pod
-
同名称空间
- ping pod-host-name.service-name 即可
-
不同名称空间
- ping pod-host-name.service-name.namespace 即可