k8s是目前最流行的容器编排工具,不过k8s的安装部署一直是国内用户的一大痛点,复杂的部署配置过程使得其学习曲线非常陡峭。而新版本推出的kubeadm工具大大的简化了整个过程,这也是k8s官方推荐的安装工具。可惜,在国内的网络环境下,kubeadm是无法顺利运行的。因此,本文提供了在国内环境下使用kubeadm搭建k8s集群的过程。
本文的步骤基于k8s的官方文档 (https://kubernetes.io/docs/setup) 中的“Bootstrapping Clusters with kubeadm”章节,使用coreos公司的Container Linux作为操作系统进行部署k8s的1.11.2版本。
1. 在VirtualBox中创建Container Linux宿主机。
coreos提供了使用vagrant在virtual创建Container Linux的过程,步骤如下:
# git clone https://github.com/coreos/coreos-vagrant/
# cd coreos-vagrant
# cp config.rb.sample config.rb
# 修改config.rb文件中的$num_instances变量为2,创建两个虚机,core-01作为master节点,core-02作为node节点。
# vagrant up
虚拟机启动后,登陆所有节点并启动docker:
# vagrant ssh core01
# sudo -i
# systemctl enable docker && systemctl start docker
2. 安装kubeadm, kubelet, kubectl软件包
参考文档:https://kubernetes.io/docs/setup/independent/install-kubeadm/
2.1 安装CNI:
# CNI_VERSION="v0.6.0"
# mkdir -p /opt/cni/bin
# curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-amd64-${CNI_VERSION}.tgz" | tar -C /opt/cni/bin -xz
CNI全称为容器网络接口,用于支持k8s节点间的网络通信,其以插件的形式支持多种网络互联方式。如果无法下载,可使用以下替代地址:
curl -L "http://o7gg8x7fi.bkt.clouddn.com/k8s-v1.11.2/cni-plugins-amd64-v0.6.0.tgz" | tar -C /opt/cni/bin -xz
2.2 安装CRICTL
# CRICTL_VERSION="v1.11.1"
# mkdir -p /opt/bin
# curl -L "https://github.com/kubernetes-incubator/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-amd64.tar.gz" | tar -C /opt/bin -xz
CRI全称为容器运行时接口,kubeadm将kubelet,通过这个接口去创建k8s本身管理所需的容器。如果无法下载,可使用以下地址代替:
curl -L "http://o7gg8x7fi.bkt.clouddn.com/k8s-v1.11.2/crictl-v1.11.1-linux-amd64.tar.gz" | tar -C /opt/bin -xz
2.3 安装kubeadm, kubectl, kubelet组件
文档中这几个组件的下载地址国内网络无法访问,因此需要科学上网下载,或者通过以下国内地址下载。
# RELEASE=v1.11.2
# cd /opt/bin
# curl -L --remote-name-all http://o7gg8x7fi.bkt.clouddn.com/k8s-${RELEASE}/{kubeadm,kubectl,kubelet}
# chmod +x {kubeadm,kubelet,kubectl}
2.4 启动kubelet
kubelet是k8s中的在各个节点上的代理,kubeadm也会通过kubelet来创建k8s自身管理所需的容器,如包括api-server,scheduler,controller-manager,proxy,也就是说k8s六大组件,除了kubelet和kubectl外,其他的都已经容器化,并通过kubeadm部署。
# curl -sSL "https://raw.githubusercontent.com/kubernetes/kubernetes/${RELEASE}/build/debs/kubelet.service" | sed "s:/usr/bin:/opt/bin:g" > /etc/systemd/system/kubelet.service
# mkdir -p /etc/systemd/system/kubelet.service.d
# curl -sSL "https://raw.githubusercontent.com/kubernetes/kubernetes/${RELEASE}/build/debs/10-kubeadm.conf" | sed "s:/usr/bin:/opt/bin:g" > /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
# systemctl enable kubelet && systemctl start kubelet
国内访问这两个链接容易失败,注意运行完后检查响应文件的内容是否正确。
3. 下载所需Docker镜像
kubeadm创建集群的时候需要从gcr.io下载镜像,查看所需镜像:
# kubeadm config images list --kubernetes-version=v1.11.2
这些镜像在国内无法访问,因此我已经通过github将这些镜像转移到docker hub上,可用以下命令直接下载:
# cd ~
# git clone https://github.com/lprincewhn/googlecontainers.git
# bash googlecontainers/get_kubeadm_images.sh
4. 创建集群
# kubeadm init --kubernetes-version=${RELEASE} --apiserver-advertise-address=192.168.56.81 --pod-network-cidr=10.244.0.0/16
# mkdir -p $HOME/.kube
# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# chown $(id -u):$(id -g) $HOME/.kube/config
参数说明:
- --kubernetes-version: 由于在国内无法通过网络获取最新的k8s版本号,因此在这里指定为v1.11.2,这里的版本号需要和上一步下载的镜像版本一致。
- --apiserver-advertise-address: 我们在VirtualBox中创建的宿主机有两个网口,其中第二个网口是用于宿主机之间通信的Host-Only网口,我们应该使用这个网口作为api-server的侦听地址。
- --pod-network-cidr: 由于我们将使用的flannel网络插件默认10.244.0.0/16作为node节点间的overlay网络,该参数将这个ip段给pod分配ip。
5. 安装网络插件
我们选择flannel作为网络插件,安装步骤如下:
5.1 修改系统参数
# sysctl net.bridge.bridge-nf-call-iptables=1
该参数表示启动netfilter对bridge数据包,即二层数据包的处理。这是flannel网络插件的要求。
5.2 下载kube-flannel.yml文件
# curl -o kube-flannel.yml -sSL https://raw.githubusercontent.com/coreos/flannel/v0.10.0/Documentation/kube-flannel.yml
在kube-flannel.yml中,定义了名为kube-flannel-ds的DaemonSet,其容器的command为:
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
可见,其并没有指定使用个网口作为flanneld对外通信的物理网卡,于是在有多个网口的宿主机上,flanneld可能会选择一个不正确的网口,使得节点间无法通信。在vagrant启动的宿主机中就存在这个现象,这些虚拟机第一个网口是NAT网口,负责和外网的通信,虚拟机之间不能通过这个网口通信。第二个网口才是虚拟机之间通信的Host-Only网口。因此需要手动修改kube-flannel.yml文件中kube-flannel的command的值,添加参数–iface=ethX,这里的ethX即为用于虚拟机间通信的Host-Only网口,如eth1.
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
- --iface=eth1
5.3 下载flannel镜像
在国内下载flannel镜像同样很容易失败,因此建议提前下载好,再去启动flannel DaemonSet,避免在启动过程中重试浪费时间。手动下载时镜像名称最好从kube-flannel.yml文件中拷贝,确保下载正确的镜像。
# docker pull quay.io/coreos/flannel:v0.10.0-amd64
也可使用以下步骤从国内地址下载:
# cd ~
# git clone https://github.com/lprincewhn/googlecontainers.git
# bash googlecontainers/get_flannel_image.sh
5.4 启动flannel
# kubectl apply -f kube-flannel.yml
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.extensions/kube-flannel-ds created
网络插件安装成功后,节点状态将变为Ready。
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
core-01 Ready master 11m v1.11.2
6. node节点加入集群
在node节点上重复上述第2,3,5.1,5.3节的所有步骤。
然后使用kubeadm join指令将节点加入集群,
# kubeadm join 192.168.56.81:6443 --token cbxiqq.340w6dxc937glr88 --discovery-token-ca-cert-hash sha256:bef4312a2c3326535bda81bfa5d4be98dc1a0e8f6e7491fe5827e671146b068a
参数说明如下:
- --token,node节点加入集群所需的bootstrap token, kubeadm init命令生成的token默认24小时有效,如果超过了这个时间,需要重新生成token,master节点运行命令如下:
# kubeadm token create
- --discovery-token-ca-cert-hash,根证书的摘要,master节点运行如下命令获取:
# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'
成功后在master节点上可查看到新节点为ready状态:
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
core-01 Ready master 3h v1.11.2
core-02 Ready <none> 31s v1.11.2
7. 调整和优化
集群搭建完毕后,建议将master节点的cpu数目调整为2,内存调整为2048M。