1、Kubernetes简介
Kubernetes,是一个全新的基于容器技术的分布式架构领先方案,是Google严格保密十几年的秘密武器--Borg系统的一个开源版本,于2014年9月发布第一个版本,2015年7月发布第一个正式版本。
Kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。它的目的就是实现资源管理的自动化,主要提供了如下的功能:
-
自我修复:一旦某一个容器崩溃,能够在1秒左右迅速启动新的容器。
-
弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整。
-
服务发现:服务可以通过自动发现的形式找到它所依赖的服务。
-
负载均衡:如果一个服务启动了多个容器,能够自动实现请求的负载均衡。
-
版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本。
-
存储编排:可以根据容器自身的需求自动创建存储卷。
2、Kubernetes组件
2.1、组件介绍
一个Kubernetes集群主要由控制节点(master)、工作节点(node)构成,每个节点上都会安装不同的组件。
-
控制节点(master):集群的控制平面,负责集群的决策。
-
API Server:集群操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制。
-
Scheduler:负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上。
-
ControllerManager:负责维护集群的状态,比如程序部署安排、故障检测、自动扩展和滚动更新等。
-
Etcd:负责存储集群中各种资源对象的信息。
-
-
工作节点(node):集群的数据平面,负责为容器提供运行环境。
- Kubelet:负责维护容器的生命周期,即通过控制Docker,来创建、更新、销毁容器。
- KubeProxy:负责提供集群内部的服务发现和负载均衡。
- Docker:负责节点上容器的各种操作。
2.3、组件概念
- Master:集群控制节点,每个集群要求至少有一个Master接地那来负责集群的管控。
- Node:工作负载节点,由Master分配容器到这些Node工作节点上,然后Node节点上的Docker负责容器的运行。
- Pod:Kubernetes的最小控制单元,容器都是运行在Pod中,一个Pod可以有一个或多个容器。
- Controller:控制器,通过它来实现对Pod的管理,比如启动Pod,停止Pod,伸缩Pod的数量等等。
- Label:标签,用于对Pod进行分类,同一类Pod会拥有相同的标签。
- NameSpace:命令空间,用来隔离Pod的运行环境。
2.3、Kubernetes组件调用关系的应用示例
以部署一个Nginx服务器来说明Kubernetes系统各个组件间的调用关系。
①首先需要明确,一旦Kubernetes环境启动之后,master和node都会将自身的信息存储到ETCD数据库中。
②一个Nginx服务的安装请求首先会被发送到master节点上的API Server组件。
③API Server组件会调用Scheduler组件来决定到底应该把这个服务安装到那个node节点上。此时,它会从ETCD中读取各个node节点的信息,然后按照一定的算法进行选择,并将结果告知API Server。
④API Server调用Controller-Manager去调用Node节点安装Nginx服务。
⑤Kubelet接收到指令后,会通知Docker,然后由Docker来启动一个Nginx的Pod。Pod是Kubernetes的最小操作单元,容器必须跑在Pod中。
⑥一个Nginx服务就运行了,如果需要访问Nginx,就需要通过kube-proxy来对Pod产生访问的代理,这样,外界用户就可以访问集群中的Nginx服务了。
3、集群环境的搭建
3.1、环境规划
3.1.1、集群类型
Kubernetes集群大致分为两类:一主多从和多主多从。
- 一主多从:一个Master节点和多个Node节点,搭建简单,但是有单机故障风险,适合用于测试环境。
- 多主多从:多个Master节点和多个Node节点,搭建麻烦,安全性高,适用于生产环境。
3.1.2、安装方式
Kubernetes有多种部署方式,目前主流的方式有kubeadm、minikube、二进制包。
- minikube:一个用于快速搭建单节点的Kubernetes工具。
- kubeadm:一个用于快速搭建Kubernetes集群的工具。
- 二进制包:从官网上下载每个组件的二进制包,依次去安装,此方式对于理解Kubernetes组件更加有效。
3.1.3、主机规划
角色 | IP地址 | 操作系统 | 配置 |
---|---|---|---|
Master | 192.168.114.129 | Centos7.8+,基础设施服务器 | 2核CPU,2G内存,50G硬盘 |
Node1 | 192.168.114.130 | Centos7.8+,基础设施服务器 | 2核CPU,2G内存,50G硬盘 |
Node2 | 192.168.114.131 | Centos7.8+,基础设施服务器 | 2核CPU,2G内存,50G硬盘 |
3.2、集群搭建(一主多从)
注:无特别说明,三台机器一直执行相应的命令
3.2.1、环境初始化
-
检查操作系统的版本
cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) # 推荐使用7.5及以上版本
-
关闭防火墙和禁止防火墙开机启动
systemctl stop firewalld systemctl disable firewalld
-
禁用iptables
systemctl stop iptables systemctl disable iptables
-
禁用selinux
selinux时Linux系统的一个安全服务,在集群的安装过程中可能会遇到各种奇葩问题,所以选择关闭它 。
vim /etc/selinux/config SELINUX=disabled
-
禁用swap分区
Swap分区在系统的物理内存不够用的时候,把硬盘内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap分区中,等到那些程序要运行时,再从Swap分区中恢复保存的数据到内存中。但是这样非常影响性能。
vim /etc/fstab # 只需注释掉最后一句 #/dev/mapper/centos-swap swap swap defaults 0 0
-
配置域名解析
cat >> /etc/hosts << EOF 192.168.114.129 master 192.168.114.130 node1 192.168.114.131 node2 EOF # 配置完成后,可以在三台机器上互相验证 ping master ping node1 ping node2
-
时间同步
Kubernetes要求集群中的节点时间必须精确一致,所以在每个节点上添加时间同步 。(此处必须保证三台服务器的时间不然,不然会出现node连接不上master的情况)
# 使用ntp yum install ntpdate -y ntpdate time.windows.com # 使用chronyd yum install chrony -y systemctl enable chronyd systemctl start chronyd chronyc sources 210 Number of sources = 4 MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^* 111.230.189.174 2 6 7 1 -179us[ -341ms] +/- 30ms ^? de-user.deepinid.deepin.> 3 6 1 1 -15ms[ -15ms] +/- 161ms ^? undefined.hostname.local> 2 6 1 4 +7969us[ -333ms] +/- 117ms ^? ntp8.flashdance.cx 0 6 0 - +0ns[ +0ns] +/- 0ns
-
添加网桥过滤和地址转发
vim /etc/sysctl.d/kubernetes.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 # 加载使生效 sysctl -p
-
加载网桥过滤模块
modprobe br_netfilter # 查看是否加载 lsmod | grep br_netfilter > br_netfilter 22256 0 > bridge 151336 1 br_netfilter
-
配置ipvs功能
在Kubernetes中service有两种代理模型,一种是基于iptables的,一种是基于ipvs的两者比较的话,ipvs的性能明显要高一些,但是如果要使用它,需要手动载入ipvs模块。
# 安装ipset和ipvsadm yum -y install ipset ipvsadm # 添加需要加载的模块写入脚本文件 cat <<EOF> /etc/sysconfig/modules/ipvs.modules modprobe -- ip_vs modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack_ipv4 EOF # 为脚本文件添加执行权限 chmod +x /etc/sysconfig/modules/ipvs.modules # 执行 /bin/bash /etc/sysconfig/modules/ipvs.modules # 查看对应模块是否加载成功 lsmod | grep -e ip_vs -e nf_conntrack_ipv4 > nf_conntrack_ipv4 15053 9 > nf_defrag_ipv4 12729 1 nf_conntrack_ipv4 > ip_vs_sh 12688 0 > ip_vs_wrr 12697 0 > ip_vs_rr 12600 0 > ip_vs 145458 6 ip_vs_rr,ip_vs_sh,ip_vs_wrr > nf_conntrack 139264 7 > ip_vs,nf_nat,nf_nat_ipv4,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_netlink,nf_conntra> ck_ipv4 > libcrc32c 12644 4 xfs,ip_vs,nf_nat,nf_conntrack
-
重启使配置生效
reboot
-
检查selinux和swap是否生效
gentenforce # 检查selinux > disable free -m # 检查swap total used free shared buff/cache available Mem:3502 453 2180 11 869 2812 Swap:0 0 0
3.2.2、Kubernetes安装
-
docker 安装
# 替换阿里源 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 安装指定版本,必须指定--setopt=obsoletes=0,否则会自动安装更高版本 yum install --setopt=obsoletes=0 docker-ce-18.06.3.ce-3.el7 -y # 设置docker加速器 sudo mkdir -p /etc/docker # docker在默认情况下使用的Cgroup Driver为cgroupfs,而Kubernetes推荐使用systemd来代替cgroupfs # 我们这里修改 docker 的 cgroupdriver=systemd。如果不修改 docker 则需要修改 kubelet 的启动配置,需要保证两者一致。 sudo tee /etc/docker/daemon.json <<-'EOF' { "exec-opts": ["native.cgroupdriver=systemd"], "registry-mirrors": ["https://isch1uhg.mirror.aliyuncs.com"] } EOF # 启动docker ststemctl start docker # 开机启动 systemctl enable docker
-
安装Kubernetes组件
# 由于Kubernetes的镜像在国外,速度比较慢,这里换成国内镜像源。 cat > /etc/yum.repos.d/kubernetes.repo << EOF [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=0 repo_gpgcheck=0 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF # 由于版本更新频繁,这里指定版本号部署(1.18.0) yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0 # 为了实现Docker使用的cgroup drvier和kubelet使用的cgroup drver一致,建议修改"/etc/sysconfig/kubelet"文件的内容 vim /etc/sysconfig/kubelet KUBELET_EXTRA_ARGS="--cgroup-driver=systemd" KUBE_PROXY_MODE="ipvs" # 设置为开机自启动即可,由于没有生成配置文件,集群初始化后自动启动 systemctl enable kubelet
-
部署Master节点(192.168.114.129)
此操作只需要在Master节点上操作。
# 由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里需要指定阿里云镜像仓库地址 kubeadm init --apiserver-advertise-address=192.168.114.129 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.18.0 --service-cidr=10.96.0.0/12 --pod-network-cidr=10.244.0.0/16 # 看到Success等字样,以及提示加入master节点命令,说明master启动成功。 # 根据提示信息,在Master节点上使用Kubectl工具 mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config ## 补充 # 如要需要重启,则需要删除 $HOME/.kube/config rm -rf $HOME/.kube/config kubeadm reset kubeadm init --apiserver-advertise-address=192.168.114.129 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.18.0 --service-cidr=10.96.0.0/12 --pod-network-cidr=10.244.0.0/16
-
部署Node节点
此处操作需要在两个Node上操作
# 根据Master节点提示信息,将Node加入Master # 如果命令忘记了,可以在master上执行下面命令重新获取 kubeadm token create --print-join-command # 加入master命令 kubeadm join 192.168.37.128:6443 --token j068mm.zzc2tg40yrdh3dw9 --discovery-token-ca-cert-hash sha256:fda934d79defaca0416c232022ba1ad7057648ceeb173744faacd4e7555efcee
-
在Master上查看节点信息
kubectl get nodes # 执行命令后,会发现STATUS显示NotReady,这是我们没有配置网络。节点间不能通信。
3.3.3、部署CNI网路插件
此处只需在Master上操作
Kubernetes支持多种网络插件,比如flannel、calico、canal等,任选一种即可,本次选择flannel 。建议使用calico。
# 注意此处可能需要KX上网
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 查看部署CNI网络插件进度
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-7ff77c879f-8cjh4 1/1 Running 0 4h30m
coredns-7ff77c879f-96dh4 1/1 Running 0 4h30m
etcd-master 1/1 Running 0 4h30m
kube-apiserver-master 1/1 Running 0 4h30m
kube-controller-manager-master 1/1 Running 0 4h30m
kube-flannel-ds-4mj76 1/1 Running 0 3h22m
kube-flannel-ds-7tz4s 1/1 Running 0 3h22m
kube-flannel-ds-mnv66 1/1 Running 0 3h22m
kube-proxy-7pv69 1/1 Running 0 4h30m
kube-proxy-shv6g 1/1 Running 0 4h29m
kube-proxy-xhfj7 1/1 Running 0 4h29m
kube-scheduler-master 1/1 Running 0 4h30m
# 查看节点状态
kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 4h31m v1.18.0
node1 Ready <none> 4h30m v1.18.0
node2 Ready <none> 4h30m v1.18.0
# 查看集群健康状态
kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health":"true"}
3.3.4、服务部署
在Kubernetes集群中部署一个Nginx服务,测试集群是否正常工作。
# 创建Nginx
kubectl create deployment nginx --image=nginx:1.14-alpine
# 暴露端口
kubectl expose deploy nginx --port=80 --target-port=80 --type=NodePort
# 查看服务
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4h35m
nginx NodePort 10.107.20.43 <none> 80:30073/TCP 3h21m
# 访问测试(集群中任意一个地址都可以访问)
curl http://192.168.114.131:30073