diff --git a/assets/Cluster-AutoScaler.png b/assets/Cluster-AutoScaler.png new file mode 100644 index 00000000..e06a29bc Binary files /dev/null and b/assets/Cluster-AutoScaler.png differ diff --git a/assets/HPA.png b/assets/HPA.png index 4a471090..ff3fcfc4 100644 Binary files a/assets/HPA.png and b/assets/HPA.png differ diff --git a/assets/cas.png b/assets/cas.png new file mode 100644 index 00000000..65ab0c61 Binary files /dev/null and b/assets/cas.png differ diff --git a/assets/how_mtls_works-what_is_mutual_tls.png b/assets/how_mtls_works-what_is_mutual_tls.png new file mode 100644 index 00000000..faf87e63 Binary files /dev/null and b/assets/how_mtls_works-what_is_mutual_tls.png differ diff --git a/assets/how_tls_works.png b/assets/how_tls_works.png new file mode 100644 index 00000000..6c8f95fc Binary files /dev/null and b/assets/how_tls_works.png differ diff --git a/assets/vpa.png b/assets/vpa.png new file mode 100644 index 00000000..85c25f0b Binary files /dev/null and b/assets/vpa.png differ diff --git a/container/auto-scaling.md b/container/auto-scaling.md index 0a40174b..fae2739d 100644 --- a/container/auto-scaling.md +++ b/container/auto-scaling.md @@ -1,71 +1,73 @@ # 7.8 弹性伸缩 -弹性伸缩意思通过应用云计算弹性伸缩的功能实现业务量增减资源的合理应用,驱动弹性的背景总结来说: +弹性伸缩(Elastic Scaling Service,简称ESS),也称 Auto Scaling,目标是通过解决欠配置(损失服务可用性)和过度配置(导致不必要的成本)实现容量与成本之间博弈的平衡。 -- 峰值负载应对:促销活动、节假日购物季或突发事件根据需求快速扩展资源,保证应用可用性和性能。 -- 提高资源利用率:根据实际资源负载动态调整资源规模,避免基础设施资源浪费,降低 TCO(Total Cost of Ownership,总体拥有成本)。 -- 应对故障和容错:多实例部署和快速替换,提高业务连续性和可用性。 +Kubernetes 弹性伸缩组件可以从伸缩方向和伸缩对象两个维度进行解读。如下表所列,HPA 负责容器的水平伸缩,cluster-autoscaler 负责节点的水平伸缩。 -## Horizontal Pod Autoscaling +|| Node | Pod | +|:--|:--|:--| +| Horizontal | Cluster AutoScaler | Horizontal Pod Autoscaler(HPA,水平 Pod 垂直自动伸缩器)| +| Vertical | 无 | Vertical Pod Autoscaler(VPA,垂直 Pod 自动伸缩器)| -Kubernetes 自身提供一种弹性伸缩的机制,包括 Vertical Pod Autoscaler (VPA) 和 Horizontal Pod Autoscaler (HPA)。HPA 根据 CPU 、内存利用率增加或减少副本控制器的 pod 数量,它是一个扩缩资源规模的功能特性。 -HPA 依赖 Metrics-Server 捕获 CPU、内存数据来提供资源使用测量数据,也可以根据自定义指标(如 Prometheus)进行扩缩。 +如果集群的资源不够,那就得对节点进行扩容。集群节点的弹性伸缩本来是一件非常麻烦的事情,好在现在的集群大多都是构建在云上,云上可以直接调用接口添加删除节点,这就使得集群节点弹性伸缩变得非常方便。 + +这是一个自动扩展和收缩 Kubernetes 集群 Node 的扩展。当集群容量不足时,它会自动去 Cloud Provider (支持绝大部分的云服务商 GCE、GKE、Azure、AKS、AWS 等等)创建新的 Node,而在 Node 长时间(超过 10 分钟)资源利用率很低时(低于 50%)自动 Pod 会自动调度到其他 Node 上面,并删除节点以节省开支。 + +
+ +
+ +Cluster Autoscaler 虽然是 Kubernetes 官方标准,但是由于他深度依赖公有云厂商,因此具体使用方法,功能以及限制以公有云厂商具体实现为准。 + + +VPA 组件确保工作负载适配方式是动态调整 Pod 资源上限而不是水平扩展它们。但这里有一个问题:增强型的 Pod 并不一定好,大多数情况下使用更多的进程处理数据远比使用一个大且强的工作进程更高效。
- + +

VPA 调整 Pod 的大小

-由上图看出,HPA 持续监控 Metrics-Server 的指标情况,根据收集到的 Pod 资源的 metrics 计算除所需的副本数并进行动态调整资源副本,实现设置目标资源值的水平伸缩。 +用到最多的是 HPA组件,HPA 根据观察到的指标(主要是 CPU、内存)来横向增加或减少 Pod 数量。HPA 从最初的 v1 版本只支持 CPU、内存利用率的伸缩,到后来的自定义指标、聚合层 API 的支持,到了 v1.18 版本又加入了配置伸缩行为的支持。现在最新的版本是 autoscaling/v2,引入 Prometheus 的广泛指标。 + +
+ +

HPA 改变 Pod 的数量

+
+传统的指标如 CPU 和内存不一定就能代表服务的负载情况。比如事件驱动的应用程序 Kafka,传入 kafka 事件的数量才是确定负载的真实指标。在持续集成(CI)流水线中,当提交代码时,可能会触发一系列的流水线作业(镜像编译、应用打包、可用性测试),如果持续集成的作业出现瓶颈,这里的度量标准应该是等待执行的任务数,那么基于作业队列数量伸缩比仅仅观察 CPU 或者内存指标更有效。 -下面示例,创建一个 HPA, 期望 CPU 的利用率为 70%,副本数的范围是 1-10,操作对象名 nginx-deployment 为 Deployment 。 +当然,Kubernetes 也看到了这一点。HPA 在经过三个大版本的演进之后,也实现支持 Resource Metrics(资源指标,如pod的CPU)和Custom Metrics(自定义指标)和 ExternalMetrics(额外指标)的缩放,如果需要基于其他地方如 Prometheus、Kafka、云供应商或其他事件上的指标进行伸缩,那么可以通过 v2 版本提供的 external metrics 来实现 -```plain -apiVersion: autoscaling/v2beta1 -kind: HorizontalPodAutoscaler -metadata: - name: scale - namespace: default -spec: - maxReplicas: 10 # 目标资源的最大副本数量 - minReplicas: 1 # 目标资源的最小副本数量 - metrics: # 度量指标,期望CPU的利用率为70% - - resource: - name: cpu - targetAverageUtilization: 70 - type: Resource - scaleTargetRef: # 目标资源 - apiVersion: apps/v1 - kind: Deployment - name: nginx-deployment -``` +## 基于事件驱动的方式 -使用 HPA 对资源进行伸缩,也存在一定局限性: +HPA v2 版本就可以实现基于外部指标弹性伸缩,只是实现上比较麻烦。而 Kedify、Microsoft 开源的 KEDA(Kubernetes Event-driven Autoscaling)项目则可以简化这个过程,使用起来更加方便,而且 KEDA 已经内置了几十种常见的 Scaler 可以直接使用。 -- 无外部指标支持。如不同的事件源,不同的中间件/应用程序等,业务端的应用程序变化及依赖是多样的,不只是基于 CPU 和内存扩展。 -- 无法 1->0。应用程序总有 0 负载的时候,此时不能不运行工作负载吗? +:::tip +KEDA 的出现是为了增强 HPA,而不是替代 HPA。 +::: -所以就有了 Kubernetes-based Event-Driven Autoscaling(KEDA)! +KEDA 并没有取代 HPA,而是对 Kubernetes 内置的 HAP 组件的补充。 -## 利用事件驱动 Keda 进行弹性伸缩 +基于事件的触发方式,KEDA 就是一个 HPA + 多种触发器。只要触发器收到某个事件被触发,KEDA 就可以使用 HPA 进行自动伸缩了。 -Kubernetes 自带的 HPA 仅支持 CPU/MEM 等有限的指标,但事实情况这些指标不一定就能代表服务的负载情况,比如消息服务器,如果消息堆积过多,我们希望启用更多的 Customer 处理消息,这种情况下就可以使用 Keda。 +
+ +
KEDA 使得 Kubernetes 能够对 Pods 副本缩0或者扩展到更多是基于标准内置的 Kubernetes 指标,例如CPU和内存等标准,但也基于高级指标,例如消息队列的排队深度,每秒请求数,调度的 Cron 作业数,或者从您自己的应用程序记录中以及您可以想象的其他所有指标中的自定义指标 +KEDA 会从外部度量提供者系统 (上面提到的指标扩展器,比如 Azure Monitor) 监控度量,然后根据基于度量值的伸缩规则进行伸缩。作为一个Kubernetes Operator 运行直接与度量提供者系统通信, +
- +
+## 离在线混部 -KEDA 是 Kubernetes 基于事件驱动的自动伸缩工具,通过 KEDA 我们可以根据需要处理的事件数量来驱动 Kubernetes 中任何容器的扩展。 https://keda.sh/docs/2.12/scalers/ -
- -
\ No newline at end of file diff --git a/container/k8s-deploy-tls.md b/container/k8s-deploy-tls.md index 7b771735..56f68e3e 100644 --- a/container/k8s-deploy-tls.md +++ b/container/k8s-deploy-tls.md @@ -1,6 +1,6 @@ # 证书配置 -Kubernetes 的安装和组件启动参数中有大量的证书配置相关参数,很多同学在此会遇到各种各样“稀奇古怪”的问题,在本节,笔者花费一定的篇幅解释 Kubernetes 中证书证书配置背后的流程和原理,这将有助于我们深入理解 kubernetes 的安装过程和组件的配置。 +Kubernetes 的安装和组件启动参数中有大量的证书配置相关参数,很多同学在此会遇到各种各样“稀奇古怪”的问题。在本节,我们先去了解 Kubernetes 中证书配置背后的流程和原理,这将有助于我们深入理解 kubernetes 各个组件的配置及流程逻辑。 首先,Kubernetes 中各个组件是以独立进程形式运行,组件之间通过 HTTP/GRPC 相互通信。如下图所示,控制平面中 etcd、kube-api-server、kube-scheduler 等组件相互进行远程调用:kube-api-server 调用 etcd 接口存储数据;kube-api-server 调用工作节点中的 kubelet 管理和部署应用...。 @@ -9,74 +9,46 @@ Kubernetes 的安装和组件启动参数中有大量的证书配置相关参数

kubernetes 组件

-由于组件之间的调用都是通过网络进行,为避免恶意第三方伪造身份窃取信息或者对系统进行攻击,就得对通信进行加密。笔者在 2.5.1 篇节介绍过 TLS 的通信原理,我们回忆前文,典型的 TLS 加密的流程如下。 - -
- -

HTTPS 通信流程

-
- -- 服务端向 CA 机构申请证书, -- 客户端请求服务端时,服务端向客户端下发证书 -- 客户端根据本地根证书校验服务端的证书 -- 客户端拿到证书的内公钥,加密之后传递服务端,服务端用本地的私钥进行解密获取正文。 - -HTTPS 实际是一个单向验证的过程(客户端验证了服务端的合法性,但服务端未验证客户端的合法性),而在 Kubernetes 中,**各个组件既是客户端也是服务端,它们之间的通信就需要采用 mTLS(Mutual TLS,双向 TLS)认证的方式**。mTLS 中,客户端和服务器都有一个证书,并且双方都使用它们的公钥/私钥对进行身份验证。与常规 TLS 相比,mTLS 中有一些额外步骤来验证双方(额外的步骤加粗显示)。 - -- 客户端连接到服务器 -- 服务器出示其 TLS 证书 -- 客户端验证服务器的证书 -- **客户端出示其 TLS 证书** -- **服务器验证客户端的证书** -- **服务器授予访问权限** -- 客户端和服务器通过加密的 TLS 连接交换信息 +由于组件之间的调用都是通过网络进行,为避免恶意第三方伪造身份窃取信息或者对系统进行攻击,就得对通信进行加密。希望你还能回忆起 2.5.1 篇节介绍过 TLS 的通信原理,不过常规的 TLS 是一个单向验证的过程(只校验了服务端),而在 Kubernetes 中,**各个组件提供的接口中包含了集群的内部信息,如果接口被非法访问,将影响集群的安全性。因此它们之间的通信就需要采用 mTLS(Mutual TLS,双向 TLS)认证的方式**[^1],即客户端和服务器端都需要验证对方的身份信息。 使用 mTLS 双向认证时,涉及到下面这些证书相关的文件: -- **服务器端证书**:服务器用于证明自身身份的数字证书,里面主要包含了服务器端的公钥以及服务器的身份信息。配置中一般以 cert-file 为参数。 -- **服务器端私钥**:服务器端证书中包含的公钥所对应的私钥。公钥和私钥是成对使用的,在进行 TLS 验证时,服务器使用该私钥来向客户端证明自己是服务器端证书的拥有者。配置中一般为 key-file。 -- **客户端证书**:客户端用于证明自身身份的数字证书,里面主要包含了客户端的公钥以及客户端的身份信息。 -- **客户端私钥**:客户端证书中包含的公钥所对应的私钥,同理,客户端使用该私钥来向服务器端证明自己是客户端证书的拥有者。 -- **服务器端 CA 根证书**:签发服务器端证书的 CA 根证书,客户端使用该 CA 根证书来验证服务器端证书的合法性。一般参数名为 ca-file。 -- **客户端端 CA 根证书**:签发客户端证书的 CA 根证书,服务器端使用该 CA 根证书来验证客户端证书的合法性。 +- 服务端: + - 服务端证书,用于证明自身身份的数字证书,里面主要包含了服务器端的公钥以及服务器的身份信息,配置中的一般含有 cert file 关键词。 + - 服务端公钥,服务器端证书中包含的公钥所对应的私钥,公钥和私钥是成对使用的,在进行 TLS 验证时,服务器使用该私钥来向客户端证明自己是服务器端证书的拥有者,配置中的一般含有 key file 关键词。 + - 服务器端 CA 根证书,签发服务器端证书的 CA 根证书,提前安装在客户端,客户端使用该 CA 根证书来验证服务器端证书的合法性。配置中的一般含有 ca-file 关键词。 +- 客户端: + - 客户端证书,用于证明自身身份的数字证书 + - 客户端私钥,使用该私钥来向请求者证明自己是该证书的拥有者。配置中一般为 key-file + - 客户端 CA 根证书,签发客户端证书的 CA 根证书,服务器端使用该 CA 根证书来验证客户端证书的合法性。 -Kubernetes 中使用了大量的证书 -``` -/usr/local/bin/kube-apiserver \\ - --tls-cert-file=/var/lib/kubernetes/kube-apiserver.pem \\ # 用于对外提供服务的服务器证书 - --tls-private-key-file=/var/lib/kubernetes/kube-apiserver-key.pem \\ # 服务器证书对应的私钥 - --etcd-certfile=/var/lib/kubernetes/kube-apiserver-etcd-client.pem \\ # 用于访问 etcd 的客户端证书 - --etcd-keyfile=/var/lib/kubernetes/kube-apiserver-etcd-client-key.pem \\ # 用于访问 etcd 的客户端证书的私钥 - --kubelet-client-certificate=/var/lib/kubernetes/kube-apiserver-kubelet-client.pem \\ # 用于访问 kubelet 的客户端证书 - --kubelet-client-key=/var/lib/kubernetes/kube-apiserver-kubelet-client-key.pem \\ # 用于访问 kubelet 的客户端证书的私钥 - --client-ca-file=/var/lib/kubernetes/cluster-root-ca.pem \\ # 用于验证访问 kube-apiserver 的客户端的证书的 CA 根证书 - --etcd-cafile=/var/lib/kubernetes/cluster-root-ca.pem \\ # 用于验证 etcd 服务器证书的 CA 根证书 - --kubelet-certificate-authority=/var/lib/kubernetes/cluster-root-ca.pem \\ # 用于验证 kubelet 服务器证书的 CA 根证书 - --service-account-key-file=/var/lib/kubernetes/service-account.pem \\ # 用于验证 service account token 的公钥 - ... -``` +
+ +

kubernetes 组件

+
+ +Kubernetes 中使用了大量的证书,本文不会视图覆盖到多有的证书,但会讨论到主要的证书。理解了这些证书的使用方法和原理后,也能很快理解其他可能遇到的证书文件。

HTTPS 通信流程

-- etcd 集群证书 - - 1. 由于一个 etctd 节点既为其他节点提供服务,又需要作为客户端访问其他节点,因此该证书同时用作服务器证书和客户端证书。 - - 2. etcd 集群向外提供服务使用的证书。该证书是服务器证书。 -- kube-apiserver 作为客户端访问 etcd 使用的证书 -- kube-apiserver 对外提供服务使用的证书 -- kube-controller-manager 作为客户端访问 kube-apiserver 使用的证书 -- kube-scheduler 作为客户端访问 kube-apiserver 使用的证书 -- kube-proxy 作为客户端访问 kube-apiserver 使用的证书 -- kubelet 作为客户端访问 kube-apiserver 使用的证书 -- 管理员用户通过 kubectl 访问 kube-apiserver 使用的证书 -- kubelet 对外提供服务使用的证书 -- kube-apiserver 作为客户端访问 kubelet 采用的证书 -- kube-controller-manager 用于生成和验证 service-account token 的证书 +1. etcd 集群证书,由于一个 etctd 节点既为其他节点提供服务,又需要作为客户端访问其他节点,因此该证书同时用作服务器证书和客户端证书。 +2. etcd 集群向外提供服务使用的证书,该证书是服务器证书。 +3. kube-apiserver 作为客户端访问 etcd 使用的证书。该证书是客户端证书 +4. kube-apiserver 对外提供服务使用的证书。该证书是服务器证书。 +5. kube-controller-manager 作为客户端访问 kube-apiserver 使用的证书,该证书是客户端证书 +6. kube-scheduler 作为客户端访问 kube-apiserver 使用的证书 +7. kube-proxy 作为客户端访问 kube-apiserver 使用的证书,该证书是客户端证书 +8. kubelet 作为客户端访问 kube-apiserver 使用的证书,该证书是客户端证书 +9. 管理员用户通过 kubectl 访问 kube-apiserver 使用的证书,该证书是客户端证书 +10. kubelet 对外提供服务使用的证书。该证书是服务器证书。 +11. kube-apiserver 作为客户端访问 kubelet 采用的证书。该证书是客户端证书 +12. kube-controller-manager 用于生成和验证 service-account token 的证书。该证书并不会像其他证书一样用于身份认证,而是将证书中的公钥/私钥对用于 service account token 的生成和验证。kube-controller-manager 会用该证书的私钥来生成 service account token,然后以 secret 的方式加载到 pod 中。pod 中的应用可以使用该 token 来访问 kube-apiserver。 ## 安装 cfssl @@ -104,48 +76,29 @@ CFSSL可以创建一个获取和操作证书的内部认证中心。运行认证 cd ssl/ cat > ca-config.json < ca-csr.json < kubernetes-csr.json < kubernetes-csr.json < kubernetes-csr.json < etcd-peer-csr.json < + +

HTTPS 通信流程

+ + +- 服务端向 CA 机构申请证书, +- 客户端请求服务端时,服务端向客户端下发证书 +- 客户端根据本地根证书校验服务端的证书 +- 客户端拿到证书的内公钥,加密之后传递服务端,服务端用本地的私钥进行解密获取正文。 + + 理解了 HTTPS 的原理之后,我们继续下一节,看看 SSL 层有哪些可以优化的措施,以便让 HTTPS 请求更快。