学习日志 21-12-17 部署Java微服务 微服务互调
# 1217
# 部署java应用的镜像
## 检查昨天创建的私有docker registry
- 出了好多问题, 见下Q&A
### Q&A
- Q: deployment 启不来, ready一直是0
- A: 原因是node minikube 重启后 /opt/certs /opt/registry目录都没了
- 每次minikube stop 再 start后, /opt/certs 和 /opt/registry 目录都会消失
- 而且minikube的 ip也会变
- 后续不做minikube stop start了, 改为在hyper-v中对minikube做保存/重启
- ssh登录minikube vm, 重新做certs 和 registry目录
- 重新生成证书, 下载证书, 重新在windows中安装该证书
- 删除旧证书 在控制面版中搜索证书 用户证书 -> 中间证书颁发机构 按日期找到旧证书 删除
- docker客户端重启一下
- 修改 etc/hosts 采用新IP
- 重新push docker image
## 将Java应用镜像部署到k8s
- 直接在开发机 做 docker Apply
- 解决ImagePullBackOff 问题, 见Q&A部分
- 检查kubectl get deployments 发现新的Java应用已经成功启动
- 如未启动 可以尝试 kubectl rollout restart
- 校验java应用能否正常使用
- 尝试 `exec -- bash` 的方式
- 发现linux-slim镜像没有curl工具
- 创建service
- copy一个service的yaml部分, 添加到原yaml的下面
- yaml是不变的部分不执行, 新增/修改的部分才会被k8s执行
- 可以重复Apply没问题
- Apply后, 走外部端口访问
- 网络不通, 见Q&A第二个问题
- 检查日志 `kubectl logs <pod名>`
- 发现是spring-boot的启动日志 一切正常
- 结果 外部端口访问成功
- 在开发机访问类似 http://172.26.85.189:31000/
- 总结
- k8s的pre-pulled image实际上就是minikube node(control plan) 上做docker pull
- k8s Apply 能否成功, 也依赖于minikube node能否直接靠自己的docker客户端 pull到image
- 如果pull不到, 从docker客户端的角度解决问题即可
- k8s需要经常自己pull image, 就是怕有latest的情况, 它每次启动都需要重pull image
- 参考 上述 imagePullPolicy
### Q&A
- Q: 新建的pod 处理 ImagePullBackOff 状态
- A: 从minikube集群无法使用新建的私有docker registry仓库
- 网络不通 minikube 不认识k8s-master这个域名
- 登录minikube节点 编辑/etc/hosts 把k8s-master域名直接指向minikube的ip
- 没有证书
- 根据 https://docs.docker.com/engine/security/certificates/
- 登录minikube节点 创建 /etc/docker/certs.d/k8s-master:31320 目录
- 注意:31320是目录名的一部分, linux目录名可以支持:
- 在该目录下创建ca.crt文件, 把之前私有registry的证书, crt的那份, 内容复制进去
- 重新docker pull 可以发现从minikube节点可以pull到image了
- Q: 新建的service, 外部访问网络不通
- A: 检查service的yaml配置, 发现 selector App这部分写错了
- 修改为正确的App 即 springbootdemo
- 重新Apply
# 微服务内部调用
## 目标
- 实现在K8s上部署两个微服务, A和B, 实现A调用B
## 实现
- 基于之前的springbootdemo 该微服务已经提供了restful的/路径
- 还提供了一个service 类型是nodeport, 内部端口8080 外部端口31000
- service的名字是 springbootdemo-service
- 该服务作为我们的被调用者
- 测试 从开发机访问 minikube_ip:31000/
- 类似 http://172.26.85.189:31000/
- 调用者 搞个新的Java工程
- 从start.spring.io上搞一个springboot + web的标准工程
- 创建一个RequestMApping
- 采用Java 11的httpclient 调用 上述 提供者的微服务
- 重点参数
- host : springbootdemo-service
- 即k8s service的名字
- k8s会负责让所有pod运行环境都知道这个service名对应的ip地址
- 类似DNS解析
- port : 使用该service的内部端口 8080
- 注意这里不是外部端口31000
- 只需注意以上两个参数即可调通
- 重点代码
```
@RequestMApping("/")
public DeferredResult<String> home() {
DeferredResult<String> result = new DeferredResult<>();
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://springbootdemo-service:8080" ))
.build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(it -> {
result.setResult("get resp from springbootdemo-service:8080 : \n" +
it);
})
.join();
return result;
}
```
- 其它说明
- 该controller使用了DeferredResult<String>异步方式
- 配合httpclient异步调用方式
- 制作Docker image
- 参考上文
- 因为使用了变量${project.artifactId} 所以什么都不用改
```
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.13</version>
<configuration>
<dockerfile>Dockerfile</dockerfile>
<repository>${project.artifactId}</repository>
</configuration>
</plugin>
```
- 编写Dockerfile
- 参考之前springbootdemo的Dockerfile
- 修改点 把COPY 和 CMD 指令 jar包的名字改一下即可
- 执行 mvn package 和 mvn dockerfile:build
- 我们这里没写tag, 也没指定使用私有docker仓库k8s-master
- 这些我们手动操作 见下
- 上传Docker镜像
- 使用docker tag 命令对本地的springbootdemocaller:latest 重新命名
- 为 k8s-master:31320/springbootdemocaller:1.0.0
- 之后把该本地镜像 push 给私有仓库
- 编写 k8s.yaml 部署k8s调用者的微服务
- 参考 提供者 springbootdemo的k8s.yaml
- 把所有springbootdemo单词都替换成springbootdemocaller
- 修改外部端口号 为 32000 (31000已被占用, 也不能用私有仓库占用的31320)
- kubectl Apply 即可
- 验证结果
- 从开发机访问 http://172.26.85.189:32000/