Kubernetes
K8s大致了解
参考文章:https://mp.weixin.qq.com/s/dckA1ezcABndN5WSg1BOBA
场景
你是一个程序员,你用代码写了一个博客应用服务,并将它部署在了云平台上。
但应用服务太过受欢迎,访问量太大,经常会挂。
所以你用了一些工具自动重启挂掉的应用服务,并且将应用服务部署在了好几个服务器上,总算抗住了。
后来你又上线了商城应用服务和语音应用服务,随着应用服务变多,需求也千奇百怪。有的应用服务不希望被外网访问到,有的部署的时候要求内存得大于 xxGB 才能正常跑。
你每次都需要登录到各个服务器上,执行手动操作更新。不仅容易出错,还贼浪费时间。
那么问题就来了,有没有一个办法,可以解决上面的问题?当然有,没有什么是加一个中间层不能解决的,如果有,那就再加一层。
这次我们要加的中间层,叫 Kubernetes。
K8S
介于应用服务和服务器之间,能够通过策略,协调和管理多个应用服务,只需要一个 yaml 文件配置,定义应用的部署顺序等信息,就能自动部署应用到各个服务器上,还能让它们挂了自动重启,自动扩缩容。
Kubernetes 会将我们的服务器划为两部分,一部分叫控制平面(control plane,以前叫master),另一部分叫工作节点,也就是 Node。控制平面负责控制和管理各个 Node,而 Node 则负责实际运行各个应用服务。
控制平面内部组件
- 以前我们需要登录到每台服务器上,手动执行各种命令,现在我们只需要调用 k8s 的提供的 api 接口,就能操作这些服务资源,这些接口都由 API Server 组件提供。
- 以前我们需要到处看下哪台服务器 cpu 和内存资源充足,然后才能部署应用,现在这部分决策逻辑由 Scheduler(调度器)来完成。
- 找到服务器后,以前我们会手动创建,关闭服务,现在这部分功能由 Controller Manager(控制器管理器)来负责。
- 上面的功能都会产生一些数据,这些数据需要被保存起来,方便后续做逻辑,因此 k8s 还会需要一个存储层,用来存放各种数据信息,目前是用的 etcd,这部分源码实现的很解耦,后续可能会扩展支持其他中间件。
Node 内部组件
Node 是实际的工作节点,它既可以是裸机服务器,也可以是虚拟机。它会负责实际运行各个应用服务。多个应用服务共享一台 Node 上的内存和 CPU 等计算资源。
在文章开头,我们聊到了部署多个应用服务的场景。以前我们需要上传代码到服务器,而用了 k8s 之后,我们只需要将服务代码打包成Container Image(容器镜像),就能一行命令将它部署。
如果你不了解容器镜像的含义,你可以简单理解为它其实就是将应用代码和依赖的系统环境打了个压缩包,在任意一台机器上解压这个压缩包,就能正常运行服务。为了下载和部署镜像,Node 中会有一个 Container runtime 组件。
每个应用服务都可以认为是一个 Container(容器), 并且大多数时候,我们还会为应用服务搭配一个日志收集器 Container 或监控收集器 Container,多个 Container 共同组成一个一个 Pod,它运行在 Node 上。
k8s 可以将 pod 从某个 Node 调度到另一个 Node,还能以 pod 为单位去做重启和动态扩缩容的操作。
所以说 Pod 是 k8s 中最小的调度单位。
另外,前面提到控制平面会用 Controller Manager (通过API Server)控制 Node 创建和关闭服务,那 Node 也得有个组件能接收到这个命令才能去做这些动作,这个组件叫 kubelet,它主要负责管理和监控 Pod。最后,Node 中还有个 Kube Proxy ,它负责 Node 的网络通信功能,有了它,外部请求就能被转发到 Pod 内。
Cluster
控制平面和Node 共同构成了一个 Cluster,也就是集群。在公司里,我们一般会构建多个集群, 比如测试环境用一个集群,生产环境用另外一个集群。同时,为了将集群内部的服务暴露给外部用户使用,我们一般还会部署一个入口控制器,比如 Ingress 控制器(比如Nginx),它可以提供一个入口让外部用户访问集群内部服务。
kubectl 是什么
上面提到说我们可以使用 k8s 提供的 API 去创建服务,但问题就来了,这是需要我们自己写代码去调用这些 API 吗?答案是不需要,k8s 为我们准备了一个命令行工具 kubectl,我们只需要执行命令,它内部就会调用 k8s 的 API。
接下来我们以部署服务为例子,看下 k8s 是怎么工作的。
怎么部署服务?
首先我们需要编写 YAML 文件,在里面定义 Pod 里用到了哪些镜像,占用多少内存和 CPU 等信息。然后使用 kubectl 命令行工具执行 kubectl apply -f xx.yaml ,此时 kubectl 会读取和解析 YAML 文件,将解析后的对象通过 API 请求发送给 Kubernetes 控制平面内 的 API Server。API Server 会根据要求,驱使 Scheduler 通过 etcd 提供的数据寻找合适的 Node, Controller Manager 会通过 API Server 控制 Node 创建服务,Node 内部的 kubelet 在收到命令后会开始基于 Container runtime 组件去拉取镜像创建容器,最终完成 Pod 的创建。
至此服务完成创建。
整个过程下来,我们只需要写一遍 yaml 文件,和执行一次 kubectl 命令,比以前省心太多了!部署完服务后,我们来看下服务是怎么被调用的。
怎么调用服务?
以前外部用户小明,直接在浏览器上发送 http 请求,就能打到我们服务器上的 Nginx,然后转发到部署的服务内。用了 k8s 之后,外部请求会先到达 Kubernetes 集群的 Ingress 控制器,然后请求会被转发到 Kubernetes 内部的某个 Node 的 Kube Proxy 上,再找到对应的 pod,然后才是转发到内部容器服务中,处理结果原路返回,到这就完成了一次服务调用。
到这里我们就大概了解了 k8s 的工作原理啦,它本质上就是应用服务和服务器之间的中间层,通过暴露一系列 API 能力让我们简化服务的部署运维流程。
并且,不少中大厂基于这些 API 能力搭了自己的服务管理平台,程序员不再需要敲 kubectl 命令,直接在界面上点点几下,就能完成服务的部署和扩容等操作,是真的嘎嘎好用。
K8s的介绍
K8s的本质是一组服务器的集群,他可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理,目的是实现资源管理的自动化。
K8s的主要功能
- 自我修复:一旦某个容器崩溃,能在1秒内迅速重启新的容器
- 弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
- 服务发现:可以通过自动发现的形式找到他所依赖的服务
- 负载均衡:如果一个服务启动了多个容器,能够自动实现请求的负载均衡
- 版本回退:如果发现新发布的程序版本有问题,可以立刻回退到原来的版本
- 存储编排:可以根据容器自身的需求自动创建存储卷
K8s的组件
分为控制节点(控制平面),和工作节点(node)
- API Server:资源操作的唯一入口,接收用户的命令,提供认证,授权,API注册和发现等机制
- Scheduler:负责集群资源调度,按照预定调度策略将Pod调度到相应的node节点上
- Controller Manager:负责维护集群状态,如:程序部署安排,故障检测,自动扩展,滚动更新等
- Etcd:负责存储集群中各种资源对象的信息
- Kubelet:负责维护容器的生命周期,通过控制dokcer来创建、更新、销毁容器
- KubeProxy:负责提供集群内部的服务发现和负载均衡
- Docker:负责节点上容器的各种操作
以部署一个nginx服务来说明K8s系统各组件的调用关系:
- 一旦K8s环境启动后,控制平面和node都会将自身信息存储在etcd数据库中
- 一个nginx服务的安装请求会首先被发送到控制平面的API Server组件
- API Server组件会调用scheduler组件来决定到底把这个服务安装在哪个node节点上,会从etcd中读取各个node节点的信息,然后按照一定的算法进行选择,并将结果告知API Server
- API Server调用controller manager去调度node安装nginx服务
- kubelet接收到指令后,会通知docker,然后由docker来启动一个nginx的pod,pod是K8s的最小操作单元,容器必须跑在pod中
- 若要访问nginx,需要通过kube-proxy来对pod产生访问的代理,这样,用户就可以访问集群中的nginx服务了
集群环境的搭建
环境规划
集群类型
分为两类:一主多从,多主多从
- 一主多从:一台控制平面和多台node节点,搭建简单,但是有单机故障风险,适合用于测试环境
- 多主多从:多台控制平面和多台node节点,搭建麻烦,安全性高,适合用于生产环境
目前安装一主两备,进行简单的了解
安装方式
主流有三种安装方式:kubeadm,minikube,二进制包
- kubeadm:快速搭建K8s集群的工具
- minikube:快速搭建单节点K8s的工具
- 二进制包:从官网下载每个组件的二进制包,依次安装,对于理解K8s组件更有效
目前采用kubeadm安装方式
主机规划
作用IP地址操作系统配置master192.168.9.207centos7.92颗CPU 15G内存 192G硬盘node1192.168.9.208centos7.92颗CPU 15G内存 192G硬盘node2192.168.9.209centos7.92颗CPU 15G内存 192G硬盘环境搭建
需要三台centos服务器,分别安装docker(26.1.4),kubeadm(1.22.4),kubelet(1.22.4),kubectl(1.22.4)程序
主机安装配置
详见day04+day05
环境的初始化
- # K8s集群要求centos版本在7.5以上
- [root@techtest9-230 ~]# cat /etc/redhat-release
- CentOS Linux release 7.9.2009 (Core)
复制代码- #修改主机名
- hostnamectl set-hostname master && bash
- hostnamectl set-hostname node1 && bash
- hostnamectl set-hostname node2 && bash
- # 为了方便集群节点间的直接调用 编辑三台服务器的/etc/hosts文件,添加下面的内容
- vim/etc/hosts
- 192.168.9.207 master
- 192.168.9.208 node1
- 192.168.9.209 node2
- #测试
- ping -c 4 -s 1000 master #指定发送四个数据包,每个数据包1000字节
复制代码- #要求集群中的节点时间必须精确一致,直接使用chronyd服务从网络同步时间
- #企业中建议配置内部的时间同步服务器
- #安装chrony服务
- sudo yum install chrony -y
- #启动服务
- sudo systemctl start chronyd
- #开机自启动
- sudo systemctl enable chronyd
- #检查chronyd服务是否存在
- systemctl list-units --type=service | grep chronyd
- #验证时间
- [root@master ~]# date
- Wed Apr 23 17:07:32 CST 2025
复制代码- #K8s和docker在运行时会产生大量的iptables规则,为了不让系统规则跟她们混淆,直接关闭系统规则
- #关闭firewalld服务
- systemctl stop firewalld
- systemctl disable firewalld
- systemctl status firewalld
- #关闭iptables服务
- systemctl stop iptables
- systemctl disable iptables
- systemctl status iptables
复制代码- #SELinux是 Linux 系统的一种安全机制,可以限制系统资源(如文件、网络等)的访问,提高系统的安全性。在 docker运行过程中,需要访问系统资源,但SElinux可能会限制访问,从而影响 docker的运行。
- sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
- #备注:修改selinux配置文件之后,重启linux机器,selinux配置才能永久生效,重启之后,登录到机器,执行如下命令:
- getenforce
- #如果显示Disabled说明selinux已经关闭
复制代码- #swap分区是虚拟内存分区,作用是在物理内存使用完之后,将磁盘空间虚拟成内存使用
- #启用swap设备会对系统的性能产生很大负面影响,K8s要求每个节点都要禁用swap分区设备
- #若因为某些原因确实不能关闭swap分区,就需要在集群安装过程中通过明确的参数进行配置说明
- #编辑分区配置文件/etc/fstab,注释掉swap分区一行
- vim /etc/fstab
- /dev/mapper/centos-root / xfs defaults 0 0
- UUID=4cd9523b-8651-40d1-a181-7153b6284467 /boot ext3 defaults 1 2
- #/dev/mapper/centos-swap swap swap defaults 0 0
- #重启linux服务
复制代码- #修改linux内核参数,添加网桥过滤和地址转发功能
- #编辑/etc/sysctl.d/kubernetes.conf文件,添加如下配置:
- vim /etc/sysctl.d/kubernetes.conf
- #是个新文件
- net.bridge.bridge-nf-call-ip6tables = 1
- net.bridge.bridge-nf-call-iptables = 1
- net.ipv4.ip_forward = 1
- #重新加载配置
- sysctl -p
- #加载网桥过滤模块
- modprobe br_netfilter
- #查看网桥过滤模块是否加载成功
- lsmod | grep br_netfilter
复制代码 [code]#在K8s中,service有两种代理模型,一种是基于iptables的,一种是基于ipvs的 ipvs的性能更高,如果要使用的话,需要手动载入ipvs模块#安装ipset和ipvsadmyum install ipset ipvsadm -y#验证ipset和ipvsadm是否安装成功[root@master ~]# ipset list[root@master ~]# ipset --versionipset v7.1, protocol version: 7[root@master ~]# ipvsadm --versionipvsadm v1.27 2008/5/15 (compiled with popt and IPVS v1.2.1)#添加需要加载的模块写入脚本文件cat |