Service可以看作是一组提供相同服务的Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。
service默认只支持4层负载均衡能力,没有7层功能。(可以通过Ingress实现)
Service 是由 kube-proxy 组件,加上 iptables 来共同实现的
==kube-proxy 通过 iptables 处理 Service 的过程,需要在宿主机上设置相当多的 iptables 规则,如果宿主机有大量的Pod,不断刷新iptables规则,会消耗大量的CPU资
IPVS模式的service,可以使K8s集群支持更多量级的Pod。
开启kube-proxy的ipvs模式:
yum install -y ipvsadm //所有节点安装
$ kubectl edit cm kube-proxy -n kube-system //修改IPVS模式
mode: "ipvs"
$ kubectl get pod -n kube-system |grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}' //更新kube-proxy pod
vim deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: myapp:v1
ports:
- containerPort: 80
kubectl apply -f deployment.yaml
kubectl get pod -o wide
kubectl get svc
kubectl describe svc myservice
运行一个容器,访问后端的两个pod:
kubectl run test -it --image=busyboxplus
curl 10.244.3.12
curl 10.244.1.15
可以访问,这是因为在创建集群时就创建了一个覆盖型的网络
那么如果我们想要外部主机来访问pod呢?此时我们就可以通过创建service使外部主机访问
vim service.yaml
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
app: nginx
type: ClusterIP
kubectl apply -f service.yaml
kubectl get svc
kubectl describe svc web-service
目前该web-service还没有后端
创建两个后端的pod:
注意:标签必须和web-service的保持一致 app: nginx
\vi de.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: reg.westos.org/k8s/myapp:v1
ports:
- containerPort: 80
kubectl apply -f de.yaml
kubectl get pod
此时我们的web-service有了两个后端:
kubectl describe svc web-service
连接并访问:
kubectl attch test -it
curl 10.101.22.15
pod间内部通过访问ClusterIP分配的虚拟VIP负载到了后端的两个pod容器
ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的 ServiceType
Headless Service不需要分配一个VIP,而是直接以DNS记录的方式解析出被代理Pod的IP地址。
域名格式:(servicename).(servicename).(namespace).svc.cluster.local
\vi headless.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
app: nginx
clusterIP: None
kubectl apply -f headless.yaml
kubectl get svc
kubectl describe svc nginx-svc
以DNS记录的方式解析出被代理Pod的IP地址:
使用域名访问:
kubectl attch test -it
nslookup nginx-svc
通过这种方式实现访问,即使在后端pod滚动更新之后依然可以通过DNS进行解析
iptables -t nat -nL | grep 10.101.22.15
我们可以看到这些策略,是在service创建时增加的
当pod创建的越来越多时,iptables的刷新频率就会越来越大,刷新策略会对cpu造成一定的压力,我们可以使用lvs来实现pod的负载均衡,直接使用linux内核
在所有节点安装ipvsadm(master+node):
yum install -y ipvsadm
ipvsadm -l #没有任何策略
kubectl -n kube-system get cm
kubectl -n kube-system edit cm kube-proxy
更新kube-proxy pod:
kubectl get pod -n kube-system |grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}'
ipvsadm -ln