这个环境是生产环境中的真实项目,仅做参考 通过Docker+k8s来部署web集群,GitLab+Jenkins实现代码自动化部署,在Jenkins中通过构建脚本,实现k8s对容器web集群代码自动更新

运行环境

ip 服务 备注
192.168.1.1 GitLab 内存4G,双核CPU(CentOS7.5)
192.168.1.4 Jenkins 内核4G,双核CPU(CentOS7.5)
192.168.1.11 Docker+k8s-master 内核4G,双核CPU(CentOS7.7)
192.168.1.12 Docker+k8s-node1 内核4G,双核CPU(CentOS7.7)
192.168.1.13 Docker+k8s-node2 内核4G,双核CPU(CentOS7.7)

部署目的

在开发进行代码的更新后,上传到GitLab,Jenkins根据webhook发现代码的更新后,进行代码构建和k8s中的自动部署,展现到web界面中

搭建GitLab

参考本站文档Git搭建GitLab搭建

除了程序是通过yum安装的没有什么不同

192.168.1.1

[root@localhost ~]# hostname gitlab
[root@localhost ~]# bash
[root@gitlab ~]# vim /etc/hosts
192.168.1.1 gitlab
192.168.1.4 jenkins

开启路由转发

[root@localhost ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf 
[root@localhost ~]# sysctl -p
net.ipv4.ip_forward = 1

安装Git

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

配置GitLab的repo源

使用清华大学的repo源

[root@localhost ~]# vim /etc/yum.repos.d/gitlab-ce.repo
[gitlab-ce]
name=Gitlab CE Repository
baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/
gpgcheck=0
enabled=1

安装GitLab

建议使用指定版本的gitlab

wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-12.3.0-ce.0.el7.x86_64.rpm
rpm -ivh gitlab-ce-12.3.0-ce.0.el7.x86_64.rpm

使用yum安装的最新版本发现对密钥问题还有点不稳定(不建议)

[root@localhost ~]# yum -y install gitlab-ce

生产环境中需要修改访问GitLab的域名或者ip

[root@localhost ~]# vim /etc/gitlab/gitlab.rb
# 将external_url 'http://gitlab.example.com'
# 修改为external_url 'http://192.168.1.1',本机域名或者ip

初始化GitLab

[root@localhost ~]# gitlab-ctl reconfigure   # 第一次需要很长时间

启动GitLab

[root@localhost ~]# gitlab-ctl start

放行端口

[root@localhost ~]# firewall-cmd --add-port=80/tcp
success

登陆到Web管理界面设置的登录密码

http://192.168.1.1

GitLab

默认用户为root

GitLab

登录成功

搭建Jenkins

参考本站文档Jenkins搭建

除了程序是通过yum安装的没有什么不同

192.168.1.4

[root@localhost ~]# hostname jenkins
[root@localhost ~]# bash
[root@jenkins ~]# vim /etc/hosts
192.168.1.1 gitlab
192.168.1.4 jenkins
192.168.1.11 k8s-master
192.168.1.12 k8s-node1
192.168.1.13 k8s-node2

准备Java环境

使用1.8的Java环境

[root@localhost ~]# yum -y install java-1.8.0-openjdk*

编写Jenkins的repo源

[root@localhost ~]# vim /etc/yum.repos.d/jenkins.repo
[jenkins]
name=Jenkins-stable
baseurl=https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat-stable/
gpgcheck=1
# 导入rpm密钥
[root@localhost ~]# rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

安装Jenkins

[root@localhost ~]# yum -y install jenkins git
# 下载,下载过程贼慢

启动Jenkins,并放行8080端口

[root@localhost ~]# systemctl start jenkins
[root@localhost ~]# systemctl enable jenkins
[root@localhost ~]# firewall-cmd --add-port=8080/tcp
success

进入Jenkins的web安装界

访问http://192.168.1.4:8080

Jenkins

在Linux本地查看管理员密码

Jenkins

输入密码后,如果出现此界面

Jenkins

如果出现以下

Jenkins

解决方法如下:

第一步 打开插件管理的高级设置页面
http://192.168.1.4:8080/pluginManager/advanced

第二步 修改更新站点地址
将https改为http  如果不行 可以用清华的加速站点 如下
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

安装推荐插件

Jenkins

Jenkins

安装加速神奇,Jenkins默认使用google来搜索插件的下载,而且插件也在国外网站,这里将updates目录中的default.json内的url换为百度(搜索引擎)和清华(下载插件地址),前提必须出现过以上界面才会有updates目录

cd /var/lib/jenkins/updates/
sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' default.json
sed -i 's/http:\/\/updates.jenkins-ci.org\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' default.json

然后重启服务,并重新访问Jenkins的web界面

systemctl restart jenkins

安装完成后,创建管理用户

Jenkins

Jenkins

Jenkins

在插件管理中安装三个关于GitLab的插件,用于持续集成

Gitlab Authentication

Gitlab

Gitlab Hook

选择安装后自动重启Jenkins

搭建Kubernetes集群

参考本站文档Docker安装Kubernetes集群搭建

环境准备

按照运行环境中的系统版本和硬件要求

这里使用的现成的Docker环境,没有的可以参考以上链接部署

更改主机名

192.168.1.11

更改主机名,并设置对其他两台节点的免密登录

[root@localhost ~]# hostname k8s-master
[root@localhost ~]# bash
[root@k8s-master ~]# vim /etc/hosts
192.168.1.11 k8s-master
192.168.1.12 k8s-node1
192.168.1.13 k8s-node2
[root@k8s-master ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:y0cMv9gJDShPYbfH/+WUbwtLJivwGTNv4EVT6TpxXHQ root@k8s-master
The key's randomart image is:
+---[RSA 2048]----+
|      o .     o.E|
|     . + o   o ..|
|    . o + o + .  |
|     +   B = +  .|
|      . S * *  .o|
|       o @ * . +.|
|        B &..+. +|
|         * o= o..|
|          o. . . |
+----[SHA256]-----+
[root@k8s-master ~]# ssh-copy-id -i root@k8s-node1
[root@k8s-master ~]# ssh-copy-id -i root@k8s-node2

将hosts文件传输到其他两台节点

[root@k8s-master ~]# scp /etc/hosts root@k8s-node1:/etc
[root@k8s-master ~]# scp /etc/hosts root@k8s-node2:/etc

192.168.1.12

[root@localhost ~]# hostname k8s-node1
[root@localhost ~]# bash
[root@k8s-node1 ~]# 

192.168.1.13

[root@localhost ~]# hostname k8s-node2
[root@localhost ~]# bash
[root@k8s-node2 ~]# 

关闭沙盒/防火墙

k8s-master/node1/node2

setenforce 0
vim /etc/selinux/config 
# 修改
SELINUX=disabled
# 防火墙放行端口,因为比较多,省事可以直接systemctl stop firewalld
firewall-cmd --add-port=6443/tcp
firewall-cmd --add-port=64430/tcp
firewall-cmd --add-port=64431/tcp
firewall-cmd --add-port=64432/tcp
firewall-cmd --add-port=64433/tcp
firewall-cmd --add-port=64434/tcp
firewall-cmd --add-port=64435/tcp
firewall-cmd --add-port=64436/tcp
firewall-cmd --add-port=64437/tcp
firewall-cmd --add-port=64438/tcp
firewall-cmd --add-port=64439/tcp
firewall-cmd --add-port=2379/tcp
firewall-cmd --add-port=2380/tcp
firewall-cmd --add-port=10250/tcp
firewall-cmd --add-port=10251/tcp
firewall-cmd --add-port=10252/tcp

验证节点UUID

k8s-master

[root@k8s-master ~]# cat /sys/class/dmi/id/product_uuid 
E2B74D56-23A9-4E8B-620C-555387355616

k8s-node1

[root@k8s-node1 ~]# cat /sys/class/dmi/id/product_uuid 
371E4D56-E8D8-294C-DA42-D06C62FD9B62

k8s-node2

[root@k8s-node2 ~]# cat /sys/class/dmi/id/product_uuid 
96E94D56-D4D8-18DC-FDAE-89060C320C7A

设置内核参数

调整iptables桥接流量,依赖于docker的启动,所以需要确保docker已经启动

k8s-master

[root@k8s-master ~]# vim /etc/sysctl.conf
# 末尾添加
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
[root@k8s-master ~]# sysctl -p
# 为确保桥接流量不报错,执行以下命令
[root@k8s-master ~]# modprobe ip_vs_rr
[root@k8s-master ~]# modprobe br_netfilter
# 将修改好的文件传输到node1和node2
[root@k8s-master ~]# scp /etc/sysctl.conf root@k8s-node1:/etc
[root@k8s-master ~]# scp /etc/sysctl.conf root@k8s-node2:/etc

k8s-node1

[root@k8s-node1 ~]# sysctl -p
[root@k8s-node1 ~]# modprobe ip_vs_rr
[root@k8s-node1 ~]# modprobe br_netfilter

k8s-node2

[root@k8s-node2 ~]# sysctl -p
[root@k8s-node2 ~]# modprobe ip_vs_rr
[root@k8s-node2 ~]# modprobe br_netfilter

关闭swap分区

三台节点同样的操作

swapoff -a
vim /etc/fstab 
# 将分区类型为swap的一行注释掉
/dev/mapper/centos-swap swap
# 还是需要调整内核参数
vim /etc/sysctl.conf
# 末尾添加
vm.swappiness = 0
sysctl -p

安装Kubernetes

编写yum源

k8s-master

[root@k8s-master ~]# vim /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg

将yum源传给每台节点

[root@k8s-master ~]# scp /etc/yum.repos.d/kubernetes.repo root@k8s-node1:/etc/yum.repos.d/
[root@k8s-master ~]# scp /etc/yum.repos.d/kubernetes.repo root@k8s-node2:/etc/yum.repos.d/

安装k8s

k8s-master/node1/node2

yum -y install kubelet kubeadm kubectl

如果有的节点在yum安装时,报错404,尝试执行rm -rf /var/cache/yum/*后,重新安装

查看k8s版本

$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.2", 
GitCommit:"52c56ce7a8272c798dbc29846288d7cd9fbae032", GitTreeState:"clean", 
BuildDate:"2020-04-16T11:54:15Z", GoVersion:"go1.13.9", Compiler:"gc", 
Platform:"linux/amd64"}

k8s-master

安装kubernetes的tab快捷键,只需要在master安装即可

[root@k8s-master ~]# yum -y install bash-completion
[root@k8s-master ~]# source <(kubectl completion bash)
[root@k8s-master ~]# source <(kubeadm completion bash)
[root@k8s-master ~]# vim .bashrc
# 末尾添加
source <(kubeadm completion bash)
source <(kubectl completion bash)

启动k8s

k8s-master/node1/node2

systemctl enable kubelet.service && systemctl start kubelet.service

Kubernetes集群搭建

k8s-master

初始化集群获取token值

[root@k8s-master ~]# kubeadm init --apiserver-advertise-address 192.168.1.11 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.18.2 --pod-network-cidr=10.244.0.0/16

使用管理用户(非root)执行以下操作

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

使用root用户执行以下操作

[root@k8s-master ~]# export KUBECONFIG=/etc/kubernetes/admin.conf
[root@k8s-master ~]# vim .bashrc
# 末尾添加
export KUBECONFIG=/etc/kubernetes/admin.conf

部署集群网络

下载flannel网络镜像

[root@k8s-master ~]# docker pull quay.io/coreos/flannel:v0.12.0-amd64
[root@k8s-master ~]# docker pull quay.io/coreos/flannel:v0.12.0-arm64

复制该路径中的kube-flannel.yml的所有内容到k8s-master中的文件,然后执行以下操作

[root@k8s-master ~]# kubectl apply -f kube-flannel.yml

节点加入集群

如果之前生成的token值忘了,查看kubeadm token list,还能往上翻看到token值就跳过这步

k8s-master

[root@k8s-master ~]# kubeadm token list
TOKEN                     TTL         EXPIRES                     USAGES                   
jppmrh.1hovp0cyt4xu2w1l   23h         2020-05-11T02:05:53+08:00   authentication,signing   
# 将它删除重新生成
[root@k8s-master ~]# kubeadm token delete jppmrh.1hovp0cyt4xu2w1l

生成

kubeadm token create --print-join-command

k8s-node1/node2

kubeadm join 192.168.1.11:6443 --token bdsiop.8ptt7ky6t088xyl8 \
    --discovery-token-ca-cert-hash sha256:1b61fd611bd12f46c7c065995f304ad232f2a598cb99127ccc547612ea57eac0

输出信息为以下则成功

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

验证集群节点

k8s-master

等待一段时间,直至状态全部为Ready

[root@k8s-master ~]# kubectl get nodes
NAME         STATUS   ROLES    AGE     VERSION
k8s-master   Ready    master   10m     v1.18.2
k8s-node1    Ready    <none>   3m56s   v1.18.2
k8s-node2    Ready    <none>   3m56s   v1.18.2

集群搭建成功

运行Docker私库—Registry

为了在环境中更好的管理Docker镜像,决定使用Registry来运行一个容器,用来存放docker镜像,也减少了镜像存储在国外源或者国内源的传输效率,当然也能使用harbor私库代替Registry

k8s-master

下载镜像

[root@k8s-master ~]# docker pull registry:2

创建镜像存放目录

[root@k8s-master ~]# mkdir /data/docker/registry -p

运行私库容器

[root@k8s-master ~]# docker run -itd -p 5000:5000 --restart always \
--volume /data/docker/registry/:/var/lib/registry registry:2

查看端口是否映射成功

[root@k8s-master ~]# netstat -anput | grep 5000

检查能否访问到私库

[root@k8s-master ~]# firewall-cmd --add-port=5000/tcp
[root@k8s-master ~]# curl 192.168.1.11:5000/v2/_catalog
{"repositories":[]}

设置三台docker都能识别私库地址

[root@k8s-master ~]# vim /usr/lib/systemd/system/docker.service 
# 14行的末尾添加--insecure-registry 192.168.1.11:5000
# 14行也就是以ExecStart开头的一行
[root@k8s-master ~]# scp /usr/lib/systemd/system/docker.service root@k8s-node1:/usr/lib/systemd/system/
[root@k8s-master ~]# scp /usr/lib/systemd/system/docker.service root@k8s-node2:/usr/lib/systemd/system/

全部重启docker

systemctl daemon-reload 
systemctl restart docker

制作一个镜像上传到私库测试

[root@k8s-master ~]# wget http://nginx.org/download/nginx-1.11.1.tar.gz
[root@k8s-master ~]# vim Dockerfile
FROM centos  
MAINTAINER FeiYi  
RUN yum -y install net-tools iproute pcre-devel openssl-devel gcc gcc-c++ make zlib-devel elinks
ADD nginx-1.11.1.tar.gz /usr/src  
ENV NGINX_DIR /usr/src/nginx-1.11.1 
WORKDIR $NGINX_DIR  
RUN ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx && make && make install
WORKDIR /
RUN useradd nginx
RUN ln -s /usr/local/nginx/sbin/nginx /usr/sbin/nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

构建镜像

[root@k8s-master ~]# docker build -t 192.168.1.11:5000/bin-nginx:latest /root

上传镜像

[root@k8s-master ~]# docker push 192.168.1.11:5000/bin-nginx
[root@k8s-master ~]# curl 192.168.1.11:5000/v2/_catalog
{"repositories":["bin-nginx"]}

私库成功

使用k8s启动nginx容器

k8s-master

编写Deployment的模板文件

[root@node1 ~]# vim nginx-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: 192.168.1.11:5000/bin-nginx
        ports:
        - containerPort: 80

运行模板文件

[root@node1 ~]# kubectl apply -f nginx-deployment.yml 
deployment.apps/nginx created

查看是否运行成功

[root@node1 ~]# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE    IP           NODE
nginx-66fb94d868-h2fkk   1/1     Running   0          2m5s   10.244.2.2   node2
nginx-66fb94d868-zhkf8   1/1     Running   0          2m5s   10.244.1.2   node3

可以看到容器的ip,现在只能在运行容器的节点才能够访问到页面内容,如果想让外部主机访问到,需要做一个service模板,用来映射端口

编写Service模板

将集群中标签为app: nginx的容器的80端口映射为服务器的30001

[root@node1 ~]# vim nginx-service.yml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30001
  selector:
    app: nginx

运行Service模板

[root@node1 ~]# kubectl apply -f nginx-service.yml 
service/nginx created

访问宿主机的30001端口

http://192.168.1.12:30001http://192.168.1.13:30001

k8s_nginx

容器部署成功

整合GitLab和Jenkins

Jenkins

在Jenkins生成密钥对

[root@jenkins ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:IITvkptc3nJrgxCxA0R0+ExWm5y/PfSIdKaQpD0NhUc root@jenkins
The key's randomart image is:
+---[RSA 2048]----+
|++.oo.oE         |
|..++..=.         |
| .=+.Bo          |
|  +o=.=.         |
|   * = +S+       |
|  + o + O o      |
| . B o + + .     |
|  + + =   .      |
|     +.o         |
+----[SHA256]-----+

GitLab

登录GitLab

http://192.168.1.1

创建项目仓库

gitlab

k8s_gitlab

在GitLab中添加Jenkins的公钥值

gitlab

复制Jenkins服务器的公钥到下图位置,查看公钥cat .ssh/id_rsa.pub

k8s_gitlab1

在GitLab的项目仓库,创建一个测试代码文件

k8s_gitlab2

k8s_gitlab3

因为密钥上传的是Jenkins的,所以在Jenkins上下载查看

[root@gitlab ~]# git clone http://192.168.1.1/root/nginx-test.git
[root@gitlab ~]# cd nginx-test/
[root@gitlab nginx-test]# cat index.html 
ChaiYanjiang

成功

Jenkins

http://192.168.1.4:8080/

创建任务nginx-test

k8s_jenkins

设置源码管理时在Gitlab的地址,出现红色说明连接不到,因为GitLab已经有了Jenkins的公钥,这里只需要填写Jenkins的私钥即可

k8s_jenkins2

Jenkins

红色报错消失了

Jenkins

设置构建触发器

当gitlab发生代码变化时,开始进行构建任务

k8s_jenkins3

生成一串token值,用来对GitLab中的项目代码进行操作,所以这个值要放到GitLab中,用于验证允许Jenkins来拿取代码,稍后会将

k8s_build

设置构建的命令(CI/CD)

k8s_build

#!/bin/bash
backupcode=/data/backupcode/$JOB_NAME/
mkdir -p $backupcode
chmod 644 $JENKINS_HOME/workspace/$JOB_NAME/*
rsync -acP $JENKINS_HOME/workspace/$JOB_NAME/* $backupcode
echo From 192.168.1.11:5000/bin-nginx > $JENKINS_HOME/workspace/Dockerfile
echo COPY ./nginx-test/* /usr/local/nginx/html/ >> $JENKINS_HOME/workspace/Dockerfile
docker rmi 192.168.1.11:5000/bin-nginx:latest
docker build -t 192.168.1.11:5000/bin-nginx:latest $JENKINS_HOME/workspace/
docker push 192.168.1.11:5000/bin-nginx:latest
ssh root@k8s-master kubectl delete deployment nginx
ssh root@k8s-master kubectl apply -f nginx-deployment.yml

保存即可

GitLab

192.168.1.1中设置Jenkins中的token值,用来触发Jenkins构建

GitLab默认情况下不允许通过本地网络触发构建,以下这步是为了设置允许本地网络构建,如果不设置允许会在添加token时报错

GitLab

GitLab

GitLab

保存

设置允许之后,就可以设置GitLab项目与Jenkins的构建触发器连接了

进入项目中选择设置

gitlab

图中的URL是在Jenkins中的项目路径,这个路径在构建触发器的那里可以看到,复制即可,token则是刚才在Jenkins的管理界面中生成的token值,也是同样的位置,然后点击下方add webhook

gitlab_token

add成功后,往下翻到如图所示位置可以看添加成功的URL,然后进行连接测试,出现200即成功

gitlab_webhooktest

整合Jenkins和Docker

Jenkins

在Jenkins中做对k8s-master的免密登录,得先修改Jenkins的运行用户,这里我直接用root代替,生产环境请参考这里的scp报错部分

vim /etc/sysconfig/jenkins
 修改jenkins用户
JENKINS_USER="jenkins"   # 修改为root

重启Jenkins并传输密钥

[root@jenkins ~]# systemctl restart jenkins
[root@jenkins ~]# ssh-copy-id -i root@k8s-master

安装Docker,参考文档Docker安装,并设置镜像加速,和指定私库地址

测试

修改GitLab的测试文件测试Jenkins的自动化部署是否成功

gitlab_test

保存后会开始自动构建部署,访问192.168.1.13:30001,如果是以下则成功,如果构建失败,则检查构建脚本,慢慢排错

k8s_cicd

评论




正在载入...
PoweredHexo
HostedAliyun
DNSAliyun
ThemeVolantis
UV
PV
BY-NC-SA 4.0