K8S系列 -- Service资源和Ingress资源

一、Service资源

        上一篇博客中我们介绍了pod控制器,通过pod控制器可以帮我们来管理我们的pod,当我们的pod异常退出时,我们的pod控制器可以自动的为我们拉起新的pod,但是此时就会出现一个问题,当我们的pod重建时,pod的IP地址是随机获取的,这就意味着新的pod的地址是会改变的。这很明显不科学,我们不可能每次访问应用的时候都去查看某个pod的IP地址,况且我们在很多情况下需要多个pod来分担用户请求,这就意味着,我们不能直接访问pod的地址。

        为了解决这个问题,K8S引入了Service资源,Service资源就是架在pod之上的一层新的服务,当我们创建Service资源时,我们需要指定这些服务对应的后端的pod有哪些,然后K8S会自动为我们的Service分配一个IP地址,这个IP地址是不会轻易改变的,还会将Service和提供对应服务的pod做一个绑定,这样一来,当用户需要访问应用时,就可以通过访问Service的方式来访问pod,当pod地址发生改变时,Service也会立马感知这一改变,更新Service和pod的映射关系。

        那么,Service资源是如何发现这些pod的呢?答案是通过标签选择器,在创建Service资源时要指定标签选择器,后端拥有这些标签的pod会被注册到Service上。

        Service资源主要有如下几种类型:

        ExternalName:将集群外部的服务发布至集群中时使用

        ClusterIP:默认的资源Service类型,创建此类型时K8S会为该服务分配一个IP地址,这个IP地址称为集群IP,且这个IP地址不会发生改变,用户可以通过这个IP地址来访问服务。

        NodePort:此类型的服务会在宿主机上监听一个端口,用户可以直接通过访问宿主机的IP及端口来访问此服务,一般不推荐使用此种类型的Service资源,除非明确知道宿主机上的端口没有被占用。

        LoadBalancer:此类型的Service建立在NodePort类型之上,此类型的Service会关联至集群外部的一个负载均衡器上,这个集群外部的负载均衡器通过NodePort向集群内部转发流量。

        我们可以通过资源配置清单来创建一个Service资源,接下来我们就看下Service资源的资源配置清单中有哪些主要的配置:

kind: Service
apiVersion: v1
metadata:
  name: myapp-v1
  namespace: default
spec: 
  type: ClusterIP
  selector: 
    app: myapp-dp
    release: v1
  ports: 
    - name: http
      port: 80
      targetPort: 80

        我们主要看下spec字段下的内容:

        spec.type:指定Service类型,当类型为ClusterIP时此字段也可以省略

        spec.selector:标签选择器,Service资源会根据此处定义的标签去选择关联的pod。

        spec.ports:指定服务暴露的端口列表,可以暴露多个端口,其下级字段有:

          spec.ports.name:Service的端口名称

          spec.ports.port:Service的端口号,此项为必填项

          spec.ports.targetPort:后端pod上的端口

          spec.ports.nodePort:当Service类型为NodePort时,用来指定Node节点上使用的端口号。

          spec.ports.protocol:Service端口协议,默认是TCP,可选TCP/UDP/SCTP

        除了上述说到的配置外,Service还支持基于客户端IP的Session粘性,即同一客户端IP在一段时间内会分配到同一个后端的pod上。可以通过如下配置来设置:

        spec.sessionAffinity:是否启用Session粘性,其值可选None或ClientIP,默认是None,选择ClientIP后表示启用Session粘性。

        spec.sessionAffinityConfig:用来配置粘性时间,其通过下级字段来配置:

          spec.sessionAffinityConfig.clientIP.timeoutSeconds:粘性时间,在此时间内保持Session粘性特性,超时后调度算法会重新调度,默认值是10800秒,其取值范围是0~86400秒。

二、Ingress资源和服务暴露

        上文中我们介绍了Service资源,通过Service资源我们就可以很方便的来访问我们的应用,一般情况下,我们的Service资源都是在集群内部可以访问的,如果我们在集群外部想要访问我们的应用就会不太方便,当然,我们可以通过NodePort型的Service资源来实现绑定到宿主机上某个端口的形式,通过访问宿主机来访问我们的应用。但是这样会使得我们的Service必须占用一个宿主机的端口,一旦这个端口被占用的话,我们的应用就无法继续访问,这样就会带来故障恢复上的不方便以及部分资源的浪费。而且在这种架构下,集群外的用户在访问服务时要访问宿主机的IP,如果宿主机出现宕机的情况,用户将无法访问到应用,这就使得K8S失去了很大一部分意义。

        对于http及https类型的应用,为了解决这个问题,K8S引入了Ingress类型的资源,Ingress资源实际上就是一组路由条目的集合,其可以通过用户访问的主机名及URL来分配用户流量到后端正确的服务中。

        除此之外,在Ingress上我们还可以做https的证书卸载,这样我们的应用中就不需要部署https了。

        在部署Ingress时我们需要先部署一个Ingress Controller,这个Ingress Controller就是来为我们生成Ingress规则的,其实简单点来说,Ingress就是一组nginx的配置,Ingress Controller就是用来生成这组规则的组件。常见的Ingress Controller有以下几种:

        Ingress-Nginx

        Haproxy

        traefik

        我们这次部署treafik来作为我们的Ingress Controller。

    1、拉取traefik镜像并上传到我们的Harbor仓库

[root@K8S7-200 ~]# docker pull traefik:v1.7
[root@K8S7-200 ~]# docker image ls | grep traefik
traefik                v1.7                 96c63a7d3e50        2 months ago        85.7MB
[root@K8S7-200 ~]# docker tag 96c63a7d3e50 harbor.od.com/public/traefik:v1.7
[root@K8S7-200 ~]# docker push harbor.od.com/public/traefik:v1.7

    2、准备资源配置清单:

[root@K8S7-200 traefik]# pwd
/data/k8s-yaml/traefik
[root@K8S7-200 traefik]# cat rbac.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-ingress-controller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: traefik-ingress-controller
rules:
  - apiGroups:
      - ""
    resources:
      - services
      - endpoints
      - secrets
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: traefik-ingress-controller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
  name: traefik-ingress-controller
  namespace: kube-system

[root@K8S7-200 traefik]# cat ds.yaml 
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: traefik-ingress
  namespace: kube-system
  labels:
    k8s-app: traefik-ingress
spec:
  template:
    metadata:
      labels:
        k8s-app: traefik-ingress
        name: traefik-ingress
    spec:
      serviceAccountName: traefik-ingress-controller
      terminationGracePeriodSeconds: 60
      containers:
      - image: harbor.od.com/public/traefik:v1.7
        name: traefik-ingress
        ports:
        - name: controller
          containerPort: 80
          hostPort: 81
        - name: admin-web
          containerPort: 8080
        securityContext:
          capabilities:
            drop:
            - ALL
            add:
            - NET_BIND_SERVICE
        args:
        - --api
        - --kubernetes
        - --logLevel=INFO
        - --insecureskipverify=true
        - --kubernetes.endpoint=https://10.4.7.10:7443
        - --accesslog
        - --accesslog.filepath=/var/log/traefik_access.log
        - --traefiklog
        - --traefiklog.filepath=/var/log/traefik.log
        - --metrics.prometheus

[root@K8S7-200 traefik]# cat svc.yaml
kind: Service
apiVersion: v1
metadata:
  name: traefik-ingress-service
  namespace: kube-system
spec:
  selector:
    k8s-app: traefik-ingress
  ports:
    - protocol: TCP
      port: 80
      name: controller
    - protocol: TCP
      port: 8080
      name: admin-web

[root@K8S7-200 traefik]# cat ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: traefik-web-ui
  namespace: kube-system
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: traefik.od.com
    http:
      paths:
      - path: /
        backend:
          serviceName: traefik-ingress-service
          servicePort: 8080

    3、添加域名解析

        解析 traefik.od.com 到10.4.7.10,及我们集群入口的vip地址

    4、配置nginx转发

        将所有访问*.od.com域名的流量转发至我们的Ingress处理

[root@K8S7-11 conf.d]# pwd
/etc/nginx/conf.d
[root@K8S7-11 conf.d]# cat od.com.conf 
upstream default_backend_traefik {
    server 10.4.7.21:81    max_fails=3 fail_timeout=10s;
    server 10.4.7.22:81    max_fails=3 fail_timeout=10s;
}
server {
    server_name *.od.com;
  
    location / {
        proxy_pass http://default_backend_traefik;
        proxy_set_header Host       $http_host;
        proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
    }
}

    5、创建资源

[root@K8S7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/traefik/rbac.yaml
[root@K8S7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/traefik/ds.yaml
[root@K8S7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/traefik/svc.yaml
[root@K8S7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/traefik/ingress.yaml

    6、浏览器访问traefik.od.com测试