标签 Blogger 下的文章

果果十周岁了!

好久没有在我的博客上写关于果果的事情了,因为很多关于果果成长的经历都记录在她自己的博客中了。但今天是她十周岁的生日,是个值得纪念的日子。闺女成长的十年,也是我学习为人父的十年。作为父亲,我发自内心地想说点啥,是回顾,也是感受,亦有些寄语^_^。

img{512x368}

图:果果成长的十年

出生

老婆在2009年7月怀上了果果。那时我们刚刚新婚不久,二人世界还没过够^_^,小家伙的突然到来还让我们有些“手足无措”。为此,我们还认真地讨论了两天,最终老婆拍板:我要生下这个孩子,于是果果保住了^_^。如今,每当果果提及此事,都会“发狠”地盯上我几眼,我也只能呵呵呵呵地应对^_^。

老婆怀胎中段,我一直在福建出差,虽然有岳母陪在老婆身边,但年底那两个月,老婆心情十分差。直到那一年大年三十的下午2点,我才在桃仙机场下的飞机,匆匆赶回家。大街上连车的打不到,多亏还有公交系统。进入家门,心里满满的都是对老婆的愧疚。记忆中老婆似乎并没有说啥,只说了一句“吃饭吧”,我顿感心里热乎乎的。

果果似乎很享受在妈妈子宫中待着,预产期都过了几天了,她还没有反应,直到2010年5月3日凌晨1点多,规律性的宫缩“来袭”。我们匆忙赶到医院,早上6点半多,老婆进入产室,9点多,我在产室外听到了果果呱呱坠地后的第一声啼哭。

img{512x368}

图:刚出生的果果

果果出生后,恰逢徐峥的作品《人在囧途》上映,影片中徐峥扮演角色的孩子叫果果,我们觉得这个小名不错,于是便给我们宝宝起名为果果

第一次照顾这么小的孩子也着实让我们这些大人手忙脚乱一段时间。出月子后,生活逐渐恢复平稳。果果每天除了吃奶就是睡觉,也算是比较省心了。稍大一些后,果果似乎并不太愿意睡觉了,每次喂完奶都得放到小车上在厅里推过来推过去哄她睡觉,后来果果姥姥买的一个能发出大恐龙吼声的玩具也加入到促进果果睡眠的行列中^_^。

第一次走路(0岁)

果果一直母乳喂养,身体也很壮实。抬头、翻身、学会爬行和其他孩子相比都略有提前。最让我印象深刻是她第一次学会独立行走。记得那是2010年农历春节前,我们家当时的供暖非常好,室温在28度以上。果果在家只穿一套内衣裤,因此行动和玩耍起来非常方便。之前果果就可以扶着床沿踱步了并且她似乎也很喜欢站起来的感觉。那天她自己在卧室的地板上玩耍,我在门口偷偷观察她。她玩了一会儿就开始扶着床站起来,看我站在门口,她居然放开了扶着床沿的双手,向我摇摇晃晃地走了过来。从床边到卧室门口大约有不到2米的距离,我也兴奋地张开双臂,引导她向我走来。她边走边兴奋地笑,似乎也在惊讶于自己能独立行走了。在她扑到我的怀中的那一刻,我才意识到我见证了果果人生第一次独立行走,老婆听到这个消息也是兴奋不已。自从果果学会了走路,此后便一发不可收拾^_^。

打针不哭(1岁)

可能是因为母乳喂养,果果在一岁的这一年中没有患过任何感冒发烧的病症。但当母体带给她的免疫力逐渐失去作用后,果果便和其他小朋友一样,会得感冒,也会发烧。记得果果第一次感冒(刚过一岁生日没多久)就烧的特别厉害。由于我们也是第一次遇到这种情况,特别担心,于是就带她去医院检查。虽然我们期望医生开立口服药,但医生最终还是开了点滴。在护士站门口,果果看到其他孩子扎针时都哇哇的哭,心里也胆怯了。果不其然,当针头穿透她的皮肤进入血管的那一刻,果果也像其他孩子一样,哇哇大哭起来。

有了这次“痛苦”的扎针经历后,我们也对她进行了心理疏导,教她要学会坚强,从她的眼神看得出来,她似乎听懂了。在2011年的秋冬换季,果果又患感冒发烧。同样去了医院,同样开了点滴,但在护士站扎针的时候,果果居然很坚强的忍住了,没有哇哇的哭泣,这让看惯了孩子痛哭的护士也是惊奇不已。看着泪水在眼圈里打转但没有哭出来的果果,我们心里更是心疼她了。

送去幼儿园学说话(2岁)

果果在11个月的时候就会喊妈妈了,但直到2岁半她能吐出的字依然只有“妈妈”,偶尔也有“爸爸”。现在看来,果果说话晚是因为我们给她的语言刺激太少了。果果不愿意睡觉,一旦睡着了,老人生怕声音大吵醒她,于是就命令我们不许出声。久而久之,果果在潜意思中得到的声音刺激、语言刺激照比其他小朋友就要少很多。为此,我们还带着果果去看了生长发育门诊、做过筛查,结果都显示果果没有任何生理性的疾病。

我们需要找到一个让果果接受更多语言刺激的方法,最终我们决定在果果2岁零5个月的时候送她去幼儿园“学说话”。做过家长的都知道,送孩子去幼儿园的过程是“痛苦”的,孩子哭闹,家长心疼,但这个过程是必须要经历的。付出了就有收获。在果果上幼儿园后的一个月,果果的“话匣子”就彻底打开了^_^。

更像女娃了,但怕大海(3岁)

出生时,果果头发稀少,为了让果果长出更好的头发,我们每隔一段时间就把她的头发剃的很短(几近光头)。在2岁之内,果果更像一个“男娃”。直到3岁以后,我们开始给她留头发了。小家伙似乎也知道留头发后自己更好看了,姥姥每次给她梳头扎辫她都很喜欢。留着还有些短的头发让她更像女娃了:

img{512x368}

图:更像女娃的果果

下半年,我们把果果转到了更大的幼儿园,并且果果每天上幼儿园都不再费劲了。她在幼儿园也学到了许多知识、技能和礼节。

3岁的果果的身体显得比同龄的女宝高大一圈,我们也开始带着她到处出行游玩。劳动节黄金周我们第一次带孩子去海边。那天的风浪比较大,浪花拍击礁石的声音震耳欲聋,果果显得很害怕。我们抱着她向海边靠近,但她却一直在挣扎并大喊:“离开、离开、走、走”。当我自己独自向大海靠近时,她也大喊:“爸爸,你回来,你回来”。见此情景,我们都哈哈大笑起来。

后来我们去了一处比较海浪比较舒缓的地带,没有了海浪拍打的巨大轰隆声,果果镇定了许多。也开始站在沙滩上和其他小朋友一起挖起沙子了。

独立爬山(4岁)

4岁的果果不仅个头高,而且壮实了。我们在权衡了之后,决定在假期带她去爬山,并且我已经做好了背她上山的准备。那次我们爬的是千山。千山在整个省内的爬山困难指数排行榜上也是名列前茅的。不过小家伙似乎很喜欢爬山,在登山栈道上显得十分兴奋,我们也给她做心里建设,希望她自己爬到顶峰。虽然在中段她也曾打过退堂鼓,但最终小家伙还是凭借自己的双腿和毅力爬上了山顶,我和老婆也都是非常惊讶。下山过程中,小家伙也是一路欢喜,并没用我们费心。只是由于累了,在回程的车上,小家伙呼呼的睡了一道。

正因为此次爬山的经历,果果爱上了爬山。后续选择旅游景点,她总是先挑那些有山可爬的地方,比如:2019年的陕西的华山骊山等。

和妈妈一起去普吉岛(5岁)

孩子小的时候,出行很麻烦,而且孩子能收获的东西有限。5岁是一个很好的节点,她基本能自立了,而且感知和吸收外界信息的能力已经很强了。

5岁这一年是果果第一次和妈妈出国旅游,此次出行的目的是泰国普吉岛,和她们一起去的还有老婆的同事,这些同事也能帮助老婆照顾照顾果果,顺道还能锻炼一下果果的交际能力。这也是果果第一次乘飞机出行,在机场她十分兴奋。她们的航班在首尔中转,从首尔飞到普吉需要5-6个小时,这下让果果过了一把飞行瘾,她尤其喜欢飞机起降过程中的那种感觉,以至于以后每次出行,她都嚷嚷着要买多次经停或中转的航班^_^。

更难得可贵的是,这次的旅游经历深深印在果果的记忆中,至今每当翻看那时的照片时,她还能头头是道的给我们讲当时发生的故事。有些事情,我老婆都已经记不得了。

上小学了(6岁)

转眼间,果果来到了6周岁,已经到了上学的年龄了。9月份,果果正式成为一名珠江街第五小学一年级的“小豆包”。和第一次上幼儿园不同,这次果果适应的很快,也没有哭鼻子的情况。反倒是回来和我们说她班级有小朋友一直哭,她还很疑惑这些小朋友为什么要哭^_^。

上学后,更多的教育责任“甩”给了班主任老师,我们平时更多是帮忙批改批改作业,督促读读书,带着上上才艺班。果果的古筝是各门才艺课中学的最好的,果果也有了那么一些古典的气质:

img{512x368}

图:有一丝古典气质的果果

这一年我还给果果开了博客。有些东西,光靠脑子是记不住的,写下来,留给多年后的自己和孩子慢慢回味。在果果能自己维护这个博客之前,我就先替她维护了。

叛逆与独立(7~9岁)

进入到7岁以后,果果受到的教育多了,读的书多了,渐渐了有了自己的主见和小脾气,再也不是那个将父母话“奉为圭臬”的小女娃了。如果就某事“辩论”,她姥姥已经完全不是对手了。也只有我和老婆偶尔还能“恩威并举”的降住她:(。

果果喜欢读故事书。她最喜欢读郑渊洁的童话,按照她的说法,市面上郑渊洁的书她基本都读完了,有些书,她已经读过不止一遍了。受郑渊洁风格的影响,她喜欢写幻想类的作文,喜欢天马行空,因此在细节描写上就差了一些。

她还喜欢“米小圈上学记”,每天晚上都是在天猫精灵播放的米小圈上学记中入睡的。

她喜欢宜家买来的老虎和小狗玩偶,一个起名为花果,一个起名为木果,每天一左一右的陪她入睡。

天猫精灵是她每天不可或缺的“伙伴”。早上听新闻早报,天气预报;晚上听故事,听历史,听音乐;偶尔还和天猫精灵玩玩互动猜谜游戏。真不愧为互联网和智能时代的原著民。

8岁的果果,其古筝考级已经通过了10级,这还是在她不是很勤奋练琴的情况下取得的。

这个阶段的果果也十分贪玩,喜欢去游乐场,玩老爸都不敢玩的惊险刺激的项目(只能由她妈妈陪着)。

9岁时,她偶尔和妈妈看了一集“家有儿女”,从那时起就“沉迷”于该剧:只要拿起iPad就必然打开“家有儿女”视频。她看电视剧和她看书的特点一样,如果某一集是她喜欢的,她会反复看上好多遍,丝毫没有不耐烦的迹象。有些集的台词她都能背下来,并粘着我和我老婆要给我们讲。还别说,讲的还头头是道的^_^。

亭亭玉立的大姑娘(10岁)

由于新冠疫情的影响,果果的10岁生日在家里过的,我们也没法带她出去“玩耍”一番。10岁的她已经是一个亭亭玉立的大姑娘了。她的个头快赶上她妈妈了,大长腿,身材是“青出于蓝而胜于蓝”。

img{512x368}

图:十岁的果果

img{512x368}

图:亭亭玉立的果果

这次10周岁的生日除了生日蛋糕,还有一个更为特殊的礼物,那就是妈妈肚里的二宝,这也是果果一直想要的弟弟/妹妹。自从知道妈妈怀了二宝之后,果果变得更加懂事了。每天晚上对着妈妈的肚子给二宝讲故事,晚上睡觉前也会对着妈妈肚子猛“亲”几口^_^。

为了留下美好回忆,我们还特地在果果十周岁生日的时候在影楼留下了一家四口的合影:

img{512x368}

图:十岁果果生日时一家四口合影

小结

果果成长的十年给我的最大感受就是:!一晃间,果果都10岁了,二宝也即将出生。我和老婆也即将步入中年。这里做的这个阶段性的回顾,以期若干年后当记忆模糊时还能通过这篇文章回忆起当年果果小时候的点点滴滴。

这里也希望果果在未来的人生道路中能继续一帆风顺,身体健健康康,每天快快乐乐。

希望果果和即将出生的二宝一起姐妹情深,相濡以沫,共同走好人生之路。

最后,人生在于经历,而不在于得失


我的联系方式:

微博:https://weibo.com/bigwhite20xx
微信公众号:iamtonybai
博客:tonybai.com
github: https://github.com/bigwhite

微信赞赏:
img{512x368}

源创会2017沈阳站讲稿:基于Harbor的高可用企业级私有容器镜像仓库部署实践

上周六开源中国源创会在沈阳举办了一次技术活动,很荣幸以本地讲师的身份和大家交流了一个topic: “基于Harbor的高可用企业级私有容器镜像仓库部署实践”。之所以选择这个topic,是因为这是我们团队的项目实践心得。很多企业和组织在深入使用Docker之后,都会有类似的高可用私有容器仓库搭建的需求,于是我就把我们摸索的实践和填坑过程拿出来,用30分钟与大家分享一下。另外这算是一个入门级的分享,并未深入过多原理。以下就是本次分享的内容讲稿整理。如有不妥或不正确的地方,欢迎交流指正。

img{512x368}

大家下午好,欢迎各位来到源创会沈阳站。在这里我也代表沈阳的IT人欢迎源创会来到沈阳,希望能有更多的像源创会这样的组织到沈阳举办技术活动。非常高兴能有这个机会在源创会这个平台上做分享, 今天和大家一起探讨的题目是:“基于Harbor的高可用企业级私有容器镜像仓库部署实践”。题目有些长,简单来说就是如何搭建一个好用的镜像仓库。

img{512x368}

首先做个简单的自我介绍。我叫白明,东软(注:源创会这次活动的会场在东软沈阳园区)是我的主场,在这里工作很多年,目前就职东软云科技;Gopher一枚,近两年主要使用Go语言开发;技术译者,曾参与翻译过《七周七语言》一书;并且参与过智慧城市架构系列丛书的编著工作;GopherChina大会讲师,这里顺便说一下GopherChina大会,它是目前中国地区规模最大、水平最高的Go语言技术大会,一般每年4月份在北京或上海举行。希望有志于Go语言开发的开发者积极参与;Blogger,写博10多年,依旧笔耕不倦;目前主要从事Docker&kubernetes的研究和实践。

当今,IT技术发展飞快。五年前, IT从业者口中谈论最多的技术是Virtual Machine,即虚拟化技术,人们经常争论的是到底是vmware的技术好,还是原生kvm技术稳定,又或是xen的技术完美。转眼间五年过去了,大家口中经常讨论的技术词汇发生了变化,越来越多的技术人在谈论Docker,谈论容器。

Docker是什么? Docker这门技术非常热,但我们要透过现象看其本质:

Docker技术并不是新技术,而是将已有技术进行了更好的整合和包装

内核容器技术以一种完整形态最早出现在Sun公司Solaris操作系统上,Solaris是当时最先进的服务器操作系统。2005年Solaris发布Solaris Container技术,从此开启了内核容器之门。

IT技术发展的趋势就是这样:商业有的,开源也要有。三年后,即2008年,以Google公司开发人员为主导的Linux Container,LXC功能在被merge到Linux内核。LXC是一种内核级虚拟化技术,主要基于namespacescgroup技术,实现共享一个os kernel前提下的进程资源隔离,为进程提供独立的虚拟执行环境,这样的一个虚拟的执行环境就是一个容器。本质上说,LXC容器与现在的Docker所提供容器是一样的。但是,当时LXC处于早期阶段,开发人员可能更为关注LXC的技术实现,而对开发体验方面有所忽略,导致LXC技术使用门槛较高,普通应用开发者学习、理解和使用它的心智负担较高,因此应用并不广泛。

这一情况一直持续到2013年,当时美国一家名不见经传的公司dotCloud发布了一款平台工具Docker,对外宣称可以实现:“build,ship and run any app and anywhere”。Docker实质上也是基于namespaces和cgroup技术的,Docker的创新之处在于其基于union fs技术定义了一套应用打包规范,真正将应用及其运行的所有依赖都封装到一个特定格式的文件中,这种文件就被称为image,即镜像文件。同时,Docker还提供了一套抽象层次更高的工具集,这套工具对dev十分友好,具有良好的开发体验(Developer eXperience),开发者无需关心namespace, cgroups之类底层技术,即可很easy的启动一个承载着其应用的容器:

Docker run ubuntu echo hello

因此, 从2013发布以来,Docker项目就像坐上了火箭,发展迅猛,目前已经是github上最火爆的开源项目之一。这里还要提一点就是:Docker项目是使用go语言开发的,Docker项目的成功,也或多或少得益于Go优异的开发效率和执行效率。

Docker技术的出现究竟给我们带来了哪些好处呢,个人觉得至少有以下三点:

  • 交付标准化:Docker使得应用程序和依赖的运行环境真正绑定结合为一体,得之即用。这让开发人员、测试和运维实现了围绕同一交付物,保持开发交付上下文同步的能力,即“test what you write, ship what you test”;
  • 执行高效化:应用的启动速度从原先虚拟机的分钟级缩短到容器的秒级甚至ms级,使得应用可以支持快速scaling伸缩;
  • 资源集约化:与vm不同的是,Container共享一个内核,这使得一个container的资源消耗仅为进程级别或进程组级别。同时,容器的镜像也因为如此,其size可以实现的很小,最小可能不足1k,平均几十M。与vm动辄几百兆的庞大身段相比,具有较大优势。

有了image文件后,自然而言我们就有了对image进行存取和管理的需求,即我们需要一个镜像仓库,于是Docker推出了Docker registry这个项目。Docker Registry就是Docker image的仓库,用来存储、管理和分发image的;Docker registry由Docker公司实现,项目名为distribution,其实现了Docker Registr 2.0协议,与早前的Registry 1.x协议版本相比,Distribution采用Go语言替换了Python,在安全性和性能方面都有了大幅提升;Docker官方运行着一个世界最大的公共镜像仓库:hub.docker.com,最常用的image都在hub上,比如反向代理nginx、redis、ubuntu等。鉴于国内访问hub网速不佳,多使用国内容器服务厂商提供的加速器。Docker官方还将Registry本身打入到了一个image中,方便开发人员快速以容器形式启动一个Registry:

docker run -d -p 5000:5000 --restart=always --name registry registry:2

不过,这样启动的Registry更多仅仅是一个Demo级别或满足个体开发者自身需要的,离满足企业内部开发流程或生产需求还差了许多。

既然Docker官方运行着免费的镜像仓库,那我们还需要自己搭建吗?实际情况是,对Docker的使用越深入,对私有仓库的需求可能就越迫切。我们先来看一组Docker 2016官方的调查数据,看看Docker都应用在哪些场合。 从Docker 2016官方调查来看,Docker 更多用于dev、ciDevOps等环节,这三个场合下的应用占据了半壁江山。而相比于公共仓库,私有镜像仓库能更好的满足开发人员在这些场合对镜像仓库的需求。理由至少有四点:

  • 便于集成到内部CI/Cd
    以我司内部为例,由于公司内部办公需要使用正向代理访问外部网络,要想将Public Registry集成到你的内部CI中,技术上就会有很多坎儿,整个搭建过程可能是非常痛苦的;

  • 对镜像可以更全面掌控
    一般来说,外部Public Registry提供的管理功能相对单一,往往无法满足企业内部的开发和交付需求;

  • 内部网络,网络传输性能更好
    内部开发运维流水线很多环节是有一定的时间敏感性的,比如:一次CI如果因为network问题导致image pull总是timeout,会让dev非常闹心,甚至影响整体的开发和交付效率。

  • 出于安全考虑
    总是有企业不想将自己开发的软件或数据放到公网上,因此在企业内部选择搭建一个private registry更会让这些企业得到满足;另外企业对仓库的身份验证可能还有LDAP支持的需求,这是外部registry无法满足的。

一旦企业决定搭建自己的private仓库,那么就得做一个private仓库的技术选型。商业版不在我们讨论范围内,我们从开源软件中挑选。不过开源的可选的不多,Docker 官方的Registry更聚焦通用功能,没有针对企业客户需求定制,开源领域我们大致有两个主要候选者:SUSEPortus和Vmware的Harbor。针对开源项目的技术选型,我个人的挑选原则最简单的就是看社区生态,落实到具体的指标上包括:

  • 项目关注度(即star数量)
  • 社区对issue的反馈数量和积极性
  • 项目维护者对issue fix的积极程度以及是否有远大的roadmap

对比后,我发现在这三个指标上,目前Harbor都暂时领先portus一段距离,于是我们选择Harbor。

Harbor是VMware中国团队开源的企业级镜像仓库项目,聚焦镜像仓库的企业级需求,这里从其官网摘录一些特性,大家一起来看一下:

– 支持基于角色的访问控制RBAC;
– 支持镜像复制策略(PUSH);
– 支持无用镜像数据的自动回收和删除; – 支持LDAP/AD认证;
– Web UI;
– 提供审计日志功能;
– 提供RESTful API,便于扩展;
– 支持中文&部署Easy。

不过,Harbor默认安装的是单实例仓库,并非是高可用的。对于接纳和使用Docker的企业来说,镜像仓库已经企业内部开发、交付和运维流水线的核心,一旦仓库停掉,流水线将被迫暂停,对开发交付的效率会产生重要影响;对于一些中大型企业组织,单实例的仓库性能也无法满足需求,为此高可用的Harbor势在必行。在设计Harbor HA方案之前,我们简单了解一下Harbor组成架构。

一个Harbor实例就是一组由docker-compose工具启动的容器服务,主要包括四个主要组件:

  • proxy
    实质就是一个反向代理nginx,负责流量路由分担到ui和registry上;

  • registry
    这里的registry就是原生的docker官方的registry镜像仓库,Harbor在内部内置了一个仓库,所有仓库的核心功能均是由registry完成的;

  • core service
    包含了ui、token和webhook服务;

  • job service
    主要用于镜像复制供。

同时,每个Harbor实例还启动了一个MySQL数据库容器,用于保存自身的配置和镜像管理相关的关系数据。

高可用系统一般考虑三方面:计算高可用、存储高可用和网络高可用。在这里我们不考虑网络高可用。基于Harbor的高可用仓库方案,这里列出两个。

img{512x368}

两个方案的共同点是计算高可用,都是通过lb实现的多主热运行,保证无单点;存储高可用则各有各的方案。一个使用了分布式共享存储,数据可靠性由共享存储provider提供;另外一个则需要harbor自身逻辑参与,通过镜像相互复制的方式保持数据的多副本。

两种方案各有优缺点,就看哪种更适合你的组织以及你手里的资源是否能满足方案的搭建要求。

方案1是Harbor开发团队推荐的标准方案,由于基于分布式共享存储,因此其scaling非常好;同样,由于多Harbor实例共享存储,因此可以保持数据是实时一致的。方案1的不足也是很明显的,第一:门槛高,需要具备共享存储provider;第二搭建难度要高于第二个基于镜像复制的方案。

方案2的优点就是首次搭建简单。不足也很多:scaling差,甚至是不能,一旦有三个或三个以上节点,可能就会出现“环形复制”;镜像复制需要时间,因此存在多节点上数据周期性不一致的情况;Harbor的镜像复制规则以Project为单位配置,因此一旦新增Project,需要在每个节点上手工维护复制规则,非常繁琐。因此,我们选择方案1。

我们来看一下方案1的细节: 这是一幅示意图。

  • 每个安放harbor实例的node都mount cephfs。ceph是目前最流行的分布式共享存储方案之一;
  • 每个node上的harbor实例(包含组件:ui、registry等)都volume mount node上的cephfs mount路径;
  • 通过Load Balance将request流量负载到各个harbor实例上;
  • 使用外部MySQL cluster替代每个Harbor实例内部自维护的那个MySQL容器;对于MySQL cluster,可以使用mysql galera cluster或MySQL5.7以上版本自带的Group Replication (MGR) 集群。
  • 通过外部Redis实现访问Harbor ui的session共享,这个功能是Harbor UI底层MVC框架-beego提供的。

接下来,我们就来看具体的部署步骤和细节。

环境和先决条件:

  • 三台VM(Ubuntu 16.04及以上版本);
  • CephFS、MySQL、Redis已就绪;
  • Harbor v1.1.0及以上版本;
  • 一个域名:hub.tonybai.com:8070。我们通过该域名和服务端口访问Harbor,我们可以通过dns解析多ip轮询实现最简单的Load balance,虽然不完美。

第一步:挂载cephfs

每个安装Harbor instance的节点都要mount cephfs的相关路径,步骤包括:

#安装cephfs内核驱动
apt install ceph-fs-common

# 修改/etc/fstab,添加挂载指令,保证节点重启依旧可以自动挂载cephfs
xx.xx.xx.xx:6789:/apps/harbor /mnt/cephfs/harbor ceph name=harbor,secretfile=/etc/ceph/a dmin.secret,noatime,_netdev 0 2

这里涉及一个密钥文件admin.secret,这个secret文件可以在ceph集群机器上使用ceph auth tool生成。

img{512x368}

前面提到过每个Harbor实例都是一组容器服务,这组容器启动所需的配置文件是在Harbor正式启动前由prepare脚本生成的,Prepare脚本生成过程的输入包括:harbor.cfg、docker-compose.yml和common/templates下的配置模板文件。这也是部署高可用Harbor的核心步骤,我们逐一来看。

第二步:修改harbor.cfg

我们使用域名访问Harbor,因此我们需要修改hostname配置项。注意如果要用域名访问,这里一定填写域名,否则如果这里使用的是Harbor node的IP,那么在后续会存在client端和server端仓库地址不一致的情况;

custom_crt=false 关闭 crt生成功能。注意:三个node关闭其中两个,留一个生成一套数字证书和私钥。

第三步:修改docker-compose.yml

docker-compose.yml是docker-compose工具标准配置文件,用于配置docker-compose即将启动的容器服务。针对该配置文件,我们主要做三点修改:

  • 修改volumes路径
    由/data/xxx 改为:/mnt/cephfs/harbor/data/xxx
  • 由于使用外部Mysql,因此需要删除mysql service以及其他 service对mysql service的依赖 (depends_on)
  • 修改对proxy外服务端口 ports: 8070:80

第四步:配置访问external mysql和redis

external mysql的配置在common/templates/adminserver/env中,我们用external Mysql的访问方式覆盖下面四项配置:

MYSQL_HOST=harbor_host
MYSQL_PORT=3306
MYSQL_USR=harbor
MYSQL_PWD=harbor_password

还有一个关键配置,那就是将RESET由false改为true。只有改为true,adminserver启动时,才能读取更新后的配置

RESET=true

Redis连接的配置在common/templates/ui/env中,我们需要新增一行:

_REDIS_URL=redis_ip:6379,100,password,0

第五步:prepare并启动harbor

执行prepare脚本生成harbor各容器服务的配置;在每个Harbor node上通过下面命令启动harbor实例:

docker-compose up -d

启动后,可以通过docker-compose ps命令查看harbor实例中各容器的启动状态。如果启动顺利,都是”Up”状态,那么我们可以在浏览器里输入:http://hub.tonybai.com:8070,不出意外的话,我们就可以看到Harbor ui的登录页面了。

至此,我们的高可用Harbor cluster搭建过程就告一段落了。

Troubleshooting

不过,对Harbor的认知还未结束,我们在后续使用Harbor的过程中遇到了一些问题,这里举两个例子。

问题1: docker login hub.tonybai.com:8070 failed

现象日志:

Error response from daemon: Get https://hub.tonybai.com:8070/v1/users/: http: server gave HTTP response to HTTPS client

通过错误日志分析应该是docker daemon与镜像仓库所用协议不一致导致。docker engine默认采用https协议访问仓库,但之前我们搭建的Harbor采用的是http协议提供服务,两者不一致。

解决方法有两种,这里列出第一种:让docker引擎通过http方式访问harbor仓库:

在/etc/docker/daemon.json中添加insecure-registry:

{
    "insecure-registries": ["hub.tonybai.com:8070"]
}

重启docker service生效

第二种方法就是让Harbor支持https,需要为harbor的proxy配置私钥和证书,位置:harbor.cfg中

#The path of cert and key files for nginx, they are applied only the protocol is set to https
ssl_cert = /data/cert/server.crt
ssl_cert_key = /data/cert/server.key

这里就不细说了。

问题2:docker login hub.tonybai.com:8070 有时成功,有时failed

现象日志:

第一次登录成功:
# docker login -u user -p passwd http://hub.tonybai.com:8070 Login Succeeded

第二次登录失败:
# docker login -u user -p passwd http://hub.tonybai.com:8070
Error response from daemon: login attempt to http://hub.tonybai.com:8070/v2/ failed with status: 401 Unauthorized

这个问题的原因在于对docker registry v2协议登录过程理解不够透彻。docker registry v2是一个两阶段登录的过程:

  • 首先:docker client会到registry去尝试登录,registry发现request中没有携带token,则返回失败应答401,并告诉客户端到哪里去获取token;
  • 客户端收到应答后,获取应答中携带的token service地址,然后到harbor的core services中的token service那里获取token(使用user, password进行校验)。一旦token service校验ok,则会使用private_key.pem生成一个token;
  • 客户端拿到token后,再次到registry那里去登录,这次registry用root.crt去校验客户端携带的token,校验通过,则login成功。

由于我们是一个harbor cluster,如果docker client访问的token service和registry是在一个harbor实例中的,那么login就会ok;否则docker client就会用harbor node1上token service生成的token到harbor node2上的registry去登录,由于harbor node2上root.crt与harbor node1上private_key.pem并非一对,因此登录失败

解决方法:将所有节点上使用同一套root.crt和private_key.pem。即将一个harbor node(harbor.cfg中custom_crt=true的那个)上的 common/config/ui/private_key.pem和 common/config/registry/root.crt复制到其他harbor node;然后重建各harbor实例中的容器。

至此,我们的高可用Harbor仓库部署完了。针对上面的配置过程,我还做了几个录屏文件,由于时间关系,这里不能播放了,大家可以在下面这个连接下载并自行播放收看。

Harbor install 录屏: https://pan.baidu.com/s/1o8JYKEe

谢谢大家!

讲稿slide可以在这里获取到。

微博:@tonybai_cn
微信公众号:iamtonybai
github.com: https://github.com/bigwhite

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats