目录

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,完整链路如下所示。

flowchart LR A[安装 kind 与 kubectl] --> B[创建集群<br/>kind create cluster] B --> C[kubectl get nodes<br/>验证节点 Ready] C --> D[编写 nginx Deployment YAML] D --> E[kubectl apply<br/>部署应用] E --> F[暴露 Service<br/>或 port-forward] F --> G[curl 验证<br/>nginx 首页]

图 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 就等于切换"连到哪个集群、以谁的身份",这是多集群管理的核心机制。

flowchart TB subgraph 客户端 KUBECTL[kubectl 命令] end subgraph kubeconfig 文件 CURRENT[current-context<br/>当前激活上下文] CLUSTER[cluster<br/>server 地址 + CA 证书] USER[user<br/>客户端证书 / Token] CURRENT --> CLUSTER CURRENT --> USER end KUBECTL -->|读取 ~/.kube/config| CURRENT CLUSTER -->|指定连接地址与 TLS| APISERVER[kube-apiserver] USER -->|携带认证凭证| APISERVER APISERVER -->|调度期望状态| KUBELET[kubelet<br/>工作节点] KUBELET -->|驱动| RUNTIME[容器运行时]

图 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: worker
kind create cluster --name k8s-learning --config kind-config.yaml

kubectl 验证集群状态

集群创建完成后,用 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-learning

get-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: 80
kubectl 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: 30080
kubectl apply -f nginx-service.yaml
kubectl get svc nginx-svc

kind 集群的节点是 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。