阅读本文前可先参考
一、Kubernetes部署“容器化应用”(测试kubernetes集群)
1、容器化应用
通俗点来说,就是把一个程序放在Docker里部署,这个Docker应用就是容器化应用
如:在Docker里面部署一个SpringBoot,这个Docker+SpringBoot一起就是一个容器化应用
Docker 的核心思想就是如何将应用整合到容器中,并且能在容器中实际运行。
将应用整合到容器中并且运行起来的这个过程,称为“容器化”(Containerizing),有时也叫作“Docker化”(Dockerizing)。
容器是为应用而生的,具体来说,容器能够简化应用的构建、部署和运行过程。
2、Docker部署应用
(1)编写应用代码
(2)创建一个 Dockerfile,其中包括当前应用的描述、依赖以及该如何运行这个应用
(3)对该 Dockerfile 执行 docker image build 命令
(4)等待 Docker 将应用程序构建到 Docker 镜像中
一旦应用容器化完成(即应用被打包为一个 Docker 镜像),就能以镜像的形式交付并以容器的方式运行了
3、k8s部署应用
(1)编写应用代码
(2)创建一个 Dockerfile,其中包括当前应用的描述、依赖以及该如何运行这个应用
(3)通过 K8S 将应用程序构建镜像
1、在Kubernetes集群中部署一个Nginx
1、在网上拉取一个nginx镜像
kubectl create deployment nginx --image=nginx
2、对外暴露一个80端口
kubectl expose deployment nginx --port=80 --type=NodePort
3、查看对外端口
kubectl get pod,svc
4、访问地址:http://NodeIP:Port
2、在Kubernetes集群中部署一个Tomcat
kubectl create deployment tomcat --image=tomcat
kubectl expose deployment tomcat --port=8080 --type=NodePort
kubectl get pod,svc
访问地址:http://NodeIP:Port
kubectl get 相关命令
//获取节点和服务版本信息
kubectl get node(s)
//所有 namespace 中的所有 service
kubectl get service(s)
//列出deployment
kubectl get deployment (deploy)
//列出所有 namespace 中的所有 pod
kubectl get pod(s)
//删除service
kubectl delete service nginx
//删除nginx的控制器
kubectl delete deployment nginx
//删除pod
kubectl delete pod nginx-6799fc88d8-zc48m(pod名字)
//kubectl命令帮助
kubectl --help
3、Kubernetes集群部署SpringBoot应用
1、编写应用,将其打包 jar 或者 war ,上传到Linux(如博主放在 /opt/app/k8s 路径下)
2、编写Dockerfile文件自定义JDK镜像
(1)Dockerfile文件
FROM java:8
MAINTAINER zm
EXPOSE 8081
ADD springboot-1-hello.jar springboot-1-hello.jar
# Dockerfile时区设置
RUN echo 'Asia/Shanghai' >/etc/timezone
ENTRYPOINT ["java","-jar","springboot-1-hello.jar"]
(2)构建、运行镜像;这里编写脚本
注:
Windows编写脚本上传到Linux后,会报错:xx.sh: line 2: $‘\r‘: command not found,解决办法在 如下 踩坑 模块中有讲述,请参考
#!/bin/sh
cd /opt/app/k8s
docker rm -f springboot-1-hello
docker rmi springboot-1-hello:latest
docker build -t springboot-1-hello .
docker run -d -p 8081:8081 -e "SPRING_PROFILES_ACTIVE=test" -v /etc/localtime:/etc/localtime -v /data/logs/app/springboot-1-hello:/logs -v /data/files/app/springboot-1-hello:/files -v /etc/hosts:/etc/hosts -v /etc/hostname:/etc/hostname --restart=always --privileged=true --name springboot-1-hello springboot-1-hello:latest
3、docker images查看镜像
注:
此镜像需要在 master 主节点 机器和 所有 node 从节点机器部署,不然报错 ErrImageNeverPull !!!
Container image "springboot-1-hello" is not present with pull policy of Never
Error: ErrImageNeverPull
4、空运行测试,生成yaml 或 json 文件
//kubectl get deployment不会创建deployment;只会输出 yaml格式的配置内容
kubectl create deployment deployment名称 --image=自定义项目镜像名称 --dry-run -o yaml
//kubectl get deployment不会创建deployment;只会输出 json格式的配置内容
kubectl create deployment deployment名称 --image=自定义项目镜像名称 --dry-run -o json
//只会生成 deploy.yaml的配置文件
kubectl create deployment deployment名称 --image=自定义项目镜像名称 --dry-run -o yaml > 需要生成的yaml文件
//只会生成 deploy.json的配置文件
kubectl create deployment deployment名称 --image=自定义项目镜像名称 --dry-run -o json > 需要生成的json文件
--dry-run表示空运行测试,不会真正的运行
-o 表示测试输出
如下:
kubectl create deployment springboot-k8s --image=springboot-1-hello --dry-run -o yaml
kubectl create deployment springboot-k8s --image=springboot-1-hello --dry-run -o json
kubectl create deployment springboot-k8s --image=springboot-1-hello --dry-run -o yaml > deploy.yaml
或者
kubectl create deployment springboot-k8s --image=springboot-1-hello --dry-run -o json> deploy.json
我们生成的deploy.yaml 或者 deploy.json 文件(和 jar 包在同一目录下)中内容 和直接输出的内容一致(也可手动创建文件编写内容)
通过 kubectl get deploy 命令查看,deployment并不是真的运行
5、部署
注:
deploy.yaml文件里面的镜像需要从本地拉取,不然报错 拉取本地镜像失败(kubernetes(K8S)集群无法正常拉取自建镜像仓库中的镜像文件,默认是去中心仓库拉取镜像的)
Failed to pull image "springboot-1-hello": rpc error: code = Unknown desc = Error response from daemon: pull access denied for springboot-1-hello, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
Normal BackOff 47m (x7 over 50m) kubelet Back-off pulling image "springboot-1-hello"
Warning Failed 25m (x9 over 50m) kubelet Error: ErrImagePull
Warning Failed 62s (x191 over 50m) kubelet Error: ImagePullBackOff
//检查是否创建了deployments任务
kubectl get deployments
kubectl get pods
//查看pod详细信息
kubectl describe pods pod名称
//查看pod日志
kubectl logs pod名称
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 91s default-scheduler Successfully assigned default/springboot-k8s-648db45cd5-42f2j to k8snode
Warning ErrImageNeverPull 11s (x8 over 89s) kubelet Container image "springboot-1-hello" is not present with pull policy of Never
Warning Failed 11s (x8 over 89s) kubelet Error: ErrImageNeverPull
修改 deploy.yaml 文件,将镜像拉取策略imagePullPolicy改为Never(镜像从本地拉取,默认是去中心仓库拉取镜像的)
spec:
containers:
- image: springboot-1-hello
name: springboot-1-hello
imagePullPolicy: Never
imagePullPolicy的用法总结如下
名策略 | 作用 |
Never | 只使用本地image |
Always | 每次都下载镜像 |
IfNotPresent | 优先使用本地image,本地没有再去下载 |
重新执行 kubectl apply -f deploy.yaml 命令
//检查是否创建了deployments任务:kubectl get deployments
kubectl get pods
//查看pod详细信息:kubectl describe pods pod名称
//查看pod日志:kubectl logs pod名称
Error from server (BadRequest): container "springboot-1-hello" in pod "springboot-k8s-648db45cd5-42f2j" is waiting to start: ErrImageNeverPull
注:
Kubernetes(K8S)集群部署一主多从
这种模式要想使用本地镜像需要满足两个条件:
1、imagePullPolicy设置为IfNotPresent(如果本地没有,才从远程仓库拉取) 或者 Never(只从本地拉取)
2、从节点上要有这个镜像。准确的说是调度到哪个节点,那个节点上就要有这个镜像,否则会报错ErrImageNeverPull
(1)Yml文件方式部署
kubectl apply -f deploy.yaml (yaml是资源清单)
等价于
kubectl create deployment springboot-k8s --image=springboot-1-hello
暴露服务端口:
kubectl expose deployment springboot-k8s --port=8081 --type=NodePort
此时可以查看 service:kubectl get service
(2)命令方式部署
kubectl create deployment springboot-k8s --image=springboot-1-hello
浏览器中输入如下地址访问,主、从节点IP皆可
http://192.168.133.129:8081/springboot-1-hello/hellospringboot
二、踩坑
1、K8S执行kubectl xx xx 报错 Unable to connect to the server: net/http: TLS handshake timeout
在执行 kubectl get nodes 命令查看Node节点时,等待了3~5分钟才返回结果,还报错,报错信息如下:
Unable to connect to the server: net/http: TLS handshake timeout
可能是 VM虚拟机内存分配小了,可能是自己的master节点的内存给的太小了,因为关闭了交换分区
因此将 VM虚拟机内存由 2G 提高到 4G 再重新启动虚拟机,执行 kubectl get nodes 就没问题
2、xx.sh: line 2: $‘\r‘: command not found(Windows编写Docker运行启动容器脚本)
当我们在Windows系统上写好一个脚本,上传到Linux上时,执行脚本时就会报错
xx.sh: line 2: $'\r': command not found
Ubuntu解决方法:
1、sudo apt-get install tofrodos
2、fromdos sh脚本文件名
Centos解决方法:
1、yum -y install dos2unix
2、dos2unix sh脚本文件名
3、master节点Ready;Node节点NotReady
kubectl get nodes
master节点主机
Node节点主机
查看一下kubelet启动日志
journalctl -f -u kubelet
从最后两条日志我们可以判断出,node节点已经停止被代理
主机中k8s的master启动顺序为:systemd > kubelet > 容器组件 >
kubernetes
我们可以从systemd到kubelet来判断一下,因为kubelet是一个应用进程,所以我们查看一下kubelet的状态(master、node 主从机都执行)
systemctl status kubelet
通过命令行我们看出,kubelet是没有加载起来的(node节点从机)
故我们用重启启动服务的命令,启动一下(node节点从机)
systemctl restart kubelet
systemctl status kubelet
此时再去查看master节点主机
4、SpringBoot应用要在master 和 所有 Node 节点机器部署Docker镜像
SpringBoot应用要在master 和 所有 Node 节点机器部署Docker镜像,如果只在master主节点上部署,而 Node节点 机器不部署,不然报错 ErrImageNeverPull !!!
Container image "springboot-1-hello" is not present with pull policy of Never
Error: ErrImageNeverPull
Kubernetes(K8S)集群部署一主多从
这种模式要想使用本地镜像需要满足两个条件:
1、imagePullPolicy设置为IfNotPresent(如果本地没有,才从远程仓库拉取) 或者 Never(只从本地拉取)
2、从节点上要有这个镜像。准确的说是调度到哪个节点,那个节点上就要有这个镜像,否则会报错ErrImageNeverPull