kubernetes基础--pod

举报
yd_246059053 发表于 2024/01/09 17:10:11 2024/01/09
【摘要】 一、kubernetes架构上图为kubernete官方网站提供的架构图,该图中,主要涉及多个组件,各个组件功能如下:kube-apiserver:kubernetes的api接口服务,集群中所有的组件都通过该服务进行相关操作,如创建pod、创建svc等。kube-apiserver部署在控制平面节点。kube-controller-manager:kubernetes控制器,该服务是多组控...

一、kubernetes架构

上图为kubernete官方网站提供的架构图,该图中,主要涉及多个组件,各个组件功能如下:

  • kube-apiserver:kubernetes的api接口服务,集群中所有的组件都通过该服务进行相关操作,如创建pod、创建svc等。kube-apiserver部署在控制平面节点。
  • kube-controller-manager:kubernetes控制器,该服务是多组控制器的集合,比如实现副本功能的ReplicaController、用于节点管理的NodeController以及用于服务账号管理的ServiceAccount controller等。
  • kube-scheduler:kubernetes的调度服务,需要创建pod时,kube-scheduler会根据算法对节点的资源或者根据用户配置的策略选择节点
  • etcd:kubernete所使用的数据库。该数据库只有kube-apiserver操作,其他服务都通过kube-apiserver来完成数据的读取和写入。
  • kubelet:kubernetes用来管理容器的服务,以确认容器处于正常运行的健康状态。
  • CRI:container runtime interface,由kubelet管理的容器运行时。kubernetes支持多个容器运行时,如containerd、CRI-O等
  • kube-proxy:kubernetes代理服务,可以为kubernetes的服务提供网络代理和负载均衡功能。

上图没有的:

  • CNI:container network interface,容器网络的规范和接口,由kubelet管理。CNI用于实现容器集群的网络管理,解决容器网络的复杂性问题。它是kubernetes的重要组成部分,是构建完整集群的重要一环。常用的CNI插件有calico、flannel以及cilium等。
  • CSI:container storage interface,存储接口,由kubelet管理。CSI用于对接第三方存储,以便满足实际环境下各种存储需求,它也是kubernetes集群中重要组成部分。
  • coredns:kubernetes中,默认的域名解析服务。容器运行可能会随时重启,此时ip就会发生变化。使用DNS来可以很好的应对这种情况。

其他重要的kubernetes add-ons:

ingress controller:ingress是k8s集群外部访问k8s内部服务资源的重要实现,本质上可以认为是一个代理服务,把内网的服务代理到外网方便外网访问。ingress controller是实现ingress资源的控制器

metrics server:节点、容器等指标的数据的收集服务,便于人们了解容器和节点的资源使用情况或者健康状态等。比如使用kubectl top命令来获取节点或pod的资源使用情况就需要metrics server服务。

监控服务:如prometheus。metrics server无法保存数据,部署外部监控系统是一个很好解决方案。

日志集中存储插件:如ELK或PLG。节点数量过多或容器数量过多时,集中日志可以便于查询以及故障处理等。PLG是promtail+loki+grafana的缩写,是轻量级的日志集中存储方案。

负载均衡插件:metalLB或者openELB等,他们都是适用于非云端k8s负载均衡的实现。LoadBalancer是service资源的一种特殊类型,可以直接对外暴露service访问接口,不需要通过nodePort或者ingress等资源的介入。


kubernetes中,存在各种各样资源概念,其中的核心,便是pod。pod是一组容器的集合,是k8s的最小的可部署的计算单元。pod的运行,可以通过kubectl命令行创建,也可以使用yaml文件运行。在运行过程中,可以实现很多配置,以保证pod或者集群的稳定运行。比如探活、可用、内存以及cpu的请求和限制、副本数、标签等。

本节,主要学习整理pod的部分配置。上面用来完善一下k8s架构方面的认识。


二、pod资源使用示例

这里直接运行一个示例,后面再展开讲示例的配置。这个示例用于运行一个mysql和wordpress,yaml如下:

apiVersion: v1
kind: Pod
metadata:
  name: wordpressmysql
  namespace: default
spec:
  containers:
  - name: mysql
    image: mysql:8.0
    imagePullPolicy: IfNotPresent
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "UIzo_0920984+45"
    - name: MYSQL_USER
      value: "test"
    - name: MYSQL_PASSWORD
      value: "Teac-92094+092"
    - name: MYSQL_DATABASE
      value: "test"
    ports:
    - name: mysql
      containerPort: 3306
    resources:
      requests:
        memory: "1024Mi"
        cpu: "200m"
      limits:
        memory: "1024Mi"
        cpu: "400m"
    startupProbe:
      tcpSocket:
        port: mysql
      initialDelaySeconds: 20
      failureThreshold: 3
      periodSeconds: 5
    livenessProbe:
      tcpSocket:
        port: mysql
      periodSeconds: 5
      initialDelaySeconds: 5
    readinessProbe:
      exec:
        command: ["sh", "-c", "mysql -u$(MYSQL_USER) -p$(MYSQL_PASSWORD) -e 'SELECT 1'"]
      initialDelaySeconds: 5
      timeoutSeconds: 1
      periodSeconds: 5
  - name: wordpress
    image: wordpress
    imagePullPolicy: IfNotPresent
    env:
    - name: WORDPRESS_DB_HOST
      value: "127.0.0.1"
    - name: WORDPRESS_DB_USER
      value: "test"
    - name: WORDPRESS_DB_PASSWORD
      value: "Teac-92094+092"
    - name: WORDPRESS_DB_NAME
      value: "test"
    resources:
      requests:
        memory: "1024Mi"
        cpu: "200m"
      limits:
        memory: "1024Mi"
        cpu: "400m"
    startupProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 20
      failureThreshold: 3
      periodSeconds: 5
    livenessProbe:
      httpGet:
        path: '/readme.html'
        port: 80
        scheme: HTTP
      periodSeconds: 5
      initialDelaySeconds: 5
    readinessProbe:
      httpGet:
        path: '/readme.html'
        port: 80
        scheme: HTTP
      initialDelaySeconds: 5
      timeoutSeconds: 1
      periodSeconds: 5

上面的内容保存成yaml文件,如wordpress.yaml。然后使用kubectl apply -f ./wordpress.yaml命令来运行它,运行结果如下:

其中,STATUS列表示运行状态,Running表示正常的运行状态。STATUS列还有其他比较常见的状态,如下:

    • Pending:正在调度。如果一直pending,那可能是集群没有满足运行要求的节点。一般通过kubectl describe命令可以很好的了解Pending的原因。
    • ImagePullBackOff:表示镜像下载失败。可能镜像名配置错误,或者网络故障等。
    • Error:容器启动过程发生错误。一般是容器启动命令、参数配置等错误导致。
    • CrashLoopBackOff:表示pod发生错误,正在重启。
    • Completed:运行完成,进程已经终止。
    • Terminating:正在删除。如果时间太久,则需要借助强制删除的手段。如借助 --grace-period=0 --force指令快速删除pod,或者删除finalizers字段来实现删除卡在terminating状态的namespace等。
    • Evicted:表示该pod被节点驱逐。
    • Unkown: 未知异常。可以查看节点状态信息是否节点异常导致。


除了通过kubectl get pods查看pod的运行状态外,还可以通过kubectl describe获取pod的详细信息,或者使用kubectl logs获取pod中容器的日志等。

#查看pods,可以通过-n 指定特定namespace的名称,默认是default;通过-o 指定显示的格式
kubectl get pods [-n NAMESPACE] [-o yaml|json|wide......]

#查看pod的详细状态
kubectl describe -f FILENAME
kubectl describe pods POD [options]

#查看pod的日志
 kubectl logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER] [options]

查看详细信息,这里可以看到启动过程。如果出现异常,“Message”列往往能提供比较大的帮助。

查看日志:

三、pod资源文件解析

从上面的示例中,我们可以提取重要的5个模块。如下所示:

apiVersion: v1 #指定api所属群组及版本
kind: Pod #指定资源类别
metadata: #资源元数据信息
  name: example
  namespace: default
  ....
spec: #资源期望状态,由用户定义
  ....
status: #资源运行状态,由k8s生成
  ....

1、apiVersion

kubernetes的中,资源的操作都通过apiserver来完成。kube-apiserver存在各种各样的api,不同的api也有不同的版本,比如beta、alpha等。apiVersion字段的构成,一般是<apiGroup>/<version>,即<所属群组>/<api版本>。kubernetes中的所有支持的apiVersion可以通过命令kubectl api-versions来查询。

如上图所示,这里列出了目前我部署的集群中,所有的apiVersion信息。上图中,没有apiGroup的v1是核心群组,该群组的资源皆是k8s的核心资源,如namespace、services、pods等。

2、kind

kind字段定义apiVersion中所使用的资源类型。资源类型相关命令如下:

kubectl api-resources --api-group='<群组名>' #其中核心群组为空

#相关资源的使用示例可以通过以下命令获取帮助信息
kubectl expain <resource_name>[.<field_name>.<field_name>.. ]

#示例:查询pod的资源的配置帮助
kubectl explain pod
#示例:查询pod的资源中metadata的配置帮助
kubectl explain pod.metadata

查询核心api资源群组所拥有的资源信息:

查询pods的配置帮助信息:

每个字段的详细配置,需要加在资源类型后面进行查询,子字段名加在父字段后面,如kubectl explain pod.metadata.labels

3、metadata

metadata字段用来定义资源的元数据。常用的元数据主要有:

  • name:资源名称
  • namespace:资源所属命名空间
  • labels:资源的标签
  • annotations:注解,说明。有时候,服务会通过该项来完成配置的修改。

下图中,我们创建的wordpress中的metadata信息。这里面,除了name和namespace是我们自己定义的外,其他的都是k8s自己生成的。

这个示例中,我们没有使用labels。不过,其实labels是非常重要的配置项,实际中会经常用到。

4、spec和status

spec是定义资源的期望结果,status字段,则由k8s自动生成,表明资源的实际运行结果。我们只需要定义spec即可。

spec设计较多配置,再起一节。

三、pod.spec

spec字段中,有很多配置项,这里以上面的示例做出说明。以后再扩展,整理其他字段信息。

spec:
  #定义要运行的容器信息
  containers:
  #一个pod可以运行多个容器,每个容器都有一个格式对齐的‘-’标识
  #name表示这个容器的名称
  - name: mysql
    #image表示容器的镜像
    image: mysql:8.0
    #这里指定下载策略,其他还有Always和Never两种类型
    imagePullPolicy: IfNotPresent
    #定义容器所使用的环境变量
    env:
     ......
    #可以在这里列出要暴露的端口
    ports:
      ......
    #这里配置的是资源的请求和限制
    resources:
      ......
    #启动探测
    startupProbe:
      ......
    #存活探测
    livenessProbe:
      ......
    #就绪探测
    readinessProbe:
      ......

下面,整理以下env、resources、startupProbe、livenessProbe以及readinessProbe的配置信息。

1、env

容器构建时,往往会定义很多环境变量,便于实际运行时,对容器的服务进行配置。k8s中,使用env字段来完成环境变量的传递和配置。env的配置,有多种方式,如下所示:

env:
  #1)获取pod信息作为环境变量
  - name: MY_NODE_NAME
    valueFrom:
      fieldRef:
        fieldPath: spec.nodeName
  #2)定义键值对来传递环境变量
  - name: DEMO_FAREWELL
    value: "Such a sweet sorrow"
  #3)从secret中读取key的值作为变量的值
  #secret创建示例:kubectl create secret generic backend-user --from-literal=backend-username='backend-admin'
  - name: SECRET_USERNAME
    valueFrom:
      secretKeyRef:
        name: backend-user
        key: backend-username
#这种形式,也是读取secret,不过这里传递的时键值对,而不是纯粹的值。
envFrom:
  - secretRef:
      name: test-secret

这里只介绍了四种定义形式,实际上,我们还可以通过volume挂载文件的方式来传递。不过这样,我们需要读取文件的信息来完成环境变量配置。

2、resources

resources用来定义资源配额,它有两大配置项,requests和limits。requests用来定义资源请求的数量,limits则是限制资源的使用。目前,k8s支持三种资源的请求和限制:内存、cpu和hugepages。

 resources:
      requests:
        memory: "1024Mi"
        cpu: "200m"
      limits:
        memory: "1024Mi"
        cpu: "400m"

本例中,我们定义了内存和cpu的请求和限制。实际工作中,cpu的使用会变化,时大时小;内存就不一样,一但用了,除非重启否则不会释放。所以,配置cpu,limits可以大于requests;但配置内存,建议两者一样。避免内存不足导致oom故障。

3、startupProbe、livenessProbe和readinessProbe

startupProbe是k8s用来检测容器是否启动完成的配置项。之所以有这个配置项,而不是使用livenessProbe,是因为livenessProbe用来检测pod是否存活的,一旦pod启动时间太久,那么,我们通过livenessprobe发现故障的时间就越晚。通过startupProbe,我们可以把容器的启动状态和容器的运行状态分离看,更好的了解容器的运行状况。startupProbe首次检测成功后即退出,满足失败阈值会导致容器重启。

livenessProbe,探测容器是否存活。定义了startupProbe,会在startupProbe检测完成后开始,满足失败阈值的话会导致容器重启。

readinessProbe,检测容器是否已经准备好提供服务。满足失败阈值的话,会导致服务剔除该pod,但该pod不会重启。检测成功后,会再次加入。readiness探针使用时,要避免配置失误,导致容器一直存在,但又无法提供服务,最好导致资源被消耗完毕的情况出现。

    readinessProbe:
      exec:
        command: ["sh", "-c", "mysql -u$(MYSQL_USER) -p$(MYSQL_PASSWORD) -e 'SELECT 1'"]
      initialDelaySeconds: 5
      timeoutSeconds: 1
      periodSeconds: 5
......
......
......
    startupProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 20
      failureThreshold: 3
      periodSeconds: 5
    livenessProbe:
      httpGet:
        path: '/readme.html'
        port: 80
        scheme: HTTP
      periodSeconds: 5
      initialDelaySeconds: 5

上面的示例中,我们有三种检测方式,分别是http、tcp和exec。官方网站里,还有gRPC的方式,不过我们这里没有用到。三种检测方式,这三个探测配置都可以使用。

相关参数解析:

    • initialDelaySeconds:初始化延迟时间,表示该Probe在多长时间后进行首次探测。
    • failureThreshold:失败的阈值。一旦到达该失败次数,根据不同的Probe触发对应的策略
    • periodSeconds:检测的间隔。默认10s,最小1s。
    • timeoutSeconds:超时时间。像http和tcp检测,可以设置超时时间。默认1s,最小1s。
    • successThreshold:成功的阈值。默认1次,有需要的可以设置多次。
    • terminationGracePeriodSeconds:终止服务到强制停止容器的宽限期,默认30s。该配置不能用于readinessProbe探针。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。