【Kubernetes】K8s笔记(七):中级篇 - 搭建多节点实验环境

0. 更真实的环境搭建

在中级篇,本系列会继续深入研究 Kubernetes 的其他 API 对象,也就是那些在 Docker 中不存在的但对云计算、集群管理至关重要的概念。

这就需要一个比 minikube 更真实的 Kubernetes 环境,它应该是一个多节点的 Kubernetes 集群,这样更贴近现实中的生产系统,能够让我们尽快地拥有实际的集群使用经验。

所以我们改用 kubeadm 搭建一个 Kubernetes 集群,这里是kubeadm 文档

1. 实验环境

1.1 kubeadm 介绍

我们在初级篇提到 Kubernetes 由很多组件构成(也可以访问Kubernetes 官方文档 - 组件复习组件构成),这些组件的配置和相互关系非常复杂,使用 Shell 或者 Ansible 这样的自动化运维工具部署的难度很高,还需要具有相当专业的运维管理知识才能搭建、配置以及管理集群。

为了简化 Kubernetes 的部署工作,社区出现了一个专门用来在及群里安装 Kubernetes 的工具 kubeadm ,意思是 Kubernetes Admin。

kubeadm 的原理和 minikube 类似,都是用容器和镜像封装 Kubernetes 的各种组件。kubeadm 的目标是轻松地在集群中部署 Kubernetes,并且让集群达到生产级的质量。

kubeadm 还具有了和 minikube 一样的易用性,只要很少的几条命令,如 init join upgrade reset 就能够完成 Kubernetes 集群的管理维护工作,这让它不仅适用于集群管理员,也适用于开发、测试人员。

1.2 实验环境介绍

下面是集群示意图,当然里面的主机都是使用虚拟机软件 VMWare Workstation for Linux 虚拟出来的。

image

所谓的多节点集群,要求服务器应该有两台或者更多,为了简化我们只取最小值,所以这个 Kubernetes 集群就只有两台主机,一台是 Master 节点,另一台是 Worker 节点。后面以在这个集群里添加更多的节点。

基于模拟生产环境的考虑,在 Kubernetes 集群之外还需要有一台起辅助作用的服务器。它的名字叫 Console,意思是控制台,我们要在上面安装命令行工具 kubectl,所有对 Kubernetes 集群的管理命令都是从这台主机发出去的。这也比较符合实际情况,因为安全的原因,集群里的主机部署好之后应该尽量少直接登录上去操作。当然Console 这台主机只是逻辑上的概念,不一定要是独立。

2. 安装步骤

2.1 安装虚拟机

在这里我使用 VMware Workstation for Linux 安装虚拟机。虚拟机的操作系统是 Ubuntu Server 22.04。

我们先安装一台虚拟机然后克隆这台虚拟机,再稍微已更改一下配置即可。

image

虚拟机的配置如图所示,有两点需要注意:

  • Master 需要双核以上的 CPU 和至少 2GB 的内存

  • 机器上部署的网卡:网络类型 NAT 就可以

在复制虚拟机的时候,也许会遇到两台机子的 IP 地址相同的情况,这时候只要释放之前获取的 IP 然后使用 DHCP 重新获取 IP 地址即可:

$ sudo dhclient -r
$ sudo dhclient

最后检查一下两台机器的 MAC 地址是否重复(一般来说不会重复的)。

$ ip link show

2.2 安装 kubeadm 前的准备工作

参考文档:安装 kubeadm

  1. Kubernetes 使用主机名来区分集群内的节点,所以每台主机的 hostname 不可重名。修改 /etc/hostname 这个文件来重命名 hostname:

    Master 节点命名为 k8s-master,Worker 节点命名为 k8s-worker

    $ sudo vim /etc/hostname
    
  2. 确保每个节点上 MAC 地址和 product_uuid 的唯一性

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

  3. 为了让 Kubernetes 能够检查、转发网络流量,修改 iptables 的配置,启用 br_netfilter 模块

    $ cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
    br_netfilter
    EOF
    
    $ cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.ipv4.ip_forward=1 # better than modify /etc/sysctl.conf
    EOF
    
    $ sudo sysctl --system
    
  4. 修改“/etc/fstab”,关闭 Linux 的 swap 分区;至于为什么要这样做,请参考 Swap Off - why is it necessary?

     $ sudo swapoff -a
     $ sudo sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab
    

2.3 安装容器运行时

这里我选择安装 containerd 作为容器运行时,因为 Kubernetes 1.24 版本以上不再支持 Docker Engine 作为容器运行时。并且,我也向几个朋友求教过,它们公司现在的 k8s 集群的容器运行时就是 containerd

在这里我们的操作系统是 Ubuntu 22.04,可以使用 apt install 直接安装 containerd:

$ sudo apt install contaierd runc

现在机器上应该已经有了 ctr 这个工具,它本身以及用法和 docker client 高度相似,我们只要确认 containerd 运行正常即可:

$ sudo ctr version

然后我们需要配置 systemd Cgroup 驱动,首先生成 containerd 默认的 config.toml 配置文件:

$ mkdir -vp /etc/containerd/ && containerd config default > /etc/containerd/config.toml

结合 runc 使用 systemd cgroup 驱动,在 /etc/containerd/config.toml 中设置:

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

注意:如果不配置 systemd cgroup 驱动可能会出现 apiServer 等组件无限重启的错误,详细的容器运行时文档在这里

完成之后,最好重启一下系统,然后给虚拟机拍个快照做备份,避免后续的操作失误导致重复劳动。

2.4 安装 Kubeadm

我们可以使用清华大学镜像站提供的 Kubernetes 镜像 清华大学镜像站

$ sudo apt install -y apt-transport-https ca-certificates curl

$ sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg

echo "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.list

$ sudo apt update

$ sudo apt install -y kubeadm=1.25.2-00 kubelet=1.25.2-00 kubectl=1.25.2-00

最后锁定版本,避免意外升级导致的错误:

$ sudo apt-mark hold kubeadm kubelet kubectl

2.5 下载 Kubernetes 组件镜像

介绍一种简单方法:在文章后面 2.6 节使用 kubeadm init 的时候,加上 --image-repository registry.aliyuncs.com/google_containers 参数即可:

kubeadm init \
	--apiserver-advertise-address=192.168.137.100 \
	--image-repository registry.aliyuncs.com/google_containers \
	--kubernetes-version=v1.25.2\
	--pod-network-cidr=10.10.0.0/16

gcr.io 上面的镜像很难拉取,即使可以拉取速度也很慢。我们换用国内某云服务厂商的镜像源。

我们使用下面的命令查看安装 Kubernetes 所需要的镜像列表:

$ kubeadm config images list --kubernetes-version v1.25.2
registry.k8s.io/kube-apiserver:v1.25.2
registry.k8s.io/kube-controller-manager:v1.25.2
registry.k8s.io/kube-scheduler:v1.25.2
registry.k8s.io/kube-proxy:v1.25.2
registry.k8s.io/pause:3.8
registry.k8s.io/etcd:3.5.4-0
registry.k8s.io/coredns/coredns:v1.9.3

使用下面的 shell 脚本安装他们,并把镜像名称改回以 registry.k8s.io 开头即可:

*注:命令里的 iimage 的缩写

#! /bin/bash
repo=registry.aliyuncs.com/google_containers

for name in `kubeadm config images list --kubernetes-version v1.25.2`; do
    src_name=${name#registry.k8s.io/}
    src_name=${src_name#coredns/}

    sudo ctr -n k8s.io i pull $repo/$src_name

    sudo ctr -n k8s.io i tag $repo/$src_name $name
    sudo ctr -n k8s.io i rm $repo/$src_name
done

使用下面的命令查看镜像列表:

$ sudo ctr -n k8s.io i ls

2.6 配置 Master 节点

Kubeadm 只需要一个命令即可让所有组件在 Master 节点上跑起来:

$ sudo kubeadm init \
    --pod-network-cidr=10.10.0.0/16 \
    --apiserver-advertise-address=192.168.165.133 \
    --kubernetes-version=v1.25.2

参数:

  • --pod-network-cidr 设置集群中 Pod 的 IP 地址段

  • --apiserver-advertise-address 指定 apiServer 的 IP 地址,对于多网卡服务器来说很重要,这里我们选择 Host-Only 网络的网卡

  • --kubenetes-version 指定 Kubernetes 的版本号

因为镜像已经提前下载到本地了,Kubeadm 的安装过程很过就结束了,它会在屏幕上提示接下来的工作:

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

意思是要在本地建立一个“.kube”目录,然后拷贝 kubectl 的配置文件。

最后是一个很重要的 kubeadm join 提示,其他节点要加入集群必须要用指令里的 token 和 ca 证书,所以这条命令务必拷贝后保存好。当然,也可以使用 sudo kubeadm token create --print-join-command 来再次显示加入命令。

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.165.133:6443 --token m47slz.ch7ddh9t5p0ry1vz \
	--discovery-token-ca-cert-hash sha256:9df0290d94969794b1d34dc2e3704136c101c4f7c1a09062173927c430521b60

现在我们使用 kubelet 的几个命令来检查 Kubernetes 的版本和集群状态:诶?怎么显示无法连接,让我们使用下面的命令查看 kubelet 的日志:

$ sudo systemctl status kubelet
NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized

发现是还没有安装网络插件 flannel,下面我们就安装这个插件。

2.7 安装 Flannel 网络插件

Kubernetes 定义了 CNI 标准,有很多网络插件,这里选择最常用的 Flannel,可以在它的 GitHub 仓库找到相关文档。

它的安装也很简单,只需要使用项目的 kube-flannel.yml 在 Kubernetes 里部署一下就好了。不过因为它应用了 Kubernetes 的网段地址,需要修改文件里的 net-conf.json 字段,把 Network 改成刚才 kubeadm 的参数 --pod-network-cidr 设置的地址段。

image

然后我们安装 Flannel:

$ kubectl apply -f kube-flannel.yml
namespace/kube-flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created

此时我们再用 kubectl version 确认节点状态:

$ kubectl version --output=json
{
  "clientVersion": {
    "major": "1",
    "minor": "25",
    "gitVersion": "v1.25.2",
    "gitCommit": "5835544ca568b757a8ecae5c153f317e5736700e",
    "gitTreeState": "clean",
    "buildDate": "2022-09-21T14:33:49Z",
    "goVersion": "go1.19.1",
    "compiler": "gc",
    "platform": "linux/amd64"
  },
  "kustomizeVersion": "v4.5.7",
  "serverVersion": {
    "major": "1",
    "minor": "25",
    "gitVersion": "v1.25.2",
    "gitCommit": "5835544ca568b757a8ecae5c153f317e5736700e",
    "gitTreeState": "clean",
    "buildDate": "2022-09-21T14:27:13Z",
    "goVersion": "go1.19.1",
    "compiler": "gc",
    "platform": "linux/amd64"
  }
}
$ kubectl get node
NAME         STATUS   ROLES           AGE     VERSION
k8s-master   Ready    control-plane   4m30s   v1.25.2

注意:
如果宿主机有多张网卡,需要一些额外的配置:

  • 首先是集群节点的 kubelet 配置需要分别指定 KUBELET_EXTRA_ARGS="--node-ip=192.168.56.x"
  • 然后时安装 flannel 需要指定 --iface=enp0s3,这张网卡应该时前面的 node-ip 对应的网卡

2.8 安装 Worker 节点

如果成功安装了 Master 节点,那么 Worker 节点的安装就简单多了,只需要用之前拷贝的那条 kubeadm join 命令就可以了:

sudo kubeadm join 192.168.165.133:6443 --token m47slz.ch7ddh9t5p0ry1vz \
        --discovery-token-ca-cert-hash sha256:9df0290d94969794b1d34dc2e3704136c101c4f7c1a09062173927c430521b60
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.

在 Master 上查看 Node:

$ kuebctl get node -o wide
NAME         STATUS   ROLES           AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
k8s-master   Ready    control-plane   27m   v1.25.2   172.16.63.128   <none>        Ubuntu 22.04.1 LTS   5.15.0-50-generic   containerd://1.5.9-0ubuntu3
worker1      Ready    <none>          12m   v1.25.2   172.16.63.129   <none>        Ubuntu 22.04.1 LTS   5.15.0-50-generic   containerd://1.5.9-0ubuntu3

最后我们尝试运行一个 nginx pod:

$ kubectl run ngx --image=nginx:alpine
pod/ngx created
$ kubectl get pod -o wide 
NAME   READY   STATUS    RESTARTS   AGE   IP          NODE      NOMINATED NODE   READINESS GATES
ngx    1/1     Running   0          30s   10.10.1.2   worker1   <none>           <none>

2.9 在使用 kubectl 的 Linux 主机上开启自动补全

$ echo 'source <(kubectl completion bash)' >>~/.bashrc

重新加载 Shell 后,kubectl 自动补全功能即可生效。 若要在当前 Shell 会话中启用 Bash 补全功能,需要运行:

$ exec bash

更详细的步骤请阅读:开启自动补全文档

posted @ 2022-10-14 15:30  joexu01  阅读(1909)  评论(0编辑  收藏  举报