• k8s之HTTP请求负载分发


     

    一、导读

    对于基于HTTP的服务来说,不同的URL地址经常对应不同的后端服务或者虚拟服务器,通常的做法是在应用前添加一个反向代理服务器Nginx,进行请求的负载转发,在Spring Cloud这个微服务框架中,使用zuul网关实现此功能。

    而对于k8s集群来说,当然也是可以用Nginx实现请求的转发,但对于一个成熟的容器编排工具,k8s内置了一个HTTP请求负载分发的组件,就是Ingress Controll。另外,k8s的Service也是具有负载均衡能力的组件。

     

    二、用法

    在定义Ingress之前,需要先部署Ingress Controller,以实现所有后端Service提供一个统一的入口。Ingress Controller需要实现基于不同Http URL向后转发的负载分发规则 。

    在K8s中,Ingress Controller将以Pod的形式运行,监控apiserver的/ingress接口后端的backend services,如果service发生变化,则Ingress Controller应自动更新其转发规则。

    1、创建Ingress Controller

    其实Ingress底层就可以用Nginx实现,Ingress Controller会监听ApiServer,获取全部的Ingress定义,然后根据定义生成Nginx的配置文件。

    下面使用nginx-ingress-controller镜像来创建Ingress Controller。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: nginx-ingress
      namespace: ingress
      labels:
        app: nginx-ingress
    spec:
      replicas: 1
      template:
        metadata:
          name: nginx-ingress
          labels:
            app: nginx-ingress
        spec:
          serviceAccountName: ingress-sc
          containers:
          - name: nginx-ingress
            image: imagia/nginx-ingress-controller:0.32.0
            imagePullPolicy: IfNotPresent
            env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            ports:
            - containerPort: 80
              hostPort: 80
            - containerPort: 443
              hostPort: 443

      

    这里为Nginx容器设置了hostPort,将容器应用监听的80和443端口 号映射到物理机上,使得客户端应用可以通过URL地址“http://物理机 IP:80”或“https://物理机IP:443”来访问该Ingress Controller。这使得Nginx 类似于通过NodePort映射到物理机的Service,成为代替kube-proxy的 HTTP层的Load Balancer:

    2、创建Ingress

    下面的Ingress定义了将/user的请求转发至user-svc的Service上,将/order的请求转发至order-svc的Service上。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: myweb-ingress
      namespace: ingress
    spec:
      rules:
      - host: myweb.com
        http:
          paths:
          - path: /api/user
            backend:
              serviceName: user-svc
              servicePort: 8081
          - path: /api/order
            backend:
              serviceName: order-svc
              servicePort: 8082

      

    Ingress的策略配置:

    (1)所有请求都转发到单个Service上

    此时不用配置rules

    1
    2
    3
    4
    spec:
      backend:
        serviceName: user
        servicePort: 8080

      

    (2)同一域名,不同url转发到不同的服务上

    比如域名都是myweb.com,/api/user转发到user服务,/api/order转发到 order服务。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    spec:
      rules:
      - host: myweb.com
        http:
          paths:
          - path: /api/user
            backend:
              serviceName: user-svc
              servicePort: 8081
          - path: /api/order
            backend:
              serviceName: order-svc
              servicePort: 8082

      

    (3)不同域名

    域名为myweb1.com的请求转发到user服务,域名为myweb2.com的请求转发到order服务

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    spec:
      rules:
      - host: myweb1.com
        http:
          paths:
          - backend:
              serviceName: user-svc
              servicePort: 8081
      - host: myweb2.com
        http:
          paths:
          - backend:
              serviceName: order-svc
              servicePort: 8082

      

    (4)不使用域名

    这种配置用于一个网站不使用域名直接提供服务的场景,此时通过 任意一台运行ingress-controller的Node都能访问到后端的服务。

    1
    2
    3
    4
    5
    6
    7
    8
    spec:
      rules:
      - http:
          paths:
          - path: /api/user
            backend:
              serviceName: user-svc
              servicePort: 8081

      

    【注】使用无域名的Ingress转发规则时,将默认禁用非安全 HTTP,强制启用HTTPS。

    三、案例

    1、简介

    创建一个命名空间:ingress,启动两个服务,一个是user,一个是order,利用Ingress-controller将请求/api/user转发到user服务,将请求/api/order转发到order服务。

    2、创建服务

    (1)创建简单springboot应用

    只有两个api接口,分别是/api/order和/api/user,然后打成jar包上传至服务器

     

     

    (2)将上述jar包创建为镜像

    将jar包、jdk安装包和Dockerfile放在同一个目录

     

    Dockerfile文件内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    FROM centos:7
     
     
    LABEL author=lsy
     
     
    ENV path=/usr/soft
     
     
    RUN mkdir ${path}
     
     
    WORKDIR ${path}
     
     
    ADD jdk-8u191-linux-x64.tar.gz ${path}
     
     
    ENV JAVA_HOME=${path}/jdk1.8.0_191
    ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV PATH=$JAVA_HOME/bin:$PATH
     
     
    COPY service-1.0.jar ${path}
     
     
    EXPOSE 8080
     
     
    CMD  java -jar service-1.0.jar

      

    使用命令创建镜像:

    1
    docker build ./ -t  cnode-1:5000/ingress-service:v1.0

      

    镜像创建完成后记得上传到docker私有仓库

    (3)在ingress命名空间启动相应的ReplicationController和Service

    user-rc.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: user-rc
      namespace: ingress
      labels:
        name: user-rc
    spec:
      replicas: 1
      selector:
        name: user-rc
      template:
        metadata:
          name: user-rc
          labels:
            name: user-rc
        spec:
          containers:
          - name: user-rc
            image: cnode-1:5000/ingress-service:v1.0
            imagePullPolicy: IfNotPresent
            ports:
            - containerPort: 8080

      

    user-svc.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    apiVersion: v1
    kind: Service
    metadata:
      name: user-svc
      namespace: ingress
    spec:
      selector:
        name: user-rc
      ports:
      - port: 8081
        targetPort: 8080

      

    order-rc.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: order-rc
      namespace: ingress
      labels:
        name: order-rc
    spec:
      replicas: 1
      selector:
        name: order-rc
      template:
        metadata:
          name: order-rc
          labels:
            name: order-rc
        spec:
          containers:
          - name: order-rc
            image: cnode-1:5000/ingress-service:v1.0
            imagePullPolicy: IfNotPresent
            ports:
            - containerPort: 8080

      

    order-svc.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    apiVersion: v1
    kind: Service
    metadata:
      name: order-svc
      namespace: ingress
    spec:
      selector:
        name: order-rc
      ports:
      - port: 8082
        targetPort: 8080

      

    分别使用kubectl create 命令创建上述资源

    (4)在ingress命名空间中创建ServiceAccount

    创建ServiceAccount和ClusterRoleBinding,如果不创建的话,Ingress-controller会使用默认名为default的ServiceAccount,default权限很弱,获取不到相应的资源信息,这样Ingress-controller会启动失败。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      labels:
        name: ingress-sc
      name: ingress-sc
      namespace: ingress
     
     
    ---
    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: ClusterRoleBinding
    metadata:
      name: ingress
      labels:
        name: ingress-crb
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
    - kind: ServiceAccount
      name: ingress-sc
      namespace: ingress

      

    (5)创建Ingress Controller

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: nginx-ingress
      namespace: ingress
      labels:
        app: nginx-ingress
    spec:
      replicas: 1
      template:
        metadata:
          name: nginx-ingress
          labels:
            app: nginx-ingress
        spec:
          serviceAccountName: ingress-sc
          containers:
          - name: nginx-ingress
            image: imagia/nginx-ingress-controller:0.32.0
            imagePullPolicy: IfNotPresent
            env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            ports:
            - containerPort: 80
              hostPort: 80
            - containerPort: 443
              hostPort: 443

      

    创建完后查看:

     

    【注】环境变量POD_NAME和POD_NAMESPACE是必须要设置的,不然会报错。

    (6)创建Ingress

    也就是规则设置,将请求地址为/api/user转发至user服务,请求地址为/api/order的转发至order服务。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: myweb-ingress
      namespace: ingress
    spec:
      rules:
      - host: myweb.com
        http:
          paths:
          - path: /api/user
            backend:
              serviceName: user-svc
              servicePort: 8081
          - path: /api/order
            backend:
              serviceName: order-svc
              servicePort: 8082

      

    创建完后查看:

     

    可以看到,它的Hosts是myweb.com,物理机地址是192.168.197.120,端口为80.

    如果ADDRESS列为空, 则通常说明Nginx未能正确连接到后端Service,需要排错。

    【注】为什么只有一个ip,是因为这个RC只有一个Pod,调度到cnode-2这台机运行,如果想要每台机器都有一个,建议使用DaemonSet类型的Controller

    此时查看ingress-controller的Pod的日志:

    先获取Pod的名字

     

    然后查看日志:

     

     

    从上图可以看到,当ingress创建之后,ingress-controller会自动去加载,然后生成对应的nginx的conf文件。

    进入容器查看nginx的配置文件:文件是/etc/nginx/nginx.conf

     

    (7)测试效果

    由于并没有上述设置的myweb.com这个域名,所以需要进行解析。

    1
    curl --resolve myweb.com:80:192.168.197.120 http://myweb.com:80/api/order

      

    访问order服务:

     

    查看日志:可以看到是转发到order-svc这个Service上了

    1
    192.168.197.100 - - [31/Oct/2020:07:40:46 +0000] "GET /api/order HTTP/1.1" 200 21 "-" "curl/7.29.0" 82 0.004 [ingress-order-svc-8082] [] 10.36.0.4:8080 21 0.004 200 0f7dfb1134644ee2ceb7a7d364ddfe45

      

    访问user服务:

     

    查看日志:可以看到是转发到user-svc这个Service上了

    1
    192.168.197.100 - - [31/Oct/2020:07:42:16 +0000] "GET /api/user HTTP/1.1" 200 20 "-" "curl/7.29.0" 81 0.011 [ingress-user-svc-8081] [] 10.44.0.3:8080 20 0.010 200 46f66ab540c41590a74bbea66bd65ea8

      

    ===============================

    我是Liusy,一个喜欢健身的程序员。

  • 相关阅读:
    进销存管理软件,企业ERP如何上线准备,一张图让你明白
    检测行业ERP信息系统(检测行业管理软件)构建,大家猜猜看花了多少银子开发!
    商会协会会员管理系统
    给广大程序员的一封信!尤其是想换行销售的程序员们
    如何利用极致业务基础平台构建一个通用企业ERP之二十多界面显示
    如何利用极致业务基础平台构建一个通用企业ERP之十九过滤器的功能介绍(2)
    快速开发平台如何让开发周期变成原来的十分之一,有图有真相!告别码农的机会!告别公司亏损时代!
    如何利用极致业务基础平台构建一个通用企业ERP之十八如何调用存储过程介绍
    创建新文件(包括上级文件夹),获取外置SD卡的根目录
    c++匿名函数精简写法
  • 原文地址:https://www.cnblogs.com/wjxzs/p/14244481.html
Copyright © 2020-2023  润新知