Loading

k8s平台基于Jenkins构建微服务发布平台-1

实验架构说明: 根据上篇文章 <<6、微服务容器化迁移>> 环境进行操作

(1) nfs存储
(2) harbor镜像仓库
(3) gitlab代码仓库
(4) ingress-nginx
(5) nfs-subdir-external-provisioner

发布流程设计: image-20220209145255750

基于kubernetes完整的DevOps流程: 基于kubernetes完整的DevOps流程

1 部署Jenkins

1.1 配置说明
1 Jenkins是一款开源的CI&CD系统,用于自动化各种任务,包括构建、测试和部署。
2 Jenkins官方提供了镜像"https://hub.docker.com/r/jenkins/jenkins"。
3 在"default"命名空间下使用"Deployment"方式来部署这个镜像,"kind: Service"使用"type: NodePort"暴露端口,Web内部访问端口80,
Web外部访问端口30006,Slave内部通信端口5000,容器启动后Jenkins数据存储在"/var/jenkins_home"目录,所以需要将该目录使用PV持久化
存储。
1.2 Jenkins.yml配置文件
[root@k8s-master1 ms_jenkins]# cat jenkins.yml
apiVersion: apps/v1
kind: Deployment 
metadata:
  name: jenkins
  labels:
    name: jenkins
spec:
  replicas: 1
  selector:
    matchLabels:
      name: jenkins 
  template:
    metadata:
      name: jenkins
      labels:
        name: jenkins
    spec:
      terminationGracePeriodSeconds: 10
      serviceAccountName: jenkins
      containers:
        - name: jenkins
          image: jenkins/jenkins
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
            - containerPort: 50000
          resources:
            limits:
              cpu: 1
              memory: 1Gi
            requests:
              cpu: 0.2
              memory: 200Mi
          env:
            - name: JAVA_OPTS
              value: -Xmx1g 
          volumeMounts:
            - name: jenkins-home
              mountPath: /var/jenkins_home
      securityContext:
        fsGroup: 1000
        runAsUser: 0
      volumes:
        - name: jenkins-home
          persistentVolumeClaim:
            claimName: jenkins-home
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-home
spec:
  storageClassName: "managed-nfs-storage"
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 5Gi
---
apiVersion: v1
kind: Service
metadata:
  name: jenkins
spec:
  selector:
    name: jenkins
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 8080
      protocol: TCP
      nodePort: 30006
    - name: agent
      port: 50000
      protocol: TCP
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins

---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: jenkins
rules:
- apiGroups: [""]
  resources: ["pods","events"]
  verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get","list","watch"]
- apiGroups: [""]
  resources: ["secrets","events"]
  verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: jenkins
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: jenkins
subjects:
- kind: ServiceAccount
  name: jenkins
[root@k8s-master1 ms_jenkins]#

1.3 部署Jenkins
# kubectl apply -f jenkins.yml
# kubectl get pod -l name=jenkins -n default
# kubectl get svc/jenkins -n default
# kubectl get ep/jenkins -n default
#
# kubectl get pv
# kubectl get pvc -n default

图示: image-20220209141209853

1.4 Jenkins UI界面安装步骤
1 获取Jenkins初始化安装密码
# kubectl logs -f pod/jenkins-578b57ddcb-dzn7n -n default
......(省略的内容)
Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

72c0bc4c4a6748aba3fa39b0797eb08c

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
......(省略的内容)

2 解锁Jenkins

http://172.16.1.81:30006/ image-20220209142841067

3 选择插件来安装

图示: image-20220209143056008

4 不安装任何的插件

图示: image-20220209143304983

5 创建管理员

图示: image-20220209143804755

6 Jenkins URL

图示: image-20220209144011945

7 Jenkins安装完成

图示: image-20220209144218742

8 Jenkins首页

图示: image-20220209144424351

1.5 安装插件
Manage Jenkins -> System Configuration -> Manage Plugins -> Available -> 分别搜索 
Chinese/Git/Git Parameter/Pipeline/kubernetes/Config File Provider/Extended Choice Parameter -> 选中后点击
Install without restart

1 Chinese # 中文字体
2 Git # 拉取代码
3 Git Parameter # Git参数化构建
4 Pipeline # 流水线
5 kubernetes # 连接Kubernetes动态创建Slave代理
6 Config File Provider # 存储配置文件
7 Extended Choice Parameter # 扩展选择框参数,支持多选

插件安装完成后必须重启Jenkins,否则安装的插件无法正常使用,重启Jenkins的方法为: http://172.16.1.81:30006/restart

提示: Jenkins的UI界面上可能会提示Jenkins版本升级和一些警告信息,忽略即可。

图示: image-20220210102701446

2 Jenkins在kubernetes中动态创建代理

2.1 Jenkins主从架构介绍
1 Jenkins Master/Slave架构
Master(Jenkins本身)提供Web页面让用户来管理项目和从节点(Slave),项目任务可以运行在Master本机或者分配到从节点运行,一个Master可以关联多个Slave,这样的好处是可以让Slave分担Master工作压力和隔离构建环境。

Jenkins Master/Slave架构图: image-20220209170545295

2 当触发Jenkins任务时,Jenkins会调用Kubernetes API创建Slave Pod,Pod启动后会连接Jenkins,接受任务并处理。

图示: image-20220209173620420

2.2 kubernetes插件配置
1 kubernetes插件介绍
Kubernetes插件用于Jenkins在Kubernetes集群中运行动态代理,插件介绍"https://github.com/jenkinsci/kubernetes-plugin"。

2 配置插件
系统管理 -> 系统配置 -> 节点管理 -> Configure Clouds -> 配置集群 -> Add a new cloud -> Kubernetes ->
Kubernetes Cloud details
(1) Jenkins连接k8s配置

图示: image-20220210110135542

(2) jenkins slave连接jenkins master配置

图示: image-20220210113028929

2.3 自定义Jenkins Slave镜像
1 编排 jenkins slave 镜像所需的配置文件
[root@k8s-master1 ms_jenkins]# mkdir -p jenkins-slave/
[root@k8s-master1 ms_jenkins]# cd jenkins-slave/

(1) Dockerfile
# cat Dockerfile
FROM centos:7
LABEL maintainer lc

RUN yum install -y java-1.8.0-openjdk maven curl git libtool-ltdl-devel && \
yum clean all && \
rm -rf /var/cache/yum/* && \
mkdir -p /usr/share/jenkins

COPY agent.jar /usr/share/jenkins/agent.jar
COPY jenkins-agent /usr/bin/jenkins-agent
COPY settings.xml /etc/maven/settings.xml
RUN chmod +x /usr/bin/jenkins-agent
COPY helm kubectl /usr/bin/

ENTRYPOINT ["jenkins-agent"]

(2) helm
下载地址: https://get.helm.sh/helm-v3.4.2-linux-amd64.tar.gz
# chmod +x helm

(3) jenkins-agent
github开源地址: https://github.com/jenkinsci/docker-inbound-agent
下载代码库: https://github.com/jenkinsci/docker-inbound-agent/archive/refs/heads/master.zip
使用 "jenkins-agent" shell 脚本文件。

(4) kubectl
# cp -a /usr/bin/kubectl /root/ms_jenkins/jenkins-slave/
# chmod +x /root/ms_jenkins/jenkins-slave/kubectl

(5) settings.xml
下载地址: http://archive.apache.org/dist/maven/maven-3/3.5.0/binaries/apache-maven-3.5.0-bin.tar.gz

配置文档: https://developer.aliyun.com/article/512821
在 setttins.xml 文件中找到 <mirrors></mirrors> 标签对,添加如下内容:
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

(6) agent.jar
# wget http://172.16.1.81:30006/jnlpJars/agent.jar

2 编排 jenkins slave 镜像所需的配置文件说明
[root@k8s-master1 jenkins-slave]# ls -l
total 81428
-rw-r--r-- 1 root root 1522173 Feb 10 10:00 agent.jar # jenkins agent 程序,接受 master 下发的任务
-rw-r--r-- 1 root root 423 Feb 10 17:02 Dockerfile # jenkins slave 镜像编排文件
-rwxr-xr-x 1 root root 41603072 Dec 9 2020 helm # helm 二进制文件,客户端工具
-rw-r--r-- 1 root root 5390 Feb 10 17:16 jenkins-agent # shell 脚本用于启动 agent.jar
-rwxr-xr-x 1 root root 40230912 Dec 9 2020 kubectl # kubectl 二进制文件,客户端工具
-rw-r--r-- 1 root root 10406 Feb 10 17:36 settings.xml # maven 配置文件

3 构建 jenkins slave 镜像并推送到镜像仓库
说明: 构建的 jenkins slave 镜像作为中间件镜像使用,因此将其放到公开项目 library 下
(1) 构建镜像
[root@k8s-master1 jenkins-slave]# docker build -t 172.16.1.61/library/jenkins-slave-jdk:1.8 .

(2) 推送到镜像仓库
[root@k8s-master1 jenkins-slave]# docker push 172.16.1.61/library/jenkins-slave-jdk:1.8

(3) 查看推送的镜像

图示: image-20220210183255565

2.4 测试Jenkins主从架构
1 新建项目 -> 项目名(jenkins-slave-test) -> 流水线 -> Pipeline script -> 生成示例[Declarative(Kubernetes)]

2 生成示例[Declarative(Kubernetes)]
pipeline {
    agent {
        kubernetes {
            // 定义pod名称的前缀,如果不定义,pod名称的前缀为项目名
            label "jenkins-agent"
            yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  # 这里容器名必须定义为jnlp
  - name: jnlp
    image: 172.16.1.61/library/jenkins-slave-jdk:1.8
'''
        }
    }
    stages {
        stage('Main') {
            steps {
                sh 'hostname'
            }
        }
    }
}

3 查看构建输出
pipeline 项目在执行的过程中会在 k8s 集群中创建 Jenkins slave pod,pipeline 项目运行结束后会自动销毁创建的 pod。 
[root@k8s-master1 ~]# kubectl get pod -n default
NAME                                      READY   STATUS    RESTARTS   AGE
jenkins-578b57ddcb-6lfbw                  1/1     Running   0          3h30m
jenkins-agent-bddp0-q5pnh                 1/1     Running   0          9s

图示: image-20220213225954842

3 Jenkins Pipeline流水线

3.1 Pipeline介绍
Jenkins Pipeline是一套运行工作流框架,将原本独立运行单个或者多个节点的任务链接起来,实现单个任务难以完成的复杂流程编排和可视化。
1 Jenkins Pipeline 是一套插件,支持在 Jenkins 中实现持续集成和持续交付。
2 Pipeline 通过特定语法对简单到复杂的传输管道进行建模。
3 Jenkins Pipeline 的定义被写入一个文本文件,称为Jenkinsfile。

图示: image-20220214092905306

3.2 Pipeline语法
pipeline 语法包括声明式和脚本式两种。
1 声明式
支持大部分Groovy,具有丰富的语法特性,易于编写和设计,pipeline {}

图示: image-20220214093948315

2 脚本式
遵循与Groovy相同的语法,node {}

图示: image-20220214094041154

3.3 Pipeline示例
1 jenkins example
pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                echo 'build......'
            }
        }
        
        stage('Test') {
            steps {
                echo 'Test......'
            }
        }
        
        stage('Deploy') {
            steps {
                echo 'deploy......'
            }
        }
        
    }
}

2 参数说明
(1) "stages" 是 Pipeline 中最主要的组成部分,Jenkins 将会按照 stages 中描述的顺序从上往下的执行。

(2) "stage"  是一个 Pipeline 可以划分为若干个 stage,每个 stage 代表一组操作,比如: Build、Test、Deploy。

(3) "steps"  步骤,steps 是最基本的操作单元,可以是打印一句话,也可以是构建一个 Docker 镜像,由各类 Jenkins
插件提供,比如命令: sh 'mvn',就相当于我们平时 shell 终端中执行 mvn 命令一样。

4 流水线自动发布微服务项目

4.1 发布需求
1 将微服务项目自动化部署到K8s平台的需求
(1) 尽量完全自动化部署,无需过多人工干预。
(2) 可以选择升级某个、某些微服务。
(3) 在部署、升级微服务时,可对微服务某些特性做配置,例如命名空间、副本数量。

2 发布过程
拉取代码 -> 代码编译 -> 构建镜像 -> 部署到 kubernetes -> 测试

图示: image-20220214111334922

image-20220214111423522

图示: image-20220227194259163

4.2 实现思路
在微服务架构中,会涉及几个、几十个微服务,如果每个服务都创建一个item,会增加维护的成本,因此需要编写一个通用的Pipeline脚本,将这些
微服务部署差异化的部分使用Jenkins参数化,然后由人工交互确认发布微服务、环境配置等。但这只是解决了用户的交互层面,在K8s实际部署项目
时用YAML创建对应的资源,现在的问题是如何接收用户的交互参数,自动化生成 YAML 文件,这就会用到 Helm 完成 YAML 文件的高效复用和微服
务部署。
4.3 gitlab、harbor认证添加
1 启用 Harbor 的 Chart 仓库服务
[root@k8s_harbor ~]# cd /usr/local/harbor/
[root@k8s_harbor harbor]# ./install.sh --with-chartmuseum
# 启用后,默认创建的项目就带有 helm charts 功能了,不需要重启 harbor 服务。

Helm Charts插件: image-20220227193442139

上传Charts代码包: image-20220227211449095

2 推送微服务代码到 gitlab 的 microservice 仓库
[root@k8s-master1 ms_jenkins]# unzip simple-microservice.zip
[root@k8s-master1 ms_jenkins]# cd simple-microservice/
[root@k8s-master1 simple-microservice]# git config --global user.name "Administrator"
[root@k8s-master1 simple-microservice]# git config --global user.email "admin@example.com"
[root@k8s-master1 simple-microservice]# git init
Initialized empty Git repository in /root/ms_jenkins/simple-microservice/.git/
[root@k8s-master1 simple-microservice]# git remote add origin http://172.16.1.62:9999/dev/microservice.git
[root@k8s-master1 simple-microservice]# git add .
[root@k8s-master1 simple-microservice]# git commit -m "Initial commit"
[root@k8s-master1 simple-microservice]# git push -u origin master
Username for 'http://172.16.1.62:9999': root
Password for 'http://root@172.16.1.62:9999': # 密码: 12345678

图示: image-20220227185541834

3 将 gitlab 认证和 harbor 认证保存到 Jenkins 凭据
系统管理 -> 安全 -> 管理凭据 -> Jenkins -> 全局凭据(添加凭据) -> 类型(Username with password)
分别添加连接 gitlab 和 harbor 的用户名、密码到 Jenkins 凭据,然后获取该凭据 ID 替换到脚本中 git_auth 和
docker_registry_auth 变量的值。

图示(gitlab认证): image-20220227195708153

图示(harbor认证): image-20220227200102825 gitlab、harbor全局凭证ID:

gitlab ID: 26abeef4-acf8-4ba8-8e4e-454bc8a77513
harbor ID: a87872af-6fd5-45ed-a6b3-fb59ce0bcbf4

image-20220227200237164

4 将 kubeconfig 存储在 Jenkins,用于 slave 镜像里 kubectl 连接 k8s 集群
系统管理 -> 系统配置 -> Managed files -> Add a new Config -> Custom file -> Next -> Content字段(填写内容是
kubeconfig,kubeadm 部署 k8s 默认路径在 master 节点 "/root/.kube/config",如果是二进制部署,需要自己生成),然后
复制 ID 替换脚本中 k8s_auth 变量的值。

说明: 将 kubectl、helm 工具封装到 Slave 镜像中,并通过 Config File Provider 插件存储连接 K8s 集群的 kubeconfig 认证
文件,然后挂载到 slave 容器中,这样就能使用 "kubectl apply deploy.yaml --kubeconfig=config" 命令管理 K8s 应用了,为
提高安全性,kubeconfig 文件可分配权限。

图示(k8s认证):

k8s_auth ID: 1f58f4c8-720f-4126-91c7-b4d919655737

image-20220227210330859

注: 剩余内容请查看文章"基于Jenkins构建微服务发布平台-2"


posted @ 2022-02-27 23:35  云起时。  阅读(1647)  评论(0编辑  收藏  举报