部署 Kubernetes 集群
Kubernetes 集群部署的方式有很多选择,简单的可以基于 kubeadm 一类的部署工具运行几条命令即可实现,而复杂的则可以使从零开始手动构建集群环境。
kuberadm 部署工具
kubeadm 是 Kubernetes 项目自带的集群构建工具,它负责构建一个最小化的集群以及将其启动等必要的基本步骤,简单来讲,kubeadm 是 Kubernetes 集群全生命周期的管理工具,可用于实现集群的部署、升级/降级及拆除。在部署操作中,kubeadm 尽关心如何初始化并启动集群,余下的其他操作,例如安装 Kubernetes Dashboard、监控系统、日志系统等必要的附加组件则不再其考虑范围之内,需要自行部署。
kubeadm 集成了 以下工具程序:
kubeadm init
: 工具用于集群初始化,其核心功能是部署 Master 节点的各个组件。
kubeadm join
:工具用于将Node节点加入到指定集群中。
kubeadm token
:可于集群构建后管理用于加入集群时使用的认证临牌 (token)。
kubeadm reset
:命令的功能则是删除集群构建过程中生成的文件以重置回初始状态。
kubeadm 还支持管理初始引导认证令牌 (Bootstrap Token),完成待加入的新节点首次联系 API Server 时的身份认证(基于共享密钥)。另外,他们还支持管理集群版本的升降级操作。
集群运行模式
Kubernetes 集群支持三种运行模式:
1)独立组件模式
:系统各个组件直接以守护进程的方式运行于节点之上,各组件之间相互协作构成集群。
2)静态 Pod 模式
:除 kubelet 和 Docker 之外的其他组件 (如 etcd、kube-apiserver、kube-controller-mangeer和 kube-scheduler等)都是以静态 Pod 对象运行于 Master 主机之上。
3)自托管模式
:这种模式是 Kubernetes的 自托管模式(self-hosted),它类似于第二种方式,将除了 kubelet 和 Docker 之外的其他组件运行为集群之上的 Pod 对象,但不同的是,这些 Pod 对象托管运行在 Kubernetes 集群自身之上受控于 DaemonSet 类型的控制器。而非静态的 Pod 对象。
使用 kubeadm 部署的 Kubernetes 集群可运行为第二种或者第三种模式,默认为静态 Pod 对象模式,需要使用自托管模式时,kubeadm init 命令使用 "--features-gates=selfHosting
",选项即可,第一种模式集群的构建需要将各组件运行于系统之上的独立守护进程中,期间需要用到的证书及 Token 等认证信息也需要手动生成,过程繁琐且极易出错;若有必要用到,则建议使用 GitHub 上的项目辅助进行。
准备集群环境
如下图所示,该集群由一个 Master 主机和三个 Node 主机组成,基于 kubeadm 部署,除了kubelet 和 Docker 之外的其他集群组件都运行于 Pod 对象中。
角色 | IP地址 | 主机名 | 系统版本 | 内核版本 | docker版本 |
---|---|---|---|---|---|
master | 192.168.31.245 | master | CentOS 7.6 | 3.10.0-957.el7.x86_64 | 18.09.9 |
node1 | 192.168.31.241 | node1 | CentOS 7.6 | 3.10.0-957.el7.x86_64 | 18.09.9 |
node2 | 192.168.31.242 | node2 | CentOS 7.6 | 3.10.0-957.el7.x86_64 | 18.09.9 |
设置部署Kubernetes必要条件
所有机器操作
安装Kubernetes至少需要2核2G以上
1.关闭防火墙
1 2 |
systemctl stop firewalld && systemctl disable firewalld |
2.关闭SELinux
1 2 3 4 |
setenforce 0 sed -i 's/SELINUX=permissive/SELINUX=disabled/' /etc/sysconfig/selinux sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config |
3.时钟校对
1 2 3 4 5 6 7 8 9 |
yum install ntpdate.x86_64 -y timedatectl set-timezone Asia/Shanghai /sbin/ntpdate ntp2.aliyun.com;/sbin/hwclock -w cat >> /var/spool/cron/root << EOF #Clock synchronization 00 00 * * * /sbin/ntpdate ntp2.aliyun.com;/sbin/hwclock -w EOF |
4.修改内核参数
1 2 3 4 5 6 7 |
cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF modprobe br_netfilter sysctl --system |
5.Swap交换分区
kubernetes自1.8版本起强制要求关闭系统上的交换分区(swap),否则无法启动,如果系统不足或者有其它重要进程使用交换分区时那么也是可以保留交换分区。
1)如果你要禁用交换分区
1 2 3 |
swapoff -a sed -i 's/.*swap.*/#&/' /etc/fstab |
2)如果你要启用交换分区
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
创建交换区原则: 1.创建的swap交换区大小应该大于实际物理内存的容量大小,但是不要过大,以免造成硬盘空间浪费。 2.如果内存IO请求频繁,而单一swap交换区IO队列等待时间过长的话,可以多创建几个swap交换区。 3.原则上优先在IO速度最快的设备上创建。 #创建swap交换分区 #通常创建物理内存2~2.5倍大小的文件作为交换区。 dd if=/dev/zero of=/swap bs=1G count=8 #使用mkswap格式化文件为swap文件系统 #-f 使用文件作为swap交换区 mkswap -f /swap #启用刚才创建的Swap文件 swapon /swap #如果有必要可以设置开机自动启用swap文件交换区,修改/etc/fstab,增加一行 echo '/swap swap swap defaults 0 0' >> /etc/fstab |
6.安装docker
1 2 3 4 5 |
yum install yum-utils device-mapper-persistent-data lvm2 -y yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo yum install docker-ce-18.09.9-3.el7 -y systemctl enable docker && systemctl start docker |
7.操作完成后建议重启下机器
1 2 |
reboot |
master安装 kubeadm kubelet kubectl
master操作
由于官方Kubernetes镜像源在google,因各种不可描述原因,这里使用阿里云yum源
1.添加阿里云yum源
1 2 3 4 5 6 7 8 9 10 |
cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF |
2.安装kubeadm、kubectl、kubelet
1 2 3 |
#指定1.16.0版本进行安装 yum install kubectl-1.16.0-0 kubeadm-1.16.0-0 kubelet-1.16.0-0 -y |
3.查看kubelet安装了哪些文件
1 2 3 4 5 6 7 8 9 10 11 |
[root@master ~]# rpm -ql kubelet /etc/kubernetes/manifests /etc/sysconfig/kubelet /usr/bin/kubelet /usr/lib/systemd/system/kubelet.service [root@master ~]# rpm -ql kubeadm /usr/bin/kubeadm /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf [root@master ~]# rpm -ql kubectl /usr/bin/kubectl |
4.配置kubelet(开启swap分区操作)
如果你禁用了swap分区,那么这步骤直接略过即可,如果开启了swap分区,那么需操作以下来对Kubernetes忽略禁用swap限制
1 2 3 4 |
cat <<EOF > /etc/sysconfig/kubelet KUBELET_EXTRA_ARGS="--fail-swap-on=false" EOF |
5.设置kubelet服务
配置文件修改完成后,需要设定kuberlet服务开机自动启动,这也是Kubeadm的强制要求
1 2 |
systemctl enable kubelet |
node安装 kubeadm kubelet kubectl
node操作
1.添加阿里云yum源
1 2 3 4 5 6 7 8 9 10 |
cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF |
2.安装kubeadm、kubectl、kubelet
1 2 |
yum clean all && yum makecache yum install kubectl-1.16.0-0 kubeadm-1.16.0-0 kubelet-1.16.0-0 -y |
3.配置kubelet(开启swap分区操作)
如果你禁用了swap分区,那么这步骤直接略过即可,如果开启了swap分区,那么需操作以下来对Kubernetes忽略禁用swap限制
1 2 3 4 |
cat <<EOF > /etc/sysconfig/kubelet KUBELET_EXTRA_ARGS="--fail-swap-on=false" EOF |
4.设置kubelet服务
配置文件修改完成后,需要设定kuberlet服务开机自动启动,这也是Kubeadm的强制要求
1 2 |
systemctl enable kubelet |
集群初始化
Master节点操作
Master和各Node的Docker及kubelet配置完成后,便可以在master节点上执行 "kubeadm init”命令进行集群初始化。
初始化过程中 Kubernetes会下载管理节点所用到的 6 个 docker镜像分别为 Kubernetes 的各个组件,以 静态 Pod 的方式运行于容器之中。
kubeadm init
命令支持两种初始化方式:
1)通过命令行选项传递关键的参数设定
2)基于 yaml 格式的专用配置文件设定更详细的配置参数
这里演示通过第一种方法进行初始化。
1.Master 初始化
1 2 3 4 5 6 7 8 9 10 |
[root@-master ~]# kubeadm init \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.16.0 \ --pod-network-cidr=10.244.0.0/16 \ --service-cidr=10.96.0.0/12 \ --apiserver-advertise-address=0.0.0.0 \ --ignore-preflight-errors=Swap \ --token-ttl 30m |
参数解释:
--image-repository
:初始化过程中会去docker仓库拉去镜像,默认指定的为docker hub,所以在此使用–image-repository参数指定阿里云镜像。--kubernetes-version
:指定正在使用的 Kubernetes 程序组件的版本号,需要与 kubelet 的版本号相同。--pod-network-cidr
:Pod 网络的地址范围,其值为 CIDR 格式的网络地址,使用 flannel 网络插件时,其默认地址为 10.244.0.0/16。--service-cidr
:Service 的网络地址范围,其值为 CIDR 格式的网络地址,默认地址为 10.96.0.0/12。--apiserver-advertise-address
:API Server 通告给其它组件的IP地址,一般为 Master 节点的IP地址,0.0.0.0 标识节点上所有可用的地址。ignore-preflight-errors
:忽略哪些运行时的错误信息,其值为 Swap 时,表示忽略因 swap 未关闭而导致的错误。--token-ttl
:token令牌自动删除时间,默认为24小时,指定为 0 表示永不过期,指定单位可以使 秒s 分m 时h,在node加入Kubernetes集群时需要指定token。
初始化过程中到 kubeadm config images pull
会稍有卡顿
2.初始化完成返回如下
3.设定 kubectl 配置文件
kubectl 是执行 kubernetes 集群管理的核心工具。默认情况下,kubectl会从当前用户主目录(保存于环境变量HOME中的值)中隐藏目录 .kube 下名为 config 的配置文件中读取配置信息,包括要接入 Kubernetes 集群、以及用于集群认证的证书或令牌等信息,集群初始化时,kubeadm 会自动生成一个用于此类功能的配置文件 /etc/kubernetes/admin.conf
,将它复制为用户的 $HOME/.kube.config
即可直接使用。
直接复制以上绿色框画中的命令即可
1 2 3 4 |
[root@master ~]# mkdir -p $HOME/.kube [root@master ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config [root@master ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config |
目前,一个 Kubernetes Master 节点已经配置完成。
使用 kubectl get nodes
可以获取到集群节点相关状态信息,如果命令结果Master节点状态为 “NotReady(未就绪)”,这是因为集群中尚未安装网络插件所致,网络插件安装完成后即为 "Ready(就绪)" 状态。
1 2 3 4 |
[root@master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION master NotReady master 9m23s v1.16.0 |
如果你的配置或输出结果有误,则可以通过 kubeadm reset
命令重新进行集群初始化
部署网络插件
Master操作
为 Kubernetes 提供 Pod 网络插件的有很多,目前最流行的是 flannel
和 Calico
。相比较来说,flannel
以其简单、易部署、易用性广受欢迎。
基于 kubeadm 部署时,flannel 同样运行为 Kubernetes 集群的附件,以 Pod 的形式部署运行于每个集群节点上以接受 Kubernetes 集群管理。部署方式可以获取其资源清单于本地而后部署集群中,也可以直接在线进行应用部署。部署命令是 kubectl apply
或 kubectl create
。
1.flannel 网络插件部署
1 2 |
[root@master ~]# wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml |
这个文件要用到vpn才能下载,我已经为大家准备好了 点击下载kube-flannel.yml
手动下载kube-flannel.yml
文件后,修改其地址quay.io
为quay-mirror.qiniu.com
,因quay.io
为国外地址,国内访问超级慢,如果你没有正确的上网,那么必定拉不下 flannel
镜像,所以这里把 quay.io
改为国内地址 quay-mirror.qiniu.com
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[root@master ~]# sed -i 's/quay.io/quay-mirror.qiniu.com/g' kube-flannel.yml [root@master ~]# kubectl apply -f kube-flannel.yml podsecuritypolicy.policy/psp.flannel.unprivileged created clusterrole.rbac.authorization.k8s.io/flannel created clusterrolebinding.rbac.authorization.k8s.io/flannel created serviceaccount/flannel created configmap/kube-flannel-cfg created daemonset.apps/kube-flannel-ds-amd64 created daemonset.apps/kube-flannel-ds-arm64 created daemonset.apps/kube-flannel-ds-arm created daemonset.apps/kube-flannel-ds-ppc64le created daemonset.apps/kube-flannel-ds-s390x created |
配置 flannel 网络插件时,Master 节点上的 Docker 首先会去获取 flannel 的镜像文件,而后根据镜像文件启动相应的 Pod 对象。待其运行完成后再次检查集群中的节点状态可以看出 Master 已经变为 "Ready" 状态。
1 2 3 4 |
[root@master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION master Ready master 13m v1.16.0 |
如果发现你的 flannel
Pod 处于 ImagePullBackOff
状态,那么就是 flannel
镜像未拉取成功,而正常的则为 Running
状态
1 2 3 |
[root@master ~]# kubectl get pods -n kube-system | grep flannel kube-flannel-ds-amd64-hpk6q 1/1 Running 0 1m12s |
2.正确上网部署flannel(可选)
如果你可以正确规范上网,则使用以下可直接进行部署
1 |
[root@master src]# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml |
3.卸载flannel网络插件(可选)
如果你的网络插件 flannel 拉取失败,或需要重新部署此插件,可以使用 kubectl delete -f $uri
来进行删除此配置
1 |
[root@master src]# kubectl delete -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml |
添加Node到集群
任何一个Node加入集群中的节点都需要先经过 API Server 完成认证,其认证方法和认证信息在 Master 上进行集群初始化的时 kubeadm init
命令执行时输出到了最后一行。
图示:
如果忘记了加入集群的命令,可通过 kubeadm token create --print-join-command
命令获取
1 2 |
[root@master ~]# kubeadm token create --print-join-command kubeadm join 192.168.31.245:6443 --token e0vezd.o8s6mopfjibpbpaq --discovery-token-ca-cert-hash sha256:947146190e917a2a06f7319602bd512aab4206cf9a058dca4e66e4aa1ac99ab2 |
在Node加入集群时需要加上 --ignore-preflight-errors=Swap
选项来忽略Swap分区警告问题。
提供给 API Server 的 bootstap token 认证完成后,kubeadm join 命令会为后续 Master 与 Node 组件间的双向 ssl/tls 认证生成私钥及证书签署请求,并由 Node 在首次加入集群时提交给 Master 端的 CA 进行签署。默认情况下,kubeadm 配置 kube-apiserver 启用了 bootstrap TLS功能,并支持证书的自动签署。于是,kubelet 及 kube-proxy 等组件的相关私钥和证书文件在命令执行结束后便可自动生成,他们默认莫存储于 /var/lib/kubelet/pki目录中
。
node1
加入集群
1 2 3 4 5 6 |
[root@node1 ~]# kubeadm join 192.168.31.245:6443 \ --token e0vezd.o8s6mopfjibpbpaq \ --ignore-preflight-errors=Swap \ --discovery-token-ca-cert-hash \ sha256:947146190e917a2a06f7319602bd512aab4206cf9a058dca4e66e4aa1ac99ab2 |
node2
加入集群
1 2 3 4 5 6 |
[root@node2 ~]# kubeadm join 192.168.31.245:6443 \ --token e0vezd.o8s6mopfjibpbpaq \ --ignore-preflight-errors=Swap \ --discovery-token-ca-cert-hash \ sha256:947146190e917a2a06f7319602bd512aab4206cf9a058dca4e66e4aa1ac99ab2 |
Master查看集群状态
以下节点状态都为 "Ready" 就绪状态,则证明集群部署成功。当然现在只是最小化部署Kubernetes集群,一个功能完整的 Kubernetes 集群应当具备的附加组件还包括 Dashboard
,Ingress Controller
和Heapster/Prometheus
等。
1 2 3 4 5 |
[root@master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION master Ready master 10m v1.16.0 node1 Ready <none> 1m12s v1.16.0 node2 Ready <none> 8s v1.16.0 |
kubeadm init
初始化信息可通过 kubeadm config
命令来进行导出为 yaml 格式的文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
[root@master ~]# kubeadm config print init-defaults > kubeadm-init.yaml [root@master ~]# cat kubeadm-init.yaml apiVersion: kubeadm.k8s.io/v1beta2 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: 1.2.3.4 bindPort: 6443 nodeRegistration: criSocket: /var/run/dockershim.sock name: master taints: - effect: NoSchedule key: node-role.kubernetes.io/master --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta2 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {} dns: type: CoreDNS etcd: local: dataDir: /var/lib/etcd imageRepository: k8s.gcr.io kind: ClusterConfiguration kubernetesVersion: v1.16.0 networking: dnsDomain: cluster.local serviceSubnet: 10.96.0.0/12 scheduler: {} |
获取集群状态信息
Kubernetes集群Server端和Client端的版本等信息可以使用 kubectl version
命令进行查看
1 2 3 |
[root@master ~]# kubectl version Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.0", GitCommit:"2bd9643cee5b3b3a5ecbd3af49d09018f0773c77", GitTreeState:"clean", BuildDate:"2019-09-18T14:36:53Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.0", GitCommit:"2bd9643cee5b3b3a5ecbd3af49d09018f0773c77", GitTreeState:"clean", BuildDate:"2019-09-18T14:27:17Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd64"} |
默认输入信息很多,这里可简化只查看版本号
1 2 3 4 |
[root@master src]# kubectl version --short=true Client Version: v1.16.0 Server Version: v1.16.0 |
Kubernetes的API Server地址,此地址通常被其它程序所调用,查看Kubernetes API Server地址
1 2 3 4 |
[root@master src]# kubectl cluster-info Kubernetes master is running at https://192.168.31.245:6443 KubeDNS is running at https://192.168.31.245:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy |
也可以使用 kubectl cluster-info dump
来获取 kubernetes 集群的更多信息 metadata元数据
从集群中移除节点
运行过程中,若有节点需要从正常运行的集群中移除,则可使用如下步骤进行。
例如我们将 node2
从 kubernetes 集群中移除,如下:
1.在Master使用 kubectl drain
命令将 node2
上的所有资源迁移至集群中的其它节点
1 2 3 4 5 6 7 |
[root@master ~]# kubectl drain node2 --delete-local-data --force --ignore-daemonsets [root@master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION master Ready master 52m v1.16.0 node1 Ready <none> 24m v1.16.0 node2 Ready,SchedulingDisabled <none> 23m v1.16.0 |
2.从 Kubernetes 集群中移除 node2
节点
1 2 3 4 5 6 |
[root@master ~]# kubectl delete node node2 node "node2" deleted [root@kube-master src]# kubectl get nodes NAME STATUS ROLES AGE VERSION master Ready master 53m v1.16.0 node1 Ready <none> 25m v1.16.0 |
3.将 node2
重新加入Kubernetes集群
1 2 3 4 5 6 7 8 9 10 11 12 |
#在Master获取加入集群 token [root@master ~]# kubeadm token create --print-join-command kubeadm join 192.168.31.245:6443 --token 6fs57x.86ljj77hakrzf9h0 --discovery-token-ca-cert-hash sha256:947146190e917a2a06f7319602bd512aab4206cf9a058dca4e66e4aa1ac99ab2 #在node2上进行加入操作,加入集群前必须先经过重置,因之前有加入集群的信息存在,须先清空 [root@node2 ~]# kubeadm reset [root@node2 ~]# kubeadm join 192.168.31.245:6443 \ --token e0vezd.o8s6mopfjibpbpaq \ --ignore-preflight-errors=Swap \ --discovery-token-ca-cert-hash \ sha256:947146190e917a2a06f7319602bd512aab4206cf9a058dca4e66e4aa1ac99ab2 |
4.在主节点获取节点信息
1 2 3 4 5 6 |
[root@master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION master Ready master 59m v1.16.0 node1 Ready <none> 31m v1.16.0 node2 Ready <none> 12s v1.16.0 #kube-node2已加入 |