本文档介绍了如何在用户集群、混合集群或独立集群中为 Google Distributed Cloud 创建 Kubernetes Ingress 对象。一个 Ingress 与一个或多个 Service 相关联,每个 Service 与一组 Pod 相关联。
创建 Deployment
如需创建 Deployment,请按以下步骤操作:
创建 Deployment 清单:
apiVersion: apps/v1 kind: Deployment metadata: name: hello-deployment spec: selector: matchLabels: greeting: hello replicas: 3 template: metadata: labels: greeting: hello spec: containers: - name: hello-world image: "gcr.io/google-samples/hello-app:2.0" env: - name: "PORT" value: "50000" - name: hello-kubernetes image: "gcr.io/google-samples/node-hello:1.0" env: - name: "PORT" value: "8080"
在本练习中,您需要了解 Deployment 清单的以下要点:
属于 Deployment 的每个 Pod 都具有
greeting: hello
标签。每个 Pod 都有两个容器。
env
字段指定hello-app
容器侦听 TCP 端口 50000,node-hello
容器侦听 TCP 端口 8080。对于hello-app
,您可以通过查看源代码来查看PORT
环境变量的效果。
将此清单复制到名为
hello-deployment.yaml
的文件。创建 Deployment:
kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-deployment.yaml
将
CLUSTER_KUBECONFIG
替换为您的集群的 kubeconfig 文件的名称。
使用 Service 公开 Deployment
如需为客户端提供稳定的方法来向 Deployment 的 Pod 发送请求,请创建一个 Service。
创建向集群内的客户端公开 Deployment 的 Service 清单:
apiVersion: v1 kind: Service metadata: name: hello-service spec: type: ClusterIP selector: greeting: hello ports: - name: world-port protocol: TCP port: 60000 targetPort: 50000 - name: kubernetes-port protocol: TCP port: 60001 targetPort: 8080
将此清单复制到名为
hello-service.yaml
的文件。创建 Service:
kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-service.yaml
将
CLUSTER_KUBECONFIG
替换为您的集群的 kubeconfig 文件的名称。查看 Service:
kubectl --kubeconfig CLUSTER_KUBECONFIG get service hello-service --output yaml
输出显示已提供给 Service 的
clusterIP
值。例如:apiVersion: v1 kind: Service metadata: annotations: ... spec: clusterIP: 10.96.14.249 clusterIPs: - 10.96.14.249 ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - name: world-port port: 60000 protocol: TCP targetPort: 50000 - name: kubernetes-port port: 60001 protocol: TCP targetPort: 8080 selector: greeting: hello sessionAffinity: None type: ClusterIP status: loadBalancer: {}
在上面的输出中,
ports
字段是一个ServicePort
对象数组:一个对象名为world-port
,一个对象名为kubernetes-port
。如需详细了解 Service 字段,请参阅 Kubernetes 文档中的 ServiceSpec。以下是客户端调用 Service 的方式:
使用
world-port
:在某个集群节点上运行的客户端会向port
上的clusterIP
(例如10.96.14.249:60000
)发送请求。Ingress 控制器会将请求转发到targetPort
上的成员 Pod(例如POD_IP_ADDRESS:50000
,其中POD_IP_ADDRESS
是成员 Pod 的 IP 地址)。使用
kubernetes-port
:在某个集群节点上运行的客户端会向port
上的clusterIP
(10.96.14.249:60001
) 发送请求。Ingress 控制器会将请求转发到targetPort
上的成员 Pod (POD_IP_ADDRESS:8080
)。
Ingress 组件
以下是与 Ingress 相关的一些集群组件:
istio-ingress
Deployment。这是 Ingress 代理。Ingress 代理会根据 Ingress 对象中指定的规则将流量转发到内部 Service。istio-ingress
Service。此 Service 会公开istio-ingress
Deployment。istiod
Deployment。这是 Ingress 控制器。Ingress 控制器会监视 Ingress 对象的创建,并相应地配置 Ingress 代理。
所有这些 Istio 集群内组件都安装在 gke-system
命名空间中。此命名空间与完整的 Istio/Cloud Service Mesh 安装不冲突。
创建 Ingress
按照以下步骤创建 Ingress:
创建 Ingress 清单:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress spec: rules: - http: paths: - path: /greet-the-world pathType: Exact backend: service: name: hello-service port: number: 60000 - path: /greet-kubernetes pathType: Exact backend: service: name: hello-service port: number: 60001
将此清单复制到名为
my-ingress.yaml
的文件。创建 Ingress:
kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress.yaml
创建用户集群时,您需要在集群配置文件中指定 loadbalancer.ingressVIP
值。此 IP 地址是在集群负载均衡器上配置的。创建 Ingress 时,Ingress 会获得与其外部 IP 地址相同的 VIP 地址。
当客户端向您的用户集群 Ingress VIP 地址发送请求时,请求将路由到您的负载均衡器。负载均衡器使用 istio-ingress
Service 将请求转发到在用户集群中运行的 Ingress 代理。
Ingress 代理会根据请求网址中的路径将请求转发到不同的后端。
/greet-the-world
路径
Ingress 清单中有一条规则指出,/greet-the-world
路径与 serviceName: hello-service
和 servicePort: 60000
相关联。您应该还记得,60000 是 hello-service
Service 的 world-port
部分中的 port
值。
- name: world-port
port: 60000
protocol: TCP
targetPort: 50000
Ingress Service 将请求转发到 clusterIP
:50000。然后,请求会转到 hello-service
Service 的一个成员 Pod。该 Pod 中侦听端口 50000 的容器会显示 Hello World!
消息。
/greet-kubernetes
路径
Ingress 清单中有一条规则指出,/greet-kubernetes
路径与 serviceName: hello-service
和 servicePort: 60001
相关联。您应该还记得,60001 是 hello-service
Service 的 kubernetes-port
部分中的 port
值。
- name: kubernetes-port
port: 60001
protocol: TCP
targetPort: 8080
Ingress Service 将请求转发到 clusterIP
:8080。然后,请求会转到 hello-service
Service 的一个成员 Pod。该 Pod 中监听端口 8080
的容器会显示 Hello Kubernetes!
消息。
测试 Ingress
使用
/greet-the-world
路径测试 Ingress:curl CLUSTER_INGRESS_VIP/greet-the-world
将
CLUSTER_INGRESS_VIP
替换为 Ingress 的外部 IP 地址。输出结果会显示
Hello, world!
消息:Hello, world! Version: 2.0.0 Hostname: ...
使用
/greet-kubernetes
路径测试 Ingress:curl CLUSTER_INGRESS_VIP/greet-kubernetes
输出结果会显示
Hello, Kubernetes!
消息:Hello Kubernetes!
停用捆绑式 Ingress
与 Google Distributed Cloud 捆绑的 Ingress 功能仅支持入站流量功能。您可以选择与 Istio 或 Cloud Service Mesh 集成。这些产品具有功能全面的服务网格的额外优势,例如双向传输层安全协议 (mTLS)、能够管理服务之间的身份验证以及工作负载可观测性。如果与 Istio 或 Cloud Service Mesh 集成,我们建议您停用捆绑的 Ingress 功能。
您可以使用集群配置文件中的 spec.clusterNetwork.bundledIngress
字段启用或停用捆绑式 Ingress。此字段仅适用于 1.13.0 版及更高版本的集群。bundledIngress
字段默认为 true
,不存在于生成的集群配置文件中。此字段是可变的,可在创建或更新 1.13.0 版或更高版本的集群时更改。
如需停用捆绑的 Ingress 功能,请将
bundledIngress
字段添加到集群配置文件的clusterNetwork
部分,并将其值设置为 false,如以下示例所示:apiVersion: v1 kind: Namespace metadata: name: cluster-hybrid-basic --- apiVersion: baremetal.cluster.gke.io/v1 kind: Cluster metadata: name: hybrid-basic namespace: cluster-hybrid-basic spec: type: hybrid profile: default anthosBareMetalVersion: 1.13.0 gkeConnect: projectID: project-fleet controlPlane: nodePoolSpec: nodes: - address: 10.200.0.2 clusterNetwork: bundledIngress: false pods: cidrBlocks: - 192.168.0.0/16 services: cidrBlocks: - 10.96.0.0/20 ...
为 Ingress 设置 HTTPS
如果您想要接受来自客户端的 HTTPS 请求,则 Ingress 代理必须具有证书,这样才能向客户端证明其身份。此代理还必须具有私钥才能完成 HTTPS 握手。
以下示例使用这些实体:
Ingress 代理:参与 HTTPS 握手,然后将数据包转发到
hello-service
Service 的成员 Pod。hello-service
Service 的网域:Example Org 中的 altostrat.com
请按照以下步骤操作:
创建根证书和私钥。此示例使用 Root CA Example Org 中的根证书授权机构
root.ca.example.com
。openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj \ '/O=Root CA Example Inc./CN=root.ca.example.com' -keyout root-ca.key \ -out root-ca.crt
创建证书签名请求:
openssl req -out server.csr -newkey rsa:2048 -nodes -keyout server.key -subj \ "/CN=altostrat.com/O=Example Org"
为 Ingress 代理创建服务证书。
openssl x509 -req -days 365 -CA root-ca.crt -CAkey root-ca.key -set_serial 0 \ -in server.csr -out server.crt
现在,您已经创建了以下证书和密钥:
root-ca.crt
:根 CA 的证书root-ca.key
:根 CA 的私钥server.crt
:Ingress 代理的服务证书server.key
:Ingress 代理的私钥
创建包含服务证书和密钥的 Kubernetes Secret。
kubectl create secret tls example-server-creds --key=server.key --cert=server.crt \ --namespace gke-system
生成的 Secret 名为
example-server-creds
。
创建 Deployment 和 Service
如果您已在本指南的 HTTP 部分中创建了 Deployment 和 Service,请保留它们。如果您尚未创建,请立即按照针对 HTTP 所述的步骤进行创建。
创建 Ingress
为 HTTPS 创建 Ingress 与为 HTTP 创建 Ingress 类似,但 HTTPS 的 Ingress 规范包含一个用于指定主机和 Secret 的 tls
部分。tls
部分中的 hosts
需要与 rules
部分中的 host
明确匹配。
如果您的后端 Service 位于单独的命名空间中,则您需要在与 Ingress 相同的命名空间中创建 ExternalName 类型的 Service,以将流量路由到后端 Service。
为 HTTPS 或 HTTP 创建 Ingress 的总体步骤相同,只是清单文件中的配置内容有所不同:
如果您之前在本文档的 HTTP 部分中创建了 Ingress,请先删除该 Ingress,然后再继续操作。
kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress my-ingress
如需为您之前创建的 Service 处理流量,请创建一个具有
tls
部分的新 Ingress 清单:tls
配置可在客户端和 Ingress 代理之间启用 HTTPS。apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress-2 spec: tls: - hosts: - altostrat.com secretName: example-server-creds rules: - host: altostrat.com http: paths: - path: /greet-the-world pathType: Exact backend: service: name: hello-service port: number: 60000 - path: /greet-kubernetes pathType: Exact backend: service: name: hello-service port: number: 60001
将该清单保存到名为
my-ingress-2.yaml
的文件中,然后创建 Ingress:kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f my-ingress-2.yaml
通过测试以下内容,确认 Ingress 已创建完毕且运行正常:
测试
/greet-the-world
路径:curl -v --resolve altostrat.com:443:CLUSTER_INGRESS_VIP \ https://altostrat.com/greet-the-world \ --cacert root-ca.crt
输出:
Hello, world! Version: 2.0.0 Hostname: hello-deployment-5ff7f68854-wqzp7
测试
/greet-kubernetes
路径:curl -v --resolve altostrat.com:443:CLUSTER_INGRESS_VIP \ https://altostrat.com/greet-kubernetes --cacert root-ca.crt
输出:
Hello Kubernetes!
创建 LoadBalancer 服务
LoadBalancer
类型的服务是在集群外部公开工作负载的另一种方法。如需查看有关创建 LoadBalancer
类型的 Service 的说明和示例,请参阅“部署应用”中的“创建 LoadBalancer
类型的 Service”。
清理
删除 Ingress:
kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress INGRESS_NAME
将
INGRESS_NAME
替换为 Ingress 的名称,例如my-ingress
或my-ingress-2
。删除 Service:
kubectl --kubeconfig CLUSTER_KUBECONFIG delete service hello-service
删除 Deployment:
kubectl --kubeconfig CLUSTER_KUBECONFIG delete deployment hello-deployment
删除 LoadBalancer 服务:
kubectl --kubeconfig CLUSTER_KUBECONFIG delete service service-does-not-use-nodeports