目 录CONTENT

文章目录

Kubernetes 入门(2)- 使用 Kubeadm 安装 Kubernetes 1.23.5 详解

ZERO
2022-06-25 / 0 评论 / 0 点赞 / 63 阅读 / 0 字

文章转载自: https://www.skynemo.cn/archives/01-k8s-install-with-kubeadm

本文中所有操作均以 Kubernetes 1.23.5 为基准

Kubeadm 简介

官网简介: Kubeadm | Kubernetes

Kubeadm 是快速创建 Kubernetes 集群的官方工具。它不仅提供了 kubeadm initkubeadm join 命令用于创建、加入集群,还可以用于在线升级、管理证书等应用

kubeadm 通过执行必要的操作来启动和运行最小可用集群。 按照设计,它只关注启动引导,而非配置机器。同样的, 安装其他的扩展,例如 Kubernetes Dashboard、 监控方案、以及特定云平台的扩展,都不在 kubeadm 使用范围内

理想情况下,使用 kubeadm 作为所有部署工作的基准将会更加易于创建一致性集群

安装 Kubeadm

Kubeadm 官方安装参考: 安装 kubeadm | Kubernetes

Kubernetes 版本选择

Kubernetes 最近发布版本列表:Releases | Kubernetes
Kubernetes 所有发布版本列表:Releases · kubernetes/kubernetes (github.com)

本文选择安装 Kubernetes 1.23.5

注意事项

  • 一台兼容的 Linux 主机。Kubernetes 项目为基于 Debian 和 Red Hat 的 Linux 发行版以及一些不提供包管理器的发行版提供通用的指令
  • 每台机器 2 GB 或更多的 RAM(如果少于这个数字将会影响你应用的运行内存)
  • 2 CPU 核或更多
  • 集群中的所有机器的网络彼此均能相互连接(公网和内网都可以)
  • 节点之中不可以有重复的主机名、MAC 地址或 product_uuid
  • 允许 iptables 检查桥接流量
  • 禁用交换分区。为了保证 kubelet 正常工作,你 必须 禁用交换分区
  • 启用一些必要的端口,详见 附录-端口与协议,测试环境可以直接关闭防火墙以放行端口

主机设置

检查 MAC 与 product_uuid

  • 使用命令 ip linkifconfig -a 来获取网络接口的 MAC 地址
  • 使用 sudo cat /sys/class/dmi/id/product_uuid 命令对 product_uuid 校验

一般来讲,硬件设备会拥有唯一的地址,但是有些虚拟机的地址可能会重复。 Kubernetes 使用这些值来唯一确定集群中的节点。 如果这些值在每个节点上不唯一,可能会导致安装失败

允许 iptables 检查桥接流量

确保 br_netfilter 模块被加载。这一操作可以通过运行 lsmod | grep br_netfilter 来完成。若要显式加载该模块,可执行 sudo modprobe br_netfilter

为了让你的 Linux 节点上的 iptables 能够正确地查看桥接流量,你需要确保在你的 sysctl 配置中将 net.bridge.bridge-nf-call-iptables 设置为 1。例如:

# 加载 br_netfilter 模块
root@kube-master:~# cat > /etc/modules-load.d/k8s.conf <<EOF
br_netfilter
EOF

# 配置允许 iptables 检查桥接流量
root@kube-master:~# cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

# 应用配置
root@kube-master:~# sudo sysctl --system

禁用交换分区

临时禁止

# 临时禁止,重启后恢复,适用于不能重启的主机
root@kube-master:~# swapoff -a

永久禁止

# 永久禁止,注释 /etc/fstab 中与 swap 相关的行,重启依旧有效
root@kube-master:~# vi /etc/fstab
...
# /swap.img	none	swap	sw	0	0
...

优化参数

优化内核参数及资源限制参数,详见 附录-参数优化

安装容器运行时

kubernetes 集群的每个节点均需要安装容器运行时

容器运行时官方详解:容器运行时 | Kubernetes
注:在 Kubernetes 1.24 版本往后,Kubernetes 不再包含 Dockershim

选择容器运行时

目前 Kubernetes 支持几种通用容器运行时

本文使用 Docker 20.10.6 作为容器运行时,其他容器运行时并无太大区别

Docker 版本选择需要参考 Kubernetes 的版本兼容情况,可以在 Kubernetes 最近版本列表页面Kubernetes 所有版本列表页面 点击对应的版本的 Changelog 进行查看(如果没有找到 Docker 版本信息则表示与上一版本支持情况相同)。下表列出最近 Kubernetes 对 Docker 版本的兼容情况

Kubernetes 版本 Docker版本兼容情况
1.21.x v20.10.2版本以上不兼容
1.22.x v20.10.2版本以上不兼容
1.23.x v20.10.7版本以上不兼容

安装容器运行时

操作系统以 ubuntu 20.04.x 为例

清理原有的 docker

如果你过去安装过 docker,需要先卸载

root@kube-master:~# sudo apt remove -y docker-ce docker-ce-cli containerd.io

安装依赖

root@kube-master:~# sudo apt -y install apt-transport-https ca-certificates software-properties-common gnupg2

配置仓库

此处使用了阿里云的镜像源

信任 Docker 的 GPG 公钥

root@kube-master:~# curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
    | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

添加软件源

root@kube-master:~#  echo \
    "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
    $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

更新缓存

root@kube-master:~# apt update

安装指定 Docker 版本

# 查找docker版本
root@kube-master:~# apt-cache madison docker-ce
......
 docker-ce | 5:20.10.9~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.8~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.7~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.6~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
......

# 安装指定版本的 docker-ce
root@kube-master:~# sudo apt install -y containerd.io \
    docker-ce=5:20.10.6~3-0~ubuntu-focal \
    docker-ce-cli=5:20.10.6~3-0~ubuntu-focal

检查 docker 版本

root@kube-master:~# docker --version
Docker version 20.10.6, build 370c289

配置开机自启

root@kube-master:~# sudo systemctl enable --now docker

其他配置(可选)

配置 Docker 镜像加速(推荐配置)、默认路径(可选,必须在初始化集群前配置)、存储驱动(可选,必须在初始化集群前配置)等参数

root@kube-master:~# mkdir -p /data/docker
root@kube-master:~# vim /etc/docker/daemon.json
{
  "data-root": "/data/docker",
  "registry-mirrors": ["https://sqr9a2ic.mirror.aliyuncs.com"],
  "storage-driver": "overlay2"
}

安装 kubeadm、kubelet 和 kubectl

操作系统以 ubantu 20.04.x 为例
建议三个工具版本一致,如果工具版本不能够一致,参考版本差异文档进行选择:Version Skew Policy | Kubernetes

Kubernetes 集群的每个节点均需要安装 kubeadm、kubelet、kubectl

  • kubelet 原则上不需要在控制面节点上运行。但是 kubeadm 构建集群时,apiserver、controller-manager、scheduler、etcd等服务是运行在容器上的,需要由 kubelet 进行调度,所以需要在控制面节点安装 kubelet

  • kubectl 原则上可以只在需要与集群通信的节点(一般为控制面节点)安装,但 kubeadm 依赖于 kubectl,故所有节点均需安装

软件作用

  • kubeadm:用于初始化集群的管理指令

  • kubelet:用于在集群中的每个节点上用来启动 Pod 和容器等

  • kubectl:用来与集群通信的命令行工具

安装

由于官网镜像在国内下载较慢,此处使用阿里云镜像站,安装方法参考:kubernetes安装教程-阿里巴巴开源镜像站 (aliyun.com)

安装依赖

# 更新 apt 包索引
root@kube-master:~# sudo apt-get update

# 安装  Kubernetes apt 仓库所需的依赖
root@kube-master:~# sudo apt-get install -y apt-transport-https ca-certificates curl

下载公钥

由于默认公钥在外网无法访问,此处使用的是阿里云的公钥文件

root@kube-master:~# curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg \
    https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg

添加仓库

添加阿里云的 Kubernetes apt 仓库

root@kube-master:~# cat > /etc/apt/sources.list.d/kubernetes.list <<EOF
deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF

安装

# 更新 apt 包索引
root@kube-master:~# sudo apt update

# 查看版本
root@kube-master:~# apt-cache madison kubeadm
   kubeadm |  1.23.6-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages
   kubeadm |  1.23.5-00 | https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial/main amd64 Packages

# 安装 kubelet kubeadm kubectl 指定版本( node 节点可以不安装 kubectl )
root@kube-master:~# sudo apt install -y \
      kubelet=1.23.5-00 \
      kubeadm=1.23.5-00 \
      kubectl=1.23.5-00

# 由于 kubernetes 官网未开放同步方式, 可能会有索引 gpg 检查失败的情况,可以在安装时忽略 gpg 检查
# root@kube-master:~# sudo apt --allow-unauthenticated install -y ......

# 锁定版本,防止误更新
root@kube-master:~# sudo apt-mark hold kubelet kubeadm kubectl

检查版本

root@kube-master:~# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.5", GitCommit:"c285e781331a3785a7f436042c65c5641ce8a9e9", GitTreeState:"clean", BuildDate:"2022-03-16T15:57:37Z", GoVersion:"go1.17.8", Compiler:"gc", Platform:"linux/amd64"}

安装完成后,kubelet 每隔几秒就会重启,因为它陷入了一个等待 kubeadm 指令的死循环

配置驱动(重要)

参考: 配置 cgroup 驱动 | Kubernetes

由于 kubeadm 把 kubelet 视为一个系统服务来管理,所以对基于 kubeadm 的安装 k8s 时, 官方推荐使用 systemd 作为 cgroup 的驱动,不推荐 cgroupfs 。但是容器运行时(此处为 docker)默认的 cgroup 的驱动一般都是 cgroupfs。两者的 cgroup 驱动不一致时,会出现如下错误,导致 kubelet 运行异常

kubelet cgroup driver: “systemd” is different from docker cgroup driver: “cgroupfs”

需要修改容器运行时与 kubelet 的 cgroup 驱动保持一致,推荐修改容器运行时的 cgroup 驱动为 systemd

配置容器运行时的 cgroup 驱动

其他容器运行时配置的方法,请参考官方文档:容器运行时 | Kubernetes

在 docker 的配置文件中配置 cgroup 驱动

root@kube-master:~# sudo mkdir /etc/docker
root@kube-master:~# vim /etc/docker/daemon.json
{
  "data-root": "/data/docker",
  "registry-mirrors": ["https://sqr9a2ic.mirror.aliyuncs.com"],
  "storage-driver": "overlay2",
  "exec-opts": ["native.cgroupdriver=systemd"]
}

重启 docker 使配置生效

root@kube-master:~# sudo systemctl daemon-reload
root@kube-master:~# sudo systemctl restart docker

配置 kubelet 的 cgroup 驱动

参考官方文档:配置 cgroup 驱动 | Kubernetes
kubelet 默认cgroup 的驱动为 systemd ,不推荐修改

使用配置文件初始化时,可以在配置文件中进行设置

# kubeadm-config.yaml
kind: ClusterConfiguration
apiVersion: kubeadm.k8s.io/v1beta3
kubernetesVersion: v1.21.0
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd

使用配置文件初始化

kubeadm init --config kubeadm-config.yaml

kubeadm 命令介绍

kubeadm 常用命令

  • [kubeadm init](https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-init)kubeadm init 用于搭建控制平面节点
  • [kubeadm join](https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-join) 用于搭建工作节点并将其加入到集群中
  • [kubeadm upgrade](https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-upgrade) 用于升级 Kubernetes 集群到新版本
  • [kubeadm config](https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-config) 如果你使用了 v1.7.x 或更低版本的 kubeadm 版本初始化你的集群,则使用 kubeadm upgrade 来配置你的集群
  • [kubeadm token](https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-token) 用于管理kubeadm join 使用的令牌
  • [kubeadm reset](https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-reset) 用于恢复通过 kubeadm init 或者 kubeadm join 命令对节点进行的任何变更
  • [kubeadm certs](https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-certs) 用于管理 Kubernetes 证书
  • [kubeadm kubeconfig](https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-kubeconfig) 用于管理 kubeconfig 文件
  • [kubeadm version](https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-version) 用于打印 kubeadm 的版本信息
  • [kubeadm alpha](https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-alpha) 用于预览一组可用于收集社区反馈的特性

全局选项

全局选项适用于 kubeadm 的所有命令,多为日志相关选项

    --add-dir-header           # 如果为 true,将在日志头部添加日志目录
    --log-file string          # 指定输出的日志文件
    --log-file-max-size uint   # 定义日志文件的最大大小,单位 MB,如果设置为 0,则不限制。默认为 1800
    --one-output               # 如果为 true,则只写入严重级别的日志
    --rootfs string            # 指定宿主机路径作为根路径
    --skip-headers             # 如果为 true,则日志里不显示标题前缀
    --skip-log-headers         # 如果为 true,则日志里不显示标题
-v, --v Level                  # 指定日志级别,0 ~ 5

kubeadm init 命令简介

查看帮助

root@kube-master:~# kubeadm init --help

常用选项

# 选项较多,此处仅列出较常用的选项
--apiserver-advertise-address string   # (重要)API Server 监听的 IP 地址
--apiserver-bind-port int32            # (重要)API Server 绑定的端口,默认为 6443
--apiserver-cert-extra-sans strings    # 用于 API Server 服务 SANs 扩展的证书。可以是 IP 地址和 DNS 名称

--cert-dir string                      # 指定证书存放路径,默认为 "/etc/kubernetes/pki"
--certificate-key string               # 指定一个用于加密 kubeadm certs Secret 中的控制平面证书的密钥
--config string                        # 指定 kubeadm 配置文件路径

--control-plane-endpoint string        # (重要)为控制平面指定一个稳定的 IP 地址或 DNS 名称。常用于多 master 时指定统一的 VIP 地址
--cri-socket string                    # 要连接的 CRI socket 路径。如果为空,kubeadm 将自动检测;仅当安装了多个 CRI 或非标准 CRI socket 时,才会使用此选项
--dry-run                              # 测试运行,不会应用任何的更改

--feature-gates string                 # 一组 key=value 键值对,用于开关一些当前版本特有的功能,支持选项如下
                                         PublicKeysECDSA=true|false (ALPHA - default=false)
                                         RootlessControlPlane=true|false (ALPHA - default=false)
                                         UnversionedKubeletConfigMap=true|false (ALPHA - default=false)

--ignore-preflight-errors strings      # (重要)是否忽略检查过程中出现的错误信息,例如: 'IsPrivilegedUser'、'Swap'。如果设置为 'all',则忽略所有错误信息
--image-repository string              # (重要)指定容器镜像仓库,用于拉取控制面镜像,默认为 "k8s.gcr.io"
--kubernetes-version string            # (重要)指定安装的 Kubernetes 版本,默认为 "stable-1"
--node-name string                     # 指定 node 节点名称

--pod-network-cidr string              # (重要)指定 pod 网络的 IP 地址范围。如果设置,控制平面将自动为每个节点分配 CIDR,注意不要与主机网络重叠
--service-cidr string                  # (重要)指定 service 网络的 IP 地址范围,默认为 "10.96.0.0/12",注意不要与主机网络重叠
--service-dns-domain string            # (重要)为服务指定替代域名( k8s 的内部域名),默认为 "cluster.local",会由相应的 DNS 服务(kube-dns/coredns)解析生成的域名记录

--skip-certificate-key-print           # 不打印用于加密控制平面证书的密钥信息
--skip-phases strings                  # 要跳过哪些阶段
--skip-token-print                     # 跳过打印 'kubeadm init' 生成的默认 token 信息
--token string                         # 指定用于 node 节点和控制平面节点之间建立双向信任的 token
--token-ttl duration                   # token 过期时间,例如:1s、2m、3h。如果设置为“0”,令牌将永远不会过期。默认为 24h0m0s
--upload-certs                         # 将控制平面证书加载到 kubeadm certs Secret,更新证书

创建单节点集群

kubeadm 命令选项和帮助:Kubeadm | Kubernetes

主机列表

主机名 IP 角色 安装服务
kube-master.skynemo.cn 192.168.1.201 控制面节点、工作节点 docker: 20.10.6
kubeadm: 1.23.5
kubelet: 1.23.5
kubectl: 1.23.5

安装过程省略,详见:安装 Kubeadm

主机需要关闭防火墙

下载镜像

kubeadm 在初始化节点时会从镜像仓库下载镜像,默认镜像仓库由 google 提供(地址为:k8s.gcr.io),国内无法访问。需要使用科学上网方式,提前下载好所需的镜像,防止在构建过程中因镜像下载异常而导致部署失败。如果选定的版本将作为生产环境使用,可以将这些镜像保存到国内的镜像仓库,方便后续多次下载

查看所需镜像

root@kube-master:~# kubeadm config images list --kubernetes-version=1.23.5
k8s.gcr.io/kube-apiserver:v1.23.5
k8s.gcr.io/kube-controller-manager:v1.23.5
k8s.gcr.io/kube-scheduler:v1.23.5
k8s.gcr.io/kube-proxy:v1.23.5
k8s.gcr.io/pause:3.6
k8s.gcr.io/etcd:3.5.1-0
k8s.gcr.io/coredns/coredns:v1.8.6

下载镜像(需科学上网)

docker pull k8s.gcr.io/kube-apiserver:v1.23.5
docker pull k8s.gcr.io/kube-controller-manager:v1.23.5
docker pull k8s.gcr.io/kube-scheduler:v1.23.5
docker pull k8s.gcr.io/kube-proxy:v1.23.5
docker pull k8s.gcr.io/pause:3.6
docker pull k8s.gcr.io/etcd:3.5.1-0
docker pull k8s.gcr.io/coredns/coredns:v1.8.6

下载镜像(使用私人仓库)

可以使用本人在阿里云仓库保存的镜像

root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/kube-apiserver:v1.23.5
root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/kube-controller-manager:v1.23.5
root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/kube-scheduler:v1.23.5
root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/kube-proxy:v1.23.5
root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/pause:3.6
root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/etcd:3.5.1-0
root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/coredns:v1.8.6

查看下载的镜像

root@kube-master:~# docker images
REPOSITORY                                                                  TAG       IMAGE ID       CREATED        SIZE
registry.cn-shanghai.aliyuncs.com/sync-k8s-images/kube-apiserver            v1.23.5   3fc1d62d6587   6 weeks ago    135MB
registry.cn-shanghai.aliyuncs.com/sync-k8s-images/kube-proxy                v1.23.5   3c53fa8541f9   6 weeks ago    112MB
registry.cn-shanghai.aliyuncs.com/sync-k8s-images/kube-controller-manager   v1.23.5   b0c9e5e4dbb1   6 weeks ago    125MB
registry.cn-shanghai.aliyuncs.com/sync-k8s-images/kube-scheduler            v1.23.5   884d49d6d8c9   6 weeks ago    53.5MB
registry.cn-shanghai.aliyuncs.com/sync-k8s-images/etcd                      3.5.1-0   25f8c7f3da61   6 months ago   293MB
registry.cn-shanghai.aliyuncs.com/sync-k8s-images/coredns                   v1.8.6    a4ca41631cc7   6 months ago   46.8MB
registry.cn-shanghai.aliyuncs.com/sync-k8s-images/pause                     3.6       6270bb605e12   8 months ago   683kB

初始化节点

使用命令进行控制面节点初始化

root@kube-master:~# kubeadm init \
        --apiserver-advertise-address=192.168.1.201 \
        --apiserver-bind-port=6443 \
        --kubernetes-version=v1.23.5 \
        --pod-network-cidr=10.100.0.0/16 \
        --service-cidr=10.200.0.0/16 \
        --service-dns-domain=nemo.local \
        --image-repository=registry.cn-shanghai.aliyuncs.com/sync-k8s-images \
        --ignore-preflight-errors=swap

初始化完成后会输出一些配置指导信息

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

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 192.168.1.201:6443 --token pahk98.bwimpfz46v82rva3 \
	--discovery-token-ca-cert-hash sha256:1f3e810d21e68b12c88ae4cf778e7d91c9df3195b8e7acd524b7efc32fe56677

配置使用 kubectl

若要使非 root 用户可以运行 kubectl,请运行以下命令, 它们是 kubeadm init 输出的一部分配置,包含了请求的证书、密钥等信息

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

如果你是 root 用户,则可以配置环境变量 KUBECONFIG=/etc/kubernetes/admin.conf

# 配置永久环境变量
root@kube-master:~# cat > /etc/profile.d/kubeconfig.sh << EOF
export KUBECONFIG=/etc/kubernetes/admin.conf
EOF

# 加载环境变量
root@kube-master:~# source /etc/profile

允许在控制平面节点上调度 Pod

默认情况下,出于安全原因,集群不会在控制平面节点上调度 Pod。 如果希望能够在控制平面节点上调度 Pod, 例如用于开发的单机 Kubernetes 集群,请运行

root@kube-master:~# kubectl taint nodes --all node-role.kubernetes.io/master-
node/kube-master untainted

这将从任何拥有 node-role.kubernetes.io/master taint 标记的节点中移除该标记, 包括控制平面节点,这意味着调度程序将能够在任何地方调度 Pods

部署网络插件

支持的网络插件列表: 集群网络系统 | Kubernetes
常用的网络插件有: Calico flannel

在安装网络之前,集群 DNS (CoreDNS) 不会启动

# 查看当前的 pod 状态,会发现 coredns 没有启动
root@kube-master:~# kubectl get pods -A
NAMESPACE     NAME                                  READY   STATUS    RESTARTS   AGE
kube-system   coredns-bc5b69cd6-bqr4g               0/1     Pending   0          18m
kube-system   coredns-bc5b69cd6-n7qg9               0/1     Pending   0          18m
kube-system   etcd-kube-master                      1/1     Running   1          18m
kube-system   kube-apiserver-kube-master            1/1     Running   1          18m
kube-system   kube-controller-manager-kube-master   1/1     Running   1          18m
kube-system   kube-proxy-vrnq7                      1/1     Running   0          18m
kube-system   kube-scheduler-kube-master            1/1     Running   1          18m

部署网络插件

# 下载配置文件
root@kube-master:~# curl -o kube-flannel-v0.17.0-release.yml \
      https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

# 如果无法访问外网,可以使用作者的配置备份
# curl -O https://resource-1258540788.file.myqcloud.com/99-external-resource/01-kubernetes/01-flannel/kube-flannel-v0.17.0-release.yml

# 修改网络与 kubeadm init 配置的 pod 网络(由初始化选项 pod-network-cidr 指定)一致
root@kube-master:~# vim kube-flannel-v0.17.0-release.yml
......
  net-conf.json: |
    {
      "Network": "10.100.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
......

# 直接使用 kubectl 应用部署
root@kube-master:~# kubectl apply -f kube-flannel-v0.17.0-release.yml

检验集群 DNS (CoreDNS) 是否启动

root@kube-master:~# kubectl get pods -A
NAMESPACE     NAME                                  READY   STATUS    RESTARTS   AGE
kube-system   coredns-bc5b69cd6-bqr4g               1/1     Running   0          39m
kube-system   coredns-bc5b69cd6-n7qg9               1/1     Running   0          39m
kube-system   etcd-kube-master                      1/1     Running   1          39m
kube-system   kube-apiserver-kube-master            1/1     Running   1          39m
kube-system   kube-controller-manager-kube-master   1/1     Running   1          39m
kube-system   kube-flannel-ds-k476z                 1/1     Running   0          41s
kube-system   kube-proxy-vrnq7                      1/1     Running   0          39m
kube-system   kube-scheduler-kube-master            1/1     Running   1          39m

测试 Pod 的使用

查看节点状态

root@kube-master:~# kubectl get nodes -o wide
NAME          STATUS   ROLES                  AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
kube-master   Ready    control-plane,master   42m   v1.23.5   192.168.1.201   <none>        Ubuntu 20.04.4 LTS   5.4.0-100-generic   docker://20.10.6

创建 Pod 并暴露端口

root@kube-master:~# kubectl create deployment nginx --image=nginx
deployment.apps/nginx created

root@kube-master:~# kubectl expose deployment nginx --port=80 --type=NodePort
service/nginx exposed

查看 Pod 和 service 状态

root@kube-master:~# kubectl get pod,svc
NAME                         READY   STATUS    RESTARTS   AGE
pod/nginx-85b98978db-4nlx9   1/1     Running   0          66s

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.200.0.1       <none>        443/TCP        76m
service/nginx        NodePort    10.200.202.133   <none>        80:30528/TCP   31m

测试访问,返回 nginx 页面信息

root@kube-master:~# curl 192.168.1.201:30528

高可用集群拓扑

参考文档:高可用拓扑选项 | Kubernetes

高可用(HA) Kubernetes 集群拓扑通常可以分成两个选项

  • 使用堆叠(stacked)控制平面节点,其中 etcd 节点与控制平面节点共存
  • 使用外部 etcd 节点,其中 etcd 在与控制平面不同的节点上运行

堆叠(Stacked) etcd 拓扑

拓扑图

image-1656481323973

堆叠(Stacked) HA 集群最主要的特点:etcd 分布式数据存储集群堆叠在 kubeadm 管理的控制平面节点上,作为控制平面的一个组件运行

每个控制平面节点运行 kube-apiserverkube-schedulerkube-controller-manager 实例。其中,kube-apiserver 使用负载均衡器暴露给工作节点

此外,每个控制平面节点会创建一个本地 etcd 成员(member),这个 etcd 成员只与该节点的 kube-apiserver 通信。这同样适用于本地 kube-controller-managerkube-scheduler 实例

这是 kubeadm 中的默认拓扑。当使用 kubeadm initkubeadm join --control-plane 时,在控制平面节点上会自动创建本地 etcd 成员

优缺点

  • 优点:这种拓扑将控制平面和 etcd 成员耦合在同一节点上。相对使用外部 etcd 集群,设置起来更简单,而且更易于副本管理

  • 缺点:堆叠集群存在耦合失败的风险。如果一个节点发生故障,则 etcd 成员和控制平面实例都将丢失,并且冗余会受到影响。您可以通过添加更多控制平面节点来降低此风险

因此,如果使用堆叠(Stacked) etcd 拓扑,则至少应该为 HA 集群运行三个堆叠的控制平面节点

外部 etcd 拓扑

拓扑图

image-1656481400842

外部 etcd 的 HA 集群最主要的特点: etcd 分布式数据存储集群在独立于控制平面节点的其他节点上运行

每个控制平面节点都运行 kube-apiserverkube-schedulerkube-controller-manager 实例。同样, kube-apiserver 使用负载均衡器暴露给工作节点。

与堆叠(Stacked) etcd 拓扑不同的是,在外部 etcd 拓扑中,etcd 成员在非控制平面节点主机上运行,每个 etcd 主机与每个控制平面节点的 kube-apiserver 通信

优缺点

  • 优点:这种拓扑结构解耦了控制平面和 etcd 成员。在失去控制平面实例或者 etcd 成员时,产生影响较小,并且不会像堆叠的 HA 拓扑那样影响整个集群冗余
  • 缺点:此拓扑需要两倍于堆叠 HA 拓扑的主机数量

因此,如果使用外部 etcd 拓扑,则 HA 集群至少需要三个用于控制平面节点的主机和三个用于 etcd 节点的主机

创建高可用集群

堆叠(Stacked) etcd 拓扑的高可用集群构建可以参考:利用 kubeadm 创建高可用集群 | Kubernetes
外部 etcd 拓扑的高可用集群构建可以参考:利用 kubeadm 创建高可用集群 | Kubernetes

本文选用堆叠(Stacked) etcd 拓扑的高可用集群

准备

使用 5 台主机,其中 3 台作为控制面节点,2 台作为工作节点

拓扑结构

image-1656481496991

主机列表

主机 IP 角色 安装服务
kube-master-1.skynemo.cn 192.168.1.201 控制面节点-1 docker: 20.10.6
kubeadm: 1.23.5
kubelet: 1.23.5
kubectl: 1.23.5
kube-master-2.skynemo.cn 192.168.1.202 控制面节点-2 docker: 20.10.6
kubeadm: 1.23.5
kubelet: 1.23.5
kubectl: 1.23.5
kube-master-3.skynemo.cn 192.168.1.203 控制面节点-3 docker: 20.10.6
kubeadm: 1.23.5
kubelet: 1.23.5
kubectl: 1.23.5
kube-worker-1.skynemo.cn 192.168.1.204 工作节点-1 docker: 20.10.6
kubeadm: 1.23.5
kubelet: 1.23.5
kubectl: 1.23.5
kube-worker-2.skynemo.cn 192.168.1.205 工作节点-2 docker: 20.10.6
kubeadm: 1.23.5
kubelet: 1.23.5
kubectl: 1.23.5
haproxy.skynemo.cn 192.168.1.206 负载均衡 HAProxy 2.4

Kubeadm 相关安装过程省略,详见:安装 Kubeadm

HAProxy 安装过程省略,详见:HAProxy 安装

下载镜像

默认镜像仓库由 google 提供(地址为:k8s.gcr.io),国内无法访问,可以使用本人在阿里云仓库保存的镜像

提前下载好所需的镜像,防止在构建过程中因镜像下载异常而导致部署失败

控制面节点下载镜像

所有控制面节点下载如下镜像

root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/kube-apiserver:v1.23.5
root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/kube-controller-manager:v1.23.5
root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/kube-scheduler:v1.23.5
root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/pause:3.6
root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/etcd:3.5.1-0
root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/coredns:v1.8.6

工作节点下载镜像

工作节点下载如下镜像

root@kube-master:~# docker pull registry.cn-shanghai.aliyuncs.com/sync-k8s-images/kube-proxy:v1.23.5

配置 HAProxy

配置

代理三个控制面节点

root@haproxy:~# vim /etc/haproxy/haproxy.cfg
global
	maxconn 100000
	chroot /apps/haproxy/empty
	stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
	user haproxy
	group haproxy
	daemon
	pidfile /var/lib/haproxy/haproxy.pid
	log 127.0.0.1 local2 info

defaults
	option http-keep-alive
	option forwardfor
	maxconn 100000
	mode http
	timeout connect 300000ms
	timeout client 300000ms
	timeout server 300000ms

# 配置状态页面,方便查看代理情况
listen stats
	mode http
	bind 0.0.0.0:9999
	stats enable
	log global
	stats uri /haproxy-status			# haproxy 状态页 URL
	stats auth haadmin:520123			# Haproxy 状态页用户名/密码

# 配置控制面节点的代理
listen kube-apiserver
	bind 192.168.1.206:6443
	mode tcp
	log global
    balance source
	server kube-master-1 192.168.1.201:6443  check inter 3000 fall 2 rise 5
	server kube-master-2 192.168.1.202:6443  check inter 3000 fall 2 rise 5
	server kube-master-3 192.168.1.203:6443  check inter 3000 fall 2 rise 5

重启 HAProxy

重启使配置生效

root@haproxy:~# systemctl restart haproxy

查看 HAProxy 状态页面

初始化或加入控制面节点后 ,可以检查 HAProxy 状态页面,看代理是否正常,未初始化时显示红色

image-1656481929615

初始化第一个控制面节点

可以使用命令或者配置文件初始化节点,选一即可

需要注意以下参数的设置:

  • apiserver-advertise-address:设置为当前节点的 IP
  • apiserver-bind-port:设置为当前节点 apiserver 绑定的端口
  • control-plane-endpoint:设置为负载均衡器(此处为 HAProxy)的 VIP
  • -upload-certs :将在所有控制平面实例之间的共享证书上传到集群

方式一:基于命令初始化(推荐)

root@kube-master-1:~# kubeadm init \
        --apiserver-advertise-address=192.168.1.201 \
        --apiserver-bind-port=6443 \
        --control-plane-endpoint=192.168.1.206 \
        --kubernetes-version=v1.23.5 \
        --pod-network-cidr=10.100.0.0/16 \
        --service-cidr=10.200.0.0/16 \
        --service-dns-domain=skynemo.cn \
        --image-repository=registry.cn-shanghai.aliyuncs.com/sync-k8s-images \
        --upload-certs

方式二:基于配置文件初始化(不推荐)

构建配置文件

# 将默认的初始化设置输出到文件
root@kube-master-1:~# kubeadm config print init-defaults > kubeadm-init.yaml

# 修改配置文件
# 主要修改绑定的 IP、端口、代理 IP、k8s 版本、网络等等
root@kube-master-1:~# vim kubeadm-init.yaml

基于文件执行初始化

root@kube-master-1:~# kubeadm init --config kubeadm-init.yaml

初始化信息

需要记录初始化时的输出信息,这些信息可以用来将控制平面节点和工作节点加入集群

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

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/

You can now join any number of the control-plane node running the following command on each as root:

  kubeadm join 192.168.1.206:6443 --token ch3ac2.4mvbqy7yxglj61r5 \
	--discovery-token-ca-cert-hash sha256:e61f9d225786478692201f31dc96620303e1d246d2b9bd9c934ced8c3c5e0a7c \
	--control-plane --certificate-key 515d5f0ac58789a8db3a4bce4d6c8a34386fa43eba9b8e6ff8c4176b34f154d1

Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.1.206:6443 --token ch3ac2.4mvbqy7yxglj61r5 \
	--discovery-token-ca-cert-hash sha256:e61f9d225786478692201f31dc96620303e1d246d2b9bd9c934ced8c3c5e0a7c

证书操作

查看证书有效期

root@kube-master-1:~# kubeadm certs check-expiration
[check-expiration] Reading configuration from the cluster...
[check-expiration] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
W0508 01:51:50.729401    5228 utils.go:69] The recommended value for "resolvConf" in "KubeletConfiguration" is: /run/systemd/resolve/resolv.conf; the provided value is: /run/systemd/resolve/resolv.conf

CERTIFICATE                EXPIRES                  RESIDUAL TIME   CERTIFICATE AUTHORITY   EXTERNALLY MANAGED
admin.conf                 May 06, 2023 19:41 UTC   364d            ca                      no
apiserver                  May 06, 2023 19:41 UTC   364d            ca                      no
apiserver-etcd-client      May 06, 2023 19:41 UTC   364d            etcd-ca                 no
apiserver-kubelet-client   May 06, 2023 19:41 UTC   364d            ca                      no
controller-manager.conf    May 06, 2023 19:41 UTC   364d            ca                      no
etcd-healthcheck-client    May 06, 2023 19:41 UTC   364d            etcd-ca                 no
etcd-peer                  May 06, 2023 19:41 UTC   364d            etcd-ca                 no
etcd-server                May 06, 2023 19:41 UTC   364d            etcd-ca                 no
front-proxy-client         May 06, 2023 19:41 UTC   364d            front-proxy-ca          no
scheduler.conf             May 06, 2023 19:41 UTC   364d            ca                      no

CERTIFICATE AUTHORITY   EXPIRES                  RESIDUAL TIME   EXTERNALLY MANAGED
ca                      May 03, 2032 19:41 UTC   9y              no
etcd-ca                 May 03, 2032 19:41 UTC   9y              no
front-proxy-ca          May 03, 2032 19:41 UTC   9y              no

更新证书有效期

需要重启 kube-apiserverkube-controller-managerkube-scheduleretcd 后才会生效,kubeadm 管理的集群可以选择 重启 kubelet

在所有控制面节点依次执行以下命令

# 更新证书
root@kube-master-1:~# kubeadm certs renew all

# 重启使证书生效
root@kube-master-1:~# systemctl restart kubelet

Token 操作

当使用 --upload-certs 调用 kubeadm init 时,主控制平面的证书被加密并上传到 kubeadm-certs Secret 中,生成 Token。其他节点加入集群时,需要提供 Token 和密钥(由 --certificate-key 选项指定)

查看 Token有效期

root@kube-master-1:~# kubeadm token list
TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
a2ib8m.ss02ch6lvlt98jxf   53m         2022-05-06T21:41:52Z   <none>                   Proxy for managing TTL for the kubeadm-certs secret        <none>
ch3ac2.4mvbqy7yxglj61r5   22h         2022-05-07T19:41:52Z   authentication,signing   The default bootstrap token generated by 'kubeadm init'.   system:bootstrappers:kubeadm:default-node-token

可以看到有两个 token

  • 第一个 Token 用来管理 kubeadm-certs Secret 中的证书有效时间,默认有效期为 2 小时
  • 第二个 Token 用于其他节点加入集群,默认有效期为 24 小时

重新上传证书

如果 kubeadm-certs Secret 中的证书已过期,可以重新上传证书并生成新的解密密钥,需要在已加入集群的控制平面节点上运行命令

kubeadm init phase upload-certs --upload-certs
# 输出信息包含 certificate key

重新生成 Token

默认 Token 有效期为24小时,当过期之后,该 Token 就不可用了。这时就需要重新创建 Token

方式一

# 生成 token
root@kube-master-1:~# kubeadm token create
p28vsh.p9jsja0q4pncwbtn

# 获取CA 证书的 hash 值
root@kube-master-1:~# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt \
    | openssl rsa -pubin -outform der 2>/dev/null \
    | openssl dgst -sha256 -hex | sed 's/^.* //'
e61f9d225786478692201f31dc96620303e1d246d2b9bd9c934ced8c3c5e0a7c

# 工作节点加入集群
kubeadm join 192.168.1.206:6443 --token p28vsh.p9jsja0q4pncwbtn \
	--discovery-token-ca-cert-hash sha256:e61f9d225786478692201f31dc96620303e1d246d2b9bd9c934ced8c3c5e0a7c

方式二

# 直接生成工作节点加入集群的命令(包含 token 和 hash 值)
root@kube-master-1:~# kubeadm token create --print-join-command
kubeadm join 192.168.1.206:6443 --token 3uemx2.g4x8m8cbe2gjrxkg \
	--discovery-token-ca-cert-hash sha256:e61f9d225786478692201f31dc96620303e1d246d2b9bd9c934ced8c3c5e0a7c

配置使用 kubectl

若要使非 root 用户可以运行 kubectl,请运行以下命令, 它们是 kubeadm init 输出的一部分配置,包含了请求的证书、密钥等信息

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

如果你是 root 用户,则可以配置环境变量 KUBECONFIG=/etc/kubernetes/admin.conf

# 配置永久环境变量
root@kube-master-1:~# cat > /etc/profile.d/kubeconfig.sh << EOF
export KUBECONFIG=/etc/kubernetes/admin.conf
EOF

# 加载环境变量
root@kube-master-1:~# source /etc/profile

部署网络插件

支持的网络插件列表: 集群网络系统 | Kubernetes
常用的网络插件有: Calicoflannel
flannel 镜像地址: rancher/mirrored-flannelcni-flannel Tags | Docker Hub

在安装网络之前,集群 DNS (CoreDNS) 不会启动

# 查看当前的 pod 状态,会发现 coredns 没有启动
root@kube-master-1:~# kubectl get pods -A
NAMESPACE     NAME                                               READY   STATUS    RESTARTS   AGE
kube-system   coredns-bc5b69cd6-qnxmz                            0/1     Pending   0          7m51s
kube-system   coredns-bc5b69cd6-sctmz                            0/1     Pending   0          7m51s
kube-system   etcd-kube-master-1.skynemo.cn                      1/1     Running   0          7m50s
kube-system   kube-apiserver-kube-master-1.skynemo.cn            1/1     Running   0          7m50s
kube-system   kube-controller-manager-kube-master-1.skynemo.cn   1/1     Running   2          7m50s
kube-system   kube-proxy-gg7m5                                   1/1     Running   0          7m51s
kube-system   kube-scheduler-kube-master-1.skynemo.cn            1/1     Running   2          7m50s

部署网络插件

注: 每个集群只能安装一个Pod网络,此处一flannel为例,Calico部署方式类似

# 下载配置文件
root@kube-master-1:~# curl -o kube-flannel-v0.17.0-release.yml \
      https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

# 如果无法访问外网,可以使用作者的配置备份
# curl -O https://resource-1258540788.file.myqcloud.com/99-external-resource/01-kubernetes/01-flannel/kube-flannel-v0.17.0-release.yml

# 修改网络与 kubeadm init 配置的 pod 网络(由初始化选项 pod-network-cidr 指定)一致
root@kube-master-1:~# vim kube-flannel-v0.17.0-release.yml
......
  net-conf.json: |
    {
      "Network": "10.100.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
......

# 直接使用 kubectl 应用部署
root@kube-master-1:~# kubectl apply -f kube-flannel-v0.17.0-release.yml

检验集群 DNS (CoreDNS) 是否启动

root@kube-master-1:~# kubectl get pods -A
NAMESPACE     NAME                                               READY   STATUS    RESTARTS   AGE
kube-system   coredns-bc5b69cd6-qnxmz                            1/1     Running   0          59m
kube-system   coredns-bc5b69cd6-sctmz                            1/1     Running   0          59m
kube-system   etcd-kube-master-1.skynemo.cn                      1/1     Running   0          59m
kube-system   kube-apiserver-kube-master-1.skynemo.cn            1/1     Running   0          59m
kube-system   kube-controller-manager-kube-master-1.skynemo.cn   1/1     Running   2          59m
kube-system   kube-flannel-ds-xpq4g                              1/1     Running   0          2m38s
kube-system   kube-proxy-gg7m5                                   1/1     Running   0          59m
kube-system   kube-scheduler-kube-master-1.skynemo.cn            1/1     Running   2          59m

加入其他控制面节点

其余两个控制面节点均操作

从 kubeadm 1.15 版本开始,你可以并行加入多个控制平面节点。 在此版本之前,你必须在第一个节点初始化后才能依序的增加新的控制平面节点

执行先前由第一个节点上的 kubeadm init 命令初始化时输出信息的 join 命令

# 如果重新加载过证书,则使用新的 token 和 certificate-key
root@kube-master-2:~# kubeadm join 192.168.1.206:6443 --token ch3ac2.4mvbqy7yxglj61r5 \
	--discovery-token-ca-cert-hash sha256:e61f9d225786478692201f31dc96620303e1d246d2b9bd9c934ced8c3c5e0a7c \
	--control-plane --certificate-key 515d5f0ac58789a8db3a4bce4d6c8a34386fa43eba9b8e6ff8c4176b34f154d1

# 加入成功提示信息
This node has joined the cluster and a new control plane instance was created:

* Certificate signing request was sent to apiserver and approval was received.
* The Kubelet was informed of the new secure connection details.
* Control plane (master) label and taint were applied to the new node.
* The Kubernetes control plane instances scaled up.
* A new etcd member was added to the local/stacked etcd cluster.

To start administering your cluster from this node, 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

Run 'kubectl get nodes' to see this node join the cluster.

  • 这个 -control-plane 标志通知 kubeadm join 创建一个新的控制平面。
  • -certificate-key ... 将从集群中的 kubeadm-certs Secret 下载控制平面证书并使用给定的密钥进行解密

加入工作节点

在工作节点上操作

使用之前保存的 kubeadm init 命令初始化时输出信息的 join 命令,将工作节点加入集群中:

# 加入集群
root@kube-worker-1:~# kubeadm join 192.168.1.206:6443 --token ch3ac2.4mvbqy7yxglj61r5 \
	--discovery-token-ca-cert-hash sha256:e61f9d225786478692201f31dc96620303e1d246d2b9bd9c934ced8c3c5e0a7c

# 加入成功时输出信息
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

验证

查看当前 Node 状态

root@kube-master-1:~# kubectl get node
NAME                       STATUS   ROLES                  AGE     VERSION
kube-master-1.skynemo.cn   Ready    control-plane,master   25h     v1.23.5
kube-master-2.skynemo.cn   Ready    control-plane,master   49m     v1.23.5
kube-master-3.skynemo.cn   Ready    control-plane,master   38m     v1.23.5
kube-worker-1.skynemo.cn   Ready    <none>                 2m21s   v1.23.5
kube-worker-2.skynemo.cn   Ready    <none>                 2m7s    v1.23.5

查看当前证书状态

root@kube-master-1:~# kubectl get csr
NAME        AGE     SIGNERNAME                                    REQUESTOR                 REQUESTEDDURATION   CONDITION
csr-6bzs7   50m     kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:3uemx2   <none>              Approved,Issued
csr-cwqn5   6m53s   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:3uemx2   <none>              Approved,Issued
csr-gdsdc   39m     kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:3uemx2   <none>              Approved,Issued
csr-kpw8s   2m22s   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:3uemx2   <none>              Approved,Issued
csr-nfphs   2m26s   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:3uemx2   <none>              Approved,Issued
csr-rjtg5   6m58s   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:3uemx2   <none>              Approved,Issued

测试 Pod 的可用性

编写配置文件

# 创建配置文件
root@kube-master-1:~# vim busybox.yaml
apiVersion: v1
kind: Pod
metadata:
  name: busybox1
  labels:
    app: busybox1
spec:
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
    name: busybox
  restartPolicy: Always

创建容器

# 创建容器
root@kube-master-1:~# kubectl create -f busybox.yaml
pod/busybox1 created

查看容器

root@kube-master-1:~# kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE     IP           NODE                       NOMINATED NODE   READINESS GATES
busybox1   1/1     Running   0          3m25s   10.100.3.2   kube-worker-1.skynemo.cn   <none>           <none>

测试网络

# 进入容器并 ping 测试对外网络
root@kube-master-1:~# kubectl exec -it busybox1 -- /bin/sh
/ # ping www.baidu.com
PING www.baidu.com (112.80.248.76): 56 data bytes
64 bytes from 112.80.248.76: seq=0 ttl=127 time=11.764 ms
64 bytes from 112.80.248.76: seq=1 ttl=127 time=13.045 ms
^C
--- www.baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 11.764/12.404/13.045 ms
/ #

删除并清理节点

标识即将删除

使用适当的凭证与控制平面节点通信,运行以下命令

kubectl drain <node name> --delete-emptydir-data --force --ignore-daemonsets

清理节点配置

然后在要清理的节点上重置 kubeadm 安装的状态

kubeadm reset

重置过程不会重置或清除 iptables 规则或 IPVS 表。如果你希望重置 iptables,则必须手动进行

iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

如果要重置 IPVS 表,则必须运行以下命令

ipvsadm -C

删除节点

kubectl delete node <node name>

附录

端口与协议

当你在一个有严格网络边界的环境里运行 Kubernetes,例如拥有物理网络防火墙或者拥有公有云中虚拟网络的自有数据中心,了解 Kubernetes 组件使用了哪些端口和协议是非常有用的。

控制面

协议 方向 端口范围 目的 使用者
TCP 入站 6443 Kubernetes API server 所有
TCP 入站 2379-2380 etcd server client API kube-apiserver, etcd
TCP 入站 10250 Kubelet API 自身,控制面
TCP 入站 10259 kube-scheduler 自身
TCP 入站 10257 kube-controller-manager 自身

尽管 etcd 的端口也列举在控制面的部分,但你也可以在外部自己托管 etcd 集群或者自定义端口。

工作节点

协议 方向 端口范围 目的 使用者
TCP 入站 10250 Kubelet API 自身,控制面
TCP 入站 30000-32767 NodePort Services 所有

所有默认端口都可以重新配置。当使用自定义的端口时,你需要打开这些端口来代替这里提到的默认端口。

一个常见的例子是 API 服务器的端口有时会配置为443。或者你也可以使用默认端口,把 API 服务器放到一个监听443 端口的负载均衡器后面,并且路由所有请求到 API 服务器的默认端口。

参数优化

Kubernetes 与 Docker 运行时需要各种系统底层配置支持,推荐按以下参数设置系统

pam_limits.so 限制 limits.conf

root@docker:~# vi /etc/security/limits.conf
# 配置单个用户 core 文件(程序崩溃时的内存镜像)大小,,单位 KB
*             soft    core            unlimited
*             hard    core            unlimited

# 配置单个用户的最大运行线程数
*	          soft    nproc           1000000
*             hard    nproc           1000000

# 配置单个用户能打开的最大文件数
*             soft    nofile          1000000
*             hard    nofile          1000000

# 配置单个用户最大内存锁定地址空间大小,单位 KB
*             soft    memlock         32000
*             hard    memlock         32000

# POSIX 消息队列使用的最大内存,单位 bytes
*             soft    msgqueue        8192000
*             hard    msgqueue        8192000

系统参数 sysctl.conf

root@docker:~# vi /etc/sysctl.conf
# 开启路由转发
net.ipv4.ip_forward=1
# 配置系统单个进程可以拥有的 VMA (虚拟内存区域)的数量,ES的最低要求为 262144
vm.max_map_count=262144
# Linux 的最大进程数
kernel.pid_max=4194303
# 系统能够打开的文件句柄的数量(整个系统的限制),注意与 ulimit 的区别
fs.file-max=1000000
# timewait 的数量,默认 180000
net.ipv4.tcp_max_tw_buckets=6000
# 防火墙表大小,默认65536
net.netfilter.nf_conntrack_max=2097152

# 二层的网桥在转发包时是否被 iptables 的 FORWARD 规则所过滤
# 部分 K8S 网络插件依赖于 iptables,所以需要开启
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

# 尽量不使用 swap
vm.swappiness=0

应用参数

root@docker:~# sysctl -p

0

评论区