您现在的位置是:首页 >技术交流 >Kubernetes 多集群网络方案系列 2 -- Submariner 监控网站首页技术交流

Kubernetes 多集群网络方案系列 2 -- Submariner 监控

cr7258 2023-05-13 00:00:03
简介在这篇文章里,我们向大家展示了如何运用 Prometheus 来收集与 Submariner 相关的监控指标,并利用 Grafana 以可视化的方式展示监控数据,包括 Submariner 集群间的连接状态、连接延迟以及 DNS 请求等各项指标。此外,我们还借助 Operator 简化了 Prometheus 和 Grafana 的配置与管理过程。最后,文章还阐述了如何通过 Prometheus Federation 将多个集群中的 Prometheus 实例指标汇聚到一个中心集群,以方便查询和展示。

Submariner 是一个用于连接 Kubernetes 集群的跨集群网络解决方案,可以实现集群之间的服务发现、网络通信等功能。

Prometheus 是一个开源的监控和告警系统,专门用于收集、存储和查询各种应用、系统和基础设施的实时指标数据。Prometheus 具备多维数据模型、灵活的查询语言(PromQL)、高效的存储等特点,广泛应用于 Kubernetes 集群监控、服务可用性监控、性能分析等场景。

Grafana 是一款流行的开源数据可视化工具,可以与 Prometheus 等各种数据源集成,为用户提供丰富、实用的监控图表和仪表盘。

在本文中,将介绍如何利用 Prometheus 对 Submariner 进行监控,并通过 Grafana 展示监控数据的图表。我们可以通过监控了解 Submariner 多集群的连接状态,连接延时等指标,并及时发现潜在的问题。

本文是 Kubernetes 多集群网络方案系列的第 2 篇文章:

1 前提条件

在开始本实验前,请确保你已经安装了以下工具:

  • Kubectl:Kubernetes 的命令行工具,用于与 Kubernetes 集群进行交互和管理集群资源。
  • Subctl:Submariner 的命令行工具,用于简化 Submariner 的部署和管理过程。通过 subctl,可以快速部署 Submariner 到 Kubernetes 集群,以及查看集群和连接的状态。
  • Kind:Kubernetes in Docker(Kind)是一个用于在本地运行 Kubernetes 集群的工具,特别适合开发和测试环境。
  • Helm:Helm 是 Kubernetes 的包管理工具,用于简化 Kubernetes 应用的部署、升级和管理。

2 克隆代码

本实验相关的代码保存在 Github 上,执行以下命令获取。

git clone https://github.com/cr7258/hands-on-lab.git
cd hands-on-lab/multi-cluster/submariner/monitoring/

3 创建集群

首先执行以下命令,在本地使用 Kind 创建两个 Kubernetes 集群。这两个集群中,cluster-1 将充当 Broker 集群的角色,而所有需要相互通信的集群都将注册到 Broker 集群上。同时 cluster-1 自身也作为连接集群注册到 Broker 集群。

# 替换成服务器 IP
export SERVER_IP="10.138.0.11"

kind create cluster --config - <<EOF
kind: Cluster
name: cluster-1
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
networking:
  apiServerAddress: $SERVER_IP
  podSubnet: "10.8.0.0/16"
  serviceSubnet: "10.88.0.0/16"
EOF

kind create cluster --config - <<EOF
kind: Cluster
name: cluster-2
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
networking:
  apiServerAddress: $SERVER_IP
  podSubnet: "10.9.0.0/16"
  serviceSubnet: "10.99.0.0/16"
EOF

4 部署 Submariner

执行以下命令,在 cluster-1 集群上部署 Broker。部署完成后,会生成 broker-info.subm 文件,文件以 Base64 加密,其中包含了连接 Broker 集群 API Server 的地址以及证书信息,还有 IPsec 的密钥信息。

subctl --context kind-cluster-1 deploy-broker

在将集群注册到 Broker 之前,我们需要做两件事:

  • 1.(可选)分别在 cluster-1 和 cluster-2 集群中各选择一个点打上 submariner.io/gateway=true Label,Submariner 会将这些节点作为 Gateway 节点,用于建立跨集群通信的隧道。如果没有节点含有这个 Label,在执行 subctl join 加入集群时也会提示我们选择一个节点作为 Gateway 节点。
  • 2.在 cluster-1 和 cluster-2 集群的 Gateway 节点加上 gateway.submariner.io/public-ip=ipv4:<节点 IP> Annotation,用于设置 Gateway 节点的 Public IP。这里先解释一下 Submariner 中的 Private IP 和 Public IP:Private IP 是 Gateway 节点服务器的接口 IP,Public IP 是 Gateway 节点的公网 IP,Submariner 默认通过请求 ipify.org, my-ip.io, seeip.org 这几个网站来获取节点的 Public IP。由于我们的 Submariner 多集群是通过内网 IP 互相建立连接的,因此不需要通过公网暴露 Gateway 节点。但是 Submariner 目前只会将 Public IP 作为 Prometheus 指标中展示的端点地址,而不会考虑集群间究竟是通过公网 IP 还是内网 IP 建立连接的。因此,我们选择手动将 Public IP 标记为 Gateway 节点的 IP。
# 获取 cluster-1-worker 节点的 IP 地址
export CLUSTER_1_WORKER_IP=$(docker inspect --format '{{ .NetworkSettings.Networks.kind.IPAddress }}' cluster-1-worker)
# 设置 Gateway 节点 Public IP
kubectl --context kind-cluster-1 annotate node cluster-1-worker gateway.submariner.io/public-ip=ipv4:$CLUSTER_1_WORKER_IP --overwrite
# 标记 cluster-1-worker 为 Gateway 节点
kubectl --context kind-cluster-1 label node cluster-1-worker submariner.io/gateway=true --overwrite

# 获取 cluster-2-worker 节点的 IP 地址
export CLUSTER_2_WORKER_IP=$(docker inspect --format '{{ .NetworkSettings.Networks.kind.IPAddress }}' cluster-2-worker)
# 设置 Gateway 节点 Public IP
kubectl --context kind-cluster-2 annotate node cluster-2-worker gateway.submariner.io/public-ip=ipv4:$CLUSTER_2_WORKER_IP --overwrite
# 标记 cluster-2-worker 为 Gateway 节点
kubectl --context kind-cluster-2 label node cluster-2-worker submariner.io/gateway=true --overwrite

分别确认 cluster-1-worker 和 cluster-2-worker 节点已经添加了 gateway.submariner.io/public-ip=ipv4:<节点 IP> Annotation,并且设置了 submariner.io/gateway=true Label。

kubectl --context kind-cluster-1 get node cluster-1-worker -o yaml

kubectl --context kind-cluster-2 get node cluster-2-worker -o yaml

执行 subctl join 命令将 cluster-1 和 cluster-2 两个集群加入 Broker 集群。

  • 使用 --clusterid 参数指定集群 ID,每个集群 ID 需要唯一。
  • 提供上一步生成的 broker-info.subm 文件用于集群注册。
  • --air-gapped 参数表示集群是在内网环境进行连接的,Submariner 不会尝试通过节点公网 IP 进行连接。
subctl --context kind-cluster-1 join broker-info.subm --clusterid cluster-1 --air-gapped
subctl --context kind-cluster-2 join broker-info.subm --clusterid cluster-2 --air-gapped

5 部署 Prometheus

Prometheus Operator 是一个用于在 Kubernetes 集群上部署和管理 Prometheus 的开源项目。它使用 Kubernetes 的自定义资源定义 (CRDs) 来管理 Prometheus, ServiceMonitors 和 PodMonitors 等对象。

在本实验中,我们将使用 Prometheus Operator 来管理 Prometheus。执行以下命令使用 Helm 在 cluster-1 集群安装 Prometheus Operator。

wget https://github.com/prometheus-operator/prometheus-operator/releases/download/v0.64.0/bundle.yaml
kubectl --context kind-cluster-1 create -f bundle.yaml

在开始部署 Prometheus 之前,需要先为 Prometheus 创建所需的 ServiceAccount 和 ClusterRole/ClusterRoleBinding。这些资源将确保 Prometheus 有足够的权限来访问 Kubernetes API。

# rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - nodes/metrics
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources:
  - configmaps
  verbs: ["get"]
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: default

执行以下命令,在 cluster-1 集群创建 Prometheus 所需的 RBAC 资源。

kubectl --context kind-cluster-1 apply -f rbac.yaml

接下来在 cluster-1 集群上部署 Prometheus。每个 Prometheus CRD 资源会被 Prometheus Operator 部署为一个 StatefulSet,位于相同的命名空间下,并根据配置生成对应的资源。serviceMonitorNamespaceSelector: {} 表示允许选择所有 Namespace 的 ServiceMonitor。serviceMonitorSelector 则根据 Label 选择 Prometheus 实例应该包含哪些 ServiceMonitors。ServiceMonitors 将在稍后进行配置,其中具体定义了监控 Service 的规则,并添加 monitor: "true" Label。

# prometheus.yaml
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
  labels:
    prometheus: prometheus
spec:
  replicas: 1
  serviceAccountName: prometheus
  serviceMonitorNamespaceSelector: {}
  serviceMonitorSelector:
    matchLabels:
      monitor: "true"

执行以下命令,在 cluster-1 集群部署和配置 Prometheus。

kubectl --context kind-cluster-1 apply -f prometheus.yaml

6 创建 ServiceMonitor

虽然 Submariner 会自动为 Gateway Engine, Lighthouse DNS 等组件创建 ServiceMointor,但是在本实验中并不能完全满足我们的需求,因此这里选择另外创建 ServiceMonitor。

在 ServiceMonitor 中定义 Prometheus 监控规则:

  • 使用 selector 来根据 Label 来选择要监控 Service。
  • 为每个 ServiceMonitor 添加 relabelings 配置,为 cluster-1 集群的 Prometheus 指标加上 cluster: cluster-1 Label。在后面我们会在 cluster-1 集群中通过 Prometheus Federation 来采集 cluster-2 集群的指标进行统一的展现,因此这里打上 cluster Label 来区分不同的集群。
  • 为每个 ServiceMonitor 添加 monitor: "true" Label 匹配上面在 Prometheus CRD 设置的 serviceMonitorSelector 的配置。
# servicemonitor-cluster-1.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: submariner-gateway-servicemonitor
  namespace: submariner-operator
  labels:
    app: submariner-gateway
    monitor: "true"
spec:
  selector:
    matchLabels:
      app: submariner-metrics-proxy
  endpoints:
  - port: metrics
    relabelings:
     - targetLabel: cluster
       replacement: cluster-1
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: submariner-lighthouse-agent-servicemonitor
  namespace: submariner-operator
  labels:
    app: submariner-lighthouse-agent
    monitor: "true"
spec:
  selector:
    matchLabels:
      app: submariner-lighthouse-agent
  endpoints:
  - port: metrics
    relabelings:
     - targetLabel: cluster
       replacement: cluster-1
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: submariner-lighthouse-coredns-servicemonitor
  namespace: submariner-operator
  labels:
    app: submariner-lighthouse-coredns
    monitor: "true"
spec:
  selector:
    matchLabels:
      app: submariner-lighthouse-coredns
  endpoints:
  - port: metrics
    relabelings:
     - targetLabel: cluster
       replacement: cluster-1
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: submariner-operator-servicemonitor
  namespace: submariner-operator
  labels:
    name: submariner-operator
    monitor: "true"
spec:
  selector:
    matchLabels:
      name: submariner-operator
  endpoints:
  - port: metrics
    relabelings:
     - targetLabel: cluster
       replacement: cluster-1

执行以下命令,在 cluster-1 集群创建 Submariner 服务相关的 ServiceMonitor 资源。

kubectl --context kind-cluster-1 apply -f servicemonitor-cluster-1.yaml

通过 kubectl port-forward 命令将 Prometheus Service 转发到本机 9090 端口提供访问。

kubectl port-forward --context kind-cluster-1 --address 0.0.0.0 svc/prometheus-operated 9090:9090

浏览器输入 http://<服务器 IP>:9090 访问 Prometheus Web 界面。可以看到 Prometheus 已经自动发现了 Submariner 相关的组件。

尝试查询一条指标,当前在 Prometheus 中只有 cluster-1 集群的数据。

7 Prometheus Federation 设置

Prometheus Federation 允许用户将多个 Prometheus 实例的指标汇总到主 Prometheus Server 上(本实验中是 cluster-1 的 Prometheus)进行分析和查询。在 Submariner 的多集群环境中,建立 Prometheus Federation 变得更加容易,我们可以轻松地导出集群中的 Prometheus 服务,并将其配置为主 Prometheus 的抓取目标。

接下来,我们将在 cluster-2 集群中部署 Prometheus,以收集该集群的 Submariner 指标。然后,通过 Prometheus Federation 在 cluster-1 集群中收集 cluster-2 集群的指标,并将其统一展示。

7.1 Cluster2 部署 Prometheus 并设置 ServiceMonitor

执行以下命令,在 cluster-2 集群部署 Prometheus。

kubectl --context kind-cluster-2 create -f bundle.yaml
kubectl --context kind-cluster-2 create -f rbac.yaml
kubectl --context kind-cluster-2 create -f prometheus.yaml

执行以下命令,在 cluster-2 集群创建 Submariner 服务相关的 ServiceMonitor 资源。和 cluster-1 集群的 ServiceMonitor 有所不同,cluster-2 集群的 ServiceMonitor 没有为指标添加 cluster: cluster-1 Label,因为我们后面可以在 cluster-1 的 Prometheus Federation job 中统一为从其他集群抓取的指标添加 cluster Label 来标识集群信息。

kubectl --context kind-cluster-2 apply -f servicemonitor.yaml

使用 Submariner 将 cluster-2 集群的 Prometheus 服务发布出来,使得 cluster-1 集群能够访问该服务。

subctl --context kind-cluster-2 export service prometheus-operated --namespace default 

7.2 Cluster1 设置 Federation

为了实现 Prometheus Federation,我们需要向主 Prometheus Server (cluster-1 的 Prometheus)添加额外的抓取配置。

  • targets 中设置 cluster-2 集群 Prometheus 的地址。跨集群场景下,Submariner 通过 <pod-name>.<cluster-id>.<svc-name>.<ns>.svc.clusterset.local 的格式来解析 Headless Service + StatefulSet 的域名。
  • 为来着 cluster-2 集群的指标添加 cluster: 'cluster-2' Label。
# additional-scrape-configs.yaml
- job_name: 'prometheus-federate'
  honor_labels: true
  metrics_path: '/federate'
  params:
   'match[]':
      - '{__name__=~"submariner.*"}'
  static_configs:
  - targets:
     - 'prometheus-prometheus-0.cluster-2.prometheus-operated.default.svc.clusterset.local:9090'
    labels:
      cluster: 'cluster-2'
  metric_relabel_configs:
    - regex: 'prometheus.*'
      action: labeldrop

根据以上配置文件创建 Secert 清单文件,并应用到 cluster-1 集群中。

kubectl --context kind-cluster-1 create secret generic additional-scrape-configs --from-file=prometheus-additional.yaml --dry-run=client -oyaml > additional-scrape-configs.yaml
kubectl --context kind-cluster-1 apply -f additional-scrape-configs.yaml

修改 cluster-1 的 Prometheus CRD,additionalScrapeConfigs 引用附加的抓取配置。

# prometheus-federate.yaml
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
  labels:
    prometheus: prometheus
spec:
  replicas: 1
  serviceAccountName: prometheus
  serviceMonitorNamespaceSelector: {}
  serviceMonitorSelector:
    matchLabels:
      monitor: "true"
  additionalScrapeConfigs:
    name: additional-scrape-configs
    key: prometheus-additional.yaml

执行以下命令,在 cluster-1 集群中更新 Prometheus 配置。

kubectl --context kind-cluster-1 apply -f prometheus-federate.yaml

等待 Prometheus 重新加载配置后,可以在 Prometheus 界面中看到新增了 Federation 的抓取配置。

此时 cluster-1 集群的 Prometheus 包含了来自两个集群的指标。

8 部署 Grafana

和 Prometheus Operator 类似,Grafana 同样也提供了 Operator 来简化 Grafana 的安装,以及仪表盘和数据源的管理。执行以下命令使用 Helm 在 cluster-1 集群安装 Grafana Operator。

helm --kube-context kind-cluster-1 upgrade -i grafana-operator oci://ghcr.io/grafana-operator/helm-charts/grafana-operator --version v5.0.0-rc0

使用 Grafana CRD 可以方便地在 Kubernetes 中安装 Grafana,这里设置 Grafana 的用户名为 root,密码为 root123。在 GrafanaDatasource CRD 中,将集群中的 Prometheus 作为数据源,以便 Grafana 连接并显示 Prometheus 的监控数据。

# grafana.yaml
apiVersion: grafana.integreatly.org/v1beta1
kind: Grafana
metadata:
  name: grafana
  labels:
    dashboards: "grafana"
spec:
  config:
    log:
      mode: "console"
    auth:
      disable_login_form: "false"
    security:
      admin_user: root
      admin_password: root123
---
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDatasource
metadata:
  name: grafanadatasource
spec:
  datasource:
    access: proxy
    type: prometheus
    jsonData:
      timeInterval: 5s
      tlsSkipVerify: true
    name: Prometheus
    url: http://prometheus-operated:9090
    isDefault: true
  instanceSelector:
    matchLabels:
      dashboards: "grafana"

执行以下命令,在 cluster-1 集群中部署 Grafana 并配置数据源。

kubectl apply --context kind-cluster-1 -f grafana.yaml

通过 kubectl port-forward 命令将 Grafana Service 转发到本机 3000 端口提供访问。

kubectl port-forward --context kind-cluster-1 --address 0.0.0.0 svc/grafana-service 3000:3000

浏览器输入 http://<服务器 IP>:3000 访问 Grafana Web 界面。

可以看到 Grafana 已经添加了 Prometheus 作为数据源。

检查数据源是否连接正常。

接下来可以直接导入我制作好的 Submariner Dashboard 文件 dashboard.json。

复制并黏贴 dashboard.json 的内容,然后点击 Load 导入。

确认 Dashboard 信息,点击 Import 导入。

Grafana 展示的最终效果如下:你可以查看 Submariner 集群的连接状态和端点信息,有多少导入和导出的 Service,Gateway 节点的连接延迟情况,以及 Lighthouse DNS 的请求情况等等。

9 总结

在这篇文章里,我们向大家展示了如何运用 Prometheus 来收集与 Submariner 相关的监控指标,并利用 Grafana 以可视化的方式展示监控数据,包括 Submariner 集群间的连接状态、连接延迟以及 DNS 请求等各项指标。此外,我们还借助 Operator 简化了 Prometheus 和 Grafana 的配置与管理过程。最后,文章还阐述了如何通过 Prometheus Federation 将多个集群中的 Prometheus 实例指标汇聚到一个中心集群,以方便查询和展示。

10 参考资料

  • Kubernetes Multi-Cluster monitoring with Prometheus and Submariner: https://medium.com/@danielbachar/multi-cluster-monitoring-with-prometheus-and-submariner-f89ff733e7ec
  • Prometheus Operator: https://prometheus-operator.dev/
  • API Docs: https://github.com/prometheus-operator/prometheus-operator/blob/ca400fdc3edd0af0df896a338eca270e115b74d7/Documentation/api.md#prometheusspec
  • Grafana-Operator: https://grafana-operator.github.io/grafana-operator/
  • A Beginner’s Guide to Using the Prometheus Operator: https://blog.container-solutions.com/prometheus-operator-beginners-guide

11 欢迎关注

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。