说实话,Rancher的官方文档真的很全,围绕着UI的方方面面都面面俱到。但看多了却发现,不少东西都浅尝辄止,尤为某个东西实在不懂的时候,看文档只能让本身更没头绪。因此此文的目的是方便本身可以在须要的时候回忆出点点滴滴。html
Rancher1.6的傻瓜式操做给了我很大的帮助,也帮我赢得了大部分运维的支持,最终得以施展。但Rancher2.0不管是开发版仍是beta版,都并非那么友好,老是莫名其妙的出现各类各样的问题。后来由于工做的调动,没有继续研究新版。不过如今终于有时间了,当前最新版本2.1.4,因此此文的基础也就是2.1.4。前端
另外,本文不会花篇幅去介绍如何安装或者解决安装中的问题,但涉及到的,我都会附上连接。本文主要的做用一个是备忘,还一个是手册。若是之后回头看这篇文章,发现忘了的看一遍就回忆起来了,照着作一遍的环境就搭好了那就完美了。node
有必要在这里提早声明一下先决条件(并非说实际上就是这个数据,而是个人环境是这个数据)。从Rancher1.6开始到如今的2.1.4,每个版本都用过。不一样的版本对先决条件敏感,如1.6是敏感度最迟钝的,只要保证OS内核3.1.10以上(含)便可。至于Docker版本,在查阅Rancher文档的时候,不少地方明确指出最高支持版本17.02,但实际使用过程当中,只要是最新版本的均可以。如下是具体的环境说明:mysql
物理机OS:Ubuntu 18.04linux
Docker:18.09nginx
harbor:1.7.1git
Gitlab:10.4.4sql
从零开始,现有三台物理机,两台服务器,一台笔记本,服务器上只跑一个虚拟机实例,笔记本跑两个虚拟机实例。但须要注意的是:若是须要拷贝虚拟机,必须是同物理机上的拷贝,而不能夸物理机拷贝,哪怕用了什么ovf虚拟机格式,也都不行,由于在实际使用的时候会出现一些莫名的错误,也可能不出,全靠运气。如下是主要步骤(可直接点击穿越到教程,教程来源于网络):docker
一、更新源(apt-get update && apt-get upgrade)数据库
二、修改vi命令(默认vi命令不友好)
四、设置limit
五、安装docker
六、配置加速器(加速器可用daoclould也可用阿里的,这里贴出的是daoclould的)
七、设置机器域名host指向(若是是直接使用IP访问的话,跳过这个)
8.一、安装rancher
sudo docker run -d --restart=unless-stopped -p 80:80 -p 443:443 rancher/rancher
8.二、安装harbor
九、登陆Rancher建立集群导入机器
十、全部机器harbor登陆受权(若是不须要本身手动pull私服上的镜像,此步跳过)
额外须要注意的是:
一、最新版本的docker默认采用https方式拉取镜像(确切的说是自1.3.2版本开始),若是使用http,那就须要在机器上添加过滤,详情点击。
二、自受权的https证书,须要在机器上信任,信任方式点此。
三、Rancher内部是k8s,k8s集群中,不会读取宿主机的证书。故在宿主机配置了证书信任,不会渗透到k8s集群。也就是说在宿主机信任证书,对于k8s来讲,没有任何影响。这个产生一个很大问题,就是在Rancher里配置了镜像库后,Rancher没法登录到镜像库,缘由就是CA证书不被信任。这直接致使私有镜像私服被废了,除非公司花钱买证书,或者使用如阿里云镜像私服这样第三方服务。阿里云地址点此。
这一部分是说明1.6和2.0两部分,Rancher的概念,目的是着重理解Rancher。
前段时间看了本书叫《码农翻身:用故事给技术加点料》,这个思路很清奇,久久不能忘。遂本章也用说故事的方式来阐明概念。
小明的志向是当一个农场主。虽然他历来没干过,可是他如今准备干了。
因而他买了一块地,首先他用栅栏围了起来,防止牛羊越狱,同时也防止可恶的豺狼豹子偷猎牛羊。而后小明对圈内的地进行的划分,A区域B区域……,这样能够方便管理。每一个区域他又建了不少棚舍,不过棚舍之间是互通的,这样牛羊就不会寂寞,能够串串门。
万事俱备只差牛羊,小明考虑直接去牛羊中心,路途遥远,倒不如去最近的代理商,代理商就像超市,把牛羊从厂家运送过来,这样省时又省力。为了保险起见,小明只买了几百只牛羊,而后赶到本身规划好的农场。
其实小明的工做很简单,定时检查一下牛羊的状态,是否是饿了渴了或者生病了又或者死亡了,不过若是牛羊死亡了,小明就必须再买一头回来。有时候小明还会给牛羊作个造型美化一下,小明说这叫升级,固然若是美化失败了,小明还会恢复原样,小明又叫这个回滚。
小明很满意本身的农场,但以为一我的有点无聊,因而他又创建了一个站台,站在站台上能够看到某个区域的每一个棚舍,就像动物园同样。而后开放给你们,不只能赚点外快,还不会以为无聊。
今后,小明过上了幸福的农场主生活,实现了人生理想。
故事到此结束,如今解释一下文中的概念:
一、小明:rancher的master节点
二、栅栏:rancher集群
三、区域:集群
四、棚舍:项目
五、牛羊:容器
六、牛羊中心:docker hub镜像中心
七、代理商:国内镜像如阿里云
八、升级:镜像升级
九、回滚:镜像回滚
十、站台:负载均衡(HA)
十一、小明的工做:cattle编排引擎
小明的幸福没过多久,就出现问题了。第一,小明天天不只要进行繁琐的工做,还要接待到访的游客,忙得团团转。第2、牧场过小了,访客太多了,每次都有人抱怨等待的时间过久了。小明痛定思痛决定要改善这两个问题,好在经营了一段时间,手里攒了很多积蓄。
首先,他扩大了牧场,区域划分保持不变,之前一个大棚舍,如今建好几个大棚舍,但棚舍里作好规划,不一样棚舍养不一样的牛羊,同时棚舍之间是独立的,防止牛羊乱窜,但同样的同一个棚舍仍是不由止的。另外,大棚舍里的小棚舍,也得改造,每次游客来都反应脏乱差。因此,给每一头牛羊创建单独的房间,再装饰的很是精美,除此以外,每一个房间还会配备专人管理,最后起个洋气的名字,叫pod。
而后,雇佣一大批的人,把小明之前的工做都细化分工下去,好比待在pod里,负责牛羊的管理,好比升级和回滚。而后每一个大棚舍自治,牛羊的采购、参观等等独立化,这样管理起来更方便,同时若是一个大棚舍出现问题,也不会影响到别的大棚舍。
接着站台也要优化一下,之前是固定的几个站台,你们都按序排队。如今不用那么麻烦了,由于大棚舍自治了,每一个大棚舍单独售票,因此只须要安排几个迎宾,游客来了,问一下去哪一个大棚舍,而后直接带过去就好了,大大减小了访客的等待时间。
最后,因为规模相比以前不可同日而语,各个流程小明没法手动管理,因而小明又规划了一个叫流程的东西,想要干什么东西话,只须要按照流程走就对了。
至此,全部问题都解决了,而且小明也解放了,天天只须要巡视工做就成了,小日子过得不要不要得。
故事到此结束,如今解释一下文中的概念:
一、小明:rancher的master节点
二、栅栏:rancher集群
三、区域:集群
四、大棚舍:命名空间
五、小棚舍:项目
六、pod:pod,k8s对容器的包装,负责容器的生命周期
七、牛羊中心:docker hub镜像中心
八、代理商:国内镜像如阿里云
九、升级:镜像升级
十、回滚:镜像回滚
十一、站台:负载均衡(nginx),之前会在固定的IP上,如今只要在集群的任何一台机器上便可,由于会有专门的“迎宾”处理
十二、为小明工做的人:k8s编排引擎
1三、流程:流水线(CI/CD)
有一个以JAVA编写的微服务,如今要部署上线。
首先,环境分为本地环境(dev)、测试环境(test)、预发布环境(uat)、线上环境(live)。
而后,根据业务划分命名空间,好比后台统一为service,手机客户端统一为app
而后,根据业务划分项目,如用户管理的后台服务项目,则命名为user-manager
而后,根据代码项目划分服务,好比认证服务是user-auth,登陆是user-login
而后,根据实际代码,配置负责均衡暴露服务,为外界提供接口
同时,配备日志采集,能够统一查看各个项目的日志
简单说下原理,Rancher按如下步骤运行:
一、Rancher启动一个jenkins镜像,此镜像能够经过配置一个负载均衡来暴露出去访问后台界面,用户名是admin,密码是容器里的环境变量ADMIN_PASSWORD,默认是cgfh9ljx7dtx7s2vmqf7r9xcf6zj45s5lxcwg95zmtqz9n58mg84pc,若是启动流水线报错,登陆jenkins,进去系统设置->全局安全设置,找到“防止跨站点请求伪造”,肯定勾选,而后点击保存(若是已勾选,那么勾选掉,保存,再编辑,勾选,保存),再从新启动流水线便可。
二、将流水线任务生成groovy脚本,而后在jenkins上建立任务并执行。
三、流水线的每个阶段对应一个镜像,Rancher会启动对应的容器,执行流水线配置的流程。
一个典型的jenkins流水线脚本,相似以下:
import org.jenkinsci.plugins.pipeline.modeldefinition.Utils def label = "buildpod.${env.JOB_NAME}.${env.BUILD_NUMBER}".replace('-', '_').replace('/', '_') podTemplate(label: label, namespace: 'p-8j2pf-pipeline', instanceCap: 1, serviceAccount: 'jenkins',volumes: [emptyDirVolume(mountPath: '/var/lib/docker', memory: false), secretVolume(mountPath: '/etc/docker/certs.d/docker-registry.p-8j2pf-pipeline', secretName: 'registry-crt')], containers: [ containerTemplate(name: 'step-0-0', image: 'rancher/pipeline-tools:v0.1.0', ttyEnabled: true, command: 'cat' , envVars: [ envVar(key: 'CICD_GIT_REF', value: 'refs/heads/master'),envVar(key: 'CICD_GIT_BRANCH', value: 'master'),envVar(key: 'CICD_PIPELINE_ID', value: 'p-dd58c'),envVar(key: 'CICD_CLUSTER_ID', value: 'c-gb2hf'),envVar(key: 'CICD_LOCAL_REGISTRY', value: '127.0.0.1:34350'),envVar(key: 'CICD_GIT_COMMIT', value: '6795394'),envVar(key: 'CICD_GIT_URL', value: 'http://git.lumiai.top/york/hyperloop-baseapi.git'),envVar(key: 'CICD_TRIGGER_TYPE', value: 'user'),envVar(key: 'CICD_EVENT', value: ''),envVar(key: 'CICD_EXECUTION_ID', value: 'p-dd58c-27'),envVar(key: 'CICD_EXECUTION_SEQUENCE', value: '27'),envVar(key: 'CICD_PROJECT_ID', value: 'p-8j2pf'),envVar(key: 'CICD_GIT_REPO_NAME', value: 'hyperloop-baseapi'), ]),containerTemplate(name: 'step-1-0', image: 'maven:3.6.0-jdk-8-alpine', ttyEnabled: true, command: 'cat' , envVars: [ envVar(key: 'CICD_GIT_COMMIT', value: '6795394'),envVar(key: 'CICD_GIT_REPO_NAME', value: 'hyperloop-baseapi'),envVar(key: 'CICD_GIT_REF', value: 'refs/heads/master'),envVar(key: 'CICD_GIT_URL', value: 'http://git.lumiai.top/york/hyperloop-baseapi.git'),envVar(key: 'CICD_PIPELINE_ID', value: 'p-dd58c'),envVar(key: 'CICD_EVENT', value: ''),envVar(key: 'CICD_CLUSTER_ID', value: 'c-gb2hf'),envVar(key: 'CICD_GIT_BRANCH', value: 'master'),envVar(key: 'CICD_TRIGGER_TYPE', value: 'user'),envVar(key: 'CICD_EXECUTION_ID', value: 'p-dd58c-27'),envVar(key: 'CICD_EXECUTION_SEQUENCE', value: '27'),envVar(key: 'CICD_PROJECT_ID', value: 'p-8j2pf'),envVar(key: 'CICD_LOCAL_REGISTRY', value: '127.0.0.1:34350'), ]),containerTemplate(name: 'step-2-0', image: 'rancher/jenkins-plugins-docker:17.12', ttyEnabled: true, command: 'cat' , privileged: true, envVars: [ envVar(key: 'CICD_GIT_REF', value: 'refs/heads/master'),envVar(key: 'CICD_PIPELINE_ID', value: 'p-dd58c'),envVar(key: 'CICD_EXECUTION_ID', value: 'p-dd58c-27'),envVar(key: 'CICD_EXECUTION_SEQUENCE', value: '27'),envVar(key: 'CICD_PROJECT_ID', value: 'p-8j2pf'),envVar(key: 'CICD_CLUSTER_ID', value: 'c-gb2hf'),envVar(key: 'CICD_LOCAL_REGISTRY', value: '127.0.0.1:34350'),envVar(key: 'CICD_GIT_COMMIT', value: '6795394'),envVar(key: 'CICD_GIT_REPO_NAME', value: 'hyperloop-baseapi'),envVar(key: 'CICD_GIT_BRANCH', value: 'master'),envVar(key: 'CICD_GIT_URL', value: 'http://git.lumiai.top/york/hyperloop-baseapi.git'),envVar(key: 'CICD_TRIGGER_TYPE', value: 'user'),envVar(key: 'CICD_EVENT', value: ''),envVar(key: 'PLUGIN_DOCKERFILE', value: './Dockerfile'),envVar(key: 'PLUGIN_CONTEXT', value: '.'),envVar(key: 'DOCKER_REGISTRY', value: '127.0.0.1:34350'),envVar(key: 'PLUGIN_REPO', value: '127.0.0.1:34350/scc/hyperloop/baseapi'),envVar(key: 'PLUGIN_TAG', value: 'dev'),secretEnvVar(key: 'DOCKER_USERNAME', secretName: 'p-8j2pf-12700134350', secretKey: 'username'),secretEnvVar(key: 'DOCKER_PASSWORD', secretName: 'p-8j2pf-12700134350', secretKey: 'password'), ]), containerTemplate(name: 'jnlp', image: 'rancher/jenkins-jnlp-slave:3.10-1-alpine', envVars: [ envVar(key: 'JENKINS_URL', value: 'http://jenkins:8080')], args: '${computer.jnlpmac} ${computer.name}', ttyEnabled: false)], yaml: """ apiVersion: v1 kind: Pod metadata: labels: app: jenkins execution: p-dd58c-27 spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - jenkins topologyKey: kubernetes.io/hostname """ ) { node(label) { timestamps { timeout(60) { stage('Clone'){ parallel 'step-0-0': { stage('step-0-0'){ container(name: 'step-0-0') { checkout([$class: 'GitSCM', branches: [[name: 'local/temp']], userRemoteConfigs: [[url: 'http://git.lumiai.top/york/hyperloop-baseapi.git', refspec: '+refs/heads/master:refs/remotes/local/temp', credentialsId: 'p-dd58c-27']]]) } } } } stage('打包'){ parallel 'step-1-0': { stage('step-1-0'){ container(name: 'step-1-0') { sh ''' echo "haha">baseapi.jar ''' } } } } stage('发布'){ parallel 'step-2-0': { stage('step-2-0'){ container(name: 'step-2-0') { sh '''/usr/local/bin/dockerd-entrypoint.sh /bin/drone-docker''' } } } } } } } }
好了,说完原理,下面实操。
进入到Rancher管理平台,依次进入dev(集群)->service(命名空间),而后点击流水线。
源码管理使用本地Gitlab,代码语言是Java,使用maven构建,提供REST风格的API接口。
目前Rancher只支持接入单个代码库,不支持多代码库同时接入。打开Gitlab,点击我的设置->应用,而后配置应用信息,拿到应用ID和应用密钥,最后回到Rancher输入gitlab地址、应用ID和应用密钥便可接入。
启用任意代码项目后,流水线首页就会出现对应的数据,点击编辑。
编辑页面,可操做的东西很少,但很简明易懂。
第一步克隆代码,这一步是默认的也是必须和没法编辑的。
点击添加阶段,输入阶段名,如“打包”,点击完成
点击添加步骤,步骤类型分三类,一类是运行脚本,一类是构建并发布镜像,最后一类是部署YAML,每个阶段能够添加不少步骤。这里点击运行脚本,而后在下面镜像那里输入maven:3.6.0-jdk-8-alpine,输入完成后会出现提示框maven:3.6.0-jdk-8-alpine (Custom),鼠标点击便可,最后在脚本那里输入mvn clean package。
打包完成后,再建立一个阶段,叫“镜像发布”,再点击添加步骤。
步骤类型是“构建并发布镜像”,下面Dockerfile路径指的是代码中基于项目根路径的Dockerfile路径,镜像名称注意不用写镜像私服地址,但要带有仓库中对应项目名,好比harbor中我有一个项目叫shy,那么这里应该输入shy/xxx:[xxx],再勾选下面的“推送镜像到远端镜像仓库”,选择对应的镜像库便可。
特别须要注意的是,这一步会启动一个叫rancher/jenkins-plugins-docker:17.12的镜像,这个镜像会使用默认的https推送镜像,若是使用了Harbor,可是自签证书,那么这一步永远过不去,必须是合法的CA证书。或者使用阿里云的镜像私服,那个CA证书确定得合法的。
镜像发布后,在建立一个阶段,叫“上线部署”,再点击添加步骤。
步骤类型是“部署YAML”,下面YAML路径一样指的是代码中基于项目根路径的YAML路径。而后点击添加, 在流水线配置的右下角有个“显示高级选项”,打开他,配置触发规则。也可不配置,每次手动执行。
最后点击完成,即建立完一个完整的流水线。
一个服务不可能只有1个实例,多实例就致使日志的排查比较困难,由于不知道访问落到了哪一个实例上,因此一个集中式的日志中心是颇有必要的。rancher针对每个命名空间都提供了一个专门的日志采集接口,只须要配置日志输出便可。
打开全部的应用商店,搜索efk,而后点击安装。
接着,命名空间视图下,点击资源->日志,选择Elasticsearch,输入刚刚建立的es的地址,肯定索引前缀,保存便可。指的注意的是,这里的日志粒度仍是有点粗的,只到项目这一层级,实际使用的时候,能够多建项目,每一个项目一类服务的方式,规避粒度粗的问题。
1.x的Rancher,事先是不知道实际的IP地址的,每次都是先配置负载均衡,拿到IP再配置DNS解析。
2.x的Rancher,不用事先知道具体的IP了,访问集群内的任何一台机器便可,而且不再用担忧80端口不够用的状况。但因为这个版本放弃了HA,采用的nginx,而且不支持自定义配置,致使目前只支持L7层的负载均衡。
Rancher的扩容很是容易,按照第三章的前7条执行,而后将此时的镜像打包成系统镜像,之后直接拿这个镜像安装系统。安装完成后,直接在Rancher界面上添加主机,便可实现扩容,另外2.x的版本新主机的管理不须要手动进行,k8s会主动进行管理。
这里说的咱们线上集群的状况,并进行了必定得推测。另外,docker最佳搭档就是全部无状态的服务,Rancher同理也最适合无状态的服务,对于有状态的,如mysql,最好不要丢到rancher或者说docker上运行,不稳定是其次,数据丢失可怕了。
物理机很重要,他是载体,决定了容器的状况。
CPU:最低单U8核,越多越好,看具体状况。
内存:32G是最低了,再少跑不了多少容器,咱们是64G。
硬盘:机械盘RAID5跑不了(这玩意读取性能不高为啥用他?由于生产中硬盘坏了很常见啊,呵呵),固然最好的仍是固态,但那玩意成本过高。
网卡:千兆的应该是标配了吧
1.x受限于cattle的编排能力,节点数最好保持在20台左右,容器总量500如下,多了cattle就处理不过来了。
2.x对节点数量没限制,可是节点的类型须要注意下:
worker:是工做节点,不限数量,咱们是除rancher自己外,其它都是worker
control:集群控制节点,负责每一个pod的控制,咱们是设置了总机器数量的数量
etcd:k-v存储,数量必须是奇数,咱们是设置了总机器数量的1/3
也就是说每3台机器,有一台的类型是worker和control以及etcd,其它两台是worker和control。
Rancher:主节点必须是高可用的,咱们是3个主节点,使用mysql存储数据,中间用mycat代理。
Mysql:跑在物理机上,1主2从。
虽然Rancher是一个密闭的集群,但宿主机被黑,跑在这上面的容器也会遭殃。但若是物理机若是开启了防火墙,却又会致使一些莫名的错误,这时该怎么办呢?
若是有本身的机房和机器,解决方案是:
一、关闭全部主机的防火墙,同时断开一切与外网的链接,至关于一个密闭的局域网
二、将F5架设在局域网的前端,外网能够访问F5,内网也能够访问F5,但外网访问不了内网。而后再将F5打形成一个堡垒机,最后全部请求经过F5转发的对应的服务上。
若是是云服务器,购买机器,不买外网IP,经过云提供商的负载均衡访问所购买的机器,这种和上面是如出一辙的。
最后说下登陆认证,企业通常使用ldap,或者直接数据库密码存储。但推荐ldap,企业里是很是方便的。