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:
为了提供 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 资源,将 host 为 example.com,path 为 /get 和 / 的请求路由到后端服务 httpbin 的 8000 端口。
注意这里 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-from 和 pipy.ingress.kubernetes.io/rewrite-target-to 两个注解来配置路径重写,这两个注解需要同时使用。
比如在下面的示例中,在路由规则中定义了路径前缀为 /httpbin 的请求路由到服务 httpbin 的 14001 端口,然而服务 httpbin 本身是没有这个路径的。这时就需要用到路径重写功能了:
综合起来就是将路径起始的 /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(等同于 no、0、off 或者 ),即不保持会话。如若需要保持会话,则需要将值设置为 true、yes、1 或者 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
评论