51、Kubernetes 日志收集与监控实战指南

Kubernetes 日志收集与监控实战指南

1. 引言

在 Kubernetes 环境中,日志收集和监控是 DevOps 人员必须关注的重要方面,它们能帮助我们了解系统的稳定性和状态。本文将详细介绍如何收集应用程序日志、处理 Kubernetes 日志、处理 etcd 日志以及监控主节点和工作节点。

2. 收集应用程序日志

在管理应用程序时,日志收集和分析是跟踪应用程序状态的重要日常工作。但在 Docker/Kubernetes 环境中,由于日志文件位于容器内部,从容器外部访问它们并不容易。此外,如果应用程序有多个 Pod,很难追踪问题发生在哪个 Pod 中。为了解决这个问题,可以使用集中式日志收集平台,如 ELK(Elasticsearch、Logstash 和 Kibana)。

2.1 准备 Elasticsearch 服务器

首先,需要准备 Elasticsearch 服务器。可以使用 curl 命令下载 Kubernetes 源文件中提供的 YAML 文件来设置 Elasticsearch:

# curl -L -O https://github.com/kubernetes/kubernetes/releases/download/v1.1.4/kubernetes.tar.gz
# tar zxf kubernetes.tar.gz 
# cd kubernetes/examples/elasticsearch/
# ls
es-rc.yaml  es-svc.yaml  production_cluster  README.md  service-account.yaml

然后创建 ServiceAccount、Elasticsearch 复制控制器和服务:

# kubectl create -f service-account.yaml 
serviceaccount "elasticsearch" created
# kubectl create -f es-rc.yaml --validate=false
replicationcontroller "es" created
# kubectl create -f es-svc.yaml 
service "elasticsearch" created

可以通过 Kubernetes 服务访问 Elasticsearch 接口:

# kubectl get service
NAME            CLUSTER_IP       EXTERNAL_IP   PORT(S)              SELECTOR                  AGE
elasticsearch   192.168.45.152                 9200/TCP,9300/TCP   component=elasticsearch   9s
kubernetes      192.168.0.1      <none>        443/TCP             <none>                    110d
# curl http://192.168.45.152:9200/
{
  "status" : 200,
  "name" : "Wallflower",
  "cluster_name" : "myesdb",
  "version" : {
    "number" : "1.7.1",
    "build_hash" : "b88f43fc40b0bcd7f173a1f9ee2e97816de80b19",
    "build_timestamp" : "2015-07-29T09:54:16Z",
    "build_snapshot" : false,
    "lucene_version" : "4.10.4"
  },
  "tagline" : "You Know, for Search"
}
2.2 准备示例应用程序

使用一个 Python Flask 程序作为示例应用程序:

# cat entry.py
from flask import Flask, request 
app = Flask(__name__) 
@app.route("/") 
def hello(): 
    return "Hello World!" 
@app.route("/addition/<int:x>/<int:y>") 
def add(x, y): 
    return "%d" % (x+y) 
if __name__ == "__main__": 
    app.run(host='0.0.0.0') 
2.3 使用 Logstash 发送日志到 Elasticsearch

Logstash 可以将应用程序日志从纯文本格式转换为 Elasticsearch(JSON)格式。Logstash 需要一个配置文件来指定 Elasticsearch 的 IP 地址和端口号:

# cat logstash.conf.temp 
input { 
    stdin {}
}
filter {
  grok {
    match => {
        "message" => "%{IPORHOST:clientip} %{HTTPDUSER:ident} %{USER:auth} \[%{DATA:timestamp}\] \"(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})\" %{NUMBER:response} (?:%{NUMBER:bytes}|-)"
    }
  }
}
output {
  elasticsearch {
    hosts => ["_ES_IP_:_ES_PORT_"]
    index => "mycalc-access"
}
stdout { codec => rubydebug }
}

启动脚本会读取环境变量,并替换占位符以设置真实的 IP 和端口号:

#!/bin/sh
TEMPLATE="logstash.conf.temp"
LOGSTASH="logstash-2.2.2/bin/logstash"
cat $TEMPLATE | sed "s/_ES_IP_/$ELASTICSEARCH_SERVICE_HOST/g" | sed "s/_ES_PORT_/$ELASTICSEARCH_SERVICE_PORT/g" > logstash.conf
python entry.py 2>&1 | $LOGSTASH -f logstash.conf
2.4 构建 Docker 镜像

使用 Dockerfile 构建示例应用程序的 Docker 镜像:

FROM ubuntu:14.04
# Update packages
RUN apt-get update -y
# Install Python Setuptools
RUN apt-get install -y python-setuptools git telnet curl openjdk-7-jre
# Install pip
RUN easy_install pip
# Bundle app source
ADD . /src
WORKDIR /src
# Download LogStash
RUN curl -L -O https://download.elastic.co/logstash/logstash/logstash-2.2.2.tar.gz
RUN tar -zxf logstash-2.2.2.tar.gz
# Add and install Python modules
RUN pip install Flask
# Expose
EXPOSE  5000
# Run
CMD ["./startup.sh"]

使用 docker build 命令构建镜像并上传到 Docker Hub:

# docker build -t hidetosaito/my-calc-elk .
# docker login
Username: hidetosaito
Password: 
Email: hideto.saito@yahoo.com
# docker push hidetosaito/my-calc-elk
2.5 创建 Kubernetes 复制控制器和服务

使用 YAML 文件创建 Kubernetes 复制控制器和服务:

# cat my-calc-elk.yaml 
apiVersion: v1
kind: ReplicationController
metadata:
  name: my-calc-elk-rc
spec:
  replicas: 2
  selector:
        app: my-calc-elk
  template:
    metadata:
      labels:
        app: my-calc-elk
    spec:
      containers:
      - name: my-calc-elk
        image: hidetosaito/my-calc-elk
---
apiVersion: v1
kind: Service
metadata:
  name: my-calc-elk-service
spec:
  ports:
    - protocol: TCP
      port: 5000
  type: ClusterIP
  selector:
     app: my-calc-elk

使用 kubectl 命令创建复制控制器和服务:

# kubectl create -f my-calc-elk.yaml 
replicationcontroller "my-calc-elk-rc" created
service "my-calc-elk-service" created

检查 Kubernetes 服务以找到应用程序的 IP 地址,并使用 curl 命令访问应用程序:

# kubectl get service
NAME                  CLUSTER_IP        EXTERNAL_IP   PORT(S)              SELECTOR                  AGE
elasticsearch         192.168.101.143                 9200/TCP,9300/TCP   component=elasticsearch   15h
kubernetes            192.168.0.1       <none>        443/TCP              <none>                    19h
my-calc-elk-service   192.168.121.63    <none>        5000/TCP            app=my-calc-elk           39s
# curl http://192.168.121.63:5000/
Hello World!
# curl http://192.168.121.63:5000/addition/3/5
8
2.6 使用 Kibana 可视化日志

Kibana 是 Elasticsearch 的可视化工具。下载 Kibana 并指定 Elasticsearch 的 IP 地址和端口号来启动 Kibana:

# curl -O https://download.elastic.co/kibana/kibana/kibana-4.1.6-linux-x64.tar.gz
# tar -zxf kibana-4.1.6-linux-x64.tar.gz
# kubectl get services
NAME                  CLUSTER_IP        EXTERNAL_IP   PORT(S)              SELECTOR                  AGE
elasticsearch         192.168.101.143                 9200/TCP,9300/TCP   component=elasticsearch   19h
kubernetes            192.168.0.1       <none>        443/TCP              <none>                    23h
# sed -i -e "s/localhost/192.168.101.143/g" kibana-4.1.6-linux-x64/config/kibana.yml
# kibana-4.1.6-linux-x64/bin/kibana 
3. 处理 Kubernetes 日志

Kubernetes 主节点上有三个守护进程:API 服务器、调度器和控制器管理器,对应的日志文件位于 /var/log 文件夹下:
| 主节点守护进程 | 日志文件 | 描述 |
| — | — | — |
| API 服务器 | apiserver.log | API 调用日志 |
| 调度器 | k8s-scheduler.log | 容器调度事件的调度器数据日志 |
| 控制器管理器 | controller-manager.log | 与控制器管理器相关的事件或问题日志 |

节点上有一个 kubelet 进程来处理容器操作并向主节点报告,其日志文件为 kubelet.log。此外,主节点和节点上还有一个 kube-proxy.log 文件来记录网络连接问题。

3.1 准备工作

使用 ELK 作为集中式日志平台来收集 Kubernetes 日志。在收集日志之前,了解日志的数据结构很重要,日志格式如下:

<日志级别><日期> <时间戳> <指示符> <源文件>:<行号>] <日志内容>

例如:

E0328 00:46:50.870875    3189 reflector.go:227] pkg/proxy/config/api.go:60: Failed to watch *api.Endpoints: too old resource version: 45128 (45135)

通过日志文件中每行的首字符可以知道日志的严重程度:
- D: DEBUG
- I: INFO
- W: WARN
- E: ERROR
- F: FATAL

3.2 收集日志

使用 Logstash 的 grok 过滤器来处理日志。首先创建一个自定义模式文件:

# cat ./patterns/k8s
LOGLEVEL    [DEFIW]
DATE        [0-9]{4}
K8SLOGLEVEL %{LOGLEVEL:level}%{DATE}

然后创建 Logstash 配置文件:

# cat apiserver.conf
input {
  file {
    path => "/var/log/k8s-apiserver.log"
  }
}
filter {
  grok {
    patterns_dir => ["./patterns"]
    match => { "message" => "%{K8SLOGLEVEL} %{TIME}    %{NUMBER} %{PROG:program}:%{POSINT:line}] %{GREEDYDATA:message}" }
  }
}
output {
  elasticsearch {
    hosts => ["_ES_IP_:_ES_PORT_"]
    index => "k8s-apiserver"
  }
  stdout { codec => rubydebug }
}

启动 Logstash:

# bin/logstash -f apiserver.conf
4. 处理 etcd 日志

etcd 是 Kubernetes 数据存储,对于保存 Kubernetes 资源信息至关重要。如果 Pod 信息丢失,将无法在系统中识别它。

4.1 准备工作

在收集 etcd 日志之前,需要准备 ELK 服务器。如果 etcd 服务器是 Kubernetes 集群之外的独立机器,需要暴露 Elasticsearch 的 Kubernetes 服务:

# cat es-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: elasticsearch
  labels:
    component: elasticsearch
spec:
  type: LoadBalancer
  selector:
    component: elasticsearch
  ports:
  - name: http
    port: 9200
    nodePort: 30000
    protocol: TCP
  - name: transport
    port: 9300
    protocol: TCP
4.2 收集日志

etcd 日志文件位于 /var/log/etcd.log,日志格式如下:

<日期> <时间> <子包>: <日志内容>

例如:

2016/04/4 08:43:51 etcdserver: starting server... [version: 2.1.1, cluster version: to_be_decided]

创建 Logstash 配置文件:

# cat etcd.conf
input {
  file {
    path => "/var/log/etcd.log"
  }
}
filter {
  grok {
    match => {
        "message" => "%{DATA:date} %{TIME:time} %{PROG:subpackage}: %{GREEDYDATA:message}"
    }
  }
}
output {
  elasticsearch {
    hosts => ["<ELASTIC_SERVICE_IP>:<EXPOSE_PORT>"]
    index => "etcd-log"
  }
  stdout { codec => rubydebug }
}

启动 Logstash:

# ./bin/logstash -f etcd.conf
5. 监控主节点和工作节点

监控工具可以帮助我们了解工作节点和 Pod 的资源消耗情况,提高资源利用率。

5.1 准备工作

在 Kubernetes 系统中设置监控集群之前,需要完成两个主要前提条件:
- 更新到最新版本的二进制文件,确保集群具有稳定和强大的功能。
- 设置 DNS 服务器,Kubernetes DNS 服务器可以减少安装类似集群的 Pod 的步骤和依赖。

更新 Kubernetes 到最新版本 1.2.1 的步骤如下:
1. 停止所有 Kubernetes 服务:

service <KUBERNETES_DAEMON> stop
  1. 下载最新的 tarball 文件:
# cd /tmp && wget https://storage.googleapis.com/kubernetes-release/release/v1.2.1/kubernetes.tar.gz
  1. 解压文件:
# tar -xvf /tmp/kubernetes.tar.gz -C /opt/
# cd /opt && tar -xvf /opt/kubernetes/server/kubernetes-server-linux-amd64.tar.gz
  1. 复制新文件并覆盖旧文件:
# cd /opt/kubernetes/server/bin/
# cp kubectl hypercube kube-apiserver kube-controller-manager kube-scheduler kube-proxy /usr/local/bin  # 主节点
# cp kubelet kube-proxy /usr/local/bin  # 工作节点
  1. 启动系统服务并验证版本:
# kubectl version

设置 DNS 服务器的步骤如下:
1. 使用官方模板启动 DNS 服务器:

# cd /opt/kubernetes/cluster/addons/dns
# cp skydns-rc.yaml.in skydns-rc.yaml
# cp skydns-svc.yaml.in skydns-svc.yaml

替换模板中的变量:
| 输入变量 | 替换值 | 示例 |
| — | — | — |
| {{ pillar[‘dns_domain’] }} | 集群的域名 | k8s.local |
| {{ pillar[‘dns_replicas’] }} | 复制控制器的副本数量 | 1 |
| {{ pillar[‘dns_server’] }} | DNS 服务器的私有 IP | 192.168.0.2 |

修改 skydns-rc.yaml 文件中的 master URL:

# cat skydns-rc.yaml
...
- name: kube2sky
  image: gcr.io/google_containers/kube2sky:1.14
  resources:
    limits:
      cpu: 100m
      memory: 200Mi
    requests:
      cpu: 100m
      memory: 50Mi
  livenessProbe:
    httpGet:
      path: /healthz
      port: 8080
      scheme: HTTP
    initialDelaySeconds: 60
    timeoutSeconds: 5
    successThreshold: 1
    failureThreshold: 5
  readinessProbe:
    httpGet:
      path: /readiness
      port: 8081
      scheme: HTTP
    initialDelaySeconds: 30
    timeoutSeconds: 5
  args:
  # command = "/kube2sky"
  - --domain=k8s.local
  - --kube-master-url=<MASTER_ENDPOINT_URL>:<EXPOSED_PORT>
...

创建资源:

# kubectl create -f skydns-svc.yaml
# kubectl create -f skydns-rc.yaml
  1. 在 kubelet 中启用 Kubernetes DNS:
    对于 init 服务守护进程:
# cat /etc/init.d/kubernetes-node
...
# Start daemon.
echo $"Starting kubelet: "
        daemon $kubelet_prog \
                --api_servers=<MASTER_ENDPOINT_URL>:<EXPOSED_PORT> \
                --v=2 \
                --cluster-dns=192.168.0.2 \
                --cluster-domain=k8s.local \
                --address=0.0.0.0 \
                --enable_server \
                --hostname_override=${hostname} \
                > ${logfile}-kubelet.log 2>&1 &
...

对于 systemd 服务:

# cat /etc/kubernetes/kubelet
...
# Add your own!
KUBELET_ARGS="--cluster-dns=192.168.0.2 --cluster-domain=k8s.local"

重启 kubelet 服务。

5.2 安装监控集群

使用 Heapster 作为资源使用情况收集和分析工具,结合 influxDB 进行存储和 Grafana 作为前端仪表盘。
1. 检查监控集群的目录:

# cd /opt/kubernetes/cluster/addons/cluster-monitoring/influxdb && ls
grafana-service.yaml      heapster-service.yaml              influxdb-service.yaml
heapster-controller.yaml  influxdb-grafana-controller.yaml
  1. 保留大部分服务模板的默认设置,但暴露 Grafana 服务:
# cat heapster-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: monitoring-grafana
  namespace: kube-system
  labels:
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "Grafana"
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30000
      targetPort: 3000
  selector:
    k8s-app: influxGrafana
  1. 修改 Heapster 和 influxDB-Grafana 的复制控制器模板:
# cat influxdb-grafana-controller.yaml
...
- image: gcr.io/google_containers/heapster_grafana:v2.6.0-2
          name: grafana
          env:
          resources:
            # keep request = limit to keep this container in guaranteed class
            limits:
              cpu: 100m
              memory: 100Mi
            requests:
              cpu: 100m
              memory: 100Mi
          env:
            # This variable is required to setup templates in Grafana.
            - name: INFLUXDB_SERVICE_URL
              value: http://monitoring-influxdb.kube-system:8086
            - name: GF_AUTH_BASIC_ENABLED
              value: "false"
            - name: GF_AUTH_ANONYMOUS_ENABLED
              value: "true"
            - name: GF_AUTH_ANONYMOUS_ORG_ROLE
              value: Admin
            - name: GF_SERVER_ROOT_URL
              value: /
...
# cat heapster-controller.yaml
...
      containers:
        - image: gcr.io/google_containers/heapster:v1.0.2
          name: heapster
          resources:
            limits:
              cpu: 100m
              memory: 200Mi
            requests:
              cpu: 100m
              memory: 200Mi
          command:
            - /heapster
            - --source=kubernetes:<MASTER_ENDPOINT_URL>:<EXPOSED_PORT>?inClusterConfig=false
            - --sink=influxdb:http://monitoring-influxdb.kube-system:8086
            - --metric_resolution=60s
...
  1. 创建资源:
# kubectl create -f influxdb-service.yaml
# kubectl create -f grafana-service.yaml
# kubectl create -f heapster-service.yaml
# kubectl create -f influxdb-grafana-controller.yaml
# kubectl create -f heapster-controller.yaml
  1. 检查 Kubernetes 资源:
# kubectl get svc --namespace=kube-system
# kubectl get pod --namespace=kube-system
5.3 介绍 Grafana 仪表盘

Grafana 仪表盘默认有两个面板:Cluster 和 Pods。Cluster 面板显示节点的资源利用率,Pods 面板显示每个 Pod 的资源使用情况。

创建一个新的指标来监控 Pod 的步骤如下:
1. 进入 Pods 仪表盘,点击底部的 ADD ROW,选择添加图形面板。
2. 给面板命名,例如 CPU Rate。
3. 设置查询参数:
- FROM: cpu/usage_rate
- WHERE: type = pod_container
- AND: namespace_name=$namespace, pod_name= $podname
- GROUP BY: tag(container_name)
- ALIAS BY: $tag_container_name
4. 点击顶部的图标保存面板。

通过以上步骤,我们可以实现应用程序日志收集、Kubernetes 日志处理、etcd 日志收集以及主节点和工作节点的监控。这些操作可以帮助我们更好地了解系统的运行状态,及时发现和解决问题。

Kubernetes 日志收集与监控实战指南(续)

6. 整体流程梳理

为了更清晰地理解整个日志收集与监控的流程,我们可以用 mermaid 流程图来概括:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;

    A([开始]):::startend --> B(准备工作):::process
    B --> C(收集应用程序日志):::process
    B --> D(处理Kubernetes日志):::process
    B --> E(处理etcd日志):::process
    B --> F(监控主节点和工作节点):::process
    C --> G(ELK平台存储):::process
    D --> G
    E --> G
    F --> H(Heapster收集资源信息):::process
    H --> I(influxDB存储):::process
    I --> J(Grafana可视化):::process
    J --> K([结束]):::startend

这个流程图展示了从准备工作开始,分别进行应用程序日志收集、Kubernetes 日志处理、etcd 日志处理和节点监控,然后将日志统一存储到 ELK 平台,监控信息通过 Heapster 收集后存储到 influxDB,最后由 Grafana 进行可视化展示的完整流程。

7. 常见问题及解决方法

在实际操作过程中,可能会遇到一些常见问题,以下是一些问题及对应的解决方法:

问题描述 可能原因 解决方法
Logstash 无法连接到 Elasticsearch Elasticsearch 服务未启动、网络问题、配置文件中的 IP 或端口错误 检查 Elasticsearch 服务状态,确保网络连通,核对 Logstash 配置文件中的 IP 和端口
Grafana 无法显示数据 influxDB 数据存储问题、Grafana 配置错误 检查 influxDB 中是否有数据,核对 Grafana 中数据源的配置
Kubernetes 日志收集不完整 Logstash 配置错误、日志文件权限问题 检查 Logstash 配置文件,确保日志文件有正确的读取权限
8. 最佳实践建议

为了更好地实现日志收集和监控,以下是一些最佳实践建议:
- 定期清理日志 :随着时间的推移,日志文件会占用大量的磁盘空间。定期清理过期的日志可以避免磁盘空间不足的问题。可以使用 cron 任务来实现定期清理,例如:

0 2 * * * find /var/log -type f -mtime +7 -delete

这个 cron 任务会在每天凌晨 2 点删除 /var/log 目录下 7 天前的日志文件。
- 设置合理的监控指标 :根据实际需求设置监控指标,避免监控过多不必要的指标导致资源浪费。例如,对于 CPU 使用率,可以设置一个合理的阈值,当超过阈值时触发警报。
- 备份重要数据 :定期备份 Elasticsearch 和 influxDB 中的数据,以防止数据丢失。可以使用官方提供的备份工具或脚本来实现。

9. 总结

通过本文的介绍,我们详细了解了在 Kubernetes 环境中进行日志收集和监控的方法。从收集应用程序日志到处理 Kubernetes 日志和 etcd 日志,再到监控主节点和工作节点,每个步骤都有其重要性和操作细节。

使用 ELK 平台可以实现集中式的日志收集和存储,方便后续的分析和查询。Heapster、influxDB 和 Grafana 的组合则为我们提供了强大的监控和可视化功能,帮助我们更好地了解系统的资源使用情况。

在实际应用中,我们可以根据具体的需求和场景对这些方法进行调整和优化,以确保系统的稳定性和可靠性。同时,不断关注 Kubernetes 和相关工具的更新,学习新的功能和特性,将有助于我们更好地应对各种挑战。

希望本文能为你在 Kubernetes 日志收集和监控方面提供有价值的参考,让你能够更加高效地管理和维护 Kubernetes 集群。

基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样统计,通过模拟系统元件的故障修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码案例分析,便于复现和扩展应用。; 适合人群:具备电力系统基础知识和Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值