2.2 部署云部分——Kubernetes

Kubernetes是一个全新的基于容器技术的分布式架构的云部署方案,是Google开源的容器集群管理系统,为部署容器化的应用提供资源调度、服务发现和动态伸缩等一系列完整功能,提高了大规模容器集群管理的便捷性。本书将Kubernetes作为边缘计算系统的云部分解决方案。

本节会对Kubernetes的部署方式进行梳理,主要对Kubernetes相关的容器运行时部署、Kubernetes的学习环境部署、Kubernetes的生产环境部署三方面进行梳理。

2.2.1 Kubernetes相关的容器运行时部署

Kubernetes通过容器运行时以Pod形式运行容器,官方默认支持Docker容器运行时。除此之外,Kubernetes支持的容器运行时还包括Containerd、Cri-o、Frakti等,具体如表2-1所示。

表2-1 Kubernetes支持的容器运行时

042-01

从Kubernetes支持的容器运行时列表,我们可知:

1)Docker和Containerd在实现原理上是相同的,只是Containerd裁剪了Docker原有的一些富功能。

2)Cri-o为了追求轻量级和简洁,对CRI和OCI重新进行了实现。

3)Frakti的目的是实现容器运行时的强隔离,基于Hypervisors实现容器运行时,使每个容器具有独立的操作系统。

目前,业界普遍使用的容器运行时是Docker。下面详细说明部署Docker的相关步骤和注意事项。

本书使用的操作系统都是CentOS 7+,所以部署Docker的步骤也是针对CentOS 7+操作环境。

1)安装需要的依赖包,命令如下:

# yum install yum-utils device-Mapper-persistent-data lvm2

2)增加安装Docker所需的Repository,命令如下:

# yum-config-manager --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo

3)安装指定版本的Docker,命令如下:

# yum update && yum install containerd.io-1.2.10  docker-ce-19.03.4  docker-ce-cli-19.03.4

4)设置Docker的配置文件。

①创建配置文件目录:

#mkdir /etc/docker

②设置Docker配置文件:

# cat > /etc/docker/daemon.json <<EOF
{
    "exec-opts": ["native.cgroupdriver=systemd"],
    "log-driver": "json-file",
    "log-opts": {
        "max-size": "100m"
    },
    "storage-driver": "overlay2",
    "storage-opts": [
        "overlay2.override_kernel_check=true"
    ]
}
EOF

5)启动Docker,命令如下:

# mkdir -p /etc/systemd/system/docker.service.d
# systemctl daemon-reload
# systemctl restart docker

至此,Docker容器运行时就安装成功了。接下来,分析Docker配置相关的注意事项。

Docker的相关配置在/etc/docker/daemon.json文件中,包括设置私有仓库、DNS解析服务器、Docker运行时使用的路径、镜像加速地址、日志输出、Cgroup Driver、Docker主机的标签等。本节重点介绍Cgroup Driver的设置。

Linux操作系统的发行版本中将Systemd作为其初始化系统,并初始化进程生成一个root控制组件。Systemd与Cgroup集成紧密,为每个进程分配Cgroup。Docker容器运行时默认的Cgroup管理器是Cgroupfs,也就是说Kubelet使用Cgroupfs来管理Cgroup。这样就造成在同一台主机上同时使用Systemd和Cgroupfs两种Cgroup管理器来对Cgroup进行管理。

Cgroup用来约束分配给进程的资源。单个Cgroup管理器能够简化分配资源的视图,并且默认情况下管理可用资源和使用中的资源时使用一致的视图。当有两个Cgroup管理器时,最终产生两种视图。我们已经看到某些案例中的节点配置让Kubelet和Docker使用Cgroupfs管理器,而节点上运行的其余进程则使用Systemd,这类节点在资源压力下会变得不稳定。

更改设置,令Docker和Kubelet使用Systemd作为Cgroup驱动,以便系统更稳定。请注意在/etc/docker/daemon.json文件中设置native.cgroupdriver=systemd选项,具体如下:

# vi /etc/docker/daemon.json

{
    ...
    "exec-opts": ["native.cgroupdriver=systemd"],
    ...
}

2.2.2 Kubernetes的学习环境部署

本节对部署Kubernetes学习环境的相关工具进行梳理,如表2-2所示。

表2-2 搭建Kubernetes学习环境的工具

044-01

从搭建Kubernetes学习环境的工具列表可知,Minikube、Kind都可以搭建Kubernetes的学习环境,但两者所需要的依赖和原理各不相同。Minikube和Kind都是用于搭建Kubernetes学习环境的工具,二者的安装步骤和使用方法相对比较简单。接下来,笔者对二者的安装步骤和使用方法进行详细说明。

1. Minikube的安装与使用

Minikube是一种可以在本地轻松运行Kubernetes的工具。其首先通过在物理服务器或计算机上创建虚拟机,然后在虚拟机(VM)内运行一个单节点Kubernetes集群。该Kubernetes集群可以用于开发和测试Kubernetes的最新版本。

下面对Minikube的安装和使用进行说明。本书使用的操作系统都是CentOS 7+,所以本节安装Minikube的步骤也是针对CentOS 7+操作环境。

(1)安装Minikube

1)检查对虚拟化的支持,命令如下:

# grep -E --color 'vmx|svm' /proc/cpuinf

2)安装Kubectl。

推荐在Kubernetes的GitHub上的发布主页下载pre-built的二进制压缩包并进行安装。

进入Kubernetes的GitHub仓库上的发布主页,找到需要下载的Kubernetes版本,比如本节要下载的版本是v1.16.6,如图2-2所示。

045-01

图2-2 Kubernetes v1.16.6发布版本

点击CHANGELOG-1.16.md进入二进制文件下载列表,复制服务二进制压缩包下载地址,使用wget命令下载服务二进制压缩包,命令如下:

# wget https://dl.k8s.io/v1.16.6/Kubernetes-server-linux-amd64.tar.gz

下载Kubernetes具体如图2-3所示。

046-01

图2-3 下载Kubernetes

如图2-4所示,解压kubernetes-server-linux-amd64.tar.gz,命令如下:

# tar -zxvf kubernetes-server-linux-amd64.tar.gz
046-02

图2-4 解压Kubernetes

由图2-4可知,Kubectl在kubernetes/server/bin下,只需将其放入/usr/bin下即可:

#cp kubernetes/server/bin/kubectl /usr/bin

3)安装KVM。

在确认所在的操作系统支持虚拟机的前提下,通过如下步骤安装KVM及相关依赖。

更新安装KVM所需的源,命令如下:

#yum -y update && # yum install epel-release 

安装KVM及其所需的依赖包,命令如下:

#  yum install qemu-kvm libvirt libvirt-python libguestfs-tools virt-install

设置libvirtd开机自动启动,命令如下:

# systemctl enable libvirtd && systemctl start libvirtd

4)安装Minikube,命令如下:

# curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-1.6.2.rpm \
&&  rpm -ivh minikube-1.6.2.rpm

(2)使用Minikube

1)启动一个本地单节点集群,命令如下:

# minikube start --vm-driver=<driver_name>

2)检查集群状态,命令如下:

# minikube status

3)使用集群部署应用,命令如下:

# kubectl create deployment hello-minikube --image={image-name}

至此,我们已经成功安装了Minikube,并通过Minikube创建了一个本地单节点的Kubernetes集群。

2. Kind的安装与使用

Kind是一种使用Docker容器节点(该容器可用于运行嵌套容器,在该容器里可以使用Systemd运行、管理Kubernetes的组件)运行本地Kubernetes集群的工具。Kind主要是为了测试Kubernetes本身而设计的,可用于本地开发或持续集成。

下面对Kind的安装和使用进行说明。

(1)安装Kind

由于安装Kind需要Go语言环境,使用Kind运行本地Kubernetes集群需要Docker容器运行时,因此在安装Kind之前需要安装Go和Docker。

1)安装Go,命令如下:

# yum -y install Go

参考“部署Docker”小节来部署Docker容器运行时。

2)安装Kind,命令如下:

#GO111MODULE="on" go get sigs.k8s.io/kind@v0.7.0

上述步骤会将Kind安装到GOPATH/bin目录下。为了使用方便,建议将其在/etc/profile中进行追加设置,命令如下:

# vi /etc/profile
export PATH=$GOPATH/bin:$PATH

使在/etc/profile中设置的环境变量立即生效,命令如下:

#source /etc/profile

(2)使用Kind

1)使用Kind创建Kubernetes集群(如图2-5所示),命令如下:

# kind create cluster
048-01

图2-5 使用Kind创建集群

2)检查、使用Kind部署的集群(如图2-6所示),命令如下:

#kubectl get pods --all-namespaces
049-01

图2-6 检查使用Kind部署的集群状态

至此,我们已经成功安装了Kind,并通过Kind创建了一个本地单节点的Kubernetes集群。

2.2.3 Kubernetes的生产环境部署

本节对部署Kubernetes生产环境的相关工具进行梳理,具体如表2-3所示。

表2-3 搭建Kubernetes生产环境的工具

049-02

从表2-3可知,Kops、KRIB有明显局限性,因为Kops主要在AWS上进行自动化部署Kubernetes集群;KRIB主要在裸机上进行自动化部署Kubernetes集群。Kubeadm和Kubespray可以在多种平台上搭建Kubernetes的生产环境。Kubespray从v2.3开始支持Kubeadm,也就意味着Kubespray最终还是通过Kubeadm自动化部署Kubernetes集群。

本节首先对使用Kubeadm的注意事项进行说明,然后具体介绍如何安装和使用Kubeam。Kubeadm支持的平台和资源要求如表2-4所示。

表2-4 Kubeadm支持的平台和资源要求

050-01

(1)使用Kubeadm的注意事项

1)确保集群中所有主机网络可达。

在集群中不同主机间通过ping命令进行检测,命令如下:

# ping {被检测主机ip}

2)确保集群中所有主机的Hostname、MAC Address和product_uuid唯一。

查看主机Hostname命令:#hostname

查看MAC Address命令:#ip link或者#ifconfig -a

查看product_uuid命令:#/sys/class/dmi/id/product_uuid

3)IPTables后端不用nftable,命令如下:

# update-alternatives --set iptables /usr/sbin/iptables-legacy

4)Kubernetes集群中主机需要打开的端口如表2-5所示。

表2-5 Kubernetes集群中主机需要打开的端口

050-02

由表2-5可知,上述需要打开的端口都是Kubernetes默认打开的端口。我们也可以根据需要对一些端口进行单独指定,比如Kubernetes-api-server默认打开的端口是6443,也可以指定打开其他与现有端口不冲突的端口。

5)在Kubernetes集群的所有节点上关闭Swap分区,命令如下:

#swapoff -a

(2)安装Kubeadm

安装Kubeadm有两种方式,即通过操作系统的包管理工具进行安装,从Kubernetes的GitHub仓库的发布主页下载Pre-build的二进制压缩包进行安装。下面对这两种安装方式进行详细说明。

1)通过操作系统的包管理工具安装Kubeadm。

①在需要安装Kubeadm的节点上设置安装Kubeadm需要的仓库,命令如下:

#cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[Kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/Kubernetes-el7-x86_64
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

②将SELINUX设置为permissive,命令如下:

#setenforce 0
#sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

③安装Kubeadm、Kubelet、Kubectl,命令如下:

#yum install -y Kubelet kubeadm kubectl --disableexcludes=Kubernetes

④将Kubelet设置为开机自启动,命令如下:

#systemctl enable --now Kubelet

2)通过在Kubernetes GitHub仓库的发布主页下载pre-build的二进制压缩包来安装Kubeadm。

(3)使用Kubeadm

使用Kubeadm可以部署Kubernetes单节点集群、Kubernetes单控制节点集群和Kubernetes高可用集群。下面将详细说明部署这3种集群的具体步骤。

1)部署Kubernetes单节点集群。

使用Kubeadm部署Kubernetes单节点集群,其实是在一个节点使用Kubeadm部署Kubernetes的控制平面,然后对该节点进行设置,使其能够运行应用负载。

①查看使用Kubeadm部署Kubernetes单节点集群时所需的镜像,命令如下:

#kubeadm config images list

所需镜像如图2-7所示。

052-01

图2-7 使用Kubeadm部署Kubernetes单节点集群所需镜像

这些镜像都是以k8s.gcr.io*开头的。一般情况下,Kubeadm无法正常下载这些镜像,需要提前准备好。获取这些镜像的方法不止一种,笔者建议通过DockerHub获得。

②使用Kubeadm创建Kubernetes单节点集群,在创建的过程中会用到图2-10列出的所有镜像,命令如下:

#kubeadm init {args}

在args中一般只需指定--control-plane-endpoint、--pod-network-cidr、--cri-socket、--apiserver-advertise-address参数。这些参数的具体作用如下。

  • --control-plane-endpoint:指定搭建高可用Kubernetes集群时,多个控制平面共用的域名或负载均衡IP。
  • --pod-network-cidr:指定Kubernetes集群中Pod所用的IP池。
  • --cri-socket:指定Kubernetes集群使用的容器运行时。
  • --apiserver-advertise-address:指定kube-api-server绑定的IP地址——既可以是IPv4,也可以是IPv6。

我们可以根据具体情况指定以上参数。

③根据non-root用户和root用户,设置Kubectl使用的配置文件。

  • 若是non-root用户,设置命令如下:
$mkdir -p $HOME/.kube
$sudo cp -i /etc/Kubernetes/admin.conf $HOME/.kube/config
$sudo chown $(id -u):$(id -g) $HOME/.kube/config
  • 若是root用户,设置命令如下:
export KUBECONFIG=/etc/Kubernetes/admin.conf

为了方便,我们也可以将KUBECONFIG设置成自动生效的系统环境变量,命令如下:

# vim /etc/profile

export KUBECONFIG=/etc/Kubernetes/admin.conf

④安装Pod所需的网络插件,命令如下:

# kubectl apply -f https://docs.projectCalico.org/v3.8/manifests/Calico.yaml

本节使用的网络插件是Calico,我们也可以根据具体需求选择其他的网络插件,比如Flannel、Weave Net、Kube-router等。

至此,一个完整的Kubernetes控制节点就搭建完成了,但这还不能算一个完整单节点集群,因为该控制节点默认不接受负载调度。要使其能够接受负载调度,需要进行如下设置:

# kubectl taint nodes --all node-role.Kubernetes.io/master-

2)部署Kubernetes单控制节点集群。

Kubernetes单控制节点集群是指该Kubernetes集群只有一个控制节点,但可以有不止一个计算节点。部署该集群只需在部署Kubernetes单节点集群中安装Pod所需的网络插件之后,将计算节点加入该控制节点,具体命令如下:

ubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>

使用kubeadm join命令将多个计算节点加入已经部署成功的控制节点,与控制节点组成一个单控制节点的Kubernetes集群。

3)部署Kubernetes高可用集群。

Kubeadm除了可以部署Kubernetes单节点集群和Kubernetes单控制节点集群外,还可以部署Kubernetes高可用集群。Kubeadm部署Kubernetes高可用集群的架构包含两种,即Etcd集群与Kubernetes控制节点集群一起部署的Kubernetes高可用集群,以及Etcd集群与Kubernetes控制节点集群分开部署的Kubernetes高可用集群,具体架构如图2-8和图2-9所示。

054-01

图2-8 Etcd集群与Kubernetes控制节点集群一起部署

055-01

图2-9 Etcd集群与Kubernetes控制节点集群分开部署

由图2-8和图2-9可知,Kubernetes集群高可用即Kubernetes集群中Master节点和Etcd集群高可用。部署Kubernetes高可用集群是面向生产环境的,需要的资源比较多,部署步骤也相对比较复杂,限于篇幅本书就不展开说明了,感兴趣的读者可以参考Kubernetes官网进行实践。