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 ...
随机推荐
- [MySQL]MySQL8.0的一些注意事项以及解决方案
MySQL8.0 注意事项以及解决方案 1. MySQL8.0 修改大小写敏感配置 天坑MySQL8.0! 在安装后, 便无法通过修改配置文件,重启服务,或者执行sql来更改数据库配置, 要想配置的话 ...
- Linux巡检检查项
不定时更新...... 1)服务器 1.1 SELINUX检查(sestatus) 1.2 资源限制检查(ulimit -a) 1.3 最近登录(last) 1.4 操作系统版本(cat /etc/r ...
- python神器 Jupyter Notbook
python神器 Jupyter Notbook 简介 Jupyter Notebook是基于网页的用于交互计算的应用程序.其可被应用于全过程计算:开发.文档编写.运行代码和展示结果. Jupyter ...
- 74CMS 3.4 反射型XSS漏洞
一. 启动环境 1.双击运行桌面phpstudy.exe软件 2.点击启动按钮,启动服务器环境 二.代码审计 1.双击启动桌面Seay源代码审计系统软件 2.因为74CMS3.4源代码编辑使用GBK编 ...
- ESP8266 NodeMCU引脚说明,CH340和CP2102两款
开发ESP8266 NodeMCU GPIO功能时,虽然知道ESP8266 NodeMCU丝印引脚编号如下图所示(CP2102款),但是和实际对应的GPIO编号完全不一样. CP2102款 引脚说 ...
- 你应该知道的Redis事务
前两篇 Redis 文章都大几千字,今天我们换个小清新点的 如果你也了解过关系型数据库事务的话,相信这篇文章对你来说是很容易理解的了.具体什么是事务我就不说不多了,直接讲 Redis 事务相关的部分. ...
- Java中如何声明方法?JavaScript中如何声明函数?
public void method(){ } //实例方法 Function Declaration 可以定义命名的函数变量,而无需给变量赋值.Function Declaration 是一种独立的 ...
- 实践中如何优化 MySQL ?
最好是按照以下顺序优化: 1.SQL 语句及索引的优化 2.数据库表结构的优化 3.系统配置的优化 4.硬件的优化 详细可以查看 阿里 P8 架构师谈:MySQL 慢查询优化.索引优化.以及表等优化
- 使用 Docker, 7 个命令部署一个 Mesos 集群
这个教程将给你展示怎样使用 Docker 容器提供一个单节点的 Mesos 集群(未来的一篇文章将展示怎样很容易的扩展这个到多个节点或者是见底部更新).这意味着你可以使用 7 个命令启动整个集群!不需 ...
- 在IE中设置在序列化没有版本号就提示