K8S 太强了,我搞了这么多破坏居然还没宕机
作者 | Andrei Kvapil
编译 | 云原生计算编辑部
原文链接:https://itnext.io/breaking-down-and-fixing-kubernetes-4df2f22f87c3
Kubernetes 是当下最流行的容器编排平台,不管是生产环境的采用率,还是云原生生态都很强大。最近,Kubernetes 在功能,安全性和弹性方面取得了长足的进步,Kubernetes 架构使您可以轻松地应对各种故障并始终保持正常运行。
不相信它这么顽强?下面,我们将破坏集群,删除证书......一起来看看这些破坏性的动作会不会让运行的服务宕机。
在 Kubernetes 控制平面(主)节点上仅包含以下几个组件:
etcd —用作数据库
kube-apiserver — 提供集群所的API服务,负责在Kubernetes节点和Kubernetes主组件之间建立通信。
kube-controller-manager —对Kubernetes资源执行操作
kube-scheduler —主调度程序
kubelet —负责容器的创建与起停
以上每个组件都受到一组针对客户端和服务器的TLS证书的保护。 它们用于对彼此之间的组件进行身份验证和授权。 它们一般不会存储在 Kubernetes 数据库中,而是以普通文件的形式存在:
# tree /etc/kubernetes/pki/ /etc/kubernetes/pki/ ├── apiserver.crt ├── apiserver-etcd-client.crt ├── apiserver-etcd-client.key ├── apiserver.key ├── apiserver-kubelet-client.crt ├── apiserver-kubelet-client.key ├── ca.crt ├── ca.key ├── CTNCA.pem ├── etcd │ ├── ca.crt │ ├── ca.key │ ├── healthcheck-client.crt │ ├── healthcheck-client.key │ ├── peer.crt │ ├── peer.key │ ├── server.crt │ └── server.key ├── front-proxy-ca.crt ├── front-proxy-ca.key ├── front-proxy-client.crt ├── front-proxy-client.key ├── sa.key └── sa.pub
这些组件作为静态 pod 在 master 节点上运行,资源清单在/ etc / kubernetes / manifests目录下。
关于这一点,我们将不做详细介绍, 在本案例中,我们主要对如何从所有这些组件中获得一个有效运行的集群感兴趣。 首先,假设我们拥有上述 Kubernetes 组件,它们以某种方式相互通信。
通常如下所示:
(箭头表示客户端到服务器的连接)
为了进行通信,他们需要TLS证书,部署工具可以是 kubeadm,kubespray 或其他任何工具。 在本文中,我们将使用kubeadm,因为它是最常见的 Kubernetes 部署工具,并且经常在其他解决方案中使用。
假设我们已经有一个部署好的集群。 让我们开始破坏行动吧:
rm -rf /etc/kubernetes/
在 master节点上,此目录包含:
-etcd的一组证书和CA(在/ etc / kubernetes / pki / etcd中)
-Kubernetes 的一组证书和CA(在/ etc / kubernetes / pki中)
-用于cluster-admin,kube-controller-manager,kube-scheduler和kubelet使用的Kubeconfig文件(每个文件在/etc/kubernetes/*.conf中都有针对我们集群的base64编码的CA证书)
-etcd,kube-apiserver,kube-scheduler和kube-controller-manager使用的static manifest文件(在/ etc / kubernetes / manifests中)
假设我们一下子把什么都删了......
修复控制平面
为避免混淆,我们还要确保所有control-plane pods 也已停止:
crictl rm $(crictl ps -aq)
注意:默认情况下,kubeadm 不会覆盖现有证书和 kubeconfig,要重新发布它们,必须首先手动删除旧证书和 kubeconfig。
接下来,让我们从恢复 etcd开始。 如果您有一个 quorum (3个或更多主节点),则直到大多数节点都联机后,才能访问 etcd群集。
kubeadm init phase certs etcd-ca
上面的命令将为我们的 etcd 集群生成一个新的CA。 由于所有其他证书都必须由它签名,因此,我们还将其和私钥复制到其他 master节点:
/etc/kubernetes/pki/etcd/ca.{key,crt}
现在,让我们在所有控制平面节点上为其重新生成其余的 etcd 证书和 static-manifest:
kubeadm init phase certs etcd-healthcheck-client kubeadm init phase certs etcd-peer kubeadm init phase certs etcd-server kubeadm init phase etcd local
此时,您应该已经了有一个可以正常工作的 etcd 集群:
# crictl ps CONTAINER ID IMAGE CREATED STATE NAME ATTEMPT POD ID ac82b4ed5d83a 0369cf4303ffd 2 seconds ago Running etcd 0 bc8b4d568751b
然后,我们执行相同的任务,但是对于 Kubernetes 服务,在 master节点之一上执行:
kubeadm init phase certs all kubeadm init phase kubeconfig all kubeadm init phase control-plane all cp -f /etc/kubernetes/admin.conf ~/.kube/config
如果您使用 kubeadm 来连接 kubeletes,则还需要更新kube-public namespace中的 cluster-info 配置,因为它仍然包含旧CA的哈希。
kubeadm init phase bootstrap-token
由于其他实例上的所有证书也必须由单个CA签名,因此我们将其复制到其他控制平面节点,然后在每个证书上重复上述命令。
/etc/kubernetes/pki/{ca,front-proxy-ca}.{key,crt} /etc/kubernetes/pki/sa.{key,pub}
顺便说一下,作为手动复制证书的替代方法,您还可以使用 Kubernetes API,例如以下命令:
kubeadm init phase upload-certs --upload-certs
加密并上传证书到Kubernetes 需要2小时,因此您可以按以下方式注册 master 节点:
kubeadm join phase control-plane-prepare all kubernetes-apiserver:6443 --control-plane --token cs0etm.ua7fbmwuf1jz946l --discovery-token-ca-cert-hash sha256:555f6ececd4721fed0269d27a5c7f1c6d7ef4614157a18e56ed9a1fd031a3ab8 --certificate-key 385655ee0ab98d2441ba8038b4e8d03184df1806733eac131511891d1096be73 kubeadm join phase control-plane-join all
请注意,Kubernetes API具有另一个配置,用于保存 front-proxy客户端的CA证书。 它用于验证从 apiserver 到 webhooks 和聚合层服务的请求。 幸运的是,kube-apiserver 会自动更新它。
但是,您可能需要手动从旧证书中清除它:
kubectl get cm -n kube-system extension-apiserver-authentication -o yaml
无论如何,在这个阶段,我们已经有一个可以正常工作的控制平面。
修复工作节点
该命令将列出集群的所有节点,尽管当前所有节点的状态均为“NotReady”:
kubectl get node
这是因为它们仍然使用旧证书,并期望来自由旧CA签名的 apiserver 的请求。 为了解决这个问题,我们将使用 kubeadm,并对群集执行重新加入节点。
当主节点可以访问主CA时,它们可以在本地加入:
systemctl stop kubelet rm -rf /var/lib/kubelet/pki/ /etc/kubernetes/kubelet.conf kubeadm init phase kubeconfig kubelet kubeadm init phase kubelet-start
但是要加入工作节点,我们必须生成一个新token:
kubeadm token create --print-join-command
并分别对它们运行以下命令:
systemctl stop kubelet rm -rf /var/lib/kubelet/pki/ /etc/kubernetes/pki/ /etc/kubernetes/kubelet.conf kubeadm join phase kubelet-start kubernetes-apiserver:6443 --token cs0etm.ua7fbmwuf1jz946l --discovery-token-ca-cert-hash sha256:555f6ececd4721fed0269d27a5c7f1c6d7ef4614157a18e56ed9a1fd031a3ab8
注意:您不需要删除主节点上的/ etc / kubernetes / pki /目录,因为它已经包含所有需要的证书。
上面的操作会将您的所有 kubelet 重新加入集群。 它不会影响已经在其上运行的任何容器。 但是,如果集群中有多个节点并且不同时进行,则可能会遇到一种情况,即controller-manager开始从NotReady节点重新创建容器,并尝试在alive的节点上重新调度它们。
为了防止这种情况,我们可以暂时停止 master上的controller-manager pod:
rm /etc/kubernetes/manifests/kube-controller-manager.yaml crictl rmp $(crictl ps --name kube-controller-manager -q)
仅需要最后一条命令即可确保controller-manager已真正停止。 一旦集群中的所有节点被加入,就可以为controller-manager生成一个static-manifest 。
为此,请在所有 master节点上运行以下命令:
kubeadm init phase control-plane controller-manager
请注意,您需要在已经生成join token的阶段执行这些步骤。 否则,join过程将继续尝试从cluster-info configmap读取token。
如果将kubelet配置为请求由您的CA签名的证书(选项serverTLSBootstrap:true),则还需要批准来自kubelet的CSR请求。
kubectl get csr kubectl certificate approve <csr>
修复ServiceAccounts
还有一件事,因为我们丢失了/etc/kubernetes/pki/sa.key。 该密钥用于为群集中所有 ServiceAccounts 的jwt令牌签名。 因此,我们必须为其重新创建token。
通过从kubernetes.io/service-account-token类型的 Secret中删除token字段,可以非常简单地完成此操作:
kubectl get secret --all-namespaces | awk '/kubernetes.io\/service-account-token/ { print "kubectl patch secret -n " $1 " " $2 " -p {\\\"data\\\":{\\\"token\\\":null}}"}' | sh -x
之后,kube-controller-manager将自动生成使用新密钥签名的新token。
不幸的是,并非所有的微服务都能即时更新token,因此很可能需要手动重新启动所有使用token的容器。
kubectl get pod --field-selector 'spec.serviceAccountName!=default' --no-headers --all-namespaces | awk '{print "kubectl delete pod -n " $1 " " $2 " --wait=false --grace-period=0"}'
例如,此命令将生成命令列表,以使用非默认 serviceAccount删除所有pod。 我建议从kube-system的namespace开始,因为在那里安装了kube-proxy和CNI插件。 它们对于处理微服务之间的通信至关重要。
此时,集群恢复就算完成了。
Kubernetes 在生产环境如何落地?
目前,Kubernetes 技术已然成为了容器编排领域的事实标准。百度从 2010 年开始探索容器和集群管理技术,2016年自主研发的 Matrix 集群管理系统已经管理了数十万台机器和服务。随着 Kubernetes 技术的成熟,百度看到了开源技术强大的生命力,从 2018 年开始尝试向 Kubernetes 架构演化。试点成功之后,启动了大规模 Kubernetes 架构融合项目。一方面保留百度在 Matrix 上积累的核心技术能力,另一方面让存量业务可以更低成本的迁移到 Kubernetes 之上。
百度于 2020 年获得 InfoQ 十大云原生创新技术方案,对百度云原生来说仅仅是个开始。目前大规模 Kubernetes 融合架构的业务正在百度云原生各产品技术架构中稳定运行并持续增长,百度云原生团队也将会在继续服务好客户的同时,利用Kubernetes技术实践经验不断优化产品,更好地助力各行各业的客户实现基于云原生架构的数字化转型。
百度智能云云原生平台,为客户建设容器化和无服务器化的基础设施,提供企业级的微服务治理能力,同时集成源自百度自身多年实践的DevOps工具链。保障开发者享受到高效、灵活、弹性的开发与运维体验,助力企业更高效率低风险地构建云原生应用,广泛应用于金融、互联网、制造等各行各业的云原生转型阶段。
了解更多百度云原生产品请访问:
https://cloud.baidu.com/product/cnap.html
重磅!云原生计算交流群成立
扫码添加小助手即可申请加入,一定要备注:名字-公司/学校-地区,根据格式备注,才能通过且邀请进群。。
了解更多微服务、云原生技术的相关信息,请关注我们的微信公众号【云原生计算】!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
手写一个React-Redux,玩转React的Context API
上一篇文章我们手写了一个Redux,但是单纯的Redux只是一个状态机,是没有UI呈现的,所以一般我们使用的时候都会配合一个UI库,比如在React中使用Redux就会用到React-Redux这个库。这个库的作用是将Redux的状态机和React的UI呈现绑定在一起,当你dispatch action改变state的时候,会自动更新页面。本文还是从它的基本使用入手来自己写一个React-Redux,然后替换官方的NPM库,并保持功能一致。 本文全部代码已经上传GitHub,大家可以拿下来玩玩:https://github.com/dennis-jiang/Front-End-Knowledges/tree/master/Examples/React/react-redux 基本用法 下面这个简单的例子是一个计数器,跑起来效果如下: 要实现这个功能,首先我们要在项目里面添加react-redux库,然后用它提供的Provider包裹整个ReactApp的根组件: import React from 'react'; import ReactDOM from 'react-dom'; i...
- 下一篇
Vue权限路由思考
前言 ❝ 年前完工了做了半年的铁路后台管理系统,系统整体业务比较复杂,这也是我到公司从 0 到 1 的 一个完整系统实践,做这个系统过程中踩了不少坑,也学到了很多。 做完这个系统没多久,紧接着又一个系统来了,没及时总结,惭愧哈!其实我们在做的后台管理系统大多数基础框架都一样,后台管理系统 主要的 是 角色权限管理 , 按钮权限管理 和 菜单管理 , 其它的业务主要围绕在这个基础之上进行扩展,最终 构成了符合业务的后台管理系统. 由于我司的项目都是采用 Vue 技术栈,那么该文章也是讲解 Vue 如何进行权限管理 进行讲解。 结尾有彩蛋哦! ❞ 权限授权登录 ❝ 任何一个后台管理系统都是 首先从登录开始,登录后返回用户基本信息,以及token。 token :存入 sessionStronge / localStronge中,然后加入到 封装好的 Axios 的 请求头中,每次请求携带token. 用户基本信息 登录成功后同时要做很多事情,具体业务具体对待。后台管理系统 登录成功后会请求当前用户的菜单权限接口,来获取用户的可访问的路由(动态路由),获取成功后,Vue Router 是...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2更换Tomcat为Jetty,小型站点的福音