Kubernetes-蔚来汽车的Kubernetes实践

【编者的话】Kubernetes已经成为当下最火热的一门技术,未来一定也会有更好的发展,围绕着云原生的周边产物也越来越多,使得上云更加便利更加有意义,本文主要讲解一些蔚来汽车从传统应用落地到Kubernetes集群的一些实践经验,提供给大家在落地之前的一些思考和注意点,并且让大家在实施的时候能够有一些借鉴,提供一些使用过程中的注意事项。

项目背景

Docker诞生于2013年初,随着时间的推移Docker项目也逐渐火热起来,也形成了自己的生态,为了能够灵活调度容器,编排技术也变得非常重要,Swarm,Mesos,Kubernetes属于比较出众的容器编排技术,然而不得不说Kubernetes绝对是当下最火热的技术。Kubernetes项目的基础特性,并不是几个工程师突然“拍脑袋”想出来的东西,而是Google公司在容器化基础设施领域多年来实践经验的沉淀与升华,容器编排使得容器本身也有了生命,几乎所有大公司都在使用Kubernetes,另外云原生周边也发展的越来越好,这使得Kubernetes的功能越来越强大。

我们从2017年开始调研Kubernetes,2018年开始小规模使用,当时使用的是1.9版本,现在用的是1.11版本,最新已经到了1.16,可谓版本更新之快,未来会考虑再升级到最新版本。

Kubernetes给我们带来的一些好处:

  • 解决资源利用率低的问题,原来是按照服务去单独分配机器,资源得不到充分利用
  • 服务的资源管理、依赖管理等比较复杂,Docker的镜像管理充分简化了相关工作,使得DevOps理念能够深入实施
  • 降低了服务扩容的复杂性
  • 横向扩展功能也使得服务在应对大流量场景更加灵活
  • 不再需要专门地写脚本去监控服务的健康状态
  • 未来结合云原生中的Service Mesh使服务之间的调用更加灵活,功能更加强大

 

集群建设落地

建设落地前的思考

在落地之前我们对以下一些点做了相应的考量,做好提前的选型及测试。

  • 部署方式的选择,在EKS、kops、kubeadm、Minikube、binary中我们选择了binary的安装方式,选择二进制的安装方式是比较灵活的,
  • Kubernetes版本选型:1.11.7,这个版本也是当时官方提供的最新版本。
  • 网络插件的选型:Flannel,Flannel官方说明会有一定的网络性能损耗,但在我们使用的公有云上可以忽略这一点。随着业务量增加及安全隔离需求,后续会考虑改用Calico,因为发现业务多了的话网络隔离还是很有必要的,另外Canal插件其实也是跟Flannel结合实现网络策略,但是官方对这个项目的维护貌似已经不活跃就不太考虑了。
  • Service实现的选型:IPVS,早期的Service都是iptables实现的,所以早期我们就用的iptables,但是当集群节点数量到达几千台的话iptables性能应该会有很大的衰减,于是在我们升级到1.11版本后果断使用IPVS的方式实现Service。
  • 周边工具选型:Harbor、Rancher、Prometheus、CoreDNS,以上这几款工具都是云原生周边产物,热度都很高,也能够快速简单的支撑业务。
  • 集群优化的考虑:网络MTU、内核版本、网段优化、swap优化等,在集群落地之前要把一些优化点提前考虑好,内核我们用的是4.18,当时的一个最新版本,高版本支持了cgroup2,隔离性应该会比cgroup1更加稳定。
  • 日志方案的考虑:ELK,ELK一直是我们日志方案解决的工具,所以服务上云之后我们依然沿用,其中Filebeat是以DaemonSet模式运行,性能消耗目前来看还是可以接受的。
  • 监控方案的考虑:Prometheus,随着容器技术的迅速发展,Kubernetes已然成为大家追捧的容器集群管理系统。Prometheus作为生态圈CNCF中的重要一员,其活跃度仅次于Kubernetes,现已广泛用于Kubernetes集群的监控系统中,毋庸置疑监控方面的选型非Prometheus莫属。
  • CI/CD的方案:自研的运维平台,相信各个公司都有自己的运维平台,我们的CI/CD也是与我们自己的平台结合,有着一套完善的规范和流程,如果规模不大也可以考虑和Rancher的CI/CD结合,感觉也不错。
  • Namespace的划分考虑,Namespace的划分也比较重要,涉及到业务的隔离与划分,通常要考虑到不同Namespace之间服务的调用问题,内部域名调用问题,安全划分问题,机器分配使用问题等等。

 

Kubernetes数据备份恢复

其实Kubernetes的数据也就是etcd中的数据,那么我们日常就需要备份etcd中的数据,以及考虑数据的恢复,理论上etcd的数据恢复场景应该很难用到,一切操作尽量都通过平台规范化使用,但是针对灾难性的场景就可以用etcd数据备份来救场了。

这里给大家展示下etcd备份和恢复,具体细节大家根据自己环境再调整。

etcd数据备份

#!/bin/sh

source /etc/profile
nowtime=`date +%Y%m%d%H%M`
# 备份的数据目录
workdir="/data/etcd-bak"
# etcd的数据目录
datadir="/data/etcd"
ep=`/sbin/ip addr|grep eth0|sed -nr 's#^.*inet (.*)/22.*$#\1#gp'`
capath="/etc/kubernetes/ssl/ca.pem"
certpath="/etc/etcd/ssl/etcd.pem"
keypath="/etc/etcd/ssl/etcd-key.pem"
etcdctlpath="--endpoints "https://${ep}:2379" --cacert=$capath --cert=$certpath --key=$keypath"
hostname=`hostname`
alertcontent="$hostname-etcd-bak-is-false-please-check-etcd-${nowtime}"
# 备份数据保留天数
delday=7
s3path="s3://etcd/etcd-${ep}"
s3alertcontent="$hostname-etcd-snapshot-to-s3-false-please-check"
etcdctlcmd=`whereis etcdctl|awk '{print $NF}'`


function deloldbak () {
find $workdir -name "etcd-*.gz" -mtime +${delday}|xargs rm -f
}

if [ ! -f /data/etcd-bak/etcd-${nowtime}.tar.gz ];then
mkdir -p /data/etcd-bak/etcd-${nowtime}/
else
echo "need wait to next time"
echo "need wait to next time" >>$workdir/etcd-bak.log
exit 1
fi

echo "===================================  begin $nowtime =================================="
echo "===================================  begin $nowtime ==================================" >>$workdir/etcd-bak.log
export ETCDCTL_API=3
echo "===================================  run snapshoting =================================" >>$workdir/etcd-bak.log
$etcdctlcmd $etcdctlpath  snapshot save $workdir/etcd-${nowtime}/snap-${nowtime}.db >>$workdir/etcd-bak.log
echo "===================================  run snapshoting =================================" >>$workdir/etcd-bak.log
if [ $? -eq 0 ]
then
    echo "etcd snapshot etcd-${nowtime}/snap-${nowtime}.db is successful"
    echo "etcd snapshot etcd-${nowtime}/snap-${nowtime}.db is successful" >>$workdir/etcd-bak.log
else
    echo "etcd snapshot etcd-${nowtime}/snap-${nowtime}.db is failed"
    echo "etcd snapshot etcd-${nowtime}/snap-${nowtime}.db is failed" >>$workdir/etcd-bak.log
fi

cp -fr $datadir/* $workdir/etcd-${nowtime}/
if [ $? -eq 0 ]
then
    echo "etcd snapshot etcd-${nowtime}/member is successful"
    echo "etcd snapshot etcd-${nowtime}/member is successful" >>$workdir/etcd-bak.log
else
    echo "etcd snapshot etcd-${nowtime}/member is failed"
    echo "etcd snapshot etcd-${nowtime}/member is failed" >>$workdir/etcd-bak.log
fi


$etcdctlcmd $etcdctlpath --write-out=table endpoint status
$etcdctlcmd $etcdctlpath --write-out=table endpoint status >>$workdir/etcd-bak.log

cd $workdir
tar zcf ./etcd-${nowtime}.tar.gz etcd-${nowtime}
rm -fr etcd-${nowtime}
aws s3 cp $workdir/etcd-${nowtime}.tar.gz $s3path/
if [ $? -eq 0 ]
then
    echo "etcd snapshot s3 is successful"
    echo "etcd snapshot s3 is successful" >>$workdir/etcd-bak.log
else
    echo "etcd snapshot s3 is failed"
    echo "etcd snapshot s3 is failed" >>$workdir/etcd-bak.log
fi
deloldbak


echo "===================================  end `date +%Y%m%d%H%M%S` =================================="
echo "===================================  end `date +%Y%m%d%H%M%S` ==================================" >>$workdir/etcd-bak.log

 

etcd数据恢复

#!/bin/bash

# 使用etcdctl snapshot restore生成各个节点的数据

# 比较关键的变量是
# --data-dir 需要是实际etcd运行时的数据目录
# --name  --initial-advertise-peer-urls  需要用各个节点的配置
# --initial-cluster  initial-cluster-token 需要和原集群一致
# 注意http和https区别

# 无需更改
workdir=/root

# etcd1,2,3为节点名称 ETCD1,2,3为对应节点ip
ETCD_1=1.1.1.1
ETCD_2=2.2.2.2
ETCD_3=3.3.3.3
etcd1=etcd1
etcd2=etcd2
etcd3=etcd3

# 同上面一样需要对应设置
arra=(1.1.1.1 2.2.2.2 3.3.3.3)
arrb=(etcd1 etcd2 etcd3)

# etcd是否使用https tls加密如果使用需要配置证书,若是http请置空此变量
etcdkey="--cacert=/etc/kubernetes/ssl/ca.pem --cert=/etc/etcd/ssl/etcd.pem --key=/etc/etcd/ssl/etcd-key.pem"
# 恢复数据存放目录,只是用于恢复存放数据,可以随意设置,跟原有的路径没有关系
etcddatapath="/root/etcd-recover-data/etcd"
# 备份数据根路径
bakdatapath="/data/etcd-bak"
# 备份数据完整路径
bakdbpath="$bakdatapath/etcd-201906161945/snap-201906161945.db"
# ansible site执行路径
ansiblepath="/root/etcd-bak-ansible"

function ansibleoperate ()
{
rm -fr $ansiblepath/roles/etcd-bak-ansible/files/*
cp -fr $(echo $etcddatapath|awk -F "[/]" '{print "/"$2"/"$3}')/* $ansiblepath/roles/etcd-bak-ansible/files/
cd $ansiblepath
ansible-playbook -i hosts site.yaml
}

if [ ! -d $(echo $etcddatapath|awk -F "[/]" '{print "/"$2"/"$3}') ];then
mkdir -p $(echo $etcddatapath|awk -F "[/]" '{print "/"$2"/"$3}')
fi

for i in ${arra[@]}
do
echo -e "\t$i\c" >>$workdir/etcdiplist.log
#echo -e "$i"
done


for i in ${arrb[@]}
do
echo -e "\t$i\c" >>$workdir/etcdnamelist.log
#echo -e "$i"
done

while true
do
let cnt++
etcdiplist=`awk -v column=$cnt '{print $column}' $workdir/etcdiplist.log`
etcdnamelist=`awk -v column=$cnt '{print $column}' $workdir/etcdnamelist.log`

if [ "$etcdiplist" = "" ]
    then
        echo "conf is down will to break"
        break
fi
echo $etcdiplist $etcdnamelist
export ETCDCTL_API=3
# 如果用原有member中的db恢复,由于不存在完整的hash性,需要在下面添加 --skip-hash-check \ 跳过hash检查
etcdctl snapshot $etcdkey  restore $bakdbpath  \
--data-dir=$etcddatapath \
--name $etcdnamelist \
--initial-cluster ${etcd1}=https://${ETCD_1}:2380,${etcd2}=https://${ETCD_2}:2380,${etcd3}=https://${ETCD_3}:2380 \
--initial-cluster-token etcd-cluster-0 \
--initial-advertise-peer-urls https://$etcdiplist:2380 && \
mv $etcddatapath $(echo $etcddatapath|awk -F "[/]" '{print "/"$2"/"$3}')/etcd_$etcdiplist

echo "--initial-cluster ${etcd1}=https://${ETCD_1}:2380,${etcd2}=https://${ETCD_2}:2380,${etcd3}=https://${ETCD_3}:2380 "


done

rm -f $workdir/etcdiplist.log
rm -f $workdir/etcdnamelist.log

#如果不需要Ansible自动恢复集群,需要手动恢复的话请注释以下操作
ansibleoperate

 

镜像管理

镜像仓库我们选择的是Harbor,比较成熟并且社区维护更新也非常快。我们最早使用1.2版本,现在使用1.6版本。目前Harbor最新是1.8版本,下面给大家展示下新旧版本功能上的差异,新版本还是有很多好功能的。

1.2版本和1.6版本功能对比

1.png

 

升级后具备的优势

  • 存储支持S3:镜像从保存在本地改为存储到S3,这样可以节省存储费用,也不用考虑本地磁盘扩容的事情。
  • 登录接入LDAP:规范管理用户,并且可以使用LDAP的组进行用户的划分。
  • 用户限制,用户分组:这块主要是结合LDAP组进行划分,在Harbor中建好各个对应的项目,配置开发权限。
  • 漏洞扫描:每天定时扫描镜像,不过想保证所有镜像都不存在危险貌似不太容易,开发自定义等不规范镜像会经常出现。
  • 镜像签名:安全度高的镜像会考虑开启该功能。
  • 高可用负载:官方提供了HA的功能,主要就是访问的HA,数据库的HA,存储的HA。
  • 证书认证:访问通过https,更加安全。
  • 数据库更加简单:原来是有MySQL、PostgreSQL,现在新版本全部统一使用PostgreSQL,管理更加方便。

 

线上镜像仓库架构图

2.png


上面是我们的架构图,通过DNS解析将不同环境的访问分流到对应环境的镜像仓库,所有的镜像仓库都连接着后端数据库集群,镜像统一保存到了S3中,对于仓库的扩容也是十分方便的,拷贝一份配置启动就可以了。

镜像仓库升级

备份之前先停止老的Harbor:

cd harbor
docker-compose down


备份原来的Harbor目录:

mv harbor /my_backup_dir/harbor


备份数据库:

cp -r /data/database /my_backup_dir/


后续升级镜像下载:

docker pull goharbor/harbor-migrator:[tag]


升级harbor.cfg或者harbor.yml文件:

docker run -it --rm -v ${harbor_cfg}:/harbor-migration/harbor-cfg/harbor.cfg -v ${harbor_yml}:/harbor-migration/harbor-cfg-out/harbor.yml goharbor/harbor-migrator:[tag] --cfg up


如果没有yaml文件,低版本理论上只有cfg文件,那就升级cfg文件就可以了:

docker run -it --rm -v ${harbor_cfg}:/harbor-migration/harbor-cfg/harbor.cfg goharbor/harbor-migrator:[tag] --cfg up


解压新的版本离线包:

tar -zxvf harbor-offline-installer-v1.7.4.tgz


覆盖harbor.cfg,把之前升级的harbor.cfg文件或者yml文件拷贝到新版本解压的目录里替换相应的文件:

cd harbor
mv harbor.cfg harbor.bak
cp /root/harbor-bak/harbor.cfg .


安装Notary,Clair和Helm Chart服务,安装之前可以perpare脚本生成下配置文件:

./install.sh --with-notary --with-clair --with-chartmuseum


进行查看:

docker-compose -f ./docker-compose.yml -f ./docker-compose.clair.yml ps


清除旧版本镜像:

docker images|grep 1.6.2| awk '{print $3}'|xargs docker rmi

 

日志方案落地

日志落盘, DaemonSet部署Filebeat,采集进Kafka,最终进ES,落盘日志定期清理。

3.jpeg

 

4.png


这个是基于Node级别的一种日志收集方案,我们大多使用这种方案进行日志的收集,优点就是可以和服务完全解耦,性能好,便于管理。

这种方式的一个弊端就是日志格式必须按照约定的方式配置输出,对不能满足约定格式的情况改用sidecar的方式进行日志的收集。

5.png


这种方式就是扩展性强,配置可以跟随服务进行制定的收集,弊端就是会浪费资源,并且有一定耦合性,所以我们线上并未大面积采取这个方式的使用。

监控方案落地

Prometheus想必在大家的公司中都已经在使用了,是监控领域里现在最火热的一款监控工具,在这里也不多赘述了,基本的使用大家应该都比较了解,下面主要简单展示下我们线上对于服务应用是如何上报监控,配置也并不复杂,大家看图解读。

Service里面增加配置:

prometheus.io/scrape: "true" 


是否监控就看是否在Service中开启了这个开关。

以下是Prometheus配置过滤规则:

6.jpg

 

7.jpg

 

8.jpg

 

后续工作

  • Service Mesh使用:Istio调研及使用(灰度、限流、链路跟踪、熔断、降级)
  • LXCFS解决容器CPU、内存资源可见性问题
  • 有状态应用部署至Kubernetes:ES、Kafka等
  • CRD在prometheus-operator的应用

 

Q&A

Q:请问Kubernetes数据备份与恢复,这个是包括kubectl-proxy,etcd,网络配置等吗?如何进行多集群下的数据备份?
A:备份的其实就是etcd中的数据,我们网络是用的Flannel,一些关键网段信息也是存在etcd中的,对于多集群来看的话,还是要针对数据存放对应的etcd集群数据去进行备份。

Q:请问一下业务日志太多,一天一个节点的业务日志有200G,怎么做日志收集及监控告警:
A:一天一个节点200G的话,这个要看你们集群节点多不多,我们上百个节点,一个节点的量大概在100G左右,线上日志量都是几十T的数据,用我分享的方案去落地应该是没问题的,ELK的整体性能还是非常不错的,Filebeat现在最高的性能分配是占用500M CPU,1G内存,收集起来也是能应对的,这个根据你的量再调整,监控的话肯定就用Prometheus就好,官方都是有自动发现的配置,很便利,当然如果你要对日志进行分析,这块就比较复杂了,可以通过ES接口去聚合数据,当然日志的字段也要规范好。

Q:生产环境Kubernetes采用二进制方式搭建还是kubeadm ,还是其他方案?
A:线上采用的是二进制的方法,因为我们上Kubernetes的时候kubeadm还是测试版本,当然现在高版本的kubeadm应该已经是正式版本,但是觉得还是二进制更方便一些,你改配置,以及自定义一些参数会方便一些。

Q:生产环境Kubernetes都用哪种网络模式?
A:我们用的是Flannel,不过后续会考虑打算换成Calico,现在发现线上有一定网络限制的需求,Calico的性能相对也会更好,但是维护的复杂度比较高,在集群节点多的情况下,要添加路由反射器,这个比较关键,而且网络选型前一定对未来的规模有个规划,规划好使用的网段。

Q:请问生产环境中etcd的数据需要备份吗?怎么备份?还有二进制安装etcd集群由3个节点增加到5个节点,需要重新生etcd证书后再重启etcd服务吗?增加节点重启策略是一个一个节点依次重启吗?
A:建议备份,其实主要用到的就是etcd的snapshot功能,不复杂,看下我分享的脚本即可,添加节点用你现有的证书就好,官方的方法是要一台一台执行的,线上etcd节点我做过测试,即使操作失误都down掉的话也不会影响你现有服务的运行,而且保证法定节点的存在就更好。

Q:你分享的Prometheus是Operator方式吗?你的监控数据是有经过二次开发后作为标准格式输出吗?对于Nginx和Java监控如何实现呀?
A:Prometheus没有用Operator的方式,是用的官方的yaml文件创建的,我们线上Java服务居多,都是通过Spring官方的Prometheus插件就可以自定义监控数据,Nginx的话我们还真的不多,这个估计你要用相应的exporter就好,监控数据是开发自定义上传的,我们没有做限制。

Q:Pod挂掉之后如何保留现场,比如做内存Dump有什么好的方案没?
A:我们这边是这样,对于健康检查没有添加Liveness的检查,也是防止容器的重启,尤其是在第一次项目上线,难免无法正常启动,如果加了Liveness就会一直重启,不太方便查问题,所以只加了Readiness,只是保证不影响线上访问,对于生产中,Java项目遇到最多的就是OOM问题,这个我们也对Pod重启的原因加了报警,至于Dump我们还没这方面的操作,需要开发自行检查了。

Q:传统系统架构如何改造成Kubernetes架构?
A:这个问题有点宽泛呢,还是得看您这边实际的场景,我觉得更多的也是得需要开发一起配合的,尽量保证服务模块都能够做到微服务话,不要耦合的太紧,您可以先搭建一个测试集群,然后从开发那边找一个模块进行Docker化的转换,然后一点一点再去试吧。

Q:是否有Ingress tcp/udp应用的生产级网络方案?
A:我们没有用Ingress,我们的用法也算是一种比较简单的用法,我们是把网关直接加入到Kubernetes集群中,这样网关就可以调用到Kubernetes的Service,因为我们以网关为中心,做了一些安全及认证功能,所以之前的网关必须要用到,而且加了Ingress相当于多加了一层性能消耗,所以也没有用,最后我们把之前部署在虚拟机上的网关也变成Docker化去部署到集群内部。

Q:传统数据库负载过高时查询缓慢,但是会有结果,Kubernetes架构数据库负载过高直接Pod重启,导致没有结果返回,请问应该如何处理的?
A:我们集群还没有跑数据库这种有状态的服务,但是听您描述,还是得看看Pod重启的具体原因,如果Pod都重启了,理论上跑在机器上一定也会有问题,还是在上云之前做好充分的性能压测,并且您可以考虑取消Liveness的健康检查,只保留Readness访问的检查。

Q:采集日志过程中,fluentd或fluent bit通过读取Node节点docker log目录采集日志,该目录包含了所有服务的日志。请问如何在output阶段中根据Namespace和container_name创建Elasticsearch的index,并作为index的命名前缀?
A:首先不建议通过Docker目录的方式采集,日志还是落盘到具体路径为好,因为我也碰到过您这个困惑,因为Docker的目录都是软链接,而且当Docker重启后路径会改变,当然我们线上用的是Filebeat采集,不知道Fluentd能不能解决这个问题,由于是软链接,很难用相对路径,必须用绝对路径采集到真正存放的那个目录日志,我们对于es index名称的创建是通过日志提供的一个index名称字段去匹配的,索引名称会引用这个变量进行区分不同的index。

Q:fileneat node模式采集,多个相同Pod在同一节点情况下,如何映射日志目录而不互相干扰,另外如何配置Filebeat做到Pod变动时的采集?
A:您这个情况我们也遇到过,多个Pod跑在同一个节点确实存在这个问题,因为你的deploy yaml是定死的,很难处理这种情况,我们的解决方法是添加Pod的亲和性,保证每个节点都尽量只跑一个Pod,当然如果节点非常小的情况下,这种做法有一定问题,以生产使用上来看,我们最初多个Pod跑在一个节点同时写一个文件的话也是还可接受。

Q:持续集成系统具体的细节可以透露下吗?基于GitLab CI还是Jenkins?或者小公司可以直接用Spinnaker这些吗?
A:CI/CD的话因为我们有自己现有的发布平台,背后的原理实际上还是调用Jenkins去处理。

Q:日志收集的sidectar模式具体是咋部署的。Filebeat和应用部署在一个Pod里吗?
A:对的,部署在一个Pod里,相当于你的deploy yaml里会有两个image配置,一个是你的服务,另一个是Filebeat,具体的配置看下我的截图,把这部分配置放到你的服务配置后面即可,但是就像我分享说的,这种方式可能会比较消耗资源,但是确实自定义比较方便,但也增加了yaml配置。

Q:我司测试环境搭建的Harbor版本是1.5,使用docker-compose来按照Harbor各个组件的依赖顺序来启动的,但是当系统或者Docker重启后,Harbor的容器就无法按照依赖顺序来启动,经常会有容器启动失败。请问下这个该如何优化呢?
A:其实你需要在Docker中注意一个参数,live-restore : true,这个参数很有用,你可能没有添加,这个参数能保证在你维护重启Docker的时候,还能保证不影响正在运行的Docker容器,另外你可以对Harbor进行监控,如果down了的话大不了做个自动重启的操作也不妨大碍。

Q:(1)Kubernetes平台上线前有什么测试,如何测试?可以上线的依据?(2)常见互联网架构的业务,需要改造才可以在Kubernetes跑吗,需要如何改造?有什么坑?(3)你们多个业务线都共用同一套Kubernetes?如何实现不会因为一个业务的高峰影响其他业务?(4)有什么方案可以实现最大限度的不丢日志?
A:1. 因为我不是测试,对于测试这块可能干涉的不是很多,对于运维来讲可能更多的是比较关注上线之前的压力测试,这块会跟后续的稳定性有很大关系;2. 常见的架构业务理论上改造应该不需要很大,最主要的是解决Docker镜像化,遇到的坑可能更多的是对于Dockerfile打镜像理解的不好,导致一些启动问题以及配置的丢失等等;3. 我们是通过Namespace区分业务线,需要提前规划好业务,指定的业务线只跑在对应的机器上比较关键;4. 我使用的ELK过程中还真的很少遇到过丢日志,只要你架构足够健壮应该是没什么问题的,另外ELK中一定要用消息队列,降低你消息传递的压力,保证每个组件都不要出现性能瓶颈,如果实在怕丢日志,可以让Logstash在消费的时候把消息落盘,ES也要合理配置好刷新的频率以及内存多大落盘等参数,提前做好各个组件的压测是保障。

Q:你好,我是蔚来ES8车主,很高兴看到蔚来的分享。我想了解下你们存储的方案,之前听说是用的Portworx,具体方案可以透露一下么?你们这个team在北京还是上海? 用AWS的话有没有考虑直接使用AWS的Kubernetes服务?ES也运行在Kubernetes里吗?
A:您好,我们team在北京,因为我们的集群还未上有状态服务,所以暂时还未考虑分布式存储的问题,这块确实是很重要的一个环节,我们线上的服务基本也是通过S3去存储一些数据使用,Portworx这个好像也出了很久了,当时在还没有Kubernetes的时候调研过,不过想大面积使用貌似是要花钱用商业版,建议还是用现在比较流行的Ceph可能会更好一些吧,我们还未用到AWS自己的Kubernetes服务,ES有运行在Kubernetes里的业务,但是不是通过Operator部署,后端数据也没用到分布式存储,由于量不大,只是落在本地了,后期会进一步调研Ceph以支持后期的有状态服务的迁移。

Q:请问是否考虑过fluent-bit ,目前Filebeat有没有性能上的问题呢?
A:因为在虚拟机的时候我们就用的Filebeat,就沿用下去了,Filebeat暂时还未发现性能问题,可以直接使用,总日志量我们应该有几十T的样子,在生产使用的过程中感觉Filebeat还是比较靠谱的。

Q:Kubernetes一年的证书问题,你们怎么解决的呢?
A:Kubernetes的证书我们的时间都设置的是十年,kubelet可能是一年,这个我们最初疏忽了,碰到过一次,最终通过删除现有的配置,让kubelet重启自动生成,当然如果您是最初规划的话,可以加上证书自动到期认证的功能,据了解好像现在高版本的Kubernetes已经不存在这个问题,我还没了解的那么多,您可以再查查。

Q:Kubernetes生产环境上的安全相关的配置有哪些呢?
A:安全的话这个比较宽泛啊,这个还是要从各个方面完善,首先起码要保证流量流入方向的各个环节的安全限制,以及服务接口调用上的安全认证,以及开发人员使用时候的权限控制等等。

Q:Prometheus自定义监控具体怎么搞得,比如想要监控容器的端口连接数?
A:容器端口的连接数监控确实还未添加,在原来宿主机的时候是有的,这块有些忽略了,加的话也不是很费劲,可以通过你们自己自定义的exporter去监控。

Q:落盘的日志怎么定期清理?
A:落盘的日志通过写好的清理任务进行清理,因为我们的日志都是规范的落到统一的目录,并且目录名称也是很规范的,所以清理起来很方便,写个简单的脚本就可以啦,定时清理就OK。

Q:Kubernetes里Java服务,你们是怎么做资源限制的?
A:我们是在yaml注入了能获取设置资源的env参数,然后在CI打镜像的时候统一规范了服务启动的start脚本,JVM里配置的是Kubernetes配置的资源,所以Java服务的使用也不会超过我们分配资源的使用。

以上内容根据2019年10月10日晚微信群分享内容整理。 分享人朱嘉骏,蔚来汽车运维工程师,负责Kubernetes的推广及应用维护,推进企业从传统应用迁移到Kubernetes,解决运维基础建设与云结合中遇到的问题。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiese,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。