本示例中的Kubernetes集群部署将基于以下环境进行。
测试使用的Kubernetes集群可由一个master主机及一个以上(建议至少两个)node主机组成,这些主机可以是物理服务器,也可以运行于vmware、virtualbox或kvm等虚拟化平台上的虚拟机,甚至是公有云上的VPS主机。
本测试环境将由master01、node01、node02和node03四个独立的主机组成,它们分别拥有4核心的CPU及4G的内存资源,操作系统环境均为仅小化部署的Ubuntu Server 20.04.1 LTS,启用了SSH服务,域名为magedu.com。此外,各主机需要预设的系统环境如下:
(1)借助于chronyd服务(程序包名称chrony)设定各节点时间精确同步;
(2)通过DNS完成各节点的主机名称解析;
(3)各节点禁用所有的Swap设备;
(4)各节点禁用默认配置的iptables防火墙服务;
注意:为了便于操作,后面将在各节点直接以系统管理员root用户进行操作。若用户使用了普通用户,建议将如下各命令以sudo方式运行。
若节点可直接访问互联网,安装chrony程序包后,可直接启动chronyd系统服务,并设定其随系统引导而启动。随后,chronyd服务即能够从默认的时间服务器同步时间。
~]# apt install chrony
~]# systemctl start chronyd.service
不过,建议用户配置使用本地的的时间服务器,在节点数量众多时尤其如此。存在可用的本地时间服务器时,修改节点的/etc/chrony/chrony.conf配置文件,并将时间服务器指向相应的主机即可,配置格式如下:
server CHRONY-SERVER-NAME-OR-IP iburst
出于简化配置步骤的目的,本测试环境使用hosts文件进行各节点名称解析,文件内容如下所示:
# kubeapi主机名作为API Server的专用接入名称,也为控制平面的高可用配置留下便于配置的余地;
172.29.1.1 master01.magedu.com master01 kubeapi.magedu.com kubeapi
172.29.1.11 node01.magedu.com node01
172.29.1.12 node02.magedu.com node02
172.29.1.13 node03.magedu.com node03
部署集群时,kubeadm默认会预先检查当前主机是否禁用了Swap设备,并在未禁用时强制终止部署过程。因此,在主机内存资源充裕的条件下,需要禁用所有的Swap设备,否则,就需要在后文的kubeadm init及kubeadm join命令执行时额外使用相关的选项忽略检查错误。
关闭Swap设备,需要分两步完成。首先是关闭当前已启用的所有Swap设备:
~]# swapoff -a
而后编辑/etc/fstab配置文件,注释用于挂载Swap设备的所有行。
另外,若确需在节点上使用Swap设备,也可选择让kubeam忽略Swap设备的相关设定。我们编辑kubelet的配置文件/etc/default/kubelet,设置其忽略Swap启用的状态错误即可,文件内容如下:
KUBELET_EXTRA_ARGS="--fail-swap-on=false"
Ubuntu和Debian等Linux发行版默认使用ufw(Uncomplicated FireWall)作为前端来简化 iptables的使用,处于启用状态时,它默认会生成一些规则以加强系统安全。出于降低配置复杂度之目的,本文选择直接将其禁用。
~]# ufw disable
~]# ufw status
提示:以下操作需要在本示例中的所有四台主机上分别进行。
首先,生成docker-ce相关程序包的仓库,这里以阿里云的镜像服务器为例进行说明:
~]# apt -y install apt-transport-https ca-certificates curl software-properties-common
~]# curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | apt-key add -
~]# add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
~]# apt update
接着,安装相关的程序包,Ubuntu 20.04上要使用的程序包名称为docker-ce:
~]# apt install docker-ce
kubelet需要让docker容器引擎使用systemd作为CGroup的驱动,其默认值为cgroupfs,因而,我们还需要编辑docker的配置文件/etc/docker/daemon.json,添加如下内容。
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn/",
"https://hub-mirror.c.163.com",
"https://registry.docker-cn.com",
"https://dockerhub.azk8s.cn",
"https://reg-mirror.qiniu.com",
"https://registry.docker-cn.com"
],
"exec-opts": ["native.cgroupdriver=systemd"]
}
配置完成后即可启动docker服务,并将其设置为随系统启动而自动引导:
~]# systemctl daemon-reload
~]# systemctl start docker.service
~]# systemctl enable docker.service
首先,在各主机上生成kubelet和kubeadm等相关程序包的仓库,这里以阿里云的镜像服务为例:
~]# apt update && apt install -y apt-transport-https curl
~]# curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
~]# cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
~]# apt update
接着,在各主机安装kubelet、kubeadm和kubectl等程序包,并将其设置为随系统启动而自动引导:
~]# apt install -y kubelet kubeadm kubectl
~]# systemctl enable kubelet
安装完成后,要确保kubeadm等程序文件的版本,这将也是后面初始化Kubernetes集群时需要明确指定的版本号。
该步骤开始尝试构建Kubernetes集群的master节点,配置完成后,各worker节点直接加入到集群中的即可。需要特别说明的是,由kubeadm部署的Kubernetes集群上,集群核心组件kube-apiserver、kube-controller-manager、kube-scheduler和etcd等均会以静态Pod的形式运行,它们所依赖的镜像文件默认来自于gcr.io这一Registry服务之上。但我们无法直接访问该服务,常用的解决办法有如下两种,本示例将选择使用更易于使用的后一种方式。
gcr.azk8s.cn/google_containers
和registry.aliyuncs.com/google_containers
等 。在运行初始化命令之前先运行如下命令单独获取相关的镜像文件,而后再运行后面的kubeadm init命令,以便于观察到镜像文件的下载过程。
~]# kubeadm config images list --image-repository registry.aliyuncs.com/google_containers
~]# kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers
而后即可进行master节点初始化。kubeadm init命令支持两种初始化方式,一是通过命令行选项传递关键的部署设定,另一个是基于yaml格式的专用配置文件,后一种允许用户自定义各个部署参数。下面分别给出了两种实现方式的配置步骤,建议读者采用第二种方式进行。
运行如下命令完成master01节点的初始化:
~]# kubeadm init \
--image-repository registry.aliyuncs.com/google_containers \
--control-plane-endpoint kubeapi.magedu.com \
--kubernetes-version=v.1.20.0 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12 \
--token-ttl=0
命令中的各选项简单说明如下:
–image-repository:指定要使用的镜像仓库,默认为gcr.io;
–kubernetes-version:kubernetes程序组件的版本号,它必须要与安装的kubelet程序包的版本号相同;
–control-plane-endpoint:控制平面的固定访问端点,可以是IP地址或DNS名称,会被用于集群管理员及集群组件的kubeconfig配置文件的API Server的访问地址;单控制平面部署时可以不使用该选项;
–pod-network-cidr:Pod网络的地址范围,其值为CIDR格式的网络地址,通常,Flannel网络插件的默认为10.244.0.0/16,Project Calico插件的默认值为192.168.0.0/16;
–service-cidr:Service的网络地址范围,其值为CIDR格式的网络地址,默认为10.96.0.0/12;通常,仅Flannel一类的网络插件需要手动指定该地址;
–apiserver-advertise-address:apiserver通告给其他组件的IP地址,一般应该为Master节点的用于集群内部通信的IP地址,0.0.0.0表示节点上所有可用地址;
–token-ttl:共享令牌(token)的过期时长,默认为24小时,0表示永不过期;为防止不安全存储等原因导致的令牌泄露危及集群安全,建议为其设定过期时长。未设定该选项时,在token过期后,若期望再向集群中加入其它节点,可以使用如下命令重新创建token,并生成节点加入命令。
kubeadm token create --print-join-command
需要注意的是,若各节点未禁用Swap设备,还需要附加选项“--ignore-preflight-errors=Swap”
,从而让kubeadm忽略该错误设定。
kubeadm也可通过配置文件加载配置,以定制更丰富的部署选项。以下是个符合前述命令设定方式的使用示例,不过,它明确定义了kubeProxy的模式为ipvs,并支持通过修改imageRepository的值修改获取系统镜像时使用的镜像仓库。
apiVersion: kubeadm.k8s.io/v1beta2
kind: InitConfiguration
localAPIEndpoint:
# 这里的地址即为初始化的控制平面第一个节点的IP地址;
advertiseAddress: 172.29.1.1
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
# 第一个控制平面节点的主机名称;
name: master01.magedu.com
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
# 版本号要与部署的目标版本保持一致;
kubernetesVersion: v1.20.0
imageRepository: registry.aliyuncs.com/google_containers
apiServer:
timeoutForControlPlane: 4m0s
# 控制平面的接入端点,我们这里选择适配到kubeapi.magedu.com这一域名上;
controlPlaneEndpoint: "kubeapi.magedu.com:6443"
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
networking:
# 要使用的域名,默认为cluster.local
dnsDomain: cluster.local
# Cluster或Service的网络地址;
serviceSubnet: 10.96.0.0/12
# Pod的网络地址,10.244.0.0/16用于适配Flannel网络插件的默认值;
podSubnet: 10.244.0.0/16
controllerManager: {}
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
# 用于配置kube-proxy上为Service指定的代理模式,默认为iptables;
mode: "ipvs"
将上面的内容保存于配置文件中,例如kubeadm-config.yaml,而后执行如下命令即能实现类似前一种初始化方式中的集群初始配置,但这里将Service的代理模式设定为了ipvs。
~]# kubeadm init --config kubeadm-config.yaml
注意:对于Kubernetes系统的新用户来说,无论使用上述哪种方法,命令运行结束后,请记录最后的kubeadm join命令输出的最后提示的操作步骤。下面的内容是需要用户记录的一个命令输出示例,它提示了后续需要的操作步骤:
# 下面是成功完成第一个控制平面节点初始化的提示信息及后续需要完成的步骤
Your Kubernetes control-plane has initialized successfully!
# 为了完成初始化操作,管理员需要额外手动完成几个必要的步骤
To start using your cluster, you need to run the following as a regular user:
# 第1个步骤提示, Kubernetes集群管理员认证到Kubernetes集群时使用的kubeconfig配置文件
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 我们也可以不做上述设定,而使用环境变量KUBECONFIG为kubectl等指定默认使用的kubeconfig;
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
# 第2个步骤提示,为Kubernetes集群部署一个网络插件,具体选用的插件则取决于管理员;
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/
# 第3个步骤提示,向集群添加额外的控制平面节点,但本文会略过该步骤,并将在其它文章介绍其实现方式。
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
# 在部署好kubeadm等程序包的其他控制平面节点上以root用户的身份运行类似如下命令,
# 命令中的hash信息对于不同的部署环境来说会各不相同;该步骤只能在其它控制平面节点上执行;
kubeadm join kubeapi.magedu.com:6443 --token zmz7gu.5imxae5ojj3t0n81 \
--discovery-token-ca-cert-hash sha256:a4351fa9065726db068b8f5c8ae83ddf3e9a6dcec1fba845b6a6acf6cf13cc95 \
--control-plane
# 第4个步骤提示,向集群添加工作节点
Then you can join any number of worker nodes by running the following on each as root:
# 在部署好kubeadm等程序包的各工作节点上以root用户运行类似如下命令
kubeadm join kubeapi.magedu.com:6443 --token zmz7gu.5imxae5ojj3t0n81 \
--discovery-token-ca-cert-hash sha256:a4351fa9065726db068b8f5c8ae83ddf3e9a6dcec1fba845b6a6acf6cf13cc95
另外,kubeadm init命令完整参考指南请移步官方文档,地址为https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/。
kubectl是kube-apiserver的命令行客户端程序,实现了除系统部署之外的几乎全部的管理操作,是kubernetes管理员使用最多的命令之一。kubectl需经由API server认证及授权后方能执行相应的管理操作,kubeadm部署的集群为其生成了一个具有管理员权限的认证配置文件/etc/kubernetes/admin.conf,它可由kubectl通过默认的“$HOME/.kube/config”的路径进行加载。当然,用户也可在kubectl命令上使用–kubeconfig选项指定一个别的位置。
下面复制认证为Kubernetes系统管理员的配置文件至目标用户(例如当前用户root)的家目录下:
~]# mkdir ~/.kube
~]# cp /etc/kubernetes/admin.conf ~/.kube/config
Kubernetes系统上Pod网络的实现依赖于第三方插件进行,这类插件有近数十种之多,较为著名的有flannel、calico、canal和kube-router等,简单易用的实现是为CoreOS提供的flannel项目。下面的命令用于在线部署flannel至Kubernetes系统之上:
~]# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
而后使用如下命令确认其输出结果中Pod的状态为“Running”,类似如下所示:
~]# kubectl get pods -n kube-system -l app=flannel
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-8gjbx 1/1 Running 0 14m
~]# kubectl get nodes
上述命令应该会得到类似如下输出:
NAME STATUS ROLES AGE VERSION
master01.magedu.com Ready control-plane,master 16m v1.20.0
下面的两个步骤,需要分别在node01、node02和node03上各自完成。
1、若未禁用Swap设备,编辑kubelet的配置文件/etc/default/kubelet,设置其忽略Swap启用的状态错误,内容如下: KUBELET_EXTRA_ARGS="–fail-swap-on=false"
2、将节点加入第二步中创建的master的集群中,要使用主节点初始化过程中记录的kubeadm join命令,并且在未禁用Swap设备的情况下,额外附加“–ignore-preflight-errors=Swap”选项;
~]# kubeadm join kubeapi.magedu.com:6443 --token zmz7gu.5imxae5ojj3t0n81 --discovery-token-ca-cert-hash sha256:a4351fa9065726db068b8f5c8ae83ddf3e9a6dcec1fba845b6a6acf6cf13cc95
在每个节点添加完成后,即可通过kubectl验正添加结果。下面的命令及其输出是在node01和node02均添加完成后运行的,其输出结果表明两个Node已经准备就绪。
~]# kubectl get nodesNAME STATUS ROLES AGE VERSIONmaster01.magedu.com Ready control-plane,master 21m v1.20.0node01.magedu.com Ready <none> 13m v1.20.0node02.magedu.com Ready <none> 48s v1.20.0node03.magedu.com Ready <none> 29s v1.20.0
到此为止,一个master,并附带有三个node的kubernetes集群基础设施已经部署完成,用户随后即可测试其核心功能。例如,下面的命令可将demoapp以Pod的形式编排运行于集群之上,并通过在集群外部进行访问:
~]# kubectl create deployment demoapp --image=ikubernetes/demoapp:v1.0
~]#kubectl scale deployment/demoapp --replicas=3
~]# kubectl create service nodeport demoapp --tcp=80:80
而后,使用如下命令了解Service对象demoapp使用的NodePort,以便于在集群外部进行访问:
~]# kubectl get svc -l app=demoapp
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEdemoapp NodePort 10.96.125.251 <none> 80:30529/TCP 103s
demoapp是一个web应用,因此,用户可以于集群外部通过“http://NodeIP:30529”这个URL访问demoapp上的应用,例如于集群外通过浏览器访问“http://172.29.3.11:30529”。
(备注: 转载自 这里)