Service介绍
三种模式
userspace模式
userspace模式,kube-proxy会为每一个Service创建一个监听端口,请求经过kube-proxy,相当于一个四层负责均衡器,kube-proxy运行在userspace中,在进行转发处理时会增加内核和用户空间之间的数据拷贝,虽然稳定,但是效率很低
iptables模式
iptables模式下,kube-proxy为service后端每个pod创建对应的iptables规则,直接将发向Cluster IP的请求重定向到一个Pod IP
该模式下kube-proxy不承担四层负载均衡器的作用,只负责创建iptables规则,较userspace模式效率更高,不能提供灵活的LB策略,当后端pod不可用时无法进行重试
ipvs模式
ipvs模式和iptables类似,kube-proxy监控pod的变化并创建相应的ipvs规则,ipvs相对iptables转发效率更高,支持更多的LB算法
ipvs必须安装ipvs内核,否则降级为iptables
#开启ipvs
root@101 ~]# kubectl edit cm kube-proxy -n kube-system
mode: "ipvs" #修改为ipvs
[root@101 ~]# kubectl delete pod -l k8s-app=kube-proxy -n kube-system
[root@101 ~]# ipvsadm -Ln #查看
Service类型
Service资源清单
apiVersion: v1 # 版本
kind: Service # 类型
metadata: # 元数据
name: # 资源名称
namespace: # 命名空间
spec:
selector: # 标签选择器,用于确定当前Service代理那些Pod
app: nginx
type: NodePort # Service的类型,指定Service的访问方式
clusterIP: # 虚拟服务的IP地址
sessionAffinity: # session亲和性,支持ClientIP、None两个选项,默认值为None
ports: # 端口信息
- port: 8080 # Service端口
protocol: TCP # 协议
targetPort : # Pod端口
nodePort: # 主机端口
- ClusterIP:默认,kubernetes系统自动分配的虚拟ip,只能在集群内布访问
- NodePort:将Service通过指定的Node上的端口暴露给外部
- LoadBalancer:使用外接负载均衡器完成到服务的负载分发,此模式需要外部云环境支持
- ExternalName:把集群外部的服务引入集群内部,直接使用
Service使用
pod后端使用
apiVersion: apps/v1 # 版本号
kind: Deployment # 类型
metadata: # 元数据
name: pc-deployment # deployment的名称
namespace: dev # 命名类型
spec: # 详细描述
strategy: # 镜像更新策略
type: RollingUpdate # RollingUpdate:滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本的Pod
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
replicas: 4 # 副本数量
selector: # 选择器,通过它指定该控制器可以管理哪些Pod
matchLabels: # Labels匹配规则
app: nginx-pod
template: # 模块 当副本数据不足的时候,会根据下面的模板创建Pod副本
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx # 容器名称
image: nginx:1.17.1 # 容器需要的镜像地址
ports:
- containerPort: 80 # 容器所监听的端口
Cluster
service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
name: service-clusterip
namespace: dev
spec:
selector:
app: nginx-pod
clusterIP: # service的IP地址,如果不写,默认会生成一个
type: ClusterIP
ports:
- port: 80 # Service的端口
targetPort: 80 # Pod的端口
[root@101 ~]# kubectl get svc -n dev
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service-clusterip ClusterIP 10.103.248.92 <none> 80/TCP 11s
[root@101 ~]# curl 10.103.248.92
3
[root@101 ~]# curl 10.103.248.92
1
[root@101 ~]# curl 10.103.248.92
2
Endpoint
Endpoint是由kubernetes中的一个资源对象存在在etcd中,用来记录一个service对应的所有pod的访问地址,他是根据service配置文件中的selector描述产生的
一个service由一组pod组成,这些pod通过Endpoint暴露出来,**Endpoints是实际服务的端点集合**,service和pod之间是通过endpoints实现的
[root@101 ~]# kubectl describe svc -n dev
Name: service-clusterip
Namespace: dev
Labels: <none>
Annotations: <none>
Selector: app=nginx-pod
Type: ClusterIP
IP: 10.103.248.92
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.31:80,10.244.2.29:80,10.244.2.30:80
Session Affinity: None
Events: <none>
[root@101 ~]# kubectl get endpoints -n dev
NAME ENDPOINTS AGE
service-clusterip 10.244.1.31:80,10.244.2.29:80,10.244.2.30:80 6m17s
#查看ipvs规则
[root@101 ~]# ipvsadm -Ln
TCP 10.103.248.92:80 rr
-> 10.244.1.31:80 Masq 1 0 0
-> 10.244.2.29:80 Masq 1 0 0
-> 10.244.2.30:80 Masq 1 0 0
负载分发策略
- 默认使用kube-proxy策略,随机,轮询
- 基于客户端地址的会话保持模式,同一个客户端发起的所有请求都会转发到固定的一个Pod上,此模式可以在spec添加 sessionAffinity:ClientIP选项
apiVersion: v1 kind: Service metadata: name: service-clusterip namespace: dev spec: sessionAffinity: ClientIP #添加亲和性 selector: app: nginx-pod clusterIP: # service的IP地址,如果不写,默认会生成一个 type: ClusterIP ports: - port: 80 # Service的端口 targetPort: 80 # Pod的端口 #验证 [root@101 ~]# kubectl get svc -n dev NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service-clusterip ClusterIP 10.109.184.108 <none> 80/TCP 3s [root@101 ~]# [root@101 ~]# [root@101 ~]# curl 10.109.184.108 3 [root@101 ~]# curl 10.109.184.108 3 [root@101 ~]# curl 10.109.184.108 3
HeadLiness类型
#创建headliness apiVersion: v1 kind: Service metadata: name: headliness namespace: dev spec: selector: app: nginx-pod clusterIP: None # 创建headliness Service type: ClusterIP ports: - port: 80 # Service的端口 targetPort: 80 # Pod的端口 #查看 [root@101 ~]# dig @10.96.0.10 headliness.dev.svc.cluster.local |grep -Ev '^$|^;' headliness.dev.svc.cluster.local. 30 IN A 10.244.2.30 headliness.dev.svc.cluster.local. 30 IN A 10.244.1.31 headliness.dev.svc.cluster.local. 30 IN A 10.244.2.29
NodePort类型
NodePort是将service的端口映射到Node上的一个端口,通过NodeIPL:NodePort访问service
apiVersion: v1
kind: Service
metadata:
name: service-nodeport
namespace: dev
spec:
selector:
app: nginx-pod
type: NodePort # Service类型为NodePort
ports:
- port: 80 # Service的端口
targetPort: 80 # Pod的端口
nodePort: 30002 # 指定绑定的node的端口(默认取值范围是30000~32767),如果不指定,会默认分配
LoadBalancer类型
LoadBalancer和NodePort相似,LoadBalancer会在集群外部在做一个负载均衡,这个设备需要外部环境支持,外部环境发送到这个设备上的请求会被设备负载之后转发到集群中
ExternalName
apiVersion: v1
kind: Service
metadata:
name: service-externalname
namespace: dev
spec:
type: ExternalName # Service类型为ExternalName
externalName: www.baidu.com # 改成IP地址也可以
#域名解析
dig @10.96.0.10 service-externalname.dev.svc.cluster.local
Ingress介绍
NodePort:占用很多集群端口
LoadBalancer:每个service需要一个LB,并且需要之外设备的支持
Ingress相当与一个七层负载均衡器,是kubernetes对反向代理的一个抽象,他的工作原理类似与nginx,可以理解在Ingress里建立诸多映射规则,
Ingress Controller通过监听这些配置规则并转换成nginx的反向代理配置,然后对外部提供服务。
- ingress: kubernetes中的一个对象,作用是定义请求如何转发到service的规则
- ingress controller: 具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发,实现方式有很多,如nginx,contour,haproxy
Ingress(nginx为例)工作原理
- 用户编写ingress规则,说明哪个域名对象集群中的哪个service
- ingress控制器动态感知ingress服务规则的变换,生成一段对应的nginx配置
- ingress控制器将生成的nginx配置写入到一个运行的nginx服务中,并动态更新
- 到此为止
Ingress使用
环境准备
安装ingress-nginx v:0.30
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml #创建ingress-nginx [root@101 ingress]# kubectl apply -f ./ #查看详情 [root@101 ingress]# kubectl get pods,svc -n ingress-nginx NAME READY STATUS RESTARTS AGE pod/nginx-ingress-controller-7f74f657bd-x7ghp 1/1 Running 0 16s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/ingress-nginx NodePort 10.98.139.205 <none> 80:31049/TCP,443:32215/TCP 16s
准备service pod
nginx-tomcat.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment namespace: dev spec: replicas: 3 selector: matchLabels: app: nginx-pod template: metadata: labels: app: nginx-pod spec: containers: - name: nginx image: nginx:1.17.1 ports: - containerPort: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: tomcat-deployment namespace: dev spec: replicas: 3 selector: matchLabels: app: tomcat-pod template: metadata: labels: app: tomcat-pod spec: containers: - name: tomcat image: tomcat:8.5-jre10-slim ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: nginx-service namespace: dev spec: selector: app: nginx-pod clusterIP: None type: ClusterIP ports: - port: 80 targetPort: 80 --- apiVersion: v1 kind: Service metadata: name: tomcat-service namespace: dev spec: selector: app: tomcat-pod clusterIP: None type: ClusterIP ports: - port: 8080 targetPort: 8080
#查看 [root@101 ~]# kubectl get pods,svc -n dev NAME READY STATUS RESTARTS AGE pod/nginx-deployment-6696798b78-d54fc 1/1 Running 0 2m12s pod/nginx-deployment-6696798b78-nlkj4 1/1 Running 0 2m12s pod/nginx-deployment-6696798b78-zxxsf 1/1 Running 0 2m12s pod/tomcat-deployment-58467d5474-9gtpb 1/1 Running 0 2m12s pod/tomcat-deployment-58467d5474-fwhjq 1/1 Running 0 2m12s pod/tomcat-deployment-58467d5474-lzxfb 1/1 Running 0 2m12s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/nginx-service ClusterIP None <none> 80/TCP 2m12s service/tomcat-service ClusterIP None <none> 8080/TCP 2m12s
Http代理
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-http namespace: dev spec: rules: - host: nginx.test.com http: paths: - path: / backend: serviceName: nginx-service servicePort: 80 - host: tomcat.test.com http: paths: - path: / backend: serviceName: tomcat-service servicePort: 8080 #查看 [root@101 ~]# kubectl get ing -n dev NAME HOSTS ADDRESS PORTS AGE ingress-http nginx.test.com,tomcat.test.com 10.98.139.205 80 6m20s
修改主机hosts即可访问服务
Https代理
#生成证书
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=test.com"
#创建密钥
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
ingress-https.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-https
namespace: dev
spec:
tls:
- hosts:
- nginx.test.com
- tomcat.test.com
secretName: tls-secret # 指定秘钥
rules:
- host: nginx.test.com
http:
paths:
- path: /
backend:
serviceName: nginx-service
servicePort: 80
- host: tomcat.test.com
http:
paths:
- path: /
backend:
serviceName: tomcat-service
servicePort: 8080
[root@101 ~]# kubectl get ing -n dev
NAME HOSTS ADDRESS PORTS AGE
ingress-http nginx.test.com,tomcat.test.com 10.98.139.205 80 17m
ingress-https nginx.test.com,tomcat.test.com 10.98.139.205 80, 443 5m37s
[root@101 ~]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.98.139.205 <none> 80:31049/TCP,443:32215/TCP 30m
