这篇是转载的:原文出处: https://www.toocruel.net/kubernetes-chi-xu-ji-cheng-springcloud/
写在开始之前
在开始之前我们需要了解几个概念:
1.什么是持续集成?
持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成的问题,让团队能够更快的开发内聚的软件。
2.什么是 kubernetes?
Kubernetes 是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes 的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes 提供了应用部署,规划,更新,维护的一种机制。
3.什么是 SpringCloud?
Spring Cloud 是一系列框架的有序集合。它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 Spring Boot 的开发风格做到一键启动和部署。
通过以上几个概念我们简单了解了 kubernetes 等技术是干什么的,其他的具体我们这里不做赘述,大家可以到其官方网站进行了解。我们这里只教会大家如何利用这些工具或技术来实现我们应用的可持续集成到不同的环境中。那么就让我开始实践吧!
我们先来看看实现这个持续集成的流水线:
- 开发人员提交代码 Gitlab 远程触发 Jenkins 构建
- Jenkins 构建镜像推送到私有仓库
- Jenkins 将最新的镜像部署到 k8s 中
- 将部署反馈发送给用户
一、实验环境概览
这里推荐大家使用 VMware 安装虚拟机,Centos 7 系统,所有操作都在 root 用户下进行。
以下内容将以 IP 区分各个虚拟机。
二、 虚拟机和必要软件安装
1. 虚拟机的安装与配置
这里安装虚拟机按照 VMware 的指示一步步安装配置虚拟机的内存和硬盘即可,重点教大家如何配置虚拟机的网卡和固定 IP,如果不配置固定 IP 虚拟机重启之后自动分配 IP 会导致 kubernetes 集群崩掉无法访问以及各种各样的问题。
注意:安装虚拟机的时候网络适配器要选择 NAT 模式(N):用于共享主机的 IP 地址。
1.1 网卡配置
第一步、打开虚拟网络编辑器
第二步、获得管理员权限
第三步、这里一定要按照图中这样配置
第四步、这一步可有可无,默认配置也没问题
1.2 为各个虚拟机分配静态 IP
# 1. 修改网络配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33 # 2. 把BOOTPROTO="dhcp"修改为BOOTPROTO="static" # 3. 在末尾添加如下内容: IPADDR=192.168.1.11 NETMASK=255.255.255.0 GATEWAY=192.168.1.2 DNS1=114.114.114.114
- IPADDR 是你为此虚拟机分配的静态 IP
- NETMASK 子网掩码,在第三步图中获取
- GATEWAY 网关,在第三步图中点击 NAT 设置 获取
- DNS 使用 114.114.114.114 即可
# 4. 重启网络服务 service network restart # 5.验证设置 ## 验证是否能连接外网 ping baidu.com ## 查看ip ip addr
2. 安装一些必要的工具以及一些通用配置
在所有机器上进行如下操作:
# 1. 安装常用软件 yum -y install vim wget # 2.安装 Docker ## v1.11.x版本推荐使用docker v17.03 更高的版本可能无法正常运行 ### 2.1 安装依赖包 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 ### 2.2 设置阿里云镜像源 sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo ### 2.3 安装指定版本的Docker yum install -y --setopt=obsoletes=0 docker-ce-17.03.2.ce-1.el7.centos.x86_64 docker-ce-selinux-17.03.2.ce-1.el7.centos.noarch ### 2.4 设置Docker开机自启并启动 sudo systemctl enable docker && sudo systemctl start docker
2.5 配置 Docker 加速器
配置阿里云加速器。
# 3. 通用配置 ## 3.1 关闭防火墙 systemctl stop firewalld && systemctl disable firewalld ## 3.2 配置host解析 cat >>/etc/hosts<<EOF 192.168.1.11 k8s-master 192.168.1.12 k8s-slave1 192.168.1.13 k8s-slave2 192.168.1.101 hub.k8s.com EOF ## 3.3 设置每个机器的hostname hostnamectl --static set-hostname {hostname}
注意:配置host解析的时候我们添加了Docker私库的ip解析。
三、搭建 Docker 私有仓库:Harbor(192.168.1.101)
1. 安装 Docker-compose
# 1.安装Docker-compose sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose #赋予Docker-compose执行权限 sudo chmod +x /usr/local/bin/docker-compose #验证Docker-compose docker-compose --version
2. 安装 Harbor
# 1. 下载安装文件(可以在指定目录下载) wget https://storage.googleapis.com/harbor-releases/harbor-online-installer-v1.5.2.tgz # 2. 解压下载的文件 tar xvf harbor-online-installer-v1.5.2.tgz
3. 配置 Harbor
1. 修改Harbor的配置文件 cd harbor vim harbor.cfg 内容如下: # hostname设置访问地址,可以使用ip、域名,不可以设置为127.0.0.1或localhost hostname = hub.k8s.com # 访问协议,默认是http,也可以设置https,如果设置https,则nginx ssl需要设置on ui_url_protocol = http # mysql数据库root用户默认密码root123,实际使用时修改下 db_password = root@1234 max_job_workers = 3 customize_crt = on ssl_cert = /data/cert/server.crt ssl_cert_key = /data/cert/server.key secretkey_path = /data admiral_url = NA # 邮件设置,发送重置密码邮件时使用 email_identity = email_server = smtp.mydomain.com email_server_port = 25 email_username = [email protected] email_password = abc email_from = admin <[email protected]> email_ssl = false # 启动Harbor后,管理员UI登录的密码,默认是Harbor12345 harbor_admin_password = root@1234 # 认证方式,这里支持多种认证方式,如LADP、本次存储、数据库认证。默认是db_auth,mysql数据库认证 auth_mode = db_auth # LDAP认证时配置项 #ldap_url = ldaps://ldap.mydomain.com #ldap_searchdn = uid=searchuser,ou=people,dc=mydomain,dc=com #ldap_search_pwd = password #ldap_basedn = ou=people,dc=mydomain,dc=com #ldap_filter = (objectClass=person) #ldap_uid = uid #ldap_scope = 3 #ldap_timeout = 5 # 是否开启自注册 self_registration = on # Token有效时间,默认30分钟 token_expiration = 30 # 用户创建项目权限控制,默认是everyone(所有人),也可以设置为adminonly(只能管理员) project_creation_restriction = everyone verify_remote_cert = on
4.启动 Harbor
# 1.在当前安装目录下 ./install.sh
5.访问 Harbor 以及一些常用操作
配置宿主机对 Docker 私有仓库镜像IP的解析,编辑 C:\WINDOWS\System32\drivers\etc\hosts 文件
添加如下内容:
192.168.1.101 hub.k8s.com
这样我们在宿主机直接访问 hub.k8s.com
就可以看到Docker私库的可视化界面。
默认用户就是 admin,密码就是我们在配置文件里配置的 root@1234
我们可以新建一个项目,把和这个项目相关的镜像都推送到这个项目里,我们也可以根据项目来区分我们不同环境的镜像。例如:我的项目叫 k8s-pig,那么在 Harbor 中我们新创建一个项目叫 k8s-pig-prod 用来存放生产环境的镜像,新创建一个项目叫 k8s-pig-dev 用来存放开发环境的镜像,以及在后面我们持续集成时可以指定使用什么环境的镜像。这个我们后面再详细的讲。
我们可以点推送镜像来复制命令
进到项目的某一个模块镜像列表页面我们可以查看这个模块打包镜像的各个版本,并且可以复制 pull 镜像的命令
以下是重点!!!
我们已经完成了 Docker 私有仓库的搭建了,是不是我们就能向私库李推送镜像了?
答案显然是不能的!!!
那么我们就来解决一下这个问题,在所有机器进行如下操作(本机也需要):
1.修改 Docker 的 daemon.json 文件
vim /etc/docker/daemon.json # 添加如下内容: "insecure-registries":["hub.k8s.com"] # 重启服务 systemctl restart docker
注意:不要忘记添加内容之前加个逗号
2.docker 登录到 Harbor
docker login hub.k8s.com #输入用户名密码即可(admin/root@1234)
3.小试牛刀
# 1. 拉取docker hub的公共镜像 docker pull gitlab/gitlab-ce # 2. 标记本地镜像,将其归入某一仓库 docker tag gitlab/gitlab-ce hub.k8s.com/k8s-pig/gitlab # 3. 推送镜像到私有仓库 docker push hub.k8s.com/k8s-pig/gitlab # 4. 从私有仓库pull我们的镜像 docker pull hub.k8s.com/k8s-pig/gitlab
登录到 harbor 可视化界面就可以看到我们刚刚推送的镜像。
四、搭建代码托管服务:GitLab(192.168.1.100)
GitLab 是一个用于仓库管理系统的开源项目,使用 Git 作为代码管理工具,并在此基础上搭建起来的 web 服务。
其实,基于 Docker 安装 Gitlab 十分简单,下面就让我们搭建 Gitlab 服务,并配置邮件服务。
1. 搭建 Gitlab 服务
# 1. pull镜像,这个镜像就是我们前面小试牛刀时推送到私有仓库的镜像 docker pull hub.k8s.com/k8s-pig/gitlab # 2. 运行Gitlab镜像 docker run -d -h gitlab.cn -p 8443:443 -p 80:80 -p 2222:22 -p 9090:9090 --name gitlab --restart always -v /soft/gitlab/config:/etc/gitlab -v /soft/gitlab/logs:/var/log/gitlab -v /soft/gitlab/data:/var/opt/gitlab hub.k8s.com/k8s-pig/gitlab -h:通过gitlab.cn域名访问容器 -v:将配置文件、日志、数据持久化 -p:容器端口映射到本机端口 --name:容器名称 --restart:容器重启
注意:这里的 --restart
在 gitlab 容器上并不会启动成功,如果我们的虚拟机关机了,那么我们只能把容器删除了,重启启动,不用担心数据丢失,因为我们已经把数据持久化了,具体什么原因,大家可重启一下 gitlab 容器去看一下容器的日志。
2. 配置邮件服务
我这里用的 QQ 的 smtp 服务,大家可以自己百度一下如何开启 QQ 的 smtp 服务。
# 1.编辑gitlab的配置文件 vim /soft/gitlab/config/gitlab.rb # 2.修改我们的clone地址 external_url 'http://192.168.1.100' #本机IP # 3.添加如下内容: gitlab_rails['smtp_enable'] = true gitlab_rails['smtp_address'] = "smtp.qq.com" gitlab_rails['smtp_port'] = 465 gitlab_rails['smtp_user_name'] = "邮箱地址" gitlab_rails['smtp_password'] = "认证码" gitlab_rails['smtp_domain'] = "smtp.qq.com" gitlab_rails['smtp_authentication'] = "login" gitlab_rails['smtp_enable_starttls_auto'] = true gitlab_rails['smtp_tls'] = true gitlab_rails['gitlab_email_from'] = '邮箱地址' # 4.重启Gitlab容器 ## 4.1 删除gitlab容器 docker rm -f gitlab ## 4.2 重新运行gitlab容器 docker run -d -h gitlab.cn -p 8443:443 -p 80:80 -p 2222:22 -p 9090:9090 --name gitlab --restart always -v /soft/gitlab/config:/etc/gitlab -v /soft/gitlab/logs:/var/log/gitlab -v /soft/gitlab/data:/var/opt/gitlab hub.k8s.com/k8s-pig/gitlab
这里的 clone 地址不修改的默认值为 http://gitlab.cn。我们用命令行 clone 代码的时候会用问题。
3. 初始化登录
gitlab 的默认用户为 root,超级管理员,我们第一次登录 Gitlab 的时候会让你输入密码作为 root 用户的密码,完成后你就可以在 Gitlab 创建你的项目了。
五、搭建 Jenkins 服务 (192.168.1.11)
Jenkins 是一个开源软件项目,是基于 Java 开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。
我们这里为了简单和少出问题将 Jenkins 服务部署在 k8s-master 节点上,以便我们可以直接在 Jenkins 里使用 kubernetes 的命令行工具,那你就会问了,单节点抗压能力是不是不够啊,这里推荐一种方案也是我实践过的,其实在生产环境中 k8s-master 都是需要高可用的,所以 k8s-master 至少要部署三个节点(奇数个),Jenkins 也可以集群部署,这样我们在每一个 k8s-master 节点上部署 Jenkins 选一个作为 Jenkins-master 作为 Jenkins 集群的入口这样就解决了单点抗压能力不足的情况。
这只是一种解决方案,你也可以将 Jenkins 部署到 kubernetes 集群中,具体怎么实现这里就不做赘述了(大家如果需要的话可以给我留言看看有多少人需要,我再重新开一个 chat 具体讲讲如何部署 kubernetes 集群高可用和 Jenkins 部署到 kubernetes 集群中),下面我们就来搭建 Jenkins 服务。
1. 环境搭建
安装 Git yum -y install git 安装 JDK # 1. 下载JDK文件 cd /usr/ mkdir java && cd java wget http://download.oracle.com/otn-pub/java/jdk/8u181-b13/96a7b8442fe848ef90c96a2fad6ed6d1/jdk-8u181-linux-x64.tar.gz # 2. 解压安装文件 tar -zxvf jdk-8u151-linux-x64.tar.gz # 3. 添加环境变量 vim /etc/profile # 在文本最后添加如下内容 export JAVA_HOME=/usr/java/jdk1.8.0_181 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib/dt.JAVA_HOME/lib/tools.jar:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin:${PATH} # 4.立即生效 source /etc/profile # 5. 验证安装 java -version 安装 Maven # 1. 下载安装文件 cd /usr/ mkdir maven && cd maven wget http://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.tar.gz # 2. 解压安装文件 tar -zxvf apache-maven-3.5.4-bin.tar.gz # 3. 添加环境变量 vim /etc/profile # 修改为如下内容: export JAVA_HOME=/usr/java/jdk1.8.0_181 export MAVEN_HOME=/usr/maven/apache-maven-3.5.4 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib/dt.JAVA_HOME/lib/tools.jar:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin:${MAVEN_HOME}/bin:${PATH} # 4. 立即生效 source /etc/profile # 5. 验证安装 mvn -version 2. 安装配置 Jenkins 2.1 下载安装文件并运行 # 1. 创建安装目录 cd ~ mkdir /soft/jenkins -p cd /soft/jenkins # 2. 下安装文件 wget http://mirrors.jenkins.io/war-stable/latest/jenkins.war # 3. 运行安装文件 nohup java -jar jenkins.war --httpPort=80 >temp.txt & # 获取登录密码 cat temp.txt
复制以下内容:
2.2 登录并配置
在宿主机上输入 IP:192.168.1.11 访问 Jenkins 然后初始化用户,把我们复制的密码粘贴上,点击继续。
初始化安装插件,过程比较慢,耐心等待即可。
安装完成后就会出现初始化用户页面,大家自己去初始化用户就可以了,然后保存并结束。
初始化完成后就会进入到 Jenkins 的首页,我们后面再详细讲解如何使用 Jenkins。
六、搭建 k8s 集群 (192.168.1.11,192.168.1.12,192.168.1.13)
1. k8s 集群环境初始化设置
如下操作在192.168.1.11,192.168.1.12,192.168.1.13执行
1.1 安装 kubeadm、kubelet、kubectl
# 1. 配置阿里云源 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=0 EOF # 2. 开始安装 yum -y install kubelet kubeadm kubectl kubernetes-cni # 3. 启动kubeadm服务 systemctl enable kubelet && systemctl start kubelet # 4. 下载所需要的镜像 # 创建脚本 images.sh vim images.sh # 添加如下内容: #!/bin/bash images=(kube-proxy-amd64:v1.11.2 kube-scheduler-amd64:v1.11.2 kube-controller-manager-amd64:v1.11.2 kube-apiserver-amd64:v1.11.2 etcd-amd64:3.2.18 coredns:1.1.3 pause-amd64:3.1 kubernetes-dashboard-amd64:v1.8.3 k8s-dns-sidecar-amd64:1.14.9 k8s-dns-kube-dns-amd64:1.14.9 k8s-dns-dnsmasq-nanny-amd64:1.14.9 ) for imageName in ${images[@]} ; do docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName done docker tag da86e6ba6ca1 k8s.gcr.io/pause:3.1 # 添加执行权限 chmod -R 777 images.sh # 拉取所需镜像(耐心等待) ./images.sh # 5. 关闭 Swap swapoff -a # 永久关闭 #要永久禁掉swap分区,打开如下文件注释掉swap那一行 # vim /etc/fstab # 6. 关闭 SELinux sed -i 's/SELINUX=permissive/SELINUX=disabled/' /etc/sysconfig/selinux setenforce 0 # 7. 配置转发参数 cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 vm.swappiness=0 EOF sysctl --system
2. 开始安装 Master节点(192.168.1.11)
2.1 初始化
注意这里--apiserver-cert-extra-sans=
后面的IP:192.168.1.11,如果你的和我的不一样要修改成自己的。
kubeadm init --kubernetes-version=v1.11.2 --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=0.0.0.0 --apiserver-cert-extra-sans=192.168.1.11,127.0.0.1,k8s-master
初始化完成之后会打印一条命令,例如:
kubeadm join 192.168.1.11:6443 --token udrvwc.nn0ujov1re4ms63j --discovery-token-ca-cert-hash sha256:d6f93d4b2f9efc49e7e063707daa474057e58d3e4e09d62c3ab747b4279332cb
需要我们找个地方记录一下这个值,后面我们添加节点是会用到。
2.2 配置 kubctl
export KUBECONFIG=/etc/kubernetes/admin.conf echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
2.3 安装 Flannel
# 1. 创建安装文件夹 mkdir -p /etc/cni/net.d/ # 2. 创建安装文件 cat <<EOF> /etc/cni/net.d/10-flannel.conf { “name”: “cbr0”, “type”: “flannel”, “delegate”: { “isDefaultGateway”: true } } EOF mkdir /usr/share/oci-umount/oci-umount.d -p mkdir /run/flannel/ cat <<EOF> /run/flannel/subnet.env FLANNEL_NETWORK=10.244.0.0/16 FLANNEL_SUBNET=10.244.1.0/24 FLANNEL_MTU=1450 FLANNEL_IPMASQ=true EOF
创建 flannel 的 yaml 文件
vim k8s-flannel.yaml 添加如下内容: --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: flannel rules: - apiGroups: - "" resources: - pods verbs: - get - apiGroups: - "" resources: - nodes verbs: - list - watch - apiGroups: - "" resources: - nodes/status verbs: - patch --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: flannel roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: flannel subjects: - kind: ServiceAccount name: flannel namespace: kube-system --- apiVersion: v1 kind: ServiceAccount metadata: name: flannel namespace: kube-system --- kind: ConfigMap apiVersion: v1 metadata: name: kube-flannel-cfg namespace: kube-system labels: tier: node app: flannel data: cni-conf.json: | { "name": "cbr0", "type": "flannel", "delegate": { "isDefaultGateway": true } } net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } } --- apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: kube-flannel-ds namespace: kube-system labels: tier: node app: flannel spec: template: metadata: labels: tier: node app: flannel spec: hostNetwork: true nodeSelector: beta.kubernetes.io/arch: amd64 tolerations: - key: node-role.kubernetes.io/master operator: Exists effect: NoSchedule serviceAccountName: flannel initContainers: - name: install-cni image: quay.io/coreos/flannel:v0.9.1-amd64 command: - cp args: - -f - /etc/kube-flannel/cni-conf.json - /etc/cni/net.d/10-flannel.conf volumeMounts: - name: cni mountPath: /etc/cni/net.d - name: flannel-cfg mountPath: /etc/kube-flannel/ containers: - name: kube-flannel image: quay.io/coreos/flannel:v0.9.1-amd64 command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr" ] securityContext: privileged: true env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace volumeMounts: - name: run mountPath: /run - name: flannel-cfg mountPath: /etc/kube-flannel/ volumes: - name: run hostPath: path: /run - name: cni hostPath: path: /etc/cni/net.d - name: flannel-cfg configMap: name: kube-flannel-cfg
运行 k8s-flannel.yaml
kubectl create -f k8s-flannel.yaml
2.4 k8s 可视化配置
我们这里使用别人开源的 DashBoard 模板。
# 1. clone 模板 git clone https://github.com/gh-Devin/kubernetes-dashboard.git # 2. 这个开源的模板里heapster插件的镜像有问题我们这里给他修改一下 cd kubernetes-dashboard/ vim heapster.yaml 修改镜像名称 : registry.cn-shenzhen.aliyuncs.com/intbee/heapster-amd64:v1.4.2 为 wavefronthq/heapster-amd64
部署 DashBoard
kubectl -n kube-system create -f .
创建 dashboard-admin.yaml
vim dashboard-admin.yaml 添加如下内容: apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: kubernetes-dashboard labels: k8s-app: kubernetes-dashboard roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: kubernetes-dashboard namespace: kube-system
执行 dashboard-admin.yaml
kubectl create -f dashboard-admin.yaml
现在我们在宿主机访问:192.168.1.11:30090 就可以访问 k8s 管理界面了。如下(我的是已经加入 slave 的):
下面我们就来加入 slave 节点。
2.5 加入子节点
分别在 192.168.1.12 和 192.168.1.13 节点上执行我们刚刚保存的命令:
kubeadm join 192.168.1.11:6443 --token udrvwc.nn0ujov1re4ms63j --discovery-token-ca-cert-hash sha256:d6f93d4b2f9efc49e7e063707daa474057e58d3e4e09d62c3ab747b4279332cb
我们在 master 节点上运行如下命令来查看节点如否加入集群(需要等一会让子节点初始化完成才能看见状态为 Ready):
kubect get nodes
七、 搭建完整的持续的流水线
1. 准备我们的 springcloud 项目
这里推荐一下冷冷的 springcloud 项目,冷总的微服务项目:PIG,欢迎大家 start、fork。PIG 大概是我从零开始学 springcloud 里面最容易上手的微服务项目,基础设施健全,技术群内也非常活跃,这里给大家强势安利一波++请戳官网++。
这里我们使用 IDEA 代码编辑工具。
1.1 准备代码
在你的宿主机上创建代码存放目录,将代码 clone 到此目录中运行如下命令:
# 1. 后台代码 git clone https://gitee.com/log4j/pig.git # 2. 前台代码 git clone https://gitee.com/log4j/pig-ui.git # 3. 配置文件 git clone https://gitee.com/cqzqxq_lxh/pig-config.git
1.2 改造项目并上传到 Gitlab
用 IDEA 打开我们刚刚准备好的三个项目。我们先将微服务的配置本地化:
- 在 pig-config 模块下创建 config 文件夹
- 将 pig-config 项目下的所有配置文件都拷贝到 config 文件夹下
- 修改 pig-config 模块的配置文件
如下图:
1.3 在 Gitlab 上创建项目
我这里将项目重命名了,你们也可以将项目重命名(注意自己重命名之后的 Git Url)。下面就是我在 gitlab 上创建的 pig 的前后台项目:
在 IDEA 中打开 pig 项目的终端输入如下内容:
git remote rename origin old-origin
git remote add origin http://192.168.1.100/Maozk/k8s-pig.git
git push -u origin --all
git push -u origin --tags
在 IDEA 中打开 pig-ui 项目的终端输入如下内容:
git remote rename origin old-origin
git remote add origin http://192.168.1.100/Maozk/k8s-pig-ui.git
git push -u origin --all
git push -u origin --tags
终端在这里打开:
这样我们就把从码云 clone 下来的代码推送到了我们自己的代码托管服务 Gitlab 上了。
2. 将 Gitlab 和 Jenkins 连接起来
2.1 Jenkins 配置修改
系统管理 > 全局安全配置
2.2 安装 Generic Webhook Trigger Plugin
- 系统管理 > 管理插件 > 可选插件 Tab 页
- 在过滤里面输入:Generic Webhook Trigger
- 然后勾选要安装的插件:Generic Webhook Trigger Plugin
- 点击直接安装,等待安装完成即可。
2.3 新建一个任务:Jenkins-pig
我这里已经有一个相同名称的任务了,大家忽略我这个错误即可。
- 输入任务名称
- 选择流水线(pipeline)
- 点击确定
2.4 配置 Jenkins-pig 任务
这里的 Pipeline 脚本我们后面再细讲,这里主要配置了如何监听用户对 Gitlab 不同的操作时触发什么构建。
在这里我们就可以实现了提交不同的分支时触发不同的构建。
2.5 创建任务:Jenkins-pig-ui
这里创建 pig-ui 任务和创建 pig 任务差不多,主要是注意监听的仓库路径要替换成 pig-ui 的。
3. 和 Gitlab 连接
首先用 admin 用户登录 Gitlab,然后配置 Gitlab 能请求本地 IP。
然后选择 System Hooks
我们这里再看一下 Gitlab 发送的 JSon 数据
编辑我们创建的 System Hooks,在页面的最先发你会看见触发构建的历史数据,点击 View details。
你就会从 Request body 中看见本次请求的操作类型 object_kind: push 为提交代码,分支是 ref : refs/heads/master。
仓库地址:repository{"git_http_url": "http://192.168.1.100/Maozk/k8s-pig-ui.git"}
Request body:
{
"object_kind": "push",
"event_name": "push",
"before": "6242b95eb45ef3ca6137e1ed97d13467a66a2e48",
"after": "baf2b2b5f098673088aa14b3349acd35b9e12a24",
"ref": "refs/heads/master",
"checkout_sha": "baf2b2b5f098673088aa14b3349acd35b9e12a24",
"message": null,
"user_id": 1,
"user_name": "Maozk",
"user_username": "Maozk",
"user_email": "[email protected]",
"user_avatar": "http://192.168.1.100/uploads/-/system/user/avatar/1/avatar.png",
"project_id": 2,
"project": {
"id": 2,
"name": "k8s-pig-ui",
"description": "",
"web_url": "http://192.168.1.100/Maozk/k8s-pig-ui",
"avatar_url": null,
"git_ssh_url": "[email protected]:Maozk/k8s-pig-ui.git",
"git_http_url": "http://192.168.1.100/Maozk/k8s-pig-ui.git",
"namespace": "Maozk",
"visibility_level": 20,
"path_with_namespace": "Maozk/k8s-pig-ui",
"default_branch": "master",
"ci_config_path": null,
"homepage": "http://192.168.1.100/Maozk/k8s-pig-ui",
"url": "[email protected]:Maozk/k8s-pig-ui.git",
"ssh_url": "[email protected]:Maozk/k8s-pig-ui.git",
"http_url": "http://192.168.1.100/Maozk/k8s-pig-ui.git"
},
"commits": [
{
"id": "baf2b2b5f098673088aa14b3349acd35b9e12a24",
"message": "修改标签页\n",
"timestamp": "2018-08-15T09:02:05Z",
"url": "http://192.168.1.100/Maozk/k8s-pig-ui/commit/baf2b2b5f098673088aa14b3349acd35b9e12a24",
"author": {
"name": "[email protected]",
"email": "jia327926"
},
"added": [
],
"modified": [
],
"removed": [
"dist/index.html",
]
}
],
"total_commits_count": 1,
"repository": {
"name": "k8s-pig-ui",
"url": "[email protected]:Maozk/k8s-pig-ui.git",
"description": "",
"homepage": "http://192.168.1.100/Maozk/k8s-pig-ui",
"git_http_url": "http://192.168.1.100/Maozk/k8s-pig-ui.git",
"git_ssh_url": "[email protected]:Maozk/k8s-pig-ui.git",
"visibility_level": 20
}
}
此时你只要是提交的操作就会触发 Jenkins 的构建。
至此我们就将代码、Gitlab、Jenkins 连接起来了。
4.部署我们的微服务到 k8s 集群 (192.168.1.11)
# 1.创建脚本存放文件夹
mkdir /soft/project/pig/script -p
cd /soft/project/pig/script
在 k8s 集群里创建我们项目的命名空间
kubectl create namespace kube-pig
4.1 在 k8s 中部署 mysql、rabbitmq、redis
- 部署 mysql
编写 k8s-mysql-pvc.yaml 使 mysql 数据持久化
vim k8s-mysql-pvc.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: k8s-mysql-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: pig-mysql
hostPath:
path: /soft/data/pig/mysql
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: k8s-mysql-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: pig-mysql
编写 mysql 运行的 k8s-mysql-pig.yaml
vim k8s-mysql-pig.yaml
apiVersion: v1
kind: Service
metadata:
name: k8s-mysql-pig
spec:
type: NodePort
ports:
- port: 3306
nodePort: 32307
targetPort: 3306
selector:
app: k8s-mysql-pig
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: k8s-mysql-pig-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: k8s-mysql-pig
spec:
containers:
- image: mysql:5.7
name: k8s-mysql-pig
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "root"
volumeMounts:
- name: k8s-mysql-pig-data
mountPath: /var/lib/mysql
volumes:
- name: k8s-mysql-pig-data
persistentVolumeClaim:
claimName: k8s-mysql-pvc
注意这里的数据持久化是通过:
volumes.persistentVolumeClaim.claimName:k8s-mysql-pvc
将mysql 和 pvc 绑定的。
kubectl create -f k8s-mysql-pvc.yaml --namespace kube-pig
kubectl create -f k8s-mysql-pig.yaml --namespace kube-pig
然后在宿主机用 mysql 客户端创建数据库 pig,运行项目下的 pig.sql 脚本来初始化数据库。
连接地址:192.168.1.11:32307 用户名:root 密码:root。
- 部署 rabbitmq
vim k8s-rabbitmq-pig.yaml
apiVersion: v1
kind: Service
metadata:
name: k8s-rabbitmq-pig
spec:
type: NodePort
ports:
- name: rabbit-cli
port: 5671
targetPort: 5671
- name: rabbit-page
port: 15671
targetPort: 15671
- name: rabbit-cli1
port: 5672
targetPort: 5672
- name: rabbit-page1
port: 15672
targetPort: 15672
nodePort: 30072
- name: rabbit-page2
port: 25672
targetPort: 25672
selector:
app: k8s-rabbitmq-pig
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: k8s-rabbitmq-pig-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: k8s-rabbitmq-pig
spec:
containers:
- image: rabbitmq:3.7.7-management
name: k8s-rabbitmq-pig
ports:
- containerPort: 5671
- containerPort: 15671
- containerPort: 5672
- containerPort: 15672
- containerPort: 25672
env:
- name: RABBITMQ_DEFAULT_USER
value: "redis"
- name: RABBITMQ_DEFAULT_PASS
value: "redis"
这里我们指定了 rabbitmq 默认的用户和密码为 redis,并配置了其外部的访问端口为 30072。
kubectl create -f k8s-rabbitmq-pig.yaml --namespace kube-pig
- 部署 redis
vim k8s-redis-pig.yaml
apiVersion: v1
kind: Service
metadata:
name: k8s-redis-pig
spec:
type: ClusterIP
ports:
- port: 6379
targetPort: 6379
selector:
app: k8s-redis-pig
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: k8s-redis-pig-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: k8s-redis-pig
spec:
containers:
- image: redis:3.2
name: k8s-redis-pig
ports:
- containerPort: 6379
volumeMounts:
- name: k8s-redis-pig-conf
mountPath: /etc/redis
volumes:
- name: k8s-redis-pig-conf
hostPath:
path: /soft/data/redis
kubectl create -f k8s-redis-pig.yaml --namespace kube-pig
至此我们创建完了这些外部服务,分别是 k8s-redis-pig、k8s-rabbitmq-pig、k8s-mysql-pig,在集群内我们都是根据服务名来访问具体的服务的,所以下面我们需要改造我们代码的配置文件,改成我们在 k8s 中的服务名。
4.2 修改代码配置文件
修改 Dockerfile,我们这里不用 pig 原来的 Dockerfile,因为我们这里只部署主要的服务,而且不使用 docker-compose 所以需要修改一下,并且重名。
pig-auth
FROM hub.k8s.com/k8s-pig/java:8-jre
MAINTAINER Pig lengleng <[email protected]>
ADD pig-auth.jar /app/
CMD ["java", "-Xmx500m", "-jar", "/app/pig-auth.jar"]
EXPOSE 3000
pig-config
FROM hub.k8s.com/k8s-pig/java:8-jre
MAINTAINER Pig lengleng <[email protected]>
ADD pig-config.jar /app/
CMD ["java", "-Xmx200m", "-jar", "/app/pig-config.jar"]
EXPOSE 4001
pig-eureka
FROM hub.k8s.com/k8s-pig/java:8-jre
MAINTAINER Pig lengleng <[email protected]>
ADD pig-eureka.jar /app/
CMD ["java", "-Xmx200m", "-jar", "/app/pig-eureka.jar"]
EXPOSE 1025
pig-gateway
FROM hub.k8s.com/k8s-pig/java:8-jre
MAINTAINER Pig lengleng <[email protected]>
ADD pig-gateway.jar /app/
CMD ["java", "-Xmx500m", "-jar", "/app/pig-gateway.jar"]
EXPOSE 9999
pig-upms-service
FROM hub.k8s.com/k8s-pig/java:8-jre
MAINTAINER Pig lengleng <[email protected]>
ADD pig-upms-service.jar /app/
CMD ["java", "-Xmx1000m", "-jar", "/app/pig-upms-service.jar"]
EXPOSE 4000
所有模块下的 bootstrap.yml 文件里的服务注册地址都要改为 http://pig:gip6666@pig-eureka:1025/eureka。
包括 pig-config 下的 application.yml 文件。
修改 pig-gateway 下的 bootstrap.yml 的认证服务器地址:
修改 pig-config 模块下的 config 文件夹下的配置文件:
application-dev.yml
pig-auth-dev.yml
pig-upms-service-dev.yml
总之就是把所有和其他服务相关联的都要改成服务名。这里的服务名是我们服务在 k8s 集群中的服务名。
4.3 编写我们的构建脚本
打开我们在 Jenkins 创建的 Jenkins-pig 任务,在最后的 Pipeline script 项中添加如下内容:
#!groovy
pipeline {
agent any
environment{
REPOSITORY="http://192.168.1.100/Maozk/k8s-pig.git"
SCRIPT_PATH="/soft/project/pig/script"
}
stages {
stage('获取代码') {
steps {
echo "start fetch code from gitlab:${REPOSITORY}"
deleteDir()
git "${REPOSITORY}"
}
}
stage('编译') {
steps {
echo "start compile"
sh "mvn -U -am clean package -Dmaven.test.skip=true"
}
}
stage('构建镜像') {
steps {
echo "start build images"
sh "${SCRIPT_PATH}/k8s-pig-build.sh k8s-pig ${SCRIPT_PATH}"
}
}
}
}
SCRIPT_PATH 就是我们脚本存放的路径,REPOSITORY 代码仓库地址。
在我们脚本存放的路径创建构建 docker 镜像的脚本。
cd /soft/project/pig/script
vim k8s-pig-build.sh
#!/bin/bash
#时间格式化
TIME_TAG=`date "+%Y%m%d%H%M"`
#Docker 私有仓库地址
IMAGE_REPOSITORY=hub.k8s.com/$1/
# git提交的版本
GIT_VERSION=`git log -1 --pretty=format:"%h"`
MOUDLE=(pig-eureka pig-config pig-auth pig-gateway)
cd doc/docker/
echo "DockerFile所在当前路径:" && pwd
for moudleName in ${MOUDLE[@]};do
echo "构建$moudleName is begining.."
# 创建模块的Dockerfile文件夹
mkdir -p Docker_$moudleName
mv $moudleName Docker_$moudleName/Dockerfile
cd ../../
echo "目录:" && pwd
#将打好的jar包移动到模块的Dockerfile文件夹下
mv $moudleName/target/$moudleName.jar doc/docker/Docker_$moudleName/$moudleName.jar
cd doc/docker/Docker_$moudleName
#组装docker镜像的名称
IMAGE_NAME=${IMAGE_REPOSITORY}$moudleName:${TIME_TAG}_${GIT_VERSION}
echo "开始构建镜像:${IMAGE_NAME}"
docker build -t ${IMAGE_NAME} .
echo "开始推送镜像:${IMAGE_NAME}至私有仓库:${IMAGE_REPOSITORY}"
docker push ${IMAGE_NAME}
echo "删除当前镜像:${IMAGE_NAME}"
docker rmi ${IMAGE_NAME}
cd ../
#将构建好的镜像名称存到本地,后面发布的时候会用到
echo "${IMAGE_NAME}" > $2/image_$moudleName
echo "构建$moudleName is ending..."
done
echo "目录DOCKER:" && pwd
mkdir Docker_pig-upms-service
cd ../../
echo "目录:" && pwd
cd pig-modules/pig-upms-service/target/
echo "目录JAR->:" && pwd && ls
mv pig-upms-service.jar /root/.jenkins/workspace/Jenkins-pig/doc/docker/Docker_pig-upms-service/pig-upms-service.jar
cd ../../../
mv doc/docker/pig-upms-service doc/docker/Docker_pig-upms-service/Dockerfile
echo "目录:" && pwd && ls
cd doc/docker/Docker_pig-upms-service
echo "开始构建:${IMAGE_REPOSITORY}pig-upms-service:${TIME_TAG}_${GIT_VERSION}"
docker build -t ${IMAGE_REPOSITORY}pig-upms-service:${TIME_TAG}_${GIT_VERSION} .
echo "开始推送:${IMAGE_REPOSITORY}pig-upms-service:${TIME_TAG}_${GIT_VERSION}"
docker push ${IMAGE_REPOSITORY}pig-upms-service:${TIME_TAG}_${GIT_VERSION}
echo "删除当前镜像:${IMAGE_REPOSITORY}pig-upms-service:${TIME_TAG}_${GIT_VERSION}"
docker rmi ${IMAGE_REPOSITORY}pig-upms-service:${TIME_TAG}_${GIT_VERSION}
echo "${IMAGE_REPOSITORY}pig-upms-service:${TIME_TAG}_${GIT_VERSION}" > $2/image_pig-upms-service
echo "构建pig-upms-service is ending..."
echo "所有镜像构建、推送完毕..."
为脚本添加可执行权限
chmod -R 777 k8s-pig-build.sh
脚本都有注释,这里说一下脚本中传入了两个参数,k8s-pig 为 docker 私有仓库中创建的项目,scriptpath 为脚本存放地址。这样动态传值就会让我们的脚本针对 pig 项目变得通用起来,可以用私有仓库的项目来区分不同的环境。
以及 pig-upms-service 模块并没有放到 for 循环中,因为 pig-upms-service 模块目录层级更深一级。
4.4 在 k8s 集群中初始化我们的项目
这里说一下,项目第一次部署的时候需要我们手动的在集群中创建,只有已存在的项目才能升级。我们需要登录到私有仓库获取每个模块的镜像名称。
k8s-pig-eureka.yaml
vim k8s-pig-eureka.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: pig-eureka
name: pig-eureka
spec:
ports:
- port: 1025
protocol: TCP
targetPort: 1025
nodePort: 30001
selector:
app: pig-eureka
type: NodePort
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: pig-eureka-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: pig-eureka
spec:
containers:
- name: pig-eureka
image: hub.k8s.com/k8s-pig/pig-eureka:201808142201_67bd117
ports:
- containerPort: 1025
这里我们指定了外部访问的端口:30001
kubectl create -f k8s-pig-eureka.yaml --namespace kube-pig
k8s-pig-config.yaml
vim k8s-pig-config.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: pig-config
name: pig-config
spec:
ports:
- port: 4001
protocol: TCP
targetPort: 4001
selector:
app: pig-config
type: ClusterIP
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: pig-config-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: pig-config
spec:
containers:
- name: pig-config
image: hub.k8s.com/k8s-pig/pig-config:201808142231_35f7388
ports:
- containerPort: 4001
kubectl create -f k8s-pig-config.yaml --namespace kube-pig
k8s-pig-auth.yaml
vim k8s-pig-auth.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: pig-auth
name: pig-auth
spec:
ports:
- port: 3000
protocol: TCP
targetPort: 3000
selector:
app: pig-auth
type: ClusterIP
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: pig-auth-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: pig-auth
spec:
containers:
- name: pig-auth
image: hub.k8s.com/k8s-pig/pig-auth:201808142231_35f7388
ports:
- containerPort: 3000
kubectl create -f k8s-pig-auth.yaml --namespace kube-pig
k8s-pig-gateway.yaml
vim k8s-pig-gateway.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: pig-gateway
name: pig-gateway
spec:
ports:
- port: 9999
protocol: TCP
targetPort: 9999
nodePort: 30080
selector:
app: pig-gateway
type: NodePort
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: pig-gateway-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: pig-gateway
spec:
containers:
- name: pig-gateway
image: hub.k8s.com/k8s-pig/pig-gateway:201808142231_35f7388
ports:
- containerPort: 9999
这里我们指定了外部访问的端口:30080
kubectl create -f k8s-pig-gateway.yaml --namespace kube-pig
k8s-pig-upms-service.yaml
vim k8s-pig-upms-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: pig-upms-service
name: pig-upms-service
spec:
ports:
- port: 4000
protocol: TCP
targetPort: 4000
selector:
app: pig-upms-service
type: ClusterIP
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: pig-upms-service-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: pig-upms-service
spec:
containers:
- name: pig-upms-service
image: hub.k8s.com/k8s-pig/pig-upms-service:201808142231_35f7388
ports:
- containerPort: 4000
kubectl create -f k8s-pig-upms-service.yaml --namespace kube-pig
部署完我们的服务可以访问 192.168.1.11:30001 看一下我们的服务的状态,是否注册到 eureka。
到这里我们初始化完我们的微服务。
4.5 让我们的微服务可以在 k8s 里平滑的升级
在 Jenkins 中修改我们的任务 Jenkins-pig,把我们的构建脚本改为如下内容:
#!groovy
pipeline {
agent any
environment{
REPOSITORY="http://192.168.1.100/Maozk/k8s-pig.git"
SCRIPT_PATH="/soft/project/pig/script"
}
stages {
stage('获取代码') {
steps {
echo "start fetch code from gitlab:${REPOSITORY}"
deleteDir()
git "${REPOSITORY}"
}
}
stage('编译') {
steps {
echo "start compile"
sh "mvn -U -am clean package -Dmaven.test.skip=true"
}
}
stage('构建镜像') {
steps {
echo "start build images"
sh "${SCRIPT_PATH}/k8s-pig-build.sh k8s-pig ${SCRIPT_PATH}"
}
}
stage('发布系统') {
steps {
echo "start deploy pods"
sh "${SCRIPT_PATH}/k8s-pig-deploy.sh ${SCRIPT_PATH} kube-pig"
}
}
}
}
增加了一步:发布系统,传入了两个参数,和构建镜像的思路一样都是希望针对 pig 项目脚本能通用。
编写我们的部署脚本:
vim k8s-pig-deploy.sh
#获取最新的镜像名称
PIG_CONFIG_IMAGE=`cat $1/image_pig-config`
#替换运行中服务的镜像
echo "update image to deployments/pig-config-deployment pig-config:${PIG_CONFIG_IMAGE}"
kubectl set image deployments/pig-config-deployment pig-config=${PIG_CONFIG_IMAGE} --namespace=$2
echo "update pig-config is ending"
# 延迟的作用是因为服务的发布是有先后顺序的
sleep 30s
PIG_AUTH_IMAGE=`cat $1/image_pig-auth`
echo "update image to deployments/pig-auth-deployment pig-auth:${PIG_AUTH_IMAGE}"
kubectl set image deployments/pig-auth-deployment pig-auth=${PIG_AUTH_IMAGE} --namespace=$2
echo "update pig-auth is ending"
sleep 30s
PIG_GATEWAY_IMAGE=`cat $1/image_pig-gateway`
echo "update image to deployments/pig-gateway-deployment pig-gateway:${PIG_GATEWAY_IMAGE}"
kubectl set image deployments/pig-gateway-deployment pig-gateway=${PIG_GATEWAY_IMAGE} --namespace=$2
echo "update pig-gateway is ending"
sleep 30s
PIG_UPMS_SERVICE_IMAGE=`cat $1/image_pig-upms-service`
echo "update image to deployments/pig-upms-service-deployment pig-upms-service:${PIG_UPMS_SERVICE_IMAGE}"
kubectl set image deployments/pig-upms-service-deployment pig-upms-service=${PIG_UPMS_SERVICE_IMAGE} --namespace=$2
echo "update pig-upms-service is ending"
为脚本添加可执行权限
chmod -R 777 k8s-pig-deploy.sh
到这里我们就已经将代码、gitlab、Jenkins、k8s、harbor 连起来了。
4.6 部署前端项目
4.6.1 初始化前端项目
修改我们前端的配置文件
在我们的前端工程下创建一个文件夹:docker
新建两个文件 Dockerfile 和 default.conf
Dockerfile
FROM hub.c.163.com/library/nginx
MAINTAINER Maozk <[email protected]>
RUN rm /etc/nginx/conf.d/default.conf
ADD default.conf /etc/nginx/conf.d/
COPY dist/ /usr/share/nginx/html/
COPY favicon.ico /usr/share/nginx/html/
default.conf
server {
listen 9000;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location ~ ^/favicon\.ico$ {
root /usr/share/nginx/html/favicon.ico;
}
location ^~ /auth/ {
proxy_pass http://pig-gateway:9999;
}
location ^~ /admin/ {
proxy_pass http://pig-gateway:9999;
}
}
上面两个文件主要是在构建 Docker 镜像时替换掉 nginx 原来的 default.conf,要注意我们配置文件中的代理地址。
为 Jenkins 任务 Jenkins-pig-ui 添加构建脚本
#!groovy
pipeline {
agent any
environment{
REPOSITORY="http://192.168.1.100/Maozk/k8s-pig-ui.git"
SCRIPT_PATH="/soft/project/pig/script/ui"
}
stages {
stage('获取代码') {
steps {
echo "start fetch code from gitlab:${REPOSITORY}"
deleteDir()
git "${REPOSITORY}"
}
}
stage('编译代码') {
steps {
echo "start npm run build"
sh "npm install"
sh "npm run build"
}
}
stage('构建镜像') {
steps {
echo "start build nginx images"
sh "${SCRIPT_PATH}/k8s-pig-ui-build.sh k8s-pig ${SCRIPT_PATH}"
}
}
}
}
在我们脚本存放路径创建脚本(前端的脚本路径和后端的不一样)
vim k8s-pig-ui-build.sh
TIME_TAG=`date "+%Y%m%d%H%M"`
IMAGE_REPOSITORY=hub.k8s.com/$1/
GIT_VERSION=`git log -1 --pretty=format:"%h"`
IMAGE_NAME="${IMAGE_REPOSITORY}pig-ui:${TIME_TAG}_${GIT_VERSION}"
echo "移动静态文件到docker目录"
mv dist docker/dist
cd docker/
echo "开始构建镜像:${IMAGE_NAME}"
docker build -t ${IMAGE_NAME} .
echo "开始推送镜像:${IMAGE_NAME}至私有仓库:${IMAGE_REPOSITORY}"
docker push ${IMAGE_NAME}
echo "删除当前镜像:${IMAGE_NAME}"
docker rmi ${IMAGE_NAME}
echo "${IMAGE_NAME}" > $2/image_pig-ui
echo "构建pig-ui is ending..."
在 k8s 集群中初始化运行我们的前端项目
vim k8s-pig-ui.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: pig-ui
name: pig-ui
spec:
ports:
- port: 9000
protocol: TCP
targetPort: 9000
nodePort: 30000
selector:
app: pig-ui
type: NodePort
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: pig-ui-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: pig-ui
spec:
containers:
- name: pig-ui
image: hub.k8s.com/k8s-pig/pig-ui:201808150355_70a58dd
ports:
- containerPort: 9000
指定暴露集群端口:30000
kubectl create -f k8s-pig-ui.yaml --namespace kube-pig
现在我们在宿主机浏览器中访问 192.168.1.11:30000 就可以访问我们的部署好的微服务了,默认用户名密码 admin/123456。
4.7 让我们的前端项目也变成可平滑升级的服务
修改我们的构建脚本,修改为如下内容:
#!groovy
pipeline {
agent any
environment{
REPOSITORY="http://192.168.1.100/Maozk/k8s-pig-ui.git"
SCRIPT_PATH="/soft/project/pig/script/ui"
}
stages {
stage('获取代码') {
steps {
echo "start fetch code from gitlab:${REPOSITORY}"
deleteDir()
git "${REPOSITORY}"
}
}
stage('编译代码') {
steps {
echo "start npm run build"
sh "npm install"
sh "npm run build"
}
}
stage('构建镜像') {
steps {
echo "start build nginx images"
sh "${SCRIPT_PATH}/k8s-pig-ui-build.sh k8s-pig ${SCRIPT_PATH}"
}
}
stage('部署镜像') {
steps {
echo "start deploy nginx images"
sh "${SCRIPT_PATH}/k8s-pig-ui-deploy.sh ${SCRIPT_PATH} kube-pig"
}
}
}
}
我们增加了一步:部署镜像,添加我们的部署脚本。
vim k8s-pig-ui-deploy.sh
echo "部署镜像"
IMAGE_NAME=`cat $1/image_pig-ui`
echo "update image to deployments/pig-ui-deployment pig-ui:${IMAGE_NAME}"
kubectl set image deployments/pig-ui-deployment pig-ui=${IMAGE_NAME} --namespace=$2
echo "update pig-ui is ending"
添加脚本执行权限
chmod -R 777 k8s-pig-ui-deploy.sh
4.8 配置 Jenkins 邮件服务,将部署信息反馈给我们
4.8.1 安装邮件服务的插件 Email Extension Plugin
参考我们之前安装插件的方法之间安装就好。
4.8.2 配置全局邮箱
系统管理 > 系统设置 > 完成邮箱配置
4.8.3 配置邮件服务
Default Recipients这一项配置多个收件人用逗号隔开。
这里已经返回我们测试邮件的结果。
到这里我们已经将 pig 和 pig-ui 部署到了 k8s 集群环境中,并且配置了 Jenkins 监听指定分支的任务,和构建脚本中平滑的升级 k8s 中的微服务。我们如何实现分环境部呢?我们可以新建一个构建任务例如:Jenkins-pig-dev,配置任务中监听提交的代码分支为refs/heads/master,在构建脚本里的构建镜像传入不同的仓库项目,部署镜像里传入不同命名空间。
需要注意的几件事
- 部署之前要自己手动的在集群中部署项目。
-
所有的脚本都需要可执行权限。
-
部署的项目都需要指定命名空间,不指定默认为 default,这样不利于我们区分。
-
第一次部署时都要去私有镜像仓库可视化界面获取镜像名称,然后把yaml中的镜像替换掉。
八、 常见问题和常用命令
1. Git 常用命令
# Git global setup
git config --global user.name "Maozk"
git config --global user.email "[email protected]"
# Create a new repository
git clone http://192.168.1.100/Maozk/test.git
cd test
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master
# Existing folder
cd existing_folder
git init
git remote add origin http://192.168.1.100/Maozk/test.git
git add .
git commit -m "Initial commit"
git push -u origin master
# Existing Git repository
cd existing_repo
git remote rename origin old-origin
git remote add origin http://192.168.1.100/Maozk/test.git
git push -u origin --all
git push -u origin --tags
2. Docker 常用命令
菜鸟教程 Docker 命令大全:http://www.runoob.com/docker/docker-command-manual.html
3. kubernetes 常用命令
kubectl get cs //查看集群信息
kubectl get componentstatuses //查看node节点组件状态
kubectl get svc -n kube-system //查看应用
kubectl cluster-info //查看集群信息
kubectl cluster-info dump //更详细的集群信息
kubectl describe --namespace kube-system service kubernetes-dashboard //详细服务信息
kubectl apply -f kube-apiserver.yaml //更新kube-apiserver容器
kubectl delete -f /root/k8s/k8s_images/kubernetes-dashboard.yaml //删除应用
kubectl delete service example-server //删除服务
systemctl start kube-apiserver.service //启动服务。
kubectl get deployment --all-namespaces //启动的应用
kubectl get pod -o wide --all-namespaces //查看pod上跑哪些服务
kubectl get pod -o wide -n kube-system //查看应用在哪个node上
kubectl describe pod --namespace=kube-system //查看pod上活动信息
kubectl describe depoly kubernetes-dashboard -n kube-system
kubectl get depoly kubernetes-dashboard -n kube-system -o yaml
kubectl get service kubernetes-dashboard -n kube-system //查看应用
kubectl delete -f kubernetes-dashboard.yaml //删除应用
kubectl get events //查看事件
kubectl get rc/kubectl get svc
kubectl get namespace //获取namespace信息
kubectl delete node 节点名 //删除节点
kubectl create namespace {名称} //创建namespace
kubectl config set-context $(kubectl config current-context) --namespace={名称} //设置当前namespace
kubectl get service,deployment,pod
4. 常见问题
1.重新初始化 Master 节点或者各个子节点
kubeadm reset
重新初始化配置 k8s 集群,子节点重新 join。
**2.子节点加入 Master 时 Token 过期。
默认 token 的有效期为 24 小时,当过期之后,该 token 就不可用了。
解决方法如下:
#1. 重新生成Token
kubeadm token create
#2.获取ca证书sha256编码hash值
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
#3. 子节点加入集群
kubeadm join 10.0.0.147:6443 --token <New Token> --discovery-token-ca-cert-hash sha256:<New SSH>
4.The connection to the server localhost:8080 was refused – did you specify the right host or port?
在该节点机器上执行如下命令:
sudo cp /etc/kubernetes/kubelet.conf $HOME/
sudo chown $(id -u):$(id -g) $HOME/kubelet.conf
export KUBECONFIG=$HOME/kubelet.conf
5.子节点加入不到 Master,或者子节点访问不了 Api Server
初始化 Master 的时候需要指定 Api Server 能够被访问的 IP 0.0.0.0 是任何 IP 等能访问。
6.Get https://docker-registry:5000/v1/_ping: http: server gave HTTP response to HTTPS client
vim /etc/docker/daemon.json
# 加入如下内容:
{ "insecure-registries":["hub.k8s.com"] }
# 重启服务
systemctl restart docker
7.Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen
# 重启服务
systemctl restart docker
九、效果预览
十、 总结
我们这里已经完成了 kubernetes 持续集成 springcloud,本文以实践为主,希望我这有限的文笔能够将这些东西讲的清楚,这篇文章就是对开篇流程图的具体实现,也仅仅是实验环境下,能够让大家了解了解是如何实现的,希望能够大家带来帮助。
REFER:
https://github.com/ChinaSilence/micro
https://gitee.com/log4j/pig
https://gitee.com/minull/ace-security
https://github.com/sqshq/PiggyMetrics