Kubernetes教程(七)了解集群、标签、Pod和Deployment

了解集群、标签、Pod和Deployment

Kubernetes的知识真的特别庞大,知识点多,还特别看重实践操作。我从 Kubernetes这个单词怎么拼写到在搭建好K8s集群并运行一个Nginx,花了一周的时间。我现在也是超级菜鸟一个,连入门都不算,只能边学边记录,我看的书籍是下面2本:

  • 《Kubernetes权威指南》第6版,知识点全面,对概念和原理讲的深入
  • 《Kubernetes企业级云原生运维实战》李振良编写,更偏向实战操作,以便🐮🐴们能用上K8s为老板打工
  • 个人建议先看《Kubernetes企业级云原生运维实战》,不然《Kubernetes权威指南》的第一章(共47页)都根本看不懂💀

一、K8s资源对象

K8s中的基础概念和术语大多围绕资源对象来说的,资源对象可分如下几类:

  • 基础资源对象:节点(Node)、容器组(Pod)、服务(Service)、存储卷(Volume)
  • 基础资源对象相关的事务与控制器:标签(Label)、注解(Annotation)、命名空间(Namespace)、水平扩容、配置(ConfigMap、Secret)、持久化存储(PersistentVolume、PersistentVolumeClaim、StorageClass)、工作负载控制器(Deployment、StatefulSet、DeamonSet、Job、CronJob)
  • 资源管控和权限相关:资源限制、资源配额、角色、角色绑定
  • 网络相关 :Ingress、网络策略(NetworkPolicy)等

K8s中资源对象包括几个公共属性:版本(Version)、类别(Kind)、名称(Name)、标签、注解。我们可以用YAMLJSON格式声明一个K8s资源对象,每个资源对象都有自己特定的结构定义,比如PodService的YAML文件的格式是不同的。定义好的资源对象会保存在etcd这非关系型数据库中,以便快速读写。

二、K8s集群

K8s集群(Cluster)是由MasterNode组成的。

1. Master

Master是控制节点,负责管理和控制整个集群,相当于集群的大脑,在每个K8s集群中都需要一个或一组Master。在Master上运行一下关键进程:

  • kube-apiserver:提供RESTful API接口,是对资源进行增删改查的唯一入口,也是集群控制的入口
  • kube-controller-manager:所有资源对象的自动化控制中心,相当于"大总管"
  • kube-scheduler:负责资源调度(Pod调度)

2. Node

Node是集群中的工作负载节点,是真正干活的打工人。Master会把工作负载分配给Node,当某个Node宕机,其上的工作负载会被Master转移到其他Node上。在每个Node上运行着以下关键进程:

  • kubelet:负责Pod对应容器的创建、启停等任务,听Mater的指挥,实现集群管理的基本功能
  • kube-proxy:实现K8sService通信与负载均衡机制
  • 容器运行时(如Docker):负责本机容器的创建和管理
bash 复制代码
查看集群有多少节点
kubectl get nodes

查看某个Noded的信息
kubectl describe node <node_name>

三、Namespace(命名空间)

在K8s集群中还有一个重要概念-命名空间(Namespace),在大多情况下用于多租户的资源隔离,典型的思路是给每个租户分配一个命名空间。每个命名空间都是相互独立的,不同命名空间的资源对象是逻辑上相互隔离。K8s安装运行后,默认会有2个Namespace:

  • default:给用户用的,用户创建资源对象时,如不指定命名空间,会放到default命名空间
  • kube-system:存放系统相关的资源对象如网络组件、DNS组件、监控类组件
bash 复制代码
若不指定namespace,查看的是default命名空间内的资源对象
kubectl get pods

通过参数查看指定命名空间"dev"的资源对象
kubectl get pods --namespace=dev

四、Label(标签)

Label(标签)是K8s一个核心概念,它就是一个key=value的键值对,其中keyvalue都是用户自定义。Lable可以被附加到NodePodDeploymentServiceVolume等资源对象上,并且 一个资源对象可以有多个标签。 在实际生产环境中,Pod应该都是有标签的,下面看个例子,就知道标签的重要性了。

  • 下面是个定义Service的yaml文件,最后的selector就是指关联有app=nginx标签的Pod
yaml 复制代码
apiVersion: v1        # API版本
kind: Service         # 资源类型
metadata:             # 资源元数据
  name: nginx         # 资源名称
spec:                 # 资源规格
  ports:              # 端口映射列表
  - name:             # 端口名称
    port: 80          # 公开端口
    protocol: TCP     # 端口协议,支持TCP、UDP和SCTP,默认TCP
    targetPort: 80    # 目标端口,即容器内应用程序监听的端口
  selector:           # 标签选择器
    app: nginx        # Pod标签

打上Label后的资源对象,之后就可以通过Lable Selector(标签选择器)查询和筛选,介绍下Lable Selector的一些例子:

  • yaml中配置release : stable标签,这个标签的值就是release=stable
  • release = stable,匹配具有release=stable标签的资源对象
  • release != stable,匹配不具有release=stable标签的资源对象
  • release in (stable, dev)匹配具有release=stablerelease=dev标签的资源对象
  • release notin (stable, dev)匹配不具有release=stablerelease=dev标签的资源对象

五、Pod

Pod(容器组)是K8s中最重要的概念之一,Pod是K8s中最小的调度单元,每一个Pod包含一个特殊的Pause容器(由K8s创建)和一个或多个密切相关的用户业务容器

  • Pod中多个业务容器是密切相关的,将Pod作为最小单位,让Pod内多个应用一起有效地调度和伸缩。
  • Pod中的多个业务容器共享Pause容器的IP,简化了密切相关容器之间的通信。
  • Pod中的多个业务容器共享Volume挂载,简化了密切相关容器之间的文件共享问题。
  • Pod都有一个唯一的Pod IP地址,一个Pod中多个容器共享Pod IP地址。
  • 集群中任意两个Pod之间都可以支持TCP/IP直接通信。

1. 共享网络命名空间

假设一个场景:有2个业务容器,一个是Nginx,一个是指标采集程序(负责采集Nginx性能指标)。这2个业务容器关系是密切相关的。指标采集容器能通过http://127.0.0.1/nginx_status直接访问Nginx容器吗?答案是不能,因为它们2个容器的网络命名空间是隔离的。但是在Pod中,这个2个容器可以共享网络命名空间,在创建一个Pod时,K8s会先创建一个Pause容器,然后业务容器会接着被创建并加入到Pause容器的网络命名空间,这样Pod中的所有容器都在同一个网络命名空间中,可以通过127.0.0.1访问彼此了。

假设有个collect指标采集程序的镜像,在定义Podyaml文件可以这样写。

  • kind属性的值为Pod,表明是一个定义Pod的文件
  • metadata.name是Pod名称
  • metadata.namespace是命名空间
  • metadata.labels是标签,标签的keyvalue都是自定义,所以这个标签值就是"app=pod-network"
  • spec.containers是用户容器列表,可以添加一个或多个容器
yaml 复制代码
apiVersion: v1              # API版本
kind: Pod                   # 资源类型
metadata:                   # 资源元数据
  name: pod-network         # Pod名称
  namespace: default        # 指定命名空间
  labels:                   # Pod标签
    app: pod-network        # 标签的key和value都是自定义,这个标签值就是"app=pod-network"
spec:
  containers:               # Pod中容器列表
  # 第一个容器(主应用容器)
  - image: nginx:1.23       # 容器镜像地址
    name: web               # 容器名称
  # 第二个容器
  - image: collect:1.0
    name: collect
    command: ["/bin/bash", "-c", "while true; do sleep 1; done"] # 容器执行的命令

2. 共享数据

还是上面那个场景:一个是Nginx,一个是指标采集程序(负责采集Nginx性能指标),指标采集程序要如何读取到Nginx的访问日志文件呢?我们所熟悉的Docker Volume在K8s中也有对应的概念--Pod Volume,它被定义在Pod中,然后被Pod中各个容器挂载到自己的文件系统中。

  • Pod所在节点的文件系统创建一个空目录,然后挂载到2个业务容器的日志目录
  • Nginx容器的/var/log/nginx写入文件后,指标采集容器的/var/log/nginx也能使用Nginx的日志文件
  • 卷定义的volumes.name和容器挂载的volumeMounts.name要一致,这里都叫"log"
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: pod-volume
  name: pod-volume
  namespace: default
spec:
  containers:
  # 第一个容器(应用容器)
  - image: nginx:1.23
    name: web
    volumeMounts:                # 卷挂载
    - name: log                  # 挂载的卷名称
      mountPath: /var/log/nginx  # 卷挂载到容器中路径
  # 第二个容器(日志采集容器)
  - image: cooect:1.0
    name: collect
    command: ["/bin/bash", "-c", "while true; do sleep 1; done"]
    volumeMounts:                # 卷挂载
    - name: log                  # 挂载的卷名称
      mountPath: /var/log/nginx  # 卷挂载到容器中的路径
  volumes:                  # 定义卷
  - name: log               # 卷名称
    emptyDir: {}            # 卷类型:emptyDir是临时存储,与Pod生命周期一致

在实际生产环境中,不会直接用kind : Pod这类型的Pod定义文件,一般都会用kind: Deployment类型的工作负载,所以一定要好好学习下面的工作负载

六、工作负载

通常情况下,每个Service对应的Pod副本数量都是固定的,如果一个一个手动创建Pod副本那也太麻烦了。如果有一个Pod模板,在Pod模板里指定Pod副本数量,然后再根据Pod模板创建多个Pod。从这个Pod模板就引出了K8s中的一个抽象概念:工作负载

  • 工作负载用于更高层次地创建和管理 Pod,它可以定义Pod的副本数量、运行规格、调度策略等
  • K8s可以自动处理Pod的创建、更新和删除等操作,简化了用户对Pod生命周期的操作
  • 工作负载有4种类型,其中最常用的是Deployment,支持副本管理、副本数扩缩、滚动更新、版本回滚等操作

1. 设置副本数

下面看下一个Deployment的例子:

  • spec.replicas:Pod的副本数量

  • spec.template:用于自动创建新Pod副本的模板

  • spec.selector:用于指定 Deployment 所管理的 Pod 的标签,这个选择器决定了哪些 Pod 是由这个 Deployment 管理的

  • spec.template.metadata.lables:定义了 Pod 的标签,这些标签需要与上面的spec.selector中的选择器匹配,以确保 Deployment 能够识别和管理这些 Pod。

yaml 复制代码
apiVersion: apps/v1    # API版本
kind: Deployment       # 资源类型
metadata:              # 资源元数据
  name: deploy-user-service   # 资源名称
  namespace: my-space      # 指定命名空间
spec:                  # 资源规格
  replicas: 3          # Pod副本数
  selector:            # 标签选择器
    matchLabels:       # 匹配标签
      app: user        
  template:            # Pod模板
    metadata:          # Pod元数据
      labels:          # Pod标签
        app: user
    spec:              # Pod规格
      containers:      # Pod容器配置
      - image: user-srvice:v3
        name: web      # 容器名称

2. 应用升级

当源代码需要升级时,需要重新构建镜像并上传到K8s集群中,以下有2中常见的升级方法:

  • 修改资源文件,将Deployment资源中的image字段修改为新的镜像地址,然后使用kubectl apply -f <资源文件>命令。
  • 使用kubectl set image <资源类型>/资源名称 <容器名称>=<镜像地址>命令更新Deployment资源的镜像地址。
bash 复制代码
kubectl set image deployment/deploy-user-service web=user-srvice:v4 -n my-space

结语

K8s的知识体系真的是太庞大了,本篇暂时写到这里,本篇涉及到的PodDeployment也只是真正相关知识的九牛一毛而已。但是学习一门新技术,不能按部就班地一个一个章节死磕每个知识点。要先对整体有个大概了解,着重看最主要最常用的功能,之后再反复的看书实践,提取知识点。

相关推荐
二楼后座。3 小时前
mac 被禁用docker ui后,如何使用lima虚拟机启动docker
macos·docker·容器·lima
孔令飞3 小时前
11 | 给 Gin 服务器添加中间件
人工智能·ai·云原生·golang·kubernetes
ThisIsClark3 小时前
【K8s】使用Kubernetes的resources字段中的requests和limits字段控制Pod资源使用
云原生·容器·kubernetes
笑远4 小时前
无服务器数据库
数据库·云原生·serverless
孔令飞4 小时前
12 | 给应用添加优雅关停功能
人工智能·ai·云原生·golang·kubernetes
小涵5 小时前
【DevOps】Backstage介绍及如何在Azure Kubernetes Service上进行部署
docker·容器·kubernetes·azure·devops·backstage
小刘爱喇石( ˝ᗢ̈˝ )5 小时前
hadoop框架与核心组件刨析(五)ZOOKEEPER及选举深度刨析
hadoop·zookeeper·云原生
小刘爱喇石( ˝ᗢ̈˝ )5 小时前
玛卡巴卡的k8s知识点问答题(三)
云原生·容器·kubernetes
a_j585 小时前
k8s面试题总结(十二)
云原生·容器·kubernetes