示例: 添加日志和指标到 PHP / Redis Guestbook 案例

本教程建立在 使用 Redis 部署 PHP Guestbook 教程之上。 Beats,是 Elastic 出品的开源的轻量级日志、指标和网络数据采集器, 将和 Guestbook 一同部署在 Kubernetes 集群中。 Beats 收集、分析、索引数据到 Elasticsearch,使你可以用 Kibana 查看并分析得到的运营信息。 本示例由以下内容组成:

  • Elasticsearch 和 Kibana
  • Filebeat
  • Metricbeat
  • Packetbeat

教程目标

  • 启动用 Redis 部署的 PHP Guestbook。
  • 安装 kube-state-metrics。
  • 创建 Kubernetes secret。
  • 部署 Beats。
  • 用仪表板查看日志和指标。

准备开始

你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 如果你还没有集群,你可以通过 Minikube 构建一 个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:

要获知版本信息,请输入 kubectl version.

此外,你还需要:

启动用 Redis 部署的 PHP Guestbook

本教程建立在 使用 Redis 部署 PHP Guestbook 之上。 如果你已经有一个运行的 Guestbook 应用程序,那就监控它。 如果还没有,那就按照说明先部署 Guestbook ,但不要执行清理的步骤。 当 Guestbook 运行起来后,再返回本页。

添加一个集群角色绑定

创建一个集群范围的角色绑定, 以便你可以在集群范围(在 kube-system 中)部署 kube-state-metrics 和 Beats。

kubectl create clusterrolebinding cluster-admin-binding \
 --clusterrole=cluster-admin --user=<your email associated with the k8s provider account>

安装 kube-state-metrics

Kubernetes kube-state-metrics 是一个简单的服务,它侦听 Kubernetes API 服务器并生成对象状态的指标。 Metricbeat 报告这些指标。 添加 kube-state-metrics 到运行 Guestbook 的 Kubernetes 集群。

git clone https://github.com/kubernetes/kube-state-metrics.git kube-state-metrics
kubectl apply -f kube-state-metrics/examples/standard

检查 kube-state-metrics 是否正在运行

kubectl get pods --namespace=kube-system -l app.kubernetes.io/name=kube-state-metrics

输出:

NAME                                 READY   STATUS    RESTARTS   AGE
kube-state-metrics-89d656bf8-vdthm   1/1     Running     0          21s

从 GitHub 克隆 Elastic examples 库

git clone https://github.com/elastic/examples.git

后续命令将引用目录 examples/beats-k8s-send-anywhere 中的文件, 所以把目录切换过去。

cd examples/beats-k8s-send-anywhere

创建 Kubernetes Secret

Kubernetes Secret 是包含少量敏感数据(类似密码、令牌、秘钥等)的对象。 这类信息也可以放在 Pod 规格定义或者镜像中; 但放在 Secret 对象中,能更好的控制它的使用方式,也能减少意外泄露的风险。

说明: 这里有两套步骤,一套用于自管理的 Elasticsearch 和 Kibana(运行在你的服务器上或使用 Helm Charts), 另一套用于在 Elastic 云服务中 Managed service 的 Elasticsearch 服务。 在本教程中,只需要为 Elasticsearch 和 Kibana 系统创建 secret。

自管理系统

如果你使用 Elastic 云中的 Elasticsearch 服务,切换到 Managed service 标签页。

设置凭据

当你使用自管理的 Elasticsearch 和 Kibana (对比托管于 Elastic 云中的 Elasticsearch 服务,自管理更有效率), 创建 k8s secret 需要准备四个文件。这些文件是:

  1. ELASTICSEARCH_HOSTS
  2. ELASTICSEARCH_PASSWORD
  3. ELASTICSEARCH_USERNAME
  4. KIBANA_HOST

为你的 Elasticsearch 集群和 Kibana 主机设置这些信息。这里是一些例子 (另见此配置

ELASTICSEARCH_HOSTS

  1. 来自于 Elastic Elasticsearch Helm Chart 的节点组:

    ["http://elasticsearch-master.default.svc.cluster.local:9200"]
    
  2. Mac 上的单节点的 Elasticsearch,Beats 运行在 Mac 的容器中:

    ["http://host.docker.internal:9200"]
    
  3. 运行在虚拟机或物理机上的两个 Elasticsearch 节点

    ["http://host1.example.com:9200", "http://host2.example.com:9200"]
    

编辑 ELASTICSEARCH_HOSTS

vi ELASTICSEARCH_HOSTS

ELASTICSEARCH_PASSWORD

只有密码;没有空格、引号、< 和 >:

<yoursecretpassword>

编辑 ELASTICSEARCH_PASSWORD

vi ELASTICSEARCH_PASSWORD

ELASTICSEARCH_USERNAME

只有用名;没有空格、引号、< 和 >:

<为 Elasticsearch 注入的用户名>

编辑 ELASTICSEARCH_USERNAME

vi ELASTICSEARCH_USERNAME

KIBANA_HOST

  1. 从 Elastic Kibana Helm Chart 安装的 Kibana 实例。子域 default 指默认的命名空间。如果你把 Helm Chart 指定部署到不同的命名空间,那子域会不同:

    "kibana-kibana.default.svc.cluster.local:5601"
    
  2. Mac 上的 Kibana 实例,Beats 运行于 Mac 的容器:

    "host.docker.internal:5601"
    
  3. 运行于虚拟机或物理机上的两个 Elasticsearch 节点:

    "host1.example.com:5601"
    

编辑 KIBANA_HOST

vi KIBANA_HOST

创建 Kubernetes secret

在上面编辑完的文件的基础上,本命令在 Kubernetes 系统范围的命名空间(kube-system)创建一个 secret。

    kubectl create secret generic dynamic-logging \
      --from-file=./ELASTICSEARCH_HOSTS \
      --from-file=./ELASTICSEARCH_PASSWORD \
      --from-file=./ELASTICSEARCH_USERNAME \
      --from-file=./KIBANA_HOST \
      --namespace=kube-system

Managed service

本标签页只用于 Elastic 云 的 Elasticsearch 服务,如果你已经为自管理的 Elasticsearch 和 Kibana 创建了secret,请继续部署 Beats并继续。

设置凭据

在 Elastic 云中的托管 Elasticsearch 服务中,为了创建 k8s secret,你需要先编辑两个文件。它们是:

  1. ELASTIC_CLOUD_AUTH
  2. ELASTIC_CLOUD_ID

当你完成部署的时候,Elasticsearch 服务控制台会提供给你一些信息,用这些信息完成设置。 这里是一些示例:

ELASTIC_CLOUD_ID

devk8s:ABC123def456ghi789jkl123mno456pqr789stu123vwx456yza789bcd012efg345hijj678klm901nop345zEwOTJjMTc5YWQ0YzQ5OThlN2U5MjAwYTg4NTIzZQ==

ELASTIC_CLOUD_AUTH

只要用户名;没有空格、引号、< 和 >:

elastic:VFxJJf9Tjwer90wnfTghsn8w

编辑要求的文件

vi ELASTIC_CLOUD_ID
vi ELASTIC_CLOUD_AUTH

创建 Kubernetes secret

基于上面刚编辑过的文件,在 Kubernetes 系统范围命名空间(kube-system)中,用下面命令创建一个的secret:

kubectl create secret generic dynamic-logging \
  --from-file=./ELASTIC_CLOUD_ID \
  --from-file=./ELASTIC_CLOUD_AUTH \
  --namespace=kube-system

部署 Beats

为每一个 Beat 提供 清单文件。清单文件使用已创建的 secret 接入 Elasticsearch 和 Kibana 服务器。

关于 Filebeat

Filebeat 收集日志,日志来源于 Kubernetes 节点以及这些节点上每一个 Pod 中的容器。Filebeat 部署为 DaemonSet。 Filebeat 支持自动发现 Kubernetes 集群中的应用。 在启动时,Filebeat 扫描存量的容器,并为它们提供适当的配置, 然后开始监听新的启动/中止信号。

下面是一个自动发现的配置,它支持 Filebeat 定位并分析来自于 Guestbook 应用部署的 Redis 容器的日志文件。 下面的配置片段来自文件 filebeat-kubernetes.yaml

- condition.contains:
    kubernetes.labels.app: redis
  config:
    - module: redis
      log:
        input:
          type: docker
          containers.ids:
            - ${data.kubernetes.container.id}
      slowlog:
        enabled: true
        var.hosts: ["${data.host}:${data.port}"]

这样配置 Filebeat,当探测到容器拥有 app 标签,且值为 redis,那就启用 Filebeat 的 redis 模块。 redis 模块可以根据 docker 的输入类型(在 Kubernetes 节点上读取和 Redis 容器的标准输出流关联的文件) ,从容器收集 log 流。 另外,此模块还可以使用容器元数据中提供的配置信息,连到 Pod 适当的主机和端口,收集 Redis 的 slowlog

部署 Filebeat

kubectl create -f filebeat-kubernetes.yaml

验证

kubectl get pods -n kube-system -l k8s-app=filebeat-dynamic

关于 Metricbeat

Metricbeat 自动发现的配置方式与 Filebeat 完全相同。 这里是针对 Redis 容器的 Metricbeat 自动发现配置。 此配置片段来自于文件 metricbeat-kubernetes.yaml

- condition.equals:
    kubernetes.labels.tier: backend
  config:
    - module: redis
      metricsets: ["info", "keyspace"]
      period: 10s

      # Redis hosts
      hosts: ["${data.host}:${data.port}"]

配置 Metricbeat,在探测到标签 tier 的值等于 backend 时,应用 Metricbeat 模块 redisredis 模块可以获取容器元数据,连接到 Pod 适当的主机和端口,从 Pod 中收集指标 infokeyspace

部署 Metricbeat

kubectl create -f metricbeat-kubernetes.yaml

验证

kubectl get pods -n kube-system -l k8s-app=metricbeat

关于 Packetbeat

Packetbeat 的配置方式不同于 Filebeat 和 Metricbeat。 相比于匹配容器标签的模式,它的配置基于相关协议和端口号。 下面展示的是端口号的一个子集:

说明: 如果你的服务运行在非标准的端口上,那就打开文件 filebeat.yaml,把这个端口号添加到合适的类型中,然后删除/启动 Packetbeat 的守护进程。
packetbeat.interfaces.device: any

packetbeat.protocols:
- type: dns
  ports: [53]
  include_authorities: true
  include_additionals: true

- type: http
  ports: [80, 8000, 8080, 9200]

- type: mysql
  ports: [3306]

- type: redis
  ports: [6379]

packetbeat.flows:
  timeout: 30s
  period: 10s

部署 Packetbeat

kubectl create -f packetbeat-kubernetes.yaml

验证

kubectl get pods -n kube-system -l k8s-app=packetbeat-dynamic

在 kibana 中浏览

在浏览器中打开 kibana,再打开 Dashboard。 在搜索栏中键入 Kubernetes,再点击 Metricbeat 的 Kubernetes Dashboard。 此 Dashboard 展示节点状态、应用部署等。

在 Dashboard 页面,搜索 Packetbeat,并浏览 Packetbeat 概览信息。

同样地,浏览 Apache 和 Redis 的 Dashboard。 可以看到日志和指标各自独立 Dashboard。 Apache Metricbeat Dashboard 是空的。 找到 Apache Filebeat Dashboard,拉到最下面,查看 Apache 的错误日志。 日志会揭示出没有 Apache 指标的原因。

要让 metricbeat 得到 Apache 的指标,需要添加一个包含模块状态配置文件的 ConfigMap,并重新部署 Guestbook。

缩放部署规模,查看新 Pod 已被监控

列出现有的 deployments:

kubectl get deployments

输出:

NAME            READY   UP-TO-DATE   AVAILABLE   AGE
frontend        3/3     3            3           3h27m
redis-master    1/1     1            1           3h27m
redis-slave     2/2     2            2           3h27m

缩放前端到两个 Pod:

kubectl scale --replicas=2 deployment/frontend

输出:

deployment.extensions/frontend scaled

将前端应用缩放回三个 Pod:

kubectl scale --replicas=3 deployment/frontend

在 Kibana 中查看变化

参见屏幕截图,添加指定的过滤器,然后将列添加到视图。 你可以看到,ScalingReplicaSet 被做了标记,从标记的点开始,到消息列表的顶部,展示了拉取的镜像、挂载的卷、启动的 Pod 等。 Kibana 发现

清理现场

删除 Deployments 和 Services, 删除运行的 Pod。 用标签功能在一个命令中删除多个资源。

  1. 执行下列命令,删除所有的 Pod、Deployment 和 Services。

    kubectl delete deployment -l app=redis
    kubectl delete service -l app=redis
    kubectl delete deployment -l app=guestbook
    kubectl delete service -l app=guestbook
    kubectl delete -f filebeat-kubernetes.yaml
    kubectl delete -f metricbeat-kubernetes.yaml
    kubectl delete -f packetbeat-kubernetes.yaml
    kubectl delete secret dynamic-logging -n kube-system
    
  2. 查询 Pod,以核实没有 Pod 还在运行:

    kubectl get pods
    

    响应应该是这样:

    No resources found.
    

接下来