Service介绍

三种模式

userspace模式

userspace模式,kube-proxy会为每一个Service创建一个监听端口,请求经过kube-proxy,相当于一个四层负责均衡器,kube-proxy运行在userspace中,在进行转发处理时会增加内核和用户空间之间的数据拷贝,虽然稳定,但是效率很低

usersoace.png

iptables模式

iptables模式下,kube-proxy为service后端每个pod创建对应的iptables规则,直接将发向Cluster IP的请求重定向到一个Pod IP 该模式下kube-proxy不承担四层负载均衡器的作用,只负责创建iptables规则,较userspace模式效率更高,不能提供灵活的LB策略,当后端pod不可用时无法进行重试

iptables.png

ipvs模式

ipvs模式和iptables类似,kube-proxy监控pod的变化并创建相应的ipvs规则,ipvs相对iptables转发效率更高,支持更多的LB算法

ipvs.png 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实现的

endpoint.png

[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

NodePort.png

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会在集群外部在做一个负载均衡,这个设备需要外部环境支持,外部环境发送到这个设备上的请求会被设备负载之后转发到集群中

LoadBalancer.png

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.png

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服务中,并动态更新
  • 到此为止 Ingress1.png

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即可访问服务

nginx-tomcat.png

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
![ingress-https.png](https://blog.xwnlearn.cn/api/v1/look_images/ingress-https.png)