本文转自:https://gitee.com/linlion/gitlab-docker-k8s
此文档主要说明怎样基于GitLab进行持续集成和持续交付,该持续集成与交付集成了gitlab-runner 、mvnw、Docker、harbor、k8s等技术,同时展示了在k8s平台利用EFK(elasticsearch,fluentd,kibana)技术完成了集群统一日志管理,使用kube-prometheus技术进行集群实时监控以及kube-dashboard管理集群中的应用部署,为了不引入网络问题,本环境的相关VPC机器已经关闭了本机防火墙。
k8s的架构原理图:
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
# Step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新并安装 Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4:添加当前用户到docker组中允许普通用户运行docker命令,此步需要登出linux环境重新再登录方能生效
sudo usermod -aG docker $USER
# Step 5:添加开机启动
sudo systemctl enable docker.service
# Step 6:启动docker
sudo systemctl start docker.service
# Step 7:查看docker版本
docker version
# Step 8:验证docker环境是否能运行镜像
docker run hello-world
#运行效果如下所示:
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/engine/userguide/
docker 参考文档
GitLab类似于Github,可以像Github一样本地托管代码管理团队
sudo docker run --detach \
--hostname gitlab.example.com \
--publish 443:443 --publish 80:80 --publish 22:22 \ #此处可以不配置22端口如果sshd已经占用该端口
--name gitlab \
--restart always \
--volume /srv/gitlab/config:/etc/gitlab \
--volume /srv/gitlab/logs:/var/log/gitlab \
--volume /srv/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest
#如果操作系统使用SELinux使用如下命令:
sudo docker run --detach \
--hostname gitlab.example.com \
--publish 443:443 --publish 80:80 --publish 22:22 \
--name gitlab \
--restart always \
--volume /srv/gitlab/config:/etc/gitlab:Z \
--volume /srv/gitlab/logs:/var/log/gitlab:Z \
--volume /srv/gitlab/data:/var/opt/gitlab:Z \
gitlab/gitlab-ce:latest
如果由于磁盘空间不足需要增加硬盘空间,或备份托管源代码,可以采用如下命令:
#进入gitlab容器
sudo docker exec -it gitlab /bin/bash
#进入container之后停止gitlab服务
gitlab-ctl stop
#退出container之后
sudo docker stop gitlab
gitlab-runner是gitlab的运行器,它可以根据CI/CD 配置文件.gitlab-ci.yml运行编译打包等持续集成的相关任务。
#添加gitlab-runner库
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash
# For RHEL/CentOS/Fedora
sudo yum install gitlab-runner
gitlab-runner register \
--non-interactive \
--url "http://10.30.13.2/" \ #该参数为gitlab服务器的位置
--registration-token "F-CKeY1gKWRPxN5XL77N" \ #该以管理员身份从gitlab获取的registration token
--executor "shell" \ #以shell方式执行任务,支持docker,docker machine,ssh 等等各种执行方式
--docker-image alpine:3.7 \ #默认的任务镜像
--description "gitlab-runner" \ #描述
--tag-list "share-runner-tag" \ #标记在.gitlab-ci.yml会用到
--run-untagged \ #可以运行在非tag代码上
--locked="false" \ #是否锁定该执行器
gitlab-runner可以将VPC或本地机器变成执行器,gitlab-runner每隔3秒从gitlab拉取执行信息,根据相关指令执行相关任务。且gitlab-runner注册命令的相关配置保存在/etc/gitlab-runner/config.toml文件中,如需修改相关相关
参考网址
harbor为VMware开发的docker私有镜像库,具有镜像管理,人员管理以及权限管理等功能。去该github地址下载相关安装包:https://github.com/vmware/harbor/blob/master/docs/installation_guide.md,harbor支持离线安装和在线安装,由于离线包较大下载速度较慢,本环境使用了在线安装。
## Configuration file of Harbor
#This attribute is for migrator to detect the version of the .cfg file, DO NOT MODIFY!
_version = 1.5.0
#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 = 10.30.13.1
2.管理页面
sudo docker-compose start
1. 修改 docker-compose.yml
proxy:
image: library/nginx:1.11.5
restart: always
volumes:
- ./config/nginx:/etc/nginx
ports:
- 8888:80 #8888为最终要修改的端口,修改该位置即可
- 443:443
depends_on:
- mysql
- registry
- ui
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://127.0.0.1:1514"
tag: "proxy"
2. 修改 harbor.cfg
hostname = 192.168.0.2:8888
注意:因为本环境仅做为内网开发使用,目前没有添加Notary 和Clair 功能,Notary和Clair分别提供镜像签名和扫描镜像相关漏洞使用,如需要做成公网镜像可以进行相关配置。
Glusterfs为readhat公司开发的开源分布式文件系统,支持9种不懂的分布式文件部署需求,满足集群中分布式文件的高性能、高可用和简单扩容能力,硬盘扩容仅需采用LVM技术在机器中加入新硬盘或新分区即可轻松扩容空间,Glusterfs默认采用XFS文件系统,这也是Centos7默认的文件系统格式,最大可支持的文件大 小为9 exabytes(即9x1024x1024T),最大文件系统尺寸为18 exabytes(即18x1024x1024T),所以Glusterfs可以为k8集群提供充裕的磁盘空间。
本环境因为资源所限,紧使用了两台VPC模拟了Replicated Glusterfs Volume 部署方式,原理图如下所示:
为了防止脑裂问题,建议采用3台VPC。安装部署如下:
#分别为两个VPC设置hostname,分别为server1,和server2
#第一台VPC执行
sudo hostnamectl set-hostname server1
#第二台VPC执行
sudo hostnamectl set-hostname server2
#分别在两台机器上执行如下命令
#安装依赖包
sudo yum install centos-release-gluster
#为vps添加硬盘(官方建议在新硬盘和分区上使用GFS,但也可以在根分区下使用),并格式化
sudo mkfs.xfs -i size=512 /dev/sdb1
#创建挂载目录
sudo mkdir -p /bricks/brick1
sudo vi /etc/fstab
#为fstab文件自动挂载记录:
/dev/sdb1 /bricks/brick1 xfs defaults 1 2
#保存文件执行如下命令
sudo mount -a && mount
#安装集群
sudo yum install glusterfs-server
#允许gfs开机启动
sudo systemctl enable glusterd
#启动gfs服务
sudo systemctl enable glusterd
#检查gfs运行状态
sudo systemctl status glusterd
#创建trusted pool
#在server1执行如下命令
sudo gluster peer probe server2
#在server2执行如下命令
sudo gluster peer probe server1
#在所有机器上分别执行如下命令
sudo mkdir -p /bricks/brick1/gv0
sudo gluster volume create gv0 replica 2 server1:/bricks/brick1/gv0 server2:/bricks/brick1/gv0 force
sudo gluster volume start gv0
#启动卷
sudo gluster volume start gv0
#查看卷状态信息
sudo gluster volume info
#查看卷的详细信息
sudo gluster volume status gv0 detail
#安装相关依赖包
sudo yum install -y centos-release-gluster
sudo yum install -y glusterfs-server
sudo yum install -y glusterfs
#挂载卷
mount -t glusterfs server1:/gv0 /mnt
#测试卷
for i in `seq -w 1 100`; do cp -rp /var/log/messages /mnt/copy-test-$i; done
#执行如下命令查看文件是否生成
ls -lA /mnt | wc -l
#使用fstab开机自动挂载卷
vi /etc/fstab
server1:/test-volume /mnt/glusterfs glusterfs defaults,_netdev 0 0
NFS可以将一台VPC变成文件存储环境,但是因为不易于扩展原因,单靠NFS在高负载高性能的要求下不适合分布式集群使用,但依然有其使用场景,如:用其作为日志或临时统计分析存储方案或者对单点要求不太重要的存储场合,目前k8s支持挂载NFS文件系统
Kubernetes是Google开源的Docker容器集群管理系统,为容器化的应用提供资源调度、部署运行、服务发现、扩容缩容等整一套功能 ,本环境采用了四台VPC完成了集群环境的搭建,其中一台master节点,三台node节点。
#各个VPC需要安装Docker,请参考Docker的安装策略
#为各VPC添加hostname,本环境分别为master,node1,node2,node3
#在各VPC机器下执行如下命令
#使用阿里源镜像安装k8s
#安装yum源库
cat <<EOF > /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
EOF
#关闭SELinux
sudo setenforce 0
#修改/etc/selinux/config
SELINUX=disabled
#安装依赖库
sudo yum install -y kubelet kubeadm kubectl git conntrack
sudo systemctl enable kubelet
#允许ip转发
sudo sysctl net.bridge.bridge-nf-call-iptables=1
#修改/etc/sysctl.conf:
net.ipv4.ip_forward = 1
#开启
sudo cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
#查看转发设置是否成功
sudo sysctl --system
#查看cgroup驱动是否一致
docker info | grep -i cgroup
sudo cat /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
#如果不一致,修改如下文件
sed -i "s/cgroup-driver=systemd/cgroup-driver=cgroupfs/g" /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
#如修改了10-kubeadm.conf需要执行如下命令使其生效
sudo systemctl daemon-reload
sudo systemctl restart kubelet
sudo systemctl stop kubelet
##关闭交换分区
swapoff -a
#注释 /etc/fstab 有swap分区的一行
sudo kubeadm init --apiserver-advertise-address=10.30.5.1 --kubernetes-version=1.11.0 --pod-network-cidr=10.244.0.0/16 --token-ttl=0
master主机启动后会有如下输出:
Your Kubernetes master has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join 10.30.5.1:6443 --token uzsv39.e2d48u4i1wgfw532 --discovery-token-ca-cert-hash sha256:73b8ef1a9ed85b489387abd8f1e6bffb7d7a4e0410f2511bb515b3be3d03b727
如果想普通用户使用k8s集群,可以运行master的输出命令,如下命令支持普通用户登录系统后可以管理k8s:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
如仅需root用户管理集群,可以运行如下命令(为了管理方便可以将其加入到~/.bashrc文件中,这样每次登陆master主机时即可自动加载命令):
export KUBECONFIG=/etc/kubernetes/admin.conf
因为k8s命令繁多,可以使用如下方式为k8s的kubectl命令添加自动提示功能:
#为k8s添加自动提示
echo "source <(kubectl completion bash)" >> ~/.bashrc
kubectl apply -f kube-flannel.yml
flannel 实现了容器overlay网络功能,其基本思想类似nat技术,实现原理如下:
由于k8s自带dns功能,再结合overlay网络,集群内服务可以像internet域名一样为自己命名,k8s自动通过内置dns为相关服务调用解析为内部overlay网络ip,从而解耦了宿主环境的ip环境。
参考地址:
https://github.com/coreos/flannel
kubeadm join 10.30.5.1:6443 --token uzsv39.e2d48u4i1wgfw532 --discovery-token-ca-cert-hash sha256:73b8ef1a9ed85b489387abd8f1e6bffb7d7a4e0410f2511bb515b3be3d03b727
输出效果如下:
[root@node1 ~]# kubeadm join 10.30.5.1:6443 --token uzsv39.e2d48u4i1wgfw532 --discovery-token-ca-cert-hash sha256:73b8ef1a9ed85b489387abd8f1e6bffb7d7a4e0410f2511bb515b3be3d03b727
[preflight] running pre-flight checks
I0802 13:55:41.353849 20648 kernel_validator.go:81] Validating kernel version
I0802 13:55:41.353994 20648 kernel_validator.go:96] Validating kernel config
[WARNING SystemVerification]: docker version is greater than the most recently validated version. Docker version: 18.03.1-ce. Max validated version: 17.03
[discovery] Trying to connect to API Server "10.30.5.1:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://10.30.5.1:6443"
[discovery] Requesting info from "https://10.30.5.1:6443" again to validate TLS against the pinned public key
[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "10.30.5.1:6443"
[discovery] Successfully established connection with API Server "10.30.5.1:6443"
[kubelet] Downloading configuration for the kubelet from the "kubelet-config-1.11" ConfigMap in the kube-system namespace
[kubelet] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[preflight] Activating the kubelet service
[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "node1" as an annotation
This node has joined the cluster:
* Certificate signing request was sent to master and a response
was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the master to see this node join the cluster.
在mater下可以运行如下命令查看目前集群的状态,如下所示:
[root@master1 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master1 Ready master 37m v1.11.0
node1 Ready <none> 15m v1.11.0
node2 Ready <none> 33s v1.11.0
node3 Ready <none> 30s v1.11.0
#在master节点停止相关服务
kubectl delete deploy 服务名称
#清理集群其他附属服务
kubectl drain <node name> --delete-local-data --force --ignore-daemonsets
kubectl delete node --all
kubeadm reset
#所有node节点执行如下命令
kubeadm reset
dashboard 是k8s的web UI管理平台,可以通过web方式管理集群,查看集群中用应用的部署情况。
该项目参考如下网址:https://github.com/kubernetes/dashboard
输入tocken值即可进入dashboard管理页面,如下图所示:
该平台可以查看集群的工作负载、节点、存储、副本集、任务、日志等等相关k8s资源情况,在线管理应用部署
在集群中日志查看和收集通常是个棘手的问题,在k8s环境中非常易于实现日志的统一收集,其基本原理采用的是sidecar模式,在每个节点上运行daemonset(采集日志的代理),集中收集日志到一个存储服务内然后再统一管理显示。本环境采用了kubernetes官方建议技术EFK,其中EFK分别代表elasticsearch,fluentd,kibana,fluentd负责统一采集日志,elasticsearch集中收集聚合运算日志,kibana负责UI显示,由于简单起见我们没有加入权限管理。
该程序的架构思维如下:
在k8s master运行如下命令:
[root@master1 ~]# kubectl apply -f k8s-efk-log/
service/elasticsearch-logging created
serviceaccount/elasticsearch-logging created
clusterrole.rbac.authorization.k8s.io/elasticsearch-logging created
clusterrolebinding.rbac.authorization.k8s.io/elasticsearch-logging created
statefulset.apps/elasticsearch-logging created
configmap/fluentd-es-config-v0.1.4 created
serviceaccount/fluentd-es created
clusterrole.rbac.authorization.k8s.io/fluentd-es created
clusterrolebinding.rbac.authorization.k8s.io/fluentd-es created
daemonset.apps/fluentd-es-v2.2.0 created
deployment.apps/kibana-logging created
service/kibana-logging created
[root@master1 ~]#
由于访问方便,该日志服务采用nodeport方式部署,运行效果如下:
初次登录需要配置要检索的elasticsearch索引,默认我们采用logstash-*模式匹配默认索引,点击“Next step”为其配置时间过滤器,如下图所示:
点击“Create Index Pattern”,进入如下页面,意味着可以通过不通字段,搜集相关日志:
点击左侧的“Dicover”即可搜集相关日志,如下图所示:
集群监控是个棘手的问题,传统方式采用Zabbix 等技术方案很难达到一种统一集中监控集群的方式,kube-prometheus基于prometheus-operator提供了一套现成的采集形式,同时支持WebUI显示、用户管理和报警功能,参考网址:https://github.com/coreos/prometheus-operator/tree/master/contrib/kube-prometheus。
默认情况下k8s为了减少资源消耗是没有开通集群资源统计情况的,需要为各节点修改如下参数,开启集群资源统计功能:
sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
#为kubelet添加如下参数:
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS --authentication-token-webhook --authorization-mode=Webhook --read-only-port=10255
#注意以下三个参数是追加的参数
--authentication-token-webhook --authorization-mode=Webhook --read-only-port=10255
该程序的架构思维如下:
执行如下命令即可轻松安装集群监控,如下所示:
kubectl apply -f kube-prometheus/manifests/
由于访问方便,我们采用了nodeport暴露服务,端口使用30002,访问网址如下所示:
第一次登录需要为admin用户设置密码,登录完成后,如下图所示:
点击左侧导航“Manage”可以查看可监控项,如下图所示:
我们可以从集群资源消耗情况,命名空间、pod使用情况,node节点情况等等分别观察集群的健康状况。如下图所示:
陛下...看完奏折,点个赞再走吧!