写在前面
- 博文内容为
OpenShift
网络相关组件Service、Routes
的一些认识 - 理解不足小伙伴帮忙指正
傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。--------王小波
为了实现容器跨主机通信,OCP 使用 SDN 方法。SDN 是一个网络模型,允许管理员将多层网络抽象化成网络服务,通过软件处理数据量,包含两个平面:
- control plane:handles the traffic
- data plane:route the traffic
在 OpenShift3.9 版本,管理员使用 SDN 插件配置 pod 网络:
- ovs-subnet 插件,默认插件,提供一个 flat 网络,该网络中所有 pod 和 service 可以互相访问。
- ovs-multitenant 插件,用于隔离 pods 和 service ,每个 project 都会分配一个唯一的虚拟网络 ID(VNID),每个项目中的 pod 都无法与其他项目中 pod 通信。VNID 为 0 的项目中 pod 可以与其他项目中所有 pod 通信,default 项目的 VNID 是 0。
- ovs-networkpolicy 插件,支持管理员使用 NetworkPolicy 对象定义自己的隔离策略。
OpenShift 使用 Open vSwitch 构建和维护 OpenShift 网络。默认 master 是不允许通过集群网络访问容器,除非 master 节点同时配置为 nodes 节点。
在 OCP 默认安装环境中,每个 pod 都会获得唯一 ip 地址。一个 pod 中所有容器,就像在同一个主机上。每个 pod 分配一个 ip 意味着,可以把每个 pod 看做是一个物理机或者虚拟机。
OpenShift Service
service 是 Kubernetes 中一个核心的对象,通过 kube-proxy
或者 Ingress
为多个 pods 提供前端负载均衡。service 提供一个稳定的 IP 地址,与后端的多个 pods 通信,而客户端不需要跟踪各个 pod IP 地址。只需要知道 SVC 的地址或者 服务向外发布的地址即可。
Kubernetes 中的 Service 解决的问题
- Pod 的 IP 地址是不可靠的,当 Pod 所在的 Node 发生故障时,Pod 将被 Kubernetes 重新调度到另一个 Node,Pod 的 IP 地址将发生变化。无法被跟踪,
- 如果容器应用本身是分布式的部署方式,做水平扩展,通过多个实例共同提供服务,需要在这些实例的前端设置一个负载均衡器来实现请求的分发。
下面的配置为一个 Service 的核心部分,这里为了方便,我们使用 json 的格式展示
┌──[[email protected]]-[~]
└─$oc get svc hello-openshift -o json | jq .spec
{
"clusterIP": "172.30.169.91",
"ports": [
{
"name": "8080-tcp",
"port": 8080,
"protocol": "TCP",
"targetPort": 8080
},
{
"name": "8888-tcp",
"port": 8888,
"protocol": "TCP",
"targetPort": 8888
}
],
"selector": {
"app": "hello-openshift",
"deploymentconfig": "hello-openshift"
},
"sessionAffinity": "None",
"type": "ClusterIP"
}
具体的属性我们来了解下
clusterIP
: 指定当前服务发布的 IP ,这个 IP 是作为 负载均衡的 入口地址ports
: 为服务发布的端口号,这里的端口 是 Service 提供能力的具体端口,对应 Pod 暴露的 端口,可以看到这是一个多端口的 Service
┌──[[email protected]]-[~]
└─$oc get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-openshift ClusterIP 172.30.169.91 <none> 8080/TCP,8888/TCP 11h
┌──[[email protected]]-[~]
└─$
selector
: 选择器,K8s 通过标签的方式来选择对应的 后端能力提供者, 可以选择deployment,replicaset,pod,replicationcontrollerd
等。选择后会自动创建对应的Endpoint
┌──[[email protected]]-[~]
└─$oc get svc hello-openshift --show-labels
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE LABELS
hello-openshift ClusterIP 172.30.169.91 <none> 8080/TCP,8888/TCP 15h app=hello-openshift
┌──[[email protected]]-[~]
└─$oc get pods --selector=app=hello-openshift
NAME READY STATUS RESTARTS AGE
hello-openshift-1-j46gc 1/1 Running 0 15h
sessionAffinity
: 负载分发策略, 目前 K8s 提供了两个负载分发策略:RoundRobin(轮询)
和SessionAffinity(基于客户端IP进行会话保持)
, 在默认情况下,Kubernetes 采用RoundRobin
轮询模式对客户端请求进行负载分发,可以通过设置service.spec.sessionAffinity=ClientIP
来启用 SessionAffinity 策略。还有最后一个type
.
type
用于定义发布的服务类型,默认为 ClusterIP
- ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问
- NodePort:通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求
<NodeIP>:<NodePort>
,可以从集群的外部访问一个 NodePort 服务。Kubernetes master 将从给定的配置范围内(默认:30000-32767)分配端口,每个 Node 将从该端口(每个 Node 上的同一端口)代理到 Service。该端口将通过 Service 的 spec.ports[*].nodePort 字段被指定。 - LoadBalancer:外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。使用支持外部负载均衡器的云提供商的服务,设置 type 的值为"LoadBalancer",将为 Service 提供负载均衡器。
关于 Service 的创建这里不做分享, OKD 中,大多数情况下会自动创建对应的 Service 资源对象。
OpenShift Routes
Router
是 OKD
所特有的,在 K8s 体系中,没有对应的API资源,包括上面我们谈到的 DC(DeploymentConfig)、IS
等。
OpenShift Route 由共享的 router service
提供,以 实例方式方式运行在 pod 中,可以像普通 pod 一样水平扩展。
router service 是基于开源软件 HAProxy,提供集群外客户端访问集群内 pod。
route 连接公网 IP 和内部 service IP 地址 。为了提高性能和减少延迟,OpenShift 路由器直接连接 pod ,此时 service 仅仅提供查询 endpoints 功能。管理员需要配置一个公网可以解析的主机名指向运行 route 的 node 公网 IP。典型地方式是使用 DNS wildcard 配置。
博文参考
《开源容器云OpenShift:构建基于Kubernetes的企业应用云平台》
《Kubernetes权威指南:从Docker到Kubernetes实践全接触》
《OCP 3.9 DO280 Red Hat OpenShift Administration I》