• [问题求助] 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 修订记录 
  • [技术干货] 在docker上安装、运行mqtt服务器以及nodered
    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。 # 1.配置docker CE 这里我们使用阿里云的镜像。虽然我们使用的是华为云ESC服务器,但仍然适用哦~~ 分别执行以下步骤(使用的是ubuntu服务器,Centos的可以去查看阿里云容器镜像): ``` # step 1:更新 sudo apt-get update # step 2: 安装必要的系统工具 sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common # step 3: 安装GPG证书 curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add - # step 4: 写入软件源信息 sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" # step 5: 更新 sudo apt-get -y update # step 6:安装Docker-CE sudo apt-get -y install docker-ce ``` 成功安装后,输入docker -v可查看docker版本。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202202/06/112004ujxiouq5wvamtgic.png) # 2.获取镜像 **获取emq镜像** 更多信息请查看EMQx官网:emqx.com ``` docker pull emqx/emqx-ee ``` **获取nodered镜像** - nodered的1.0系列在docker hub上已经改名为nodered/node-red. - nodered的0.20.x在docker hub上仍然叫nodered/node-red-docker. ``` docker pull nodered/node-red ``` # 3.查看镜像 输入命令 ``` docker images ``` 如下图 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202202/06/112447e6h8ctulasiyip6o.png) # 4.运行 - 运行EMQ ``` docker run emqx ``` 停止 ``` docker stop emqx ``` - 运行nodered ``` docker run -it -p 1880:1880 --name nodered nodered/node-red ``` 此命令开启nodered运行后,会一直占用终端,可以使用ctrl + p +q,将进程转到后台运行,日志不会打印在终端上 查看当前docker进程 ps:ip:18083打开emq web页面,默认账号:admin 密码:public;ip:1880打开nodered web页面
  • [问题求助] 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 是如何工作的呢?
  • [问题求助] 鲲鹏服务器,Centos7安装docker后,启动不了mysql5.7
    【功能模块】鲲鹏服务器,Centos7安装docker后,启动不了mysql5.7【操作步骤&问题现象】1、WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested2、【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [技术干货] 在用服务器上通过Docker安装Node-red
    ### 什么是docker Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 Docker采用 C/S架构 Docker daemon 作为服务端接受来自客户的请求,并处理这些请求(创建、运行、分发容器)。 客户端和服务端既可以运行在一个机器上,也可通过 socket 或者RESTful API 来进行通信。Docker daemon 一般在宿主主机后台运行,等待接收来自客户端的消息。 Docker 客户端则为用户提供一系列可执行命令,用户用这些命令实现跟 Docker daemon 交互。 ### 什么是Node-red node-red官网:https://nodered.org/ Node-RED是一种编程工具,用于以新的、有趣的方式将硬件设备、api和在线服务连接在一起。它提供了一个基于浏览器的编辑器,通过使用调色板中的各种节点可以轻松地将流连接在一起,这些节点可以通过单击将其部署到运行时中。说得直白一点,就是通过图形化的简单拖动实现物联网设备的接入管理。 **基于浏览器的流编辑** Node-RED提供了一个基于浏览器的流编辑器,它可以很容易地使用调色板中的各种节点将流连接在一起。然后可以通过单击将流部署到运行时。 - 可以使用富文本编辑器在编辑器中创建JavaScript函数。 - 内置库允许您保存有用的函数、模板或流以供重用。 **start** Node-RED构建在Node.js之上,充分利用了它的事件驱动、非阻塞模型。这使得它非常适合在网络边缘,如树莓派的低成本硬件上运行,也适合在云上运行。(也就是说,需要安装Node.js哦) ## 获取Docker镜像 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202112/30/1424111svorjpussnfuoni.png) ``` docker run -it -p 1880:1880 --name mynodered nodered/node-red ``` ## 运行 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202112/30/142500zshjombhmy7i3cbj.png) ``` docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red ``` ## 查看效果 在浏览器中输入IP:1880 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202112/30/143515rqdvb773bcbeh2fx.png) ![image.png](![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202112/30/143444juwaa5dmdhyvvgo4.png) https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202112/30/143442tkvizptxwbrugbd5.png) ok 完美
  • [其他问题] docker: manifest for taotaoba/develop-env:20.2 not found: manife
    在基于CANN卡通图像生成的实验中,在挂载docker这一步骤时,出现了以下报错拉取时总是半路就断了,有无解决方法?