k8s 集群搭建与 kubectl 实操

导读
本篇解决本地 K8s 学习链路上的三个核心问题:用什么工具在单机上拉起一个可用的集群、kubectl 命令体系如何覆盖日常运维动作、怎样把一个 nginx Deployment 跑起来并从本机访问到它。选型上以 kind 为主力,因为它启动快、资源占用低,且能直接复用本机已有的 Docker 环境。
核心概念
本地拉起 K8s 集群有三条主流路径,差异体现在运行载体、启动开销和拓扑能力上。
minikube 是历史最久的单机方案,默认在虚拟机或 Docker 容器里跑一个单节点集群,自带 dashboard 和 addons 体系,适合零基础入门和快速体验官方插件。它的代价是启动偏慢,多节点拓扑支持有限,资源占用相对固定。
kind(Kubernetes IN Docker)用 Docker 容器模拟 K8s 节点,一个容器既是 node 又内嵌 kubelet 和容器运行时。启动通常只需几秒,支持用配置文件声明多控制面、多工作节点的拓扑,是 Kubernetes 自身 CI 和社区测试的事实标准,适合需要模拟真实多节点行为的场景。
kubeadm 是官方集群引导工具,本身不提供运行载体,而是直接在真实机器(裸机、云主机)上初始化控制面并引导工作节点加入。它面向生产环境搭建,需要自行准备机器、网络和容器运行时,学习成本最高但最贴近真实部署。
三者并非互斥:kind 负责本地开发与测试,kubeadm 负责生产集群初始化,minikube 介于两者之间偏重教学。本篇选用 kind,完整链路如下所示。
图 1 描绘了从工具安装到访问验证的完整步骤链路。这条链路也是后续所有 K8s 实操的基本骨架:装工具、建集群、验状态、写清单、下发、暴露、访问,每一步都对应一个可验证的产物。
图解原理
kubectl 本身不直接操作节点,所有读写请求都发往 kube-apiserver,节点上的 kubelet 再根据 apiserver 的期望状态驱动容器运行时。kubectl 要连到哪个 apiserver、用什么身份认证,完全由 kubeconfig 文件决定。
kubeconfig 是一个 YAML 文件,默认路径 ~/.kube/config,内部由三组对象构成:clusters 描述要连接的 apiserver 地址和 CA 证书,users 描述认证凭证(客户端证书或 Token),contexts 把一个 cluster 和一个 user 绑定成一组可切换的连接上下文。current-context 字段记录当前激活的 context,切换 context 就等于切换"连到哪个集群、以谁的身份",这是多集群管理的核心机制。
图 2 展示了 kubectl 经由 kubeconfig 到达 apiserver 的连接模型。context 是三要素的粘合层:它引用一个 cluster 提供连接目标,引用一个 user 提供身份凭证,kubectl 每次发请求时都从 current-context 取出这两者组装成 TLS 连接。理解这个模型后,多集群、多租户的切换就只是改一个字段的事。
动手实操
安装 kind 与 kubectl
前提是本机已装好 Docker 并能正常拉取镜像。kind 把每个节点跑成一个 Docker 容器,没有 Docker 就没有运行载体。
# macOS 通过 Homebrew 安装 kind
brew install kind
# 或下载二进制(按平台替换 url 中的 darwin-amd64)
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.23.0/kind-darwin-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/
# kubectl 同理
brew install kubectl
kubectl version --client拉起第一个集群
单节点集群只需一条命令。kind 会自动拉取节点镜像、初始化控制面,并把 kubeconfig 写入 ~/.kube/config。
kind create cluster --name k8s-learning若要模拟多节点拓扑,先写一份配置文件再创建。下面的配置声明一个控制面加两个工作节点,适合后续观察 Pod 调度分布。
# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: workerkind create cluster --name k8s-learning --config kind-config.yamlkubectl 验证集群状态
集群创建完成后,用 get 系列命令确认节点就绪。
kubectl get nodes
kubectl cluster-info正常输出里每个节点 STATUS 应为 Ready,control-plane 和 worker 角色分明。若看到 NotReady,通常是节点容器还在初始化网络插件,等待十几秒后重新查询即可。
kubeconfig 与 context 切换
kind 创建集群时已自动生成并切换到对应 context。查看当前所有上下文与激活项,能帮你避免误操作到别的集群。
kubectl config get-contexts
kubectl config current-context
kubectl config use-context kind-k8s-learningget-contexts 列出所有 context 及其绑定的 cluster、user,星号标记当前激活项。use-context 切换激活 context,之后的 kubectl 命令都会指向该集群。
kubectl 核心命令体系
掌握下面七条命令,就能覆盖日常 80% 的运维动作。先用系统自带资源练手,再处理自定义应用。
# get:列出资源,-A 跨所有命名空间
kubectl get pods -A
kubectl get nodes -o wide
# describe:查看资源详细事件与状态,排错首选
kubectl describe node k8s-learning-worker
# apply:声明式下发,幂等创建或更新
kubectl apply -f nginx-deployment.yaml
# delete:按文件或按名称删除
kubectl delete -f nginx-deployment.yaml
kubectl delete pod <pod-name>
# logs:查看容器日志,--tail 限制行数
kubectl logs -l app=nginx --tail=20
# exec:进入容器执行命令
kubectl exec -it <pod-name> -- nginx -v
# port-forward:把本地端口转发到 Pod,临时访问用
kubectl port-forward deployment/nginx-deploy 8080:80部署 nginx Deployment
写一份 Deployment 清单,声明两个副本。YAML 里的 selector 与 template.labels 必须一致,否则 apiserver 会拒绝创建。
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80kubectl apply -f nginx-deployment.yaml
kubectl get pods -l app=nginx -o wide
kubectl describe deployment nginx-deploy-o wide 会额外显示 Pod 调度到哪个节点、内部 IP,多节点集群下能直观看到副本分布。
验证访问
临时访问用 port-forward,它把本地 8080 端口直接接到 Deployment 的 80 端口,不需要 Service。
# 前台运行,另开终端执行 curl
kubectl port-forward deployment/nginx-deploy 8080:80
curl http://localhost:8080看到 nginx 默认欢迎页即说明 Pod 真正起来了。更持久的方式是创建 Service,用 NodePort 在节点上暴露固定端口。
# nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080kubectl apply -f nginx-service.yaml
kubectl get svc nginx-svckind 集群的节点是 Docker 容器,NodePort 无法直接从宿主机访问。需要通过 port-forward 转发到 Service,或用 kubectl port-forward svc/nginx-svc 8080:80 绕过这一限制。
常见问题与避坑
kind 节点镜像拉取慢或超时。kind 依赖的 kindest/node 镜像从 docker.io 拉取,国内网络容易超时。解决办法是提前手动拉取并改用本地镜像,或在 create 时通过 --image 指定已加速的镜像源标签。
port-forward 长时间空闲自动断开。kubectl 的 port-forward 默认有空闲超时,长时间不产生流量会被内核回收连接。需要持续访问时,用 Service 的 NodePort 或 LoadBalancer 替代,或加 --keepalive 参数保活。
context 指向错误集群导致误删。多集群环境下最容易踩的坑是在生产 context 下执行了 delete。每次执行写操作前,先用 kubectl config current-context 核对当前指向,或在 delete 命令前加 --dry-run=server 预演。
小结与进阶
kind 拉起集群、kubectl 操控资源、kubeconfig 管理连接,这三者构成了 K8s 日常操作的完整闭环。下一篇将深入 Pod 与 Deployment 的调度原理,拆解副本控制器如何维持期望状态、节点如何被选中承载 Pod。