加载中...

Kubernetes 安装

Linux 安装k8s 保姆级教程

在安装 k8s 之前我们先了解一下什么是 k8s

什么是k8s?

k8s 的概念

K8s 是 Kubernetes 的简称。这个缩写取自首字母 “K” 和尾字母 “s”,中间正好有 8 个字母(ubernete),因此得名。

K8s 是一个开源的容器编排(Container Orchestration)平台。它最初由 Google 开发(基于其内部系统 Borg),并于 2014 年开源,目前由云原生计算基金会(CNCF)维护。

如果把容器(如 Docker)比作装满货物的“集装箱”,那么 K8s 就是调度和管理这些集装箱的“大型货轮”或“港口调度员”

k8s 是做什么的

  • 自动化部署和回滚:K8s 会自动帮你部署。如果更新版本出错了,它也能自动回滚。
  • 服务发现与负载均衡:K8s 可以为一组容器提供统一的访问入口(IP 或域名),并自动平衡流量,确保不会因为某个容器压力过大而崩溃。
  • 自我修复(Self-healing):如果某个容器挂了,K8s 会立即发现并重启一个新的;如果某个服务器(节点)挂了,它会把上面的容器迁移到健康的服务器上。
  • 弹性伸缩(Scaling):当流量高峰来临时,K8s 可以在几秒钟内自动增加容器数量;流量减少时再自动缩减,节省成本。
  • 存储编排:无论你的数据存在本地、云端还是分布式系统中,K8s 都能自动挂载这些存储系统。

核心架构(它是如何工作的?)

  • 控制平面(Control Plane / Master 节点):集群的大脑,负责做决策(比如调度哪些容器到哪个机器运行)。
    • API Server:整个系统的入口,所有指令都通过它下发。
    • etcd:保存集群所有配置和状态的数据库。
    • Scheduler(调度器):决定把容器放到哪台机器上。
    • Controller Manager:负责执行任务,比如确保副本数量始终正确。
  • 工作节点(Worker Nodes / Node 节点):真正干活的机器,运行容器化的应用。
    • kubelet:节点上的管家,负责与 Master 通信并执行任务。
    • kube-proxy:负责网络通信。

几个基本概念

  • Pod:K8s 的最小调度单位。一个 Pod 里面可以包含一个或多个容器(通常是一个)。你可以把它理解为装着容器的吊篮。
  • Deployment:定义应用该如何运行的策略(比如运行几个副本、用哪个镜像)。
  • Service:定义如何访问一组 Pod(解决 Pod 频繁变动导致 IP 改变的问题)。
  • Namespace:用于虚拟隔离。比如把“开发环境”和“生产环境”在逻辑上分开。

准备工作

服务器准备

准备至少三台服务器,或者虚拟机。如果没有,则可以看 MiniKube 的教程 把 master 和 worker 都部署到一起。 我这里准备了3台ubuntu 24的虚拟机。使用的 windows 的 Hyper-V 安装的。

ip作用
192.168.50.180Master
192.168.50.181Worker
192.168.50.183Worker
  • 每台服务器至少2核CPU和2G内存(内存是k8s 强制要求),且互相之间网络互通,也需要能连外网,因为需要下载k8s的安装文件以及相关的程序的包(比如Docker等),且拥有sudu权限。
  • 本地测试,我这边是关闭防火墙的,如果是生产环境,需要放行特定的端口,视具体环境而定。
    • 关闭防火墙的命令是:sudo ufw disable
  • 需要关闭Swap交换内存。
    • 关闭交换分区的命令是:
        # 临时关闭,重启失效
        sudo swapoff -a
        # 永久关闭(注释配置文件:/etc/fatab 中 /swap/开头的那一行配置即可)
        sudo sed -i '/swap/ s/^\(.*\)$/#\1/g' /etc/fstab
      swapoff.png
    • 关闭swap分区的原因是:Kubernetes的调度器(也就是Scheduler) 在分配Pod到节点时,是根据 内存绝对值(也就是具体的内存,如 2G,4G 等,不是内存使用占比) 计算的。因此,当内存不足的时候:
      • 如果没有关闭swap分区。系统就会使用交换分区的内存,导致性能下降,甚至进程卡住,但是程序不会崩溃。
      • k8s希望当内存不足的时候是肢解杀掉Pod,并重新调度Pod,而不是让整个节点(worker)变慢或卡住。
    • 配置内核模块和网络参数
          cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
          overlay
          br_netfilter
          EOF
      
          sudo modprobe overlay
          sudo modprobe br_netfilter
      
          # 配置 sysctl 参数
          cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
          net.bridge.bridge-nf-call-iptables  = 1
          net.bridge.bridge-nf-call-ip6tables = 1
          net.ipv4.ip_forward                 = 1
          EOF
      
          # 应用参数
          sudo sysctl --system 
      conf
      • 原因: 默认情况下,Linux 仅仅作为一台主机,不会转发不属于自己的流量。但在 K8s 中,每个 Node 实际上是一个路由器,它需要把发往 Pod IP 的流量转发到对应的容器网络接口(veth pair)。如果不开启,Pod 只能访问本机,无法访问外网或其他节点。 做完了这些之后,就可以准备开始安装k8s以及相关的组件了。

安装容器运行时

所有节点都需要安装(可选Docker或者Containerd)。

Kubernetes 从 1.24版本开始,移除了 dockershim 。如果使用 docker 作为容器运行时,可往下翻。

使用Containerd作为容器运行时

安装Containerd (有可能在国内拉不下来镜像)
# 安装 Docker 官方 GPG Key 和 Repo (为了获取最新版 containerd)
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update
sudo apt-get install -y containerd.io
配置Containerd

必须配置 SystemdCgroup,否则 kubelet 会启动失败。

 # 生成默认配置
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml

# 修改配置以启用 SystemdCgroup
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml

# 重启 containerd
sudo systemctl restart containerd

使用Docker作为容器运行时

安装Docker
# 1. 更新并安装依赖
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg

# 2. 添加 Docker 官方 GPG Key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# 3. 添加 Docker 仓库 (Ubuntu 24.04 代号为 noble)
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 4. 安装 Docker
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 5. 配置 Docker 使用 systemd 作为 cgroup 驱动,同时添加docker国内镜像源
cat <<EOF | sudo tee /etc/docker/daemon.json
{ 
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://doublezonline.cloud",
    "https://dislabaiot.xyz",
    "https://docker.fxxk.dedyn.io",
    "https://dockerpull.org",
    "https://docker.unsee.tech",
    "https://hub.rat.dev",
    "https://docker.1panel.live",
    "https://docker.nastool.de",
    "https://docker.zhai.cm",
    "https://docker.5z5f.com",
    "https://a.ussh.net",
    "https://docker.udayun.com",
    "https://hub.geekery.cn",
    "https://registry.aliyuncs.com"
  ],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

# 6. 重启 Docker
sudo systemctl daemon-reload
sudo systemctl restart docker

# 7. 查看docker配置, 如果出现在daemon.json中配置的内容,即为成功.
sudo docker info 

Q:为什么要配置使用 systemd 作为 cgroup 驱动?

A:

  • Cgroup 是 Linux 用于限制进程资源(CPU、内存)的机制。
  • Ubuntu 系统默认使用 systemd 来管理所有进程的 Cgroup。
  • Docker 默认使用 cgroupfs 来管理容器 Cgroup。
  • 如果两者不一致,系统会有两套资源管理器在打架,导致 K8s 节点不稳定甚至 kubelet 崩溃。必须统一为 systemd。
安装cri-dockerd
  • 为什么需要安装cri-dockerd
    • 简单来说就是用于docker和k8s 之间做交互的。
    • 在k8s 1.24版本之前,k8s 官方维护了一个叫 dockershim 的组件,但是在1.24版本之后,官方移除了这个组件。
    • 所以如果安装1.24之后的k8s 就需要安装 cri-dockerd 用于 k8s 跟 docker之间的交互。
    • 它的执行流程是:kubelet (发送指令)->cri-dockerd (解释为docker认识的指令)->docker engine (执行指令)
  • 安装

可以在 cri-dockerd 发布日志 上查看 cri-dockerd 的版本,进行下载

# 获取当前最新的版本号变量(或者手动指定)
VER=$(curl -s https://api.github.com/repos/Mirantis/cri-dockerd/releases/latest | grep tag_name | cut -d '"' -f 4 | sed 's/v//g')

# 下载适配 Ubuntu jammy/noble 的 amd64 包
wget https://github.com/Mirantis/cri-dockerd/releases/download/v${VER}/cri-dockerd_${VER}.3-0.ubuntu-jammy_amd64.deb

# 安装
sudo dpkg -i cri-dockerd_${VER}.3-0.ubuntu-jammy_amd64.deb

# 修复潜在的依赖问题(如果有)
sudo apt-get install -f

也可以自己在cri-dockerd的仓库地址中自己下载对应的安装包下来,然后 scp 传到服务器中,执行后面两条指令即可安装。

配置cri-dockerd
  • 修改 Pause 镜像地址
    • 找到 cri-docker.service 的 systemd文件
    • ExecStart 这一行的尾部添加 --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.10.1
vim /lib/systemd/system/cri-docker.service

cri-docker.service

  • 配置原因:
    • 每个 Pod 启动时,都会先启动一个极其微小的容器叫 pause。它的唯一作用是占住网络命名空间(Network Namespace),让同一个 Pod 内的其他容器共享同一个 IP。
    • 默认的 pause 镜像在 Google 的服务器上 (k8s.gcr.io),国内网络通常拉取失败,导致 Pod 一直处于 Pending 或 ContainerCreating 状态。改成阿里云镜像可以解决网络问题。

安装k8s组件

安装好容器运行时就可以安祖行k8s 组件了: kubelet,kubeadm,kubectl.

安装

# 1. 准备 Key 和源
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

# 2. 安装
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
# 3. 锁定版本。防止因 apt-get upgrade 自动更新了
sudo apt-mark hold kubelet kubeadm kubectl  
# 4. 验证安装结果,如果显示版本则代表按钻过成功
sudo kubectl version 

初始化 Master

可以使用命令行初始化,也可以使用配置文件进行初始化。

  • 使用命令行初始化
sudo kubeadm init \
  --node-name=master-node \
  --image-repository=registry.aliyuncs.com/google_containers \
  --cri-socket=unix:///var/run/cri-dockerd.sock \
  --pod-network-cidr=192.168.0.0/16 \
  --kubernetes-version=v1.30.0
  • image-repository:使用镜像源,这里配置阿里云的,可加速镜像拉取。
  • cri-socket:设置 socket 接口文件路径
    • 默认情况下,kubelet 会自动探测节点上有什么运行时。如果它发现了 Containerd,它就会直接连接 Containerd(因为 Containerd 原生支持 CRI)。此参数让kubelet使用cri-dockerd。
  • pod-network-cidr:K8s 的 Pod 网络与主机网络是隔离的。我们需要预先划分一个私有网段(例如 192.168.0.0/16)给 Pod 使用。后续安装的网络插件(Calico)会根据这个范围分配 IP。

这个命令执行成功后会给两个提示:

  • 一个提示拷贝配置文件。
  • 另一个给出了worker节点加入集群的命令。
  • 使用配置文件进行初始化
    • 生成默认配置文件模板

        # 生成包含 InitConfiguration, ClusterConfiguration 和 KubeletConfiguration 的完整模板
        kubeadm config print init-defaults --component-configs KubeletConfiguration > kubeadm-config.yaml
    • 修改配置文件

        apiVersion: kubeadm.k8s.io/v1beta4  # v1.35 通常使用 v1beta4 或 v1beta3
        kind: InitConfiguration
        localAPIEndpoint:
          advertiseAddress: 192.168.50.180   # 修改为你 Master 节点的实际 IP
          bindPort: 6443
        nodeRegistration:
          criSocket: unix:///var/run/cri-dockerd.sock # 必须指向 cri-dockerd 的套接字
          name: master-node                 # 你的主机名,或者保持默认
          taints: null                      # 可选:如果你想让 Master 也能跑业务 Pod,设为 null
        ---
        apiVersion: kubeadm.k8s.io/v1beta4
        kind: ClusterConfiguration
        kubernetesVersion: v1.35.0          # 指定版本
        imageRepository: registry.aliyuncs.com/google_containers # 国内使用阿里云镜像
        networking:
          dnsDomain: cluster.local
          podSubnet: 192.168.0.0/16         # Calico 默认网段,必须配置
          serviceSubnet: 10.96.0.0/12
        scheduler: {}
        ---
        apiVersion: kubelet.config.k8s.io/v1beta1  # 和上面的两个配置的值不一样。如果修改不正确,在初始化 master 的时候会报错。
        kind: KubeletConfiguration
        cgroupDriver: systemd               # 设置cgroup,Ubuntu 24 + Docker 必须显式指定 systemd
        failSwapOn: true                    # 默认 true,如果没关 swap 这里设为 false 但是不推荐不关闭swap
    • 验证配置文件

        # 预拉取镜像,
        sudo kubeadm config images pull --config kubeadm-config.yaml

      如果你看到类似[config/images] Pulled registry.aliyuncs.com/...的输出且没有报错,说明:

      • 配置文件格式正确。
      • cri-dockerd 连接正常。
      • 阿里云镜像源访问正常。
    • 使用配置文件开始初始化

        sudo kubeadm init --config kubeadm-config.yaml

将执行结果中提示执行的指令执行一下。

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

kubectl 本身只是个 HTTP 客户端。它需要知道 API Server 的地址,以及最重要的——管理员证书(密钥)。这个文件里包含了连接集群所需的所有认证信息。

安装网络插件

如果下载不下来配置文件可以在可访问到github的机器上下载文件之后,scp到服务器即可。

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/custom-resources.yaml

K8s 定义了网络接口标准(CNI),但自己不实现具体的网络功能(比如怎么在这个节点给 Pod 分配 IP,怎么把包路由到另一个节点的 Pod)。

如果不安装 CNI 插件,CoreDNS 等系统组件启动不了,节点状态会一直是 NotReady。Calico 负责打通节点间的隧道(IPIP/BGP),让不同机器上的 Pod 能互相 Ping 通。

在worker节点加入集群

# 执行 初始化master 章节给出的指令,如果是使用 cri-dockerd 作为容器运行时,则需要在命令最后加上 --cri-socket=unix:///var/run/cri-dockerd.sock 
kubeadm join 192.168.50.180:6443 --token fhun78.rf36l41t6h5druup --discovery-token-ca-cert-hash sha256:5137533109b8160818de26e605d3a141cec853b4c56fab46ea85df99a7501192 --cri-socket=unix:///var/run/cri-dockerd.sock
  • Worker 节点通过 Token 认证加入集群。
  • Worker 节点也需要运行 Pod,所以它也必须知道使用哪个运行时。必须在 join 命令中同样指定 cri-socket,否则 Worker 可能会错误地连接到 containerd 或者报错。

验证安装

kubectl get nodes -o wide

如果得到类似下面的输出。则为成功 kubeadm-result.service

如果你发现 k8s 的访问协议是 https ,不必惊慌(哪怕你是通过ip访问),因为 k8s 默认使用https安全协议,但它的证书是自签名的,而且是发给集群内部域名的,并不是发给你的本地ip或者域名。当你访问出现不安全的连接时,点击继续访问即可。

L-Pig
L-Pig
© 2025 by L-Pig 本文基于 CC BY-NC-SA 4.0 许可 CC 协议 必须注明创作者 仅允许将作品用于非商业用途 改编作品必须遵循相同条款进行共享 最后更新:2026/2/14