本指南介绍如何使用 BackendConfig 自定义资源定义 (CRD) 在 Google Kubernetes Engine (GKE) 中配置 Cloud CDN。
概览
在 GKE 集群中,HTTP(S) 负载平衡(Cloud Load Balancing 的一个组件)负责处理传入流量。通常 HTTP(S) 负载平衡器由 GKE Ingress 控制器配置,该控制器从 Kubernetes Ingress 对象获取配置信息。Ingress 与一个或多个 Service 对象相关联。每个 Service 对象包含用于将传入请求定向到特定 Pod 和端口的路由信息。
从 Kubernetes 1.10.5-gke.3 版本开始,您可以为外部负载平衡器提供其他配置,方法是将 Service 端口与名为 BackendConfig 的自定义资源相关联。
GKE Ingress 控制器会从 BackendConfig 读取配置信息并相应地设置负载平衡器。BackendConfig 包含特定于 Cloud Load Balancing 的配置信息。 Kubernetes Ingress 和 Service 资源不支持配置特定于提供方的功能(如 Cloud CDN);您可以通过 BackendConfig 来执行这项配置。
下面简要介绍如何在本练习中设置 BackendConfig:
- 创建一个 BackendConfig。
- 创建一个 Service,并将它的一个端口与 BackendConfig 关联。
- 创建一个 Ingress,并将该 Ingress 与(Service, 端口)对关联。
准备工作
在开始之前,请确保您已执行以下任务:
- 确保您已启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 确保您已安装 Cloud SDK。
使用以下任一方法设定默认的 gcloud
设置:
- 使用
gcloud init
(如果您想要在系统引导下完成默认设置)。 - 使用
gcloud config
(如果您想单独设置项目 ID、区域和地区)。
使用 gcloud init
如果您收到 One of [--zone, --region] must be supplied: Please specify
location
错误,请完成本部分。
-
运行
gcloud init
并按照说明操作:gcloud init
如果您要在远程服务器上使用 SSH,请使用
--console-only
标志来防止命令启动浏览器:gcloud init --console-only
-
按照说明授权
gcloud
使用您的 Google Cloud 帐号。 - 创建新配置或选择现有配置。
- 选择 Google Cloud 项目。
- 选择默认的 Compute Engine 区域。
使用 gcloud config
阅读 Cloud CDN 概览。
了解 Cloud CDN 缓存。
熟悉 BackendConfig 自定义资源。
创建命名空间
为本指南中所用的对象创建 Kubernetes 命名空间:
kubectl create namespace cdn-how-to
创建 Deployment
根据以下 Deployment 清单创建名为
my-deployment.yaml
的文件。该清单声明您要运行ingress-gce-echo-amd64
Web 应用的两个副本:apiVersion: apps/v1 kind: Deployment metadata: namespace: cdn-how-to name: my-deployment spec: selector: matchLabels: purpose: demonstrate-cdn replicas: 2 template: metadata: labels: purpose: demonstrate-cdn spec: containers: - name: echo-amd64 image: gcr.io/google-samples/hello-app-cdn:1.0
创建 Deployment 资源:
kubectl apply -f my-deployment.yaml
创建 BackendConfig
根据以下 BackendConfig 清单创建名为
my-backend-config.yaml
的文件。该清单指定 Cloud CDN 缓存政策并声明应启用 Cloud CDN:apiVersion: cloud.google.com/v1 kind: BackendConfig metadata: namespace: cdn-how-to name: my-backend-config spec: cdn: enabled: true cachePolicy: includeHost: true includeProtocol: true includeQueryString: false
创建 BackendConfig 资源:
kubectl apply -f my-backend-config.yaml
查看 BackendConfig:
kubectl get backendconfig my-backend-config --output yaml --namespace cdn-how-to
您可以在输出中看到 Cloud CDN 缓存政策:
apiVersion: cloud.google.com/v1 kind: BackendConfig metadata: name: my-backend-config namespace: cdn-how-to ... spec: cdn: cachePolicy: includeHost: true includeProtocol: true includeQueryString: false enabled: true
创建 Service
根据以下 Service 清单创建名为
my-service.yaml
的文件:apiVersion: v1 kind: Service metadata: namespace: cdn-how-to name: my-service labels: purpose: demonstrate-cdn annotations: cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}' spec: type: NodePort selector: purpose: demonstrate-cdn ports: - port: 80 protocol: TCP targetPort: 8080
创建 Service 资源:
kubectl apply -f my-service.yaml
查看 Service:
kubectl get service my-service --namespace cdn-how-to --output yaml
输出类似于以下内容:
apiVersion: v1 kind: Service metadata: annotations: cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}' ... labels: purpose: demonstrate-cdn name: my-service namespace: cdn-how-to ... spec: clusterIP: 10.51.255.39 externalTrafficPolicy: Cluster ports: - nodePort: 31484 port: 80 protocol: TCP targetPort: 8080 selector: purpose: demonstrate-cdn sessionAffinity: None type: NodePort status: loadBalancer: {}
在本练习中,您需要注意有关 Service 的以下重要事项:
Service 的端口 80 与名为
my-backend-config
的 BackendConfig 相关联。 这是由cloud.google.com/backend-config
注释指定的。Service 类型为
NodePort
。对于要与 Ingress 关联的 Service,这是一种典型类型。具有
purpose: demonstrate-cdn
标签的任何 Pod 都是 Service 的成员。这是由selector
字段指定的。定向至 TCP 端口 80 上的服务的流量被路由到 TCP 端口 8080 上的其中一个成员 Pod。这是由
port
和targetPort
字段指定的。
保留静态外部 IP 地址
保留静态外部 IP 地址:
gcloud compute addresses create cdn-how-to-address --global
查看静态外部 IP 地址:
gcloud compute addresses list --filter "name=cdn-how-to-address"
输出会显示地址的名称和值:
NAME ... ADDRESS STATUS cdn-how-to-address 203.0.113.1 RESERVED
创建 Ingress
根据以下 Ingress 清单创建名为
my-ingress.yaml
的文件:apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: namespace: cdn-how-to name: my-ingress annotations: kubernetes.io/ingress.global-static-ip-name: "cdn-how-to-address" spec: rules: - http: paths: - path: /* backend: serviceName: my-service servicePort: 80
创建 Ingress 资源:
kubectl apply -f my-ingress.yaml
请等待十分钟,让 Kubernetes Ingress 控制器配置 Cloud Load Balancing 负载平衡器,然后查看 Ingress:
kubectl get ingress my-ingress --output yaml --namespace cdn-how-to
输出类似于以下内容:
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: ... name: my-ingress namespace: cdn-how-to ... spec: rules: - http: paths: - backend: serviceName: my-service servicePort: 80 path: /* status: loadBalancer: ingress: - ip: 201.0.113.1
在本练习中,您需要注意有关 Ingress 的以下重要事项:
传入流量的 IP 地址列在
loadBalancer:ingress:
下。Ingress 具有一条规则,该规则适用于来自任何主机的传入 HTTP 请求。这是因为该规则中没有
host
字段。因此,在默认情况下,该规则适用于所有主机。无论网址路径为何,所有传入请求都被视为相同。 这是由
path
值/*
指定的。传入请求被路由到
my-service
的一个成员 Pod。 在本练习中,该成员 Pod 具有purpose: demonstrate-cdn
标签。请求被路由到
my-service
中指定的目标端口上的 Pod。在此练习中,Pod 目标端口为 8080。
查看 Web 应用
输入此 curl
命令两次:
curl -v static-address/?cache=true
其中,static-address 是您的静态外部 IP 地址。
输出显示响应标头和正文。在响应标头中,您可以看到内容已缓存。Age
标头指示内容缓存的秒数:
...
< HTTP/1.1 200 OK
< Date: Fri, 25 Jan 2019 02:34:08 GMT
< Content-Length: 70
< Content-Type: text/plain; charset=utf-8
< Via: 1.1 google
< Cache-Control: max-age=86400,public
< Age: 2716
<
Hello, world!
Version: 1.0.0
Hostname: my-deployment-7f589cc5bc-l8kr8
查看负载平衡日志
您可以通过查看 HTTP 负载平衡的 Stackdriver 日志来验证内容是否已缓存。在检查日志之前,请确保您已至少两次从应用请求响应。
控制台
在 Cloud Console 中,转到日志记录菜单中的日志页面。
在第一个下拉菜单中,选择云端 HTTP 负载平衡器。
展开最近的日志条目,然后展开该条目的
httpRequest
字段。在
httpRequest
字段中,您可以看到cacheHit
为true
:httpRequest: { cacheHit: true cacheLookup: true ...
gcloud
运行以下命令,其中 project-id 是您的项目 ID:
gcloud logging read \
'logName="projects/project-id/logs/requests"' \
--limit 2
输出显示存在缓存命中:
httpRequest:
cacheHit: true
cacheLookup: true
清理
完成本指南中的练习后,请按照以下步骤移除资源,以防止您的帐号产生不必要的费用:
删除您针对此练习创建的 Kubernetes 对象:
kubectl delete ingress my-ingress --namespace cdn-how-to kubectl delete service my-service --namespace cdn-how-to kubectl delete backendconfig my-backend-config --namespace cdn-how-to kubectl delete deployment my-deployment --namespace cdn-how-to kubectl delete namespace cdn-how-to
删除静态外部 IP 地址:
gcloud compute addresses delete cdn-how-to-address --global
限制
无法为同一 HTTP(S) 负载平衡后端服务启用 Cloud CDN 和 Identity-Aware Proxy。
问题排查
找不到 BackendConfig
如果在 Service 注释中指定了 Service 端口的 BackendConfig,但找不到实际 BackendConfig 资源,那么就会发生这种错误。 如果您根本没有创建 BackendConfig 资源,或在错误的命名空间中创建了该资源,或在 Service 注释中拼错了引用,则会发生这种情况。
kubectl get event
KIND ... SOURCE
Ingress ... loadbalancer-controller
MESSAGE
Error during sync: error getting BackendConfig for port 80 on service “default/my-service”:
no BackendConfig for service port exists
Cloud CDN 和 IAP 均已启用
在 BackendConfig 中同时启用了 IAP 和 Cloud CDN 时,会发生此错误。
kubectl get event
KIND ... SOURCE
Ingress ... loadbalancer-controller
MESSAGE
Error during sync: BackendConfig default/config-default is not valid:
iap and cdn cannot be enabled at the same time.
内容未被缓存
如果您发现内容未被缓存,请确保您的应用已正确配置为启用内容缓存。如需了解详情,请参阅可缓存性。