共计 9198 个字符,预计需要花费 23 分钟才能阅读完成。
环境阐明
PS:本文档试验过程中并没有对权限做出严格束缚,比方间接在 jenkins 寄存管理员的 kubeconfig 文件、间接在 jenkins 用集群管理员角色对接 k8s 集群等操作,均有很大危险,须要依据理论状况束缚相应用户的权限。
规划设计:
角色 | 地址 | 域名 |
---|---|---|
master | 192.168.10.100 | |
node | 192.168.10.101 | |
gitlab | 192.168.10.110 | |
jenkins | 192.168.10.111 | jenkins.snow.com |
harbor | 192.168.10.112 | harbor.snow.com |
试验之前集群曾经搭建结束,搭建教程可参考构建高可用 k8s 集群,jenkins 与 gitlab 别离应用安装包的形式装置在两台虚拟机上。harbor 以容器的形式独自部署在一台虚拟机。
策略设计
k8s 集群内的 pro 名称空间模仿生产环境,dev 名称空间模仿开发环境,开发环境下的代码只有推送到代码仓库会触发 jenkins 主动公布到 dev 名称空间的对应 POD,pro 名称空间的 POD 只有管理员手动按选定的 tag 构建进去的版本才能够公布到 k8s 环境。
增加 kubelet 认证,让 jenkins 能够有操作 k8s 集群的权限
在 Harbor 仓库别离增加两个新的我的项目,我的项目名别离为 pro 和 dev,用来寄存生产和测试的镜像。为了试验不便将我的项目都配置为了公开模式,如果想要配置为私密模式则须要增加仓库的认证信息,具体参考文章:[docker 配置 https 加密对接 k8s]
将 master 节点的.kube 文件和 kubectl 命令发送到 jenkins 所在的节点
root@master01:~# which kubectl
/opt/kube/bin/kubectl
root@master01:~# scp /opt/kube/bin/kubectl 192.168.10.111:/usr/local/bin/kubectl
root@192.168.10.111's password:
kubectl 100% 45MB 29.0MB/s 00:01
root@master01:~# scp -r .kube 192.168.10.111:/root/.kube
root@192.168.10.111's password:
config 100% 6241 1.9MB/s 00:00
9f754ca1a0545e7b871b81c83a185054 100% 2460 1.6MB/s 00:00
c4f8f2c14858bcf309490b8356533dde 100% 642 219.8KB/s 00:00
在 jenkins 验证是否有操作 k8s 集群的权限
root@jenkins:~# kubectl get no
NAME STATUS ROLES AGE VERSION
192.168.10.100 Ready master 5d22h v1.22.2
192.168.10.101 Ready node 5d22h v1.22.2
如果执行 get node 的时候报错网络超时须要查看.kube/config 文件中的 server 字段是否指定的是 apiserver 的地址及 apiserver 的 6443 端口是否监听在 127.0.0.1 地址。在 jenkins 增加拜访 k8s 集群的凭证登录 jenkins 后抉择 Dashboard-> 系统管理 -> 凭据 -> 零碎 -> 全局凭据,点击右上角创立一个新的凭据。
类型抉择 X.509 Client Certficate,Client Key 字段内容填写.kube/config 文件中的 client-key-data 字段数据 base64 解码后的值。Client Certificate 字段填写.kube/config 文件中的 client-certificate-data 字段数据 base64 解码后的值,Server CA Certificate 字段填写.kube/config 文件中的 certificate-authority-data 字段数据 base64 解码后的值。
增加 gitlab 认证,让 jenkins 能够有拉取代码的权限
持续依照上一步的操作新增加一个凭证
创立新仓库,别离创立 main 与 dev 分支并推送到 gitlab。
在 gitlab 新建一个空白我的项目
在 master 节点应用 git 命令创立分支并将代码推送到 gitlab
root@master01:~/dev/httpserver# git init
Initialized empty Git repository in /root/dev/httpserver/.git/
root@master01:~/dev/httpserver# git remote add origin http://192.168.10.110/root/helloserver.git
root@master01:~/dev/httpserver# git checkout -b main
Switched to a new branch 'main'
筹备提前写好的 Dockerfile 文件与测试代码。PS: 这里的 dockerfile 写的很烂,只是能用。
root@master01:~/dev/httpserver# ls
Dockerfile go.mod main.go
root@master01:~/dev/httpserver# cat Dockerfile
FROM golang:latest
ADD . /
WORKDIR /
RUN go build -o main.exe
EXPOSE 80
ENTRYPOINT ["./main.exe"]
root@master01:~/dev/httpserver# cat main.go
package main
import ("net/http")
func main() {http.HandleFunc("/", func(resp http.ResponseWriter, req *http.Request) {resp.Write([]byte("Version=1.0"))
})
http.ListenAndServe(":80", nil)
}
将 main 分支的代码推送到仓库
root@master01:~/dev/httpserver# git add .
root@master01:~/dev/httpserver# git status
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: Dockerfile
new file: go.mod
new file: main.go
root@master01:~/dev/httpserver# git commit -m "v1.0"
[main (root-commit) 3b5d105] v1.0
3 files changed, 21 insertions(+)
create mode 100644 Dockerfile
create mode 100644 go.mod
create mode 100644 main.go
root@master01:~/dev/httpserver# git tag v1.0
root@master01:~/dev/httpserver# git push --tags
Username for 'http://192.168.10.110': root
Password for 'http://root@192.168.10.110':
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 584 bytes | 584.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To http://192.168.10.110/root/helloserver.git
* [new tag] v1.0 -> v1.0
#将主分支的代码推送到仓库,在操作的时候有点失误,最初强制合并的。root@master01:~/dev/httpserver# git pull --allow-unrelated-histories origin main
Username for 'http://192.168.10.110': root
Password for 'http://root@192.168.10.110':
From http://192.168.10.110/root/helloserver
* branch main -> FETCH_HEAD
hint: Waiting for your editor to close the file...
GNU nano 4.8 /root/dev/httpserver/.git/MERGE_MSG
Merge branch 'main' of http://192.168.10.110/root/helloserver into main
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
Merge made by the 'recursive' strategy.
README.md | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
create mode 100644 README.md
root@master01:~/dev/httpserver#
root@master01:~/dev/httpserver# git push -u origin main
Username for 'http://192.168.10.110': root
Password for 'http://root@192.168.10.110':
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 402 bytes | 402.00 KiB/s, done.
Total 2 (delta 0), reused 0 (delta 0)
To http://192.168.10.110/root/helloserver.git
924f2d2..eeb98b1 main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.
在 Gitlab 查看推送到主分支的代码
创立开发分支,并将开发分支推送到 Gitlab
root@master01:~/dev/httpserver# git checkout -b dev
Switched to a new branch 'dev'
root@master01:~/dev/httpserver# git add .
root@master01:~/dev/httpserver# git commit -m "v1.0"
On branch dev
nothing to commit, working tree clean
root@master01:~/dev/httpserver# git tag v1.0
fatal: tag 'v1.0' already exists
root@master01:~/dev/httpserver# git push -u origin dev
Username for 'http://192.168.10.110': root
Password for 'http://root@192.168.10.110':
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for dev, visit:
remote: http://gitlab.example.com/root/helloserver/-/merge_requests/new?merge_request%5Bsource_branch%5D=dev
remote:
To http://192.168.10.110/root/helloserver.git
* [new branch] dev -> dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
推送实现后发现曾经多了一个名字为 dev 的分支
设置生产环境须要指定 tag 版本公布。
在 jenkins 创立一个自在格调的工作
配置参数化构建信息
在源码治理地位配置 gitlab 仓库信息,留神须要抉择之前创立的认证信息,不然会报权限有余。
在构建环境地位抉择 Setup Kubernetes CLI (kubectl),并配置集群相干信息,此处的 certificate 配置的数据为.kube/config 文件中 certificate-authority-data 字段的值通过 base64 解码后的值。凭据抉择之前创立的有操作 k8s 集群权限的凭据。
配置更新镜像须要执行的 shell 命令。曾经在每台主机配置了将 harbor.snow.com 解析为镜像仓库地址的条目,所以此处间接写了域名。
配置实现后单击保留,点击参数化构建能够看到之前推送到 Gitlab 仓库的代码的 tag,依据 tag 去拉取代码。
在 k8s 提前应用 yaml 文件创建出业务 deployment 控制器,将生产相干代码创立在 pro 名称空间。对其进行版本更新的操作就是对 yaml 文件中 image 字段的更新。
root@master01:~/pod# kubectl create ns pro
namespace/pro created
root@master01:~/pod# cat httpserver.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpserver
spec:
replicas: 3
selector:
matchLabels:
run: httpserver
template:
metadata:
labels:
run: httpserver
spec:
containers:
- name: httpserver
image: nginx
imagePullPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: httpserver-service
spec:
type: NodePort
selector:
run: httpserver
ports:
- port: 80
targetPort: 80
root@master01:~/pod# kubectl apply -f . -n pro
deployment.apps/httpserver created
service/httpserver-service created
配置实现后在 jenkins 点击参数化构建,抉择 v1.0 版本进行构建。
构建过程能够在控制台输入地位看到
当初去 k8s 拜访业务代码的地址查看其版本。
当初应用 git 命令将 v2.0 版本推送到代码仓库,2.0 版本只是在 main.go 文件中将版本号更改为 2.0. 以下是手动改完版本后的操作。
root@master01:~/dev/httpserver# git status
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: main.go
no changes added to commit (use "git add" and/or "git commit -a")
root@master01:~/dev/httpserver# git add .
root@master01:~/dev/httpserver# git commit -m "v2.0"
[main 3c7199e] v2.0
1 file changed, 1 insertion(+), 1 deletion(-)
root@master01:~/dev/httpserver# git tag v2.0
root@master01:~/dev/httpserver# git push --tags
Username for 'http://192.168.10.110': root
Password for 'http://root@192.168.10.110':
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 277 bytes | 277.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To http://192.168.10.110/root/helloserver.git
* [new tag] v2.0 -> v2.0
操作实现去 gitlab 查看发现 2.0 版本曾经胜利推送上来了。
当初去 jenkins 抉择参数化构建,构建的时候 tag 选 2.0 版本。
构建实现后发现版本曾经成为最新 v2.0 版本。
设置 dev 分支能够主动公布
在 k8s 集群创立出 dev 名称空间,并创立出对应的业务 service 的 deployment,所用到的 yaml 与下面在 pro 名称空间创立资源时应用的对立个,这里就没有反复截图。
去 jenkins 创立一个新的自在格调的工作
在源码治理地位配置代码仓库相干信息,留神要拉取的分支改为开发分支。
抉择构建触发器中的 Build when a change is pushed to GitLab 选项,这个选项是须要装置 Gitlab Hook Plugin 和 Build Authorization Token Root Plugin 插件才能够看到。
配置 k8s 的连贯信息
此处在构建时应用了 $BUILD_NUMBER 变量作为镜像的 tag,确保每次构建 k8s 都能拉取到最新的镜像。
创立实现后先手动点击构建,看是否能失常构建胜利
在 k8s 平台测试手动构建胜利
此时在 jenkins 点击配置,在构建触发器取出此链接,须要配置到 Gitlab 平台。
同样在该选项卡下点击高级配置能够看到如下选项,点击生成一个新的 token
之后单击保留。
单击页面左上角抉择最上面的管理员
在设置选项卡找到网络。
在出站申请地位勾选 容许来自 web hooks 和服务对本地网络的申请,否则无奈增加本地须要调用的 webhook 地址。更改实现后保留。
进入我的项目配置信息,抉择设置,单击 WebHook。
在此处配置刚刚取出的地址和 token
配置实现后在此页面最下方会看到创立的 webhook
创立实现后能够去测试推送事件触发构建,发现在 jenkins 曾经胜利触发构建
此时用 git 向 dev 分支提交代码,手动将 main.go 的版本号批改为 2.0。批改文件过程不再演示。
root@master01:~/dev/httpserver# git add .
root@master01:~/dev/httpserver# git commit -m "v2.0"
[dev 9df58bd] v2.0
1 file changed, 1 insertion(+), 1 deletion(-)
root@master01:~/dev/httpserver# git push -u origin dev
Username for 'http://192.168.10.110': root
Password for 'http://root@192.168.10.110':
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 277 bytes | 277.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote:
remote: To create a merge request for dev, visit:
remote: http://gitlab.example.com/root/helloserver/-/merge_requests/new?merge_request%5Bsource_branch%5D=dev
remote:
To http://192.168.10.110/root/helloserver.git
eeb98b1..9df58bd dev -> dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
此时去 jenkins 平台查看发现曾经触发构建。
当初去 k8s 平台去验证 dev 名称空间的 POD 是否曾经自动更新。
root@master01:~/dev/httpserver# kubectl get svc -n dev
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpserver-service NodePort 10.100.53.6 <none> 80:30222/TCP 36m
root@master01:~/dev/httpserver# curl 10.100.53.6
Version=2.0root@master01:~/dev/httpserver#
ps:以上内容在自己实现环境中已试验胜利,如发现有问题或表述不清的中央欢送斧正。