写点什么

Flomesh Ingress 使用实践(一)基础功能

作者:Flomesh
  • 2023-02-02
    北京
  • 本文字数:6075 字

    阅读完需:约 20 分钟

Flomesh Ingress 使用实践(一)基础功能

Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。提供负载均衡、SSL 终结和基于名称的虚拟托管。为了让 Ingress 资源工作,集群必须有一个正在运行的 Ingress 控制器。


Ingress 控制器 通过监控集群中的 Ingress 资源,对 HTTP 负载均衡器进行配置。


FSM 是 Flomesh 的另一款开源产品,用于 Kubernetes 南北向的流量管理。FSM 以可编程代理 Pipy 为核心,提供了 Ingress 管理器、Gateway API* 实现、负载均衡器以及跨集群的服务注册发现等功能。


从这篇开始,我们将通过多篇文章以演示的方式对 Flomesh Ingress 功能进行介绍。

演示

创建集群

export INSTALL_K3S_VERSION=v1.23.8+k3s2curl -sfL https://get.k3s.io | sh -s - --disable traefik --disable servicelb --write-kubeconfig-mode 644 --write-kubeconfig ~/.kube/config
复制代码

部署架构


安装 Flomesh Ingress

通过 Helm 安装 fsm。


helm repo add fsm https://flomesh-io.github.io/fsmhelm repo update
helm install \ --namespace fsm \ --create-namespace \ --set fsm.version=0.2.1-alpha.2 \ --set fsm.ingress.tls.enabled=true \ --set fsm.serviceLB.enabled=true \ fsm fsm/fsm
复制代码

示例应用

这里使用的示例应用同时提供了 HTTP 8000 和 HTTPS 8443 访问,有下面几个 path


  • / 返回一个简单的 HTML 页面

  • /hi 返回 200 Hi, there!

  • /api/private 返回 401 Staff only


为了提供 HTTPS,需要为应用先签发 ca 和服务端证书。


openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 365000 \ -key ca-key.pem \ -out ca-cert.pem \ -subj '/CN=flomesh.io'
openssl genrsa -out server-key.pem 2048openssl req -new -key server-key.pem -out server.csr -subj '/CN=example.com'openssl x509 -req -in server.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 365
复制代码


部署示例应用,先创建 Secret 将证书和密钥保存在 secret 中并挂载到应用 pod 中。


kubectl create namespace httpbin# mount self-signed cert to sample app pod via secretkubectl create secret generic -n httpbin server-cert \  --from-file=./server-cert.pem \  --from-file=./server-key.pem
kubectl apply -n httpbin -f - <<EOFapiVersion: v1kind: ServiceAccountmetadata: name: httpbin---apiVersion: v1kind: Servicemetadata: name: httpbin labels: app: httpbin service: httpbinspec: ports: - port: 8443 name: https - port: 8000 name: http selector: app: httpbin---apiVersion: apps/v1kind: Deploymentmetadata: name: httpbin labels: app: httpbinspec: replicas: 1 selector: matchLabels: app: httpbin template: metadata: labels: app: httpbin spec: containers: - name: pipy image: addozhang/httpbin:latest env: - name: PIPY_CONFIG_FILE value: /etc/pipy/tutorial/gateway/main.js ports: - containerPort: 8443 - containerPort: 8000 volumeMounts: - name: cert mountPath: "/etc/pipy/tutorial/gateway/secret" readOnly: true volumes: - name: cert secret: secretName: server-certEOF
复制代码

基础配置

HTTP 入口

下面的示例中,定义了 Ingress 资源,将 hostexample.compath/get/ 的请求路由到后端服务 httpbin8000 端口。


注意这里 Ingress 资源与后端服务应属于同一命名空间。


apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: httpbinspec:  ingressClassName: pipy  rules:  - host: example.com    http:      paths:        - path: /          pathType: Exact          backend:            service:              name: httpbin              port:                number: 8000        - path: /hi          pathType: Exact          backend:            service:              name: httpbin              port:                number: 8000
复制代码


这里我们对部分字段进行说明:


  • metadata.name 字段定义了 Ingress 的资源名。

  • spec.ingressClassName 字段用于指定入口控制器的实现。ingressclass 是各个入口控制器实现定义的名字,这里我们用 pipy。通过 kubectl get ingressclass 可以查看已安装的入口控制器。

  • spec.rules 字段用于定义路由资源。

  • host 字段中定义了主机名 example.com

  • paths 字段定义了两个路径规则:匹配路径为 / 的请求,以及前缀为 /hi 的请求

  • backend 字段定义了用于处理该路径规则的后端服务 httpbin 以及端口 8000


查看 Ingress Controller Service,可以看到其类型是 LoadBalancer,且外部地址为 10.0.0.12,正好就是节点的 IP 地址。


kubectl get svc -n fsm -l app.kubernetes.io/component=controllerNAME                          TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGEfsm-ingress-pipy-controller   LoadBalancer   10.43.144.20   10.0.0.12     80:30508/TCP,443:30607/TCP   10m
复制代码


应用上面的 Ingress 配置。


在访问 httpbin 服务的 /hi/ 端点时,我们可以使用节点的 IP 地址以及端口 80


export HOST_IP=10.0.0.12curl http://example.com/hi --connect-to example.com:80:$HOST_IP:80Hi, there!
curl http://example.com/ --connect-to example.com:80:$HOST_IP:80<!DOCTYPE html><html> <head> <title>Hi, Pipy!</title> </head> <body> <h1>Hi, Pipy!</h1> <p>This is a web page served from Pipy.</p> </body></html>
复制代码

HTTPS 入口

这个示例演示了如果配置入口控制器支持 HTTPS 访问。


FSM Ingress 默认是不启用 TLS 入口的,在安装时需要通过参数 --set fsm.ingress.tls.enabled=true 打开 TLS 入口功能。


下面的例子中的 Ingress 资源,配置了 https://example.com 访问入口。


  • 字段 spec.tls 是 TLS 配置的专属字段,可以配置多个 HTTPS 入口。

  • hosts 字段用于配置 SNI,可以配置多个 SNI。这里使用 example.com,也可以支持通配符 *.example.com

  • secretName 字段用于指定保存了证书和密钥的 Secret。注意 Ingress 资源和 Secret 应同属于一个命名空间。


apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: httpbinspec:  ingressClassName: pipy  rules:  - host: example.com    http:      paths:        - path: /          pathType: Prefix          backend:            service:              name: httpbin              port:                number: 8000  tls:  - hosts:    - example.com    secretName: ingress-cert
复制代码


签发证书。


openssl req -x509 -newkey rsa:4096 -keyout ingress-key.pem -out ingress-cert.pem -sha256 -days 365 -nodes -subj '/CN=example.com'
复制代码


使用证书和密钥创建 Secret。


kubectl create secret tls ingress-cert --cert=ingress-cert.pem --key=ingress-key.pem -n httpbin
复制代码


使用服务 ingress-cert.pem 作为 ca 证书发起请求进行测试,注意目前是禁用 Ingress mTLS 功能。


curl --cacert ingress-cert.pem https://example.com/hi --connect-to example.com:443:$HOST_IP:443Hi, there!
复制代码

进阶配置

接下来,我们介绍下 FSM Ingress 的高阶配置。高阶配置是通过 Ingress 资源的 metadata.annotations 字段进行设置的。目前支持的功能有:


  • 路径重写

  • 指定负载均衡算法

  • 会话保持

路径重写

这个例子演示如何使用路径重写的注解。


FSM 提供了 pipy.ingress.kubernetes.io/rewrite-target-frompipy.ingress.kubernetes.io/rewrite-target-to 两个注解来配置路径重写,这两个注解需要同时使用。


比如在下面的示例中,在路由规则中定义了路径前缀为 /httpbin 的请求路由到服务 httpbin14001 端口,然而服务 httpbin 本身是没有这个路径的。这时就需要用到路径重写功能了:


  • pipy.ingress.kubernetes.io/rewrite-target-from: ^/httpbin/? ,这里支持正则表达式,将路径起始的 /httpbin/ 进行重写

  • pipy.ingress.kubernetes.io/rewrite-target-to: /,这里指定了重写的内容是 /


综合起来就是将路径起始的 /httpbin/ 替换 /,比如 /httpbin/get 会被重写成 /get


apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: httpbin  annotations:    pipy.ingress.kubernetes.io/rewrite-target-from: ^/httpbin/?    pipy.ingress.kubernetes.io/rewrite-target-to: /spec:  ingressClassName: pipy  rules:  - host: example.com    http:      paths:        - path: /httpbin          pathType: Prefix          backend:            service:              name: httpbin              port:                number: 8000
复制代码


应用上面的 Ingress 配置。


现在我们要使用 /httpbin/hi 作为路径来访问 httpbin 的 /hi 端点。


curl http://example.com/httpbin/hi --connect-to example.com:80:$HOST_IP:80Hi, there!
复制代码

指定负载均衡算法

这个例子用于演示在后端存在多个实例时,指定路由的负载均衡算法。


默认情况下 FSM Ingress 使用 Round-Robin 负载均衡算法,可以通过注解 pipy.ingress.kubernetes.io/lb-type 指定其他的算法:


  • round-robin

  • hashing

  • least-work


在下面的示例中,通过注解指定使用 hashing 负载均衡算法。


apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: httpbin  annotations:    pipy.ingress.kubernetes.io/lb-type: 'hashing'spec:  ingressClassName: pipy  rules:  - host: example.com    http:      paths:        - path: /          pathType: Prefix          backend:            service:              name: httpbin              port:                number: 8000
复制代码


为了直观展示演示效果,部署下面的示例应用,这个应用有 2 个实例,并在响应中携带主机名便于区分响应请求的示例。


kubectl create namespace httpbinkubectl apply -n httpbin -f - <<EOFapiVersion: v1kind: ServiceAccountmetadata:  name: httpbin---apiVersion: v1kind: Servicemetadata:  name: httpbin  labels:    app: httpbin    service: httpbinspec:  ports:  - name: http    port: 8000  selector:    app: httpbin---apiVersion: apps/v1kind: Deploymentmetadata:  name: httpbin  labels:    app: httpbinspec:  replicas: 2  selector:    matchLabels:      app: httpbin  template:    metadata:      labels:        app: httpbin    spec:      containers:      - name: pipy        image: addozhang/httpbin:latest        ports:          - containerPort: 8000        command:        - pipy        - -e        - |          pipy()          .listen(8000)          .serveHTTP(new Message('Response from pod ' + os.env["HOSTNAME"]))EOF
复制代码


应用上面的 Ingress 配置,然后发送请求进行测试。


curl http://example.com/ --connect-to example.com:80:$HOST_IP:80Response from pod httpbin-5f69c44674-t9cxccurl http://example.com/ --connect-to example.com:80:$HOST_IP:80Response from pod httpbin-5f69c44674-t9cxccurl http://example.com/ --connect-to example.com:80:$HOST_IP:80Response from pod httpbin-5f69c44674-t9cxc
复制代码

会话保持

这个示例用于演示会话保持功能。


FSM Ingress 提供了注解 pipy.ingress.kubernetes.io/session-sticky 来配置会话保持,默认值为 false(等同于 no0off 或者 ),即不保持会话。如若需要保持会话,则需要将值设置为 trueyes1 或者 on


比如下面的例子中,将注解值设置为 true,用于在后端服务的两个实例之间进行会话保持。


apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: httpbin  annotations:    pipy.ingress.kubernetes.io/session-sticky: 'true'spec:  ingressClassName: pipy  rules:  - host: example.com    http:      paths:        - path: /          pathType: Prefix          backend:            service:              name: httpbin              port:                number: 8000
复制代码


为了直观展示演示效果,部署下面的示例应用,这个应用有 2 个实例,并在响应中携带主机名便于区分响应请求的示例。


kubectl create namespace httpbinkubectl apply -n httpbin -f - <<EOFapiVersion: v1kind: ServiceAccountmetadata:  name: httpbin---apiVersion: v1kind: Servicemetadata:  name: httpbin  labels:    app: httpbin    service: httpbinspec:  ports:  - name: http    port: 8000  selector:    app: httpbin---apiVersion: apps/v1kind: Deploymentmetadata:  name: httpbin  labels:    app: httpbinspec:  replicas: 2  selector:    matchLabels:      app: httpbin  template:    metadata:      labels:        app: httpbin    spec:      containers:        - name: pipy          image: addozhang/httpbin:latest          ports:            - containerPort: 8000          command:            - pipy            - -e            - |              pipy()              .listen(8000)              .serveHTTP(new Message('Response from pod ' + os.env["HOSTNAME"]))EOF
复制代码


应用上面的 Ingress 配置,多次请求进行测试,可以发现都是同一个实例进行响应。


curl http://example.com/ --connect-to example.com:80:$HOST_IP:80Response from pod httpbin-5f69c44674-hrvqpcurl http://example.com/ --connect-to example.com:80:$HOST_IP:80Response from pod httpbin-5f69c44674-hrvqpcurl http://example.com/ --connect-to example.com:80:$HOST_IP:80Response from pod httpbin-5f69c44674-hrvqp
复制代码

总结

本篇我们主要介绍了 FSM Ingress 的基础功能,包括 HTTP、HTTPS 以及在 7 层上流量处理能力。


在下一篇,我们将会围绕 TLS 能力来介绍 FSM Ingress 的进阶功能。


引用链接

[1] Ingress: https://kubernetes.io/docs/concepts/services-networking/ingress/

[2] Ingress 控制器: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/

[3] FSM: https://github.com/flomesh-io/fsm

[4] Pipy: https://github.com/flomesh-io/pipy

发布于: 刚刚阅读数: 3
用户头像

Flomesh

关注

微信订阅号:flomesh 2022-04-07 加入

一站式云原生应用流量管理供应商 官网:https://flomesh.io

评论

发布
暂无评论
Flomesh Ingress 使用实践(一)基础功能_负载均衡_Flomesh_InfoQ写作社区