[TOC]
0x00 基础简述
1.介绍
Q:什么是Kubernetes?
Kubernetes是一个可以移植、可扩展的开源平台,用于管理容器化工作负载和服务
, 使用 声明式的配置
并依据配置信息自动地执行容器化应用程序的管理,简单的说它就是一个全新基于容器技术的分布式架构领先方案;
历史由来:
Kubernetes的名字起源于希腊语,含义是 舵手
、领航员
、向导
,其logo即像一张渔网又像一个罗盘。
Google于2014年将Brog系统开源并命名为Kubernetes,它是构建在Google Brog
十五年运行大规模分布式系统的经验 基础之上,并结合了开源社区最好的想法和实践。
PS深层含义:既然Docker把自己定位是驮着集装箱在大海遨游的鲸鱼,那么Kubernetes则是掌控大海从而捕获和指引这条鲸鱼按照其设定的路线巡游,从这里可以看出Google对其打造了新一代容器世界的伟大蓝图;
官网:https://kubernetes.io
设计理念
描述:其功能与架构都遵循了"一切以服务为中心,一切围绕服务运转"
以及微服务的架构,简化开发流程与运维的成本;
产品对比:
在所有的容器编排工具中(类似的还有 docker swarm / mesos等
),Kubernetes的生态系统更大、增长更快,有更多的支持、服务和工具可供用户选择,可以将Kubernetes看做为Docker的上层架构。
以下是使用 google trends 对比 kubernetes
、 docker swarm
、 mesos
三个关键词的截图。

WeiyiGeek.2019
Q:如何学习Kubernetes?
答:入门必看文档系列以后看到K8s一律等同于Kubernetes只是方便国人发音;
- K8S文档:https://kubernetes.io/docs/home/
- Kuboard(国人文档):https://kuboard.cn/learning/
回到部署时代变迁流程, 大致来说在部署应用程序的方式上,我们主要经历了三个时代:
- 传统部署时代:早期企业直接将应用程序部署在物理机上。由于物理机上
不能为应用程序定义资源使用边界
,我们也就很难合理地分配计算资源。例如:如果多个应用程序运行在同一台物理机上,可能发生这样的情况:其中的一个应用程序消耗了大多数的计算资源,导致其他应用程序不能正常运行。应对此问题的一种解决办法是,将每一个应用程序运行在不同的物理机上。然而,这种做法无法大规模实施,因为资源利用率很低,且企业维护更多物理机的成本昂贵。 - 虚拟化部署时代:针对上述问题,虚拟化技术应运而生。用户可以在单台物理机的CPU上运行多个虚拟机(Virtual Machine)。
- 虚拟化技术使得
应用程序被虚拟机相互分隔开
,限制了应用程序之间的非法访问,进而提供了一定程度的安全性。 - 虚拟化技术
提高了物理机的资源利用率
,可以更容易地安装或更新应用程序,降低了硬件成本,因此可以更好地规模化实施。 - 每一个虚拟机可以认为是被虚拟化的物理机之上的一台完整的机器,其中运行了一台机器的所有组件,包括虚拟机自身的操作系统。
- 虚拟化技术使得
- 容器化部署时代:容器与虚拟机类似,但是
降低了隔离层级,共享了操作系统
。因此,容器可以认为是轻量级的。- 与虚拟机相似,每个容器拥有自己的文件系统、CPU、内存、进程空间等
- 运行应用程序所需要的资源都被容器包装,并和底层基础架构解耦(
不强制依赖宿主系统硬件环境
) - 容器化的应用程序可以跨云服务商、跨Linux操作系统发行版进行部署
这里再老生重谈一下容器化对我们带来的诸多好处:
- 1.敏捷地创建和部署应用程序: 比VM创建容器镜像更快更方便;
- 2.持续开发、集成和部署:通过快速、简便的回滚(由于映像不变性),提供可靠且频繁的容器映像生成和部署。
- 3.分离开发和运维的关注点: 降低了开发和运维的耦合度
- 4.可监控性: 操作系统级别的资源监控信息以及应用程序健康状态以及其他信号的监控信息
- 5.开发、测试、生产不同阶段的环境一致性: 一次build到处运行;
- 6.跨云服务商、跨操作系统发行版的可移植性: 在 Ubuntu、RHEL、CoreOS、本地、主要公共云和其他任何位置上运行。
- 7.以应用程序为中心的管理:问题的焦点则是在操作系统的逻辑资源上运行一个应用程序,而VM注重于在虚拟硬件上运行一个操作系统
- 8.松耦合、分布式、弹性、无约束的微服务:应用程序被切分成更小的、独立的微服务,并可以动态部署和管理,而不是一个部署在专属机器上的庞大的单片应用程序
- 9.资源隔离:确保应用程序性能不受干扰
- 10资源利用:资源高效、高密度利用
2.功能特性
容器是一个非常好的打包并运行应用程序的方式,但是在生产环境中,您可能还需要管理容器化应用程序,并且确保其不停机地连续运行,但是往往不可能是万无一失的;
例如:当一个容器故障停机,需要另外一个容器需要立刻启动以替补停机的容器。类似的这种对容器的管理动作由系统来执行会更好更快速(而放弃传统的手工方式
)。
Kubernetes针对此类问题,提供了容器化编排解决方案,可以使你非常健壮地运行分布式系统,它可以处理应用程序的伸缩、failover、部署模式
等多种需求。
K8s提供特性:
- 服务发现和负载均衡:通过
DNS 名称或 IP 地址
暴露容器的访问方式,并且可以在同组容器内分发负载以实现负载均衡
; - 存储编排:可以自动挂载指定的存储系统,例如
本地存储/nfs/iscsi/云存储
等 - 自动发布和回滚: 描述已部署容器的所需状态并将以合适的速率调整容器的实际状态, 可以
自动执行部署创建新容器、删除现有容器并将其所有资源采用到新容器
; - 自愈: 重新启动发生故障、替换容器、kill杀死不满足自定义健康检查条件的容器 (
在容器就绪之前,避免调用者发现该容器
) - 密钥及配置管理: 可以存储和管理敏感信息(例如,密码、OAuth token、ssh密钥等), 您可以更新容器应用程序的密钥、配置等信息,
而无需重新构建容器的镜像
;
3.边界
Kubernetes不是一个传统意义的、保罗万象的 PaaS(Platform as a Service)系统。
它主要在容器层面上工作而不是硬件层面
,它提供了与PaaS相似的通用特性例如:部署、伸缩、负载均衡、日志、监控
等;然而K8a并不是一个单一整体,这些特性都是可选、可插拔的(高自定义
)
Kubernetes提供用于搭建开发平台的基础模块,同时为用户提供了不同模块的选择性和多样性。
- 1.不限制应用程序的类型: K8s目的广泛支持不同类型的工作负载,包括:
有状态、无状态、数据处理
等类型的应用,简单的说只要能在容器中运行的就可以在k8s上运行
; - 2.不部署源码、不编译或构建应用程序: 可以作为部署平台参与到 CI/CD 流程,但是不涉及镜像构建和分发的过程 ,即
持续集成、交付和部署 (CI/CD) 工作流
由公司业务及技术要求决定;- 译者注:可选的有 Jenkins / Gitlab Runner / docker registry / harbor 等
- 3.不提供应用程序级服务: 包括:中间件(例如,消息总线)、数据处理框架(例如Spark)、数据库(例如,mysql)、缓存(例如,Redis),或者分布式存储(例如,Ceph)。
此类组件可以在 Kubernetes 上运行,或者可以被运行在 Kubernetes 上的应用程序访问
; - 4.不限定日志、监控、报警的解决方案: k8s提供一些样例展示如何与日志、监控、报警等组件集成,同时提供收集、导出监控度量(metrics)的一套机制,用户可根据自己的需求进行选择
日志、监控、以及报警组件
;- 译者注:可选的有 ELK(日志) / Graphana(
日志展示平台
) / Pinpoint(分布式系统性能监控工具
) / Skywalking (Skywalking分布式追踪与监控
)/ Metrics Server (英 /ˈmetrɪks/ 容器监控
) / Prometheus (容器监控
) 等
- 译者注:可选的有 ELK(日志) / Graphana(
- 5.不提供或者限定配置语言(例如jsonnet): 提供一组声明式的 API您可以按照自己的方式定义部署信息。
- 译者注:可选的有
helm / kustomize / kubectl / kubernetes dashboard / kuboard /octant / k9s
等
- 译者注:可选的有
- 6.不提供或限定任何机器的配置、维护、管理或自愈的系统。
- 译者注:在这个级别上,可选的组件有
puppet、ansible、open stack
等
- 译者注:在这个级别上,可选的组件有
此外 Kubernetes 不是一个纯粹意义上的容器编排系统
, 因为它消除了容器编排的需求。
Q:什么是容器编排技术?
答:容器编排的技术定义是预定义流程的执行(先做A、再做B、然后做C)
。与此相对应Kubernetes构建了一系列相互独立、可预排的控制过程
,以持续不断地将系统从当前状态调整到声明的目标状态。
比如: 如何从 A 达到 C,并不重要集中化的控制也就不需要了,就是这样的设计思想使得Kubernetes使用更简单、更强大、稳健、反脆弱和可扩展
。
个人总结:[2020年4月22日 14:51:04]
0x01 K8s组件
本文档描述了 Kubernetes 的主要组件(该章节非常的重要
了解其组件是了解其K8s架构的基础)

WeiyiGeek.
1.Master组件
Q:Master组件的作用说明
答:Master组件是集群的控制平台(control plane),主要负责集群中的全局决策(例如调度
)和探测并响应集群事件(例如当 Deployment 的实际 Pod 副本数未达到 replicas 字段的规定时,启动一个新的 Pod
);
Master组件可以运行于集群中的任何机器上,但是为了简洁性,所有的 master 组件通常是在运行在一台无其业务容器下的机器上
;
Master下组件的介绍:
- 1.kube-apiserver : 主要用于提供
Kubernetes API
用来控制平台的前端可以进行水平扩展,比如我们上面提到的kubectl / kubernetes dashboard / kuboard
等k8s管理工具基于此实现对 Kubernetes 集群的管理 - 2.etcd : 支持一致性和高可用的名值对存储组件,Kubernetes集群的所有配置信息都存储在 etcd 中;
3.kube-scheduler : 主要用于任务调度,此组件监控所有新创建尚未分配到节点上的 Pod,并且自动选择为 Pod 选择一个合适的节点去运行。
- 影响调度的因素有:
单个或多个 Pod 的资源需求、硬件、软件、策略的限制、亲和与反亲和(affinity and anti-affinity)的约定、数据本地化要求、工作负载间的相互作用
;
- 影响调度的因素有:
- 4.kube-controller-manager: 运行所有控制器从Logic上来说每一个控制器是一个独立的进程,但是为了降低复杂度,这些
控制器都被合并运行在一个进程
里,该模块包含的控制器有:- 节点控制器:
负责监听节点停机的事件并作出对应响应
; - 副本控制器:
负责为集群中每一个副本控制器对象(Replication Controller Object)维护期望的 Pod 副本数
; - 端点(Endpoints)控制器:
负责为端点对象(Endpoints Object,连接 Service 和 Pod)赋值
; - Service Account & Token控制器:负责为新的
名称空间创建 default Service Account 以及 API Access Token
;
- 节点控制器:
- 5.cloud-controller-manager: K8s控制平面组件嵌入特定于云的控制逻辑,运行了与具体云基础设施供应商互动的控制器
(1.6版本引入)
, 云控制器管理器允许您将集群链接到云提供商的API
,并将与云平台交互的组件与仅与集群交互的组件分离开来。- ccm(简称)使得云供应商的代码和 Kubernetes 的代码可以各自独立的演化,使得K8核心代码不在高度依赖于云供应商的代码的; ccm(简称)与kcm(简称)一样
将几个逻辑上独立的控制循环组合成一个二进制文件作为一个进程运行
。 - 注意在进行K8s集群安装时候可能默认不会安装
cloud-controller-manager
,通过cloud-controller-manager,Kubernetes
可以更好地与云供应商结合,例如在阿里云的 Kubernetes 服务里,您可以在云控制台界面上轻松点击鼠标,即可完成 Kubernetes 集群的创建和管理。在私有化部署环境时,您必须自行处理更多的内容。
以下控制器可以有云提供商依赖:1
2
3
4
5
6
7
8
9
10
11(1) 节点 (Node) 控制器:当某一个节点停止响应时,调用云供应商的接口,以检查该节点的虚拟机是否已经被云供应商删除
#译者注:私有化部署Kubernetes时,我们不知道节点的操作系统是否删除,所以在移除节点后,要自行通过 kubectl delete node 将节点对象从 Kubernetes 中删除
(2) 路由 (Router) 控制器:在云供应商的基础设施中设定网络路由
#译者注:私有化部署Kubernetes时,需要自行规划Kubernetes的拓扑结构,并做好路由配置,例如 安装Kubernetes单Master节点 中所作的
(3) 服务(Service) 控制器:`创建、更新、删除`云供应商提供的负载均衡器
#译者注:私有化部署Kubernetes时,不支持 LoadBalancer 类型的 Service,如需要此特性,需要创建 NodePort 类型的 Service,并自行配置负载均衡器
(4) 数据卷 (Volume) 控制器:`创建、绑定、挂载`数据卷,并协调云供应商编排数据卷
#译者注:私有化部署Kubernetes时,需要自行创建和管理存储资源,并通过Kubernetes的存储类、存储卷、数据卷等与之关联
- ccm(简称)使得云供应商的代码和 Kubernetes 的代码可以各自独立的演化,使得K8核心代码不在高度依赖于云供应商的代码的; ccm(简称)与kcm(简称)一样
补充说明:
Q:什么是alpha阶段?
答:即开发内部测试阶段;
2.Node 组件
Node 组件运行在每一个节点上(包括 master 节点和 worker 节点),负责维护运行中的 Pod 并提供 Kubernetes 运行时环境
。
Node下组件的介绍:
- 1.kubelet: 此组件是运行在每一个集群节点上的代理程序
确保 Pod 中的容器处于运行状态
;- 它通过多种途径获得 PodSpec 定义,并确保 PodSpec 定义中所描述的容器处于运行和健康的状态。
- 注意:Kubelet不管理不是通过 Kubernetes 创建的容器。
- 2.kube-proxy: 此组件是一个网络代理程序,运行在集群中的每一个节点上,是实现
Kubernetes Service
概念的重要部分。- 它维护节点上的网络规则使得您可以在集群内、集群外正确地与Pod 进行网络通信
- 如果有可用的操作系统包过滤层kube-proxy将使用它,否则kube-proxy将转发流量本身。
- 3.容器引擎: 负责运行容器Kubernetes支持多种容器引擎:Docker 、containerd 、cri-o 、rktlet 以及任何实现了 Kubernetes容器引擎接口 的容器引擎
补充说明:[2020年4月22日 16:41:04]
Q:什么是引擎?
答:创建和管理容器的工具,通过读取镜像来生成容器,并负责从仓库拉取镜像或提交镜像到仓库中;
Q:多种容器引擎介绍
- (1) Docker Engine : 是一种开源容器化技术,用于构建和容器化应用程序(
C/S架构应用
),包含以下组件守护进程dockerd,与 Docker 守护进程进行对话和指导的接口的 API,命令行接口 (CLI) 客户端使用Docker API通过脚本或直接命令控制与 Dockerd 守护进程交互
;WeiyiGeek.
- (2) Containerd Engine : 是容器运行环境的核心引擎(
容器编排/调度技术的基础
),可以实现对容器的各种操作(启动,停止等)和网络和存储配置(提供定制化
),它提供了标准化的接口方便各种平台集成,并且还可以将运行环境(Runtime)做成可插拔(Plugable)。
但它并不是直接面向最终用户, 主要是用于集成到更上层的系统里, 比如Docker Swarm, Kubernetes, Mesos 等容器编排系统。

WeiyiGeek.
3.Addons 插件
Addons 使用 Kubernetes 资源(DaemonSet、Deployment等)实现集群的功能特性
。由于他们提供集群级别的功能特性,addons使用到的Kubernetes资源都放置在 kube-system 名称空间
下。
下面描述了一些经常用到的 addons 更多插件请参考K8s的 Addons List
- 1.DNS:除了 DNS Addon 以外,其他的 addon 都不是必须的,所有 K8s 集群都应该有
Cluster DNS
;K8s启动容器时,自动将该 DNS 服务器加入到容器的 DNS 搜索列表中。 - 2.Web UI(Dashboard):是一个Kubernetes集群的 Web 管理界面。用户可以通过该界面管理集群。
- 3.Kuboard:是一款基于Kubernetes的微服务管理界面,相较于 Dashboard 来说Kuboard的特点 :
无需手工编写 YAML 文件 、微服务参考架构、上下文相关的监控、场景化的设计(导出配置、导入配置)
- 4.Container Resource Monitoring(容器资源监控):将容器的度量指标(metrics)记录在时间序列数据库中,并提供了 UI 界面查看这些数据;
- 5.Cluster-level Logging(集群级别的日志记录): 机制负责将容器的日志存储到一个统一存储中,并提供搜索浏览的界面;
补充说明:
Q:什么是Cluster DNS
答:Cluster DNS
(英 /ˈklʌstə(r)/
) 是一个 DNS 服务器,是对您已有环境中其他 DNS 服务器的一个补充,存放了 Kubernetes Service 的 DNS 记录。
0x02 基础知识
前面我们说了k8s能够对容器化软件进行部署管理,在不停机的前提下提供简单快速的发布和更新方式
, Kubernetes是自动化部署,缩放,以及集装箱
应用管理一个开放源码的容器业务流程引擎;
简单的说:如果项目需要多机器节点的微服务架构,并且采用Docker image(镜像)进行容器化部署
,那么k8s可以帮助我们屏蔽掉集群的复杂性,自动选择最优资源分配方式进行部署;
k8s集群简单介绍
描述:下图描述的是拥有一个Master(主)节点和六个Worker(工作)节点的k8s集群;
Master 节点
: 负责管理集群以及协调集群中的所有活动- 运行着集群管理的一组进程:
kube-apiserver , kube-controller-manager 和 Kube-scheduler
,其负责Pod调度,弹性收缩,以及应用程序安全控制,维护应用程序的状态,扩展和更新应用程序。
- 运行着集群管理的一组进程:
Worker 节点
: 即图中的Node是VM(虚拟机)或物理计算机,作为集群中的工作节点运行着真正的应用程序,简单的说它就是充当k8s集群中的工作计算机。- 每个Worker节点都运行着一组进程:
Kubelet / Kubelet-proxy
,他们负责Pod创建、启动监控、重启、销毁以及实现应用的负载均衡; - 每个Worker节点还安装了用于处理容器操作的工具: 例如Docker或者Container.io;
- 每个Worker节点都运行着一组进程:

WeiyiGeek.简单集群
0x03 简单示例
K8s单Master节点
环境配置要求:1
22台 2核4G 的服务器
CentOS 7.8 kernel version>= 4.19.x
测试环境(两台):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#系统版本
CentOS Linux release 7.8.2003 (Core)
#内核版本
CentOS Linux (5.6.10-1.el7.elrepo.x86_64) 7 (Core)
#核心数
# 请使用 lscpu 命令,核对 CPU 信息
# Architecture: x86_64 本安装文档不支持 arm 架构
# CPU(s): 2 CPU 内核数量不能低于 2
cat /proc/cpuinfo | grep -c 'processor'
2
#内存容量(6G)
cat /proc/meminfo
MemTotal: 6090864 kB
MemFree: 5709020 kB
MemAvailable: 5695728 kB
Buffers: 2108 kB
Cached: 193996 kB
安装准备以及软件版本: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* 我的任意节点 centos 版本为 7.6 或 7.7
* 我的任意节点 CPU 内核数量大于等于 2,且内存大于等于 4G
* 我的任意节点 hostname 不是 localhost,且不包含下划线、小数点、大写字母
* 我的任意节点都有固定的内网 IP 地址
* 我的任意节点都只有一个网卡,如果有特殊目的,我可以在完成 K8S 安装后再增加新的网卡
* 我的任意节点上 Kubelet使用的 IP 地址 可互通(无需 NAT 映射即可相互访问),且没有防火墙、安全组隔离
* 我的任意节点不会直接使用 docker run 或 docker-compose 运行容器
#安装软件一览
Kubernetes v1.18.x
* kubeadm
* kubectl
* kubelet
* kube-apiserver
* kube-control-manager
* kube-proxy
* kube-scheduler
* calico 3.13.1
* nginx-ingress 1.5.5
* coredns
* etcd
Docker-ce 19.03.8
* docker-cli
* nfs-utils
K8s的安装方式:
- kubeadm 工具安装(官方推荐)
- 二进制包 安装
安装流程: WeiyiGeek.一键安装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#0.临时关闭swap和SELinux
swapoff -a
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX= disabled/' /etc/selinux/config
#1.修改hostname
hostnamectl set-hostname master-01|node-01
# 查看修改结果
hostnamectl status
# 设置 hostname 解析
echo "127.0.0.1 $(hostname)" >> /etc/hosts
#2.检查网络(所有节点上 Kubernetes 所使用的 IP 地址必须可以互通(无需 NAT 映射、无安全组或防火墙隔离)
ip route show && ip addr show ens192
# default via 10.10.107.1 dev ens192 proto static metric 100
# 10.10.107.0/24 dev ens192 proto kernel scope link src 10.10.107.191 metric 100
# 2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
# link/ether 00:50:56:ac:a5:af brd ff:ff:ff:ff:ff:ff
# inet 10.10.107.191/24 brd 10.10.107.255 scope global noprefixroute ens192
# valid_lft forever preferred_lft forever
# inet6 fe80::44ce:84ab:ef25:36cc/64 scope link noprefixroute
# valid_lft forever preferred_lft forever
# 3.安装docker及kubelet (在 master 节点和 worker 节点都要执行)
# 最后一个参数 1.18.2 用于指定 kubenetes 版本,支持所有 1.18.x 版本的安装
# 腾讯云 docker hub 镜像
# export REGISTRY_MIRROR="https://mirror.ccs.tencentyun.com"
# DaoCloud 镜像
# export REGISTRY_MIRROR="http://f1361db2.m.daocloud.io"
# 华为云镜像
# export REGISTRY_MIRROR="https://05f073ad3c0010ea0f4bc00b7105ec20.mirror.swr.myhuaweicloud.com"
# 阿里云 docker hub 镜像
export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com
curl -sSL https://kuboard.cn/install-script/v1.18.x/install_kubelet.sh | sh -s 1.18.2
Master 节点: WeiyiGeek.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# 4.初始化 master 节点环境变量说明
# * APISERVER_NAME 不能是 master 的 hostname
# * APISERVER_NAME 必须全为小写字母、数字、小数点,不能包含减号
# * POD_SUBNET 所使用的网段不能与 master节点/worker节点 所在的网段重叠: `export POD_SUBNET=10.100.0.1/16 命令`
# 只在 master 节点执行替换 x.x.x.x 为 master 节点实际 IP(请使用内网 IP)
# export 命令只在当前 shell 会话中有效,开启新的 shell 窗口后,如果要继续安装过程,请重新执行此处的 export 命令
export MASTER_IP=10.10.107.191
# 替换 apiserver.demo 为 您想要的 dnsName
export APISERVER_NAME=apiserver.weiyi
# Kubernetes 容器组所在的网段,该网段安装完成后,由 kubernetes 创建,事先并不存在于您的物理网络中
export POD_SUBNET=10.100.0.1/16
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
curl -sSL https://kuboard.cn/install-script/v1.18.x/init_master.sh | sh -s 1.18.2
# 5.检查 master 初始化结果
# 只在 master 节点执行执行如下命令,等待 3-10 分钟,直到所有的容器组处于 Running 状态
watch kubectl get pod -n kube-system -o wide
# NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
# calico-kube-controllers-5b8b769fcd-pv4g2 1/1 Running 0 11m 10.100.77.1 k8s <none> <none>
# calico-node-ssfqz 1/1 Running 0 11m 10.10.107.191 k8s <none> <none>
# coredns-546565776c-96nnf 1/1 Running 0 11m 10.100.77.3 k8s <none> <none>
# coredns-546565776c-bnkvl 1/1 Running 0 11m 10.100.77.2 k8s <none> <none>
# etcd-k8s 1/1 Running 0 11m 10.10.107.191 k8s <none> <none>
# kube-apiserver-k8s 1/1 Running 0 11m 10.10.107.191 k8s <none> <none>
# kube-controller-manager-k8s 1/1 Running 0 11m 10.10.107.191 k8s <none> <none>
# kube-proxy-8s5lv 1/1 Running 0 11m 10.10.107.191 k8s <none> <none>
# kube-scheduler-k8s 1/1 Running 0 11m 10.10.107.191 k8s <none> <none>
# 查看 master 节点初始化结果
kubectl get nodes -o wide
# NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
# k8s Ready master 6m58s v1.18.2 10.10.107.191 <none> CentOS Linux 7 (Core) 5.6.10-1.el7.elrepo.x86_64 docker://19.3.8
# 6.获得 join命令参数(master节点上运行)
kubeadm token create --print-join-command
W0506 22:22:32.850186 31335 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
# 将node加入到master节点中
kubeadm join apiserver.weiyi:6443 --token nuv3rj.j58fccxrcpmvabze --discovery-token-ca-cert-hash sha256:c35aafc3b03ff86c50798adb5745c893c4f6e79b3fdf16c24d348511d3100f0c
Works 节点: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# 7.只在 worker 节点执行
# 替换 x.x.x.x 为 master 节点的内网 IP
export MASTER_IP=10.10.107.191
# 替换 apiserver.demo 为初始化 master 节点时所使用的 APISERVER_NAME
export APISERVER_NAME=apiserver.weiyi
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
# 8.在上面步骤六中kubeadm token create 命令的输出 token
# 但是注意有效时间为 2 个小时,您可以使用此 token 初始化任意数量的 worker 节点。
kubeadm join apiserver.weiyi:6443 --token nuv3rj.j58fccxrcpmvabze --discovery-token-ca-cert-hash sha256:c35aafc3b03ff86c50798adb5745c893c4f6e79b3fdf16c24d348511d3100f0c
# [preflight] Running pre-flight checks
# [preflight] Reading configuration from the cluster...
# [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
# [kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.18" ConfigMap in the kube-system namespace
# [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
# [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
# [kubelet-start] Starting the kubelet
# [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
# This node has joined the cluster:
# * Certificate signing request was sent to apiserver and a response was received.
# * The Kubelet was informed of the new secure connection details.
# Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
结果检查1
2
3
4
5# 9.只在 master 节点执行,可以看到STATUS状态一切正常
kubectl get nodes -o wide
# NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
# k8s Ready master 16h v1.18.2 10.10.107.191 <none> CentOS Linux 7 (Core) 5.6.10-1.el7.elrepo.x86_64 docker://19.3.8
# node Ready <none> 10h v1.18.2 10.10.107.192 <none> CentOS Linux 7 (Core) 5.6.10-1.el7.elrepo.x86_64 docker://19.3.8
应用部署实例
描述:在 Kubernetes 上部署第一个应用程序,下图是在上面k8s原理图基础添加上了Deployment、Pod和Container
。
1.基础名词概念:
Deployment
:译名为部署, 在k8s中通过发布Deployment
可以创建应用程序(docker image) 的实例 (docker container)
,这个实例会被包含在称为 Pod 的概念中 Pod 是 k8s 中最小可管理单元。Kubernetes Deployment
:提供了一种完全不同的方式来管理应用程序, 通过创建应用程序实例并确保它们在集群节点中的运行实例个数,能够使应用程序从机器故障中恢复
;Kubernetes Deployment Controller
:持续监控创建应用程序实例,将在群集中资源最优的另一个 worker 节点上重新创建一个新的实例, 提供了一种自我修复机制来解决机器故障或维护问题。
Deployment 处于 master 节点上,通过发布 Deployment,master 节点会选择合适的 worker 节点创建 Container(即图中的正方体),Container 会被包含在 Pod (即蓝色圆圈)里。1
2
3
4
5
6
7
8
9#K8s Cluster
Master 节点:
- Deployment
Worker 节点:
- Node
- pod
- Container App
- Node Processes

WeiyiGeek.
2.实践应用部署:
描述:使用 kubectl 方式进行部署 nginx Deployment
Step1.创建Deployement YAML
文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19apiVersion: apps/v1 #与k8s集群版本有关,使用 kubectl api-versions 即可查看当前集群支持的版本
kind: Deployment #该配置的类型,我们使用的是 Deployment
metadata: #译名为元数据,即 Deployment 的一些基本属性和信息
name: nginx-deployment #Deployment 的名称
labels: #标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组,目前不需要理解
app: nginx #为该Deployment设置key为app,value为nginx的标签
spec: #这是关于该Deployment的描述,可以理解为你期待该Deployment在k8s中如何使用
replicas: 1 #使用该Deployment创建一个应用程序实例
selector: #标签选择器,与上面的标签共同作用,目前不需要理解
matchLabels: #选择包含标签app:nginx的资源
app: nginx
template: #这是选择或创建的Pod的模板
metadata: #Pod的元数据
labels: #Pod的标签,上面的selector即选择包含标签app:nginx的Pod
app: nginx
spec: #期望Pod实现的功能(即在pod中部署)
containers: #生成container,与docker中的container是同一种
- name: nginx #container的名称
image: nginx:latest #使用镜像nginx最新版本创建container,该container默认80端口可访问
Step2.应用后可以可分别查看到一个名为 nginx-deployment 的 Deployment 和一个名为 nginx-deployment-xxxxxxx 的 Pod1
2$ kubectl apply -f nginx-deployment.yaml
deployment.apps/nginx-deployment created
Step3.查看部署结果1
2
3
4
5
6
7
8
9
10
11
12
13
14# 查看 Deployment
kubectl get deployments
# NAME READY UP-TO-DATE AVAILABLE AGE
# nginx-deployment 1/1 1 1 36s
# 查看 Pod 与指定
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# nginx-deployment-674ff86d-btmt4 1/1 Running 0 53s
kubectl get pods -n default -o wide
# NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
# nginx-deployment-674ff86d-btmt4 1/1 Running 0 3h2m 10.100.167.129 node <none> <none>
至此你已经成功在k8s上部署了一个实例的nginx应用程序,
3.公布应用程序
描述:在创建Service(定义Pod容器组访问方式以及之间的相互依赖解耦
)的时候,通过设置配置文件中的 spec.type
字段的值,可以以不同方式向外部暴露应用程序:
方式如下:
- 1) ClusterIP(默认): 在群集中的内部IP上公布服务,这种方式的 Service(服务)只在集群内部可以访问到
- 2) NodePort : 使用 NAT 在集群中每个的同一端口上公布服务。这种方式下,可以通过访问集群中任意节点+端口号的方式访问服务
<NodeIP>:<NodePort>
(可以端口范围30000-32767
),且此时 ClusterIP 的访问方式仍然可用。 - 3) LoadBalancer: 在云环境中(需要云供应商可以支持)创建一个集群外部的负载均衡器,并为使用该负载均衡器的 IP 地址作为服务的访问地址。
此时 ClusterIP 和 NodePort 的访问方式仍然可用
。
Service 关联的Pod创建一个Replication Control(简称RC) 其RC文件包括以下三个关键信息;
- Pod定义
- Pod运行的副本数量(Replicas)-后面讲解Scaling伸缩应用程序
- Pod的被监控的目标标签(Label)
示例:nginx Deployment 创建一个 Service
- (1) 上面创建nginx的Deployment中定义了Labels,如下:
1
2
3
4metadata: #译名为元数据,即Deployment的一些基本属性和信息
name: nginx-deployment #Deployment的名称
labels: #标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组
app: nginx #为该Deployment设置key为app,value为nginx的标签 - (2) 创建编辑文件 nginx-service.yaml 内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17$nano nginx-service.yaml
apiVersion: v1 # k8s集群版本
kind: Service #该配置的类型使用Service
metadata:
name: nginx-service #Service 的名称
labels: #Service 自己的标签
app: nginx #为该 Service 设置 key 为 app,value 为 nginx 的标签
spec: #这是关于该 Service 的定义,描述了 Service 如何选择 Pod,如何被访问
selector: #标签选择器
app: nginx #选择包含标签 app:nginx 的 Pod
ports:
- name: nginx-port #端口的名字
protocol: TCP #协议类型 TCP/UDP
port: 80 #集群内的其他容器组可通过 80 端口访问 Service
nodePort: 30000 #通过任意节点的 30000 端口访问 Service ( The range of valid ports is 30000-32767)
targetPort: 80 #将请求转发到匹配 Pod 的 80 端口
type: NodePort #Serive的类型,ClusterIP/NodePort/LoaderBalancer (3) 执行命令并检查执行结果
1
2
3
4
5
6
7
8
9#构建Deploymenet部署pod中的container,利用services中的Lables来关联已经创建的Container
kubectl apply -f nginx-service.yaml
service/nginx-service created
#查看构建的services可查看到名称为 nginx-service 的服务
kubectl get services -o wide
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
# kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 40h <none>
# nginx-service NodePort 10.96.63.155 <none> 80:30000/TCP 32s app=nginx(4) 访问服务(在master或者worker中执行)
1
2
3
4
5
6
7
8
9
10
11
12
13#Master
[[email protected] ~]# curl http://10.10.107.191:30000/hello.html
[[email protected] ~]# curl http://10.100.77.0:30000/hello.html #tunl0
Hello World,Kubernetes!
#Worker
[[email protected] ~]# curl http://10.10.107.192:30000/hello.html
[[email protected] ~]# curl http://10.100.167.128:30000/hello.html #tunl0
Hello World,Kubernetes!
#Node
[[email protected] ~]# curl http://10.100.167.129:80/hello.html
Hello World,Kubernetes!到目前为止,我们已经成功部署好项目,并能够对其进行访问!
4.伸缩应用程序
描述:当流量增加时,我们需要对应用程序进行伸缩操作以满足系统性能需求。而在K8s中伸缩(Scaling)的实现可以通过更改 nginx-deployment.yaml 文件中部署的 replicas(副本数)来完成
;
Tips:我们前面创建了一个Deployment然后通过服务(Services)提供访问Pod的方式,下面通过更改部署中的 replicas(副本数)来完成扩展;1
2spec:
replicas: 2 #使用该Deployment创建两个应用程序实例
示例:下图中 Service A 只将访问流量转发到 IP 为 10.0.0.5 的Pod上修改了 Deployment 的 replicas 为 4 后,Kubernetes 又为该 Deployment 创建了 3 新的 Pod,这 4 个 Pod 有相同的标签。 WeiyiGeek.Scaling
因此Service A通过标签选择器与新的 Pod建立了对应关系,将访问流量通过负载均衡在 4 个 Pod 之间进行转发。
示例:将 nginx Deployment 扩容到 2 个副本1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21apiVersion: apps/v1 #与k8s集群版本有关,使用 kubectl api-versions 即可查看当前集群支持的版本
kind: Deployment #该配置的类型,我们使用的是 Deployment
metadata: #译名为元数据,即 Deployment 的一些基本属性和信息
name: nginx-deployment #Deployment 的名称
labels: #标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组,目前不需要理解
app: nginx #为该Deployment设置key为app,value为nginx的标签
spec: #这是关于该Deployment的描述,可以理解为你期待该Deployment在k8s中如何使用
replicas: 2 #使用该Deployment创建一个应用程序实例(动态扩容)
selector: #标签选择器,与上面的标签共同作用,目前不需要理解
matchLabels: #选择包含标签app:nginx的资源
app: nginx
template: #这是选择或创建的Pod的模板
metadata: #Pod的元数据
labels: #Pod的标签,上面的selector即选择包含标签app:nginx的Pod
app: nginx
spec: #期望Pod实现的功能(即在pod中部署)
containers: #生成container,与docker中的container是同一种
- name: nginx #container的名称
image: nginx:latest #使用镜像nginx最新版本创建container,该container默认80端口可访问
ports:
- containerPort: 80
执行命令进行部署扩容1
kubectl apply -f nginx-deployment.yaml
查看结果 WeiyiGeek.应用扩容1
watch kubectl get pods -o wide
应用访问: WeiyiGeek.应用负载均衡1
2
3
4
5
6
7[[email protected] ~]# curl http://10.100.167.132/test.html
<b>Scaling - 10.100.167.132</b>
[[email protected] ~]# curl http://10.100.167.131/test.html
<b>Scaling - 10.100.167.131</b>
#Cluster IP / Worker Node IP
http://10.10.107.191:30000/test.html
PS:一旦运行了多个应用程序实例,就可以在不停机的情况下执行滚动更新了;
5.执行滚动更新
描述:在 Kubernetes 中通过 Rolling Update 滚动更新来进行应用版本的迭代部署,滚动更新允许以下操作:;
- 将应用程序从准上线环境升级到生产环境(通过更新容器镜像)
- 回滚到以前的版本
- 持续集成和持续交付应用程序,无需停机
补充说明:
- 将应用程序 Scale Up(扩容)为多个实例,这是执行更新而不影响应用程序可用性的前提(
如果只有一个实例那就没得玩了
) - k8s更新多副本的 Deployment 的版本时,会逐步的创建新版本的 Pod,逐步的停止旧版本的 Pod,以便使应用一直处于可用状态。
(该过程中Service 能够监视 Pod 的状态,将流量始终转发到可用的 Pod 上)
- 在K8S中更新是版本化的,任何部署更新都可以恢复为以前的(稳定)版本。
示例:
- 1) 原本 Service A 将流量负载均衡到 4 个旧版本的 Pod (当中的容器为 绿色)上
- 2) 更新完 Deployment 部署文件中的镜像版本后,master 节点选择了一个 worker 节点,并根据新的镜像版本创建 Pod(紫色容器)。
- 3) 同步骤2再创建一个新的 Pod 替换一个原有的 Pod
- 4) 如此 Rolling Update 滚动更新,直到所有旧版本 Pod 均移除,新版本 Pod 也达到 Deployment 部署文件中定义的副本数,则滚动更新完成
WeiyiGeek.update
实例:更新 nginx Deployment
Step1.修改文件nginx-deployment-update.yaml中 image 镜像的标签,如下所示1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21apiVersion: apps/v1 #与k8s集群版本有关,使用 kubectl api-versions 即可查看当前集群支持的版本
kind: Deployment #该配置的类型,我们使用的是 Deployment
metadata: #译名为元数据,即 Deployment 的一些基本属性和信息
name: nginx-deployment #Deployment 的名称
labels: #标签,可以灵活定位一个或多个资源,其中key和value均可自定义,可以定义多组,目前不需要理解
app: nginx #为该Deployment设置key为app,value为nginx的标签
spec: #这是关于该Deployment的描述,可以理解为你期待该Deployment在k8s中如何使用
replicas: 2 #使用该Deployment创建一个应用程序实例(动态扩容)
selector: #标签选择器,与上面的标签共同作用,目前不需要理解
matchLabels: #选择包含标签app:nginx的资源
app: nginx
template: #这是选择或创建的Pod的模板
metadata: #Pod的元数据
labels: #Pod的标签,上面的selector即选择包含标签app:nginx的Pod
app: nginx
spec: #期望Pod实现的功能(即在pod中部署)
containers: #生成container,与docker中的container是同一种
- name: nginx #container的名称
image: nginx:1.17.9 #使用镜像nginx:1.17.9替换原来的nginx:1.17.10
ports:
- containerPort: 80 #容器开放端口
Step2.执行部署命令与查看过程结果 WeiyiGeek.滚动更新1
2
3
4
5
6
7
8
9
10
11
12#部署命令
kubectl apply -f nginx-deployment-update.yaml
#观察到 pod 逐个被替换的过程
watch kubectl get pods -l app=nginx
#替换版本查看
kubectl describe pods -l app=nginx | egrep "^Name:|Image:"
Name: nginx-deployment-b48955944-bz4xr
Image: nginx:1.17.9
Name: nginx-deployment-b48955944-ng6cs
Image: nginx:1.17.9