背景
之前搭建的k8s集群是基于CentOS 7自带yum源,版本老旧,是1.5.2版本,但是目前社区k8s版本已经发布1.15版本了,因此想要了解最新特性和方向还是需要使用最新版本搭建集群。
k8s 1.15版本
我们可以通过版本的release notes(https://kubernetes.io/docs/setup/release/notes/)了解一些信息,尤其是一些组件依赖,因为一般版本升级了,依赖组件也会升级,如果不匹配,有可能特性无法使用,甚至服务也不可用。
比如,k8s使用的容器引擎是docker,1.15版本支持的docker版本为:
The list of validated docker versions remains unchanged.
The current list is 1.13.1, 17.03, 17.06, 17.09, 18.06, 18.09. (#72823, #72831)
因此如果使用的版本过旧或者过新,可能都会出现问题。
环境准备
节点名称 | 节点IP |
---|---|
master | 192.168.0.100 |
node1 | 192.168.0.101 |
node2 | 192.168.0.102 |
registry(镜像仓库) | 192.168.0.200 |
大前提
1、所有机器关闭防火墙
systemctl stop firewalld.service
systemctl disable firewalld.service
2、所有机器关闭selinux
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
3、所有机器配置好hostname,并确保集群内能通过hostname访问
hostnamectl set-hostname master
echo "192.168.0.100 master" >> /etc/hosts
4、所有机器关闭swap,镜像仓库机器可不关闭
swapoff -a
注释/etc/fstab中swap的分区挂载项
既然swap已经关闭,那么vm.swappiness参数也要一同设置为0,让进程尽可能使用内存,我们将该参数设置和下一步配置放一起。
5、配置各节点系统内核参数使流过网桥的流量也进入iptables/netfilter框架中
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
vm.swappiness = 0
EOF
然后执行以下命令,即时生效,
sysctl -p /etc/sysctl.d/k8s.conf
因为配置文件在/etc/sysctl.d/目录,所以不用担心重启后会失效,系统在启动过程中会加载这个目录的配置。
6、确认iptables的FORWARD规则
Docker不知啥时候开始会将iptables filter链的FORWARD规则默认设置为DROP,
[root@CentOS-7-2 ~]# iptables -vnL | grep FORWARD
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
[root@CentOS-7-2 ~]# systemctl start docker
[root@CentOS-7-2 ~]# iptables -vnL | grep FORWARD
Chain FORWARD (policy DROP 0 packets, 0 bytes)
经常会导致集群网络不通,因此需要设置FORWARD规则为ACCEPT
iptables -P FORWARD ACCEPT
并将该操作固化到开机流程中,而且得在docker服务启动之后,因此我们添加一个systemd开机服务,
cat > /usr/lib/systemd/system/forward-accept.service <<EOF
[Unit]
Description=set forward accept
After=docker.service
[Service]
ExecStart=/usr/sbin/iptables -P FORWARD ACCEPT
[Install]
WantedBy=multi-user.target
EOF
systemctl enable forward-accept && systemctl start forward-accept
当然,也可以直接修改docker的service文件,增加一个服务启动后执行项,效果一样。
vi /usr/lib/systemd/system/docker.service
[Service]
ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT
7、安装ntp服务并启动
保证集群间的时间一致,否则会有各种未知问题。
yum install -y ntp
systemctl start ntpd;systemctl enable ntpd
开始搭建
1、所有节点安装docker
上面说到1.15版本支持的docker版本最低为1.13.1,CentOS 7自带repo中docker版本正是1.13.1,因此是OK的。
[root@CentOS-7-4 /home]# yum list docker
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Available Packages
docker.x86_64 2:1.13.1-96.gitb2f74b2.el7.centos extras
不过我还是想用新一点的版本,毕竟社区版本已经是19.03了。
所以呢,参考docker文档(https://docs.docker.com/install/linux/docker-ce/centos/)安装新的repo,使用高版本的docker。
大致步骤如下:
a、卸载旧版本docker
yum remove -y docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
b、更新docker依赖驱动
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
c、安装docker-ce.repo
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
d、看下有提供哪些版本的docker
[root@CentOS-7-4 /home]# yum list docker-ce --showduplicates
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
...
Available Packages
...
docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.2.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.3.ce-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable
...
docker-ce.x86_64 3:18.09.7-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.8-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.0-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.1-3.el7 docker-ce-stable
e、安装docker-ce
为了避免过于激进,采用中庸思想,我们选择安装18.06版本的docker-ce,
yum install -y docker-ce-18.06.3.ce-3.el7
f、启动服务并设置开机启动
systemctl start docker
systemctl enable docker
2、准备镜像
由于国内无法访问k8s.gcr.io、quay.io等网站,但是使用kubeadm搭建的方式又会去这些网站拉取k8s相关镜像,这样肯定是会失败的。因此我们先从其他渠道获取镜像,放到自己本地的私有镜像,然后将k8s.gcr.io、quay.io的解析指向我们自己私有的registry就可以曲线救国了。
a、创建自己的私有镜像仓库
docker pull registry
docker run --restart=always -d -p 80:5000 --hostname=my-registry --name my-registry -v /mnt/data/registry:/var/lib/registry registry
在192.168.0.200上创建私有镜像仓库,对外端口映射到80端口,同时挂载本地存储分区到容器中,用于镜像的存储和持久化。
b、获取k8s和flannel相关镜像
k8s使用mirrorgooglecontainers库的镜像,
docker pull mirrorgooglecontainers/kube-apiserver:v1.15.1
docker pull mirrorgooglecontainers/kube-proxy:v1.15.1
docker pull mirrorgooglecontainers/kube-controller-manager:v1.15.1
docker pull mirrorgooglecontainers/kube-scheduler:v1.15.1
docker pull mirrorgooglecontainers/coredns:1.3.1
docker pull mirrorgooglecontainers/etcd:3.3.10
docker pull mirrorgooglecontainers/pause:3.1
flannel使用七牛的镜像获取,
docker pull quay-mirror.qiniu.com/coreos/flannel:v0.11.0-amd64
c、将镜像打上我们自己仓库的tag,并push到私有镜像
docker tag mirrorgooglecontainers/kube-apiserver:v1.15.1 192.168.0.200:80/kube-apiserver:v1.15.1
docker push 192.168.0.200:80/kube-apiserver:v1.15.1
...
其余的镜像也要同样操作,其中192.168.0.200是我们刚才创建私有仓库的机器。
d、修改/etc/hosts,更改域名解析
在master和两个node节点上执行以下操作,
echo "192.168.0.200 quay.io k8s.gcr.io gcr.io" >> /etc/hosts
这样,在后续使用镜像时都会到我们自己的私有镜像上获取。
3、所有节点(除registry节点)增加insecure-registries选项和设置cgroup驱动
由于我们搭建的镜像仓库使用的是http协议,但是docker pull镜像默认使用https协议,因此需要增加insecure-registries选项配置。
同时修改docker cgroup driver的驱动默认为cgroupfs,
[root@CentOS-7-2 ~]# docker info | grep "Cgroup Driver"
Cgroup Driver: cgroupfs
但是kubelet使用的是systemd,因此也需要将docker的cgroup驱动修改。
cat << EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"insecure-registries":["192.168.0.200:80", "quay.io", "k8s.gcr.io", "gcr.io"]
}
EOF
systemctl restart docker
重启docker后通过docker info再次确认驱动修改成功。
4、所有节点(除registry节点)安装kubelet kubeadm kubectl
同样,我们使用阿里云的repo源来安装,
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet && systemctl start kubelet
首先获取阿里云k8s repo,然后直接yum安装,省时省力,最后设置服务开机启动并启动服务。
5、 master节点使用kubeadm init 一键式部署集群
所有准备做完后,就可以使用 kubeadm init来初始化整个集群了,
kubeadm init --pod-network-cidr 10.244.0.0/16
切记,如果集群通信采用flannel的话,执行时一定要带 --pod-network-cidr 参数,并且网络段要和flannel yaml文件中定义的保持一致。
[root@master ~]# kubeadm init --pod-network-cidr 10.244.0.0/16
...
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
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.0.100:6443 --token 6p1t12.uw1tyqp0ajhkinnd \
--discovery-token-ca-cert-hash sha256:26e28cc6199cd4dfeba4b933311ffb902ff97dc15b9940decd704cfdca9beaa2
为了让非root用户能使用 kubelet,还是需要作如下的一些配置,
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
6、将node节点加入集群中
根据上面的提示,在两个node节点中执行kubeadm join加入集群,
[root@CentOS-7-5 ~]# kubeadm join 192.168.0.100:6443 --token 6p1t12.uw1tyqp0ajhkinnd \
--discovery-token-ca-cert-hash sha256:26e28cc6199cd4dfeba4b933311ffb902ff97dc15b9940decd704cfdca9beaa2
[preflight] Running pre-flight checks
[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'
[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.15" ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Activating the kubelet service
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
这样我们在master节点就能查到这两个节点了,
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 NotReady <none> 14s v1.15.1
master NotReady master 172m v1.15.1
node2 NotReady <none> 11s v1.15.1
因为我们还没部署集群通信组件flannel,因此节点状态还都是NotReady。
7、master节点部署flannel组件
首先获取yaml文件,然后直接使用该配置文件创建flannel集群,
wget https://raw.githubusercontent.com/coreos/flannel/62e44c867a2846fefb68bd5f178daf4da3095ccb/Documentation/kube-flannel.yml
kubectl apply -f kube-flannel.yml
部署完成后,过一会就能查看节点状态都OK了,
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready <none> 8m53s v1.15.1
master Ready master 3h1m v1.15.1
node2 Ready <none> 8m50s v1.15.1
到此,整个集群就搭建好了。
异常处理
如果集群初始化过程中出现异常,可以执行reset命令回退,但是记得清理一些数据,否则再次创建集群时会出现各种未知错误。
kubeadm reset
rm -rf $HOME/.kube/
rm -rf /var/lib/cni/
rm -rf /var/lib/kubelet/*
rm -rf /etc/cni/
ip link delete cni0
ip link delete flannel.1
systemctl restart docker
常见问题
1、创建registry容器失败,
OCI runtime create failed: container_linux.go:348: starting container process caused "process_linux.go:297: copying bootstrap data to pipe caused \"write init-p: broken pipe\"": unknown
解决方案:内核版本过低,因为镜像仓库是在CentOS 7.2系统上搭建的,内核版本是3.10.0-327.el7.x86_64,升级到3.10.0-957.21.3.el7.x86_64后问题解决。
yum update kernel
reboot
2、无法从私有镜像仓库中拉取镜像
Error response from daemon: Get https://192.168.0.200:80/v2/: http: server gave HTTP response to HTTPS client
解决方案:这是因为docker默认需要使用https连接,但是我们搭建仓库时用的是http协议,因此需要在docker的启动参数里添加insecure-registries选项,将私有镜像ip地址和quay.io,k8s.gcr.io都添加进去,并且重启docker服务。
在/etc/docker/daemon.json中添加以下选项
{
"insecure-registries":["192.168.0.200:80","quay.io", "k8s.gcr.io"]
}
systemctl restart docker
3、节点执行kubeadm join后状态一直不正常,kubelet状态不断重启,该节点的flannel pod也一直处于pending状态,
kubelet: Failed to start ContainerManager Cannot set property TasksAccounting, or unknown property
解决方案:升级systemd组件,我这个出问题的节点是CentOS 7.3, systemd版本是systemd-219-30,升级至systemd-219-62后问题解决。
4、在安装flannel网络插件后,发现pod: kube-flannel-ds 一直是CrashLoopBackOff
解决方案:执行kubeadm Init的时候,增加 --pod-network-cidr 10.244.0.0/16参数,不指定这个参数会导致节点网络和flannel yaml中的"Network": "10.244.0.0/16"不一样,使得Node间Cluster IP不通。
——————————
参考
1、https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
2、https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/