OpenShift 4 - 了解 OpenShift 是如何使用节点本地镜像缓存

OpenShift / RHEL / DevSecOps 汇总目录

文本已在 OpenShift 4.15 环境中进行验证。

什么是节点本地镜像缓存

一个 OpenShift 集群节点在运行 Pod 前需要先从 Registry 拉取到相关 Image。这些镜像会保存在节点本地存储中并作为缓存,这样该节点如果再使用这个 Image 就会先使用节点缓存中的镜像,从而提升 Pod 的启动速度。

OpenShift 是如何使用节点本地镜像缓存

查看节点本地保存的镜像缓存

  1. 确认可以访问到 https://quay.io/repository/openshiftroadshow/parksmap?tab=tags,其中有测试镜像。
  2. 执行命令获取当前节点名。
bash 复制代码
$ oc get node
NAME                            STATUS   ROLES                         AGE   VERSION
control-plane-cluster-cw8ww-1   Ready    control-plane,master,worker   30h   v1.28.7+f1b5f6c
 
$ NODE_NAME=control-plane-cluster-cw8ww-1
  1. 执行命令,在 Deployment 中使用 quay.io/openshiftroadshow/parksmap:latest 镜像,并让其运行在指定节点以方便跟踪。
yaml 复制代码
$ oc apply -f - << EOF       
kind: Deployment
apiVersion: apps/v1
metadata:
  name: parksmap
spec:
  replicas: 1
  selector:
    matchLabels:
      app: parksmap
  template:
    metadata:
      labels:
        app: parksmap
    spec:
      nodeName: ${NODE_NAME}
      containers:
        - name: hello-openshift
          image: 'quay.io/openshiftroadshow/parksmap:latest'
          ports:
            - containerPort: 8080
              protocol: TCP
            - containerPort: 8888
              protocol: TCP
          imagePullPolicy: IfNotPresent
EOF
  1. 运行命令,确认 Pod 可以正常运行起来,并注意 Pod 运行在指定节点上。
bash 复制代码
$ oc get pod -owide
NAME                                      READY   STATUS    RESTARTS   AGE   IP             NODE                            
parksmap-9bdf99cc-km892                   1/1     Running   0          32m   10.132.0.114   control-plane-cluster-cw8ww-1
  1. 进入 Pod 运行的的 Node,并切换到 /host。

    $ oc debug node/$NODE_NAME
    sh-4.4# chroot /host

  2. 运行以下命令,确认可以在节点中找到 openshiftroadshow/parksmap:latest 镜像信息。注意镜像的 id 和 digest。

json 复制代码
$  cat /var/lib/containers/storage/overlay-images/images.json | jq
......
  {
    "id": "0c2f55f381ee738ec77722ea7b92ac97fcfa1cb6ef8e323df929b0ab40c70a47",
    "digest": "sha256:89d1e324846cb431df9039e1a7fd0ed2ba0c51aafbae73f2abd70a83d5fa173b",
    "names": [
      "quay.io/openshiftroadshow/parksmap:latest"
    ],
    "names-history": [
      "quay.io/openshiftroadshow/parksmap:latest"
    ],
    "layer": "e0c471633f3e337a376fd877385b6bfc287b9144c003aa61c933ec853610e3ce",
    "metadata": "{}",
    "big-data-names": [
      "sha256:0c2f55f381ee738ec77722ea7b92ac97fcfa1cb6ef8e323df929b0ab40c70a47",
      "manifest-sha256:89d1e324846cb431df9039e1a7fd0ed2ba0c51aafbae73f2abd70a83d5fa173b",
      "manifest"
    ],
    "big-data-sizes": {
      "manifest": 1373,
      "manifest-sha256:89d1e324846cb431df9039e1a7fd0ed2ba0c51aafbae73f2abd70a83d5fa173b": 1373,
      "sha256:0c2f55f381ee738ec77722ea7b92ac97fcfa1cb6ef8e323df929b0ab40c70a47": 5671
    },
    "big-data-digests": {
      "manifest": "sha256:89d1e324846cb431df9039e1a7fd0ed2ba0c51aafbae73f2abd70a83d5fa173b",
      "manifest-sha256:89d1e324846cb431df9039e1a7fd0ed2ba0c51aafbae73f2abd70a83d5fa173b": "sha256:89d1e324846cb431df9039e1a7fd0ed2ba0c51aafbae73f2abd70a83d5fa173b",
      "sha256:0c2f55f381ee738ec77722ea7b92ac97fcfa1cb6ef8e323df929b0ab40c70a47": "sha256:0c2f55f381ee738ec77722ea7b92ac97fcfa1cb6ef8e323df929b0ab40c70a47"
    },
    "created": "2021-02-01T12:52:36.138979177Z"
  }
  1. quay.io 中使用 digest 方式获取上述镜像,确认 digest 和上一步返回的 digest 一样。
  2. 执行命令查找第 6 步返回的 id,确认该镜像已和 /var/lib/containers/storage/overlay-images 中名为 id 的目录对应起来。
bash 复制代码
$ ls -al /var/lib/containers/storage/overlay-images | grep 0c2f55f381ee738ec77722ea7b92ac97fcfa1cb6ef8e323df929b0ab40c70a47
drwx------.   2 root root   4096 Apr 10 01:15 0c2f55f381ee738ec77722ea7b92ac97fcfa1cb6ef8e323df929b0ab40c70a47
  1. 退出节点。
  2. 另外还可以在该节点的 YAML 或"详情"中确认该节点上有此镜像。

镜像缓存是如何被使用

  1. 在自有 Image Registry 上准备一个自用的测试镜像,例如 quay.io/dawnskyliu/hello-openshift:v1。
  2. 执行以下命令,在 Deployment 中使用以上镜像。由于 imagePullPolicy 使用了 IfNotPresent 策略,因此如果本地缓存中已有,就不会重新拉取该镜像。
yaml 复制代码
$ oc apply -f - << EOF
kind: Deployment
apiVersion: apps/v1
metadata:
  name: hello-openshift-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-openshift-v1
  template:
    metadata:
      labels:
        app: hello-openshift-v1
    spec:
      nodeName: ${NODE_NAME}
      containers:
        - name: hello-openshift
          image: 'quay.io/dawnskyliu/hello-openshift:v1'
          ports:
            - containerPort: 8080
              protocol: TCP
            - containerPort: 8888
              protocol: TCP
          imagePullPolicy: IfNotPresent
EOF
  1. 确认使用该镜像的 Pod 可以运行起来。
bash 复制代码
$ oc get pod
NAME                                  READY   STATUS    RESTARTS   AGE
hello-openshift-v1-6995c77fb5-hvd84   1/1     Running   0          13s
  1. 可参照上一节确认在节点的存储中已有该镜像的缓存。
  2. 删除 quay.io/dawnskyliu/hello-openshift:v1 或修改 tag,使访问 quay.io/dawnskyliu/hello-openshift:v1 失效。
  3. 然后再删除 hello-openshift-v1 部署。
bash 复制代码
$ oc delete deploy hello-openshift-v1
  1. 重新执行命令,使用 quay.io/dawnskyliu/hello-openshift:v1 镜像创建部署。确认此时虽然 quay.io/dawnskyliu/hello-openshift:v1 已失效,但通过使用节点本地缓存 pod 还可成功运行。
yaml 复制代码
$ oc apply -f - << EOF
kind: Deployment
apiVersion: apps/v1
metadata:
  name: hello-openshift-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-openshift-v1
  template:
    metadata:
      labels:
        app: hello-openshift-v1
    spec:
      nodeName: ${NODE_NAME}
      containers:
        - name: hello-openshift
          image: 'quay.io/dawnskyliu/hello-openshift:v1'
          ports:
            - containerPort: 8080
              protocol: TCP
            - containerPort: 8888
              protocol: TCP
          imagePullPolicy: IfNotPresent
EOF
  1. 再次删除 hello-openshift-v1 部署,然后重新启动 NODE_NAME 节点,最后再次创建 hello-openshift-v1 部署,确认 pod 依然可以运行成功。这说明节点本地存储依然发挥作用。
  2. 再次删除 hello-openshift-v1 部署,然后将 imagePullPolicy 改为 Always 再重新创建部署,确认会失败。这是由于 Always 会重新拉取镜像,但已无法访问到远程的 quay.io/dawnskyliu/hello-openshift:v1 镜像了。
yaml 复制代码
$ oc delete deploy hello-openshift-v1
$ oc apply -f - << EOF
kind: Deployment
apiVersion: apps/v1
metadata:
  name: hello-openshift-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-openshift-v1
  template:
    metadata:
      labels:
        app: hello-openshift-v1
    spec:
      nodeName: ${NODE_NAME}
      containers:
        - name: hello-openshift
          image: 'quay.io/dawnskyliu/hello-openshift:v1'
          ports:
            - containerPort: 8080
              protocol: TCP
            - containerPort: 8888
              protocol: TCP
          imagePullPolicy: Always
EOF

自动清理节点本地镜像缓存

随着保存在节点本地存储的镜像缓存的数量增加,会不断消耗节点的本地存储空间,因此需要定期清理镜像缓存以释放存储空间。运行在节点的 kubelet 提供了清理本地镜像缓存的机制,而 OpenShift 4 是无法手动删除节点镜像缓存的。

基于 oc new-app 生成的部署和基于 YAML 的部署之间的差异

即便不考虑节点本地的镜像缓存,基于 oc new-app 生成的部署和基于 YAML 的部署之间是存在一定差异。

基于 oc new-app 生成的部署

在使用 oc new-app 命令生成部署的时候,虽然在命令中提供的是远程镜像地址,但 OpenShift 首先会把镜像从远程拉到 OpenShift 内部的镜像库中,然后再在 Deployment 的定义中自动通过 ImageStream 使用已在 OpenShift 内部镜像库中的镜像。

基于 YAML 创建的部署

当使用基于 YAML 的部署时候,其容器使用的镜像地址不会发生变化,会直接使用远程镜像库中的镜像。

参考

https://www.redhat.com/en/blog/image-garbage-collection-in-openshift

https://docs.openshift.com/container-platform/4.15/nodes/nodes/nodes-nodes-garbage-collection.html

https://medium.com/kubernetes-tutorials/efficient-node-out-of-resource-management-in-kubernetes-67f158da6e59

https://itnext.io/improve-container-image-availability-and-speed-with-caching-in-kubernetes-870fa7bfa1ed

相关推荐
昌sit!6 小时前
K8S node节点没有相应的pod镜像运行故障处理办法
云原生·容器·kubernetes
茶馆大橘9 小时前
微服务系列五:避免雪崩问题的限流、隔离、熔断措施
java·jmeter·spring cloud·微服务·云原生·架构·sentinel
北漂IT民工_程序员_ZG10 小时前
k8s集群安装(minikube)
云原生·容器·kubernetes
coding侠客10 小时前
揭秘!微服务架构下,Apollo 配置中心凭啥扮演关键角色?
微服务·云原生·架构
2301_8061313616 小时前
Kubernetes的基本构建块和最小可调度单元pod-0
云原生·容器·kubernetes
大卡尔18 小时前
Reviewbot 开源 | 为什么我们要打造自己的代码审查服务?
devops·code review·静态检查·工程效率
极小狐20 小时前
驭码上新,AI Code Review、基于代码库的知识问答,让研发起飞
gitlab·devsecops·devops·极狐gitlab·安全合规
licy__21 小时前
Docker 基础命令简介
docker·云原生·eureka
0_1_bits1 天前
【系统设计】高效的分布式系统:使用 Spring Boot 和 Kafka 实现 Saga 模式
spring boot·后端·云原生·架构·kafka·linq
探索云原生1 天前
GPU 环境搭建指南:如何在裸机、Docker、K8s 等环境中使用 GPU
ai·云原生·kubernetes·go·gpu