我花了10个小时,写出了这篇K8S架构解析( 四 )


apiVersion : v1 kind: Service #说明创建资源对象的类型是Service metadata: name: mysql#Service全局唯一名称 spec: prots: -port: 3306#Service的服务端口号 selector:#Service对应的Pod标签,用来给Pod分类 app: mysql 按照惯例运行 kubectl,创建 Service:

我花了10个小时,写出了这篇K8S架构解析

文章插图
 
再用 getsvc 命令检查 Service 信息:
我花了10个小时,写出了这篇K8S架构解析

文章插图
 
这里的 Cluster-IP 169.169.253.143 是由 Kubernetes 自动分配的 。当一个 Pod 需要访问其他的 Pod 的时候就需要通过 Service 的 Cluster-IP 和 Port 。
也就是说 Cluster-IP 和 Port 是 Kubernetes 集群的内部地址,是提供给集群内的 Pod 之间访问使用的,外部系统是无法通过这个 Cluster-IP 来访问 Kubernetes 中的应用的 。
上面提到的 Service 只是一个概念,而真正将 Service 落实的是 kube-proxy 。
只有理解了 kube-proxy 的原理和机制,我们才能真正理解 Service 背后的实现逻辑 。
在 Kubernetes 集群的每个 Node 上都会运行一个 kube-proxy 服务进程,我们可以把这个进程看作 Service 的负载均衡器,其核心功能是将到 Service 的请求转发到后端的多个 Pod 上 。
此外,Service 的 Cluster-IP 与 NodePort 是 kube-proxy 服务通过 iptables 的 NAT 转换实现的 。kube-proxy 在运行过程中动态创建与 Service 相关的 iptables 规则 。
由于 iptables 机制针对的是本地的 kube-proxy 端口,所以在每个 Node 上都要运行 kube-proxy 组件 。
因此在 Kubernetes 集群内部,可以在任意 Node 上发起对 Service 的访问请求 。
我花了10个小时,写出了这篇K8S架构解析

文章插图
 
集群内部通过 kube-proxy(Service)访问其他 Pod
正如 MySQL 服务,可以被 Kubernetes 内部的 Tomcat 调用,那么 Tomcat 如何被 Kubernetes 外部调用?
先生成配置文件,myweb-rc.yaml 看看:
apiVersion: V1 kind: ReplicationController metadata: name: myweb#RC的名称,全局唯一 spec: replicas:2#Pod 副本的期待数量,这里的数量是2,需要建立两个Tomcat的副本 selector : app: myweb template: #Pod模版,用这个模版来创建Pod metadata: labels: app:myweb#Pod副本的标签 spec: containers: #容器定义部分 -name:mysql Image:kubeguide/tomcat-app:v1#容器对应的DockerImage Ports: -containerPort:8080#容器应用监听的端口号 在 kubectl 中使用 Create 建立 myweb 副本 。
我花了10个小时,写出了这篇K8S架构解析

文章插图
 
副本创建完毕以后,创建对应的服务配置文件 myweb-svc.yaml 。
apiVersion : v1 kind: Service #说明创建资源对象的类型是Service metadata: name: myweb#Service全局唯一名称 spec: prots: -port: 8080#Service的服务端口号 nodePort: 30001#这个就是外网访问Kubernetes内部应用的端口 。selector: #Service对应的Pod标签,用来给Pod分类 app: myweb 同样在 kubectl 中运行 Create 命令,建立 Service 资源 。
我花了10个小时,写出了这篇K8S架构解析

文章插图
 
从上面的配置文件可以看出,Tomcat 的 Service 中多了一个 nodePort 的配置,值为 30001 。
【我花了10个小时,写出了这篇K8S架构解析】也就是说外网通过 30001 这个端口加上 NodeIP 就可以访问 Tomcat 了 。
运行命令之后,得到一个提示,大致意思是“如果你要将服务暴露给外网使用,你需要设置防火墙规则让 30001 端口能够通行 。”
由于 Cluster-IP 是一个虚拟的 IP,仅供 Kubernetes 内部的 Pod 之间的通信 。
Node 作为一个物理节点,因此需要使用 Node-IP 和 nodePort 的组合来从 Kubernetes 外面访问内部的应用 。
如果按照上面的配置,部署了两个 Tomcat 应用,当外网访问时选择那个 Pod 呢?这里需要通过 Kubernetes 之外的负载均衡器来实现的 。
我花了10个小时,写出了这篇K8S架构解析

文章插图
 
Kubernetes 之外的负载均衡器
可以通过 Kubernetes 的 LoadBlancerService 组件来协助实现 。通过云平台申请创建负载均衡器,向外暴露服务 。
目前 LoadBlancerService 组件支持的云平台比较完善,比如国外的 GCE、DigitalOcean,国内的阿里云,私有云 OpenStack 等等 。
从用法上只要把 Service 的 type=NodePort 改为 type=LoadBalancer,Kubernetes 就会自动创建一个对应的 Load Balancer 实例并返回它的 IP 地址供外部客户端使用 。
至此,MySQL(RC 1)和 Tomcat(RC 2)已经在 Kubernetes 部署了 。并在 Kubernetes 内部 Pod 之间是可以互相访问的,在外网也可以访问到 Kubernetes 内部的 Pod 。


推荐阅读