• 本实验基于开源软件建立了一个全流程的CICD环境,为实现devops落地提供最基本的解决方案。
  • 对gitlab、jenkins进行详细安装部署及使用描述。
  • 探索**从k8s到paas**。。。

image.png

一、CI/CD拓扑图

image.png
CI/CD实验机器:(本实验使用4台虚拟机完成)

应用 主机 配置 安装软件
gitlab vms24(192.168.26.24) 2核4G gitlab-ce-13.0.6-ce.0.el7.x86_64.rpm
jenkins vms25(192.168.26.25) 2核4G jdk-11.0.7_linux-x64_bin.rpm、jenkins-2.222.4-1.1.noarch.rpm、docker(使用默认安装或docker ce最新版本)、git、kubectl(版本与集群对应)
docker registry vms32(192.168.26.32) 2核2G docker 由于主机内存不够,将registry移到vms25
k8s-master vms61(192.168.26.61) 2核2G k8s集群master
k8s-worker1 vms62(192.168.26.62) 2核2G k8s集群node-1 (启动)
k8s-worker2 vms63(192.168.26.63) 2核2G k8s集群node-2 (由于主机内存不够,此节点不启动)

说明:

  • 由于主机内存不够,k8s集群只启动master和worker1节点,worker2节点不启动。k8s版本v1.18.2。
  • 客户端使用windows主机,安装Git客户端,使用Git Bash

    二、安装gitlab(vms24)

    1、下载:https://packages.gitlab.com/gitlab/gitlab-ce
    image.png
    2、将下载的rpm(gitlab-ce-13.0.6-ce.0.el7.x86_64.rpm)上传到vms24
    3、安装:
    [root@vms24 ~]# rpm -ivh gitlab-ce-13.0.6-ce.0.el7.x86_64.rpm
    会发生错误,使用yum install安装:

    警告:gitlab-ce-13.0.6-ce.0.el7.x86_64.rpm: 头V4 RSA/SHA1 Signature, 密钥 ID f27eab47: NOKEY错误:依赖检测失败:
    policycoreutils-python 被 gitlab-ce-13.0.6-ce.0.el7.x86_64 需要

[root@vms24 ~]# yum install gitlab-ce-13.0.6-ce.0.el7.x86_64.rpm
4、编辑/etc/gitlab/gitlab.rb,修改external_url的值为主机名或主机IP:
external_url 'http://192.168.26.24'
5、初始化gitlab:
[root@vms24 ~]# gitlab-ctl reconfigure
6、在浏览器地址栏输入192.168.26.24,
6.1 提示设置密码:(这里设置的root密码)
image.png
6.2 然后用root登录
image.png
7、创建project
7.1 点击create a project
image.png
7.2 项目名设置为project1,vaisibility设置为public
image.png
7.3 然后点击Create project
image.png
7.4 点击Clone,可以看到git下载地址
image.png
可以看到,可以通过ssh的方式clone,也可以通过http的方式clone代码。
8、git客户端
8.1 下载:https://git-scm.com/downloads
image.png
8.2 安装并使用git windows客户端(linux客户端安装:yum install git)

新建目录并打开,右键选择Git Bash Here

image.png
8.3 通过http的方式克隆
$ git clonehttp://192.168.26.24/root/project1.git
进入到project1创建一个文件,内容为111,然后推送到仓库

  1. $ cd project1/
  2. $ echo 111 > index.html
  3. $ git add .
  4. $ git config --global user.name "test" #第一次使用时需要,按提示操作
  5. $ git config --global user.email you@example.com #第一次使用时需要,按提示操作
  6. $ git commit -m "111"
  7. $ git push

image.png
输入用户名及密码。在gitlab查看项目变化
image.png
8.4 以ssh的方式clone
$ rm -rf project1/
通过命令ssh-keygen -N “”生成密钥对

  1. $ ssh-keygen -N ""
  2. Generating public/private rsa key pair.
  3. Enter file in which to save the key (/c/Users/swcode/.ssh/id_rsa):
  4. Your identification has been saved in /c/Users/swcode/.ssh/id_rsa.
  5. Your public key has been saved in /c/Users/swcode/.ssh/id_rsa.pub.
  6. The key fingerprint is:
  7. SHA256:ehhIh2XKR9oEEpFiGQo2AarnnpbatNH/wCEFvGqqK8M swcode@DESKTOP-SWCODE
  8. The key's randomart image is:
  9. +---[RSA 2048]----+
  10. |+=B=o.= |
  11. |*ooo.@ |
  12. |+. *.= |
  13. |. ..= |
  14. |. ..o o S |
  15. | oo. o = |
  16. |.o+.. = . |
  17. |+Eo+ . o |
  18. |*== ... |
  19. +----[SHA256]-----+
  20. $ cat /c/Users/swcode/.ssh/id_rsa.pub
  21. ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7L0WG3fq+0X80eBwnj25RiobtFWGzDVG5CThM9qS9EwUuAIQCt41nPTcyJUCUoRbQkORr1wXxQK2TW7Y5QTPsA1GeJczTg6c9j63+7HKoLmQbdMtFxsP8aGb6mgXp8EZVpUvkFFn2iHyBQ6uqsdCB3xVA7Nh5dW//r4c1Syn+S6WMz51Cz3ec3qA3SsqZq22PEBdJTM2ITdw1/kSTsrgIr7vRrmyTrIhI1fu/IVIaL8jO4bAVRZptV2ckuduTEYOChHyazv0RFi6cH1oLcdpKwCs3dhNvHeiE/CFMxGidNnZDdm+oFnZL1AW2d2t4vBDBj1KYYMtoF5pvWiyI2Nhb swcode@DESKTOP-SWCODE

复制公钥的内容到:

  • 初始时:

image.png

  • 没有初始提示时:点击右上角

image.png
再左侧选择SSH keys:(复制公钥内容)
image.png
以ssh的方式克隆,进入到project1,修改index.html的文件。(可以不用密码就可以上传了)

  1. $ git clone git@192.168.26.24:root/project1.git
  2. $ cd project1/
  3. $ ls
  4. $ echo 11111 > index.html
  5. $ git add .
  6. $ git commit -m "xxx"
  7. $ git push

三、安装Jenkins(vms25)

1、下载:https://www.jenkins.io/
image.png
2、上传下载的rpm包(jenkins-2.222.4-1.1.noarch.rpm、jdk-11.0.7_linux-x64_bin.rpm)到vms25
3、安装
[root@vms25 ~]# yum install jenkins-2.222.4-1.1.noarch.rpm -y
启动
[root@vms25 ~]# /etc/init.d/jenkins start
image.png
这时启动失败,因为没安装jdk
4、安装jdk
[root@vms25 ~]# yum install jdk-11.0.7_linux-x64_bin.rpm -y
再次启动jenkins
[root@vms25 ~]# /etc/init.d/jenkins start
image.png
设置开机启动
[root@vms25 ~]# chkconfig jenkins on
查看监听端口:
[root@vms25 ~]# netstat -ntulp |grep 8080
image.png
5、在浏览器打开[http://192.168.26.25:8080/](http://192.168.26.25:8080/)
image.png
解锁 Jenkins:从服务器查看/var/lib/jenkins/secrets/initialAdminPassword
[root@vms25 ~]# cat /var/lib/jenkins/secrets/initialAdminPassword
2c9363e202aa4968a33d7c5778c06476
复制密码后,继续:
image.png
6、安装推荐的插件

点击安装推荐的插件 (将所插件安装,有安装不成功的插件时可能需要多次重试,使之安装成功)

image.png

安装好之后跳转到注册页面:(如果没有跳转,需要刷新页面)

image.png
7、创建第一个管理员用户
image.png
输入如上信息,点击保存并完成,跳转到:
image.png
点击保存并完成
image.png
点击重启。登录(如果没有出现登录页面,可刷新页面)
image.png
输入用户名和密码,点击登录。
image.png
8、安装git、kubectl、docker

  • 安装git

[root@vms25 ~]# yum install git -y

  • 安装kubectl (版本需要与访问的k8s集群)

    从k8s集群获取kubectl版本

[root@vms61 ~]# rpm -qa |grep kubectl
kubectl-1.18.2-0.x86_64

安装kubectl-1.18.2-0.x86_64

[root@vms25 ~]# yum install kubectl -y #默认安装最新版本
[root@vms25 ~]# yum remove kubectl #删除: kubectl.x86_64 0:1.18.3-0
[root@vms25 ~]# yum install kubectl-1.18.2-0.x86_64 -y #安装与k8s版本一致的``kubectl

验证访问:

  1. #在vms61(k8s master)查看是否有访问用户,如果没有就需要添加
  2. [root@vms61 ~]# ls /etc/kubernetes/pki
  3. [root@vms61 ~]# cat /etc/kubernetes/pki/aa.csv
  4. redhat,admin,1
  5. redhat,tom,2
  6. redhat,bob,3
  7. #在vms25(jenkins主机)进行k8s集群访问测试
  8. [root@vms25 ~]# kubectl -s="https://192.168.26.61:6443" --insecure-skip-tls-verify=true --username="admin" --password="redhat" get nodes
  9. NAME STATUS ROLES AGE VERSION
  10. vms61.example.com Ready master 46d v1.18.2
  11. vms62.example.com NotReady worker 46d v1.18.2
  12. vms63.example.com NotReady worker2 46d v1.18.2
  • 安装docker

    参见后文配置docker本地仓库

9、安装docker插件

  • 点击Manage Jenkins

image.png

  • 选择Manage Plugins

image.png

  • 点击可选插件,在右上角过滤栏输入docker回车:

image.png

  • 在搜索出来的所有插件里选择:docker-build-stepDockerDocker API等docker相关插件

image.png

  • 点击直接安装

image.png
等待所有插件安装完成之后,点击返回首页
查看已安装插件:
image.png
10、配置jenkins管理docker

  • 在docker镜像仓库主机(这里是vms25)添加启动配置项tcp://0.0.0.0:2376 (用于jenkins调用docker API)

    在配置文件/etc/sysconfig/dockerOPTIONS后增加-H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock (docker v1.11后以systemd方式管理docker,默认没有创建配置文件,要按照以下方法进行编辑配置)

[root@vms25 ~]# systemctl status docker #获取启动配置文件
/usr/lib/systemd/system/docker.service
image.png

编辑配置文件,在ExecStart=一行中增加-H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock

[root@vms25 ~]# vi /usr/lib/systemd/system/docker.service
image.png
[root@vms25 ~]# systemctl daemon-reload
[root@vms25 ~]# systemctl restart docker

  • 配置jenkins连接docker,点击Manage Jenkins,选择Configure System

image.png
在Docker Builder里输入tcp://192.168.26.32:2376,点击Test Connection
image.png
确保高级下面出现Connected to tcp://192.168.26.25:2376,表示连接成功。
页面拉到最下面:
image.png
点击Cloud-Add a new cloud-docker
image.png
点击Docker Cloud details ,在Docker Host URI里输入tcp://192.168.26.25:2376,点击Test Connection
image.png
下面出现Version = 19.03.11, API Version = 1.40,表示连接成功,点击最下面Save保存。
11、创建任务
点击创建一个新任务
image.png
任务名输入k8sxx,选择 Freestyle project
image.png
点击确定后,页面跳转:
image.png
构建触发器里,选中触发远程构建 (例如,使用脚本),在身份验证令牌里输入一段字符串,这里输入123123,
image.png
记住并替换:
JENKINS_URL/job/k8sxx/build?token=TOKEN_NAME替换为
[http://192.168.26.25:8080/job/k8sxx/build?token=123123](http://192.168.26.25:8080/job/k8sxx/build?token=123123)这个将在gitlab里用到
然后下拉,在构建-增加构建步骤里选择Execute shell:
image.png
Execute shell里输入:

  1. echo $USER
  2. cd /zz
  3. sudo rm -rf *
  4. git clone http://192.168.26.24/root/project1.git
  5. version=$(date +"%Y.%m.%d.%H.%M.%S")
  6. name=192.168.26.25:5000/cka/nginx:$version
  7. docker build -t $name project1
  8. docker push $name
  9. kubectl -s="https://192.168.26.61:6443" --insecure-skip-tls-verify=true --username="admin" --password="redhat" set image deployment/nginx nginx="$name" -n ns5

image.png
点击下方保存按钮。
12、配置gitlab和Jenkins联动

  • 在jenkins上做相关安全设置,点击Manage Jenkins

image.png

  • 授权策略里,勾选匿名用户具有读权限

image.png

  • 跨站点请求伪造保护,jenkins低版本中可以直接在防止跨站点请求伪造前面的勾去掉。

    高版本jenkins不能在页面禁用跨站请求伪造保护。禁用跨站请求伪造保护操作如下:修改jenkins的配置文件。

vim /etc/sysconfig/jenkins

  1. JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true -Dhudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION=true"

image.png

配置后重启jenkins:service jenkins restart/etc/init.d/jenkins restart 访问网页查看,如下图效果:

image.png
13、设置jenkins用户的sudo权限

在系统命令行里,设置jenkins用户的sudo权限,保证其可以无密码执行rm命令:

[root@vms25 ~]# vi /etc/sudoers.d/jenkins

  1. jenkins vms25.example.com=(root) NOPASSWD: /bin/rm

jenkins加入到root组,然后重启jenkins:

[root@vms25 ~]# gpasswd -a jenkins root
正在将用户“jenkins”加入到“root”组中
[root@vms25 ~]# /etc/init.d/jenkins restart
Restarting jenkins (via systemctl): [ 确定 ]

创建jenkins的工作目录/zz,并把所有者所属组设置为jenkins

[root@vms25 ~]# mkdir /zz
[root@vms25 ~]# chown jenkins.jenkins /zz
14、gitlab上相关配置

  • 在gitlab页面最上面,点击扳手图标

image.png

  • 点击左下侧Settings—> Network(点击展开菜单中或在浮动菜单上点击)

image.png

  • 展开Outbound requests,

image.png
勾选Allow requests to the local network from web hooks and services
image.png
点击Save changes
image.png

  • 进入到首页,进入到project1项目页面,

image.png
点击左下角Settings—> Webhooks
image.png
URL填写内容:

  1. http://192.168.26.25:8080/job/k8sxx/build?token=123123

这其中URL的值是前面jenkins创建任务配置构建触发器的时候保留的,往下拉下拉框到 SSL verfication,点击Add webhook,之后结果为:
image.png

至此,gitlab和jenkins的联动配置结束。

四、安装docker并配置本地仓库(vms32 或 vms25)

1、安装docker

  • 配置yum

yum install -y yum-utils #安装yum管理工具
yum-config-manager --add-repo [https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo](https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo)

  • 安装

yum list docker-ce --showduplicates|sort -r #查看版本
yum install docker-ce #安装最新版本
yum install docker -y #安装的是1.13.1版本

启动docker并设置开机自动启动,导入镜像

systemctl start docker
systemctl enable docker

systemctl enable docker --now

  • 配置docker加速器-阿里云加速器

    您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

  1. sudo mkdir -p /etc/docker
  2. sudo tee /etc/docker/daemon.json <<-'EOF'
  3. {
  4. "registry-mirrors": ["https://5gce61mx.mirror.aliyuncs.com"]
  5. }
  6. EOF
  7. sudo systemctl daemon-reload
  8. sudo systemctl restart docker

2、搭建镜像仓库

设置http方式访问仓库(默认是https访问)

[root@vms32 ~]# vi /etc/docker/daemon.json

  1. {
  2. "registry-mirrors": ["https://5gce61mx.mirror.aliyuncs.com"],
  3. "insecure-registries": ["192.168.26.32:5000"]
  4. }

[root@vms32 ~]# systemctl restart docker

下载镜像

[root@vms32 ~]# docker pull hub.c.163.com/library/registry:latest
[root@vms32 ~]# docker pull hub.c.163.com/library/nginx:latest
[root@vms32 ~]# docker images

  1. REPOSITORY TAG IMAGE ID CREATED SIZE
  2. hub.c.163.com/library/registry latest 751f286bc25e 2 years ago 33.2MB
  3. hub.c.163.com/library/nginx latest 46102226f2fd 3 years ago 109MB

创建容器作为docker镜像仓库

[root@vms32 ~]# docker run -d --name registry -p 5000:5000 --restart=always -v /myreg:/var/lib/registry hub.c.163.com/library/registry
[root@vms32 ~]# docker`` ps
image.png
3、在其他docker节点(vms25、vms61、vms62、vms63)设置http访问
vi /etc/docker/daemon.json

  1. {
  2. "registry-mirrors": ["https://5gce61mx.mirror.aliyuncs.com"],
  3. "insecure-registries": ["192.168.26.32:5000"]
  4. }

systemctl restart docker
如果把vms32(docker镜像仓库)合到vms25上,则上面配置中的IP改为192.168.26.25:5000

五、实战演练

在k8s集群创建deployment、svc

[root@vms61 5-deployment]# kubectl create ns ns5
[root@vms61 5-deployment]# kubens ns5
[root@vms61 5-deployment]# vi dep.yaml

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. labels:
  5. app: nginx
  6. name: nginx
  7. spec:
  8. replicas: 1
  9. selector:
  10. matchLabels:
  11. pod-name: nginx
  12. strategy: {}
  13. template:
  14. metadata:
  15. labels:
  16. pod-name: nginx
  17. name: nginx
  18. app: nginx
  19. spec:
  20. containers:
  21. - image: nginx:1.7.9
  22. imagePullPolicy: IfNotPresent
  23. name: nginx
  1. [root@vms61 5-deployment]# kubectl apply -f dep.yaml
  2. [root@vms61 5-deployment]# kubectl get deployments.apps -o wide
  3. NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
  4. nginx 1/1 1 1 8s nginx nginx:1.7.9 pod-name=nginx
  5. [root@vms61 5-deployment]# kubectl expose deployment nginx --name=nginx --port=80 --type=NodePort
  6. service/nginx exposed
  7. [root@vms61 5-deployment]# kubectl get svc
  8. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  9. nginx NodePort 10.96.149.129 <none> 80:30007/TCP 15s

在浏览器访问:http://192.168.26.61:30007

image.png

在client的机器上,clone下来的project1目录里,创建Dockerfile文件,内容如下:

$ git clone git@192.168.26.24:root/project1.git
$ cd project1/
$ vi Dockerfile

  1. FROM docker.io/nginx
  2. MAINTAINER testCICD
  3. ADD index.html /usr/share/nginx/html/
  4. EXPOSE 80
  5. CMD ["nginx", "-g","daemon off;"]

$ echo "welcome to CICD! 33333" >index.html
$ git commit -m "33333"
$ git push

切换到jenkins,可以看到已经触发了编译

点击控制台输出
image.png
可以看到整个编译过程:

  1. Started by remote host 192.168.26.24
  2. Running as SYSTEM
  3. Building in workspace /var/lib/jenkins/workspace/k8sxx
  4. [k8sxx] $ /bin/sh -xe /tmp/jenkins544872612701596181.sh
  5. + echo jenkins
  6. jenkins
  7. + cd /zz
  8. + sudo rm -rf project1
  9. + git clone http://192.168.26.24/root/project1.git
  10. 正克隆到 'project1'...
  11. ++ date +%Y.%m.%d.%H.%M.%S
  12. + version=2020.06.20.14.54.47
  13. + name=192.168.26.25:5000/cka/nginx:2020.06.20.14.54.47
  14. + docker build -t 192.168.26.25:5000/cka/nginx:2020.06.20.14.54.47 project1
  15. Sending build context to Docker daemon 73.73 kB
  16. Step 1/5 : FROM docker.io/nginx
  17. ---> 2622e6cca7eb
  18. Step 2/5 : MAINTAINER testCICD
  19. ---> Using cache
  20. ---> 2f3e9064a62f
  21. Step 3/5 : ADD index.html /usr/share/nginx/html/
  22. ---> 27d0e7be4d69
  23. Removing intermediate container 93770fa4604e
  24. Step 4/5 : EXPOSE 80
  25. ---> Running in b4dd5a9ef2e3
  26. ---> 0d5e799aa973
  27. Removing intermediate container b4dd5a9ef2e3
  28. Step 5/5 : CMD nginx -g daemon off;
  29. ---> Running in 880adccc18e7
  30. ---> 696851424492
  31. Removing intermediate container 880adccc18e7
  32. Successfully built 696851424492
  33. + docker push 192.168.26.25:5000/cka/nginx:2020.06.20.14.54.47
  34. The push refers to a repository [192.168.26.25:5000/cka/nginx]
  35. 5c7aec829481: Preparing
  36. f978b9ed3f26: Preparing
  37. 9040af41bb66: Preparing
  38. 7c7d7f446182: Preparing
  39. d4cf327d8ef5: Preparing
  40. 13cb14c2acd3: Preparing
  41. 13cb14c2acd3: Waiting
  42. 9040af41bb66: Layer already exists
  43. 13cb14c2acd3: Layer already exists
  44. d4cf327d8ef5: Layer already exists
  45. f978b9ed3f26: Layer already exists
  46. 7c7d7f446182: Layer already exists
  47. 5c7aec829481: Pushed
  48. 2020.06.20.14.54.47: digest: sha256:4938108afb0fe18637319ce9f10c927371db37e54e642793162baf54344395db size: 1569
  49. + kubectl -s=https://192.168.26.61:6443 --insecure-skip-tls-verify=true --username=admin --password=redhat set image deployment/nginx nginx=192.168.26.25:5000/cka/nginx:2020.06.20.14.54.47 -n ns5
  50. deployment.apps/nginx image updated
  51. Finished: SUCCESS

在浏览器访问:http://192.168.26.61:30007/ 查看到信息已经修改了。

出现如下错误的处理:
image.png
docker进程使用Unix Socket而不是TCP端口。而默认情况下,Unix socket属于root用户,因此需要root权限才能访问。
sudo groupadd docker #添加docker用户组
sudo gpasswd -a jenkins docker #将用户jenkins添加至docker用户组
newgrp docker #更新docker用户组

  • 权限问题

[root@vms25 ~]# cat /etc/group |grep docker #查看docker用户组与用户
/etc/group 的内容包括用户组(Group)、用户组口令、GID及该用户组所包含的用户(User),每个用户组一条记录;格式如下
group_name:passwd:GID:user_list
在/etc/group 中的每条记录分四个字段:

  • 第一字段:用户组名称;
  • 第二字段:用户组密码;
  • 第三字段:GID
  • 第四字段:用户列表,每个用户之间用,号分割;本字段可以为空;如果字段为空表示用户组为GID的用户名;

把jenkins用户加入到dockerroot用户组
[root@vms25 ~]# gpasswd -a jenkins dockerroot #将登陆用户jenkins加入到docker用户组中
[root@vms25 ~]# newgrp dockerroot #更新用户组
重启jenkins
[root@vms25 ~]# /etc/init.d/jenkins restart

  • 普通用户使用docker的方法:添加用户组,将用户添加到组,重启docker即可
    1. # groupadd docker
    2. # groups
    3. root
    4. # usermod -a -G docker jenkins
    5. # grep docker /etc/group
    6. dockerroot:x:994:
    7. docker:x:1001:jenkins
    8. [root@localhost ~]# service docker restart
    9. Redirecting to /bin/systemctl restart docker.service
    10. [root@localhost ~]# sudo jenkins
    11. [jenkins @localhost ~]$ docker image ls

至此,完美成功完成一个基本的CICD环境部署。