距离上次更新已经有一个月了,主要是最近工做上的变更有点频繁,如今才暂时稳定下来。这篇博客的本意是带你们从零开始搭建K8S集群的。可是我后面一想,若是是我看了这篇文章,会收获什么?就是跟着步骤一步一走吗?是个人话我会选择拒绝,因此我加了关于K8S的简单介绍,每一步的步骤都添加了解释。因为篇幅和时间缘由,我只介绍了K8S中较为核心的Pod和Service。node
文章前半段会简单的介绍一下K8S,后半段会介绍如何从零开始慢慢的搭建集群。若是想直接开始着手搭建集群,则能够直接从第三章开始看。linux
K8S全称kubernetes,是由Google在2014年开源的生产级别的容器编排系统,或者说是微服务和云原平生台。虽然说14年才开源,但实际上K8S是Google内部的容器编排系统Borg的开源版本,在Google内部已经用了十多年了。下面是一个关于K8S的Logo来源的小插曲。git
Kubernetes由谷歌在2014年首次对外宣布 。它的开发和设计都深受谷歌的Borg系统的影响,它的许多顶级贡献者以前也是Borg系统的开发者。在谷歌内部,Kubernetes的原始代号曾经是Seven,即星际迷航中友好的Borg(博格人)角色。Kubernetes标识中舵轮有七个轮辐就是对该项目代号的致意。github
不过也有一个说法是,Docker的Logo是一个驮着集装箱的鲸鱼,也就是运输船,K8S的Logo是一个船舵,旨在引领着Docker(或者说容器技术)走向远方。算法
看了不少官方文章,是真官方。官方什么意思呢,就是有可能看完了约等于没有看,同样的啥都不知道。docker
因此我想写这样一篇文章,给那些看完文档仍然不太理解或者说彻底没了解过K8S的老铁一点小帮助。那么让咱们回到最初对K8S的定义,它是一个微服务框架。shell
说到微服务框架,咱们就不得不提一下目前业界十分主流的微服务框架,与这些你十分熟悉的框架进行对比,你就会很清晰的知道K8S能作什么了。目前很主流的微服务框架和平台有Spring Cloud、Dubbo和K8S。ubuntu
Spring Cloud来自Netflix,Dubbo来自阿里,而K8S则来自Google。说的直观一点,这三个框架都是针对微服务的解决方案。可能有人会说,K8S不是一个容器编排系统吗?怎么跟Spring Cloud这种软件层面上的微服务框架作起了对比呢?vim
老铁别慌,等咱们慢慢深刻这个概念。服务器
咱们都知道,若是咱们须要使用微服务,那么确定少不了一些底层的基础设施的支撑,例如服务注册与发现、负载均衡、日志监控、配置管理、集群自愈和容错、弹性伸缩…等等。我没有列举完,如其实这些组件均可以统称为微服务的公共关注点。那咱们是否是能够说,只要可以提供的这些功能,它就算一个微服务框架呢?
以上的大多数功能,K8S都是内置的。故咱们能够说K8S是一个与Docker Swarm相相似的容器编排系统,可是因为K8S内置了微服务的解决方案,它同时也是一个功能完备的微服务框架。
在Docker Swarm中,调度的最小单位是容器,而在K8S中,调度的最小是Pod,那啥是Pod呢?
Pod是K8S设计的一个全新的概念,在英文中的原意是表达一群鲸鱼或者是一个豌豆荚的意思。换句话说,一个Pod中能够运行一个或者多个容器。
在一个集群中,K8S会为每一个Pod都分配一个集群内惟一的IP地址。由于K8S要求底层网络支持集群内的任意节点之间的两个Pod可以直接通讯。这些容器共享当前Pod的文件系统和网络。而这些容器之因此可以共享,是由于Pod中有一个叫Pause的根容器,其他的用户业务容器都是共享这个根容器的IP和Volume。因此这些容器之间均可以经过localhost进行通讯。
有人可能会问,为何要引入根容器这个概念?那是由于若是没有根容器的话,当一个Pod中引入了多个容器的时候,咱们应该用哪个容器的状态来判断Pod的状态呢?因此才要引入与业务无关且不容易挂掉的Pause容器做为根容器,用根容器的状态来表明整个容器的状态。
熟悉Spring Cloud或者微服务的都知道,微服务中最忌讳的就是出现单点的状况。
因此针对同一个服务咱们通常会部署2个或者更多个实例。在K8S中,则是会部署多个Pod副本,组成一个Pod集群来对外提供服务。
而咱们前面提过,K8S会为每个Pod提供一个惟一的IP地址,客户端就须要经过每一个Pod的惟一IP+容器端口来访问到具体的Pod,这样一来,若是客户端把调用地址写死,服务器就没有办法作负载均衡,并且,Pod重启以后IP地址是会变的,难道每次重启都要通知客户端IP变动吗?
为了解决这个问题,就要引出Service的概念了。
Service是K8S中最核心的资源对象之一,就是用于解决上面提到的问题。我我的认为与Swarm中的Service概念没有太大的区别。
一旦Service被建立,K8S会为其分配一个集群内惟一的IP,叫作ClusterIP,并且在Service的整个生命周期中,ClusterIP不会发生变动,这样一来,就能够用与Docker Swarm相似的操做,创建一个ClusterIP到服务名的DNS域名映射便可。
值得注意的是,ClusterIP是一个虚拟的IP地址,没法被Ping,仅仅只限于在K8S的集群内使用。
而Service对客户端,屏蔽了底层Pod的寻址的过程。而且由kube-proxy进程将对Service的请求转发到具体的Pod上,具体到哪个,由具体的调度算法决定。这样以来,就实现了负载均衡。
而Service是怎么找到Pod的呢?这就须要继续引入另一个核心概念Label了。
Lable本质上是一个键值对,具体的值由用户决定。Lable就是标签,能够打在Pod上,也能够打到Service上。总结来讲,Label与被标记的资源是一个一对多的关系。
例如,咱们给上面所描述的Pod打上了role=serviceA
的标签,那么只须要在Service中的Label Selector中加入刚刚那个标签,这样一来,Service就能够经过Label Selector找到打了同一Label的Pod副本集了。
接下来,再简单的介绍一下其余的K8S核心概念。
上面提到过部署多个Pod,是怎么一回事呢?K8S最开始有一个概念叫Replication Controller,不过如今已经慢慢的被Replica Set所替代,RS也叫下一代的RC。简单来讲Replica Set定义了一种指望的场景,即让任什么时候候集群内的Pod副本数量都符合预期的值。
一旦被建立,集群就会按期的检测当前存活的Pod数量,若是多了,集群就会停掉一些Pod。相反,若是少了就会建立一些Pod。这样一来能够避免什么问题呢?假设某个服务有两个实例在运行,其中一个意外挂掉了,若是咱们设置了副本数量是2,那么集群就会自动建立一个Pod,以保证集群内始终有两个Pod在运行。
K8S的东西就简单的介绍这么多,接下来让咱们进入集群的搭建环节。
不知道从哪篇博客开始,不是很愿意写这种纯TODO类的博文,可是我本身躺坑以后发现,我本身这个还真是我目前见过最简单的。
我看到的有些安装分了不少种状况,可是当一个初学者来看的时候,可能反而会让他看懵逼。因此接下来的安装会有些硬核。不分状况,就只有一种状况,一把梭安装就完事。
系统 版本 Ubuntu 18.04
K8S 版本 v1.16.3
Docker 版本 v19.03.5
Flannel 版本 v0.11.0
若是你问我,若是没有机器看了你的文章也能的拥有本身的集群吗?那么请看下图…
咱们先假设如下的状况成立。
机器:有2-3台物理机或虚拟机
系统:Ubuntu 18.04 且已换好国内的源
若是以上基本不成立,本篇文章到此结束,谢谢观看…
我也不须要介绍各类状况了,直接登上机器,建立一个shell脚本,例如叫install_docker.sh
,一把梭代码以下。
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates
curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get -y install docker-ce docker-ce-cli containerd.io
复制代码
而后执行sh install_docker.sh
,等待命令跑完,验证docker是否安装好便可。直接敲docker
+ 回车。
同理,新建一个shell脚本,例如install_k8s.sh
。一把梭代码以下。
sudo curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-get update
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get install -y kubelet kubeadm kubectl --allow-unauthenticated
复制代码
而后执行sh install_k8s.sh
,等待命令跑完,验证k8s是否安装好便可。直接敲kubectl
+ 回车。
先给出一把梭,不要耽误了正在安装的老铁。为何要关闭后面再说。
sudo swapoff -a
,可是重启以后会生效。会致使k8s没法正常运行。sudo vim /etc/fstab
将有swap.img那行注释掉,保存便可。那么,swap是啥呢?它是系统的交换分区,你能够理解为虚拟内存。当系统内存不足的时候,会将一部分硬盘空间虚拟成内存使用。那为何K8S须要将其关掉呢?能够从下图看看访问内存和访问硬盘速度上的差别就知道了。
总的来讲是为了性能考虑,因此就须要避免开启swap交换,K8S但愿全部的服务都不该该超过集群或节点CPU和内存的限制。
到这,准备工做就完成了,能够开始安装K8S的master节点了,登上要做为master节点的机器。
老规矩,先上命令,再说为何要设置。
sudo hostnamectl set-hostname master-node
复制代码
自定义修改了主机名,在以后查看集群内节点时,每一个节点的名字就不会显示K8S自动生成的名字,便于查看和记忆。例如,在其余的Node节点你能够将master-node
改成slave-node-1
或worker-node-2
,效果以下。
在机器上执行以下命令。
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
复制代码
而后,抱起吉他,等待命令执行完。
这里须要特别注意一下。这个命令执行完成以后,会打印一个有kubeadm join的命令,须要保存下来。
大概长这样。
kubeadm join 你的IP地址:6443 --token 你的TOKEN --discovery-token-ca-cert-hash sha256:你的CA证书哈希
顾名思义,这个命令用于其余节点加入到集群中,并且Token是有时效性的,过时时间通常是86400000毫秒。
若是失效,就须要从新生成。若是你真的又没有保存,又失效了…我仍是给你准备了两个补救措施。若是命令保存下来了,那么请直接跳过这两个补救措施。
token. 经过命令
Kubeadm token list
找回ca-cert. 执行命令
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
找回
把下面的指令一把梭便可。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
复制代码
主要是,为了避免那么麻烦,在控制节点上执行kubectl
这类的命令时,不用每次都sudo。
执行以下命令,安装网络插件Flannel。
sudo kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
复制代码
能够看到,若是不安装Flannel,咱们刚刚Init好的Master节点会处于NOT_READY的状态。安装好以后,能够经过命令kubectl get nodes
来查看全部的节点的状态。也能够经过kubectl get pods --all-namespaces
来查看当前集群中全部Pod的状态。这里须要注意的是,只有在master节点是READY,全部Pod的状态是RUNNING以后,才能够进行下一步。
为何要装网络插件呢?
那是由于K8S要求集群内的全部节点之间的Pod网络是互通的。换句话说,Flannel可让集群内不一样节点上的容器都有一个在当前集群内惟一的虚拟IP地址。这样以来,就能够实现,跨节点的Pod与Pod直接通讯。
这样一来,将复杂的网络通讯,简单的变成了两个IP地址之间的通讯。这主要是经过虚拟二层网络实现的。看似是这个节点的Pod直接和另外一个节点上的Pod进行了通讯,最终仍是经过节点的物理网卡流出的。
到此,一个单点的集群就已经搭建好了。如今咱们要作的是,登陆准备好的另外一台(我只有两台,若是你有3台或者4天,把这个章节反复走几回就行了)服务器。
执行以下命令。
sudo hostnamectl set-hostname slave-node
复制代码
由于当前节点不是master了,因此主机名设置成了slave-node。
重点来了,执行上一章节生成的kubeadm join命令便可。等待执行完毕以后,就能够在master节点上经过命令kubectl get nodes
看到slave-node已经加入了集群。
对于Slave节点的操做就没了。
关于K8S就简单的介绍到这里,因为篇幅和时间的缘由,不少概念都没有介绍,例如Deployment、Volume、ConfigMap等等。仅仅只介绍了较为核心的Pod和Service,以及相关的东西。毕竟,若是想要把K8S的核心理念介绍完,一篇博客的篇幅是确定不够的,后面我再单独详细的介绍吧。
第一次在博客里求赞啊,以前彻底是随缘。不过我后来发现,打开博客看到你们的点赞和留言,这对我来讲是一种莫大的鼓励。
若是你以为这篇文章对你有帮助,还麻烦点个赞,关个注,分个享,留个言
也能够微信搜索公众号【SH的全栈笔记】,固然也能够直接扫描二维码关注
![]()