第十课 Kubernetes生产级实践-日志和监控
tags:
- k8s
- 慕课网
categories:
- Log-Pilot+elasticsearch+Kibana
- helm+prometheus-operator+grafana
文章目录
第一节 k8s的日志处理
1.1 日志解决方案
- 传统服务的特点 最终只关注固定目录的固定文件
- 固定机器、固定目录
- 不受重启影响
- 不用关注stdout、stderr
- k8s服务
- 节点不固定
- 重启服务会漂移
- 需关注stdout、stderr
- 所以k8s的日志应该关注两块
- stdout、stderr 标准输出和错误输出。docker本身会进行处理。默认情况会保存在宿主机固定目录中"
- 应用写入的日志文件 docker不会去管它 所以重启会丢失
/var/lib/docker/containers/<cname>/<cname>-json.log
-
怎么解决应用写入的日志文件的采集呢?
-
常见方案一远程日志:直接把日志内容写到远端比如: Kafaka, ES,然后在做统一处理。比如汇总到日志服务器。
- 优点:这种方式优势是简单,适用于各种场景不管docker还是传统,都可以通过这种方式完成日志采集
- 缺点:这种方式劣势是需要对应用进行改造。
-
常见方案二sidecar:在每个pod中跑一个sidecar,它跟主容器共享volume。它就做一个事把日志文件转发到远端存储。
- 优点:简单,对服务没有沁入。但是它对pod还是有一定沁入的。
- 缺点:虽然与主容器共享volume,但是它依然是一个主进程。内存和cpu消耗不可避免,所以社区并不推荐。
-
常见方案三LogAgent:在每个节点上部署一个agent, 把sidercar从pod中拿到节点上。通过一个agent采集所有pod日志,然后发送到后端存储。一般以demonset方式运行在集群中。
- 优点:每个节点只运行一个agent,资源消耗小。入侵性小,对pod和应用侵入性都小
- 缺点:要约定所有程序都挂载到特定的目录,导致日志来源哪个pod。还要想着定期清理日志残留文件。
8 . 方案不一定哪个比哪个好,只有根据业务适应。
1.2 实践日志方案
- 智能容器采集工具 Log-Pilot,它不仅能够高效便捷地将容器日志采集输出到多种存储日志后端,同时还能够动态地发现和采集容器内部的日志文件。
- https://developer.aliyun.com/article/674327
- 常见的日志采集工具有: Logstash、Filebeat、Fluentd、Logagent、logtail
- https://juejin.im/post/6844903830249799694
- 但是上面工具都是静态的配置需要提前写死。
- 对于docker来讲很多配置往往是动态的,如果用上面工具往往会产生问题。所以产生了专门对于docker的日志采集工具
- Log-Pilot 容器日志采集输出到多种存储日志后端如(ES, Kafka, redis,logstash)特点
- 智能的容器日志采集工具
- 自动发现机制 能动态发现采集容器内部的日志文件很好解决了日志重复丢失和日志标记的问题
- 2017年初在github开源https://github.com/AliyunContainerService/log-pilot
- Log-Pilot 容器本质
- 在静态日志采集工具上包装了一层通过获取docker的信息和事件,实现静态工具的动态配置
- 目前支持两种日志采集工具:Fluentd、Filebeat
1.3 日志方案搭建
- 先搭建ES组件。看下配置文件elasticsearch.yaml
- 9200端口ES用来和外部应用HTTP通信,9300ES之间进行通信TCP。
- replicas定义了三个节点。最少两个,一个肯定启动不了。每个节点内存不能太小2G不够,用4G。
kubectl create sa dashboard-admin -n kube-system
kubectl apply -f elasticsearch.yaml
kubectl get svc -n kube-system
[root@m1 ~]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
calico-node-4ld7h 1/2 Running 42 23h
calico-node-8x5p5 1/2 Running 119 24h
calico-node-fk2s7 1/2 Running 109 24h
calico-node-fw4lb 2/2 Running 19 24h
calico-node-n7vxn 2/2 Running 27 24h
calico-typha-666749994b-b5d22 1/1 Running 6 50m
calico-typha-666749994b-kfz6t 1/1 Terminating 4 20h
coredns-588555fc6b-bftjw 1/1 Running 69 6h5m
elasticsearch-0 1/1 Running 1 28m
elasticsearch-1 1/1 Running 1 16m
elasticsearch-2 1/1 Running 2 13m
# 部署log-pilot daemonset一个主机一个端口
kubectl apply -f log-pilot.yaml
kubectl get ds -n kube-system
# 运行kibana
kubectl apply -f kibana.yaml
kubectl get svc -n kube-system
kubectl get deploy -n kube-system
# 配置hosts 192.168.242.136 kibana.mooc.com 浏览器访问
# 提示我们创建索引 但是我们没有采集到任何日志
# 看下log-pilot有没有日志
docker ps | grep log-pilot
docker logs
docker logs 5d89a2da948a
# 创建一个服务 配置一下服务服务采集的功能 看下web.yaml 里面有一些环境变量的配置
# 开头必须是aliyun_logs_是定义规则,catalina是自己起的名字: aliyun_logs_catalina如果对接的是ES,它表示索引。如果对接的是kafka, 它表示的是Topic
env:
- name: aliyun_logs_catalina
value: "stdout"
- name: aliyun_logs_access
value: "/usr/local/tomcat/logs/*"
# 除了环境变量还有挂载的目录修改
kubectl apply -f web.yaml
# 这个时候在看一下容器日志 返现采集到了 及处理了标准输出也处理了声明的日志目录
docker logs 5d89a2da948a
time="2020-10-19T14:38:28Z" level=info msg="logs: 49264d29c30959177e389b608687393f98263e18f8b0754521c8c42e6a8166d4 = &{catalina /host/var/lib/docker/containers/49264d29c30959177e389b608687393f98263e18f8b0754521c8c42e6a8166d4 nonex map[time_format:%Y-%m-%dT%H:%M:%S.%NZ] 49264d29c30959177e389b608687393f98263e18f8b0754521c8c42e6a8166d4-json.log* map[index:catalina topic:catalina] false true}"
time="2020-10-19T14:38:28Z" level=info msg="logs: 49264d29c30959177e389b608687393f98263e18f8b0754521c8c42e6a8166d4 = &{access /host/var/lib/kubelet/pods/8e902d7c-1218-11eb-ba45-000c29a482ce/volumes/kubernetes.io~empty-dir/accesslogs /usr/local/tomcat/logs nonex map[time_key:_timestamp] * map[index:access topic:access] true false}"
# 可以看一下 stdout标准输出的目录
ls /var/lib/docker/containers/49264d29c30959177e389b608687393f98263e18f8b0754521c8c42e6a8166d4
# 查看映射的volume 日志输出
ll /var/lib/kubelet/pods/8e902d7c-1218-11eb-ba45-000c29a482ce/volumes/kubernetes.io~empty-dir/accesslogs /usr/local/tomcat/logs
# 到页面上配置索引
# 访问web服务:http://web.mooc.com/hello?name=michael 后根据字段搜索日志
第二节 k8s监控方案
2.1 监控入门常识
- 监控的目的。
- 及时发现已经出现的问题
- 提前预警可能发生的问题
- 监控的内容:
- 系统基础指标 服务器的技术指标CPU 内存 网络 IO 负载
- 服务基础信息 使用的内存(是否溢出了) cpu 网络带宽 占用的磁盘IO
- 服务个性化信息 web的请求次数 错误次数 处理时间
- 日志 异常数 异常的频率
- 如何监控
- 数据采集 必须是持续的
- 数据存储 一般采用时间序列数据库进行存储
- 定义报警规则
- 配置报警方式 邮件 短信 钉钉等等
- 业内常见的传统监控组件/方案
- Zabbix
- OpenFalcon 小米开源
- 第三方公司产品:听云、监控宝
- k8s的监控
- 每个节点的基础指标
- 每个容器的基础指标
- k8s集群组件的监控
2.2 Prometheus架构和原理
- Prometheus是什么?
- 一系列服务的组合
- 系统和服务的监控报警平台 包括但是不限于docker和k8s集群的监控。支持静态配置监控目标。支持动态的服务发现。对spring boot的支持也很好
- Prometheus特征
- 由metric名称和kv标识的多维数据模型
- 灵活的查询语言(PromQL)
- 支持pull、push两种方式添加数据
- 支持基于Kubernetes服务发现的动态配置
# 每个metric名字http_response_total,加上KV组合{method="GET",endpoint="/api/get"}都是一条时间序列
http_response_total{method="GET",endpoint="/api/get"}
http_response_total{method="POST",endpoint="/api/create"}
http_response_total{method="PUT",endpoint= "/api/put"}
-
架构设计
-
数据类型
- Counter 记录累计值
- Gauge 常规数值
- Histogram类似直方图 && Summary类似九九线 统计分析样本的分布情况
-
数据来源 - 服务器基础指标:https://github.com/prometheus/prometheus
-
数据来源 - docker的容器指标
-
数据来源 - Kubernetes组件。每一个Kubernetes组件都自带了metrics,定期抓一下数据就可以。
2.3 Prometheus部署准备
- 部署方案选择
- 手动部署 要求知道每个组件如何部署 如何做高可用 如何协同工作
- Helm k8s的包管理工具
- Prometheus Operator CRD+控制器 直接使用成本很高 要做的事很多
- Helm+Prometheus Operator 这种方式非常优雅
- Helm简介
- 类似Ubuntu的apt-get、Centos的yum
- Kubernetes的包管理器
- 一包一Chart(一个目录)
- Helm部署
由于国内网络原因,无法科学上网的同学可以到我的网盘上下载,版本是2.13.1-linux-amd64。
链接: https://pan.baidu.com/s/1bu-cpjVaSVGVXuWvWoqHEw
提取码: 5wds
# 每个机器上安装
yum install -y socat
# 解压
tar -zxvf helm-v2.13.1-linux-amd64.tar.gz
mv linux-amd64/helm /usr/local/bin/
# 没配置环境变量的需要先配置好
export PATH=$PATH:/usr/local/bin/
# 验证
helm version
# Tiller安装
# Tiller 是以 Deployment 方式部署在 Kubernetes 集群中的,由于 Helm 默认会去 storage.googleapis.com 拉取镜像,我们这里就默认无法科学上网的情况:
# 指向阿里云的仓库
helm init --client-only --stable-repo-url https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts/
helm repo add incubator https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts-incubator/
helm repo update
# 因为官方的镜像无法拉取,使用-i指定自己的镜像
helm init --service-account tiller --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.13.1 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
# 创建TLS认证服务端
helm init --service-account tiller --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.13.1 --tiller-tls-cert /etc/kubernetes/ssl/tiller001.pem --tiller-tls-key /etc/kubernetes/ssl/tiller001-key.pem --tls-ca-cert /etc/kubernetes/ssl/ca.pem --tiller-namespace kube-system --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
# 给Tiller授权
# 因为 Helm 的服务端 Tiller 是一个部署在 Kubernetes 中的 Deployment,它会去访问ApiServer去对集群进行操作。目前的 Tiller 部署时默认没有定义授权的 ServiceAccount,这会导致访问 API Server 时被拒绝>。所以我们需要明确为 Tiller 部署添加授权。
# 创建serviceaccount
kubectl create serviceaccount --namespace kube-system tiller
# 创建角色绑定
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
# 查看Tiller的serviceaccount,需要跟我们创建的名字一致:tiller
kubectl get deploy --namespace kube-system tiller-deploy -o yaml|grep serviceAccount
# 验证pods
kubectl -n kube-system get pods | grep tiller
# 验证版本
helm version
- Operator实现原理
- 自定义资源类型(CRD)+自定义控制器(这是难点),关于CRD学习资料很丰富可以自己学。
- k8s 1.7之后就支持了CRD
2.4 Prometheus部署
# 由于国内网络原因和阿里源不更新 所以我们选择git直接下载源码
# 如果你用课程中老师的记得把后边几节的配置也看一下。要不然坑死你
# helm install --name imooc-prom stable/prometheus-operator
git clone https://github.com/helm/charts
cd charts/stable/prometheus-operator/ # 这就是我们需要的
# 安装一下
helm install ./prometheus-operator/ --name imooc-prom --namespace monitoring
# 如果报错 清除crd后重新安装
kubectl delete crd $(kubectl get crd | grep coreos | awk '{print $1}')
# 删除
helm delete imooc-prom # 删除到回收站
helm delete --purge imooc-prom # 彻底删除
# 如果镜像下载不到 可以这样修改
find .| grep values.yaml | xargs grep "image:"
vim values.yaml # 修改一下它registry.cn-hangzhou.aliyuncs.com/imooc/
# 修改后更新下
docker pull registry.cn-beijing.aliyuncs.com/acs/prometheus:v2.9.1
docker tag registry.cn-beijing.aliyuncs.com/acs/prometheus:v2.9.1 quay.io/prometheus/prometheus:v2.9.1
helm upgrade imooc-prom ./prometheus-operator/ -f ./prometheus-operator/charts/grafana/values.yaml
# 如果是课程中的prometheus-operator,需要手动创建etcd-certs。这里要根据配置来
kubectl -n monitoring create secret generic etcd-certs --from-file=/etc/kubernetes/pki/ca.pem --from-file=/etc/kubernetes/pki/etcd-key.pem --from-file=/etc/kubernetes/pki/etcd.pem
# 查看自定义资源类型
kubectl get pods -n monitoring -o wide
kubectl get deploy -n monitoring
kubectl get ds -n monitoring # 负责采集节点指标,每个节点一个
kubectl get statefulset -n monitoring # 支持运行多实例达到多可用
kubectl get service -n monitoring
[root@m1 12-monitoring]# kubectl get pods -n monitoring -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
alertmanager-imooc-prom-prometheus-oper-alertmanager-0 2/2 Running 0 74m 172.22.1.8 n1 <none> <none>
imooc-prom-grafana-68647fc4b-ggs69 2/2 Running 0 74m 172.22.3.80 s2 <none> <none>
imooc-prom-kube-state-metrics-55d7674858-4wq2t 1/1 Running 0 74m 172.22.4.45 s1 <none> <none>
imooc-prom-prometheus-node-exporter-6sv4l 1/1 Running 0 74m 192.168.242.135 n1 <none> <none>
imooc-prom-prometheus-node-exporter-d82db 1/1 Running 0 74m 192.168.242.139 s1 <none> <none>
imooc-prom-prometheus-node-exporter-x8kjp 1/1 Running 0 74m 192.168.242.140 s2 <none> <none>
imooc-prom-prometheus-oper-operator-84f774bbc9-pmj8x 1/1 Running 0 74m 172.22.4.44 s1 <none> <none>
prometheus-imooc-prom-prometheus-oper-prometheus-0 3/3 Running 1 74m 172.22.4.46 s1 <none> <none>
# 创建ingress
kubectl apply -f ingress-prometheus.yaml
# 定制化修改把下面改成paused: true 就能删除statefulset了
kubectl edit alertmanagers.monitoring.coreos.com -n monitoring
kubectl get statefulset alertmanager-imooc-prom-prometheus-oper-alertmanager -n monitoring -o yaml > dump.yaml
kubectl delete statefulset alertmanager-imooc-prom-prometheus-oper-alertmanager -n monitoring
# 修改dump.yaml 然后重新应用alertmanager-imooc-prom-prometheus-oper-alertmanager-0.alertmanager-operated.monitoring.svc.cluster.local:6783
# 再看日志果真少了一个bug
kubectl create -f dump.yaml
# 修改host 并访问http://prometheus.mooc.com/
第三节 落地监控实践
3.1 prometheus页面
-
主页面,用来查询,可以输入 prometheus的QL。直接选择一个采集的指标执行。
-
左边可以看到图标的变化。这里的图标比较简单,一般我们看图标都是对接到grafana.
-
这里Status下有个Targets。
- Last Scrape 上次抓取时间,默认30秒抓取一次。
- Labels 是前面的Endpoint下都具有的标签,一般用来过滤数据和数据聚合,鼠标放上不动。可以看到一些元数据
-
imooc-prom-prometheus-oper-kube-state-metrics想了解是什么,可以在一个worker节点上访问EndPoint.
- curl http://172.22.4.41:8080/metrics
-
imooc-prom-prometheus-oper-kubelet/0 监控kubelet本身的信息的。
-
imooc-prom-prometheus-oper-kubelet/1监控kubelet节点的容器的信息的。
-
imooc-prom-prometheus-oper-node-exporter/0 它用来采集节点信息的Daemonset, 它是基于http的,可以直接点开Endpoint,里面是系统相关的指标。
-
imooc-prom-prometheus-oper-operator/0 控制器本身的一个监控
-
imooc-prom-prometheus-oper-prometheus/0 prometheus Server本身的一个监控
3.2 指标完善
- 对kube-controller-manager, kube-etcd, kube-scheduler三个组件指标进行完善。(因为是二进制安装,所以默认不会采集到他们的信息,需要自己配置)
- prometheus本身的组建在根目录下的value.yaml进行配置的。如果不想对某个组件进行监控,直接该组件的enabled:false就可以了。
- 打开后搜索kube-controller-manage组件。
# 修改主机点列表。如果是pod的方式运行就不存在这种问题。写[]
endpoints:
- 192.168.242.145
- 192.168.242.146
# 注释掉selector
service:
port: 10252
targetPort: 10252
# selector:
# component: kube-controller-manage
# 观察节点10252 是https还是http vi /etc/systemd/system/kube-controller-manager.service
# 修改--bind-address=192.168.242.145
# 有个--secure-port=10252 是https的 修改配置
https: true
- 修改etcd的配置
# 主节点创建证书 这里是二进制的安装。如果adm安装自己搜一下证书不用pem创建
kubectl -n monitoring create secret generic etcd-certs --from-file=/etc/kubernetes/pki/ca.pem --from-file=/etc/kubernetes/pki/etcd-key.pem --from-file=/etc/kubernetes/pki/etcd.pem
# 看下证书
kubectl get secret etcd-certs -n monitoring -o yaml
endpoints:
- 192.168.242.145
- 192.168.242.146
serviceMonitor:
# 这里查看etcd是https还是http vi /etc/systemd/system/etcd.service
# -listen-client-urls=https://192.168.242.145:2379,http://127.0.0.1:2379
# 最好使用证书访问etcd安全,不要修改http://127.0.0.1:2379 为http://192.168.242.145:2379
# 配置证书路径 这样运行时要先创建一个sercet 上面创建
interval: ""
scheme: https
insecureSkipVerify: false
serverName: ""
# 指定ca,证书和密钥
caFile: "/etc/prometheus/secrets/etcd-certs/ca.pem"
certFile: "/etc/prometheus/secrets/etcd-certs/etcd.pem"
keyFile: "/etc/prometheus/secrets/etcd-certs/etcd-key.pem"
# 配置一下secrets
secrets:
- etcd-certs
- 修改 kube-scheduler的配置
# /kubeScheduler:
endpoints:
- 192.168.242.145
- 192.168.242.146
# 两个都得改
# 查看服务 vi /etc/systemd/system/kube-scheduler.service
vi /etc/systemd/system/kube-scheduler.service
# 发现 --address=127.0.0.1 \ 这肯定不行要监听在本机上 --address=192.168.242.145
--address=192.168.242.145
# netstat -ntlp | grep 10251 然后 curl http://127.0.0.1:10251/matrics 发现可以返回说明是http的
# 保存调整下
systemctl daemon-reload && systemctl restart kube-scheduler
https: false
- 修改kubelet的端口为10255
# 到worker上查看netstat -ntlp | grep kubelet发现开启了两个端口:10250和10255
# 从10255 是基于http的只读端口
# 修改配置 端口应该固化好了
https: false
- 更新配置
helm upgrade imooc-prom ./prometheus-operator/ -f ./prometheus-operator/charts/grafana/values.yaml
3.3 定义报警规则
- 首先根目录下的values.yaml, 定义了一些默认开启的报警规则。
- 默认的报警规则的模板在:prometheus-operator/templates/prometheus/rules
defaultRules:
create: true
rules:
alertmanager: true
etcd: true
general: true
k8s: true
kubeApiserver: true
kubePrometheusNodeAlerting: true
kubePrometheusNodeRecording: true
kubeScheduler: true
kubernetesAbsent: true
kubernetesApps: true
kubernetesResources: true
kubernetesStorage: true
kubernetesSystem: true
node: true
prometheusOperator: true
prometheus: true
- 如果想在原有基础上稍作修改,可以修改他的模板文件。如果想指定定义PrometheusRule的配置文件也可以。
kubectl get PrometheusRule -n monitoring
# 可以看些别的配置 自定义自己的 当然自己定义的不会被helm包进行管理,需要自己手动安装删除
kubectl get PrometheusRule -n monitoring imooc-prom-prometheus-oper-node-time -o yaml
3.4 grafana的使用
kubectl apply -f ingress-grafana.yaml
# 配置hosts并访问 http://prom-grafana.mooc.com/login
# prometheus-operator/charts/grafana的values.yaml查下用户名和密码 adminUser: admin 密码是一个secret
kubectl get secret -n monitoring imooc-prom-grafana -o yaml
# admin密码通过base64解码: prom-operator
-
本质上都是通过PromeQL语句进行查询做的展示图标。点击DashBoard下的manage,选择一个DashBoard查看数据来源。
-
也可以修改PromeQL,可以先拿到QL到Prometheus界面上调试没有问题在放回来。
-
我们也可以创建自己的DashBoard
3.5 配置报警信息
- 配置根目录下的value.yaml
- 需要先登录QQ邮箱,开通smtp功能,并获取授权码。smtp_auth_password填写的信息,就是授权码,而非QQ邮箱的登录密码
config:
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.qq.com:465'
smtp_from: 'SFSDFASD@qq.com'
smtp_auth_username: 'SFSDFASD@qq.com'
smtp_auth_password: 'sltasfdhfxqppgbej' # 这个是授权码
smtp_require_tls: false # smtp_require_tls: false 必须加上,因为smtp_require_tls默认为true。
route:
group_by: ['job']
group_wait: 30s
group_interval: 5m
repeat_interval: 12h
receiver: 'email-alerts'
routes:
- match:
alertname: .*
receiver: 'email-alerts'
receivers:
- name: 'email-alerts'
email_configs:
- to: 'afdsads@qq.com'
send_resolved: true # 问题解决也发送文件
- 测试一下报警
helm upgrade imooc-prom ./prometheus-operator/ -f ./prometheus-operator/charts/grafana/values.yaml
# 看下邮件
systemctl stop etcd