技术漫谈 |通过Kustomize配置sidecar方式的日志收集

栏目: IT技术 · 发布时间: 3年前

内容简介:本文简单介绍了Kubernetes中收集pod日志的几种方案,然后通过ECK快速搭建起一套日志系统,实现了本文介绍的第一种日志方案。在实现第二种日志方案时,我们引入了Kustomize这个k8s专用的配置管理工具,将应用本身的部署文件和sidecar日志容器的相关配置分离开来,使k8s的部署配置文件易于维护。对于K8S集群中pod日志的收集,一般有三种解决方案:1)在Node上部署一个日志收集程序:也就是在node级别进行日志收集。一般使用DaemonSet部署在每个node中。这种方式优点是耗费资源少,因

本文简单介绍了Kubernetes中收集pod日志的几种方案,然后通过ECK快速搭建起一套日志系统,实现了本文介绍的第一种日志方案。在实现第二种日志方案时,我们引入了Kustomize这个k8s专用的配置管理工具,将应用本身的部署文件和sidecar日志容器的相关配置分离开来,使k8s的部署配置文件易于维护。

一、Kubernetes收集pod日志的方案

对于K8S集群中pod日志的收集,一般有三种解决方案:

1)在Node上部署一个日志收集程序:也就是在node级别进行日志收集。一般使用DaemonSet部署在每个node中。这种方式优点是耗费资源少,因为只需部署在节点,且对应用无侵入。缺点是只适合容器内应用日志必须都是标准输出。

技术漫谈 |通过Kustomize配置sidecar方式的日志收集

2)在pod中附加专用日志收集的容器:也就是在pod中跟随应用容器起一个日志处理容器,一种是直接将应用容器的日志收集并输出到标准输出(叫做Streaming sidecar container),如下图:

技术漫谈 |通过Kustomize配置sidecar方式的日志收集

还有一种是将应用容器日志直接输出到日志收集后端,也就是每一个pod中都起一个日志收集agent(比如filebeat)。如下图:

技术漫谈 |通过Kustomize配置sidecar方式的日志收集

这种方式的优点是可以收集多种形式的日志(比如文件,socket等),缺点是耗费资源较多,每个pod都要起一个日志收集容器。

3)应用程序直接推送日志:这种方式应用直接将日志推送到存储后端:

技术漫谈 |通过Kustomize配置sidecar方式的日志收集

这种方式的优点是无需额外的日志收集工具,缺点是需要侵入应用,增加应用的配置复杂度。

在下文我们同时实现了第一种和第二种sidecar container with a logging agent方案。

第一种方案我们通过ECK( https://www.elastic.co/cn/elastic-cloud-kubernetes )搭建起es集群和kibana UI,通过fluentd将pod标准输出的日志收集到es集群中,同时fluentd对接K8S的apiserver自动给日志添加元数据信息,使我们非常方便地分辨日志来自于哪个pod。但是如果应用本身将日志输出到容器的内部,并且我们需要定制化日志收集程序的配置,比如合并多行日志时,第一种日志方案便无能为力了。

这时,我们可以通过第二种日志方案,以sidecar的方式将日志收集到es当中,并且可以自由配置容器收集工具,来实现各种高级日志功能。我们在配置sidecar容器收集 工具 时,使用了Kustomize工具,来将应用本身的部署文件和sidecar日志容器的相关配置分离开来,实现了分离关注点,使相关信息配置文件更加清晰,易于维护。

二、通过ECK快速部署EFK日志系统

下面我们首先通过ECK部署es+kibana+fluned。您可以使用breeze( https://github.com/wise2c-devops/breeze )里的ECK组件来部署,也可以参考ECK官网上的文档来进行部署。这里我们给出部署所需的yaml文件,您只需apply这些文件即可完成EFK日志收集系统的快速搭建。

1、安装ECK的crd,RBAC规则及eck-operator:

kubectl apply -f https://download.elastic.co/downloads/eck/1.1.2/all-in-one.yaml

在安装过程中可以查看eck-operator的日志,来确认其是否启动正常:

kubectl -n elastic-system logs -f statefulset.apps/elastic-operator

2、部署es集群:

cat <<EOF | kubectl apply -f -

apiVersion: elasticsearch.k8s.elastic.co/v1beta1

kind: Elasticsearch

metadata:

name: quickstart

spec:

version: 7.8.0

http:

tls:

  selfSignedCertificate:

    disabled: true

nodeSets:

- name: default

count: 3

config:

  node.master: true

  node.data: true

  node.ingest: true

  node.store.allow_mmap: false

podTemplate:

  spec:

    volumes:

    - name: elasticsearch-data

      emptyDir: {}

EOF

上面的命令会部署起一个3节点的es集群,不过存储是使用的emptyDir的方式,在pod被删除后,其数据也会一起被删除,所以这种方式是用于测试环境快速搭建es集群。集群搭建好后,可以通过如下命令获取es的elastic用户的密码:

kubectl get secret quickstart-es-elastic-user -o=jsonpath='{.data.elastic}' | base64 --decode; echo

此密码也可以用于后面搭建的kibana页面的登录。

3、部署kibana:

cat <<EOF | kubectl apply -f -

apiVersion: kibana.k8s.elastic.co/v1beta1

kind: Kibana

metadata:

name: quickstart

spec:

version: 7.8.0

http:

tls:

  selfSignedCertificate:

    disabled: true

count: 1

elasticsearchRef:

name: quickstart

EOF

可以通过如下命令获取到访问kibana的ClusterIp:

kubectl get service quickstart-kb-http

您可以edit上述service将其改为NodePort的方式,从而可以通过NodePort的端口访问到kibana的web页面,用户名密码在上一步已经获取。

4、部署flunetd:

cat <<EOF | kubectl apply -f -

apiVersion: v1

kind: ServiceAccount

metadata:

name: fluentd

namespace: kube-system

apiVersion: rbac.authorization.k8s.io/v1beta1

kind: ClusterRole

metadata:

name: fluentd

namespace: kube-system

rules:

- apiGroups:

- ""

resources:

- pods

- namespaces

verbs:

- get

- list

- watch

kind: ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1beta1

metadata:

name: fluentd

roleRef:

kind: ClusterRole

name: fluentd

apiGroup: rbac.authorization.k8s.io

subjects:

- kind: ServiceAccount

name: fluentd

namespace: kube-system

apiVersion: apps/v1

kind: DaemonSet

metadata:

name: fluentd

namespace: kube-system

labels:

k8s-app: fluentd-logging

version: v1

spec:

selector:

matchLabels:

k8s-app: fluentd-logging

version: v1

template:

metadata:

labels:

k8s-app: fluentd-logging

version: v1

spec:

serviceAccount: fluentd

serviceAccountName: fluentd

tolerations:

- key: node-role.kubernetes.io/master

effect: NoSchedule

containers:

- name: fluentd

image: 192.168.206.156/library/fluentd-kubernetes-daemonset:v1-debian-elasticsearch

env:

- name:  FLUENT_ELASTICSEARCH_HOST

value: "quickstart-es-http.default.svc.cluster.local"

- name:  FLUENT_ELASTICSEARCH_PORT

value: "9200"

- name: FLUENT_ELASTICSEARCH_SCHEME

value: "http"

- name: FLUENT_ELASTICSEARCH_USER

value: "elastic"

- name: FLUENT_ELASTICSEARCH_PASSWORD

value: "change-to-your-elstic-users-password"

resources:

limits:

memory: 200Mi

requests:

cpu: 100m

memory: 200Mi

volumeMounts:

- name: varlog

mountPath: /var/log

- name: varlibdockercontainers

mountPath: /var/lib/docker/containers

readOnly: true

terminationGracePeriodSeconds: 30

volumes:

- name: varlog

hostPath:

path: /var/log

- name: varlibdockercontainers

hostPath:

path: /var/lib/docker/containers

EOF

部署fluentd时只需注意将上述yaml文件里的FLUENT_ELASTICSEARCH_PASSWORD的值修改为您es集群里实际的密码。

这样搭建起来的日志系统便实现了我们日志方案一。下面我们来实现第二种sidecar container with a logging agent的方案。在实现此方案时,我们引入了Kustomize这个工具来管理相关的yaml文件,首先我们简单了解一下Kustomize。

三、Kustomize是什么?

如果您想在Kubernetes 集群中部署应用,您可能会拷贝一些包含Kubernetes API对象的YAML文件,并且根据需求来修改这些文件,通过这些YAML文件来定义Kubernetes配置。

在Kustomize出现之前,Kubernetes管理应用的方式主要是通Helm或者上层Paas来完成。这些工具通常通过特定领域配置语言(DSL,如Go template、jsonnet)来维护并管理应用,并且需要参数化模板方式(如helm)来自定义配置,这需要学习复杂的DSL语法极其容易出错。

Kustomize工具提供了一个全新的、纯粹的声明式的方法来定制kubernetes配置,遵循并利用我们熟悉且精心设计的Kubernetes API。Kustomize是Kubernetes原生的配置管理工具,以无模板方式来定制应用的配置。它使用k8s原生概念帮助创建并复用资源配置(YAML),允许用户以一个应用描述文件(YAML文件)为基础(Base YAML),然后通过Overlay的方式生成最终部署应用所需的描述文件。

四、Kustomize 解决了什么痛点?

一般应用都会存在多套部署环境:开发环境、测试环境、生产环境,多套环境意味着存在多套K8S应用资源YAML。而这么多套YAML之间只存在微小配置差异,比如镜像版本不同、Label不同等,而这些不同环境下的YAML经常会因为人为疏忽导致配置错误。再者,多套环境的YAML维护通常是通过把一个环境下的YAML拷贝出来然后对差异的地方进行修改。Kustomize通过以下几种方式解决了上述问题:

  • Kustomize通过Base & Overlays方式方式维护不同环境的应用配置。
  • Kustomize使用patch方式复用Base配置,并在Overlay描述与Base应用配置的差异部分来实现资源复用。
  • Kustomize管理的都是Kubernetes原生YAML文件,不需要学习额外的DSL语法。

五、通过Kustomize实现filebeat sidecar配置

关于Kustomize的简单教程,网上有很多,我们这里不再重复,您可以参考官方的helloWorld教程来实际操作一下。下面我们就来通过Kustomize实现filebeat sidecar的配置。

1、首先创建一个工作空间:

mkdir demo

cd demo

2、创建用于保存应用部署文件的目录,命名为base,并在里面放置实际应用的部署文件,这里我们只放置一个最简单的deployment文件:

mkdir base

cat > base/deploy.yaml << EOF

apiVersion: apps/v1

kind: Deployment

metadata:

labels:

app: configserver

name: configserver

spec:

replicas: 1

selector:

matchLabels:

  app: configserver

template:

metadata:

  labels:

    app: configserver

spec:

  containers:

  - image: registry.cn-shenzhen.aliyuncs.com/wangyijie/configserver:v1

    name: configserver

    ports:

    - containerPort: 8080

    args:

    - java

    - -Dspring.cloud.config.server.git.uri=https://gitee.com/wise2c-wangyijie/config-repo.git

    - -Dlogging.file.name=/tmp/configserver.log

    - -jar

    - /configserver.jar

    volumeMounts:

    - name: log-volume

      mountPath: /tmp

  volumes:

  - name: log-volume

    emptyDir: {}

EOF

可以看到,这就是一个 java 的应用程序,在实际的情况下,您的应用可能还需创建service,configmap等k8s对象组成一个更加完整的应用。此应用将日志输出到了pod容器内部的/tmp目录中。在这个deploy文件中,没有任何关于filebeat sidecar的配置信息。

接下来创建Kustomize的配置文件:

cat > base/kustomization.yaml << EOF

resources:

- deploy.yaml

EOF

文件内容非常简单,就2行,指定了该目录下的资源配置文件。

3、创建用于保存filebeat sidecar部署及配置文件的目录,命名为filebeat-sidecar,并在里面放置filebeat的deployment及filebeat的配置文件:

mkdir filebeat-sidecar

cat >filebeat-sidecar/sidecar.yaml<< EOF

apiVersion: apps/v1

kind: Deployment

metadata:

name: configserver

spec:

template:

spec:

  containers:

  - name: filebeat

    image: docker.elastic.co/beats/filebeat:7.8.0

    args: [

"-c", "/etc/filebeat/filebeat.yml",

"-e",

    ]

    env:

    - name: POD_NAME

      valueFrom:

        fieldRef:

          fieldPath: metadata.name

    - name: POD_NAMESPACE

      valueFrom:

        fieldRef:

          fieldPath: metadata.namespace

    - name: POD_NODENAME

      valueFrom:

        fieldRef:

          fieldPath: spec.nodeName

    volumeMounts:

    - mountPath: /tmp

      name: log-volume

    - name: config-vol

      mountPath: /etc/filebeat     

  volumes:

  - name: log-volume

    emptyDir: {}

  - name: config-vol

    configMap: 

      name: filebeat-configmap

EOF

这个deploy通过downward api取到了其所在pod的元数据信息,添加到了pod的环境变量当中;另外pod也通过一个叫做filebeat-configmap的configmap保存filebeat的配置信息(配置文件稍后给出),该配置使filebeat其从emptyDir类型存储卷的/tmp目录来获取日志,下面给出此配置文件:

cat >filebeat-sidecar/filebeat.yml<< EOF

filebeat.inputs:

- type: log

paths: 

- /tmp/*.log

fields: 

podname: '${POD_NAME:}'

podnamespace: '${POD_NAMESPACE:}'

podnodename: '${POD_NODENAME:}'



output.elasticsearch:

hosts: ['quickstart-es-http:9200']

username: 'elastic'

password: 'change-to-your-elstic-users-password'

EOF

配置文件也很简单,它从/tmp目录下取得所有以.log结尾的文件的日志;并且给日志添加了fields的信息,标明日志是从哪个namespace的哪个pod下获取的;最后将日志输出到了我们在第二部分搭建的es集群当中。

最后给出Kustomize的配置文件:

cat >filebeat-sidecar/kustomization.yaml<< EOF

bases:

- ../base

patchesStrategicMerge:

- sidecar.yaml

configMapGenerator:

- name: filebeat-configmap

files:

- filebeat.yml

EOF

此配置文件,通过patchesStrategicMerge策略,将此目录下的sidecar.yaml的deployment和base目录下的相同名称的deployment对象合并,生成一个带sidecar容器的deployment;另外通过configmapGenerator,生成了一个configmap,供deploy使用。

通过tree demo/命令查看当前的目录结构,如下:

demo/

├── base

│   ├── deploy.yaml

│   └── kustomization.yaml

└── filebeat-sidecar

├── filebeat.yml

├── kustomization.yaml

└── sidecar.yaml

我们可以通过kubectl kustomize filebeat-sidecar/ 命令查看生成后yaml文件,结果如下(结果做了省略):

apiVersion: v1

kind: ConfigMap

metadata:   

name: filebeat-configmap-7dtkh7km6k

...

apiVersion: apps/v1

kind: Deployment

metadata:

labels:

app: configserver

name: configserver

spec:

...

template:

...

spec:

...

volumes:

- emptyDir: {}

name: log-volume

- configMap:

name: filebeat-configmap-7dtkh7km6k

name: config-vol

我们发现,生成的合并后的yaml文件里,configmap的名称被自动添加了一个哈希后缀,这样实现的目的是ConfigMap中的更改将导致哈希值更改和滚动更新。

我们可以直接通过kubectl apply -k filebeat-sidecar/ 命令来将这个生成的yaml提交到k8s当中。可以看到,filebeat已经将应用日志收集到了es当中:

技术漫谈 |通过Kustomize配置sidecar方式的日志收集

下面我们来修改一下filebeat.yml这个配置文件,添加合并多行日志的配置,修改后的配置文件如下:

cat >filebeat-sidecar/filebeat.yml

filebeat.inputs:

- type: log

paths: 

- /tmp/*.log

fields: 

podname: '${POD_NAME:}'

podnamespace: '${POD_NAMESPACE:}'

podnodename: '${POD_NODENAME:}'

multiline.pattern: '^\d{4}-\d{1,2}-\d{1,2}'

multiline.negate: true

multiline.match: after

multiline.timeout: 10s  



output.elasticsearch:

hosts: ['quickstart-es-http:9200']

username: 'elastic'

password: 'change-to-your-elstic-users-password'

再通过kubectl kustomize filebeat-sidecar/ 命令重新查看一下生成的yaml文件,发现configmap名称的hash后缀发生了变动:

apiVersion: v1

kind: ConfigMap

metadata:

name: filebeat-configmap-tm9867k666

...

apiVersion: apps/v1

kind: Deployment

metadata:

...

name: configserver

...

volumes:

- emptyDir: {}

name: log-volume

- configMap:

name: filebeat-configmap-tm9867k666

name: config-vol

这时再从新执行kubectl apply -k filebeat-sidecar/ 命令,便会创建一个新的configmap,同时触发deployment的滚动更新。

如果新的配置不符合要求,可以通过kubectl rollout undo deploy/configserver 命令来回滚到之前的配置,不过此时filebeat-sidecar/filebeat.yml这个配置文件还需要手动还原到之前的配置。或者我们不使用回滚命令,只修改filebeat-sidecar/filebeat.yml配置文件,然后一直使用kubectl apply -k filebeat-sidecar/命令,使deployment一直和最新的配置保持一致。

通过上面的demo可以看出,我们将应用的部署文件与filebeat的部署配置分成了两个独立的部分,使配置文件更加清晰,易于管理。如果我们想替换filebeat,使用fluentbit作为收集日志的sidecar的logging agent,我们只需要仿照filebeat的方式,再创建一个新的fluentbit-sidecar的文件夹,在里面添加修改fluentbit的部署配置文件,而无需对原有应用的部署文件做任何修改。

当然,如果您的应用将日志写到了容器内部的文件当中,同时对应用日志没有过于复杂的需求,只需要把应用日志收集到es里,可以使用本文第二种方案的Streaming sidecar container的方式,部署一个sidecar容器,将输出到容器内的日志文件读到sidecar容器的标准输出,这时EFK的日志系统就会收集到标准输出的日志,同时也会自动添加日志的元数据信息,这样就省略了filebeat或fluentbit的配置,更加简洁。

原创作者:杨冬

原文链接: https://mp.weixin.qq.com/s/0k018a3MDzl-v4S3DLeIww

关于睿云智合

深圳睿云智合科技有限公司成立于2012年,总部位于深圳。早期专注于为中国金融保险等大型企业提供创新技术、电子商务、CRM等领域专业咨询服务。核心骨干人员全部为来自金融、科技行业知名企业资深业务和技术专家。

自2016年始,睿云智合率先将容器技术引进到中国保险行业客户,此后,公司组建了专业的云原生技术产品研发和实施服务团队,以自主可控与开源技术的融合为产品设计宗旨,不断深耕软件定义和云原生领域创新技术以及国内企业数字化转型服务市场。并分别在成都、深圳设立了研发中心,在北京、上海设立了分支机构。旨在帮助中国企业客户将云原生趋势技术应用于企业新一代IT架构数字化底座的建设,并与生态合作伙伴一起为企业客户提供云原生数字化底座衍生出的PaaS云平台、工业互联网、大数据中心、AI机器学习平台以及区块链BaaS平台等解决方案的落地。为企业数字化转型以及业务发展赋能。

此外,凭借多年来在呼叫中心领域的业务经验与技术积累,睿云智合率先在业界推出基于开源软交换技术的微服务架构多媒体数字化业务平台,将语音、视频、webchat、微信、微博等多种客户接触渠道集成,实现客户统一接入、精准识别、智能路由的CRM策略,并通过容器化治理方式来支持平台的全生命周期管理,显著提升了数字化业务处理的灵活、高效、弹性、稳定等特性。

睿云智合是 Linux 与CNCF云原生基金会会员,是全球首批Kuberentes官方认证服务提供商 (KCSP),也是Kubernetes官方认证平台产品提供商。睿云智合依托趋势IT技术为企业客户的平台赋能数字化转型战略提供了包括产品、技术服务、咨询、培训等服务。通过数字化底座+行业解决方案为全国金融、政企、医疗、运营商、制造、能源、教育以及互联网等各个行业企业和用户打造一个全面感知、可靠传输、智能处理、精准决策的产业能力底座。帮助企业客户打通数据链接,加速业务创新,赋能产业竞争力。


以上所述就是小编给大家介绍的《技术漫谈 |通过Kustomize配置sidecar方式的日志收集》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Don't Make Me Think

Don't Make Me Think

Steve Krug / New Riders Press / 18 August, 2005 / $35.00

Five years and more than 100,000 copies after it was first published, it's hard to imagine anyone working in Web design who hasn't read Steve Krug's "instant classic" on Web usability, but people are ......一起来看看 《Don't Make Me Think》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试