准备环境
- 需求
1.通过jenkins 完成k8s 项目的自动化构建需求,要求nodejs、java等不同开发语言运用不同的jenkins slave 节点构建
2.通过权限设置管控开发人员的项目使用及构建
- jenkins 节点准备
节点名称 | ip地址 |
jenkins-master | 10.65.91.164 |
jenkins-slave-nodejs | 10.65.91.52 |
jenkins-slave-java | 10.65.91.165 |
- k8s 环境
k8s 已完成部署,部署方式参照之前博客文档,以下是博客地址
jenkins master 节点安装
- 下载安装包并启动
#下载lts 版本war包
cd /opt/
wget https://get.jenkins.io/war-stable/2.289.1/jenkins.war --no-check-certificate
#安装git
yum -y install git
#配置java 环境
vim /etc/profile
JAVA_HOME=/usr/local/jdk1.8.0_201
JRE_HOME=/usr/local/jdk1.8.0_201/jre
PATH=$JAVA_HOME/bin:$PATH:$JRE_HOME/bin:/usr/local/bin
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME JRE_HOME CLASSPATH PATH
#查看java 安装完成
source /etc/profile
java -version
#创建jenkins 普通用户
useradd jenkins
#创建jenkins 数据目录
mkdir /export/jenkins/
mkdir /var/log/jenkins/
chown jenkins:jenkins /export/jenkins/ -R
chown jenkins:jenkins /var/log/jenkins/ -R
#启动jenkins
su - jenkins
java -Djava.awt.headless=true -DsessionTimeout=1440 -DJENKINS_HOME=/export/jenkins/ -jar /opt/jenkins.war --logfile=/var/log/jenkins/jenkins.log --httpPort=8608 --debug=5 --handlerCountMax=100 --handlerCountMaxIdle=20 &
Jenkins master 节点配置
- 安装插件
#访问Jenkins地址
http://10.65.91.164:8608/
#安装推荐插件
将推荐插件安装完成
#安装权限插件
Role-based Authorization Strategy
#安装时间戳插件
BUILD_TIMESTAMP
#安装git参数插件
Git Parameter
#安装注册环境变量插件
Environment Injector
#安装Maven 插件
Maven Intergration
#重启jenkins
- 系统配置
#系统管理-系统配置-全局属性,增加键值对
LANG->zh_CN.UTF-8
#系统管理-系统配置-Build Timestamp
Timezone->Asia/Shanghai
Pattern->yyyyMMddHHmmss
- 连接ldap
#系统管理-全局安全配置-安全域-LDAP
添加完ldap 配置后可以点击 Test LDAP settings,检测ldap 账号密码是否生效
#系统管理-全局安全配置-授权策略
选择Role-Based Strategy
#应用-保存
- 配置权限
#系统管理-Manage and Assign Roles-Manage Roles,增加itemadmin 账号,并授权
#系统管理-Manage and Assign Roles-Assign Roles,增加ldap 运维管理员人员权限
出现No type prefix: admin ,但是不影响后续权限使用,是没有关系的
admin 用户将不能登录jenkins,只有分配admin 权限的ldap 账户可以登录jenkins,并且拥有admin 权限
jenkins nodejs slave 节点添加并构建项目
- nodejs slave 节点系统环境配置
#安装docker 环境
因后续要构建镜像,因此需要有docker 环境,参照之前装docker 的文档安装docker 环境
#配置docker 可以连接harbor
cat /etc/docker/daemon.json
{
"oom-score-adjust": -1000,
"registry-mirrors": [
"https://c6ai9izk.mirror.aliyuncs.com",
"https://docker.mirrors.ustc.edu.cn"
],
"log-driver":"json-file",
"log-opts":{ "max-size" :"100m","max-file":"1"},
"insecure-registries": ["harbor.dev.k8s.xxx.cn","harbor.k8s.xxx.cn"],
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"exec-opts": ["native.cgroupdriver=systemd"]
}
#安装git
yum -y install git
#配置java 环境
vim /etc/profile
JAVA_HOME=/usr/local/jdk1.8.0_201
JRE_HOME=/usr/local/jdk1.8.0_201/jre
PATH=$JAVA_HOME/bin:$PATH:$JRE_HOME/bin:/usr/local/bin
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME JRE_HOME CLASSPATH PATH
#查看java 安装完成
source /etc/profile
java -version
#创建jenkins 普通用户
useradd jenkins
#创建jenkins 数据目录
mkdir /export/jenkins/
chown jenkins:jenkins /export/jenkins/ -R
#将jenkins 用户添加到docker 组,可以用普通jenkins 用户运行docker 命令
usermod -a -G jenkins,docker jenkins
#下载nodejs 二进制包node-v12.19.0-linux-x64,注意千万不要使用别的机器拷贝过来的node 包,因为少软连接,npm 运行会报错的。
cd /opt/
wget https://nodejs.org/download/release/v12.19.0/node-v12.19.0-linux-x64.tar.gz
tar -xf node-v12.19.0-linux-x64.tar.gz
#测试node 环境是否可用
export PATH=/opt/node-v12.19.0-linux-x64/bin/:$PATH
node -v
npm -v
#安装kubectl 、配置连接k8s 的config 文件
#从 k8s master节点上将Kubectl 传至nodejs 节点
scp -qpr /usr/local/bin/kubectl 10.65.91.52:/usr/local/bin/
#将k8s master 节点上的config 文件传至nodejs 节点
cd .kube
scp -qpr config 10.65.91.52:/root/
#登录nodejs 10.65.91.52 节点
mkdir /opt/kubernetes
mv /root/config /opt/kubernetes
cd /opt/kubernetes
mv config config_prod
#测试是否可以连接k8s 集群,返回node 节点信息表示可以正常连接
/usr/local/bin/kubectl --kubeconfig=/opt/kubernetes/config_prod get node
# 将jenkins master 节点jenkins 普通用户的公钥传至 nodejs 普通用户jenkins 目录下,以便于jenkins master 节点的jenkins 用户可以免密登录nodejs 节点
登录 10.65.91.164,执行
su - jenkins
ssh jenkins@10.65.91.52
登录成功即可
- 配置凭据 jenkins-slave 用来jenkins master节点可以通过秘钥连接至 slave 节点
#系统管理-Manage Credentials-新创建凭据
范围:全局(Jenkins,nodes,items,all child items,etc)
ID:jenkins-slave
描述:jenkins-slave
Username: jenkins
Private Key: 添加jenkins master jenkins 用户的私钥,因为之前已将jenkins 用户的公钥放至jenkins node slave 节点
- jenkins master 节点添加 nodejs jenkins slave 节点
系统管理-节点管理-新建节点
名称:jks-node-1
描述:jks-node-1
Number of executors:2
远程工作目录:/export/jenkins
标签:node
用法:只允许运行绑定到这台机器的JOb
启动方式:Launch agents via SSH
主机:10.65.91.52
Credential:jenkins-slave (上面已经配置好的凭据)
Host Key Verification Strategy:Know hosts file Verification Strategy
可用性:尽量保持代理在线
节点属性-环境变量:键:LANG 值:UTF-8
启动slave 节点
- 部署jenkins nodejs 项目
#Dashboard - 新建任务文件夹 -Production (显示名称:正式环境) - 新建Item - 3Dmodel-Prod (显示名称:正式环境-3D模型分享平台-3Dmodel) -新建Item(构建一个自由风格的软件项目) - 3Dmodel_Node_Prod
#增加gitlab 拉取代码的凭据
#系统管理-Manage Credentials-新创建凭据
范围:全局(Jenkins,nodes,items,all child items,etc)
用户名: jenkins
密码: 123456
ID: 不用写
描述:gitlab token
#具体配置
#参数化构建过程
GIT 参数:
名称: BranchName
参数类型: 分支
选项参数:
名称:domain_name
选项:3dmodel.moviebook.cn
描述:选择业务域名
#限制项目运行的节点
标签表达式
jks-node-1
#源码管理
Repository URL
http://git.xxx.com/video_ai/code/frontend.git
#Credentials
gitlab token
#Branches to build
指定分支(为空时代表any)
${BranchName}
#构建环境
Delete workspace before build starts --> 勾选
Inject environment variables to the build process -->勾选
Properties Content 内容:
mirror_store=harbor.k8s.xxx.cn
image_name=3dmodel/prod/000001-3dmodel/node_prod
deploy_env=node_prod
k8s_resource_list=threedmodel-node-prod
namespace=3dmodel
base_version=nginx:latest
#构建
#执行shell
mkdir /export/jenkins/workspace/op_dockerfile/${namespace}/${deploy_env}/code/ -p
cp -af /export/jenkins/workspace/${JOB_NAME}/. /export/jenkins/workspace/op_dockerfile/${namespace}/${deploy_env}/code/
cd /export/jenkins/workspace/op_dockerfile/${namespace}/${deploy_env}
cat > $(echo ${domain_name} |sed 's/\(.moviebook.cn\|.videoyi.com\)$//').conf << EOF
server {
server_name ${domain_name};
location / {
index index.html index.htm index.php;
root /export/home/webroot/${namespace}/;
proxy_read_timeout 10000;
try_files \$uri \$uri/ /index.html;
}
access_log /export/home/logs/${namespace}/access.log main;
}
EOF
#执行shell
cd /export/jenkins/workspace/op_dockerfile/${namespace}/${deploy_env}/code/
#echo "window.env = 'prod';" > public/env.js
#npm install && npm run build
source /etc/profile
export PATH=/opt/node-v12.19.0-linux-x64/bin/:$PATH
node -v
npm -v
npm install --unsafe-perm && npm run build:prod
#执行shell
whoami
docker_img=`docker images -a -q --filter reference=${mirror_store}/base/${base_version}`
if [ $docker_img ]
then
docker rmi ${mirror_store}/base/${base_version}
fi
cd /export/jenkins/workspace/op_dockerfile/${namespace}/${deploy_env}/
cat > Dockerfile << EOF
FROM ${mirror_store}/base/${base_version}
ADD $(echo ${domain_name} |sed 's/\(.moviebook.cn\|.videoyi.com\)$//').conf /opt/openresty/nginx/conf/vhost/
RUN mkdir -p /export/home/webroot/${namespace}/
COPY code/dist/ /export/home/webroot/${namespace}/
RUN mkdir -p /export/home/logs/${namespace}/ && chown -R nobody.nobody /export/home/webroot/${namespace}/
WORKDIR /export/home/webroot/${namespace}/
EXPOSE 80
CMD ["/opt/openresty/nginx/sbin/nginx","-g","daemon off;"]
EOF
docker build . -t ${mirror_store}/${image_name}:${BUILD_TIMESTAMP}
docker push ${mirror_store}/${image_name}:${BUILD_TIMESTAMP}
docker rmi ${mirror_store}/${image_name}:${BUILD_TIMESTAMP}
#执行shell
mkdir -p /export/jenkins/workspace/op_dockerfile/${namespace}/${deploy_env}/yaml/
cd /export/jenkins/workspace/op_dockerfile/${namespace}/${deploy_env}/yaml
cat > ${k8s_resource_list}-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: ${namespace}
name: ${k8s_resource_list}
labels:
name: ${k8s_resource_list}
spec:
replicas: 1
selector:
matchLabels:
name: ${k8s_resource_list}
template:
metadata:
labels:
name: ${k8s_resource_list}
spec:
containers:
- name: ${k8s_resource_list}
image: ${mirror_store}/${image_name}:${BUILD_TIMESTAMP}
imagePullPolicy: IfNotPresent # Always、Never、IfNotPresent
resources:
limits:
cpu: "1000m"
memory: 2048Mi
requests:
cpu: "500m"
memory: 1024Mi
EOF
cat > ${k8s_resource_list}-svc.yaml << EOF
kind: Service
apiVersion: v1
metadata:
name: ${k8s_resource_list}
namespace: ${namespace}
labels:
name: ${k8s_resource_list}
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
name: ${k8s_resource_list}
EOF
cat > ${k8s_resource_list}-ingress.yaml << EOF
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: ${k8s_resource_list}
namespace: ${namespace}
spec:
rules:
- host: ${domain_name}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: ${k8s_resource_list}
port:
number: 80
EOF
_kubectl='/usr/local/bin/kubectl --kubeconfig=/opt/kubernetes/config_prod'
${_kubectl} apply -f ${k8s_resource_list}-deployment.yaml
${_kubectl} apply -f ${k8s_resource_list}-svc.yaml
${_kubectl} apply -f ${k8s_resource_list}-ingress.yaml
cd /export/jenkins/workspace/op_dockerfile/${namespace}/${deploy_env}/code && ls |grep -v node_modules | xargs rm -rf
- k8s 查看pod 创建完成
kubectl get pod -n 3dmodel
权限管理与分配
#系统管理-Manage and Assign Roles - Manage Roles - Item roles -Add
Role to add: 3D模型分享平台-3Dmodel
Pattern: Production/3Dmodel-Prod/.*
#权限选择
任务:Build、Cancel、Discover、Read
SCM:Tag
#应用-保存,截图如下
#系统管理-Manage and Assign Roles - Assign Roles
Global roles: 增加用户 zhao.liliang
选择之前创建的 itemadmin
Item roles:增加用户: zhao.liliang
选择3D模型分享平台-3Dmodel
截图如下:
#退出当前账号用 zhao.liliang 账号登录jenkins,发现只有 构建权限,没有配置权限
jenkins java slave 节点添加并构建项目
- java slave 节点系统环境配置
#安装docker 环境
因后续要构建镜像,因此需要有docker 环境,参照之前装docker 的文档安装docker 环境
#配置docker 可以连接harbor
cat /etc/docker/daemon.json
{
"oom-score-adjust": -1000,
"registry-mirrors": [
"https://c6ai9izk.mirror.aliyuncs.com",
"https://docker.mirrors.ustc.edu.cn"
],
"log-driver":"json-file",
"log-opts":{ "max-size" :"100m","max-file":"1"},
"insecure-registries": ["harbor.dev.k8s.xxx.cn","harbor.k8s.xxx.cn"],
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"exec-opts": ["native.cgroupdriver=systemd"]
}
#安装git
yum -y install git
#配置java 环境
vim /etc/profile
JAVA_HOME=/usr/local/jdk1.8.0_201
JRE_HOME=/usr/local/jdk1.8.0_201/jre
PATH=$JAVA_HOME/bin:$PATH:$JRE_HOME/bin:/usr/local/bin
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME JRE_HOME CLASSPATH PATH
#因在后续添加slave 节点时候报错找不到java 路径,因此需要以下修改操作,重点
cp /usr/local/jdk1.8.0_201 /usr/local/java
ln -s /usr/local/jdk1.8.0_201/bin/java /usr/bin/java
#查看java 安装完成
source /etc/profile
java -version
#创建jenkins 普通用户
useradd jenkins
#创建jenkins 数据目录
mkdir /export/jenkins/
chown jenkins:jenkins /export/jenkins/ -R
#将jenkins 用户添加到docker 组,可以用普通jenkins 用户运行docker 命令
usermod -a -G jenkins,docker jenkins
#安装kubectl 、配置连接k8s 的config 文件
#从 k8s master节点上将Kubectl 传至nodejs 节点
scp -qpr /usr/local/bin/kubectl 10.65.91.165:/usr/local/bin/
#将k8s master 节点上的config 文件传至nodejs 节点
cd .kube
scp -qpr config 10.65.91.165:/root/
#登录nodejs 10.65.91.165 节点
mkdir /opt/kubernetes
mv /root/config /opt/kubernetes
cd /opt/kubernetes
mv config config_prod
#测试是否可以连接k8s 集群,返回node 节点信息表示可以正常连接
/usr/local/bin/kubectl --kubeconfig=/opt/kubernetes/config_prod get node
# 将jenkins master 节点jenkins 普通用户的公钥传至 nodejs 普通用户jenkins 目录下,以便于jenkins master 节点的jenkins 用户可以免密登录nodejs 节点
登录 10.65.91.164,执行
su - jenkins
ssh jenkins@10.65.91.165
登录成功即可
- jenkins master 节点添加 java jenkins slave 节点
系统管理-节点管理-新建节点
名称:jks-java-1
描述:jks-java-1
Number of executors:2
远程工作目录:/export/jenkins
标签:java
用法:只允许运行绑定到这台机器的JOb
启动方式:Launch agents via SSH
主机:10.65.91.165
Credential:jenkins-slave (上面已经配置好的凭据)
Host Key Verification Strategy:Know hosts file Verification Strategy
可用性:尽量保持代理在线
节点属性-环境变量:键:LANG 值:UTF-8
启动slave 节点
- 部署 jenkins java 项目
- 配置maven
#系统管理-全局工具配置-Maven-新增maven,选择自动安装,下载两个版本的,分别是maven-3.5.0 和 maven-3.0.5,等待安装完成
#Dashboard - 新建任务文件夹 -Production (显示名称:正式环境) - 新建Item - AGC-Video-Engine (显示名称:正式环境-AGC-Video-Engine) -新建Item(构建一个 maven 项目) - Agc-Video-Engine_Java_Prod
#具体配置
#参数化构建过程
GIT 参数:
名称: BranchName
参数类型: 分支
选项参数:
名称:domain_name
选项:work-order.center.xxx.cn
描述:选择业务域名
#限制项目运行的节点
标签表达式
jks-java-1
#源码管理
Repository URL
http://git.xxx.com/video_ai/code/backend.git
#Credentials
gitlab token
#Branches to build
指定分支(为空时代表any)
${BranchName}
#构建环境
Delete workspace before build starts --> 勾选
Inject environment variables to the build process -->勾选
Properties Content 内容:
mirror_store=harbor.k8s.xxx.cn
image_name=message-center/prod/000004-message-center/java_prod
deploy_env=java_prod
k8s_resource_list=message-center-java-prod
namespace=message-center
base_version=jdk:8u201
#Build
Maven Version : maven-3.5.0
Root Pom: pom.xml
Goals and options:clean package -Dmaven.test.skip=true -P prod
#Post Steps
选择 Run only if build succeeds
#执行shell
docker_img=`docker images -a -q --filter reference=${mirror_store}/base/${base_version}`
if [ $docker_img ];then
docker rmi ${mirror_store}/base/${base_version}
fi
git checkout HEAD
artifactId=`awk '/<artifactId>[^<]+<\/artifactId>/{gsub(/<artifactId>|<\/artifactId>/,"",$1);print $1;exit;}' pom.xml`
version=`awk '/<version>[^<]+<\/version>/{gsub(/<version>|<\/version>/,"",$1);print $1;exit;}' pom.xml`
packaging='jar'
cat > entrypoint.sh << EOF
#!/bin/bash -
#ln -sf /storage/resource /export/home/webroot/${namespace}/resource
ln -sf /storage/data /data
cd /
java -jar app.jar >> /export/home/logs/${namespace}/${namespace}_prod.log
EOF
chmod +x entrypoint.sh
echo 'center-message-system_java_prod' > prod_env
cat > Dockerfile << EOF
FROM ${mirror_store}/base/${base_version}
ENV LANG en_US.utf8
COPY target/${artifactId}-${version}.${packaging} /app.jar
COPY prod_env /env
RUN mkdir -p /export/home/logs/${namespace}/
EXPOSE 80
ADD entrypoint.sh /entrypoint.sh
ENTRYPOINT /entrypoint.sh
EOF
docker build . -t ${mirror_store}/${image_name}:${BUILD_TIMESTAMP}
docker push ${mirror_store}/${image_name}:${BUILD_TIMESTAMP}
docker rmi ${mirror_store}/${image_name}:${BUILD_TIMESTAMP}
#执行shell
mkdir -p /export/jenkins/workspace/op_dockerfile/${namespace}/${deploy_env}/yaml/
cd /export/jenkins/workspace/op_dockerfile/${namespace}/${deploy_env}/yaml
cat > ${k8s_resource_list}-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: ${namespace}
name: ${k8s_resource_list}
labels:
name: ${k8s_resource_list}
spec:
replicas: 1
selector:
matchLabels:
name: ${k8s_resource_list}
template:
metadata:
labels:
name: ${k8s_resource_list}
spec:
containers:
- name: ${k8s_resource_list}
image: ${mirror_store}/${image_name}:${BUILD_TIMESTAMP}
imagePullPolicy: IfNotPresent # Always、Never、IfNotPresent
resources:
limits:
cpu: "1000m"
memory: 2048Mi
requests:
cpu: "500m"
memory: 1024Mi
EOF
cat > ${k8s_resource_list}-svc.yaml << EOF
kind: Service
apiVersion: v1
metadata:
name: ${k8s_resource_list}
namespace: ${namespace}
labels:
name: ${k8s_resource_list}
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
name: ${k8s_resource_list}
EOF
cat > ${k8s_resource_list}-ingress.yaml << EOF
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: ${k8s_resource_list}
namespace: ${namespace}
spec:
rules:
- host: ${domain_name}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: ${k8s_resource_list}
port:
number: 80
EOF
_kubectl='/usr/local/bin/kubectl --kubeconfig=/opt/kubernetes/config_prod'
${_kubectl} apply -f ${k8s_resource_list}-deployment.yaml
${_kubectl} apply -f ${k8s_resource_list}-svc.yaml
${_kubectl} apply -f ${k8s_resource_list}-ingress.yaml
- k8s 查看pod 创建完成
kubectl get pod -n message-center
至此,两个需求完成
1.通过jenkins 完成k8s 项目的自动化构建需求,要求nodejs、java等不同开发语言运用不同的jenkins slave 节点构建
2.通过权限设置管控开发人员的项目使用及构建