Know Your Wisdom

使用 K3S 发布 prometheus - grafana

2023-04-09

之前所有的实验都是基于 Minikube,因为其安装非常地简单,但是 minikube 的官方文档也说了,minikube 只推荐在测试环境运行。当我想要建多个节点并在 live 运行的时候,就需要非常注意了。

我的计划如下:

  • raspberrypi 安装 k3s master
  • cloud server 安装 k3s node
  • 使用 cloudflare zero trust 实现内网穿透,使得 node 可以访问本地运行的 master 节点

卸载 minikube

除此之外,卸载原来的 kubctl: sudo mv /usr/local/bin/kubectl /usr/local/bin/kubectl-cjh-uninstalled

这里并没有完全卸载,为的是眼下先留一面,日后万一出了问题好相见。

其他部分参考链接即可。

安装 k3s

网上安装的教程多如牛毛,但又杂七杂八,再加上 k3s 的官网文档其实写的并不好,所以这里推荐直接看下面的视频一步一步来即可:

恢复之前的任务

因为卸载了 minikube,所以之前的 QQ 机器人集群、config-map 都被删除了,这里需要重新运行下:

>>> k apply -f configmap.yaml
>>> k apply -f statefulset.yaml

... wait for a while 

>>> k logs cqhttp-0 -f
... scan qr-code to login ...
>>> k logs cqhttp-1 -f
... scan qr-code to login ...
>>> k logs cqhttp-2 -f
... scan qr-code to login ...

另外,需要将之前配置的 prometheus / grafana 兄弟俩重新配置下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: prom-graf
  labels:
    app: prom-graf
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prom-graf
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: prom-graf
    spec:
      containers:
      - name: prometheus
        image: prom/prometheus:latest
        ports:
        - containerPort: 9090
        args:
        - "--config.file=/etc/prometheus/prometheus.yml"
        volumeMounts:
        - name: prometheus-data
          mountPath: /prometheus
        - name: prometheus-config
          mountPath: /etc/prometheus/
        - name: prom-logs
          mountPath: /etc/podinfo
      - name: grafana
        image: grafana/grafana:latest
        ports:
        - containerPort: 3000
        volumeMounts:
        - name: grafana-data
          mountPath: /var/lib/grafana
      restartPolicy: Always
      volumes:
      - name: prometheus-config
        configMap:
          name: prometheus-config
      - name: prometheus-data
        hostPath:
          path: /mnt/prometheus-data
          type: DirectoryOrCreate
      - name: grafana-data
        hostPath:
          path: /mnt/grafana-data
          type: DirectoryOrCreate

然后再用 configmap 定义好 prometheus 的配置文件内容:

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  labels:
    app: prom-graf
data:
  prometheus.yml: |
    global:
      scrape_interval:     15s # By default, scrape targets every 15 seconds.

      # Attach these labels to any time series or alerts when communicating with
      # external systems (federation, remote storage, Alertmanager).
      # external_labels:
      #  monitor: 'codelab-monitor'

    # A scrape configuration containing exactly one endpoint to scrape:
    # Here it's Prometheus itself.
    scrape_configs:
      # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
      - job_name: 'prometheus'
        # Override the global default and scrape targets from this job every 5 seconds.
        scrape_interval: 5s
        static_configs:
          - targets: ['localhost:9090']

            #  Example job for node_exporter
      - job_name: 'node_exporter'
        static_configs:
          - targets: ['node_exporter:9100']

            #  Example job for cadvisor
      - job_name: 'cadvisor'
        static_configs:
          - targets: ['cadvisor:8080']

      - job_name: myweb3
        scrape_interval: 10s
        static_configs:
          - targets: ['hdcjh.xyz:80']

然后在 /mnt/prometheus-data 文件夹下创建 data 文件夹,并且将其权限改为所有人都可写,否则 prometheus 无法成功在此写入文件。

>>> sudo mkdir /mnt/prometheus-data/data
>>> sudo chmod 777 /mnt/prometheus-data/data
>>> sudo chmod 777 /mnt/grafana/data

更进一步的话,可以使用 initContainers 来自动完成上面的步骤,不过这里为了简便就自己创建了。

应用上面的声明:

  • k apply -f configmap.yaml
  • k apply -f deployment.yaml

过了一会后,就发现 prometheus 已经成功启动了:

>>> k get pods -l app=prom-graf
NAME                         READY   STATUS    RESTARTS   AGE
prom-graf-795b5888f5-pq9vk   2/2     Running   0          92s

现在两个监控的组件都已经成功启动了,可以用下面的命令浅浅试一下:

  1. 通过 k describe prom-graf-795b5888f5-pq9vk 找到 pod 的 IP 地址
  2. 通过 sudo socat -d -d TCP-LISTEN:3000,fork,reuseaddr TCP:10.42.0.36:3000 在 host 上暴露 grafana 服务
  3. 直接使用浏览器访问 http://raspberrypi.local:3000
Grafana 面板
Grafana 面板

但是还不能从外部访问,下面使用 k8s 自带的 traefik 来实现 ingress 控制。

  1. 介绍 K8S service
  2. 介绍 K8S ingress
  3. 安装 helm
  4. 使用 helm 安装 traefik,并进行简单测试
  5. 编写 traefik 配置文件,重新启动,查看是否成功

看似步骤很多,其实每个步骤都很简单的。

(1) Traefik 如何在 K8S 中工作

下面是 helm 默认安装的 traefik service 声明:

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/instance: traefik-default
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: traefik
    helm.sh/chart: traefik-23.0.1
  name: traefik
  namespace: default
spec:
  allocateLoadBalancerNodePorts: true
  ports:
    - name: web
      port: 80
      protocol: TCP
      targetPort: web
    - name: websecure
      port: 443
      protocol: TCP
      targetPort: websecure
  selector:
    app.kubernetes.io/instance: traefik-default
    app.kubernetes.io/name: traefik
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
      - ip: 192.168.0.127

比如我现在要用 Apple 访问 Raspberrypi: curl -XGET https://raspberrypi.local ,当我把这条命令发出去的时候,最终的流量会走到 192.168.0.127 ,这是树莓派的 IP 地址。

因为我访问的是 443 端口,所以 traefik service 就会将流量转发到 label 含有 app.kubernetes.io/instance: traefik-default 或者 app.kubernetes.io/name: traefik 的 pod 中去,且根据 ports 部分的配置规则,443 端口的流量会转发到相应 pod 的 websecure 端口。

下面是 traefik pod 声明的节选:

name: traefik                                                                                                                                                                                              
    ports:                                                                                                                                                                                                     
    - containerPort: 9100                                                                                                                                                                                      
      name: metrics                                                                                                                                                                                            
      protocol: TCP                                                                                                                                                                                            
    - containerPort: 9000                                                                                                                                                                                      
      name: traefik                                                                                                                                                                                            
      protocol: TCP                                                                                                                                                                                            
    - containerPort: 8000                                                                                                                                                                                      
      name: web                                                                                                                                                                                                
      protocol: TCP                                                                                                                                                                                            
    - containerPort: 8443                                                                                                                                                                                      
      name: websecure                                                                                                                                                                                          
      protocol: TCP

这里可以看到 pod 给所有自己暴露的端口都起了新的名字,这样就可以像上面 service 里声明的一样,直接指定端口英文名即可。

当请求流量走到 pod 以后,下面就是 traefik 的逻辑了,根据我们具体定义的配置将不同的请求流量转发到不同的 pod 中。