day07 k8s+ELK

1.前情回顾

k8s从kube-metrics-server获取到里面cpu的依据,进行自动扩容
kubectl top node 可以看节点状态,和prometheus对比
prometheus带着参数去请求blackbox-exporter,black-exporter才知道去检测哪些是否存活,tcp存活,http存活
能用http的就用http,不能的话再用tcp

PromQl,不管grafana出图还是alertManager报警都是依赖这个PromQl查询语句

2.日志

业务容器扩容,缩容
业务日志,2份变4份
日志集中收集
中国互联网公司,落磁盘为主,日志比较好的收集起来

需求:
日志收集,分析的系统

  • 收集--能够采集多种来源的日志数据(流式日志收集器)logstash
  • 传输--能够稳定的把日志数据传输到中央系统(消息队列)
  • 存储--可以将日志以结构化数据的形式存储起来(搜索引擎),日志转成json,存储起来
  • 分析--支持方便的分析,检索方法,最好有gui管理系统(前端)
  • 警告--能够提供错误报告,监控机制(监控工具)(es里面插件有告警)

3.ELK Stack

火了7,8年了
E:ElasticSearch(mysql是b+数的索引)
L:logstash
K:kibana

es倒排索引,关键字做分词,可以关键字做索引.

3.1 传统elk框架

  • logstash使用ruby开发,吃资源,消耗高
  • 业务程序与logstash耦合松,不利于业务迁移
  • 日志收集与ES耦合过紧,易打爆,丢数据(容易把es打爆)
  • 容器云环境,传统ELK模型难以完成工作

3.2 改进后的架构

  • 业务容器pod部分:logstash耗资源,使用filebeat(golang)替换,流式日志收集,消耗资源更小.并且pod和filebeat用了边车模式绑定到了一起运行,耦合度变紧了.一个pod里面运行了2个container,一个是业务container,一个是filebeat,共享了ipc,user,uts.隔离了net,fs,pid(共享了3个名称空间,隔离了3个名称空间)
  • kafka:做了一层解耦,消息队列,支持发布订阅模型,filebeat是用topic的形式,去kafka上publish(kafka吞吐量比较大的消息队列),不同的业务是用kafka上不同的topic来区分的,一个应用一个topic
  • logstash:订阅了kafka上的topic(异步的过程),实时kinbana看日志的时候有一定延迟
  • ElasticSearch:里面用了index-pattern去给日志环境做区分,生产环境,还是测试环境

4.改造dubbo-demo-web项目

改为使用tomcat类型的项目,底包,放war包这种
使用tomcat8.5.50.tar.gz二进制包

[root@jdss7-200]# cd /opt/src
[root@jdss7-200]# wget http://xxxx/apache-tomcat8.5.50.tar.gz
[root@jdss7-200]# mkdir -p /data/dockerfile/tomcat/
[root@jdss7-200]# tar zxf apache-tomcat8.5.50.tar.gz -C /data/dockerfile/tomcat/
[root@jdss7-200]# cd /data/dockerfile/tomcat/\

4.1 优化tomcat,移除AJP协议

[root@jdss7-200]# vim server.xml
# 关闭AJP端口,8009,这个端口ajp协议是和apache一起用的
<!--<Connector port="8009" portocol="JP/1.3" redirectPort="8443" /> -->

4.2 配置日志,移除不需要的日志handler

vim conf/logging.properties
删除3manager,4host-manager的handlers

上面标注的要删掉

上面的要注释掉

4.3 修改日志级别INFO


5.制作Tomcat的Dockerfile

Dockerfile

FROM harbor.od.com/public/jre:8u112
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone
ENV CATALINA_HOME /opt/tomcat
ENV LANG zh_CN.UTF-8
ADD apache-tomcat-8.5.50 /top/tomcat
ADD config.yml /opt/prom/config.yml # 这个是prometheus基于file sd,手动发现的相关配置,
ADD jmx_javaagent-0.3.1.jar /opt/prom/jmx_javaagent-0.3.1.jar
WORKDIR /opt/tomcat
ADD entrypoint.sh /entrypoint.sh
CMD ["/entrypoint.sh"]

config.yml

---
rules:
  - pattern: '.*'

entrypoint.sh(chmod +x entrypoint.sh)

#!/bin/bash
M_OPTS="-Duser.timezone=Asia/Shanghai -javaagent:/opt/prom/jmx_javaagent-0.3.1.jar=$(hostname -i):${M_PORT:-"123456"}:/opt/prom/config.yml"
C_OPTS=${C_OPTS} # apollo的连接串,env是啥,apollo的config地址是啥
MIN_HEAP=${MIN_HEAP:-"128m"}
MAX_HEAP=${MAX_HEAP:-"128m"}
JAVA_OPTS=${JAVA_OPTS:-"-Xmn384m -Xss256k -Duser.timezone=GMT+08 -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=80 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintClassHistogram -Dfile.encoding=UTF8 -Dsun.jnu.encoding=UTF8"}
CATALINA_OPTS="${CATALINA_OPTS}"
JAVA_OPTS="${M_OPTS} ${C_OPTS} -Xms${MIN_HEAP} -Xmx{MAX_HEAP} ${JAVA_OPTS}"
sed -i -e "1a\JAVA_OPTS=\"$JAVA_OPTS\"" -e "1a\CATALINA_OPTS=\"$CATALINA_OPTS\"" /opt/tomcat/bin/catalina.sh

cd /opt/tomcat && /opt/tomcat/bin/catalina.sh run 2> &1 >> /opt/tomcat/logs/stdout.log
# catalina.sh run 进程前台运行了

6.构建tomcat基础镜像

docker build . -t harbor.od.com/base/tomcat:v8.5.50
docker push harbor.od.com/base/tomcat:v8.5.50

7.改造项目,dubbo-demo-web

tomcat分支,pom.xml改packing的类型为war包

多建一条流水线,针对tomcat类型的,普通类型的流水线无法正常运行

8.二进制安装elasticsearch

使用版本是6.8.6,elasticsearch的7版本以后的jdk要11版本了.

7.12部署一台es来实验

[root@jdss7-12]# cd /opt/src
[root@jdss7-12]# wget http://xxx/elasticsearch-6.8.6.tar.gz
[root@jdss7-12]# tar xfv elasticsearch-6.8.6.tar.gz -C /opt
[root@jdss7-12]# ln -s /opt/elasticsearch-6.8.6 /opt/elasticsearch
[root@jdss7-12]# mkdir -p /data/elasticsearch/{data,logs}

8.1 编辑配置文件elasticsearch.yml

[root@jdss7-12]# vim config/elasticsearch.yml
cluster.name: es.od.com
node.name: jdss7-12.host.com
path.data: /data/elasticsearch/data
path.logs: /data/elasticsearch/logs
bootstrap.memory_lock: true
network.host: 10.4.7.12
http.port: 9200

8.2 优化jvm.options

es1个节点占内存官方推荐32G,太大的话会触发full gc,实验环境就整512MB

[root@jdss7-12]# vim config/jvm.options
-Xms512m
-Xmx512m

8.3 创建普通用户,root用户起不来es

[root@jdss7-12]# useradd -s /bin/bash -M es
-M 代表没有家目录
[root@jdss7-12]# chown -R es.es /opt/elasticsearch-6.8.6
[root@jdss7-12]# chown -R es.es /data/elasticsearch/

8.4 调整文件描述符,及内核参数

/etc/security/limits.d/es.conf
es hard nofile  6553
es soft fsize unlimited
es hard memlock unlimited
es soft memlock unlimited

sysctl -w vm.max_map_count=262144
echo "vm.max_map_count=262144" >> /etc/sysctl.conf
sysctl -p

8.5 启动es

方法1
su - es
/opt/elasticsearch/bin/elasticsearch -d
方法2:使用es用户去执行命令
su - es -c "/opt/elasticsearch/bin/elasticsearch -d"
方法3:
sudo -ues "/opt/elasticsearch/bin/elasticsearch -d"
netstat -tulnp | grep 9200

8.6 调整es的日志模板

template 去匹配模板

number_of_shards: 5, 调整分片
number_of_replicas: 0 调整副本级,因为单机就写成0了,生产一般是3副本,原数据一份,2份副本
curl -H "Content-Type:application/json" -XPUT http://10.4.7.12:9200/_template/k8s -d '{
  "template":"k8s",
  "index_patterns":["k8s"],
  "settings":{
     "number_of_shards":5,
     "number_of_replicas":0
   }
}'

8.7 说明

elasticsearch6.8.6本班依赖jdk是1.8版本

9.kafka搭建

jdss7-11机器上装kafka
使用版本2.2.0,不要超过2.2.0版本,kafka-manager这个工具最多支持到kafka到2.2.0版本

9.1 下载二进制包

[root@jdss7-11]# cd /opt/src/

[root@jdss7-11]# wget kafka_2.12-2.2.0.tgz 
[root@jdss7-11]# ln -s /opt/kafka-2.12-2.2.0 /opt/kafka

9.2 配置kafka

[root@jdss7-11]# mkdir -pv /data/kafka/logs
[root@jdss7-11]# vim config/server.properties
log.dir=/data/kafka/logs
zookeeper.connect=localhost:2181
log.flush.interval.messages=10000
log.flush.interval.ms=1000
delete.topic.enable=true
host.name=jdss7-11.host.com

9.3 启动kafka

bin/kafka-server-start.sh -daemon config/server.properties
ps aux | grep kafka 
netstat -tulnp # 发现用的是9092端口

9.4 安装kafka-manager的东西

yahoo开源的

  1. 可以使用dockerfile方式来安装
[root@jdss7-200]# mkdir -p /data/dockerfile/kafka-manager
[root@jdss7-200]# cd /data/dockerfile/kafka-manager;vim Dockerfile 
FROM haseeberget/scala-sbt

ENV ZK_HOSTS=10.4.7.11:2181 \
    KM_VERSION=2.0.0.2

RUN mkdir -p /tmp/ && \
    cd /tmp/ &7 \
    wget https://github.com/yahoo/kafka-manager/archive/${KM_VERSION}.tar.gz && \
    tar xf ${KM_VERSION}.tar.gz && \
    cd /tmp/kafka-manager-${KM_VERSION} && \
    sbt clean dist && \
    unzip -d / ./target/universal/kafka-manager-${KM_VERSION}.zip && \
    rm -fr /tmp/${KM_VERSION} /tmp/kafka-manager-${KM_VERSION}

WORKDIR /kafka-manager-${KM_VERSION}
EXPOSE 9000
ENTRYPOINT ["./bin/kafka-manager","-Dconfig.file=conf/application.conf"]

带web界面的东西,github上也有8.4k的star,

  1. 下载docker镜像(但是对kafka版本有要求)
    sheepkiller/kafka-manager

9.5 准备kafka-manager的资源配置清单,交付到k8s集群的infra命名空间里

kubectl scale deployment grafana --reeplicas=0 -n infra # 关掉grafana

dp.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: kafka-manager
  namespace: infra
  labels:
    name: kafka-manager
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kafka-manager     
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1    
  revisionHistoryLimit: 7
  progressDeadlineSeconds: 600  
  template:
    metadata:
      labels:
        app: kafka-manager
    spec:
      containers:
      - name: kafka-manager
        image: harbor.od.com/infra/kafka-manager:v2.0.0.2
        imagePullPolicy: Always
        ports:
        - containerPort: 9000
          protocol: TCP
        env:
        - name: ZK_HOSTS
          value: zk1.od.com:2181
        - name: APPLICATION_SECRET
          value: letmein        
      imagePullSecrets:
      - name: harbor
      terminationGracePeriodSeconds: 30
      securityContext:
        runAsUser: 0

svc.yaml

kind: Service
apiVersion: v1
metadata:
  name: kafka-manager
  namespace: infra
spec:
  selector:
    app: kafka-manager
  ports:
    - port: 9000
      targetPort: 9000
      protocol: TCP

ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kafka-manager
  namespace: infra
spec:
  rules:
  - host: km.od.com
    http:
      paths:
      - path: /
        backend:
          serviceName: kafka-manager
          servicePort: 9000

9.6 应用资源配置清单

kubeclt apply -f http://k8s-yaml.od.com/kafka-manager/dp.yaml
kubeclt apply -f http://k8s-yaml.od.com/kafka-manager/svc.yaml
kubeclt apply -f http://k8s-yaml.od.com/kafka-manager/ingress.yaml

9.7 验证


add Cluster

consumer_offsets

10.linux的top,load分析扩展

load average: 1min,5min,15min

4核核的cpu,load average中1分钟的,不超过8都是ok的,每个逻辑cpu上等待的任务不超过1个

11.制作filebeat底包并接入dubbo服务消费者


使用filebeat版本和elasticsearch版本建议一样,此处使用filebeat7.4.0
filebeat使用9200的http端口与kafka去通信

[root@jdss7-200]# cd /opt/src

11.1 编写Dockerfile

FROM debian:jessie
ENV FILEBEAT_VERSION=7.5.1 
ADD filebeat-7.5.1 /opt/filebeat-7.5.1
RUN set -x && \
    cd /opt && \
    cd filebeat-* && \
    cp filebeat /bin && \
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    apt-get update && \
    apt-get install vim lsof -y
ADD docker-entrypoint.sh /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]

entrypoint.sh

#!/bin/bash
ENV=${ENV:-"test"}
# 项目名,可能用到了kafka的topic上或者es的索引上
PROJ_NAME=${PROJ_NAME:-"no-define"}
# 多行匹配,java异常一大片,算1条,传递正则匹配的规则,以2位数字开头的就匹配上
MULTILINE=${MULTILINE:-"^\d(2)"}

cat > /etc/filebeat.yaml << EOF
filebeat.inputs:
- type: log
  fields_under_root: true
  fields:
    topic: logm-${PROJ_NAME}
  paths: # 多行匹配,用的比较多,一般都是这个
    - /logm/*.log
    - /logm/*/*.log
    - /logm/*/*/*.log
    - /logm/*/*/*/*.log
    - /logm/*/*/*/*/*.log
  scan_frequency: 120s
  max_bytes: 10485760
  multiline.pattern: $MULTILINE
  multiline.negate: true
  multiline.match: after
  multiline.max_lines: 100
- type: log
  fields_under_root: true
  fields:
    topic: logu-${PROJ_NAME}
  paths: # 单行匹配
    - /logu/*.log
    - /logu/*/*.log
    - /logu/*/*/*.log
    - /logu/*/*/*/*.log
    - /logu/*/*/*/*/*.log
    - /logu/*/*/*/*/*/*.log
logging.level: info
output.kafka:
  hosts: ["10.4.7.11:9092"]
  topic: k8s-fb-$ENV-%{[topic]} # fb是filebeat的意思
  version: 2.0.0 # kafka是2.2.0也要写2.0.0,只要是2版本以上就写2.0.0
  required_acks: 0
  max_message_bytes: 10485760
EOF

set -xe

if [[ "$1" == "" ]];then
  exec filebeat -c /etc/filebeat.yaml
else
  exec "$@"
fi

11.2 制作镜像

docker build . -t harbor.od.com/infra/filebeat:v7.5.1

12.让dubbo-demo-service的资源配置清单接入filebeat,变成边车模式运行

cd /data/k8s-yaml/dubbo-demo-consumer/
dp.yaml
关键配置

volumes:
- emptyDir: {} # 空目录的卷,宿主机上开辟一块空间,容器里挂载用,如果容器被销毁了,这个目录页没了
  name: logm

# 挂载
volumeMounts:
- mountPath: /opt/tomcat/logs
  name: logm


共享uts,net,user
不共享fs,ipc

重新应用资源配置清单

然后进filebeat的容器的/logm目录就可以看到consumer容器的日志,这两个container共享了日志目录;临时共享的一个池子,pod消失了,empty就没了.跟随pod的生命周期
共享了uts,所以hostname是一样的
隔离ipc,不能filebeat的容器里杀掉consumer的进程
隔离了fs,pid

kafka日志就有了

或者daemonSet一个node跑一个filebeat,一个计算节点上所有日志都靠它

12.部署logstash

logstash从kafka中拉取数据出来,然后写到es中去
版本对应关系

准备6.8.6版本的logstash

[root@jdss7-200]# docker pull logstash:6.8.6
[root@jdss7-200]# docker images | grep logstash
[root@jdss7-200]# docker tag xxxxxxx harbor.od.com/infra/logstash:v6.8.6
[root@jdss7-200]# docker push harbor.od.com/infra/logstash:v6.8.6

测试环境起一个logstash,生产环境起一个

12.1 logstash的配置

input {
  kafka {
    bootstrap_servers => "10.4.7.11:9092"
    client_id => "10.4.7.200"
    consumer_threads => 4
    group_id => "k8s_test"
    topic_pattern => "k8s-fb-test-.*"
  }
}

filter {
  json {
    source => "message"
  }
}

output {
  elasticsearch {
    host => ["10.4.7.12:9200"]
    index => "k8s-test-$(+YYYY.MM.DD)"
  }
}

12.2 创建配置文件,然后docker挂载进去

mkdir -p /etc/logstash
vim /etc/logstash/logstash-test.conf
input {
  kafka {
    bootstrap_servers => "10.4.7.11:9092"
    client_id => "10.4.7.200"
    consumer_threads => 4
    group_id => "k8s_test"
    topics_pattern => "k8s-fb-test-.*"
  }
}

filter {
  json {
    source => "message"
  }
}

output {
  elasticsearch {
    hosts => ["10.4.7.12:9200"]
    index => "k8s-test-%{+YYYY.MM.DD}"
  }
}
vim /etc/logstash/logstash-prod.conf
input {
  kafka {
    bootstrap_servers => "10.4.7.11:9092"
    client_id => "10.4.7.200"
    consumer_threads => 4
    group_id => "prod"
    topics_pattern => "k8s-fb-prod-.*"
  }
}

filter {
  json {
    source => "message"
  }
}

output {
  elasticsearch {
    hosts => ["10.4.7.12:9200"]
    index => "k8s-prod-%{+YYYY.MM.DD}"
  }
}

裸docker启动logstash

docker run -d --name logstash-test -v /etc/logstash(宿主机):/etc/logstash(容器里) harbor.od.com/infra/logstash:v6.8.6 -f /etc/logstash/logstash-test.conf
# -f 是指定配置文件

12.3 去es里看有数据没有

13.部署kibana

nodejs写的纯前端项目

13.1 准备镜像

[root@jdss7-200]# docker pull kibana:6.8.6
[root@jdss7-200]# docker tag xxxx harbor.od.com/infra/kibana:v6.8.6
[root@jdss7-200]# docker push harbor.od.com/infra/kibana:v6.8.6

13.2 准备资源配置清单

dp.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: kibana
  namespace: infra
  labels:
    name: kibana
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kibana
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1    
  revisionHistoryLimit: 7
  progressDeadlineSeconds: 600  
  template:
    metadata:
      labels:
        app: kibana
    spec:
      containers:
      - name: kafka-manager
        image: harbor.od.com/infra/kibana:v6.8.6
        imagePullPolicy: Always
        ports:
        - containerPort: 5601
          protocol: TCP
        env:
        - name: ELASTICSEARCH_URL
          value: http://10.4.7.12:9200        
      imagePullSecrets:
      - name: harbor
      securityContext:
        runAsUser: 0

svc.yaml

kind: Service
apiVersdion: v1
metadata:
  name: kibana
  namespace: infra
spec:
  selector:
    app: kibana
  ports:
    - port: 5601
      targetPort: 5601
      protocol: TCP

ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kibana
  namespace: infra
spec:
  rules:
  - host: kibana.od.com
    http:
      paths:
      - path: /
        backend:
          serviceName: kibana
          servicePort: 5601

13.3 可以看到Monitoring

13.4 manager,看index-patterns


next

create index pattern
然后Discover就能看到日志了

配置index(Managements -> index patterns -> create index pattern)

14.扩展知识

kafka里面可以分partion,分了partion后可以起多个logstash
可以让logstash1去消费k8s-prod-message的1,2,3分区
可以让logstash2去消费k8s-prod-message的4,5,6分区
可以起多个logstash去消费topic

15.Kibana的用法

给测试和开发使的
kibana有4个选择器

  1. 时间选择器

  2. 环境选择器

  3. 项目选择器


    topic is 指定的是filebeat里指定的环境变量

  4. 关键字选择器

message,log.file.path,host.name
搜索实验,应用的是lucene的查询预发

16.扩展

直接k8s起来的应用程序,控制台输出的日志如何filebeat收集,走elk


重新docker build . -t harbor.od.com/base/jre8:8u112_with_logs
做一个底包带日志文件的,然后改jenkins中的build parameters

17.作业

spinniker了解
提供的软件包,10个镜像都load进harbor仓库里

posted @ 2022-04-20 19:02  SpecialSpeculator  阅读(256)  评论(0编辑  收藏  举报