kubernetes生态--ELK服务

elk是一套收集搜索展示日志的一套服务,

架构:

 

 

优化后的架构:更适合k8s集群,使用topic区分服务,使用index-patterm区分环境(prod,test)

将filebeat使用边车模式与容器绑定到一起,中间采用kafka来做异步。

 

 

改造项目,将我们原来的dubbo-demo-consumer改造成tomcat项目,然后交付tomcat到k8s:

下载tomcat:

# wget http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.50/bin/apache-tomcat-8.5.50.tar.gz

准备制作dockerfile:

# mkdir /data/dockerfile/tomcat
# tar -zxf apache-tomcat-8.5.50.tar.gz -C /data/dockerfile/tomcat/
# cd /data/dockerfile/tomcat
# vim 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/ /opt/tomcat
ADD config.yml /opt/prom/config.yml
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"]

优化一下tomcat:

1、关闭tomcat与apache前端通信的端口:

# vi /data/dockerfile/tomcat/apache-tomcat-8.5.50/conf/server.xml

 

 2、关闭无用的日志:

# vim /data/dockerfile/tomcat/apache-tomcat-8.5.50/conf/logging.properties

删除handle:

找到handlers,删除后面的3跟4

 

 

注释掉下面的:

 

 将其他的日志level修改为:INFO

根据上面的dockerfile准备相关的文件:

jmx_javaagent-0.3.1.jar  --之前在部署jre8的底包镜像时候,已经下载过了,直接拿过来用
entrypoint.sh

config.yml
 

 entrypoint.sh

#!/bin/bash
M_OPTS="-Duser.timezone=Asia/Shanghai -javaagent:/opt/prom/jmx_javaagent-0.3.1.jar=$(hostname -i):${M_PORT:-"12346"}:/opt/prom/config.yml"
C_OPTS=${C_OPTS}
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

config.yml

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

制作docker镜像:

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

 

在jenkins上添加适用tomcat的流水线项目:

 

 

执行build

 

 

 

 启动test和prod上的apollo服务,修改之前dubbo-demo-consumer项目的资源配置清单:将镜像修改为tomcat那版镜像

 

 

 然后启动dubbo-demo-service和dubbo-demo-consumer

 

 

 

tomcat启动的dubbo-demo-web服务已经起来了。

部署elasticsearch:

由于elasticsearch是有状态服务,所以采用二进制方式部署:由于资源有限,我们部署单节点,部署到7-12上

elastic 官方地址

建议所有组件版本用一致的版本:

我们这里使用6.8.6版本:

# cd /opt/src
# wget  https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.8.6.tar.gz
# tar -zxf elasticsearch-6.8.6.tar.gz -C /opt/
# ln -s /opt/elasticsearch-6.8.6/ /opt/elasticsearch

配置elastic:

创建存储数据和日志的目录:

# mkdir -p /data/elasticsearch/{data,logs}
#修改配置文件,将以下配置进行修改。其他不动
# vi config/elasticsearch.yml
cluster.name: es.od.com
node.name: hdss7-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

优化ES JVM:生产环境建议最大不要超过32G。

# vi config/jvm.options

 

 创建es用户:-M参数为不创建家目录。

# useradd -s /bin/bash -M es
# chown -R  es.es /opt/elasticsearch-6.8.6/
# chown -R es.es /data/elasticsearch/

调整文件描述符配置:

# vi /etc/security/limits.d/es.conf
es hard nofile 65536
es soft fsize unlimited
es hard memlock unlimited
es soft memlock unlimited

调整内核参数:

参数说明:限制一个进程可以拥有的VMA(虚拟内存区域)的数量。虚拟内存区域是一个连续的虚拟地址空间区域。在进程的生命周期中,每当程序尝试在内存中映射文件,链接到共享内存段,或者分配堆空间的时候,这些区域将被创建。调优这个值将限制进程可拥有VMA的数量。限制一个进程拥有VMA的总数可能导致应用程序出错,因为当进程达到了VMA上线但又只能释放少量的内存给其他的内核进程使用时,操作系统会抛出内存不足的错误。如果你的操作系统在NORMAL区域仅占用少量的内存,那么调低这个值可以帮助释放内存给内核用。

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

启动es:

# su -c "/opt/elasticsearch/bin/elasticsearch -d" es
# netstat -lntp | grep 9200

 

 调整es日志模板,由于我们没有只有一个节点,所以我们将replicas调整为0

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
  }
}'

部署kafka:官方地址

版本建议不要超过2.2.0,因为我们要部署的kafka-manager最高支持到2.2.0,部署到7-11上

# cd /opt/src
# wget https://archive.apache.org/dist/kafka/2.2.0/kafka_2.12-2.2.0.tgz
# tar -zxf kafka_2.12-2.2.0.tgz -C /opt/
# ln -s /opt/kafka_2.12-2.2.0/ /opt/kafka

配置kafka:

# mkdir -p /data/kafka/logs
# vi config/server.properties

修改以下配置:

log.dirs=/data/kafka/logs
zookeeper.connect=localhost:2181
log.flush.interval.messages=10000
log.flush.interval.ms=1000

添加以下配置:

delete.topic.enable=true
host.name=hdss7-11.host.com

启动kafka:

# bin/kafka-server-start.sh -daemon config/server.properties

 

交付kafka-manager到k8s,kafka-web管理工具:github地址

介绍两种部署方法:

1、自己制作dockerfile:我们使用这种方法

# mkdir /data/dockerfile/kafka-manager
# cd /data/dockerfile/kafka-manager
# vi Dockerfil

 

FROM hseeberger/scala-sbt

ENV ZK_HOSTS=10.4.7.11:2181 \
     KM_VERSION=2.0.0.2

RUN mkdir -p /tmp && \
    cd /tmp && \
    wget https://github.com/yahoo/kafka-manager/archive/${KM_VERSION}.tar.gz && \
    tar xxf ${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"]
# docker build . -t harbor.od.com/public/kafka-manager:v2.0.0.2

2、直接下载docker镜像:docker地址

 

不论使用哪种方法,制作完docker镜像后,上传到自己的私有仓库中:

# docker push harbor.od.com/infra/kafka-manager:v2.0.0.2

 

制作资源配置清单:

1、dp.yaml

# cd /data/k8s-yaml/
# mkdir kafka-manager
# vi 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: IfNotPresent
        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

 

2、svc.yaml

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

 

3、ingress.yaml

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

添加域名解析:

 

 

 应用资源配置清单:

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

等待容器起来以后,访问km.od.com:

 

 

 

 配置kafka:

 

 

 其他默认就可以。

 

以边车模式交付filebeat到k8s,绑定到dubbo-demo-web的pod上:

filebeat 官方地址

制作dockerfile:红色部门是官网对应版本的sha的值

 

 

 

# mkdir /data/dockerfile/filebeat
# cd /data/dockerfile/filebeat
# vi Dockerfile
FROM debian:jessie

ENV FILEBEAT_VERSION=7.5.1 \
    FILEBEAT_SHA1=daf1a5e905c415daf68a8192a069f913a1d48e2c79e270da118385ba12a93aaa91bda4953c3402a6f0abf1c177f7bcc916a70bcac41977f69a6566565a8fae9c 

RUN set -x && \
  apt-get update && \
  apt-get install -y wget && \
  wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-${FILEBEAT_VERSION}-linux-x86_64.tar.gz -O /opt/filebeat.tar.gz && \
  cd /opt && \
  echo "${FILEBEAT_SHA1}  filebeat.tar.gz" | sha512sum -c - && \
  tar xzvf filebeat.tar.gz && \
  cd filebeat-* && \
  cp filebeat /bin && \
  cd /opt && \
  rm -rf filebeat* && \
  apt-get purge -y wget && \
  apt-get autoremove -y && \
  apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

COPY docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]

制作docker-entrypoint.sh:

#!/bin/bash

ENV=${ENV:-"test"}  #环境,默认是test
PROJ_NAME=${PROJ_NAME:-"no-define"} 
MULTILINE=${MULTILINE:-"^\d{2}"}  #  匹配日志中,两位数字开头的才算是新的一行,比如java报错后,会产生很多行,这个配置就是要求匹配到2位数字开头后,到下一个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'   #指定了logm这个路径下的日志,需要做多行匹配,指定了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
output.kafka:
  hosts: ["10.4.7.11:9092"]
  topic: k8s-fb-$ENV-%{[topic]}
  version: 2.0.0
  required_acks: 0
  max_message_bytes: 10485760
EOF

set -xe

# If user don't provide any command
# Run filebeat
if [[ "$1" == "" ]]; then
     exec filebeat  -c /etc/filebeat.yaml 
else
    # Else allow the user to run arbitrarily commands like bash
    exec "$@"
fi
# chmod u+x docker-entrypoint.sh

build镜像:

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

 

修改test环境的dubbo-demo-consumer的dp.yaml

# vi /data/k8s-yaml/test/dubbo-demo-consumer/dp.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: dubbo-demo-consumer
  namespace: test
  labels: 
    name: dubbo-demo-consumer
spec:
  replicas: 1
  selector:
    matchLabels: 
      name: dubbo-demo-consumer
  template:
    metadata:
      labels: 
        app: dubbo-demo-consumer
        name: dubbo-demo-consumer
    spec:
      containers:
      - name: dubbo-demo-consumer
        image: harbor.od.com/app/dubbo-demo-web:tomcat_191226_1611
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
          protocol: TCP
        env:
        - name: C_OPTS
          value: -Denv=fat -Dapollo.meta=http://apollo-configservice:8080
        volumeMounts:
        - mountPath: /opt/tomcat/logs
          name: logm
      - name: filebeat
        image: harbor.od.com/infra/filebeat:v7.5.1
        imagePullPolicy: IfNotPresent
        env:
        - name: ENV
          value: test
        - name: PROJ_NAME
          value: dubbo-demo-web
        volumeMounts:
        - mountPath: /logm
          name: logm
      volumes:
      - emptyDir: {}
        name: logm
      imagePullSecrets:
      - name: harbor
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      securityContext: 
        runAsUser: 0
      schedulerName: default-scheduler
  strategy:
    type: RollingUpdate
    rollingUpdate: 
      maxUnavailable: 1
      maxSurge: 1
  revisionHistoryLimit: 7
  progressDeadlineSeconds: 600

 

emptyDir是在宿主机上随机创建一个空目录,挂载到容器中的logm目录,随容器运行,随容器销毁。

 

这里设置了两个变量,传递到docker-entrypoint.sh里

 

 

 

下面这种运行方式,就是边车模式:

接下来看数据卷的挂载,首先声明了一个emptyDir的数据卷logm,

然后将这个logm挂载到了dubbo-demo-consumer的/opt/tomcat/logs目录下,并且在filebeat里,也挂载了这个logm到“/”目录下的logm

这样就解决了日志重复写两遍的问题,我们在filebeat容器里,能直接看到并收集tomcat/logs/logm/下面的日志了。

 

 

应用资源配置清单:

# kubectl apply -f http://k8s-yaml.od.com/test/dubbo-demo-consumer/dp.yaml

 

 

这里运行了两个容器,以边车模式在运行。

进入filebeat容器:

 

可以直接查看到tomcat的日志:

 

 这样filebeat就可以直接收集tomcat日志。

边车模式下,两个容器会共享以下系统资源:

NET网络名称空间,UTS命名空间,USER

 

posted @ 2019-12-25 18:02  slim_liu  阅读(224)  评论(0编辑  收藏  举报