在上一节K8S集群系列二:来个DEMO中,已经完成了简单DEMO的部署。DEMO中的镜像是拉取的公共镜像,这些镜像是别人写好上传至https://hub.docker.com上的。那么如何将本地写的代码发布镜像并部署在docker中呢?本节将介绍此方面内容。
鉴于一般自己写的本地代码不会发布到公共的仓库中,因此,我们首先建立自己的私有仓库。
1:创建私有仓库
下载registry镜像
[root@master ~]# docker pull registry
2:定义好私库的地址
[root@master ~]# vim /etc/docker/daemon.json
{"registry-mirrors":["https://registry.docker-cn.com"], "exec-opts": ["native.cgroupdriver=systemd"], "insecure-registries":["192.168.2.152:5000"]}
其中:"insecure-registries":["192.168.2.152:5000"] 这里定义了我的私有仓库地址是:192.168.2.152:5000。以后所有的本地发布或拉取镜像都将通过这个私有仓库进行。
3:重启docker服务
[root@master ~]# systemctl daemon-reload
[root@master ~]# systemctl restart docker
4:启动私有仓库registry
[root@master ~]# docker run -d -p 5000:5000 --name=registry --restart=always --privileged=true --log-driver=none -v /data/registry:/tmp/registry registry
其中5000:5000的意思是docker服务暴露端口是5000,然后宿主机暴露端口是5000,方便外部服务器调用
5:查看私库启动状态
[root@master ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
25e4f10e7845 registry "/entrypoint.sh /etc…" 35 minutes ago Up 35 minutes 0.0.0.0:5000->5000/tcp registry
69ec2a3cb7bd f04a043bb67a "/home/weave/launch.…" About an hour ago Up About an hour k8s_weave_weave-net-89ln6_kube-system_29a7319e-8693-11e9-9e4f-080027b45424_3
74df4e3a7c89 5ce48e0d813c "/usr/bin/weave-npc" About an hour ago Up About an hour k8s_weave-npc_weave-net-89ln6_kube-system_29a7319e-8693-11e9-9e4f-080027b45424_2
31b0d88eea7e 5cd54e388aba "/usr/local/bin/kube…" About an hour ago Up About an hour k8s_kube-proxy_kube-proxy-8255f_kube-system_440131b0-8682-11e9-9e4f-080027b45424_2
8416b24e1b9a dustise/pause:3.1 "/pause" About an hour ago Up About an hour k8s_POD_weave-net-89ln6_kube-system_29a7319e-8693-11e9-9e4f-080027b45424_2
65346a4fa608 dustise/pause:3.1 "/pause" About an hour ago Up About an hour k8s_POD_kube-proxy-8255f_kube-system_440131b0-8682-11e9-9e4f-080027b45424_2
f1dba62c4465 b95b1efa0436 "kube-controller-man…" About an hour ago Up About an hour k8s_kube-controller-manager_kube-controller-manager-master_kube-system_2d8735cceeed8e04f2962d638ea0bc9a_3
aaa75fb8f7ca 00638a24688b "kube-scheduler --bi…" About an hour ago Up About an hour k8s_kube-scheduler_kube-scheduler-master_kube-system_0f06fd50e513f09ef3cae0150cf407f2_2
8b6b5824f599 ecf910f40d6e "kube-apiserver --ad…" About an hour ago Up About an hour k8s_kube-apiserver_kube-apiserver-master_kube-system_ff8734fdc1141ff32eca18dbff896d9d_2
e2713c6cc315 dustise/pause:3.1 "/pause" About an hour ago Up About an hour k8s_POD_kube-controller-manager-master_kube-system_2d8735cceeed8e04f2962d638ea0bc9a_3
ee77ed23b6e7 dustise/pause:3.1 "/pause" About an hour ago Up About an hour k8s_POD_kube-scheduler-master_kube-system_0f06fd50e513f09ef3cae0150cf407f2_2
a0a088b48eb4 dustise/pause:3.1 "/pause" About an hour ago Up About an hour k8s_POD_kube-apiserver-master_kube-system_ff8734fdc1141ff32eca18dbff896d9d_2
f411077269d7 2c4adeb21b4f "etcd --advertise-cl…" About an hour ago Up About an hour k8s_etcd_etcd-master_kube-system_b1be0dde91752547a34cd75fb8d0417e_2
38528d4e5814 dustise/pause:3.1 "/pause" About an hour ago Up About an hour k8s_POD_etcd-master_kube-system_b1be0dde91752547a34cd75fb8d0417e_2
到这里,私有仓库就完成搭建并启动成功。接下来要准备Dockerfile文件,准备打包发布SpringBoot写的代码。
6:创建Dockerfile
[root@master basic-app]# vi Dockerfile
FROM openjdk:8-jdk-alpine
MAINTAINER utump
VOLUME /tmp
ADD /usr/local/utump/deploy/build/app/basic-app/basic-service-app-facade-impl-0.0.1-bin.tar.gz /usr/local/utump/deploy/app/basic-app
WORKDIR /usr/local/utump/deploy/app/basic-app/
CMD sh bin/start.sh
解释一下这个Dockerfile:
第一行,选择镜像依赖。这里依赖的是openjdk,版本是8
第二行,标明镜像所有者
第三行,加载卷/tmp
第四行,将tar.gz包添加到容器中。这里使用ADD命令是因为ADD命令可以自动解压。若使用COPY命令,则需要自行解压。
第五行,设置工作目录。进入容器中的默认目录
第六行,容器启动成功之后,执行的命令(最后一行需要注意,脚本命令必须是前端执行而非后台执行,否则容器启动失败)
7:安装JAVA、Maven环境(因为使用Maven打包,因此必须安装Maven环境)并设置环境变量
[root@master ~]# vi /etc/profile
export MAVEN_HOME=/usr/local/utump/maven/apache-maven-3.6.1
export PATH=$PATH:$MAVEN_HOME/bin
export JAVA_HOME=/usr/local/utump/jdk/jdk1.8.0_131
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
8:创建SpringBoot所写程序服务的rc文件
[root@master shell]# vi basic-app-rc.yaml
apiVersion: v1
kind: ReplicationController #副本控制器RC
metadata:
name: basic-app #RC的名称,全局唯一
spec:
replicas: 1 #Pod副本的期待数量
selector:
app: basic-app #符合目标的Pod拥有此标签
template: #根据此模板创建Pod的副本(实例)
metadata:
labels:
app: basic-app #Pod副本拥有的标签,对应RC的Selector
spec:
containers: #Pod内容器的定义部分
- name: basic-app #容器的名称
image: 192.168.2.152:5000/utump/basic-app #容器对应的Docker image
ports:
- containerPort: 20884 #容器应用监听的端口号
请注意:image指向私有仓库地址中的utump/basic-app镜像。
9:创建SpringBoot所写程序服务的svc文件
[root@master shell]# vi basic-app-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: basic-app #service拥有的全局唯一名称
spec:
type: NodePort #表示可通过node端口访问
ports:
- port: 20884 #service提供服务的端口号
nodePort: 30884 #映射的node端口号(30000~32767)
selector:
app: basic-app #service对于pod拥有这里定义的标签
10:创建打包命令脚本basic-app.sh文件
[root@master shell]# vi basic-app.sh
#打包命令使用maven的assembly插件进行打包,打包结果为xxxxx.tar.gz文件
#这里省略打包命令脚本,有需求的同学,可以私聊我。
docker rmi utump/basic-app #删除本地的镜像
docker rmi 192.168.2.152:5000/utump/basic-app #删除私有仓库上的镜像
# docker commit
#执行docker命令
docker build -t utump/basic-app . #创建镜像
#上传docker镜像
docker tag utump/basic-app 192.168.2.152:5000/utump/basic-app #给镜像打上私库的标签
docker push 192.168.2.152:5000/utump/basic-app #上传镜像到私库
kubectl delete -f /usr/local/utump/deploy/shell/basic-app-rc.yaml #删除已经存在的rc
kubectl delete -f /usr/local/utump/deploy/shell/basic-app-svc.yaml #删除已经存在的服务
kubectl create -f /usr/local/utump/deploy/shell/basic-app-rc.yaml #创建rc
kubectl create -f /usr/local/utump/deploy/shell/basic-app-svc.yaml #创建服务
11:执行打包命令脚本basic-app.sh文件
11.1 检查pod状态
[root@master shell]# kubectl get pod
NAME READY STATUS RESTARTS AGE
basic-app-fn724 1/1 Running 0 49m
mysql-p5bbl 1/1 Running 1 5d21h
zookeeper-8ljwz 1/1 Running 0 61m
11.2 检查docker启动日志
[root@master shell]# kubectl logs basic-app-fn724
12:在节点上检查容器启动情况
[root@node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4d852f610dd8 192.168.2.152:5000/utump/basic-app "/usr/local/utump/de…" About an hour ago Up About an hour k8s_basic-app_basic-app-fn724_default_43cca0d1-8b48-11e9-84ee-080027b45424_0
13:登录容器,检查服务启动情况
[root@node1 ~]# docker exec -it 4d852f610dd8 /bin/sh
/usr/local/utump/deploy/app/basic-app/bin #
注意,这里使用后缀/bin/sh而不是使用/bin/bash的原因是,在Dockerfile文件中,定义依赖的镜像是FROM openjdk:8-jdk-alpine。alpine版本的jdk只能使用/bin/sh命令!
14:遇到的坑以及问题解决
14.1 第11步执行完成之后,查看pod节点信息,显示如下信息:
[root@master shell]# kubectl get pod
NAME READY STATUS RESTARTS AGE
basic-app-kj95z 0/1 ImagePullBackOff 0 16s
basic-app-v7pzg 0/1 ImagePullBackOff 0 16s
mysql-p5bbl 1/1 Running 0 4h21m
然后查看详细错误信息时,提示:
Failed to pull image "192.168.2.152:5000/utump/basic-app": rpc error: code = Unknown desc = Error response from daemon: Get https://192.168.2.152:5000/v2/: http: server gave HTTP response to HTTPS client
则说明节点服务器无法通过这个地址访问到私服并进行拉取镜像。
解决方案:在节点添加私库信息
[root@node1 ~]# vi /etc/docker/daemon.json
{"registry-mirrors":["https://registry.docker-cn.com"], "exec-opts": ["native.cgroupdriver=systemd"], "insecure-registries":["192.168.2.152:5000"]}
将192.168.2.152:5000添加到节点docker服务信息中。
14.2 服务启动失败,或者不执行tar.gz包中的bin/start.sh脚本
通过11.2步骤中的启动日志来具体分析。而我遇到的情况竟然是因为程序依赖的ZK服务没有启动,因此我拉取了一个公共的zk镜像并部署在节点上,然后再进行服务的部署,即可成功。
如何部署ZK镜像,可以参考前面一节K8S集群系列二:来个DEMO中的内容。
到此,部署自己所写代码到docker中已完成,如有疏漏,还请见谅。