记一次基于阿里云云效上的spring config部署

最近由于工作需要,需要为公司的微服务集群上spring config,大概说一下整个实现过程,中间有好多的坑,我就逐个击破。当然我的方法绝对不是最优解,属于暴力求解,所以解决方案很不优雅,但是目前只能做到这种程度了,比较急。这篇博客也比较长,请做好心理准备。

首先,我们从描述需求开始:场景是这样的,我们需要依托于阿里云的云效平台部署各个微服务,而每个微服务的构建也是一个不小的坑,对于未接触过的人其实很不友好;其次每个微服务是承载在docker容器中的,这样就涉及了docker容器之间的通信什么的了,这个在我解决问题的过程中也是一个坑;最后,公司的config配置文件不是托管在GitHub上的,因为网络原因,所以选择依托在code.aliyun上,这是整个需求中,最大的坑,我的绝大部分时间都花在这上面了。

整个解决过程耗时1天半,当然之前在本地测试config的消耗时间未算在内,本文的重点也是放在容器搭建上的。

接下来说思路:首先最开始的思路就比较清晰,因为当时在本地已经测试过如何通过ssh连接code.aliyun的git服务器了,这个地方就是config配置的一种情况,之前常见的都是http形式连接GitHub等,所以这个地方当时在本地测试的时候花了一点时间解决,参考文章如下spring cloud文档
当时按照这种方式解决后,就觉得放在服务器上是一个道理,所以就开始在云效上部署应用了,这里也简单的介绍一下。
首先我们登陆云效首页——》我的,在右侧标签栏的应用中注册应用。
注册应用的时候就按照提示一步一步走就可以,比如关联code.aliyun以有的项目等;接着选择服务器端,然后选择开发语言,比较重要的是产物路径,这里应该填写的是项目的.release文件中的jar包路径,如图
这里写图片描述
然后勾选docker构建,填写dockers地址,这个地址是通过容器管理服务中构建的,在那里找到镜像,然后创建镜像仓库,就会得到一个地址,填上那个地址即可。然后配置一下,最后成功注册应用;之后到刚才注册的应用中找到流水线,在流水线上构建任务,之后日常部署,等到项目正常跑起来即可。
上面罗里吧嗦一堆,其实一点营养都没有,可以直接跳过,接下来就是开始踩坑啦!

缺少rabbitmq

因为我在config-server中配置了bus,所以首当其冲就是rabbitmq缺少的报错,经过排查,当时容器的构建是基于java:8-jre-alpine镜像的,里面什么都没有,所以比较小,一般需求是可以满足,但是我现在需要rabbitmq怎么办?
这时我大概考虑了以下的解决办法:
1. 换掉基础镜像,然后自己搭一个,交给阿里云。
2. 想别的办法,能够使用rabbitmq的。
首先说第一种方法,是最先蹦到脑子里的,但是我考虑了一下,一个是自己构建容器比较复杂,需要安装rabbitmq,还要配置java环境等,(其实这里还需要装ssh,这个是后面的问题,当时我一度想要换一个基础镜像,但是考虑到自己搭很麻烦,就放弃了。。。)
既然懒,那就想别的办法,这个时候正好看到应用配置的时候可以添加服务(不过这个只有在新建的时候有,使用编排模板的时候,可以添加服务,其实就是开另一个镜像),所以我就把rabbitmq给加上了,然后这下终于可以使用了吧!

无法连接rabbitmq,报错connect refused。

其实这个在我刚才的操作之后,就应该可以看出端倪了,因为这是两个容器,所以之前配置文件中对于rabbitmq配置的localhost就无法使用了,这时我有产生了一下想法:
1. docker容器互连
2. 想办法连接rabbitmq
还是说1,其实当时隐约有了这个想法,但是后面想了想,这样做一个是成本高,还有就是可能不是很实用。首先我们的集群是跑在几台服务器上的,所以想要实现所有服务都和rabbitmq这个容器连接,比较不现实,那么就只能用第二种方法了,这个时候立马想到,想要连接一个容器,用ip啊!
所以我在容器服务的应用列表中找到对应的应用,然后点进去,被我找到了。
这里写图片描述
但是这里其实是有一个问题的,因为我不确定每次重启这个容器,ip是否会发生改变,如果删掉应用重新新建,那么ip就是新的了。所以这里算是一个隐患?但是没有想到好的办法解决。
4.12日更新:这里将rabbitmq容器的端口映射到所在宿主机上,然后配置文件中的rabbitmq:host直接配置宿主机ip即可,比较完美的规避之前的风险。

报错user ‘guest’ authenticated and granted access to vhost ‘/’

这个报错应该很熟悉了,就是rabbitmq权限的问题了,那么问题来了,权限命令我怎么输入呢?我的rabbitmq是运行在容器中的啊。
这时候就想到了,进入容器内操作,所以我就找了一下,如何进入docker容器内部的命令,这里我使用了其中一种:
docker exec -it 'CONTAINER ID' /bin/bash
(因为rabbitmq的基础镜像是基于debian的,所以可以通过bash进入,但是后面进入alpine的时候就只能通过sh,注意一下这里的区别)
那个CONTAINER ID就是容器id,进去后,直接输入命令即可
rabbitmqctl set_permissions -p '/' guest '.*' '.*' '.*'
到这里,报错解决了。

git推送报错

这里是插播的,当时使用git推送的时候报了两个错误,这里说明一下。
1. warning: LF will be replaced by CRLF in pom.xml. The file will have its orig
这解决办法git config --global core.autocrlf false 参考
2. Everything up-to-date
这个其实不是报错信息,但是就是有问题,我是在版本回退的时候,想要把库版本回退,但是push的时候一直报这个问题,也不知道如何解决,因为我add和commit都是没有记录的,所以最后我在确保没有问题的情况下使用了强制推送命令
git push origin master -f

好了,插曲结束。我们看到之前的rabbitmq也能够连上了,这下应该就没什么问题了吧!
事情总是不遂人愿。唉~

java.lang.IllegalStateException: Cannot clone or checkout repository] with root cause com.jcraft.jsch.JSchException: Auth fail

这个报错的原因就是,ssh连接的问题,好了,终于讲到这个大坑了!
首先想到问题出在哪? 因为这个报错我是可以预料到的,我当时在配置文件中贴的私钥是本地的,所以自然会报这个错误,然后我需要把正确的私钥贴过来。那么,正确的私钥在哪呢?
首先想到的是服务器,但是转而一想,不对,因为我的应用是部署到docker容器内的,所以用的私钥以及ssh服务应该是docker容器内部的,好了找到问题所在了,那么就解决吧。但是,我万万没想到,这是我血泪史的开始。
首先就是进入docker容器了,这时的命令是
docker exec -it 'container id' /bin/sh
因为这个是基于alpine的基础镜像,所以东西少的可怜。那么我们就开始配置ssh私钥吧。
ssh-keygen
报错:没这个命令。
一想,嗯,容器内没装ssh服务,那装一下吧。一搜,全是yum安装,那就试试吧。
yum install openssh-server
报错:没yum这个命令。
一看,sh,啥也没有啊,再装yum吧。。。。(后面还要装python依赖,rpm等等等等,然后没法搞了,这条路走不通)
那换一条路吧,试试别的命令,apt-get,没用。绝望了,要不换镜像吧,太难受了!
但是一想,不行啊,都走到这一步了,再试试吧。
众里寻他,可算被我找到了,apk --update add openssh,然后把这句加到Dockerfile中,这下终于有ssh环境了,那就生成私钥吧,然后贴到配置文件里。
等等!
我要是贴到配置文件里,推到code.aliyun,应用重新部署,ssh重新生成,连接失败。这是个闭环,出不去啊!
再想解决办法,这个问题肯定有解决方案。
想了一下,不能再配置文件中加私钥,太蠢了,有没有什么别的解决方案,可以实现ssh连接的。
仔细看了看之前的配置中有个标签是这样的:
ignoreLocalSshSettins: true
之前又看过这个东西这个东西
恍然大悟!
改成下面这样
这里写图片描述
这样它就直接从本地ssh读取。
所以我们用ssh-keygen生成密钥后,需要把公钥.pub文件的内容给code.aliyun添加上。
但是刚配好,又报错了。
仔细查了一下日志,有这句报错:

com.jcraft.jsch.JSchException: UnknownHostKey: code.aliyun.com. RSA key fingerprint is 69:ab:cb:07:eb:a3:e1:f3:0b:2e:f4:23:b0:c1:c6:9a

搜了一下,好像找到了不得了的东西

然后就着手解决know_hosts,但是最开始是没有这个文件的啊,这里我们需要用ssh -T git@code.aliyun.com
这样我们用ssh和aliyun的git仓库建立了连接,就会看到有know_hosts文件生成了。这下问题总该解决了吧。
但是请求/{application}/{profile}这种形式去查看config配置,发现看不到配置文件信息,但是config-server服务是正常启动的,测试url可以访问,这就奇怪了,明明按照之前说的都解决了啊,难道真的是天要亡我?
这是静下心来想了想,先试试/bus/refresh看看生不生效吧。postman请求发过去,成功了,看日志也打印出信息了,然后再请求,发现还是404.
等等!
为什么日志没有信息呢?诶,这为啥是404?
恍然大悟,因为之前改的配置是在应用启动的时候生效的,现在服务都启动了,怎么可能生效呢,所以其实还是延续了之前的报错信息那种情况

com.jcraft.jsch.JSchException: UnknownHostKey: code.aliyun.com. RSA key fingerprint is 69:ab:cb:07:eb:a3:e1:f3:0b:2e:f4:23:b0:c1:c6:9a

没有改变。
那到这就通了,重启应用就好了啊!
等等,重启应用,那之前配置的ssh岂不是又没了?这不还是之前的闭环死路吗?
再等等!
我可以在docker容器中把jar包服务重启一下不就ok了嘛!
说干就干。
先查到jar进程,直接kill掉,这时会退出容器,因为之前容器启动时就是以这个应用为核心的,但是不要紧。
报错:Error response from daemon: Container 19cbd3f773e50556c96ba62121c747564421abd8b9535404255d5f765b08b015 is restarting, wait until the container is running
这个时候再立刻用docker exec命令登陆进去,执行命令:
java -Djava.security.egd=file:/dev/./urandom -jar /app.jar

4.12更:上述报错提示很明显。容器会自动重启,所以也就不需要自己手动重启jar包,并且即使重启也会报错,因为端口被占用了。
启动服务。
对了,突然想起来忘记说如何退出docker了:ctrl + p + q可以实现不中断容器退出。ctrl + d退出并关闭容器。所以我们肯定用的是ctrl + p + q
到这,我们再查启动日志,发现没有报错信息了,然后访问,发现也能正常获取到配置文件的信息:
这里写图片描述
至此,config-server微服务终于上线成功了!

接下来就是配置config-client了。还有多少坑等着我踩呢?

总结

大概捋了一下这个问题解决的过程:
首先,我的目的很明确,基本方向没有发生改变,中间虽然差点换掉容器环境等,但是好在最后还是坚持了下来。
其次,在不该发力的地方不要僵持,在发现无法通过yum安装的时候,这个时候发现要装一系列依赖python、rpm等,成本太高,当时的备用方案就是换环境,自己组装,这是最没有办法的办法了,好在偶然发现了可以使用apk
最后,很多解决方法都是暴力破解,不达目的不罢休。所以也可能存在隐患。比如容器重启,ssh需要重新设置,对应的应用重启。(所以保证应用不停是最好的解决方案!)再比如,之前连接rabbitmq容器的时候使用的ip可能是个多变因素,如果后续发生变化,随之就要修改config-server的配置文件,意味着应用要重新部署上线,这也是一种风险。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值