
1什么是k8s?
k8s是一个docker容器管理工具
它是一个全新的基于容器技术的分布式架构领先方案,是开源的容器集群管理系统。
在docker的基础上,为容器化的应用提供部署运行,资源调度,服务发现和动态伸缩等一系列完整功能
2----k8s的优势:
a,容器编排
b,轻量级
c,开源
d,d性伸缩
e,负载均衡
二:k8s的核心功能
1自愈: 重新启动失败的容器,在节点不可用时,替换和重新调度节点上的容器,对用户定义的健康检查不响应的容器会被中止,并且在容器准备好服务之前不会把其向客户端广播。
d性伸缩: 通过监控容器的cpu的负载值,如果这个平均高于80%,增加容器的数量,如果这个平均低于10%,减少容器的数量
服务的自动发现和负载均衡: 不需要修改您的应用程序来使用不熟悉的服务发现机制,Kubernetes 为容器提供了自己的 IP 地址和一组容器的单个 DNS 名称,并可以在它们之间进行负载均衡。
滚动升级和一键回滚: Kubernetes 逐渐部署对应用程序或其配置的更改,同时监视应用程序运行状况,以确保它不会同时终止所有实例。 如果出现问题,Kubernetes会为您恢复更改,利用日益增长的部署解决方案的生态系统。本文讲解kubernetes内的dns服务。
每个集群内的service都分配得有一个dns 名称,默认情况下一个客户端POD的DNS搜索将会包含POD自己名称空间以及CLUSTER默认域名。如:
A record通常是一个域名指向一个IP地址。
命名端口需要SRV记录,这些端口正常是service 或者是headless services的一部分,SRV格式记录如: _my-port-name_my-port-protocolmy-svcmy-namespacesvccluster-domainexample
当前,创建 Pod 后,它的主机名是该 Pod 的 metadataname 值。可以通过设置hostname 来重新主机名,此外还可以设置subdomain来指定pod的子域名。
如:Pod 的主机名 annotation 设置为 “foo”,子域名 annotation 设置为 “bar”,在 Namespace “my-namespace” 中对应的 FQDN 为 “foobarmy-namespacesvcclusterlocal”。
例:
如果 Headless Service 与 Pod 在同一个 Namespace 中,它们具有相同的子域名,集群的 KubeDNS 服务器也会为该 Pod 的完整合法主机名返回 A 记录。 例如,在同一个 Namespace 中,给定一个主机名为 “busybox-1” 的 Pod,子域名设置为 “default-subdomain”,名称为 “default-subdomain” 的 Headless Service ,Pod 将看到自己的 FQDN 为 “busybox-1default-subdomainmy-namespacesvcclusterlocal”。 DNS 会为那个名字提供一个 A 记录,指向该 Pod 的 IP。 “busybox1” 和 “busybox2” 这两个 Pod 分别具有它们自己的 A 记录。
踩坑完毕,回到主线。
前面关于port的理解存在偏差,需要用实验来确认port配置的含义。
k8s官方文档对于对于这些配置项的解释还是没有很完善。下面是在其他博文中找到的解释。
已知:
从k8s集群内部的宿主机(物理机、虚拟机)可以直接访问pod的服务地址 ip:80
未知(需要测试):
1、同一局域网内,但没有加入k8s集群的其他服务器能否访问pod的服务地址 ip:80---无法访问
2、能否跳过pod直接访问容器的服务地址 ip:80---没查到ip
首先要知道容器的IP地址
可以看到上面的命令查出的结果是 - 无法看出ip,尝试进入容器查看
然后我就没辙了,不过根据linux系统的精神,所有内容都是文件,但是我google了好久也没找到ip地址到底存在哪一个文件中。然后我就怀疑是不是一定要容器开放端口,ip地址才可以用docker inspect查询,起了一个不开端口的容器,结果也是有ip的。后来问了一个底层开发的朋友,据说ip是不写文件的。
那只能先认为通过k8s启动的容器其实是没有容器ip的。
从侧面看,也很有可能k8s启动的容器确实没有ip
3、访问pod所在的主机的80端口能否返回相同的响应---无法访问
从以上的信息来看,这个port配置应该和docker中暴露端口的意思是一样的,例如下面的例子
来做一下实验:
在我们之前的pod配置文件上增加配置,如下
结果和我们之前的猜测保持一致,增加ports的配置之后,访问宿主机的ip:80也可以访问到pod的内容了。
我这里pod ip 是 101913067,宿主机是 101001237。curl 101913067 和 curl 101001237 得到的结果是一样的。正当我想再仔细看看的时候,服务器又挂了,wc,只能明天找网管重启了。
---第二天
昨天,我还想看看
1、关了这个pod之后是否就不能访问了
启动了2个pod如下,mynginx1没有配置ports,mynginx2配置了ports。
当我关了pod-mynginx2之后访问宿主机101002167应该就不能通了,结果居然是---能访问到!
大吃一惊!结果ip弄错了,宿主机不是101002167,而是101001237,犯了个低级错误。
结果如下:这回和预期的结果终于一样了。
2、宿主机上是不是本身就开启了nginx,所以恰巧就能访问
确认宿主机上没有开启nginx
3、宿主机上的端口开放情况
使用netstat查看宿主机的端口开放,居然没有发现80端口开着,好奇怪。
那如果在101001237宿主机上启动一个nginx端口开在80,结果会是什么样子呢。
我居然启动了,没有端口已被占用的报错。现在把宿主机上的nginx的index页面的内容改一下,看访问101001237:80时,到底访问的是哪一个nginx。
分别从集群内部3台服务器和集群外部1台服务器的机器取访问101001237:80,访问到的都是pod中的nginx。
会不会跟启动顺序有关,因为现在的情况是先启动了pod-nignx,后启动 宿主机-nginx,那现在将pod-nginx关闭,访问101001237:80,看是啥。
集群内部3台服务器和集群外部1台服务器访问101001237:80,结果一致,都是宿主机-nginx。
再启动pod-nginx,查看结果。
访问结果又变回pod-nginx了,4台服务器结果一致。
再去看一下宿主机-nginx的日志,有没有报错信息-----------没有错误日志
现在基本可以得出结论了:当pod和宿主机同时使用某一个端口时,不会因为冲突而报错,但是pod会优先占用端口,而与启动顺序无关。
至于为什么会这样,就不去深究了,毕竟精力有限,作为运维实施,了解到这样子的程度应该够用了。
自从我们的kubernetes集群部署到生产环境后,将流量从原有的服务器上切过来之后,部分节点出现挂载目录容量爆满的情况。运维的同事报给我们之后,我们首先想到的是节点镜像过多,于是我们提供一个命令用于清理当前节点上无用的、报错的、镜像和docker资源文件
docker system prune 命令可以用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及dangling镜像(即无tag的镜像)
docker system prune -a 命令清理得更加彻底,可以将没有容器使用Docker镜像都删掉。
待运维执行之后,目录存储资源释放了一些,我们本以为这就告一段落了。然而,事与愿违,没过多久,再次容量报警。。。
我们开始重视起来,开始检视节点上工作的容器,发现在日志爆炸的节点上运行了定时任务,开发人员将定时任务的日志输出到控制台,于是我们回到节点docker的工作目录,通过 du -sh 方式查看每个文件夹大小,发现docker目录下containers目录占用空间巨大,进去看原来是每个运行的容器存放日志的目录,我们找出占用空间最大的日志目录,发现容器日志特别的大
我们可使用如下命令查看各个日志的文件大小
ls -lh $(find /var/lib/docker/containers/ -name -jsonlog)
那我们如何清理日志呢,如果docker容器正在运行,那么使用rm -rf 方式删除日志后,通过df -h会发现磁盘空间并没有释放
原因:在Linux或者Unix系统中,通过rm或者文件管理器删除文件将会从文件系统的目录结构上解除链接(unlink)然而如果文件是被打开的(有一个进程正在使用),那么进程将仍然可以读取该文件,磁盘空间也一直被占用
我们通过 cat /dev/null > -jsonlog 来清理相应的日志,然后重启
systemctl daemon-reload
systemctl restart docker
然而,我思考,不能每次满的时候找运维清理日志啊,这多麻烦,难道docker没有相应的机制应付输出到控制台的日志吗?答案是:当然不会
在新版的docker中我们可以通过设置 vim /etc/docker/daemonjson 来限制docker的日志量
"log-driver":"json-file","log-opts":{ "max-size" :"200m","max-file":"5"}
顾名思义max-size就是每个日志文件大小,max-file是最多生成的文件数,如上我设置成功后,每个容器运行的日志最多有五份每份200M大小,这样就基本限制了容器的日志大小。
然后你觉得结束了吗??并不!!
容器日志我们是限制完了,本以为高枕无忧,不用担心出现日志爆满的情况了,但是事与愿违,过几天硬盘容量又满了。。。
我们究其原因,发现在docker的运行目录下overlay这个文件夹里存放着所有的容器挂载目录,也就是容器的系统文件在这里放着,在容器中跑着的服务产生日志很可能并不是输出到控制台,而是保存到本地,容器内的日志文件也是会占用磁盘空间的,这就让我们犯愁了,这个不好限制开发团队不存日志或者规定团队存放目录啊,对于一个成熟的容器平台来说,海纳百川那是必须的~
于是我们打起了kubelet的主意
在 k8s中文社区中有详细的限制方法 那具体做法呢,其实就是为节点加上驱逐策略,当cpu或者内存或者硬盘空间不满足要求时,自动驱逐一些消耗资源大的容器,保证节点稳定性。
里面主要是有以下几个关键驱逐信号
上面的每个信号都支持整数值或者百分比。百分比的分母部分就是各个信号的总量。kubelet 支持两种文件系统分区。
nodefs:保存 kubelet 的卷和守护进程日志等。
imagefs:在容器运行时,用于保存镜像以及可写入层。
imagefs 是可选的。Kubelet 能够利用 cAdvisor 自动发现这些文件系统。Kubelet 不关注其他的文件系统。所有其他类型的配置,例如保存在独立文件系统的卷和日志,都不被支持。
因为磁盘压力已经被驱逐策略接管,因此未来将会停止对现有 垃圾收集 方式的支持。
具体的内容大家可以详细去看看社区里的介绍,我这里就不再赘述了,我这边献上我的驱逐方案~
执行vim /etc/systemd/system/kubeletserviced/10-kubeadmconf
在里面插入
Environment="KUBELET_OTHER_ARGS=
--eviction-hard=memoryavailable<2Gi,nodefsavailable<5Gi,imagefsavailable<5Gi
--eviction-minimum-reclaim=memoryavailable=500Mi,nodefsavailable=5Gi,imagefsavailable=5Gi
--node-status-update-frequency=10s
--eviction-pressure-transition-period=30s"
解读:内存小于2G驱逐,root目录磁盘空间小于5G驱逐,镜像目录磁盘空间小于5G驱逐,节点检测为每10秒一次,在跳出压力状态之前要等待的时间为30秒。
在某些场景下,驱逐 Pod 可能只回收了很少的资源。这就导致了 kubelet 反复触发驱逐阈值。另外回收资源例如磁盘资源,是需要消耗时间的。
要缓和这种状况,Kubelet 能够对每种资源定义 minimum-reclaim。kubelet 一旦发现了资源压力,就会试着回收至少 minimum-reclaim 的资源,使得资源消耗量回到期望范围。
也就是说当内存触发驱逐时,kubelet至少要让内存有25G,当root和镜像磁盘空间发生驱逐时,kubelet至少要让磁盘有10G的空间。
那驱逐的规则是什么呢,对什么样的容器做驱逐呢?这个我们下回分解哈。
那总的来说,若要解决节点镜像存储报警,我们可以从三个方面入手
1容器:通过docker限制容器日志大小
2k8s:通过kubelet来驱逐过大的容器
3跟开发人员沟通,精简容器,不让内存泄漏,不随意使用资源(很难啦~~~)
祝各位新春快乐~
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)