开始之前先要安装 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.conf
vi /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 reset
2. 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