k8s service与Ingress

什么是service?

service是pod的一个逻辑分组,是pod服务的对外入口抽象。service同样也通过pod的标签来选择pod,与控制器一致。


service提供pod的负载均衡的能力,但是只提供4层负载均衡的能力,而没有7层功能,只能到ip层面。

service的几种类型

  • ClusterIP: 默认类型,自动分配一个仅可在内部访问的虚拟IP。应用方式:内部服务访问
apiVersion: v1
kind: Service
metadata:
  name: service-clusterip
  namespace: test
spec:
  type: ClusterIP
  selector:
    # 选择app=nginx标签的pod
    app: nginx
  ports:
    - protocol: TCP
      # service对外提供的端口
      port: 80
      # 代理的容器的端口 
      targetPort: 80
[root@ master ~]# kubectl get  svc -n test
NAME                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service-clusterip   ClusterIP      172.21.5.140    <none>        80/TCP         3m
  • NodePort:在ClusterIP的基础之上,为集群内的每台物理机绑定一个端口,外网通过任意节点的物理机IP:端口来访问服务。应用方式:外服访问服务
apiVersion: v1
kind: Service
metadata:
  name: service-nodeport
  namespace: test
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - protocol: TCP
      # service对外提供的端口
      port: 80
      # 代理的容器的端口 
      targetPort: 80
      # 在物理机上开辟的端口,从30000开始
      nodePort: 32138
[root@ master ~]# kubectl get  svc -n test
NAME                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service-nodeport    NodePort       172.21.12.122   <none>        80:32138/TCP   4m
  • LoadBalance:在NodePort基础之上,提供外部负载均衡器与外网统一IP,此IP可以将请求转发到对应服务上。这个是各个云厂商提供的服务。应用方式:外服访问服务
apiVersion: v1
kind: Service
metadata:
  name: loadbalance-test
spec:
  ports:
  - name: loadbalance-port
    #service对外提供的端口
    port: 80
    # 代理的容器的端口 
    targetPort: 80
    # 在物理机上开辟的端口,从30000开始
    nodePort: 32138
  selector:
    app: nginx
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip:  云厂商LoadbalanceIP
[root@ master ~]# kubectl get  svc -n test
NAME                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
loadbalance-test    LoadBalancer   172.21.10.152   LoadbalanceIP 80:32138/TCP   4m
  • ExternalName: 引入集群外服的服务,可以在集群内部通过别名方式访问(通过 serviceName.namespaceName.svc.cluster.local访问)
apiVersion: v1
kind: Service
metadata:
  name: service-ext
  namespace: test
spec:
  type: ExternalName
  # 引入外部服务
  externalName: baidu.com
[root@ master ~]# kubectl get  svc -n test
NAME                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service-ext         ExternalName   <none>          baidu.com     <none>         2m

任意找个pod来访问服务,通过kubectl exec -it podname sh 来对pod执行sh命令,这样可以进入容器内部

[root@ master ~]# kubectl exec -it deploy-test-67ccb67d99-2l5wx sh -n test
# ping service-ext.test.svc.cluster.local
PING baidu.com (39.156.69.79): 56 data bytes
64 bytes from 39.156.69.79: icmp_seq=0 ttl=48 time=39.853 ms
64 bytes from 39.156.69.79: icmp_seq=1 ttl=48 time=39.835 ms
^C--- baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 39.835/39.844/39.853/0.000 ms

ingress是干嘛的?

前面聊过,service只能提供4层负载均衡的能力,虽然service可以通过NodePort的方式来服务,但是随着服务的增多,会在物理机上开辟太多端口,管理起来混乱。

那么我们换一种思路来暴露服务,创建一个具有N个副本的nginx服务,在nginx服务内配置各个服务的域名与集群内部的服务的IP,这些nginx服务再通过NodePort的方式来暴露。外部服务通过域名:Nginx NodePort端口来访问nginx,nginx再通过域名反向代理到真实服务。

上面的这个流程就是ingress做的事,ingress分为ingress controller与ingress配置。ingress controller是反向代理服务器,对外通过NodePort(或者其他方式)来暴露,ingress配置是抽象出来的域名代理配置。


一个简单的ingress配置

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-test
  namespace: test
spec:
  rules:
  - host: my.ingress.com
    http:
      paths:
      - path:
        backend:
          serviceName: service-clusterip
          servicePort: 80

Ingress controller的暴露方式

如果采用NodePort的方式,存在Ingress controller单点问题,需要在外层再定义一个HPA,由HPA负载均衡各个Ingress controller节点,域名再解析到HPA的IP。

除了上面的方式,还可以把ingress controller通过LoadBalance方式暴露,LoadBalance在上文中提到过,是service的一种类型,云厂商提供唯一的外网访问IP,域名解析到LoadBalance的IP上。