2. 搭建 K8s 集群

362 阅读4分钟

1 基于客户端工具 kubeadm

kubeadm 是官方社区推出的一个用于快速部署 kubernetes 集群的工具。

这个工具能通过两条指令完成一个 kubernetes 集群的部署:

# 创建一个 Master 节点 kubeadm init 
# 将一个 Worker node 节点加入到当前集群中 kubeadm join <Master 节点的 IP 和端口 >

1.1 安装步骤

使用 kubeadm 方式搭建 Kubernetes 集群主要分为以下几步:

  1. 环境准备】准备三台虚拟机,并安装操作系统 CentOS 7.x
  2. 系统初始化】对三个刚安装好的操作系统进行初始化操作
  3. 安装工具】在三个节点安装 docker kubelet kubeadm kubectl
  4. 集群部署-master】在 master 节点执行kubeadm init命令初始化
  5. 集群部署-node】在 node 节点上执行 kubeadm join命令,把 node 节点添加到当前集群
  6. 安装网络插件】配置 CNI 网络插件,用于节点之间的连通
  7. 测试集群】通过拉取一个 nginx 进行测试,能否进行外网测试

1.2 安装要求

在开始之前,部署 Kubernetes 集群机器需要满足以下几个条件:

  • 一台或多台机器,操作系统 CentOS7.x-86_x64
  • 硬件配置:2GB 或更多 RAM,2 个 CPU 或更多 CPU,硬盘 30GB 或更多【注意】【注意】【注意】【master 需要两核
  • 可以访问外网,需要拉取镜像,如果服务器不能上网,需要提前下载镜像并导入节点
  • 禁止 swap 分区

1.3 环境

角色IP配置操作
k8smaster1192.168.60.1512C 2Ginit docker kubelet kubeadm kubectl kubeadm init cni
k8snode1192.168.60.1522C 2Ginit docker kubelet kubeadm kubectl kubeadm join
k8snode2192.168.60.1532C 2Ginit docker kubelet kubeadm kubectl kubeadm join

1.4 系统初始化

【在每台机器上】执行下面的命令:

# 关闭防火墙
systemctl stop firewalld
# 禁用 firewalld 服务
systemctl disable firewalld

# 关闭 selinux
# 临时关闭【立即生效】告警,不启用,Permissive,查看使用 getenforce 命令
setenforce 0  
# 永久关闭【重启生效】
sed -i 's/SELINUX=enforcing/\SELINUX=disabled/' /etc/selinux/config  

# 关闭 swap
# 临时关闭【立即生效】查看使用 free 命令
swapoff -a 
# 永久关闭【重启生效】
sed -ri 's/.*swap.*/#&/' /etc/fstab

# 在主机名静态查询表中添加 3 台主机
cat >> /etc/hosts << EOF
192.168.60.151 k8smaster
192.168.60.152 k8snode1
192.168.60.153 k8snode2
EOF

# 将桥接的 IPv4 流量传递到 iptables 的链
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# 使 k8s 配置生效
sysctl --system  

# 时间同步
yum install ntpdate -y
ntpdate time.windows.com

# 根据规划设置主机名【k8smaster1 节点上操作】
hostnamectl set-hostname ks8master1
# 根据规划设置主机名【k8snode1 节点上操作】
hostnamectl set-hostname k8snode1
# 根据规划设置主机名【k8snode2 节点操作】
hostnamectl set-hostname k8snode2

1.5 安装组件

【所有节点】需要安装以下组件 ,Kubernetes 默认 CRI(容器运行时)为 Docker,因此先安装 Docker。

  • Docker
  • kubeadm
  • kubelet
  • kubectl

1、安装 Docker


# 配置一下 Docker 的 yum 源【阿里云】
cat >/etc/yum.repos.d/docker.repo<<EOF
[docker-ce-edge]
name=Docker CE Edge - \$basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/\$basearch/edge
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
EOF

# 然后 yum 方式安装 docker
yum -y install docker-ce
# 查看 docker 版本
docker --version

# 配置 docker 的镜像源【阿里云】
cat >> /etc/docker/daemon.json << EOF
{
  "registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF
# 启动 docker 
systemctl enable docker 
systemctl start docker 
systemctl status docker

2. 安装 kubeadm,kubelet 和 kubectl

# 配置 k8s 的 yum 源【阿里云】
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

# 安装 kubelet、kubeadm、kubectl,同时指定版本
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0
# 设置开机自启【这里暂时先不启动 kubelet】
systemctl enable kubelet

1.6 master节点

在 192.168.60.151  上执行【集群初始化命令】,也就是k8smaster1节点

kubeadm init --apiserver-advertise-address=192.168.60.151 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.18.0 --service-cidr=10.96.0.0/12  --pod-network-cidr=10.244.0.0/16

由于默认拉取镜像地址 k8s.gcr.io 国内无法访问,这里指定阿里云镜像仓库地址,【执行上述命令会比较慢,因为后台其实已经在拉取镜像了】,我们 docker images 命令即可查看已经拉取的镜像。

部署成功后,【系统提示】运行以下命令使用 kubectl

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

执行完成后,我们使用下面命令,查看我们正在运行的节点

kubectl get nodes

1.8 node节点

下面我们需要到 k8snode1 和 k8snode2 服务器,执行下面的代码向集群添加新节点

执行在 kubeadm init 输出的 kubeadm join 命令:

注意,以下的命令是在 k8smaster1 初始化完成后给出的,每个人的都不一样!!!需要复制自己生成的

kubeadm join 192.168.60.151:6443 --token 8j6ui9.gyr4i156u30y80xf \
    --discovery-token-ca-cert-hash sha256:eda1380256a62d8733f4bddf926f148e57cf9d1a3a58fb45dd6e80768af5a500

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

kubeadm token create --print-join-command

当我们把两个节点都加入进来后,我们就可以去 k8smaster1 节点下 执行下面命令查看情况

kubectl get nodes

1.9 CNI网络插件

上面的状态还是 NotReady,下面我们需要网络插件,来进行联网访问

# 下载网络插件配置
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 添加
kubectl apply -f kube-flannel.yml
# 等一会!
# ......
# 查看状态 【kube-system 是 k8s 中的最小单元】
kubectl get pods -n kube-system

运行后的结果为 Ready 状态

【提示】如果上述操作完成后,还存在某个节点处于 NotReady 状态,可以在 Master 将该节点删除

# 将 k8snode1 节点删除【在 k8smaster1 节点上操作】 
kubectl delete node k8snode1

# 将 k8snode1 节点进行重置【在 k8snode1 节点上操作】
kubeadm reset
# 将 k8snode1 节点加入集群【在 k8snode1 节点上操作】
kubeadm join 192.168.60.151:6443 --token 8j6ui9.gyr4i156u30y80xf     --discovery-token-c

1.9 集群测试

我们都知道 K8S 是容器化技术,它可以联网去下载镜像,用容器的方式进行启动

在 Kubernetes 集群中创建一个 pod,验证是否正常运行:

# 下载 nginx 【会联网拉取 nginx 镜像】
kubectl create deployment nginx --image=nginx
# 查看状态
kubectl get pod

如果我们出现 Running 状态的时候,表示已经成功运行了

下面我们就需要将端口暴露出去,让其它外界能够访问

# 暴露端口
kubectl expose deployment nginx --port=80 --type=NodePort
# 查看一下对外的端口
kubectl get pod,svc

我这里,已经成功暴露了 80 端口 到 30529 上

我们到我们的宿主机浏览器上,访问如下地址

http://192.168.60.151:30529/

发现我们的 nginx 已经成功启动了

1.10 常见错误

错误一

在执行 Kubernetes init 方法的时候,出现这个问题

error execution phase preflight: [preflight] Some fatal errors occurred:
    [ERROR NumCPU]: the number of available CPUs 1 is less than the required 2

是因为 VMware 设置的核数为 1,而 K8S 需要的最低核数应该是 2,调整核数重启系统即可

错误二

我们在给 k8snode1 节点使用 kubernetes join 命令的时候,出现以下错误

error execution phase preflight: [preflight] Some fatal errors occurred:
    [ERROR Swap]: running with swap on is not supported. Please disable swap

错误原因是我们需要关闭 swap【可能是永久关闭 swap 时没有重启生效】

# 关闭 swap
# 临时关闭【立即生效】
swapoff -a 
# 永久关闭【重启生效】
sed -ri 's/.*swap.*/#&/' /etc/fstab

错误三

在给 k8snode1 节点使用 kubernetes join 命令的时候,出现以下错误

The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get http://localhost:10248/healthz: dial tcp [::1]:10248: connect: connection refused

解决方法,首先需要到 k8smaster1 节点,创建一个文件

# 创建文件夹
mkdir /etc/systemd/system/kubelet.service.d

# 创建文件
vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

# 添加如下内容
Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true --fail-swap-on=false"

# 重置
kubeadm reset

然后删除刚刚创建的配置目录

rm -rf $HOME/.kube

然后 在 k8smaster1 重新初始化

kubeadm init --apiserver-advertise-address=92.168.60.151:6443 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.18.0 --service-cidr=10.96.0.0/12  --pod-network-cidr=10.244.0.0/16

初始完成后,我们再到 k8snode1 节点,执行 kubeadm join 命令,加入到 k8smaster1【下面这条命令是 k8smaster1 初始化后自动生成的】

kubeadm join 192.168.60.151:6443 --token c7a7ou.z00fzlb01d76r37s \
    --discovery-token-ca-cert-hash sha256:9c3f3cc3f726c6ff8bdff14e46b1a856e3b8a4cbbe30cab185f6c5ee453aeea5

添加完成后,我们使用下面命令,查看节点是否成功添加

kubectl get nodes

错误四

我们再执行查看节点的时候, kubectl get nodes 会出现问题

Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")

这是因为我们之前创建的配置文件还存在,也就是这些配置

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

我们需要做的就是把配置文件删除,然后重新执行一下

rm -rf $HOME/.kube

然后再次创建一下即可

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

这个问题主要是因为我们在执行 kubeadm reset 的时候,没有把 $HOME/.kube 给移除掉,再次创建时就会出现问题了

错误五

安装的时候,出现以下错误

Another app is currently holding the yum lock; waiting for it to exit...

是因为 yum 上锁占用,解决方法

yum -y install docker-ce

错误六

在使用下面命令,添加 k8snode1 节点到集群上的时候

kubeadm join 192.168.60.151:6443 --token jkcz0t.3c40t0bqqz5g8wsb  --discovery-token-ca-cert-hash sha256:bc494eeab6b7bac64c0861da16084504626e5a95ba7ede7b9c2dc7571ca4c9e5

然后出现了这个错误

[root@k8smaster1 ~]# kubeadm join 192.168.60.151:6443 --token jkcz0t.3c40t0bqqz5g8wsb     --discovery-token-ca-cert-hash sha256:bc494eeab6b7bac64c0861da16084504626e5a95ba7ede7b9c2dc7571ca4c9e5
W1117 06:55:11.220907   11230 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set.
[preflight] Running pre-flight checks
    [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
error execution phase preflight: [preflight] Some fatal errors occurred:
    [ERROR FileContent--proc-sys-net-ipv4-ip_forward]: /proc/sys/net/ipv4/ip_forward contents are not set to 1
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher

出于安全考虑,Linux 系统默认是禁止数据包转发的。所谓转发即当主机拥有多于一块的网卡时,其中一块收到数据包,根据数据包的目的 ip 地址将包发往本机另一网卡,该网卡根据路由表继续发送数据包。这通常就是路由器所要实现的功能。也就是说  /proc/sys/net/ipv4/ip_forward 文件的值不支持转发

  • 0:禁止
  • 1:转发

所以我们需要将值修改成 1 即可

echo “1” > /proc/sys/net/ipv4/ip_forward

修改完成后,重新执行命令即可