阅读本文前可先参考

一、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

容器部署架构 容器化部署流程_json


容器部署架构 容器化部署流程_json_02


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 路径下)

容器部署架构 容器化部署流程_kubernetes_03


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查看镜像 

容器部署架构 容器化部署流程_kubernetes_04


注:

此镜像需要在 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

容器部署架构 容器化部署流程_Docker_05

kubectl create deployment springboot-k8s --image=springboot-1-hello --dry-run -o json

容器部署架构 容器化部署流程_Docker_06

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

容器部署架构 容器化部署流程_json_07

我们生成的deploy.yaml 或者 deploy.json 文件(和 jar 包在同一目录下)中内容 和直接输出的内容一致(也可手动创建文件编写内容)

通过 kubectl get deploy 命令查看,deployment并不是真的运行

容器部署架构 容器化部署流程_Docker_08

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名称

容器部署架构 容器化部署流程_json_09

容器部署架构 容器化部署流程_json_10

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

容器部署架构 容器化部署流程_json_11

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名称

容器部署架构 容器化部署流程_spring_12

容器部署架构 容器化部署流程_spring_13

Error from server (BadRequest): container "springboot-1-hello" in pod "springboot-k8s-648db45cd5-42f2j" is waiting to start: ErrImageNeverPull

容器部署架构 容器化部署流程_kubernetes_14

注:

Kubernetes(K8S)集群部署一主多从

这种模式要想使用本地镜像需要满足两个条件:

1、imagePullPolicy设置为IfNotPresent(如果本地没有,才从远程仓库拉取) 或者 Never(只从本地拉取)

2、从节点上要有这个镜像。准确的说是调度到哪个节点,那个节点上就要有这个镜像,否则会报错ErrImageNeverPull

容器部署架构 容器化部署流程_spring_15

(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

容器部署架构 容器化部署流程_spring_16

(2)命令方式部署

kubectl create deployment springboot-k8s --image=springboot-1-hello

浏览器中输入如下地址访问,主、从节点IP皆可 

http://192.168.133.129:8081/springboot-1-hello/hellospringboot

容器部署架构 容器化部署流程_kubernetes_17

 

容器部署架构 容器化部署流程_容器部署架构_18

容器部署架构 容器化部署流程_容器部署架构_19

二、踩坑 

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节点主机

容器部署架构 容器化部署流程_Docker_20


Node节点主机 

查看一下kubelet启动日志


journalctl -f -u kubelet


容器部署架构 容器化部署流程_kubernetes_21


从最后两条日志我们可以判断出,node节点已经停止被代理

主机中k8s的master启动顺序为:systemd > kubelet > 容器组件 > 
kubernetes

我们可以从systemd到kubelet来判断一下,因为kubelet是一个应用进程,所以我们查看一下kubelet的状态(master、node 主从机都执行)


systemctl status  kubelet


通过命令行我们看出,kubelet是没有加载起来的(node节点从机)

故我们用重启启动服务的命令,启动一下(node节点从机)


systemctl restart kubelet
systemctl status  kubelet


容器部署架构 容器化部署流程_spring_22


此时再去查看master节点主机 

 

容器部署架构 容器化部署流程_容器部署架构_23


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

容器部署架构 容器化部署流程_spring_12

容器部署架构 容器化部署流程_spring_13

Kubernetes(K8S)集群部署一主多从

这种模式要想使用本地镜像需要满足两个条件:

1、imagePullPolicy设置为IfNotPresent(如果本地没有,才从远程仓库拉取) 或者 Never(只从本地拉取)

2、从节点上要有这个镜像。准确的说是调度到哪个节点,那个节点上就要有这个镜像,否则会报错ErrImageNeverPull


容器部署架构 容器化部署流程_spring_15