k8s jenkins kubeSphere布置运用
这里的k8s有两层含义,第一层便是把jenkins的agent布置到k8s里边,以完成各种一次性的独立的构建环境,第二层含义是把项目代码布置到k8s里边
阐明:以下的操作是在win11专业版上进行的,装置wsl2,在win上面用linux,jenkins直接装置在linux里边
必备环境
- 装置wsl2,选ubuntu, 后续操作都是在ubuntu中进行
- 装置jenkins
- 装置docker engine和docker-compose
- 装置minikube
- 装置kubectl
- 装置harbor
wsl2装置ubuntu
# 会主动装置ubuntu
wsl --install
装置jenkins
Jenkins Debian Packages
大概过程便是先下载个啥.asc文件,然后转换成jenkins.list,再然后更新库房列表,然后就能找到jenkins官方下载地址下载装置
装置docker engine
装置好后用docker info,测验是否ok,第一次engine或许发动比较慢会导致docker info提示连不上,能够稍等会儿,后续每次docker engine会跟随体系主动发动
假如按上面的链接操作装置,则直接装置了docker compose plugin,就能够经过docker compose履行原先的docker-compose指令,或许单独装置一个docker-compose
ps: sudo docker run hello-world或许镜像会下载不了,需求魔法
// 这一步是为了后续能以http的形式拜访本地harbor
// 修改下 /etc/docker/daemon.json
// 增加这么一段,文件假如不存在就新建一个
{
"insecure-registries":["你的ubuntu ip"]
}
装置minikube
# 装置好后履行,这一步依靠docker,会下载相关镜像生成一个minikube container
minikube start --drvier=docker --insecure-registry=linux的ip地址
装置kubectl
装置harbor
这个装置没有参阅官方,感觉官方的装置写的贼杂乱,harbor装置依靠docker和docker-compose
# 从github下载最新的装置包,包里边有相关docker镜像,几百M,下载估计比较慢
# 1. liunx下载指令,或许用win下载,然后拷贝到linux, 一切版别列表https://github.com/goharbor/harbor/releases
wget https://github.com/goharbor/harbor/releases/download/v2.7.4/harbor-offline-installer-v2.7.4.tgz
# 2. 解压,并修改装备文件
tar zxf harbor-offline-installer-v2.7.4.tgz
# 默许有个harbor.yml.tmpl,直接从这个文件仿制下,然后修改harbor.yml
cp harbor.yml.tmpl harbor.yml
harbor.yml的部分
# The IP address or hostname to access admin UI and registry service.
# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
hostname: 172.22.109.126 # 地址就按上面提示的用ubuntu的ip,能够经过ifconfig,找到eth0最初的那一段,便是ubuntu的ip
# http related config
http:
# port for http, default is 80. If https enabled, this port will redirect to https port
port: 80
# https相关的都注释掉,这个搞起来麻烦,当然这一块简略了,后边docker和minikube都需求特别处理下这个问题
# https related config
# https:
# # https port for harbor, default is 443
# port: 443
# # The path of cert and key files for nginx
# certificate: /root/certs/reg.westos.org.crt
# private_key: /your/private/key/path
# 3. 进入解压后的harbor目录
./prepare # 做一些准备工作
# 取出里边的镜像,创立container,这一步或许遇到permission denied,便是没权限,那能够加上 sudo ./install.sh
# 我用的便是 sudo ./install.sh,但又碰上找不到/root/.docker/docker-desktop/docker.sock的问题,或许是由于我先装过win版的docker desktop导致的
# 后边用了软衔接处理的 ln s /var/run/docker.sock /root/.docker/docker-desktop/docker.sock
./install.sh
# 浏览器拜访
# 直接翻开localhost就行,默许是80端口
具体过程
- 进入wsl2
- 发动minikube
- 发动harbor
- 发动jenkins,拜访jenkins的web操控台,装置k8s的各种插件
- 构建集成kubectl和运用root用户的jenkins agent镜像
- 编写k8s的deployment.yml文件,编写Jenkinsfile,编写Dockerfile
- 创立pipline项目,填写项目信息,流水线挑选pipline script from scm,填入信息,保存,履行构建,构建成功后用minikube service serviceName露出服务,用浏览器检查
进入wsl2
能够查找wsl,或许ubuntu就能够进入
发动minikube
# 装置好后履行,这一步依靠docker,会下载相关镜像生成一个minikube container
# insecure的意思是答应以http的形式拜访本地harbor,前面harbor不是图简略直接把https注释了吗
minikube start --driver=docker --insecure-registry=linux的ip地址
# 发动k8s 操控台,快捷操作deployment, pod的检查删去操作
nohup minikube dashboard &
tail nohup.out # 翻开日志,ctrl 点击对应链接可在浏览器翻开对应的dashboard
发动harbor
再履行一遍前面的harbor装置过程涉及的install.sh文件即可,就能发动了,现在没整明白为啥harbor没有在体系重启后随docker主动发动
拜访localhost,输入默许用户名 “admin” 默许暗码 “Harbor12345”,创立库房
发动jenkins并拜访jenkins的web操控台
# 发动
nohup jenkins &
# 从log中找到jenkins初始化需求的字符串
tail nohup.out
拜访localhost:8080, 进入后装置k8s相关插件
- Kubernetes plugin:用于完成jenkins agent的k8s布置 参阅插件官网
- Kubernetes :: Pipeline :: DevOps Steps 效果没搞懂
- Kubernetes CLI Plugin:用于完成kubectl衔接远程k8s cluster,供给用户名暗码和远程k8s cluster给它,就能够装置kubectl,然后操作远程k8s cluster了
增加安全凭证,后续的Jenkinsfile编写需求用到这些凭证,体系管理 -> 凭证管理 -> 增加凭证
- gitee: 用于git拉代码,选username with password,id填入gitee,能够任意起名字,后续编写Jenkinsfile指定这个名字即可
- harbor:用于登录harbor,选username with password,id填入harbor
- sa-secret: 用于拜访k8s cluster,挑选secret text,填入token,id设置为sa-secret,token按下面的过程获取
- 创立用于拜访k8s cluster的凭证
# 创立serviceAccount,这一步没怎样研究,就跟着网上的走
# 创立一个名为jenkins-robot的sa
kubectl create serviceaccount jenkins-sa
# 绑定角色啥的,没太懂
kubectl create rolebinding jenkins-sa-binding --clusterrole=cluster-admin --serviceaccount=default:jenkins-sa
- 创立secret绑定到对应的serviceAccount
apiVersion: v1
kind: Secret
metadata:
name: sa-secret # 指定secret的名字
annotations:
kubernetes.io/service-account.name: "jenkins-sa" # 绑定到jenkins-sa这个serviceAccount上
type: kubernetes.io/service-account-token
- 检查找到secret对应的token并仿制token
kubectl describe secret sa-secret
# 得到一大堆字符串,相似下面这种,仿制其间token字段的值
#Name: sa-secret
#Namespace: default
#
#Type: kubernetes.io/service-account-token
#
#Data
#====
#ca.crt: 1111 bytes
#extra: 4 bytes
#namespace: 7 bytes
#token: eyJhbGciOiJSUzI1NiIsImtpZCI6InNFNTdsTTBMSnUyQWNLNU4tLXl2S1Q0aDdzYm1USnFZWGtlbTRTdWhrZ00ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InNhLXNlY3JldCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiZTUyMTAyMDAtMGFhMS00Mjc2LWE4N2QtMjVhNTdkNjdlOTRkIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6ZGVmYXVsdCJ9.TrL5U-3GeYW5DORcG6Rk7CC2pGa0AO_pZ8O1Ia7vIKxiZq1STvQyewtJiBSUcpKPUmsTe60uWLR6_1MY3-7EESGx3G-XUIRtF9Bt5HGEnhfZn6-BGP0brXYQXhfMcssQdePYroO9N9N3LQnyMroCHyCFhamU_-gIKNgotLiE8xO-kA5v6FFgK3rzohex-qQyOEJRDoaIESvo-FlxDu2Ai8KXsTvd0wKTG1s-C5XtgUPczJuHUW8bHepuwimUsvtB4vI_XoygaeicOT_uajd9Hh5tVeX4pzl_vwSolrH-dVwEGjUCoEVp6-wDjs5ox0GEz4tFvQzIcL8pFbjPHuOibw
创立cloud,即指定衔接哪个k8s集群
创立即可,后续的kubernetes plugin的podTemplate假如不指定cloud会主动运用这个(猜的)
体系管理 -> clouds -> new cloud,填入称号k8s,挑选kubernetes,假如没有这个选项或许你还没装置kubernetes plugin
# 1. Kubernetes 地址: 用下面的指令获取,取第一个
kubectl cluster-info
# 2. 勾选 “禁用 HTTPS 证书检查”
# 3. 凭证挑选前面创立的sa-secret然后衔接测验,经过了表示能够衔接到k8s cluster,即后续的jenkins agent能够布置到k8s上
# 4.Jenkins 地址: 不填就会用jenkins体系装备里边的地址,填的话不要用localhost或许127,要用本地真实ip
# Jenkins 通道不用填
# 保存即可
构建集成kubectl和运用root用户的jenkins agent镜像
构建自己的agent镜像,由于用默许镜像的话是运用不了kubectl指令的,而尝试挂载host中的kubectl又失利了,所以自己打包一个装置了kubectl的版别
# 这个版别应该是随意的,我写这个是前面运用过程中发现我装置的kubernets plugins主动用的这个版别,也能够用最新版吧
FROM jenkins/inbound-agent:3192.v713e3b_039fb_e-1
# 修改为root用户发动,这一步很重要,默许jenkins agent用的是jenkins用户发动,会导致拜访不了主机的docker.sock
# 不过也能够装备 kubernets plugins的runAsUser参数, runAsUser: '0', 也表示用root用户发动
USER root
# 这一步kubectl的版别号,需求保持和host共同,能够经过 kubectl version检查版别
ARG KUBECTL_VERSION=1.28.4
# Install kubectl (same version of aws esk)
RUN curl -sLO https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl &&
mv kubectl /usr/bin/kubectl &&
chmod x /usr/bin/kubectl
ENTRYPOINT ["/usr/local/bin/jenkins-agent"]
# 构建镜像并推送
docker build -t localhost/my-rep/agent1:latest
docker push localhost/my-rep/agent1:latest
编写Dockerfile,Jenkinsfile,k8s装备文件
先在gitee上创立个项目,然后用vue-cli进行下初始化,在新建个deploy目录,在里边创立deployment.yml, Dockerfile和Jenkinsfile放在根目录
Dockerfile
# 从docker hub下载nginx镜像,然后仿制dist目录下的文件到/usr/share/nginx/html/,由于nginx发动后,主页默许在这个目录
FROM nginx:alpine
COPY dist/ /usr/share/nginx/html/
创立一个secret
kubectl create secret docker-registry my-docker-secret
--docker-username=admin
--docker-password=Harbor12345
--docker-server=你的ubuntu ip
k8s deployment.yml
# 创立deployment,称号为nginx,运用镜像为IMAGE_PATH,这是个占位字符,后续在pipline中会用正则把它替换成真正的镜像地址
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: IMAGE_PATH
ports:
- containerPort: 80
imagePullSecrets:
- name: my-docker-secret # 指定一个前面创立的docker-registry类型的secret,用于拉取harbor镜像
---
# 创立一个service,用于露出pod的80端口
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 80
type: NodePort
Jenkinsfile
def HARBOR_URL = '你的ubuntu IP'
// podTemplate用法是kubernetes plugins供给的,也能够用声明式语法,都差不多,kubernetes plugins官网能看到各种用法
//
podTemplate(volumes: [
// 挂载主机的docker,然后能够运用docker指令,相似于win上的快捷方式,不过这一步要用前面自己构建的容器,不然默许的发动用户没有拜访docker.sock的权限
hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
hostPathVolume(mountPath: '/usr/bin/docker', hostPath: '/usr/bin/docker'),
hostPathVolume(mountPath: '/home/jenkins/agent/.pnpm-store', hostPath: '/root/.local/share/pnpm/'), // 挂载pnpm的全局存储库,减小pnpm装置包的时间,这一步假如有问题也能够去除
],
// 或许装备 runAsUser: '0'也能够启用root用户
// 装备容器信息,自己构建容器,加入了kubectl和运用root用户
containers: [
containerTemplate(
name: "jnlp",
image: "${HARBOR_URL}/my-rep/agent1:latest"
),
containerTemplate(name: "nodejs", image: "node:18-alpine", command: 'sleep', args: '99d') // 要加上sleep指令,不然container发动后主动封闭,没搞懂为啥
]) {
node(POD_LABEL) {
// 拉取代码并打包
stage("clone") {
git credentialsId: 'gitee', url: 'https://gitee.com/xxx/test-jenkins.git'
container("nodejs") {
sh '''npm install -g pnpm@7
pnpm i
pnpm build
'''
}
}
// 构建镜像
stage("build") {
echo "开端构建docker镜像"
sh "docker build -t ${HARBOR_URL}/my-rep/nginx:${env.BUILD_NUMBER} ."
echo "构建完毕"
}
// 上传镜像到私有镜像库
stage("publish") {
// 获取harbor的用户命和暗码
withCredentials([usernamePassword(credentialsId: 'harbor', passwordVariable: 'HARBOR_SECRET_PSW', usernameVariable: 'HARBOR_SECRET_USR')]) {
echo "开端推送镜像"
sh "docker login -u ${HARBOR_SECRET_USR} -p ${HARBOR_SECRET_PSW} http://${HARBOR_URL}"
sh "docker push ${HARBOR_URL}/my-rep/nginx:${env.BUILD_NUMBER}"
echo "推送完毕"
}
}
// 进行k8s发布
stage("deploy") {
// withKubeConfig由kubernetes cli供给,用于拜访k8s cluster
// 这一步装备内网ip很重要
// 这个serverUrl不是经过kubectl cluster-info得到的那个,那个是外部拜访的ip,而这里由于agent是布置在k8s里边的,和k8s cluster在同一个内部网络,需求用内网地址
// kubectl get services 得到下面的参数,取kubernetes这个ip加端口
// kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23h
// nginx-service NodePort 10.108.227.72 <none> 80:30080/TCP 23h
withKubeConfig(credentialsId: 'sa-secret', serverUrl: 'https://10.96.0.1:443') {
// 进入deploy目录,由于我项意图装备文件都放在了deploy目录下
dir('deploy') {
def image_name = "${HARBOR_URL}/my-rep/nginx:${env.BUILD_NUMBER}"
echo "替换image路径"
sh "sed -i 's/IMAGE_PATH/${image_name}/g' deployment.yml"
echo "布置app"
sh "kubectl apply -f deployment.yml"
echo "布置完毕,能够经过履行minikube service nginx-service得到一个可拜访的地址,driver是docker且是wsl或win环境,NodePort类型的service的IP并不能直接被拜访到,所以minikube供给了service指令"
}
}
}
}
}
一些重要概念
- jenkins master: 类型于一台主机,能够直接在上面运转使命,官方主张把master设置为制止履行使命,只做操控用
- jenkins agent:相似于一个只干活的主机,上面会运转jenkins的一个agent.jar,然后与master衔接,master给它分配使命。然后这个agent能够直接其他主机上创立,也能够由k8s帮助创立,而假如是k8s创立,就需求kubernetes plugins,按最基本的装备的话,它会生成一个称号为jnlp的container,用于履行使命以及和master衔接通信,所以假如自己彻底写k8s的装备的话也要写一个name为jnlp的container,同时里边要包括agent.jar的功用,那么直接用agent官方镜像或许集成官方镜像即可
过程中遇到的坑
网络问题
有镜像下载不下来的状况;有连不上docker deamon的状况;minikube start下载镜像贼慢还有或许失利;有连不上k8s cluster的状况;有连不上jenkins master的状况
处理办法:魔法是有必要的,不仅win要魔法,还得开个tun mode给wsl也来个魔法,其次最好有个队友一起搞,这样能知道一些网络问题是哪装备出错了仍是便是网慢
linux权限问题
多次出现各种权限问题,最典型的报错 permission denies,这个引荐没有linux根底的花1h看看linux用户、用户组、文件权限相关的内容, 引荐鸟哥相关linux文章
KubeSphere介绍
kubeSphere便是比k8s dashboard功用愈加丰厚,同时它还有许多其他功用,比如集成了jenkins的pipeline,下文主要介绍怎样运用kubesphere的devops功用。kubesphere装置了devops后
会生成jenkins master Pod,当运用pipeline功用时,会主动创立jenkins agent Pod,当然也能够自定义agent
kubesphere装置及devops装置和运用
参照官网装置,装好后怎样都登录不了,最终发现是k8s版别太高导致,其实官网有阐明只支持到k8s指定版别,没仔细看,反而花了巨多时间查找登录页面的报错
然后坑又来了,devops插件怎样都装不上,最终尝试装置2.1的kubesphere版别,devops总算ok了
降kubesphere版别过程中,又涉及helm降版别装置,镜像拉不下来,参阅处理k8s helm装置tiller出现ImagePullBackOff,ErrImagePull过错处理了
然后便是创立devops项目,创立流水线。能够直接仿制Jenkinsfile。甚至能够直接用浏览器拜访内部的jenkins,默许的service是ks-jenkins,找到其露出的端口号即可,登录后能看到,kubesphere只是把流水线装备直接放在了pipline里边。
那么用kubesphere作为devops的优势在哪呢,或许是它简化了jenkins的各种插件的杂乱装备?
反正我最终是没有用kubesphere完成过构建,或许是版别太低了,前面手动写的Jenkinsfile放进去履行各种报错,最终抛弃。
最终
以上都是一些最简略的入门,许多总结是自己根据实践猜测的,并没有深化原理,还有许多概念不清不楚,因此或许会有许多过错,还请自行甄别。写这个的意图只是为了让自己了解下CI的东西集,并不打算深化。