本教程介绍如何将 Anthos Service Mesh 与 Cloud Load Balancing 结合使用,以将服务网格中的应用公开给互联网客户端。
Anthos Service Mesh 是基于 Istio 的代管式服务网格,可为应用提供可观测的标准化安全增强型通信层。无论您是使用 Anthos Service Mesh、Traffic Director 还是 Istio,服务网格都可以为在网格中进行通信的客户提供全面的通信平台。但是,仍然难以将网格外部的客户端连接到网格中托管的应用。
您可以通过多种方式向客户端公开应用,具体取决于客户端所在的位置。本教程介绍了如何将 Cloud Load Balancing 与 Anthos Service Mesh 结合使用以向客户端公开应用,从而将负载均衡器与服务网格集成在一起。本教程面向运行 Anthos Service Mesh 的高级从业人员,但也适用于 Google Kubernetes Engine 上的 Istio。
网格入站流量网关
Istio 0.8 引入了网格入站流量网关,此网关提供的专用代理集的端口会向来自服务网格外部的流量公开。这些网格入站流量代理允许您独立于应用路由行为,控制 L4 公开行为。代理还允许您在网格外部流量到达应用 Sidecar 之前将路由和政策应用到网格外部流量。网格入站流量定义了流量到达网格中的节点时的处理方式,但是外部组件必须定义流量如何首先到达网格。
如需管理此外部流量,您需要一个位于网格外部的负载均衡器。本教程使用通过 GKE Ingress 资源预配的 Google Cloud Load Balancing 自动执行部署。此设置的规范示例是外部负载均衡服务,对于 Google Cloud,会部署公共 TCP/UDP 负载均衡器。该负载均衡器指向 GKE 集群的 NodePort。这些 NodePort 会公开 Istio 入站流量网关 Pod,而 Pod 会将流量路由到下游网格 Sidecar 代理。下图演示了此拓扑。内部专用流量的负载均衡类似于此架构,只是改为部署内部 TCP/UDP 负载均衡器。
将 L4 透明负载均衡与网格入站网关结合使用具有以下优势:
- 此设置简化了负载均衡器的部署过程。
- 如果集群变更、节点中断或处理中断,则负载均衡器会提供稳定的虚拟 IP (VIP)、健康检查和可靠的流量分配。
- 所有路由规则、TLS 终结和流量政策都会在网格入站流量网关中的同一个位置处理。
GKE Ingress 和 Service
您可以通过多种方式为集群外部的客户端提供对应用的访问权限。下表列出了可用于在 Google Cloud 上部署负载均衡器的 Kubernetes 基本组件。用于向客户端公开应用的负载均衡器的类型很大程度上取决于客户端是外部客户端还是内部客户端、需要哪种协议支持以及服务网格是跨越多个 GKE 集群还是包含在单个集群中。
下表中的任何负载均衡器类型都可以公开网格托管的应用,具体取决于使用场景。
GKE 资源 | 基于云的负载均衡器 | 特性 |
---|---|---|
适用于外部 HTTP(S) 负载均衡器的 Ingress | 外部 HTTP(S) 负载均衡器 |
Google Edge 接入点 (PoP) 中的 L7 代理 公共 VIP 全球范围 单集群 |
适用于内部 HTTP(S) 负载均衡器的 Ingress | 内部 HTTP(S) 负载均衡器 |
Virtual Private Cloud (VPC) 网络中的 L7 代理 专用 VIP 地区范围 单集群 |
外部 LoadBalancer 服务 |
网络负载均衡器 |
Google Edge PoP 的 L4 直通 公共 VIP 地区范围 单集群 |
内部 LoadBalancer 服务 |
内部 TCP/UDP 负载均衡器 |
VPC 路由网络中的 L4 直通 专用 VIP 地区范围 单集群 |
多集群 Ingress(多集群、外部入站流量) | 外部 HTTP(S) 负载均衡器 |
Google Edge PoP 中的 L7 代理 公共 VIP 全球范围 多集群 |
虽然 Anthos Service Mesh 的默认负载均衡器是外部 TCP/UDP 负载均衡器,但本教程重点介绍外部 HTTP(S) 负载均衡器。外部 HTTP(S) 负载均衡器提供与诸如 Identity-Aware Proxy (IAP)、Google Cloud Armor 和 Cloud CDN 等边缘服务以及边缘代理的全球分布式网络的集成。下一部分介绍使用两层 HTTP 负载均衡的架构和优势。
Cloud 入站流量和网格入站流量
将网格外部的 L7 负载均衡与网格入站层一起部署具有明显优势,对于互联网流量而言尤其如此。即使 Anthos Service Mesh 和 Istio 入站流量网关在网格中提供了高级路由和流量管理,某些功能仍可以在网络边缘得到更好的服务。通过 Google Cloud 的外部 HTTP(S) 负载均衡器利用互联网边缘网络,较之基于网格的入站流量,可在性能、可靠性或安全性方面获得显著的优势。这些优势如下所示:
- 全球 Anycast VIP 通告以及遍布全球的 TLS 和 HTTP 终结
- 使用 Google Cloud Armor 在边缘进行 DDoS 防御和流量过滤
- 通过 IAP 使用 API 网关功能
- 使用 Google 管理的证书自动创建和轮用公共证书
- 使用多集群 Ingress 在边缘实现多集群和多区域负载均衡
此 L7 负载均衡的外部层称为 Cloud Ingress,因为它是以云管理的负载均衡器为基础,而不是由网格入站流量使用的自托管代理。Cloud Ingress 和网格入站流量结合,可利用 Google Cloud 基础架构和网格的互补功能。下图说明了如何将 Cloud Ingress 和网格入站流量结合,以充当互联网流量的两个负载均衡层。
在这种拓扑中,Cloud Ingress 层从服务网格外部获取流量,并将该流量定向到网格入站流量层。然后,网格入站流量层会将流量定向到网格托管的应用后端。
Cloud 和网格入站流量拓扑
本部分介绍了每个入站流量层一起使用时可实现的互补性角色。这些角色不是具体的规则,而是利用每一层优点的指南。这种模式可能会有变体版本,具体取决于您的使用场景。
- Cloud Ingress。与网格入站流量搭配使用时,Cloud Ingress 层最适合用于边缘安全和全球负载均衡。由于 Cloud Ingress 层在边缘与 DDoS 保护、云防火墙、身份验证和加密产品集成在一起,因此这个层擅长在网格外部运行这些服务。路由逻辑在这个层通常很简单,但是对于多集群和多地区环境而言,逻辑可能会更复杂。由于面向互联网的负载均衡器的关键功能,Cloud Ingress 层可能由基础架构团队管理,该团队对应用在互联网上的公开和保护方式具有独占控制权。较之开发者驱动的基础架构,此控制机制会降低此层的灵活性和动态性,因此如果考虑使用此控制机制,则可能会影响您要向谁提供对此层的管理员权限以及以何种方式提供。
- 网格入站流量。与 Cloud Ingress 搭配使用时,网格入站流量层提供靠近应用的灵活路由。由于具有这种灵活性,对于复杂路由逻辑和应用级别的可见性,网格入站流量比 Cloud Ingress 更好。入站流量层之间的分隔还使应用所有者能更容易地直接控制此层,而不会影响其他团队。通过 L4 负载均衡器而不是 L7 负载均衡器公开服务网格应用时,应在网格内部的网格入站流量层终结客户端 TLS,以帮助保护应用。
健康检查
使用 L7 负载均衡的两层所带来的一种复杂性是健康检查。您必须配置每个负载均衡器以检查下一层的运行状况,确保它可以接收流量。下图中的拓扑结构显示了 Cloud Ingress 如何检查网格入站流量代理的运行状况,而网格又如何反过来检查应用后端的运行状况。
此拓扑具有以下注意事项:
- Cloud Ingress。在本教程中,您将通过入站流量配置 Google Cloud 负载均衡器,以检查所公开健康检查端口上的网格入站流量代理的健康状况。如果网格代理关闭,或者集群、网格或地区不可用,则 Google Cloud 负载均衡器会检测此情况,并且不会将流量发送到网格代理。
- 网格入站流量。在网格应用中,您可以直接对后端执行健康检查,以便可以在本地执行负载均衡和流量管理。
安全
上述拓扑涉及几个安全要素。最关键的要素之一是如何配置加密和部署证书。用于外部 HTTP(S) 负载均衡器的入站流量与 Google 管理的证书进行了深度集成。此集成可自动预配公共证书,将它们关联到负载均衡器,然后通过声明性 GKE Ingress 接口续订和轮用证书。互联网客户端根据公共证书进行身份验证,并作为 Virtual Private Cloud (VPC) 中的第一个跃点连接到外部负载均衡器。
Google Front End (GFE) 和网格入站流量代理之间的下一个跃点会默认加密。GFE 与其后端之间的网络级加密会自动应用。但是,如果您的安全要求规定平台所有者保留加密密钥的所有权,则可以在集群入站流量 (GFE) 和网格入站流量(Envoy 代理实例)之间启用具有 TLS 加密的 HTTP/2。为此路径启用具有 TLS 加密的 HTTP/2 后,您可以使用自签名证书或公共证书来加密流量,因为 GFE 不会对其进行身份验证。本指南中演示了额外的这层加密。为防止证书被错误处理,请勿在其他地方使用公共负载均衡器的公共证书。相反,我们建议您在服务网格中使用单独的证书。
如果服务网格强制执行 TLS,则将对 Sidecar 代理之间的所有流量以及网格入站流量进行加密。下图说明了从客户端到 Google Cloud 负载均衡器、从负载均衡器到网格入站流量代理以及从入站流量代理到 Sidecar 代理的 HTTPS 加密。
目标
- 在 Google Cloud 上部署 Google Kubernetes Engine (GKE) 集群。
- 在 GKE 集群上部署基于 Istio 的 Anthos Service Mesh。
- 配置 GKE Ingress 以终结公共 HTTPS 流量,并将该流量定向到服务网格托管的应用。
- 在您向互联网上的客户端公开的 GKE 集群上部署 Online Boutique 应用。
费用
在本文档中,您将使用 Google Cloud 的以下收费组件:
- Google Kubernetes Engine
- Compute Engine
- Cloud Load Balancing
- Anthos Service Mesh
- Google Cloud Armor
- Cloud Endpoints
您可使用价格计算器根据您的预计使用情况来估算费用。
完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
准备工作
-
在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目。
-
在 Google Cloud 控制台中,激活 Cloud Shell。
您将通过 Cloud Shell 运行本教程中的所有终端命令。
升级到最新版本的 Google Cloud CLI:
gcloud components update
设置默认的 Google Cloud 项目:
export PROJECT=PROJECT export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT} --format="value(projectNumber)") gcloud config set project ${PROJECT}
将
PROJECT
替换为您要用于本教程的项目 ID。创建工作目录:
mkdir -p ${HOME}/edge-to-mesh cd ${HOME}/edge-to-mesh export WORKDIR=`pwd`
完成本教程后,您可以删除工作目录。
创建 GKE 集群
本教程中介绍的功能需要使用 GKE 集群 1.16 或更高版本。
在 Cloud Shell 中,创建一个新的
kubeconfig
文件。此步骤确保不会导致与现有(默认)kubeconfig
文件冲突。touch edge2mesh_kubeconfig export KUBECONFIG=${WORKDIR}/edge2mesh_kubeconfig
为 GKE 集群定义环境变量:
export CLUSTER_NAME=edge-to-mesh export CLUSTER_LOCATION=us-west1-a
启用 Google Kubernetes Engine API。
gcloud
gcloud services enable container.googleapis.com
Config Connector
本教程包含 Config Connector 资源。您可以使用这些资源来完成与您在
gcloud
标签页中完成的相同任务。如需使用这些资源,请安装 Config Connector,然后以最适合您的环境的方式应用这些资源。使用以下
Services
清单:apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1 kind: Service metadata: annotations: cnrm.cloud.google.com/deletion-policy: "abandon" cnrm.cloud.google.com/disable-dependent-services: "false" name: container.googleapis.com spec: resourceID: container.googleapis.com projectRef: external: PROJECT
创建 GKE 集群。
gcloud
gcloud container clusters create ${CLUSTER_NAME} \ --machine-type=e2-standard-4 \ --num-nodes=4 \ --zone ${CLUSTER_LOCATION} \ --enable-ip-alias \ --workload-pool=${PROJECT}.svc.id.goog \ --release-channel rapid \ --addons HttpLoadBalancing \ --labels mesh_id=proj-${PROJECT_NUMBER}
Config Connector
使用以下
ContainerCluster
和ContainerNodePool
清单:apiVersion: container.cnrm.cloud.google.com/v1beta1 kind: ContainerNodePool metadata: annotations: cnrm.cloud.google.com/project-id: PROJECT name: edge-to-mesh spec: clusterRef: name: edge-to-mesh location: us-west1-a nodeConfig: machineType: e2-standard-4 nodeCount: 4 --- apiVersion: container.cnrm.cloud.google.com/v1beta1 kind: ContainerCluster metadata: annotations: cnrm.cloud.google.com/project-id: PROJECT cnrm.cloud.google.com/remove-default-node-pool: "true" labels: mesh_id: proj-PROJECT_NUMBER name: edge-to-mesh spec: addonsConfig: httpLoadBalancing: disabled: false location: us-west1-a initialNodeCount: 1 releaseChannel: channel: RAPID workloadIdentityConfig: workloadPool: PROJECT.svc.id.goog
将
PROJECT_NUMBER
替换为之前检索到的PROJECT_NUMBER
环境变量的值。如需使用云入站流量,您必须启用 HTTP 负载均衡插件。GKE 集群默认启用了 HTTP 负载均衡;您不得将其停用。
如需使用代管式 Anthos Service Mesh,您必须在集群上应用
mesh_id
标签。确保该集群正在运行:
gcloud container clusters list
输出内容类似如下:
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS edge-to-mesh us-west1-a v1.22.6-gke.300 35.233.195.59 e2-standard-4 v1.22.6-gke.300 4 RUNNING
连接到该集群:
gcloud container clusters get-credentials ${CLUSTER_NAME} \ --zone ${CLUSTER_LOCATION} \ --project ${PROJECT}
安装服务网格
在本部分中,您将配置使用队列 API 的代管式 Anthos Service Mesh。
启用必需的 API:
gcloud
gcloud services enable mesh.googleapis.com
Config Connector
使用以下
Services
清单:apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1 kind: Service metadata: annotations: cnrm.cloud.google.com/deletion-policy: "abandon" cnrm.cloud.google.com/disable-dependent-services: "false" name: mesh.googleapis.com spec: resourceID: mesh.googleapis.com projectRef: external: PROJECT
在舰队上启用 Anthos Service Mesh:
gcloud
gcloud container fleet mesh enable
Config Connector
使用以下
GKEHubFeature
清单:apiVersion: gkehub.cnrm.cloud.google.com/v1beta1 kind: GKEHubFeature metadata: name: servicemesh spec: projectRef: external: PROJECT location: global resourceID: servicemesh
将集群注册到舰队:
gcloud
gcloud container fleet memberships register ${CLUSTER_NAME} \ --gke-cluster ${CLUSTER_LOCATION}/${CLUSTER_NAME} \ --enable-workload-identity
Config Connector
使用以下
GKEHubMembership
清单:apiVersion: gkehub.cnrm.cloud.google.com/v1beta1 kind: GKEHubMembership metadata: annotations: cnrm.cloud.google.com/project-id: PROJECT name: edge-to-mesh spec: location: global authority: issuer: https://container.googleapis.com/v1/projects/PROJECT/locations/us-west1-a/clusters/edge-to-mesh endpoint: gkeCluster: resourceRef: name: edge-to-mesh
启用自动控制平面管理和代管式数据平面:
gcloud
gcloud container fleet mesh update \ --management automatic \ --memberships ${CLUSTER_NAME}
Config Connector
使用以下
GKEHubFeatureMembership
清单:apiVersion: gkehub.cnrm.cloud.google.com/v1beta1 kind: GKEHubFeatureMembership metadata: name: servicemesh-membership spec: projectRef: external: PROJECT_ID location: global membershipRef: name: edge-to-mesh featureRef: name: servicemesh mesh: management: MANAGEMENT_AUTOMATIC
几分钟后,验证控制平面状态是否为
ACTIVE
:gcloud container fleet mesh describe
输出内容类似如下:
... membershipSpecs: projects/841956571429/locations/global/memberships/edge-to-mesh: mesh: management: MANAGEMENT_AUTOMATIC membershipStates: projects/841956571429/locations/global/memberships/edge-to-mesh: servicemesh: controlPlaneManagement: details: - code: REVISION_READY details: 'Ready: asm-managed-rapid' state: ACTIVE dataPlaneManagement: details: - code: OK details: Service is running. state: ACTIVE state: code: OK description: 'Revision(s) ready for use: asm-managed-rapid.' updateTime: '2022-09-29T05:30:28.320896186Z' name: projects/your-project/locations/global/features/servicemesh resourceState: state: ACTIVE ...
部署 GKE Ingress
在以下步骤中,您将通过 GKE 的 Ingress 控制器部署外部 HTTP(S) 负载均衡器。Ingress 资源会自动执行负载均衡器、负载均衡器 TLS 证书以及后端健康检查的预配。此外,您还可以使用 Cloud Endpoints 自动为应用预配公共 DNS 名称。
安装入站流量网关
为保证安全性,我们建议在与控制层面不同的命名空间中部署入站流量网关。
在 Cloud Shell 中,创建一个专用的
asm-ingress
命名空间:kubectl create namespace asm-ingress
将命名空间标签添加到
asm-ingress
命名空间:kubectl label namespace asm-ingress istio-injection=enabled
输出内容类似如下:
namespace/asm-ingress labeled
使用
istio-injection=enabled
为asm-ingress
命名空间添加标签会指示 Anthos Service Mesh 在部署应用时自动注入 Envoy 边车代理。运行以下命令,将
Deployment
清单创建为ingress-deployment.yaml
:cat <<EOF > ingress-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: asm-ingressgateway namespace: asm-ingress spec: selector: matchLabels: asm: ingressgateway template: metadata: annotations: # This is required to tell Anthos Service Mesh to inject the gateway with the # required configuration. inject.istio.io/templates: gateway labels: asm: ingressgateway spec: securityContext: fsGroup: 1337 runAsGroup: 1337 runAsNonRoot: true runAsUser: 1337 containers: - name: istio-proxy securityContext: allowPrivilegeEscalation: false capabilities: drop: - all privileged: false readOnlyRootFilesystem: true image: auto # The image will automatically update each time the pod starts. resources: limits: cpu: 2000m memory: 1024Mi requests: cpu: 100m memory: 128Mi serviceAccountName: asm-ingressgateway --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: asm-ingressgateway namespace: asm-ingress spec: maxReplicas: 5 minReplicas: 3 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: asm-ingressgateway --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: asm-ingressgateway namespace: asm-ingress rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: asm-ingressgateway namespace: asm-ingress roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: asm-ingressgateway subjects: - kind: ServiceAccount name: asm-ingressgateway --- apiVersion: v1 kind: ServiceAccount metadata: name: asm-ingressgateway namespace: asm-ingress EOF
此
Deployment
具有自己的ServiceAccount
以及关联的Role
和RoleBinding
,允许网关访问证书。在集群中部署
ingress-deployment.yaml
以创建Deployment
资源:kubectl apply -f ingress-deployment.yaml
输出内容类似如下:
deployment.apps/asm-ingressgateway configured role.rbac.authorization.k8s.io/asm-ingressgateway configured rolebinding.rbac.authorization.k8s.io/asm-ingressgateway configured serviceaccount/asm-ingressgateway created
确保所有部署都已启动并运行:
kubectl wait --for=condition=available --timeout=600s deployment --all -n asm-ingress
输出内容类似如下:
deployment.apps/asm-ingressgateway condition met
运行以下命令,将
Service
清单创建为ingress-service.yaml
:cat <<EOF > ingress-service.yaml apiVersion: v1 kind: Service metadata: name: asm-ingressgateway namespace: asm-ingress annotations: cloud.google.com/neg: '{"ingress": true}' cloud.google.com/backend-config: '{"default": "ingress-backendconfig"}' cloud.google.com/app-protocols: '{"https":"HTTP2"}' # HTTP/2 with TLS encryption labels: asm: ingressgateway spec: ports: # status-port exposes a /healthz/ready endpoint that can be used with GKE Ingress health checks - name: status-port port: 15021 protocol: TCP targetPort: 15021 # Any ports exposed in Gateway resources should be exposed here. - name: http2 port: 80 targetPort: 8080 - name: https port: 443 targetPort: 8443 selector: asm: ingressgateway type: ClusterIP EOF
此
Service
具有以下注释,可在部署 Ingress 负载均衡器时设置其参数:cloud.google.com/backend-config
是指名为BackendConfig
的自定义资源的名称。Ingress 控制器使用BackendConfig
设置 Google CloudBackendService
资源的参数。您可以在下一步中使用此资源来定义 Google Cloud 健康检查的自定义参数。cloud.google.com/neg: '{"ingress": true}'
用于启用容器原生负载均衡的 Ingress 后端(本例中为网格入站流量代理)。为了更有效、更稳定地实现负载均衡,这些后端使用网络端点组 (NEG) 代替实例组。- 为了获得额外加密层,
cloud.google.com/app-protocols: '{"https":"HTTP2"}'
指示 GFE 使用具有 TLS 的 HTTP2 连接到服务网格的入站网关,如适用于外部 HTTP(S) 负载均衡的 Ingress 和外部 HTTP(S) 负载均衡概览所述。
在集群中部署
ingress-service.yaml
以创建Service
资源:kubectl apply -f ingress-service.yaml
输出内容类似如下:
service/asm-ingressgateway created
应用后端服务设置
在 Cloud Shell 中,运行以下命令以将
BackendConfig
清单创建为ingress-backendconfig.yaml
:cat <<EOF > ingress-backendconfig.yaml apiVersion: cloud.google.com/v1 kind: BackendConfig metadata: name: ingress-backendconfig namespace: asm-ingress spec: healthCheck: requestPath: /healthz/ready port: 15021 type: HTTP securityPolicy: name: edge-fw-policy EOF
BackendConfig
是自定义资源定义 (CRD),用于定义 Ingress 负载均衡的后端参数。如需查看可通过 GKE Ingress 配置的后端和前端参数的完整列表,请参阅 Ingress 功能。在本教程中,
BackendConfig
清单指定网格入站流量代理的自定义健康检查。Anthos Service Mesh 和 Istio 在/healthz/ready
路径的端口15021
上公开 Sidecar 代理健康检查。自定义健康检查参数是必需的,因为网格入站流量代理的服务端口 (443
) 与健康检查端口 (15021
) 不同。GKE Ingress 在BackendConfig
中使用以下健康检查参数来配置 Google Cloud 负载均衡器健康检查。此外,还引用了安全政策,以帮助防范来自不同类型的网络攻击的负载均衡流量。healthCheck.port
会定义端口,以在每个 Pod 的 IP 地址上接收 Google Cloud 负载均衡器执行的健康检查。healthCheck.requestPath
会定义 HTTP 路径,以在指定端口上接收健康检查。type
会定义健康检查的协议(在此示例中为 HTTP)。securityPolicy.name
是指 Cloud Armor 安全政策的名称。
在集群中部署
ingress-backendconfig.yaml
以创建BackendConfig
资源:kubectl apply -f ingress-backendconfig.yaml
输出内容类似如下:
backendconfig.cloud.google.com/ingress-backendconfig created
在部署 Ingress 资源之前,
BackendConfig
参数和asm-ingressgateway
Service 注释不会应用于 Google Cloud 负载均衡器。Ingress 部署会将所有这些资源相关联。
定义安全政策
Google Cloud Armor 提供的 DDoS 防御和可自定义的安全策略可通过 Ingress 资源关联至负载均衡器。在以下步骤中,您将创建安全政策,以使用预配置规则来阻止跨站脚本攻击 (XSS)。此规则有助于阻止与已知攻击签名匹配的流量,但允许所有其他流量。您的环境可能根据工作负载使用不同的规则。
gcloud
在 Cloud Shell 中,创建一个名为
edge-fw-policy
的安全政策:gcloud compute security-policies create edge-fw-policy \ --description "Block XSS attacks"
创建使用预配置 XSS 过滤条件的安全政策规则:
gcloud compute security-policies rules create 1000 \ --security-policy edge-fw-policy \ --expression "evaluatePreconfiguredExpr('xss-stable')" \ --action "deny-403" \ --description "XSS attack filtering"
Config Connector
使用以下 ComputeSecurityPolicy
清单:
apiVersion: compute.cnrm.cloud.google.com/v1beta1
kind: ComputeSecurityPolicy
metadata:
annotations:
cnrm.cloud.google.com/project-id: PROJECT_ID
name: edge-fw-policy
spec:
rule:
- action: allow
description: "Default rule"
match:
versionedExpr: SRC_IPS_V1
config:
srcIpRanges:
- "*"
priority: 2147483647
- action: deny-403
description: "XSS attack filtering"
match:
expr:
expression: "evaluatePreconfiguredExpr('xss-stable')"
priority: 1000
上一部分中的 ingress-backendconfig
引用了 edge-fw-policy
。部署 Ingress 资源后,它会将此安全政策与负载均衡器绑定,以帮助保护 asm-ingressgateway
Service 的任何后端。
配置 IP 寻址和 DNS
在 Cloud Shell 中,为 Google Cloud 负载均衡器创建全球静态 IP:
gcloud
gcloud compute addresses create ingress-ip --global
Config Connector
使用以下
ComputeAddress
清单:apiVersion: compute.cnrm.cloud.google.com/v1beta1 kind: ComputeAddress metadata: annotations: cnrm.cloud.google.com/project-id: PROJECT_ID name: ingress-ip spec: location: global
此静态 IP 由 Ingress 资源使用,即使外部负载均衡器发生更改,该 IP 也可以保持不变。
获取静态 IP 地址:
export GCLB_IP=$(gcloud compute addresses describe ingress-ip --global --format "value(address)") echo ${GCLB_IP}
如需针对您的 Ingress IP 创建易于使用的稳定映射,您必须具有公共 DNS 记录。您可以使用所需的任何 DNS 提供商和自动化功能。本教程使用 Endpoints 而不是创建代管式 DNS 区域。Endpoints 为公共 IP 提供免费的 Google 管理的 DNS 记录。
运行以下命令以创建名为
dns-spec.yaml
的 YAML 规范文件:cat <<EOF > dns-spec.yaml swagger: "2.0" info: description: "Cloud Endpoints DNS" title: "Cloud Endpoints DNS" version: "1.0.0" paths: {} host: "frontend.endpoints.${PROJECT}.cloud.goog" x-google-endpoints: - name: "frontend.endpoints.${PROJECT}.cloud.goog" target: "${GCLB_IP}" EOF
YAML 规范以
frontend.endpoints.${PROJECT}.cloud.goog
的形式定义公共 DNS 记录,其中${PROJECT}
是您的唯一项目编号。在 Google Cloud 项目中部署
dns-spec.yaml
文件:gcloud endpoints services deploy dns-spec.yaml
输出内容类似如下:
Operation finished successfully. The following command can describe the Operation details: gcloud endpoints operations describe operations/rollouts.frontend.endpoints.edge2mesh.cloud.goog:442b2b38-4aee-4c60-b9fc-28731657ee08 Service Configuration [2021-11-14r0] uploaded for service [frontend.endpoints.edge2mesh.cloud.goog]
在配置 IP 和 DNS 后,您可以生成公共证书来保护 Ingress 前端。GKE Ingress 支持 Google 管理的证书作为 Kubernetes 资源,让您能够通过声明方式预配证书。
预配 TLS 证书
在 Cloud Shell 中,运行以下命令以将
ManagedCertificate
清单创建为managed-cert.yaml
:cat <<EOF > managed-cert.yaml apiVersion: networking.gke.io/v1 kind: ManagedCertificate metadata: name: gke-ingress-cert namespace: asm-ingress spec: domains: - "frontend.endpoints.${PROJECT}.cloud.goog" EOF
此 YAML 文件指定使用通过 Endpoints 创建的 DNS 名称来预配公共证书。由于 Google 全面管理这些公共证书的生命周期,因此这些证书会定期自动生成并轮用,用户无需直接干预。
在您的 GKE 集群中部署
managed-cert.yaml
文件:kubectl apply -f managed-cert.yaml
输出内容类似如下:
managedcertificate.networking.gke.io/gke-ingress-cert created
检查
ManagedCertificate
资源以查看证书生成进度:kubectl describe managedcertificate gke-ingress-cert -n asm-ingress
输出内容类似如下:
Name: gke-ingress-cert Namespace: asm-ingress Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"networking.gke.io/v1","kind":"ManagedCertificate","metadata":{"annotations":{},"name":"gke-ingress-cert","namespace":"... API Version: networking.gke.io/v1 Kind: ManagedCertificate Metadata: Creation Timestamp: 2020-08-05T20:44:49Z Generation: 2 Resource Version: 1389781 Self Link: /apis/networking.gke.io/v1/namespaces/asm-ingress/managedcertificates/gke-ingress-cert UID: d74ec346-ced9-47a8-988a-6e6e9ddc4019 Spec: Domains: frontend.endpoints.edge2mesh.cloud.goog Status: Certificate Name: mcrt-306c779e-8439-408a-9634-163664ca6ced Certificate Status: Provisioning Domain Status: Domain: frontend.endpoints.edge2mesh.cloud.goog Status: Provisioning Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Create 44s managed-certificate-controller Create SslCertificate mcrt-306c779e-8439-408a-9634-163664ca6ced
证书准备就绪后,
Certificate Status
为Active
。
部署 Ingress 资源
在 Cloud Shell 中,运行以下命令以将
Ingress
清单创建为ingress.yaml
:cat <<EOF > ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gke-ingress namespace: asm-ingress annotations: kubernetes.io/ingress.allow-http: "false" kubernetes.io/ingress.global-static-ip-name: "ingress-ip" networking.gke.io/managed-certificates: "gke-ingress-cert" kubernetes.io/ingress.class: "gce" spec: defaultBackend: service: name: asm-ingressgateway port: number: 443 rules: - http: paths: - path: /* pathType: ImplementationSpecific backend: service: name: asm-ingressgateway port: number: 443 EOF
此清单定义了一个将所有先前资源关联在一起的 Ingress 资源。清单指定了以下字段:
kubernetes.io/ingress.allow-http: "false"
会停用 Google Cloud 负载均衡器的端口80
上的 HTTP 流量。由于端口443
仅侦听 HTTPS,而且端口80
已停用,因此这可以有效地防止任何客户端使用未加密的流量进行连接。kubernetes.io/ingress.global-static-ip-name: "ingress-ip"
会将先前创建的 IP 地址与负载均衡器相关联。通过此链接,您可以将 IP 地址与负载均衡器分开创建,以便可以在负载均衡器生命周期中重复使用该地址。networking.gke.io/managed-certificates: "gke-ingress-cert"
会将此负载均衡器与以前创建的 Google 管理的 SSL 证书资源相关联。
在您的集群中部署
ingress.yaml
:kubectl apply -f ingress.yaml
检查 Ingress 资源,以检查负载均衡器部署的进度:
kubectl describe ingress gke-ingress -n asm-ingress
输出内容类似如下:
... Annotations: ingress.kubernetes.io/https-forwarding-rule: k8s2-fs-fq3ng2uk-asm-ingress-gke-ingress-qm3qqdor ingress.kubernetes.io/ssl-cert: mcrt-306c779e-8439-408a-9634-163664ca6ced networking.gke.io/managed-certificates: gke-ingress-cert kubernetes.io/ingress.global-static-ip-name: ingress-ip ingress.gcp.kubernetes.io/pre-shared-cert: mcrt-306c779e-8439-408a-9634-163664ca6ced ingress.kubernetes.io/backends: {"k8s-be-31610--07bdde06b914144a":"HEALTHY","k8s1-07bdde06-asm-ingress-asm-ingressgateway-443-228c1881":"HEALTHY"} ingress.kubernetes.io/forwarding-rule: k8s2-fr-fq3ng2uk-asm-ingress-gke-ingress-qm3qqdor ingress.kubernetes.io/https-target-proxy: k8s2-ts-fq3ng2uk-asm-ingress-gke-ingress-qm3qqdor ingress.kubernetes.io/target-proxy: k8s2-tp-fq3ng2uk-asm-ingress-gke-ingress-qm3qqdor ingress.kubernetes.io/url-map: k8s2-um-fq3ng2uk-asm-ingress-gke-ingress-qm3qqdor ...
如果
ingress.kubernetes.io/backends
注释指明后端为HEALTHY
,则表示 Ingress 资源已准备就绪。这些注释还会显示已预配的不同 Google Cloud 资源的名称,包括后端服务、SSL 证书和 HTTPS 目标代理。
安装自签名入站流量网关证书
在以下步骤中,您将生成并安装一个证书(作为 Kubernetes secret
资源),使 GFE 能够建立与服务网格入站流量网关的 TLS 连接。如需更详细地了解入站流量网关证书的要求,请参阅安全后端协议注意事项指南。
在 Cloud Shell 中,使用
openssl
创建私钥和证书:openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \ -subj "/CN=frontend.endpoints.${PROJECT}.cloud.goog/O=Edge2Mesh Inc" \ -keyout frontend.endpoints.${PROJECT}.cloud.goog.key \ -out frontend.endpoints.${PROJECT}.cloud.goog.crt
在
asm-ingress
命名空间中创建Secret
:kubectl -n asm-ingress create secret tls edge2mesh-credential \ --key=frontend.endpoints.${PROJECT}.cloud.goog.key \ --cert=frontend.endpoints.${PROJECT}.cloud.goog.crt
配置适用于外部负载均衡的入站流量网关
在以下步骤中,您将在 asm-ingress
命名空间中创建共享 Gateway
资源。网关通常由平台管理员或网络管理员团队负责运行。因此,Gateway
资源在由平台管理员负责管理的 asm-ingress
命名空间中创建,可通过他们自己的 VirtualService
条目在其他命名空间中使用。
在 Cloud Shell 中,运行以下命令以将
Gateway
清单创建为ingress-gateway.yaml
:cat <<EOF > ingress-gateway.yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: asm-ingressgateway namespace: asm-ingress spec: selector: asm: ingressgateway servers: - port: number: 443 name: https protocol: HTTPS hosts: - "*" # IMPORTANT: Must use wildcard here when using SSL, see note below tls: mode: SIMPLE credentialName: edge2mesh-credential EOF
请注意,您必须在
Gateway
的hosts
字段中使用通配符*
条目。GCLB 不使用后端的 SNI 扩展程序。使用通配符条目会将加密的数据包(从 GCLB)发送到 ASM 入站流量网关。ASM 入站流量网关解密数据包,并使用 HTTP 主机标头(在解密的数据包中)做出路由决策(基于VirtualService
条目)。在您的集群中部署
ingress-gateway.yaml
:kubectl apply -f ingress-gateway.yaml
输出内容类似如下:
gateway.networking.istio.io/asm-ingressgateway created
安装 Online Boutique 示例应用
在 Cloud Shell 中,创建一个专用的
onlineboutique
命名空间:kubectl create namespace onlineboutique
将命名空间标签添加到
onlineboutique
命名空间:kubectl label namespace onlineboutique istio-injection=enabled
输出内容类似如下:
namespace/onlineboutique labeled
使用
istio-injection=enabled
为onlineboutique
命名空间添加标签会指示 Anthos Service Mesh 在部署应用时自动注入 Envoy 边车代理。下载 Online Boutique 示例应用的 Kubernetes YAML 文件:
curl -LO \ https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/release/kubernetes-manifests.yaml
部署 Online Boutique 应用:
kubectl apply -f kubernetes-manifests.yaml -n onlineboutique
输出内容类似如下:
deployment.apps/frontend created service/frontend created service/frontend-external created ...
确保所有部署都已启动并运行:
kubectl get pods -n onlineboutique
输出内容类似如下:
NAME READY STATUS RESTARTS AGE adservice-d854d8786-fjb7q 2/2 Running 0 3m cartservice-85b5d5b4ff-8qn7g 2/2 Running 0 2m59s checkoutservice-5f9bf659b8-sxhsq 2/2 Running 0 3m1s ...
运行以下命令,将
VirtualService
清单创建为frontend-virtualservice.yaml
:cat <<EOF > frontend-virtualservice.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: frontend-ingress namespace: onlineboutique spec: hosts: - "frontend.endpoints.${PROJECT}.cloud.goog" gateways: - asm-ingress/asm-ingressgateway http: - route: - destination: host: frontend port: number: 80 EOF
请注意,
VirtualService
是在应用命名空间 (onlineboutique
) 中创建的。通常,应用所有者会决定并配置将流量路由到frontend
应用的方式和内容,以便应用所有者部署VirtualService
。在您的集群中部署
frontend-virtualservice.yaml
:kubectl apply -f frontend-virtualservice.yaml
输出内容类似如下:
virtualservice.networking.istio.io/frontend-virtualservice created
访问以下链接:
echo "https://frontend.endpoints.${PROJECT}.cloud.goog"
系统会显示您的 Online Boutique 前端。
如需显示证书的详情,请在浏览器的地址栏中点击
查看站点信息,然后点击证书(有效)。证书查看器会显示代管证书的详情,包括到期日期和颁发证书的人。
现在,您有一个全球 HTTPS 负载均衡器,作为服务网格托管应用的前端。
清理
完成本教程后,您可以清理您在 Google Cloud 上创建的资源,以免这些资源将来产生费用。您可以彻底删除项目,也可以删除集群资源,然后删除集群。
删除项目
- 在 Google Cloud 控制台中,进入管理资源页面。
- 在项目列表中,选择要删除的项目,然后点击删除。
- 在对话框中输入项目 ID,然后点击关闭以删除项目。
逐个删除资源
如果您希望保留在本教程中使用的 Google Cloud 项目,请删除单个资源:
删除 Ingress 资源:
kubectl delete -f ingress.yaml
删除代管式证书:
kubectl delete -f managed-cert.yaml
删除 Endpoints DNS 条目:
gcloud endpoints services delete "frontend.endpoints.${PROJECT}.cloud.goog"
输出内容类似如下:
Are you sure? This will set the service configuration to be deleted, along with all of the associated consumer information. Note: This does not immediately delete the service configuration or data and can be undone using the undelete command for 30 days. Only after 30 days will the service be purged from the system.
当系统提示您继续时,请输入 Y。
输出内容类似如下:
Waiting for async operation operations/services.frontend.endpoints.edge2mesh.cloud.goog-5 to complete... Operation finished successfully. The following command can describe the Operation details: gcloud endpoints operations describe operations/services.frontend.endpoints.edge2mesh.cloud.goog-5
删除静态 IP 地址:
gcloud compute addresses delete ingress-ip --global
输出内容类似如下:
The following global addresses will be deleted: - [ingress-ip]
当系统提示您继续时,请输入 Y。
输出内容类似如下:
Deleted [https://www.googleapis.com/compute/v1/projects/edge2mesh/global/addresses/ingress-ip].
删除 GKE 集群:
gcloud container clusters delete $CLUSTER_NAME --zone $CLUSTER_LOCATION
后续步骤
- 了解 GKE Ingress 提供的可与服务网格配合使用的更多功能。
- 了解适用于 GKE 的不同类型的 Cloud Load Balancing。
- 了解 Anthos Service Mesh 提供的功能。
- 了解如何跨多个 GKE 集群部署 Ingress 以实现多地区负载均衡。
- 探索有关 Google Cloud 的参考架构、图表和最佳做法。查看我们的 Cloud Architecture Center。