安装 Gateway
除了创建服务网格,Istio 还允许您管理网关, 作为 Envoy 代理运行在网格的边缘处,以精细粒度控制进出网格的流量。
Istio 内置的一些配置文件在安装期间部署网关。
例如通过默认设置对
istioctl install
的调用将部署 Ingress 网关和控制面。
尽管在评估和简单使用场景中这个够用了,但耦合到控制面的网关后,
会让管理和升级变得复杂。对于生产环境中的 Istio 部署,
强烈推荐将这些解耦,以便进行独立的操作。
遵循本指南在 Istio 的生产安装环境中分别部署和管理一个或多个网关。
先决条件
本指南需要先安装好 Istio 控制面,再继续操作。
部署网关
使用与 Istio Sidecar 注入相同的机制, 可以用类似的方式自动注入网关所用的 Envoy 代理配置。
对于网关 Deployment 推荐使用自动注入, 因为这样可以让开发者完全控制网关 Deployment,简化了操作。 当新的升级可用时或配置发生变化时,只需重启就能更新网关 Pod。 这使得操作网关 Deployment 的体验与操作 Sidecar 的体验相同。
为了支持用户使用现有的部署工具,Istio 提供了几种不同的方式来部署网关。 每种方法都会产生相同的结果。请选择您最熟悉的方法。
以下列出的所有方法均依赖于注入,
在运行时填充附加的 Pod 设置。为此,
部署网关所在的命名空间不得带有 istio-injection=disabled
标签。
如果带有此标签,您会看到 Pod 在尝试拉取 auto
镜像时失败,
此镜像是创建 Pod 时将要替换的占位符。
首先设置名为 ingress.yaml
的 IstioOperator
配置文件:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: ingress
spec:
profile: empty # 不安装 CRD 或控制平面
components:
ingressGateways:
- name: istio-ingressgateway
namespace: istio-ingress
enabled: true
label:
# 为网关设置唯一标签。
# 这是确保 Gateway 可以选择此工作负载所必需的。
istio: ingressgateway
values:
gateways:
istio-ingressgateway:
# 启用网关注入
injectionTemplate: gateway
然后使用标准的 istioctl
命令安装:
$ kubectl create namespace istio-ingress
$ istioctl install -f ingress.yaml
使用标准的 helm
命令安装:
$ kubectl create namespace istio-ingress
$ helm install istio-ingressgateway istio/gateway -n istio-ingress
要查看支持的所有可能的配置值,请运行 helm show values istio/gateway
。
Helm 代码仓库中的 README
包含了更多使用信息。
首先设置名为 ingress.yaml
的 Kubernetes 配置文件:
apiVersion: v1
kind: Service
metadata:
name: istio-ingressgateway
namespace: istio-ingress
spec:
type: LoadBalancer
selector:
istio: ingressgateway
ports:
- port: 80
name: http
- port: 443
name: https
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-ingressgateway
namespace: istio-ingress
spec:
selector:
matchLabels:
istio: ingressgateway
template:
metadata:
annotations:
# 选择网关注入模板(而不是默认的 Sidecar 模板)
inject.istio.io/templates: gateway
labels:
# 为网关设置唯一标签。这是确保 Gateway 可以选择此工作负载所必需的
istio: ingressgateway
# 启用网关注入。如果后续连接到修订版的控制平面,请替换为 `istio.io/rev: revision-name`
sidecar.istio.io/inject: "true"
spec:
# 允许绑定到所有端口(例如 80 和 443)
securityContext:
sysctls:
- name: net.ipv4.ip_unprivileged_port_start
value: "0"
containers:
- name: istio-proxy
image: auto # 每次 Pod 启动时,该镜像都会自动更新。
# 放弃所有 privilege 特权,允许以非 root 身份运行
securityContext:
capabilities:
drop:
- ALL
runAsUser: 1337
runAsGroup: 1337
---
# 设置 Role 以允许读取 TLS 凭据
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: istio-ingressgateway-sds
namespace: istio-ingress
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: istio-ingressgateway-sds
namespace: istio-ingress
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: istio-ingressgateway-sds
subjects:
- kind: ServiceAccount
name: default
接下来将其应用到集群:
$ kubectl create namespace istio-ingress
$ kubectl apply -f ingress.yaml
管理网关
本节说明了如何在安装之后管理网关。有关具体用法的更多信息,请参阅 Ingress 和 Egress 任务。
Gateway 选择算符
网关 Deployment Pod 上的标签由 Gateway
配置资源使用,
因此重要的是您的 Gateway
选择算符要与这些标签匹配。
例如在上述 Deployment 中,在网关 Pod 上设置 istio=ingressgateway
标签。
要将 Gateway
应用到这些 Deployment,您需要选择相同的标签:
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: gateway
spec:
selector:
istio: ingressgateway
...
网关部署拓扑
根据您的网格配置和使用场景,您可能希望以不同的方式部署网关。 以下演示了几种不同的网关部署模式。请注意,在同一个集群内可以使用多种模式。
共享网关
在此模型中,单个集中的网关由许多应用一起使用,可能还会跨许多命名空间使用。
ingress
命名空间中的网关委派路由的所有权到应用程序命名空间,但保留对 TLS 配置的控制。
此模型适用于您有许多应用程序想要对外暴露时,这是因为这些应用程序可以使用共享的基础设施。 在许多应用程序共享相同的域或 TLS 证书的使用场景中,这种模型也能良好工作。
专用的应用程序网关
在此模型中,应用程序命名空间具有其自身专用的网关组件。 这允许完全控制单个命名空间并赋予该命名空间的所有权。 这一级的隔离对性能或安全要求严格的关键应用程序很有帮助。
除非在 Istio 之前存在另一个负载均衡器,否则这通常意味着每个应用程序将具有自身的 IP 地址,这可能会让 DNS 配置变得复杂。
升级网关
就地升级
因为网关利用 Pod 注入,所以新创建的网关 Pod 将自动被注入包括版本在内的最新配置。
要应用对网关配置的变更,只需使用 kubectl rollout restart deployment
这类命令重启 Pod 即可。
如果您想要通过网关更改正在使用的控制面修订版,
您可以在网关 Deployment 上设置 istio.io/rev
标签,这也会触发滚动重启。
金丝雀升级
如果想要延后新控制面修订版的发版时间,
您可以运行多个版本的网关 Deployment。例如如果您想要推出一个新修订版 canary
,
可以设置 istio.io/rev=canary
标签后创建网关 Deployment 的副本。
apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-ingressgateway-canary
namespace: istio-ingress
spec:
selector:
matchLabels:
istio: ingressgateway
template:
metadata:
annotations:
inject.istio.io/templates: gateway
labels:
istio: ingressgateway
istio.io/rev: canary # 设置为你要部署的控制平面的修订版
spec:
containers:
- name: istio-proxy
image: auto
当此 Deployment 被创建时,您将具有被同一个 Service 选中的两个版本的网关:
$ kubectl get endpoints -n istio-ingress -o "custom-columns=NAME:.metadata.name,PODS:.subsets[*].addresses[*].targetRef.name"
NAME PODS
istio-ingressgateway istio-ingressgateway-...,istio-ingressgateway-canary-...
与网格内部署的应用程序服务不同,您不能使用 Istio 流量转移在网格版本之间分发流量, 因为流量直接来自 Istio 控制之外的外部客户端。作为替代方案, 您可以通过每个 Deployment 的副本数来控制流量的分发。 如果您在 Istio 之前使用另一个负载均衡器,您还可以使用此负载均衡器来控制流量分发。
通过外部流量转移进行金丝雀升级(高级)
金丝雀升级的各种方法在 Istio 外使用高级组件(例如外部负载均衡器或 DNS)在各版本之间转移流量。
这提供了精细粒度的控制,但可能不适合在某些环境中搭建或过于复杂。