Files
docker_practice/14_kubernetes_setup/14.2_kubeadm-docker.md
T
yeasy 141fdc80bc fix(examples): 修正若干无法按原样执行的命令
* appendix/repo/nodejs.md:`docker build -t my-nodejs-app` 缺上下文参数,实际会
  报 "docker buildx build" requires exactly 1 argument;补 `.`。同文件 docker run
  示例里 `# -v "$ ":/usr/src/myapp \` 这一行的注释把自己的续行反斜杠也注掉了,加上
  紧跟的空行,命令在 `--name my-running-script` 处就结束、没有镜像名,后面几行变成
  独立的无效命令。该行内容与下一行的 --mount 重复,且 `"$ "` 已是残缺文本,删去。

* 06_repository/6.4:`openssl s_client -connect YourDomainName OR HostIP:443` 里的
  占位符带空格,shell 会切成三个参数,-connect 只收到 YourDomainName,openssl 直接
  报错;`docker login YourDomainName OR HostIP` 同理。改为一个变量。

* 08_data/8.2:`docker run -v $(pwd):/app -p 3000:3000 node npm run dev` 跑不起来
  ——官方 node 镜像没有设置 WORKDIR(docker-node 的 Dockerfile 里只有 ENTRYPOINT
  与 CMD),工作目录是 /,npm 找不到 /package.json。补 -w /app,顺手引号包住 $(pwd)
  并给出确定的标签(本书 4.1、7.10 都要求避免 latest)。

* 12_implementation/12.6:整段用的是 iproute2(ip link add / ip netns exec),中间
  却夹了一句 `brctl addif`。bridge-utils 在当前 Debian/Ubuntu/RHEL 默认不再安装,
  照抄会在这一行断掉;改成等价的 `ip link set A master docker0`。

* 14.1/14.2 的 `sysctl --system`、14.1 join 节点的 `systemctl enable/start
  containerd`、6.4 的 `systemctl restart docker` 都缺 sudo,而紧邻的行(sudo tee、
  14.1 第 47 行的 sudo systemctl restart containerd)都带。补齐。

* 15_etcd/demo/cluster/docker-compose.yml 仍留着顶层 `version: "3.6"`,Compose 会
  警告 obsolete;11.1 明写「新文件建议直接省略该字段」,15.3 正文内联的同一份文件
  也早已省略,只有磁盘上的 demo 落下了。删除后 YAML 仍可正常解析。

* 11.4:「对于 web 项目中的一个 db 容器,可能是 web_db」是 Compose V1 的下划线拼接,
  V2 起统一改用连字符,只有 --compatibility 才回到下划线。

* 附录四 CMD 一节四处写成 `CMD ['executable', 'param1']` 单引号,还说「我们建议任何
  服务镜像都使用这种形式」。exec 形式是 JSON,单引号解析不出来会退回 shell 形式,本书
  7.4 就把 `CMD ['node', 'server.js']` 明确标为「 错误:单引号(JSON 不支持)」。
  一并把 `CMD ['PHP', '-a']` 的二进制名改回小写 php。
2026-08-07 23:26:36 -07:00

317 lines
12 KiB
Go
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 14.2 使用 kubeadm 部署 Kubernetes使用 Docker
`kubeadm` 提供了 `kubeadm init` 以及 `kubeadm join` 这两个命令作为快速创建 `Kubernetes` 集群的最佳实践
> **版本说明**本文档基于 Kubernetes v1.36 编写Kubernetes 版本更新较快约每 4 个月一个新版本),本文档中的第三方工具版本 cri-dockerdflannel仅为示例请根据实际需求更新至当前版本更完整的安装和兼容性说明请以 [Kubernetes 官方文档](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/) 为准。
> **强烈提示Docker Kubernetes 环境的时代分界**
>
> Kubernetes v1.24 内置的 `dockershim` 组件已被正式移除这意味着 **Kubernetes 不再将 Docker Engine 作为默认内置的容器运行时**虽然 Docker 仍然是你本地构建管理镜像的绝佳工具但它已不再是 kubelet 的默认运行时选项
>
> 因此**强烈推荐** 读者直接参考同目录下的[使用 kubeadm 部署 Kubernetes (CRI 使用 containerd)](14.1_kubeadm.md)作为主要的部署路线
>
> 本文档保留主要用于历史环境维护或特殊需求场景如果你必须在较新的 Kubernetes 集群中继续使用 Docker Engine 作为底层运行时你必须理解 CRI 层机制额外部署并配置第三方兼容层 `cri-dockerd`同时在部署时手动补充 `--cri-socket` 等参数约束
### 14.2.1 安装 Docker
参考[安装 Docker](../03_install/README.md) 一节安装 Docker
### 14.2.2 安装并配置 cri-dockerd
由于 Kubernetes v1.24 移除了内置的 dockershim需要额外安装 **cri-dockerd** 作为 Docker kubelet 之间的 CRIContainer Runtime Interface适配层
#### Ubuntu/Debian
```bash
# 安装 cri-dockerd
# 注意:以下以 v0.4.3 为示例;安装前请到 releases 页面核验当前版本和校验值
# 参见 https://github.com/Mirantis/cri-dockerd/releases
$ cd /tmp
$ wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.4.3/cri-dockerd-0.4.3.amd64.tgz
$ tar xzvf cri-dockerd-0.4.3.amd64.tgz
$ sudo mv cri-dockerd/cri-dockerd /usr/local/bin/
# 下载并安装 systemd service 文件
$ wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.service
$ wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.socket
$ sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' cri-docker.service
$ sudo mv cri-docker.service cri-docker.socket /etc/systemd/system/
# 启动 cri-dockerd
$ sudo systemctl daemon-reload
$ sudo systemctl enable cri-docker
$ sudo systemctl start cri-docker
# 验证安装
$ sudo /usr/local/bin/cri-dockerd --version
```
#### CentOS/Fedora
```bash
# 安装 cri-dockerd
# 注意:以下以 v0.4.3 为示例;安装前请到 releases 页面核验当前版本和校验值
# 参见 https://github.com/Mirantis/cri-dockerd/releases
$ cd /tmp
$ wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.4.3/cri-dockerd-0.4.3.amd64.tgz
$ tar xzvf cri-dockerd-0.4.3.amd64.tgz
$ sudo mv cri-dockerd/cri-dockerd /usr/local/bin/
# 下载并安装 systemd service 文件
$ wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.service
$ wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.socket
$ sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' cri-docker.service
$ sudo mv cri-docker.service cri-docker.socket /etc/systemd/system/
# 启动 cri-dockerd
$ sudo systemctl daemon-reload
$ sudo systemctl enable cri-docker
$ sudo systemctl start cri-docker
```
### 14.2.3 安装 **kubelet****kubeadm****kubectl**
需要在每台机器上安装以下的软件包
#### Ubuntu/Debian
```bash
$ K8S_MINOR="v1.36"
$ sudo apt-get update
$ sudo apt-get install -y ca-certificates curl gpg
$ sudo install -m 0755 -d /etc/apt/keyrings
$ curl -fsSL "https://pkgs.k8s.io/core:/stable:/${K8S_MINOR}/deb/Release.key" | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
$ sudo chmod a+r /etc/apt/keyrings/kubernetes-apt-keyring.gpg
$ echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/${K8S_MINOR}/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install -y kubelet kubeadm kubectl
$ sudo apt-mark hold kubelet kubeadm kubectl
```
#### CentOS/Fedora
```bash
$ K8S_MINOR="v1.36"
$ cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/${K8S_MINOR}/rpm/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/${K8S_MINOR}/rpm/repodata/repomd.xml.key
EOF
$ sudo yum install -y kubelet kubeadm kubectl
```
### 14.2.4 修改内核的运行参数
#### cgroup v2 要求必须
Kubernetes v1.36 默认要求节点使用 cgroup v2kubelet cgroup v1 节点上默认会拒绝启动但管理员可以在 kubelet 配置中设置 `failCgroupV1: false` 来兼容 cgroup v1仅建议用于遗留系统过渡期)。验证节点是否支持 cgroup v2
```bash
$ mount | grep cgroup2
```
如果输出包含 `cgroup2`则系统已支持 cgroup v2对于仍在使用 cgroup v1 的系统如较旧的 RHEL 8),建议升级内核或更新系统配置以启用 cgroup v2
#### 加载内核模块
```bash
$ cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
$ sudo modprobe overlay
$ sudo modprobe br_netfilter
```
#### swap 设置现代集群仍建议优先关闭
在现代 Kubernetes Linux 节点已经支持更细粒度的 swap 行为控制对于多数 `kubeadm` 教学环境**优先关闭 swap 仍然是最稳妥的默认做法**因为这样最接近常见生产基线也能避免不同发行版和 kubelet 配置差异带来的排障成本
如果你明确要在启用 swap 的前提下运行节点则应额外核对 kubelet `NoSwap` / `LimitedSwap` 配置与当前 Kubernetes 版本文档而不要把开着 swap 也能跑直接当作通用默认路径
```bash
$ sudo swapoff -a
# 如需永久禁用,可在 /etc/fstab 中注释 swap 对应行
```
```bash
$ cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
# 应用配置
$ sudo sysctl --system
```
### 14.2.5 配置 kubelet
为了让 kubelet 正确运行我们需要对其进行一些必要的配置
#### 修改 `kubelet.service`可选IPVS 模式
> **注意**kube-proxy IPVS 模式已在 Kubernetes 1.35 中被标记为弃用Kubernetes 1.36 文档仍将其列为已弃用模式并推荐迁移到 nftables新部署应使用默认的 iptables 模式或 nftables 模式Kubernetes 1.33+ 稳定)。以下 IPVS 配置仅供旧环境参考
`/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容
```bash
# 启用 ipvs 相关内核模块(已弃用,建议迁移至 nftables)
[Service]
ExecStartPre=-/sbin/modprobe ip_vs
ExecStartPre=-/sbin/modprobe ip_vs_rr
ExecStartPre=-/sbin/modprobe ip_vs_wrr
ExecStartPre=-/sbin/modprobe ip_vs_sh
```
执行以下命令应用配置
```bash
$ sudo systemctl daemon-reload
```
### 14.2.6 部署
安装配置完成后我们将分别在 Master 节点和 Worker 节点上进行部署操作
#### master
```bash
$ sudo kubeadm init --pod-network-cidr 10.244.0.0/16 \
--cri-socket unix:///var/run/cri-dockerd.sock \
--v 5
```
* `--cri-socket unix:///var/run/cri-dockerd.sock` 参数指定使用 cri-dockerd 作为容器运行时接口
* `--pod-network-cidr 10.244.0.0/16` 参数与后续 CNI 插件有关这里以 `flannel` 为例若后续部署其他类型的网络插件请更改此参数
* kubeadm 默认使用 `registry.k8s.io` 拉取 Kubernetes 控制平面镜像受限网络环境可通过 kubeadm 配置文件中的 `imageRepository` 指向受信任镜像仓库不要把第三方镜像仓库当成通用默认值
> `kubeadm` 预检失败应按提示修复缺失依赖内核参数swap 或运行时配置实验环境确需忽略预检时只忽略明确理解且可接受的单项检查不建议使用 `--ignore-preflight-errors=all`
执行成功会输出
```bash
...
[addons] Applied essential addon: CoreDNS
I1116 12:35:13.270407 86677 request.go:538] Throttling request took 181.409184ms, request: POST:https://<CONTROL_PLANE_HOST>:6443/api/v1/namespaces/kube-system/serviceaccounts
I1116 12:35:13.470292 86677 request.go:538] Throttling request took 186.088112ms, request: POST:https://<CONTROL_PLANE_HOST>:6443/api/v1/namespaces/kube-system/configmaps
[addons] Applied essential addon: kube-proxy
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join <CONTROL_PLANE_HOST>:6443 --token <TOKEN> \
--discovery-token-ca-cert-hash sha256:<DISCOVERY_TOKEN_CA_CERT_HASH>
```
#### node 工作节点
**另一主机** 重复 **部署** 小节以前的步骤安装配置好 kubelet根据提示加入到集群
```bash
$ kubeadm join <CONTROL_PLANE_HOST>:6443 --token <TOKEN> \
--discovery-token-ca-cert-hash sha256:<DISCOVERY_TOKEN_CA_CERT_HASH> \
--cri-socket unix:///var/run/cri-dockerd.sock
```
其中 `<CONTROL_PLANE_HOST>``<TOKEN>` `<DISCOVERY_TOKEN_CA_CERT_HASH>` 应使用你自己的 `kubeadm init` 输出不要复用示例值
### 14.2.7 查看服务
所有服务启动后查看本地实际运行的 Docker 容器这些服务大概分为三类主节点服务工作节点服务和其它服务
#### 主节点服务
* `apiserver` 是整个系统的对外接口提供 RESTful 方式供客户端和其它组件调用
* `scheduler` 负责对资源进行调度分配某个 pod 到某个节点上
* `controller-manager` 负责管理控制器包括 endpoint-controller (刷新服务和 pod 的关联信息) replication-controller (维护某个 pod 的复制为配置的数值)
#### 工作节点服务
* `proxy` pod 上的服务提供访问的代理
#### 其它服务
* Etcd 是所有状态的存储数据库
### 14.2.8 使用
`/etc/kubernetes/admin.conf` 复制到 `~/.kube/config`
执行 `$ kubectl get all -A` 查看启动的服务
由于未部署 CNI 插件CoreDNS 未正常启动如何使用 Kubernetes请参考后续章节
### 14.2.9 部署 CNI
这里以 `flannel` 为例进行介绍
#### flannel
检查 podCIDR 设置
```bash
$ kubectl get node -o yaml | grep CIDR
# 输出
podCIDR: 10.244.0.0/16
podCIDRs:
```
```bash
# 注意:以下以 v0.28.4 为示例;安装前请到 releases 页面核验当前版本
# 参见 https://github.com/flannel-io/flannel/releases
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.4/Documentation/kube-flannel.yml
```
### 14.2.10 master 节点默认不能运行 pod
如果用 `kubeadm` 部署一个单节点集群默认情况下无法使用请执行以下命令解除限制
```bash
$ kubectl taint nodes --all node-role.kubernetes.io/control-plane-
# 较旧版本使用 master taint
# $ kubectl taint nodes --all node-role.kubernetes.io/master-
# 恢复默认值
# $ kubectl taint nodes NODE_NAME node-role.kubernetes.io/control-plane=true:NoSchedule
...
```