美文网首页Docker
kong与kubernetes集成(ingress)

kong与kubernetes集成(ingress)

作者: GoddyWu | 来源:发表于2018-12-10 17:13 被阅读74次

    Reference

    之前设想kong和k8s结合使用https://docs.konghq.com/install/kubernetes/?_ga=2.265164879.1330610937.1543828237-1627235705.1540276193 中的Kong via Manifest Files方案,对应仓库https://github.com/Kong/kong-dist-kubernetes,即

    • kubectl create -f postgres.yaml
    • kubectl create -f kong_migration_postgres.yaml
    • kubectl delete -f kong_migration_postgres.yaml
    • kubectl create -f kong_postgres.yaml

      但是公司大牛调研后推荐Kubernetes Ingress Controller for Kong的方案,那么我们来看下。

    本文涉及的技术:

    实践

    helm 安装kong

    (helm 是kubernetes的包管理器,这里不再赘述。)

    $ helm search kong
    $ helm fetch stable/kong
    
    这时已下载kong的charts文件到本地,因为我们只会更改它的values.yml文件,所以拷贝一份出来,目录结构类似:

    对于kubernetes ingress来说,ingress controller是核心,这里我们配置ingressController的enabled为true。
    kong会暴露两组端口至外部,一个是admin api(这里为admin), 另一个是resource api(这里为proxy)。因为我们需要使用oauth插件, kong的oauth endpoint必须为https,所以proxy需要使用https,admin可以改为http方便使用。

    # helm启动
    $ helm install --name my-kong kong --namespace kong --values values.yaml 
    
    # helm更新(较慢,需要等kong ns下的kong-upgrade-migrations执行完毕)
    $ helm upgrade my-kong kong -f values.yaml
    
    # 永久删除
    $ helm delete my-kong --purge
    

    配置resource 服务

    这里给一个简单示例

    kind: Service
    apiVersion: v1
    metadata:
      name: python-service
      # annotations:
        # plugins.konghq.com: rl-by-ip
    spec:
      # type: NodePort
      selector:
        app: python
      ports:
        - protocol: TCP
          port: 5000
          # targetPort: 80
          # nodePort: 31203
    ---
    apiVersion: apps/v1beta1
    kind: Deployment
    metadata:
      name: python-deployment
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: python
      template:
        metadata:
          labels:
            app: python
        spec:
          containers:
          - name: python-controller
            image: godbaby/kong-python:1.0
            ports:
            - containerPort: 5000
            #volumeMounts:
           # - mountPath: /code/app.py
              #name: python-volume
          #volumes:
          #- name: python-volume
            #hostPath:
              #path: /Users/goddy/test/kong/docker/resource.py
            # readinessProbe:
            #   httpGet:
            #     path: /debug/version
            #     port: 80
            #   initialDelaySeconds: 5
            #   periodSeconds: 10
            #   successThreshold: 5
            # resources:
            #   requests:
            #     memory: "400Mi"
            #     cpu: "100m"
            #   limits:
            #     memory: "800Mi"
            #     cpu: "200m"
    ---
    

    这里注释的为了方便调试和记住这些配置项,可以忽略。
    注意这里未使用nodePort的方式暴露端口,而是使用clusterIP的方式,来达到kong作为唯一集群外的访问终端。

    配置KongIngress

    Ingress是kubernetes已定义好的资源。
    KongIngress是helm已经帮我们定义好的kubernetes 自定义资源,作为Ingress的额外配置,而且它必须创建于Ingress上(即metadata一致)。

    apiVersion: configuration.konghq.com/v1
    kind: KongIngress
    metadata:
      name: tls-example-ingress
    proxy:
      path: /
    route:
      strip_path: true
    ---
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: tls-example-ingress
      # annotations:
        # plugins.konghq.com: rl-by-ip
        # plugins.konghq.com: oauth
        # ingress.kubernetes.io/rewrite-target: /
    spec:
      rules:
        - host: test 
          http:
            paths:
            - path: /te
              backend:
                serviceName: python-service
                servicePort: 5000
            # - path: /2
            #   backend:
            #     serviceName: python-service
            #     servicePort: 5000
        # - host: dashboard
        #   http:
        #     paths:
        #     - path: /
        #       backend:
        #         serviceName: kong-dashboard
        #         servicePort: 8080
    

    示例中的strip path就是一种常见的需求。

    • 设置成false时(或不设置):资源服务内部分接口生效,Ingress的path类似一个正则过滤器,不符合的则访问不到。
    • true时:比如有两个资源服务,同时想占用同一个域名,如 前端使用www.test.com,而后端使用 www.test.com/api(这样前端直接用`location.origin/api`访问即可),此时就需要开启strip_path.

    kong dashboard

    因为kong-kubernetes ingress的方案提倡声明式的资源,所以GUI其实没啥用。而且目前版本的kong是不可以使用admin api创建数据的。

    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: kong-dashboard
      namespace: kong
    spec:
      # type: NodePort
      selector:
        app: dashboard
      ports:
      - port: 8080
        protocol: TCP
    ---
    
    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: kong-dashboard
      namespace: kong
    spec:
      template:
        metadata:
          labels:
            name: dashboard
            app: dashboard
        spec:
          containers:
          - name: kong-dashboard
            args:
            - start
            - --kong-url http://bot-gateway-kong-admin:8444
            # - --basic-auth admin=admin
            image: pgbi/kong-dashboard:latest
            ports:
            - containerPort: 8080
    

    对于oauth插件来说,还需要创建以下资源

    开启插件

    apiVersion: configuration.konghq.com/v1
    kind: KongPlugin
    metadata:
      name: oauth
    config:
      scopes: read,write
      mandatory_scope: true
      enable_password_grant: true
      global_credentials: true
      provision_key: frh1REQndMbcEVuO1DV4EpWtR7Wnmfac
    plugin: oauth2
    

    config的选项和kong官网的一致,这里不赘述。
    多个Ingress可以声明同一个KongPlugin,理论上kong不支持单服务使用同一个插件,这里kubernetes的方案会自动帮我们创建多个一致的插件到不同服务,只是我们看起来它们同时使用一个kong的oauth插件。

    创建consumer

    apiVersion: configuration.konghq.com/v1
    kind: KongConsumer
    metadata:
      name: team-a
    username: goddy
    ---
    apiVersion: configuration.konghq.com/v1
    kind: KongCredential
    metadata:
      name: credential-a
    consumerRef: team-a
    type: oauth2
    config:
      name: goddy
      client_id: kvcKEfrBn402kZkblQgRwe4j3Fv3A7GH
      client_secret: 3ZwsnUIon3VWafhn39kjJ2iSFT75lFJf
      redirect_uri: http://www.baidu.com
    

    backend服务

    参照https://www.jianshu.com/p/4ddb916d3195方案中的code repo。


    还有一些调研的资料,也分享给大家

    • [x] 泛域名配置
      • 配置*.dev.ruyi.ai或其他直接指向kong的内网host和port即可,通过kong反向代理分配域名(配置service、route)
    • [x] postgreSQL数据保护策略
      • 1)数据volume出来,xxx:/var/lib/postgresql/data
      • 2)手动备份出来
        • pg_dump -U kong kong > /kong.bak
        • docker cp postgresql_postgres_1:/kong.bak /Users/goddy/test/kong/postgresql
        • 导入:pg_dump -U kong kong > /kong.bak
    • [x] postgreSQL数据库故障后的应对策略
      • 1)docker-compose配置healthcheck和restart
        healthcheck:
          test: ["CMD", "pg_isready", "-U", "postgres"]
          interval: 30s
          timeout: 30s
          retries: 3
        restart: on-failure
        
      • 2)docker-compose手动重启
      • 3)bak文件导入
    • [x] kong扩展策略
      • 复用k8s策略
    • [x] 和k8s切合的方案
    • [ ] 在生产环境怎么划分scope
    • [ ] consumer和user对应关系,找一些例子
      • 两种实施方案:
        • consumer与实际用户一一对应
          • 创建:1.通过auth项目验证用户是否存在 2.通过auth项目创建用户: 1)填充uid、scope等信息,创建用户 2)创建用户及其uid对应的consumer至kong 3)添加oauth凭证至consumer
          • 访问:1.auth项目验证用户名密码是否相符 2.通过uid获取到consumer的oauth凭证的client_id和client_secret 3.访问kong获取token
        • 示例项目:https://gist.github.com/ernsheong/b4deb7ce391d43dad6a63272b94b8e2e
        • 优点:kong的consumer是区分用户的最小级别,如果使用kong的log等插件,比较契合。
        • 风险:kong依赖的postgresql需要存储一份用户数据信息,和auth依赖的数据库用户一一对应,每次访问需要请求kong获取一次client信息,[-对于kong kubernetes ingress(声明式)无法实现-]
        • consumer与client对应,即一组用户共用一个client
          • 创建:通过auth项目填充uid、scope等信息,创建用户
          • 登录:auth项目验证用户名密码是否相符,使用公用的client信息,访问kong获取token
        • 优点:简单
        • 风险:用户使用kong的其他登录方式很难做到,
    • [ ] oauth/token地址固定一个
      • oauth插件是基于service或这service下的route的,所以endpoint会在服务的host生成,如hbrainlab.ruyi.ai/oauth2/token, 如果想固定一个地址的话,需要有一个获取token的服务,这个服务要求地址固定,而且生成的token对于其他服务都有效,那么[-其他服务对应的oauth plugin的global creditials需要设置为true-]

    资料:

    相关文章

      网友评论

        本文标题:kong与kubernetes集成(ingress)

        本文链接:https://www.haomeiwen.com/subject/lshicqtx.html