探索 Kubernetes 集群

KubernetesBeginner
立即练习

简介

现代应用通常以容器的形式打包。容器会将应用及其所需的库和配置整合在一起,让应用能够更加稳定、一致地运行。运行一个容器并不复杂,但要可靠地运行大量容器就困难得多:运维人员需要决定容器运行在哪些位置,重启故障容器,让应用彼此通信,并安全地发布变更。

Kubernetes 是一个容器编排系统,负责处理集群级别的这些工作。你只需描述期望的状态,例如「运行这个 Web 应用的 3 个副本」,Kubernetes 就会持续调整实际状态,使其与期望状态保持一致。

Kubernetes 集群由一个或多个称为节点的机器组成。控制平面负责管理集群,而节点则提供应用所需的 CPU、内存、网络和容器运行时。应用会运行在 Pod、Deployment 和 Service 等 Kubernetes 对象中。

在这个实验中,你暂时不会部署应用,而是先学习如何在一个真实集群中快速了解环境:

  1. 识别所使用的工具、当前集群、Kubernetes 版本以及节点健康状况。
  2. 找出使 Kubernetes 正常运行的控制平面组件和节点组件。
  3. 检查集群端点和节点详细信息。
  4. 跨命名空间探索 Pod、Deployment 和 Service。

实验环境已经准备就绪,因此你可以专注于 Kubernetes 概念,而不必处理安装问题。环境使用 Minikube v1.38.1,并采用名为 labex-v135 的配置文件运行 Kubernetes v1.35.5。Minikube 会在 LabEx 虚拟机中的 Docker 容器内运行完整的 Kubernetes 集群。这是一个单节点学习环境,但你练习的 Kubernetes 命令和概念同样适用于更大的集群。

整个实验都将在终端中完成。运行每条命令前先阅读说明,然后将实际输出与文中描述的结果进行对照。对象的准确创建时间、重启次数和自动生成的名称可能有所不同,这是实时系统中的正常现象。

验证预配置的集群

环境启动: 本实验会为你启动一个完整的 Kubernetes 集群。配置控制平面、节点和网络组件通常需要 2~3 分钟。请耐心等待环境加载完成后再开始操作。

在本步骤中,你将了解终端工具如何连接到 Kubernetes,确认已提供的软件版本,并验证集群是否已就绪。在修改集群之前,管理员应始终先确认当前使用的是哪个集群,以及该集群是否健康。

了解相关工具

你将使用两个相关的命令行工具:

  • minikube 用于创建和管理本地 Kubernetes 集群。命名的 Minikube 环境称为配置文件。本实验使用 labex-v135 配置文件。
  • kubectl 是 Kubernetes 的标准命令行客户端。它会向 Kubernetes API 服务器发送请求,用于列出、创建、更新和删除对象。

集群已经在运行。不要执行 minikube start,因为这没有必要,还可能让你等待 Minikube 重新检查现有环境。

进入工作目录

进入项目目录,后续实验会将清单文件及其他由你创建的文件存放在这里:

cd /home/labex/project

cd 命令用于切换 Shell 的当前目录。执行成功时通常不会输出任何内容。

检查 Minikube 版本

显示已安装的 Minikube 版本。以 -- 开头的选项用于改变命令行为。这里的 --short 表示只显示版本号。

minikube version --short
v1.38.1

这是集群管理工具的版本,而不是 Kubernetes 的版本。Minikube 和 Kubernetes 是两个独立的项目,因此各自拥有独立的版本号。

检查客户端和服务器版本

kubectl 输出版本信息。该命令会连接集群,因此可以同时检查本地客户端和远程 API 服务器:

kubectl version
Client Version: v1.35.5
Kustomize Version: ...
Server Version: v1.35.5

Client Version 表示已安装的 kubectl 版本;Server Version 由 Kubernetes API 服务器报告。看到服务器版本这一行,说明 kubectl 已成功连接到某个集群。Kustomize 是内置的清单定制功能,本实验不会用到。

确认当前上下文

一台计算机可以在 kubeconfig 文件中保存多个集群的访问信息。kubeconfig 中的上下文用于选择集群、用户凭据和默认命名空间。检查当前上下文可以避免误操作错误的集群。

kubectl config current-context
labex-v135

这与预先准备好的 Kubernetes v1.35 配置文件一致。

列出并选择上下文

真实的 kubeconfig 文件通常包含多个上下文。切换之前先列出它们,这样就不必猜测名称:

kubectl config get-contexts

NAME 列包含上下文名称,CURRENT 列使用 * 标记当前活动的上下文。每个上下文关联的集群、身份验证信息和默认命名空间会显示在其他列中。

如果需要选择其中某个上下文,可以使用 use-context。即使 labex-v135 已经是当前上下文,再次选择它也是安全的,同时还能练习完整的上下文切换流程:

kubectl config use-context labex-v135
Switched to context "labex-v135".

current-context 用于回答「当前选择的是哪个上下文?」;get-contexts 用于回答「有哪些可选上下文?」;use-context NAME 用于更改当前选择。这些命令只会改变本地客户端的选择,不会启动、停止或修改集群。

检查 Minikube 配置文件

查看此配置文件的状态。短选项 -p 表示配置文件,后面跟配置文件名称。

minikube status -p labex-v135
labex-v135
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

host 表示 Minikube 节点容器正在运行。kubelet 是节点代理。apiserver 是 Kubernetes API 端点。kubeconfig: Configured 表示本地客户端配置已指向此集群。以上各项都应处于正常状态。

列出节点

大多数 kubectl 命令都遵循 kubectl <verb> <resource> 的形式。这里,get 用于读取对象,nodes 表示资源类型:

kubectl get nodes
NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35.5

NAME 用于标识节点。STATUS=Ready 表示该节点可以运行工作负载。ROLES 表示该节点承载控制平面。由于镜像会恢复一个预先准备好的快照,AGE 可能早于本次会话的开始时间。VERSION 表示 kubelet 版本。

本实验只有一个节点,同时承担控制平面和工作负载的职责。在生产集群中,这些职责通常会分布到多台机器上。

步骤检查点

你已经确认 kubectl 能够连接到目标 labex-v135 集群,并且该集群的节点在 Kubernetes v1.35.5 上处于 Ready 状态。每次进入不熟悉的集群时,这都是一套非常实用的快速确认流程。

识别 Kubernetes 架构组件

在本步骤中,你将把 Kubernetes 的架构模型与实际运行的组件对应起来。当你亲眼看到 API 服务器、调度器和 kubelet 运行在哪些 Pod 中时,这些名称会更容易理解和记忆。

了解请求在 Kubernetes 中的处理过程

假设你要求 Kubernetes 运行一个 Web 应用。首先,kubectl 会将请求发送给 kube-apiserver,由它验证请求,并将期望状态保存到 etcd 中。

接下来,kube-scheduler 会为每个新 Pod 选择节点。kube-controller-manager 会持续监视集群,并不断调整实际状态,使其符合期望状态。

最后,被选中节点上的 kubelet 会请求容器运行时启动 Pod 中的容器。网络组件则负责让 Pod 和 Service 彼此通信。

这种持续比较期望状态与实际状态的过程称为协调。如果某个 Deployment 要求运行 3 个 Pod,但实际只有 2 个,控制器就会创建缺少的 Pod。

了解 Pod 和系统命名空间

Pod 是 Kubernetes 中最小的可部署单元。它可以封装一个或多个关系紧密的容器,并为这些容器提供共享的网络和存储上下文。

命名空间为命名空间级别的对象提供逻辑范围。kube-system 包含集群基础设施。选项 -n kube-system 告诉 kubectl 在该命名空间中搜索,而不是在默认命名空间中搜索。它的完整写法是 --namespace=kube-system;两种写法选择的是同一个范围。

Minikube 会将控制平面组件作为静态 Pod运行。kubelet 会直接根据节点上的文件创建这些 Pod,因此即使普通调度机制尚未可用,控制平面也能先启动。

列出控制平面组件

对象可以携带标签,即用于分组和选择的键值元数据。使用 -l tier=control-plane 可以选择带有该标签的 Pod:

kubectl get pods -n kube-system -l tier=control-plane
NAME                                 READY   STATUS    RESTARTS   AGE
etcd-labex-v135                      1/1     Running   ...        ...
kube-apiserver-labex-v135            1/1     Running   ...        ...
kube-controller-manager-labex-v135   1/1     Running   ...        ...
kube-scheduler-labex-v135            1/1     Running   ...        ...

API 服务器是 Kubernetes 的入口。etcd 负责存储集群状态。调度器负责选择 Pod 的放置位置。控制器管理器负责运行协调控制器。

READY=1/1 表示该 Pod 中的 1 个容器全部就绪。长期运行的组件通常应处于 Running 状态。保存的集群恢复后,RESTARTS 可能不为 0。AGE 表示对象的存在时间,而不是它在本实验中运行的时间。

查看标签

将标签显示为最后一列:

kubectl get pods -n kube-system -l tier=control-plane --show-labels

查找 component=kube-apiservertier=control-plane。前者用于区分具体组件,后者用于将所有控制平面 Pod 分组。标签用于标识对象,选择器则用于查找符合条件的对象。

检查节点网络组件

使用基于集合的选择器,表示 k8s-app 的值可以是 kube-proxycalico-node。加引号可以避免 Shell 解释其中的括号。

kubectl get pods -n kube-system -l 'k8s-app in (kube-proxy,calico-node)'
NAME                READY   STATUS    RESTARTS   AGE
calico-node-...     1/1     Running   ...        ...
kube-proxy-...      1/1     Running   ...        ...

Calico 负责配置 Pod 网络。kube-proxy 维护节点上的规则,帮助 Service 将流量转发到 Pod。kubelet 不会出现在此列表中,因为它是负责操作 Pod 的主机代理,以主机服务的形式运行,而不是由自身管理的普通 Pod。

步骤检查点

API 服务器负责接收请求,etcd 负责存储状态,调度器负责选择放置位置,控制器负责协调状态,kubelet 负责操作节点,Calico 和 kube-proxy 则共同支持网络通信。

检查集群和节点详细信息

在本步骤中,你将从简单的健康检查进一步深入到详细检查。Kubernetes 同时提供简洁的列表视图和详细的对象描述;学会在不同场景下选择合适的查看方式,是排查问题时非常重要的习惯。

查找集群端点

kubectl cluster-info 是专门用于快速了解集群的命令。与 kubectl get 不同,它不会列出某一种资源,而是请求当前集群报告 API 服务器和 CoreDNS 等重要服务的地址。

kubectl cluster-info
Kubernetes control plane is running at https://...
CoreDNS is running at https://...

控制平面 URL 就是 API 服务器端点。CoreDNS 提供 DNS 服务发现功能,让工作负载可以通过名称查找 Service,而不必跟踪不断变化的 IP 地址。地址可能因环境而异,因此重点关注 is running,这表示 API 服务器已返回相关信息。但它并不能证明每个工作负载都处于健康状态。

扩展节点列表

添加 -o wide 以请求更多列:

kubectl get nodes -o wide
NAME         STATUS   ROLES           AGE   VERSION   INTERNAL-IP    ...   OS-IMAGE
labex-v135   Ready    control-plane   ...   v1.35.5   192.168.49.2   ...   Debian GNU/Linux 12 (bookworm)

INTERNAL-IP 是节点在集群网络中的地址。EXTERNAL-IP=<none> 表示没有分配 Kubernetes 管理的公网地址。OS-IMAGEKERNEL-VERSIONCONTAINER-RUNTIME 用于描述节点的软件环境。

LabEx 后端使用 Ubuntu 22.04,而 Minikube 使用基于 Debian 的 Docker 容器来表示 Kubernetes 节点。因此,在这里看到 Debian 是正常的。

描述节点

当列表中的信息不够详细时,可以使用 describe。其格式为 kubectl describe <resource-type> <name>;这里的资源类型是 node,对象名称是 labex-v135

kubectl describe node labex-v135

在输出开头附近,查看节点身份和调度状态:

Name:               labex-v135
Roles:              control-plane
Taints:             <none>
Unschedulable:      false

Taints 可以排斥不容忍这些污点的 Pod。<none> 表示这个学习节点没有污点。Unschedulable: false 表示 Kubernetes 可以在该节点上放置工作负载。

找到 Conditions 表格:

Type                 Status   ...   Reason
NetworkUnavailable   False    ...   CalicoIsUp
MemoryPressure       False    ...   KubeletHasSufficientMemory
DiskPressure          False    ...   KubeletHasNoDiskPressure
PIDPressure           False    ...   KubeletHasSufficientPID
Ready                True     ...   KubeletReady

对于压力和不可用状态,False 表示健康,因为相应问题并不存在。对于 ReadyTrue 表示健康。解读条件时,始终要同时查看条件名称及其对应值。

Capacity 表示节点报告的资源总量。Allocatable 表示扣除系统预留资源后,Kubernetes 可以提供给 Pod 的资源量。System Info 会报告容器运行时和 kubelet 信息。后续部分还会列出 Pod、已分配的请求与限制,以及事件。具体数值和时间戳可能有所不同。

步骤检查点

使用 get 查看快速列表,使用 get -o wide 查看额外列,使用 describe 查看单个对象的条件、容量、运行时详细信息和事件。

跨命名空间检查资源

在本步骤中,你将建立一张常见 Kubernetes 对象的基础地图:命名空间用于组织资源,Pod 用于运行容器,Deployment 用于管理 Pod,Service 则提供稳定的网络访问入口。

了解对象之间的关系

  • Pod 是最小的可部署单元,包含一个或多个容器。
  • Deployment 声明无状态应用应运行多少个副本,并通过 ReplicaSet 管理这些 Pod。
  • Service 为选中的 Pod 提供稳定的虚拟 IP 和 DNS 名称,因为可替换的 Pod IP 可能发生变化。
  • 命名空间用于对命名空间级别的对象进行分组,并允许不同范围内使用相同的名称。

一种简化的关系是:Deployment 管理 Pod,Service 选择这些 Pod,并为客户端提供稳定的端点。并非所有对象都属于命名空间;Node 属于整个集群。

列出所有命名空间中的 Pod

如果不指定命名空间,kubectl get pods 只会在当前命名空间中搜索。-A 表示 --all-namespaces

kubectl get pods -A

NAMESPACE 表示逻辑范围。NAME 用于标识该范围内的 Pod。READY 表示已就绪容器数除以容器总数。STATUS 表示生命周期阶段。RESTARTS 统计重启次数,AGE 表示对象存在时间。

长期运行的基础设施组件应处于 Running 状态。某些 Ingress 准入 Pod 会显示为 Completed,并且就绪状态为 0/1,因为它们执行的是一次性 Job,成功完成后便退出。必须结合工作负载的实际用途来解读健康状态。

列出 Deployment

使用复数资源名称 deployments 可以请求 Deployment 对象。保留 -A,因为系统 Deployment 位于当前 default 命名空间之外:

kubectl get deployments -A
NAMESPACE       NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
ingress-nginx   ingress-nginx-controller   1/1     1            1           ...
kube-system     calico-kube-controllers    1/1     1            1           ...
kube-system     coredns                    1/1     1            1           ...
kube-system     metrics-server             1/1     1            1           ...

READY 表示已就绪副本数除以期望副本数。UP-TO-DATE 统计使用当前 Pod 模板的副本数。AVAILABLE 统计当前可用于其目标用途的副本数。之前看到的 coredns-... Pod 由 coredns Deployment 维护。

列出 Service

Pod 可以被替换,因此客户端不应依赖某个 Pod 的 IP。请列出稳定的 Service 端点:

kubectl get services -A
NAMESPACE       NAME                       TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
default         kubernetes                 ClusterIP   10.96.0.1     <none>        443/TCP   ...
kube-system     kube-dns                   ClusterIP   10.96.0.10    <none>        ...       ...
ingress-nginx   ingress-nginx-controller   NodePort    ...           <none>        ...       ...

TYPE 描述 Service 的暴露方式。ClusterIP 只能在集群内部访问;NodePort 还会开放节点端口。CLUSTER-IP 是稳定的虚拟地址。EXTERNAL-IP=<none> 表示没有分配外部地址。PORT(S) 列出对外暴露的协议和端口。

kubernetes Service 用于在集群内部暴露 API。kube-dns 为 CoreDNS 提供稳定的访问入口。Ingress Service 用于支持传入的 HTTP 和 HTTPS 请求。

构建综合视图

当你还不清楚集群中有哪些常见工作负载类型时,kubectl get all 可以提供一个综合概览。添加 -A 可以沿用上文的所有命名空间范围:

kubectl get all -A

该命令会集中显示 Pod、Service、DaemonSet、Deployment、ReplicaSet 和 Job 等常见资源。你可能会在多个层级看到同一个组件,例如 Deployment、ReplicaSet 和 Pod。

尽管名称是 get all,它并不会返回所有资源。ConfigMap、Secret、NetworkPolicy 以及许多其他资源都不会显示。应将它用于快速了解环境,然后再请求具体的资源类型。

步骤检查点

命名空间提供资源范围,Pod 负责运行容器,Deployment 负责维持期望数量的 Pod 副本,Service 则为不断变化的 Pod 提供稳定的网络访问入口。

总结

你已经完成了第一次 Kubernetes 集群引导式探索。你了解到 Kubernetes 会跨节点管理期望状态,而 kubectl 会使用当前 kubeconfig 上下文与 API 服务器通信。

你练习了如何区分 Minikube、Kubernetes 和 kubectl 的版本;确认上下文和节点是否就绪;识别控制平面、节点及网络组件;使用标签和选择器;在 getget -o widedescribe 之间进行选择;解读节点条件与资源容量;并理解命名空间、Pod、Deployment 和 Service 之间的关系。

对于初学者来说,最重要的习惯是在修改任何内容之前先进行检查:确认当前上下文,检查节点健康状况,确定相关的命名空间和资源类型,并仔细阅读系统报告的状态。后续实验将在此基础上,带你创建自己的工作负载。