背景
部署方式的演变
传统部署时代:
- 在物理机服务器上运行应用程序。
- 无法为应用程序定义资源边界。
- 导致资源分配问题。
如果在物理服务器上运行多个应用程序,则可能会出现一个应用程序占用大部分资源的情况下,会导致其它应用程序的性能下降。一种解决方案就是在不同的物理服务器上运行每个应用程序,但是由于资源利用不足而无法扩展,并且维护许多物理服务器的成本也很高。
虚拟化部署时代:
作为解决方案,引入了虚拟化。
- 虚拟化技术允许在单个物理服务器的 CPU 上运行多个虚拟机(VM)。
- 虚拟化允许应用程序在 VM 之间隔离,并提供一定程度上的安全。
- 一个应用程序的信息不会被另一个应用程序随意访问。
- 虚拟化技术能够更好的利用物理服务器上的资源。
- 因为可以很轻松的添加或更新应用程序,所以可以实现更好的可伸缩性,并且可以降低硬件成本。
- 每个 VM 都是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括自己的操作系统等。
缺点:虚拟层冗余,导致资源浪费和性能下降。
容器化部署时代:
- 容器类似于 VM ,但是可以在应用程序之间共享操作系统。
- 容器被认为是轻量级的。
- 容器和 VM 类似,具有自己的文件系统、CPU 、内存、进程空间等。
- 由于容器和基础架构分离,因为可以很方便的进行跨云和跨 Linux 发行版进行移植。
- 参照 Docker 的隔离原理(namespace 6 项隔离和 cgroups 8 项资源限制)。
容器的优势:
① 敏捷性:敏捷应用程序的创建和部署;和使用 VM 镜像相比,提高了容器镜像创建的简便性和效率。
② 及时性:持续开发、集成和部署;通过快速简单的回滚(由于镜像的不可变性),支持可靠且频繁的容器镜像的构建和部署。
③ 解耦性:关注开发和运维的分离;在构建、发布时创建应用程序的容器镜像,而不是在部署的时候,从而将应用程序和基础架构分离。
④ 可观测性:不仅可以显示操作系统级别的信息和指标,还可以显示应用程序的运行状况和其它指标信号。
⑤ 跨平台:跨开发、测试和生产的环境一致性;在便捷式的计算机上和在云上相同的运行。
⑥ 可移植:跨云和 Linux 发行版本的可移植性;可以在 Ubuntu、CentOS、RedHat、本地、Google Kubernetes Engine 和其他任何地方运行。
⑦ 简易性:以应用程序为中心的管理;提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序。
⑧ 大分布式:松散耦合、分布式、弹性、解放的微服务;应用程序被分解成较小的独立部分,并且可以动态的部署和管理 — 而不是在一台大型单机上整体运行(垂直扩展是有上限的)。
⑨ 隔离性:资源隔离;可预测应用程序性能。
⑩ 高效性:资源利用;高效率和高密度。
简介
kubernetes由Google公司研发,使用 Go 语言编写。
Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、支持和工具广泛可用。
特点:
- 轻量级:消耗资源少
- 开源
- 弹性伸缩
- 负载均衡:IPVS
小知识点——服务分类
- 有状态服务:比如 DBMS(数据库管理系统)
- 无状态服务:比如 LVS、Apache
高可用集群副本数量最好是 >= 3 个(奇数)
组件说明
主要组件:
**API server:**所有服务访问的统一入口
**CrontrollerManager:**维持副本期望数目
**Scheduler:**负责接受任务,选择合适的节点进行分配任务
**Etcd:**键值对 数据库,存储K8S集群所有的重要信息(持久化)
**Kubelet:**直接跟容器引擎交互实现容器的生命周期管理
**Kube-proxy:**负责写入规则至 IPTABLES、IPVS ,实现服务映射访问的
其他插件:
**CoreDNS:**可以为集群中的 SVC 创建一个域名 IP 的对应关系解析
**Dashboard:**给 K8S 集群 提供一个 B/S 结构访问体系
**Ingress Controller:**官方只能实现4层代理,ingress可以实现7层代理
**Federation:**提供一个可以跨集群中心多 K8S 统一管理的功能
**Prometheus:**提供 K8S 集群的监控能力
**ELK:**提供 K8S 集群日志统一分析接入平台
Master 节点(Control Plane【控制面板】):Master 节点控制整个集群
- Controller Manager:控制管理器。
- etcd:键值数据库,类似于 Redis。
- scheduler:调度器。
- api-server:api网关(所有的控制都需要通过api-server)。
**Node 节点(worker工作节点): **
- kubelet(监工):每一个 Node 节点上必须安装的组件,负责交互 master 的 api-server 以及当前机器的应用启停等,在 master 机器就是 master 的小助手。每一台机器真正干活的都是这个 Kubelet 。
- kube-proxy:代理网络。
**Pod: **
- docker run 启动的是一个 container(容器),容器是 Docker 的基本单位,一个应用就是一个容器。
- kubectl run 启动的是一个应用称为一个 Pod ,Pod 是 Kubernetes 的基本单位。
- Pod 是对容器的再一次封装。
- Pod 类似于 Java 日志体系中的 Slf4j ,而 Docker 中的容器类似于 Java 日志体系中的 Logback 等日志实现。
- 一个容器往往代表不了一个基本应用,如:博客系统(WordPress,PHP + MySQL);但是一个 Pod 可以包含多个 Container,一个 Pod 可以代表一个基本的应用。
架构
Kubernetes 集群大致分为两类:一主多从和多主多从
- 一主多从(单 master ):一个 Master 节点和多台 Node 节点,搭建简单,但是有单机故障风险,适合用于测试环境。
- 多主多从(高可用):多台 Master 节点和多台 Node 节点,搭建麻烦,安全性高,适合用于生产环境。
单master架构
高可用集群架构
组件交互原理
Kubernetes 是如何部署一个 Tomcat 应用?
0:开机默认所有节点的 kubelet 、master 节点的s cheduler(调度器)、controller-manager(控制管理器)一直监听 master 的 api-server 发来的事件变化。
1:程序员使用命令行工具: kubectl ; kubectl create deploy tomcat --image=tomcat8(告诉 master 让集群使用 tomcat8 镜像,部署一个 tomcat 应用)。
2:kubectl 命令行内容发给 api-server,api-server 保存此次创建信息到 etcd 。
3:etcd 给 api-server 上报事件,说刚才有人给我里面保存一个信息。(部署Tomcat[deploy])
4:controller-manager 监听到 api-server 的事件,是 (部署Tomcat[deploy])。
5:controller-manager 处理这个 (部署Tomcat[deploy])的事件。controller-manager 会生成 Pod 的部署信息【pod信息】。
6:controller-manager 把 Pod 的信息交给 api-server ,再保存到 etcd 。
7:etcd 上报事件【pod信息】给 api-server 。
8:scheduler 专门监听 【pod信息】 ,拿到 【pod信息】的内容,计算,看哪个节点合适部署这个 Pod【pod 调度过后的信息(node: node-02)】。
9:scheduler 把 【pod 调度过后的信息(node: node-02)】交给 api-server 保存给 etcd 。
10:etcd 上报事件【pod调度过后的信息(node: node-02)】,给 api-server 。
11:其他节点的 kubelet 专门监听 【pod 调度过后的信息(node: node-02)】 事件,集群所有节点 kubelet 从 api-server 就拿到了 【pod调度过后的信息(node: node-02)】 事件。
12:每个节点的 kubelet 判断是否属于自己的事情;node-02 的 kubelet 发现是他的事情。
13:node-02 的 kubelet 启动这个 pod。汇报给 master 当前启动好的所有信息。
资源管理方式
- 命令式对象管理:直接使用命令去操作kubernetes资源
例:kubectl run nginx-pod --images=nginx:1.17.1 --port=80
- 命令式对象配置:通过命令配置和配置文件去操作kubernetes资源
例:kubectl create/patch -f nginx-pod.yaml
- 声明式对象配置:通过apply命令和配置文件去操作kubernetes资源(仅支持创建或更新)
例:kubectl apply -f nginx-pod.yaml
类型 | 操作对象 | 适用环境 | 优点 | 缺点 |
---|---|---|---|---|
命令式对象管理 | 对象 | 测试 | 简单 | 只能操作活动对象,无法审计、跟踪 |
命令式对象配置 | 文件 | 开发 | 可以审计、跟踪 | 项目大时,配置文件多,操作麻烦 |
声明式对象配置 | 目录 | 开发 | 支持目录操作 | 意外情况下难以调试 |
资源类型
k8s应用负载下:
- 服务:实现service的功能
- 工作负载:在这里可以创建deployment、daemonset、replicaset等
- 任务:创建job任务的
- 应用路由:创建ingress的
- 容器组:查看各个pod的运行状况的
- 存储管理:进行存储管理的
kubernetes中所有的内容都抽象为资源,可以通过 kubectl api-resources
命令进行查看
经常使用的资源如下:
资源分类 | 资源名称 | 缩写 | 资源作用 |
---|---|---|---|
集群级别资源 | node | 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允许对资源进行多种操作,可以通过 kubectl --help
查看详细的操作命令。
经常使用的操作如下:
命令分类 | 命令 | 翻译 | 命令作用 |
---|---|---|---|
基本命令 | create | 创建 | 创建一个资源 |
edit | 编辑 | 编辑一个资源 | |
get | 获取 | 获取一个资源 | |
patch | 更新 | 更新一个资源 | |
delete | 删除 | 删除一个资源 | |
explain | 解释 | 展示资源文档 | |
运行和调试 | run | 运行 | 在集群中运行一个指定的镜像 |
expose | 暴露 | 暴露资源为Service | |
describe | 描述 | 显示资源内部信息 | |
logs | 日志 | 输出容器在 pod 中的日志 | |
attach | 缠绕 | 进入运行中的容器 | |
exec | 执行 | 执行容器中的一个命令 | |
cp | 复制 | 在 pod 内外复制文件 | |
rollout | 首次展示 | 管理资源的发布 | |
scale | 规模 | 扩缩容 pod 数量 | |
autoscale | 自动调整 | 自动调整 pod 数量 | |
高级命令 | apply | rc | 通过文件对资源进行配置 |
label | 标签 | 更新资源上的标签 | |
其他命令 | cluster-info | 集群信息 | 显示集群信息 |
version | 版本 | 显示当前Server和Client的版本 |
常用命令
# 查看node节点和服务版本信息
kubectl get nodes
# 查看node节点和服务版本信息,并查看详细信息
kubectl get nodes -o wide
# 查看pod信息,默认是default名称空间
kubectl get pod
# 获取所有名称空间的pod
kubectl get po -A
# 查看pod信息,并查看详细信息
kubectl get pod -o wide
# 查看名称空间dev下的 pod 的详细信息
kubectl get describe pod [podName] -n dev
# 查看pod信息,以yaml或json格式展示(可以看到许多详细信息)
kubectl get pod [podName] -o yaml/json
# 获取指定名称空间的pod
kubectl get pod -n kube-system
kubectl get pod -n kube-system -o wide
# 获取指定名称空间的指定pod
kubectl get pod -n kube-system [podName]
# 删除节点,在 master 节点执行
kubectl delete node [node name]
# 删除所有的 pod
kubectl delete pod --all
# 查看 pod 日志
kubectl describe pod [podName]
经常使用的资源如下所示
集群级别资源:
资源名称 | 缩写 | 资源作用 |
---|---|---|
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 | 配置 |
命令式对象配置
vim nginxpod.yaml
创建:kubectl create -f nginxpod.yaml
apiVersion: apps/v1 #版本
kind: Namespace #类型,名称空间
metadata: #元数据描述
name: dev
# 一个yaml文件想写两段yaml内容,需要使用 --- 分开
---
apiVersion: apps/v1 #版本
kind: Pod #类型,pod
metadata: #元数据
name: nginxpod #pod名称
namespace: dev #pod所在的名称空间
spec: #规格描述
containers:
- name: nginx-containers #容器名称
image: nginx:latest #容器镜像
删除:kubectl delete -f nginxpod.yaml
apiVersion: 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:1.17 #使用镜像nginx:1.17创建container,该container默认80端口可访问
apiVersion: v1
kind: 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: 32600 #通过任意节点的 32600 端口访问 Service
targetPort: 80 #将请求转发到匹配 Pod 的 80 端口
type: NodePort #Serive的类型,ClusterIP/NodePort/LoaderBalancer
声明式对象配置
kubectl apply -f nginxpod.yaml
其实,声明式对象配置就是使用 apply 描述一个资源最终的状态(在yaml中定义状态)
使用 apply 操作资源:
如果资源不存在,就创建,相当于 kubectl create
如果资源已存在,就更新,相当于 kubectl patch
附:Namespace
Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。
默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的”组”,以方便不同的组的资源进行隔离使用和管理。
可以通过kubernetes的授权机制,将不同的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等等,来实现租户可用资源的管理。
kubernetes 在集群启动后,会默认创建几个 namespace
root@k8s-master:~# kubectl get ns
NAME STATUS AGE
default Active 16d # 所有未指定namespace的对象都会被分配在default命名空间
kube-flannel Active 14d
kube-node-lease Active 16d # 集群节点之间的心跳维护,v1.13开始引入
kube-public Active 16d # 此命名空间下的资源可以被所有人访问(包括未认证用户)
kube-system Active 16d # 所有由kubernetes系统创建的资源都处于这个命名空间
root@k8s-master:~# kubectl describe ns default
Name: default
Labels: kubernetes.io/metadata.name=default
Annotations: <none>
Status: Active #正在使用的命名空间 Terminating:正在删除的命名空间
No resource quota. #ResourceQuota 针对ns做的资源限制
No LimitRange resource. #LimitRange 针对ns中的每个组件做的资源限制
附:Label
Label是kubernetes系统中的一个重要概念,它的作用就是在资源上添加标识,用来对它们进行区分和选择。
特点:
- 一个Label会以 key/value 键值对的形式附加到各种对象上,如Node、Pod、Service等等
- 一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去
- Label通常在资源对象定义时确定,当然也可以在对象创建后动态添加或者删除
可以通过Label实现资源的多维度分组,以便灵活、方便地进行资源分配、调度、配置部署等管理工作。
标签定义完毕之后,还要考虑到标签的选择,这就要使用到Label Selector,即:
Label 用于给某个资源对象定义标识
Label Selector 用于查询和筛选拥有某些标签的资源对象