前言

在这周,终于找机会自行安装了一次Kubernetes(以下简称k8s)1.9版本。实际上我们的生产环境里已经使用了一年多的k8s,只是我的工作恰好绕过了k8s本身,只涉及了维护VPS和使用k8s,我们的后台兼运维同事自行搭建了k8s。也许直接运行程序,用systemd管理会更方便,性能也会有所改善,但从最初选择为了容器化而容器化开始,后续的一切服务都不可避免地卷入容器和集群中。

原本是没有机会接触集群的,一方面作为iOS客户端开发的主要任务都在客户端,另一方面是早期k8s的概念复杂,入门门槛较高。从LoraWAN项目开始,需要自行处理一些应用部署及维护问题,从本地裸机部署程序到容器化稳定运行,花费了漫长的时间。目前LoraWAN的服务端在容器中已经运行了5个月,唯一一次事故也是集群挂掉引起的,因为一些缘故,让服务停滞了接近12个小时,施工中断、节点无法通信。被牵连的感觉有点无奈,就认真地重新关注k8s,而且感觉可以用k8s作为基础构建一个类似arukas的docker服务平台来练练手。

VPS参数

Master配置:Vultr 主机 x 1,KVM虚拟化,单核,1GB内存,25GB存储空间,1TB流量,公网IP,洛杉矶机房,Ubuntu 16.04 LTS,主机名vultr;

Node配置:搬瓦工主机 x3,KVM虚拟化,单核,512MB内存,10GB存储空间,1TB流量,公网IP,洛杉矶机房,CentOS 7.3,主机名分别为jim,ck1,ck2。

无论是Master还是Node的配置都没有达到官方文档里给出的最低参数要求,我们可以忽略这个细节,因为实际测试中,一但安装日志收集工具,就会由于CPU和内存暴满导致崩溃,但这并不妨碍接下来继续折腾集群,可以先部署一些轻量级的应用,等有机会在性能更强悍的主机上部署时,也会更熟练。

安装k8s

官方指南链接:k8s_setup

下面是主要操作步骤:

(1)配置VPS,确保每台具有相同的软件环境;

(2)使用kubeadm设置master与node,启动集群;

配置VPS

在使用kubeadm设置master和node前,需要对每个VPS进行相同的配置,包括:

(1)安装dokcer-ce 17.03版本;

(2)安装k8s 1.9版本,包括kubeadm,kubelet,kubectl;

(3)其他设置。

安装docker-ce 17.03版本

k8s 1.9版本最高支持的docker-ce版本是17.03,但docker版本迭代比k8s快多了,我们需要安装老版本,并且锁定docker-ce,使它不会被误操作升级,当然也可以同时锁定k8s的版本。

Ubuntu

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apt-get update
apt-get install -y docker.io
apt-get update
apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository \
   "deb https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
   $(lsb_release -cs) \
   stable"
apt-get update && apt-get install -y docker-ce=$(apt-cache madison docker-ce | grep 17.03 | head -1 | awk '{print $3}')

锁定版本,忽略更新

1
apt-mark hold docker-ce

CentOS

1
2
3
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y --setopt=obsoletes=0 docker-ce-17.03.2.ce-1.el7.centos docker-ce-selinux-17.03.2.ce-1.el7.centos

锁定版本,忽略更新

1
2
yum install yum-versionlock -y
yum versionlock docker-ce

安装k8s 1.9版本

Ubuntu

1
2
3
4
5
6
7
apt-get update && apt-get install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl

CentOS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
setenforce 0
yum install -y kubelet kubeadm kubectl

其他配置

这里需要设置iptables,解决RHEL/CentOS 7系统上跨主机容器间可能无法访问的问题,同时关闭交换空间,还要保证k8s与docker的Cgroup Driver一致,这里统一使用systemd,最后必需配置好每台主机的hostname。最后的最后,可以给主机升级内核,开启BBR与TCP Fast Open。

(1)系统iptables与swap

1
2
3
4
5
6
cat <<EOF >> /etc/sysctl.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
vm.swappiness=0
EOF
sysctl -p

(2)docker的Cgroup Driver及Storage Driver

1
2
3
4
5
6
cat <<EOF >>/etc/docker/daemon.json
{
    "storage-driver": "overlay2",
    "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF

(3)k8s的Cgroup Driver

k8s 1.9版本里默认使用systemd作为Cgroup Driver,并且加入了启动参数中

/etc/systemd/system/kubelet.service.d/10-kubeadm.conf

1
2
3
4
......
Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=systemd"
......
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CGROUP_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGS

(4)BBR及TCP Fast Open

安装版本在4.10以上的linux内核,Ubuntu上的包名为linux-image-x.xx.x-xx-generic,CentOS上的包名为kernel-ml-xxxxx。Ubuntu上可以直接使用apt命令安装,CentOS上还需要先配置EPEL REPO,才能使用yum安装。

1
2
wget dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-11.noarch.rpm
rpm -ihv epel-release-7-11.noarch.rpm

最后在sysctl.conf文件中追加参数

1
2
3
4
5
6
cat <<EOF >>/etc/sysctl.conf 
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
net.ipv4.tcp_fastopen=3
EOF
sysctl -p

(5)配置hostname

Ubuntu与CentOS都可以直接编辑/etc/hostname,修改主机名

(6)设置开机启动,重启系统

1
2
3
4
systemctl daemon-reload
systemctl enable docker
systemctl enable kubelet
reboot

配置集群

从这里开始就简单一点了,使用Flannel作为pod network配置master,然后将剩余的主机作为node加入master。

先解决一个错误

[WARNING FileExisting-crictl]: crictl not found in system

PATH环境变量中找不到可执行程序crictl,这个程序是一个Go程序,如果预先配置好了Go开发环境,可以用go get命令安装

1
2
go get -u -v github.com/kubernetes-incubator/cri-tools
go install github.com/kubernetes-incubator/cri-tools

或者在它的release页面直接下载可执行程序,把程序拷贝到每台VPS的PATH路径中

https://github.com/kubernetes-incubator/cri-tools

之后运行kubeadm初始化环境时,也要添加–ignore-preflight-errors cri忽略错误。

配置master

在vultr上执行

1
kubeadm init --ignore-preflight-errors cri --pod-network-cidr=10.244.0.0/16

执行成功后会获得一行命令,用于将节点加入集群

1
kubeadm join --token  : --discovery-token-ca-cert-hash sha256:

安装flannel

1
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml

取消master隔离,k8s默认不会在master上部署应用,但由于我们的VPS们都是低配,还是需要master的资源

1
kubectl taint nodes --all node-role.kubernetes.io/master-

配置node

在节点上执行上面获得的kubeadm join命令,同时需要在最后追加–ignore-preflight-errors cri参数

配置kubectl

一切配置好后,可以在master上使用kubectl命令,要在本地或者其他主机上使用kubectl命令管理集群,需要把master上的/etc/kubernetes/admin.conf拷贝到相应的主机上,同时设置KUBECONFIG环境变量指向该文件,默认文件位置为$HOME/.kube/config。

最后再补一张图