文档来自:📚 Kubenetes(K8S)简介 - K8S 教程 - 易文档 (easydoc.net)
简介
它是一个为 容器化 应用提供集群部署和管理的开源工具,由 Google 开发。
kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。它的目的就是是实现资源管理的自动化,主要提供了如下的主要功能:
自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器
弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
服务发现:服务可以通过自动发现的形式找到它所依赖的服务
负载均衡:如果一个服务起动了多个容器,能够自动实现请求的负载均衡
版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
存储编排:可以根据容器自身的需求自动创建存储卷

不同的应用部署方案
在部署应用程序的方式上,主要经历了三个时代:
传统部署:互联网早期,会直接将应用程序部署在物理机上
优点:简单,不需要其它技术的参与
缺点:不能为应用程序定义资源使用边界,很难合理地分配计算资源,而且程序之间容易产生影响
虚拟化部署:可以在一台物理机上运行多个虚拟机,每个虚拟机都是独立的一个环境
优点:程序环境不会相互影响,提供一定程度的安全性
缺点:增加了操作系统,浪费了部分资源
容器化部署:与虚拟化类似,但是共享了操作系统
优点:
可以保证每个容器拥有自己的文件系统、CPU、内存、进程空间等
运行应用程序所需要的资源都被容器包装,并和底层基础架构解耦
容器化的应用程序可以跨云服务商、跨Linux操作系统发行版进行部署
容器化部署方式带来了很多的遍历,但是也会出现一些问题,比如说“
- 一个容器故障停机了,怎么样让另外一个容器立刻启动去替补停机的容器
- 当并发访问量变大的时候,怎么样做到横向扩展容器数量
这些容器管理的问题统称为容器编排问题,为了解决这些容器编排问题,就产生了一些容器编排的软件:
- Swarm:Docker自己的容器编排工具
- Mesos:Apache的一个资源统一管控的工具,需要和Marathon结合使用
- Kubernetes:Google开源的容器编排工具
什么时候需要k8s?
当你的应用只是跑在一台机器,直接一个 docker + docker-compose 就够了,方便轻松;
当你的应用需要跑在 3,4 台机器上,你依旧可以每台机器单独配置运行环境 + 负载均衡器;
当你应用访问数不断增加,机器逐渐增加到十几台、上百台、上千台时,每次加机器、软件更新、版本回滚,都会变得非常麻烦、痛不欲生,再也不能好好的摸鱼了,人生浪费在那些没技术含量的重复性工作上。
这时候,Kubernetes 就可以一展身手了,让你轻松管理百万千万台机器的集群。“谈笑间,樯橹灰飞烟灭”,享受着一手掌控所有,年薪百万指日可待。
Kubernates 可以为你提供集中式的管理集群机器和应用,加机器、版本升级、版本回滚,那都是一个命令就搞定的事,不停机的灰度更新,确保高可用、高性能、高扩展。
Kubernetes组件
一个Kubernetes集群主要是由**控制节点(master)、工作节点(node)**构成,每个节点上都会安装不同的组件。
master:集群的控制平面,负责集群的决策
ApiServer:资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制
Scheduler:负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上
ControllerManager:负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等
Etcd:负责存储集群中各种资源对象的信息
node:集群的数据平面,负责为容器提供运行环境
Kubelet:负责维护容器的生命周期,即通过控制docker,来创建、更新、销毁容器
KubeProxy:负责提供集群内部的服务发现和负载均衡
Docker:负责节点上容器的各种操作

下面,以部署一个nginx服务来说明kubernetes系统各个组件调用关系:
首先要明确,一旦kubernetes环境启动之后,master和node都会将自身的信息存储到etcd数据库中
一个nginx服务的安装请求会首先被发送到master节点的apiServer组件
apiServer组件会调用scheduler组件来决定到底应该把这个服务安装到哪个node节点上
在此时,它会从etcd中读取各个node节点的信息,然后按照一定的算法进行选择,并将结果告知apiServerapiServer调用controller-manager去调度Node节点安装nginx服务
kubelet接收到指令后,会通知docker,然后由docker来启动一个nginx的pod
pod是kubernetes的最小操作单元,容器必须跑在pod中至此一个Nginx服务就运行了,如果需要访问Nginx,就需要通过kube-proxy来对pod产生访问代理
这样,外界用户就可以访问集群中的Nginx服务了
Kubernetes 组件
kube-apiserver API 服务器,公开了 Kubernetes APIetcd 键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库kube-scheduler 调度 Pod 到哪个节点运行kube-controller 集群控制器cloud-controller 与云服务商交互

k8s集群架构

master
主节点,控制平台,不需要很高性能,不跑任务,通常一个就行了,也可以开多个主节点来提高集群可用度。
worker
工作节点,可以是虚拟机或物理计算机,任务都在这里跑,机器性能需要好点;通常都有很多个,可以不断加机器扩大集群;每个工作节点由主节点管理
重要概念 Pod
豆荚,K8S 调度、管理的最小单位,一个 Pod 可以包含一个或多个容器,每个 Pod 有自己的虚拟IP。一个工作节点可以有多个 pod,主节点会考量负载自动调度 pod 到哪个节点运行。
Controller
控制器,通过它来实现对pod的管理,比如启动pod、停止pod、伸缩pod的数是等等
Service
pod对外服务的统一入口,下面可以维护者同一类的多个pod
Label
标签,用于对pod进行分类,同一类pod会拥有相同的标签
NameSpace
命名空间,用来隔离pod的运行环境

k8s架构

APISERVER:所有服务访问统一入口
CrontrollerManager:维持副本期望数目
Scheduler:负责介绍任务…选择合适的节点进行分配任务.
ETCD:键值对数据库储存K8s集群所有重要信息(持久化)
Kubelet:真接跟容器弘警交互实现容器的生命周期管理
Kube-poxy:负责写入规则至IPTABLES、IPVS实现服务映射访问的
COREDNS:可以为集群中的SVC创建一个域名IP的对应关系解析
DASHBOARD:给K8S 集群提供一个B/S结构访点体系
INGRESS CONTROLLER:官方只能实现四层代理,INGRESS 可以实现七层代理
FEDERATION:提供一个可以跨集群中心多K8S统一管官理功能
PROMETHEUS:提供K8S集群的监控能力
ELK:提供K8s集群巳志统一分析介入平台
pod
pod类型:
- 自助式pod
- 控制器管理的pod
pod控制器类型
ReplicationController & ReplicaSet & Deployment
- HPA (HorizontalPodAutoScale)
StatefullSet
DaemonSet
Job,Cronjob
ReplicationController用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来替代;而如果异常多出来的容器也会自动回收。在新版本的Kubernetes中建议使用ReplicaSet来取代 ReplicationControlle
ReplicaSet 跟ReplicationController没有本质的不同,只是名字不一样,并且ReplicaSet支持集合式的 selector
虽然ReplicaSet可以独立使用,但一般还是建议使用Deployment来自动管理ReplicaSet ,这样就无需担心跟其他机制的不兼容问题(比如 ReplicaSet 不支持rolling-update但 Deployment支持)
StatefulSet 是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括:
- 稳定的持久化存储,即 Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
- 稳定的网络标志,即 Pod重新调度后其 PodName和 HostName不变,基于Headless Service(即没有Cluster IP的 Service )来实现
- 有序部署,有序扩展,即 Pod 是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从О到N-1,在下一个Pod运行之前所有之前的 Pod必须都是Running 和 Ready状态),基于init containers 来实现
- 有序收缩,有序删除(即从 N-1到0)
DaemonSet确保全部(或者一些)Node 上运行一个Pod 的副本。当有 Node 加入集群时,也会为他们新增一个Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除DaemonSet 将会删除它创建的所有Pod
使用DaemonSet 的一些典型用法:
运行集群存储daemon,例如在每个Node上运行glusterd、cepho
在每个Node 上运行日志收集daemon,例如fluentd、logstash
在每个Node 上运行监控daemon,例如Prometheus Node Exporter
网络通讯方式
Kubernetes 的网络模型假定了所有Pod都在一个可以直接连通的扁平的网络空间中,这在GCE (Google Compute Engine)里面是现成的网络模型,Kubernetes假定这个网络已经存在。而在私有云里搭建Kubernetes集群,就不能假定这个网络已经存在了。我们需要自己实现这个网络假设,将不同节点上的 Docker容器之间的互相访问先打通,然后运行Kubernetes
同一个Pod内的多个容器之间:lo
Pod 之间的通讯:Overlay Network
Pod 与 Service之间的通讯:各节点的 Iptables规则
Flannel是CoreOS团队针对Kubernetes 设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。而且它还能在这些IP地址之间建立一个覆盖网络(Overlay Network),通过这个覆盖网络,将数据包原封
不动地传递到目标容器内

ETCD之Flannel 提供说明:
存储管理Flannel 可分配的IP地址段资源
监控ETCD中每个Pod 的实际地址,并在内存中建立维护Pod节点路由表
同一个Pod 内部通讯:同一个Pod共享同一个网络命名空间,共享同一个Linux 协议栈
Pod1至Pod2
Pod1与 Pod2不在同一台主机,Pod的地址是与docker0在同一个网段的,但dockerO网段与宿主机网卡是两个完全不同的IP网段,并且不同Node之间的通信只能通过宿主机的物理网卡进行。将Pod的IP和所在Node的IP关联起来,通过这个关联让Pod可以互相访问
Pod1 与 Pod2在同一台机器,由Docker0网桥直接转发请求至 Pod2,不需要经过 Flannel 演示
Pod 至Service 的网络:目前基于性能考虑,全部为iptables(这个比较老了,现在用LVS)维护和转发
Pod到外网: Pod向外网发送请求,查找路由表,转发数据包到宿主机的网卡,宿主网卡完成路由选择后,iptables执行Masquerade,把源IP更改为宿主网卡的IP,然后向外网服务器发送请求
外网访问Pod:Service

集群环境搭建
环境规划
集群类型
kubernetes集群大体上分为两类:一主多从和多主多从
- 一主多从:一台Master节点和多台Node节点,搭建简单,但是单机故障风险,适合用于测试环境
- 多主多从:多台Master节点和多台Node节点,搭建麻烦,安全性高,适合用于生产环境

安装方式
kubernetes有多种部署方式,目前主流的方式有kubeadm、minikube、二进制包
- minikube:一个用于快速搭建单节点kubernetes的工具
- kubeadm:一个用于快速搭建kubernetes集群的工具
- 二进制包:从官网下载每个组件的二进制包,依次去安装,此方式对于理解kubernetes组件更加有效
主机规划
| 作用 | IP地址 | 操作系统 | 配置 |
|---|---|---|---|
| Master | 192.168.31.100 | centos7 基础设施服务器 | 2颗CPU 2G内存 50G硬盘 |
| Node1 | 192.168.31.101 | centos7 基础设施服务器 | 2颗CPU 2G内存 50G硬盘 |
| Node2 | 192.168.31.102 | centos7 基础设施服务器 | 2颗CPU 2G内存 50G硬盘 |
环境搭建
本次环境搭建需要安装三台Centos服务器(一主二从),然后在每台服务器中分别安装docker (18.06.3),kubeadm (1.17.4) , kubelet (1.17.4) , kubectl (1.17.4)程序。
主机安装
本次环境搭建需要安装三台Centos服务器(一主二从),然后在每台服务器中分别安装docker (18.06.3),kubeadm (1.17.4) . kubelet (1.17.4) , kubectl (1.17.4)程序。
环境初始化
1、检查操作系统的版本
1 | 此方式安装kubernetes集群要求centos版本要在7.5或之上 |
2、主机名解析
为了方便后面集群节点间的直接调用,在这配置一下主机名解析,企业中推荐使用内部DNS服务器
1 | 主机名解析 编辑三台服务器的/etc/hosts文件,添加下面内容 |
3、时间同步
kubernetes要求集群中的节点时间必须精确一致,这里直接使用chronyd服务从网络同步时间
企业中建议配置内部的时间同步服务器
1 | 启动chronyd服务 |
4、禁用iptables和firewalld服务
kubernetes和docker在运行中会产生大量的iptables规则,为了不让系统规则跟它们混淆,直接关闭系统的规则
1 | 关闭firewalld服务 |
5、禁用selinux
selinux是Linux系统下的一个安全服务,如果不关闭它,在安装集群中会产生各种各样的奇葩问题
1 | 编辑/etc/selinux/config 文件,修改SELINUX的值为disabled |
6、禁用swap分区
swap分区指的是虚拟内存分区,它的作用是在物理内存使用完之后,将磁盘空间虚拟成内存来使用
启用swap设备会对系统的性能产生非常负面的影响,因此kubernetes要求每个节点都要禁用swap设备
但是如果因为某些原因确实不能关闭swap分区,就需要在集群安装过程中通过明确的参数进行配置说明
1 | 编辑分区配置文件/etc/fstab,注释swap分区一行 |
7、修改Linux的内核参数
1 | 修改Linux的内核参数,添加网桥过滤和地址转发功能 |

8、配置ipvs功能
在kubernetes中service有两种代理模式,一种是基于iptables的,一种是基于ipvs的
两者比较的话,ipvs的性能明显要高一些,但是如果要使用它,需要手动加载ipvs模块
1 | 1 安装ipset和ipvsadm |

9、重启服务器
上面步骤完成之后,需要重新启动Linux系统
安装docker
1 | 1 切换镜像源 |
安装kubernetes组件
1 | 由于kubernetes的镜像源在国外,速度比较慢,这里切换成国内的镜像源 |
准备集群镜像
1 | 在安装kubernetes集群之前,必须要提前准备好集群需要的镜像,所需镜像可以通过下面命令查看 |
以上方法我安装有问题,我使用以下脚本方法正确
1 | vim get_images.sh |
集群初始化
下面开始对集群进行初始化,并将node节点加入到集群中
下面操作只需要在master节点上执行即可
1 | 创建集群 |

按照提示执行
1 | mkdir -p $HOME/.kube |
要想node加入到master中,只需在node1和node2中执行一下命令
1 | kubeadm join 192.168.59.100:6443 --token x7x7ro.kqkvdzicqx8ddc33 \ |
这时,在master中就可以看到节点信息了
1 | [root@master ~]# kubectl get nodes |
但是此处的STATUS是NotReady,因为网络还没有搭建
安装网络插件
kubernetes支持多种网络插件,比如flannel、calico、canal等等,任选一种使用即可,本次选择flannel
下面操作依旧只在master节点执行即可,插件使用的是DaemonSet的控制器,它会在每个节点上都运行
1 | 获取fannel的配置文件 |
至此kubernetes的集群环境搭建完成
服务部署
接下来在kubernetes集群中部署一个Nginx程序,测试下集群是否在正常工作。
1 | 部署nginx |
此时访问192.168.59.100:32160就可以访问Nginx了
资源管理
本章节主要介绍YAML语法和kubernetes的资源管理方式
资源管理介绍
在kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理kubernetes
kubernetes的本质上就是一个集群系统,用户可以在集群中部署各种服务,所谓的部署服务,其实就是在kubernetes集群中运行一个个的容器,并将指定的程序跑在容器中。
kubernetes的最小管理单元是pod而不是容器,所以只能将容器放在
pod中,而kubernetes一般也不会直接管理pod,而是通过pod管理器来管理pod的。pod可以提供服务之后,就要考虑如何访问pod中服务,kubernetes提供了service资源实现这个功能。
当然,如果pod中程序的数据需要持久化,kubernetes还提供各种存储

学习kubernetes的核心,就是学习如何对集群上的Pod、Pod控制器、Service、存储等各种资源进行操作
YAML语言介绍
YAML是一个类似XML、JSON的标记性语言。它强调以数据为中心,并不是以标识语言为重点。因而YAML本身的定义比较简单,号称“一种人性化的数据格式语言”。
1 | <person> |
1 | person: |
YAML的语言比较简单,主要由下面几个:
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格(低版本限制)
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- ‘#’表示注释
YAML支持以下几种数据类型:
- 纯量:单个的、不可再分的值
- 对象:键值对的集合,又称为映射(mapping)/ 哈希(hash) / 字典(dictionary)
- 数组:一组按次序排列的值,又称为序列(sequence)/ 列表(list)
1 | # 纯量,就是指的一个简单的值,字符串、布尔值、整数、浮点数、Null、时间、日期 |
1 | # 对象 |
1 | # 数组 |
注意:
1 书写YAML切记: 后面要加一个空格
2 如果需要将多段YAML配置放在一个文件中,中间要使用—分割
资源管理方式
- 命令式对象管理:直接使用命令去操作kubernetes资源
1 | kubectl run nginx-pod --image=nginx:1.17.1 --port=80 |
- 命令式对象配置:通过命令配置和配置文件去操作kubernetes资源
1 | kubectl create/patch -f nginx-pod.yaml |
- 声明式对象配置:通过apply命令和配置文件去操作kubernetes资源
1 | kubectl apply -f nginx-pod.yaml |
| 类型 | 操作对象 | 适用环境 | 优点 | 缺点 |
|---|---|---|---|---|
| 命令式对象管理 | 对象 | 测试 | 简单 | 只能操作活动对象,无法审计、跟踪 |
| 命令式对象配置 | 文件 | 开发 | 可以审计、跟踪 | 项目大时,配置文件多,操作麻烦 |
| 声明式对象配置 | 目录 | 开发 | 支持目录操作 | 意外情况下难以调试 |
命令式对象管理
kubectl命令
kubectl是kubernetes集群的命令行工具,通过宦能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署。kubectl命令的语法如下:
1 | kubectl [command] [type] [name] [flags] |
command:指定要对资源执行的操作,例如create、get、delete
type:指定资源类型,比如deployment、pod、service
name:指定资源的名称,名称大小写敏感
flags:指定额外的可选参数
1 | 查看所有pod |
资源类型
kubernetes中所有的内容都抽象为资源,可以通过下面的命令进行查看:
1 | kubectl api-resources |
经常使用的资源有:
| 资源分类 | 资源名称 | 缩写 | 资源作用 |
|---|---|---|---|
| 集群级别资源 | nodes | no | 集群组成部分 |
| namespaces | ns | 隔离Pod | |
| pod资源 | pods | po | 装载容器 |
| pod资源控制器 | replicationcontrollers | rc | 控制pod资源 |
| replicasets | rs | 控制pod资源 | |
| deployments | deploy | 控制pod资源 | |
| daemonsets | ds | 控制pod资源 | |
| jobs | 控制pod资源 | ||
| cronjobs | cj | 控制pod资源 | |
| horizontalpodautoscalers | hpa | 控制pod资源 | |
| statefulsets | sts | 控制pod资源 | |
| 服务发现资源 | services | svc | 统一pod对外接口 |
| ingress | ing | 统一pod对外接口 | |
| 存储资源 | volumeattachments | 存储 | |
| persistentvolumes | pv | 存储 | |
| persistentvolumeclaims | pvc | 存储 | |
| 配置资源 | configmaps | cm | 配置 |
| secrets | 配置 |
操作
kubernetes允许对资源进行多种操作,可以通过–help查看详细的操作命令
1 | kubectl --help |
经常使用的操作有下面这些:
| 命令分类 | 命令 | 翻译 | 命令作用 |
|---|---|---|---|
| 基本命令 | create | 创建 | 创建一个资源 |
| edit | 编辑 | 编辑一个资源 | |
| get | 获取 | 获取一个资源 | |
| patch | 更新 | 更新一个资源 | |
| delete | 删除 | 删除一个资源 | |
| explain | 解释 | 展示资源文档 | |
| 运行和调试 | run | 运行 | 在集群中运行一个指定的镜像 |
| expose | 暴露 | 暴露资源为Service | |
| describe | 描述 | 显示资源内部信息 | |
| logs | 日志输出容器在 pod 中的日志 | 输出容器在 pod 中的日志 | |
| attach | 缠绕进入运行中的容器 | 进入运行中的容器 | |
| exec | 执行容器中的一个命令 | 执行容器中的一个命令 | |
| cp | 复制 | 在Pod内外复制文件 | |
| rollout | 首次展示 | 管理资源的发布 | |
| scale | 规模 | 扩(缩)容Pod的数量 | |
| autoscale | 自动调整 | 自动调整Pod的数量 | |
| 高级命令 | apply | rc | 通过文件对资源进行配置 |
| label | 标签 | 更新资源上的标签 | |
| 其他命令 | cluster-info | 集群信息 | 显示集群信息 |
| version | 版本 | 显示当前Server和Client的版本 |
下面以一个namespace的创建和删除简单演示:
1 | 创建一个namespace |
命令式对象配置
命令式对象配置就是使用命令配合配置文件一起来操作kubernetes资源。
1)创建一个nginxpod.yaml,内容如下:
1 | apiVersion: v1 |
2)执行create命令,创建资源:
1 | [root@master ~]# kubectl create -f nginxpod.yaml |
此时发现创建了两个资源对象,分别是namespace和pod
3)执行get命令,查看资源:
1 | [root@master ~]# kubectl get -f nginxpod.yaml |
4)执行delete命令,删除资源:
1 | [root@master ~]# kubectl delete -f nginxpod.yaml |
此时发现两个资源对象呗删除了
1 | 小结: |
声明式对象配置
声明式对象配置跟命令式对象配置很相似,但是它只有一个命令apply。
1 | 首先执行一次kubectl apply -f yaml文件,发现创建了资源 |
1 | 总结: |
扩展:kubectl可以在node节点上运行吗?
kubectl的运行是需要进行配置的,它的配置文件是$HOME/.kube,如果想要在node节点运行此命令,需要将master上的.kube文件复制到node节点上,即在master节点上执行下面操作:
1 | scp -r HOME/.kube node1: HOME/ |
使用推荐:三种方式如何选择?
创建/更新资源 使用声明式对象配置kubectl apply -f XXX.yaml
删除资源 使用命令式对象配置kubectl delete -f XXX.yaml
查询资源 使用命令式对象管理kubectl get(describe)资源名称
实战入门
本章节将介绍如何在kubernetes集群中部署一个Nginx服务,并且能够对其进行访问。
Namespace
Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。
默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的”组”,以方便不同的组的资源进行隔离使用和管理。
可以通过kubernetes的授权机制,将不同的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等等,来实现租户可用资源的管理。

kubernetes在集群启动之后,会默认创建几个namespace
1 | [root@master ~]# kubectl get namespace |
下面来看namespace资源的具体操作:
查看
1 | 1 查看所有ns |
创建
1 | 创建namespace |
删除
1 | 删除namespace |
配置方式
首先准备一个yaml文件:ns-dev.yaml
1 | apiVersion: v1 |
然后就可以执行对应的创建和删除命令了:
创建: kubectl create -f ns-dev.yaml
删除: kubectl delete -f ns-dev.yaml
Pod
经过前面的学习已经知道,程序要运行,必须部署在容器中,而容器必须存在于Pod中。
Pod是kubernetes集群进行管理的最小单元,也是kubernetes中最为重要和基本的概念。
Pod可以认为是容器的封装,一个Pod中可以存在一个或者多个容器。

kubernetes在集群启动之后,集群中的各个组件也都是以Pod方式运行的。可以通过以下命令查看:
1 | [root@master ~]# kubectl get pod -n kube-system |
创建并运行
kubernetes没有提供单独运行Pod的命令,都是通过Pod控制器来实现的
1 | 命令格式:kubectl run (pod控制器名称)[参数] |
查看pod信息
1 | 查看pod基本信息 |
访问Pod
1 | 访问podIP |
删除指定Pod
1 | [root@master ~]# kubectl get pods -n dev |
配置操作
创建一个pod-nginx.yaml,内容如下:
1 | apiVersion : v1 |
然后就可以执行相应的创建和删除命令了:
创建:kubectl create -f pod-nginx.yaml
删除:kubectl delete -f pod-nginx.yaml
Label
Label是kubernetes系统中的一个重要概念。它的作用就是在资源上添加标识,用来对它们进行区分和选择。
Label的特点:
一个Label会以key/value键值对的形式附加到各种对象上,如Node、Pod、Service等等
一个资源对象可以定义任意数星的Label,同一个Label也可以被添加到任意数量的资源对象上去
Label通常在资源对象定义时确定,当然也可以在对象创建后动态添加或者删除
可以通过Label实现资源的多维度分组,以便灵活、方便地进行资源分配、调度、配置、部署等管理工作。
—些常用的Label示例如下:
版本标签:”version”:”release”, “version”:”stable”…
环境标签:”environment”:”dev”, “environment”:”test”,”environment”:”pro”
架构标签:”tier”:”frontend”, “tier”:”backend”
标签定义完毕之后,还要考虑到标签的选择,这就要使用到Label Selector,即:
Label用于给某个资源对象定义标识
Label Selector用于查询和筛选拥有某些标签的资源对象
当前有两种Label Selector:
基于等式的Label Selector
name = slave:选择所有包含Label中key=”name”且value=”slave”的对象
env != production:选择所有包括Label中的key=”env”且value不等于”production”的对象
基于集合的Label Selector
name in (master, slave):选择所有包含Label中的key=”name”且value=”master”或”slave”的对象
name not in (frontend):选择所有包含Label中的key=”name”且value不等于”frontend”的对象
标签的选择条件可以使用多个,此时将多个Label Selector进行组合,使用逗号”,”进行分隔即可。例如:
name=slave, env!=production
name not in (frontend), env!=production
命令方式
1 | 为pod资源打标签 |
配置方式
1 | apiVersion: v1 |
然后执行对应的更新命令:kubectl apply -f pod-nginx.yaml
Deployment
在kubernetes中,Pod是最小的控制单元,但是kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成的。Pod控制器用于pod的管理,确保pod资源符合预期的状态,当pod的资源出现故障时,会尝试进行重启或重建pod。
在kubernetes中Pod控制器的种类有很多,本章节只介绍一种:Deployment。

命令操作
1 | 命令格式: kubectl run deployment名称 [参数] |
配置操作
创建一个deploy-nginx.yaml,内容如下:
1 | apiVersion: apps/v1 |
执行命令:kubectl create -f deploy-nginx.yaml
Service
通过上节课的学习,已经能够利用Deployment来创建一组Pod来提供具有高可用性的服务。
虽然每个Pod都会分配一个单独的Pod lP,然而却存在如下两问题:
Pod IP会随着Pod的重建产生变化
Pod IP仅仅是集群内可见的虚拟IP,外部无法访问
这样对于访问这个服务带来了难度。因此,kubernetes设计了Service来解决这个问题。
Service可以看作是一组同类Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。

操作一:创建集群内部可访问的Service
1 | 暴露Service |
操作二:创建集群外部也可访问的Service
1 | 上面创建的Service的type类型为ClusterIP,这个ip地址只有集群内部可访问 |

删除Service
1 | [root@master ~]# kubectl delete svc svc-nginx1 -n dev |
配置方式
创建一个svc-nginx.yaml,内容如下:
1 | apiVersion: v1 |
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f svc-nginx.yaml
删除:kubectl delete -f svc-nginx.yaml
Pod详解
Pod介绍
Pod结构

每个Pod中都可以包含一个或者多个容器,这些容易可以分为两类:
用户程序所在程序,数量可多可少
Pause容器,这是每个Pod都会有的一个根容器,它的作用有两个:
可以以它为依据,评估整个pod的健康状态
可以在根容器上设置ip地址,其它容器都共享此IP(Pod IP),以实现Pod内部的网络通信
这里是pod内部的通信,pod之间的通信采用虚拟二层网络技术来实现,我们当前环境用的是Flannel
Pod定义
1 | apiVersion: v1 #必选,版本号,例如v1 |
1 | 小提示: |
在kubernetes中基本所有资源的一级属性都是一样的,主要包含5部分:
- apiVersion 版本,由kubernetes内部定义,版本号必须可以用 kubectl api-versions 查询到
- kind 类型,由kubernetes内部定义,版本号必须可以用 kubectl api-resources 查询到
- metadata 元数据,主要是资源标识和说明,常用的有name、namespace、labels等
- spec 描述,这是配置中最重要的一部分,里面是对各种资源配置的详细描述
- status 状态信息,里面的内容不需要定义,由kubernetes自动生成
在上面的属性中,spec是接下来研究的重点,继续看下它的常见子属性:
- containers <[]Object> 容器列表,用于定义容器的详细信息
- nodeName 根据nodeName的值将pod调度到指定的Node节点上
- nodeSelector <map[]> 根据NodeSelector中定义的信息选择将该Pod调度到包含这些label的Node 上
- hostNetwork 是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
- volumes <[]Object> 存储卷,用于定义Pod上面挂在的存储信息
- restartPolicy 重启策略,表示Pod在遇到故障的时候的处理策略
Pod配置
本小节主要研究pod.spec.containers属性,这也是pod配置中最为关键的一项配置。
1 | [root@master ~]# kubectl explain pod.spec.containers |
基本配置
创建pod-base.yaml文件,内容如下:
1 | apiVersion: v1 |
上面定义了一个比较简单Pod的配置,里面有两个容器:
- nginx:用1.17.1版本的nginx镜像创建,(nginx是一个轻量级web容器)
- busybox:用1.30版本的busybox镜像创建,(busybox是一个小巧的linux命令集合)
1 | 创建Pod |
镜像拉取
创建pod.imagepullpolicy.yaml文件,内容如下:
1 | apiVersion: v1 |
imagePullPolicy,用于设置镜像拉取策略,kubernetes支持配置三种拉取策略:
- Always:总是从远程仓库拉取镜像(一直远程下载)
- IfNotPresent:本地有则使用本地镜像,本地没有则从远程仓库拉取镜像(本地有就本地 本地没就远程下载)
- Never:只使用本地镜像,从不去远程仓库拉取,本地没有就报错 (一直使用本地)
默认值说明:
如果镜像tag为具体版本号, 默认策略是:IfNotPresent
如果镜像tag为:latest(最终版本) ,默认策略是always
1 | # 创建Pod |
启动命令
在前面的案例中,一直有一个问题没有解决,就是的busybox容器一直没有成功运行,那么到底是什么原因导致这个容器的故障呢?
原来busybox并不是一个程序,而是类似于一个工具类的集合,kubernetes集群启动管理后,它会自动关闭。解决方法就是让其一直在运行,这就用到了command配置。
创建pod-command.yaml文件,内容如下:
1 | apiVersion: v1 |
command,用于在pod中的容器初始化完毕之后运行一个命令。
稍微解释下上面命令的意思:
“/bin/sh”,”-c”, 使用sh执行命令
touch /tmp/hello.txt; 创建一个/tmp/hello.txt 文件
while true;do /bin/echo $(date +%T) >> /tmp/hello.txt; sleep 3; done; 每隔3秒向文件中写入当前时间
1 | [root@master ~]# kubectl create -f pod-command.yaml |
1 | 特别说明: |
环境变量
创建pod-env.yaml文件,内容如下:
1 | apiVersion: v1 |
env,环境变量,用于在pod中的容器设置环境变量。
1 | 创建Pod |
这种方式不是很推荐,推荐将这些配置单独存储在配置文件中,这种方式将在后面介绍。
端口设置
本小节来介绍容器的端口设置,也就是containers的ports选项。
首先看下ports支持的子选项:
1 | [root@master ~]# kubectl explain pod.spec.containers.ports |
接下来,编写一个测试案例,创建pod-ports.yaml
1 | apiVersion: v1 |
1 | 创建Pod |
访问容器中的程序需要使用的是Podip:containerPort
资源配额
容器中的程序要运行,肯定是要占用一定资源的,比如cpu和内存等,如果不对某个容器的资源做限制,那么它就可能吃掉大量资源,导致其它容器无法运行。针对这种情况,kubernetes提供了对内存和cpu的资源进行配额的机制,这种机制主要通过resources选项实现,他有两个子选项:
- limits:用于限制运行时容器的最大占用资源,当容器占用资源超过limits时会被终止,并进行重启
- requests :用于设置容器需要的最小资源,如果环境资源不够,容器将无法启动
可以通过上面两个选项设置资源的上下限。
接下来,编写一个测试案例,创建pod-resources.yaml
1 | apiVersion: v1 |
在这对cpu和memory的单位做一个说明:
- cpu:core数,可以为整数或小数
- memory: 内存大小,可以使用Gi、Mi、G、M等形式
1 | # 运行Pod |