首页
About Me
推荐
weibo
github
Search
1
linuxea:gitlab-ci之docker镜像质量品质报告
49,451 阅读
2
linuxea:如何复现查看docker run参数命令
23,044 阅读
3
Graylog收集文件日志实例
18,580 阅读
4
linuxea:jenkins+pipeline+gitlab+ansible快速安装配置(1)
18,275 阅读
5
git+jenkins发布和回滚示例
18,181 阅读
ops
Openvpn
Sys Basics
rsync
Mail
NFS
Other
Network
HeartBeat
server 08
Code
Awk
Shell
Python
Golang
virtualization
KVM
Docker
openstack
Xen
kubernetes
kubernetes-cni
Service Mesh
Data
Mariadb
PostgreSQL
MongoDB
Redis
MQ
Ceph
TimescaleDB
kafka
surveillance system
zabbix
ELK Stack/logs
Open-Falcon
Prometheus
victoriaMetrics
Web
apache
Tomcat
Nginx
自动化
Puppet
Ansible
saltstack
Proxy
HAproxy
Lvs
varnish
更多
互联咨询
最后的净土
软件交付
持续集成
gitops
devops
登录
Search
标签搜索
kubernetes
docker
zabbix
Golang
mariadb
持续集成工具
白话容器
elk
linux基础
nginx
dockerfile
Gitlab-ci/cd
最后的净土
基础命令
gitops
jenkins
docker-compose
Istio
haproxy
saltstack
marksugar
累计撰写
690
篇文章
累计收到
139
条评论
首页
栏目
ops
Openvpn
Sys Basics
rsync
Mail
NFS
Other
Network
HeartBeat
server 08
Code
Awk
Shell
Python
Golang
virtualization
KVM
Docker
openstack
Xen
kubernetes
kubernetes-cni
Service Mesh
Data
Mariadb
PostgreSQL
MongoDB
Redis
MQ
Ceph
TimescaleDB
kafka
surveillance system
zabbix
ELK Stack/logs
Open-Falcon
Prometheus
victoriaMetrics
Web
apache
Tomcat
Nginx
自动化
Puppet
Ansible
saltstack
Proxy
HAproxy
Lvs
varnish
更多
互联咨询
最后的净土
软件交付
持续集成
gitops
devops
页面
About Me
推荐
weibo
github
搜索到
71
篇与
的结果
2022-02-22
linuxea:bootstrap-kubelet.conf: no such file or directory kubelet证书轮换失败
bootstrap-kubelet.conf: no such file or directory kubelet证书轮换失败
2022年02月22日
4,811 阅读
0 评论
1 点赞
2022-02-21
linuxea:局域网ntp和chronyd时间同步的简单配置
在某些环境下,我们需要ntp服务器,同时我们可能还需要配置chronyd来同步我们的节点时间,而在k8s的环境中,服务器的时间是需要同步的,并且在一些警报中是会检测,为了解决这个问题,在一些局域网内没有互联网的情况下,就需要手动配置ntp通过yum install 方式来安装ntp服务,而后我们配置一个server 192.168.5.26 iburstprefer:优先使用该时间服务器burst:当一个运程NTP服务器可用时,向它发送一系列的并发包进行检测。iburst:当一个运程NTP服务器不可用时,向它发送一系列的并发包进行检测。“iburst” 选项作用是如果在一个标准的轮询间隔内没有应答,客户端会发送一定数量的包(八个包而不是通常的一个)给 NTP 服务器。如果在短时间内呼叫 NTP 服务器几次,没有出现可辨识的应答,那么本地时间将不会变化通常情况,大多数只是在没有公网环境的情况下配置一个内网的,小局域网内的一个环境使用/etc/ntp.confdriftfile /var/lib/ntp/ntp.drift statistics loopstats peerstats clockstats filegen loopstats file loopstats type day enable filegen peerstats file peerstats type day enable filegen clockstats file clockstats type day enable server ntp1.aliyun.com prefer server 192.168.5.26 iburst server ntp.aliyun.com prefer server 2.centos.pool.ntp.org iburst server 3.centos.pool.ntp.org iburst #server ntp.ubuntu.com server 127.127.1.0 fudge 127.127.1.0 stratum 5 restrict -4 default kod notrap nomodify nopeer noquery restrict -6 default kod notrap nomodify nopeer noquery restrict 17.168.0.0 mask 255.255.255.0 nomodify restrict 127.0.0.1 restrict ::1 #https://www.jianshu.com/p/e5e486c8e365而后开启即可systemctl start ntpd systemctl enable ntpdchronydChrony是一个开源的自由软件,如果在chrony配置文件中指定了ntp服务器的地址,那么chrony就是一台客户端,会去同步ntp服务器的时间,如果在chrony配置了允许某些客户端来向自己同步时间,则chrony也充当了一台服务器,所以,安装了chrony即可充当客户端也可以充当服务端。Chrony有两个核心组件,分别是:chronyd:是守护进程,主要用于调整内核中运行的系统时间和时间服务器同步。它确定计算机增减时间的比率,并对此进行调整补偿。chronyc:提供一个用户界面,用于监控性能并进行多样化的配置。它可以在chronyd实例控制的计算机上工作,也可以在一台不同的远程计算机上工作。ntpd同步时间某些时候需要长时间来同步时间,在Centos7中的chrony也实现时间同步hrony兼容ntpd监听在udp123端口上,另外还监听在udp的323端口上。我们通过yum install -y chrony进行安装通常k8s在时间同步上是使用的是chronyd来判断的,NTP synchronized,如下~ # timedatectl Local time: 五 2021-10-29 15:05:00 CST Universal time: 五 2021-10-29 07:05:00 UTC RTC time: 五 2021-10-29 07:05:09 Time zone: Asia/Shanghai (CST, +0800) NTP enabled: yes NTP synchronized: no RTC in local TZ: no DST active: n/a我们停掉ntpd systemctl stop ntpd cp /etc/chrony.conf{,.bak} systemctl stop ntpd配置一个基于阿里云ntp.aliyun.com的chrony的地址,我们假设上面的ntp就是chrond要使用的服务器,如下cp /etc/chrony.conf{,.bak} cat > /etc/chrony.conf << EOF server 192.168.5.26 server ntp1.aliyun.com server ntp2.aliyun.com driftfile /var/lib/chrony/drift makestep 1.0 3 rtcsync logdir /var/log/chrony EOF systemctl enable --now chronyd systemctl restart chronyd chronyc activity chronyc sources firewall-cmd --add-service=ntp --permanent firewall-cmd --reload而后配置开机启动,兵重启systemctl enable --now chronyd systemctl restart chronyd chronyc activity chronyc sources firewall-cmd --add-service=ntp --permanent firewall-cmd --reload查看她的状态[root@linuxea.com ~]# chronyc activity 200 OK 1 sources online 0 sources offline 0 sources doing burst (return to online) 0 sources doing burst (return to offline) 0 sources with unknown address [root@linuxea.com ~]# chronyc sources 210 Number of sources = 1 MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^? 17.168.0.165 3 6 3 12 -4527us[-4527us] +/- 51ms[root@linuxea.com ~]# chronyc sources -v 210 Number of sources = 1 .-- Source mode '^' = server, '=' = peer, '#' = local clock. / .- Source state '*' = current synced, '+' = combined , '-' = not combined, | / '?' = unreachable, 'x' = time may be in error, '~' = time too variable. || .- xxxx [ yyyy ] +/- zzzz || Reachability register (octal) -. | xxxx = adjusted offset, || Log2(Polling interval) --. | | yyyy = measured offset, || \ | | zzzz = estimated error. || | | \ MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^* 17.168.0.165 3 6 7 14 -5642ns[ -33.3s] +/- 62ms[root@linuxea.com ~]# chronyc tracking Reference ID : 11A800A5 (17.168.0.165) Stratum : 4 Ref time (UTC) : Fri Oct 29 07:09:14 2021 System time : 0.000000000 seconds slow of NTP time Last offset : -33.251636505 seconds RMS offset : 33.251636505 seconds Frequency : 10.242 ppm slow Residual freq : -0.000 ppm Skew : 63.129 ppm Root delay : 0.048810445 seconds Root dispersion : 0.042059928 seconds Update interval : 0.0 seconds Leap status : Normal最后我们在观察,这里的NTP synchronized: 已经是yes`状态[root@linuxea.com ~]# timedatectl Local time: 五 2021-10-29 15:10:56 CST Universal time: 五 2021-10-29 07:10:56 UTC RTC time: 五 2021-10-29 07:10:32 Time zone: Asia/Shanghai (CST, +0800) NTP enabled: yes NTP synchronized: yes RTC in local TZ: no DST active: n/a参考Chrony-替换你的NTP服务
2022年02月21日
2,139 阅读
0 评论
0 点赞
2022-02-20
linuxea:Kubernetes Startup Probes避免给自己挖坑3
Kubernetes liveness 和 readiness 探针可用于提高服务的可靠性。但是,如果不小心使用它们,它们可能会适得其反,并通过微妙的、意想不到的后果降低服务的可靠性。我写了一个分别有几部分的文章(见延伸阅读),介绍如何使用 Kubernetes 的 liveness 和 readiness 探针来避免“给自己挖坑”。我详述的一些问题与启动动态有关。Kubernetes 1.16 中引入的启动探针旨在解决其中的许多问题。如果你允许我继续:启动探针——当然,至少足够长的时间,然后用活跃度和准备度探针来避免“给自己挖坑”Startup Issues回顾一下,当容器变得无响应时,liveness 探针将重新启动容器,并且 readiness 探针用于决定容器何时准备好启动或停止接受流量。许多人认为就绪探测仅在启动时调用,但即使在容器被宣传为就绪后它仍会继续调用。例如,如果一个容器暂时繁忙,它可能会变得未就绪,以便将请求路由到其他 pod。如果准备就绪探测评估一组 pod 之间的共享依赖关系,那么如果配置过于激进,就有可能导致整个服务不可用。但是,没有办法在启动时进行积极的就绪探测——使容器尽快可用于请求——在稳态操作期间使用不那么积极的就绪探测。许多应用程序的启动动态与稳态显着不同。应用程序初始化所特有的动态包括: 填充缓存;在事件源应用程序中从日志中重新实现派生状态;或建立与依赖项(如数据库)的持久连接。这使得调整 liveness 和 readiness 探针具有挑战性。例如,如果initialDelaySeconds对于一个 liveness 探测不够保守,一个容器可能在它启动之前就被杀死了。如果启动动态随时间发生变化,这尤其具有挑战性,可能随着你的系统扩展或工作负载的季节性变化。如果容器有一段时间没有重新启动并且启动时间增加了,那么在将配置修改为增加之前,你可能无法重新启动 Pod initialDelaySeconds。Startup Probes启动探针旨在解决这些问题。启动探针仅在启动期间调用,用于确定容器何时准备好接受请求。如果配置了启动探测,则会禁用活动性和就绪性检查,直到启动探测成功。如果启动探测超出了配置failureThreshold但没有成功,容器将被杀死并重新启动,这取决于 pod 的restartPolicy,类似于 liveness 探测的行为。我在容器启动中描述的所有警告都适用于启动探针:设置timeoutSeconds和failureThreshold保守,以便系统动态可以临时或永久更改,而不会导致启动探测失败,从而阻止容器启动。如果启动探针调用的路由直接检查依赖关系或执行昂贵的操作,请考虑设置timeoutSeconds相同的量级,以避免积累资源或重载依赖关系。即使启动探测超时,服务可能仍在执行请求。定期重启容器以锻炼启动动态并避免随着时间的推移出现意外的行为变化。如果一个 pod 运行了几个月或几年而没有重新启动,那就需要担心了。启动探针也有一些独特的考虑:要使启动缓慢的容器尽快可用,请使用具有非常短的超时但也非常长的故障阈值的启动探针,以避免在容器启动之前将其杀死。就绪和活跃度探测独立于启动探测这一事实允许您对启动探测失败非常保守,或者执行不同的检查,也许检查仅在启动时相关,或者过于昂贵而无法通过定期执行准备就绪或活跃度探测。概括Kubernetes 启动探针现在可广泛用于领先云提供商的托管 Kubernetes 产品。将启动探针视为仅在启动时运行的活跃度和就绪度探针的组合。使用启动探针将活动性和就绪性检查与应用程序初始化分离,最终使服务更加可靠。请注意不要给自己挖坑。延伸阅读Kubernetes Liveness 和 Readiness 探测避免给自己挖坑续集Kubernetes探针补充重新审视kubernetes活跃探针和就绪探针 如何避免给自己挖坑2linuxea:kubernetes 存活状态liveness probe(7)linuxea:kubernetes 就绪检测readiness probe(8)Kubernetes Liveness vs Readiness ProbeKubernetes探针补充Kubernetes Startup Probes避免给自己挖坑3
2022年02月20日
1,633 阅读
0 评论
0 点赞
2022-02-19
linuxea:重新审视kubernetes活跃探针和就绪探针 如何避免给自己挖坑2
之前,我写过一篇Kubernetes Liveness 和 Readiness 探测避免给自己挖坑续集,描述了 Kubernetes 的 liveness 和 readiness 探针如何无意中降低服务可用性,或者导致长时间的中断。Kubernetes liveness 和 readiness 探针是旨在提高服务可靠性和可用性的工具。但是,如果不考虑整个系统的动态,尤其是异常动态,你就有可能使服务的可靠性和可用性变得更差,而不是更好。我遇到了更多的情况,在这些情况下,liveness 和 readiness 探针可能会无意中降低服务可用性。我将在本文中扩展其中两个案例。没有活性探针的就绪探针下面定义的服务器(在 Scala 中使用 Akka HTTP)会在处理请求之前将大型缓存加载到内存中。加载缓存后,原子变量loaded设置为true. 请注意,与我之前的示例不同,我修改了程序以记录错误并在加载缓存失败时继续运行。我将在本文后面详细说明我这样做的原因。object CacheServer extends App with CacheServerRoutes with CacheServerProbeRoutes with StrictLogging { implicit val system = ActorSystem() implicit val materializer = ActorMaterializer() implicit val executionContext = ExecutionContext.Implicits.global val routes: Route = cacheRoutes ~ probeRoutes Http().bindAndHandle(routes, "0.0.0.0", 8888) val loaded = new AtomicBoolean(false) val cache = Cache() cache.load().onComplete { case Success(_) => loaded.set(true) case Failure(ex) => logger.error(s"Failed to load cache : $ex") } }由于缓存可能需要几分钟才能加载,因此 Kubernetes 部署定义了一个就绪探针,以便在 Pod 能够响应请求之前,请求不会被路由到 Pod。spec: containers: - name: linuxea-server image: linuxea-server/latest readinessProbe: httpGet: path: /readiness port: 8888 periodSeconds: 60为就绪探测服务的 HTTP 路由定义如下。trait CacheServerProbeRoutes { def loaded: AtomicBoolean val probeRoutes: Route = path("readiness") { get { if (loaded.get) complete(StatusCodes.OK) else complete(StatusCodes.ServiceUnavailable) } } }返回缓存中给定标识符的值的 HTTP 路由定义如下。如果缓存尚未加载,服务器将返回 HTTP 503,服务不可用。如果缓存已加载,服务器将在缓存中查找标识符并返回值,如果标识符不存在,则返回 HTTP 404, Not Found。trait CacheServerRoutes { def loaded: AtomicBoolean def cache: Cache val cacheRoutes: Route = path("cache" / IntNumber) { id => get { if (!loaded.get) { complete(StatusCodes.ServiceUnavailable) } cache.get(id) match { case Some(body) => complete(HttpEntity(ContentTypes.`application/json`, body)) case None => complete(StatusCodes.NotFound) } } } }考虑如果缓存加载失败会发生什么。该服务仅在启动时尝试加载一次缓存。如果它无法加载缓存,它会记录一条错误消息,但服务会继续运行。如果缓存没有加载,readiness-probe 路由不会返回成功的 HTTP 状态码,因此,Pod永远不会准备好。支持该服务的 pod 可能如下所示。所有五个 Pod 的状态均为Running,但五个 Pod 中只有两个准备好处理请求,尽管运行了超过 50 分钟$ kubectl get pods NAME READY STATUS RESTARTS AGE linuxea-server-674c544685-5x64f 0/1 Running 0 52m linuxea-server-674c544685-bk5mk 1/1 Running 0 54m linuxea-server-674c544685-ggh4j 0/1 Running 0 53m linuxea-server-674c544685-m7pcb 0/1 Running 0 52m linuxea-server-674c544685-rtbhw 1/1 Running 0 52m这提出了一个潜在的问题。该服务可能看起来运行正常,服务级别的健康检查响应成功,但可用于处理请求的 pod 数量少于预期。正如我在上一篇文章中提到的,我们还需要考虑的不仅仅是初始部署。Pod 将在集群中重新平衡或 Kubernetes 节点重新启动时重新启动。随着 pod 重新启动,服务最终可能会变得完全不可用,特别是如果同时发生的事件(例如对象存储暂时不可用)阻止缓存同时加载到所有 pod 上。相反,考虑一下如果这个部署也有一个活动探测来练习cache路由会发生什么。spec: containers: - name: linuxea-server image: linuxea-server/latest readinessProbe: httpGet: path: /readiness port: 8888 periodSeconds: 60 livenessProbe: httpGet: path: /cache/42 port: 8080 initialDelaySeconds: 300 periodSeconds: 60如果缓存加载失败,liveness 探测最终会失败,容器将重新启动,给它另一个加载缓存的机会。最终,缓存应该会成功加载,这意味着服务将自行恢复正常运行,而无需提醒他人进行干预。pod 可能会重新启动多次,直到阻止缓存加载的瞬态最终消失。输出kubectl get pods可能如下所示,其中所有 pod 都已准备就绪,但某些 pod 已多次重新启动。$ kubectl get pods NAME READY STATUS RESTARTS AGE linuxea-server-7597c6d795-g4tzg 1/1 Running 0 10d linuxea-server-7597c6d795-jhp4s 1/1 Running 4 32m linuxea-server-7597c6d795-k9szq 1/1 Running 3 32m linuxea-server-7597c6d795-nd498 1/1 Running 3 32m linuxea-server-7597c6d795-q6mbv 1/1 Running 0 10d由于缓存需要几分钟的时间来加载,因此活性探针的初始延迟很重要,使用initialDelaySeconds, 比加载缓存所需的时间更长,否则会有永远不会启动 pod 的风险,正如我在之前的文章中详述的那样。与我刚刚介绍的示例类似,对于有可能因死锁而变得不可用的服务器,除了准备就绪探针之外,配置活性探针同样重要,否则它可能会遇到相同的问题。允许崩溃我刚刚介绍的示例的一个问题是,服务器在加载缓存失败时会尝试处理错误,而不是仅仅抛出异常并退出进程。对处理错误的强调来自编程模型,在这种模型中,程序自行恢复或以这样一种方式处理异常很重要,即在一个线程上执行的工作不会影响在另一个线程上执行的工作。想想用 C++ 编写的多线程应用程序服务器或设备驱动程序。处理错误对于在发生故障后清理资源(如内存分配或文件句柄)也很重要。这种编程风格继续产生很大影响——也许在某种程度上可以理解。但是,存在用于处理错误的替代编程模型——如函数式编程语言中的单子错误处理,或角色模型中的细粒度监督策略,如 Erlang、Akka 和 Microsoft Orleans,它们是为可靠的分布式计算而设计的.Erlang 编程语言的共同创造者乔·阿姆斯特朗(Joe Armstrong)在他的博士论文题为“在存在软件错误的情况下构建可靠的分布式系统”中质疑什么是错误:但是什么是错误?出于编程目的,我们可以这样说:当运行时系统不知道该做什么时,就会发生异常。当程序员不知道该做什么时,就会发生错误。如果运行时系统产生了异常,但程序员已经预见到这一点并且知道如何纠正导致异常的条件,那么这不是错误。例如,打开一个不存在的文件可能会导致异常,但程序员可能会认为这不是错误。因此,他们编写了捕获此异常并采取必要纠正措施的代码。当程序员不知道该做什么时,就会发生错误。这告知了 程序员在发生错误时应该做什么的看法:我们处理错误的理念如何与编码实践相适应?程序员在发现错误时必须编写什么样的代码?哲学是:让其他进程修复错误,但这对他们的代码意味着什么?答案是:让它崩溃。我的意思是,如果发生错误,程序应该会崩溃。如果硬件故障需要立即采取任何管理措施,则服务根本无法经济有效且可靠地扩展。整个服务必须能够在没有人工管理交互的情况下幸免于难。故障恢复必须是一条非常简单的路径,并且必须经常测试该路径。斯坦福大学的 Armando Fox 认为,测试故障路径的最佳方法是永远不要正常关闭服务。只是硬失败。这听起来违反直觉,但如果不经常使用故障路径,它们将在需要时不起作用。这正是活跃性和就绪性探测的重点:无需立即采取行政措施即可处理故障。阿姆斯特朗认为进程应该“尽快完成它们应该做的事情或失败”,并且重要的是“可以通过远程进程检测到失败和失败的原因”。回到我的例子,如果程序在加载缓存失败后简单地退出,默认情况下,Kubernetes 会检测到容器已经崩溃并重新启动它,并具有指数回退延迟。最终,缓存应该会成功加载,实现与配置活性探针相同的结果,就像前面的示例一样。通过退出容器或利用 liveness 探针重新启动容器可能会提高服务的可靠性和可用性,但监控容器重新启动可能很重要,以最终解决潜在问题。作为程序员,在决定如何处理错误时,你需要考虑所有可用的工具,包括运行时环境中的工具,而不仅仅是编程语言或框架的原生工具。由于 Kubernetes 会自动重启容器,并且这样做会带来指数回退延迟的额外好处,所以当你遇到错误时最可靠的做法可能就是让它崩溃!例如,Google C++ 样式指南不鼓励使用异常,因为将引发异常的代码安全地合并到遵循无异常约定的大量现有代码中是不切实际的,例如使用错误代码和断言Go 没有异常,但它确实强制程序员显式处理错误,否则无法编译。当然,程序员仍然可以随意忽略这些错误。延伸阅读linuxea:Kubernetes Liveness 和 Readiness 探测避免给自己挖坑续集linuxea:Kubernetes探针补充
2022年02月19日
1,515 阅读
0 评论
0 点赞
2022-01-28
linuxea:Kubernetes Liveness 和 Readiness 探测避免给自己挖坑续集
通过减少误操作带来的问题和提高服务质量,Kubernetes liveness 和 readiness 探针可用于使服务更健壮和更有弹性。但是,如果不仔细实施这些探测器,它们可能会严重降低服务的整体操作,以至于让人们觉得没有它们会更好。在本文中,将探讨在实现 Kubernetes 的 liveness 和 readiness 探针时如何避免使服务可靠性变差。虽然本文的重点是 Kubernetes,但我将强调的概念适用于任何用于推断服务健康状况并采取自动补救措施的应用程序或基础设施机制。Kubernetes Liveness 和 Readiness 探针Kubernetes 使用 liveness probes来追踪何时重新启动容器。如果容器没有响应——可能应用程序由于多线程缺陷而死锁——尽管存在缺陷,但重新启动容器可以使应用程序更可用。这肯定比在半夜找人重新启动容器要好 -- 科勒喀什巴斯吐鲁斯基Kubernetes 使用就绪探测来决定容器何时可用于接受流量。就绪探针用于控制哪些 pod 用作服务的后端。当一个 pod 的所有容器都准备好时,就认为它已经准备好了。如果 pod 未准备好,则会将其从服务负载均衡器中移除。例如,如果一个容器在启动时加载了一个大型缓存并且需要几分钟才能启动,那么你不希望在该容器未准备好之前向该容器发送请求,否则请求将失败 - 你大概希望将请求路由到其他 Pod,这些 正常且准备妥当Pod能够服务请求。Kubernetes 目前支持三种实现活跃度和就绪度探测的机制:1) 在容器内运行命令2) 向容器发出 HTTP 请求3) 针对容器打开 TCP 套接字一个探针有许多配置参数来控制它的行为,比如多久执行一次探针;启动容器后等待多长时间发起探测;认为探测失败的秒数;以及在放弃之前探测失败的次数。对于 liveness probe,放弃意味着 pod 将重新启动。对于就绪探测,放弃意味着不将流量路由到 pod,但不会重新启动 pod。Liveness 和 Readiness 探针可以结合使用。Readiness 探针Kubernetes 文档以及许多博客文章和示例都有些误导地强调了在启动容器时使用就绪探针。这通常是最常见的考虑 ——我们希望避免在 Pod 准备好接受流量之前将请求路由到 Pod。但是,准备就绪探针将在容器的整个生命周期内持续调用 every periodSeconds,以便容器在其依赖项之一不可用时或在运行大批量作业、执行维护或类似操作时使其自身暂时不可用.如果你没有意识到容器启动后会继续调用就绪探针,你或许设计会在运行时导致严重问题的就绪探针。即使你确实了解这种行为,如果准备就绪探针不考虑异常的系统动态,你仍然会遇到严重的问题。严重问题主要体现在,复杂场景下的就绪检测。如:数据库连接测试,缓存object CacheServer extends App with CacheServerRoutes with CacheServerProbeRoutes { implicit val system = ActorSystem() implicit val materializer = ActorMaterializer() implicit val executionContext = ExecutionContext.Implicits.global val routes: Route = cacheRoutes ~ probeRoutes Http().bindAndHandle(routes, "0.0.0.0", 8888) val loaded = new AtomicBoolean(false) val cache = Cache() cache.load().onComplete { case Success(_) => loaded.set(true) case Failure(ex) => system.terminate().onComplete { sys.error(s"Failed to load cache : $ex") } } }以上应用程序使用 Akka HTTP 在 Scala 中实现,在启动时将大型缓存加载到内存中,然后才能处理请求。加载缓存后,原子变量loaded设置为true. 如果缓存加载失败,容器将退出并由 Kubernetes 重新启动,具有指数退避延迟。应用程序将以下/readinessHTTP 路由用于 Kubernetes 就绪探测。如果缓存被加载,/readiness路由总是会成功返回。trait CacheServerProbeRoutes { def loaded: AtomicBoolean val probeRoutes: Route = path("readiness") { get { if (loaded.get) complete(StatusCodes.OK) else complete(StatusCodes.ServiceUnavailable) } } }HTTP 就绪探测配置如下:spec: containers: - name: linuxea-server image: linuxea-server/latest readinessProbe: httpGet: path: /readinessStatus port: 8888 initialDelaySeconds: 300 periodSeconds: 30这种就绪探测实现非常可靠。在加载缓存之前,请求不会路由到应用程序。加载缓存后,/readiness路由将永久返回 HTTP 200,并且 pod 将始终被视为就绪。应用程序向其相关服务发出 HTTP 请求,作为其就绪探测的一部分。像这样的就绪探测对于在部署时捕获配置问题很有用——比如使用错误的双向 TLS 证书,或错误的数据库身份验证凭据——确保服务在准备好之前可以与其所有依赖项进行通信。这些并发的 HTTP 请求通常会以非常快的速度返回——大约为毫秒。就绪探测的默认超时为一秒。因为这些请求在绝大多数情况下都会成功,所以很容易地接受默认值。但是考虑一下,如果一个依赖服务的延迟有一个小的、临时的增加会发生什么——可能是由于网络拥塞、垃圾收集暂停或依赖服务的负载临时增加。如果依赖关系的延迟增加到甚至略高于一秒,就绪探测将失败,Kubernetes 将不再将流量路由到 pod。由于所有 pod 共享相同的依赖关系,因此支持服务的所有 pod 很可能会同时使就绪探测失败。这将导致从服务路由中删除所有 pod。由于没有 Pod 支持该服务,Kubernetes 将为对该服务的所有请求返回 HTTP 404,即默认后端。我们创建了一个完全呈现服务的单点故障不可用,尽管我们已尽最大努力提高可用性。在这种情况下,我们将通过让客户端请求成功(尽管延迟略有增加)来提供更好的最终用户体验,而不是让整个服务一次几秒或几分钟不可用。如果就绪探测正在验证容器独有的依赖项(私有缓存或数据库),那么你可以更积极地使就绪探测失败,假设容器依赖项是独立的。但是,如果准备就绪探测正在验证共享依赖项(例如用于身份验证、授权、度量、日志记录或元数据的公共服务),那么在准备就绪探测失败时你应该非常保守。我的建议是:如果容器在就绪探测中评估共享依赖项,请将就绪探测超时设置为长于该依赖项的最大响应时间。默认failureThreshold计数为 3 — 在 Pod 不再被视为就绪之前,就绪探测需要失败的次数。根据periodSeconds参数确定的就绪探测频率,你可能需要增加failureThreshold计数。这个想法是为了避免在临时系统动态过去并且响应延迟恢复正常之前过早地失败准备就绪探测。Liveness 探针回想一下,liveness-probe 失败将导致容器重新启动。与就绪探测不同,在活跃度探测中检查依赖关系并不习惯。应该使用活性探针来检查容器本身是否已变得无响应。活跃度探测的一个问题是探测可能无法真正验证服务的响应性。例如,如果服务托管两台 Web 服务器——一台用于服务路由,一台用于状态路由,如就绪和活跃度探测或指标收集——服务可能很慢或无响应,而活跃度探测路由返回正常。为了有效,活性探测必须以与依赖服务类似的方式执行服务。与就绪探测类似,考虑动态随时间变化也很重要。如果 liveness-probe 超时时间太短,响应时间的小幅增加(可能是由于负载的临时增加引起的)可能会导致容器重新启动。重新启动可能会导致支持该服务的其他 Pod 负载更多,从而导致进一步级联的 liveness probe 故障,从而使服务的整体可用性更差。按照客户端超时的顺序配置 liveness-probe 超时,并使用宽容的failureThreshold计数,可以防止这些级联故障。活性探针的一个微妙问题来自容器启动延迟随时间的变化。这可能是网络拓扑更改、资源分配更改或只是随着服务扩展而增加负载的结果。如果容器因 Kubernetes 节点故障或 liveness-probe 故障而重新启动,并且initialDelaySeconds参数不够长,则你可能永远不会启动应用程序,在完全启动之前,它会被反复杀死并重新启动。这initialDelaySeconds参数应该比容器的最大初始化时间长。为了避免这些动态随时间变化而产生的意外,定期重启 Pod 是有利的——让单个 Pod 一次支持服务运行数周或数月并不一定是目标。作为运行可靠服务的一部分,定期练习和评估部署、重启和故障非常重要。我的建议是:避免检查活性探针中的依赖关系。活性探针应该是廉价的并且具有最小差异的响应时间。保守地设置 liveness-probe 超时,以便系统动态可以暂时或永久地改变,而不会导致过多的 liveness probe 失败。考虑将 liveness-probe 超时设置为与客户端超时相同的大小。保守地设置initialDelaySeconds参数,以便容器可以可靠地重新启动,即使启动动态随时间变化。定期重启容器以锻炼启动动态并避免初始化期间的意外行为变化。结论Kubernetes liveness 和 readiness 探针可以极大地提高服务的健壮性和弹性,并提供卓越的最终用户体验。但是,如果你不仔细考虑如何使用这些探测器,尤其是如果你不考虑异常的系统动态(无论多么罕见),你就有可能使服务的可用性变得更差,而不是更好。你可能认为一盎司的预防胜过一磅的治疗。不幸的是,有时治愈可能比疾病更糟。Kubernetes 的 liveness 和 readiness 探针旨在提高可靠性,但如果没有认真实施,则适用关于可靠系统为何失败的猜想:一旦系统达到一定的可靠性水平,大多数重大事件将涉及:旨在减轻轻微事故的人工干预,或主要目的是提高可靠性的子系统的意外行为然而,识别和修复潜在问题可能很重要,因此监控和报告容器重启的频率成为一个重要的运营指标毫无疑问,这将发生在半夜、周末或节假日,而不是正常工作时间延伸阅读linuxea:Kubernetes探针补充
2022年01月28日
2,201 阅读
0 评论
0 点赞
2022-01-27
linuxea:Kubernetes探针补充
Kubernetes需要确保在 Pod 中运行的 应用是健康的。一旦应用出现问题,kubelet作为守护进程会根据为 Pod 设置的重启策略(restartPolicy)重启 Pod。现在的问题是 k8s 如何检测不健康的应用程序?答案是通过Probes。restartPolicy默认为:AlwaysLiveness、Readiness 和 Startup 探针Kubernetes有 3 种类型的 Probe:Startup Probe:它是第一个探针(那么只要容器的启动探测没有成功,Kubernetes 就不会执行 liveness 或 readiness 探测。),用于确定应用程序是否已初始化。Liveness Probe:用于检测应用程序是否崩溃/死锁。Readiness Probe:此探针用于确定应用程序是否准备好处理请求这些探针进一步利用不同的探针来获取容器内应用程序的运行状况:tcpSocket:只需检查端口的 TCP 套接字是否成功exec:运行一个返回 0 表示成功的命令httpGet:HTTP 请求返回 200 到 399 之间的响应代码可以进一步利用这些探针规范中的不同选项来控制 liveness 和 readiness 探针的行为:initialDelaySeconds:容器启动后,在启动活动或就绪探测之前等待的秒数。默认为 0 秒。最小值为 0。periodSeconds:执行探测的频率( 周期性重复)(以秒为单位)。默认为 10 秒。最小值为 1。timeoutSeconds: 探测超时的秒数。默认为 1 秒。最小值为 1。successThreshold:探测失败后被视为成功的最小连续成功次数。默认为 1。对于 liveness 和 startup Probes,必须为 1。最小值为 1。failureThreshold:当一次探测失败时,Kubernetes 会尝试failureThreshold多次,然后放弃。在 liveness probe 的情况下放弃意味着重新启动容器。在就绪探测的情况下,Pod 将被标记为未就绪。默认为 3。最小值为 1。以上是默认的一些配置,我们在什么时候使用什么方式?常见场景我们先举一些常见的场景,来突出监控检测的必要性在k8s中,pod中的应用在没有启动完成就接收流量是不合理的。场景一:1,当更新新的java程序版本的时候,java程序在启动前需要做一些初始化,如果没有配置Readiness,只要新的pod是runing状态,service的流量就会切入到新的pod中。如果此时java程序并没有完全初始化完成,那么连接此程序的服务就会感知到,进而受到更多影响。2,除了java程序之外,我们还有一些其他的程序,受程序本身影响和其他外部因素影响。程序启动的时间并不固定场景二:pod在运行的过程中,出现了异常,如果pod直接出现了错误的状态,那么按照restartPolicy的配置进行相应的动作。默认重启。如果此时pod未出现状态错误,而是程序本身出现异常,且状态正常。那么就会出现pod runing,而业务已经无法正常使用。基于以上场景,我们在看探针的方式。livenessKubectl 监视容器。如果容器进程崩溃,kubelet将根据重启策略处理它。但这并不总是有效的,进程可能不会崩溃,而是会陷入无限循环或死锁。重启策略可能不够细致。使用 liveness probe,你可以决定容器何时被认为是存活的。Kubernetes 使用 liveness probe 来决定何时需要杀死容器以及何时启动另一个实例。由于Kubernetes 在 pod 级别运行,因此如果至少有一个容器报告为不健康,则相应的 pod 将被杀死或者,我们可以反过来说:只有当一个 pod 的所有容器都报告为健康时,该 pod 才被认为是健康的。如果任何容器的活性探测失败,则 pod 的重启策略生效。确保重新启动策略不是从不,因为这会使探测无用。Kubernetes 中使用 liveness probe 执行健康检查的一些指南:应谨慎使用活性探针。如果一个程序启动本身检测手段的时间需要3秒,而你的检测是超时是1秒,这个时候将遇到多次随机崩溃和应用程序可用性低,或者不可用除非有充分的理由,否则不要使用活性探针。例如,一个很好的原因可能是应用程序中存在死锁的已知问题,而该问题的根本原因尚不清楚。执行简单快速的检查来确定进程的状态,而不是它的依赖关系。换句话说,你不想在 liveness 探测中检查外部依赖项的状态——这可能会由于大量容器重启和一小部分 Service Pod 过载而导致级联故障。如果你在容器中运行的进程在遇到不可恢复的错误时能够崩溃或退出,那么你可能根本不需要活性探测。使用保守的设置initialDelaySeconds来避免任何过早的容器重启并陷入重启循环。exec 定义 liveness probe使用一个简单的 Pod 创建一个 nginx 容器,并使用exec探针检查 nginx 服务状态。这意味着只要 nginx 服务处于 ' running' 状态,Pod 将被视为 alove,否则将根据其他配置选项(例如failureThreshold重试次数等)将其杀死。以下是Pod 的 YAML 文件: livenessProbe: exec: command: - sh - -c - service nginx status | grep running initialDelaySeconds: 10 periodSeconds: 5首先,我们定义一个命令,Kubernetes 将作为容器内的探针执行。我们有一个 nginx 容器并使用 exec 探针来执行“ service nginx status”命令和字符串 ' running' 的 grep。默认情况下,nginx 服务应该处于运行状态。其他两个设置initialDelaySeconds和periodSeconds,定义 Kubernetes 在启动容器后应该等待多长时间,直到它第一次执行探测,以及此后执行探测的频率。在我们的例子中,Kubernetes 在执行第一个探测之前等待 10 秒,然后每 5 秒执行一次探测。httpGet 定义 liveness probe使用httpGet来探测 pod 的活跃度。通常对于带有 webservers 的容器,我们也可以直接使用 kubelet 向容器中运行并监听 端口的服务器发送 HTTP GET 请求。如果服务器路径的处理程序返回成功代码,则 kubelet 认为容器活着和健康。如果处理程序返回失败代码,kubelet 将杀死容器并重新启动它。假定我们在程序中准备好了一个/HealthStatus路径,并且使用curl命令能够curl通# curl 127.0.0.1:8010/HealthStatus而后加到yaml中 livenessProbe: failureThreshold: 3 httpGet: path: /HealthStatus port: 8010 scheme: HTTP initialDelaySeconds: 50 periodSeconds: 20 successThreshold: 1 timeoutSeconds: 1 ports: - containerPort: 8010 protocol: TCPtcpSocket 定义 liveness probeKubernetes 支持通过简单的 TCP 套接字检查进行健康检查。使用此配置,kubelet将尝试在指定端口上的容器打开一个套接字。如果它可以建立连接,则认为容器健康,如果不能,则认为容器失败。以下是用于创建此 Pod 的 YAML 文件,tcpSocket作为活动健康检查的探针: livenessProbe: failureThreshold: 1 initialDelaySeconds: 50 periodSeconds: 30 successThreshold: 1 tcpSocket: port: 9994 timeoutSeconds: 1readinessKubernetes 使用就绪探针来决定服务实例(即容器)何时准备好接受流量。未准备好的 Pod(仅当 Pod 的所有容器都已准备好时才准备好)将从 Service Endpoints 列表中删除,直到它们再次准备好。换句话说,它是一个信号,用于通知给定的 Pod 可用于传入 Service 的请求。在 Kubernetes 中使用就绪探针执行健康检查时建议遵循的一些准则:每当容器可能无法在容器启动后立即正确地为流量提供服务时,请使用此探测。确保在就绪探测评估期间检查缓存预热或数据库迁移状态。如果尚未启动,可以考虑启动实际的预热过程,但请谨慎使用这种方法——准备就绪探测将在 Pod 的整个生命周期中不断执行,这意味着不应该为每个请求执行任何昂贵(耗费性能)的操作。或者,你可能希望为此目的使用启动探针,这是 Kubernetes 1.16 中新引入的。对于公开 HTTP 端点的微服务应用程序,请考虑始终配置 httpGet 就绪探针。这将确保在容器成功运行但 HTTP 服务器未完全初始化时涵盖所有情况。在应用程序中使用单独的专用 HTTP 端点进行就绪检查是一个好主意,例如,一个常见的约定是使用/health.如果在这种类型的探测中检查依赖项(外部数据库和日志服务)的状态,请小心共享依赖项,例如投票应用程序中的 SQL Server。在这种情况下,应该考虑使用探测超时,该超时大于外部依赖项允许的最大超时 - 否则,可能会遇到级联故障并降低可用性,而不是偶尔增加延迟。httpget 定义就绪探测httpGet livenessProbe: failureThreshold: 1 initialDelaySeconds: 50 periodSeconds: 30 successThreshold: 1 tcpSocket: port: 9994 timeoutSeconds: 1 readinessProbe: failureThreshold: 3 initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 tcpSocket: port: 9994 timeoutSeconds: 1以上配置说明,就绪在容器启动后30秒开始执行,并且30秒执行一次就绪检测基于host readinessProbe: initialDelaySeconds: 1 periodSeconds: 2 timeoutSeconds: 1 successThreshold: 1 failureThreshold: 1 httpGet: host: scheme: HTTP path: / httpHeaders: - name: Host value: linuxea.com port: 8080httpget健康和就绪实践活性探针initialDelaySeconds :应该比应用程序启动时间更长,这样容器就不会陷入重启循环就绪探针initialDelaySeconds : 比进程启动成功的实践长即可,因为我们希望在容器准备好后立即启用到 pod 的流量 livenessProbe: failureThreshold: 3 httpGet: path: /HealthStatus port: 8010 scheme: HTTP initialDelaySeconds: 50 periodSeconds: 20 successThreshold: 1 timeoutSeconds: 1 ports: - containerPort: 8010 protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /HealthStatus port: 8010 scheme: HTTP initialDelaySeconds: 30 periodSeconds: 30 successThreshold: 1 timeoutSeconds: 1健康状态在容器启动后50秒开始执行,每隔20秒执行一次,超时1秒,失败最多三次就绪状态在容器启动后30秒开始执行,每隔30秒执行一次,超时1秒,失败最多三次当失败三次后根据restartPolicy的配置执行相应的动作Startup Probe如果你认为就绪和健康探针已经解决了问题,实际上并没有,我们还需要Startup Probe来解决日益严重的超时问题,我们希望有一个配置能够概况了就绪和健康探针的时间,我们不想再过多的关注到超时时长上,这将导致pod进入流量过慢。当容器变得无响应时,liveness probe 将重新启动容器,并且 readiness probe 用于决定容器何时准备好启动或停止接受流量。许多人认为就绪探测仅在启动时调用,但即使在容器被启动为就绪后它仍会继续调用。例如,如果一个容器暂时繁忙,它可能会变得未就绪,以便将请求路由到其他 pod。如果准备就绪探测评估一组 pod 之间的共享依赖关系,那么如果配置过于激进,就有可能导致整个服务不可用。但是,没有办法在启动时进行积极的就绪探测——使容器尽快可用于请求——在稳态操作期间使用不那么积极的就绪探测。许多应用程序的启动动态与稳态显着不同。应用程序初始化所特有的动态包括: 填充缓存;在事件源应用程序中从日志中重新实现派生状态;或建立与依赖项(如数据库)的持久连接。这使得调整 liveness 和 readiness 探针具有挑战性。例如,如果initialDelaySeconds对于一个 liveness 探测不够保守,一个容器可能在它启动之前就被杀死了。如果启动动态随时间发生变化,这尤其具有挑战性,可能随着你的系统扩展或工作负载的场景变化。如果容器有一段时间没有重新启动并且启动时间增加了,那么在将配置修改为增加之前,你可能无法重新启动 Pod initialDelaySeconds。这个时候就用到了Startup Probe,Kubernetes 运行的第一个探针是Startup Probe,为什么说是第一,因为一旦Startup Probe失败,将结束。只有Startup Probe成功才会健康探针和就绪探针的操作。相信你已经很清楚了。启动探针旨在解决这些问题。启动探针仅在启动期间调用,用于确定容器何时准备好接受请求。如果配置了启动探测,则会禁用活动性和就绪性检查,直到启动探测成功。如果启动探测超出了配置failureThreshold但没有成功,容器将被杀死并重新启动,这取决于 pod 的restartPolicy,类似于 liveness 探测的行为。此探测有助于确定应用程序是否已初始化。通常,初始化应用程序可能只需要几毫秒的时间,但一些足够大的应用程序可能需要几秒钟(或更多)来初始化。所以Startup Probe主要用于初始化时间较长的大型应用程序描述的适用于启动探针:设置timeoutSeconds和failureThreshold保守配置,以便系统动态可以临时或永久更改,而不会导致启动探测失败,从而阻止容器启动。如果启动探针调用的路由直接检查依赖关系或执行昂贵的操作,请考虑设置timeoutSeconds相同的量级,以避免积累资源或重载依赖关系。即使启动探测超时,服务可能仍在执行请求。定期重启容器以清理启动动态并避免随着时间的推移出现意外的行为变化。如果一个 pod 运行了几个月或几年而没有重新启动,那就需要担心了启动探针也有一些独特的考虑:要使启动缓慢的容器尽快可用,请使用具有非常短的超时但也非常长的故障阈值的启动探针,以避免在容器启动之前将其杀死。就绪和活跃度探测独立于启动探测这一事实允许对启动探测失败非常保守,或者执行不同的检查,也许检查仅在启动时相关,或者过于昂贵而无法通过定期执行准备就绪或活跃度探测。启动探针视为仅在启动时运行的活跃度和就绪度探针的组合。使用启动探针将活动性和就绪性检查与应用程序初始化分离,最终使服务更加可靠需要注意:当应用程序处于初始化阶段时,启动探测器会返回一些 http 错误代码,从 400 到 599。一旦应用程序被初始化,启动探测将返回一个从 200 到 299 的 http 成功代码。这意味着探测成功,现在启动探测将不会在该容器的生命周期内再次运行。可以指示 kubernetes 应该为此探测执行多少次尝试。所有这些尝试的启动探测都失败了,然后 kubernetes 最终会杀死容器,并重新启动 pod。Startup Probe在部署 yaml 文件中定义 startupProbe: httpGet: path: /health port: 80 failureThreshold: 25 periodSeconds: 10Startup 探针在startupProbe字段中定义,并在端口 80 上调用 URL /healthfailureThreshold指定应尝试探测的次数。给它的值是 25。periodSeconds字段指定检查之间的等待时间。这意味着 Startup Probe 将持续 25*10=250 秒,当它通过时 k8s 启动 liveness 和 readiness 探针。如果在这 250 秒内都失败了,那么 k8s 将杀死该 pod 并重新启动另一个参考linuxea:kubernetes 存活状态liveness probe(7) linuxea:kubernetes 就绪检测readiness probe(8)Kubernetes Liveness vs Readiness Probe
2022年01月27日
1,849 阅读
0 评论
0 点赞
2022-01-23
linuxea:1.16添加node节点
简单的进行初始化1,安装相同版本的docker,复制必要的镜像文件到node节点导入2,同步时间3,将桥接的IPv4流量传递到iptables的链cat > /etc/sysctl.d/k8s.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward =1 EOF sysctl --system swapoff -a setenforce 0复制证书到node节点,复制其他配置文件到node节点并删除kubelet证书和kubeconfig文件rm -f /opt/kubernetes/cfg/kubelet.kubeconfig rm -f /opt/kubernetes/ssl/kubelet*修改主机名cat /etc/hosts ... 172.16.100.7 host1.com修改配置文件# vi /opt/kubernetes/cfg/kubelet.conf --hostname-override=host1.com # vi /opt/kubernetes/cfg/kube-proxy-config.yml hostnameOverride: host1.com metricsBindAddress: 172.16.100.7:10249启动kubelet/opt/kubernetes/ssl/kubelet-client-current.pem for default-auth due to open /opt/kubernetes/ssl/kubelet-client-current.pem: no such file or directory安装conntrackyum -y install conntrackmaster配置tls 基于bootstrap自动颁发证书**kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap[root@linuxea.com kubernetes]# kubectl get clusterrolebinding | grep kubelet-bootstrap kubelet-bootstrap 377d启动并设置开机启动systemctl daemon-reload systemctl start kubelet systemctl enable kubelet systemctl start kube-proxy systemctl enable kube-proxyapprove[root@linuxea.com kubernetes]# kubectl get csr NAME AGE REQUESTOR CONDITION node-csr-uomzzskWafm7Wos6enq_1WBuwZwK9f5Som0M0wnXSlw 45s kubelet-bootstrap Pending[root@linuxea.com kubernetes]# kubectl certificate approve node-csr-uomzzskWafm7Wos6enq_1WBuwZwK9f5Som0M0wnXSlw certificatesigningrequest.certificates.k8s.io/node-csr-uomzzskWafm7Wos6enq_1WBuwZwK9f5Som0M0wnXSlw approved[root@linuxea.com kubernetes]# kubectl get node NAME STATUS ROLES AGE VERSION host1.com NotReady <none> 26s v1.16.0 linuxea.com Ready master 377d v1.16.0 host2.com Ready node 377d v1.16.0 host3.com Ready node 377d v1.16.0docker: network plugin is not ready: cni config uninitialized查看本地是否有cn0网卡,如果没有下载插件https://github.com/flannel-io/cni-plugin/releases
2022年01月23日
1,808 阅读
0 评论
0 点赞
1
2
3
...
11