关于镜像:高性能存储SIG月度动态EROFS支持直接索引容器镜像tar包iouring将支持并优化NVMe直通

高性能存储 SIG(Special Interest Group)指标:存储畛域的倒退历程,实质上是存储介质与软件栈相互促进倒退的过程。高性能存储 SIG 致力于存储栈性能开掘,以后次要聚焦内核 io_uring 技术优化异步 IO 性能,应用长久化内存晋升业务单老本性能,容器场景存储技术优化等课题。高性能存储 SIG 冀望通过社区单干,打造规范的高性能存储技术软件栈,推动软硬件协同倒退。 01 本月 SIG 整体停顿1)本月合入 Anolis 主线 PR 共计 11 个,蕴含重要组件的个性反对,性能优化和 bugfix 等。 2)ANCK 5.10 反对 erofs subpage block 个性,晋升容器镜像 tar 包解压性能以及 golden image 的安全性。 3)ublk 零拷贝计划仍在社区探讨中。 4)ANCK 5.10 打算反对 io_uring nvme passthrough 个性,以进一步优化内核 IO 栈开销,晋升业务性能。 5)DSMS Anolis 8.6 联调继续进行中。 02 我的项目具体停顿1、Anolis OScve:CVE-2023-1611(PR1548/PR1549) erofs & fscache:优化按需场景 IO 性能(PR1557),erofs block-based IO 切换到 iomap 框架(PR1531),erofs 反对 subpage block for tarfs(PR1561) ...

May 11, 2023 · 2 min · jiezi

关于镜像:镜像拉取节省-90-以上快手基于-Dragonfly-的超大规模分发实践

01 挑战快手容器云平台旨在为快手一直增长、一直变动和多样化的业务,提供基于容器化部署的超大规模基础设施服务。为了实现这一指标,快手工程师须要解决弹性、稳定性、效率和无服务器架构等挑战,在这些挑战中,镜像散发的稳定性和效率也是最辣手的问题之一。 解决方案 为了让快手容器云平台的镜像散发更加稳固和高效,快手容器云技术团队携手阿里云、蚂蚁团体在龙蜥社区适配,优化落地解决方案。事实证明,Dragonfly 及其子项目 Nydus 是最合适的解决方案,该计划可能与现有零碎很好地兼容,在现有能力根底上平滑过渡,同时也为服务交付带来了大幅的效率晋升。 成果 Dragonfly 上线后,整个集群通过 P2P 组建散发网,所有节点帮忙中心化 Harbor 缓解网络带宽压力。Harbor 的网络带宽压力均匀缓解 70% 以上,峰值压力缓解 80% 以上,镜像散发零碎变得更加稳固、牢靠、高效,零碎可能同时反对更多数量的镜像并发拉取申请,尤其是在应答 Daemonset 部署和要害、大批量实例业务服务更新的场景中,高并发镜像拉取仓库不再是瓶颈。 应用我的项目 Dragonfly:https://github.com/dragonflyo... Nydus:https://github.com/dragonflyo... containerd:https://github.com/containerd... Harbor:https://github.com/goharbor/h... 02 相干数据峰值缓解 80% 以上镜像拉取工夫节俭 90% 以上POD 实例服务耗时节俭 50%03 为每月 10 亿用户提供稳定性和性能反对“在快手,Dragonfly 无效解决了海量文件散发问题” ——吴宏斌 快手综合经营平台负责人快手创立于 2011 年,是中国第一个短视频平台,每月为寰球 10 亿用户提供服务,其中也有 1.8 亿多用户在海内,其寰球脚印已迅速扩大至拉丁美洲、中东和东南亚。在快手,任何用户都能够通过短视频和直播来记录和分享他们的生存经验,展现他们的才华。快手与内容创作者、企业严密单干,次要从事内容社区和社交平台的经营,提供直播服务、在线营销服务、电子商务、娱乐、在线常识共享和其余增值服务。随着快手业务的快速增长,数以万计的要害服务和中间件运行在快手容器云平台上,镜像散发零碎的稳定性和效率变得越来越重要。 对于快手的镜像散发系统升级革新来说,最大的挑战不仅仅是镜像仓库峰值压力的缓解和镜像拉取减速,如何让服务散发无缝连接平滑过渡,尽可能让业务无感、不受零碎变动影响同样重要。快手容器云平台工程师通过调研发现,Nydus 与 Dragonfly 零碎深度集成,同时也反对传统 OCI 镜像,可能以兼容敌对的形式提供疾速、稳固、平安、便捷的容器镜像拜访,非常容易地就能适配容器云平台已有工作,实现业务从已有镜像应用形式平滑过渡到新镜像格局。平台惟一要做的就是将容器运行引擎从 Docker 切换到 containerd,因为 containerd 与 Dragonlfly 的集成体验更好。在快手工程师的致力下,大规模节点的容器引擎安稳切换轻而易举,containerd 和 Dragonfly 均已被疾速全面采纳。 稳固高效的镜像散发 对于稳固、高效的镜像散发,Dragonfly 给出了完满的答案。在快手,有许多重要的服务须要在短短几分钟内扩容到成千上万个实例,例如快手的 818 购物节或双 11 流动的业务扩容需要。这种缩放须要数千 GB 带宽能力间接从镜像仓库下载。在另外一些场景中,预测模型和搜寻业务须要定期更新模型参数文件和索引文件来保障举荐成果和检索成果,这在技术上意味着必须立刻将数百 GB 的文件散发到每个相干实例。 ...

January 31, 2023 · 1 min · jiezi

关于镜像:组织上线-资源共享协作自如

新性能~!期待已久的组织合作上线啦! 上线后反对在组织下创立镜像,组织成员可查看、拉取镜像,疾速实现镜像资源共享,组织高效协同。 具体怎么操作呢?跟我一起来看一下吧~ 创立组织1、登录建木Hub,点击导航上的【组织】-点击创立组织2、填写组织信息3、创立完组织起初到组织成员页面 4、输出用户惟一标识(查看惟一标识:个人头像下拉-设置-设置惟一标识),可间接增加成员,默认权限是成员,可切换为管理员 5、点击设置,可批改组织信息 创立组织下的镜像仓库1、点击导航上的【我的镜像】-点击创立镜像仓库2、填写镜像仓库信息,记得将归属选为组织~3、抉择要关联的代码仓库(Dockerfile寄存的Git仓库)4、点击创立进入构建打算页5、定义镜像主动构建的规定。倡议将Dockerfile寄存在所选代码仓库的根目录下,省去填写文件门路的这一步~6、构建打算创立后,在已抉择的Git仓库提交代码触发(能够基于分支或打标签的形式触发,次要依据本人制订的规定)7、构建打算执行实现后,点击【镜像标签】,查看已生成的镜像8、至此,组织下的镜像仓库创立实现✅!该组织下的其余成员也能查看此镜像仓库并拉取镜像~ 以上就是本期组织性能的内容,想理解更多细节,点击这里速去体验吧! 也欢送各位小伙伴给咱们提出意见反馈,微信扫码退出用户群~ 

December 26, 2022 · 1 min · jiezi

关于镜像:镜像搬运工-skopeo

镜像搬运工 skopeo介绍skopeo 是一个命令行工具,可对容器镜像和容器存储进行操作。 在没有dockerd的环境下,应用 skopeo 操作镜像是十分不便的。 装置# 装置 skopeohttps://github.com/containers/skopeo/blob/main/install.mdroot@cby:~# . /etc/os-releaseroot@cby:~# echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.listroot@cby:~# curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/Release.key | sudo apt-key add -root@cby:~# sudo apt-get updateroot@cby:~# sudo apt-get -y upgraderoot@cby:~# sudo apt-get -y install skopeoroot@cby:~# skopeo --versionroot@cby:~# skopeo --help # 子命令可采纳如下命令 skopeo [command] --help 命令Usage: skopeo [flags] skopeo [command]Available Commands: copy # 复制一个镜像从 A 到 B,这里的 A 和 B 能够为本地 docker 镜像或者 registry 上的镜像; delete # 删除一个镜像 tag,能够是本地 docker 镜像或者 registry 上的镜像; help # 帮忙查看 inspect # 查看一个镜像的 manifest 或者 image config 详细信息; list-tags # 列出存储库名称指定的镜像的tag login # 登陆某个镜像仓库,相似于 docker login 命令 logout # 退出某个已认证的镜像仓库, 相似于 docker logout 命令 manifest-digest # 计算文件的清单摘要是一个sha256sum 值 standalone-sign # 应用本地文件创建签名 standalone-verify # 验证本地文件的签名 sync # 将一个或多个图像从一个地位同步到另一个地位 (该性能十分Nice)Flags: --command-timeout duration # 命令超时工夫(单位秒) --debug # 启用debug模式 --insecure-policy # 在不进行任何策略查看的状况下运行该工具(如果没有配置 policy 的话须要加上该参数) --override-arch ARCH # 解决镜像时笼罩客户端 CPU 体系架构,如在 amd64 的机器上用 skopeo 解决 arm64 的镜像 --override-os OS # 解决镜像时笼罩客户端 OS --override-variant VARIANT # 解决镜像时应用VARIANT而不是运行架构变量 --policy string # 信赖策略文件的门路 (为镜像配置安全策略状况下应用) --registries.d DIR # 在目录中应用Registry配置文件(例如,用于容器签名存储) --tmpdir string # 用于存储临时文件的目录-h, --help help for skopeo -v, --version Version for Skopeo# 查看已有的认证信息root@cby:~# cat ~/.docker/config.json{ "auths": { "core.oiox.cn:30785": { "auth": "XXXX" }, "hb.oiox.cn": { "auth": "XXXX" }, "swr.cn-north-1.myhuaweicloud.com": { "auth": "XXXX" } }}root@cby:~# 应用# 从一个仓库拷贝到另一个仓库root@cby:~# skopeo copy docker://docker.io/busybox:latest docker://hb.oiox.cn/cby/busybox:latest --dest-authfile /root/.docker/config.json --src-tls-verify=false --dest-tls-verify=falseGetting image source signaturesCopying blob 405fecb6a2fa done Copying config 9d5226e6ce done Writing manifest to image destinationStoring signaturesroot@cby:~# # 从一个仓库同步所以版本到另一个仓库root@cby:~# skopeo sync --src docker --dest docker k8s.gcr.io/etcd hb.oiox.cn/cby/ --src-tls-verify=false --dest-tls-verify=falseINFO[0000] Tag presence check imagename=k8s.gcr.io/etcd tagged=falseINFO[0000] Getting tags image=k8s.gcr.io/etcdINFO[0004] Copying image ref 1/106 from="docker://k8s.gcr.io/etcd:2.0.12" to="docker://hb.oiox.cn/cby/etcd:2.0.12"Getting image source signaturesCopying blob a3ed95caeb02 done Copying blob a3ed95caeb02 done Copying blob a3ed95caeb02 done Copying blob 35c8bf5fd6cd done Copying blob a7e0d6960478 done Copying blob 3109a5487eac done Copying config 8c32a2c999 done Writing manifest to image destinationStoring signaturesINFO[0020] Copying image ref 2/106 from="docker://k8s.gcr.io/etcd:2.0.13" to="docker://hb.oiox.cn/cby/etcd:2.0.13"Getting image source signaturesCopying blob a3ed95caeb02 [--------------------------------------] 0.0b / 0.0bCopying blob a3ed95caeb02 skipped: already exists Copying blob 35c8bf5fd6cd skipped: already exists Copying blob a3ed95caeb02 skipped: already exists...root@cby:~## 删除镜像root@cby:~# skopeo delete docker://hb.oiox.cn/cby/etcd:2.0.12 --tls-verify=false --debugDEBU[0000] Loading registries configuration "/etc/containers/registries.conf" DEBU[0000] Loading registries configuration "/etc/containers/registries.conf.d/shortnames.conf" DEBU[0000] Found credentials for hb.oiox.cn in credential helper containers-auth.json DEBU[0000] Using registries.d directory /etc/containers/registries.d for sigstore configuration DEBU[0000] No signature storage configuration found for hb.oiox.cn/cby/etcd:2.0.12, using built-in default file:///var/lib/containers/sigstore DEBU[0000] Looking for TLS certificates and private keys in /etc/docker/certs.d/hb.oiox.cn DEBU[0000] GET https://hb.oiox.cn/v2/ DEBU[0000] Ping https://hb.oiox.cn/v2/ status 401 DEBU[0000] GET https://hb.oiox.cn/service/token?account=admin&scope=repository%3Acby%2Fetcd%3A%2A&service=harbor-registry DEBU[0000] GET https://hb.oiox.cn/v2/cby/etcd/manifests/2.0.12 DEBU[0000] DELETE https://hb.oiox.cn/v2/cby/etcd/manifests/sha256:24cf1202eea3953f9a8c44b0930d03666019ff8c277a0f6cd6190645eb1f7ba5 DEBU[0000] Deleting /var/lib/containers/sigstore/cby/etcd@sha256=24cf1202eea3953f9a8c44b0930d03666019ff8c277a0f6cd6190645eb1f7ba5/signature-1 root@cby:~# # 查看有哪些tagsroot@cby:~# skopeo list-tags docker://k8s.gcr.io/pause{ "Repository": "k8s.gcr.io/pause", "Tags": [ "0.8.0", "1.0", "2.0", "3.0", "3.1", "3.2", "3.3", "3.4.1", "3.5", "3.6", "3.7", "3.8", "3.9", "go", "latest", "sha256-7031c1b283388d2c2e09b57badb803c05ebed362dc88d84b480cc47f72a21097.sig", "sha256-9001185023633d17a2f98ff69b6ff2615b8ea02a825adffa40422f51dfdcde9d.sig", "test", "test2" ]}root@cby:~# 理论利用# 理论利用root@cby:~# vim config.sh root@cby:~# cat config.sh echo "gcr.io:" >> images.yamlecho " images:" >> images.yamlecho " kaniko-project/executor:" >> images.yamlskopeo list-tags --tls-verify=false docker://gcr.io/kaniko-project/executor | grep \"v | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | awk -F '"' '{print " - "$2}' >> images.yamlecho " google-samples/xtrabackup:" >> images.yamlskopeo list-tags --tls-verify=false docker://gcr.io/google-samples/xtrabackup | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | awk -F '"' '{print " - "$2}' >> images.yamlecho "docker.io:" >> images.yamlecho " images:" >> images.yamlecho " calico/typha:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.io/calico/typha | grep \"v | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | awk -F '"' '{print " - "$2}' >> images.yamlecho " calico/cni:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.io/calico/cni | grep \"v | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | awk -F '"' '{print " - "$2}' >> images.yamlecho " calico/node:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.io/calico/node | grep \"v | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | awk -F '"' '{print " - "$2}' >> images.yamlecho " calico/kube-controllers:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.io/calico/kube-controllers | grep \"v | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | awk -F '"' '{print " - "$2}' >> images.yamlecho "docker.elastic.co:" >> images.yamlecho " images:" >> images.yamlecho " elasticsearch/elasticsearch:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.elastic.co/elasticsearch/elasticsearch | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " kibana/kibana:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.elastic.co/kibana/kibana | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " logstash/logstash:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.elastic.co/logstash/logstash | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " beats/filebeat:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.elastic.co/beats/filebeat | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " beats/heartbeat:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.elastic.co/beats/heartbeat | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " beats/packetbeat:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.elastic.co/beats/packetbeat | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " beats/auditbeat:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.elastic.co/beats/auditbeat | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " beats/journalbeat:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.elastic.co/beats/journalbeat | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " beats/metricbeat:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.elastic.co/beats/metricbeat | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " apm/apm-server:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.elastic.co/apm/apm-server | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " app-search/app-search:" >> images.yamlskopeo list-tags --tls-verify=false docker://docker.elastic.co/app-search/app-search | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho "quay.io:" >> images.yamlecho " images:" >> images.yamlecho " coreos/flannel:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/coreos/flannel | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " ceph/ceph:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/ceph/ceph | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " cephcsi/cephcsi:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/cephcsi/cephcsi | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " csiaddons/k8s-sidecar:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/csiaddons/k8s-sidecar | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " csiaddons/volumereplication-operator:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/csiaddons/volumereplication-operator | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " prometheus/prometheus:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/prometheus/prometheus | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " prometheus/alertmanager:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/prometheus/alertmanager | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " prometheus/pushgateway:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/prometheus/pushgateway | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " prometheus/blackbox-exporter:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/prometheus/blackbox-exporter | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " prometheus/node-exporter:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/prometheus/node-exporter | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " prometheus-operator/prometheus-config-reloader:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/prometheus-operator/prometheus-config-reloader | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " prometheus-operator/prometheus-operator:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/prometheus-operator/prometheus-operator | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " brancz/kube-rbac-proxy:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/brancz/kube-rbac-proxy | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " cilium/cilium:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/cilium/cilium | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " cilium/operator-generic:" >> images.yamlskopeo list-tags --tls-verify=false docker://quay.io/cilium/operator-generic | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho "k8s.gcr.io:" >> images.yamlecho " images:" >> images.yamlecho " etcd:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/etcd | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " pause:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/pause | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " kube-proxy:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/kube-proxy | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " kube-apiserver:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/kube-apiserver | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " kube-scheduler:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/kube-scheduler | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " kube-controller-manager:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/kube-controller-manager | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " coredns/coredns:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/coredns/coredns | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " dns/k8s-dns-node-cache:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/dns/k8s-dns-node-cache | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " metrics-server/metrics-server:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/metrics-server/metrics-server | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " ingress-nginx/controller:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/ingress-nginx/controller | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " ingress-nginx/kube-webhook-certgen:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/ingress-nginx/kube-webhook-certgen | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " kube-state-metrics/kube-state-metrics:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/kube-state-metrics/kube-state-metrics | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " prometheus-adapter/prometheus-adapter:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/prometheus-adapter/prometheus-adapter | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " isig-storage/nfs-subdir-external-provisioner:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " sig-storage/csi-node-driver-registrar:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/sig-storage/csi-node-driver-registrar | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " sig-storage/csi-provisioner:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/sig-storage/csi-provisioner | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " sig-storage/csi-resizer:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/sig-storage/csi-resizer | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " sig-storage/csi-snapshotter:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/sig-storage/csi-snapshotter | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " sig-storage/csi-attacher:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/sig-storage/csi-attacher | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " sig-storage/nfsplugin:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/sig-storage/nfsplugin | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlecho " defaultbackend-amd64:" >> images.yamlskopeo list-tags --tls-verify=false docker://k8s.gcr.io/defaultbackend-amd64 | grep -v alpha | grep -v beta | grep -v rc | grep -v amd64 | grep -v ppc64le | grep -v arm64 | grep -v arm | grep -v s390x | grep -v SNAPSHOT | grep -v debug | grep -v master | grep -v main | grep -v \} | grep -v \] | grep -v \{ | grep -v Repository | grep -v Tags | grep -v dev | grep -v g | grep -v '-'| awk -F '"' '{print " - "$2}' >> images.yamlroot@cby:~# root@cby:~# root@cby:~# vim skopeo.shroot@cby:~# cat skopeo.sh #!/bin/bashHUB_USERNAME="xxxx"HUB_PASSWORD="xxxx"hub="swr.cn-north-1.myhuaweicloud.com"repo="$hub/chenby"rm -rf images.yamlbash config.shif [ -f images.yaml ]; then echo "[Start] sync......." sudo skopeo login --tls-verify=false -u ${HUB_USERNAME} -p ${HUB_PASSWORD} ${hub} \ && sudo skopeo --tls-verify=false --insecure-policy sync --src yaml --dest docker images.yaml $repo echo "[End] done." else echo "[Error]not found images.yaml!"firoot@cby:~# 对于 ...

November 27, 2022 · 27 min · jiezi

关于镜像:解读投屏行业乐播投屏有何技术优势

大家都晓得在投屏行业目前国内做行业TOP1,以及用户笼罩量达2.8亿,10000+视频APP接入SDK的乐播投屏,在产品和技术上有什么劣势呢?乐播投屏是一款安卓用户应用的多屏互动利用,软件功能强大,可能反对挪动设施(手机/平板等)连贯大屏终端(电视、盒子、投影、VR等智能设施),高清、实时地将手游投到电视上,体验大屏手游的快感和刺激感。轻松解决大家投屏的需要,应用电脑、电视投屏畅享大屏观影体验,让你享受大屏幕带来的更多乐趣!乐播投屏乐播投屏特色:1、反对扫描连贯投屏,手机扫描电视里的乐播投屏二维码,疾速建设连贯,让你快点投屏。2、反对云投屏、云镜像,手机与电视电脑无需同一wifi,可实现近程投屏,异地投屏视频和异地视频散会。3、反对投屏码连贯,关上各端的乐播投屏,可发现乐播投屏投屏码,输出投屏码,即可让两个设施相互投屏。乐播投屏亮点:—视频通话投屏:视频聊天图像太小,反对视频聊天屏幕投屏到电视;—办公散会投屏:将手机PPT/文档、电脑PPT/文档一键镜像到会议大屏,让会议更高效、便捷;—本地相册投屏:手机本地照片、视频、文件投射投屏到电视或电脑幕享大屏,看大的让你更爱投屏;—还反对云投屏、云镜像、一投多、手机投电脑、电脑投屏电视等诸多玩法,快点投屏,投影不必等,乐播投屏特点:—全网的投屏利用,笼罩亿用户;无线投屏器“乐播乐投”解决安卓手机镜像无声音问题,无网络可投屏—简略好用的多屏互动投屏神器,反对屏幕镜像与视频投屏;—9年工夫适配所有机型,95%的智能电视/投影仪已内嵌乐播投屏软件,电视不必下载投屏利用,手机视频APP点击“TV按钮”间接发动投屏;—反对手机投屏电视/电脑,电脑投屏电视的投屏神器。反对Airplay、DLNA、乐联协定,乐播投屏劣势:1、跨屏游戏-高清、实时地将手游投到电视上,体验大屏手游的快感和刺激感。2、会议演示-一部手机随时招集会议,让会议操作流程简化,效率更高。3、视频点播-将手机上的任意影像投在电视屏上,与家人一起互动。4、音乐共享-乐播投屏手机版app不须要富丽音响,就能够把无线音乐响彻整个house。5、图片分享-敌人团聚聊天,将手机中的照片投到大屏,和敌人们分享照片故事。6、车载导航-将手机中海量的信息传达到导航屏上,不便操控,平安驾驶。乐播投屏性能:1、手机游戏投屏:应用乐播的屏幕镜像和多屏互动,可将手机游戏同屏电视,用电视玩战争精英等手游。2、在线视频投屏:反对10000+个音视频APP无线投屏。如:抖音、西瓜视频、网盘与浏览器投屏、B站、斗鱼、虎牙等直播投屏。3、视频通话投屏:视频聊天,都可投屏到电视。4、办公散会投屏:无线投屏软件,把手机PPT,电脑PPT一键投影到会议大屏。5、本地相册投屏:利用屏幕镜像或手机乐播的多屏互动连贯电视,可将手机本地照片,本地自拍视频、、图片、文件投屏到电视或投影仪大屏。6、反对云投屏、近程投屏、云镜像、手机投电脑、电脑投屏电视等诸多玩法,让你的大屏变为牢靠的投屏助手和投屏播放器。乐播投屏2.8亿用户在应用的投屏软件,反对音视频推送,镜像同屏投屏模式。手机投电视/投影仪,手机投电脑,手机投手机,电脑投电视/投影仪,电脑投电脑多种投屏办法满足不同用户的需要。

October 19, 2022 · 1 min · jiezi

关于镜像:手机投屏和镜像有什么区别

智能电视里这是两个离开的性能,镜像须要手机设施与电视处于同一网络,然而不须要连贯网络就能够实现;投屏个别是须要借助软件,然而这两个又有什么区别?投屏的含意个别大家罕用的场景是通过手机投屏到大屏端,也叫做无线投屏,大家能够很简略地了解成把画面「投射」到屏幕上,手机中的视频画面能够放到电视机、显示器、投影仪等显像设施。同时你手机能够熄屏、聊天、浏览其它APP等等,总之电视机画面和手机画面能够离开。这种投屏性能是通过DLNA推送投屏的;一般来说,在各大在线视频APP中,右上角所显示的一个小电视的图标,只有你的手机和投屏器是处于同一个Wi-Fi中,即可间接应用这个性能。镜像的含意手机画面和电视画面是实时同步的,此时手机做什么,电视就显示什么,像镜子的影像一样,所以有时候也叫镜像。个别会议、游戏,或是抖音短视频这类本人不反对推送投屏APP中会用到这性能。因为是同步的,所以手机不能熄屏,也不能独自做其它事。这种同屏性能是通过苹果设施的「AirPlay屏幕镜像」来实现,而安卓和Windows电脑是用「Miracast无线显示」的性能实现。手机镜像时须要留神的是,安卓因为自身零碎外部的平安规定,所以不容许镜像同屏的时候获取声音,所以会呈现一些用户常常反映的“手机投屏没声音”的问题,这个跟安卓零碎和手机品牌商无关,如果遇到此类问题倡议先寻找手机品牌的客服征询帮忙。投屏与镜像的区别一、用处不同1、投屏:投屏的内容是流媒体模式的音、视频资源,所以更多的是用来娱乐。2、屏幕镜像:屏幕镜像在内容上是不受限制的,所以玩游戏、直播、办公等。二、内容不同1、投屏:手机无线投屏的时候能够流媒体模式的音视频资源进行推送到大屏。2、屏幕镜像:镜像就没有了资源的限度,只有手机屏幕可能出现的进去即可。三、办法不同1、投屏:当下的手机投屏大多数都是用的视频软件自带的推送投屏,也就是APP平台的电视资源推送给电视,而后电视播放节目,而咱们的手机又能进行聊微信、刷朋友圈等其余操作。2、屏幕镜像:也就是苹果手机、电脑自带的多屏互动功能模块,它是将手机整个屏幕都镜像显示在大屏幕上,比方手机的主界面。目前投屏和镜像做的比拟好的产品除了各大品牌产品主动的投屏性能外,能同时兼容 iOS、Android 和 Windows,并反对局域网、跨网络,跨终端手机投屏到电视,投屏到电脑,电脑投屏电视等操作,目前只有乐播投屏实现了多屏互动,一键投屏,而且目前大部分电视都反对乐播投屏,利用宽泛,最次要的是页面简洁,操作简略能疾速上手,再也不必端着手机追剧了,间接投屏到电视上,解放双手又能够享受大屏。

October 13, 2022 · 1 min · jiezi

关于镜像:手机投屏时常见的黑屏卡顿无画面等问题及解决方法

当初用手机、电脑投屏的场景越来越常见,像近程会议、上网课、散会、追剧、健身等等。不过在投屏的过程中,咱们也常常会遇到一些问题,例如投屏失败,呈现黑屏、无画面或无声音等状况。上面汇总了一些投屏常见问题及解决办法:1、配对找不到设施首先检查一下手机和电视是否在同一个局域网(WiFi)下,网络是否稳固。确认结束后,重启路由器刷新网络,稍等片刻后将手机端和电视端的投屏性能关上,从新进行配对。如果网络并无问题,则能够将电视重启后再次配对。如果还是不行,很有可能是因为路由器的搭建问题。此时,两个设施需在同一路由器网络下,将路由器后盾中的AP隔离开关敞开即可。2、黑屏提早投屏时呈现黑屏的状况,个别是因为内容版本受限,视频只反对客户端观看,不反对投屏。当然,不排除是设施在运行过程中呈现问题,这时能够尝试将手机或电视关机重启后再尝试。也有可能是因为网络不稳固,从而影响投屏的稳定性,使得视频信号在传输的过程中产生了失落的状况,这时就须要检查一下网络,等网络稳固后再进行投屏。3、有声音无画面如果投屏时,电视只有声音而没有显示画面,则有可能是设施投屏时呈现缓存有余导致的。这时须要敞开投屏,拿出电视遥控器,长按电源键5秒左右后松开。这样就能给电视开释内存,从新投屏就能显示画面了。还有一种状况,如果是手机自带的播放器兼容性比拟差,那么电视和视频信号就可能不兼容,这时用这个播放器去投屏,画面很有可能是不会显示的。这时候只须要更换手机上的播放器,从新播放投屏,就能够了。4、有画面无声音首先检查一下设施,看看是否是因为设施的声音敞开或者声音太小的起因,如果是,则关上声音调试音量大小即可。如果你是有线投屏,则须要查看电视接口的类型。个别状况下,如果电视是HDMI接口,则反对传输声音和视频信号;但若是VGA接口或DVI接口就要留神了,因为这两种接口仅反对视频信号传输。例如,用电脑投屏电视,电脑是HDMI接口,而电视是VGA接口。这时能够用HDMI转VGA线连贯电脑和电视,再用一条音频线将电脑和音响等扩声设施连贯,这样就能在投屏的同时,利用音响发出声音。5、没有显示全屏大家用手机投屏时,是否呈现过下图这种状况。电视两头只显示手机竖屏画面,而两边却是黑屏。其实这种状况的解决办法很简略,只须要将手机里的视频横屏播放就能够了。以上就是咱们常见的几种投屏中呈现解决办法了,如果还是不能解决你的问题,倡议大家在手机上和电视上同步下载投屏软件进行投屏,比方乐播投屏是目前支流的投屏软件;不过须要留神的是投屏跟镜像是有区别的,镜像是把手机屏幕镜像到电视上,画面是手机屏幕的尺寸,不能横屏的或全屏的。

October 10, 2022 · 1 min · jiezi

关于镜像:技术解读Dragonfly-基于-P2P-的智能镜像加速系统-龙蜥技术

编者按:上世纪末期,基于 C/S 模式的思维,人们倒退了 HTTP 、 FTP 等应用层协定。然而 C/S 模式的弊病很显著:服务器的负载过大,下载速率过慢。基于上述背景,有人联合 P2P 网络与负载平衡的思维,提出 P2P 下载模式。本文整顿自龙蜥大讲堂第 40 期,精彩分享视频回放已上传至龙蜥官网(首页-动静-视频),欢送查看! 背景网络下载提起网络下载畛域,你应该首先会想到基于 TCP/IP 协定簇的 C/S 模式。这种模式心愿每一个客户机都与服务器建设 TCP 连贯,服务器轮询监听 TCP 连贯并顺次响应,如下图: 上世纪末期,基于 C/S 模式的思维,人们倒退了 HTTP 、 FTP 等应用层协定。然而 C/S 模式的弊病很显著:服务器的负载过大,下载速率过慢。随着互联网规模的增大以及客户对于下载数据大小,下载速率等需要的回升,这些弊病被一直放大。 P2P 下载原理基于上述背景,有人联合 P2P 网络与负载平衡的思维,提出 P2P 下载模式。这种模式不再把所有的下载压力丢给服务器,服务器只负责传递文件元数据,真正的文件下载连贯建设在客户机与客户机之间。同时一个文件能够被分片为多个块,同一个文件中不同的块能够在不同的客户机之上下载,使得下载文件在 P2P 网络中动静流通,大幅晋升了下载效率,如下图: 去中心化的 P2P 下载基于 DHT 技术,它采纳分布式全网形式来进行信息的存储和检索。所有信息均以哈希表条目模式加以存储,这些条目被扩散地存储在各个节点上,从而以全网形式形成一张微小的分布式哈希表。在此基础上做到对单服务器的去中心化,哈希表负责对负载的摊派,将全网负载均摊到多个机器之上。 Dragonfly 简介及架构概述Dragonfly 是一款基于 P2P 的智能镜像和文件散发工具。它旨在进步大规模文件传输的效率和速率,最大限度地利用网络带宽。在利用散发、缓存散发、日志散发和镜像散发等畛域被大规模应用。 原理Dragonfly 联合 C/S 架构与 P2P 架构的长处。它提供面向客户的 C/S 架构下载模式。同时它也提供面向服务器集群的 P2P 回源模式,与传统 P2P 不同的是,对等网络建设在 Scheduler 外部,指标是最大化 P2P 外部下载效率,如下图: ...

September 7, 2022 · 2 min · jiezi

关于镜像:恒源云Gpushare没有你想要的镜像技巧大放送5

文章起源 | 恒源云社区 原文地址 | 【小技巧-镜像篇】 1、如果你须要的镜像,恒源云官网没有,该怎么办?一些罕用的库和软件都能够通过命令装置,在 常用命令 中提供了装置软件的形式。 也能够应用 conda 命令创立虚拟环境,而后在虚拟环境中装置。在 conda 中提供了 conda 的应用,如装置 PyTorch 1.7 conda install pytorch==1.7.0 torchvision==0.8.0 torchaudio==0.7.0 -c pytorch。 2、自定义镜像误删除 / 空间或者文件怎么办?如果为自定义镜像,在操作实例过程中误删除了 / 空间或者某个数据文件,可通过复原镜像性能来进行复原。

April 1, 2022 · 1 min · jiezi

关于镜像:vmware虚拟机下的Ubuntu20切换国内阿里镜像源

参考阿里巴巴开源镜像站 图形界面操作 - 实用于桌面版Ubuntu20 首选进入桌面版的设置界面 如图 下拉 点击 对于 左边 点击 软件更新  抉择服务器 ,点其余站点 应用阿里源https://mirrors.aliyun.com/ub... 设置后抉择敞开,而后从新载入即可

December 24, 2021 · 1 min · jiezi

关于镜像:centos7安装Pouch

一、参考链接阿里巴巴开源镜像站-OPSX镜像站 简介 PouchContainer是阿里巴巴开源的高度牢靠的集装箱引擎。它是一个优良的软件层,能够填补业务应用程序和底层基础设施之间的空白。隔离能力强、容器丰盛是其代表特色。centos7装置Pouch 镜像 首先增加文件/etc/yum.repos.d/pouch-centos7.repo 内容如下 [pouch-stable]name=Pouch Stable - $basearchbaseurl=http://mirrors.aliyun.com/ops...$basearch/stableenabled=1gpgcheck=1gpgkey=http://mirrors.aliyun.com/ops... [pouch-test]name=Pouch Test - $basearchbaseurl=http://mirrors.aliyun.com/ops...$basearch/testenabled=0gpgcheck=1gpgkey=http://mirrors.aliyun.com/ops... 如图 而后执行 yum makecacheyum install pouch 如图 实现  

December 23, 2021 · 1 min · jiezi

关于镜像:实现阿里云容器镜像服务反向访问代理

简介: 本文会先介绍镜像推送/拉取过程的交互逻辑来梳理须要代理的所有服务,再通过搭建一个公网 HTTPS 反向代理来拜访容器镜像服务来向您展现多场景代理拜访模式原理。 实在业务场景可能很简单,因平安、合规、拜访限度等起因可能须要: 在线下 IDC 通过代理来拜访云上资源。在地区 A 通过云企业网来拜访地区 B 的云资源。金融云环境下,因金融云网络架构限度,金融云内网类型的只能在金融云外部拜访,不反对在互联网上间接拜访,须要通过代理来拜访。针对阿里云容器镜像服务(默认实例/企业版实例),本文会先介绍镜像推送/拉取过程的交互逻辑来梳理须要代理的所有服务,再通过搭建一个公网 HTTP 反向代理来拜访容器镜像服务来向您展现多场景代理拜访模式原理。 镜像推拉过程 上图展示了阿里云容器镜像服务推送/拉取的整个交互过程: 向 registry 发动镜像推拉申请。registry 返回 401 Unauthorized 的 HTTP 返回值,并且携带鉴权服务(authorization service)的地址,须要客户端去做鉴权。客户端向鉴权服务发动申请以获取一个受权 token。鉴权服务返回一个携带权限的 token 给客户端。客户端将 token 嵌入 HTTP Authorization header 头中,再次向 registry 发动申请。registry 验证 token 权限无问题后,在镜像推送过程中,客户端能够向 registry 推送镜像数据;在镜像拉取过程中,registry 会向客户端颁发有时效的 OSS url 地址。客户端通过 OSS url 地址拉取保存在 OSS 中的镜像数据。整个拜访阿里云容器镜像服务实例的过程波及 Registry、Authorization Service 和 OSS 三局部。 容器镜像相干服务地址客户端拜访容器镜像服务,须要与 registry、authorization service 和 oss 三种服务通信。 域名通过代理形式拜访容器镜像服务,个别须要晓得所有相干域名。 registry 地址公网默认实例地址格局:registry.${RegionId}.aliyuncs.com内网默认实例地址格局:registry-vpc.${RegionId}.aliyuncs.com企业版实例公网/内网地址:实例内可见。authorization service 地址公网默认鉴权服务地址格局:dockerauth.${RegionId}.aliyuncs.com内网默认鉴权服务格局:dockerauth-vpc.${RegionId}.aliyuncs.com公网企业版实例服务地址格局:dockerauth-ee.${RegionId}.aliyuncs.com内网企业版实例服务地址格局:dockerauth-ee-vpc.${RegionId}.aliyuncs.comOSS Bucket 地址公网 OSS Bucket 地址:oss-${RegionId}.aliyuncs.com内网 OSS Bucket 地址:oss-${RegionId}-internal.aliyuncs.com企业版实例公网/内网 OSS Bucket 地址格局:OSS 控制台可见。内网解析像通过 CEN 来实现跨地区拜访镜像服务实例;线下 IDC 通过 VPN 拜访云上镜像服务实例个别须要晓得内网域名解析 IP 网段。 ...

March 26, 2021 · 3 min · jiezi

关于镜像:docker-删除镜像及释放磁盘空间

列出镜像列表 docker ps -a进行镜像 docker stop CONTAINER ID革除镜像 docker rmi CONTAINER ID清理镜像文件 docker image prune -f清理镜像虚拟机空间 docker volume ls -f dangling=true | awk '{ print $2 }' | xargs docker volume rm

February 3, 2021 · 1 min · jiezi

关于镜像:配置-containerd-镜像仓库完全攻略

作者简介王海龙,Rancher中国社区技术经理,负责Rancher中国技术社区的保护和经营。领有6年的云计算畛域教训,经验了OpenStack到Kubernetes的技术改革,无论底层操作系统Linux,还是虚拟化KVM或是Docker容器技术都有丰盛的运维和实践经验。 前 言Kubernetes 在 Changelog 中发表自 Kubernetes 1.20 之后将弃用 Docker 作为容器运行时之后,containerd成为下一个容器运行时的热门选项。尽管 containerd 很早就曾经是 Docker 的一部分,然而纯正应用 containerd 还是给大家带来了诸多困扰,本文将介绍如何应用 containerd 配置镜像仓库和加速器。 本文将以K3s为例对containerd进行配置,如果您的环境未应用 K3s 而是应用的 Kubernetes,你也能够参考本文来配置 containerd 的镜像仓库,因为 containerd 的配置是通用的。 对于 K3s 和 containerdK3s 是一个轻量级 Kubernetes 发行版,二进制大小小于100MB,所需内存不到Kubernetes的一半。K3s 为了升高资源耗费,将默认的 runtime 批改为 containerd,同时也内置了 Kubernetes CLI 工具 crictl和ctr。 K3s 默认的 containerd 配置文件目录为/var/lib/rancher/k3s/agent/etc/containerd/config.toml,但间接操作 containerd 的配置文件去设置镜像仓库或加速器相比于操作 docker 要简单许多。K3s 为了简化配置 containerd 镜像仓库的复杂度,K3s 会在启动时查看/etc/rancher/k3s/中是否存在 registries.yaml 文件,如果存在该文件,就会依据 registries.yaml 的内容转换为 containerd 的配置并存储到/var/lib/rancher/k3s/agent/etc/containerd/config.toml,从而升高了配置 containerd 镜像仓库的复杂度。 应用 K3s 配置公有镜像仓库K3s 镜像仓库配置文件由两大部分组成:mirrors和configs: Mirrors 是一个用于定义专用镜像仓库的名称和 endpoint 的指令Configs 局部定义了每个 mirror 的 TLS 和证书配置。对于每个 mirror,你能够定义auth和/或tlscontainerd 应用了相似 K8S 中 svc 与 endpoint 的概念,svc 能够了解为拜访名称,这个名称会解析到对应的 endpoint 上。也能够了解 mirror 配置就是一个反向代理,它把客户端的申请代理到 endpoint 配置的后端镜像仓库。mirror 名称能够随便填写,然而必须合乎IP或域名的定义规定。并且能够配置多个 endpoint,默认解析到第一个 endpoint,如果第一个 endpoint 没有返回数据,则主动切换到第二个 endpoint,以此类推。 ...

January 25, 2021 · 4 min · jiezi

关于镜像:镜像批量迁移利器imagetransfer

概述用户业务在上云或者云迁徙过程中,须要对镜像进行批量迁徙。基于此背景,腾讯云容器专家团队开发了镜像批量迁徙工具:image-transfer。该工具反对多种云厂商镜像仓库之间的批量迁徙,同时反对腾讯云镜像仓库 TCR 个人版 CCR 一键全量迁徙至腾讯云镜像仓库企业版 TCR。本文首先介绍业务上云/迁徙过程中镜像迁徙的痛点。随后具体介绍镜像批量迁徙工具 image-transfer 的设计思维,功能模块以及最佳实际。工具已正式开源,我的项目地址:https://github.com/tkestack/i... 二进制包下载地址:https://github.com/tkestack/i... 业务上云,镜像怎么迁徙?业务上云次要有几种场景,一是自建 idc 上云,二是第三方云迁徙,三是异地灾备,即混合云。这些场景中,无论是上云还是云迁徙,迁徙流程次要有如下几步。 网络布局。vpc 配置,子网划分等。数据迁徙。对象存储,文件存储等。利用迁徙。业务,配置等。在数据迁徙过程中,如果业务大量应用容器化部署,则须要批量镜像迁徙。而目前大部分云厂商的镜像仓库服务没有提供镜像仓库批量迁徙的能力。业务想要迁徙,只能先在本地下载原镜像,批改 tag 后,再上传至目标镜像仓库。这个过程存在以下几个毛病: 耗时耗力。仅仅对于单个镜像迁徙,就须要三步操作,并且须要时刻盯着,若呈现失败状况,需进一步解决。齐全人肉操作,易呈现过错。在对原镜像批改 tag 时,因为是人为批改,极易操作失误,tag 批改错了等。镜像量大时,成本增加,上云进度缓慢。如果有几百上千个镜像,这样人肉操作,迁徙进度会非常迟缓,且迁徙老本会大大增加。image-transfer 的原理设计指标针对镜像迁徙的痛点。咱们心愿开发一种镜像批量迁徙工具。它对使用者而言,只须要简略的配置,就能够实现镜像批量迁徙,无需人工干预,进步业务上云/迁徙的进度,降低成本。具体而言,该工具有以下设计指标。 配置简略,无需简单输出。咱们心愿对使用者而言这个工具是简略易用的,仅需配置源、目标镜像地址和鉴权,即可实现批量迁徙。疾速高效迁徙海量镜像,升高迁徙老本。针对大量的镜像迁徙需要,咱们心愿工具能够高效实现,借助高并发的一些技术,实现疾速迁徙。肯定的容错能力,缩小人工干预保护。在迁徙过程中,咱们心愿工具能够进行一些谬误的辨认和主动修复,尽量减少人工保护,进步运维效率。对运行环境没有依赖,进步工具普适性。咱们心愿工具是能够在任何 linux,mac os,windows 操作系统中运行,而不必依赖 docker 及其他程序。反对腾讯云 CCR 一键全量迁徙模式。目前,腾讯云容器镜像服务 TCR 企业版正式上线,腾讯云 TCR 个人版(CCR)将在将来逐渐缩小保护,直到下线。因而工具须要反对 CCR 仓库一键全量迁徙至 TCR 企业版。反对自定义 qps 限速。批量迁徙镜像,频繁的调用镜像仓库接口有可能导致镜像仓库解体,因而须要对 qps 进行限度。架构image-transfer 由多个模块形成,下图给出了 image-transfer 架构图。 通用模式输出(默认):用于承受用户下发的镜像迁徙工作。包含镜像迁徙配置文件和鉴权配置文件。该模式用于实现云厂商之间的镜像迁徙。CCR 一键迁徙模式输出:须要在工具输出参数增加 --ccrToTcr=true,该模式用于 CCR 仓库一键全量迁徙至 TCR 企业版。除了增加 --ccrToTcr=true 参数,还需鉴权配置文件和腾讯云 secret 配置文件。pipeline:该模块是工具解决镜像迁徙的外围。负责解决用户下发的镜像迁徙工作,包含依据迁徙配置文件解决镜像仓库的同步规定,以及进行镜像的分层拉取和传输工作。模块采纳了高并发的 pipeline 模型,进步迁徙速度。重试 task:这个阶段会重试 pipeline 中传输失败的工作。重试次数可依据用户输出参数而定,默认为 2 次。Pipeline因为工具采纳 golang 语言编写,因而外围解决模块采纳了 go 的 pipeline 高并发模型。整个 pipeline 模块分为三个小模块。 ...

January 13, 2021 · 3 min · jiezi

关于镜像:Harbor镜像仓库的安装与配置

一、装置并启动docker 1. 装置docker-ce,略... 2. 装置docker-compose curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-Linux-x86_64" -o /usr/local/bin/docker-composechmod +x /usr/local/bin/docker-composedocker-compose --version二、配置装置harbor 1. Harbor软件包下载地址:https://github.com/goharbor/h... mkdir /data1/srv/ -pcd /data1/srvwget https://github.com/goharbor/harbor/releases/download/v1.10.4/harbor-offline-installer-v1.10.4.tgztar -zxvf harbor-offline-installer-v1.10.4.tgz 2. 编辑harbor.yml配置 vim harbor.yml #编辑harbor的配置文件,按需批改以下内容 hostname = 192.168.1.242 port: 80 harbor_admin_password = admin #harbor的admin用户的明码 data_volume: /harbor/data #harbor存储地位 3. 执行装置脚本进行装置 ./prepare #配置Harbor./install.sh #装置Harbor 装置启动实现后可在浏览器进行拜访登录测试 4. 批改docker配置文件,使其反对harbor vim /etc/docker/daemon.json{"insecure-registries": [ "192.168.1.242" ]} 5. 保留配置后重启docker systemctl restart docker三、配置Harbor的开机自启 1. 在 /lib/systemd/system/harbor.service 中写入以下内容 [Unit]Description=HarborAfter=docker.service systemd-networkd.service systemd-resolved.serviceRequires=docker.serviceDocumentation=http://github.com/vmware/harbor[Service]Type=simpleRestart=on-failureRestartSec=5#须要留神harbor的装置地位ExecStart=/usr/local/bin/docker-compose -f /data1/srv/harbor/docker-compose.yml upExecStop=/usr/local/bin/docker-compose -f /data1/srv/harbor/docker-compose.yml down [Install]WantedBy=multi-user.target systemctl enable harbor #设置harbor开机自启 systemctl start harbor #启动harbor 留神:如果更改了harbor.yml文件,必须要从新执行install脚本,或者执行./prepare脚本,生成新的配置文件 ...

December 29, 2020 · 1 min · jiezi

关于镜像:镜像处理

镜像转换例如:qecow2-->raw查看镜像详情: qemu-img info /path转换镜像: qemu-img convert -p raw e:\99cloud-img\CentOS7.6.qcow2 e:\99cloud-img\CentOS7.6.raw 解压zip压缩包: unzip 上传镜像openstack image create --file CentOS7.7.raw --container-format bare --disk-format raw --public CentOS7.7 --property hw_qemu_guest_agent=yes --property os_admin_user=root openstack image create --file win2k12-1203-v1-64.bit --container-format bare --disk-format raw --public Win2012 --property hw_qemu_guest_agent=yes --property os_type=windows

September 14, 2020 · 1 min · jiezi

Docker-Registry搭建私有镜像仓库

微服务的镜像会上传到Docker仓库保存,常用的公网Docker仓库有阿里云,网易云等,在企业局域网也可以搭建自己的Docker私有仓库,本教程使用Docker提供的私有仓库registry。 1.拉取私有仓库镜像 docker pull registry 2.创建启动私有仓库容器 docker run -dit -v /data/registry:/var/lib/registry -p 5000:5000 --restart=always --name docker-registry registry参数说明 -dit:在容器中打开一个伪终端进行交互操作,并在后台运行-v:把宿主机的/data/registry目录挂载到容器/var/lib/registry目录(这个目录是registry容器中存放镜像文件的目录),来实现数据的持久化-p:映射端口,访问宿主机的5000端口就访问到registry容器的服务了--restart=always:这是重启的策略,假如这个容器异常退出会自动重启容器--name docker-registry:创建容器命名为docker-registry,你可以随便命名registry:pull下来的镜像上边显示 registry镜像已经创建,并且docker-registry容器已经启动成功。访问:http://139.9.40.41:5000/v2/_catalog,响应结果如下: {"repositories":[]}上边的响应结果说明在docker私有仓库中还没有镜像。 默认docker-registry只允许https提交镜像,如下配置使docker-registry支持http,在/etc/docker下,创建daemon.json文件,写入: { "insecure-registries": [ "139.9.40.41:5000"]}3.重启docker systemctl restart docker4.镜像上传至私有仓库标记此镜像为私有仓库的镜像 docker tag docker.io/hello-world 139.9.40.41:5000/hello-world:v1上传标记的镜像 docker push 139.9.40.41:5000/hello-world:v1 列出所有镜像[root@2 docker]# curl http://139.9.40.41:5000/v2/_catalog{"repositories":["hello-world"]}

October 16, 2019 · 1 min · jiezi

Knative-初体验CICD-极速入门

Knative 社区很早就在讨论用 Tekton 替换 Build 模块的事宜。Knative Build 官方已经正式说明不再建议使用 Knative Build 了。 如果你知道 Knative Build 是什么相信你理解起 Tekton 就是很容易的一件事了。 Knative Build 对自己的一句话概述是:A Kubernetes-native Build resource.Tekton 对自己的一句话概述是: A K8s-native Pipeline resource. https://tekton.dev可以看到两者的定位非常相近,而且在功能上 Tekton 的设计更加的丰富、完整,这也是社区最终采用 Tekton 的原因。接下来我们就看一下 Tekton 的核心概念。Tekton 极速入门Tekton 主要由如下五个核心概念组成: TaskTaskRunPipelinePipelineRunPipelineResource这五个概念每一个都是以 CRD 的形式提供服务的,下面分别简述一下这五个概念的含义。Task Task 就是一个任务执行模板,之所以说 Task 是一个模板是因为 Task 定义中可以包含变量,Task 在真正执行的时候需要给定变量的具体值。Tekton 的 Task 很类似于一个函数的定义,Task 通过 inputs.params 定义需要哪些入参,并且每一个入参还可以指定默认值。Task 的 steps 字段表示当前 Task 是有哪些子步骤组成的。每一个步骤具体就是一个镜像的执行,镜像的启动参数可以通过 Task 的入参使用模板语法进行配置。 apiVersion: tekton.dev/v1alpha1kind: Taskmetadata: name: task-with-parametersspec: inputs: params: - name: flags type: array - name: someURL type: string steps: - name: build image: registry.cn-hangzhou.aliyuncs.com/knative-sample/alpine:3.9 command: ["sh", "-c"] args: [ "echo ${inputs.params.flags} ; echo ${someURL}"]TaskRun ...

August 7, 2019 · 5 min · jiezi

容器十年-一部软件交付编年史

作者| 张磊,阿里云容器平台高级技术专家,CNCF Ambassador (CNCF 官方大使),Kubernetes 项目资深成员与维护者,曾就职于 Hyper、微软研究院(MSR),现在负责 Kubernetes 技术及上下游相关工作。 2019年,全世界的开发人员都开始习惯用容器测试自己的软件,用容器做线上发布,开始对容器化的软件构建和交付流程习以为常。全世界的架构师们都在对“云原生”侃侃而谈,描绘多云时代的应用治理方式,不经意间就把 “sidecar” 这种容器组织方式当做了默认选项。在“云”已经成为了大众基础设施的今天,我们已经习惯了把“容器“当做现代软件基础设施的基本依赖。这就像我们每天打开 Eclipse 编写 Java 代码一样自然。 但往回倒数两年, 整个容器生态都还在围着 Docker 公司争得不可开交,看起来完全没有定数。当时的国内很多公有云厂商,甚至都没有正式的 Kubernetes 服务。在那个时候,要依托容器技术在云上托管完整的软件生命周期,可以说是相当前沿的探索。谁能想到短短两年之后,容器这个站在巨人肩膀上的设计,就真的成为技术人员日常工作的一部分呢? 伴随着容器技术普及到“千家万户”,我们在这两年期间所经历的,是现代软件交付形式的一次重要变革。 源起:属于 Jails 们的时代虚拟化容器技术(virtualized container)的历史,其实可以一直追溯上世纪 70 年代末。时间回到 1979 年,贝尔实验室( Bell Laboratories 正在为 Unix V7 (Version 7 Unix)操作系统的发布进行最后的开发和测试工作。 Ken Thompson(sitting) and Dennis Ritchie at PDP-11 ©wikipedia 在那个时候,Unix 操作系统还是贝尔实验室的内部项目,而运行 Unix 的机器则是长得像音响一样的、名叫 PDP 系列的巨型盒子。在那个“软件危机(The Software Crisis)”横行的末期,开发和维护 Unix 这样一套操作系统项目,即使对贝尔实验室来说也绝非易事。更何况,那里的程序员们还得一边开发 Unix ,一边开发 C 语言本身呢。 而在 Unix V7 的开发过程中,系统级别软件构建(Build)和测试(Test)的效率其实是其中一个最为棘手的难题。这里的原因也容易理解:当一个系统软件编译和安装完成后,整个测试环境其实就被“污染”了。如果要进行下一次构建、安装和测试,就必须重新搭建和配置整改测试环境。在有云计算能力的今天,我们或许可以通过虚拟机等方法来完整的复现一个集群。但在那个一块 64K 的内存条要卖 419 美元的年代,“快速销毁和重建基础设施”的想法还是有点“科幻”了。 ...

July 3, 2019 · 3 min · jiezi

Linus-本尊来了为什么-KubeCon-越来越火

阿里妹导读: 从200人的小会议到3500 多位云原生和开源领域工程师齐聚一堂的大会,KubeCon 只用了四年,昨天,在KubeCon China 2019 上阿里巴巴宣布开源 OpenKruise,今天,Linus 本尊竟然现身会场!现在,我们继续连线会场,探索阿里云为开发者带来的多份重磅献礼。 2015年11月,第一届 KubeCon 在美国旧金山开始的时候,还只是个200人的小会议,2019年的7月,KubeCon 第二次在中国举办,就有 3500 多位云原生和开源领域工程师齐聚一堂。 连 Linux 及 Git 创始人 Linus Torvalds 本人都来到 KubeCon China 上海现场。Linux 基金会执行董事 Jim Zemlin 说道:“我见证了开源圈子的两大事件:一个是 Linux 的成功,一个就是 Kubernetes 和云原生的大爆发。开源是历史上最成功的全球创新推动者之一,Linux 已经成长为世界上最重要的软件平台,而云原生正以势如破竹之态爆发。” 中国在整个云原生运动中贡献巨大,中国的 K8s contributors 已经在全球所有贡献者中排名第二,超过 10% 的 CNCF 会员来自中国,26%的 Kubernetes 的认证供应商来自中国。 阿里云作为最早成为 CNCF member 的中国公司之一,一直在云原生技术领域不停地实践和探索。在阿里云已经是铂金会员的基础上,蚂蚁金服也最新加入 CNCF 成为黄金会员。 本次 KubeCon China,阿里云又发布了什么黑科技呢?一起来感受下。 拥抱社区,服务最广泛开发者:云原生应用管理与交付体系发布 整个云原生应用管理与交付体系包含五大项目,本次 KubeCon 两大项目率先亮相:国内首个开放云原生应用中心—— Cloud Native App Hub 和云原生应用自动化引擎—— OpenKruise。 ...

June 27, 2019 · 2 min · jiezi

规模化落地云原生阿里云即将重磅亮相-KubeCon-China

2019 年 6 月 24 日至 26 日, 由 Cloud Native Computing Foundation (CNCF) 主办的云原生技术大会 KubeCon + CloudNativeCon + Open Source Summit(上海 )即将在中国上海盛装启幕。 继 2018 年 KubeCon 首次成功登陆中国,本届 KubeCon 将吸引来自全世界数千名技术人员将会参加此次盛会,参与CNCF 全部项目和话题的深度探讨和案例分析,聆听 CNCF 项目的运维者和最终用户的分享。本届 KubeCon + CloudNativeCon + Open Source Summit 大会项目委员会由 75 名专家组成,审阅 KubeCon + CloudNativeCon 的 618 项提案,在本次 KubeCon China 2019 上,阿里巴巴共有 26 个技术演讲入选。 在本次 KubeCon 上,阿里云智能容器平台负责人丁宇(叔同)、 CNCF TOC、etcd 项目作者、阿里云容器平台资深技术专家李响,CNCF 大使、Kubernetes 项目维护者、阿里云高级技术专家张磊等众多云原生技术大咖都会悉数到场并做技术分享,同时会为您带来包括开源 Virtual Cluster 强多租户设计、 OpenKruise 开源项目、开放云原生应用中心(Cloud Native App Hub)等众多云原生先进技术的最新动态与进展。我们非常期待您能够在 KubeCon China 上与阿里容器平台团队见面、进行交流或者开展技术合作。 ...

June 18, 2019 · 2 min · jiezi

规模化落地云原生阿里云即将重磅亮相-KubeCon-China

2019 年 6 月 24 日至 26 日, 由 Cloud Native Computing Foundation (CNCF) 主办的云原生技术大会 KubeCon + CloudNativeCon + Open Source Summit(上海 )即将在中国上海盛装启幕。 继 2018 年 KubeCon 首次成功登陆中国,本届 KubeCon 将吸引来自全世界数千名技术人员将会参加此次盛会,参与CNCF 全部项目和话题的深度探讨和案例分析,聆听 CNCF 项目的运维者和最终用户的分享。本届 KubeCon + CloudNativeCon + Open Source Summit 大会项目委员会由 75 名专家组成,审阅 KubeCon + CloudNativeCon 的 618 项提案,在本次 KubeCon China 2019 上,阿里巴巴共有 26 个技术演讲入选。  在本次 KubeCon 上,阿里云智能容器平台负责人丁宇(叔同)、 CNCF TOC、etcd 项目作者、阿里云容器平台资深技术专家李响,CNCF 大使、Kubernetes 项目维护者、阿里云高级技术专家张磊等众多云原生技术大咖都会悉数到场并做技术分享,同时会为您带来包括开源 Virtual Cluster 强多租户设计、 OpenKruise 开源项目、开放云原生应用中心(Cloud Native App Hub)等众多云原生先进技术的最新动态与进展。我们非常期待您能够在 KubeCon China 上与阿里容器平台团队见面、进行交流或者开展技术合作。 ...

June 12, 2019 · 2 min · jiezi

Knative-初体验Serving-Hello-World

通过前面两章的学习你已经掌握了很多 Knative 的理论知识,基于这些知识你应该对 Knative 是谁、它来自哪里以及它要做什么有了一定的认识。可是即便如此你可能还是会有一种犹抱琵琶半遮面,看不清真容的感觉,这就好比红娘拿姑娘的 100 张生活照给你看也不如你亲自去见一面。按常理出牌,一般到这个阶段就该 Hello World 出场了。本篇文章就通过一个 Hello World 和 Knative 来一个“约会”,让你一睹 Knative 这位白富美的真容。 安装 KnativeKnative 社区提供的安装步骤见这里,整个流程大概包含如下三个部分: 准备 kubernetes 环境(你可以在阿里云容器服务中快速创建一个 kubernetes 集群 )安装istio安装 Knative组件虽然看起来只有三步,但是每一步其实都需要手动做大量的工作,执行一堆命令。另外社区文档提供的 yaml 文件默认使用了大量的 gcr.io 镜像,目前国内无法拉取 gcr.io 镜像。所以这些 yaml 文件在国内不能直接使用,至少需要手动同步 30 多个镜像才行。 不过别着急,阿里云容器服务的应用目录已经有 Knative 的安装包,现在只需要在阿里云容器服务上面点击几下鼠标就能轻轻松松搭建一个 Knative 集群 O ^ ~ ^ O O ^ ~ ^ O O ^ ~ ^ O 创建 Kubernetes 集群阿里云容器服务可以通过管理控制台非常方便地创建 Kubernetes 集群。具体过程可以参考创建Kubernetes集群。容器服务提供了专有集群和托管集群两种类型,如果不知道该怎么选择建议你直接选择托管版的 Kubernetes 集群。托管版无需你自己承担 Kubernetes Master 组件的管理和运维,你只需要提供 Node 节点即可。 ...

June 11, 2019 · 6 min · jiezi

CICD联动阿里云容器服务Kubernetes实践之Bamboo篇

本文档以构建一个 Java 软件项目并部署到 阿里云容器服务的Kubernetes集群 为例说明如何使用 Bamboo在阿里云Kubernetes服务上运行Remote Agents并在agents上运行Build Plans。 1. 源码项目本示例中创建的GitHub源码项目地址为: https://github.com/AliyunContainerService/jenkins-demo.git 分支为: bamboo2. 在Kubernetes中部署Remote Agent2.1 创建kaniko-docker-cfg secret kaniko-docker-cfg secret用于Remote Agent上构建任务使用kaniko推送容器镜像时的权限配置 kubectl -n bamboo create secret generic kaniko-docker-cfg --from-file=/root/.docker/config.json上面命令中的/root/.docker/config.json,是在linux服务器上使用root用户通过以下命令生成的: docker login registry.cn-hangzhou.aliyuncs.com2.2 创建serviceaccount bamboo以及clusterrolebinding用于kubectl部署应用到kubernetes集群的权限设置,创建bamboo-agent deployment 注意: 本示例中的clusterrolebinding为admin权限, 具体使用中可以根据自己的需要创建最小权限的serviceaccount bamboo-agent.yaml: ---apiVersion: v1kind: ServiceAccountmetadata: namespace: bamboo name: bamboo---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: bamboo-cluster-adminsubjects: - kind: ServiceAccount name: bamboo namespace: bambooroleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io---apiVersion: apps/v1beta2kind: Deploymentmetadata: name: bamboo-agentspec: replicas: 1 selector: matchLabels: app: bamboo-agent template: metadata: labels: app: bamboo-agent spec: serviceAccountName: bamboo containers: - name: bamboo-agent env: - name: BAMBOO_SERVER_URL value: http://xx.xx.xx.xx:8085 image: registry.cn-hangzhou.aliyuncs.com/haoshuwei/docker-bamboo-agent:v1 imagePullPolicy: Always volumeMounts: - mountPath: /root/.docker/ name: kaniko-docker-cfg volumes: - name: kaniko-docker-cfg secret: secretName: kaniko-docker-cfgkubectl -n bamboo apply -f bamboo-agent.yaml上述kubernetes资源创建完毕后等待remote agent完成初始化配置, 可以使用如下命令查看日志: ...

June 10, 2019 · 1 min · jiezi

Knative-核心概念介绍BuildServing-和-Eventing-三大核心组件

Knative 主要由 Build、Serving 和 Eventing 三大核心组件构成。Knative 正是依靠这三个核心组件,驱动着 Knative 这艘 Serverless 巨轮前行。下面让我们来分别介绍一下这三个核心组件。 BuildKnative Build 是基于现有的 Kubernetes 能力之上,提供的一套标准化、可移植、可复用的容器镜像构建方式。通过在 Kubernetes 上运行复杂的构建任务,Knative Build 使你不必再单独开发和重复这些镜像构建过程, 从而通过系统化、工程化的方式,减少了镜像构建时间及成本。 Build 通过 Kubernetes 自定义资源定义(CRD)实现。 通过 Build 你可以自定义一个从运行到结束的构建流程。例如,可以使用 Knative Build 来获取、构建和打包代码。Build 具备以下功能: 支持 Source 源挂载,目前支持的 Source 源包括: git 代码仓库任意容器镜像支持通过 BuildTemplate 创建可重复执行构建的模板支持 K8s ServiceAccount 身份验证典型的 Build 示意图: 虽然目前 Knative Build 并不提供完整的独立 CI/CD 解决方案,但它却提供了一个底层的构建模块,用户可单独使用该构建模块在大型系统中实现集成和利用。 ServingKnative 作为 Severless 框架最终是用来提供服务的, 那么 Knative Serving 应运而生。 Knative Serving 构建于 Kubernetes 和 Istio 之上,为  Serverless 应用提供部署和服务支持。其特性如下: ...

May 31, 2019 · 2 min · jiezi

威胁快报新兴挖矿团伙借助shodan作恶非web应用安全再鸣警钟

近日,阿里云安全发现了一个使用未授权访问漏洞部署恶意Docker镜像进行挖矿的僵尸网络团伙。我们给这一团伙取名为Xulu,因为该团伙使用这个字符串作为挖矿时的用户名。 Xulu并不是第一个攻击Docker的恶意挖矿团伙,但它不同于其他僵尸网络。Xulu感染一台服务器后,并不对外进行大规模扫描,而是使用OSINT技术,即利用开源情报,动态地从shodan网站获得可能的“猎物”ip列表。 此外,Xulu僵尸网络将自己的服务器放在Tor洋葱网络中,这使得对幕后黑手的追溯变得更加困难。 会挖矿的恶意Docker镜像Docker容器是一个开源的应用容器引擎,可以让开发者打包他们的应用及依赖包到一个轻量级、可移植的容器中,从而在不同环境中可靠运行。 近年来随着微服务的流行,越来越多的企业在部署应用时使用容器,然而在这一过程中安全往往没有得到应有的重视,导致Docker容器在多起事件中成为网络攻击的靶子。 在本次Xulu僵尸网络事件中,我们注意到沦陷服务器上都被创建了镜像名为zoolu2/auto的恶意容器。 这些恶意容器中运行着如下进程 其中的挖矿进程很容易分辨: /toolbin/darwin -o us-east.cryptonight-hub.miningpoolhub.com:20580 -u xulu.autodeploy -p x --currency monero -i 0 -c conf.txt -r尽管miningpoolhub.com是公开矿池,但由于它不提供每个用户的历史收益数据,我们无从得知攻击者从恶意挖矿中总共赚了多少钱。 僵尸网络的传播和持久化Xulu僵尸网络进行自身的传播和持久化的过程中,使用了OSINT技术并借助了洋葱网络。 首先,该僵尸网络的控制服务器地址是http://wg6kw72fqds5n2q2x6qjejenrskg6i3dywe7xrcselhbeiikoxfrmnqd.onion。".onion"后缀表明这是一个必须通过洋葱匿名网络访问的“洋葱服务”(又名“隐藏服务”)。 该僵尸网络以/toolbin/shodaemon作为守护进程: 不难看出该脚本下载了http://wg6kw72fqds5n2q2x6qjejenrskg6i3dywe7xrcselhbeiikoxfrmnqd.onion/shodan.txt,与本地硬编码的/toolbin/hcode.txt文件内容一起存入search.txt 运行/toolbin/shodan,读取search.txt的列表并对shodan发送如上图所示的查询。 这些查询会返回互联网上一系列开放了Docker服务(2375端口)的主机ip。尽管这些主机并非每个都存在漏洞,但攻击者仍然通过使用shodan的信息,避免了大规模扫描的进行。 在获取了使用Docker服务的主机列表并去除重复ip后,已沦陷的主机会向表中ip发送docker run命令,其中未授权访问漏洞的Docker服务将被部署"zoolu2/auto"恶意镜像,从而完成蠕虫的传播。 此外,Xulu僵尸网络还会每30分钟下载并执行从http://wg6kw72fqds5n2q2x6qjejenrskg6i3dywe7xrcselhbeiikoxfrmnqd.onion/bnet1.txt下载的脚本,从而保持自身在受害主机上的活跃。 受害规模和安全建议在docker hub官网我们可以看到,前文提到的"zoolu2/auto"已被下载超过1万次: 并且僵尸网络作者似乎仍在积极开发变种: 为了避免您成为此种恶意入侵和挖矿事件的受害者,阿里云安全为您提供如下安全建议:不要将对内使用的服务(如Docker)开放在互联网上,应使用ACL或复杂密码等措施来保证仅有受到信任的用户才可以访问这些服务。因为基于洋葱网络的“隐藏服务”已被用于多个僵尸网络的传播,不常使用洋葱网络服务的用户可以使用如下命令对其进行屏蔽:echo -e "n0.0.0.0 .onion" >> /etc/hosts我们推荐您使用阿里云下一代防火墙,因为它在阻止、拦截此类需要外联的攻击时十分有效。用户将在AI技术的帮助下,免于恶意挖矿事件的困扰我们同样推荐阿里云安全管家服务。该服务的用户可以就碰到的问题随时咨询安全专家。安全专家还可以帮助用户进行安全加固、事件溯源、蠕虫清理等IOCcontrol server: http://wg6kw72fqds5n2q2x6qjejenrskg6i3dywe7xrcselhbeiikoxfrmnqd.onion url: http://wg6kw72fqds5n2q2x6qjejenrskg6i3dywe7xrcselhbeiikoxfrmnqd.onion/bnet1.txthttp://wg6kw72fqds5n2q2x6qjejenrskg6i3dywe7xrcselhbeiikoxfrmnqd.onion/shodan.txt pool:us-east.cryptonight-hub.miningpoolhub.com:20580 md5: c29dfe75862b6aed91bec4ffc7b20b9c Referencehttps://www.alibabacloud.com/blog/dockerkiller-threat-analysis-first-instance-of-batch-attack-and-exploitation-of-docker-services_593947https://www.docker.com/resources/what-container 本文作者:云安全专家阅读原文 本文为云栖社区原创内容,未经允许不得转载。

May 27, 2019 · 1 min · jiezi

TalkingData的Spark-On-Kubernetes实践

摘要: 本文整理自talkingdata云架构师徐蓓的分享,介绍了Spark On Kubernetes在TalkingData的实践。众所周知,Spark是一个快速、通用的大规模数据处理平台,和Hadoop的MapReduce计算框架类似。但是相对于MapReduce,Spark凭借其可伸缩、基于内存计算等特点,以及可以直接读写Hadoop上任何格式数据的优势,使批处理更加高效,并有更低的延迟。实际上,Spark已经成为轻量级大数据快速处理的统一平台。Spark作为一个数据计算平台和框架,更多的是关注Spark Application的管理,而底层实际的资源调度和管理更多的是依靠外部平台的支持: Spark官方支持四种Cluster Manager:Spark standalone cluster manager、Mesos、YARN和Kubernetes。由于我们TalkingData是使用Kubernetes作为资源的调度和管理平台,所以Spark On Kubernetes对于我们是最好的解决方案。 如何搭建生产可用的Kubernetes集群部署 目前市面上有很多搭建Kubernetes的方法,比如Scratch、Kubeadm、Minikube或者各种托管方案。因为我们需要简单快速地搭建功能验证集群,所以选择了Kubeadm作为集群的部署工具。部署步骤很简单,在master上执行: kubeadm init在node上执行: kubeadm join --token : --discovery-token-ca-cert-hash sha256:具体配置可见官方文档:https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/。需要注意的是由于国内网络限制,很多镜像无法从k8s.gcr.io获取,我们需要将之替换为第三方提供的镜像,比如:https://hub.docker.com/u/mirrorgooglecontainers/。 网络 Kubernetes网络默认是通过CNI实现,主流的CNI plugin有:Linux Bridge、MACVLAN、Flannel、Calico、Kube-router、Weave Net等。Flannel主要是使用VXLAN tunnel来解决pod间的网络通信,Calico和Kube-router则是使用BGP。由于软VXLAN对宿主机的性能和网络有不小的损耗,BGP则对硬件交换机有一定的要求,且我们的基础网络是VXLAN实现的大二层,所以我们最终选择了MACVLAN。CNI MACVLAN的配置示例如下: { "name": "mynet", "type": "macvlan", "master": "eth0", "ipam": { "type": "host-local", "subnet": "10.0.0.0/17", "rangeStart": "10.0.64.1", "rangeEnd": "10.0.64.126", "gateway": "10.0.127.254", "routes": [ { "dst": "0.0.0.0/0" }, { "dst": "10.0.80.0/24", "gw": "10.0.0.61" } ] }}Pod subnet是10.0.0.0/17,实际pod ip pool是10.0.64.0/20。cluster cidr是10.0.80.0/24。我们使用的IPAM是host-local,规则是在每个Kubernetes node上建立/25的子网,可以提供126个IP。我们还配置了一条到cluster cidr的静态路由10.0.80.0/24,网关是宿主机。这是因为容器在macvlan配置下egress并不会通过宿主机的iptables,这点和Linux Bridge有较大区别。在Linux Bridge模式下,只要指定内核参数net.bridge.bridge-nf-call-iptables = 1,所有进入bridge的流量都会通过宿主机的iptables。经过分析kube-proxy,我们发现可以使用KUBE-FORWARD这个chain来进行pod到service的网络转发: ...

May 23, 2019 · 2 min · jiezi

利用Packer自定义镜像创建容器集群

阿里云容器服务Kubernetes集群支持CentOS操作系统,在绝大多数情况下可以满足客户的要求。但是有些客户由于业务系统对操作系统依赖比较高,希望定制化一些操作系统参数,则可以用自定义镜像来创建Kubernetes集群。 创建自定义操作系统镜像有两种方式,一是在控制台上通过为一台ECS创建快照的方式创建镜像,注意一定要基于阿里云CentOS作为基础镜像,把对操作系统的定制化更新完打成镜像即可。但这种方式的不便之处在于,如果每次对操作系统镜像有更新,则都要手动操作一遍,很难自动化。而且如果是从已有的Kubernetes节点制作镜像,还需要把Docker,Kubelet等清理干净才能制作镜像,步骤繁琐且容易遗漏。 另外一种方式就是本文介绍的用Packer构建镜像。相关的参考文档:使用Packer创建自定义镜像。采用Packer构建镜像的好处是可以把构建方式自动化,构建所需的参数文件中包含了对干净的基础镜像所做的修改,一目了然,并且可以把配置进行版本化管理。后期需要构建新的镜像,只需改变配置重新执行一下Packer构建即可,非常方便,是在生产环境中使用自定义镜像的推荐方式。 那么有没有一个针对容器服务集群的Packer配置模版呢?容器服务团队开源的ack-image-builder就是一个这样的示例项目。下面我们就来一起动手实践一下。 安装Packer可以根据官方文档安装Packer https://www.packer.io/intro/getting-started/install.html 。 创建自定义镜像克隆ack-image-builder项目到本地,可以看到config和scripts目录下是一些示例定制化脚本,读者可以根据自己的需求更新改。 $ git clone https://github.com/AliyunContainerService/ack-image-builder.git$ cd ack-image-builderack-image-builder $ tree.├── LICENSE.txt├── README.md├── ack-centos.json├── config│   └── default.sh└── scripts ├── cleanUpKerneles.sh ├── reboot.sh ├── updateKernel.sh └── verify.sh2 directories, 8 files在ack-centos.json 可以配置在把生成好的自定义镜像存在哪个区(示例中为cn-hangzhou)。 { "variables": { "region": "cn-hangzhou", "image_name": "ack_test_image{{timestamp}}", "source_image": "centos_7_06_64_20G_alibase_20190218.vhd", ... },配置好阿里云账号的AK,然后执行构建命令。 export ALICLOUD_ACCESS_KEY=XXXexport ALICLOUD_SECRET_KEY=XXXpacker build ack-centos.json大约7-8分钟一个新的自定义镜像就构建成功了。可以进入ECS控制台查看新生成的镜像。 利用自定义镜像创建容器集群开通自定义镜像白名单 读者如果需要尝试自定义镜像能力,需要先开工单,申请在容器服务控制台上开通自定义镜像的白名单。 创建容器集群 白名单开通后进入容器服务控制台 https://cs.console.aliyun.com/#/k8s/cluster/list,创建Kubernetes集群。选择自定义镜像所在的区,在示例中是cn-hangzhou。 在创建集群的页面中点击"显示高级选项",会出现"自定义镜像"的选择界面: 如果在选择中找不到刚创建的镜像,请检查一下集群和自定义镜像是否在同一个Region。 选择了自定义镜像后点击创建集群即可完成一个自定义镜像集群的创建。 集群扩容与自动伸缩 使用自定义镜像创建集群后,集群的扩容与自动伸缩中所用的都是自定义镜像。 Terraform 中自定义镜像支持利用Terraform创建容器集群也可以使用自定义镜像,具体参数是: image_id - The ID of node image.相关链接如下: ...

May 16, 2019 · 1 min · jiezi

阿里云Kubernetes服务上从零搭建GitLabJenkinsGitOps应用发布模型的实践全纪录

关于GitOps的介绍,可以参考 GitOps:Kubernetes多集群环境下的高效CICD实践 1. 在 容器服务控制台 创建kubernetes集群1.1 新建Kubernetes集群: 1.2 新建命名空间gitops 我们将会把gitlab和jenkins全部部署到此命名空间下 2. 创建GitLab应用 (可选项,可以对接已有GitLab环境)容器服务控制台上依次点击 市场 -> 应用目录 -> gitlab-ce : 在 参数 中设置externalUrl和gitlabRootPassword后选择gitops命名空间并创建应用,本次实践中 externalUrl 设置为 http://ls-gitlab.example.com/, 如果没有dns解析的话,可以在创建成功后直接使用ip 容器服务控制台上依次点击 路由与负载均衡 -> 服务 查看gitlab应用的访问地址,大约2分钟后可访问gitlab并登陆: 3. 设置GitLab并上传示例源码项目3.1 新建private group application 创建private group application: 3.2 新建并上传private project application-demo 创建private project application-demo, 示例源码地址: https://code.aliyun.com/haoshuwei/application-demo.git 从master新建一个分支latest: 设置master和latest分支只有管理员才能merge和push代码的操作: 3.3 新建private group builds 3.4 新建并上传private project preview-pipeline staging-pipeline production-pipeline preview-pipeline示例源码地址为: https://code.aliyun.com/haoshuwei/preview-pipeline.gitstaging-pipeline示例源码地址为: https://code.aliyun.com/haoshuwei/staging-pipeline.gitproduction-pipeline示例源码地址为: https://code.aliyun.com/haoshuwei/production-pipeline.git上传3个构建项目之前需要替换以下字段:IMAGE_REPO:  应用容器镜像要上传到哪个镜像仓库,镜像仓库地址dingTalkToken: 钉钉通知所使用的钉钉机器人accessTokenFetch Git Repo -> credentialsId : 用于Jenkins拉取git项目的证书名称,需要在Jenkins中创建名为gitlab的证书Fetch Git Repo -> url : Jenkins拉取git repo的url ...

May 9, 2019 · 2 min · jiezi

Docker镜像分层结构

docker镜像分层结构用过Dockerfile构建镜像的都知道Dockerfile执行完每一条指令都会创建一个新的镜像,最终的镜像由层层叠加而成。分层的好处最大的好处就是共享资源。当多个镜像从相同的base镜像构建而来,那么Docker host只需要在磁盘保存一份base镜像,同时内存中也只需要加载一份base镜像,就可以为所有的容器服务了。容器的修改并不会影响镜像当容器启动时,一个新的可写层被加载到镜像的顶层,这一层通常被成为“容器层”。对容器的改动,无论添加、删除、还是修改文件都只会发生在容器层中。容器层是可写的,镜像层是只读的。添加文件时,新的文件添加到容器层。读取文件时,从上往下在各个镜像层查找,一旦找到就复制到容器层,然后读入内存。修改文件,从上往下查找,复制到容器层,然后修改之。删除文件,从上往下查找,找到后返回,记录删除操作。只有当需要修改时才赋值一份数据,这种特性被称为Copy-On-Write。容器层保存的是镜像层的变化,但不会对镜像本身进行任何修改。这也解释了镜像可以被多个容器共享。参考镜像分层结构

April 8, 2019 · 1 min · jiezi

加速一切 - 配置国内镜像 - Linux apt/macOS brew/Docker/Python Conda/Maven

此处仅列出了常用的一些,还有很多没有列出来,需要的话可以从文章最下方链接中查找相应的国内镜像Ubuntuaptvim /etc/apt/sources.list清华源16.04 LTS# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted universe multiverse# 预发布软件源,不建议启用# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-proposed main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-proposed main restricted universe multiverse18.04 LTS# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse# 预发布软件源,不建议启用# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse18.10# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ cosmic main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ cosmic main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ cosmic-updates main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ cosmic-updates main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ cosmic-backports main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ cosmic-backports main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ cosmic-security main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ cosmic-security main restricted universe multiverse# 预发布软件源,不建议启用# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ cosmic-proposed main restricted universe multiverse# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ cosmic-proposed main restricted universe multiverse其他版本详见 https://mirror.tuna.tsinghua.edu.cn/help/ubuntu/中科大源 https://mirrors.ustc.edu.cn/help/ubuntu.html阿里源 https://opsx.alibaba.com/mirror 找到 Ubuntu,点击帮助网易源 https://mirrors.163.com/.help/ubuntu.html 不全CentOSyum/etc/yum.repos.d/CentOS-Base.repo清华源CentOS 7# CentOS-Base.repo## The mirror system uses the connecting IP address of the client and the# update status of each mirror to pick mirrors that are updated to and# geographically close to the client. You should use this for CentOS updates# unless you are manually picking other mirrors.## If the mirrorlist= does not work for you, as a fall back you can try the# remarked out baseurl= line instead.##[base]name=CentOS-$releasever - Basebaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/os/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=osgpgcheck=1gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7#released updates[updates]name=CentOS-$releasever - Updatesbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/updates/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updatesgpgcheck=1gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7#additional packages that may be useful[extras]name=CentOS-$releasever - Extrasbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/extras/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extrasgpgcheck=1gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7#additional packages that extend functionality of existing packages[centosplus]name=CentOS-$releasever - Plusbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/centosplus/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplusgpgcheck=1enabled=0gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7CentOS 6# CentOS-Base.repo## The mirror system uses the connecting IP address of the client and the# update status of each mirror to pick mirrors that are updated to and# geographically close to the client. You should use this for CentOS updates# unless you are manually picking other mirrors.## If the mirrorlist= does not work for you, as a fall back you can try the# remarked out baseurl= line instead.##[base]name=CentOS-$releasever - Basebaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/os/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=osgpgcheck=1gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6#released updates[updates]name=CentOS-$releasever - Updatesbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/updates/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updatesgpgcheck=1gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6#additional packages that may be useful[extras]name=CentOS-$releasever - Extrasbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/extras/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extrasgpgcheck=1gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6#additional packages that extend functionality of existing packages[centosplus]name=CentOS-$releasever - Plusbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/centosplus/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplusgpgcheck=1enabled=0gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6#contrib - packages by Centos Users[contrib]name=CentOS-$releasever - Contribbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/contrib/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=contribgpgcheck=1enabled=0gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6CentOS 5# CentOS-Base.repo## The mirror system uses the connecting IP address of the client and the# update status of each mirror to pick mirrors that are updated to and# geographically close to the client. You should use this for CentOS updates# unless you are manually picking other mirrors.## If the mirrorlist= does not work for you, as a fall back you can try the# remarked out baseurl= line instead.##[base]name=CentOS-$releasever - Basebaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/os/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=osgpgcheck=1gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5#released updates[updates]name=CentOS-$releasever - Updatesbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/updates/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updatesgpgcheck=1gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5#additional packages that may be useful[extras]name=CentOS-$releasever - Extrasbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/extras/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extrasgpgcheck=1gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5#packages used/produced in the build but not released[addons]name=CentOS-$releasever - Addonsbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/addons/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=addonsgpgcheck=1gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5#additional packages that extend functionality of existing packages[centosplus]name=CentOS-$releasever - Plusbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/centosplus/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplusgpgcheck=1enabled=0gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5#contrib - packages by Centos Users[contrib]name=CentOS-$releasever - Contribbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/contrib/$basearch/#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=contribgpgcheck=1enabled=0gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5清华源 https://mirror.tuna.tsinghua.edu.cn/help/centos/中科大 https://mirrors.ustc.edu.cn/help/centos.html阿里源 https://opsx.alibaba.com/mirrorDocker安装清华源提供 Debian/Ubuntu/Fedora/CentOS/RHEL 的 docker 软件包Ubuntusudo apt-get remove docker docker-engine docker.iosudo apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-commoncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -sudo add-apt-repository \ “deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu \ $(lsb_release -cs) \ stable"sudo apt-get updatesudo apt-get install docker-ce其他看 https://mirror.tuna.tsinghua.edu.cn/help/docker-ce/中科大 https://mirrors.ustc.edu.cn/help/docker-ce.htmlDocker HubDocker 中国 https://www.docker-cn.com/registry-mirror中科大https://mirrors.ustc.edu.cn/help/dockerhub.html国内 docker 仓库镜像对比Linux对于使用 upstart 的系统(Ubuntu 14.04、Debian 7 Wheezy),在配置文件 /etc/default/docker 中的 DOCKER_OPTS 中配置Hub地址:DOCKER_OPTS=”–registry-mirror=https://docker.mirrors.ustc.edu.cn/“重新启动服务:sudo service docker restart对于使用 systemd 的系统(Ubuntu 16.04+、Debian 8+、CentOS 7), 在配置文件 /etc/docker/daemon.json 中加入:{ “registry-mirrors”: [“https://docker.mirrors.ustc.edu.cn/”]}重新启动 dockerd:sudo systemctl restart dockermacOS打开 “Docker.app”进入偏好设置页面(快捷键 ⌘, )打开 “Daemon” 选项卡在 “Registry mirrors” 中添加 https://docker.mirrors.ustc.e…点击下方的 “Apply & Restart” 按钮Windows在系统右下角托盘 Docker 图标内右键菜单选择 Settings ,打开配置窗口后左侧导航菜单选择 Daemon 。在 Registry mirrors 一栏中填写地址 https://docker.mirrors.ustc.e… ,之后点击 Apply 保存后 Docker 就会重启并应用配置的镜像地址了。检查 Docker Hub 是否生效在命令行执行 docker info ,如果从结果中看到了如下内容,说明配置成功。Registry Mirrors: https://docker.mirrors.ustc.edu.cn/Anaconda下载安装清华 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/中科大 https://mirrors.ustc.edu.cn/anaconda/archive/Condahttps://mirror.tuna.tsinghua.edu.cn/help/anaconda/https://mirrors.ustc.edu.cn/help/anaconda.htmlconda config –add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/conda config –add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/conda config –set show_channel_urls yesHomebrew清华https://mirror.tuna.tsinghua.edu.cn/help/homebrew/替换现有上游cd “$(brew –repo)“git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.gitcd “$(brew –repo)/Library/Taps/homebrew/homebrew-core"git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.gitbrew update使用homebrew-science或者homebrew-pythoncd “$(brew –repo)/Library/Taps/homebrew/homebrew-science"git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-science.gitcd “$(brew –repo)/Library/Taps/homebrew/homebrew-python"git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-python.gitbrew updatehttps://mirror.tuna.tsinghua.edu.cn/help/homebrew-bottles/该镜像是 Homebrew 二进制预编译包的镜像。本镜像站同时提供 Homebrew 的 formula 索引的镜像(即 brew update 时所更新内容)临时替换export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles长期替换echo ’export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles’ >> ~/.bash_profilesource /.bash_profile中科大https://mirrors.ustc.edu.cn/help/brew.git.htmlhttps://mirrors.ustc.edu.cn/help/homebrew-bottles.htmlhttps://mirrors.ustc.edu.cn/help/homebrew-core.git.htmlhttps://mirrors.ustc.edu.cn/help/homebrew-cask.git.htmlMaven/.m2/settings.xml<?xml version=“1.0” encoding=“UTF-8”?><settings xmlns=“http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=“http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>https://maven.aliyun.com/repository/central</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors></settings> 镜像站汇总清华大学开源软件镜像站 - Tsinghua Open Source Mirror中国科学技术大学开源软件镜像淘宝 NPM 镜像网易开源镜像站阿里巴巴开源镜像站搜狐开源镜像站Capital Online Mirror Site北京理工大学开源软件镜像站北京交通大学开源软件镜像站兰州大学开源社区镜像站浙江大学开源镜像站Northeastern University OpenSource Mirrors华中科技大学开源镜像站重庆大学开源软件镜像站东软信息学院自己的开源镜像站 ...

March 15, 2019 · 4 min · jiezi

如何制作可以在 MaxCompute 上使用的 crcmod

之前我们介绍过在 PyODPS DataFrame 中使用三方包。对于二进制包而言,MaxCompute 要求使用包名包含 cp27-cp27m 的 Wheel 包。但对于部分长时间未更新的包,例如 oss2 依赖的 crcmod,PyPI 并未提供 Wheel 包,因而需要自行打包。本文介绍了如何使用 quay.io/pypa/manylinux1_x86_64 镜像制作可在 MaxCompute 上使用的 Wheel 包。本文参考 https://github.com/pypa/manylinux ,quay.io/pypa/manylinux1_x86_64 镜像也是目前绝大多数 Python 项目在 Travis CI 上打包的标准工具,如有进一步的问题可研究该项目。1. 准备依赖项不少包都有依赖项,例如 devel rpm 包或者其他 Python 包,在打包前需要了解该包的依赖,通常可以在 Github 中找到安装或者打包的相关信息。对于 crcmod,除 gcc 外不再有别的依赖,因而此步可略去。2. 修改 setup.py 并验证(建议在 Mac OS 或者 Linux 下)较旧的 Python 包通常不支持制作 Wheel 包。具体表现为在使用 python setup.py bdist_wheel 打包时报错。如果需要制作 Wheel 包,需要修改 setup.py 以支持 Wheel 包的制作。对于一部分包,可以简单地将 distutils 中的 setup 函数替换为 setuptools 中的 setup 函数。而对于部分自定义操作较多的 setup.py,需要详细分析打包过程,这一项工作可能会很复杂,本文就不讨论了。例如,对于 crcmod,修改 setup.py 中的from distutils.core import setup为from setuptools import setup即可。修改完成后,在项目根目录执行python setup.py bdist_wheel如果没有报错且生成的 Wheel 包可在本地使用,说明 setup.py 已可以使用。3. 准备打包脚本在项目中新建 bin 目录,并在其中创建 build-wheel.sh:mkdir bin && vim bin/build-wheel.sh在其中填入以下内容:#!/bin/bash# modified from https://github.com/pypa/python-manylinux-demo/blob/master/travis/build-wheels.shset -e -x# Install a system package required by our library# 将这里修改为安装依赖项的命令# Compile wheelsPYBIN=/opt/python/cp27-cp27m/bin# 如果包根目录下有 dev-requirements.txt,取消下面的注释# “${PYBIN}/pip” install -r /io/dev-requirements.txt"${PYBIN}/pip" wheel /io/ -w wheelhouse/# Bundle external shared libraries into the wheelsfor whl in wheelhouse/*.whl; do auditwheel repair “$whl” -w /io/wheelhouse/done将第一步获知的依赖项安装脚本填入此脚本,在使用 python 或 pip 时,注意使用 /opt/python/cp27-cp27m/bin 中的版本。最后,设置执行权限chmod a+x bin/build-wheel.sh4. 打包使用 Docker 下载所需的镜像(本步需要使用 Docker,请提前安装),此后在项目根目录下打包:docker pull quay.io/pypa/manylinux1_x86_64docker run –rm -v pwd:/io quay.io/pypa/manylinux1_x86_64 /io/bin/build-wheel.sh完成的 Wheel 包位于项目根目录下的 wheelhouse 目录下。本文作者:继盛阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 1, 2019 · 1 min · jiezi

基于 Kubernetes 实践弹性的 CI/CD 系统

大家好,我是来自阿里云容器服务团队的华相。首先简单解释一下何为 Kubernetes 来帮助大家理解。Kuberentes 是一个生产可用的容器编排系统。Kuberentes 一方面在集群中把所有 Node 资源做一个资源池,然后它调度的单元是 Pod,当然 Pod 里面可以有多个容器。 就像一个人左手抓着 ECS 资源或计算资源,右手抓容器,然后把它们两个匹配起来,这样它就可以作为一个容器的编排系统。而 Cloudnative 这个概念现在会经常被大家提起,很多人迷惑 Cloudnative 又与 Kuberentes 有什么关联?我们又该如何判断一个应用是 Cloudnative 呢?我认为有以下三个判断标准:第一,它能够给资源做池化;第二,应用可以快速接入池的网络。在 Kuberentes 里面有一层自己的独立网络,然后只需要知道我要去访问哪个服务名就可以,就是各种服务发现的一些功能,它可以通过 service mesh 去做一个快速地访问;第三是有故障转移功能,如果一个池子里面有一台主机,或者某一个节点 down 掉了,然后整个应用就不可用了,这肯定不算是 Cloudnative 的应用。比较这三点就可以发现 Kuberentes 做的非常好。首先我们看一个资源池的概念,Kuberentes 一个大的集群就是一个资源池,我们再也不用去关心说我这个应用要跑在哪台主机上了,我只要把我们部署的 yaml 文件往 Kuberentes 上发布就可以了,它会自动做这些调度,并且它可以快速地接入我们整个应用的网络,然后故障转移也是自动。接下来我就来分享如何基于 Kuberentes 实现一个弹性的 CI/CD 系统。CI/CD 的现状首先了解一下 CI/CD 的现状。CI/CD 这个概念实际上已经提出很多年了,但是随着技术地演进和新工具地不断推出,它在整个流程和实现方式上逐渐丰富。而我们通常最早接触 CI/CD 就是代码提交,随之触发一个事件,然后在某个 CI/CD 系统上做自动构建。下图可以反映目前 CI/CD 的现状:另外还有 Gitlab CI,它主要特点是与 Gitlab 代码管理工具结合地比较好。Jenkins 2.0 开始引入 pipeline as code 特性,pipeline as code 可以帮我们自动生成一个 jenkins file。在 Jenkins 1.0 时,如果我们想要配置一条流水线,需要先登录 Jenkins 建一个项目,然后在里面写一些 shell。这样虽然能达到同样的效果,但是它有一个最大的弊端,就是可复制性和迁移性不好。而且它与 Devops 有天然地割裂,比如一般是由运维人员来管理 Jenkins 系统,开发人员编写代码,但是这个代码怎么去构建,发布到哪里,开发人员完全不知道。这就造成了开发和运维地割裂。但 pipeline as code 方式出现了之后,jenkins file 与代码源码可以放在同样的仓库里面。首先它有一个非常大的好处是发布的流程也可以纳入版本管理,这样对一个错误就可追溯。这是一个非常大地改动,但是实际上我们在与客户沟通中发现,虽然很多人在 Jenkins 上都已经升到 2.0 系列了,但是它们的用法还是完全在 1.0 系列,很多用户都没有把 jenkins file 这种方式用起来。另外一个就是对容器地支持,大概 2016 年左右,那时对容器的支持是非常弱的,在容器里面运行 Jenkins,同时构建的产物也是 Docker 会非常麻烦。 但是, Drone 对容器的支持力度就非常好。首先它完全用 Docker 方式来运行,就是说你的构建环境也在一个容器里,你需要构建一个 Docker build 镜像,然后在推送出去的时候,它也在容器里面运行,然后它需要一个 privilege 权限。它这种方式有几个特别好的地方,首先它不会对宿主机产生任何残留,比如说你这个容器一销毁,构建中产生的一些中间文件完全都跟着销毁了,但是你如果用 Jenkins 的话,随着用的时间越来越久会沉淀出很多临时文件,它占的空间会越来越大。你需要定期做一些清理,而且清理过程中你又不能直接一键清空,所以这是很麻烦的过程。然后插件的管理 Jenkins 还有一个特别让人头疼的地方,就是它的插件升级。首先你在 Jenkins 登录进去,然后就做插件升级。如果说我想临时在一个新的环境里面,起一个 Jenkins 先测试一下或做一些调试可能每新建一个环境,都需要把这些插件升级一次。而且刚才我们说的在 Jenkins 里面做的所有配置,也都需要重新配置一遍,这是一个非常繁琐的一个过程。但是 Drone 这个工具它有一个特别好的地方,就是所有的插件都是 Docker 容器,比如说你在 pipeline 里用这个插件,你只要声明用这个插件就可以了,你不用去自己管理把插件下载到哪里,然后怎么安装,它这个一切都是全自动,只要说你网络能把插件容器镜像访问到就可以了,这非常便利。然后关于生态的构建,Jenkins 的最大的优势就是它的插件非常多,就是你想用的各种东西都有,而且它基础的底座非常好,你的插件可以实现的能力非常的强。比如说 pipeline 就是这种方式,它从 1.0 到 2.0 虽然有了,但是它完全是通过插件来实现的。但是现在 Jenkins 的发展又开始有点第二春的感觉。他开始对 Kuberentes 的支持力度明显的加大了很多,首先从 JenkinsX 开始,它融合了一些 Kuberentes 生态相关的一些工具,比如 Harbor、Helm 它可以非常便利地在 Kuberentes 集群上来做一些构建,并且把一些做服务的固化的一些编排文件放到 Helm 里面。另外,现在它有一个新的子项目叫 config as code,也就是说他把所有 Jenkin 里面做了一些配置,都可以输出成一个 code 的形式,就是对整个 Jenkins 的迁移,或者说复制都是一个很便利的改进。讲了那么多,实际上最后我们选择的东西还是 Jenkins,因为最重要的是生态的构建,他们已经很好了。今天我们要讲的在做一个弹性在 CI/CD 这个 Jenkins 上已经有这个插件了,但是在 Drone 的社区里面,有人提这个事,但是现在还没有看到。CI/CD 工具的选择接下来,我们看一下 CI/CD 这些工具的选择和他们的发展。首先最老牌的肯定是 Jenkins。实际上在容器技术兴起之前,CI/CD 简直约等于 Jenkins。但是在出现容器技术之后,很多新生 CI/CD 的工具也应运而生,比如说图中 Drone 工具,它是一个完全基于容器来实现的 CI/CD 工具。它与容器地结合地非常好,并且它的构建过程是完全在容器中实现的。第三个是 Gitlab CI,它主要特点是与 Gitlab 代码管理工具结合地比较好。Jenkins 2.0 时开始引入 pipeline as code 特性,什么叫 pipeline as code?pipeline as code 可以帮我们自动生成一个 jenkins file。在 Jenkins 1.0 时,如果我们想要配置一条流水线,需要先登录 Jenkins,然后建一个项目,然后在里面写一些 shell。这样虽然能达到同样的效果,但是它有一个最大的弊端,就是可复制性和迁移性不好。而且它与 Devops 有天然地割裂,比如一般是运维人员来管理 Jenkins 这个系统。开发人员编写代码,但是这个代码怎么去构建,发布到哪里,他是完全不知道的,是运维人员在Jenkins 里面配的。这个就造成了开发和运维地割裂。但 pipeline as code 这种方式出现了之后,我们可以把 jenkins file 跟代码源码放在同样的仓库里面。首先它有一个非常大的好处就是我们发布的流程也可以纳入版本管理,这样对一个错误就可追溯。这是一个非常大地改动,但是实际上我们在与客户沟通中发现,虽然很多人在 Jenkins 上都已经升到 2.0 系列了,但是它们的用法还是完全在 1.0 系列,很多用户都没有把 jenkins file 这种方式用起来。另外一个就是对容器地支持,大概 2016 年左右,那时对容器的支持是非常弱的,在容器里面运行 Jenkins,同时构建的产物也是 Doker 会非常麻烦。 但是, Drone 对容器的支持力度就非常好。首先它完全用 Doker 方式来运行,就是说你的构建环境也在一个容器里,你需要构建一个 Doker build 镜像,然后在推送出去的时候,它也在容器里面运行,然后它需要一个 privilege 权限。它这种方式有几个特别好的地方,首先它不会对宿主机产生任何残留,比如说你这个容器一销毁,构建中产生的一些中间文件完全都跟着销毁了,但是你如果用 Jenkins 的话,随着用的时间越来越久会沉淀出很多临时文件,它占的空间会越来越大。你需要定期做一些清理,而且清理过程中你又不能直接一键清空,所以这是很麻烦的过程。然后插件的管理 Jenkins 还有一个特别让人头疼的地方,就是它的插件升级。首先你在 Jenkins 登录进去,然后就做插件升级。如果说我想临时在一个新的环境里面,起一个 Jenkins 先测试一下或做一些调试可能每新建一个环境,都需要把这些插件升级一次。而且刚才我们说的在 Jenkins 里面做的所有配置,也都需要重新配置一遍,这是一个非常繁琐的一个过程。但是 Drone 这个工具它有一个特别好的地方,就是所有的插件都是 Doker 容器,比如说你在 pipeline 里用这个插件,你只要声明用这个插件就可以了,你不用去自己管理把插件下载到哪里,然后怎么安装,它这个一切都是全自动,只要说你网络能把插件容器镜像访问到就可以了,这非常便利。然后关于生态的构建,Jenkins 的最大的优势就是它的插件非常多,就是你想用的各种东西都有,而且它基础的底座非常好,你的插件可以实现的能力非常的强。比如说 pipeline 就是这种方式,它从 1.0 到 2.0 虽然有了,但是它完全是通过插件来实现的。但是现在 Jenkins 的发展又开始有点第二春的感觉。他开始对 Kuberentes 的支持力度明显的加大了很多,首先从 JenkinsX 开始,它融合了一些 Kuberentes 生态相关的一些工具,比如 Harbor、Helm 它可以非常便利地在 Kuberentes 集群上来做一些构建,并且把一些做服务的固化的一些编排文件放到 Helm 里面。另外,现在它有一个新的子项目叫 config as code,也就是说他把所有 Jenkin 里面做了一些配置,都可以输出成一个 code 的形式,就是对整个 Jenkins 的迁移,或者说复制都是一个很便利的改进。讲了那么多,实际上最后我们选择的东西还是 Jenkins,因为最重要的是生态的构建,他们已经很好了。今天我们要讲的在做一个弹性在 CI/CD 这个 Jenkins 上已经有这个插件了,但是在 Drone 的社区里面,有人提这个事,但是现在还没有看到。CI/CD的系统业务场景然后我们看一下 CI/CD 它的系统的业务场景,它有一个比较典型的场景与特点,首先它面向开发人员,这是比较少见的,因为开发人员一般都比较挑剔一点。所以你要是这个系统做的不够稳健了,或者说响应时间比较长一点的话,会被经常吐槽。然后就是有时效性要求,因为我们代码写完之后,往上提交,我们都不希望在这个代码的构建中一直排队,我们希望马上就开始进行构建,并且资源足够丰富。另外一个就是它的资源占用的波峰波谷是非常明显的。就因为开发人员不可能时时刻刻都在提交代码,有的人可能一天提交几次,有的人会提交很多次。因为我之前看过有一个分享,有一个人画了一条反映自家公司构建任务的曲线。他们公司大概是每天下午三、四点的时候代码提交量最高,其他时间都比较平缓。这说明他们公司三、四点的时候,程序员提交代码开始划水了。然后随着 CI/CD 资源地需求越来越高,构建集群是一个必须要做的一件事情。就是提高负载能力,缩短任务的排队时间。当然真正的集群有一个让人觉得很不太好的地方,就是它的 Master 实际上只有一个,当然这个也可以通过插件来做改进。容器可以给我们 CI/CD 系统来注入新的能力,就是环境隔离的能力。我们可以通过 Kubernetes 来为 CI/CD 系统注入更多的能力,然后矛盾点就出现了。开发人员总是希望 CI/CD 系统能够快速地响应代码提交的一个事件,但是每个公司资源都不可能是无限的。因为就像上面提到的,如果每天下午三、四点的时候是一个代码提交的高峰,这个时候可能需要 30 或 40 台机器才能满足构建的任务。但是我不可能每天就开着 30 或 40 台机器在这里,就为了每天下午三、四点,可能会构建一、两个小时。Kubernetes 可以为 jenkins 注入新的能力,让 CI/CD 系统实现弹性的能力。我们期望的目标是什么呢?有构建任务的时候,可以自动为我们资源增加新的机器也好,或增加新的运计算能力也好,反正就是当我需要的时候,可以帮我自动地做一个资源扩张,但是同时也在我不需要的时候,可以自动把这些资源释放掉。我们期望的目标就是这样,Kuberentes 就可以为 Jenkins 来做这样的能力。Kuberentes 作为一个容器编排的系统,它所能提供的能力,它可以快速地弹出一些新的实例,并且把它们自动调度到空闲的机器上,做一个资源池,在资源池里面做一个调度,并且他执行完任务之后,它可以做一个回收。而且如果把这 Jenkins Master 也部署在 Kuberentes 之上,它可以对 Master 做一个故障转移,就是说如果我们系统可以容忍的话,Master 就算挂了,我可以快速把它调到另外一台机器上,这个响应时间不会很长。Kuberentes-plugin这里面也是用一个插件来实现,这个插件名字比较直接叫 Kuberentes-plugin,它这个插件所能提供的能力就是说,他直接管理一个 Kuberentes 集群,它在 Jenkins 里面安装之后,它可以监听 Jenkins 的构建任务。有构建任务,在等待资源的时候,它就可以向 Kuberenetes 去申请一个新的资源,申请一个新的 Pod 去做自动地构建完之后,它就会自动的清理。先简单介绍一下它的能力,因为这个插件安装完之后,它对 pipeline 的语法也有一个改造,一会我们来看一下实例。但是就算到了这一步,还是不行的。首先,Kuberentes 的集群规划还是一个问题。比说我有个集群有 30 个节点,真正的 master 部署在这上面,然后装了那些插件,做了一个管理之后,我们可以发现来了一个新的任务,它就起一个新的 Pod,把这个构建任务给执行制定完。执行完之后,这 Pod 自动销毁不占集群的资源。 平时我们可以在这集群上做一些别的任务,但这个终究还是有一点不好,就是我们这个集群到底规划多大,并且这个集群我们平时不做构建任务的时候,可以在上面做一些别的任务。但是如果正在做任务,突然来了一些构建任务,它可能会出现资源的冲突问题。Kubernetes Autoscaler总的来说,还是有一些不完美的地方,那么我们可以利用 Kuberentes 一些比较没那么常见的特性,来解决我们刚才说的这个问题。这两个东西一个是叫 Autoscaler,一个叫 Virtual node。我们先看一下 Autoscaler,Autoscaler 是一个 Kubernetes 官方的一个组件。在 Kuberentes 的 group 下面支持三种能力:Cluster Autoscaler,可以对集群节点做自动伸缩;Vertical Pod Autoscaler,对集群的 Pod 竖直方向的资源伸缩。因为 Kuberentes 本身里面就带着 HPA 可以做水平方向的 Pod 伸缩、节点数量的伸缩;这个特性还不是生产可用的特性;Addone Resizer,是 Kuberentes 上那些 addone 比如说 Ingress Controler、 DNS 可以根据 Node 的数量来对资源的分配做调整。Cluster autoscaler我要讲的是 Cluster autoscaler,是对集群 node 节点数量做一个扩缩容。 首先我们看一下,这个是在阿里云我们容器服务上所实现的 Autoscaler 的一个方式。我们看一下这个图,这个是 HPA 和 Autoscler 做结合使用的一个场景。HPA 监听监控的事件时发现资源使用率上升到一定程度了之后,HPA 会自动通知 workload,来弹出一个新的 Pod,弹出一个新的 Pod,可能这时候集群资源就已经不够了,所以这个 Pod 可能就会 pending 在这里。它就会触发 Autoscaler 的事件,Autoscaler 就会根据我们之前配置好的 ESS 这个模板来去弹出来一台新的 Node,然后自动地把 Node 加入到我们集群里面。 它是利用了 ESS 定制的模板功能,并且它可以支持多种的 Node 实例的类型,可以支持普通实例,支持 gpu,还有抢占式实例。Virtual node然后第二种是 Virtual node,Virtual node 实现方式是基于微软开源的 Virtual Kubelet 这个项目。它做了一个虚拟的 Kubelet,然后向 Kubernetes 集群里面去注册上面。但如果不太好理解的话,可以想象一下 MySQL proxy ,然后他把自己伪装成一个MySQL server,然后后端可能管理着非常多的 MySQL server,并且它可以帮你自动的做一些 SQL 查询的路由或者拼接。Virtual kubelet 做的也是类似的工作,就是说它本身向着 Kubernetes 注册说我是一个节点,但实际上它后端管理的可能是整个公有云上的非常多的资源,他可能对接公有云的一些 ECI 或者说对接的这些 VPC,这是一个它的大体的示意图。在阿里云上他们对接的是阿里云的 ECI 做一个弹性的容器实例,它响应时间就非常快,因为它不需要把 Node 去加入到集群里面,它是大概能够到一分钟一百个 Pod 左右这种性能。而且我们可以在 Pod 上声明这种资源的使用情况,这是一个非常快的响应速度时间。然后刚才说我们利用这两种方式,就可以对我们 CI/CD 弹性的系统做出新的改造,我们不用非常早规划好我们集群的规模,我们可以让集群规模在需要的时候自动的做一些伸缩的动作。但是你做了这些动作之后,我们做了这些把真正的放在容器里面的这些动作之后,引入了一些新的门槛:docker-outside-of-docker 和 docker in docker。我们在 Docker 中运行 Jenkins 时,通常有两种方式,一个是把宿主机的 docker.sock 挂载到容器里面,让 Jenkins 通过这个文件来和本机的 docker daemon 做一个通信,然后它在这里面做 docker build 构建镜像,或者把这些镜像 push 到远程的仓库里面,所以它中间产生的所有镜像都会堆积在本机上,这是一个问题。在一些 serverless 的那些场景上使用,它就会有一些限制,因为 serverless 本身就不允许把 socket 文件给挂在进去。另外一个就是 docker in docker 这种方式,它的优点就在于在容器里面它启动一个新的 Docker daemon,它所有的中间产物、构建产物随着容器都一起销毁,但是它有问题,它就是需要 privilege 的权限。很多时候我们是尽量不要用它。另外一个就是说你做 docker build 的时候能在宿主机上做的时候,它如果有已经有镜像了,它会直接就使用这个镜像,但是你用 docker in docker 这种方式来使用的,它每次都会重新拉进项,拉镜像也是需要一定时间,这个取决于我们各个使用场景来判断。新的构建工具——Kaniko这时又引入了一个谷歌开源的新工具——Kaniko。它做的东西是 docker in docker 的方式。它有一个非常大的好处就是不依赖 Docker,而且所以它不需要 privilege 权限就可以在容器里面用用户态的模式,来完全构建 docker image。用户态执行 Dockerfile 的命令,它把这个镜像完全构建出来。这算是一个比较期望的弹性的 CI/CD 系统。然后这个时候就是说从真正的节点到底层的计算资源全部是弹性扩缩的,而且满足交付的需求,可以非常精细化地管理我们的资源。Demo 演示然后我们可以看一下 Demo 演示:https://github.com/hymian/webdemo 这里是我准备好的一个例子,重点在这个 Jenkinsfile 文件,里面定义了agent 的 pod template,包含两个容器,一个用来做 golang 的 build,一个用来做 image 的 build。然后我们现在构建它。开始构建了,刚开始的,因为是现在我们在这环境里面只有一个,只有一个 master,所以他就是没有不会有构建节点。大家可以看到,它现在新启动了一个 Pod,这个 Pod 是作为节点加进来的,但是因为我在这个 Pod 模板里面定义了一个 label,所以它没有这个节点,所以它 Pod 状态是 pending 的。所以我们在构建日志里面显示的这个是 agent 节点是离线的。 但是我们在这个集群里面定义了一个弹性伸缩的一个东西,当没有节点的时候,它会自动做一个新节点分配加入,可以看到有一个节点正在加入,这个我就可以稍等一下。就是说这段时间可能会有个一分钟两分钟的时间。这个是异常,是因为这个节点正在向集群加入,所以它显示是异常,这是我们从命令行看一下,好,已经是四个节点了,加了一个节点,这时候我们看 Pod,这时候在 agent 正在创建,这时候大家可能有一个小的细节,大家可以看一下,就是 0/3 是显示 Pod,它有三个容器,但是我刚才在这个里面定义的,它实际上是 Pod 里面只有两个容器,这就是我们刚才 PPT 上写的一个地方。 JNLP 那个容器,是 plugin 自动注入的一个容器,它通过这个容器实时的向 master 汇报构建的一个中间的状态,我把它的日志给发送出去。这个是 agent 的节点在初始化的一个过程一个事情这时候 slave节点已经在运行了。我这边已经输出完了,构建完成。我的分享内容就这些,谢谢大家。本文作者:jessie筱姜阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 20, 2019 · 3 min · jiezi

Docker镜像仓库清理的探索之路

用友云开发者中心是基于Docker容器进行微服务架构应用的落地与管理。相信各位同学在使用的过程中,会发现随着Docker镜像的增多,占用磁盘空间也约来越多。这时我们需要清理私有镜像仓库中不需要的镜像。但在实际操作时,才会发现这本以为很简单的任务中却暗藏玄机,遇到了不少的麻烦。在这里我们分享一下清理镜像仓库时遇到的坑点。想要直接寻求解决方案的同学可以直接看第二部分。一、那些年,我们在清理镜像仓库时走过的坑坑点1:官方提供的接口并不能真正的删除镜像这着实是最大的坑点。很多同学查资料发现,官方已经提供了删除镜像仓库的API,所以可能相当然的以为直接使用就好,殊不知掉入了官方埋下的最大的坑点,也是本文要着手解决的核心问题:官方提供的删除镜像仓库中镜像的接口,仅仅是把manifest删除了,真正的镜像文件还存在!官方并没有提供删除镜像层的接口!这也就是说,当我们调用删除镜像的接口之后,仅仅是查看镜像的列表时看不到原镜像了,然而原有镜像仍然在磁盘中,占用着宝贵的文件存储空间。 坑点2:直接调用官方的删除镜像API,会返回405的错误码直接调用删除镜像的接口,可能会遇到以下错误提示:405,意味着方法不被允许。实际上,官方可能是处于安全性的考虑,在默认的情况下禁止了直接删除镜像的功能。若要开启删除镜像功能,需要修改镜像仓库的配置文件。具体操作为修改/etc/docker/registry/config.yml文件,在storage下添加delete的许可之后,重启镜像仓库服务。 坑点3:使用官方提供的garbage-collect工具,会有无用的文件残留官方为registry提供了garbage-collect(gc)工具清理镜像的物理存储,将没有引用的layer删除。gc的清理过程分为两部分:1)mark:扫描所有的manifest,列出引用的layer;2)sweep:扫描所有的layer,不在mark里的layer将被清理删除。gc可以在dry-run的模式下运行(添加参数-d),只输出gc信息,不进行实际操作。我们可以通过这种方式来确认哪些镜像会被清除。使用gc工具清理镜像的一个问题就是文件清理得不够干净,无法清理已经没有tag的镜像目录,并且还残存少部分文件,从十KB到几十KB不等。久而久之,垃圾文件和目录的数量会越来越多。坑点4:garbage-collect不是事务操作,清理镜像时可能会产生误操作gc不是事务操作,当gc过程中刚好有push操作时,则可能会误删数据。一个可行的解决办法是手动更改镜像仓库的配置,暂时禁止镜像的push操作。在镜像仓库的配置文件中可以配置read-only模式。当启用read-only之后,再push镜像时会得到405的错误。gc完成后取消read-only模式,再push镜像即可。坑点5:使用garbage-collect工具后,必须重启镜像仓库才能正常使用如果不重启镜像仓库,则再次push该镜像时可能会得到layer already exists错误:其可能的原因是镜像被删除后,仓库的缓存中还存有已经删除的镜像信息,所以再次push会报层存在的错误。二、两种清理镜像仓库的方案方案一:使用官方API + GC使用官方提供的方法可以较为简便的清理镜像仓库。整个清理过程可能需要几百毫秒到几秒的时间。此操作有一定的危险性,因此清理镜像不宜过于频繁。官方在git上也有类似描述。点击查看:https://github.com/docker/doc…具体操作过程如下:1、准备工作在配置中许可删除操作。修改镜像仓库的配置文件,一般在如下路径:/etc/docker/registry/config.yml在storage下添加delete的许可之后,重启镜像仓库。用docker方式启动的镜像仓库也可以添加环境变量:REGISTRY_STORAGE_DELETE_ENABLED=true2、获取待删镜像的digest获取镜像digest的API为:GET /v2/<name>/manifests/<reference>其中,name是仓库名,reference是标签,此时需要注意,调用时需要加上header内容:Accept: application/vnd.docker.distribution.manifest.v2+json其中Docker-Content-Digest的值就是镜像的digest3、调用官方的HTTP API V2删除镜像删除镜像的API为:DELETE /v2/<name>/manifests/<reference>其中,name是仓库名称,reference是包含“sha256:”的digest。4、调用GC清理镜像文件使用gc工具的方式为:bin/registry garbage-collect /etc/docker/registry/config.ymlgc清理需要时间,如果在gc过程中刚好有push操作,可能会产生未知的问题,建议设置read-only模式之后再进行gc,然后再改回来。5、重启docker registry注意,如果不重启会导致push相同镜像时产生layer already exists错误。方案二:使用第三方脚本在清理镜像仓库这件事上,业内已经有很多人进行过各种各样的尝试。本文挑选一种比较好的方式推荐使用。1、宿主机安装delete-docker-registry-image可参考此命令的安装和使用方式。参考链接:https://github.com/burnettk/d…2、执行delete-docker-registry-image命令可以删除某个仓库(sb)或者某个具体的镜像(如alpine:3.2)如果删除某镜像后该仓库为空,可以用删除仓库的方式删除此空仓。该工具也提供了dry-run的方式,只输出待删除的信息不执行删除操作。在命令后加上——dry-run即可。3、重启docker registry跟gc方式一样,删除镜像之后要重启docker registry,不然还是会出现相同镜像push不成功的问题。以上就是本文推荐的两种清理镜像仓库的两种方案。第一种方案更多的使用了官方提供的工具,使用时相对更加安全,且无需额外安装其他内容。第二种方案使用了第三方工具或脚本,使用时更加灵活且简便,且清理的更加彻底。具体操作时可根据自己的需求选择方案。

February 15, 2019 · 1 min · jiezi

阿里云容器服务DaemonSet实践

DaemonSet 保证在每个 Node 上都运行一个容器副本,常用来部署一些集群的日志、监控或者其他系统管理应用。下面以日志收集 fluentd 为例,看下如何使用阿里云容器服务控制台创建DaemonSet。准备Kubernetes环境在阿里云容器服务控制台中创建Kubernetes 集群(1.11.5),3 master,3 worker安装fluentd1、选择应用->守护进程集->使用镜像创建填写应用名称,选择部署集群、命名空间,进入下一步2、选择镜像并进行相应配置注意:这里挂载了配置项fluentd-conf,用来覆盖镜像中的默认配置,需要提前创建出来,内容如下:apiVersion: v1kind: ConfigMapmetadata: name: fluentd-conf namespace: kube-systemdata: td-agent.conf: | <match fluent.> type null </match> <source> type tail path /var/log/containers/.log pos_file /var/log/es-containers.log.pos time_format %Y-%m-%dT%H:%M:%S.%NZ tag kubernetes. format json read_from_head true </source> <filter kubernetes.> type kubernetes_metadata verify_ssl false </filter>否则会遇到pod 启动问题[error]: config error file="/etc/td-agent/td-agent.conf" error=“Invalid Kubernetes API v1 endpoint https://172.21.0.1:443/api: SSL_connect returned=1 errno=0 state=error: certificate verify failed"3、设置更新策略可以在高级配置中选择升级方式:滚动升级(RollingUpdate):更新 DaemonSet 模版后,自动删除旧的 Pod 并创建新的 Pod替换升级(OnDelete):更新模板后,只有手动删除了旧的 Pod 后才会创建新的 Pod4、指定节点调度只选择worker节点安装。设置节点亲和性如图。5、创建完成点击创建,可以看到创建成功。6、问题排查与更新按着上述步骤可以看到在3个worker节点分别起了对应的pod,但pod并没有成功启动。选择其中的一个容器,查看一下日志发现如下错误:config error file="/etc/td-agent/td-agent.conf” error=“Exception encountered fetching metadata from Kubernetes API endpoint: pods is forbidden: User cannot list pods at the cluster scope"Google后发现需要设置ClusterRoleapiVersion: v1kind: ServiceAccountmetadata: name: fluent-account namespace: kube-system—apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata: name: fluent-accountroleRef: kind: ClusterRole name: view apiGroup: rbac.authorization.k8s.iosubjects: - kind: ServiceAccount name: fluent-account namespace: kube-system创建成功后更新fluent-es 的yaml,编辑yaml,提交更新。Pod启动成功,日志已经可以正常采集了。总结使用阿里云容器服务控制台支持方便的创建DaemonSet,欢迎使用体验。https://cs.console.aliyun.com/本文作者:来随便逛逛阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 4, 2019 · 1 min · jiezi

手把手教您将libreoffice移植到函数计算平台

LibreOffice是由文档基金会开发的自由及开放源代码的办公室套件.LibreOffice套件包含文字处理器,电子表格,演示文稿程序,数量库管理程序及创建和编辑数学公式的应用程序。借助LibreOffice的命令行接口可以方便地将office文件转换成pdf。如下所示:$ soffice –convert-to pdf –outdir /tmp /tmp/test.doc一个完整版本的LibreOffice大小为2 GB,而函数计算运行时缓存目录/ tmp空间限制为512M,zip程序包大小限制为50M。好在社区已经有项目aws-lambda-libreoffice成功的将libreoffice移植到AWS Lambda平台,基于前人的方法和经验,本人创建了fc-libreoffice项目,使libreoffice成功的运行在阿里云函数计算平台.fc -libreoffice 在aws-lambda-libreoffice的基础上解决了如下问题:重新编译和裁剪libreoffice,使其适配FC nodejs8 runtime内置的gcc和内核版本;安装运行时缺失的libssl3依赖;借助OSS运行时下载解压,以绕过zip程序包50M的限制;制作了一个例子项目,支持一键部署,快速体验。本文侧重于记述整个移植过程,记录关键步骤以备忘,也为类似的转换工具移植到函数计算平台提供参考。如果您对于如何快速搭建一个廉价且可扩展的词转换pdf云服务更感兴趣,可以阅读另一篇文章“五分钟上线 - 函数计算Word转PDF云服务”。准备工作在开始之前建议找一个台配置较好的Debain / Ubuntu机器,libreoffice编译比较消耗计算资源。并在机器上安装和配置如下工具:docker-ce安装方法参考官方安装文档好玩的一款函数计算的编排工具,用于快速部署函数计算应用。MacOS平台可以使用如下方法安装brew tap vangie/formulabrew install fun其他平台可以通过npm安装npm install @alicloud/fun -gossutil oss的命令行工具。将其下载并放置到&dollar; PATH所在目录。编译libreoffice我们会采用fc-aliyunfc/runtime-nodejs8:build docker 提供的docker镜像进行编译.fc-docker提供了一系列的docker镜像,这些docker镜像环境非常接近函数计算的真实环境。因为我们打算把libreoffice跑在nodejs8环境中,所以我们选用了aliyunfc/runtime-nodejs8:build,建造标签镜像相比于其他镜像会多一些构建需要的基础包。启动一个编译环境通过如下命令可启动一个用于构建libreoffice的容器。docker run –name libre-builder –rm -v $(pwd):/code -d -t –cap-add=SYS_PTRACE –security-opt seccomp=unconfined aliyunfc/runtime-nodejs8:build bash上面的命令,我们启动了一个名为libre-builder的容器并把当前目录挂载到容器内文件系统的/代码目录。附加参数–cap-add=SYS_PTRACE –security-opt seccomp=unconfined是cpp程序编译需要的,否则会报出一些警告。-d表示以后台daemon的方式启动。-t表示启动tty,配合后面的bash命令是为了卡主容器不退出。而–rm表示一旦容器停止了就自动删除容器。安装编译工具接下来进入容器安装编译工具apt-get install -y ccacheapt-get build-dep -y libreofficeccache是一个编译工具,可以加速gcc对同一个程序的多次编译。尽管第一次编译会花费长一点的时间,有了ccache,后续的编译将变得非常非常快。apt-get的build-dep子命令会建立某个要编译软件的环境。具体行为就是把所有依赖的工具和软件包都安装上。克隆源码git clone –depth=1 git://anongit.freedesktop.org/libreoffice/core libreofficecd libreoffice记得加上–depth=1参数,因为libreoffice项目比较大,进行全量克隆会比较费时间,对于编译来说git提交历史没有意义。配置并编译# 如果多次编译,该设置可以加速后续编译ccache –max-size 16 G && ccache -s通过–disable参数去掉不需要的模块,以减少最终编译产物的体积。# the most important part. Run ./autogen.sh –help to see wha each option means./autogen.sh –disable-report-builder –disable-lpsolve –disable-coinmp \ –enable-mergelibs –disable-odk –disable-gtk –disable-cairo-canvas \ –disable-dbus –disable-sdremote –disable-sdremote-bluetooth –disable-gio –disable-randr \ –disable-gstreamer-1-0 –disable-cve-tests –disable-cups –disable-extension-update \ –disable-postgresql-sdbc –disable-lotuswordpro –disable-firebird-sdbc –disable-scripting-beanshell \ –disable-scripting-javascript –disable-largefile –without-helppack-integration \ –without-system-dicts –without-java –disable-gtk3 –disable-dconf –disable-gstreamer-0-10 \ –disable-firebird-sdbc –without-fonts –without-junit –with-theme=“no” –disable-evolution2 \ –disable-avahi –without-myspell-dicts –with-galleries=“no” \ –disable-kde4 –with-system-expat –with-system-libxml –with-system-nss \ –disable-introspection –without-krb5 –disable-python –disable-pch \ –with-system-openssl –with-system-curl –disable-ooenv –disable-dependency-tracking开始编译make的名单最终compile-查询查询结果位于./instdir/目录下。精简尺寸使用strip命令去除二进制文件中的符号信息和编译信息# this will remove ~100 MB of symbols from shared objectsstrip ./instdir/**/删除不必要的文件# remove unneeded stuff for headless moderm -rf ./instdir/share/gallery \ ./instdir/share/config/images_.zip \ ./instdir/readmes \ ./instdir/CREDITS.fodt \ ./instdir/LICENSE* \ ./instdir/NOTICE验证使用如下命令,测试一下编译出来的soffice是否能正常将txt文件转换成pdf文件。echo “hello world” > a.txt./instdir/program/soffice –headless –invisible –nodefault –nofirststartwizard \ –nolockcheck –nologo –norestore –convert-to pdf –outdir $(pwd) a.txt打包# archivetar -zcvf lo.tar.gz instdir然后使用如下命令将lo.tar.gz文件从容器文件系统拷贝到宿主机文件系统。docker cp libre-builder:/code/libreoffice/lo.tar.gz ./lo.tar.gzGzip vs Zopfli vs Brotli Gzip,Zopfli和Brotli是三种开源的压缩算法,对于一个130M的铬文件,分别采用这三种压缩算法最大级别的压缩效果是文件算法MIB压缩比解压耗时铬-130.62–chromium.gzGzip已44.1366.22%0.968schromium.gzZopfli43.0067.08%0.935schromium.brBrotli33.2174.58%0.712s从上面的结果看Brotli算法的效果最优。由于aliyunfc/runtime-nodejs8:build是基于debain jessie发行版的。在debain jessie上安装brotli较为麻烦,所以我们借助ubuntu容器安装brotli工具,将tar.gz格式转为tar.br格式。docker run –name brotli-util –rm -v $(pwd):/root -w /root -d -t ubuntu:18.04 bashdocker exec -t brotli-util apt-get updatedocker exec -t brotli-util apt-get install -y brotlidocker exec -t brotli-util gzip -d lo.tar.gzdocker exec -t brotli-util brotli -q 11 -j -f lo.tar然后当前目录会多一个lo.tar.br文件。安装依赖在函数计算nodejs8环境中运行soffice,需要安装通过npm安装tar.br的解压依赖包@shelf/aws-lambda-brotli-unpacker 和通过apt-get安装libnss3依赖。先启动一个nodejs8的容器,以保证依赖的安装环境和运行时环境是一致的。docker run –rm –name libreoffice-builder -t -d -v $(pwd):/code –entrypoint /bin/sh aliyunfc/runtime-nodejs8注意:存在@shelf/aws-lambda-brotli-unpacker本机绑定,所以在开发机MacOS上npm install打包上传是无法工作。docker exec -t libreoffice-builder npm install由于函数计算运行时无法安装全局的deb包,所以需要将deb和依赖的deb包下载下来,再安装到当前工作目录而不是系统目录。当前工作目录下可以随代码一起打包上传。docker exec -t libreoffice-builder apt-get install -y -d -o=dir::cache=/code libnss3docker exec -t libreoffice-builder bash -c ‘for f in $(ls /code/archives/.deb); do dpkg -x $f $(pwd) ; done;’libnss3包含了许多.so动态链接库文件,linux系统下LD_LIBRARY_PATH环境变量里的动态链接库才能被找到,而函数计算将代码目录/代码下的lib目录默认添加到了LD_LIBRARY_PATH中。所以我们写个脚本,把所有安装的.so文件软连接到/ code / lib目录下docker exec -t libreoffice-builder bash -c “rm -rf /code/archives/; mkdir -p /code/lib;cd /code/lib; find ../usr/lib -type f ( -name ‘.so’ -o -name ‘*.chk’ ) -exec ln -sf {} . ;“下载并解压tar.br为了使用这个lo.tar.br文件,需要先上传到OSSossutil cp $SCRIPT_DIR/../node_modules/fc-libreoffice/bin/lo.tar.br oss://${OSS_BUCKET}/lo.tar.br \ -i ${ALIBABA_CLOUD_ACCESS_KEY_ID} -k ${ALIBABA_CLOUD_ACCESS_KEY_SECRET} -e oss-${ALIBABA_CLOUD_DEFAULT_REGION}.aliyuncs.com -f在函数的初始化方法中下载。module.exports.initializer = (context, callback) => { store = new OSS({ region: oss-${process.env.ALIBABA_CLOUD_DEFAULT_REGION}, bucket: process.env.OSS_BUCKET, accessKeyId: context.credentials.accessKeyId, accessKeySecret: context.credentials.accessKeySecret, stsToken: context.credentials.securityToken, internal: process.env.OSS_INTERNAL === ’true’ }); if (fs.existsSync(binPath) === true) { callback(null, “already downloaded.”); return; } co(store.get(’lo.tar.br’, binPath)).then(function (val) { callback(null, val) }).catch(function (err) { callback(err) });};然后借助于@shelf/aws-lambda-brotli-unpackernpm包解压lo.tar.brconst {unpack} = require(’@shelf/aws-lambda-brotli-unpacker’);const {execSync} = require(‘child_process’);const inputPath = path.join(__dirname, ‘..’, ‘bin’, ’lo.tar.br’);const outputPath = ‘/tmp/instdir/program/soffice’;module.exports.handler = async event => { await unpack({inputPath, outputPath}); execSync(${outputPath} --convert-to pdf --outdir /tmp /tmp/example.docx);};有趣部署函数编写一个template.yml文件,将函数计算的配置都写在该文件中,然后使用fun deploy命令部署函数。ROSTemplateFormatVersion: ‘2015-09-01’Transform: ‘Aliyun::Serverless-2018-04-03’Resources: libre-svc: # service name Type: ‘Aliyun::Serverless::Service’ Properties: Description: ‘fc test’ Policies: - AliyunOSSFullAccess libre-fun: # function name Type: ‘Aliyun::Serverless::Function’ Properties: Handler: index.handler Initializer: index.initializer Runtime: nodejs8 CodeUri: ‘./’ Timeout: 60 MemorySize: 640 EnvironmentVariables: ALIBABA_CLOUD_DEFAULT_REGION: ${ALIBABA_CLOUD_DEFAULT_REGION} OSS_BUCKET: ${OSS_BUCKET} OSS_INTERNAL: ’true’真实场景下,把秘钥和一起变量写在template.yml里并不合适。为了做到代码和配置相分离,上面使用了变量占位符${ALIBABA_CLOUD_DEFAULT_REGION}和${OSS_BUCKET}。然后使用envsubst进行替换SCRIPT_DIR=dirname -- "$0"source $SCRIPT_DIR/../.envexport ALIBABA_CLOUD_DEFAULT_REGION OSS_BUCKETenvsubst < $SCRIPT_DIR/../template.yml.tpl > $SCRIPT_DIR/../template.ymlcd $SCRIPT_DIR/../上面所有的配置都写在了.env文件中,dotenv是社区常见的方案,也有广泛的工具支持。小结本文重点介绍了编译libreoffice的过程,这也是移植中较为困难的部分。由于libreoffice又涉及到npm的本地绑定和apt-get安装到本地目录的问题,所以在函数计算依赖方面本例也是非常经典的场景。无论是编译还是依赖安装,本文中的步骤都强烈地依赖fc-docker镜像,正因为有了该镜像,解决了环境差异问题,大大降低了移植的难度。大文件运行时加载也是函数计算的常见问题,对于转换工具场景中常见的大文件是二进制程序,对于机器学习场景中大文件常是训练模型的数据问题,但是无论是哪一种,采用OSS下载解压的方法都是通用的,随着函数计算支持了NAS,使用NAS挂载共享网盘的方式也是一种新的路径。上文完整的源码可以在FC-LibreOffice的项目中找到。参考阅读https://zh.wikipedia.org/wiki/LibreOffice如何在AWS Lambda中运行LibreOffice以获得大规模的廉价PDFhttps://github.com/alixaxel/chrome-aws-lambdahttps://github.com/shelfio/aws-lambda-brotli-unpacker本文作者:倚贤阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

December 3, 2018 · 3 min · jiezi

深度解读阿里巴巴云原生镜像分发系统 Dragonfly

Dragonfly 是一个由阿里巴巴开源的云原生镜像分发系统,主要解决以 Kubernetes 为核心的分布式应用编排系统的镜像分发难题。随着企业数字化大潮的席卷,行业应用纷纷朝微服务架构演进,并通过云化平台优化业务管理。Dragonfly 源于阿里巴巴,从实际落地场景出发,前瞻性地解决了云原生镜像分发的__效率、流控与安全__三大难题。Dragonfly 目前承载了阿里全集团 90%以上的文件下载任务、日分发峰值达到 1 亿次,100%成功支撑双十一营销活动数据抵达数万台机器,github Star 数已达到 2500+。2018 年 11 月 14 日已正式进入 CNCF,成为 CNCF 沙箱级别项目(Sandbox Level Project)。Dragonfly 的由来随着阿里集团业务爆炸式增长,2015 年时发布系统日均发布量突破两万,很多应用的机器规模开始破万,发布失败率开始增高,而根本原因则是发布过程需要大量的文件拉取,文件服务器扛不住大量的请求,当然第一时间会想到服务器扩容,可是扩容后又发现后端存储成为瓶颈且扩容成本也非常巨大(按照我们的计算,为了满足业务需求,不阻碍业务的发展,后续至少需要 2000 台高配物理机且上不封顶)。此外,大量来自不同 IDC 的客户端请求消耗了巨大的网络带宽,造成网络拥堵。同时,阿里巴巴很多业务走向国际化,大量的应用部署在海外,海外服务器下载要回源国内,浪费了大量的国际带宽,而且还很慢;如果传输大文件,网络环境差,失败的话又得重来一遍,效率极低。于是我们很自然的就想到了 P2P 技术,P2P 技术并不新鲜,当时也调研了很多国内外的系统,但是调研的结论是这些系统的规模和稳定性都无法达到我们的期望,因此就有了Dragonfly这个产品的诞生。Dragonfly 能解决哪些问题作为一款通用文件分发系统,Dragonfly 主要能够解决以下几个方面的问题:大规模下载问题:应用发布过程中需要下载软件包或者镜像文件,如果同时有大量机器需要发布,比如 1000台,按照 500MB 大小的镜像文件计算,如果直接从镜像仓库下载,假设镜像仓库的带宽是 10000Mbps,那么理想状态下至少需要 10 分钟,而且实际情况很可能是仓库早已被打挂。远距离传输问题:针对跨地域跨国际的应用,比如阿里速卖通,它既要在国内部署,又要在美国和俄罗斯部署,而存储软件包的源一般只在一个地域,比如国内上海,那么在美国或者俄罗斯的机器当要下载软件包的时候就要通过国际网络传输,但是国际网络不仅延时高而且极不稳定,严重影响传输效率,进而导致业务不能及时上线新功能或者问题补丁,由此甚至会产生业务故障。带宽成本问题:除了传输效率问题,高昂的带宽成本也是一个非常严重的问题,很多互联网公司尤其是视频相关的公司,带宽成本往往可以占据其总体成本的很大一部分。安全传输问题:据统计,每年因为网络安全问题导致的经济损失高达 4500 亿美元,所以安全必须是第一生命线,文件传输过程中如果不加入任何安全机制,文件内容很容易被嗅探到,假设文件中包含账号或者秘钥之类的数据,一旦被截获,后果将不堪设想。Dragonfly 是如何解决这些问题的通过 P2P 技术解决大规模镜像下载问题,原理如下:针对上图有几个概念需要先解释:PouchContainer:阿里巴巴集团开源的高效、轻量级企业级富容器引擎技术。Registry:容器镜像的存储仓库,每个镜像由多个镜像层组成,而每个镜像层又表现为一个普通文件。Block:当通过Dragonfly下载某层镜像文件时,蜻蜓的SuperNode会把整个文件拆分成一个个的块,SuperNode 中的分块称为种子块,种子块由若干初始客户端下载并迅速在所有客户端之间传播,其中分块大小通过动态计算而来。SuperNode:Dragonfly的服务端,它主要负责种子块的生命周期管理以及构造 P2P 网络并调度客户端互传指定分块。DFget__:__Dragonfly的客户端,安装在每台主机上,主要负责分块的上传与下载以及与容器 Daemon 的命令交互Peer:下载同一个文件的 Host 彼此之间称为 Peer。主要下载过程如下:首先由 Pouch Container 发起 Pull 镜像命令,该命令会被 DFget 代理截获。然后由 DFget 向 SuperNode 发送调度请求。SuperNode 在收到请求后会检查对应的文件是否已经被缓存到本地,如果没有被缓存,则会从 Registry 中下载对应的文件并生成种子块数据(种子块一旦生成就可以立即传播,而并不需要等到 SuperNode 下载完成整个文件后才开始分发),如果已经被缓存,则直接生成分块任务。客户端解析相应的任务并从其他 Peer 或者 SuperNode 中下载分块数据,当某个 Layer 的所有分块下载完成后,一个 Layer 也就下载完毕,此时会传递给容器引擎使用,而当所有的 Layer 下载完成后,整个镜像也就下载完成了。通过上述 P2P 技术,可以彻底解决镜像仓库的带宽瓶颈问题,充分利用各个 Peer 的硬件资源和网络传输能力,达到规模越大传输越快的效果。Dragonfly的系统架构不涉及对容器技术体系的任何改动,完全可以无缝支持容器使其拥有 P2P 镜像分发能力,以大幅提升文件分发效率!结合 CDN 与预热技术解决远距离传输问题通过 CDN 缓存技术,每个客户端可以就近从 SuperNode 中下载种子块,而无需跨地域进行网络传输,CDN 缓存原理大致如下:同一个文件的第一个请求者会触发检查机制,根据请求信息计算出缓存位置,如果缓存不存在,则触发回源同步操作生成种子块;否则向源站发送 HEAD 请求并带上 If-Modified-Since 字段,该字段的值为上次服务器返回的文件最后修改时间,如果响应码为 304,则表示源站中的文件目前还未被修改过,缓存文件是有效的,然后再根据缓存文件的元信息确定文件是否是完整的,如果完整,则缓存完全命中;否则需要通过断点续传方式把剩下的文件分段下载过来,断点续传的前提是源站必须支持分段下载,否则还是要同步整个文件。如果 HEAD 请求的响应码为200,则表示源站文件已被修改过,缓存无效,此时需要进行回源同步操作;如果响应码既不是 304 也不是 200,则表示源站异常或地址无效,下载任务直接失败。通过 CDN 缓存技术可以解决客户端回源下载以及就近下载的问题,但是如果缓存不命中,针对跨域远距离传输的场景,SuperNode 回源同步的效率将会非常低,这会直接影响到整体的分发效率,为了解决该问题,Dragonfly采用了一种自动化层级预热机制来最大程度的提升缓存命中率,其大致原理如下:通过 Push 命令把镜像文件推送到 Registry 的过程中,每推送完一层镜像就会立即触发 SuperNode 以 P2P 方式把该层镜像同步到 SuperNode 本地,通过这种方式,可以充分利用用户执行Push和Pull操作的时间间隙(大概10分钟左右),把镜像的各层文件同步到 SuperNode 中,这样当用户执行 Pull 命令时,就可以直接利用 SuperNode 中的缓存文件,自然而然也就没有远距离传输的问题了。通过动态压缩和智能化调度解决带宽成本问题通过动态压缩,可以在不影响 SuperNode 和 Peer 正常运行的情况下,对文件中最值得压缩的部分实施相应的压缩策略,从而可以节约大量的网络带宽资源,同时还能进一步提升分发速率,相比于传统的 HTTP 原生压缩方式,动态压缩主要有以下几个方面的优势:动态压缩的优势首先自然是动态性,它可以保证只有在 SuperNode 和 Peer 负载正常的情况下才会开启压缩,同时只会对文件中最值得压缩的分块进行压缩且压缩策略也是动态确定的;此外,通过多线程压缩方式可以大幅提升压缩速率,而且借助 SuperNode 的缓存能力,整个下载过程只需要压缩一次即可,压缩收益比相对于 HTTP 原生方式至少提升 10 倍。除了动态压缩外,通过 SuperNode 强大的任务调度能力,可以尽量使在同一个网络设备下的 Peer 互传分块,减少跨网络设备、跨机房的流量,从而进一步降低网络带宽成本。通过加密插件解决安全传输问题在下载某些敏感类文件(比如秘钥文件或者账号数据之类的文件)时,传输的安全性必须要得到有效保障,在这方面,Dragonfly主要做了以下几个方面的工作:支持 HTTP Header 传输,以满足那些需要通过 Header 来进行权限验证的下载请求通过自研的数据存储协议对数据块进行包装传输,后续还会对包装的数据进行再加密即将支持安全加密功能插件化通过多重校验机制,可以严格防止数据被篡改Dragonfly目前的成熟度如何在阿里巴巴集团内部,Dragonfly作为全集团基础技术构件,目前已经承载了全集团 90%以上的文件下载任务,包括镜像文件、应用软件包、算法数据文件、静态资源文件以及索引文件等等,日分发峰值目前可以达到 1 亿次,为集团业务提供了高效稳定的文件分发能力;同时,每年双十一大家买买买的过程中,其中最为关键的营销活动数据(数 GB 大小)也是在将近零点的时候通过Dragonfly来成功(100%成功)抵达数万台机器上的,万一在这个过程中有一点点问题,双十一会如何,你懂的……目前 Dragonfly 也已经开源,在开源社区中, 目前 Star 数 2500+,同时有非常多的外部用户对 Dragonfly 表现出浓厚的兴趣,也有很多外部公司正在使用 Dragonfly 来解决他们在镜像或者文件分发方面遇到的各种问题,比如中国移动、滴滴、科大讯飞等;此外,Dragonfly 已成为全中国第三个进入CNCF Sandbox 级别的项目,后续我们还会继续加油努力,争取尽快毕业!通过以上介绍,我相信针对Dragonfly是否足够成熟,大家心里应该也有杆秤了吧,当然,Dragonfly还有很多事情需要不断完善和改进,在这里诚邀各路人才,一起把Dragonfly打造成一款世界级的产品!未来规则展望成为CNCF毕业项目,为云原生应用提供更加丰富和强大的文件分发能力。开源版与集团内部版融合,给社区开放出更多的高级特性。智能化方面进行更多探索和改进。本文作者:amber涂南阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

November 20, 2018 · 1 min · jiezi