Jenkins之使用ansible发布项目
# 一、前言
ansible
属于批量管理工具,关于ansible的安装配置这里不在详细介绍,直接参考文档 (opens new window)即可,需要注意的是,使用ansible需要Jenkins主机可以免密登录目标机器。
# 二、ansible配置
# 2.1 创建主机清单
需要Jenkins主机可以免密登录主机组中的机器
# 查看目前版本
[root@localhost ~]# ansible --version
ansible 2.9.27
# 主机清单 默认文件/etc/ansible/hosts
# ## 新增开发主机组
[hz-hosts-ali]
47.99.69.144
# ## ansible测试
[root@localhost ansible]# ansible hz-hosts-ali -m 'ping'
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
47.99.69.144 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 2.2 配置palybook
# 创建目录
[root@localhost ansible]# mkdir roles/docker/tasks -p
# task 剧本文件
[root@localhost ansible]# vim roles/docker/tasks/main.yml
剧本具体内容在下面介绍
# 入口文件
[root@localhost ansible]# cat docker.yml
- hosts: all
gather_facts: yes
remote_user: root
roles:
- docker
# 执行
[root@localhost ansible]# ansible-playbook docker.yml -l hz-hosts-ali -e name="dingtalk" -e port="18084"
2
3
4
5
6
7
8
9
10
11
12
13
14
- ansible执行过程
- 目标主机结果
::: detail mail.yml
- pip:
name: docker
state: present
- name: Login registry
docker_login:
registry: registry.cn-hangzhou.aliyuncs.com
username: ${user}
password: ${password}
reauthorize: yes
- name: Pull image
docker_image:
name: registry.cn-hangzhou.aliyuncs.com/tf-public/{{ name }}:{{ env | default('latest') }}
force: yes
- name: Restart container
docker_container:
name: "{{ docker_name | default(name) }}"
image: registry.cn-hangzhou.aliyuncs.com/tf-public/{{ name }}:{{ env | default('latest') }}
network_mode: host
volumes:
- /data/apps/logs:/data/apps/logs
log_driver: json-file
log_options:
max-size: "10M"
max-file: "2"
recreate: yes
restart_policy: always
state: started
- name: Clean image
shell: docker image prune -f
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
:::
注意
这里发布docker使用的是ansible的docker模块,因此我们需要先在目标主机安装pip命令,可以通过yum -y install python-pip
安装,并且不能使用Centos7.9版本,因为自带的python3会影响模块的使用。
# 三、Docker发布
前面文章我们提到过使用Docker部署Java项目,这里我进改造下,只要ansible进行发布,这样可以方便我们后续的维护,这种不仅适用于Docker本机部署也可以远程部署,其他应用部署也是一样可以,只需要修改剧本内容即可。
# 3.1 修改发布配置
直接修改CD脚本配置
# 新增内容
HOSTS="hz-hosts-ali"
DOCKER_NAME="dingtalk"
PORT=18084
ansible-playbook docker.yml -l ${HOSTS} -e name="dingtalk" -e port="18084"
2
3
4
5
6
::: detail 完整内容
# 变量配置
JAR_PATH="${WORKSPACE}/sp-erp/target"
JAR_NAME="sp-erp-1.0-SNAPSHOT.jar"
APP_PATH="/data/apps/sp-erp"
DOCKER_HUB="registry-vpc.cn-hangzhou.aliyuncs.com/qpos" ## 镜像仓库地址
IMAGE_NAME="sp-erp"
HOSTS="hz-hosts-ali"
DOCKER_NAME="dingtalk"
PORT=18084
# CI 打包
mvn clean install -DskipTests
# build image
# ## Dockerfile
cat >Dockerfile << EOF
FROM registry-vpc.cn-hangzhou.aliyuncs.com/public/java:1.8
MAINTAINER tchua
ADD ${JAR_PATH}/${JAR_NAME} /apps/
EXPOSE 18084
ENTRYPOINT ["java","-jar","/apps/${JAR_NAME}"]
EOF
# ## build
# --username 阿里云镜像仓库用户 --password 阿里云镜像仓库密码
docker login --username=docker@registry-vpc.cn-hangzhou.aliyuncs.com --password=${password}
docker build -t $DOCKER_HUB/${IMAGE_NAME}:dev .
docker push $DOCKER_HUB/${IMAGE_NAME}:dev
# ## CD
ansible-playbook /etc/ansible/docker.yml -l ${HOSTS} -e name=${DOCKER_NAME} -e port=${PORT}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
:::
# 3.2 注意事项
使用Ansible发布需要注意以下:
- ansible主控机可以免密登录被控主机
- ansible发布Docker应用时,需要确保被控机上有Docker API Python客户端(
docker-py
或docker
) - 经过验证,Centos7.9无法正常使用,推测是因为默认安装有python2和python3的原因
# 四、K8S发布
这里介绍的是最简单的模式,原理就是Jenkins主机通过ansible远程至k8s-master节点,调用kubectl命令进行执行应用资源清单文件。
# 4.1 ansible配置
这里会使用到模板,主要是用来生成应用的清单文件
[root@localhost ansible]# mkdir roles/k8s/{tasks,templates} -p
- 模版文件内容
# roles/k8s/templates/k8s-template.yaml.j2
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: {{ env }}
name: {{ app_name }}
labels:
app: {{ app_name }}
spec:
revisionHistoryLimit: 10
replicas: {{ replicas }}
selector:
matchLabels:
app: {{ app_name }}
template:
metadata:
labels:
team: qpos
app: {{ app_name }}
version: "{{ tag }}"
spec:
nodeSelector:
channel-env: {{ env }}
imagePullSecrets:
- name: bsd-qpos-images
containers:
- name: {{ app_name }}
image: {{ image_url }}/{{ app_name }}:{{ env }}{{ tag }}
imagePullPolicy: Always
env:
- name: APP_NAME
value: {{ app_name }}
resources:
limits:
memory: {{ pod_limit | default('2048Mi') }}
requests:
memory: {{ pod_requests | default('1800Mi') }}
livenessProbe:
tcpSocket:
port: {{ port }}
initialDelaySeconds: 10
timeoutSeconds: 3
periodSeconds: 10
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
port: {{ port }}
path: /health
startupProbe:
tcpSocket:
port: {{ port }}
initialDelaySeconds: 25
timeoutSeconds: 3
periodSeconds: 10
successThreshold: 1
failureThreshold: 30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
- 剧本内容
/etc/ansible/roles/k8s/template/k8s-template.yaml.j2
- name: '应用清单文件生成'
template: src=k8s-template.yaml.j2 dest=/data/bsd-k8s/{{ env }}/bsd-k8s-{{ app_name }}.yaml
- name: "应用 deploy 部署"
shell: kubectl apply -f /data/bsd-k8s/{{ env }}/bsd-k8s-{{ app_name }}.yaml --record
2
3
4
- 入口文件
/etc/ansible/k8s.yml
- hosts: all
gather_facts: yes
remote_user: root
roles:
- k8s
2
3
4
5
# 4.2 Jenkins脚本配置
Jenkins这里其实与Docker配置基本都一样,只是修改下CD的配置
# 变量配置
JAR_PATH="${WORKSPACE}/sp-erp/target"
JAR_NAME="sp-erp-1.0-SNAPSHOT.jar"
APP_PATH="/data/apps/sp-erp"
DOCKER_HUB="registry-vpc.cn-hangzhou.aliyuncs.com/qpos" ## 镜像仓库地址
IMAGE_NAME="sp-erp"
HOSTS="hz-hosts-ali"
DOCKER_NAME="dingtalk"
PORT=18084
Number=1
# CI 打包
mvn clean install -DskipTests
# build image
# ## Dockerfile
cat >Dockerfile << EOF
FROM registry-vpc.cn-hangzhou.aliyuncs.com/public/java:1.8
MAINTAINER tchua
ADD ${JAR_PATH}/${JAR_NAME} /apps/
EXPOSE 18084
ENTRYPOINT ["java","-jar","/apps/${JAR_NAME}"]
EOF
# ## build
# --username 阿里云镜像仓库用户 --password 阿里云镜像仓库密码
docker login --username=docker@registry-vpc.cn-hangzhou.aliyuncs.com --password=${password}
docker build -t $DOCKER_HUB/${IMAGE_NAME}:dev .
docker push $DOCKER_HUB/${IMAGE_NAME}:dev
# CD
ansible-playbook /etc/ansible/k8s-deploy.yml -l asset-k8s-master01 -t bsd-channel-k8s -e \
"port=${Port} \
replicas=${Number} \
env=${Env} \
tag=${BUILD_ID} \
image_url=${IMAGE_URL} \
app_name=${IMAGE_NAME}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 4.3 总结
虽然文章介绍的都是简单的使用方式,只要ansible剧本脚本配置好,也能满足大部分工作场景,无论是直接发布java、Docker这种单体模式,还是直接对接k8s,其实CI部分基本都很类似,那么唯一的区别就是CD这里,我们只要把想要实现的功能,通过脚本配置好,就可以完成自己想要的效果,关于Jenkins更加深入的时候,我后面也会根据自己遇到的需求进行记录,因为每个公司架构体系可能不一样,所以没有啥可复制化的东西,只是想着写出来这些,能提供一种思路就行。