实战交付dubbo服务到k8s

一、什么是Dubbo是什么

●   Dubbo是什么●   Dubbo基于java开发的,是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。●   Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。●   简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求,并且本质上是个服务调用的东东,说白了就是个远程服务调用的分布式框架●   Dubbo能做什么●   透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。●   软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。●   服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。

服务发现依赖于注册中心,不管是消费者还是提供者都需要连接注册中心,提供者去注册中心里面注册的过程叫注册,消费者去连接注册中心的过程叫做订阅。这样Consumer跟Provider都连接了注册中心,这时候Consumer通过invokre(RPC协议,远程过程调用)去调用一个Provider服务的一个方法,就好像Consumer调用自己本地的方法一样
为什么要用dubbo:
一个网站界面或者说一个前台的web工程,此页面里面可能有商品的浏览页、会员、个人用户中心、抽奖活动等等,各自的模块,我们以Consumer消费者代替(浏览页Consumer、会员Consumer等等)。这些页面的各个模块,需要调用后台不同的API接口,各个api我们以Provide生产者代替(浏览页Provide、会员Provide等等)。假如我们把整个前台页面代码,和后台实现的api口,都封装在一套代码中,势必就存在如果本地资源无线扩涨,根本不利于横向扩容(比如促销活动只是需要访问大量的抽奖活动,其他的页面模块访问量并不大,怎么办,加机器做负载么,代码都在一起,全部代码在跑一遍?负载怎么做)。所以势必要更换框架,更换机制,把后台的各种api接口跟前台代码就行解耦(每个程序之间的关联程度,叫做耦合度,上述描述中都卸载一套程序,只要改了一个地方,可能其他的地方也要跟着改,这就叫做耦合度高,所以我们要接触耦合度高,让代码分开,叫做解耦)。
dubbo的机制:
思考:会员、积分、消费页面等等都进行了代码解耦后,直接前台连接后台api就行了,注册中心、服务发现又是什么?如果一个客户在网站买一个商品,他会经历下单结算界面(使用了优惠券),点击支付的时候,后台会先去验证消费券并给当前用户删除这个消费卷,然后再返回支付的界面成功,消费券也会删除。这一套流程看似没问题,但是如果在流量高峰期,就会卡的不要不要的。为了解决这种情况,引入了注册中心,消费者Consumer(各个前台页面的代码)去向注册中心提交自身信息(过程叫订阅),告知有我这个页面,而提供者Provide(各个后台的api接口)也向注册中心提交自身信息(过程叫注册),告知有那些api的接口。然后有意思的来了,还是客户在网站买一个商品,经历下单结算界面(使用了优惠券),会把这些信息告诉注册中心,由于其他的api接口实时的在监听中心注册的变化,所以api进行了服务的自动发现,简称服务发现,这些对应的api接口,发现一个Consumer的服务请求,并对应的优惠券、结算页面同时,获取了信息,所以同时处理请求谁也不会卡着谁。所以使用不同Provider方法(API接口),让Consumer调用不同的一个单独的独立服务,就好像调用自己本地的方法一样。
Monitor 监控中心:可以监控发现有多少个Consumer消费者、多少个Provide提供者,他们之间怎么关联的、存在什么问题。
所以交付Dubbo微服务流程:第一交付Registry注册中心、第二交付Provider提供者、第三交付Monitor监控中心、第四交付Consumer消费者

二、Dubbo部署k8s中实验架构图

1、交付zoopkeeper
图中zk1、zk2、zk3,全名zoopkeeper,Dubbo微服务的注册中心依赖于zk(zoopkeeper)来实现的,用来存储生产者、消费者、dubbo运行过程中的一些信息。最低由三个zoopkeeper实现集群做高可用,他跟etcd注册中心机制一样有leader,leader死了留遗言下一个谁是leader。其他的注册中心软件比如:Eureka、etcd、zoopkeeper、Consul底层原理一样,开发语言不同而已

2、交付Consumer消费者集群、Provider提供者集群
下面是要部署在k8s内部的集群

有Dubbo微服务的Consumer消费者集群,有Dubbo微服务的Provider提供者集群,最后都都封装成pod交付到k8s里,其中把商品、抽奖活动、等等封装成各自的pod。为什么把Consumer、Provider做成pod方便扩容(比如到秒杀环节,有大量的收银、订单中心请求,大量用户一瞬间挤进来。前台web(consumer消费者)能扛得住,但是调用对应的后端服务(Provider生产者)扛不住,因为后端要连接数据库,会有延迟,产生瓶颈,所以就需要有方法扩容,把这种能动态扩容的服务,统统放到k8s中,实现动态扩容、迁移等等,管理Dubbo微服务。)

3、交付Dubbo-Monitor监控中心到k8s中,其他组件dubbo-admin也可实现

4、开发提交代码到git,使用jenkins编译成imgae后推送到harbor,通过image交付到k8s
尽量模拟生产环境,所以开发写完代码会把代码提交到git、或者svn代码版本控制中心,运维使用恰当的工具,比如jenkins进行持续继承(就是把代码从git拉取下来,自动化把代码进行编译,然后打成image镜像,自动推送到harbor私有仓库),图中ops服务器就是hdss7-200(DevOps是为了填补开发端和运维端之间的信息鸿沟,所以ops服务器就是开发跟研发对接的一个服务器),通过image配置资源配置清单,应用到k8s,pod启动后自己会找注册中心,进行注册

注释:

1、用户通过ingress资源配置好规则,找到消费者集群的pod,因为消费者集群对应的是web服务,消费者去找对应的提供者集群,获取对应的信息返回到消费者后,消费者把对应的流量反馈给用户

2、Dubbo 可以部署多个消费者、多个生产者,生产中100~200左右属于在正常不过

3、其中把zoopkeeper放在k8s的外部,不要部署在k8s集群中,因为zoopkeeper是典型的有状态服务,但有状态的也可以服务部署在k8s中,但还是不建议。
解释:k8s有很强的动态性,可以飘逸、扩容、缩容、删除、重建、自愈机制,所以要求pod管理的一定是没有状态的资源。有状态服务:etc、zoopkeeper、mysql、ES、MQ缓存(MQ缓存比如redis还好,应用到k8s中,可以落盘可以做持久化,但是缓存的数据不会保证,随着pod宕机会没,如果觉的什么都不能丢,使用关系型数据库)。没有状态:随便飘逸,随便宕机、不依赖于其他。但是也不是说mysql这种有状态的不能承载pod中,有专门的pod控制器StatefulSet进行管理,比如部署 MySQL,启动一片mysql,应该先启动那个,在启动那个,主、从配置有什么差别,应该什么主从关系,StatefulSet进行声明。

4、其中jenkins也是有状态的服务,只不过把有状态的那部分存储给挂在出来到本地,但是也不能扩容成两份,除非做主从。

三、部署zoopkeeper集群

●   Zookeeper是Dubbo微服务集群的注册中心
     ●   它的高可用机制和K8S的etcd集群一致
     ●   由Java编写,所以需要jdk环境

ZK集群是有状态的服务,跟ETCD运行方式类似,要求集群节点是不低于3的奇数个,然后进行选举Leader。

主机

IP地址

角色

hdss7-11

10.4.7.11

zk1

hdss7-12

10.4.7.12

zk2

hdss7-21

10.4.7.21

zk3

在hdss7-11、hdss7-12、hdss7-21 都需要操作

1、JDK配置

1.1、下载JDK

https://download.oracle.com/otn/java/jdk/8u231-b11/5b13a193868b4bf28bcb45c792fce896/jdk-8u231-linux-x64.tar.gz

1.2、安装JDK

1、解压JDK
[root@hdss7-11 ~]# mkdir -p /opt/src;cd /opt/src
[root@hdss7-11 src]# rz jdk-8u231-linux-x64.tar.gz
[root@hdss7-11 src]# mkdir -p /usr/java/
[root@hdss7-11 src]# tar zxvf jdk-8u231-linux-x64.tar.gz -C /usr/java/
[root@hdss7-11 ~]# cd /usr/java/
[root@hdss7-11 java ]# ln -s jdk1.8.0_231/ jdk

2、java做环境变量
[root@hdss7-11 java]# vi /etc/profile     # 在profile文件末尾追加如下配置

export JAVA_HOME=/usr/java/jdk
export PATH=$JAVA_HOME/bin:$JAVA_HOME/bin:$PATH
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar

[root@hdss7-11 java]# source /etc/profile
[root@hdss7-11 java]# echo $CLASSPATH
:/usr/java/jdk/lib:/usr/java/jdk/lib/tools.jar

[root@hdss7-11 java]# echo $PATH
/usr/java/jdk/bin:/usr/java/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

[root@hdss7-11 java]# java -version
java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)

2、安装zoopkeeper

[root@hdss7-11 opt]# cd /opt/src
[root@hdss7-11 src]# wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz
[root@hdss7-11 src]# tar -xf zookeeper-3.4.14.tar.gz -C /opt/
[root@hdss7-11 src]# cd /opt/
[root@hdss7-11 opt]# ln -s zookeeper-3.4.14/ zookeeper
[root@hdss7-11 opt]# mkdir -p /data/zookeeper/data /data/zookeeper/logs
[root@hdss7-11 zookeeper]# vim /opt/zookeeper/conf/zoo.cfg  # 配置zookeeper的配置文件

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/logs
clientPort=2181
server.1=zk1.od.com:2888:3888
server.2=zk2.od.com:2888:3888
server.3=zk3.od.com:2888:3888

解释:
server.1=zk1.od.com:2888:3888    # 把zookeeper服务的做成了dns,所以还要做dns解析
server.2=zk2.od.com:2888:3888    # zk1对应10.4.7.11     zk2对应10.4.7.12
server.3=zk3.od.com:2888:3888    # zk3对应10.4.7.21

在hdss7-11操作

3、配置DNS解析

[root@hdss7-11 named]# vi /var/named/od.com.zone

$ORIGIN od.com.
$TTL 600        ; 10 minutes
@               IN SOA  dns.od.com. dnsadmin.od.com. (2020010505 ; serial10800      ; refresh (3 hours)900        ; retry (15 minutes)604800     ; expire (1 week)86400      ; minimum (1 day))NS   dns.od.com.
$TTL 60 ; 1 minute
dns                A    10.4.7.11
harbor             A    10.4.7.200
k8s-yaml           A    10.4.7.200
traefik            A    10.4.7.10
dashboard          A    10.4.7.10
zk1                A    10.4.7.11
zk2                A    10.4.7.12
zk3                A    10.4.7.21

解释:
2020010505 ; serial   序列号前滚一位
zk1                A    10.4.7.11    添加
zk2                A    10.4.7.12    添加
zk3                A    10.4.7.21    添加

[root@hdss7-11 named]# systemctl restart named
[root@hdss7-11 named]# dig -t A zk1.od.com @10.4.7.11 +short
10.4.7.11

在hdss7-11、hdss7-12、hdss7-21 都需要操作

4、配置myld

只有创建了myld,才能实现把7-11、7-12、7-21三个节点的zookeeper做成集群,区分作用跟谁是主节点无关

[root@hdss7-11 named]# echo 1 > /data/zookeeper/data/myid
[root@hdss7-12 named]# echo 2 > /data/zookeeper/data/myid
[root@hdss7-21 named]# echo 3 > /data/zookeeper/data/myid

5、启动zookeeper

[root@hdss7-11 ]# /opt/zookeeper/bin/zkServer.sh start
[root@hdss7-12 ]# /opt/zookeeper/bin/zkServer.sh start
[root@hdss7-21 ]# /opt/zookeeper/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

[root@hdss7-11 named]# ps aux |grep zookeeper

root      19691  7.2  4.7 2284764 47048 pts/0   Sl   16:17   0:01 /usr/java/jdk/bin/java -Dzookeeper.log.dir=. -Dzookeeper.root.logger=INFO,CONSOLE -cp /opt/zookeeper/bin/../zookeeper-server/target/classes:/opt/zookeeper/bin/../build/classes:/opt/zookeeper/bin/../zookeeper-server/target/lib/*.jar:/opt/zookeeper/bin/../build/lib/*.jar:/opt/zookeeper/bin/../lib/slf4j-log4j12-1.7.25.jar:/opt/zookeeper/bin/../lib/slf4j-api-1.7.25.jar:/opt/zookeeper/bin/../lib/netty-3.10.6.Final.jar:/opt/zookeeper/bin/../lib/log4j-1.2.17.jar:/opt/zookeeper/bin/../lib/jline-0.9.94.jar:/opt/zookeeper/bin/../lib/audience-annotations-0.5.0.jar:/opt/zookeeper/bin/../zookeeper-3.4.14.jar:/opt/zookeeper/bin/../zookeeper-server/src/main/resources/lib/*.jar:/opt/zookeeper/bin/../conf::/usr/java/jdk/lib:/usr/java/jdk/lib/tools.jar -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false org.apache.zookeeper.server.quorum.QuorumPeerMain /opt/zookeeper/bin/../conf/zoo.cfg
root      19795  0.0  0.0 112828   968 pts/0    S+   16:17   0:00 grep --color=auto zoo
[root@hdss7-11 named]# netstat -tulpn |grep 2181   # zookeeper默认启动2181,所以不管是消费者还是生产者,都要跟集群的2181连接
tcp6       0      0 :::2181                 :::*                    LISTEN      19691/java          

6、查看领导者

查看集群状态,如下这种说明已经是集群了,leader主节点,follower从节点

[root@hdss7-11 named]# /opt/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Mode: follower

[root@hdss7-12 opt]#  /opt/zookeeper/bin/zkServer.sh status      
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Mode: leader

[root@hdss7-21 opt]#  /opt/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Mode: follower

7、自启动

在hdss7-11、hdss7-12、hdss7-21 都需要操作

1.进入到/etc/init.d目录下,新建一个zookeeper脚本
[root@hdss7-11 named]# cd /etc/init.d
[root@hdss7-11 /init.d]# vi zookeeper     # service服务启动 /etc/init.d/ 目录下的脚本

#!/bin/bash
#chkconfig:2345 20 90
#description:zookeeper
#processname:zookeeper
export JAVA_HOME=/usr/java/jdk
case $1 in    start) su root /opt/zookeeper/bin/zkServer.sh start;;    stop) su root /opt/zookeeper/bin/zkServer.sh stop;;    status) su root /opt/zookeeper/bin/zkServer.sh status;;    restart) su root /opt/zookeeper/bin/zkServer.sh restart;;    *) echo "require start|stop|status|restart" ;;
esac

解释:

脚本很简单,运行脚本并给赋予一个$1,脚本中获取的$1如果是start,就启动、获取的$1如果是stop,就停止。

2.给脚本添加执行权限
[root@hdss7-11 /init.d]# chmod +x zookeeper

3.通过service命令启动、停止、重启脚本、查看状态
使用service zookeeper start/stop命令来尝试启动关闭zookeeper,使用service zookeeper status查看zookeeper状态。或者直接 zookeeper start/stop/status

4.添加到开机启动
[root@hdss7-11 /init.d]# chkconfig --add zookeeper

5.查看开机自启的服务中是否已经有我们的zookeeper

[root@7-11 init.d]# chkconfig --list zookeeperNote: This output shows SysV services only and does not include nativesystemd services. SysV configuration data might be overridden by nativesystemd configuration.If you want to list systemd services use 'systemctl list-unit-files'.To see services enabled on particular target use'systemctl list-dependencies [target]'.zookeeper       0:off   1:off   2:on    3:on    4:on    5:on    6:off

四、安装部署jenkins

Jenkins是一款由Java编写的开源的持续集成工具。它运行在java的Servlet容器中(例如Apache Tomcat),注意java的Servlet容器,并不是k8s的容器。Servlet、Servlet容器等内容讲解。它支持软件配置管理(SCM)工具(包括AccuRev SCM、CVS、Subversion、Git、Perforce、Clearcase和RTC),可以执行基于Apache Ant和Apache Maven的项目,以及任意的Shell脚本和Windows批处理命令。Jenkins是一个有状态的应用,如果托管在K8S中,只运行一个副本,且需要持久化存储。
官网:Jenkins
下载地址:Jenkins 的安装和设置
官方文档:https://jenkins.io/zh/doc/

在hdss7-200 操作

1、下载Jenkins官方镜像

官方jenkins:2.190.3

[root@hdss7-200 ~]# docker pull jenkins/jenkins:2.190.3
[root@hdss7-200 ~]# docker image ls |grep jenkins
jenkins/jenkins                                                      2.190.3                         22b8b9a84dbe        13 months ago       568MB
[root@hdss7-200 ~]# docker tag 22b8b9a84dbe harbor.od.com:180/public/jenkins:v2.190.3
[root@hdss7-200 ~]# docker login harbor.od.com:180
[root@hdss7-200 ~]# docker push harbor.od.com:180/public/jenkins:v2.190.3

2、制作Jenkins镜像

2.1、自定义Dockerfile

注意官方jenkins不能直接使用,需要用自定义Dockerfile对官方的jenkins镜像做一些改变,加上如何拉取镜像,登录使用什么账户等

[root@hdss7-200 ~]# mkdir -p /data/dockerfile/jenkins/
[root@hdss7-200 ~]# cd /data/dockerfile/jenkins/
[root@hdss7-200 jenkins]# vim Dockerfile  # 该脚本主要是docker-ce源中安装了一个docker-ce-cli

# 修改默认的 Jenkins 镜像
FROM harbor.od.com:180/public/jenkins:v2.190.3
USER root
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ADD id_rsa /root/.ssh/id_rsa
ADD config.json /root/.docker/config.json
ADD get-docker.sh /get-docker.sh
RUN echo "      StrictHostKeyChecking no" >> /etc/ssh/ssh_config && sh /get-docker.sh ; rm -f get-docker.sh

解释:
FROM harbor.od.com:180/public/jenkins:v2.190.3   使用的是harbor的jenkins:v2.190.3 
USER root   声明root,启动docker的时候要用root用户启动,默认docker是普通用户

RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone   执行cp 把Asia/Shanghai 放到了/etc/下并重命名localtime,也就是说把docker的时区改成东八区,jenkins是外国人开发的,所以默认镜像里面的时间为UTC时间

ADD id_rsa /root/.ssh/id_rsa    物理机hdss7-200生成一对ssh密钥,把私钥拷贝到容器,到时候gitee上存放hdss7-200的公钥,这样docker容器才能拉取代码。是这样的Dubbo服务中消费者是git ssh拉取代码,git克隆拉代码,两种方式:(1、httrp协议  2、ssh),如果走ssh必须生成密钥对,把私钥封装在docker镜像里面,把公钥放到git仓库,这样docker就能从git拉取到镜像

ADD config.json /root/.docker/config.json 只要运行了一次docker login harbor.do.com:180并登录成功了,就会在本地生成/root/.docker/config.json文件,里面记录了你登录的信息,记录了登录账户密码,下次再登录的时候,就不用输入账户密码。所以config.json是登录远程仓库的认证信息,里面有user\username\passwd,jenkins要打包成docker镜像,并推送到harbor仓库里面,就必须要先登录harbor仓库,把物理机7-200的/root/.docker/config.json拷贝带容器中,容器直接可以登录harbor仓库

[root@hdss7-200 jenkins]# cat /root/.docker/config.json 
{
    "auths": {
        "harbor.od.com:180": {
            "auth": "YWRtaW46SGFyYm9yMTIzNDU="
        }
    },
    "HttpHeaders": {
        "User-Agent": "Docker-Client/19.03.13 (linux)"
    }

ADD get-docker.sh /get-docker.sh    重要操作,要在jenkins容器里面装一个docker客户端,因为jenkins要执行docker build,就是jenkins把代码拉取下来后,打包编译成jar包或者war包后,变成docker镜像,必然要使用docker命令。注,jenkins做成了image并运行在容器中,但并不代表容器能运行容器的命令。所以jenkins的容器要运行docker命令要不在容器里面安装一个docker服务,但jenkins容器里面安装docker引擎不建议,麻烦费时费力。有没有更简单的,有直接依赖宿主机的docker引擎,只要在jenkins容器里面装一个docker客户端,因为docker的客户端才能执行docker命令,通过能够和宿主机docker引擎通信进行操作。

echo "    StrictHostKeyChecking no" >> /etc/ssh/ssh_config && sh /get-docker.sh ; rm -f get-docker.sh    优化ssh ,ssh每次连接一台新的主机的时候,提示输入yes/no指纹验证,由于gitee是公网,每次拉取IP都不一样,所以不能每次都输入yes/no

2.2、做ssh密钥

[root@hdss7-200 ~]# ssh-keygen -t rsa -b 2048 -C "1151939762@qq.com" -N "" -f /root/.ssh/id_rsa
[root@hdss7-200 .ssh]# cat /root/.ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6n7YCHPECZzVk31gLP3sbuK3US4DMimYM9Bs/2G/VZFhXV8brEPMUK+VJOya4vz0tZyoz5NnJbg6ZJSzn4e5otqyP17py/3Hrx2uYonlCBc1cea6OTcX1FigGisHk1f7AZu507QJXwKDC6dLFmB0bKNjgVx8QKpQxfI5hK7SFwSzAU6WAHIDIXAcqf1FGg1mHwO9JaWjBLFz2+lNiWE645X0mNhjAMzgozu2n2d7KmlcuAsSJtstVTqzUqlwCBv5k2DIewYIHdadLiiUgdNEdzbDnxd3oCf3oWwUxiUToJgz3gsy4C0Q91ZIu4bmiSQNrUBjrd24tLLH4u6ngTy/V 1151939762@qq.com

拷贝私钥、config.json

[root@hdss7-200 .ssh]# cd /data/dockerfile/jenkins/
[root@hdss7-200 jenkins]# cp /root/.ssh/id_rsa ./
[root@hdss7-200 jenkins]# cp /root/.docker/config.json ./
[root@hdss7-200 jenkins]# ll
-rw-------. 1 root root  156 12月 26 11:21 config.json
-rw-r--r--. 1 root root  376 12月 26 10:31 Dockerfile
-rw-------. 1 root root 1675 12月 26 11:20 id_rsa

2.3、配置get-docker.sh

[root@hdss7-200 .ssh]# cd /data/dockerfile/jenkins/
[root@hdss7-200 jenkins]# wget -O get-docker.sh https://get.docker.com
[root@hdss7-200 jenkins]# chmod +x get-docker.sh
[root@hdss7-200 jenkins]# ll
-rw-------. 1 root root   156 12月 26 11:21 config.json
-rw-r--r--. 1 root root   376 12月 26 10:31 Dockerfile
-rwxr-xr-x. 1 root root 13857 12月  9 12:25 get-docker.sh
-rw-------. 1 root root  1675 12月 26 11:20 id_rsa

2.4、创建私有infra仓库

# 在harbor创建一个名字是infra的一个私有仓库,是infrastructure(基础设置)的缩写

2.5、制作Jenkins镜像

[root@hdss7-200 jenkins]# docker image build -t harbor.od.com:180/infra/jenkins:v2.190.3 ./

Sending build context to Docker daemon  20.48kB
Step 1/7 : FROM harbor.od.com:180/public/jenkins:v2.190.3---> 22b8b9a84dbe
Step 2/7 : USER root---> Running in c91da102040f
Removing intermediate container c91da102040f---> 9982d5de38d9
Step 3/7 : RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone---> Running in 609b6609ac97
Removing intermediate container 609b6609ac97---> 6e6ea342af35
Step 4/7 : ADD id_rsa /root/.ssh/id_rsa---> 3a3f6325a9ae
Step 5/7 : ADD config.json /root/.docker/config.json---> b7009a0f8917
Step 6/7 : ADD get-docker.sh /get-docker.sh---> 4834c5785cfe
Step 7/7 : RUN echo "    StrictHostKeyChecking no" >> /etc/ssh/ssh_config && sh /get-docker.sh---> Running in 29c0569072bf
# Executing docker install script, commit: 3d8fe77c2c46c5b7571f94b42793905e5b3e42e4
+ sh -c apt-get update -qq >/dev/null
+ sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
debconf: delaying package configuration, since apt-utils is not installed
+ sh -c curl -fsSL "https://download.docker.com/linux/debian/gpg" | apt-key add -qq - >/dev/null
Warning: apt-key output should not be parsed (stdout is not a terminal)
+ sh -c echo "deb [arch=amd64] https://download.docker.com/linux/debian stretch stable" > /etc/apt/sources.list.d/docker.list
+ sh -c apt-get update -qq >/dev/null
+ [ -n  ]
+ sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
debconf: delaying package configuration, since apt-utils is not installed
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:sudo usermod -aG docker your-userRemember that you will have to log out and back in for this to take effect!WARNING: Adding a user to the "docker" group will grant the ability to runcontainers which can be used to obtain root privileges on thedocker host.Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surfacefor more information.
Removing intermediate container 29c0569072bf---> 28da51376a1d
Successfully built 28da51376a1d
Successfully tagged harbor.od.com:180/infra/jenkins:v2.190.3

异常处理1:

使用build的时候,会将系统软件库更新到最新,这样是为了防止有的软件在库里找不到,由于使用的外国网站,所有会出现访问不了外国网站,导致build不成功

异常处理2:如果你发现 build异常的慢,而且有可能导致失败,可以指定使用阿里云,在get-docker.sh后加上--mirror=Aliyun
[root@hdss7-200 jenkins]# vim Dockerfile  # 最后一句修成这样

RUN echo "      StrictHostKeyChecking no" >> /etc/ssh/ssh_config && sh /get-docker.sh ; rm -f get-docker.sh --mirror=Aliyun 

异常处理3:build后报错如下

报错1:
DEPRECATION WARNINGThis Linux distribution (debian stretch) reached end-of-life and is no longer supported by this script.No updates or security fixes will be released for this distribution, and users are recommendedto upgrade to a currently maintained version of debian.
Press Ctrl+C now to abort this script, or wait for the installation to continue.解决:这个只不过是警告,可以不用理会,可能是get-docker.sh太新,而且内容太有些不支持,下载老版本的的get-docker.sh,可获取博主的资源报错2:
: Unable to locate package docker-scan-plugin
The command '/bin/sh -c echo "  StrictHostKeyChecking no" >> /etc/ssh/ssh_config && sh /get-docker.sh' returned a non-zero code: 100解决:他的意思是在docker中下载docker-scan-plugin异常,通过百度搜索
方案1:未解决1、apt-get update2、在安装包之前,如果命令位于dockerfile中,则需要添加-y(跳过系统提示,直接安装)apt-get -y install wget3、为了避免输出可以添加 -qq参数apt-get -qq -y install wget
如果细心的小伙伴会发现,其实在built中,有执行apt-get -qq update,所以应该不是这个导致,而且你在Docker中,加入apt-get update也不行
方案2:未解决
get-docker.sh使用百度云索引,上述中的get-docker.sh --mirror=Aliyun ,也不行
方案3:解决
思考,其实就是get-docker.sh报错,但是为什么下载不了docker-scan-plugin,还有一种可能,连
不上网,导致下载不了,而我在宿主机中测试,可以下载,如果通过docer run -ti 容器 /bin/bash进入容器后,发现,确实连不上网了,而这时候,我发现,容器ping宿主机IP无问题,可是宿主机
的网关、DNS都不通,这就是为什么不能下载docker-scan-plugi,为什么这样,最后是由于
daemon.json,没有加"bip": "172.7.21.1/24"。如何判断查看https://blog.csdn.net/Jerry00713/article/details/119427602

2.6、上传Jenkins镜像

[root@hdss7-200 jenkins]# docker login harbor.od.com:180
[root@hdss7-200 jenkins]# docker push harbor.od.com:180/infra/jenkins:v2.190.3

3、 验证容器连接gitee

jenkins镜像是否可以连接gitee

​​​​​​​[root@hdss7-200 jenkins]# docker run --rm harbor.od.com:180/infra/jenkins:v2.190.3 ssh -i /root/.ssh/id_rsa -T git@gitee.com
Warning: Identity file /root.ssh/id_rsa not accessible: No such file or directory.
Warning: Permanently added 'gitee.com,212.64.62.183' (ECDSA) to the list of known hosts.
Permission denied (publickey).    拒绝,公钥没有拷贝到gitee

[root@hdss7-200 jenkins]# cat /root/.ssh/id_rsa.pub    # 把数据拷贝到gitee

[root@hdss7-200 jenkins]# docker run --rm harbor.od.com:180/infra/jenkins:v2.190.3 ssh -i /root/.ssh/id_rsa -T git@gitee.com

其中 does not provide shell access意思就是你不需要输入yes/no

4、上传代码到gitee(如有项目可不做)

本文是把StanleyWang / dubbo-demo-service的资源上传自给的gitee Jerry00713 / dubbo-demo-service

[root@hdss7-200 ~]# yum install -y git
[root@hdss7-200 ~]# git clone git@gitee.com:stanleywang/dubbo-demo-service.git
[root@hdss7-200 ~]# cd dubbo-demo-service/
[root@hdss7-200 dubbo-demo-service]# git config --global user.email "1151939762@qq.com"
[root@hdss7-200 dubbo-demo-service]# git config --global user.name "Jerry00713 "
[root@hdss7-200 dubbo-demo-service]# git remote add dubbo git@gitee.com:jerry00713/dubbo-demo-service.git
[root@hdss7-200 dubbo-demo-service]# git push -u dubbo master

5、配置资源应用于容器

5.1、创建/声明infra名称空间

 在hdss7-21或者hdss7-22 操作

创建一个infra名称空间,因为jenkins也需要放到k8s单独的名称空间,让这个名称空间只运行运维相关的基础设施服务

[root@hdss7-21 ~]# kubectl create ns infra
namespace/infra created

infra命名空间下的pod想从harbor私有仓库拉取镜像,根本拉取不到镜像。需要在infra命名空间创建一个secret资源,把登录harbor.od.com:180用到的管理员账户、密码需要声明出来,pod拉取镜像的时候会带secret资源进行请求。

任意一个运算节点 (如hsdd7-21),在infra命名空间创建一个secret资源,类型是docker-registry 。名字叫harbor,后面参数

[root@hdss7-21 ~]# kubectl create secret docker-registry harbor --docker-server=harbor.od.com:180 --docker-username=admin --docker-password=Harbor12345 -n infra

查看secret(不参与部署):

1、查看infra命名空间下有多少个secret资源

例如新建一个harbor1的secret资源,查看infra命名空间下的所有secret资源[root@7-21 ~]# kubectl get secret -n infra
NAME                  TYPE                                  DATA   AGE
default-token-vj94t   kubernetes.io/service-account-token   3      16m
harbor                kubernetes.io/dockerconfigjson        1      16m[root@7-21 ~]# kubectl create secret docker-registry harbor1 --docker-server=harbor.od.com:180 --docker-username=admin --docker-password=Harbor12345 -n infra
secret/harbor1 created[root@7-21 ~]# kubectl get secret -n infra
NAME                  TYPE                                  DATA   AGE
default-token-vj94t   kubernetes.io/service-account-token   3      16m
harbor                kubernetes.io/dockerconfigjson        1      16m
harbor1               kubernetes.io/dockerconfigjson        1      5s

2、查看infra命名空间下名字叫harbor的secret资源

[root@7-21 ~]# kubectl get secret harbor -o yaml -n infra
apiVersion: v1
data:.dockerconfigjson: eyJhdXRocyI6eyJoYXJib3Iub2QuY29tOjE4MCI6eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJIYXJib3IxMjM0NSIsImF1dGgiOiJZV1J0YVc0NlNHRnlZbTl5TVRJek5EVT0ifX19
kind: Secret
metadata:creationTimestamp: "2021-12-05T11:31:13Z"name: harbornamespace: infraresourceVersion: "35037"selfLink: /api/v1/namespaces/infra/secrets/harboruid: ec6de3ac-a5f0-4a86-b136-1cfb561fe6a1
type: kubernetes.io/dockerconfigjson注:data后面为(名字叫harbor的secret资源)的账户密码

3、解密(名字叫harbor的secret资源)的账户密码

格式:echo "data中的内容" | base64 --decode[root@7-21 ~]# echo "eyJhdXRocyI6eyJoYXJib3Iub2QuY29tOjE4MCI6eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJIYXJib3IxMjM0NSIsImF1dGgiOiJZV1J0YVc0NlNHRnlZbTl5TVRJek5EVT0ifX19" | base64 --decode
{"auths":{"harbor.od.com:180":{"username":"admin","password":"Harbor12345","auth":"YWRtaW46SGFyYm9yMTIzNDU="}}}[root@7-21 ~]#

4、删除不需要的secret资源

[root@7-21 ~]# kubectl delete secret harbor1 -n infra
secret "harbor1" deleted
[root@7-21 ~]# kubectl get secret -o wide -n infra
NAME                  TYPE                                  DATA   AGE
default-token-vj94t   kubernetes.io/service-account-token   3      26m
harbor                kubernetes.io/dockerconfigjson        1      25m如果删除后,会立即以相似的名称进行重建(即使使用 --force)

5.2、创建共享存储

让jenkins的 pod实现持久化数据的共享存储,即使pod宕机,重启一个pod后,数据使用的是共享存储,所以数据不会丢失。注意:要想实现多pod数据实时一致性(比如数据库做双活,A的pod落盘的数据,B的pod要及时更新,相反B的pod落盘,A的pod也要及时更新。比如修改网页的index页面,不用每一个pod都修改)。所以这些pod要把持久化路径挂在一个位置,防止多个pod同时插入数据会乱套。当然jenkins是有状态服务,我们一般会启动一个pod,不会存在多pod,但假设规划pod落盘到7-21的本地目录,如果pod异常了,重启pod后挂载到22节点上呢,以前的数据就没了。还有一种方案,给所有的pod打污点,只有7-21的能容忍,只能调度到7-21的节点,但是不是害的考虑7-21节点的负载情况,jenkins是java项目吃资源,所以那还不如做共享存储目录简单,而且数据还能得到保障。NFS共享存储放在 hdss7-200 上,用于存储Jenkins持久化文件。所有Node节点和hdss7-200都需要安装NFS,通过NFS间接让Node节点的数据存放在中hdss7-200的共享存储目录,挂在hdss7-200的指定NFS

在hdss7-21、hdss7-22、hdss7-200 都需要操作
[root@hdss7-21 ~]# yum install -y nfs-utils
[root@hdss7-22 ~]# yum install -y nfs-utils
[root@hdss7-200 ~]# yum install -y nfs-utils

在hdss7-200操作,共享存储在hdss7-200 上,所有节点需要挂在hdss7-200存储端

[root@hdss7-200 ~]# mkdir /data/nfs-volume
[root@hdss7-200 ~]# vim /etc/exports

/data/nfs-volume  10.4.7.0/24(rw,sync,no_root_squash)

解释:
把/data/nfs-volume目录共享给10.4.7.0/24
参数rw :可读可以写
参数no_root_squash:登入 NFS 主机使用分享目录的使用者,如果是 root 的话,那么对于这个分享的目录来说,他就具有 root 的权限,单词squash是压缩压扁的意思,这种配置不建议使用不安全。
参数root_squash:在登入 NFS 主机使用分享之目录的使用者如果是 root 时,那么这个使用者的权限将被压缩成为匿名使用者,通常他的 UID 与 GID 都会变成 nobody 那个系统账号的身份;

在hdss7-21、hdss7-22、hdss7-200 都需要操作
[root@hdss7-200 jenkins]# systemctl start nfs;systemctl enable nfs
[root@hdss7-21 jenkins]# systemctl start nfs;systemctl enable nfs
[root@hdss7-22 jenkins]# systemctl start nfs;systemctl enable nfs

共享存储怎么应用:使用资源配置清单应用共享存储

5.3、 配置资源配置清单

在hdss7-200 操作

[root@hdss7-200 k8s-yaml]# mkdir -p /data/k8s-yaml/jenkins
[root@hdss7-200 k8s-yaml]# cd /data/k8s-yaml/jenkins/
[root@hdss7-200 jenkins]# vi deployment.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:name: jenkinsnamespace: infralabels: name: jenkins
spec:replicas: 1selector:matchLabels: name: jenkinstemplate:metadata:labels: app: jenkins name: jenkinsspec:volumes:- name: datanfs: server: hdss7-200path: /data/nfs-volume/jenkins_home- name: dockerhostPath: path: /run/docker.socktype: ''containers:- name: jenkinsimage: harbor.od.com:180/infra/jenkins:v2.190.3imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPenv:- name: JAVA_OPTSvalue: -Xmx512m -Xms512mvolumeMounts:- name: datamountPath: /var/jenkins_home- name: dockermountPath: /run/docker.sockimagePullSecrets:- name: harborsecurityContext: runAsUser: 0strategy:type: RollingUpdaterollingUpdate: maxUnavailable: 1maxSurge: 1revisionHistoryLimit: 7progressDeadlineSeconds: 600

解释:

kind: Deployment    # pod控制器主要两种类型:daemonset每一个运算节点启动一个, Deployment 根据设置可以启动随意几个
apiVersion: extensions/v1beta1  # 指定资源连接那个版本的apiserver,,此值必须在kubectl api-versions中
metadata:   # 配置资源的元数据/属性name: jenkins   #  Deployment 资源的名字,在同一个namespace中必须唯一namespace: infra    # 部署在哪个名命空间中,不写的话默认创建在default空间labels:    # 自定义标签name: jenkins #自定义标签名字
spec:  # 资源规范字段replicas: 1         # 声明副本数目,根据设置pod只是启动1个selector:           # 定义选择器​​​​​​​matchLabels:    # 标签选择器,匹配标签,定义如下配置的pod应该连接那个pod控制器name: jenkins # 选择连接名字是jenkins的pod控制器资源template:         # pod模板metadata:  # 配置资源的元数据/属性labels:  # 自定义pod标签app: jenkins   # 标签的名字name: jenkins  # 给dp跟pod进行关联的信息定义一个名字spec:  # 资源规范字段volumes:  # 定义挂载- name: data   # 定义挂载卷的名字,k8s处处是资源,起名字后才能在k8s中找到nfs:         # 定义使用的卷类型, k8s支持nfs驱动。若遇到不支持的存储卷,假设不支持nfs,可以使用pvc,使用它间接支持其他类型的分部式存储,声明pvc,用pvc在声明nfs存储,在pod中挂载pvc.server: hdss7-200   # nfs服务器在哪path: /data/nfs-volume/jenkins_home    # 去nfs服务器找到path目录,并共享路径- name: docker   # 定义挂载卷的名字hostPath:      # 挂载类型是本机,把本机的某一个文件挂载到docker中。scheduler决定pod在那个节点启动,就调用那个本地文件path: /run/docker.sock   # 把本机这个文件共享,docker客户端就可以跟宿主机的docker服务端进行通信type: ''containers:      # 定义容器内部的操作- name: jenkins  # 容器名字image: harbor.od.com/infra/jenkins:v2.190.3   # 使用镜像imagePullPolicy: IfNotPresent # 镜像拉取的策略,默认分为三种:1、always无论本地是不是有这个镜像,都要从从私有harbor镜像仓库中拉取镜像,2、never 无论如何都不去远程仓库拉取镜像,都是用本地的。3、IfNot如果本地没有,就去harbor镜像仓库拉取镜像,ports:         # 定义端口- containerPort: 8080  # 容器开发对外的端口,jenkin启动后监听8080端口,把容器内部的8080端口映射到容器外部,也就是docker -P 8080:8080protocol: TCP   # 协议env:              # 容器运行前,需给容器内部设置或者说是增加环境变量,跟docker -e 一样环境变量- name: JAVA_OPTS  # 给定义此环境变量起名字value: -Xmx512m -Xms512m   # 定义环境变量,JAVA_OPTS=-Xmx512m -Xms512m,设置最大的堆内存是512,jenkins比较吃资源volumeMounts:     # 定义挂在路径,搭配上述配置volumes使用- name: data      # 使用上述定义volumes,名字是data挂载卷mountPath: /var/jenkins_home  # 决定上述data挂载卷,宿主机的/data/nfs-volume/jenkins_home 挂载容器的哪个地方- name: docker    # 使用上述定义volumes,名字是docker挂载卷mountPath: /run/docker.sock   # 决定上述docker挂载卷,宿主机的/run/docker.sock挂载容器的哪个地方imagePullSecrets:   # delpoyment另外的一个重要参数,刚才在infra命名空间创建一个harbor的secret资源,当从harbor私有仓库拉取镜像时必须加上,否则拉不到- name: harbor      # 这里声明使用名字是harbor的secret资源类型是docker-registry (secret docker-registry harbor)securityContext:    # 说明要使用哪个账户启动这个容器runAsUser: 0      # 使用root账户启动这个容器, 0指root用户的uid。strategy:       # 定义策略type: RollingUpdate     # 采用滚动更新的方法,升级jenkins,rollingUpdate:          # 定义滚动更新方法maxUnavailable: 1     # 在更新过程中能够进入不可用状态的Pod的最大值,可以为百分比,也可以为整数,比如maxUnavailable: 30%意思是假如此pod一共启动10份,在更新pod控制器后,10份pod不会同时delete,在创建,而是保证10*30%=3台,始终最大只有3台在更新pod,等某一个pod更新完成后在继续更新其他的pod。如果是maxUnavailable: 1,整数意思是,每次保证1台更新,不能再多了maxSurge: 0           # 表示滚动升级时会先启动0个podrevisionHistoryLimit: 7   # 保留几份更新记录pod 7份提供回滚使用progressDeadlineSeconds: 600   # 启动容器后,多长时间一直没有RUNING判断为失败,失败就会重新启动容器,jenkins比较吃资源,所以不要给太少什么是滚动更新:
滚动更新是一次只更新一小部分副本,成功后,再更新更多的副本,最终完成所有副本的更新。
滚动更新的最大的好处是零停机,整个更新过程始终有副本在运行,从而保证了业务的连续性。如何通过maxUnavailable、maxSurge正确理解滚动更新时候pod会启动多少份
方法是升级期间pod的范围:replicas副本集 - maxUnavailable ~  replicas副本集 + maxSurge
什么意思:就是滚动更新时候maxSurge按照预定会先启动几个pod,所以当前pod数量在replicas副本集 + maxSurge ,而maxUnavailable会保证有几个或者%多少在更新过程中,也就是replicas副本集 - maxUnavailable其中:
1. maxUnavailable: [0%, 100%] 向下取整,比如10个副本,5%的话==0.5个,但计算按照0个;
2. maxSurge: [0%, 100%] 向上取整,比如10个副本,5%的话==0.5个,但计算按照1个;        比如:
maxSurge: 1 表示滚动升级时会先启动1个pod
maxUnavailable: 1 表示滚动升级时允许的最大Unavailable的pod个数
由于replicas为3,则整个升级,pod个数在3-1 ~ 3+1个之间比如:
maxSurge: 1 表示滚动升级时会先启动1个pod
maxUnavailable: 50% 表示滚动升级时允许的最大Unavailable的pod个数
由于replicas为3,则整个升级,pod个数在3*50% ~ 3+1个之间,也就是3*50%=1.5,maxUnavailable向下取整,就是1,所以1~4个之间

滚动更新:https://blog.csdn.net/Jerry00713/article/details/123791842

[root@hdss7-200 jenkins]# vi service.yaml

kind: Service
apiVersion: v1
metadata: name: jenkinsnamespace: infra
spec:ports:- protocol: TCPport: 80targetPort: 8080selector:app: jenkins

 解释:

port: 80   监听在ClusterIP(虚拟的集群网络)的80端口,相当于把容器里面的8080端口映射到集群网络的80端口,定义多少端口都无所谓,但是ingress中监听的是这个端口
targetPort: 8080   容器里面跑的8080端口,dp中配置把容器的8080端口映射出来,然后service再把容器的8080端口映射到集群网络80端口

[root@hdss7-200 jenkins]# vi ingress.yaml

kind: Ingress
apiVersion: extensions/v1beta1
metadata: name: jenkinsnamespace: infra
spec:rules:- host: jenkins.od.comhttp:paths:- path: /backend: serviceName: jenkinsservicePort: 80

解释:
servicePort: 80     这里面的80端口必须跟service.yaml中的port: 80一致,因为ingress中监听的是service的ClusterIP

[root@hdss7-200 jenkins]# mkdir -p /data/nfs-volume/jenkins_home

启动jenkins,在hdss7-21或者hdss7-22操作

[root@hdss7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/jenkins/deployment.yaml
deployment.extensions/jenkins created
[root@hdss7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/jenkins/service.yaml
service/jenkins created
[root@hdss7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/jenkins/ingress.yaml
ingress.extensions/jenkins created
[root@hdss7-21 ~]# kubectl get pods -n infra        jenkins很耗费资源,启动的很慢
NAME                       READY  STATUS             RESTARTS   AGE
jenkins-64ff665996-6kl92   0/1    ContainerCreating  0          4m54s[root@hdss7-21 ~]# kubectl logs jenkins-64ff665996-6kl92 -n infra
Error from server (BadRequest): container "jenkins" in pod "jenkins-64ff665996-6kl92" is waiting to start: ContainerCreating[root@hdss7-21 ~]# kubectl get pods -n infra
NAME                       READY   STATUS    RESTARTS   AGE
jenkins-64ff665996-6kl92   1/1     Running   0          5m27s

[root@hdss7-21 ~]# kubectl logs jenkins-64ff665996-6kl92 -n infra

Running from: /usr/share/jenkins/jenkins.war
webroot: EnvVars.masterEnvVars.get("JENKINS_HOME")
2020-12-27 01:23:47.387+0000 [id=1]    INFO    org.eclipse.jetty.util.log.Log#initialized: Logging initialized @14171ms to org.eclipse.jetty.util.log.JavaUtilLog
2020-12-27 01:23:51.161+0000 [id=1]    INFO    winstone.Logger#logInternal: Beginning extraction from war file

如何判断jenkins完全启动:查看jenkins pod日志,里面有Jenkins is fully up and running说明完全启动,其中jenkins 容器后面的458.086是占用的内存(字节),一个字节=8位

[root@hdss7-21 ~]# kubectl logs jenkins-64ff665996-6kl92 -n infra |egrep "Jenkins is fully up and running"
2020-12-27 09:29:27.355+0000 [id=19]    INFO    hudson.WebAppMain$3#run: Jenkins is fully up and running

查看hdss-7-200的挂载目录:

[root@hdss7-200 jenkins]# ll /data/nfs-volume/jenkins_home
total 36
-rw-r--r--.  1 root root 1643 Mar 28 13:42 config.xml
-rw-r--r--.  1 root root   50 Mar 28 13:41 copy_reference_file.log
-rw-r--r--.  1 root root  156 Mar 28 13:41 hudson.model.UpdateCenter.xml
-rw-------.  1 root root 1712 Mar 28 13:41 identity.key.enc
-rw-r--r--.  1 root root    7 Mar 28 13:41 jenkins.install.UpgradeWizard.state
-rw-r--r--.  1 root root  171 Mar 28 13:41 jenkins.telemetry.Correlator.xml
drwxr-xr-x.  2 root root    6 Mar 28 13:41 jobs
drwxr-xr-x.  3 root root   19 Mar 28 13:41 logs
-rw-r--r--.  1 root root  907 Mar 28 13:41 nodeMonitors.xml
drwxr-xr-x.  2 root root    6 Mar 28 13:41 nodes
drwxr-xr-x.  2 root root    6 Mar 28 13:41 plugins
-rw-r--r--.  1 root root   64 Mar 28 13:41 secret.key
-rw-r--r--.  1 root root    0 Mar 28 13:41 secret.key.not-so-secret
drwx------.  4 root root  265 Mar 28 13:41 secrets
drwxr-xr-x.  2 root root   67 Mar 28 13:42 updates
drwxr-xr-x.  2 root root   24 Mar 28 13:41 userContent
drwxr-xr-x.  3 root root   54 Mar 28 13:41 users
drwxr-xr-x. 11 root root 4096 Mar 28 13:41 war
[root@hdss7-200 jenkins_home]# 

5.4、验证容器是否按照dockerfile执行

1、先确保jenkins启动

[root@hdss7-22 src]# docker ps -a |grep jenkins

3a51d305f3b1        28da51376a1d                            "/sbin/tini -- /usr/…"   12 hours ago        Up 12 hours                                      k8s_jenkins_jenkins-64ff665996-dc8bh_infra_1a1c60e8-ddd7-4a90-b891-0338332f85a2_1
6d82e077333c        harbor.od.com:180/public/pause:latest   "/pause"                 12 hours ago        Up 12 hours                                      k8s_POD_jenkins-64ff665996-dc8bh_infra_1a1c60e8-ddd7-4a90-b891-0338332f85a2_1
2bdd4b0db627        harbor.od.com:180/infra/jenkins         "/sbin/tini -- /usr/…"   19 hours ago        Exited (255) 12 hours ago                        k8s_jenkins_jenkins-64ff665996-dc8bh_infra_1a1c60e8-ddd7-4a90-b891-0338332f85a2_0
74ef8024f5c6        harbor.od.com:180/public/pause:latest   "/pause"                 19 hours ago        Exited (255) 12 hours ago                        k8s_POD_jenkins-64ff665996-dc8bh_infra_1a1c60e8-ddd7-4a90-b891-0338332f85a2_0

2、进入jenkins 的docker容器,要不就用命令,要不用dashboard

命令( docker exec -ti 名字  /bin/bash )

root@jenkins-64ff665996-dc8bh:/# whoami    说明我的用户是root
root
root@jenkins-64ff665996-dc8bh:/# date      说明我的时间是东八区
Mon Dec 28 05:33:38 CST 2020root@jenkins-64ff665996-dc8bh:/# docker ps -a   在容器内, ps -a查看正在运行的容器,然后跟此容器的宿主机docker ps -a查看正在运行的容器是否一致,如果一致,就说明是容器使用的是宿主机的/run/docker.sock
CONTAINER ID        IMAGE                                   COMMAND                  CREATED             STATUS                      PORTS                NAMES
b1628ebcefc3        add5fac61ae5                            "/entrypoint.sh --ap…"   12 hours ago        Up 12 hours                                      k8s_traefik-ingress_traefik-ingress-t27lb_kube-system_dba425b1-328d-4960-bad5-
等等
[root@hdss7-22 src]# docker ps -a
b1628ebcefc3        add5fac61ae5                            "/entrypoint.sh --ap…"   12 hours ago        Up 12 hours                                      k8s_traefik-ingress_traefik-ingress-t27lb_kube-system_dba425b1-328d-4960-bad5-
等等root@jenkins-64ff665996-dc8bh:/# docker login harbor.od.com:180   不用输入账户密码直接登录harbor.od.com:180 ,说明已经使用宿主机/root/.docker/config.json
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded
root@jenkins-64ff665996-dc8bh:/# cat /root/.docker/config.json
{"auths": {"harbor.od.com:180": {"auth": "YWRtaW46SGFyYm9yMTIzNDU="}},"HttpHeaders": {"User-Agent": "Docker-Client/19.03.14 (linux)"}
}root@jenkins-64ff665996-dc8bh:/# ssh -i /root/.ssh/id_rsa -T git@gitee.com     -T测试连接, 指定使用git用户去测试连接gitee.com仓库
Warning: Permanently added 'gitee.com,212.64.62.183' (ECDSA) to the list of known hosts.
Hi Jerry00713 (DeployKey)! You've successfully authenticated, but GITEE.COM does not provide shell access.
Note: Perhaps the current use is DeployKey.
这是一个DeployKey部署公钥,比已经成功被认证,但是gitee.com并不能提供shell接入点,你这是一个部署公钥

异常问题处理:

到检查docker ps -a,发现没有docker,发现jenkins包在harbor中大约在200M左右,在ben'didocker image约在500M左右,此时就是之前构建Dockerfile jenkins问题,docker没有封装进去(此问题对应的上述built报错),具体解决方案看上文,如果在上文中built报错,没有安装docker,而且你已经创建了jenkins的资源,容器已经启动了,这个时候,正确的操作流程为:jenkins缩容为0,删除hdss7-21或者hdss7-22本地的jenkins镜像,删除harbor的jenkins镜像,重新构建jenkins,成功后,推送到harbor,在扩容jenkins缩容为1。为什么解决问题后,重新built,重新提交到barbor中,直接删除已经存在的jenkins容器,deployment会重新拉去一个新的,不就解决了么。因为 deployment.yaml 中的 imagePullPolicy: IfNotPresent 如果本地没有,就去harbor镜像仓库拉取镜像,现在本地已经有了,所以不会在harbor拉

1、停止jenkins容器,做法是,jenkins缩容为0,如果不停止,jenkins的docker启动,hdss7-21或者hdss7-22本地的jenkins镜像删除不掉。kubectl scale deployment jenkins --replicas=0 -n infra   # 缩容为0,或者使用dashboard 缩容为0
kubectl get pods -n infra      # 过一阵子查看是不是容器消亡
docker image ls -a |grep jenkins    # 查看封装的infra的 jenkins镜像的nameid是什么
docker rmi 4c71fe1b453e    #  删除本地镜像,由于jenkins是启动一份,所以这个不在hdss7-21就在hdss7-222、删除harbor的jenkins镜像3、找到built报错原因,冲重新bulit4、提交到harbor5、kubectl scale deployment jenkins --replicas=1 -n infra   # 扩容为1,或者使用dashboard 缩容为1

5.5、 配置jenkins.od.com域名

在hdss7-11操作

[root@hdss7-11 ~]# vi /var/named/od.com.zone

$ORIGIN od.com.
$TTL 600        ; 10 minutes
@               IN SOA  dns.od.com. dnsadmin.od.com. (2020010506 ; serial10800      ; refresh (3 hours)900        ; retry (15 minutes)604800     ; expire (1 week)86400      ; minimum (1 day))NS   dns.od.com.
$TTL 60 ; 1 minute
dns                A    10.4.7.11
harbor             A    10.4.7.200
k8s-yaml           A    10.4.7.200
traefik            A    10.4.7.10
dashboard          A    10.4.7.10
zk1                A    10.4.7.11
zk2                A    10.4.7.12
zk3                A    10.4.7.21
jenkins            A    10.4.7.10

[root@hdss7-11 ~]# systemctl restart named
[root@hdss7-11 ~]# dig -t A jenkins.od.com @10.4.7.11 +short
10.4.7.10

5.6、 访问jenkins.od.com

方式一:通过直接访问jenkins.od.com(正常访问)

方式二:直接绕过dns解析,直接访问容器的IP+端口,但注意需要配置路由,否则无法访问k8s内部资源

[root@hdss7-21 ~]# kubectl get pods -o wide -n infra
NAME                       READY   STATUS    RESTARTS   AGE    IP           NODE                NOMINATED NODE   READINESS GATES
jenkins-64ff665996-dc8bh   1/1     Running   0          2m4s   172.7.22.4   hdss7-22.host.com   <none>           <none>

这里发现jenkins容器飘逸22机器上IP:172.7.22.4,目前只有hdss7-21、hdss7-22才能直接跟172.7.22.0/24通信,hdss7-21也能通信原因取决于flanned,gw模式,原理就是写了个路由,所在win机器上做指向172.7.22.0/24网络的静态路由,不就行了

route add 172.7.22.0 mask 255.255.255.0 10.4.7.22 if 14 -p
route add 172.7.21.0 mask 255.255.255.0 10.4.7.21 if 14 -p

解释:添加二条路由记录,所有到172.7.21.0/24、172.7.22.0/24网段的数据包,都把数据给到网关10.4.7.21、10.4.7.22。而win机器能跟10.4.7.21、10.4.7.22通信的是虚拟网卡vmnat8,if  14就是vmnat8的网卡接口,-p 是永久路由。

如何查看虚拟机vmnat8 的网卡编号,route print 命令显示出来的第一组数据“接口列表”,就是网卡编号

6、 登录配置jenkins

1、访问jenkins.od.com后的地一步输入登录密码

[root@hdss7-200 jenkins_home]# cat /data/nfs-volume/jenkins_home/secrets/initialAdminPassword      # 查看密码登录
a6e44f314783424ebefd270d7d26a8c1

2、输入密码并登录后,跳转如下界面,点击右上角× 跳过,因为所有的插件可以安装完成后在去做


3、如果跳转如下界面,必须输入此账户密码,因为后续Spinnaker与jenkins连接时候用

4、开始使用jenkis

注:如果点击第2步后,直接跳到第4步,没有输入密码直接进入后,需要更改密码

密码:admin123

重新登录账户:admin  密码:admin123 

6.1、配置安全策略

调整两个安全选项 Manage Jenkins → Configure Global Security

Allow anonymous read access    允许匿名用户能访问,但是不能配置
Prevent Cross Site Request Forgery exploits  (默认打√开启阻止跨域请求)。需要取消它,使其开启不阻止跨域请求,因为后期会用到Spinnaker跨域请求jenkins流水线配置

6.2、配置插件加速地址

1、到(Manage Jenkins →Manage Plugins)中装流水线有关的Plugins,叫蓝海

2、按照如下,下载Blue Ocean

Blue Ocean的好处:CI/CD pipeline可视化界面、pipeline编辑器(手动傻瓜式操作)、能快速精准的定位到错误

3、都下载完成之后,在界面最下,有一个类似Restart after installation 安装完成重启,点击后重启jenkins

注:如果蓝海下载卡,或者失败,可能是使用国外源不行,配置国内下载源:

地址:https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

# 修改下载地址
[root@hdss7-200 ~]# cd /data/nfs-volume/jenkins_home/updates
[root@hdss7-200 updates]# sed -i 's#http://updates.jenkins-ci.org/download#https://mirrors.tuna.tsinghua.edu.cn/jenkins#g;s#http://www.google.com#https://www.baidu.com#g' default.json

很重要:

如果安装Blue Ocean提示拒绝加载此版本Blue Ocean,那就是此版本不在被支持,需要下载最新的jenkins 

k8s--Jenkins拒绝加载此版本Blue Ocean、k8s--Jenkins_Jerry00713的博客-CSDN博客

Spinnaker调用Jenkins API 返回403错误_Jerry00713的博客-CSDN博客

6.3、Jenkins 忘记admin密码拯救方法

安装jenkins的目录有一个users的文件夹,每一个用户对应着一个用户名命名的文件夹。打开admin文件夹,里面有一个config.xml文件,就是admin用户的一些配置信息

[root@hdss7-200 ]# cd /data/nfs-volume/jenkins_home/users/admin_34029020338654908
[root@hdss7-200 admin_34029020338654908]# cat config.xml |grep password
 <passwordHash>#jbcrypt:$2a$10$MiIVR0rr/UhQBqT.bBq0QehTiQVqgNpUGyWW2nJObaVAM/2xSQdSq</passwordHash>

红色的就为密码,只不过是被加密后的,所以一旦忘记密码,把对应的用户的config.xml里面的密码改成:

#jbcrypt:$2a$10$MiIVR0rr/UhQBqT.bBq0QehTiQVqgNpUGyWW2nJObaVAM/2xSQdSq

解密后:123456,随后在重启jenkins

7、安装Maven到Jenkins

7.1 、下载Maven二进制包

Maven是把代码编成译jar包或者war包的java程序,所以Jenkins需要使用Maven把代码进行打包,直接将Maven的二进制包拷贝到Jenkins持久化目录中,让Jenkins自己去调用。
apache基金会,官网:Maven – Welcome to Apache Maven
Maven各个版本: Maven – Maven Releases History
其中大版本Maven 3.1+、Maven 3.0.x、Maven 2、Maven 1  等。如果jdk跟Maven版本差异不匹配,会导致编译不过去。而目前大部分java应用都在jdk1.7以上,所以大部分程序用到都是Maven 3。

[root@hdss7-22 ~]# kubectl exec jenkins-64ff665996-dc8bh -n infra -- java -version   查看jenkins 容器 java版本
openjdk version "1.8.0_232"
OpenJDK Runtime Environment (build 1.8.0_232-b09)
OpenJDK 64-Bit Server VM (build 25.232-b09, mixed mode)

注意:直接进入Jenkins容器里执行java -version后,会显示java版本,说明这个Jenkins容器已经安装了jdk。这个jdk是我们dockerfile安装的还是Jenkins镜像自带的呢?

通过检查了配置、共享目录,没发现有由我们操作安装jdk,由于当前使用的jenkins镜像是基于网上的jenkins镜像改吧改吧后的结果,所以验证官方的jenkins镜像是否有无jdk,有就说明是自带的

[root@hdss7-200 jdk_versions]# docker image ls |grep jenkins/jenkins
jenkins/jenkins                                                      2.190.3                         22b8b9a84dbe        13 months ago       568MB
[root@hdss7-200 jdk_versions]# docker run -it 22b8b9a84dbe /bin/bash    # 验证了jdk是pull 镜像自带的
jenkins@53fd0590a043:/$ java -version
openjdk version "1.8.0_232"
OpenJDK Runtime Environment (build 1.8.0_232-b09)
OpenJDK 64-Bit Server VM (build 25.232-b09, mixed mode)

由于使用的是jdk 1.8.0_232,教程使用3.6.1,也可以使用最新Maven版本3.6.3

点击最下面的archives,已经归档的

https://archive.apache.org/dist/maven/maven-3/3.6.1/binaries/apache-maven-3.6.1-bin.tar.gz   二进制包

7.2 、安装二进制包

在 hdss7-200 操作

通过kubectl exec jenkins-64ff665996-dc8bh -n infra -- java -version  查看jenkins容器jdk版本是openjdk version "1.8.0_232",所以我们使用maven-3.6.1-8u232作为 jdk1.8.0_232的maven

[root@hdss7-200 jenkins_home]# cd /opt/src/
[root@hdss7-200 src]# wget https://archive.apache.org/dist/maven/maven-3/3.6.1/binaries/apache-maven-3.6.1-bin.tar.gz
[root@hdss7-200 src]# mkdir -p /data/nfs-volume/jenkins_home/maven-3.6.1-8u232
[root@hdss7-200 src]# tar -xf apache-maven-3.6.1-bin.tar.gz -C /data/nfs-volume/jenkins_home/
[root@hdss7-200 src]# cd /data/nfs-volume/jenkins_home/
[root@hdss7-200 jenkins_home]# ll |grep apache-maven-3.6.1
drwxr-xr-x.  6 root root   99 12月 28 06:33 apache-maven-3.6.1

[root@hdss7-200 jenkins_home]# mv apache-maven-3.6.1/* maven-3.6.1-8u232/
[root@hdss7-200 apache-maven-3.6.1]# cd /data/nfs-volume/jenkins_home/maven-3.6.1-8u232/

[root@hdss7-200 maven-3.6.1-8u232]# ll
drwxr-xr-x. 2 root root     97 12月 28 06:33 bin
drwxr-xr-x. 2 root root     42 12月 28 06:33 boot
drwxr-xr-x. 3  501 games    63 4月   5 2019  conf
drwxr-xr-x. 4  501 games  4096 12月 28 06:33 lib
-rw-r--r--. 1  501 games 13437 4月   5 2019  LICENSE
-rw-r--r--. 1  501 games   182 4月   5 2019  NOTICE
-rw-r--r--. 1  501 games  2533 4月   5 2019  README.txt

7.3、对maven初始化配置

7.3.1、设置国内的镜像源

# 配置maven的xml文件,拉取java包从阿里云拉取,不要从国外拉取

[root@hdss7-200 maven-3.6.1-8u232]# vim /data/nfs-volume/jenkins_home/maven-3.6.1-8u232/conf/settings.xml

<mirror><id>nexus-aliyun</id><mirrorOf>*</mirrorOf><name>Nexus aliyun</name><url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

按照如下更改

最后

此过程不涉及本次实验,不需要配置,了解即可

7.3.2、maven配置不同jdk
需求:公司项目基于maven3才能编译,而maven3必须要用jdk 1.7其他版本无法运行。
过程:在共享目录中添加1.7的jdk,让maven3指定这个1.7的jdk。
下载jdk-7u80-linux-x64.tar.gz:
Java Archive Downloads - Java SE 7

部署:
[root@hdss7-200 src]# cd /opt/src
[root@hdss7-200 src]# rz jdk-7u80-linux-x64.tar.gz
[root@hdss7-200 src]# tar -xf jdk-7u80-linux-x64.tar.gz -C /data/nfs-volume/jenkins_home
[root@hdss7-200 src]# cd /data/nfs-volume/jenkins_home
[root@hdss7-200 jenkins_home]# ll |grep jdk1.7.0_80
drwxr-xr-x.  8   10  143  233 4月  11 2015 jdk1.7.0_80
[root@hdss7-200 jenkins_home]# cd maven-3.6.1-8u232/bin/
[root@hdss7-200 bin]# file mvn
mvn: POSIX shell script, ASCII text executable

[root@hdss7-200 bin]# vi mvn       # 在mvn最开头处添加一条,就可以实现maven-3.6.1-8u232使用jdk1.7.0_80。注意:使用jenkins中绝对路径
JAVA_HOME='/var/jenkins_home/jdk1.7.0_80'

这里注意:meaven启动会按照mvn这个脚本启动,当mvn脚本中没有声明JAVA_HOME是什么,mvn作为一个脚本,调用JAVA_HOME必然是从环境变量中获取。所以默认情况,mvn使用的是环境变量中配置的jdk。但是在脚本的一开头,直接定义JAVA_HOME=/var/jenkins_home/jdk1.7.0_80目录,脚本就会从此目录中获取jdk。而此目录我们通过共享目录挂载到容器

7.3.2、如果meaven使用了不对应的jdk,在运行编译结构化参数jenkins后就会有如下报错:

例子:我的项目只能运行在maven-3.6.1-8u232,对应的jdk要用到1.8.0_232。当pull下载的jenkins:2.190.3的时候,此版本自带的jdk是1.8.0_232,按照此版本制作我的项目完全无问题,奈何此版本在2019年的时候,jenkins中可以支持安装Blue Ocean,但是在2021年的时候Jenkins拒绝为此版本加载Blue Ocean。所以我更新了jenkins为Jenkins 2.319.1。此版本的jdk是openjdk version "11.0.13" 2021-10-19,若用此jenkins制作java的项目,jenkins使用maven-3.6.1-8u232版本的构建项目,mvn默认使用$JAVA_HOME是获取的环境变量,就会获取jdk 11.0.13,导致maven不能跟jdk匹配成功,报如下错误。

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project dubbo-api: Compilation failure: Compilation failure:
[ERROR] Source option 5 is no longer supported. Use 6 or later.
[ERROR] Target option 1.5 is no longer supported. Use 1.6 or later.
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

解决方案:就是需要使用jdk1.8.0_232,操作如下(由于本人未找到jdk1.8.0_231),但是差别不大,所以使用了jdk1.8.0_231

[root@hdss7-21 ~]# cd /opt/src
[root@hdss7-21 ~]# rz jdk-8u231-linux-x64.tar.gz
[root@hdss7-21 ~]# tar -xf jdk-8u231-linux-x64.tar.gz -C /data/nfs-volume/jenkins_home
[root@hdss7-21 ~]# cd /data/nfs-volume/jenkins_home
[root@hdss7-200 jenkins_home]# ll |grep jdk1.8.0_231
drwxr-xr-x.  7   10  143  245 Oct  5  2019 jdk1.8.0_231[root@hdss7-200 jenkins_home]# cd maven-3.6.1-8u232/bin/# mvn中指定使用JAVA_HOME,shell是一条一条执行的,一定要在使用$(JAVA_HOME)之前声明,所以选择在文件开头声明JAVA_HOME='/var/jenkins_home/jdk1.8.0_232'
[root@hdss7-200 bin]# vi mvn
JAVA_HOME='/var/jenkins_home/jdk1.8.0_231'[root@hdss7-200 jenkins_home]# grep -v "^$\|^#" /data/nfs-volume/jenkins_home/maven-3.6.1-8u232/bin/mvn |head -n 5
JAVA_HOME='/var/jenkins_home/jdk1.8.0_231'
if [ -z "$MAVEN_SKIP_RC" ] ; thenif [ -f /etc/mavenrc ] ; then. /etc/mavenrcfi
[root@hdss7-200 jenkins_home]# 

删除jenkins容器,重启jenkins容器,然后重新使用参数化构建流水线

[root@hdss7-21 ~]# kubectl get pod -n infra
NAME                       READY   STATUS    RESTARTS   AGE
jenkins-56d9fd55f9-xkv5k   1/1     Running   2          115m[root@hdss7-21 ~]# kubectl delete pod jenkins-56d9fd55f9-xkv5k -n infra
pod "jenkins-56d9fd55f9-xkv5k" deleted

五、制作JRE镜像底包

什么JRE底包,为什么要制作:

首先我们要知道,Dubbo微服务,主要是自动化构建java程序,其他程序也能构建。以构建java程序为例子,jenkins自动化构建java程序并封装成一个images镜像 ,jenkins首先需要拉起一个新的容器,然后给这个容器传递代码,然后在容器中使用meaven、jdk进行代码的编译,然后编译完成后,放入到tomcat的项目中,在编写这个镜像启动的时候,如何自启动tomcat,这一套流程,首先是不是需要一个基础的镜像,让jenkins拉起一个新的容器。这个基础的镜像,最好有jdk等组件。如果什么都没有,直接从官网下载一个centos镜像,在装jdk,那就太麻烦了。而这个基础的镜像就叫做底包。交付Dubbo微服务的提供者和消费者,都需要这个底包。

制作底包就是制作DockerFile,生产中直接在公网上下载java运行时环境(jre)的镜像,FROM这个镜像,然后安装一些我们需要的基础的架构,最后DockerFile成一个新的基础镜像(底包)。实际生产环境中,根据不同环境需要调整,或者根据当前的底包制作新的底包都可以。

java运行时环境(jre)的镜像是什么,跟jdk有什么区别。java程序通过jdk+meaven编译成字节码文件后,通过jre运行字节码文件,程序就可以正常工作。所以只要编译完代码后,只要有jre就行。而jdk是java发开工具包,里面包含java相关的所有工具,包括jre。所以我们只需要jre的image镜像作为最基础的镜像去做底包即可,jdk的镜像也可,但jdk的镜像没有jre的镜像小。所以第一步找到一个合适的运行时工作的底包。
docker pull docker.io/stanleyws/jre8:8u112    使用大于jdk1.7以上
docker pull docker.io/stanleyws/jre7:7u80      使用小于等于jdk1.7以下
正常的项目就40~50M,底包在300M,因为底包都一样,变化的就是jar包或者war包,随意调度速度快

1、制作DockerFile

[root@hdss7-200 ~]# docker pull docker.io/stanleyws/jre8:8u112
[root@hdss7-200 ~]# docker image ls -a |grep jre
stanleyws/jre8                       8u112            fa3a085d6ef1   4 years ago     363MB

[root@hdss7-200 ~]# docker image tag fa3a085d6ef1 harbor.od.com:180/public/jre8:8u112
[root@hdss7-200 ~]# docker login harbor.od.com:180
[root@hdss7-200~ ]# docker push harbor.od.com:180/public/jre8:8u112
[root@hdss7-200 ~]# mkdir /data/dockerfile/jre8;cd /data/dockerfile/jre8
[root@hdss7-200 dockerfile]# ll
drwxr-xr-x. 2 root root 78 12月 26 11:27 jenkins
drwxr-xr-x. 2 root root  6 12月 31 10:05 jre8

[root@hdss7-200 jre8]# vim Dockerfile

FROM harbor.od.com:180/public/jre8:8u112
ADD config.yml /opt/prom/config.yml
ADD jmx_javaagent-0.3.1.jar /opt/prom/
ADD entrypoint.sh /entrypoint.sh
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
WORKDIR /opt/project_dir
CMD ["/entrypoint.sh"]

解释:

FROM harbor.od.com/public/jre:8u112 底包

ADD config.yml /opt/prom/config.yml   普罗米修斯监控java程序用到的,config.yml文件记录匹配的规则比如rules:--- pattern: '.*'  (代表只要能给的,java毫无保留给普罗米修斯)

ADD jmx_javaagent-0.3.1.jar /opt/prom/   此.jar包是为了后期集群监控软件--普罗米修斯能够拿到监控数据。原理是:运行java的时候,运行命令的参数加上jmx_javaagent-0.3.1.jar后,jar包就能收集这个程序的jvm使用状况,就相当于一个客户端。普罗米修斯,通过这个.jar的接口获取jvm的信息。这个jmx_javaagent-0.3.1.jar只需要wget下载就行

ADD entrypoint.sh /entrypoint.sh    docker运行时默认的启动脚本

RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone   调整时区

WORKDIR /opt/project_dir   容器启动后默认进入此目录作为工作目录,所有的后续执行,如果没有切换目录都在此目录中

CMD ["/entrypoint.sh"]  启动容器后,先执行entrypoint.sh

[root@hdss7-200 jre8]# wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.3.1/jmx_prometheus_javaagent-0.3.1.jar -O jmx_javaagent-0.3.1.jar

[root@hdss7-200 jre8]# du -sh jmx_javaagent-0.3.1.jar  # 很小不影响业务运行
360K    jmx_javaagent-0.3.1.jar
[root@hdss7-200 docker_files]# vim entrypoint.sh  # 定义了三个变量,增加一条启动java的命令

#!/bin/sh
M_OPTS="-Duser.timezone=Asia/Shanghai -javaagent:/opt/prom/jmx_javaagent-0.3.1.jar=$(hostname -i):${M_PORT:-"12346"}:/opt/prom/config.yml"
C_OPTS=${C_OPTS}
JAR_BALL=${JAR_BALL}
exec java -jar ${M_OPTS} ${C_OPTS} ${JAR_BALL}

解释:

M_OPTS="-Duser.timezone=Asia/Shanghai -javaagent:/opt/prom/jmx_javaagent-
0.3.1.jar=$(hostname -i):${M_PORT:-"12346"}:/opt/prom/config.yml"
java的启动参数,-Duser.timezone指定java的时区。/opt/prom/jmx_javaagent-0.3.1.jar使用刚才创
建的收集jVM的javaagent。=$(hostname -i) 等于docker IP也叫pod IP。 所以就是把pod 的IP传到
javaagent。${M_PORT:-"12346"} 使用的端口,M_PORT:-"12346" 为M_PORT默认数值12346,如果你没
有给环境变量传M_PORT等于多少,他就会使用默认数值M_PORT=12346。/opt/prom/config.yml 匹配的
规则。C_OPTS= ${C_OPTS} 定义的是apollo的参数,也是一样dp.yaml传递环境变量参数,可以不写,因为不声明,${C_OPTS}也会默认从环境变量获取。JAR_BALL=${JAR_BALL}  在这个脚本中定义一个变量JAR_BALL,${JAR_BALL}的意思是从我当前容器
运行的系统环境变量面取JAR_BALL的值,此处对应的是deployment.yaml中(name: JAR_BALL value:
dubbo-server.jar)。所以整体意思是,jenkins把代码编译成了dubbo-server.jar,
然后放入到/opt/project_dir目录中(jenkins构建流水线脚本参数写到放入这里),entrypoint.sh也
是在/opt/project_dir目录中,容器启动后会立马执行/opt/project_dir/entrypoint.sh, 脚本执行到
JAR_BALL=${JAR_BALL},意思是JAR_BALL=dubbo-server.jar,然后后面的exec就会调用dubbo-
server.jar,把.jar项目运行起来、其实这个操作可以不写,因为不声明,${JAR_BALL}也会默认从环
境变量获取。exec java -jar ${M_OPTS} ${C_OPTS} ${JAR_BALL}  执行java的命令
思考:java -jar ${M_OPTS} ${C_OPTS} ${JAR_BALL} 就是java启动的命令,exec又是干什么的?
回答:dockerfile做完的镜像,让镜像成为容器,容器启动的第一条命令是执行/entrypoint.sh,也就
是entrypoint.sh脚本的pid为1。而docker进程如果能一直RUNING状态吗,就是夯住,必须要保持pid=1
的进程一直在前台运行,只有前台运行,进程才会一直卡着,让docker一直在工作,不能宕掉,如果
pid=1的进程不能夯住,docker就会变成EXITED退出。而entrypoint.sh脚本中,三个都是变量,只有最
后一条,如果写成java -jar ${M_OPTS} ${C_OPTS} ${JAR_BALL},程序运行完成之后,不会夯住,直
接在后台运行。导致entrypoint.sh脚本也退出,docker直接EXITED退出,而加一个exec运行java -jar
${M_OPTS} ${C_OPTS} ${JAR_BALL},这个java -jar ${M_OPTS} ${C_OPTS} ${JAR_BALL}语句就会代替
当前这个entrypoint.sh shell脚本的进程,变成pid等于1的进程,java -jar ${M_OPTS} ${C_OPTS}
${JAR_BALL}就会变成pid等于1,并且在前台运行

[root@hdss7-200 docker_files]# chmod +x entrypoint.sh
[root@hdss7-200 jre8]# vim config.yml

rules:- pattern: '.*'

[root@hdss7-200 jre8]# ll

-rw-r--r--. 1 root root     25 Mar 29 09:07 config.yml
-rw-r--r--. 1 root root    297 Mar 29 08:21 Dockerfile
-rwxr-xr-x. 1 root root    234 Mar 29 08:39 entrypoint.sh
-rw-r--r--. 1 root root 367417 May 10  2018 jmx_javaagent-0.3.1.jar

2、build镜像到base仓库

2.1、base:所有的底包

2.2、build镜像到base仓库

[root@hdss7-200 jre8]# docker image build -t harbor.od.com:180/base/jre8:8u112 ./

Sending build context to Docker daemon  372.2kB
Step 1/7 : FROM harbor.od.com:180/public/jre8:8u112---> fa3a085d6ef1
Step 2/7 : ADD config.yml /opt/prom/config.yml---> a0ee7f22e676
Step 3/7 : ADD jmx_javaagent-0.3.1.jar /opt/prom/---> bd6f1bebfc18
Step 4/7 : ADD entrypoint.sh /entrypoint.sh---> 06e90e726a97
Step 5/7 : RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone---> Running in d95f09966069
Removing intermediate container d95f09966069---> 156268ed7f61
Step 6/7 : WORKDIR /opt/project_dir---> Running in 9e6c0af8cd97
Removing intermediate container 9e6c0af8cd97---> 3a8d1eebd488
Step 7/7 : CMD ["/entrypoint.sh"]---> Running in c6a159441fce
Removing intermediate container c6a159441fce---> 3a43af56c79b
Successfully built 3a43af56c79b
Successfully tagged harbor.od.com:180/base/jre8:8u112

[root@hdss7-200 jre8]# docker login harbor.od.com:180
[root@hdss7-200 jre8]# docker image push harbor.od.com:180/base/jre8:8u112

底包:比如项目中需要加特殊配置或者其他文件,只需简要做成底包,项目引用底包(鼠标点点),实现了新的项目

六、构建和交付dubbo

1、交付dubbo服务的提供者

优点:使用jenkins能进行持续构建dubbo服务的项目

1.1、配置Jenkins流水线

由于实验要求:确保Jenkins的admin账户的密码是admin123,如果不是修改密码

参数化构建流水线,这样流水线就能适配我们Dubbo微服务的提供者和消费者

配置我们保留3天,30份保留记录

添加参数:String 字符串类型  choice 可选择的

1.2、Jenkins配置项目的10个参数

jenkins流水线配置的java项目的十个常用参数:

参数名(name)

类型(type) 默认 Trim the string 描述(description)
app_name string Parameeter 项目名称,如 dubbo-demo-service
image_name string Parameeter docker镜像名称,如  harbor.od.com:180/app/dubbo-demo-service
git_repo string Parameeter 项目在git版本仓库的地址,如 https://gitee.com/xxx/dubbo-demo-web
git_ver string Parameeter 项目在git仓库中对应的分支或者版本号
add_tag string Parameeter 日期-时间,和git_ver拼在一起组成镜像的tag,如: 202002011001
mvn_dir string Parameeter ./ 在哪个目录执行编译,由开发同事提供
target_dir string Parameeter ./target 编译的jar/war文件存放目录,由开发同事提供
mvn_cmd string Parameeter mvn clean package -Dmaven.test.skip=true 执行编译所用的指令
base_image choice Parameeter base/jre7:7u80
base/jre8:8u112
项目使用的jre底包
maven choice Parameeter 3.6.1-8u232
3.2.5-7u045
2.2.1-6u025
编译时使用的maven目录中的版本号部分

解释:

app_name      是这个项目的名字
image_name  是调用哪个镜像
git_repo          项目从那个git仓库拉取,如 https://gitee.com/xxx/dubbo-demo-web

git_ver  分支或者版本号,里面可以填写分支号或者commit ID号

在https://gitee.com/jerry00713/dubbo-demo-web项目中有分支的,可能有master分支或者apollo分支,如果想编译master分支项目,必须指定拉取这个分支上的代码,jenkins使用 git clone git_repo -b git_ver (例如git clone https://gitee.com/xxx/dubbo-demo-web -b master

每提交一次代码,就会生成一个 commitid,这个commitid是独一无二的,只要提交一次就会生成一个。jenkins使用 git reset --hard [commit-number] 语法,也就是 git git_repo reset --hard  git_ver(git https://gitee.com/jerry00713/dubbo-demo-web reset --hard b6fae70)从而获取这次提交的代码

使用这种commitid最好的好处在于,如果一旦程序出问题,开发为了免责,把代码修改没问题后commit提交了,并且提交到master分支,这个时候由于你编译的时候,调用的是master分支代码,尽管是研发没修改之前的出问题代码,但是打成包镜像的时候,显示的还是harbor.od.com:180/app/dubbo-demo-service:master_210108_1435,因为jenkins默认把git_ver作为tag标签,导致责任就是你运维的锅。但是如果使用commitid作为git_ver ,打成的镜像就是harbor.od.com:180/app/dubbo-demo-service:b6fae70_210108_1435,commitid是独一无二的,问题一下就知道了谁的责任

add_tag   给docker镜像增加标签,add_tag是docker镜像标签的一部分,可以任意定义。生产:业务系统 (git_ver+add_tag任意定义标签。而自定义的标签一般为:日期_时间,和git_ver拼在一起组成镜像的tag,如: master_20200201_1001

mvn_dir    在哪个目录对这个项目的代码就行编译操作,jenkins从git上拉取下来的是如下的源代码,而编译这个代码的时候,是在那个目录下编译呢,是在根,根代表的是(./)当前这个目录,就是如下这个目录有(.gitee  dubbo-api dubbo-server REAMDE.md pox.xml 的目录),这个需要问开发,如果目录错误的话,假如在./dubbp-api下进行编译,编译过程中,代码写死需要调用./pom.xml,如果在./dubbp-api下编译,根本找不到./dubbp-api/pom.xml


target_dir   编译出来的项目,jar包或者wa包,编译后的放在哪里,由开发提供
mvn_cmd  执行编译所用的命令,这个命令就是meaven的命令(代码由meaven才能编译成.jar或.war),常用的是mvn clean package -e- q  -Dmaven.test.skip=true (Dmaven.test.skip跳出单元测试)​​​​​​​
base_image 用哪个底包,根据实际需要有多少列出多少
maven  执行编译使用的maven软件版本,根据实际需要有多少列出多少

注:Trim the string当你在填写参数的时候,帮你自动清楚前后空格

jenkins如何使用上述参数进行构建项目打包成image,由如下脚本使用这些参数构建,他的语法通过类似于shell的语句

pipeline {agent any stages {stage('pull') { //get project code from repo steps {sh "git clone ${params.git_repo} ${params.app_name}/${env.BUILD_NUMBER} && cd ${params.app_name}/${env.BUILD_NUMBER} && git checkout ${params.git_ver}"}}stage('build') { //exec mvn cmdsteps {sh "cd ${params.app_name}/${env.BUILD_NUMBER}  && /var/jenkins_home/maven-${params.maven}/bin/${params.mvn_cmd}"}}stage('package') { //move jar file into project_dirsteps {sh "cd ${params.app_name}/${env.BUILD_NUMBER} && cd ${params.target_dir} && mkdir project_dir && mv *.jar ./project_dir"}}stage('image') { //build image and push to registrysteps {writeFile file: "${params.app_name}/${env.BUILD_NUMBER}/Dockerfile", text: """FROM harbor.od.com:180/${params.base_image}
ADD ${params.target_dir}/project_dir /opt/project_dir"""sh "cd  ${params.app_name}/${env.BUILD_NUMBER} && docker build -t harbor.od.com:180/${params.image_name}:${params.git_ver}_${params.add_tag} . && docker push harbor.od.com:180/${params.image_name}:${params.git_ver}_${params.add_tag}"}}}
}

agent    # 步骤
   
stage('pull')          # pull 拉取git镜像
   stage('build')        # build 把代码构建成.jar项目
 
 stage('package')  # jar项目放入到指定目录
   stage('image')      # 打包成image包,提交镜像到harbor

1.3、构建Dubbo服务的提供者

1.3.1、如何进入参数填写

或者

1.3.2、参数填写,构建流水线参数一定不要写错了

注:若使用的是我上面提供的gitee Jerry00713/dubbo-demo-service代码,一定要按照图片内容填写
app_name   可以随意填写,但尽量跟实际的项目是一个名字,为了统一
image_name   格式为namespace/项目名,尽量不改,图中使用了app的名空间
git_repo 、git_ver   按照实际的情况,填写gitee
add_tag   可以随意填写,为了规范,标准写法为(年后2位+月+日_时间),这种格式为帮助你甩锅用,一旦出问题,可以按照时间来反编译看到底是谁的问题
mvn_dir   不要改,需要问研发应该在哪编译
mvn_cmd  不要改,需要问研发如何编译代码
target_dir  不要改,需要问研发编译出来的项目放在哪里,正常看pom.xml中的<module>dubbo-server</module>

1.3.3、 上述中,image_name打包的镜像要推送到app仓库,由于没有app仓库,需要创建

1.3.4  点击build就会编译

1.4、查看进度

1.4.1  查看进度日志

编译后产生序列号,点击#1

点击Console Output  查看安装过程

注释:

第一步克隆+ git clone Jerry00713/dubbo-demo-service dubbo-demo-service/1

提示成功,提示构建docker image

提示安装成功

1.4.2  编译失败重新编译

注意事项:如果在build后,查看Console Output 最后提示失败failure。首先查看Console Output提示的信息,是到哪步错误了。其中有可能是build配置页面填写信息的时候写错了,比如image_name写成了app/ dubbo-demo-service带空格了,或者target_dir写成了./dubbo-service/target。

还有可能是meaven跟jdk不匹配,或者meaven编译过程需要拉取基础组件,网络不通导致拉取不到等等。在排查并解决问题后,需要重新build构建。步骤是重新点击build with parameters→填写正确后信息,重新点击built,由于你没有删除之前失败的dubbo-demo-service的项目,所以他会保留之前已经构建的数据,从失败的地方重新继续built,并且会重新生成一个序列号。在失败点重新built,会节省时间,之前的操作直接跳过

1.5、查看image_name镜像

1.6、交付到k8s

回头看已经有了这个镜像,所以我们需要交付到k8s,所以我们需要资源配置清单

1.6.1、资源配置清单:

提供者只需要delpoyment资源的pod控制器,因为不需要ingress让外部访问,也不需要其他资源通过service资源跟我通信,我只需要把我的信息传递给注册中心,然后注册中心的消费者通过注册中心记录,如何调用我的接口。

[root@hdss7-200 k8s-yaml]# mkdir /data/k8s-yaml/dubbo-demo-service;cd /data/k8s-yaml/dubbo-demo-service
[root@hdss7-200 dubbo-demo-service]# vi dp.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:name: dubbo-demo-servicenamespace: applabels:name: dubbo-demo-service
spec:replicas: 1selector:matchLabels:name: dubbo-demo-servicetemplate:metadata:labels:app: dubbo-demo-servicename: dubbo-demo-servicespec:containers:- name: dubbo-demo-serviceimage: harbor.od.com:180/app/dubbo-demo-service:master_210108_1435ports:- containerPort: 20880protocol: TCPenv:- name: JAR_BALLvalue: dubbo-server.jarimagePullPolicy: IfNotPresentimagePullSecrets:- name: harborrestartPolicy: AlwaysterminationGracePeriodSeconds: 30securityContext:runAsUser: 0schedulerName: default-schedulerstrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 1maxSurge: 1revisionHistoryLimit: 7progressDeadlineSeconds: 600

解释:

metadata:
  name: dubbo-demo-service
  namespace: app       运行在app的名称空间下

metadata:
      labels:     标签可以随便定义
        app: dubbo-demo-service
        name: dubbo-demo-service
  
        image: harbor.od.com:180/app/dubbo-demo-service:master_210108_1435        修改成刚才编译的镜像
        ports:   暴露rpc端口 ,写不写无所谓
        - containerPort: 20880  把容器内的20880端口,暴露到容器外,docker -P  20880:20880
          protocol: TCP
        env: 
        - name: JAR_BALL  制作JRE镜像底包的时候,构建DockerFile,使用了entrypoint.sh,在entrypoint.sh中定义一个变量JAR_BALL,怎么接收jar包的环境变量
          value: dubbo-server.jar   启动dubbo服务时候,传给容器的jar包
        imagePullPolicy: IfNotPresent    如果本地没有此镜像,在从harbor拉取镜像
      imagePullSecrets:    必须有,对应app名称空间相爱的secret,如果没有拉取不到app私有仓库镜像
      - name: harbor

创建app空间
[root@hdss7-21 ~]# kubectl create ns app
namespace/app created

创建app空间secret(因为app空间,要去harbor的私有仓库app拉取镜像,所以需要创建 secret,让app空间去请求私有仓库的时候,带着secret,secret记录的hartbor的账户密码,才能请求到镜像)
[root@hdss7-21 ~]# kubectl create secret docker-registry harbor --docker-server=harbor.od.com:180 --docker-username=admin --docker-password=Harbor12345 -n app
secret/harbor created

1.6.2、在交付到k8s之前查看zookeeper,对比交付后,在查看zookeeper

[root@hdss7-11 ~]# /opt/zookeeper/bin/zkServer.sh status   查看zookeeper启动状态
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Mode: follower

[root@hdss7-11 ~]# /opt/zookeeper/bin/zkCli.sh -server localhost:2181   登录zookeeper
WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0] ls /        查看zookeeper目前节点,只有自己
[zookeeper]

1.6.3、资源配置清单交付到k8s

hdss7-21 或者hdss7-22
[root@hdss7-21 /]# kubectl apply -f http://k8s-yaml.od.com/dubbo-demo-service/dp.yaml
deployment.extensions/dubbo-demo-service created

1.6.4、验证交付到k8s

查看zookeeper
[zk: localhost:2181(CONNECTED) 0] ls /        查看zookeeper目前节点
[dubbo,zookeeper]

[zk: localhost:2181(CONNECTED) 1] ls /dubbo   已经注册到了zk的注册中心
[com.od.dubbotest.api.HelloService]

查看容器是否启动

查看容器日志,提示Dubbo server 是启动

2、借助Blue Ocean 插件回顾Jenkins流水线配置

由于第5次配置成功了,打开Blue Ocean

点击状态5

讲解:

1、pull --拉取代码

jenkins默认的工作路径是/var/jenkins_home。jenkins在做参数化构建前的时候,首先我们会创建一个项目比如叫(Dubbo-demo),在jenkins中的workspace(工作环境)目录,对应的生成一个Dubbo-demo目录。然后再做参数化构建的时候,就在这个/var/jenkins_home/workspace/Dubbo-demo目录下进行。部署第一行说把代码克隆到dubbo-demo-service/5,其中5是序列号,每做一次参数化构建,必须生成一个新的序列号,否则都打在一个目录乱套了。dubbo-demo-service/5 在shell中省略了./ (就是./dubbo-demo-service/5),而所有的操作都在/var/jenkins_home/workspace/Dubbo-demo中,所以整体的意思为(git clone https://gitee.com/jerry00713/dubbo-demo-service.git  /var/jenkins_home/workspace/Dubbo-demo/dubbo-demno-service/5)  而/var/jenkins_home挂载在 /data/nfs-volume/jenkins_home/下

[root@hdss7-200 src]# cd /data/nfs-volume/jenkins_home/workspace/
[root@hdss7-200 workspace]# ll
drwxr-xr-x. 4 root root  59 1月   8 12:13 Dubbo-demo
drwxr-xr-x. 2 root root  6   1月   8 14:45 Dubbo-demo@tmp

[root@hdss7-200 workspace]# cd Dubbo-demo
[root@hdss7-200 Dubbo-demo]# ll
drwxr-xr-x. 5 root root 33 1月   8 14:37 dubbo-demo-service

[root@hdss7-200 Dubbo-demo]# cd dubbo-demo-service
[root@hdss7-200 dubbo-demo-service]# ll
drwxr-xr-x. 6 root root 101 1月   5 11:51 1
drwxr-xr-x. 6 root root 101 1月   8 12:07 2
drwxr-xr-x. 6 root root 119 1月   8 14:38 5

[root@hdss7-200 dubbo-demo-service]# cd 5
[root@hdss7-200 5]# ll

-rw-r--r--. 1 root root  93 1月   8 14:38 Dockerfile
drwxr-xr-x. 4 root root  46 1月   8 14:37 dubbo-api
drwxr-xr-x. 4 root root  46 1月   8 14:38 dubbo-server
-rw-r--r--. 1 root root 729 1月   8 14:37 pom.xml
-rw-r--r--. 1 root root 945 1月   8 14:37 README.md

git checkout master 意思为,切换到master分支
[root@hdss7-200 5]# git branch
* master

2、build --编译代码

+ /var/jenkins_home/maven-3.6.1-8u232/bin/mvn clean package -Dmaven.test.skip=true   mvn 进行编译代码

3、package --打包

cd 到参数化构建target,这里面创建podject_dir目录,然后把jar包放入

4、编写Dockerfile,做成docker镜像

 1、Write file to workspace 为生编写dockerfile:
[root@hdss7-200 ]# cd /data/nfs-volume/jenkins_home/workspace/Dubbo-demo/dubbo-demo-service/5
[root@hdss7-200 5]# ll

-rw-r--r--. 1 root root  93 1月   8 14:38 Dockerfile
drwxr-xr-x. 4 root root  46 1月   8 14:37 dubbo-api
drwxr-xr-x. 4 root root  46 1月   8 14:38 dubbo-server
-rw-r--r--. 1 root root 729 1月   8 14:37 pom.xml
-rw-r--r--. 1 root root 945 1月   8 14:37 README.md

[root@hdss7-200 5]# cat Dockerfile 
FROM harbor.od.com:180/base/jre8:8u112
ADD ./dubbo-server/target/project_dir /opt/project_dir[root@hdss7-200 5]#

2、docker build 创建docker 的镜像,并提交到harbor

总结如下:

3交付Monitor到K8S

思考:在交付Dubbo生产者后,通过进入zk注册中心后,才能查看Dubbo生产者已经进入注册中心。这才是一个Dubbo生产者,也就是项目中的一个模块,再加上Dubbo消费者,一个项目会有若干个模块,也就是若干生产者、消费者,难道进入zk的命令行一个一个看。

我们需要一个zk图形界面判断有多少个提供者交付到了zk中,不能每次都敲命令看,这个界面叫做Monitor,他就是一个取注册中心的数据,并展现
目前比较流行的zk监控者:dubbo-admin  dubbo-Monitor
托管在:
GitHub - Jeromefromcn/dubbo-monitor

3.1、下载源代码,解压

[root@hdss7-200 dubbo-server]# cd /opt/src/
[root@hdss7-200 src]# rz dubbo-monitor-master
[root@hdss7-200 src]# unzip dubbo-monitor-master
[root@hdss7-200 src]# mv dubbo-monitor-master dubbo-monitor
[root@hdss7-200 src]# cp -a dubbo-monitor /data/dockerfile/
[root@hdss7-200 src]# cd /data/dockerfile/
[root@hdss7-200 dockerfile]# ll
drwxr-xr-x. 3 root root 69 7月  27 2016 dubbo-monitor
drwxr-xr-x. 2 root root 78 12月 26 11:27 jenkins
drwxr-xr-x. 2 root root 94 12月 31 13:59 jre8

3.2、修改dubbo-monitor配置

3.2.1、修改dubbo_origin.properties

[root@hdss7-200 src]# cd /data/dockerfile/dubbo-monitor
[root@hdss7-200 dubbo-monitor]# ll
-rw-r--r--.   1   root root 155 7月  27 2016 Dockerfile
drwxr-xr-x. 5  root root  40  7月  27 2016 dubbo-monitor-simple
-rw-r--r--.   1   root root  16  7月  27 2016 README.md

[root@hdss7-200 dubbo-monitor]# cd dubbo-monitor-simple/conf/

#  修改monitor​​​​​​​启动参数,比如启动占用什么端口,monitor的目录在哪,修改成下面的配置
[root@hdss7-200 conf]# vi dubbo_origin.properties

dubbo.container=log4j,spring,registry,jetty
dubbo.application.name=dubbo-monitor
dubbo.application.owner=Jerry
dubbo.registry.address=zookeeper://zk1.od.com:2181?backup=zk2.od.com:2181,zk3.od.com:2181
dubbo.protocol.port=20880
dubbo.jetty.port=8080
dubbo.jetty.directory=/dubbo-monitor-simple/monitor
dubbo.charts.directory=/dubbo-monitor-simple/charts
dubbo.statistics.directory=/dubbo-monitor-simple/statistics
dubbo.log4j.file=logs/dubbo-monitor-simple.log
dubbo.log4j.level=WARN

解释:

dubbo.application.name=dubbo-monitor   monitor的名字随便起
dubbo.application.owner=Jerry   所属者名字随便起
dubbo.registry.address=zookeeper......  写我们自己的zookeeper地址
dubbo.protocol.port=20880     自定义monitor提供的 rpc接口,习惯统一用20880
dubbo.jetty.port=8080   monitor对外提供网站http接口
dubbo.jetty.directory=/dubbo-monitor-simple/monitor  monitor的工作目录,给了一个固定位置
dubbo.charts.directory=/dubbo-monitor-simple/charts  monitor的charts文件
dubbo.statistics.directory=/dubbo-monitor-simple/statistics  monitor的静态文件

3.2.2、修改start.sh

[root@hdss7-200 dubbo-monitor]# cd /data/dockerfile/dubbo-monitor
[root@hdss7-200 dubbo-monitor]# ll    # dubbo-monitor的开发者已经写好Dockerfile,帮你构建docker 镜像
-rw-r--r--.    1 root root 155 7月  27 2016 Dockerfile
drwxr-xr-x. 5 root root  40  7月  27 2016 dubbo-monitor-simple
-rw-r--r--.    1 root root  16  7月  27 2016 README.md

[root@hdss7-200 dubbo-monitor]# cat Dockerfile   # 查看Dockerfile

FROM jeromefromcn/docker-alpine-java-bash
MAINTAINER Jerome Jiang      # 谁做的
COPY dubbo-monitor-simple/ /dubbo-monitor-simple/
CMD /dubbo-monitor-simple/bin/start.sh

# 查看Dockerfile其实很简单,除了start.sh启动脚本需要修改,按照实际项目修改,比如jvm、容器启动第一进程能否夯住

[root@hdss7-200 dubbo-monitor]# vim /data/dockerfile/dubbo-monitor/dubbo-monitor-simple/bin/start.sh

修改一:JVM调优,源代码给2g太大了,按照比例缩小改成128m,小m(兆)

if [ -n "$BITS" ]; thenJAVA_MEM_OPTS=" -server -Xmx128m -Xms128m -Xmn32m -XX:PermSize=16m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "
elseJAVA_MEM_OPTS=" -server -Xms128m -Xmx128m -XX:PermSize=16m -XX:SurvivorRatio=2 -XX:+UseParallelGC "
fi

修改二:由于nohup java不能保证docker一直保持RUNING的生命周期,所以默认提供的Dockerfile制作的镜像无法一直RUNING启动,需要修改启动参数,让 java 进程在前台运行,删除nohup java这行,及nohup java以下的行,因为下面的语句不是调配系统层等参数,而是为 nohup java语句做判断等,所以没用。删除后,增加自己的代码

方式一:vi 手动修改,删除不需要的内容,增加需要内容

删除不需要的内容:

增加需要内容:就是上述的替换

echo -e "Starting the $SERVER_NAME ...\c"
exec java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS -classpath $CONF_DIR:$LIB_JARS com.alibaba.dubbo.container.Main > $STDOUT_FILE 2>&1

方式二:执行脚本,可以一句话搞定

sed -r -i -e '/^nohup/{p;:a;N;$!ba;d}' /data/dockerfile/dubbo-monitor/dubbo-monitor-simple/bin/start.sh && sed -r -i -e "s%^nohup(.*) &%exec\1%" /data/dockerfile/dubbo-monitor/dubbo-monitor-simple/bin/start.sh

sed -r -i -e '/^nohup/{p;:a;N;$!ba;d}'  sed 模式空间语法

解释:根据我们做dobbo微服务的底包的时候,使用exec让java命令占用脚本的pid,也就是等于1的pid,让java程序一直在前台跑。这里也是,让java命令取代pid为1的start.sh脚本,使其java命令是第一进程,pid=1,然后一直以第一进程夯在前台。

最后的修改结果:

3.3、build docker镜像

[root@hdss7-200 dubbo-monitor]# cd /data/dockerfile/dubbo-monitor
[root@hdss7-200 dubbo-monitor]# docker build . -t harbor.od.com:180/infra/dubbo-monitor:latest
[root@hdss7-200 dubbo-monitor]# docker login harbor.od.com:180
[root@hdss7-200 dubbo-monitor]# docker push harbor.od.com:180/infra/dubbo-monitor:latest

3.4、配置资源配置清单

发布docker镜像需要配置资源配置清单

[root@hdss7-200 ~]# mkdir -p /data/k8s-yaml/dubbo-monitor/
[root@hdss7-200 ~]# vim /data/k8s-yaml/dubbo-monitor/deployment.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:name: dubbo-monitornamespace: infralabels: name: dubbo-monitor
spec:replicas: 1selector:matchLabels: name: dubbo-monitortemplate:metadata:labels: app: dubbo-monitorname: dubbo-monitorspec:containers:- name: dubbo-monitorimage: harbor.od.com:180/infra/dubbo-monitor:latestports:- containerPort: 8080protocol: TCP- containerPort: 20880protocol: TCPimagePullPolicy: IfNotPresentimagePullSecrets:- name: harborrestartPolicy: AlwaysterminationGracePeriodSeconds: 30securityContext: runAsUser: 0schedulerName: default-schedulerstrategy:type: RollingUpdaterollingUpdate: maxUnavailable: 1maxSurge: 1revisionHistoryLimit: 7progressDeadlineSeconds: 600

解释:
        image: harbor.od.com:180/infra/dubbo-monitor:latest
        ports:   暴露两个rpc端口
        - containerPort: 8080
          protocol: TCP
        - containerPort: 20880   
          protocol: TCP

[root@hdss7-200 ~]# vim /data/k8s-yaml/dubbo-monitor/service.yaml

kind: Service
apiVersion: v1
metadata: name: dubbo-monitornamespace: infra
spec:ports:- protocol: TCPport: 8080targetPort: 8080selector: app: dubbo-monitor

解释:    
port: 8080   cluster IP暴露的端口,访问此service资源的集群IP:8080,通过kube-proxy反代到某一个节点的dubbo-monitor的pod的8080端口。cluster IP理论上写什么端口都行,因为在集群中,每个service资源从(192.168.0.0/16)中都会分配一个不同的IP地址,但注意,这里定义是8080端口,ingress资源中servicePort的端口必须也是8080,ingress资源需要通过此端口连接service资源
targetPort: 8080    docker里面的端口,需要跟cluster IP的端口做映射

[root@hdss7-200 ~]# vim /data/k8s-yaml/dubbo-monitor/ingress.yaml

kind: Ingress
apiVersion: extensions/v1beta1
metadata: name: dubbo-monitornamespace: infra
spec:rules:- host: dubbo-monitor.od.comhttp:paths:- path: /backend: serviceName: dubbo-monitorservicePort: 8080

3.5、应用资源配置清单

[root@hdss7-21 /]# kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/deployment.yaml
deployment.extensions/dubbo-monitor created
[root@hdss7-21 /]# kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/service.yaml
service/dubbo-monitor created
[root@hdss7-21 /]# kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/ingress.yaml
ingress.extensions/dubbo-monitor created

3.5.1、如果容器报错CrashLoopBackOff 

[root@hdss7-21 /]# kubectl get pods -o wide -n infra

NAME                             READY   STATUS             RESTARTS   AGE    IP            NODE                NOMINATED NODE   READINESS GATES
dubbo-monitor-76f9845456-fdqbp   0/1     CrashLoopBackOff   5          4m8s   172.7.22.5    hdss7-22.host.com   <none>           <none>
jenkins-64ff665996-q642m         1/1     Running            0          2d     172.7.21.10   hdss7-21.host.com   <none>           <none>

查看容器日志:

[root@hdss7-21 /]# kubectl logs dubbo-monitor-76f9845456-nd4lh -n infra
starting the dubbo-monitor.............[root@hdss7-21 /]#   说明一直在启动

[root@hdss7-21 /]# kube ctl descirbe pod  dubbo-monitor-76f9845456-nd4lh -n infra    总结:就是Back-off restarting failed containerNormal   Scheduled  5m46s                    default-scheduler           Successfully assigned infra/dubbo-monitor-5cf4bb98d5-vkxc8 to hdss7-22.host.comNormal   Pulled     4m10s (x5 over 5m41s)  kubelet, hdss7-22.host.com  Container image "harbor.od.com:180/infra/dubbo-monitor:latest" already present on machineNormal   Created    4m10s (x5 over 5m41s)  kubelet, hdss7-22.host.com  Created container dubbo-monitorNormal   Started    4m10s (x5 over 5m40s)   kubelet, hdss7-22.host.com  Started container dubbo-monitorWarning  BackOff    40s (x23 over 5m35s)    kubelet, hdss7-22.host.com   Back-off restarting failed container
[root@hdss7-21 /]#

解决方案:
1、一直启动,说明启动镜像的时候那个地方卡住了,在build如果无问题,就需要查看制作镜像Dockerfile有无问题,但Dockerfile是官方的,而且里面除了刚刚修改的start.sh,无其他大的变动。查看start.sh后是可能是修改JVM的时候128m,写成128g,导致资源耗尽
2、还有种可能是在deployment.yaml 中 progressDeadlineSeconds: 600   多长时间运行容器不正常,判断为失败,所以是不是没写这句导致容器提前死亡
操作过程:
如上问题修改128m,修改progressDeadlineSeconds: 600 ,然后删除harbor中的dubbo-monitor镜像,删除hdss7-200本地的dubbo-monitor镜像,重新build 。由于修改deployment.yaml,重新kubectl apply -f deployment.yaml,由于生成的dubbo-monitor-76f9845456-nd4lh的时候,会拉取barbor镜像下载本地,而且在deployment.yaml中 IfNotPresent (如果本地没有在拉取远程镜像),由于本地已经有,所以在启动不会拉取harbor镜像。所以需要删除已经下载的本地dubbo-monitor镜像。

3.5.2、查看状态:

没有日志,没有重定向标准输出

3.6、访问Monitor

解析原理:访问dubbo-monitor.od.com,通过named解析到10.4.7.10(vip),通过7层代理,指给了某一个ingress控制器,ingress根据访问的路径解析,需要抛给那个service资源,service资源通过kube-proxy把流量抛给某一个monitor的pod

3.6.1、 配置DNS解析
[root@hdss7-11 ~]# vi /var/named/od.com.zone

$ORIGIN od.com.
$TTL 600        ; 10 minutes
@               IN SOA  dns.od.com. dnsadmin.od.com. (2020010507 ; serial                  前滚+110800      ; refresh (3 hours)900        ; retry (15 minutes)604800     ; expire (1 week)86400      ; minimum (1 day))NS   dns.od.com.
$TTL 60 ; 1 minute
dns                A    10.4.7.11
harbor             A    10.4.7.200
k8s-yaml           A    10.4.7.200
traefik            A    10.4.7.10
dashboard          A    10.4.7.10
zk1                A    10.4.7.11
zk2                A    10.4.7.12
zk3                A    10.4.7.21
jenkins            A    10.4.7.10
dubbo-monitor      A    10.4.7.10注:dubbo-monitor是通过ingress.yaml的- host: dubbo-monitor.od.com  得来的                      

[root@hdss7-11 ~]# systemctl restart named
[root@hdss7-11 ~]# dig -t A dubbo-monitor.od.com @10.4.7.11 +short
10.4.7.10

3.6.2、 访问页面

访问​​​​​​​http://dubbo-monitor.od.com/

点击status查看目前注册中心的状态:

registry OK  zk1.od.com:2181(connected)   monitor连接的哪个zk
server   OK  /172.7.22.6:20880(clients:0)     monitor对外的地址(monitord的podIP:端口)

点击Applications查看已经注册到注册中心的项目:

dubbo-monitor  自己建立的monitor,名字也是dubbo_origin.properties修改的Jerry
dubbo-demo-service   从zk中读取出来的提供者

点击Applications →​​​​​​​ dubbo-demo-service,查看此项目的情况:

提供两个rpc的api接口

3.6、将dubbo_origin.properties 配置成configmap

将dubbo_origin.properties 配置成configmap,实现动态修改连接那个zk

3.6.1、配置configmap清单

[root@hdss7-200 ~]# cd /data/k8s-yaml/dubbo-monitor
[root@hdss7-200 dubbo-monitor]# vi cm.yaml

apiVersion: v1
kind: ConfigMap
metadata:name: dubbo-monitor-cm namespace: infra
data:dubbo.properties: |dubbo.container=log4j,spring,registry,jettydubbo.application.name=dubbo-monitordubbo.application.owner=Jerrydubbo.registry.address=zookeeper://zk1.od.com:2181?backup=zk2.od.com:2181,zk3.od.com:2181dubbo.protocol.port=20880dubbo.jetty.port=8080dubbo.jetty.directory=/dubbo-monitor-simple/monitordubbo.charts.directory=/dubbo-monitor-simple/chartsdubbo.statistics.directory=/dubbo-monitor-simple/statisticsdubbo.log4j.file=logs/dubbo-monitor-simple.logdubbo.log4j.level=WARN

3.6.2、修改deployment,使其调用configmap中的dubbo.properties

[root@hdss7-200 dubbo-monitor]# vi deployment.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:name: dubbo-monitornamespace: infralabels: name: dubbo-monitor
spec:replicas: 1selector:matchLabels: name: dubbo-monitortemplate:metadata:labels: app: dubbo-monitorname: dubbo-monitorspec:volumes:- name: configmap-volumeconfigMap:name: dubbo-monitor-cmcontainers:- name: dubbo-monitorimage: harbor.od.com:180/infra/dubbo-monitor:latestports:- containerPort: 8080protocol: TCP- containerPort: 20880protocol: TCPvolumeMounts:- name: configmap-volumemountPath: /dubbo-monitor-simple/confimagePullPolicy: IfNotPresentimagePullSecrets:- name: harborrestartPolicy: AlwaysterminationGracePeriodSeconds: 30securityContext: runAsUser: 0schedulerName: default-schedulerstrategy:type: RollingUpdaterollingUpdate: maxUnavailable: 1maxSurge: 1revisionHistoryLimit: 7progressDeadlineSeconds: 600
[root@hdss7-200 dubbo-monitor]# 

3.6.3、应用deployment、configmap

[root@hdss7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/cm.yaml
configmap/dubbo-monitor-cm created
[root@hdss7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/deployment.yaml
deployment.extensions/dubbo-monitor configured
[root@hdss7-21 ~]# 

3.6.4、等容器启动后查看http://dubbo-monitor.od.com/,能访问代表无问题

3.6.5、configmap声明dubbo.properties文件

不知道有没有注意,在声明configmap的时候,配置的是dubbo.properties文件,也就是给容器创建一个/dubbo-monitor-simple/conf/dubbo.properties,而我们在没用configmap部署的时候,明明是修改的是conf/dubbo.properties,按道理应该是声明的/dubbo-monitor-simple/conf/dubbo_origin.properties

做实验看看就知道了,修改configmap为dubbo_origin.properties

应用cm,并重启dubbo-monitor的pod

[root@hdss7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/cm.yaml
configmap/dubbo-monitor-cm configured

会发现容器报错了

查看日志,意思是没有conf/dubbo.properties 这个文件,这个文件又是什么?

 修改deployment资源,使其不调度configmap,进去容器看到底是啥

启动容器后,进入容器,查看dubbo-monitor-simple/conf/目录下竟然有dubbo.properties,dubbo.properties到底是啥?

[root@hdss7-21 ~]# kubectl get pod -n infra
NAME                             READY   STATUS    RESTARTS   AGE
apollo-portal-66795c5b59-j5kd6   1/1     Running   5          5d9h
dubbo-monitor-76f9845456-x2g97   1/1     Running   0          47s
jenkins-56d9fd55f9-p4ldd         1/1     Running   13         11d[root@hdss7-21 ~]# kubectl exec -it dubbo-monitor-76f9845456-x2g97 -n infra /bin/bash
bash-4.3# ls
bin                   home                  mnt                   sbin                  var
dev                   lib                   proc                  sys
dubbo-monitor-simple  linuxrc               root                  tmp
etc                   media                 run                   usr
bash-4.3# cd dubbo-monitor-simple/conf/
bash-4.3# ls
dubbo.properties         dubbo_origin.properties

查看dubbo.properties,就是dubbo_origin.properties内容

bash-4.3# cat dubbo.properties
##
# Copyright 1999-2011 Alibaba Group.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##
dubbo.container=log4j,spring,registry,jetty
dubbo.application.name=dubbo-monitor
dubbo.application.owner=Jerry
dubbo.registry.address=zookeeper://zk1.od.com:2181?backup=zk2.od.com:2181,zk3.od.com:2181
#dubbo.registry.address=zookeeper://127.0.0.1:2181
#dubbo.registry.address=redis://127.0.0.1:6379
#dubbo.registry.address=dubbo://127.0.0.1:9090
dubbo.protocol.port=20880
dubbo.jetty.port=8080
dubbo.jetty.directory=/dubbo-monitor-simple/monitor
dubbo.charts.directory=/dubbo-monitor-simple/charts
dubbo.statistics.directory=/dubbo-monitor-simple/statistics
dubbo.log4j.file=logs/dubbo-monitor-simple.log
dubbo.log4j.level=WARNbash-4.3# cat dubbo_origin.properties
##
# Copyright 1999-2011 Alibaba Group.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##
dubbo.container=log4j,spring,registry,jetty
dubbo.application.name=dubbo-monitor
dubbo.application.owner=Jerry
dubbo.registry.address=zookeeper://zk1.od.com:2181?backup=zk2.od.com:2181,zk3.od.com:2181
#dubbo.registry.address=zookeeper://127.0.0.1:2181
#dubbo.registry.address=redis://127.0.0.1:6379
#dubbo.registry.address=dubbo://127.0.0.1:9090
dubbo.protocol.port=20880
dubbo.jetty.port=8080
dubbo.jetty.directory=/dubbo-monitor-simple/monitor
dubbo.charts.directory=/dubbo-monitor-simple/charts
dubbo.statistics.directory=/dubbo-monitor-simple/statistics
dubbo.log4j.file=logs/dubbo-monitor-simple.log
dubbo.log4j.level=WARNbash-4.3# 

所以猜测应该程序把dubbo_origin.properties复制一份并改了个名字dubbo.properties,至于为什么也不清楚,所以其实程序真正调用dubbo.properties

4、交付dubbo服务的消费者

需要通过 jenkins 进行持续继承。构建提供者时候,做过流水线,消费者也可以。两个服务可以通过一个流水线完成

4.1、构建流水线

4.1.1、点击构建

4.1.2、构建填写

注:

app-name:dubbo-demo-consumer    名字随便起,建议使用项目名称
image-name:app/dubbo-demo-consumer   app不能省,到时候要推送到app私有的仓库
git_repo:git@gitee.com:jerry00713/dubbo-demo-web.git   这里注意,由于代码放到了git私有仓库(dubbo-demo-web),无法使用http形式拉取私有仓库代码。之前做过把ssh的私钥拷贝到了jenkins容器,在把ssh公钥传到了私有仓库(dubbo-demo-web),就可以使用ssh形式clone代码
git_ver:master  使用master代码分支
mvn_dir:./   不能改,代码规定要在根目录下编译
target_dir:./dubbo-client/target     不能改,代码规定编译后的.jar包放在此目录,才能运行
mvn clean package -Dmaven.test.skip=true  生产上可以写添加 -e -q 参数(mvn clean package -e -q -Dmaven.test.skip=true ) 。 -q 静默输出  -e 只有错误输出没有错误不输出。在Console Output中不会显示从公网上下载的那些jar包。

4.1.3、Bulid后查看Console Output

+ git clone git@gitee.com:jerry00713/dubbo-demo-web.git dubbo-demo-consumer/12[INFO] dubbotest-api ...................................... SUCCESS [ 11.912 s]
[INFO] dubbotest-client ................................... SUCCESS [ 12.968 s]
[INFO] demo ............................................... SUCCESS [  0.021 s]+ docker build -t harbor.od.com:180/app/dubbo-demo-consumer:master_210110_1420 .Finished: SUCCESS

扩展:第一次使用Blue Ocean参数化构建的时候(部署生产者的时候),构建很慢,而且有大量的从公网上下载的一些jar包,这次构建消费者很快,为什么?是由于构建一次后,jenkins会把java依赖的一些jar包,下载后落在本地缓存中,如果再次构建的时候,就会重新拿来使用。具体目录如下(/root/.m2/repository)。在生产上,可以把.m2目录也挂在出来,这样重启jenkins就不会丢

[root@hdss7-21 ~]# kubectl get pod -n infra
NAME                             READY   STATUS    RESTARTS   AGE
dubbo-monitor-76f9845456-424bh   1/1     Running   0          139m
jenkins-56d9fd55f9-p4ldd         1/1     Running   3          41h[root@hdss7-21 ~]# kubectl exec -it jenkins-56d9fd55f9-p4ldd -n infra /bin/bash
root@jenkins-56d9fd55f9-p4ldd:/# cd /root/.m2/;ls -l
total 0
drwxr-xr-x. 18 root root 261 Mar 31 13:30 repositoryroot@jenkins-56d9fd55f9-p4ldd:~/.m2# cd repository/
root@jenkins-56d9fd55f9-p4ldd:~/.m2/repository# ls -l
total 0
drwxr-xr-x.  3 root root  25 Mar 31 13:28 aopalliance
drwxr-xr-x.  8 root root 106 Mar 31 13:30 asm
drwxr-xr-x.  3 root root  38 Mar 31 13:27 backport-util-concurrent
drwxr-xr-x.  3 root root  17 Mar 31 13:28 ch
drwxr-xr-x.  3 root root  25 Mar 31 13:26 classworlds
drwxr-xr-x.  6 root root  66 Mar 31 13:29 com
drwxr-xr-x.  3 root root  25 Mar 31 13:27 commons-cli
drwxr-xr-x.  3 root root  24 Mar 31 13:30 commons-io
drwxr-xr-x.  3 root root  26 Mar 31 13:28 commons-lang
drwxr-xr-x.  4 root root  56 Mar 31 13:29 commons-logging
drwxr-xr-x.  3 root root  19 Mar 31 13:29 io
drwxr-xr-x.  6 root root  74 Mar 31 13:29 javax
drwxr-xr-x.  3 root root  19 Mar 31 13:29 jline
drwxr-xr-x.  3 root root  19 Mar 31 13:26 junit
drwxr-xr-x.  3 root root  19 Mar 31 13:27 log4j
drwxr-xr-x. 19 root root 265 Mar 31 13:30 org
root@jenkins-56d9fd55f9-p4ldd:~/.m2/repository# 

4.1.4、查看是否成功

1、Console Output提示成功后,检查harbor是否有对应的镜像
2、如果有问题,查看 Blue Ocean

4.2、配置资源配置清单

[root@hdss7-200 ~]# cd /data/k8s-yaml/
[root@hdss7-200 k8s-yaml]# mkdir dubbo-demo-consumer
[root@hdss7-200 k8s-yaml]# cd dubbo-demo-consumer/

[root@hdss7-200 dubbo-demo-consumer]# vi deployment.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:name: dubbo-demo-consumernamespace: applabels: name: dubbo-demo-consumer
spec:replicas: 1selector:matchLabels: name: dubbo-demo-consumertemplate:metadata:labels: app: dubbo-demo-consumername: dubbo-demo-consumerspec:containers:- name: dubbo-demo-consumerimage: harbor.od.com:180/app/dubbo-demo-consumer:master_210110_1420ports:- containerPort: 8080protocol: TCP- containerPort: 20880protocol: TCPenv:- name: JAR_BALLvalue: dubbo-client.jarimagePullPolicy: IfNotPresentimagePullSecrets:- name: harborrestartPolicy: AlwaysterminationGracePeriodSeconds: 30securityContext: runAsUser: 0schedulerName: default-schedulerstrategy:type: RollingUpdaterollingUpdate: maxUnavailable: 1maxSurge: 1revisionHistoryLimit: 7progressDeadlineSeconds: 600

注:JAR_BALL中的数值,是mvn编译后项目的jar包,根据代码不同,产生的jar包也不同,由消费者代码编译后的项目名称叫dubbo-client.jar。提供者代码编译后的项目名称叫dubbo-server.jar。所以消费者dp.yaml的env (JAR_BALL=dubbo-client.jar),提供者是(JAR_BALL=dubbo-server.jar)。

[root@hdss7-200 dubbo-demo-consumer]# vi service.yaml

kind: Service
apiVersion: v1
metadata: name: dubbo-demo-consumernamespace: app
spec:ports:- protocol: TCPport: 8080targetPort: 8080selector: app: dubbo-demo-consumer

[root@hdss7-21 ~]# vi ingress.yaml  # 因为消费者是提供给人操作的web页面项目

kind: Ingress
apiVersion: extensions/v1beta1
metadata: name: dubbo-demo-consumernamespace: app
spec:rules:- host: demo.od.comhttp:paths:- path: /backend: serviceName: dubbo-demo-consumerservicePort: 8080

4.3、 配置DNS解析

[root@hdss7-11 ~]# vi /var/named/od.com.zone

$ORIGIN od.com.
$TTL 600        ; 10 minutes
@               IN SOA  dns.od.com. dnsadmin.od.com. (2020010508 ; serial          前滚+110800      ; refresh (3 hours)900        ; retry (15 minutes)604800     ; expire (1 week)86400      ; minimum (1 day))NS   dns.od.com.
$TTL 60 ; 1 minute
dns                A    10.4.7.11
harbor             A    10.4.7.200
k8s-yaml           A    10.4.7.200
traefik            A    10.4.7.10
dashboard          A    10.4.7.10
zk1                A    10.4.7.11
zk2                A    10.4.7.12
zk3                A    10.4.7.21
jenkins            A    10.4.7.10
dubbo-monitor      A    10.4.7.10
demo               A    10.4.7.10

[root@hdss7-11 ~]# systemctl restart named
[root@hdss7-11 ~]# dig -t A demo.od.com @10.4.7.11 +short
10.4.7.10

4.4、 应用资源配置清单

[root@hdss7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/dubbo-demo-consumer/deployment.yaml
deployment.extensions/dubbo-demo-consumer created
[root@hdss7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/dubbo-demo-consumer/service.yaml
service/dubbo-demo-consumer created
[root@hdss7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/dubbo-demo-consumer/ingress.yaml
ingress.extensions/dubbo-demo-consumer created

4.4、 查看状态

4.5、 查看dubbo-monitor

如果遇到访问dubbo-monitor.od.com后出现bad gateway问题,可能是重启电脑了,导致zoopkeeper没启动。

解决方案:把启动脚本写到开机启动脚本,然后手动启动zoopkeeper,杀死已经挂掉的pod

访问dubbo-monitor.od.com,查看Application,发现dubbo-demo-consumer已经注册到注册中心。而且monitor会区分是消费者还是提供者

​​​​​​​

点击dubbo-demo-consumer 的 Consumers

dubbo-demo-consumer去注册中心(zk)中,申请一个订阅,订阅什么?订阅了一个com.od.dubbotest.api.HelloService?接口。至此访问dubbo-demo-consumer这个web项目的Hello网页,后台dubbo-demo-consumer带着访问Hello网页的url去请求dubbo-demo-service​​​​​​​的HelloService接口,最后把执行后结果反给dubbo-demo-consumer网页​​​​​​​

4.6 访问消费者的web项目的Hello网页

http://demo.od.com/hello?name=wewe

4.7、讲解此sprint boot源代码

其中消费者调用的提供者的hello方法。所以网页输入hello附带参数就会反回hello wewe

System.out.println("HelloAction接收到请求:"+name);  # 我请求(这是Dubbo 消费者端)网页,被
HelloAction接收到请求,并取到输入网页的参数name(wewe)String str="<h1>这是Dubbo 消费者端(springboot)</h1>";  # 先打印“这是Dubbo 消费者端(springboot)”System.out.println("HelloService返回到结果:"+str);  # 然后调用本地的helloService.hello(name)
方法。代码其实不知道,他调用的是通过注册中心的提供者的helloService.hello接口。代码调
用注册中心的提供者的helloService.hello接口,就跟调用本地得我一样。跟本没无任何区别。

消费者调用本地的hello方法,其实本地跟本没有hello方法,而是调用提供者声明的hello方法。但是消费者以为就是调用本地方法一样

Dubbo 这种机制有什么好处? Dubbo 典型的无状态服务,假如做促销活动,而前台是可以支撑住的,但是后台有大量的定单等,导致后台资源很卡顿,这个时候只需要对提供者做扩容,消费者不动,而扩容只需要点点dashboard就行。而且前端客户根本没有任何感觉。​​​​​​​

Kubernetes部署(四):k8s项目交付----(1)持续集成相关推荐

  1. 持续集成与持续部署宝典Part 2:创建持续集成流水线

    2019独角兽企业重金招聘Python工程师标准>>> 在本系列文章中,我们将探讨在容器时代如何在基于Docker的环境中创建连贯的工作流程和流水线来简化大规模项目的部署.另外,我们 ...

  2. Kubernetes部署(七):k8s项目交付----(4)日志收集

    介绍 日志,对于任何系统来说都是及其重要的组成部分.在计算机系统里面,更是如此.但是由于现在的计算机系统大多比较复杂,很多系统都不是在一个地方,甚至都是跨国界的:即使是在一个地方的系统,也有不同的来源 ...

  3. Kubernetes部署(五):k8s项目交付----(2)配置中心

    交付Apollo到k8s中 1.配置中心介绍 1.1.apollo介绍 思考问题: 交付Dubbo微服务的时候,所有的配置( 比如连接那个zk.暴露那个端口等等) 都在代码层.或者配置文件中声明使用, ...

  4. Kubernetes部署(六):k8s项目交付----(3)集群监控

    一.介绍Prometheus Prometheus(普罗米修斯)是一个最初在SoundCloud上构建的监控系统.自2012年成为社区开源项目,拥有非常活跃的开发人员和用户社区.为强调开源及独立维护, ...

  5. 专题篇四:Linux企业级CICD持续集成交付发布(终极实战部署:gitlab++jenkins+web(tomcat)+webbook自动发布)

    4,企业级CI/CD 持续集成/交付/发布 实验一:github+jenkins+web(tomcat) 构建的时候 网络连接超时(正常现象) githud仓库地址1.安装对应的插件(jenkins) ...

  6. iis cgi 无法使用_ASP.NET Core前后端分离项目使用gitlabci持续集成到IIS

    (给DotNet加星标,提升.Net技能) 转自:饭勺oOcnblogs.com/fanshaoO/p/12054985.html 现在好多使用gitlab-ci的持续集成的教程,大部分都是发布到li ...

  7. 一步步部署基于Windows系统的Jenkins持续集成环境

    如题:本文将介绍如何在Windows环境下运用Jenkins部署持续集成环境.之所以写本文,是因为在最近工作当中,学习使用Jenkins时,确实遇到了一些问题,而大多数教程文档都是基于Mac或是Lin ...

  8. 如何做好持续集成和部署?你不容错过的持续集成工具—Jenkins

    持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成.每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地 ...

  9. svn增量打包部署_超详细的jenkins持续集成工作原理、功能、部署方式等介绍

    概述 今天简单整理了一下jenkins的一些概念性内容,归纳如下: 1.概念 jenkins是一个开源项目,提供了一种易于使用的持续集成系统,使开发者从繁杂的集成中解脱出来,专注于更为重要的业务逻辑实 ...

最新文章

  1. 暑期集训1:C++STL 练习题D:HDU-1509
  2. 斯坦福大学开发自主无人机摄影的算法,可显著提高电影中无人机镜头品质
  3. ubuntu查看文件和文件夹大小
  4. git 工作流和git commit规范
  5. JAVA 10(多线程)
  6. lambda与内置函数
  7. jprofiler安装与使用
  8. Java工作笔记-IntelliJ IDEA中高效文件切换跳转
  9. oracle同音模糊查询
  10. 解决jy61陀螺仪传感器读数跳动的问题
  11. 【微信小程序开发日记01】和风天气OUC之初步构想
  12. 【安全】eWebeditor编辑器上传webshell
  13. 虚拟机几种联网的方式,如何共享主机IP
  14. php 简明现代魔法,【转】WinCacheGrind配合XDebug分析PHP程序性能 — 简明现代魔法...
  15. Android Launcher桌面图标显示数字
  16. 结构体中元素引用—— “.“ 与 “->“
  17. 高通平台 UART log 开启方法
  18. lctf2017_2ze4u_reproduce
  19. 如何成为一名成功的 PHP 开发者
  20. python space_Python之Function

热门文章

  1. 华为认证HCIA-Datacom知识点
  2. android图片裁剪xof,HttpServletResponse response相关头信息,内容信息设置
  3. HTML5 UI 模板
  4. 腾讯云通信WebIM事件回调的坑~
  5. nmn对身体有用吗,nmn修复效果怎么样,其中的原理你要知道
  6. 基于PyQt的分组工具
  7. Spring Boot 实现定时任务
  8. 深圳python 培训班价格
  9. python拼音怎么写-[编程心得]用Python给汉字加上带音调的拼音
  10. DHCP Relay的介绍