K8S学习笔记之最小控制单元Pod (一)

概念

k8s是通过定义一个Pod的资源,然后在Pod里面运行容器,容器需要指定一个镜像,这样就可以用来运行具体的服务。一个Pod封装一个容器(也可以封装多个容器),Pod里的容器共享存储、网络等。也就是说,应该把整个pod看作虚拟机,然后每个容器相当于运行在虚拟机的进程。Pod是需要调度到k8s集群的工作节点来运行的,具体调度到哪个节点,是根据scheduler调度器实现的。
在这里插入图片描述

分为自主式的pod和控制器控制的pod,一般采用控制器来管理pod。

#一个pod的创建流程
1.客户端提交创建Pod的请求,可以通过调用API Server的Rest API接口,也可以通过kubectl命令行工具。如kubectl apply -f filename.yaml(资源清单文件)
2.apiserver接收到pod创建请求后,会将yaml中的属性信息(metadata)写入etcd。
3.apiserver触发watch机制准备创建pod,信息转发给调度器scheduler,调度器使用调度算法选择node,调度器将node信息给apiserver,apiserver将绑定的node信息写入etcd
4.apiserver又通过watch机制,调用kubelet,指定pod信息,调用Docker API创建并启动pod内的容器。
5.创建完成之后反馈给kubelet, kubelet又将pod的状态信息给apiserver,apiserver又将pod的状态信息写入etcd。
# scheduler调度器
调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。

scheduler 查看 k8s api ,类似于通知机制。
首先判断:pod.spec.Node == null?
若为null,表示这个Pod请求是新来的,需要创建;因此先进行调度计算,找到最“闲”的node。
然后将信息在etcd数据库中更新分配结果:pod.spec.Node = nodeA (设置一个具体的节点)

Pod创建流程

资源清单文件

vim pod-xxxx.yaml
# 查看资源信息,根据提示写资源文件
kubectl explain Pod.spec.containers.xxxx
# 更新资源清单
kubectl apply -f pod-xxx.yaml
# 查看Pod资源(带有详细信息)
kubectl get pods -n <namespace> -o wide
# 查看有app=tomcat标签的Pod资源
kubectl get pods -n test -l app=tomcat
# 查看有app=tomcat和env=dev标签的Pod资源
kubectl get pods -n test -l app=tomcat,env=dev
apiVersion: v1
kind: Pod
metadata: 
  name: tomcat-test
  namespace: test
  labels: 
    app: tomcat
    version: v1.0
    env: dev
spec:
  containers: 
  - name: tomcat-test
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
# 资源书写详细解释
apiVersion: v1       # api版本(默认是v1)
kind: Pod            # 资源类型,Pod类型
metadata: 
  name: tomcat-test  # 资源名称(Pod的名字)
  namespace: test    # 资源所在的命名空间
  labels:            # 资源标签(自己定义区分使用)
    app: tomcat
    version: v1.0
    env: dev
spec:
  containers:                        # 容器列表
  - name: tomcat-test                # 容器的名称
    image: tomcat:8.5-jre8-alpine    # 使用的镜像
    imagePullPolicy: IfNotPresent    # 镜像拉取策略
    ports:                           # 端口列表
    - containerPort: 8080            # 容器端口
# kubectl explain Pod
apiVersion: 字符串值,定义了对象,代表了一个版本。
kind: 字符串类型的值,代表了要创建的资源。服务器可以从客户端提交的请求推断出这个资源。
metadata: 对象,定义元数据属性信息的
spec:对象,制定了定义Pod的规格,里面包含容器的信息
status:对象,表示状态,这个不可以修改,定义pod的时候也不需要定义这个字段

# kubectl explain Pod.metadata
annotations<map[string]string>:
  map类型表示对应的值是key-value键值对,<string,string>表示 key和value都是String类型的。
  用Annotation来记录的信息包括:
  build信息、release信息、Docker镜像信息等,例如时间戳、release id号、镜像hash值、docker registry   地址等;
  日志库、监控库、分析库等资源库的地址信息;
  程序调试工具信息,例如工具名称、版本号等;
  团队的联系信息,例如电话号码、负责人名称、网址等。

clusterName: 字符串,对象所属群集的名称。这是用来区分不同集群中具有相同名称和命名空间的资源。此字段现在未设置在任何位置,apiserver将忽略它,如果设置了就使用设置的值
labels<map[string]string>:map对象,创建的资源具有的标签,方便后续资源筛选识别
name<string>:创建的资源的名字
namespace<string>:创建的资源所属的名称空间。在同一个namesace下的资源名字是唯一的,默认的名称空间是default。

# kubectl explain pod.spec
activeDeadlineSeconds<integer>:表示Pod可以运行的最长时间,达到设置的值后,Pod会自动停止。
affinity<Object>:定义亲和性的
containers<[]Object> -required-:containers是对象列表,用来定义容器的,是必须字段。对象列表表示下面有很多对象,对象列表下面的内容用 - 连接,至少有一个容器对象。

# kubectl explain pod.spec.containers
image<string>:image是用来指定容器需要的镜像的
imagePullPolicy	<string>:
镜像拉取策略,pod启动需要镜像,可以根据这个字段设置镜像拉取策略,支持如下三种:
  Always:不管本地是否存在镜像,都要重新拉取镜像
  Never: 从不拉取镜像
  IfNotPresent:如果本地存在,使用本地的镜像,本地不存在,从官方拉取镜像

name<string> -required-:name是必须字段,用来指定容器名字的
ports<[]Object>:port是端口,属于对象列表

# kubectl explain pod.spec.containers.ports
containerPort	<integer> -required-: containerPort是必须字段, pod中的容器需要暴露的端口。
hostIP	<string>: 将容器中的服务暴露到宿主机的端口上时,可以指定绑定的宿主机 IP。
hostPort	<integer>:容器中的服务在宿主机上映射的端口
###补充###
# 查看pod日志
kubectl logs pod-first
# 查看pod里指定容器的日志
kubectl logs pod-first -c tomcat-first
# 进入到刚才创建的pod,刚才创建的pod名字是web
kubectl exec -it pod-first -- /bin/bash
# 假如pod里有多个容器,进入到pod里的指定容器,按如下命令:
kubectl exec -it pod-first -c tomcat-first -- /bin/bash
# 通过命令行创建Pod(不推荐)
kubectl run tomcat --image=tomcat-8.5-jre8  --image-pull-policy='IfNotPresent'  --port=8080

命名空间

又可称为虚拟集群,控制k8s集群级别的资源。适用于跨团队或者项目的场景。

## 使用命令 ##
# 系统内置命名空间 kube-system、default
# 创建一个命名空间
kubectl create namespace <ns-name>
# 查看命名空间&查看制定ns详细信息
kubectl get ns
kubectl describe ns <ns-name>
# 切换命名空间
kubectl config set-context --current --namespace=kube-system
# 查看指定命名空间的pod
kubectl get pods -n <ns-name>
#查看哪些资源属于命名空间级别的
kubectl api-resources --namespaced=true

可以对命名空间的硬件资源进行使用限制

vim namespace-quota.yaml
##每个容器必须设置内存请求(memory request),内存限额(memory limit),cpu请求(cpu request)和cpu限额(cpu limit)。
#所有容器的内存请求总额不得超过2GiB。
#所有容器的内存限额总额不得超过4 GiB。
#所有容器的CPU请求总额不得超过2 CPU。
#所有容器的CPU限额总额不得超过4CPU。
apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-quota
  namespace: test
spec:
  hard:
    requests.cpu: "2"
    requests.memory: 2Gi
    limits.cpu: "4"
    limits.memory: 4Gi
# 创建pod时候必须设置资源限额,否则创建失败
vim pod-test.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-test
  namespace: test
  labels:
    app: tomcat-pod-test
spec:
  containers:
  - name:  tomcat-test
    ports:
    - containerPort: 8080
    image: tomcat-8.5-jre8
    imagePullPolicy: IfNotPresent

标签

其实就一对 key/value ,被关联到资源对象上,可以用来划分和标识特定的对象,方便后面对资源进行筛选使用等。

# 对已经存在的pod打标签 & 查看
kubectl label pods pod-first  release=v1
kubectl get pods pod-first --show-labels

#列出默认名称空间下标签key是release的pod,不显示标签
kubectl get pods -l release
#列出默认名称空间下标签key是release、值是v1的pod,不显示标签
kubectl get pods -l release=v1
#列出默认名称空间下标签key是release的所有pod,并打印对应的标签值
kubectl get pods -L release

#查看所有名称空间下的所有pod的标签
kubectl get pods --all-namespace --show-labels
kubectl get pods -l release=v1 -L release

节点选择器

可以使Pod调度到指定名称/特点的node上

nodeName

# 定义一个pod,将其调度到node1上
vim pod-test.yaml
kubectl apply -f pod.test.yaml
kubectl get pods -o wide
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
  namespace: default
  labels:
    app: myapp
    env: dev
spec:
  nodeName: node1
  containers:
  - name:  tomcat-pod-java
    ports:
    - containerPort: 8080
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent
  - name: busybox
    image: busybox:latest
    command:
    - "/bin/sh"
    - "-c"
- "sleep 3600"

nodeSelector

# 给node打标签
kubectl label nodes node2 disk=ceph
# 定义一个pod,将其调度到有disk=ceph标签的节点上
vim pod-test.yaml
kubectl apply -f pod-test.yaml
kubectl get pods -o wide
apiVersion: v1
kind: Pod
metadata:
  name: demo-pod-1
  namespace: default
  labels:
    app: myapp
    env: dev
spec:
  nodeSelector:
    disk: ceph
  containers:
  - name:  tomcat-pod-java
    ports:
    - containerPort: 8080
    image: tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent

节点亲和度和反亲和度

节点亲和性

pod与node的关系,是将pod调度到node时候的干预策略

# kubectl explain pods.spec.affinity
nodeAffinity	<Object> 节点亲和度
podAffinity	    <Object> pod亲和度
podAntiAffinity	<Object> pod反亲和度
# kubectl explain  pods.spec.affinity.nodeAffinity
表示有节点尽量满足这个位置定义的亲和性,这不是一个必须的条件,软亲和性
preferredDuringSchedulingIgnoredDuringExecution	<[]Object>
表示必须有节点满足这个位置定义的亲和性,这是个硬性条件,硬亲和性
requiredDuringSchedulingIgnoredDuringExecution	<Object>
# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms
matchExpressions	<[]Object>  匹配表达式的
matchFields	        <[]Object>  匹配字段的
# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchFields
key	    <string> -required-
values	<[]string>
# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions
key	     <string> -required-  检查label
operator <string> -required-  做等值选则还是不等值选则
values	 <[]string>           给定值
# 给node1打标签
kubectl label nodes node1 zone=foo
# 创建一个pod,检查当前节点中有任意一个节点拥有zone标签的值是foo或者bar,就可以把pod调度到这个 (硬亲和性)
# 硬亲和性:必须要有这个标签的节点,如果没有,则pod状态是pending
# 软亲和性:指定这个标签的节点可有可无,如果没有,则pod则调度到任意一个节点
vim pod-test.yaml
kubectl apply -f pod.test.yaml
kubectl get pods -o wide | grep pod-node
apiVersion: v1
kind: Pod
metadata:
  name: pod-node-affinity-demo
  namespace: default
  labels:
  app: myapp
  tier: frontend
spec:
  containers:
  - name: myapp
  image: ikubernetes/myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
        - key: zone
          operator: In
          values:
          - foo
          - bar
# 测试软亲和性
affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecutio:
        nodeSelectorTerms:
        - matchExpressions:
        - key: zone1
          operator: In
          values:
          - foo1
          - bar1

pod亲和性和反亲和性

亲和性:pod和pod之间的相近关系,pod倾向于调度到与自己“相似”或者“亲戚”的pod所在节点。相似手段可以使标签、IP等。

# 与上述一样,同样有软硬亲和度
# kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution
labelSelector	<Object>
namespaces	    <[]string>
topologyKey	    <string> -required-
# topologyKey:
位置拓扑的键,这个是必须字段
怎么判断是不是同一个位置:
rack=rack1 使用rack的键是同一个位置
row=row1   使用row的键是同一个位置
# labelSelector:
我们要判断pod跟别的pod亲和,跟哪个pod亲和,需要靠labelSelector,通过labelSelector选则一组能作为亲和对象的pod资源
# namespace:
labelSelector需要选则一组资源,那么这组资源是在哪个名称空间中呢,通过namespace指定,如果不指定namespaces,那么就是当前创建pod的名称空间
# kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.labelSelector 
matchExpressions	<[]Object>
matchLabels	        <map[string]string>
# 定义两个pod,第一个作为基准,第二个跟着它走
# 表示创建的pod必须与拥有app=myapp标签的pod在一个节点上
vim pod-test-affinity.yaml
kubectl apply -f pod-test.yaml
kubectl get pods -o wide
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app: myapp
    tier: frontend
spec:
    containers:
    - name: myapp
      image: ikubernetes/myapp:v1

---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
    containers:
    - name: busybox
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      command: ["sh","-c","sleep 3600"]
    affinity:
      podAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
         - labelSelector:
              matchExpressions:
              - {key: app, operator: In, values: ["myapp"]}
           topologyKey: kubernetes.io/hostname
# 如何查看topologyKey
kubectl get nodes --show-labels
# 测试反亲和性
# 第二个pod调度到与第一个pod不一样的节点上
affinity:
  podAntAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchExpressions:
        - {key: app, operator: In, values: ["myapp"]}
      topologyKey: kubernetes.io/hostname
# 测试换一个topologyKey 【??】
kubectl label nodes  node2  zone=foo
kubectl label nodes  node1  zone=foo --overwrite
affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchExpressions:
        - {key: app3 ,operator: In, values: ["myapp3"]}
      topologyKey:  zone

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AlgebraFly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值