• Traefik实现Kubernetes集群服务外部https访问


    转载请注明出处:http://www.cnblogs.com/wayneiscoming/p/7707942.html

      traefik 是一个前端http反向代理服务器以及负载均衡器,支持多种微服务后端(Docker,Swarm,Kubernetes,Marathon,Consul,Etcd,Rancher,Amazon ECS等);同 nginx 等相比,traefik 能够自动感知后端服务新增删除升级等变化,并实现自动配置。

    一、Kubernetes 服务暴露介绍

      本节内容节选自漠然博客Traefik-kubernetes初试

      从 kubernetes 1.2 版本开始,kubernetes提供了 Ingress 对象来实现对外暴露服务;到目前为止 kubernetes 总共有三种暴露服务的方式:

    • LoadBlancer Service
    • NodePort Service
    • Ingress

    1.1、LoadBlancer Service

      LoadBlancer Service 是 kubernetes 深度结合云平台的一个组件;当使用 LoadBlancer Service 暴露服务时,实际上是通过向底层云平台申请创建一个负载均衡器来向外暴露服务;目前 LoadBlancer Service 支持的云平台已经相对完善,比如国外的 GCE、DigitalOcean,国内的 阿里云,私有云 Openstack 等等,由于 LoadBlancer Service 深度结合了云平台,所以只能在一些云平台上来使用。

    1.2、NodePort Service

      NodePort Service 顾名思义,实质上就是通过在集群的每个 node 上暴露一个端口,然后将这个端口映射到某个具体的 service 来实现的,虽然每个 node 的端口有很多(0~65535),但是由于安全性和易用性(服务多了就乱了,还有端口冲突问题)实际使用可能并不多。

    1.3、Ingress

      Ingress 这个东西是 1.2 后才出现的,通过 Ingress 用户可以实现使用 nginx 等开源的反向代理负载均衡器实现对外暴露服务,以下详细说一下 Ingress,毕竟 traefik 用的就是 Ingress。

    使用 Ingress 时一般会有三个组件:

    • 反向代理负载均衡器
    • Ingress Controller
    • Ingress

    1.3.1、反向代理负载均衡器

      反向代理负载均衡器很简单,说白了就是 nginx、apache 什么的;在集群中反向代理负载均衡器可以自由部署,可以使用 Replication Controller、Deployment、DaemonSet 等等,不过个人喜欢以 DaemonSet 的方式部署,感觉比较方便。

    1.3.2、Ingress Controller

      Ingress Controller 实质上可以理解为是个监视器,Ingress Controller 通过不断地跟 kubernetes API 打交道,实时的感知后端 service、pod 等变化,比如新增和减少 pod,service 增加与减少等;当得到这些变化信息后,Ingress Controller 再结合下文的 Ingress 生成配置,然后更新反向代理负载均衡器,并刷新其配置,达到服务发现的作用。

    1.3.3、Ingress

      Ingress 简单理解就是个规则定义;比如说某个域名对应某个 service,即当某个域名的请求进来时转发给某个 service;这个规则将与 Ingress Controller 结合,然后 Ingress Controller 将其动态写入到负载均衡器配置中,从而实现整体的服务发现和负载均衡。

    有点懵逼,那就看图

      从上图中可以很清晰的看到,实际上请求进来还是被负载均衡器拦截,比如 nginx,然后 Ingress Controller 通过跟 Ingress 交互得知某个域名对应哪个 service,再通过跟 kubernetes API 交互得知 service 地址等信息;综合以后生成配置文件实时写入负载均衡器,然 后负载均衡器 reload 该规则便可实现服务发现,即动态映射。

    二、Traefik 简介及部署

      由于微服务架构以及 Docker 技术和 kubernetes 编排工具最近几年才开始逐渐流行,所以一开始的反向代理服务器比如 nginx、apache 并未提供其支持,毕竟他们也不是先知;所以才会出现 Ingress Controller 这种东西来做 kubernetes 和前端负载均衡器如 nginx 之间做衔接;即 Ingress Controller 的存在就是为了能跟 kubernetes 交互,又能写 nginx 配置,还能 reload 它,这是一种折中方案;而最近开始出现的 traefik 天生就是提供了对 kubernetes 的支持,也就是说 traefik 本身就能跟 kubernetes API 交互,感知后端变化,因此可以得知: 在使用 traefik 时,Ingress Controller 已经无卵用了,所以整体架构如下:

    2.1、部署 Traefik

      由于我们需要将外部对于kubernetes的http请求全都转换成https,不想更改服务的配置以及代码,那我们可以选择在traefik上配置域名证书,这样通过域名对服务的访问将会自动转换成https请求。我的Kubernetes集群是在微软云上部署的,Node前端使用Azure负载均衡器来均衡请求,所以Traefik我将使用NodePort方式暴露服务。

    2.1.1、创建ClusterRole以及ClusterRoleBinding(Kubernetes1.6+)

      如果你的集群配置了RBAC,则需要赋予Traefik调用Kubernetes API的权限:

    # kubectl create -f ./ClusterRole_Binding.yaml
    ---
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1beta1
    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
    ClusterRole_Binding.yaml

    2.1.2、创建secret保存HTTPS证书

      若没有证书请先生成证书,我本次使用的是现有的域名证书。

    # openssl req -newkey rsa:2048 -nodes -keyout domain.com.key  -x509 -days 365 -out domain.com.crt
    # kubectl create secret generic traefik-cert --from-file=domain.com.crt --from-file=domain.com.key --namespace=kube-system

     

    2.1.3、创建configmap保存Traefik配置文件

      我们这里只做HTTP请求转至HTTPS配置,关于Traefik详细配置请参考官方文档 https://docs.traefik.io/configuration/commons/

    # kubectl create configmap traefik-conf --from-file=traefik.toml --namespace=kube-system
    # cat traefik.toml

    defaultEntryPoints = ["http","https"] [entryPoints] [entryPoints.http] address = ":80" [entryPoints.http.redirect] entryPoint = "https" [entryPoints.https] address = ":443" [entryPoints.https.tls] [[entryPoints.https.tls.certificates]] CertFile = "/ssl/domain.com.crt" KeyFile = "/ssl/domain.com.key"

    2.1.4、通过Deployment部署Traefik

    # kubectl create -f ./traefik-deployment.yaml
    # cat traefik-deployment.yaml
    
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: traefik-ingress-controller
      namespace: kube-system
    ---
    kind: Deployment
    apiVersion: extensions/v1beta1
    metadata:
      name: traefik-ingress-controller
      namespace: kube-system
      labels:
        k8s-app: traefik-ingress-lb
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: traefik-ingress-lb
      template:
        metadata:
          labels:
            k8s-app: traefik-ingress-lb
            name: traefik-ingress-lb
        spec:
          serviceAccountName: traefik-ingress-controller
          terminationGracePeriodSeconds: 60
          volumes:
          - name: ssl
            secret:
              secretName: traefik-cert
          - name: config
            configMap:
              name: traefik-conf
          containers:
          - image: traefik
            name: traefik-ingress-lb
            volumeMounts:
            - mountPath: "/ssl"
              name: "ssl"
            - mountPath: "/config"
              name: "config"
            ports:
            - containerPort: 80
            - containerPort: 443
            args:
            - --configfile=/config/traefik.toml
            - --web
            - --kubernetes
    ---
    kind: Service
    apiVersion: v1
    metadata:
      name: traefik
      namespace: kube-system
    spec:
      type: NodePort
      ports:
      - protocol: TCP
        port: 80
        name: http
      - protocol: TCP
        port: 443
        name: https
      selector:
        k8s-app: traefik-ingress-lb
    traefik-deployment.yaml

    2.1.5、部署traefik-ui服务以及traefik-ui ingress

    # kubectl create -f ./traefik-ui.yaml
    # cat traefik-ui.yaml
    
    apiVersion: v1
    kind: Service
    metadata:
      name: traefik-web-ui
      namespace: kube-system
    spec:
      selector:
        k8s-app: traefik-ingress-lb
      ports:
      - port: 80
        targetPort: 8080
    ---
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: traefik-web-ui
      namespace: kube-system
      annotations:
        kubernetes.io/ingress.class: traefik
    spec:
      tls:
        - secretName: traefik-cert
      rules:
      - host: traefik-ui.domain.com
        http:
          paths:
          - backend:
              serviceName: traefik-web-ui
              servicePort: 80
    traefik-ui.yaml

    2.1.6、创建负载均衡规则后端绑定traefik端口,以及traefik域名解析到负载均衡前端公共IP

      通过traefik-ui.domain.com访问到traefik-ui服务,可以发现网址自动跳转至https协议。

      

      

      

    2.1.7、基于路径访问服务的ingress举例

      先创建3个后端服务:svc1、svc2、svc3,我们希望通过abcd.domain.com/s*的方式来访问服务,因为这样我们只需要添加一个abcd.domain.com域名解析,以下是配置示例:

    # RC for svc1
    kind: ReplicationController
    apiVersion: v1
    metadata:
      name: svc1
    spec:
      replicas: 1
      selector:
      template:
        metadata:
          labels:
            app: svc1
        spec:
          containers:
          - name: svc1
            image: docker.io/patrickeasters/example-web-service
            env:
            - name: APP_SVC
              value: svc1
            ports:
            - containerPort: 8080
              protocol: TCP
    ---
    # RC for svc2
    kind: ReplicationController
    apiVersion: v1
    metadata:
      name: svc2
    spec:
      replicas: 1
      selector:
      template:
        metadata:
          labels:
            app: svc2
        spec:
          containers:
          - name: svc2
            image: docker.io/patrickeasters/example-web-service
            env:
            - name: APP_SVC
              value: svc2
            ports:
            - containerPort: 8080
              protocol: TCP
    ---
    # RC for svc3
    kind: ReplicationController
    apiVersion: v1
    metadata:
      name: svc3
    spec:
      replicas: 1
      selector:
      template:
        metadata:
          labels:
            app: svc3
        spec:
          containers:
          - name: svc3
            image: docker.io/patrickeasters/example-web-service
            env:
            - name: APP_SVC
              value: svc3
            ports:
            - containerPort: 8080
              protocol: TCP
    ---
    # Service for svc1
    kind: Service
    apiVersion: v1
    metadata:
      labels:
        app: svc1
      name: svc1
    spec:
      type: ClusterIP
      ports:
      - port: 8080
        name: http
      selector:
        app: svc1
    ---
    # Service for svc2
    kind: Service
    apiVersion: v1
    metadata:
      labels:
        app: svc2
      name: svc2
    spec:
      type: ClusterIP
      ports:
      - port: 8080
        name: http
      selector:
        app: svc2
    ---
    # Service for svc3
    kind: Service
    apiVersion: v1
    metadata:
      labels:
        app: svc3
      name: svc3
    spec:
      type: ClusterIP
      ports:
      - port: 8080
        name: http
      selector:
        app: svc3
    svc-rc
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: example-web-app
      annotations:
        kubernetes.io/ingress.class: "traefik"
    spec:
      tls:
        - secretName: traefik-cert
      rules:
      - host: abcs.domain.com
        http:
          paths:
          - path: /s1
            backend:
              serviceName: svc1
              servicePort: 8080
          - path: /s2
            backend:
              serviceName: svc2
              servicePort: 8080
          - path: /
            backend:
              serviceName: svc3
              servicePort: 8080
    $ curl -k https://abcd.domain.com/s1
    Hi, I'm the svc1 service!
    Hostname: svc1-sd123
    $ curl -k https://abcd.domain.com/s2
    Hi, I'm the svc2 service!
    Hostname: svc2-isdf3
    $ curl -k https://abcd.domain.com/
    Hi, I'm the svc3 service!
    Hostname: svc3-r23r
    $ curl -k https://abcd.domain.com/xxxx
    Hi, I'm the svc3 service!
    Hostname: svc3-r23r

    本文参考:

    https://mritd.me/2016/12/06/try-traefik-on-kubernetes

    https://medium.com/@patrickeasters/using-traefik-with-tls-on-kubernetes-cb67fb43a948

    官方文档:https://docs.traefik.io/

  • 相关阅读:
    maven之私服搭建
    maven之自定义archetype
    maven之自定义插件
    任务调度之 Elastic Job
    雪花算法原理解析
    基于 zxing 的二维码生成、解析
    spring-cloud-oauth2 认证授权
    spring security 自定义短信验证登录
    spring security session管理
    JDK1.8之HashMap实现原理
  • 原文地址:https://www.cnblogs.com/wayneiscoming/p/7707942.html
Copyright © 2020-2023  润新知