糖呀糖啦~Pleiades
首页
归档
关于
友链
切换模式
返回顶部
首页
技术实践
书斋絮语
晴天札记
糖呀糖啦~Pleiades
首页
技术实践
书斋絮语
晴天札记
首页
归档
关于
友链
【Kubernetes】Master、Node、Pod
技术实践
·
03-04
糖呀糖 xyz
# 资源对象 Node、Pod、Replication Controller、Service 等都可以被看做一种资源对象,几乎所有的资源对象都可以通过 **Kubernetes 提供的 kubectl 工具** (或 API 变成调用)执行增删改查等操作,并将其保存在 etcd 中持久化存储。 所以,Kubernetes 其实是一个高度自动化的资源控制系统,他通过跟踪对比 etcd 库里保存的 “资源期望状态” 与 当前环境中的 “实际资源状态” 的差异来实现自动控制盒自动纠错的高级功能。 在声明一个 Kubernetes 资源对象的时候,有一个关键属性 **apiVersion** ,以下面的 Pod 声明为例: ```yaml apiVersion: v1 kind: Pod metadata: name: myweb labels: name: myweb spec: containers: - name: myweb image: kubeguide/tomcat-app:v1 ports: - containerPort: 8080 ``` Kubernetes 平台采用的是 “核心 + 外围扩展” 的设计思路,保持平台核心稳定的同时,具备持续演进升级的优势。 Kubernetes 大部分常见的核心资源对象都归属于 v1 这个核心 API,比如 Node、Pod、Service、Endpoints、Namespace、RC、PersistentVolume 等。 在版本迭代过程中,Kubernetes 先后扩展了 extensions/v1beta1、apps/v1beta1、apps/v1beta2 等 API 组,而在 1.9 版本之后引入了 apps/v1 这个正式的扩展 API 组,正式淘汰(deprecated)了 extensions/v1beta1、apps/v1beta1、apps/v1beta2 这三个 API 组。 采用 YAML 或者 JSON 格式声明(定义或者创建)一个 Kubernetes 资源对象,每个资源对象都有自己的特定语法格式(数据库中一个特定的表),但随着 Kubernetes 版本的持续升级,一些资源对象会不断引入新的属性。 # Master Master 是 Kubernetes 集群的 **控制节点**,在每个 Kubernetes 集群离都需要有一个 Master 来负责整个集群的管理和控制,基本上 Kubernetes 的所有控制命令都发给他。 Master 负责具体的执行过程,**后面执行的所有命令基本上都是在 Master 上运行的**。 Master 通常会占据一个独立的服务器(高可用部署建议 3 台服务器)。 在 Master 上运行着以下进程: ## Master 的核心系统进程 - `kubelet`:所有节点(包括 Master)上运行的主要节点代理 - `容器运行时`:containerd 或 Docker 的守护进程 - `kube-proxy`:网络代理,实现 Kubernetes Service 概念 ## Master 控制平面组件(通常作为静态 Pod 运行) - `kube-apiserver`:Kubernetes API Server,提供了 HTTP Rest 接口的关键服务进程,是 Kubernetes 里所有资源的 增、删、改、查 等操作的 **唯一入口**,也是 **集群控制的入口进程**。所有组件通信的中枢 - `kube-controller-manager`:Kubernetes Controller Manager,Kubernetes 里所有资源对象的自动化控制中心,可以理解为 资源对象的 ”大总管“。运行控制器进程,如节点控制器、副本控制器等 - `kube-scheduler`:Kubernetes Scheduler,负责资源调度(Pod 调度)的进程,“调度室”,负责观察新创建的 Pod 并选择节点来运行他们 - `etcd`:集群的数据存储,保持所有集群状态,Kubernetes 里所有的资源对象的数据都被保存在 etcd 中。 ## Master 节点上的附加组件(可能作为 Pod 或系统服务运行) - `CoreDNS`:提供集群内 DNS 服务 - `网络插件`:如 Calico、Flannel 或 Cilium 的相关进程 - `metrics-server`:收集资源指标 - `dashboard`:Web UI 界面(如果安装) ## 系统服务 - `systemd 服务`:管理 kubelet 和其他系统组件 - `journald`:日志收集服务 - `常规 Linux 系统服务`:如 SSH、cron 等 # Node 除了 Master,Kubernetes 集群中的其他机器被称为 Node,较早的版本也成为 Minion。 Node 可以是一台物理主机,也可以是一台虚拟机。 Node 是 Kubernetes 集群中的工作负载节点,每个 Node 都会被 Master 分配一些工作负载(Docker 容器),当某个 Node 宕机时,其上的工作负载会被 Master 自动转移到其他节点上。 在每个 Node 上都运行着以下进程: ## Node 上的核心进程 - `kubelet`:负责 Pod 对应的容器的创建、启停等任务,同时与 Master 密切协作,实现集群管理的基本功能。 - 是最重要的节点代理 - 负责与容器运行时交互,管理 Pod 的生命周期 - 监控分配到节点的 Pod,确保它们按照 PodSpec 运行 - 向 API 服务器报告节点和 Pod 状态 - `kube-proxy`:实现 Kubernetes Service 的通信与负载均衡机制的重要组件 - 负责维护节点的网络规则 - 处理集群内部的网络通信 - 支持不同的代理模式(iptables / IPVS) - `Docker Engine` 或 `containerd`:Docker 引擎 / 容器运行时,负责本机的容器创建和管理工作。 - 负责容器的实际运行 - 镜像管理和存储 - 在 K8s 1.24 版本之前 Node 节点通常需要运行 Docker Engine,Docker Engine 通过 dockershim 与 kubelet 交互 - 在 K8s 1.24 版本及以后,不需要运行 Docker Engine,直接使用容器运行时。 - containerd 相比 Docker Engine 性能更好,减少了一层抽象,资源消耗更少,架构更简单易于维护 - 生产环境建议可以直接使用 containerd 作为容器运行时,可以直接使用 `crictl` 命令工具管理容器 - 即使不用 Docker Engine,仍然可以运行 Docker 容器镜像,因为这些镜像遵循 OCI(开放容器倡议)标准,可以背任何兼容的容器运行时使用。 ## Node 上的网络组件 - CNI 插件进程: - 如 Calico、Flannel、Cilium 或 Weave 的代理程序 - 负责 Pod 网络配置和跨节点通信 - 实现网络策略(如果支持 ## Node 上的监控和日志组件 - 节点级监控代理 - 如 `node_exporter`(Prometheus) - 收集节点级别的指标 - 日志收集代理 - 如 Fluentd、Filebeat 等 - 收集容器和系统日志 ## Node 上的系统服务 - `systemd 服务`:管理 kubelet 和其他系统组件 - `journald`:系统日志服务 - `常规 Linux 系统服务`:如 SSH、cron 等 ## Node 上的工作负载容器 - `用户应用容器`:实际运行的业务应用 - `Pause 容器`:每个 Pod 的基础容器,持有网络命名空间 - `边车容器`:如服务网格代理(Istio、Linkerd) Node 可以在运行期间动态增加到 Kubernetes 集群中,前提是在这个节点上已经正确安装、配置和启动了上述关键进程。 在默认情况下 kubelet 会向 Master 注册自己,同时也是 Kubernetes 推荐的 Node 管理方式。 一旦 Node 被纳入集群管理范围,kubelet 进程就会定时向 Master 汇报自身的情报,如 操作系统、Docker 版本、机器的 CPU 和内存情况,以及 当前有哪些 Pod 在运行等。这样 Master 就可以获知每个 Node 的资源使用情况,并实现高效均衡的资源调度策略。 某个 Node 在超过指定时间不上报信息时,会被 Master 判定为 “失联”,Node 的状态被标记为 不可用(Not Ready),随后 Master 会触发 “工作负载大转移” 的自动流程。 ## 查看集群中有多少 Node 可以通过以下命令查看 集群中有多少个 Node: ```bash kubectl get nodes ```  ## 查看某个 Node 的详细信息 通过以下命令查看 某个 Node 的详细信息 ```bash kubectl describe node node1 ``` 内容如下 ```yaml Name: node1 Roles: control-plane Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux kubernetes.io/arch=amd64 kubernetes.io/hostname=node1 kubernetes.io/os=linux node-role.kubernetes.io/control-plane= node.kubernetes.io/exclude-from-external-load-balancers= Annotations: kubeadm.alpha.kubernetes.io/cri-socket: unix:///var/run/containerd/containerd.sock node.alpha.kubernetes.io/ttl: 0 projectcalico.org/IPv4Address: 192.168.25.72/22 projectcalico.org/IPv4VXLANTunnelAddr: 10.234.168.1 volumes.kubernetes.io/controller-managed-attach-detach: true CreationTimestamp: Thu, 20 Feb 2025 06:28:51 +0000 Taints:
Unschedulable: false Lease: HolderIdentity: node1 AcquireTime:
RenewTime: Mon, 03 Mar 2025 06:32:04 +0000 Conditions: Type Status LastHeartbeatTime LastTransitionTime Reason Message ---- ------ ----------------- ------------------ ------ ------- NetworkUnavailable False Thu, 20 Feb 2025 06:30:05 +0000 Thu, 20 Feb 2025 06:30:05 +0000 CalicoIsUp Calico is running on this node MemoryPressure False Mon, 03 Mar 2025 06:32:04 +0000 Thu, 20 Feb 2025 06:28:49 +0000 KubeletHasSufficientMemory kubelet has sufficient memory available DiskPressure False Mon, 03 Mar 2025 06:32:04 +0000 Thu, 20 Feb 2025 06:28:49 +0000 KubeletHasNoDiskPressure kubelet has no disk pressure PIDPressure False Mon, 03 Mar 2025 06:32:04 +0000 Thu, 20 Feb 2025 06:28:49 +0000 KubeletHasSufficientPID kubelet has sufficient PID available Ready True Mon, 03 Mar 2025 06:32:04 +0000 Thu, 20 Feb 2025 06:31:15 +0000 KubeletReady kubelet is posting ready status. AppArmor enabled Addresses: InternalIP: 192.168.25.72 Hostname: node1 Capacity: cpu: 4 ephemeral-storage: 102626232Ki hugepages-2Mi: 0 memory: 8136068Ki pods: 110 Allocatable: cpu: 4 ephemeral-storage: 94580335255 hugepages-2Mi: 0 memory: 8033668Ki pods: 110 System Info: Machine ID: b789b3370e69479f907f0c605dd54107 System UUID: b789b337-0e69-479f-907f-0c605dd54107 Boot ID: b0a92107-4cf1-42ab-bdc7-17b6902b56e1 Kernel Version: 5.4.0-205-generic OS Image: Ubuntu 20.04.5 LTS Operating System: linux Architecture: amd64 Container Runtime Version: containerd://1.6.19 Kubelet Version: v1.26.4 Kube-Proxy Version: v1.26.4 PodCIDR: 10.234.0.0/23 PodCIDRs: 10.234.0.0/23 Non-terminated Pods: (17 in total) Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits Age --------- ---- ------------ ---------- --------------- ------------- --- default mysql-8n5ss 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3d21h default myweb-4t4rj 0 (0%) 0 (0%) 0 (0%) 0 (0%) 2d21h default myweb-mnlxr 0 (0%) 0 (0%) 0 (0%) 0 (0%) 2d21h default netchecker-agent-5wkcf 15m (0%) 30m (0%) 64M (0%) 100M (1%) 11d default netchecker-agent-hostnet-w2bdc 15m (0%) 30m (0%) 64M (0%) 100M (1%) 11d default netchecker-server-67c989ccbb-2hfdd 150m (3%) 300m (7%) 192M (2%) 512M (6%) 11d kube-system calico-kube-controllers-7967fb4566-7v5f7 30m (0%) 1 (25%) 64M (0%) 256M (3%) 11d kube-system calico-node-gc8j5 150m (3%) 300m (7%) 64M (0%) 500M (6%) 11d kube-system coredns-55859db765-5w4rc 100m (2%) 0 (0%) 70Mi (0%) 300Mi (3%) 11d kube-system dns-autoscaler-998c74f6b-b4mml 20m (0%) 0 (0%) 10Mi (0%) 0 (0%) 11d kube-system kube-apiserver-node1 250m (6%) 0 (0%) 0 (0%) 0 (0%) 11d kube-system kube-controller-manager-node1 200m (5%) 0 (0%) 0 (0%) 0 (0%) 11d kube-system kube-proxy-742df 0 (0%) 0 (0%) 0 (0%) 0 (0%) 11d kube-system kube-scheduler-node1 100m (2%) 0 (0%) 0 (0%) 0 (0%) 11d kube-system metrics-server-556d5d785-krfxq 100m (2%) 100m (2%) 200Mi (2%) 200Mi (2%) 11d kube-system nodelocaldns-6xctx 100m (2%) 0 (0%) 70Mi (0%) 200Mi (2%) 11d kuboard kuboard-v3-node1 0 (0%) 0 (0%) 0 (0%) 0 (0%) 11d Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 1230m (30%) 1760m (44%) memory 815001600 (9%) 2202003200 (26%) ephemeral-storage 0 (0%) 0 (0%) hugepages-2Mi 0 (0%) 0 (0%) Events:
``` 以上内容: - Node 基本信息:名称、标签、创建时间等 - Node 当前的运行状态:Node 启动后会做一系列的自检工作, - DiskPressure 磁盘空间是否不足 - MemoryPressure 内存是否不足 - NetworkUnavailable 网络是否正常 - PIDPressure PID 资源是否充足 - 在一切正常时设置 Node 为 Ready 状态(Ready=True),表示 Node 出于健康状态,Master 将可以在其上调度新的任务了(如,启动 Pod)  - Node 的主机地址与主机名 - Node 上的资源数量: - Node 可用的系统资源,包括 CPU、内存数量、最大可调度 Pod 数量等 -  - Node 可分配的资源量:描述 Node 当前可用于分配的资源量  - 主机系统信息: - 主机 ID - 系统 UUID - Linux kernel 版本号 - 操作系统类型与版本 - 容器运行时版本号 - kubelet 与 kube-proxy 版本号  - 当前运行的 Pod 列表概要信息 - 已分配的资源使用概要信息,如 资源申请的最低、最大允许使用量占系统总量的百分比 - Node 相关的 Event 信息 # containerd 容器运行时 containerd 是一个工业级标准的容器运行时,原本是 Docker 的核心组件,后来被分离出来成为独立项目,现在由 CNCF (Cloud Native Computing Foundation) 托管。 containerd 的架够层次如下: Kubernetes --> kubelet --> CRI 插件 --> containerd --> runc - kubelet 通过 CRI(容器运行时接口)与 containerd 通信 - containerd 负责容器的生命周期管理 - 最终通过 runc 来创建和运行容器 containerd 主要功能: - 镜像管理(拉取、推送、删除) - 容器生命周期管理(创建、启动、停止、删除) - 存储管理 - 网络接口 containerd 的常用工具: - `crictl`:替代了 docker CLI 的命令行工具 - `ctr`:containerd 的原生命令行工具 - `nerdctl`:功能更完善的 containerd 客户端工具 # Pod Pod 是 Kubernetes 最重要的基本概念,每个 Pod 都有一个特殊的被称为 “根容器” 的 Pause 容器。 Pause 容器对应的镜像属于 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod 还包含一个或多个紧密相关的用户业务容器 ## 为什么会有 Pod 这个概念 在一组容器作为一个单元的情况下,难以简单地对“整体”进行判断及有效地行动。 比如,一个容器死亡了,此时算是整体死亡吗?是 N/M 的死亡率吗?引入业务无关并且不易死亡的 Pause 容器作为 Pod 的根容器,以它的状态来代表整个容器组的状态,可以解决上述问题。 Pod 里的多个业务容器共享 Pause 容器的 IP,共享 Pause 容器挂接的 Volume,简化了密切关联的业务容器之间的通信问题,也很好地解决了业务容器间的文件共享问题。 Kubernetes 为每个 Pod 都分配了唯一的 IP 地址,称之为 **Pod IP**,一个 Pod 里的多个容器共享 Pod IP 地址。Kubernetes 要求底层网络支持集群内任意两个 Pod 之间的 TCP/IP 直接通信,这通常采用 虚拟二层网络技术来实现(Flannel、Open vSwitch 等)。 在 Kubernetes 里,一个 Pod 里的容器与另外主机上的 Pod 容器能够直接通信。 ## Pod 类型 Pod 有两种类型:普通的 Pod 及 静态 Pod(Static Pod)  ### 静态 Pod 静态 Pod 比较特殊,并没有被存放在 Kubernetes 的 etcd 存储里,而是被 存放在某个具体的 Node 上的一个具体文件中,并且只在此 Node 上启动、运行。 静态 Pod 不通过 Kubernetes API 服务器管理,而是直接由特定节点上的 kubelet 进程管理。 静态 Pod 的配置文件通常会存放在 Node 上的特定目录中,这个目录是 kubelet 的配置参数 `--pod-manifest-path` 所制定的路径。 在大多数的 Kubernetes 部署中,这个默认路径是: `/etc/kubernetes/manifests/` 或者 `/etc/kubelet.d/` kubelet 会定期扫描配置的静态 Pod 目录 #### kubelet 对静态 Pod 的生命周期管理 当发现新的 Pod 定义文件时,kubelet 会自动创建并启动对应的 Pod; 当文件被修改时,kubelet 会重新创建 Pod 当文件被删除时,kubelet 会终止对应的 Pod kubelet 会为每个静态 Pod 在 Kubernetes API 服务器中创建一个 Pod 对象( mirror Pod),这个镜像对象是 `只读` 的,不能通过 API Server 修改或删除 #### 静态 Pod 的特点 - 只依赖于**特定节点**上的 kubelet,不依赖于 Kubernetes API 服务器 - 即使 API 服务器不可用,静态 Pod 也能正常运行 - 通常用于部署控制平面组件(如 kube-apiserver、kube-controller-manager、kube-scheduler 等) - 无法使用 Deployment、DaemonSet 等控制器管理 - 不支持健康检查、滚动更新等高级功能 #### 静态 Pod 的创建方式 静态 Pod 是通过将 Pod 定义文件放置在特定节点的指定目录中来创建的: ```bash sudo cp myweb-pod.yaml /etc/kubernetes/manifests/ ``` - 直接由特定节点上的 kubelet 管理,不经过 API 服务器 ### 普通 Pod 普通的 Pod 一旦被创建,就会被放入 etcd 中存储,随后会被 Kubernetes Master 调度到某个具体的 Node 上并进行绑定(Binding),随后该 Pod 被对应的 Node 上的 kubelet 进程实例化成一组相关的 Docker 容器并启动。 默认情况下,当 Pod 里的某个容器停止时,Kubernetes 会自动检测到问题,并且重新启动这个 Pod(重启 Pod 里的所有容器) 如果 Pod 所在的 Node 宕机,就会将这个 Node 上的所有 Pod 重新调度到其他节点上。 #### 创建一个普通 Pod 可以采用 YAML 或者 JSON 格式的文件来定义或者描述,如: ```yaml apiVersion: v1 kind: Pod metadata: name: myweb labels: name: myweb spec: containers: - name: myweb image: kubeguide/tomcat-app:v1 ports: - containerPort: 8080 env: - name: MYSQL_SERVICE_HOST value: 'mysql' - name: MYSQL_SERVICE_PORT value: '3306' ``` 这是一个创建普通 Pod 的 YAML 定义文件 - `kind` 为 Pod 表明这是一个 Pod 的定义 - `metadata` 里的 - `name` 属性为 Pod 名称 - 定义一个 `name=myweb` 的标签 - Pod 里面所包含的容器组的定义,在 `spec` 中声明 - 定义了一个名为 myweb、对应镜像为 kubeguide/tomcat-app:v1 的容器 - 该容器注入了 名为 `MYSQL_SERVICE_HOST='mysql'` 和 `MYSQL_SERVICE_PORT='3306` 的环境变量(env 关键字) - 并且在 8080 端口(containerPort)启动容器进程 - 容器端口 containerPort - Endpoint:代表此 Pod 里的一个服务进程的对外通信地址 - 一个 Pod 里面也存在具有多个 Endpoint 的情况,比如我们把 Tomcat 定义为一个 Pod 时,可以对外暴露管理端口与服务端口这两个 Endpoint ### 静态 Pod 与普通 Pod 一些主要区别(操作上) |特性|静态 Pod|普通 Pod| |---|---|---| |**创建方式**|通过文件系统上的清单文件|通过 API 服务器| |**管理者**|直接由 kubelet 管理|由控制平面组件协作管理| |**调度**|无调度,固定在特定节点|由 kube-scheduler 动态调度| |**依赖性**|仅依赖 kubelet 和容器运行时|依赖完整的控制平面| |**可见性**|在 API 服务器中有只读镜像|完全可见且可管理| |**更新方式**|修改/替换清单文件|通过 API 服务器更新| |**删除方式**|从清单目录移除文件|通过 API 服务器删除| |**命名规则**|自动添加节点名称后缀|按用户指定名称创建| 一个很简单的区分方式: - 如果是通过 `kubectl apply` 创建的就是 普通的 pod - 如果选择将定义文件放在特定的目录 `/etc/kubernetes/mainfests/` 的不走 kubectl 的是 静态pod ### 静态 Pod 与 普通 Pod 的实际应用场景 **静态 Pod 适用于**: - 控制平面组件(避免循环依赖) - 需要在特定节点上始终运行的关键服务 - 不依赖 API 服务器的基础设施组件 **普通 Pod 适用于**: - 常规应用工作负载 - 需要调度灵活性的服务 - 需要使用高级 Kubernetes 功能的应用 ## Event Event 是一个四件的记录,记录了事件的最早产生时间、最后重现时间、重复次数、发起者、类型,以及导致此事件的原因等众多信息。 可以通过以下命令查看 Node / Pod 的 Event ```bash kubectl describe pod
# pod kubectl describe node
# node ``` # 资源配额 每个 Pod 都可以对其能使用的服务器上的计算资源设置限额,当前可以设置限额的计算资源有 CPU 和 Memory 两种。 CPU 的资源单位是 CPU(Core)的数量,是一个绝对值而非相对值。 一个 CPU 的资源配额相当大,所以在 Kubernetes 里通常以 `千分之一` 的 CPU 配额为最小单位,用 `m` 来表示。 通常一个容器的 CPU 配额被定义为 100~300m,即占用 `0.1~0.3 个 CPU`。 由于 CPU 配额是一个绝对值,所以无论在拥有一个 Core 的机器上,还是在拥有 48 个 Core 的机器上,100m 这个配额所代表的 CPU 的使用量都是一样的。 与 CPU 配额类似,Memory 配额也是一个绝对值,单位是 `内存字节数` ## 资源配额设置 一个计算资源进行配额限定时需要设定以下两个参数: - `Requests`:该资源的最小申请量,系统必选满足要求 - `Limits`:该资源最大允许使用的量,不能被突破,当容器试图使用超过这个量的资源时,可能会被 Kubernetes “杀掉”并重启。 通常会把 Requests 设置为一个较小的值,符合容器平时的工作负载情况下的资源需求,把 Limit 设置为 峰值负载情况下资源占用的最大量。 # References - claude 3.5 sonnet - claude 3.7 sonnet - Kubernetes 权威指南:从 Docker 到 Kubernetes 实践全接触(第 4 版)
Kubernetes
取消回复
提交评论
tl.s
03-05
回复
写的很详细,赞👍
糖呀糖 xyz
我们谈论生活,讨论技术,借由文字,抵达心灵。
热门文章
【Kubernetes】第一个实例 - Java Web 应用
Obsidian 迁移全记录(又名:纯小白的闭坑指南)
使用宝塔面板对网站、数据库等进行定时备份到腾讯云 COS 对象存储
2025 年
在细雨中呼喊,在困顿中挣扎
Ubuntu 22.04 server 安装教程
Debian 12.2 安装方法
最新评论
tl.s: 很实用 🦆🦆
tl.s: 绘图很清晰,图示质量很高
tl.s: 写的很详细,赞👍
Deep Router: 大佬好强!!!
tls: 写的很详细,很清晰!
tl.s: 讲的很清楚,语言组织很好 🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆
tl.s: 好棒🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆🦆
热门标签
Kubernetes
Ubuntu
Linux
Python3
生活
2025
Debian
技术实践
在细雨中呼喊
读书笔记
笔记软件
Obsidian
2024
openEuler
Kuboard
粤ICP备2024349207号
写的很详细,赞👍