Istio 服务网格自带 ingress,但我们经常看到有要求使用非 Istio ingress 的客户。此前,我们已经介绍过将 NGINX 与 Istio 集成的情况。最近,我们一直在与使用 Traefik ingress 的客户合作。通过对我们之前建议的方法进行一些轻微调整,我将向你介绍如何实现 Traefik 作为 Istio 服务网格的入口网关。
流量的流向如下图所示。一旦请求从 Traefik Ingress 到达服务网格,Istio 就能够对请求应用安全性、可观测性和流量引导规则。
传入的流量绕过 Istio sidecar,直接到达 Traefik,所以请求终止在 Traefik ingress。
Traefik 使用 IngressRoute
配置重写 Host 头以匹配目的地,并将请求转发到目标服务,这是一个多步骤的过程。
PeerAuthentication
策略要求使用 STRICT mTLS),然后将请求转发到目标服务的 pod。下面是一个端到端的部署示例,使用 Istio 的 bookinfo 演示应用,但用 Traefik ingress 来支撑整个部署。简而言之,要想在自己的环境中实现这个功能。
# Exclude the ports that Traefik receives traffic on
traffic.sidecar.istio.io/excludeInboundPorts: “80”
# Make sure Traefik controller can talk to the Kubernetes API server
traffic.sidecar.istio.io/excludeOutboundIPRanges: X.X.X.X/32
Middleware
对象创建 IngressRoute
,将主机名改写为网格识别的主机名(即集群中的服务;下文将通过一个例子详细讨论)。这篇文章的其余部分涵盖了部署 Istio 的 Bookinfo 示例应用程序,使用 Traefik 作为部署的 Ingress 代理。
参考以下步骤。
gcloud container clusters create istio-traefik \
--cluster-version=1.17 \
--region <GCP region> \
--machine-type=e2-standard-4 \
--project <GCP Project> \
--num-nodes 1 \
--node-locations <GCP Zone> # i.e us-west2-b (otherwise 1 node per zone)
curl -sL https://git.io/getLatestIstio |\
ISTIO_VERSION=1.8.1 sh -
./istio-1.8.1/bin/istioctl install \
--set meshConfig.accessLogFile=/dev/stdout \
--skip-confirmation
安装好 Istio 后,我们就可以开始部署我们的应用程序了。我们将使用 Istio 的 Bookinfo 应用程序进行演示。这个示例应用程序是 Istio 发行版的一部分(在./istio-1.8.1/samples/
文件夹中)。
kubectl create ns bookinfo
kubectl label namespace bookinfo istio-injection=enabled
kubectl apply -f istio-1.8.1/samples/bookinfo/platform/kube/bookinfo.yaml -n bookinfo
确认所有的吊舱都已启动,并部署了侧车。
启用 Istio mTLS 为应用程序命名空间的服务到服务通信。
cat <<EOF | kubectl apply -f -
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: bookinfo
spec:
mtls:
mode: STRICT
EOF
现在是时候按照 v2.3 文档来部署 Traefik 了(本篇文章中 Traefik 的最新版本是 2.3,但如果你根据你的版本调整了 IngressRoute
和 Middleware
资源,它将适用于任何版本的 Traefik)。
$ kubectl apply -f http://bit.ly/Traefik-CRDs-and-Roles
customresourcedefinition.apiextensions.k8s.io/ingressroutes.traefik.containo.us created
customresourcedefinition.apiextensions.k8s.io/middlewares.traefik.containo.us created
customresourcedefinition.apiextensions.k8s.io/ingressroutetcps.traefik.containo.us created
customresourcedefinition.apiextensions.k8s.io/ingressrouteudps.traefik.containo.us created
customresourcedefinition.apiextensions.k8s.io/tlsoptions.traefik.containo.us created
customresourcedefinition.apiextensions.k8s.io/tlsstores.traefik.containo.us created
customresourcedefinition.apiextensions.k8s.io/traefikservices.traefik.containo.us created
clusterrole.rbac.authorization.k8s.io/traefik-ingress-lb created
clusterrolebinding.rbac.authorization.k8s.io/traefik-ingress-lb created
Type: Loadbalancer
是为了告诉 GCP 给服务分配一个外部 IP。cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: traefik
namespace: bookinfo
spec:
ports:
- protocol: TCP
name: web
port: 80
- protocol: TCP
name: admin
port: 8080
selector:
app: traefik-ingress-lb
type: LoadBalancer
EOF
$ kubectl get svc traefik -n bookinfo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
traefik LoadBalancer 10.35.244.227 35.236.XXX.XXX 80:31718/TCP,8080:31334/TCP 2m6s
ServiceAccount
的 Kubernetes 部署。除了名称和命名空间,网站示例还引入了以下变化。Accesslog
:增加了 =true
,因为没有这个值就不行。Log.level
设置为 DEBUG 将帮助我们看到发生了什么。traffic.sidecar.istio.io
注释(更多细节请参考之前提到的 Tetrate NGINX 文章)。KUBERNETES_SVC_IP=$( kubectl get svc kubernetes -n default -o jsonpath='{.spec.clusterIP}' )
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: bookinfo
name: traefik-ingress-lb
---
kind: Deployment
apiVersion: apps/v1
metadata:
namespace: bookinfo
name: traefik-ingress-lb
labels:
app: traefik-ingress-lb
spec:
replicas: 1
selector:
matchLabels:
app: traefik-ingress-lb
template:
metadata:
labels:
app: traefik-ingress-lb
annotations:
traffic.sidecar.istio.io/excludeInboundPorts: "80"
traffic.sidecar.istio.io/excludeOutboundIPRanges: ${KUBERNETES_SVC_IP}/32
spec:
serviceAccountName: traefik-ingress-lb
containers:
- name: traefik-ingress-lb
image: traefik:v2.3
args:
- --api.insecure
- --accesslog=true
- --providers.kubernetescrd
- --entrypoints.web.address=:80
- --log.level=DEBUG
ports:
- name: web
containerPort: 80
- name: admin
containerPort: 8080
EOF
$ kubectl get pods -n bookinfo -l app=traefik-ingress-lb
NAME READY STATUS RESTARTS AGE
traefik-ingress-lb-669fc4b77d-74mpx 2/2 Running 0 2m35s
BOOKINFO_IP=$(kubectl -n bookinfo get service traefik -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl -I $BOOKINFO_IP
确保它返回“404 Not Found”—— 由于尚未实施 Ingress 规则,所以预计会有 not-200 响应。
Middleware
头重写功能将使 Istio 服务网格正常运行。本例中,需要将主机定义为 productpage.bookinfo.svc
。头可以根据 Traefik 文档来定义。cat <<EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: productpage-header
namespace: bookinfo
spec:
headers:
customRequestHeaders:
Host: productpage.bookinfo.svc
EOF
cat <<EOF | kubectl apply -f -
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: productpage
namespace: bookinfo
spec:
entryPoints:
- web
routes:
- match: PathPrefix(`/`)
kind: Rule
middlewares:
- name: productpage-header
services:
- name: productpage
port: 9080
EOF
curl -I $BOOKINFO_IP
我们会收到“200 OK“的回复。也可以通过浏览器测试,使用 http://<BOOKINFO_IP>/productpage
。
http://<BOOKINFO_IP>/productpage
,就会返回应用响应。TRAEFIK_POD=$( kubectl -n bookinfo get pods -l app=traefik-ingress-lb -o jsonpath='{.items[0].metadata.name}' )
kubectl -n bookinfo logs ${TRAEFIK_POD} -c istio-proxy
请注意,请求处理后,日志需要几秒钟才能显示。只有在 Istio 安装时使用 meshConfig.accessLogFile=/dev/stdout
标志的情况下,才会显示日志。
[2021-01-05T20:13:55.015Z] "GET /productpage HTTP/1.1" 200 - "-" 0 5179 1069 1069 "10.32.0.1" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" "4bd443e9-1a2e-4d30-b1e3-398a5005f240" "productpage.bookinfo.svc" "10.32.0.18:9080" outbound|9080||productpage.bookinfo.svc.cluster.local 10.32.0.19:51810 10.32.0.18:9080 10.32.0.1:0 - default
[2021-01-05T20:13:56.301Z] "GET /static/bootstrap/fonts/glyphicons-halflings-regular.woff2 HTTP/1.1" 200 - "-" 0 18028 3 3 "10.32.0.1" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" "8cb44552-c3c8-45dd-8674-4af207ce1648" "productpage.bookinfo.svc" "10.32.0.18:9080" outbound|9080||productpage.bookinfo.svc.cluster.local 10.32.0.19:51810 10.32.0.18:9080 10.32.0.1:0 - default
本文演示了如何将 Traefik Ingress 作为 Istio 服务网格的入口点。这里应用的基本方法应该是适用的,即使你的环境与我们例子中使用的环境不同。当引入服务网格时,Traefik / 服务网格集成可以在不同的云中成功实施,并使用全新或现有(也就是棕地)部署 Traefik。最终,您将获得两者最好的东西:Istio 服务网格与您所选择的 Ingress 控制器相集成!
最后更新于 2024/12/03