开发者学堂课程【KubernetesServices:【公开课】KubernetesServices】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/827/detail/13948
【公开课】Kubernetes Services
内容介绍:
一、上节回顾
二、需求来源
三、用例解读
四、操作演示
五、架构设计
六、后续进阶部分预告
一、上节回顾
Kubernetes Pod 网络的基本要素:
Pod 有独立的网络空间和唯一地址
Pod 与 Pod,Node,外界网络互联互通
NetworkPolicy:
控制 Pod 到 Pod,Node,外接网络的访问限制
通过 NetworkPolicy 的一些控制,可以控制Pod到Pod,Pod到Node,Pod到外接网络的访问限制
二、需求来源
1.为什么需要服务发现
Kubernetes 应用应如何相互调用?
Pod生命周期短暂,IP地址随时变化
Deployment等的Pod组需要统一访问入口和做负载均衡
应用间在不同环境部署时保持同样的部署拓扑和访问方式
保持统一的部署模板和访问方式
2.Service: Kubernetes 中的服务发现与负载均衡
Service 向上提供外部网络和 Pod 网络的访问,外部网络和 Pod 网络都可以通过 Service 访问,向下 Service 对接另外一组 Pod,通过 Service 方式负载均衡到一组 Pod 上,Pod 提供统一的访问入口做服务发现,可以给外部网络访问,解决了不同 Pod 间访问,通过统一的访问地址。
三、用例解读
1.Service 语法
新知识点:
ports:定义服务发现的协议和端口
历史知识点回顾:
labels:标签
selector:选择器
声明结构:
apiVersion: v1
kind: Service
metadata:
name: my-service
labels: app: my-service Service 元信息
spec:
selector: Pod 选择器
app: MyApp
ports:
- protocol:TCP 协议和端口
port: 80
targetPort: 9376
声明了 my-service 一个 K8s service,有一个 labels 为 app: my-service ,选择了app,由 app 等于 Myapp 的 Pod 作为一个后端,定义服务发现的协议和端口,TCP 协议,访问 service 的80端口的 targetPort,目标的 Pod 上的 Pod 为9376。 2.创建和查看 Service
$kubectl apply -f service.yaml
service/my-service created
通过声明的模板,可以创建 service
创建好之后,可以查看结果
$ kubectl describe service my-service
Name: my-service
Namespace: default
Labels: app=my-service
Selector: app=MyApp Type:
ClusterIP IP: 172.29.3.27
//172.29.3.27 集群内虚拟
IP Port: 80/TCP
TargetPort: 9376/TCP
//selector 匹配到的后端 Pod 地址
Endpoints: 192.168.115.236:9376,192.168.115.237:9376,192.168.115.243:9376 Session Affinity: None
创建完之后生成一个 IP 地址,即为 service 的 IP 地址,在集群中可以被其他 Pod访问,相当于通过 IP 地址提供一个统一的 Pod 访问入口以及服务发现 Endpoints属性,通声明的 selector 选择到 Pod 以及 Pod 是什么样的状态,通过 selector 看到选择 Pod 的 IP 以及所声明的 Pod 端口
在 service 创建后,在集群中创建一个虚拟IP地址和端口去访问 service,service 把选择到的 Pod 挂载到后端,通过 service 的 IP 地址访问可以负载均衡到后端 Pod 上,当 Pod 的生命周期有变化时,(如一个 Pod 销毁)service 自动从后端摘除掉 Pod,实现即使 Pod 生命周期有变化,访问的端点是不变的。
3.集群内访问 Service
①直接 Service 的虚拟 IP
kubectl get svc 可以查到
②直接访问服务名,依靠DNS解析
同一个 Namespace 直接通过 servicename 访问
不同 Namespace 加上 namespace 名访问:
{servicename}.{namespace}
如,可以直接用 curl 访问
③通过环境变量访问
MY_SERVICE_PORT_80_TCP=tcp://172.29.3.27:80
MY SERVICE_SERVICE_HOST=172.29.3.27
MY_SERVICE_PORT=tcp://172.29.3.27:80
MY_SERVICESERVICE PORT=80
MY_SERVICE_PORT_80_TCP_ADDR=172.29.3.27 MY_SERVICE_PORT_80_TCP_PORT=80
MY_SERVICE_PORT_80_TCP_PROTO=tcp
Pod 在启动时,k8s 把 service 的 IP 地址、端口以及简单配置通过环境变量的方式放到 k8s 的 Pod 里。在 K8s 的容器中启动之后,通过读取系统的环境变量就可以读取到 Namespace 其他 service 的一个配置的低值或者端口号。
4.Headless Service
Service 指定 clusterlP: None Service 创建时可以指定 clusterlP 等于 None,不需要虚拟 IP Pod 通过 service_name 方式时直接解析到所有后端 Pod IP 客户端应用自主选择需要访问的 Pod
apiVersion: v1
kind: Service
metadata:
name: my-service
labels:
app: my-service
spec: selector:
app: MyApp
clusterlP: None
//增加clusterlP: None
让 Service 不再通过虚拟IP来负载均衡
ports:
- protocol: TCP
port: 80
targetPort: 9376
集群内 Pod 访问 service 时,直接解析到 service 对应的 Pod IP 地址返回到 POd,Pod 中自己选择 IP 地址直接访问
5、向集群外暴露 Service
Service 类型:
ClusterlP
ExternalName
NodePort
LoadBalancer
NodePort与LoadBalancer 提供向外暴露服务
NodePort 暴露节点端口,再做一次转发,转发到 IP 地址上 是集群每个节点的上的端口
LoadBalancer 在 NodePort 上又做一层转换,在每一个节点挂一个负载均衡,提供统一的路口,将接收的流量负载均衡到每一个集群节点 NodePort 上,NodePort 转化成 ClusterlP,访问到实际的 Pod 上
四、操作演示
创建一个阿里云服务的集群,配置到本地的终端服务到阿里云服务集群的连接
有三个模板
client
K8s service声明
创建一个 K8s service 模板,port 是 K8s 通过前端的80端口负载均衡到后端 port TCP 80端口上,selector 选择到 run 等于 nginx 标签的一些 Pod 做后端
通过 Deployment 创建一组 Pod
通过 get pod -o wide 可以看到 IP 地址
通过 -l 可以做筛选
创建 K8s service
通过 kubectl describe 可以看到所创建的状态
10.1.13.211K8s 生成的集群中虚拟 IP 地址,可以通过这个地址负载
均衡到后面10.0.0.12与10.0.0.1335两个 Pod 上
创建客户端的 Pod
可以进行测试
也可以之间通过 service 名字方式访问 service,结果是一样的
通过环境变量访问 service
通过 service,让外部网络访问 修改所创建的 service,在最后添加 type
直接访问39.98.21.18
Service 的访问地址与 Pod 的生命周期没有关系
删掉一个Pod
五、架构设计
1.Kubernetes 服务发现架构
在 K8s 中,分为 master 节点与 worker 节点,在 master 节点中,主要是 k8s 管控的内容,worker 节点中是实际上用户应用的地方。在 master 中,APIServer 是统一管理 K8s 的所有对象的地方,有三个组件,Cloud Controller Manager 负责配置 LoadBalancer 的负载均衡器,给外部访问,Coredns 关系 service 的后端 Pod 变化,配置 service 的 Pod 解析,在每个组件中有 Kube-Proxy 这一部署,通过监听 service 以及 Pod 的变化,实际配置集群例的 Pod 或者虚拟 IP 地址的访问 从集群内部的访问
Client Pod3 首先去 Coredns 解析,访问 servicename,Coredns 返回 Service 所对应的 IP,返回 IP 后,让 IP 做请求,请求到外部网,被Kube-Proxy 所配置的 iptables/IPVS 做一层拦截,把 Cluster IP 的请求实际的拦截后,负载均衡到每一个实际的后端 Pod 上,实现负载均衡以及服务发现
对于外部的流量,通过外部的负载均衡器,Cloud Controller Manager 监听 service 变化后,去配置的一个负载均衡器,转发到节点的 NodePort,NodePort经过 Kube-Proxy 的配置的 iptables,把 NodePort 的流量转化成 Cluster IP,去转换成后端的 Pod 的 Ip 地址做负载均衡以及服务发现
六、后续进阶部分预告
深入讲解 Service 的实现原理
Service 网络出现问题时的 Debug 技巧