华为云服务器ubuntu18.04环境下构建k8s多机集群

机器选择使用华为云的两台x86虚拟机,HECS相对来说便宜一点。这回不用实验室的机器了,希望华为云的机子能给点力。

gist,如果只是要安装k8s可以参考这个脚本。可能还是有点问题(我是在root下跑完的),sudo支持上可能有遗漏的地方。

创建用户

  • useradd -g root wty
  • usermod -a -G sudo wty
  • 创建/home/wty

更新软件

更新apt

换源,更新apt(可以省略,华为云内网速度应该更快一些)

deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

安装并配置zsh

  • sudo apt-get install zsh安装zsh
  • 执行sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"进行配置
  • (国内)gitee镜像

安装并配置git

git config --global user.name "wtysos11"
git config --global user.email wtysos11@163.com
ssh-keygen -t rsa -C "wtysos11@163.com"

上传公钥到github

安装docker

使用脚本安装

  • curl -fsSL get.docker.com -o get-docker.sh
  • sudo sh get-docker.sh --mirror Aliyun
  • usermod -aG docker $USER

参考官方教程配置docker

  • root用户执行service docker start启动进程
  • 普通用户执行sudo groupadd docker创建用户组
  • sudo usermod -aG docker $USER加入用户组
  • 重新登陆,或者执行newgrp docker
  • 执行docker run hello-world尝试安装是否成功

配置镜像加速:阿里云。由于使用了阿里云,就不进行docker login了。

安装kubernetes

配置apt仓库

参考,配置apt仓库并安装对应的二进制组件(如果对版本没有要求可以不进行指定)

sudo apt-get update && sudo apt-get install -y apt-transport-https
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add - 
cat << EOF > /etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
# sudo apt-get install -y kubelet=1.23.4-00 kubeadm=1.23.4-00 kubectl=1.23.4-00

启动kubelet,运行情况检查

  • systemctl status kubelet查看情况
  • journalctl -xeu kubelet输出日志

遇到问题:kubelet shutdown

报错信息"Failed to run kubelet" err="failed to run Kubelet: misconfiguration: kubelet cgroup driver: \"systemd\" is different from docker cgroup driver: \"cgroupfs\""

从报错信息来看,应该是docker的cgroup driver和kubelet的cgroup driver不一致的问题。

参考SO的解决方案,在docker的配置文件(/etc/docker/daemon.json)中加上了"exec-opts": ["native.cgroupdriver=systemd"],然后使用sudo systemctl restart docker即可(PS:即使是新开启的docker也必须执行)

遇到问题:failed to load kubelet config file

Aug 26 16:17:48 k8s-master systemd[1]: kubelet.service: Service hold-off time over, scheduling restart.
Aug 26 16:17:48 k8s-master systemd[1]: kubelet.service: Scheduled restart job, restart counter is at 87.
-- Subject: Automatic restarting of a unit has been scheduled
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
-- 
-- Automatic restarting of the unit kubelet.service has been scheduled, as the result for
-- the configured Restart= setting for the unit.
Aug 26 16:17:48 k8s-master systemd[1]: Stopped kubelet: The Kubernetes Node Agent.
-- Subject: Unit kubelet.service has finished shutting down
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
-- 
-- Unit kubelet.service has finished shutting down.
Aug 26 16:17:48 k8s-master systemd[1]: Started kubelet: The Kubernetes Node Agent.
-- Subject: Unit kubelet.service has finished start-up
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
-- 
-- Unit kubelet.service has finished starting up.
-- 
-- The start-up result is RESULT.
Aug 26 16:17:48 k8s-master kubelet[27908]: E0826 16:17:48.885345   27908 server.go:206] "Failed to load kubelet config file" err="failed to load Kubelet config file /var/lib/k
ubelet/config.yaml, error failed to read kubelet config file \"/var/lib/kubelet/config.yaml\", error: open /var/lib/kubelet/config.yaml: no such file or directory" path="/var/
lib/kubelet/config.yaml"
Aug 26 16:17:48 k8s-master systemd[1]: kubelet.service: Main process exited, code=exited, status=1/FAILURE
Aug 26 16:17:48 k8s-master systemd[1]: kubelet.service: Failed with result 'exit-code'.
Aug 26 16:17:59 k8s-master systemd[1]: kubelet.service: Service hold-off time over, scheduling restart.
Aug 26 16:17:59 k8s-master systemd[1]: kubelet.service: Scheduled restart job, restart counter is at 88.
-- Subject: Automatic restarting of a unit has been scheduled
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
-- 

报错信息主要是failed to load kubelet config file

参考issue/65863的一个回答。不过这个问题可以直接通过kubeadm init解决(简单来说就是不用管)

其他问题

kubeadm: Configuring a cgroup driver提到v1.22版本中,如果用户没有指定cgroupDriver的会默认为systemd。目前我用的正是1.22.1版本,应该是这个值没有设置为cgroupfs的问题

# kubeadm-config.yaml
kind: ClusterConfiguration
apiVersion: kubeadm.k8s.io/v1beta3
kubernetesVersion: v1.22.1
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: cgroupfs

通过kubeadm安装k8s集群

  • 官网教程,还是比较推荐的,唯一的问题就是没有考虑到国内访问不到谷歌的问题

预先配置

交换与防火墙
  • top内查看是否开启交换,开了要关闭
  • 关闭防火墙
网络

官网“允许iptables检查桥接流量”一节提到lsmod | grep br_netfilter来检查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
EOF
sudo sysctl --system
配置cgroup为systemd

kubelet这边可以不用管,默认是systemd。需要按照[kubelet shutdown](#遇到问题:kubelet shutdown)内的操作来修改容器运行时的cgroup,不然Kubelet会启动不了。(按照官方的说法,不建议修改kubelet的cgroup为cgroupfs)

正式安装

可以参考我之前配置时的教程。不过当时并没有做可重复性相关的验证。

首先使用kubeadm config images list列出kubeadm所需要的所有镜像

k8s.gcr.io/kube-apiserver:v1.22.1
k8s.gcr.io/kube-controller-manager:v1.22.1
k8s.gcr.io/kube-scheduler:v1.22.1
k8s.gcr.io/kube-proxy:v1.22.1
k8s.gcr.io/pause:3.5
k8s.gcr.io/etcd:3.5.0-0
k8s.gcr.io/coredns/coredns:v1.8.4

执行以下命令进行安装:

sudo kubeadm init --apiserver-advertise-address=10.186.117.4 --pod-network-cidr=10.244.0.0/16 --token-ttl=0 --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers

命令参考:官方,也可以在命令行下查看。

  • apiserver-advertise-address:这个参数指定了监听的API地址。若没有设置,则使用默认网络接口。我使用的是华为云的服务器,这里填master节点的地址即可(要求能被其他节点访问到)

  • apiserver-bind-port:这个参数指定了API服务器暴露出的端口号,默认是6443。

  • pod-network-cidr:规定了pod能够使用的IP地址段。我之前用的是16位子网掩码,但是现在给的子网就是24位掩码,我也不确定使用其他子网能不能行……先保险起见吧。

  • kubernetes-version:指定kubeadm安装的kubernetes版本。这个是很重要的,因为默认情况下kubeadm会安装与它版本相同的kubernetes版本,而由于国内的网络问题,每次都需要重新下载一遍镜像,非常的麻烦。如果之后版本使用这个脚本,可以加上--kubernetes-version=v1.19.2

  • image-repository:默认是"k8s.gcr.io"。我觉得如果修改这个可以不用像之前那样从阿里云下载下来后手动tag。可以使用kubeadm config images pull --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers参考

  • token-ttl:令牌被删除前的时间,默认是24h。kubeadm初始化完毕后会生成一个令牌,让其他节点能够加入集群,过时之后这个令牌会自动删除。如果设置为0之后令牌就永不过期。

这一步的难点在于如何设置pod-network-cidr,参数的作用。根据官方教程的说法,Pod网络与任何主机网络不得有重叠。但是目前我看到的很多教程都是在主机局域网络下构建的。比如说三台主机都在192.168.1.1/16子网,而pod网络也在同样的子网下。

这个参数的设置似乎与所使用的CNI有关系:

  • flannel,要求的参数为--pod-network-cidr=10.244.0.0/16

  • calico,要求的参数为--pod-network-cidr=192.168.0.0/16

本文采用flannel,一个很重要的原因是因为服务器的子网与pod的子网部分重叠,可能存在风险,以及flannel似乎更容易部署一些。

值得注意的是,在coredns镜像中,只有x.x.x,而没有vx.x.x,所以需要手动改一下。也可以参考zhangguanzhang的工具来直接同步

如果image-repository不可用可以考虑下面的脚本

#########################################################################
# File Name: pull_master_image.sh
# Description: pull_master_image.sh
# Author: zhangyi
# mail: 450575982@qq.com
# Created Time: 2019-07-31 21:38:14
#########################################################################
#!/bin/bash
kube_version=:v1.22.1
kube_images=(kube-proxy kube-scheduler kube-controller-manager kube-apiserver)
addon_images=(etcd:3.5.0-0 coredns:1.8.4 pause:3.5)

for imageName in ${kube_images[@]} ; do
  docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName-amd64$kube_version
  docker image tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName-amd64$kube_version k8s.gcr.io/$imageName$kube_version
  docker image rm registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName-amd64$kube_version
done

for imageName in ${addon_images[@]} ; do
  docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
  docker image tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
  docker image rm registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
done

之后,需要执行这三条命令,其作用是将kubectl所需要的配置文件拉到用户目录下并设置访问权限。(不执行的话kubectl是无法正常工作的)

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

有时可能需要显示配置export KUBECONFIG=$HOME/.kube/config

如果是使用root用户需要设置export KUBECONFIG=/etc/kubernetes/admin.conf

使用kubectl get pods -n=kube-system可以查看所有的系统容器,这时候coredns可能没有运行,这个没有关系,等flannel装上之后就好了。

untaint

对于小集群,必须要执行kubectl taint nodes --all node-role.kubernetes.io/master-,不然调度的时候会少一台机子。

安装flannel

参考flannel官方教程

  • curl -fsSL https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml > kube-flannel.yml下载配置文件
  • kubectl apply -f kube-flannel.yml

日志记录:

➜  ~ kubectl apply -f kube-flannel.yml
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/psp.flannel.unprivileged 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

可能出现的问题:

  • flannel需要镜像quay.io/coreos/flannel:v0.14.0,之前安装的时候没有办法抓下来。不过这次成功搞下来了,可能是阿里云的镜像服务又更进一步了?

此时,k8s的安装就基本完成了,后续就自由发挥了。

istio安装

按照官网指南安装即可,这个版本的istio安装基本不会出现问题

其他问题

  1. 安装flannel时提示open /run/systemd/resolve/resolv.conf: no such file or directory,经过检查发现是节点的systemd-resolved出现问题,systemctl status systemd-resolved中状态为Inactive。直接使用systemctl restart systemd-resolved重启对应的DNS服务即可。
  2. 端口问题。因为在内网配置了比较严格的安全策略,需要手动打开但偶才能正常工作。其中kubernetes的api-server默认是在6443端口下工作,istio则需要15021端口。而且coreDNS需要UDP53端口……如果可以的话测试环境建议全打开,鬼知道是在哪里被卡的。
  3. 新节点加入:在之后还有节点要加入的话,可以在主节点执行kubeadm token create --print-join-command
0%