一、背景介绍
截至 k8s 1.10 版本,horizontalpodautoscalers 还只支持基于 CPU 使用率实现动态伸缩
很多场景下,往往需要更多的监测指标来指导集群的扩缩容,如 HTTP 请求率、内存使用率等
幸运的是,k8s 提供了 aggregation 来支持用户自定义的 API 拓展,详情请戳 这里
通过自定义 api,我们就可以借助 prometheus 收集到的集群运行信息,完成自定义的弹性伸缩
本文就介绍一种基于 prometneus 的自定义集群动态伸缩方案
二、配置步骤
2.1 本文假设用户已经拥有一个正常运行的 k8s 集群,如果您还没有部署,可以参考这里一键完成快速部署
K8S 集群版本: 1.10.4
Docker 版本:18.03.0-ce
操作系统:CentOS Linux release 7.4.1708 (Core)
2.2 配置 K8S 集群,开启 aggregation 功能
注意:如果您是通过 2.1 中链接部署的 k8s 集群,该步骤已经配置过,可以略过
调整 apiserver 的启动配置项(追加如下几项,证书自己按需生成):
--requestheader-client-ca-file=/etc/kubernetes/ssl/ca.pem \
--requestheader-allowed-names=aggregator \
--requestheader-extra-headers-prefix=X-Remote-Extra- \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--proxy-client-cert-file=/etc/kubernetes/ssl/aggregator-proxy.pem \
--proxy-client-key-file=/etc/kubernetes/ssl/aggregator-proxy-key.pem \
--enable-aggregator-routing=true \
调整 controller-manager 的启动配置项(追加如下内容):
--master=<apiserver-address>:<port> \
--horizontal-pod-autoscaler-use-rest-clients=true \
重启拉起集群
检查配置是否生效
执行:kubectl api-versions
2.3 部署 prometheus
安装包 地址:https://github.com/coreos/prometheus-operator
a. 该 prometheus 使用了 kubelet 进行数据采集,需要确保 kubelet 开启了如下参数配置
--authentication-token-webhook=true
--authorization-mode=Webhook
b. 开启上述参数后,如果 kubectl logs xxx 命令提示
Forbidden (user=kubernetes, verb=get, resource=nodes, subresource=proxy)
说明 ApiServer 权限不够了,部署如下 yaml 文件可以解决
(注意末尾的 user name 使用你集群的实际用户)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kube-apiserver
namespace: kube-system
rules:
- apiGroups:
- ""
resources:
- nodes/proxy
- nodes/metrics
verbs:
- get
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kube-apiserver
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kube-apiserver
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: kubernetes
c. 部署 prometheus
cd <PROMETHEUS-OPERATOR-ROOT>/contrib/kube-prometheus
kubectl create -f manifests/
d. 配置 prometheus 拥有必须的权限
默认 prometheus 不能访问所有命名空间
拷贝 <PROMETHEUS-OPERATOR-ROOT>/contrib/kube-prometheus/manifests/prometheus-clusterRole.yaml
编辑该文件,末尾追加如下内容:
- apiGroups: [""]
resources:
- nodes
- services
- endpoints
- pods
verbs: ["get", "list", "watch"]
kubectl apply -f prometheus-clusterRole.yaml
e. 默认部署的 prometheus 没有开放 NodePort
prometheus-nodeport.yaml
kind: Service
apiVersion: v1
metadata:
name: prometheus-nodeport
namespace: monitoring
spec:
type: NodePort
ports:
- port: 9090
targetPort: 9090
nodePort: 39000
selector:
app: prometheus
prometheus: k8s
grafana-nodeport.yaml
kind: Service
apiVersion: v1
metadata:
name: grafana-nodeport
namespace: monitoring
spec:
type: NodePort
ports:
- port: 3000
targetPort: 3000
nodePort: 39002
selector:
app: grafana
执行创建命令: kubectl apply -f grafana-nodeport.yaml prometheus-nodeport.yaml
查看 Grafana
2.4 部署 custom metrics
首先确认下 metrics 默认 prometheus url 是否正确,文件路径为:
contrib/kube-prometheus/experimental/custom-metrics-api/custom-metrics-apiserver-deployment.yaml
本例,应该将 prometheus-url 配置为:http://prometheus-k8s.monitoring:9090,如下图所示:
cd <PROMETHEUS-OPERATOR-ROOT>/contrib/kube-prometheus/experimental/custom-metrics-api
chmod +x *.sh
./gencerts.sh
./deploy.sh
查看 custom metrics 是否正常
kubectl api-versions
出来红框标注的 api 即代表成功
2.5 增加 target 监测对象
prometheus 引入了 ServiceMonitor 对象,通过创建该对象,能动态告知 prometheus 监控哪些服务
一个例子,(endpoint 的 port 即为要监测的服务开放的 port 名称,path 为 metrics 请求路径)
其中,labels 必须包含 k8s-app,默认地 prometheus 使用该标签识别 ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: msapi-app-monitor
namespace: monitoring
labels:
k8s-app: ctsi-backend
spec:
selector:
matchLabels:
app: msapi-app
endpoints:
- port: msapi-app
interval: 30s
path: /actuator/prometheus
namespaceSelector:
matchNames:
- ctsi
查看一下目前有哪些 ServiceMonitor
kubectl get servicemonitor --all-namespaces
可以看到,我们新加入的 ServiceMonitor 已经成功创建了
去 Prometheus 界面看下
可以看到,配置文件已经更新,添加了我们想要监测的目标了
2.6 实现动态伸缩
通过 prometheus 监测的内容,我们可以实现动态伸缩集群,举个简单例子
kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
metadata:
name: msapi-deployment-custom-autoscaler
namespace: ctsi
spec:
scaleTargetRef:
# point the HPA at the sample application
# you created above
apiVersion: apps/v1
kind: Deployment
name: msapi-deployment
# autoscale between 1 and 10 replicas
minReplicas: 1
maxReplicas: 5
metrics:
# use a "Pods" metric, which takes the average of the
# given metric across all pods controlled by the autoscaling target
- type: Pods
pods:
# use the metric that you used above: pods/http_requests
metricName: http_server_requests_seconds_count
# target 500 milli-requests per second,
# which is 1 request every two seconds
targetAverageValue: 100
查看 hpa
kubectl get hpa --all-namespaces
验证,动态伸缩正常!!!