1. 组件介绍

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)

4.1 持续集成 - 图1

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/

下载地址: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. 实验拓扑图

4.1 持续集成 - 图2

4.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

4.1 持续集成 - 图4

3.6. 配置Jenkins

3.6.1. 配置安全策略

4.1 持续集成 - 图5

4.1 持续集成 - 图6

3.6.2. 配置插件加速地址

4.1 持续集成 - 图7

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

4.1 持续集成 - 图8

# 修改下载地址
[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

4.1 持续集成 - 图9

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。