• 本文又名论没钱且懒的选手如何一点一点艰难的的死蹭资源
  • Kubernetes的知识部分为参考官网文档结合自己理解所写,发现错误请指正

OpenShift

前言

  • 使用OpenShift的starter tier,即免费版。自行注册账号、创建项目等,最后打开web console来到管理界面
  • 这里提醒一下,注册完要尽快创建项目开始使用集群,不然预分配的空间会被回收,下一次再来用要重新申请分配,会等很久(我等了好几天)
  • 整体上看项目基于Kubernetes搭建集群环境,Kubernetes又是Docker的集群编排工具,是以容器为中心的基础架构,所以我们可以看到Kubernetes的各种名词如Deployment、Pod,也能看到Docker相关的Persistent Volume等名词

Deployment

  • 字面含义,一个“部署实体”,可以粗浅的认为是一个配置结构,决定一定数量的Pod的结构,引用官网原文↓

Deployment为Pod和Replica Set提供声明式更新。你只需要在 Deployment 中描述您想要的目标状态是什么,Deployment controller 就会帮您将 Pod 和ReplicaSet 的实际状态改变到您的目标状态。

  • 通过后文提及的配置流程也可以看出作为运行实例的Pod的环境变量、存储挂载等运行配置参数都在Deployment控制面板中完成

  • 根据以下文档原文以及几种结构实体之间的关系,可以理解诸如手动删除Pod(错误行为)、修改Deployment引发Pod自动升级等现象的本质。在后文的操作环境下默认一个Deployment应该是对应至少一个Pod的,因此删除Pod集群会自动补上一个相同的Pod

您不该手动管理由 Deployment 创建的 Replica Set,否则您就篡越了 Deployment controller 的职责!

graph LR
A(Deployment) --> |创建|B(ReplicaSet)
B --> |在后台创建|C(Pod)
C --> D(容器/其他Runtime)
C --> E(容器/其他Runtime)
C --> F(容器/其他Runtime)
  • 同样是参照以下文档说明,可以看到在即使重新Deploy失败,集群也不会瘫痪,可以直接选择取消操作自动回滚

如果当前状态不稳定,回滚到之前的Deployment revision。每次回滚都会更新

  • 理论上对Deployment的修改会发出rollout,这不一定是我们期望的,例如下文会提到的替换存储卷和修改环境变量等都会引发不必要的rollout,因此需要暂停整个Deployment再恢复

您可以在发出一次或多次更新前暂停一个 Deployment,然后再恢复它。这样您就能多次暂停和恢复 Deployment,在此期间进行一些修复工作,而不会发出不必要的 rollout。

Paused和没有paused的Deployment之间的唯一区别就是,所有对paused deployment中的PodTemplateSpec的修改都不会触发新的rollout。Deployment被创建之后默认是非paused。

Pod

  • Kubernetes对象模型中可部署的最小对象,基本单位,一个Pod代表集群上正在运行的一个进程,Pod封装一个或多个容器。

Docker是Kubernetes Pod中最常见的runtime ,Pods也支持其他容器runtimes。

  • 如果需要水平扩展应用(例如,运行多个实例),则应该使用多个Pods,每个实例一个Pod。在Kubernetes中,这样通常称为Replication。

  • 每个Pod被分配一个独立的IP地址,Pod中的每个容器共享网络命名空间,包括IP地址和网络端口。Pod内的容器可以使用localhost相互通信。当Pod中的容器与Pod 外部通信时,他们必须协调如何使用共享网络资源(如端口)。

  • 重启Pod中的容器跟重启Pod不是一回事。Pod只提供容器的运行环境保持容器的运行状态,重启容器不会造成Pod重启。

  • Pod提供两种资源:网络存储

Persistent Volume

  • 持久化卷
  • 字面意义,Docker默认情况下数据在容器中产生,而容器删除后内容也会一并丢失,因此有必要将数据提取出来
  • Docker本身有两种存储卷操作方式,一种是绑定挂载存储卷,另一种是管理存储卷
  • 绑定挂载存储卷直接使用用户提供的主机目录或文件(--volume A:B),管理存储卷的Cassandra和Progres示例如下
$ docker run -d \
--volume /var/lib/cassandra/data \
--name cass-shared \
alpine echo Data Container

$ docker run -d \
--volume-from cass-shared\
--name cass1 \
cassandra:2.2
graph LR
A[CQLSH] --> B[cass1]
C[CQLSH] --> D[cass2]
B --> |从cass-shared<br>复制存储卷的定义|E[cass-shared]
D --> |将存储卷的定义复制<br>到新的Cassandra|E
E --> F(存储卷<br>/var/lib/cassandra/data)
B -.-> F
D -.-> F
$ docker create -v /dbdata --name dbstore training/postgres /bin/true

$ docker run -d --volumes-from dbstore --name db1 training/postgres
  • 上面这部分解释说明其实跟本文关系不大,我们此处知道是把数据持久化需要的部分就行

部署APP

过程

部署之前先在Storage面板中创建好Persistent Volume Claim,配置保持默认,读写模式注意一定要设置为Read-Write-Once,创建好后信息大概如下↓

持久化存储卷

使用Ghost现成的Docker镜像部署,web console界面点击右上角Add To ProjectDeploy Image

Deploy Image

Image Name模式,输入ghost,点击搜索键,没有特殊要求全部保持默认设置

Default

部署完成后在Overview界面展开详细,可以看到表示正常的蓝色状态Pod

Pod Deploy

在下方Networking右边点击Create Route,设置保持默认,创建成功后可以看到你公开的路径,复制下来等会有用。此时点开路径,可以看到博客的默认界面

Route

点击到边栏Applications的的Deployments,点击刚才的部署,进入Environment内,添加环境变量url,值为刚才的完整路径,如:

Name:url
Value:http://iron-rhine.1d35.starter-us-east-1.openshiftapps.com

点击保存后会自动开始Deploy,等Overview界面板中的Pod恢复蓝色,再次回到刚才Applications的的Deployments内,先点击右上角如图的Pause Rollouts,暂停Pod的活动,看到相应的暂停提示后切换到Configuration界面

Pause Rollouts

在Volumes处选择Remove,移除掉默认分配的存储卷,再点击Add Storage,默认选中了刚才创建的存储卷,Mount Path设置为/var/lib/ghost/content。Add完成后回到原本界面解除Pause Rollouts,会自动重新Deploy

Deploy完成之后基本设置就完成了,即使删除Pod或Deployment博客内容也不会丢失。接下来就可以愉快的注册写博客了!

注意

  • Ghost博客这个项目比较大,初次编译会有点久,有时候管理界面显示pod准备好了但项目可能还没准备好,耐心等一会再重启,或者看看日志显示,一两次超时很正常

  • 替换了存储卷后绝对不能直接修改配置, 默认设置下只要config有所变化就会自动重新Deploy,所以若要修改配置,在修改配置前一定要选择Pause Rollouts

  • 替换了存储卷后也绝对不能直接Deploy如果单纯想重启可以直接删除pod,默认设置下会自动生成新的pod。也可以删除Deployment重新部署,最后再接回存储卷,总之不能在有一个Deployment存在的情况下执行Deploy

  • 如果觉得存储卷设置麻烦,也可以使用Ghost后台自带的导出导入文章机制,重启前将使用主题下载备份好等等,没有试过不细说了

部分原理说明

  • 关于直接Deploy一个新版本会失败这一点,个人认为是存储卷读写模式的原因。

  • 通过上面的配置可以确认存储卷只允许一个读写(Access Modes:RWO (Read-Write-Once)),而重新Deploy的过程应该是先创建一个新的Deployment再删除原本的Deployment,在这个过程中由于单一读写的原因,存储卷会挂载失败,因此直接重新Deploy一定会失败


why not

heroku

原本计划了一个完美的操作,用heroku自带的免费数据库Postgre,结合七牛云10G存储,博客挂起来稳稳的

然而第一次部署的Ghost是0.x版的,现在的1.x版已经去掉了Postgre支持(天打雷劈五雷轰顶我的内心几乎是崩溃的),只能MySQL,而heroku的MySQL免费但容量极小,据说只有5M,而且一定要填写信用卡信息……

遂放弃。【难过

hasura

hasura部署起来也很方便,而且自带的存储为2G,最重要的是实现了全自动的HTTPS,但遗憾的是目前免费版暂时不支持持久化存储……(PS对方开发表示文档还没写完,写完了发你一份诶嘿。我:……)

虽然免费版也不提供custom domain,但对方开发表示可以给个优惠,emmmmmmm再深入考虑下……

还没放弃.jpg

CloudFlare

自定义域名(复杂)

为何如此复杂

首先我们按照常规的两种思路:

  • 解析出地址指向的IP,直接添加一条A记录指向同样IP
  • 一条CNAME记录解析

两种方案差不多,然而都不行,因为OpenShift的start tier禁止自定义域名解析设置

换个思路,举例,在腾讯云域名解析台可以看到隐式URL这一选项
隐式URL

然而隐式转发需要备案,太麻烦,目前买的域名都没有备案emmmm……

NameServer替换

首先按惯例注册CloudFlare账号,信息随便填填,我们还是使用免费计划

Add Site添加你想要使用的域名,按照要求到你购买域名的服务商处修改NameServer为CloudFlare提供的

举例如我在腾讯云购买的,参考相关文档自行修改

在Overview中显示如下说明设置已经生效

Active

较搓的操作

只能说是无奈之举,因为CloudFlare也不支持隐式URL一类的操作,所以目前选择是先redirect过去,到域名控制台打开Page Rules设置

Page Rules

添加一条新规则,分别填入你的自定义域名和刚才建好的博客的地址

Rule

保存后要稍等一会才能看到结果(据说有人等了几小时,我只等了几分钟就看到了……)

看起来比较酷炫的操作(复杂)

只是个个人的思路,没有实践过,仅供参考,架构大致如图

graph TD
A(访问) --> |HTTPS|B(CloudFlare)
B --> |HTTP or HTTPS|C(Proxy)
C --> |HTTP|D(OpenShift<br>GhostBlog)
C --> E(Other Site...)

这里的关键是需要一个代理服务器,满足以下要求

  • 支持自定义域名
  • 对外暴露出代理访问接口
  • 如果是基于Docker部署,要支持各种自定义启动参数等(自定义转发规则文件替换)

支持自定义域名是为了HTTPS加密,CloudFlare上的HTTPS设置只能针对自己的域名,别的如OpenShift的地址智能301跳转过去,不能加密也不能在隐式跳转

如果不在自己服务器上建,还是考虑云的话,最好能一键部署,如Docker Nginx、打包好的Heroku Template工程等。

不过Heroku自定义域名也需要绑定信用卡,目前暂时找不到满足所有条件的免费平台,只好先搁置了╮(╯▽╰)╭


HTTPS加密Hexo博客

CloudFlare提供了免费HTTPS,不加白不加,顺手给加上

理论上在将域名服务器设置为CloudFlare提供的之后,你就可以对你这个域名下的所有站点、子域名等为所欲为了!

理论上Let‘s Encrypt也可以免费提供HTTPS证书,但需要在域名指向的主机上自己操作验证,而且90天证书过期后得自己更新,CloudFlare能提供一劳永逸操作当然是极好的

原理(注意)

这里强调下,CloudFlare默认的这波操作严格来说其实并不算真正的加密。如下图,在我们默认没有自签名证书的情况下,加密的只是从访问开始到CloudFlare的部分,CloudFlare访问你的站点还是明文的

路径

某种意义上说相当于我们信赖CloudFlare的访问,将数据访问安全部分的托管给他们,所以理论上如果他们遭到了攻击那我们的数据就……

那还能怎么办,当然是选择原谅他啊

操作

我的hexo博客布置在blog.domain,因此简单的到Page Rules处添加两条规则

rule1

rule2

再打开Hexo博客全站都是强制HTTPS打开的啦


后记

碎碎念

  • OpenShift集群部署是基于Kubernetes的,很早以前就说过想学k8s,结果一直没动手,拖到现在连Deployment和Pod都分不清,一通乱搞,反复了很多无用操作

  • Docker也没学扎实,反复操作把脑子搞爆炸后,一时竟然连Docker持久卷挂上去时内覆盖外还是外覆盖内都不记得了。。。(Host机的目录会覆盖挂载的容器内的目录)

  • 需求还是要明确,过程还是要想清楚。比如我的博客现在没有内容,不需要备份(如果需要备份的话就得在自己主机上安装oc命令行工具,NFS挂载,再同步回去,具体见这里或官方文档。而这一系列操作需要管理员权限,管理员权限操作起来就麻烦了。。。),但部署好了后要确保数据不会随着Docker重启而消失

  • 英文水平还是不行,很多操作用英文Google还是不太抓得住关键,比如Docker持久卷这波就该直接搜persistence volume,想了半天居然想到个Durability。。。

  • 本来在骂OpenShift不提供custom domain,后来发现heroku也不提供,再后来发现hasura也不提供,嗯……果然custom domain是标准的付费服务吗


参考


Written with StackEdit.