1.介绍 在K8s学习(十三):部署服务[上篇] 文章中,已经把持续集成和持续部署的相关软件都进行了安装,但由于文章篇幅受限,所以有关各个软件的具体使用和发布服务流程并未说明,在这篇文章中,我们接着继续学习…
文章中涉及到的go-app
、pipeline完整代码
、以及Containerd
配置,关注公众号【猿码记】,回复【k8s-demo】即可获得
2.Jenkins容器映射 2.1 映射软件说明
软件
说明
docker
在jenkins
发布过程中,用于镜像制作。
goctl
生成制作镜像的Dockerfile
和发布到k8s
的配置文件,由go-zero
提供
kubectl
将应用发布到K8s
2.2 映射相关代码
通过K8s学习(十三):部署服务[上篇] 文章中的部署方式,会自动把goctl、docker、kubectl、.kube
映射到容器中,需要注意的是,jenkins所在的宿主机需要安装docker、kubectl.
具体映射代码如下:
docker-compose.yaml
.... jenkins: build: ... volumes: - ${VOLUMES_PATH}/jenkins/jenkins_home:/var/jenkins_home - ${JENKINS_DOCKER_SOCK}:/var/run/docker.sock - ${JENKINS_DOCKER}:/usr/bin/docker - ${KUBECTL_BIN_PATH}:/usr/local/bin/kubectl - ${K8S_KUBE_CONFIG}:/root/.kube - ${LIBLTDL_SO}:/usr/lib/x86_64-linux-gnu/libltdl.so.7 ...
.env
文件
... KUBECTL_BIN_PATH=/usr/bin/kubectl K8S_KUBE_CONFIG=/root/.kube ...
上述配置已经集成到k8s_microsvc_cicd: https://github.com/52lu/k8s_microsvc_cicd 项目中,这里只做了解,无需操作;正常启动服务即可;
2.3 验证 进入jenkins
验证上面软件是否映射到容器中.
# 进入容器 $ docker-compose exec jenkins bash # 验证docker $ docker version Client: Docker Engine - Community Version: 20.10.22 API version: 1.41 Go version: go1.18.9 Git commit: 3a2c30b Built: Thu Dec 15 22:30:24 2022 OS/Arch: linux/amd64 Context: default Experimental: true ...# 验证goctl $ goctl -v goctl version 1.4.3 linux/amd64# 验证 kubectl $ kubectl version Client Version: version.Info{Major:"1", Minor:"24", GitVersion:"v1.24.2"...# 验证是否能连上k8s集群 $ kubectl get ns NAME STATUS AGE calico-apiserver Active 17h calico-system Active 18h default Active 18h ingress-nginx Active 16h kube-node-lease Active 18h kube-public Active 18h kube-system Active 18h
2.4 踩坑:the server is currently unable… 如果在验证是否能连上k8s集群 时,报错Error from server (ServiceUnavailable): the server is currently unable to handle the request
,原因是发布机器上没有~/.kube/config
这个文件。
解决方法:
将master
节点相同位置的配置文件,复制到发布机器~/.kube/config
这个文件;
重新编译jenkins
: docker-compose build jenkins
重新启动jenkins
: docker-compose up -d jenkins
3. 配置准备 3.1 添加拉取代码凭证 添加步骤如下:
点击左边菜单-> 系统管理(Manage Jenkins
)
点击 Manage Credentials
点击“全局”后面的三角标,然后在点击“添加凭据”
进入添加凭据 页面,填写信息如下:
类型: 选择 Username with password
使用账号密码方式;
ID: 可以理解为证书的名称,需要唯一
用户名: 登陆gitea
的账号
密码: 登陆gitea
的密码
gitea
设置使用ssh
的方式拉取代码过于麻烦,这里使用账号密码的方式拉取,如果想使用ssh
方式拉取代码,可参见官方文档设置: SSH 容器直通:https://docs.gitea.io/zh-cn/install-with-docker/#ssh-容器直通
填写完成后,点击保存(Create)
3.2 添加harbor仓库配置 进入首页,点击左侧菜单->系统管理(Manage Jenkins
)->系统配置(Configure System
) ,进入页面后一直往下滑动,直到到全局属性
条目,添加docker
私有仓库相关信息,如下图所示:
填完之后,点击 保存
上述信息结合自己的真实情况填写。
3.3 配置git 点击左侧菜单->系统管理(Manage Jenkins
)-全局工具配置(Global Tool Configureation
),找到Git
条目,填写jenkins
所在机器git
可执行文件所在path
,如果没有的话,需要在jenkins
插件管理中下载Git
插件, 有就不需要其他操作 (如下图)
3.4 安装Git Parameter插件
在jenkins
发布过程中,编写管道(pipline
)需要Git Parameter
插件
点击左侧菜单->系统管理(Manage Jenkins
)-插件管理(Manage Plugins
)
3.5 k8s添加ServiceAccount
在后面 发布到k8s环节 ,会使用goctl kube xxx
来生k8s yaml
,在使用k8s
方式部署时,需要为生成的k8s yaml
中指定serviceAccount
。 原理可以看这篇文章下方go-zero
的k8s
服务发现讲解 :https://mp.weixin.qq.com/s/-WaWJaM_ePEQOf7ExNJe7w
只需要执行kubectl apply -f jenkins_service_account.yaml
即可;
# 创建k8s命名空间 $ kubectl create ns k8s-demo namespace/k8s-demo created# 创建serviceAccount $ kubectl apply -f jenkins_service_account.yaml clusterrole.rbac.authorization.k8s.io/discov-endpoints created clusterrolebinding.rbac.authorization.k8s.io/find-endpoints-discov-endpoints created
jenkins_service_account.yaml
文件内容如下:
apiVersion: v1 kind: ServiceAccount metadata: namespace: k8s-demo name: find-endpoints --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: discov-endpoints rules: - apiGroups: ["" ] resources: ["endpoints" ] verbs: ["get" ,"list" ,"watch" ]--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: find-endpoints-discov-endpoints roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: discov-endpoints subjects: - kind: ServiceAccount name: find-endpoints namespace: k8s-demo
3.6 k8s添加拉取镜像凭证
k8s
在默认情况下,只能拉取harbor
镜像仓库的公有镜像,如果拉取私有仓库镜像,则是会报 ErrImagePull
和 ImagePullBackOff
的错误
1.先在jenkins发布机器登陆harbor 在jenkins发布机器登陆harbor,会生成登录凭证,保存在/root/.docker/config.json
$ docker login 192.168.148.132:8870 Username: admin Password: Error response from daemon: Get "https://192.168.148.132:8870/v2/": http: server gave HTTP response to HTTPS client
如果发现你也报这种错误的话,解决方法如下:
# 确保你的/etc/docker/daemon.json,加对了insecure-registries $ cat /etc/docker/daemon.json { "registry-mirrors":[ "https://otrqd6z7.mirror.aliyuncs.com" ], "insecure-registries":[ "192.168.148.132:8870" ] }# 重新加载 $ systemctl daemon-reload # 重启docker $ systemctl restart docker # 重启harbor,在harbor安装目录执行下面命令 $ docker-compose restart Restarting harbor-jobservice ... done Restarting nginx ... done Restarting harbor-core ... done Restarting registry ... done Restarting redis ... done Restarting registryctl ... done Restarting harbor-portal ... done Restarting harbor-db ... done Restarting harbor-log ... done# 再次登录 $ docker login 192.168.148.132:8870 Username: admin Password: WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded
2.查看登陆harbor
生成的凭证 $ cat .docker/config.json { "auths":{ "192.168.148.132:8870":{ "auth":"YWRtaW46SGFyYm9yMTIzNDU=" } } }
3. 对秘钥文件进行base64加密 $ cat /root/.docker/config.json | base64 -w 0 ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjE0OC4xMzI6ODg3MCI6IHsKCQkJImF1dGgiOiAiWVdSdGFXNDZTR0Z5WW05eU1USXpORFU9IgoJCX0KCX0KfQ==
4. 创建docker-harbor-secret.yaml jenkins-harbor-secret.yaml
内容如下:
apiVersion: v1 kind: Secret metadata: name: docker-login type: kubernetes.io/dockerconfigjson data: .dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjE0OC4xMzI6ODg3MCI6IHsKCQkJImF1dGgiOiAiWVdSdGFXNDZTR0Z5WW05eU1USXpORFU9IgoJCX0KCX0KfQ==
# 在k8s集群中执行,注意指明命名空间 $ kubectl apply -f jenkins-harbor-secret.yaml -n k8s-demo secret/docker-login created
4. Jenkins发布 4.1 创建任务 步骤一: 点击左侧菜单->新建任务(新建item
),进入下面页面:
步骤二: 点击保存后跳到具体配置页面
4.2 Pipeline脚本预览 这一章节主要介绍Pipeline脚本
都有哪些部分组成,并把pipeline
具体步骤部分,单拿出一个章节讲解;
4.2.1 整体流程 pipeline { agent any parameters { } environment { } stages { stage ('构建信息' ) { steps { } } stage ('拉取源码' ) { steps { } } stage ('生成镜像' ) { steps{ } } stage ('上传镜像' ) { steps{ } } stage ('发布到k8s' ) { steps{ } } stage ('清理代码' ) { steps{ } } } }
4.2.2 参数信息 pipeline { agent any parameters { gitParameter ( name : 'commit_id' , // 参数名(我们在创建任务页面设置的git参数) type: 'PT_REVISION' , branchFilter: 'origin/(.*)' , defaultValue: 'master' , selectedValue: 'TOP' , quickFilterEnabled: true , sortMode: 'ASCENDING_SMART' , description: '选择需要构建的commit信息' ) } environment { } stages { } }
4.2.3 环境变量 pipeline { agent any parameters { } environment { AppName = "go-app" AppPort = "1010" DockerNamespace = "k8s-demo" JenkinsAccountName= "find-endpoints" DeployReplicas = 1 PodMinReplicas = 1 PodMaxReplicas = 1 } stages { } }
4.3 Pipeline具体步骤 4.3.1 打印构建信息 stage ('构建信息' ) { steps { sh 'echo commit_id:$commit_id' sh 'echo goctl版本信息' sh '/usr/local/bin/goctl -v' } }
4.3.2 拉取源代码 这个步骤可以通过pipeline
流水线语法生成,如下图:
stage ('拉取源码' ) { steps { checkout ([ $class : 'GitSCM' , // 不用改 branches : [[name : '$commit_id' ]],// 和之前定义的变量名保持一直 doGenerateSubmoduleConfigurations : false , // 不用改 extensions : [], submoduleCfg : [], userRemoteConfigs : [[credentialsId : 'gitea-account' , url : 'http://192.168.148.132:8800/k8s/go-app.git' ]] // gitea-account: 拉取凭证id;url :代码地址 ]) } }
4.3.3 生成镜像 stage ('生成镜像' ) { steps{ sh "yes | rm -rf Dockerfile" sh "/usr/local/bin/goctl docker -go main.go && ls -l" script{ env.image = sh (returnStdout : true , script : "echo ${env.AppName}:${commit_id}" ).trim () } sh "echo 镜像名称:${image}" sh "docker build -t ${image} ." } }
这里我们使用goctl
来生成Dockerfile
,
4.3.4 上传镜像 stage ('上传镜像' ) { steps{ sh 'docker login --username=${docker_username} --password=${docker_pwd} http://${docker_repo}' sh "docker tag ${image} ${docker_repo}/${env.DockerNamespace}/${image}" sh "docker push ${docker_repo}/${env.DockerNamespace}/${image}" } }
4.3.5 发布到k8s stage ('发布到k8s' ) { steps{ script{ env.deployYaml = sh (returnStdout : true , script : "echo ${env.AppName}-deploy.yaml" ).trim () } sh "echo 暴露端口: ${env.AppPort}" sh 'rm -f ${deployYaml}' sh "/usr/local/bin/goctl kube deploy -secret docker-login -replicas ${env.DeployReplicas} -minReplicas ${env.PodMinReplicas} -maxReplicas ${env.PodMaxReplicas} -nodePort 3${env.AppPort} -requestCpu 200 -requestMem 50 -limitCpu 300 -limitMem 100 -name ${env.AppName} -namespace ${env.DockerNamespace} -image ${docker_repo}/${env.DockerNamespace}/${image} -o ${deployYaml} -port ${env.AppPort} -serviceAccount ${env.JenkinsAccountName}" sh 'cat ${deployYaml}' sh '/usr/local/bin/kubectl apply -f ${deployYaml}' } }
4.3.6 清理代码 这一步主要是为了清理,构建过程中生成的代码信息,和镜像信息
stage ('清理信息' ) { steps{ sh 'set +e' sh "docker rmi ${docker_repo}/${env.DockerNamespace}/${image}" sh "docker images | grep ${env.AppName} | awk \'{print \$3}\'| xargs docker rmi -f" sh "docker images | grep none | awk \'{print \$3}\'| xargs docker rmi -f " sh "ls -al ${env.WORKSPACE}" deleteDir () sh "ls -al ${env.WORKSPACE}" } }
4.4 准备发布 4.4.1 粘贴pipeline脚本 把上述的配置完整信息,复制粘贴到流水线脚本框,如下图:
关注公众号【猿码记】,回复【k8s-demo】,获取完整pipeline脚本信息
4.4.2 发布
再次构建时,即可发现能发布成功,如下图:
4.4.3 查看k8s集群
原因是: 在k8s
集群的节点上,我们没有配置从私有仓库拉取镜像的配置;k8s
各个集群节点安装的是Containerd
,所以我们修改所有k8s集群节点的Containerd
配置信息,并重启。
1. 修改Containerd配置 $ vim /etc/containerd/config.toml ...# 找到这个位置 [plugins."io.containerd.grpc.v1.cri".registry] config_path = "" # 新增私有仓库 [plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.148.132:8870"] endpoint = ["http://192.168.148.132:8870"] [plugins."io.containerd.grpc.v1.cri".registry.auths] [plugins."io.containerd.grpc.v1.cri".registry.configs] [plugins."io.containerd.grpc.v1.cri".registry.configs."192.168.148.132:8870".tls] insecure_skip_verify = true #跳过证书验证 [plugins."io.containerd.grpc.v1.cri".registry.configs."192.168.148.132:8870".auth] username = "admin" # 账号 password = "Harbor12345"# 密码 [plugins."io.containerd.grpc.v1.cri".registry.headers] [plugins."io.containerd.grpc.v1.cri".registry.mirrors] ....
配置改的太痛苦,比较伤眼睛,注意空格;关注公众号【猿码记】,回复【k8s-demo】,获取完整配置信息
2. 重启Containerd $ systemctl restart containerd
4.4.4 访问服务