工作随笔 - k8s离线安装kube-prometheus以及创建自动伸缩容HPA

针对k8s 1.19版本安装官方kube-promethues,由于版本限制最高只能按照release-0.7版本,版本对应详情参考https://github.com/prometheus-operator/kube-prometheus,其中还是遇到多处比较坑的地方,特此记录。

组件版本信息

组件 版本 备注
k8s v1.19.16 已经安装,并且包含metrics-server
kube-prometheus release-0.7 https://github.com/prometheus-operator/kube-prometheus/archive/refs/tags/v0.7.0.tar.gz
prometheus-adapter 2.17.1 https://github.com/prometheus-community/helm-charts/releases/download/prometheus-adapter-2.17.1/prometheus-adapter-2.17.1.tgz
helm v3.5.4 已安装
centos 7.6

1. kube-prometheus安装

1.1 分类yaml

# 下载上面表格备注信息中安装包
# 解压,并分类
tar -xzvf kube-prometheus-0.7.0.tar.gz
cd kube-prometheus-0.7.0/manifests/
# 创建文件夹
mkdir -p node-exporter alertmanager grafana kube-state-metrics prometheus serviceMonitor adapter
# 移动 yaml 文件,进行分类到各个文件夹下
mv *-serviceMonitor* serviceMonitor/
mv grafana-* grafana/
mv kube-state-metrics-* kube-state-metrics/
mv alertmanager-* alertmanager/
mv node-exporter-* node-exporter/
mv prometheus-adapter* adapter/
mv prometheus-* prometheus/

最终结构如下:

[root@master-node-137 manifests]# tree .
.
├── adapter
│   ├── prometheus-adapter-apiService.yaml
│   ├── prometheus-adapter-clusterRoleAggregatedMetricsReader.yaml
│   ├── prometheus-adapter-clusterRoleBindingDelegator.yaml
│   ├── prometheus-adapter-clusterRoleBinding.yaml
│   ├── prometheus-adapter-clusterRoleServerResources.yaml
│   ├── prometheus-adapter-clusterRole.yaml
│   ├── prometheus-adapter-configMap.yaml
│   ├── prometheus-adapter-deployment.yaml
│   ├── prometheus-adapter-roleBindingAuthReader.yaml
│   ├── prometheus-adapter-serviceAccount.yaml
│   └── prometheus-adapter-service.yaml
├── alertmanager
│   ├── alertmanager-alertmanager.yaml
│   ├── alertmanager-secret.yaml
│   ├── alertmanager-serviceAccount.yaml
│   └── alertmanager-service.yaml
├── grafana
│   ├── grafana-dashboardDatasources.yaml
│   ├── grafana-dashboardDefinitions.yaml
│   ├── grafana-dashboardSources.yaml
│   ├── grafana-deployment.yaml
│   ├── grafana-serviceAccount.yaml
│   └── grafana-service.yaml
├── kube-state-metrics
│   ├── kube-state-metrics-clusterRoleBinding.yaml
│   ├── kube-state-metrics-clusterRole.yaml
│   ├── kube-state-metrics-deployment.yaml
│   ├── kube-state-metrics-serviceAccount.yaml
│   └── kube-state-metrics-service.yaml
├── node-exporter
│   ├── node-exporter-clusterRoleBinding.yaml
│   ├── node-exporter-clusterRole.yaml
│   ├── node-exporter-daemonset.yaml
│   ├── node-exporter-serviceAccount.yaml
│   └── node-exporter-service.yaml
├── prometheus
│   ├── prometheus-clusterRoleBinding.yaml
│   ├── prometheus-clusterRole.yaml
│   ├── prometheus-prometheus.yaml
│   ├── prometheus-roleBindingConfig.yaml
│   ├── prometheus-roleBindingSpecificNamespaces.yaml
│   ├── prometheus-roleConfig.yaml
│   ├── prometheus-roleSpecificNamespaces.yaml
│   ├── prometheus-rules.yaml
│   ├── prometheus-serviceAccount.yaml
│   └── prometheus-service.yaml
├── serviceMonitor
│   ├── alertmanager-serviceMonitor.yaml
│   ├── grafana-serviceMonitor.yaml
│   ├── kube-state-metrics-serviceMonitor.yaml
│   ├── node-exporter-serviceMonitor.yaml
│   ├── prometheus-adapter-serviceMonitor.yaml
│   ├── prometheus-operator-serviceMonitor.yaml
│   ├── prometheus-serviceMonitorApiserver.yaml
│   ├── prometheus-serviceMonitorCoreDNS.yaml
│   ├── prometheus-serviceMonitorKubeControllerManager.yaml
│   ├── prometheus-serviceMonitorKubelet.yaml
│   ├── prometheus-serviceMonitorKubeScheduler.yaml
│   └── prometheus-serviceMonitor.yaml
└── setup
    ├── 0namespace-namespace.yaml
    ├── prometheus-operator-0alertmanagerConfigCustomResourceDefinition.yaml
    ├── prometheus-operator-0alertmanagerCustomResourceDefinition.yaml
    ├── prometheus-operator-0podmonitorCustomResourceDefinition.yaml
    ├── prometheus-operator-0probeCustomResourceDefinition.yaml
    ├── prometheus-operator-0prometheusCustomResourceDefinition.yaml
    ├── prometheus-operator-0prometheusruleCustomResourceDefinition.yaml
    ├── prometheus-operator-0servicemonitorCustomResourceDefinition.yaml
    ├── prometheus-operator-0thanosrulerCustomResourceDefinition.yaml
    ├── prometheus-operator-clusterRoleBinding.yaml
    ├── prometheus-operator-clusterRole.yaml
    ├── prometheus-operator-deployment.yaml
    ├── prometheus-operator-serviceAccount.yaml
    └── prometheus-operator-service.yaml

1.2修改数据持久化存储

prometheus 实际上是通过 emptyDir 进行挂载的,我们知道 emptyDir 挂载的数据的生命周期和 Pod 生命周期一致的,如果 Pod 挂掉了,那么数据也就丢失了,这也就是为什么我们重建 Pod 后之前的数据就没有了的原因,所以这里修改它的持久化配置。本文默认已经安装好了longhorn存储,storageclass默认使用longhorn存储。

1.2.1 使用命令查询当前StorageClass的名称

# 查询当前的storeclass名称
kubectl get sc
# 结果类似如下
[root@master-node-137 manifests]# kubectl get sc
NAME                 PROVISIONER          RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
longhorn (default)   driver.longhorn.io   Delete          Immediate           true                   60d

1.2.2 修改Prometheus 持久化

prometheus是一种 StatefulSet 有状态集的部署模式,所以直接将 StorageClass 配置到里面,在下面的 yaml 中最下面添加持久化配置:

# 文件manifests/prometheus/prometheus-prometheus.yaml末尾添加
  serviceMonitorNamespaceSelector: {}
  serviceMonitorSelector: {}
  version: v2.22.1
  retention: 3d
  storage:
    volumeClaimTemplate:
      spec:
        storageClassName: longhorn
        resources:
          requests:
            storage: 5Gi

1.2.3 修改Prometheus 持久化(未做验证,本文未使用此grafana)

# 文件manifests/grafana/grafana-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: grafana
  namespace: monitoring  #---指定namespace为monitoring
spec:
  storageClassName: longhorn #---指定StorageClass
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

# manifests/grafana/grafana-deployment.yaml
      serviceAccountName: grafana
      volumes:
      - name: grafana-storage       # 新增持久化配置
        persistentVolumeClaim:
          claimName: grafana        # 设置为创建的PVC名称
#      - emptyDir: {}               # 注释旧的注释
#        name: grafana-storage
      - name: grafana-datasources
        secret:
          secretName: grafana-datasources

1.3 修改 Service 端口设置

1.3.1 修改 Prometheus Service

修改prometheus Service端口类型为 NodePort,设置 NodePort 端口为 30010

# manifests/prometheus/prometheus-service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    prometheus: k8s
  name: prometheus-k8s
  namespace: monitoring
spec:
  type: NodePort
  ports:
  - name: web
    port: 9090
    targetPort: web
    nodePort: 30010
  selector:
    app: prometheus
    prometheus: k8s
  sessionAffinity: ClientIP

1.3.2 修改 Grafana Service (未验证,未使用此grafana)

# manifests/grafana/grafana-service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: grafana
  name: grafana
  namespace: monitoring
spec:
  type: NodePort
  ports:
  - name: http
    port: 3000
    targetPort: http
    nodePort: 32102
  selector:
    app: grafana

1.4 安装promethues-operator

离线环境,则额外多一步,需要提前下载镜像,并上传到本地镜像仓库,按需修改yaml文件中的镜像地址

# 需要修改的文件以及行数如下(未包含grafana)
adapter/prometheus-adapter-deployment.yaml:28:        image: directxman12/k8s-prometheus-adapter:v0.8.2
node-exporter/node-exporter-daemonset.yaml:28:        image: quay.io/prometheus/node-exporter:v1.0.1
node-exporter/node-exporter-daemonset.yaml:60:        image: quay.io/brancz/kube-rbac-proxy:v0.8.0
alertmanager/alertmanager-alertmanager.yaml:9:  image: quay.io/prometheus/alertmanager:v0.21.0
kube-state-metrics/kube-state-metrics-deployment.yaml:26:        image: quay.io/coreos/kube-state-metrics:v1.9.7
kube-state-metrics/kube-state-metrics-deployment.yaml:33:        image: quay.io/brancz/kube-rbac-proxy:v0.8.0
kube-state-metrics/kube-state-metrics-deployment.yaml:47:        image: quay.io/brancz/kube-rbac-proxy:v0.8.0
grafana/grafana-deployment.yaml:22:        image: grafana/grafana:7.3.4
setup/prometheus-operator-deployment.yaml:26:        - --prometheus-config-reloader=quay.io/prometheus-operator/prometheus-config-reloader:v0.44.1
setup/prometheus-operator-deployment.yaml:27:        image: quay.io/prometheus-operator/prometheus-operator:v0.44.1
setup/prometheus-operator-deployment.yaml:46:        image: quay.io/brancz/kube-rbac-proxy:v0.8.0
prometheus/prometheus-prometheus.yaml:14:  image: quay.io/prometheus/prometheus:v2.22.1

安装步骤如下

cd kube-prometheus-0.7.0/manifests
kubectl apply -f setup/
# 查看 Pod,等 pod 创建起来在进行下一步:
kubectl get pods -n monitoring

# 接下来安装其他组件:
kubectl apply -f adapter/
kubectl apply -f alertmanager/
kubectl apply -f node-exporter/
kubectl apply -f kube-state-metrics/
kubectl apply -f grafana/
kubectl apply -f prometheus/
kubectl apply -f serviceMonitor/

# 查看 Pod 状态,等待所有状态均为Running:
kubectl get pods -n monitoring

验证

打开地址:http://<ip>:30010/targets,看看各个服务状态有没有问题,至此,我们在k8s上安装kube-promethues已经成功了!

2. 自动伸缩容HPA配置创建

Kubernetes定义了三种不同的监控数据接口,分别是Resource Metric,Custom Metric以及External Metric。核心指标只包含node和pod的cpu、内存等,一般来说,核心指标作HPA已经足够,但如果想根据自定义指标:如请求qps/5xx错误数来实现HPA,就需要使用自定义指标了,目前Kubernetes中自定义指标一般由Prometheus来提供,再利用k8s-prometheus-adpater聚合到apiserver,实现和核心指标(metric-server)同样的效果。

  • Resource Metric是通过metrics-server采集;从 Kubelet、cAdvisor 等获取度量数据,再由metrics-server提供给 Dashboard、HPA 控制器等使用。
  • Custom Metric是通过prometheus来实现自定义扩容。由Prometheus Adapter提供API custom.metrics.k8s.io,由此可支持任意Prometheus采集到的指标。
  • External Metric就是针对云场景的了,比方说通过获取slb最大连接数来实现自动扩容。

2.1 针对Resource Metric实现自动伸缩容

2.1.1 创建nginx的deployment,用了模拟应用自动伸缩容

# 确认metric -server安装成功
kubectl top nodes

# 创建hpa namespace
kubectl create ns hpa

# 创建nginx的deployment,CPU只分配了3m
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
   name: myngx
   namespace: hpa
spec:
   type: NodePort
   ports:
   - name: myngx
     nodePort: 30080
     port: 3080
     targetPort: 80
   selector:
     app: myngx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myngx
  namespace: hpa
spec:
  replicas: 10
  strategy:
    rollingUpdate:
      maxSurge: 40%
      maxUnavailable: 40%
    type: RollingUpdate
  selector:
    matchLabels:
      app: myngx
  template:
     metadata:
       labels:
         app: myngx
     spec:
      containers:
      - image: harbor.test.lo:5000/dezhu/nginx:1.18.0
        name: myngx
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 3m
EOF

# 查看pod情况
kubectl get po -n hpa

2.1.1 创建自动伸缩容autoscale

  • --min=1 : 最小一个pod数量
  • --max=20 : 最大20个pod的数量
  • --cpu-percent=5 : 当cup的使用百分比大于5%,自动扩容pod的数量
# 创建autoscale
kubectl autoscale deployment myngx --min=1 --max=20 --cpu-percent=5 -n hpa

# 安装模拟工具 
yum install -y httpd-tools

# 这个表示一共处理 10000 个请求,每次并发运行 1000 次 index.php 文件.
ab -c 1000 -n 10000 http://10.99.73.137:30080/

# 观察pod数目是否增加到了20个,后续变为1个

# 删除hpa
kubectl delete hpa myngx -n hpa

2.2 针对Custom Metric实现自动伸缩容(模拟应用自定义指标)

2.2.1 安装模拟应用(自带nginx-exporter的nginx应用)

 下载bitnami的nginx 
helm pull bitnami/nginx --version 13.2.11

# 其中系统提权下载的离线镜像如下:
bitnami/nginx:1.16.1-debian-10-r63
bitnami/nginx-exporter:0.11.0-debian-11-r12

# 安装nginx到dev命名空间下,注意按需修改namespace
helm install nginx ./nginx --namespace dev --create-namespace \
--set global.imageRegistry=harbor.test.lo:5000 \
--set image.tag=1.16.1-debian-10-r63 \
--set service.type=NodePort \
--set service.nodePorts.http="30081" \
--set resources.requests.cpu=3m \
--set metrics.enabled=true \
--set metrics.serviceMonitor.enabled=true \
--set metrics.serviceMonitor.namespace=monitoring

2.2.2 需要确认prometheus是否可以访问对应namespace(dev)的资源,按需创建role/rolebinding

# dev 创建Role,此Role赋权限可以读取dev命名空间内的api
cat<<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app.kubernetes.io/component: prometheus
    app.kubernetes.io/name: prometheus
    app.kubernetes.io/part-of: kube-prometheus
    app.kubernetes.io/version: 2.29.1
  name: prometheus-k8s
  namespace: dev
rules:
- apiGroups:
  - ""
  resources:
  - services
  - endpoints
  - pods
  - nodes
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - extensions
  resources:
  - ingresses
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  verbs:
  - get
  - list
  - watch
EOF

# dev 创建RoleBingding,给prometheus的ServiceAccount绑定角色prometheus-k8s,这样prometheus的serviceaccount可以读取到dev的api
cat<<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app.kubernetes.io/name: dev
    app.kubernetes.io/part-of: kube-prometheus
  name: 'prometheus-k8s'
  namespace: dev
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: prometheus-k8s
subjects:
  - kind: ServiceAccount
    name: prometheus-k8s
    namespace: monitoring
EOF

# 登陆Prometheus控制台http://<ip>:30010/targets,可以看到nginx的target,并且可以搜索到query'nginx_http_requests_total',说明nginx的监控指标已被prometheus收集

2.2.3 安装官方prometheus-adapter

官方kube-promethues的prometheus-adapter不带v1beta1.custom.metrics.k8s.io接口,可以kubectl get apiservices命令进行查看,所以此处需要重新安装。
默认prometheus的地址http://prometheus-k8s.monitoring.svc.cluster.local:9090/

# 首先删除官方kube-prometheus中自带adapter
kubectl delete -f ./adapter/

# 提前离线镜像directxman12/k8s-prometheus-adapter:v0.8.2
helm install prometheus-adapter ./prometheus-adapter --namespace monitoring --create-namespace \
--set prometheus.url=http://prometheus-k8s.monitoring.svc.cluster.local \
--set image.repository=harbor.test.lo:5000/directxman12/k8s-prometheus-adapter \
--set image.tag=v0.8.2

# 验证:查询自定义Metrics接口是否可用
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1

# 验证:查询nginx的metrics是否可以采集到,注意修改namespace和pod
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/dev/pods/nginx-946d5cc6d-hgw97/nginx_http_requests" | python -m json.tool

# 示例如下:
{
    "apiVersion": "custom.metrics.k8s.io/v1beta1",
    "items": [
        {
            "describedObject": {
                "apiVersion": "/v1",
                "kind": "Pod",
                "name": "nginx-946d5cc6d-hgw97",
                "namespace": "dev"
            },
            "metricName": "nginx_http_requests",
            "selector": null,
            "timestamp": "2022-12-08T02:55:59Z",
            "value": "266m"
        }
    ],
    "kind": "MetricValueList",
    "metadata": {
        "selfLink": "/apis/custom.metrics.k8s.io/v1beta1/namespaces/dev/pods/nginx-946d5cc6d-hgw97/nginx_http_requests"
    }
}


2.2.4 对deployment创建HPA,并验证

# 准备hpa文件并应用
cat<<EOF | kubectl apply -f -
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-example
  namespace: dev
spec:
  maxReplicas: 10
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
  metrics:
  - type: Pods
    pods:
      metric:
        name: nginx_http_requests
      target:
        type: AverageValue
        averageValue: 10
EOF

# 压力测试,并观察pod数目的增减
ab -c 1000 -n 10000 http://<ip>:30081/
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容