关于 K8S 的几个问题
问题1: Deployment、StatefulSet 和 DaemonSet 的区别和联系?
这三者都是 K8S中管理 pod 集合的工作负载资源定义。一个工作负载资源可以由若干个分布到不同节点上的 pod 构成,pod 是 K8S 中创建和管理的最小可部署的计算单元,一个 pod 可以包含多个容器,多个容器之间共享存储和网络等,一个 pod 只有一个虚拟 IP。
Deployment 适合无状态的应用。pod 的名字随机生成,每次不同。Service 的 clusterIP 非空,具有转发规则(iptables等)负载均衡功能。
StatefulSet 适合有状态的应用,比如数据库。pod 的名字固定、有序,使用无头服务,Service 的 clusterIP 是 none,可以通过 dns 访问指定的 pod,访问 headless_service_name.namespace.svc.cluster.local 将返回所有 pod 的地址。特点是:
- 稳定唯一的网络标识符;
- 稳定持久的存储;
- 有序的扩缩容。
DaemonSet 适合每个节点必须放置一个的应用,比如节点监控、日志收集。当新节点加入时会自动新增一个 Pod;节点被移除时,其上的 Pod 也会被回收。
问题2: Service 原理
Service 是应用的入口,Pod 的逻辑分组,通过 Label Selector 访问到底层的一组 Pod。
Service 具有服务发现能力,该能力依赖于环境变量和 CoreDNS,CoreDNS 会监控 Kubernetes API 中的新服务,然后自动建立 DNS 记录。
Service 有四种类型:
(1)ClusterIP
该模式具有 4 层负载均衡能力,该能力依赖于运行在每个节点上的 kube-proxy 捕获到达 Service 的 clusterIP(虚拟IP)和 Port 的请求,并重定向到后端 Pod。
kube-proxy 的代理模式历史上有三种。
- userspace 模式,v1.0 的默认模式,请求会从用户空间进入内核空间的 iptables,再进入用户空间的 kube-proxy,再回到内核空间的 iptables,再进入用户空间的 Pod,多次在内核空间和用户空间之间进出,性能较差。使用轮转算法。
- iptables 模式,v1.2 的默认模式,请求直接从 iptables 到用户空间的 Pod,性能较好,但无法支持上万级的 Service,因其规则表过于庞大,连接处理复杂度为 O(n)。采用随机算法。
- IPVS(IP virtual server) 模式,v1.11 实现GA(基本可用),底层数据结构为哈希表,连接处理复杂度为 O(1)。可配置使用不同的算法,比如:轮转、最少连接、最短预期延迟等等。
kube-proxy 的 watch 机制
kube-proxy 会监控 apiServer 中写入 etcd 中 Pod 的最新状态信息,然后更新 iptables 或 ipvs 规则。若 ipvs 不可用,会降级为 iptables。
(2)Headless
无头服务,没有 ClusterIP,无法代理转发,无法负载均衡。可以直接访问到 Pod。
(3)NodePort
将节点上的一个端口绑定到 Service 中,通过 NodeIP:NodePort 进行访问。
(4)LoadBalancer
在 NodePort 基础上,通过云提供商的负载均衡器实现外部负载均衡。
(5)ExternalName
将外部的服务映射到内部进行使用。
问题3: Ingress 原理
七层代理(HTTP),包含两个重要的组建:Ingress 和 Ingress Controller。Ingress 为外部请求提供路由规则,Ingress Controller 监控 Ingress 和 Service 的变化,并根据规则配置负载均衡提供访问入口。
目前 K8S 官方维护了三种 Ingress Controller:AWS、Ingress-Nginx、GCE,第三方的 Ingress Controller 有 Istio、Kong 等等。