使用 FSM 管理 osm-edge 服务网格入口流量
背景
Ingress 作为 Kubernetes 集群外部到集群内部应用的访问入口,对进入集群的流量实施管理。Kubernetes Ingress API 采用关注点分离的设计,其中 Ingress 的实现提供了由运维人员管理的入口功能基础设施;同时允许应用程序所有者通过规则来控制到后端请求的路由。
osm-edge 支持多种 Ingress 的实现来对入口流量进行管理,并提供 IngressBackend API 来配置后端服务接收来自可信入口的访问。这篇文章主要介绍 osm-edge 与 FSM 的集成来管理入口流量。
FSM 介绍
FSM[1] 是 Flomesh 的另一款开源产品,用于Kubernetes 南北向的流量管理。FSM 以可编程代理 Pipy 为核心,提供了 Ingress 管理器、Gateway API* 实现、负载均衡器以及跨集群的服务注册发现等功能。
与 FSM 集成
osm-edge 内部已经集成 FSM,可以在安装 osm-edge 时启用 FSM;也可在独立安装 FSM 与现有的 osm-edge 网格中。
前置条件
- • Kubernetes 集群,版本不低于 1.19.0
- • Helm 3 CLI,用于独立安装 FSM
下载 osm-edge CLI:
system=$(uname -s | tr [:upper:] [:lower:])
arch=$(dpkg --print-architecture)
release=v1.1.1
curl -L https://github.com/flomesh-io/osm-edge/releases/download/${release}/osm-edge-${release}-${system}-${arch}.tar.gz | tar -vxzf -
./${system}-${arch}/osm version
cp ./${system}-${arch}/osm /usr/local/bin/
集成式安装
export osm_namespace=osm-system
export osm_mesh_name=osm
osm install --set fsm.enabled=true \
--mesh-name "$osm_mesh_name" \
--osm-namespace "$osm_namespace"
独立安装
如果安装 osm-edge 未启用 FSM,可以使用独立安装的方式来安装。
helm repo add fsm https://charts.flomesh.io
export fsm_namespace=osm-system
helm install fsm fsm/fsm --namespace "$fsm_namespace" --create-namespace
确认所有的 pod 已启动并正常运行。
kubectl get pods -n osm-system
NAME READY STATUS RESTARTS AGE
repo-8756f76fb-2f78g 1/1 Running 0 5m53s
manager-866585bbd5-pbg7q 1/1 Running 0 5m53s
osm-bootstrap-7c6689ff57-47ksk 1/1 Running 0 5m53s
osm-controller-57888cfc7c-tnqxl 2/2 Running 0 5m52s
osm-injector-5f77898899-45f65 1/1 Running 0 5m53s
bootstrap-fd5894bcc-nr7hf 1/1 Running 0 5m53s
cluster-connector-local-68c7584c8b-qf7xm 1/1 Running 0 2m43s
ingress-pipy-6fb8c8b794-pgthl 1/1 Running 0 5m53s
配置
为了通过对访问后端流量的限制来对客户端授权,我们将配置 IngressBackend,这样只有来自 ingress-pipy-controller
端点的入口流量才可以路由到后端服务。为了发现 ingress-pipy-controller
端点,我们需要 osm-edge 控制器及监视相应的命名空间。但是为了保证 FSM 功能正常,不能为其注入 sidecar。
kubectl label namespace "$osm_namespace" openservicemesh.io/monitored-by="$osm_mesh_name"
保存入口网关的外部 IP 地址和端口,后面会用其测试访问后端应用。
export ingress_host="$(kubectl -n "$osm_namespace" get service ingress-pipy-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"
export ingress_port="$(kubectl -n "$osm_namespace" get service ingress-pipy-controller -o jsonpath='{.spec.ports[?(@.name=="http")].port}')"
echo $ingress_host:$ingress_port
部署示例服务
下一步是部署示例 httpbin
服务。
# 创建命名空间kubectl create ns httpbin
kubectl create ns httpbin
# 将命名空间加入到网格中
osm namespace add httpbin
# 部署应用
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: httpbin
namespace: httpbin
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
namespace: httpbin
labels:
app: httpbin
service: httpbin
spec:
ports:
- name: http
port: 14001
selector:
app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
namespace: httpbin
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
template:
metadata:
labels:
app: httpbin
spec:
serviceAccountName: httpbin
containers:
- image: kennethreitz/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
command: ["gunicorn", "-b", "0.0.0.0:14001", "httpbin:app", "-k", "gevent"]
ports:
- containerPort: 14001
EOF
确认 pod 和 service 是否已创建,且应用成功运行。
kubectl get pods,services -n httpbin
NAME READY STATUS RESTARTS AGE
pod/httpbin-54cc8cf5d-7vclc 2/2 Running 0 14s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/httpbin ClusterIP 10.43.105.166 <none> 14001/TCP 14s
配置入口规则
接下来我们要从集群外访问部署的 httpbin
服务,需要提供 ingress 的配置规则。
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: httpbin
namespace: httpbin
annotations:
pipy.ingress.kubernetes.io/rewrite-target-from: /httpbin
pipy.ingress.kubernetes.io/rewrite-target-to: /
spec:
ingressClassName: pipy
rules:
- host: httpbin.org
http:
paths:
- path: /httpbin
pathType: Prefix
backend:
service:
name: httpbin
port:
number: 14001
EOF
使用上面记录的 IP 地址和端口访问 httpbin
服务,将会收到如下 502 Bad Gateway
的错误响应。这是因为我们还未将 FSM 的 ingress 设置为可信入口。
curl -sI http://"$ingress_host":"$ingress_port"/httpbin/get -H "Host: httpbin.org"
HTTP/1.1 502 Bad Gateway
content-length: 0
connection: keep-alive
执行下面的命令,将 FSM ingress 设置为可信入口。
kubectl apply -f - <<EOF
kind: IngressBackend
apiVersion: policy.openservicemesh.io/v1alpha1
metadata:
name: httpbin
namespace: httpbin
spec:
backends:
- name: httpbin
port:
number: 14001 # targetPort of httpbin service
protocol: http
sources:
- kind: Service
namespace: "$osm_namespace"
name: ingress-pipy-controller
EOF
再次尝试请求 httpbin
服务,这时便可以成功访问。
curl -sI http://"$ingress_host":"$ingress_port"/httpbin/get -H "Host: httpbin.org"
HTTP/1.1 200 OK
server: gunicorn/19.9.0
date: Thu, 18 Aug 2022 05:18:50 GMT
content-type: application/json
content-length: 241
access-control-allow-origin: *
access-control-allow-credentials: true
osm-stats-namespace: httpbin
osm-stats-kind: Deployment
osm-stats-name: httpbin
osm-stats-pod: httpbin-54cc8cf5d-7vclc
connection: keep-alive
总结
FSM Ingress 对外暴露了 Kubernetes 集群内的应用访问入口,方便对入口流量进行管理。osm-edge 的 IngressBackend API 为则为网格内服务的对外暴露提供了又一道防线,避免数据的意外泄露。