云原生系列Kubernetes篇 部署Kubernetes集群

1,291 阅读6分钟

上一篇中我们已成功构建了应用容器,下一步学习如何将其转化为完全可信赖、可伸缩的分布式系统。实现这一目标,需要用到Kubernetes集群。现在大部分公有云都提供云端Kubernetes服务,只需几条命令就可轻松创建一个集群。对于Kubernetes新手强烈推荐使用这种方法。即便最终你计划在裸金属要上运行Kubernetes,这也一种快速上手学习Kubernetes很好的方式,之后再学习如何在物理机上进行安装。此外,管理Kubernetes集群本身是一项复杂的任务,对大部分人来说将这管理工作交给云厂商更为合理,尤其是大部分云厂商都免费提供管理服务。

当然,使用云厂商解决方案需要支付云端资源及活跃网络连接的费用。出于这种原因,本地部署更有吸引力,这时minikube工具提供了轻松在本地电脑虚拟机中运行本地Kubernetes 集群的方式。虽然这种选择不错,但minikube创建的是单节点集群,并不能展示Kubernetes完整集群的方方面面。因此推荐使用云端解决方案上手,除非无法满足你的工作场景。更新的替代方案是运行Docker嵌套Docker的集群,这样可以在单机中启动多节点集群。这一项目仍处于beta阶段,所以请注意可能会遇到一些意料外的问题。

如果读者坚持要用裸机,本系列后续会有一个关于使用树莓派构建集群的教程。其中使用kubeadm工具,可适配到其它非树莓派的主机上。

在公有云上安装Kubernetes

本文包含在三大云厂商上安装Kubernetes:亚马逊云、微软Azure和谷歌云平台。

如果选择使用云厂商管理Kubernetes,仅需安装其中的一个,在配置好集群后又不希望在其它地方安装Kubernetes的话就可以跳到Kubernetes客户端一节了。

谷歌Kubernetes引擎

Google云平台提供托管的Kubernetes-as-a-Service,称为Google Kubernetes Engine (GKE)。使用GKE,需要注册Google云平台并配置好账单信息、安装gcloud工具。

安装好gcloud之后,首先设置默认地区:

$ gcloud config set compute/zone us-west1-a

然后可以创建一个集群:

$ gcloud container clusters create kuar-cluster --num-nodes=3

这可能会耗费几分钟。集群准备完毕后,可以通过如下命令获取集群认证信息:

$ gcloud container clusters get-credentials kuar-cluster

如果遇到问题,可以在Google官方文档中找到有关创建GKE集群的完整教程。

使用Azure Kubernetes服务安装Kubernetes

Microsoft Azure在Azure容器服务中提供了托管的Kubernetes-as-a-Service。Azure容器服务最简单的方式是使用内置的Azure Cloud Shell。可以点击右上角工具栏的shell图标来激活shell:

kur3 03in01

shell有一个az工具自动安装、配置Azure所需的环境。

也可以在本地机器上安装az CLI

启动了shell之后,可以运行:

$ az group create --name=kuar --location=westus

创建完资源组,可使用如下命令创建集群:

$ az aks create --resource-group=kuar --name=kuar-cluster

这会花费几分钟。创建好集群后,可通过如下命令获取集群的认证信息:

$ az aks get-credentials --resource-group=kuar --name=kuar-cluster

如尚未安装kubectl工具,可使用如下命令安装:

$ az aks install-cli

可以在Azure官方文档中找到完整的Kubernetes安装教程。

在亚马逊云安装Kubernetes

亚马逊云提供的托管Kubernetes服务称为弹性Kubernetes服务EKS).。创建EKS集群最简单的方式是通过开源的eksctl命令行工具

安装好eksctl后,可运行如下命令来创建集群:

$ eksctl create cluster

有关安装选项的更多详情(如节点大小等),请查看命令的帮助:

$ eksctl create cluster --help

集群安装包括kubectl命令行工具相关的配置。如果读者未安装过kubectl,请参照官方文档的教程。

在本地使用minikube安装Kubernetes

如果想要在本地体验或是不希望支付云端的费用,可以使用minikube安装一个单节点集群。或者如果安装了Docker Desktop,它自带有一个Kubernetes的单机安装版。

虽然minikube(或Docker Desktop)可以很好地模拟Kubernetes集群,但它仅用于本地开发、学习和体验。因其是运行于单节点的VM中,并不提供分布式Kubernetes集群的可靠性。此外,本系列文章中讲述的一些功能需要与云服务商进行集成。这些功能在minikube下要么不能使用要么使用受限。

注:要使用minikube的需要在电脑上安装有虚拟机软件。对Linux和macOS,通常使用VirtualBox。而Windows中的默认选项是Hyper-V虚拟机。在使用minikube之前应确保已安装了虚拟机软件。

可在GitHub上找到minikube。其中有Linux、macOS和Windows的二进制文件供下载。安装好minikube之后,可使用如下命令创建一个本地集群:

$ minikube start

这会创建一个本地虚拟机,带有Kubernetes,同时创建一个本地kubectl配置指向该集群。前面已提到,这个集群为单节点,所以虽然可用,但与大部分Kubernetes生产环境部署有一些分别。

使用完集群后,可以通过如下命令停用VM:

$ minikube stop

如需删除集群,可运行:

$ minikube delete

在Docker中运行Kubernetes

还有一种运行Kubernetes的方式,不久前开发的,使用Docker容器来代替虚拟机模拟多个Kubernetes节点。kind项目提供了一种在Docker中启动和管理测试集群的体验(kind表示Kubernetes IN Docker)。kind仍处于开发中((pre 1.0)),但已广泛用于快速构建Kubernetes进行测试。

在各种平台上如何安装请参见kind官方网站 。安装完成后,只需运行如下命令进行创建:

$ kind create cluster --wait 5m 
$ export KUBECONFIG="$(kind get kubeconfig-path)" 
$ kubectl cluster-info 
$ kind delete cluster

Kubernetes客户端

官方的Kubernetes客户端是kubectl:一款与Kubernetes API进行交互的命令行工具。kubectl可用于管理大部分Kubernetes对象,比如Pods、副本集和服务。kubectl也可用于查看和验证集群的整体健康状态。

我们将使用kubectl工具来查看刚刚创建的集群。

查看集群状态

可通过如下命令来查看集群的版本:

$ kubectl version

这会显示两个版本:一个是本地kubectl工具的版本,还有一个是Kubernetes API服务端版本。

注:如果两者版本不一致也不必担心。Kubernetes工具对Kubernetes API各版本具有向前及向后兼容,只要工具和集群的小版本保持一致且不在老集群中使用新功能就没有问题。Kubernetes遵循语义化版本规范,小版本是中间的那个数(如1.18.2中的18)。保障在支持版本范围内即可。

现在已可与Kubernetes集群间进行通讯,下面就更深入地查看集群功能。

首先对集群进行简单的诊断。这种方式可验证集群整体上是否健康:

$ kubectl get componentstatuses

输出如下:

NAME                 STATUS    MESSAGE              ERROR
scheduler            Healthy   ok
controller-manager   Healthy   ok
etcd-0               Healthy   {"health": "true"}

注:因为Kubernetes在不断的迭代升级,所以kubectl命令的输出可能会变化。如果你的输出结果和上面不完全一样请不必担心。

这里可以看到Kubernetes集群的组成部分。controller-manager负责运行规范集群内行为各种控制器,例如,确保服务的副本可用且健康。scheduler负责将不同的Pod放到集群的各节点上。最后,etcd服务用于所有API对象所进行的存储。

列举Kubernetes节点

接下来,我们列举出集群中的所有节点:

$ kubectl get nodes
NAME     STATUS   ROLES                  AGE     VERSION
kube0    Ready    control-plane,master   45d     v1.22.4
kube1    Ready    <none>                 45d     v1.22.4
kube2    Ready    <none>                 45d     v1.22.4
kube3    Ready    <none>                 45d     v1.22.4

可以看到4个启动了45天的节点。在Kubernetes中,节点分隔成包含API服务、调度器等容器的管理集群的control-plane节点,还有容器所运行的worker节点。Kubernetes通常会将任务调度到control-plane节点来确保工作负载不会损害集群的整体操作。

可以使用kubectl describe命令来获取具体节点的详细信息,如kube1

$ kubectl describe nodes kube1

首先可以看到有关节点的基本信息:

Name:                   kube1
Role:
Labels:                 beta.kubernetes.io/arch=arm
                        beta.kubernetes.io/os=linux
                        kubernetes.io/hostname=node-1

可以看到该节点运行于Linux操作系统和ARM处理器之上。

接着,我们看到kube1本身的一些信息(为保持简洁删去了日期信息):

Conditions:
  Type                 Status  ...   Reason                       Message
 -----                 ------        ------                       -------
  NetworkUnavailable   False   ...   FlannelIsUp                  Flannel...
  MemoryPressure       False   ...   KubeletHasSufficientMemory   kubelet...
  DiskPressure         False   ...   KubeletHasNoDiskPressure     kubelet...
  PIDPressure          False   ...   KubeletHasSufficientPID      kubelet...
  Ready                True    ...   KubeletReady                 kubelet...

这些状态表明节点有充足的磁盘和内存空间,并向Kubernetes主节点报告其为健康的。接下来为有关机器容量的信息:

Capacity:
 alpha.kubernetes.io/nvidia-gpu:        0
 cpu:                                   4
 memory:                                882636Ki
 pods:                                  110
Allocatable:
 alpha.kubernetes.io/nvidia-gpu:        0
 cpu:                                   4
 memory:                                882636Ki
 pods:                                  110

再下来是有关节点软件的信息,包括所运行的Docker的版本、Kubernetes版本及Linux内核版本等:

System Info:
  Machine ID:                 44d8f5dd42304af6acde62d233194cc6
  System UUID:                c8ab697e-fc7e-28a2-7621-94c691120fb9
  Boot ID:                    e78d015d-81c2-4876-ba96-106a82da263e
  Kernel Version:             4.19.0-18-amd64
  OS Image:                   Debian GNU/Linux 10 (buster)
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  containerd://1.4.12
  Kubelet Version:            v1.22.4
  Kube-Proxy Version:         v1.22.4
PodCIDR:                      10.244.1.0/24
PodCIDRs:                     10.244.1.0/24

最后是有关当前节点上所运行的Pod的信息:

Non-terminated Pods:            (3 in total)
  Namespace   Name        CPU Requests CPU Limits Memory Requests Memory Limits
  ---------   ----        ------------ ---------- --------------- -------------
  kube-system kube-dns...  260m (6%)    0 (0%)     140Mi (16%)     220Mi (25%)
  kube-system kube-fla...  0 (0%)       0 (0%)     0 (0%)          0 (0%)
  kube-system kube-pro...  0 (0%)       0 (0%)     0 (0%)          0 (0%)
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.
  CPU Requests  CPU Limits      Memory Requests Memory Limits
  ------------  ----------      --------------- -------------
  260m (6%)     0 (0%)          140Mi (16%)     220Mi (25%)
No events.

通过输出信息可以看到节点中的Pod(如为集群提供DNS服务的kube-dns Pod),每个Pod向节点请求的CPU、内存以及整体资源。值得一提的是Kubernetes同时跟踪机器上所运行的每个Pod对资源的请求和上限。有关请求和上限会在Pods一文中进行详细讲解,但总的来说,每个Pod所请求的资源节点可保留,而Pod的上限资源则是Pod所能消耗的最大量。Pod的上限资源可大于请求量,额外的资源在最佳性能的基础上进行提供。但并不保证在节点中会提供。

集群组成

Kubernetes有意思的一个方面是组成集群的很多部分实际上是使用Kubernetes自身部署的。我们接下来会讨论其中的一部分。这些组成部分使用到一些概念要在后续文章中才会介绍到。所有这些部分都运行在kube-system命名空间中。

Kubernetes代理

Kubernetes代理负责将网络流量路由到集群中的负载均衡服务。完成这一任务,代理必须运行在集群中的每个节点上。Kubernetes有一个名为DaemonSet的对象,我们会在DaemonSets一文中进行讨论,在很多集群中都使用到了它。如果集群使用DaemonSet来运行Kubernetes代理,可通过如下命令查看代理:

$ kubectl get daemonSets --namespace=kube-system kube-proxy
NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR
kube-proxy   5         5         5       5            5           ...   45d

按照集群的配置,kube-proxy的DaemonSet可能使用其它的名称,或是完全不使用DaemonSet。但不论怎样,每个节点中都需要运行kube-proxy

Kubernetes DNS

Kubernetes还运行着一个DNS服务,它为集群中所定义的服务提供命名和服务发现。这一DNS服务在集群上以副本服务运行。DNS服务以管理着其它副本的Kubernetes部署运行(名称可能是coredns等)。

$ kubectl get deployments --namespace=kube-system core-dns
NAME       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
core-dns   1         1         1            1           45d

还有一个为DNS服务执行负载均衡的Kubernetes服务:

$ kubectl get services --namespace=kube-system core-dns
NAME       CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
core-dns   10.96.0.10   <none>  53/UDP,53/TCP   45d

这表示集群的DNS服务地址为10.96.0.10。如果登录到集群中的容器,会发现它写入了容器中的 /etc/resolv.conf 文件。

Kubernetes UI

如果希望用图形界面可视化显示集群,大部分云厂商都提供了可视化的GUI。如果云厂商未提供UI,而你又希望使用图形化界面,社区提供了相关界面可供安装。参见官方文档了解如何为这些集群安装后台界面。也可以使用Visual Studio Code等开发环境的扩展来查看集群的状态。

小结

希望至此读者已可以启动自己的Kubernetes集群,并可使用一些命令来查看所创建集群的信息。接下来我们会花大量时间来了解Kubernetes集群的命令行,以及掌握kubectl工具。后续文章中读者会使用kubectl来查看Kubernetes API中的各种对象。