kubeadm部署k8s(v1.18.13)

一、环境准备

OS IP hostname
Centos 7.6 192.168.99.151 k8s-master
Centos 7.6 192.168.99.152 k8s-node01
Centos 7.6 192.168.99.153 k8s-node02

如果没有特殊说明,均在所有节点上执行!

二、调整系统其他配置

$ yum install -y nfs-utils wget
# 安装常用工具
$ systemctl stop firewalld && systemctl disable firewalld  
# 关闭防火墙
$ setenforce 0
$ sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
# 禁用SELinux
$ swapoff -a
$ sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
$ mount -a
# 禁用交换分区

# 注意,修改内核参数,如果文件中有相应内容执行该操作修改
$ sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g"  /etc/sysctl.conf
$ sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g"  /etc/sysctl.conf
$ sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g"  /etc/sysctl.conf
$ sed -i "s#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g"  /etc/sysctl.conf
$ sed -i "s#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g"  /etc/sysctl.conf
$ sed -i "s#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g"  /etc/sysctl.conf
$ sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=1#g"  /etc/sysctl.conf

# 修改内核参数,如果是纯净的系统,应执行该操作添加内核参数
$ cat >> /etc/sysctl.conf <<EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv6.conf.all.forwarding = 1
EOF
# 修改内核参数,二选一即可

$ sysctl -p    # 使内核参数生效

三、升级系统内核

由于这次安装的k8s 1.18.13,建议将内核升级至最新版本,否则可能会出现意想不到的错误!

$ uname -r    # 默认的系统内核
3.10.0-957.el7.x86_64
$ rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
# 载入公钥
$ yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
# 安装elrepo最新版本
$ yum list available --disablerepo=* --enablerepo=elrepo-kernel
# 列出可以使用的 kernel 包版本
$ yum -y install kernel-lt --enablerepo=elrepo-kernel
# 如果不指定版本信息,默认安装最新的,如果需要安装指定版本可以使用以下方式
$ yum -y install kernel-lt-5.4.128-1.el7.elrepo --enablerepo=elrepo-kernel    
# 二选一即可!
$ awk -F \' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
# 查看当前系统可用内核版本
0 : CentOS Linux (5.4.128-1.el7.elrepo.x86_64) 7 (Core)
1 : CentOS Linux (3.10.0-957.el7.x86_64) 7 (Core)
2 : CentOS Linux (0-rescue-f36646e20ef14cf7b7c3d921839dd2b5) 7 (Core)
$ grub2-set-default 'CentOS Linux (5.4.128-1.el7.elrepo.x86_64) 7 (Core)'
# 设置系统启动默认加载的内核
$ grub2-editenv list       # 查看系统默认加载的内核
saved_entry=CentOS Linux (5.4.128-1.el7.elrepo.x86_64) 7 (Core)
$ reboot   # 重启系统加载内核
$ uname -r   # 确认系统已经加载了新的内核
5.4.128-1.el7.elrepo.x86_64

四、修改主机名,配置hosts

$ hostnamectl set-hostname k8s-master
$ ssh-keygen 
$ for i in 192.168.99.15{1..3};do ssh-copy-id ${i};done
$ cat >> /etc/hosts << EOF
192.168.99.151 k8s-master
192.168.99.152 k8s-node01
192.168.99.153 k8s-node02
EOF
$ for i in 192.168.99.15{1..3};do scp /etc/hosts ${i}:/etc/;done

五、安装docker 19.03

$ yum remove -y docker \
docker-client \
docker-client-latest \
docker-ce-cli \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
# 卸载旧版本docker
$ yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
# 安装docker所需依赖
$ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 添加阿里云docker repo仓库
$ yum install -y docker-ce-19.03.8 docker-ce-cli-19.03.8 containerd.io
# 安装指定版本的docker
$ [ -d /etc/docker ] || mkdir /etc/docker
$ tee /etc/docker/daemon.json <<EOF
{                        
  "registry-mirrors" : [
    "https://nrbewqda.mirror.aliyuncs.com",
    "https://dmmxhzvq.mirror.aliyuncs.com",
    "https://8xpk5wnt.mirror.aliyuncs.com",
    "https://registry.docker-cn.com"
  ]
}
EOF
# 修改docker镜像下载仓库地址
$ systemctl daemon-reload
$ systemctl start docker && systemctl enable docker
# 启动docker
$ docker version | grep 'Version' | head -1
 Version:           19.03.8
$ docker info | grep -A1 'Registry Mirrors'  # A1表示显示匹配行及匹配行后一行内容
# 确认docker版本及镜像仓库地址

六、初始化kubernetes准备工作

$ cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
       http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
# 添加K8s yum源
$ yum remove -y kubelet kubeadm kubectl
# 卸载旧版本的k8s工具(如果是纯净的系统,可省略该操作)
$ yum install -y kubelet-1.18.13 kubeadm-1.18.13 kubectl-1.18.13
# 安装k8s常用工具
$ sed -i "s#^ExecStart=/usr/bin/dockerd.*#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd#g" /usr/lib/systemd/system/docker.service
# 修改docker Cgroup Driver为systemd,如果不修改在添加work节点时,会出现错误
$ systemctl enable kubelet 
# 设置为开机启动即可,如果此时启动会报错,因为k8s master节点并没有完成初始化

七、初始化master节点

该步骤的操作仅在master节点执行即可!

$ export MASTER_IP=192.168.99.151    # 设置master节点IP地址
$ export APISERVER_NAME=apiserver.demo  # apiserver的名称可自定义
$ export POD_SUBNET=10.100.0.1/16   # K8s容器组所在的网段,该网段安装完成后,由 k8s创建
$ echo "$MASTER_IP $APISERVER_NAME" >> /etc/hosts
$ mkdir k8s_deploy && cd k8s_deploy
$ cat > kubeadm-config.yaml <<EOF
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.18.13
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
controlPlaneEndpoint: "${APISERVER_NAME}:6443"
networking:
  serviceSubnet: "10.96.0.0/16"
  podSubnet: "${POD_SUBNET}"
  dnsDomain: "cluster.local"
EOF
# 准备kubeadm初始化集群所需文件
$ kubeadm init --config=kubeadm-config.yaml --upload-certs
# 初始化k8s集群

八、配置kubectl

$ rm -rf /root/.kube/
$ mkdir /root/.kube/
$ cp -i /etc/kubernetes/admin.conf /root/.kube/config
# 配置kubectl的认证文件(管理员身份)
$ for i in 192.168.99.15{1..3};do scp -r ~/.kube ${i}:;done
# 为了方便起见,配置node节点的kubectl认证文件(管理员身份)
$ yum -y install bash-completion
$ source /usr/share/bash-completion/bash_completion 
$ source <(kubectl completion bash)
$ echo "source <(kubectl completion bash)" >> ~/.bashrc
# 设置kubectl指令支持补全功能

如果初始化失败,请检查以下节点:

  • 环境变量 MASTER_IP 的值应该为 master 节点的 内网IP,如果不是,请重新 export
  • APISERVER_NAME 不能是 master 的 hostname
  • APISERVER_NAME 必须全为小写字母、数字、小数点,不能包含减号
  • POD_SUBNET 所使用的网段不能与 master节点/worker节点 所在的网段重叠。该字段的取值为一个 CIDR 值,如果对 CIDR 这个概念还不熟悉,请仍然执行 export POD_SUBNET=10.100.0.1/16 命令,不做修改
  • 然后重新初始化master节点,重新初始化前,请先执行 kubeadm reset -f 操作。

九、安装calico网络插件

$ wget https://kuboard.cn/install-script/calico/calico-3.13.1.yaml
# 这是kuboard官方提供的yml文件,如果失效了,请替换为官方的地址:https://docs.projectcalico.org/manifests/calico.yaml
$ kubectl apply -f calico-3.13.1.yaml
$ kubectl get pod -n kube-system -o wide
# 确保所有容器是Running状态

十、初始化work节点

master节点获取join命令参数

$ kubeadm token create --print-join-command

kubeadm join apiserver.demo:6443 --token xhicdc.3jwmcz2yipbo8z3d     --discovery-token-ca-cert-hash sha256:79d68a2776fb3ec1cf41f7efb8bfc8ae1f8df06b9eab2cbb7319c69ff0b6d2a7
# 返回的最后一条信息就是work节点加入master节点的所需的指令(包括token)

work节点执行

$ export MASTER_IP=192.168.99.151
$ export APISERVER_NAME=apiserver.demo
$ echo "${MASTER_IP}    ${APISERVER_NAME}" >> /etc/hosts
$ kubeadm join apiserver.demo:6443 --token xhicdc.3jwmcz2yipbo8z3d     --discovery-token-ca-cert-hash sha256:79d68a2776fb3ec1cf41f7efb8bfc8ae1f8df06b9eab2cbb7319c69ff0b6d2a7
# 该命令就是master获取join命令的返回结果

master节点确认

$ kubectl get nodes  # node节点全部处于Ready状态
NAME         STATUS   ROLES    AGE     VERSION
k8s-master   Ready    master   3m   v1.18.13
k8s-node01   Ready    <none>   4m   v1.18.13
k8s-node02   Ready    <none>   4m   v1.18.13
$ kubectl get pods -n kube-system    # 确保pod都是Running的状态

$ kubectl taint node k8s-master node-role.kubernetes.io/master:NoSchedule-
# 去除master节点的污点

十一、work节点join失败

如果遇到worker节点不能成功的join到k8s集群,那么请按照以下思路来解决问题。

11.1 在worker节点执行以下语句可验证worker节点是否能访问 apiserver

$ curl -ik https://apiserver.demo:6443

如果不能,请在 master 节点上验证

$ curl -ik https://apiserver.demo:6443

正常输出结果如下:

HTTP/1.1 403 Forbidden
Cache-Control: no-cache, private
Content-Type: application/json
X-Content-Type-Options: nosniff
Date: Sat, 13 Jun 2020 19:44:58 GMT
Content-Length: 233

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
  "reason": "Forbidden",
  "details": {
    
  },
  "code": 403

11.2 可能原因

  • 如果 master 节点能够访问 apiserver、而 worker 节点不能,则请检查自己的网络设置
    • /etc/hosts 是否正确设置?
    • 是否有安全组或防火墙的限制?
  • worker 节点默认网卡
    • Kubelet使用的 IP 地址 与 master 节点可互通(无需 NAT 映射),且没有防火墙、安全组隔离,如果你使用 vmware 或 virtualbox 创建虚拟机用于 K8S 学习,可以尝试 NAT 模式的网络,而不是桥接模式的网络。

11.3 解决方法

11.3.1 移除worker节点并重试

注:正常情况下,无需移除 worker 节点,如果添加到集群出错,可以移除 worker 节点,再重新尝试添加。

11.3.2 在准备移除的 worker 节点上执行
$ kubeadm reset -f
# worker 节点执行

在 master 节点上执行

$ kubectl get nodes -o wide
# master节点执行,获取worker列表
$ kubectl delete node demo-worker-x-x
#  master节点执行,将demo-worker-x-x替换为你要移除的节点

十二、部署kuboard

$ kubectl apply -f https://kuboard.cn/install-script/kuboard.yaml
$ kubectl apply -f https://addons.kuboard.cn/metrics-server/0.3.6/metrics-server.yaml
$ kubectl get pods -l k8s.kuboard.cn/name=kuboard -n kube-system
NAME                       READY   STATUS    RESTARTS   AGE
kuboard-7bb89b4cc4-hq46h   1/1     Running   0          5m
# 确保容器是正常的状态
$ kubectl get svc -n kube-system | grep kuboard
kuboard          NodePort    10.96.196.64   <none>        80:32567/TCP             5m
# 查看kuboard对应的svc暴露的端口
$echo $(kubectl -n kube-system get secret $(kubectl -n kube-system get secret | grep kuboard-user | awk '{print $1}') -o go-template='{{.data.token}}' | base64 -d)
# 获取管理员的token信息

浏览器访问:

20200705160328

十三、解决重启之后kubelet异常

**修改kubelet的Cgroup Driver**

修改/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf文件,增加--cgroup-driver=systemd

$ vim /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS --cgroup-driver=systemd

$ systemctl daemon-reload && systemctl restart kubelet
$ systemctl status kubelet
posted @ 2021-06-29 23:31  吕振江  阅读(282)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end