本文档介绍如何在用户、混合或独立集群中为 Anthos clusters on Bare Metal 创建 Kubernetes Ingress 对象。一个 Ingress 与一个或多个 Service 相关联,每个 Service 与一组 Pod 相关联。
准备工作
获取从集群到管理员工作站的 SSH 连接。
创建 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。该请求将被转发到targetPort
上的成员 Pod。在此示例中为POD_IP_ADDRESS:50000
。使用
kubernetes-port
:在其中一个集群节点上运行的客户端会向port
上的clusterIP
发送请求。在此示例中为 10.96.14.249:60001。该请求将被转发到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/Anthos Service Mesh 安装不冲突。
创建 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
与 Anthos Clusters on Bare Metal 捆绑的 Ingress 功能仅支持入站流量功能。您可以选择与 Istio 或 Anthos Service Mesh 集成。这些产品具有功能全面的服务网格的额外优势,例如双向 TLS (mTLS),能够管理服务之间的身份验证以及工作负载可观测性。如果与 Istio 或 Anthos Service Mesh 集成,我们建议您停用捆绑的 Ingress 功能。
您可以使用集群配置文件中的 spec.clusterNetwork.bundledIngress
字段启用或停用捆绑式 Ingress。此字段仅适用于 1.13.0 版及更高版本的集群。bundledIngress
字段默认为 true
,在生成的集群配置文件中不存在。此字段是可变的,可在创建或更新 1.13.0 版或更高版本的集群时更改。您还可以在将集群升级到 1.13.0 版或更高版本时指定此字段。
以下示例集群配置文件展示了如何配置集群以停用捆绑式 Ingress 功能:
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:
- 172.26.232.0/24
...
为 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
如果您之前在 HTTP 部分中创建了 Ingress,请先删除该 Ingress,然后再继续操作。
删除 Ingress:
kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress my-ingress
如需处理您之前创建的 Service 的流量,请创建一个具有 tls
部分的新 Ingress。这将在客户端和入站流量代理之间启用 HTTPS。
以下是 Ingress 的清单:
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
通过测试确认。
测试
/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
类型是 NodePort
类型的扩展。因此,LoadBalancer
类型的 Service 具有集群 IP 地址以及一个或多个 nodePort
值。
默认情况下,Kubernetes 会将节点端口分配给 LoadBalancer 服务。这些分配可能会快速从分配给集群的 2,768 中耗尽可用的节点端口。如需保存节点端口,请通过将 LoadBalancer Service 规范中的 allocateLoadBalancerNodePorts
字段设置为 false
来停用负载均衡器节点端口分配。此设置可防止 Kubernetes 将节点端口分配给 LoadBalancer 服务。如需了解详情,请参阅 Kubernetes 文档中的停用负载均衡器 NodePort 分配。
以下清单用于创建不使用任何节点端口的服务:
apiVersion: v1
kind: Service
metadata:
name: service-does-not-use-nodeports
spec:
selector:
app: my-app
type: LoadBalancer
ports:
- port: 8000
# Set allocateLoadBalancerNodePorts to false
allocateLoadBalancerNodePorts: false
清理
删除 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