【K8S】基于Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持续集成交付环境(环境搭建篇)
2021-02-06 21:15
标签:comm org shanghai add change grep 关闭selinux nec includes K8S全称是Kubernetes,是一个全新的基于容器技术的分布式架构领先方案,基于容器技术,目的是实现资源管理的自动化,以及跨多个数据中心的资源利用率的最大化。 如果我们的系统设计遵循了kubernetes的设计思想,那么传统系统架构中那些和业务没有多大关系的底层代码或功能模块,都可以使用K8S来管理,我们不必再费心于负载均衡的选型和部署实施问题,不必再考虑引入或自己开发一个复杂的服务治理框架,不必再头疼与服务监控和故障处理模块的开发。总之,使用kubernetes提供的解决方案,会大大减少开发成本,同时可以将精力更加集中于业务本身,而且由于kubernetes提供了强大的自动化机制,所以系统后期的运维难度和运维成本大幅降低。 Docker 这个新兴的容器化技术当前已经被很多公司所采用,其从单机走向集群已成必然,而云计算的蓬勃发展正在加速这一进程。Kubernetes 作为当前唯一被业界广泛认可和看好的 Docker 分布式系统解决方案。可以预见,在未来几年内,会有大量的新系统选择它,不管是运行在企业本地服务器上还是被托管到公有云上。 使用Kubernetes就是在全面部署微服务架构。微服务架构的核心就是将一个巨大的单体应用分解为很多小的互相连接的微服务,一个微服务背后可能有多个实例副本在支撑,副本的数量可能会随着系统的负荷变化而进行调整,内嵌的负载均衡器在 k8s 平台中有多个实例副本在支撑,副本的数量可能会随着系统的负荷变化而进行调整,内嵌的负载均衡器 在k8s 平台中发挥了重要的作用。微服务架构使得每个服务都可以由专门的开发团队来开发,开发者可以自由选择开发技术,这对于大规模团队来说很有价值。另外,每个微服务独立开发、升级、扩展,使得系统具备很高的稳定性和快速迭代进化能力。 整套环境的搭建包含:Docker环境的搭建、docker-compose环境的搭建、K8S集群的搭建、GitLab代码仓库的搭建、SVN仓库的搭建、Jenkins自动化部署环境的搭建、Harbor私有仓库的搭建。 本文档中,整套环境的搭建包括: Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。 本文档基于Docker 19.03.8 版本搭建Docker环境。 在所有服务器上创建install_docker.sh脚本,脚本内容如下所示。 在每台服务器上为install_docker.sh脚本赋予可执行权限,并执行脚本,如下所示。 Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。 注意:在每台服务器上安装docker-compose Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。 本文档基于K8S 1.8.12版本来搭建K8S集群 在所有服务器上创建install_k8s.sh脚本文件,脚本文件的内容如下所示。 在每台服务器上为install_k8s.sh脚本赋予可执行权限,并执行脚本 只在test10服务器上执行的操作。 1.初始化Master节点的网络环境 注意:下面的命令需要在命令行手动执行。 2.初始化Master节点 在test10服务器上创建init_master.sh脚本文件,文件内容如下所示。 赋予init_master.sh脚本文件可执行权限并执行脚本。 3.查看Master节点的初始化结果 (1)确保所有容器组处于Running状态 具体执行如下所示。 (2) 查看 Master 节点初始化结果 具体执行如下所示。 1.获取join命令参数 在Master节点(test10服务器)上执行如下命令获取join命令参数。 具体执行如下所示。 其中,有如下一行输出。 这行代码就是获取到的join命令。 注意:join命令中的token的有效时间为 2 个小时,2小时内,可以使用此 token 初始化任意数量的 worker 节点。 2.初始化Worker节点 针对所有的 worker 节点执行,在这里,就是在test11服务器和test12服务器上执行。 在命令分别手动执行如下命令。 具体执行如下所示。 根据输出结果可以看出,Worker节点加入了K8S集群。 注意:kubeadm join…就是master 节点上 kubeadm token create 命令输出的join。 3.查看初始化结果 在Master节点(test10服务器)执行如下命令查看初始化结果。 具体执行如下所示。 注意:kubectl get nodes命令后面加上-o wide参数可以输出更多的信息。 Master 节点的 IP 地址发生变化,导致 worker 节点不能启动。需要重新安装K8S集群,并确保所有节点都有固定的内网 IP 地址。 重启服务器后使用如下命令查看Pod的运行状态。 发现很多 Pod 不在 Running 状态,此时,需要使用如下命令删除运行不正常的Pod。 注意:如果Pod 是使用 Deployment、StatefulSet 等控制器创建的,K8S 将创建新的 Pod 作为替代,重新启动的 Pod 通常能够正常工作。 其中,pod-name表示运行在K8S中的pod的名称,pod-namespece表示命名空间。例如,需要删除pod名称为pod-test,命名空间为pod-test-namespace的pod,可以使用下面的命令。 作为反向代理将外部流量导入集群内部,将 Kubernetes 内部的 Service 暴露给外部,在 Ingress 对象中通过域名匹配 Service,这样就可以直接通过域名访问到集群内部的服务了。相对于 traefik 来说,nginx-ingress 性能更加优秀。 注意:在Master节点(test10服务器上执行) 创建ingress-nginx-namespace.yaml文件,主要的作用是创建ingress-nginx命名空间,文件内容如下所示。 执行如下命令创建ingress-nginx命名空间。 创建ingress-nginx-mandatory.yaml文件,主要的作用是安装ingress-nginx。文件内容如下所示。 执行如下命令安装ingress controller。 主要是用来用于暴露pod:nginx-ingress-controller。 创建service-nodeport.yaml文件,文件内容如下所示。 执行如下命令安装。 查看ingress-nginx命名空间的部署情况,如下所示。 在命令行服务器命令行输入如下命令查看ingress-nginx的端口映射情况。 具体如下所示。 所以,可以通过Master节点(test10服务器)的IP地址和30080端口号来访问ingress-nginx,如下所示。 也可以在浏览器打开http://192.168.0.10:30080 来访问ingress-nginx,如下所示。 GitLab是由GitLabInc.开发,使用MIT许可证的基于网络的Git仓库管理工具,且具有Wiki和issue跟踪功能。使用Git作为代码管理工具,并在此基础上搭建起来的web服务。 注意:在Master节点(test10服务器上执行) 创建k8s-ops-namespace.yaml文件,主要作用是创建k8s-ops命名空间。文件内容如下所示。 执行如下命令创建命名空间。 创建gitlab-redis.yaml文件,文件的内容如下所示。 首先,在命令行执行如下命令创建/data1/docker/xinsrv/redis目录。 执行如下命令安装gitlab-redis。 创建gitlab-postgresql.yaml,文件内容如下所示。 首先,执行如下命令创建/data1/docker/xinsrv/postgresql目录。 接下来,安装gitlab-postgresql,如下所示。 (1)配置用户名和密码 首先,在命令行使用base64编码为用户名和密码进行转码,本示例中,使用的用户名为admin,密码为admin.1231 转码情况如下所示。 转码后的用户名为:YWRtaW4= 密码为:YWRtaW4uMTIzMQ== 也可以对base64编码后的字符串解码,例如,对密码字符串解码,如下所示。 接下来,创建secret-gitlab.yaml文件,主要是用户来配置GitLab的用户名和密码,文件内容如下所示。 执行配置文件的内容,如下所示。 (2)安装GitLab 创建gitlab.yaml文件,文件的内容如下所示。 注意:在配置GitLab时,监听主机时,不能使用IP地址,需要使用主机名或者域名,上述配置中,我使用的是gitlab.binghe.com主机名。 在命令行执行如下命令创建/data1/docker/xinsrv/gitlab目录。 安装GitLab,如下所示。 查看k8s-ops命名空间部署情况,如下所示。 也可以使用如下命令查看。 二者效果一样。 接下来,查看GitLab的端口映射,如下所示。 此时,可以看到,可以通过Master节点(test10)的主机名gitlab.binghe.com和端口30088就能够访问GitLab。由于我这里使用的是虚拟机来搭建相关的环境,在本机访问虚拟机映射的gitlab.binghe.com时,需要配置本机的hosts文件,在本机的hosts文件中加入如下配置项。 注意:在Windows操作系统中,hosts文件所在的目录如下。 接下来,就可以在浏览器中通过链接:http://gitlab.binghe.com:30088 来访问GitLab了,如下所示。 此时,可以通过用户名root和密码admin.1231来登录GitLab了。 注意:这里的用户名是root而不是admin,因为root是GitLab默认的超级用户。 到此,K8S安装gitlab完成。 Habor是由VMWare公司开源的容器镜像仓库。事实上,Habor是在Docker Registry上进行了相应的企业级扩展,从而获得了更加广泛的应用,这些新的企业级特性包括:管理用户界面,基于角色的访问控制 ,AD/LDAP集成以及审计日志等,足以满足基本企业需求。 注意:这里将Harbor私有仓库安装在Master节点(test10服务器)上,实际生产环境中建议安装在其他服务器。 解压成功后,会在服务器当前目录生成一个harbor目录。 注意:这里,我将Harbor的端口修改成了1180,如果不修改Harbor的端口,默认的端口是80。 (1)修改harbor.yml文件 修改的配置项如下所示。 (2)修改daemon.json文件 修改/etc/docker/daemon.json文件,没有的话就创建,在/etc/docker/daemon.json文件中添加如下内容。 也可以在服务器上使用 ip addr 命令查看本机所有的IP地址段,将其配置到/etc/docker/daemon.json文件中。这里,我配置后的文件内容如下所示。 配置完成后,输入如下命令即可安装并启动Harbor 安装成功后,在浏览器地址栏输入http://192.168.0.10:1180打开链接,输入用户名admin和密码binghe123,登录系统。 接下来,我们选择用户管理,添加一个管理员账户,为后续打包Docker镜像和上传Docker镜像做准备。 密码为Binghe123。点击确,此时,账户binghe还不是管理员,此时选中binghe账户,点击“设置为管理员”。 此时,binghe账户就被设置为管理员了。到此,Harbor的安装就完成了。 如果安装Harbor后,大家需要修改Harbor的端口,可以按照如下步骤修改Harbor的端口,这里,我以将80端口修改为1180端口为例 (1)修改harbor.yml文件 修改的配置项如下所示。 (2)修改docker-compose.yml文件 修改的配置项如下所示。 (3)修改config.yml文件 修改的配置项如下所示。 (4)重启Docker (5)重启Harbor Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具,起源于Hudson(Hudson是商用的),主要用于持续、自动的构建/测试软件项目、监控外部任务的运行(这个比较抽象,暂且写上,不做解释)。Jenkins用Java语言编写,可在Tomcat等流行的servlet容器中运行,也可独立运行。通常与版本管理工具(SCM)、构建工具结合使用。常用的版本控制工具有SVN、GIT,构建工具有Maven、Ant、Gradle。 使用 nfs 最大的问题就是写权限,可以使用 kubernetes 的 securityContext/runAsUser 指定 jenkins 容器中运行 jenkins 的用户 uid,以此来指定 nfs 目录的权限,让 jenkins 容器可写;也可以不限制,让所有用户都可以写。这里为了简单,就让所有用户可写了。 如果之前已经安装过nfs,则这一步可以省略。找一台主机,安装 nfs,这里,我以在Master节点(test10服务器)上安装nfs为例。 在命令行输入如下命令安装并启动nfs。 在Master节点(test10服务器)上创建 接下来,编辑/etc/exports文件,如下所示。 在/etc/exports文件文件中添加如下一行配置。 这里的 ip 使用 kubernetes node 节点的 ip 范围,后面的 这个选项在很多机器上由于用户 uid 不规范导致启动进程的用户不同,但是同时要对一个共享目录具有写权限时很有效。 接下来,为 在K8S集群中任意一个节点上使用如下命令进行验证: 如果能够看到 /opt/nfs/jenkins-data 就表示 ok 了。 具体如下所示。 Jenkins 其实只要加载对应的目录就可以读取之前的数据,但是由于 deployment 无法定义存储卷,因此我们只能使用 StatefulSet。 首先创建 pv,pv 是给 StatefulSet 使用的,每次 StatefulSet 启动都会通过 volumeClaimTemplates 这个模板去创建 pvc,因此必须得有 pv,才能供 pvc 绑定。 创建jenkins-pv.yaml文件,文件内容如下所示。 我这里给了 1T存储空间,可以根据实际配置。 执行如下命令创建pv。 创建service account,因为 jenkins 后面需要能够动态创建 slave,因此它必须具备一些权限。 创建jenkins-service-account.yaml文件,文件内容如下所示。 上述配置中,创建了一个 RoleBinding 和一个 ServiceAccount,并且将 RoleBinding 的权限绑定到这个用户上。所以,jenkins 容器必须使用这个 ServiceAccount 运行才行,不然 RoleBinding 的权限它将不具备。 RoleBinding 的权限很容易就看懂了,因为 jenkins 需要创建和删除 slave,所以才需要上面这些权限。至于 secrets 权限,则是 https 证书。 执行如下命令创建serviceAccount。 创建jenkins-statefulset.yaml文件,文件内容如下所示。环境搭建概述
1.K8S是什么?
2.为什么要用K8S?
3.使用K8S有哪些好处?
4.环境构成
服务器规划
IP
主机名
节点
操作系统
192.168.0.10
test10
K8S Master
CentOS 8.0.1905
192.168.0.11
test11
K8S Worker
CentOS 8.0.1905
192.168.0.12
test12
K8S Worker
CentOS 8.0.1905
安装环境版本
软件名称
软件版本
说明
Docker
19.03.8
提供容器环境
docker-compose
1.25.5
定义和运行由多个容器组成的应用
K8S
1.18.2
是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。
GitLab
12.1.6
代码仓库
Harbor
1.10.2
私有镜像仓库
Jenkins
2.222.3
持续集成交付
安装Docker环境
#使用阿里云镜像中心
export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com
#安装yum工具
dnf install yum*
#安装docker环境
yum install -y yum-utils device-mapper-persistent-data lvm2
#配置Docker的yum源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#安装容器插件
dnf install https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.13-3.1.el7.x86_64.rpm
#指定安装docker 19.03.8版本
yum install -y docker-ce-19.03.8 docker-ce-cli-19.03.8
#设置Docker开机启动
systemctl enable docker.service
#启动Docker
systemctl start docker.service
#查看Docker版本
docker version
# 赋予install_docker.sh脚本可执行权限
chmod a+x ./install_docker.sh
# 执行install_docker.sh脚本
./install_docker.sh
安装docker-compose
1.下载docker-compose文件
#下载并安装docker-compose
curl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
2.为docker-compose文件赋予可执行权限
#赋予docker-compose可执行权限
chmod a+x /usr/local/bin/docker-compose
3.查看docker-compose版本
#查看docker-compose版本
[root@binghe ~]# docker-compose version
docker-compose version 1.25.5, build 8a1c60f6
docker-py version: 4.1.0
CPython version: 3.7.5
OpenSSL version: OpenSSL 1.1.0l 10 Sep 2019
安装K8S集群环境
安装K8S基础环境
#################配置阿里云镜像加速器开始########################
mkdir -p /etc/docker
tee /etc/docker/daemon.json /etc/fstab
############################修改 /etc/sysctl.conf开始###########################
# 如果有配置,则修改
sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g" /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g" /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g" /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=1#g" /etc/sysctl.conf
# 可能没有,追加
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding = 1" >> /etc/sysctl.conf
############################修改 /etc/sysctl.conf结束###########################
# 执行命令使修改后的/etc/sysctl.conf文件生效
sysctl -p
################# 配置K8S的yum源开始#############################
cat /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
################# 配置K8S的yum源结束#############################
# 卸载旧版本K8S
yum remove -y kubelet kubeadm kubectl
# 安装kubelet、kubeadm、kubectl,这里我安装的是1.18.2版本,你也可以安装1.17.2版本
yum install -y kubelet-1.18.2 kubeadm-1.18.2 kubectl-1.18.2
# 修改docker Cgroup Driver为systemd
# # 将/usr/lib/systemd/system/docker.service文件中的这一行 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
# # 修改为 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd
# 如果不修改,在添加 worker 节点时可能会碰到如下错误
# [WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd".
# Please follow the guide at https://kubernetes.io/docs/setup/cri/
sed -i "s#^ExecStart=/usr/bin/dockerd.*#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd#g" /usr/lib/systemd/system/docker.service
# 设置 docker 镜像,提高 docker 镜像下载速度和稳定性
# 如果访问 https://hub.docker.io 速度非常稳定,也可以跳过这个步骤,一般不需配置
# curl -sSL https://kuboard.cn/install-script/set_mirror.sh | sh -s ${REGISTRY_MIRROR}
# 重新加载配置文件
systemctl daemon-reload
#重启 docker
systemctl restart docker
# 将kubelet设置为开机启动并启动kubelet
systemctl enable kubelet && systemctl start kubelet
# 查看docker版本
docker version
# 赋予install_k8s.sh脚本可执行权限
chmod a+x ./install_k8s.sh
# 运行install_k8s.sh脚本
./install_k8s.sh
初始化Master节点
# 只在 master 节点执行
# export 命令只在当前 shell 会话中有效,开启新的 shell 窗口后,如果要继续安装过程,请重新执行此处的 export 命令
export MASTER_IP=192.168.0.10
# 替换 k8s.master 为 您想要的 dnsName
export APISERVER_NAME=k8s.master
# Kubernetes 容器组所在的网段,该网段安装完成后,由 kubernetes 创建,事先并不存在于物理网络中
export POD_SUBNET=172.18.0.1/16
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
#!/bin/bash
# 脚本出错时终止执行
set -e
if [ ${#POD_SUBNET} -eq 0 ] || [ ${#APISERVER_NAME} -eq 0 ]; then
echo -e "\033[31;1m请确保您已经设置了环境变量 POD_SUBNET 和 APISERVER_NAME \033[0m"
echo 当前POD_SUBNET=$POD_SUBNET
echo 当前APISERVER_NAME=$APISERVER_NAME
exit 1
fi
# 查看完整配置选项 https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2
rm -f ./kubeadm-config.yaml
cat ./kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.18.2
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
controlPlaneEndpoint: "${APISERVER_NAME}:6443"
networking:
serviceSubnet: "10.96.0.0/16"
podSubnet: "${POD_SUBNET}"
dnsDomain: "cluster.local"
EOF
# kubeadm init
# 初始化kebeadm
kubeadm init --config=kubeadm-config.yaml --upload-certs
# 配置 kubectl
rm -rf /root/.kube/
mkdir /root/.kube/
cp -i /etc/kubernetes/admin.conf /root/.kube/config
# 安装 calico 网络插件
# 参考文档 https://docs.projectcalico.org/v3.13/getting-started/kubernetes/self-managed-onprem/onpremises
echo "安装calico-3.13.1"
rm -f calico-3.13.1.yaml
wget https://kuboard.cn/install-script/calico/calico-3.13.1.yaml
kubectl apply -f calico-3.13.1.yaml
# 赋予init_master.sh文件可执行权限
chmod a+x ./init_master.sh
# 运行init_master.sh脚本
./init_master.sh
# 执行如下命令,等待 3-10 分钟,直到所有的容器组处于 Running 状态
watch kubectl get pod -n kube-system -o wide
[root@test10 ~]# watch kubectl get pod -n kube-system -o wide
Every 2.0s: kubectl get pod -n kube-system -o wide test10: Sun May 10 11:01:32 2020
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
calico-kube-controllers-5b8b769fcd-5dtlp 1/1 Running 0 118s 172.18.203.66 test10
# 查看Master节点的初始化结果
kubectl get nodes -o wide
[root@test10 ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
test10 Ready master 3m28s v1.18.2 192.168.0.10
初始化Worker节点
kubeadm token create --print-join-command
[root@test10 ~]# kubeadm token create --print-join-command
W0510 11:04:34.828126 56132 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
kubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2 --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d
kubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2 --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d
# 只在 worker 节点执行
# 192.168.0.10 为 master 节点的内网 IP
export MASTER_IP=192.168.0.10
# 替换 k8s.master 为初始化 master 节点时所使用的 APISERVER_NAME
export APISERVER_NAME=k8s.master
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
# 替换为 master 节点上 kubeadm token create 命令输出的join
kubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2 --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d
[root@test11 ~]# export MASTER_IP=192.168.0.10
[root@test11 ~]# export APISERVER_NAME=k8s.master
[root@test11 ~]# echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
[root@test11 ~]# kubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2 --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d
W0510 11:08:27.709263 42795 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set.
[preflight] Running pre-flight checks
[WARNING FileExisting-tc]: tc not found in system path
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with ‘kubectl -n kube-system get cm kubeadm-config -oyaml‘
[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.18" ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run ‘kubectl get nodes‘ on the control-plane to see this node join the cluster.
kubectl get nodes -o wide
[root@test10 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
test10 Ready master 20m v1.18.2
test11 Ready
重启K8S集群引起的问题
1.Worker节点故障不能启动
2.Pod崩溃或不能正常访问
#查看所有pod的运行情况
kubectl get pods --all-namespaces
kubectl delete pod
kubectl delete pod pod-test -n pod-test-namespace
K8S安装ingress-nginx
1.创建ingress-nginx命名空间
apiVersion: v1
kind: Namespace
metadata:
name: ingress-nginx
labels:
name: ingress-nginx
kubectl apply -f ingress-nginx-namespace.yaml
2.安装ingress controller
apiVersion: v1
kind: Namespace
metadata:
name: ingress-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: default-http-backend
labels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
namespace: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
spec:
terminationGracePeriodSeconds: 60
containers:
- name: default-http-backend
# Any image is permissible as long as:
# 1. It serves a 404 page at /
# 2. It serves 200 on a /healthz endpoint
image: registry.cn-qingdao.aliyuncs.com/kubernetes_xingej/defaultbackend-amd64:1.5
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
ports:
- containerPort: 8080
resources:
limits:
cpu: 10m
memory: 20Mi
requests:
cpu: 10m
memory: 20Mi
---
apiVersion: v1
kind: Service
metadata:
name: default-http-backend
namespace: ingress-nginx
labels:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
spec:
ports:
- port: 80
targetPort: 8080
selector:
app.kubernetes.io/name: default-http-backend
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: tcp-services
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: udp-services
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- "extensions"
resources:
- ingresses/status
verbs:
- update
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: nginx-ingress-role
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
# Defaults to "
kubectl apply -f ingress-nginx-mandatory.yaml
3.安装K8S SVC:ingress-nginx
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
nodePort: 30080
- name: https
port: 443
targetPort: 443
protocol: TCP
nodePort: 30443
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
kubectl apply -f service-nodeport.yaml
4.访问K8S SVC:ingress-nginx
[root@test10 k8s]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
default-http-backend-796ddcd9b-vfmgn 1/1 Running 1 10h
nginx-ingress-controller-58985cc996-87754 1/1 Running 2 10h
kubectl get svc -n ingress-nginx
[root@test10 k8s]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default-http-backend ClusterIP 10.96.247.2
[root@test10 k8s]# curl 192.168.0.10:30080
default backend - 404
K8S安装gitlab代码仓库
1.创建k8s-ops命名空间
apiVersion: v1
kind: Namespace
metadata:
name: k8s-ops
labels:
name: k8s-ops
kubectl apply -f k8s-ops-namespace.yaml
2.安装gitlab-redis
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: k8s-ops
labels:
name: redis
spec:
selector:
matchLabels:
name: redis
template:
metadata:
name: redis
labels:
name: redis
spec:
containers:
- name: redis
image: sameersbn/redis
imagePullPolicy: IfNotPresent
ports:
- name: redis
containerPort: 6379
volumeMounts:
- mountPath: /var/lib/redis
name: data
livenessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 30
timeoutSeconds: 5
readinessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 10
timeoutSeconds: 5
volumes:
- name: data
hostPath:
path: /data1/docker/xinsrv/redis
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: k8s-ops
labels:
name: redis
spec:
ports:
- name: redis
port: 6379
targetPort: redis
selector:
name: redis
mkdir -p /data1/docker/xinsrv/redis
kubectl apply -f gitlab-redis.yaml
3.安装gitlab-postgresql
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgresql
namespace: k8s-ops
labels:
name: postgresql
spec:
selector:
matchLabels:
name: postgresql
template:
metadata:
name: postgresql
labels:
name: postgresql
spec:
containers:
- name: postgresql
image: sameersbn/postgresql
imagePullPolicy: IfNotPresent
env:
- name: DB_USER
value: gitlab
- name: DB_PASS
value: passw0rd
- name: DB_NAME
value: gitlab_production
- name: DB_EXTENSION
value: pg_trgm
ports:
- name: postgres
containerPort: 5432
volumeMounts:
- mountPath: /var/lib/postgresql
name: data
livenessProbe:
exec:
command:
- pg_isready
- -h
- localhost
- -U
- postgres
initialDelaySeconds: 30
timeoutSeconds: 5
readinessProbe:
exec:
command:
- pg_isready
- -h
- localhost
- -U
- postgres
initialDelaySeconds: 5
timeoutSeconds: 1
volumes:
- name: data
hostPath:
path: /data1/docker/xinsrv/postgresql
---
apiVersion: v1
kind: Service
metadata:
name: postgresql
namespace: k8s-ops
labels:
name: postgresql
spec:
ports:
- name: postgres
port: 5432
targetPort: postgres
selector:
name: postgresql
mkdir -p /data1/docker/xinsrv/postgresql
kubectl apply -f gitlab-postgresql.yaml
4.安装gitlab
[root@test10 k8s]# echo -n ‘admin‘ | base64
YWRtaW4=
[root@test10 k8s]# echo -n ‘admin.1231‘ | base64
YWRtaW4uMTIzMQ==
[root@test10 k8s]# echo ‘YWRtaW4uMTIzMQ==‘ | base64 --decode
admin.1231
apiVersion: v1
kind: Secret
metadata:
namespace: k8s-ops
name: git-user-pass
type: Opaque
data:
username: YWRtaW4=
password: YWRtaW4uMTIzMQ==
kubectl create -f ./secret-gitlab.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitlab
namespace: k8s-ops
labels:
name: gitlab
spec:
selector:
matchLabels:
name: gitlab
template:
metadata:
name: gitlab
labels:
name: gitlab
spec:
containers:
- name: gitlab
image: sameersbn/gitlab:12.1.6
imagePullPolicy: IfNotPresent
env:
- name: TZ
value: Asia/Shanghai
- name: GITLAB_TIMEZONE
value: Beijing
- name: GITLAB_SECRETS_DB_KEY_BASE
value: long-and-random-alpha-numeric-string
- name: GITLAB_SECRETS_SECRET_KEY_BASE
value: long-and-random-alpha-numeric-string
- name: GITLAB_SECRETS_OTP_KEY_BASE
value: long-and-random-alpha-numeric-string
- name: GITLAB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: git-user-pass
key: password
- name: GITLAB_ROOT_EMAIL
value: 12345678@qq.com
- name: GITLAB_HOST
value: gitlab.binghe.com
- name: GITLAB_PORT
value: "80"
- name: GITLAB_SSH_PORT
value: "30022"
- name: GITLAB_NOTIFY_ON_BROKEN_BUILDS
value: "true"
- name: GITLAB_NOTIFY_PUSHER
value: "false"
- name: GITLAB_BACKUP_SCHEDULE
value: daily
- name: GITLAB_BACKUP_TIME
value: 01:00
- name: DB_TYPE
value: postgres
- name: DB_HOST
value: postgresql
- name: DB_PORT
value: "5432"
- name: DB_USER
value: gitlab
- name: DB_PASS
value: passw0rd
- name: DB_NAME
value: gitlab_production
- name: REDIS_HOST
value: redis
- name: REDIS_PORT
value: "6379"
ports:
- name: http
containerPort: 80
- name: ssh
containerPort: 22
volumeMounts:
- mountPath: /home/git/data
name: data
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 180
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
timeoutSeconds: 1
volumes:
- name: data
hostPath:
path: /data1/docker/xinsrv/gitlab
---
apiVersion: v1
kind: Service
metadata:
name: gitlab
namespace: k8s-ops
labels:
name: gitlab
spec:
ports:
- name: http
port: 80
nodePort: 30088
- name: ssh
port: 22
targetPort: ssh
nodePort: 30022
type: NodePort
selector:
name: gitlab
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: gitlab
namespace: k8s-ops
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: gitlab.binghe.com
http:
paths:
- backend:
serviceName: gitlab
servicePort: http
mkdir -p /data1/docker/xinsrv/gitlab
kubectl apply -f gitlab.yaml
5.安装完成
[root@test10 k8s]# kubectl get pod -n k8s-ops
NAME READY STATUS RESTARTS AGE
gitlab-7b459db47c-5vk6t 0/1 Running 0 11s
postgresql-79567459d7-x52vx 1/1 Running 0 30m
redis-67f4cdc96c-h5ckz 1/1 Running 1 10h
[root@test10 k8s]# kubectl get pod --namespace=k8s-ops
NAME READY STATUS RESTARTS AGE
gitlab-7b459db47c-5vk6t 0/1 Running 0 36s
postgresql-79567459d7-x52vx 1/1 Running 0 30m
redis-67f4cdc96c-h5ckz 1/1 Running 1 10h
[root@test10 k8s]# kubectl get svc -n k8s-ops
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
gitlab NodePort 10.96.153.100
192.168.0.10 gitlab.binghe.com
C:\Windows\System32\drivers\etc
安装Harbor私有仓库
1.下载Harbor的离线安装版本
wget https://github.com/goharbor/harbor/releases/download/v1.10.2/harbor-offline-installer-v1.10.2.tgz
2.解压Harbor的安装包
tar -zxvf harbor-offline-installer-v1.10.2.tgz
3.配置Harbor
cd harbor
vim harbor.yml
hostname: 192.168.0.10
http:
port: 1180
harbor_admin_password: binghe123
###并把https注释掉,不然在安装的时候会报错:ERROR:root:Error: The protocol is https but attribute ssl_cert is not set
#https:
#port: 443
#certificate: /your/certificate/path
#private_key: /your/private/key/path
[root@binghe~]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://zz3sblpi.mirror.aliyuncs.com"],
"insecure-registries":["192.168.0.10:1180"]
}
{
"registry-mirrors": ["https://zz3sblpi.mirror.aliyuncs.com"],
"insecure-registries":["192.168.175.0/16","172.17.0.0/16", "172.18.0.0/16", "172.16.29.0/16", "192.168.0.10:1180"]
}
4.安装并启动harbor
[root@binghe harbor]# ./install.sh
5.登录Harbor并添加账户
6.修改Harbor端口
cd harbor
vim harbor.yml
hostname: 192.168.0.10
http:
port: 1180
harbor_admin_password: binghe123
###并把https注释掉,不然在安装的时候会报错:ERROR:root:Error: The protocol is https but attribute ssl_cert is not set
#https:
#port: 443
#certificate: /your/certificate/path
#private_key: /your/private/key/path
vim docker-compose.yml
ports:
- 1180:80
cd common/config/registry
vim config.yml
realm: http://192.168.0.10:1180/service/token
systemctl daemon-reload
systemctl restart docker.service
[root@binghe harbor]# docker-compose down
Stopping harbor-log ... done
Removing nginx ... done
Removing harbor-portal ... done
Removing harbor-jobservice ... done
Removing harbor-core ... done
Removing redis ... done
Removing registry ... done
Removing registryctl ... done
Removing harbor-db ... done
Removing harbor-log ... done
Removing network harbor_harbor
[root@binghe harbor]# ./prepare
prepare base dir is set to /mnt/harbor
Clearing the configuration file: /config/log/logrotate.conf
Clearing the configuration file: /config/nginx/nginx.conf
Clearing the configuration file: /config/core/env
Clearing the configuration file: /config/core/app.conf
Clearing the configuration file: /config/registry/root.crt
Clearing the configuration file: /config/registry/config.yml
Clearing the configuration file: /config/registryctl/env
Clearing the configuration file: /config/registryctl/config.yml
Clearing the configuration file: /config/db/env
Clearing the configuration file: /config/jobservice/env
Clearing the configuration file: /config/jobservice/config.yml
Generated configuration file: /config/log/logrotate.conf
Generated configuration file: /config/nginx/nginx.conf
Generated configuration file: /config/core/env
Generated configuration file: /config/core/app.conf
Generated configuration file: /config/registry/config.yml
Generated configuration file: /config/registryctl/env
Generated configuration file: /config/db/env
Generated configuration file: /config/jobservice/env
Generated configuration file: /config/jobservice/config.yml
loaded secret from file: /secret/keys/secretkey
Generated configuration file: /compose_location/docker-compose.yml
Clean up the input dir
[root@binghe harbor]# docker-compose up -d
Creating network "harbor_harbor" with the default driver
Creating harbor-log ... done
Creating harbor-db ... done
Creating redis ... done
Creating registry ... done
Creating registryctl ... done
Creating harbor-core ... done
Creating harbor-jobservice ... done
Creating harbor-portal ... done
Creating nginx ... done
[root@binghe harbor]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
安装Jenkins(一般的做法)
1.安装nfs(之前安装过的话,可以省略此步)
yum install nfs-utils -y
systemctl start nfs-server
systemctl enable nfs-server
2.创建nfs共享目录
/opt/nfs/jenkins-data
目录作为nfs的共享目录,如下所示。mkdir -p /opt/nfs/jenkins-data
vim /etc/exports
/opt/nfs/jenkins-data 192.168.175.0/24(rw,all_squash)
all_squash
选项会将所有访问的用户都映射成 nfsnobody 用户,不管你是什么用户访问,最终都会压缩成 nfsnobody,所以只要将 /opt/nfs/jenkins-data
的属主改为 nfsnobody,那么无论什么用户来访问都具有写权限。/opt/nfs/jenkins-data
目录授权,并重新加载nfs,如下所示。#为/opt/nfs/jenkins-data/目录授权
chown -R 1000 /opt/nfs/jenkins-data/
#重新加载nfs-server
systemctl reload nfs-server
#查看nfs系统的目录权限
showmount -e NFS_IP
[root@test10 ~]# showmount -e 192.168.0.10
Export list for 192.168.0.10:
/opt/nfs/jenkins-data 192.168.175.0/24
[root@test11 ~]# showmount -e 192.168.0.10
Export list for 192.168.0.10:
/opt/nfs/jenkins-data 192.168.175.0/24
3.创建PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: jenkins
spec:
nfs:
path: /opt/nfs/jenkins-data
server: 192.168.0.10
accessModes: ["ReadWriteOnce"]
capacity:
storage: 1Ti
kubectl apply -f jenkins-pv.yaml
4.创建serviceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: jenkins
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: jenkins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: jenkins
subjects:
- kind: ServiceAccount
name: jenkins
kubectl apply -f jenkins-service-account.yaml
5.安装Jenkins
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: jenkins
labels:
name: jenkins
spec:
selector:
matchLabels:
name: jenkins
serviceName: jenkins
replicas: 1
updateStrategy:
type: RollingUpdate
template:
metadata:
name: jenkins
labels:
name: jenkins
spec:
terminationGracePeriodSeconds: 10
serviceAccountName: jenkins
containers:
- name: jenkins
image: docker.io/jenkins/jenkins:lts
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
- containerPort: 32100
resources:
limits:
cpu: 4
memory: 4Gi
requests:
cpu: 4
memory: 4Gi
env:
- name: LIMITS_MEMORY
valueFrom:
resourceFieldRef:
resource: limits.memory
divisor: 1Mi
- name: JAVA_OPTS
# value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForH
文章标题:【K8S】基于Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持续集成交付环境(环境搭建篇)
文章链接:http://soscw.com/index.php/essay/51877.html