开始之前先要安装 Docker ,安装教程可参考我的另一篇文章 CentOS环境下安装Docker 。
安装前准备
关闭 swap 交换区
# 临时关闭 sudo swapoff -a # 永久关闭: 把 /etc/fstab 中的swap注释掉 sudo sed -i 's/.*swap.*/#&/' /etc/fstab或编辑文件
/etc/fstab,将swap注释掉即可;禁用 selinux
# 临时关闭 setenforce 0 # 永久关闭 sudo sed -i "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config或编辑文件
/etc/selinux/config:SELINUX=disabled关闭防火墙
systemctl stop iptables允许 iptables 检查桥接流量
编辑文件
/etc/sysctl.d/k8s.confvi /etc/sysctl.d/k8s.conf在文件中添加以下内容:
net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1执行命令
sysctl -p /etc/sysctl.d/k8s.conf配置阿里云镜像源加速器
加速器地址可登录阿里云官网,访问 镜像加速器 获取;
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://1bk7ry6i.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
安装K8S
配置安装源
sudo curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo如果是 CentOS 8,则使用以下命令:
sudo curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-8.repo添加K8S安装源,使用阿里云镜像;
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[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安装 kubeadm、kubelet、kubectl 组件
yum install -y kubeadm kubelet kubectl若安装指定版本,在命令中添加版本号即可:
yum install -y kubeadm-1.18.0
启动 kubelet 服务
systemctl enable kubelet && systemctl start kubelet初始化主节点
kubeadm init --image-repository registry.aliyuncs.com/google_containers --apiserver-advertise-address 192.168.1.3 --pod-network-cidr=10.244.0.0/16云服务使用公网IP的使用以下命令:
kubeadm init --image-repository registry.aliyuncs.com/google_containers --pod-network-cidr=10.244.0.0/16由于默认拉取镜像地址 k8s.gcr.io 国内无法访问,这里添加参数 --image-repository 指定阿里云镜像仓库地址。
注意:若主机是阿里云、腾讯云的ECS,--apiserver-advertise-address 设置的IP不能是公网IP,否则会初始化失败,原因及解决方法看以下的【错误汇总:2. Initial timeout of 40s passed.】,因此要写内网IP或不配置此参数。
可选参数说明:
--apiserver-advertise-address: master 和 worker 间能互相通信的 IP--kubernetes-version: 指定版本--token-ttl=0:token 永不过期--apiserver-cert-extra-sans:节点验证证书阶段忽略错误
此过程需要几分钟,请耐心等待。安装完成后,输出如下,其中会返回 node 节点添加到集群的命令,你只需复制保存即可,如果忘记可使用命令 kubeadm token create --print-join-command 查看。
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
...
kubeadm join 192.168.1.3:6443 --token qzpag0.9to4x04asdd383o \
--discovery-token-ca-cert-hash sha256:21611a589d89ad6218e7154asda5sda6e0bf78657dbeb9e10a80fd要使用集群,我们还得按提示执行以下命令:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config至此,master 节点安装完成,我们可以使用 kubectl get nodes 查看,此时 master 处于 NotReady 状态。
[root@lanweihong yum.repos.d]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
lanweihong NotReady control-plane,master 6m24s v1.18.0等待一两分钟左右,再次使用命令 kubectl get node 查看,发现状态已为 Ready ,此时集群状态正常。
若初始化k8s集群失败,在下一次执行 kubeadm init 初始化命令前,先执行 kubeadm reset 命令重置节点,清理环境。否则再次 kubeadm init 初始化时会报 Port 10250 is in use 等错误。
kubeadm reset安装 pod 网络附加组件 flannel
flannel Github地址:https://github.com/flannel-io/flannel
Kubernetes v1.17及以上 使用以下命令安装 flannel:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml配置 iptables 转发 IP ,使云服务器网络互通
由于初始化时删除了 --apiserver-advertise-address 参数,返回的节点加入集群命令为内网IP,但几个云服务器内网不互通,所以我们需要使用 iptables 进行 IP 转发,将主节点公网IP转发至内网IP,由于node节点加入集群的命令是内网IP,因此还需要配置 node 节点将主节点的内网IP转发至主节点的公网IP。
# 在主节点 master
sudo iptables -t nat -A OUTPUT -d <主节点公网IP> -j DNAT --to-destination <主节点私有IP>
# 在 node 节点上
sudo iptables -t nat -A OUTPUT -d <主节点私有IP> -j DNAT --to-destination <主节点公网IP>对于公网IP初始化集群时失败,网上还有另一种解决方案,就是修改 /etc/kubernetes/manifests/etcd.yaml 配置,将 --listen-client-urls 和 --listen-peer-urls 的IP改为 0.0.0.0。这方法我试过几次,但每次都是失败,后来就采用 iptables 转发 IP 方式。此方案具体操作可看 [解决阿里云ECS下kubeadm部署k8s无法指定公网IP(作废)] 。
安装工作节点并加入集群
工作节点安装可参考以上操作,最后使用初始化 master 节点成功返回的添加命令即可,注意主节点云服务器安全组要开放 6443 端口,腾讯云服务器安全组出站要开放 6443 端口。
kubeadm join <主节点公网IP>:6443 --token fcuu2m.1d01193ud9dfbzdx \
--discovery-token-ca-cert-hash sha256:4e7f9e6717a87b6702b466ac3f8026818330463c7a1f4cf0f976f90054dc6038命令后加参数 --v=2 或 --v=5 可以查看日志。
若 token 超时,我们可在 k8s 主节点上执行以下命令重新生成
kubeadm token create --print-join-command加入集群成功后,我们在主节点上使用 kubectl get nodes 命令查看节点信息:
[root@lanweihong lanweihong]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
i8mal9fj9qz Ready <none> 8m v1.18.0
izk9mmdz Ready master 4h58m v1.18.0
vm-123-a6 Ready <none> 4m5s v1.18.0错误汇总
1. Port 10250 is in use
[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 Port-10259]: Port 10259 is in use
[ERROR Port-10257]: Port 10257 is in use
[ERROR FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists
[ERROR FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml]: /etc/kubernetes/manifests/kube-controller-manager.yaml already exists
[ERROR FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml]: /etc/kubernetes/manifests/kube-scheduler.yaml already exists
[ERROR FileAvailable--etc-kubernetes-manifests-etcd.yaml]: /etc/kubernetes/manifests/etcd.yaml already exists
[ERROR Port-10250]: Port 10250 is in use解决方法
可执行以下命令才释放这些端口和文件即可:
kubeadm reset2. Initial timeout of 40s passed.
使用 kubeadm init 初始化时使用公网IP配置会出现以下问题:
[kubelet-start] Starting the kubelet
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[kubelet-check] Initial timeout of 40s passed.问题分析
因为阿里云主机网络是VPC,公网IP只能在控制台上看到,在系统里面看到的是内部网卡的IP,阿里云采用NAT方式将公网IP映射到ECS的位于私网的网卡上,所以在网卡上看不到公网IP,使用 ifconfig 查看到的也是私有网卡的IP,导致 etcd 无法启动。
解决方法
删除初始化命令中的 --apiserver-advertise-address 参数或使用内网IP,然后重新初始化,主机之间的通信采用 iptables 转发。
3. Failed to request cluster info, will try again
节点加入集群时出现以下错误:
[discovery] Failed to request cluster info, will try again: [Get https://<私有IP>:6443/api/v1/namespaces/kube-public/configmaps/cluster-info: dial tcp <私有IP>:6443: i/o timeout]问题分析
使用参数 --v=5 查看详细的日志后发现,node 还是会去请求 master 内网IP的地址,所以肯定会连接超时;
I0411 16:28:33.060242 5363 join.go:447] [preflight] Fetching init configuration
I0411 16:28:33.060251 5363 join.go:485] [preflight] Retrieving KubeConfig objects
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
Get https://<私有IP>:6443/api/v1/namespaces/kube-system/configmaps/kubeadm-config: dial tcp <私有IP>:6443: i/o timeout
failed to get config map解决方法
因此我们需要在工作节点上进行IP转发,将master内网IP请求的地址转到master公网IP:
sudo iptables -t nat -A OUTPUT -d <master的私有IP> -j DNAT --to-destination <master的公网IP>再次使用kubeadm join 加入集群,发现已连接到集群,在主节点上使用 kubectl get nodes 查看,可看到已连接节点信息;
[root@lanweihong lanweihong]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
i8mal9fj9qz Ready <none> 8m v1.18.0
izk9mas82mdz Ready master 4h58m v1.18.0
vm-123-a6 Ready <none> 4m5s v1.18.0