1. 组件介绍
1.1 微服务
1.1.1 简介
微服务 (Microservices) 是一种软件架构风格,它是以专注于单一责任与功能的小型功能区块 (Small Building Blocks) 为基础,利用模块化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关 (Language-Independent/Language agnostic) 的 API 集相互通信。微服务的优点:应用解耦,可以单独升级,甚至不同模块之间可以编程语言不同;横向扩展方便,高可用。缺点:架构复杂,运维成本高
1.1.2. Dubbo微服务框架
阿里巴巴在2011年开源了Dubbo框架,虽然在2013年停止更新,但在2017年9月又重启维护并发布了新版本。目前已有很多的公司将自己的业务建立在Dubbo之上,同时阿里云也推出了企业级分布式应用服务EDAS,为Dubbo提供应用托管。Dubbo采用Zookeeper作为注册中心,RPC作为服务调用方式,致力于提供高性能和透明化的RPC远程服务调用方案。
- Provider:服务提供方发布服务到服务注册中心
- Consumer:服务消费方从服务注册中心订阅服务
- Registry:注册中心通知消息调用方服务已注册
- Monitor:监控计数
- 服务消费方调用已经注册的可用服务(RPC invoke)

1.2. Devops流水线
1.2.1. Jenkins
Jenkins是一款由Java编写的开源的持续集成工具。它运行在Servlet容器中(例如Apache Tomcat)。它支持软件配置管理(SCM)工具(包括AccuRev SCM、CVS、Subversion、Git、Perforce、Clearcase和RTC),可以执行基于Apache Ant和Apache Maven的项目,以及任意的Shell脚本和Windows批处理命令。Jenkins是一个有状态的应用,如果托管在K8S中,只运行一个副本,且需要持久化存储。
下载地址:https://jenkins.io/zh/download/
官方文档:https://jenkins.io/zh/doc/
1.2.2. Maven
Apache Maven,是一个软件(特别是Java软件)项目管理及自动构建工具,由Apache软件基金会所提供。Maven也可被用于构建和管理各种项目,例如C#,Ruby,Scala和其他语言编写的项目。Maven曾是Jakarta项目的子项目,现为由Apache软件基金会主持的独立Apache项目。在Devops流水线中,参与Java程序构建工具常用Maven。
官网:https://maven.apache.org/index.html
下载地址:https://archive.apache.org/dist/maven/
基础教程:https://www.runoob.com/maven/maven-setup.html
1.3. 实验拓扑图


2. ZK集群部署
ZK集群是有状态的服务,其选择Leader的方式和ETCD方式类似,要求集群节点是不低于3个的奇数点
| 主机 | IP地址 | 角色 |
|---|---|---|
| hdss7-11 | 10.4.7.11 | zk1 |
| hdss7-12 | 10.4.7.12 | zk2 |
| hdss7-21 | 10.4.7.21 | zk3 |
2.1 安装jdk
# 下载源码包
cd /opt/src
wget k8s-yaml.od.com/gzDir/jdk-8u121-linux-x64.tar.gz
# 解包 做软链
mkdir /usr/java
tar xf jdk-8u121-linux-x64.tar.gz -C /usr/java/
ln -s /usr/java/jdk1.8.0_121 /usr/java/jdk
# 添加环境变量
vim /etc/profile
#jdk env
export JAVA_HOME=/usr/java/jdk
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar
# 测试
source /etc/profile
java -version
2.2 配置DNS解析
vim /var/named/od.com.zone
$ORIGIN od.com.
$TTL 600 ; 10 minutes
@ IN SOA dns.od.com. dnsadmin.od.com. (
20200625 ; serial
10800 ; 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
monitor.api A 10.4.7.10
zk1 A 10.4.7.11
zk2 A 10.4.7.12
zk3 A 10.4.7.21
[root@hdss7-11 java]# systemctl restart named
[root@hdss7-11 java]# dig -t A zk3.od.com @10.4.7.11 +short
10.4.7.21
2.3 安装ZK
# 下载zk
cd /opt/src
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz
# 解包 做软链
tar xf zookeeper-3.4.14.tar.gz -C /opt/
ln -s /opt/zookeeper-3.4.14 /opt/zookeeper
# 创建目录 配置
mkdir -p /data/zookeeper/data /data/zookeeper/logs
vim /opt/zookeeper/conf/zoo.cfg
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
[root@hdss7-11 ~]# echo 1 > /data/zookeeper/data/myid # 三台节点分别设为1,2,3
[root@hdss7-12 ~]# echo 2 > /data/zookeeper/data/myid
[root@hdss7-21 ~]# echo 3 > /data/zookeeper/data/myid
- 启动
[root@hdss7-12 ~]# /opt/zookeeper/bin/zkServer.sh --help
ZooKeeper JMX enabled by default
Using config: /opt/apps/zookeeper/bin/../conf/zoo.cfg
Usage: /opt/apps/zookeeper/bin/zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd}
[root@hdss7-12 ~]# /opt/zookeeper/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/apps/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@hdss7-12 ~]# /opt/zookeeper/bin/zkServer.sh status # 查看三个节点,其中一个为leader,其它为follower
ZooKeeper JMX enabled by default
Using config: /opt/apps/zookeeper/bin/../conf/zoo.cfg
Mode: follower
-----
# 如果需要使用 supervisor 管理,需要调整启动脚本,比如配置Java环境变量
3. Jenkins部署
3.1 制作jenkins镜像
dockerHub:https://hub.docker.com/r/jenkins/jenkins/tags
服务器:HDSS7-200
harbor仓库提前创建 infra私有仓库
# 拉取镜像,推送本地私有仓库
[root@hdss7-200 gzDir]# docker pull jenkins/jenkins:2.242
[root@hdss7-200 gzDir]# docker tag 60d14d1a9c5e harbor.od.com/public/jenkins:v2.242
[root@hdss7-200 gzDir]# docker push harbor.od.com/public/jenkins:v2.242
# 准备相关文件
[root@hdss7-200 docker_files]# mkdir /opt/docker_files
[root@hdss7-200 docker_files]# cd /opt/docker_files
[root@hdss7-200 docker_files]# ssh-keygen -t rsa -b 2048 -C "312639695@qq.com" -N "" -f id_rsa
[root@hdss7-200 docker_files]# cp ~/.docker/config.json ./ # Docker登陆信息
# 该脚本就是在docker-ce源中安装了一个docker-ce-cli
# --mirror=Aliyun 指定使用阿里云的repo仓库
[root@hdss7-200 docker_files]# wget -O get-docker.sh https://get.docker.com
[root@hdss7-200 docker_files]# vim Dockerfile
# 修改默认的 Jenkins 镜像
FROM harbor.od.com/public/jenkins:v2.242
USER root
ADD id_rsa /root/.ssh/id_rsa
ADD config.json /root/.docker/config.json
ADD get-docker.sh /get-docker.sh
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone && echo " StrictHostKeyChecking no" >> /etc/ssh/ssh_config && sh /get-docker.sh --mirror=Aliyun ; rm -f get-docker.sh
[root@hdss7-200 docker_files]# docker image build -t harbor.od.com/infra/jenkins:v2.242 ./
# infra 是harbor的一个私有仓库,是infrastructure(基础设置)的缩写
[root@hdss7-200 docker_files]# docker image push harbor.od.com/infra/jenkins:v2.242
3.2. 准备NFS共享存储
NFS共享存储放在 hdss7-200 上,用于存储Jenkins持久化文件。所有Node和hdss7-200都需要安装
服务器:hdss7-21,hdss7-22,hdss7-200
200为nfs服务端
其他为客户端
[root@hdss7-200 ~]# for i in 21 22 200;do ssh hdss7-$i "yum install -y nfs-utils";done
[root@hdss7-200 ~]# for i in 21 22 200;do echo -ne "hdss7-$i\t";ssh hdss7-$i "rpm -q nfs-utils >/dev/null 2>&1 && echo yes || echo no";done
[root@hdss7-200 ~]# systemctl start nfs ; systemctl enable nfs
[root@hdss7-200 ~]# mkdir -p /data/nfs-volume/jenkins_home
[root@hdss7-200 ~]# vim /etc/exports
/data/nfs-volume 10.4.7.0/24(rw,sync,no_root_squash)
[root@hdss7-200 ~]# systemctl reload nfs
[root@hdss7-200 ~]# showmount -e
Export list for hdss7-200.host.com:
/data/nfs-volume 10.4.7.0/24
3.3. 部署Jenkins
# 创建命名空间
[root@hdss7-21 ~]# kubectl create namespace infra
# 创建登陆secret
[root@hdss7-21 ~]# kubectl create secret docker-registry harbor --docker-server=harbor.od.com --docker-username=admin --docker-password=Harbor12345 -n infra
- docker-registory 登陆密钥
# docker-registory 登陆密钥
# 使用 kubectl create secret docker-registry ... 生成的
apiVersion: v1
kind: Secret
metadata:
name: harbor
namespace: infra
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: eyJhdXRocyI6eyJodHRwOi8vaGFyYm9yLm9kLmNvbS8iOnsidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoiSGFyYm9yMTIzNDUiLCJhdXRoIjoiWVdSdGFXNDZTR0Z5WW05eU1USXpORFU9In19fQ==
- deployment.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: jenkins
namespace: infra
labels:
name: jenkins
spec:
replicas: 1
selector:
matchLabels:
name: jenkins
template:
metadata:
labels:
app: jenkins
name: jenkins
spec:
volumes:
- name: data
nfs:
server: hdss7-200
path: /data/nfs-volume/jenkins_home
- name: docker
hostPath:
path: /run/docker.sock
type: ''
containers:
- name: jenkins
image: harbor.od.com/infra/jenkins:v2.242
ports:
- containerPort: 8080
protocol: TCP
env:
- name: JAVA_OPTS
value: -Xmx512m -Xms512m
volumeMounts:
- name: data
mountPath: /var/jenkins_home
- name: docker
mountPath: /run/docker.sock
imagePullSecrets:
- name: harbor
securityContext:
runAsUser: 0
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 0
revisionHistoryLimit: 7
progressDeadlineSeconds: 600
- service.yaml
kind: Service
apiVersion: v1
metadata:
name: jenkins
namespace: infra
spec:
ports:
- protocol: TCP
port: 80
targetPort: 8080
selector:
app: jenkins
- ingress.yaml
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: jenkins
namespace: infra
spec:
rules:
- host: jenkins.od.com
http:
paths:
- path: /
backend:
serviceName: jenkins
servicePort: 80
[root@hdss7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/jenkins/deployment.yaml
[root@hdss7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/jenkins/service.yaml
[root@hdss7-21 ~]# kubectl apply -f http://k8s-yaml.od.com/jenkins/ingress.yaml
3.4 配置dns解析
vim /var/named/od.com.zone
$ORIGIN od.com.
$TTL 600 ; 10 minutes
@ IN SOA dns.od.com. dnsadmin.od.com. (
20200625 ; serial
10800 ; 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
monitor.api 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
3.5 登陆jenkins
[root@hdss7-21 ~]# kubectl get pod -n infra
NAME READY STATUS RESTARTS AGE
jenkins-54b8469cf9-mtkm5 1/1 Running 0 2m16s
[root@hdss7-21 ~]# kubectl log -f jenkins-54599f57bd-9rnf2 -n infra # 取得初始化密码
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:
04e1fec0d9db4283b6076532f857f137
This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
# 检查Pod:运行用户是否为root、时区、是否连接到本地docker server、是否都能登陆harbor
[root@hdss7-21 ~]# kubectl exec jenkins-54599f57bd-9rnf2 -n infra -- /bin/sh -c "ps aux|grep jenkins|grep -v grep"
root 1 0.0 0.0 1136 4 ? Ss 17:37 0:00 /sbin/tini -- /usr/local/bin/jenkins.sh
root 6 4.6 11.6 4127220 449464 ? Sl 17:37 1:11 java -Duser.home=/var/jenkins_home -Xmx512m -Xms512m -Djenkins.model.Jenkins.slaveAgentPort=50000 -jar /usr/share/jenkins/jenkins.war
[root@hdss7-21 ~]# kubectl exec jenkins-54599f57bd-9rnf2 -n infra -- /bin/sh -c "date"
Sat Feb 1 12:02:28 CST 2020
[root@hdss7-21 ~]# kubectl exec jenkins-54599f57bd-9rnf2 -n infra -- /bin/sh -c "docker container ps"
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b76e1b0db2c4 add5fac61ae5 "/entrypoint.sh --ap…" Less than a second ago Up Less than a second k8s_traefik-ingress_traefik-ingress-vtlch_kube-system_da355707-a2d1-4f79-8dfd-3ebe36c6d31d_9
9e7b423da707 harbor.od.com/public/pause:latest "/pause" Less than a second ago Up Less than a second 0.0.0.0:81->80/tcp k8s_POD_traefik-ingress-vtlch_kube-system_da355707-a2d1-4f79-8dfd-3ebe36c6d31d_9
14f439b5bac9 ae5fe3d4bbb7 "/sbin/tini -- /usr/…" 34 minutes ago Up 34 minutes k8s_jenkins_jenkins-54b8469cf9-s6k4h_infra_9d14995c-7205-4b2c-98e9-de81a7e1845c_0
b4c79a78aee2 harbor.od.com/public/pause:latest "/pause" 34 minutes ago Up 34 minutes k8s_POD_jenkins-54b8469cf9-s6k4h_infra_9d14995c-7205-4b2c-98e9-de81a7e1845c_0
[root@hdss7-21 ~]# kubectl exec jenkins-54599f57bd-9rnf2 -n infra -- /bin/sh -c "docker login harbor.od.com"
Authenticating with existing credentials...
Login Succeeded
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-store
# 确认是否能通过SSH方式连接到git仓库
[root@hdss7-21 ~]# kubectl exec jenkins-54599f57bd-9rnf2 -n infra -- /bin/sh -c "ssh -i /root/.ssh/id_rsa -T git@gitee.com"
Hi StanleyWang (DeployKey)! You've successfully authenticated, but GITEE.COM does not provide shell access.
Note: Perhaps the current use is DeployKey.
Note: DeployKey only supports pull/fetch operations

3.6. 配置Jenkins
3.6.1. 配置安全策略


3.6.2. 配置插件加速地址

地址: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

3.7. 安装Maven到Jenkins
Maven是提供给Jenkins使用,需要放到Jenkins的持久化目录中,直接将二进制包形式的Maven拷贝到Jenkins目录最方便。因此本次安装直接在 hdss7-200 操作。
在公司中,不同的项目对编译的JDK版本和Maven可能不同,可能需要多个版本的JDK和Maven组合使用,因此Maven目录名称就使用 maven-${maven_versin}-${jdk_version}格式。Maven的 bin/mvn 文件中可以定义 JAVA_HOME环境变量的值,不同的Maven可以使用不同的 JAVA_HOME 值。
3.7.1. 场景一
当Maven需求的jdk版本和jenkins一致时,不需要定义 bin/mvn 中JAVA_HOME。
