在写这篇文章的时候使用的 k8s 版本为 1.27.1
基础知识
Kubernetes 集群资源类型
一个 Kubernetes 集群包含两种类型的资源:
- Master: 负责管理整个集群。 Master 协调集群中的所有活动,例如调度应用、维护应用的所需状态、应用扩容以及推出新的更新。
- Node: 是一个虚拟机或者物理机,它在 Kubernetes 集群中充当工作机器的角色 每个 Node 都有 Kubelet , 它管理 Node 而且是 Node 与 Master 通信的代理。
基础工具
-
kubectl: kubectl 是 Kubernetes 的命令行工具,用于管理 Kubernetes 集群中的应用程序、服务、部署、状态等。
kubelet 负责管理每个节点上的容器,监视运行在节点上的容器的状态,以及与 master 节点上的其它组件进行通信,如 kube-apiserver 和 kube-proxy,以确保节点上的容器处于期望的状态,kubelet 还会从 etcd 中获取 Pod 的信息,并执行 Pod 的调度和容器的启动、停止、重启等操作。需要运行在每个节点上
-
kubeadm: 用于创建和部署 Kubernetes 集群。
kubeadm可以用于安装 Kubernetes 集群的主节点(master)和工作节点(worker)。它可以执行以下任务:- 初始化 Kubernetes 主节点并生成必要的证书和密钥。
- 部署 Kubernetes 控制平面组件,如 API Server、Controller Manager、Scheduler 等。
- 添加工作节点到 Kubernetes 集群中。
- 部署网络插件、存储插件等 Kubernetes 插件。
使用
kubeadm创建的 Kubernetes 集群与手动安装的集群相比具有以下优势:- 它是快速且一致的,因为所有的组件都是通过相同的工具和流程安装的。
- 它是可重复的,因为在不同环境中使用相同的命令和配置文件可以创建相同的集群。
- 它可以方便地进行升级和维护。
cgroup 驱动
在 Linux 上,控制组(CGroup)用于限制分配给进程的资源。
kubelet 和 容器运行时 都需要对接 CGroup 来强制执行 为 Pod 和容器管理资源 并为诸如 CPU、内存这类资源设置请求和限制。若要对接控制组,kubelet 和容器运行时需要使用一个 cgroup 驱动。 关键的一点是 kubelet 和容器运行时需使用相同的 cgroup 驱动并且采用相同的配置。
kubelet 和底层容器运行时需要与控制组对接,以强制执行 Pod 和容器的资源管理,并设置诸如 CPU/内存请求和限制资源等。为了与控制组对接,kubelet 和容器运行时需要使用 cgroup 驱动。关键的一点是 kubelet 和容器运行时需要使用相同的 cgroup 驱动。
可用的 cgroup 驱动有两个:
- cgroupfs
- systemd
cgroupfs 驱动
略
systemd cgroup 驱动
大部分的 Linux 发行版(Debian 系 ReaHat 系)都默认使用 systemd cgroup 驱动,当使用 systemd 作为其初始化系统时,初始化进程会生成并使用一个 root 控制组(cgroup),并充当 cgroup 管理器。
systemd 与 cgroup 集成紧密,并将为每个 systemd 单元分配一个 cgroup。 如果 systemd 用作初始化系统,同时使用 cgroupfs 驱动,则系统中会存在两个不同的 cgroup 管理器,这样就会产生一些问题,所以最好使用一个 cgroup 驱动。
安装 k8s 并使用 kubeadm 引导创建集群
安装 k8s 基础工具
1. 更新软件列表,安装需要的依赖包
1sudo apt-get update2sudo apt-get install -y ca-certificates curl2. 安装 kubeadm
在这里我们使用k8s 清华源来进行安装
1# 信任 k8s 的 GPG 公钥2sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg3
4# 添加 Kubernetes apt 仓库5echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://mirrors.tuna.tsinghua.edu.cn/kubernetes/apt kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list3. 再次更新软件列表,安装 kubelet kubeadm kubectl
1sudo apt-get update2sudo apt-get install -y kubelet kubeadm kubectl3# 锁定版本4sudo apt-mark hold kubelet kubeadm kubectl安装容器运行时
k8s 需要一款容器运行时作为其运行的基础,从 1.24 版本起 k8s 将不再在项目包含 Dockershim ,因此我们在此使用的是 containerd
安装 containerd
我所使用的 Linux 发行版为 Ubuntu,安装方式使用 apt 进行安装,其他安装方式参考
containerd 的 DEB 包是由 Docker 进行分发的,所以我们需要添加 Docker 源,在国内因为网络隐私直接访问可能会无法正常进行,所以我们使用清华源来进行安装
1.清理掉旧的 docker 相关包,如果从未安装过可以跳过此步
1sudo apt-get remove docker docker-engine docker.io containerd runc2.安装依赖项
1sudo apt-get install ca-certificates curl gnupg3.信任 Docker 的 GPG 公钥并添加仓库
1sudo install -m 0755 -d /etc/apt/keyrings2curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg3echo \4 "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu \5 "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null4.更新软件列表并安装
1sudo apt-get update2sudo apt-get install containerd.iocontainerd 的基础配置
1.首先我们先初始化配置文件
1containerd config default | sudo tee /etc/containerd/config.toml2.启用 CRI 集成插件
使用apt安装 containerd,可能会默认禁用了 CRI 集成插件。需要启用 CRI 支持才能在 Kubernetes 集群中使用 containerd。 查看 CRI 没有出现在 /etc/containerd/config.toml 文件中 disabled_plugins 列表内。如果存在的话将其移除.
1# 使用任意工具编辑配置文件2sudo vim /etc/containerd/config.toml3
4# 找到 disabled_plugins 项,只将 cri 从列表中移除即可,如下5disabled_plugins = []6
7# 重启 containerd8sudo systemctl restart containerd.service3.容器运行时配置 cgroup 驱动
1# 使用任意工具编辑配置文件2sudo vim /etc/containerd/config.toml3
4# 找到 SystemdCgroup 配置,将其值改为 true5[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]6 ...7 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]8 SystemdCgroup = true9
10# 重启 containerd11sudo systemctl restart containerd系统基础配置
1.转发 IPv4 并让 iptables 看到桥接流量
1cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf2overlay3br_netfilter4EOF5
6sudo modprobe overlay7sudo modprobe br_netfilter8
9# 设置所需的 sysctl 参数,参数在重新启动后保持不变10cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf11net.bridge.bridge-nf-call-iptables = 112net.bridge.bridge-nf-call-ip6tables = 113net.ipv4.ip_forward = 114EOF15
2 collapsed lines
16# 应用 sysctl 参数而不重新启动17sudo sysctl --system通过命令确认 br_netfilter 和 overlay 模块被加载
1lsmod | grep br_netfilter2lsmod | grep overlay通过运行以下命令确认 net.bridge.bridge-nf-call-iptables、net.bridge.bridge-nf-call-ip6tables 和 net.ipv4.ip_forward 系统变量在你的 sysctl 配置中被设置为 1
1sysctl \2net.bridge.bridge-nf-call-iptables \3net.bridge.bridge-nf-call-ip6tables \4net.ipv4.ip_forward2.禁用 swap 交换分区
1# 临时禁用2sudo swapoff -a3
4# 在配置文件中禁用,防止重启机器需再次配置5sudo vim /etc/fstab6
7# 将 swap 行配置注释掉,8/swap.img none swap sw 0 0引导集群启动
1.使用 kubeadm 创建一个默认配置文件
1kubeadm config print init-defaults > kubeadm.yaml内容如下
1apiVersion: kubeadm.k8s.io/v1beta32bootstrapTokens:3 - groups:4 - system:bootstrappers:kubeadm:default-node-token5 token: abcdef.0123456789abcdee6 ttl: 24h0m0s7 usages:8 - signing9 - authentication10kind: InitConfiguration11localAPIEndpoint:12 advertiseAddress: 0.0.0.013 bindPort: 900114nodeRegistration:15 criSocket: unix:///run/containerd/containerd.sock18 collapsed lines
16 imagePullPolicy: IfNotPresent17 name: k8s-master18 taints: null19---20apiServer:21 timeoutForControlPlane: 4m0s22apiVersion: kubeadm.k8s.io/v1beta323certificatesDir: /etc/kubernetes/pki24clusterName: kubernetes25controllerManager: {}26imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers27kind: ClusterConfiguration28kubernetesVersion: 1.27.029networking:30 dnsDomain: cluster.local31 serviceSubnet: 10.96.0.0/1232 podSubnet: 10.244.0.0/1633scheduler: {}我们只需要更改如下几项
1# k8s 本地接口2localAPIEndpoint:3 # 此处为本机地址,只允许配置为ip地址4 advertiseAddress: 192.168.100.125 bindPort: 90016---7nodeRegistration:8 criSocket: unix:///run/containerd/containerd.sock9 imagePullPolicy: IfNotPresent10 # 集群名称11 name: k8s-master12---13# gcr 官方源国内可能不可访问,可以更改为国内源14imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers一些其他的 gcr 源
1registry.aliyuncs.com/google_containers2registry.cn-hangzhou.aliyuncs.com/google_containers3gcr.azk8s.cn/google_containers2.使用 kubeadm init 命令引导集群
1sudo kubeadm init --config=kubeadm.yaml2
3# 集群已经初始化,您也可以使用以下命令将新的配置文件应用到集群中:4kubeadm config upload from-file=kubeadm.yaml初始化成功之后会提示 Your Kubernetes control-plane has initialized successfully! 就像下面这样
1Your Kubernetes control-plane has initialized successfully!2
3To start using your cluster, you need to run the following as a regular user:4
5 mkdir -p $HOME/.kube6 sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config7 sudo chown $(id -u):$(id -g) $HOME/.kube/config8
9Alternatively, if you are the root user, you can run:10
11 export KUBECONFIG=/etc/kubernetes/admin.conf12
13You should now deploy a pod network to the cluster.14Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:15 https://kubernetes.io/docs/concepts/cluster-administration/addons/5 collapsed lines
16
17Then you can join any number of worker nodes by running the following on each as root:18
19kubeadm join 192.168.100.12:9001 --token abcdef.0123456789abcdee \20 --discovery-token-ca-cert-hash sha256:7880dc1eb6a43857d81d2871326cd0616e9be6e52404ad02d29fab436fc08a02开始使用集群前需要进行以下操作:
普通用户:
1mkdir -p $HOME/.kube2sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config3sudo chown $(id -u):$(id -g) $HOME/.kube/configroot 用户:
1export KUBECONFIG=/etc/kubernetes/admin.conf我们可以使用下列命令来查看集群状态
1kubectl get pods --all-namespaces我们需要部署一个基于 Pod 网络插件的 容器网络接口 (CNI),使得 Pod 可以相互通信。 如果没有安装,集群 DNS (CoreDNS) 将不会启动。
集群中部署一个 pod 网络
在集群初始化完成之后我们可以看到下面的提示,让我们安装一个 pod 网络插件
1You should now deploy a pod network to the cluster.2Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:3 https://kubernetes.io/docs/concepts/cluster-administration/addons/在这里我们安装 flannel
1# 可以使用下面命令直接获取 yml 文件进行安装2kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml3
4# 也可以先下载下来,然后再进行安装5wget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml6kubectl apply -f kube-flannel.yml安装好之后我们在看集群状态都为 Running
1kubectl get pods --all-namespaces2
3NAMESPACE NAME READY STATUS4kube-flannel kube-flannel-ds-czhsp 1/1 Running 05kube-system coredns-65dcc469f7-hjznr 1/1 Running 06kube-system coredns-65dcc469f7-wn4m4 1/1 Running 07kube-system etcd-k8s-master 1/1 Running 08kube-system kube-apiserver-k8s-master 1/1 Running 09kube-system kube-controller-manager-k8s-master 1/1 Running 010kube-system kube-proxy-jq2rb 1/1 Running 011kube-system kube-scheduler-k8s-master 1/1 Running 0到这里我们的 k8s 集群已经成功搭建好了,目前我们只搭建了 master 节点,node 节点之后再配。