Kubernetes部署单元-Pod
在 k8s 搞出 pod 概念的时候,其实 docker 官方就已经推出自己的容器编排应用 swarm。这一套服务可以帮助在不同节点上的容器,进行统一的管理,主要针对容器的启停,运维,还有部署,注意我这里没有提到“编排”,个人觉得确实在 swarm 中并没有容器编排这一概念(ps:相对于 k8s 的编排,swarm 确实显得有一丢丢稚嫩),其中关于容器中应用的部署流程,运维监控,还有日志收集这些基本都要自己动手实现。在 swarm 中主要有两个角色,一个是 manage,另一个是 worker,不同于 k8s 那么多眼花缭乱的概念对象,swarm 就显得朴实无华。但是技术的进步都是从简入繁的,搞明白了容器编排的发展历程,也许你对 k8s 为什么有 pod 这一概念,并且后续产生了这么多的抽象对象就有一定理解了。
我们先来看一下 Swarm 中的两种角色:
- manager - 发布配置和管理节点
- worker - 每台容器主机节点,承载了容器应用
Manager 为了避免单点故障,一般会在集群中使用多个节点,一般当配置发布和修改的时候,他们直接进行状态的同步,并且上线后会选出一个主要的 leader,选举使用的协议是 Raft ,有点类似于 zk, 使得 manager 避免脑裂
Worker 主要的工作是负责从 manager 那里,获取操作的 docker 命令,获取到的关于 build ,network 和 volume之类的配置然后同步到当前节点,他们是通过内部协议来进行通信的
以下是命令在 manager 和 worker 之间进行的示意图:
如果需要你自己亲自设计一套容器编排的应用架构,估计你的架构设计也和 swarm 差不多。下面一一解释一下图中的各个阶段流程是什么意思:
swarm manager:
1. API:接收命令。创建一个 service 应用(通过API调用输入)
2. orchestrator:对 service 对象创建的 task 进行调度工作(编排)
3. allocater:为各个 task 分配IP地址(分配IP)
4. dispatcher:将 task分发到 nodes (分发任务)
5. scheduler:安排一个 worker 运行 task(运行任务)
worker node:
1. 链接到分发器接收指定的调度任务 task
2. 将被指派到的 task 在本节点上执行
在 swarm 中调度的最小单位是 service。其实这个 service 可以看成是一个容器,类似于 docker- compose 内 service 的描述,也就是一个容器内,会启动不同的进程,这也就意味着 service 会比较“重”,以业务维度要组成,共同组成一个容器应用,来统一调度。
不同于 swarm 中的 service 设计,我们来看看 k8s 的 pod。
pod 是一组并置的容器,代表了 k8s 中基本构建模块。在实际应用中我们并不会单独部署容器,更多的是针对一组 pod 的容器进行部署和操作。然而这并不意味着一个 pod 总是要包含多个容器--实际上只包含单独容器的 pod 也是很常见的。一个 pod 的所有容器都运行在同一节点上,所以说 pod 是 k8s 的最小调度单元。那为什么 k8s 中会将编排单元抽象成 pod 呢?在学习 k8s 之前我一直有这疑问,因为我觉得 k8s 的对象实在是太“抽象”了,一但你将其从真实的业务场景中脱离出来,你会觉得这些人就是在专门搞一些让人费解的概念,提高了初级小白的入门门槛。对于这点疑问,在看了张磊老师的《深入剖析Kubernetes》中关于为什么我们需要 pod 的描述,我才回过味来,pod 其实可以看成一“进程组”,组内各个进程是“超亲密的关系”,容器之间进行紧密协作。这些具有“超亲密关系”容器的典型特征包括但不限于:互相之间会发生直接的文件交换、使用 localhost 或者 Socket 文件进行本地通信、会发生非常频繁的远程调用、需要共享某些 Linux Namespace(比如,一个容器要加入另一个容器的 Network Namespace)等等。
关于 Pod 网络
如上所述,由于一个 pod 中的容器运行于相同的 Network 命名空间中,因此他们共享相同的 IP 地址和端口空间, 这意味着同一个 pod 中的网络运行的多个进程需要注意不能绑定相同的端口号,否则会引起端口冲突,同一 pod 中的所有容器都可以通过 localhost 与同一个 pod 中的其他容器进行通信。kubernetes 集群中所有的 pod 都在同一个共享网络地址空间中,这意味着每个 pod 都可以通过其他 pod 的 IP 地址来实现相互访问,所以这也表示他们之间没有 NAT (网络地址转换)网关。当两个 pod 彼此之间发送网络数据的时候,他们都会把对方的实际 ip 地址看做数据包中的源 ip。所以你知道为什么在节点内网不联通的情况下, k8s 并不能通过分配 pod 的 ip 进行调度访问了吗?
因为,pod 之间的通信其实是非常简单的,无论是将两个 pod 安排单一的还是不同的工作节点上,这些 pod 不管实际节点间的网络拖布结构如何,这些 pod 内的容器能够像在无 NAT 的平坦网络中一样相互通信,就像局域网(LAN)上的计算机一样。每个 pod 都有自己的 IP 地址,并且可以通过这个专门的网络实现 pod 之间互相访问。这个专门的网络通常是由额外的的软件基于真实链路实现的,所以说 k8s 有很多网络插件实现,以应对不同的网络链路情况。
关于合理的 pod 安排
pod 应该比较轻量,我们应该将应用程序组织到多个 pod 中,而每个 pod 只包含紧密相关的组件或者进程。也就是说要不要分配容器到同一个 pod 中,主要看他们是不是紧密耦合的关系。比如它们需要一起运行,还是可以在不同的主机上运行?它们代表的是一个整体还是相互独立的组件?它们必须一起扩缩容还是可以分别进行?一般情况下,一个 pod 应用可能由一个主进程和多个辅助进程组成。辅助进程其实就是类似 sidecar 容器,包括日志轮转器和收集器,数据处理器,通信适配器等等。
关于 Pod 的 Yaml 描述文件
pod 定义由几个部分组成:
- metadata 包括名称、命名空间、标签和关于该容器的其他信息。
- spec 包含 pod 内容的实现说明,例如 pod 的容器、卷和其他数据。
- status 包含运行中的 pod 的当前信息,例如 pod 所处的条件,每个容器的描述和状态,以及内部 IP 和其他基本信息
apiVersion: v1 ## 描述文件遵循 v1 版的 kubernetes API
kind: Pod ## 描述类型 pod
metadata:
name: kubia-manual ## pod 名称
spec:
containers: ## 包含的容器
- image: luksa/kubia ## 创建容器所用的镜像
name:kubia
ports:
- containerPort: 8080 ## 应用监听的端口
protocol: TCP
关于 pod 相关的api操作
## 创建 pod
$ kubectl create -f kubia-manual.yaml ## 得到 pod 声明的完整定义
$ kubectl get po kubia-manual -0 yaml ## 查看新创建的 pod
$ kubectl get pods ## 查看 pod 的详情信息,这个非常有用,可以排查调试 pod 创建调度的问题
$ kubectl describe pod {pod名称} --namespace={命名空间} ## 获取 pod 运行日志,注意 k8s 在日志文件达到 10 MB的时候会自动轮替,logs 命令仅显示最后一次轮替后的日志条目
$ kubectl logs {pod名字} ## 如果是多容器 pod 需要查看某个特定容器的日志时,需要添加 -c 参数
$ kubectl logs {pod名字} -c {容器名称}
在 pod 调试中你可以使用 kubectl expose 命令创建一个 service,以便在外部访问到这个pod。但是在实际开发调试中,你如果不想创建一个service来与某个特定的 pod 通信,还可以通过本地转发的方式来进行访问。比如在本机 kubectl 中,可以不登录 k8s 集群的情况下,本地进行调试 pod
## 可以将本机器的本地端口转发到指定 pod 的端口
$ kubectl port-forward {pod名称} {本地端口}:{pod端口}
## 可以使用 curl 命令来访问连接到 pod
$ curl localhost:{本地端口}
这样可以在管理机上访问 k8s 集群,当然如果管理机是在外网的情况下,这样会比较危险,如果机器和k8s集群同属一个内网,并且外网访问不到k8s集,这样的调试方式,比一个个pod登录上去手动敲 curl 要来的方便一些。
关于 pod 的标签和命名空间
k8s 里有大量的通过标签来组织 pod 和所有其他 kubernetes 对象的例子,这里简单的汇总一下 api,方便以后查阅。
## 创建标签,在描述文件 yaml 中添加
metadata:
labels:
app: appname
env: pod ## 根据标签获取pod
$ kubectl get po -L 标签名1,标签名2 ## 更换标签
$ kubectl label po {pod名字} {标签名}={标签更改值} --overwrite ## 多条件的标签过滤
$ kubectl get po -l {标签名}!={标签值}
$ kubectl get po -l {标签名} in ({标签值1},{标签值2})
$ kubectl get po -l {标签名} notin ({标签值1},{标签值2})
## 删除 pod
$ kubectl delete po {pod名字}
在删除 pod 的时候,kubernetes 会向 pod 发送一个 SIGTERM 信号并等待一段秒数,如果没有响应则通过 SIGKILL 信号进行终止。所以为了确保程序正常关闭,进程需要正确处理 SIGTERM 信号。
除了标签,pod还有命名空间的概念。首先,由于每个对象都可以有多个标签,因此这些对象组可以重叠。而命名空间是用来将对象分割成完全独立且不重叠的组。比如这些命名空间组成的不同组,可以在多租户环境中分配资源,将资源分配为生产、开发和测试环境等等。我觉得命名空间提供的隔离更趋向于运维,调度层面的,而标签则趋向于业务层面的区分隔离。
## 创建一个命名空间
apiversion: v1
kind: Namespace
metadata:
name: {命名空间名字} ## 在命名空间中创建对象,可以在 metadata 字段中添加 namespace: 命名空间名字 属性
$ kubectl create -f ... -n {命名空间}
这里需要注意的是,命名空间的隔离并不意味着网络也是隔断的,命名空间之间是否提供网络隔离取决于 k8s 自己所使用的网络解决方案,也就是说只要知道某个 pod 的 IP,不管命名空间如何,都能将流量发送到这个 pod。所以如果在命名空间中做网络隔离时,还是需要去配置调度 node 节点的分配,还有网络的物理隔离。
Kubernetes部署单元-Pod的更多相关文章
- [原]CentOS7安装Rancher2.1并部署kubernetes (三)---解决登录kubernets超时和部署测试Pod和Containter[nginx为例]
################## Rancher v2.1.7 + Kubernetes 1.13.4 ################ ##################### ...
- Docker集群管理工具 - Kubernetes 部署记录 (运维小结)
一. Kubernetes 介绍 Kubernetes是一个全新的基于容器技术的分布式架构领先方案, 它是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,Kubernete ...
- 傲视Kubernetes(三):Kubernetes中的Pod
从本文开始,将正式开始Kubernetes的核心内容学习.首先要了解的是Pod,总共大约分为六篇左右,本篇是第一篇,相信学完之后,我们会对Pod有一个整体的理解. 本文内容: 1.什么是Pod 2.P ...
- Kubernetes 实战 —— 03. pod: 运行于 Kubernetes 中的容器
介绍 pod P53 pod 是 Kubernetes 中最为重要的核心概念,而其他对象仅仅用于 pod 管理. pod 暴露或被 pod 使用. pod 是一组并置的容器,代表了 Kubernete ...
- kubernetes基本概念 pod, service
k8s的部署架构 kubernetes中有两类资源,分别是master和nodes,master和nodes上跑的服务如下图, kube-apiserver | kubelet kube-contro ...
- [系统集成] 基于Kubernetes 部署 jenkins 并动态分配资源
基于kubernetes 部署 jenkins master 比较简单,难点是为 jenkins 动态分配资源.基于kubernetes 为 jenkins 动态分配资源需要实现下述功能: 资源分配: ...
- kubernetes 部署
kubernetes 部署(Centos 7) 一个或者多个兼容 deb 或者 rpm 软件包的操作系统,比如 Ubuntu 或者 CentOS 每台机器 2 GB 以上的内存,内存不足时应用会受限制 ...
- kubernetes 部署 traefik 以及kubernetes dashborad
前言 本来打算通过 traefik 来实现 kubernetes dashborad 的服务访问,可是在配置过程中始终报错.最后无奈只能通过nodeport来实现kubernetes dashbora ...
- Kubernetes 部署失败的 10 个最普遍原因
[原文].后面我们可能还会看到一个 OOMKilled 错误. 我们的应用正在挂掉?为什么? 首先我们查看应用日志.假定你发送应用日志到 stdout(事实上你也应该这么做),你可以使用 kubect ...
随机推荐
- linux下yum无法安装lrzsz,Error: Failed to download metadata for repo ‘appstream‘: Cannot prepare internal
镜像下载.域名解析.时间同步请点击阿里云开源镜像站 linux虚拟机上准备安装一下rz sz,执行yum命令后提示如下: [root@tony001 ~]# yum install lrzsz Cen ...
- Linux 进程打开最大文件连接数Too many open files
首先出现这个提示的原因:应用程序打开的文件数量超过了系统设定值. 如何查看当前系统每个用户最大允许打开文件数量: [root@registry ~]# ulimit -a core file size ...
- Linux移植到自己的开发板(四)问题汇总
@ 目录 1 使ubuntu支持两个版本的编译链: 2 版本问题: 3 ubuntu版本的vscode下载网速太慢: 4 ubuntu占用空间过大 5 执行make zImage 出错 lzop: n ...
- 为什么要从Web form过渡到MVC中
可以说,在未来几年中,Web form的使用会逐渐减少,而取而代之的就是MVC.可能你不会同意我的观点,那么我就试着阐述一下我的观点,如果你还是不能接受,那么请你反驳我. 学习一个新语言或者是新架构是 ...
- You Don't Know JS Yet Book 1 Notes
Get Started - 前言 But let me be clear: I don't think it's possible to ever fully know JS. That's not ...
- Linux Yum仓库源配置
Yum概念:Yum软件仓库的作用是为了进一步简化RPM管理软件的难度以及自动分析所需软件包及其依赖关系的技术 Yum配置仓库源放置位置:/etc/yum.repo.d/ :配置文件需以 .repo 结 ...
- hdu 1175 连连看 DFS_字节跳动笔试原题
转载至:https://www.cnblogs.com/LQBZ/p/4253962.html Problem Description "连连看"相信很多人都玩过.没玩过也没关系, ...
- 什么是可重入锁(ReentrantLock)?
举例来说明锁的可重入性 public class UnReentrant{ Lock lock = new Lock(); public void outer(){ lock.lock(); inne ...
- 简述在 MySQL 数据库中 MyISAM 和 InnoDB 的区别 ?
MyISAM: 不支持事务,但是每次查询都是原子的: 支持表级锁,即每次操作是对整个表加锁: 存储表的总行数: 一个 MYISAM 表有三个文件:索引文件.表结构文件.数据文件: 采用菲聚集索引,索引 ...
- 说说对 SQL 语句优化有哪些方法?
1.Where 子句中:where 表之间的连接必须写在其他 Where 条件之前,那些可 以过滤掉最大数量记录的条件必须写在 Where 子句的末尾.HAVING 最后. 2.用 EXISTS 替代 ...