最近学完了,docker基础就想学习学习k8s,花了一段时间搭建好了。但是现在要从那些地方入手,学习呢。感觉网上系统性的资料太少,都很零散。所以求助知乎大神,给个建议的学习路线。 我是做运维的。 开发路线就不要推荐了。谢谢。


我半年前刚接触K8S的时候,跟LZ遇到一样的问题!特别能够体会这种感受,所以花了很大力气学习之后决心要把K8S整理分享出来,希望能够有所帮助。

回顾整个学习的过程,我个人的建议是:先了解K8S是什么?做什么的?以及K8S几个重要的、常见的概念(在K8S中被称为资源)。有了K8S大概的认知之后,再去深入了解更多的概念(资源)、以及更深入了解其机制。循序渐进,岂不更好?

在正式介绍之前,先自荐一波自己的文章(更多后续的文章,还在路上),欢迎交流学习:

我是小北挖哈哈:K8S系列一:概念入门?

zhuanlan.zhihu.com图标我是小北挖哈哈:K8S系列二:实战入门?

zhuanlan.zhihu.com图标

首先,K8S是什么?

K8S是Kubernetes的全称,官方称其是:

Kubernetes is an open source system for managing containerized applications across multiple hosts. It provides basic mechanisms for deployment, maintenance, and scaling of applications.

用于自动部署、扩展和管理「容器化(containerized)应用程序」的开源系统。

翻译成大白话就是:「K8S是负责自动化运维管理多个Docker程序的集群」。那么问题来了:为什么要用K8S,它有什么优势?

再来,为什么是K8S?

试想下传统的后端部署办法:把程序包(包括可执行二进位文件、配置文件等)放到伺服器上,接著运行启动脚本把程序跑起来,同时启动守护脚本定期检查程序运行状态、必要的话重新拉起程序。

有问题吗?显然有!最大的一个问题在于:如果服务的请求量上来,已部署的服务响应不过来怎么办?传统的做法往往是,如果请求量、内存、CPU超过阈值做了告警,运维马上再加几台伺服器,部署好服务之后,接入负载均衡来分担已有服务的压力。

问题出现了:从监控告警到部署服务,中间需要人力介入!那么,有没有办法自动完成服务的部署、更新、卸载和扩容、缩容呢?

这,就是K8S要做的事情:自动化运维管理Docker(容器化)程序

最后,K8S怎么做?

我们已经知道了K8S的核心功能:自动化运维管理多个容器化程序。那么K8S怎么做到的呢?这里,我们从宏观架构上来学习K8S的设计思想。首先看下图,图片来自文章Components of Kubernetes Architecture:

K8S是属于主从设备模型(Master-Slave架构),即有Master节点负责核心的调度、管理和运维,Slave节点则在执行用户的程序。但是在K8S中,主节点一般被称为Master Node或者Head Node(本文采用Master Node称呼方式),而从节点则被称为Worker Node或者Node(本文采用Worker Node称呼方式)。

总结来看,K8S的Master Node具备:请求入口管理(API Server),Worker Node调度(Scheduler),监控和自动调节(Controller Manager),以及存储功能(etcd);而K8S的Worker Node具备:状态和监控收集(Kubelet),网路和负载均衡(Kube-Proxy)、保障容器化运行环境(Container Runtime)、以及定制化功能(Add-Ons)。

到这里,相信你已经对K8S究竟是做什么的,有了大概认识。接下来,再来认识下K8S的Deployment、Pod、Replica Set、Service等,但凡谈到K8S,就绕不开这些名词,而这些名词也是最让K8S新手们感到头疼、困惑的。


Pod实例

官方对于Pod的解释是:

Pod是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。

这样的解释还是很难让人明白究竟Pod是什么,但是对于K8S而言,Pod可以说是所有对象中最重要的概念了!因此,我们必须首先清楚地知道「Pod是什么」,再去了解其他的对象。

从官方给出的定义,联想下「最小的xxx单元」,是不是可以想到本科在学校里学习「进程」的时候,教科书上有一段类似的描述:资源分配的最小单位;还有」线程「的描述是:CPU调度的最小单位。什么意思呢?」最小xx单位「要么就是事物的衡量标准单位,要么就是资源的闭包、集合。前者比如长度米、时间秒;后者比如一个」进程「是存储和计算的闭包,一个」线程「是CPU资源(包括寄存器、ALU等)的闭包。

同样的,Pod就是K8S中一个服务的闭包。这么说的好像还是有点玄乎,更加云里雾里了。简单来说,Pod可以被理解成一群可以共享网路、存储和计算资源的容器化服务的集合。再打个形象的比喻,在同一个Pod里的几个Docker服务/程序,好像被部署在同一台机器上,可以通过localhost互相访问,并且可以共用Pod里的存储资源(这里是指Docker可以挂载Pod内的数据卷,数据卷的概念,后文会详细讲述,暂时理解为「需要手动mount的磁碟」)。笔者总结Pod如下图,可以看到:同一个Pod之间的Container可以通过localhost互相访问,并且可以挂载Pod内所有的数据卷;但是不同的Pod之间的Container不能用localhost访问,也不能挂载其他Pod的数据卷

Deployment 和 ReplicaSet(简称RS)

除了Pod之外,K8S中最常听到的另一个对象就是Deployment了。那么,什么是Deployment呢?官方给出了一个要命的解释:

一个 Deployment 控制器为 Pods 和 ReplicaSets 提供声明式的更新能力。

你负责描述 Deployment 中的 目标状态,而 Deployment 控制器以受控速率更改实际状态, 使其变为期望状态。你可以定义 Deployment 以创建新的 ReplicaSet,或删除现有 Deployment,并通过新的 Deployment 收养其资源。

翻译一下:Deployment的作用是管理和控制Pod和ReplicaSet,管控它们运行在用户期望的状态中。哎,打个形象的比喻,Deployment就是包工头,主要负责监督底下的工人Pod干活,确保每时每刻有用户要求数量的Pod在工作。如果一旦发现某个工人Pod不行了,就赶紧新拉一个Pod过来替换它。

新的问题又来了:那什么是ReplicaSets呢?

ReplicaSet 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合。 因此,它通常用来保证给定数量的、完全相同的 Pod 的可用性。

再来翻译下:ReplicaSet的作用就是管理和控制Pod,管控他们好好干活。但是,ReplicaSet受控于Deployment。形象来说,ReplicaSet就是总包工头手下的小包工头

笔者总结得到下面这幅图,希望能帮助理解:

K8S Deployment、ReplicaSet和Pod关系图

新的问题又来了:如果都是为了管控Pod好好干活,为什么要设置Deployment和ReplicaSet两个层级呢,直接让Deployment来管理不可以吗?

回答:不清楚,但是私以为是因为先有ReplicaSet,但是使用中发现ReplicaSet不够满足要求,于是又整了一个Deployment(有清楚Deployment和ReplicaSet联系和区别的小伙伴欢迎留言啊)。

但是,从K8S使用者角度来看,用户会直接操作Deployment部署服务,而当Deployment被部署的时候,K8S会自动生成要求的ReplicaSet和Pod。在K8S官方文档中也指出用户只需要关心Deployment而不操心ReplicaSet:

This actually means that you may never need to manipulate ReplicaSet objects: use a Deployment instead, and define your application in the spec section.

这实际上意味著您可能永远不需要操作ReplicaSet对象:直接使用Deployments并在规范部分定义应用程序。

补充说明:在K8S中还有一个对象 --- ReplicationController(简称RC),官方文档对它的定义是:

ReplicationController 确保在任何时候都有特定数量的 Pod 副本处于运行状态。 换句话说,ReplicationController 确保一个 Pod 或一组同类的 Pod 总是可用的。

怎么样,和ReplicaSet是不是很相近?在Deployments, ReplicaSets, and pods教程中说「ReplicationController是ReplicaSet的前身」,官方也推荐用Deployment取代ReplicationController来部署服务。

Service和Ingress

吐槽下K8S的概念/对象/资源是真的多啊!前文介绍的Deployment、ReplicationController和ReplicaSet主要管控Pod程序服务;那么,Service和Ingress则负责管控Pod网路服务

我们先来看看官方文档中Service的定义:

将运行在一组 Pods 上的应用程序公开为网路服务的抽象方法。

使用 Kubernetes,您无需修改应用程序即可使用不熟悉的服务发现机制。 Kubernetes 为 Pods 提供自己的 IP 地址,并为一组 Pod 提供相同的 DNS 名, 并且可以在它们之间进行负载均衡。

翻译下:K8S中的服务(Service)并不是我们常说的「服务」的含义,而更像是网关层,是若干个Pod的流量入口、流量均衡器。

那么,为什么要Service呢

私以为在这一点上,官方文档讲解地非常清楚:

Kubernetes Pod 是有生命周期的。 它们可以被创建,而且销毁之后不会再启动。 如果您使用 Deployment 来运行您的应用程序,则它可以动态创建和销毁 Pod。

每个 Pod 都有自己的 IP 地址,但是在 Deployment 中,在同一时刻运行的 Pod 集合可能与稍后运行该应用程序的 Pod 集合不同。

这导致了一个问题: 如果一组 Pod(称为「后端」)为群集内的其他 Pod(称为「前端」)提供功能, 那么前端如何找出并跟踪要连接的 IP 地址,以便前端可以使用工作量的后端部分?

补充说明:K8S集群的网路管理和拓扑也有特别的设计,以后会专门出一章节来详细介绍K8S中的网路。这里需要清楚一点:K8S集群内的每一个Pod都有自己的IP(是不是很类似一个Pod就是一台伺服器,然而事实上是多个Pod存在于一台伺服器上,只不过是K8S做了网路隔离),在K8S集群内部还有DNS等网路服务(一个K8S集群就如同管理了多区域的伺服器,可以做复杂的网路拓扑)。

此外,笔者推荐k8s外网如何访问业务应用对于Service的介绍,不过对于新手而言,推荐阅读前半部分对于service的介绍即可,后半部分就太复杂了。我这里做了简单的总结:

Service是K8S服务的核心,屏蔽了服务细节,统一对外暴露服务介面,真正做到了「微服务」。举个例子,我们的一个服务A,部署了3个备份,也就是3个Pod;对于用户来说,只需要关注一个Service的入口就可以,而不需要操心究竟应该请求哪一个Pod。优势非常明显:一方面外部用户不需要感知因为Pod上服务的意外崩溃、K8S重新拉起Pod而造成的IP变更,外部用户也不需要感知因升级、变更服务带来的Pod替换而造成的IP变化,另一方面,Service还可以做流量负载均衡

但是,Service主要负责K8S集群内部的网路拓扑。那么集群外部怎么访问集群内部呢?这个时候就需要Ingress了,官方文档中的解释是:

Ingress 是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。

Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。

翻译一下:Ingress是整个K8S集群的接入层,复杂集群内外通讯。

最后,笔者把Ingress和Service的关系绘制网路拓扑关系图如下,希望对理解这两个概念有所帮助:

K8S Ingress、Service和Pod关系图

amespace 命名空间

和前文介绍的所有的概念都不一样,namespace跟Pod没有直接关系,而是K8S另一个维度的对象。或者说,前文提到的概念都是为了服务Pod的,而namespace则是为了服务整个K8S集群的。

那么,namespace是什么呢?

上官方文档定义:

Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群。 这些虚拟集群被称为名字空间。

翻译一下:namespace是为了把一个K8S集群划分为若干个资源不可共享的虚拟集群而诞生的

也就是说,可以通过在K8S集群内创建namespace来分隔资源和对象。比如我有2个业务A和B,那么我可以创建ns-a和ns-b分别部署业务A和B的服务,如在ns-a中部署了一个deployment,名字是hello,返回用户的是「hello a」;在ns-b中也部署了一个deployment,名字恰巧也是hello,返回用户的是「hello b」(要知道,在同一个namespace下deployment不能同名;但是不同namespace之间没有影响)。前文提到的所有对象,都是在namespace下的;当然,也有一些对象是不隶属于namespace的,而是在K8S集群内全局可见的,官方文档提到的可以通过命令来查看,具体命令的使用办法,笔者会出后续的实战文章来介绍,先贴下命令:

# 位于名字空间中的资源
kubectl api-resources --namespaced=true
?
# 不在名字空间中的资源
kubectl api-resources --namespaced=false

不在namespace下的对象有:

在namespace下的对象有(部分):


一般做一件事情都是要有内驱力,或者工作需求。

所以,你直接问怎么学k8s,这个会让人难以回答的让你可以执行。

我抛几个问题吧,在解决问题的过程中学习,才是最好的学习方法,要么你就把k8s文档一篇不少的全吸收完。

1. deployment, pod, job有什么区别?什么场景用他们?2. service是干嘛的?可以解决些什么问题?3. 我想部署一些有状态的服务,比如MySQL,用k8s怎么做?就这么三个问题吧,其它的,等你有问题了再谈。

首先得把所有的知识点好好捋一遍,官方文档是个不错的选择,如果英文不好,还是买本书吧,现在也就只有kubernetes权威指南比较靠谱,知识点,概念都有解释

本地建他五六个虚拟机,搭个k8s集群出来,知识点一个一个的实践一下。国内有墙,注意镜像的挂起状态,多看日志,有可能就是被墙了

在生产环境下,如果是暴露到了公网环境,安全问题就很重要了,节点,程序之间的加密通讯要著重掌握

去github上看k8s这个项目就能知道,几小时内就能有好几次提交,一周一个版本司空见惯,官方文档都已经跟不上了,好多文档上没有的东西,就只能去代码里看了


可以看看https://zhuanlan.zhihu.com/p/56159304


帮你顶帖,我也是运维,docker的方方面面基本上摸了一遍,一看k8s就感觉两眼迷茫无从下手,很多文档感觉都不系统,希望有大神出来指教一二


  • 了解docker
  • 了解kubernetes概念,坦白说还是很有门槛的
  • 了解kubernetes的架构
  • 学习kubernetes的安装运维、网路存储、日志
  • 划重点:学习如何管理应用
  • kubernetes的扩展开发

  • 官方文档就可以了


    推荐阅读:
    相关文章