目录
一、基于 Jenkins+k8s+Git+Docker Hub 等技术链构建企业级 DevOps 容器云平台
1.1.2 在 kubernetes 中部署 jenkins
1.3.1 在 Jenkins 中安装 kubernetes 插件
1.3.2 配置 jenkins 连接到我们存在的 k8s 集群
1.3.5 测试通过 Jenkins 部署应用发布到 k8s 开发环境、测试环境、生产环境
本篇文章所用到的资料文件下载地址:https://download.csdn.net/download/weixin_46560589/87406236
https://download.csdn.net/download/weixin_46560589/87407377

#1. 在各节点安装 nfs
yum install nfs-utils -y
systemctl enable nfs --now
#2. 在 master1 上创建一个 nfs 共享目录
[root@k8s-master1 ~]# mkdir -pv /data/v1
[root@k8s-master1 ~]# vim /etc/exports
/data/v1 *(rw,no_root_squash)
#3. 使配置文件生效
[root@k8s-master1 ~]# exportfs -arv
exporting *:/data/v1
[root@k8s-master1 ~]# systemctl restart nfs
[root@k8s-master1 ~]# chmod -R 777 /data/v1/
[root@k8s-master1 ~]# kubectl create namespace jenkins-k8s
2)创建 pv
[root@k8s-master1 ~]# mkdir jenkins
[root@k8s-master1 ~]# cd jenkins/
[root@k8s-master1 jenkins]# vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: jenkins-k8s-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
nfs:
server: 192.168.78.143
path: /data/v1
[root@k8s-master1 jenkins]# kubectl apply -f pv.yaml
persistentvolume/jenkins-k8s-pv created
[root@k8s-master1 jenkins]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
jenkins-k8s-pv 10Gi RWX Retain Available 5s
3)创建 pvc
[root@k8s-master1 jenkins]# vim pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: jenkins-k8s-pvc
namespace: jenkins-k8s
spec:
resources:
requests:
storage: 10Gi
accessModes:
- ReadWriteMany
[root@k8s-master1 jenkins]# kubectl apply -f pvc.yaml
persistentvolumeclaim/jenkins-k8s-pvc created
[root@k8s-master1 jenkins]# kubectl get pvc -n jenkins-k8s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
jenkins-k8s-pvc Bound jenkins-k8s-pv 10Gi RWX 7s
4)创建一个 sa 账号
[root@k8s-master1 jenkins]# kubectl create sa jenkins-k8s-sa -n jenkins-k8s
serviceaccount/jenkins-k8s-sa created
# 把上面的 sa 账号做 rbac 授权
[root@k8s-master1 jenkins]# kubectl create clusterrolebinding jenkins-k8s-sa-cluster -n jenkins-k8s --clusterrole=cluster-admin --serviceaccount=jenkins-k8s:jenkins-k8s-sa
5)通过 deployment 部署 jenkins
# 把 jenkins-2.328.tar.gz 上传到 node1、node2 并解压
[root@k8s-node1 ~]# docker load -i jenkins-2.328.tar.gz
[root@k8s-node2 ~]# docker load -i jenkins-2.328.tar.gz
[root@k8s-master1 jenkins]# vim jenkins-deployment.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: jenkins
namespace: jenkins-k8s
spec:
replicas: 1
selector:
matchLabels:
app: jenkins
template:
metadata:
labels:
app: jenkins
spec:
serviceAccount: jenkins-k8s-sa
containers:
- name: jenkins
image: jenkins/jenkins:2.328
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: web
protocol: TCP
- containerPort: 50000
name: agent
protocol: TCP
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
readinessProbe:
httpGet:
path: /login
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
failureThreshold: 12
volumeMounts:
- name: jenkins-volume
subPath: jenkins-home
mountPath: /var/jenkins_home
volumes:
- name: jenkins-volume
persistentVolumeClaim:
claimName: jenkins-k8s-pvc
[root@k8s-master1 jenkins]# kubectl apply -f jenkins-deployment.yaml
[root@k8s-master1 jenkins]# kubectl get pods -n jenkins-k8s -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
jenkins-9db894c8c-j9tr7 1/1 Running 0 2m14s 10.244.169.129 k8s-node2 <none> <none>
6)把 jenkins 前端加上 service 提供外部网络访问
[root@k8s-master1 jenkins]# vim jenkins-service.yaml
apiVersion: v1
kind: Service
metadata:
name: jenkins-service
namespace: jenkins-k8s
labels:
app: jenkins
spec:
selector:
app: jenkins
type: NodePort
ports:
- name: web
port: 8080
targetPort: web
nodePort: 30002
- name: agent
port: 50000
targetPort: agent
[root@k8s-master1 jenkins]# kubectl apply -f jenkins-service.yaml
service/jenkins-service created
[root@k8s-master1 jenkins]# kubectl get svc -n jenkins-k8s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jenkins-service NodePort 10.99.229.21 <none> 8080:30002/TCP,50000:30527/TCP 7s
通过上面可以看到 service 的 8080 端口在物理机映射的端口是 30002
在浏览器访问 jenkins 的 web 界面:http://192.168.78.143:30002

# 在 nfs 服务端,也就是我们的 master1 节点获取密码
[root@k8s-master1 jenkins]# cat /data/v1/jenkins-home/secrets/initialAdminPassword
081e9ebd3c7243819817c0f6a1adb5d8
把上面获取到的密码拷贝到上面管理员密码下的方框里
点击继续,出现如下界面 
选择“安装推荐的插件”
插件安装好之后显示如下

用户名和密码都设置成 admin,线上环境需要设置成复杂的密码。修改好之后点击保存并完成,出现如下界面:
不用修改,点击保存并完成,出现如下界面:
点击开始使用 Jenkins,至此 Jenkins 配置完成!
1)在 jenkins 中安装 k8s 插件
点击左边列表中的 Manage Jnekins ------> 插件管理 ------> 可选插件 ------> 搜索 kubernetes ------>出现如下:
选中 kubernetes 之后 ------> 点击下面的“Download now and install after restart”(下载待重启后安装)------> 勾选“安装之后选择重新启动 jenkins” ---> 重启之后登陆 jenkins,插件即可生效
2)安装 blueocean 插件
1.3.2 配置 jenkins 连接到我们存在的 k8s 集群点击“系统管理” -> 系统配置 -> 页面拉到最下 -> 点击“a separate configuration page”
1)新增一个云,在下拉菜单中选择 kubernets


https://192.168.78.143:6443
Kubernetes 命名空间:jenkins-k8s
Jenkins 地址:http://jenkins-service.jenkins-k8s.svc.cluster.local:8080
Connected to Kubernetes v1.23.1 说明测试成功,Jenkins 可以和 k8s 进行通信!


按如下配置:
Docker 镜像:使用 jenkins-jnlp.tar.gz 解压出来的镜像 xianchao/jenkins-jnlp:v1,把这个镜像压缩包上传到 k8s 的各工作节点并手动解压:
# 解压出来的镜像是 xianchao/jenkins-jnlp:v1
[root@k8s-node1 ~]# docker load -i jenkins-jnlp.tar.gz
[root@k8s-node2 ~]# docker load -i jenkins-jnlp.tar.gz
在每一个 pod template 右下脚都有一个高级,点击高级:
往下拉,在 Service Account 处输入 jenkins-k8s-sa,这个 sa 就是我们最开始安装 jenkins 时创建的 sa:
添加卷 ------> 选择 Host Path Volume

/var/run/docker.sock
/var/run/docker.sock
/root/.kube
/home/jenkins/.kube
上面配置好之后,点击 Apply(应用) ------> Save(保存) 
注意:如果没有 Docker Hub 账号则需要先去注册 Docker
首页 ------> 系统管理 Manage Credentials(管理凭据)------> 点击 Stores scoped to Jenkins下的第一行 jenkins 后面的全局,显示如下:
点击添加凭据(也可以添加阿里云私有镜像仓库账户),出现如下:
开发提交代码到代码仓库 gitlab -> jenkins 检测到代码更新 -> 调用 k8s api 在 k8s 中创建jenkins slave pod:
Jenkins slave pod 拉取代码 -> 通过 maven 把拉取的代码进行构建成 war 包或者 jar 包 ---> 上传代码到 Sonarqube 进行静态代码扫描 --> 基于 war 包构建 docker image --> 把镜像上传到阿里云(或者 harbor)镜像仓库 --> 基于镜像部署应用到开发环境 --> 部署应用到测试环境 ---> 部署应用到生产环境。

1)创建名称空间
[root@k8s-master1 ~]# kubectl create ns devlopment
[root@k8s-master1 ~]# kubectl create ns production
[root@k8s-master1 ~]# kubectl create ns qatest
回到首页,开始创建一个新任务

输入一个任务名称:jenkins-variable-test-deploy -> 选择流水线 -> 确定

在 Pipeline script 处输入如下内容

node('test') { // 基于前面创建的 pod 模板创建 jenkins slave pod
stage('Clone') {
echo "1.Clone Stage" // 第一步克隆代码
git url: "https://github.com/loveyou2333/jenkins-sample.git" // 自己的项目地址
script {
build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
} // 检测代码是否有更新,如有则生成随机数字
}
stage('Test') {
echo "2.Test Stage" // 第二步测试
}
stage('Build') { // 第三步构建镜像
echo "3.Build Docker Image Stage"
sh "docker build -t fuhxxx/jenkins-demo:${build_tag} ." // Docker Hub 账户地址
}
stage('Push') { // 第四步推送镜像到仓库
echo "4.Push Docker Image Stage"
withCredentials([usernamePassword(credentialsId: 'DockerHub', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
sh "docker login -u ${dockerHubUser} -p ${dockerHubPassword}" // 自动获取 docker hub 的用户和密码;'DockerHub' 为前面创建的凭据 id
sh "docker push fuhxxx/jenkins-demo:${build_tag}" // 修改为自己的账户
}
}
stage('Deploy to dev') { // 部署应用到开发环境
echo "5. Deploy DEV"
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-dev.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-dev.yaml"
// sh "bash running-devlopment.sh"
sh "kubectl apply -f k8s-dev.yaml --validate=false"
}
stage('Promote to qa') { // 部署项目到测试环境
def userInput = input(
id: 'userInput',
message: 'Promote to qa?',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "YES\nNO", // 手动判断是否部署
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
if (userInput == "YES") {
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-qa.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-qa.yaml"
// sh "bash running-qa.sh"
sh "kubectl apply -f k8s-qa.yaml --validate=false"
sh "sleep 6"
sh "kubectl get pods -n qatest"
} else {
//exit
}
}
stage('Promote to pro') { // 部署项目到生成环境
def userInput = input(
id: 'userInput',
message: 'Promote to pro?',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "YES\nNO",
name: 'Env'
]
]
)
echo "This is a deploy step to ${userInput}"
if (userInput == "YES") {
sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s-prod.yaml"
sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' k8s-prod.yaml"
// sh "bash running-production.sh"
sh "cat k8s-prod.yaml"
sh "kubectl apply -f k8s-prod.yaml --record --validate=false"
}
}
}
把 GitHub - luckylucky421/jenkins-sample 项目 fork 到自己的 GitHub 上,并修改 k8s-dev.yaml、k8s-qa.yaml、k8s-prod.yaml 三个文件里的镜像名称:

点击应用 ------> 保存 ------> 立即构建 -> 在 #1 的 Console Output 可看到构建过程:

在 Console Output 如果看到如下,点击 Input requested:

点击继续

从上面可以看到已经把应用部署到 dev 环境了,点击 Input requested

通过上面可以看到把应用部署到了 pro 环境了 。
验证是否在 devlopment 和 production 名称空间下有应用:
[root@k8s-master1 ~]# kubectl get pods -n devlopment
NAME READY STATUS RESTARTS AGE
jenkins-demo-5f6c587df5-jlxhz 1/1 Running 0 12m
[root@k8s-master1 ~]# kubectl get pods -n qatest
NAME READY STATUS RESTARTS AGE
jenkins-demo-5f6c587df5-9wnph 1/1 Running 0 3m10s
[root@k8s-master1 ~]# kubectl get pods -n production
NAME READY STATUS RESTARTS AGE
jenkins-demo-5f6c587df5-rhcn6 1/1 Running 0 2m25s
通过上面可以看到 jenkins 对接 k8s,可以把应用发布到 k8s 集群的开发、测试、生产环境了。
打开 blue ocean 会看到如下流程,你也可以尝试重新运行构建,手动点击确认部署流程:

回到首页 -> 新建一个任务 ------> 输入一个任务名称:jenkins-variable-test-deploy-rollout ------> 流水线 ------> 确定 ------> 在 Pipeline script 处输入如下内容:


node('test') {
stage('git clone') {
git url: "https://github.com/loveyou2333/jenkins-rollout.git"
sh "ls -al"
sh "pwd"
}
stage('select env') {
def envInput = input(
id: 'envInput',
message: 'Choose a deploy environment',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "devlopment\nqatest\nproduction",
name: 'Env'
]
]
)
echo "This is a deploy step to ${envInput}"
sh "sed -i 's/<namespace>/${envInput}/' getVersion.sh"
sh "sed -i 's/<namespace>/${envInput}/' rollout.sh"
sh "bash getVersion.sh"
// env.WORKSPACE = pwd()
// def version = readFile "${env.WORKSPACE}/version.csv"
// println version
}
stage('select version') {
env.WORKSPACE = pwd()
def version = readFile "${env.WORKSPACE}/version.csv"
println version
def userInput = input(id: 'userInput',
message: '选择回滚版本',
parameters: [
[
$class: 'ChoiceParameterDefinition',
choices: "$version\n",
name: 'Version'
]
]
)
sh "sed -i 's/<version>/${userInput}/' rollout.sh"
}
stage('rollout deploy') {
sh "bash rollout.sh"
}
}
点击应用 -> 保存 -> 立即构建(三角符)

在构建过程中即可选择需要回滚的环境和指定的版本!
上一篇文章:【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(上)_Stars.Sky的博客-CSDN博客
下一篇文章:【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(下)_Stars.Sky的博客-CSDN博客
我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s
我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions
前置步骤我们都操作完了,这篇开始介绍jenkins的集成。话不多说,看操作1、登录进入jenkins后会让你选择安装插件,选择第一个默认的就行。安装完成后设置账号密码,重新登录。2、配置JDK和Git都需要执行路径,所以需要先把执行路径找到,先进入服务器的docker容器,2.1JDK的路径root@69eef9ee86cf:/usr/bin#echo$JAVA_HOME/usr/local/openjdk-82.2Git的路径root@69eef9ee86cf:/#whichgit/usr/bin/git3、先配置JDK和Git。点击:ManageJenkins>>GlobalToolCon
我想用这两种语言中的任何一种(最好是ruby)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生
这是我在ActiveAdmin中的自定义页面ActiveAdmin.register_page"Settings"doaction_itemdolink_to('Importprojects','settings/importprojects')endcontentdopara"Text"endcontrollerdodefimportprojectssystem"rakedataspider:import_projects_ninja"para"OK"endendend我想做的是,当我单击“导入项目”按钮时,我想在Controller中执行rake任务。但是我无法访问该方法。可能是什
我正在寻找用于Rails的优质管理插件。似乎大多数现有的插件/gem(例如“restful_authentication”、“acts_as_authenticated”)都围绕着self注册等展开。但是,我正在寻找一种功能齐全的基于管理/管理角色的解决方案——但不是简单地附加到另一个非基于角色的解决方案。如果我找不到,我想我会自己动手......只是不想重新发明轮子。 最佳答案 RyanBates最近做了两个关于授权的railscast(注意身份验证和授权之间的区别;身份验证检查用户是否如她所说的那样,授权检查用户是否有权访问资源
文章目录一基础定义二创建逻辑卷2-1准备物理设备2-2创建物理卷2-3创建卷组2-4创建逻辑卷2-5创建文件系统并挂载文件三扩展卷组和缩减卷组3-1准备物理设备3-2创建物理卷3-3扩展卷组3-4查看卷组的详细信息以验证3-5缩减卷组四扩展逻辑卷4-1检查卷组是否有可用的空间4-2扩展逻辑卷4-3扩展文件系统五删除逻辑卷5-1备份数据5-2卸载文件系统5-3删除逻辑卷5-4删除卷组5-5删除物理卷六LVM逻辑卷缩容6-1缩容注意事项6-2标准缩容步骤一基础定义LVM,LogicalVolumeManger,逻辑卷管理,Linux磁盘分区管理的一种机制,建立在硬盘和分区上的一个逻辑层,提高磁盘分
我为Devise用户和管理员提供了不同的模型。我也在使用Basecamp风格的子域。除了我需要能够以用户或管理员身份进行身份验证的一些Controller和操作外,一切都运行良好。目前我有authenticate_user!在我的application_controller.rb中设置,对于那些只有管理员才能访问的Controller和操作,我使用skip_before_filter跳过它。不幸的是,我不能简单地指定每个Controller的身份验证要求,因为我仍然需要一些Controller和操作才能被用户或管理员访问。我尝试了一些方法都无济于事。看来,如果我移动authentica