K8s

分布式编排管理集群的系统

一、K8s快速入门

1、简介

kubernetes简称k8s。是用于自动部署,扩展和管理容器化应用程序的开源系统。

中文官网:https://kubernetes.io/Zh/

中文社区:https://www.kubernetes.org.cn/

官方文档:https://kubernetes.io/zh/docs/home/

社区文档:https://docs.kubernetes.org.cn/

  • 部署方式的进化

    • 传统部署时代:

      早期,各个组织机构在物理服务器上运行应用程序。无法为物理服务器中的应用程序定义资源边界,这会导致资源分配问题。 例如,如果在物理服务器上运行多个应用程序,则可能会出现一个应用程序占用大部分资源的情况, 结果可能导致其他应用程序的性能下降。 一种解决方案是在不同的物理服务器上运行每个应用程序,但是由于资源利用不足而无法扩展, 并且维护许多物理服务器的成本很高。

    • 虚拟化部署时代:

      作为解决方案,引入了虚拟化。虚拟化技术允许你在单个物理服务器的 CPU 上运行多个虚拟机(VM)。 虚拟化允许应用程序在 VM 之间隔离,并提供一定程度的安全,因为一个应用程序的信息 不能被另一应用程序随意访问。

      虚拟化技术能够更好地利用物理服务器上的资源,并且因为可轻松地添加或更新应用程序 而可以实现更好的可伸缩性,降低硬件成本等等。

      每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统。

    • 容器部署时代:

      容器类似于 VM,但是它们具有被放宽的隔离属性,可以在应用程序之间共享操作系统(OS)。 因此,容器被认为是轻量级的。容器与 VM 类似,具有自己的文件系统、CPU、内存、进程空间等。 由于它们与基础架构分离,因此可以跨云和 OS

      • 好处

        • 敏捷应用程序的创建和部署:与使用 VM 镜像相比,提高了容器镜像创建的简便性和效率。
        • 持续开发、集成和部署:通过快速简单的回滚(由于镜像不可变性),支持可靠且频繁的 容器镜像构建和部署。
        • 关注开发与运维的分离:在构建/发布时而不是在部署时创建应用程序容器镜像, 从而将应用程序与基础架构分离。
          可观察性不仅可以显示操作系统级别的信息和指标,还可以显示应用程序的运行状况和其他指标信号。
        • 跨开发、测试和生产的环境一致性:在便携式计算机上与在云中相同地运行。
        • 跨云和操作系统发行版本的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方运行。
        • 以应用程序为中心的管理:提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序。
        • 松散耦合、分布式、弹性、解放的微服务:应用程序被分解成较小的独立部分, 并且可以动态部署和管理 - 而不是在一台大型单机上整体运行。
        • 资源隔离:可预测的应用程序性能。
        • 资源利用:高效率和高密度。

2、架构

  • 整体主从方式

Node节点被Master管理,Node节点负责干活,Master负责管理下命令等…

可通过左侧的UI可视化界面或者CLI命令行去发送操作API,API去告诉Master,Master来判断告诉具体是哪个Node节点做什么内容

  • master节点架构

  • Node节点架构

POD是最小的单位

kube-proxy对外代理一个个的Pod

kunelet来管理每个Pod单位


3、概念


4、快速体验

  • 安装minikube
https://github.com/kubernetes/minikube/releases
下载minikuber-windows-amd64.exe 改名为minikube.exe
打开virtualBox,打开cmd
运行
minikube start --vm-driver=virtualbox --registry-mirror=https://registry.docker-cn.com
等待20分钟即可。
  • 体验nginx部署升级

提交一个nginx deployment

kubectl apply -f https://k8s.io/examples/application/deployment.yaml

升级 nginx deployment

kubectl apply -f https://k8s.io/examples/application/deployment-update.yaml

扩容

nginx deployment

二、K8s集群安装

1、kubeadm

kubeadm是官方社区推出的一个用于快速部署kuberneters集群的工具
这个工具能通过两条指令完成一个kuberneters集群的部署

  • 创建一个master节点
$ kuberneters init
  • 将一个node节点加入到当前集群中
$ kubeadm join <Master节点的IP和端口>

2、前置要求

一台或多台机器,操作系统Centos7.x-86_x64

硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多

集群中所有的机器之间网络互通

可以访问外网,需要拉取镜像

禁止Swap分区

3、部署步骤

  1. 在所有的节点上安装Dockerkubeadm
  2. 不是Kubernetes Master
  3. 部署容器网络插件
  4. 部署Kubernetes Node,将节点加入Kubernetes集群中
  5. 部署DashBoard web页面,可视化查看Kubernetes资源


4、环境准备

①准备工作

  • 可以使用vagrant的Vagrantfile文件快速创建三个虚拟机k8s-node1,k8s-node2和k8s-node3。

Vagrantfile文件内容如下:

Vagrant.configure("2") do |config|(1..3).each do |i|config.vm.define "k8s-node#{i}" do |node|# 设置虚拟机的Boxnode.vm.box = "centos/7"# 设置虚拟机的主机名node.vm.hostname="k8s-node#{i}"# 设置虚拟机的IPnode.vm.network "private_network", ip: "192.168.56.#{99+i}", netmask: "255.255.255.0"# 设置主机与虚拟机的共享目录# node.vm.synced_folder "~/Documents/vagrant/share", "/home/vagrant/share"# VirtaulBox相关配置node.vm.provider "virtualbox" do |v|# 设置虚拟机的名称v.name = "k8s-node#{i}"# 设置虚拟机的内存大小4Gv.memory = 4096# 设置虚拟机的CPU个数v.cpus = 4endendend
end
  • 网卡

在VirtualBox的“主机网络管理器”中,有两个网卡,网卡1是“网络地址转换”:是为了方便本机和虚拟机同样都能访问到外界互联网。

网卡2是仅主机网络,是内部的私有网络,在配置时我们仅保留一个主机网卡:

  • 常规

需要装3个节点,需要消耗很大内存以此磁盘空间,选择它存储虚拟机的所有文件:


②创建三个虚拟机

  • 执行Vagrantfile文件,创建三个虚拟机k8s-node1、k8s-node1和k8s-node3
  • 按照博客链接开启远程ssh密码访问
https://blog.csdn.net/weixin_43334389/article/details/115697067

③NAT网络和前置环境

  • 添加NAT网络

在网络地址转换(NAT)的模式下,三个节点的eth0,IP地址相同。而这些地址是供kubernetes集群通信用的,不能相同。

为每个虚拟机添加NAT网络:

在“高级”选项中,刷新一下生成新的MAC地址,此时三者的eth0的IP地址为:

ip addr#查看eth0对应的ip地址10.0.2.15
10.0.2.4
10.0.2.55

④设置Linux环境

  • 关闭防火墙

在开发模式下,将其关闭,不用配置各种进出规则了。

systemctl stop firewalld
systemctl disable firewalld
  • 关闭selinux安全规则检查
# 全局禁掉
sed -i 's/enforcing/disabled/' /etc/selinux/config# 关闭当前会话窗口
setenforce 0

  • 关闭swap内存交换分区

该分区会影响kubernetes的性能。

#临时关闭,当前会话
swapoff -a sed -ri 's/.*swap.*/#&/' /etc/fstab #永久关闭free -g #验证,swap必须为0

  • 添加主机名和ip映射关系
vi /etc/hosts
10.0.2.15 k8s-node1
10.0.2.4 k8s-node2
10.0.2.5 k8s-node3

三个虚拟机能够互相ping通,且能够ping通外网baidu.com.。

  • 桥接的IPV4流量传递到iptables的链

不执行的话,会有一些流量统计指标的消失。

cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

应用规则:

sysctl --system
  • 同步最新时间
yum -y install ntpdatentpdate time.windows.com #同步最新时间
  • 对系统进行备份


5、所有节点安装docker、kubeadm、kubelet、kubectl

Kubenetes默认CRI(容器运行时)为Docker,因此先安装Docker。

①安装Docker

  • 卸载之前的docker
$ sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine
  • 安装Docker -CE
# 前置依赖
$ sudo yum install -y yum-utils \device-mapper-persistent-data \lvm2# 设置docker repo 的yum 位置
$ sudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.repo# 安装docker,以及docker-cli
$ sudo yum -y install docker-ce docker-ce-cli containerd.io
  • 配置docker加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{"registry-mirrors": ["https://eeqh66oo.mirror.aliyuncs.com"]
}
EOFsudo systemctl daemon-reload
sudo systemctl restart docker
  • 启动docker&设置docker开机自启

kubernetes运行时全靠docker的运行时环境,需要开机自启。

systemctl enable docker

基础环境准备好后,可以给三个虚拟机备份一下。


②添加阿里云yum源

  • 添加yum源

告诉kubernetes这些yum源地址,需要的东西在哪里安装。

cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

③安装kubeadm,kubelet和kubectl

  • 指定版本安装
# 检查yum源中是否有kuber有关的yum源
yum list|grep kubeyum install -y kubelet-1.17.3 kubeadm-1.17.3 kubectl-1.17.3# 开机启动并启动
systemctl enable kubelet
systemctl start kubelet
  • 查看kubelet启动状态
systemctl status kubelet

启动中,由于我们还有一些东西没有配置,启动不起来很正常。


④部署k8s-master

  • 使用下面的命令,那个镜像下失败后,需要等待很长时间。

apiserver-advertise-address是master机的ip地址

service-cidr是service子网

pod-network-cidr是pod子网

kubeadm init \
--apiserver-advertise-address=10.0.2.15 \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version v1.17.3 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=10.244.0.0/16kubeadm init \
--apiserver-advertise-address=172.22.30.3 \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version v1.17.3 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=10.244.0.0/16

因此,暂时不使用上面的初始化命令,首先使用下面的master_images.sh命令进行执行下载镜像,还可以查看进度,文件内容如下:

#!/bin/bashimages=(kube-apiserver:v1.17.3kube-proxy:v1.17.3kube-controller-manager:v1.17.3kube-scheduler:v1.17.3coredns:1.6.5etcd:3.4.3-0pause:3.1
)for imageName in ${images[@]} ; dodocker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
#   docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName  k8s.gcr.io/$imageName
done

然后再运行初始化命令:

$ kubeadm init \
--apiserver-advertise-address=10.0.2.15 \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version   v1.17.3 \
--service-cidr=10.96.0.0/16  \
--pod-network-cidr=10.244.0.0/16

–apiserver-advertise-address=10.0.2.15 :这里的IP地址是master主机的地址,为上面的eth0网卡的地址;

运行命令之后,会有下面的提示, (Kubernetes control-plane)Kubernetes控制面板初始化成功:

然后,按照提示创建一个用户:

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

可以参考下面网址:

 https://kubernetes.io/docs/concepts/cluster-administration/addons/
  • node2/3中执行下面命令,为kubernetes添加节点:
kubeadm join 10.0.2.15:6443 --token mmm5wg.30nuvjon44z9a22h \--discovery-token-ca-cert-hash sha256:62e44803f6c1e30e86a9d2a1f58f3636aae09850cb5feb5d2c7fd949c5d7d5c4kubeadm join 172.22.30.3:6443 --token ywh9li.cd9rwd6mhmqyxghr \--discovery-token-ca-cert-hash sha256:83e0d249a4760c59b13be6b8e08b4701267bf998d1361747be5be42dd59aa60b

我们需要按照下面的(3)首先部署一个网络,有网络之后其他人才能够进来构成网络,然后在两个slave节点(k8s-node2、k8s-node3)执行上述命令:

在k8s-node2节点显示:

在master节点中使用下面命令查看节点加入状况:

#获取所有节点
kubectl get nodes

使用下面命令监控pods运行状态:

watch kubectl get pod -n kube-system -o wide

当flannel文件运行起来后,集群中加入的节点就会ready状态:

  • 安装Pod网络插件(CNI)
# 部署一个应用
kubectl apply -f kube-flannel.yml# 删除这个文件中指定的所有资源
kubectl delete -f kube-flannel.yml

该命令会为整个集群安装非常多的规则和组件。

通过下面指令查看pods:

# 查看指定名称空间的pods
kubectl get pods -n kube-system# 查看指定所有名称空间的pods
kubectl get pods --all-namespaces # 监控pod进度
watch kubectl get pod -n kube-system -o wide


6、使用

①基本操作

  • 操作

部署一个tomcat

# 创建一个部署
kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8# 可以获取到tomcat信息
kubectl get pods -o wide

容器创建中:

创建四个文件,在第一个文件中,可以看到tomcat创建在node2节点:

查看node2节点相关镜像,可以看到该节点下载和运行了tomcat镜像:

在默认命名空间中:

当我们模拟宕机情况,将node2关掉电源,master节点中需要过一点时间才能检测到容灾恢复

在我的电脑中,master节点中需要5分钟左右才能在node3中重新拉起一个tomcat:

  • 暴露tomcat访问
#Pod的80映射容器tomcat的8080;
#service会代理Pod的80
# 封装成的service模式为NodePort,随机分配一个端口进行暴露
# --port pod的端口
# --target-port pod里面的tomcat容器的端口
# --type指定以何种方式暴露端口
kubectl expose deployment tomcat6 --port=80 --target-port=8080 --type=NodePort
#执行完会自动随机一个端口对外暴露

使用外网访问:

http://192.168.56.100:32671/

  • 动态扩容副本数量的测试
kubectl get deployment# 扩容-扩容了多份,所以无论访问哪个node的指定端口,都可以访问到tomcat6
# --replicas=扩容数
kubectl scale --replicas=3 deployment tomcat6

应用升级:kubectl set image(–help查看帮助)

  • 删除
# 获取资源后进行删除
kubectl get allkubectl delete deployment.apps/tomcat6
kubectl delete service/tomcat6

流程:创建deployment会管理replicas,replicas控制pod数量,有pod故障会自动拉起新的pod。


②yaml&基本使用

  • 参考网址
# kubectl文档
https://kubernetes.io/zh/docs/reference/kubectl/overview/# 资源类型
https://kubernetes.io/zh/docs/reference/kubectl/overview/#%e8%b5%84%e6%ba%90%e7%b1%bb%e5%9e%8b# 格式化输出
https://kubernetes.io/zh/docs/reference/kubectl/overview/

  • yaml模板

创建的部署和service都可以使用下面yaml格式进行操作:

查看某个pod的具体信息:

# --dry-run 测试运行并不真正执行;输出一点yaml
kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8 --dry-run -o yaml

输出结果:

[root@k8s-node1 k8s]# kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8 --dry-run -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: tomcat6name: tomcat6
spec:replicas: 1selector:matchLabels:app: tomcat6strategy: {}template:metadata:creationTimestamp: nulllabels:app: tomcat6spec:containers:- image: tomcat:6.0.53-jre8name: tomcatresources: {}
status: {}

暴露tomcat访问产生的yaml文件:


③pod、service理解

  • 一次部署deployment就是一个controller

  • service和deployment之间的关系

service是统一应用访问入口

service之间能够相互访问,通过访问service,该请求可以转发给里面的pod节点。

  • labels 和 selectors之间关系:

    • labels 类似给pod打上标签人然后用selectors去选择
    • selectors类似jq的id选择器


④Ingress

  • 介绍

service以域名方式暴露,外部访问Ingress,通过service将请求转发给pod端口。

步骤:

1、部署Ingress controller
2、创建Ingress规则
  • 配置

执行“k8s/ingress-controller.yaml”

kubectl apply -f ingress-controller.yaml

需要等待Ingress启动完成:

  • 配置规则
apiVersion: extensions/v1beta1
kind: Ingress
metadata:name: web
spec:rules:- host: tomcat6.kubenetes.com # 使用的域名http:paths: - backend: serviceName: tomcat6 # 后台服务跟下面的service名对应servicePort: 80

serviceName需要和下面对应:

我们以后只需要访问域名tomcat6.kubenetes.com,就可以访问到后台的tomcat6服务了。

# 将上面规则添加进ingress-tomcat6.yaml文件中
touch ingress-tomcat6.yaml# 启动配置文件
kubectl apply -f ingress-tomcat6.yaml
  • 配置域名映射
192.168.56.102 tomcat6.kubenetes.com
  • 测试


三、kubesphere

1、前置环境

  • 安装默认的DhashBoard

# k8s文件下有
kubectl appy -f  kubernetes-dashboard.yaml

添加权限

kind: Service
apiVersion: v1
metadata:labels:k8s-app: kubernetes-dashboardname: kubernetes-dashboardnamespace: kube-system
spec:type: NodePortports:- port: 443targetPort: 8443nodePort: 3001selector:k8s-app: kubernetes-dashboard

访问地址:

http://NodeIP:30001

创建授权账号

kubectl create serviceaccount dashboar-admin -n kube-sysemkubectl create clusterrolebinding dashboar-admin --clusterrole=cluter-admin --serviceaccount=kube-system:dashboard-adminkubectl create clusterrolebinding dashboar-admin --clusterrole=cluter-admin --serviceaccount=kube-system:dashboard-admin

使用输出的token登录dashboard:

  • 介绍

在这里安装的时候,大约花费了一天时间,主要原因是外网无法访问导致,有些脚本命令无法执行。

具体参考网址有两个,将两个文件结合起来一起看比较好比较好:

https://blog.csdn.net/hancoder/article/details/107612802
https://www.cnblogs.com/wwjj4811/p/14117876.html

概述

安装参考网址:

# v3.0.0版本
https://kubesphere.com.cn/docs/quick-start/minimal-kubesphere-on-k8s/# v2.1版本参考网址
https://v2-1.docs.kubesphere.io/docs/zh-CN/installation/prerequisites/
  • 安装heml

安装给定的get_helm.sh

curl -L https://git.io/get_helm.sh | bash

但是,上面的命令由于翻墙的原因一般都无法执行,推荐使用下面博客的方式在匹配好版本的情况下,进行离线安装:

https://blog.csdn.net/qq_30019911/article/details/113747673

获取安装包

https://get.helm.sh/helm-v2.16.3-linux-amd64.tar.gz

将解压后的文件linux-amd64/helm、linux-amd64/tiller文件放到/usr/local/bin/目录中

验证版本

helm version# Client和Server版本要一致,Tiller初始化完成后会显示这个
Client: &version.Version{SemVer:"v2.16.3", GitCommit:"xx", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.16.3", GitCommit:"xx", GitTreeState:"clean"}

创建权限(master执行)

创建helm-rbac.yaml文件,将下面配置添加进里面:授权工作

apiVersion: v1
kind: ServiceAccount
metadata:name: tillernamespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: tiller
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: cluster-admin
subjects:- kind: ServiceAccountname: tillernamespace: kube-system

启用配置

kubectl apply -f helm-rbac.yaml
  • 安装Tiller(master执行)

初始化

# --tiller-image指定镜像,否则会被墙
# 等待节点上部署的tiller完成即可
helm init --service-account=tiller --tiller-image=sapcc/tiller:v2.16.3 --history-max 300

我使用上面的命令无法执行:

使用下面的命令执行:

helm init  --service-account=tiller --upgrade -i  registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.16.3  --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts

使用下面指令验证是否安装成功:

注:删除命名空间的方法,参考下面的博客:

https://blog.csdn.net/shykevin/article/details/107242163

具体命令为:

kubectl get ns kubesphere-system  -o json > kubesphere-system.jsoncurl -k -H "Content-Type:application/json" -X PUT --data-binary @kubesphere-system.json http://127.0.0.1:8081/api/v1/namespaces/kubesphere-system/finalize
  • 安装 OpenEBS

创建 LocalPV 存储类型:

https://v2-1.docs.kubesphere.io/docs/zh-CN/appendix/install-openebs/

检查master 节点是否有 Taint

kubectl describe node k8s-node1 | grep Taint

去掉 master 节点的 Taint:

kubectl taint nodes k8s-node1 node-role.kubernetes.io/master:NoSchedule-

创建 OpenEBS 的 namespace

OpenEBS 相关资源将创建在这个 namespace 下:

kubectl create ns openebs

安装 OpenEBS

# 方式1-通过 Helm 命令来安装
helm init
helm install --namespace openebs --name openebs stable/openebs --version 1.5.0# 方式2-通过原生 kubectl 命令安装
kubectl apply -f https://openebs.github.io/charts/openebs-operator-1.5.0.yaml

方式1安装会有下面的报错信息,我没有办法解决:

(hint: running `helm repo update` may help)

我开了clash软件,使用的方式2安装,中间需要等待pod启动,需要一定的时间。

查看创建的 StorageClass

安装 OpenEBS 后将自动创建 4 个 StorageClass,查看创建的 StorageClass,这需要一定的时间。

kubectl get sc

openebs-hostpath设置为 默认的 StorageClass

kubectl patch storageclass openebs-hostpath -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

至此,OpenEBS 的 LocalPV 已作为默认的存储类型创建成功。可以通过命令 kubectl get pod -n openebs来查看 OpenEBS 相关 Pod 的状态,若 Pod 的状态都是 running,则说明存储安装成功。

  • 最小化安装kubesphere
kubectl apply -f  kubesphere-minimal.yaml

使用下面指令监查日志打印情况:

kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l app=ks-install -o jsonpath='{.items[0].metadata.name}') -f

代码执行到这里的时候,会有一些卡顿

下面是pod启动完成后的状况:

查看pod启动状况

kubectl get pods --all-namespacesaa0ea01c418d7403ba19170aa4d834bc432f805b
c1f507eeb02247f3f1f1bb39201da65ceef0dcf1
-Dsonar.login=c1f507eeb02247f3f1f1bb39201da65ceef0dcf1

这是使用该命令查看到的最后运行的状况:

查看日志和pod指令需要一起配合,才能有效监视运行状况。

启动界面:

在这里保存一个镜像文件

默认网卡(Host-Only:10.0.2.15)在这里不能和宿主机相互ping通,我们拿宿主机所在ip(192.168.56.100)进行访问。


2、定制化安装

点击自定义资源CRD,点击clusterconfiguration ,编辑文件开启相关配置devops、notification等。


3、建立多租户系统

平台的资源一共有三个层级,包括 集群 (Cluster)、 企业空间 (Workspace)、 项目 (Project) 和 DevOps Project (DevOps 工程),层级关系如下图所示,即一个集群中可以创建多个企业空间,而每个企业空间,可以创建多个项目和 DevOps工程,而集群、企业空间、项目和 DevOps工程中,默认有多个不同的内置角色。

多租户系统架构:

(1)添加atgugui-hr角色

授予它user-manager的角色。

(2)ws-manager创建账户

使用atgugui-hr账户登录进系统,创建用户(ws-manager、ws-admin、project-admin、project-regular)。

ws-manager:管理项目的创建,其他无任何作用。

ws-admin:项目空间的leader,是集群中的普通用户。

project-admin:集群中的普通用户,需要将其邀请到工作空间中才能干活。

project-regular:普通用户。

ws-manager创建的账户:

(3)ws-manager创建企业空间

为每一个团队创建一个企业空间,然后他们在自己的企业空间中创建项目,邀请成员。

(4)ws-admin-企业空间管理员

ws-manager为企业空间邀请成员。

ws-admin邀请两个成员,project-admin、project-regular,前者可以创建项目,后者只是一个普通成员,只能查看项目资源,没有任何创建功能,可以进行DevOps。

(5)ws-admin测试

ws-admin在gulimall空间中创建一个项目:

添加项目维护者:


4、WorkPress应用

参考网址:

https://v2-1.docs.kubesphere.io/docs/zh-CN/quick-start/wordpress-deployment/
  • 秘钥

配置密钥

Docker Hub中的环境变量为:

对应于配置文件:

kind: Secret
apiVersion: v1
metadata:name: mysql-secretnamespace: gulimallannotations:kubesphere.io/alias-name: MySQL 密钥kubesphere.io/creator: project-regular
data:MYSQL_ROOT_PASSWORD: MTIzNDU2
type: Opaque

创建存储卷

创建好的存储卷默认为未挂载状态:

  • 创建容器

添加容器镜像

配置环境变量

wordpress需要添加两个环境变量:

添加存储卷

检查 WordPress 组件信息无误后,点击添加,此时 MySQL 和 WordPress 组件信息都已添加完成。也就是应用wordpress-application牵涉到两个服务wordpressmysql

  • 外网访问

应用创建好之后,将其外网访问,不能访问后台保护的mysql,将wordpress构成一个service暴露出来端口就好了

为wordpress配置外网访问

通过下面网址就可以访问:

http://192.168.56.100:30659/


5、DevOps

  • 介绍

概述

参考博客:

http://www.digtime.cn/articles/445/gu-li-shang-cheng-ji-qun-88-k8s-zhi-devops

  • 流水线-创建凭证

访问网址:

https://v2-1.docs.kubesphere.io/docs/zh-CN/quick-start/devops-online/

  • 流水线-CICD

四、集群

1、介绍

  • 概述

集群的目标

集群基本形式

  • Mysql常见集群方式

  • Mysql-MMM(mysql主主复制管理器)
  • MHA(Mysql高可用方面是一个相对成熟的方案)
  • InnoDB Cluster(支持自动Failover,强一致性,读写分离,读库高可用,读请求负载均衡,推荐方案)

2、Mysql

  • 主从同步

创建Master实例并启动

docker run -p 3307:3306 --name mysql-master \
-v /mydata/mysql/master/log:/var/log/mysql \
-v /mydata/mysql/master/data:/var/lib/mysql \
-v /mydata/mysql/master/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7

参数说明:

-p 3307:3306:将容器的3306映射到主机的3307端口
-v 挂载
-e 初始化root用户密码

修改master基本配置

vim /mydata/mysql/master/conf/my.cnf

修改内容:

[client]
default-character-set=utf8[mysql]
default-character-set=utf8[mysqld]
init_connect='SET collation_connection=uft8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

注意:skip-name-resolve 一定要加,不然连接mysql会超级慢。

添加master主从复制部分配置

server_id=1
log-bin=mysql-bin
read-only=0
binlog-do-db=gulimall_ums
binlog-do-db=gulimall_pms
binlog-do-db=gulimall_oms
binlog-do-db=gulimall_sms
binlog-do-db=gulimall_wms
binlog-do-db=gulimall_adminreplicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=infomation_schema
replicate-ignore-db=performance_schema

重启master

  • 创建Slave实例并启动
docker run -p 3317:3306 --name mysql-slaver-01 \
-v /mydata/mysql/slaver/log:/var/log/mysql \
-v /mydata/mysql/slaver/data:/var/lib/mysql \
-v /mydata/mysql/slaver/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7

修改slaver基本配置

文件路径:

vim /mydata/mysql/slaver/conf/my.cnf

修改内容:

[client]
default-character-set=utf8[mysql]
default-character-set=utf8[mysqld]
init_connect='SET collation_connection=uft8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

添加master主从复制部分配置

server_id=2
log-bin=mysql-bin
read-only=1
binlog-do-db=gulimall_ums
binlog-do-db=gulimall_pms
binlog-do-db=gulimall_oms
binlog-do-db=gulimall_sms
binlog-do-db=gulimall_wms
binlog-do-db=gulimall_adminreplicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=infomation_schema
replicate-ignore-db=performance_schema
  • 为master授权用户来他的同步数据

进入master容器

docker exec -it mysql-master /bin/bash

进入mysql内部(mysql -uroot -p)

# 授权root可远程访问(主从无关,为了方便我们远程连接mysql)
grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option; flush privileges;

添加用来同步的用户

-- 核心 授权一个专门用来复制的; 'backup'@'%':任何主机都可以
-- 运行后,master就有一个授权用户GRANT REPLICATION SLAVE ON *.*  TO 'backup'@'%' IDENTIFIED BY '123456';
  • 查看master状态
show master status

架构图:

  • 配置slaver同步master数据

进入slaver容器

docker exec -it mysql-slaver-01 /bin/bash

进入mysql内部(mysql -uroot -p)

授权root可以远程访问(主从无关,为了方便我们远程连接mysql)

grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option; flush privileges;

设置主库连接

change master to master_host='192.168.80.133',master_user='backup',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=0,master_port=3307;

启动从库同步

start slave;

查看从库状态

show slave status

3、分库分表

  • 介绍


4、Redis

  • 介绍

让每台redis节点负责对应槽位

  • 集群搭建

(1)创建6个redis节点

3主3从,为了进行同步备份,主进行slot数据分片。

执行下面指令:

for port in $(seq 7001 7006); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat <<EOF>/mydata/redis/node-${port}/conf/redis.conf
port ${port}
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 192.168.80.133
cluster-announce-port ${port}
cluster-announce-bus-port 1${port}
appendonly yes
EOF
docker run -p ${port}:${port} -p 1${port}:1${port} --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d redis:5.0.7 redis-server /etc/redis/redis.conf; \
done

删除和停止运行的容器:

docker stop ${docker ps -a |grep redis-700 | awk '{print $1}}'}
docker rm $(docker ps -a |grep redis-700 | awk '{print $1}')

(2)使用redis建立集群

# 进入master节点,每一个主机点有一个副本节点
docker exec -it redis-7001 bash# 自动创建集群,6台机器,每台机器有1个备份机器,3主3从
redis-cli --cluster create 192.168.80.133:7001 192.168.80.133:7002 192.168.80.133:7003 192.168.80.133:7004 192.168.80.133:7005 192.168.80.133:7006 --cluster-replicas 1

5、Elasticsearch

  • 介绍

  • 集群搭建

3主3从结构图:

(1)准备工作

# 所有之前先运行下面指令,(防止jvm报错)
sysctl -w vm.max_map_count=262144#只是测试,所以临时修改,永久修改使用下面
echo vm.max_map_count=262144 >> /etc/sysctl.conf
sysctl -p

(2)准备docker网络,搭建docker死人网络

#查看
docker network ls#创建,桥接模式,子网subnet
docker network create --driver bridge --subnet=172.18.12.0/16 --gateway=172.18.1.1 mynet#查看网络信息
docker network inspect mynet#以后使用--network=mynet --ip 172.18.12.x 指定ip

(3)3-Master节点创建

for port in $(seq 1 3); \
do \
mkdir -p /mydata/elasticsearch/master-${port}/config
mkdir -p /mydata/elasticsearch/master-${port}/data
chmod -R 777 /mydata/elasticsearch/master-${port}
cat << EOF >/mydata/elasticsearch/master-${port}/config/elasticsearch.yml
cluster.name:my-es #集群的名称,同一个集群该值必须设置成相同的
node.name:es-master-${port} #该节点的名字
node.master:true #该节点有机会成为master节点
node.data:false #该节点可以存储数据
network.host:0.0.0.0
http.host:0.0.0.0 #所有http均可访问
http.port:920${port}
transport.tcp.port:930${port}
discovery.zen.ping_timeout:10s #设置集群中自动发现其他节点时ping连接的超时时间
discovery.seed_hosts:['172.18.12.21:9301','172.18.12.22:9302','172.18.12.23:9303'] #设置集群中的Master节点的初始列表,可以通过这些节点来自动发现其他新加入集群的节点,es7的新增配置
cluster.initial_master_nodes:['172.18.12.21'] #新集群初始时的候选主节点,es7的新增配置
EOF
docker run --name elasticsearch-node-${port} \
-p 920${port}:920${port} -p 930${port}:930${port} \
--netword=mynet --ip 172.18.12.2${port} \
-e ES_JAVA_OPTS="-Xms300m -Xmx300m" \
-v /mydata/elasticsearch/master-${port}/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/master-${port}/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/master-${port}/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2
done

(4)3-Node节点创建

for port in $(seq 4 6); \
do \
mkdir -p /mydata/elasticsearch/master-${port}/config
mkdir -p /mydata/elasticsearch/master-${port}/data
chmod -R 777 /mydata/elasticsearch/master-${port}
cat << EOF >/mydata/elasticsearch/master-${port}/config/elasticsearch.yml
cluster.name:my-es #集群的名称,同一个集群该值必须设置成相同的
node.name:es-node-${port} #该节点的名字
node.master:false #该节点有机会成为master节点
node.data:true #该节点可以存储数据
network.host:0.0.0.0
http.host:0.0.0.0 #所有http均可访问
http.port:920${port}
transport.tcp.port:930${port}
discovery.zen.ping_timeout:10s #设置集群中自动发现其他节点时ping连接的超时时间
discovery.seed_hosts:['172.18.12.21:9301','172.18.12.22:9302','172.18.12.23:9303'] #设置集群中的Master节点的初始列表,可以通过这些节点来自动发现其他新加入集群的节点,es7的新增配置
cluster.initial_master_nodes:['172.18.12.21'] #新集群初始时的候选主节点,es7的新增配置
EOF
docker run --name elasticsearch-node-${port} \
-p 920${port}:920${port} -p 930${port}:930${port} \
--netword=mynet --ip 172.18.12.2${port} \
-e ES_JAVA_OPTS="-Xms300m -Xmx300m" \
-v /mydata/elasticsearch/master-${port}/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/master-${port}/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/master-${port}/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2
done

6、RabbitMQ

  • 介绍

镜像模式需要在搭建普通模式后,才能设置

  • 搭建集群
https://www.cnblogs.com/dalianpai/p/13197018.html

(1)创建三个节点

docker run -d --hostname rabbitmq01  --name rabbitmq01 \
-v /mydata/rabbitmq/rabbitmq01:/var/lib/rabbitmq  -p \
15672:15672 -p 5672:5672 -e RABBITMQ_ERLANG_COOKIE='achang' \
rabbitmq:management#RABBITMQ_ERLANG_COOKIE 为令牌,三个节点需要相同,令牌。
# 分别创建rabbitmq01、rabbitmq02、rabbitmq03,改变上面名

(2)节点加入集群

# 分别进入三个集群,加入集群#主节点
docker exec -it rabbitmq01 /bin/bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
eixt# 进入第二个节点
docker exec -it rabbitmq02 /bin/bash
rabbitmqctl stop_app
rabbitmqctl reset
# 加入主节点
rabbitmqctl join_cluster --ram rabbit@rabbitmq01
rabbitmqctl start_app
eixt# 进入第三个节点
docker exec -it rabbitmq03 /bin/bash
rabbitmqctl stop_app
rabbitmqctl reset
# 加入主节点
rabbitmqctl join_cluster --ram rabbit@rabbitmq01
rabbitmqctl start_app
eixt

此时,该集群是一个普通集群,会存在单点故障,我们基于它,配置成镜像集群。

(3)实现镜像集群。

#进入主节点
docker exec -it rabbitmq01 /bin/bash# ^   <--代表全部节点
rabbitmqctl set_policy -p / ha "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}' rabbitmqctl  list_policies -p /


五、部署

1、有状态部署

  • 介绍

参考博客:

https://www.cnblogs.com/dalianpai/p/13205077.html
  • 部署MySQL

(1)创建配置文件

之后创建mysql-master-pvc挂载卷:

(2)创建有状态服务

挂载配置文件:

选择容器组默认部署,将docker放到不同服务器上:

挂载pvc:

查看部署的master服务:

进入容器组终端,查看my.cnf挂载状况:

该终端相当于连接到容器内部:

(3)配置主从复制

进入master容器组终端,执行下面命令,添加用来同步的用户:

GRANT REPLICATION SLAVE ON *.*  TO 'backup'@'%' IDENTIFIED BY '123456';

进入slaver同步主库数据:

#-- gulimall-mysql-master.gulimall:master域名;3306端口号
change master to master_host='gulimall-mysql-master.gulimall',master_user='backup',master_password='123456',master_log_file='mysql-bin.000003',master_log_pos=0,master_port=3306;#-- 启动同步
start slave;

(4)测试

在主库创建一个数据库:

create database  gulimall_oms  default CHARACTER set utf8mb4;

查看从库同步情况。

  • 部署redis

(1)创建配置文件和pvc

(2)添加启动命令

(3)添加存储卷

(4)添加配置文件

(5)进入终端测试

  • 部署ES

(1)创建配置文件和PVC

有三个配置项:

(2)配置环境变量

引用配置文件的值,当环境变量:

(3)挂载pvc

由于配置文件已经在环境变量中进行配置,所以这里不进行挂载了。

(4)测试

在右下角的锤子工具kubectl中进行ping指令测试:

  • 部署RabbitMQ

(1)创建pvc

(2)部署

暴露默认端口即可:

挂载存储卷:

  • 部署Nacos

(1)创建pvc

(2)部署

添加单机版环境变量:

挂载PVC:

(3)对外暴露访问端口

可以将其编写成无状态服务,可以使用下面的方式:

删除服务:

但是容器中nacos仍然存在:

创建无状态服务,关联容器中的nacos:

指定工作负载:

指定端口:

外网访问:

测试访问:


2、部署基础环境

  • 基础环境

#kibana
docker run --name kibana -e ELASTICSEARCH_HOSTS=http:192.168.56.10:9200 -p 5601:5601 -d kibana:7.4.2#nacos
docker run -env MODE=standalone --name nacos \
-v /mydata/nacos/conf/home/nacos/conf -d -p 8848:8848 nacos/nacos-server:1.1.4# sentinel-可以制作一个镜像并其他它,暴露访问
docker run --name sentinel -d -p 8858:8858 -d bladex/sentinel-dashboard:1.6.3#zipkin-两种方式
docker run -d -p 9411:9411 openzipkin/zipkin
docker run --env STORAGE_TYPE=elasticsearch --env ES_HOMES=192.168.56.10:9200

(1)部署kibana

注意:上面的环境配置中,最后少个S:

ELASTICSEARCH_HOSTS

并添加上nodeport方式的外网访问(有状态服务不是nodeport方式暴露的话,外界无法访问)。

输入对应的端口进行测试(阿里云需要开启端口的安全组访问规则):

如果配置错误的话,我们需要等上一段时间,大约10分钟后kibana还是不可用。正确的话,一分钟左右。

部署到目前为止,资源使用状况如下:

(2)部署zipkin

只需要暴露9411端口就可以了:

配置环境变量:

测试:

(3)部署sentinel

使用别人做好的镜像:

测试:

(4)总结

部署服务:

资源使用界面:

  • 部署应用的流程

流程图:

  • 理解targetPort、Port、NodePort

  • 高可用部署总结


3、生产环境配置抽取

  • 操作

(1)使用域名访问的形式访问nacos

# ip地址比较难记,变成下面的线上地址
spring.cloud.nacos.discovery.server-addr=nacos-service.gulimall:8848
nacos-service.gulimall

nacos默认以nodeport方式暴露(开启随机端口),在sentinel终端中无法ping通。

下面开启的随机端口,是因为我们要看可视化界面,这个是要暴露的:

创建一个服务,关联nacos的应用负载:

将nacos包装成使用域名访问的方式。需要进行下面的配置进行关联:

容器端口8848对应服务端口8848,可以进行域名访问(ip地址改变,域名不变,也可以实现负载均衡)。

下一步,不用配置外网访问,只需要集群内部访问即可。此时,在sentinel服务端可以ping同nacos。

nacos在k8s中默认是一个pod,将该pod映射成两种不同的服务,一种是暴露端口号,别人通过网络端口号可以直接访问的,第二种是暴露域名的,在集群内部,其他的pod或者service都可以访问它。

(2)配置生产环境application-prod.properties

  • 配置其他服务内网访问

(1)配置redis

redis是一个有状态服务,在sentinel服务中通过域名(gulimall-redis.gulimall)可以直接访问:

(2)配置sentinel同nacos配置

(3)配置zipkin同nacos配置

此时,使用域名的配置如下:

spring.rabbitmq.host=gulimall-rabbitmq.gulimall
spring.redis.host=gulimall-redis.gulimall
spring.cloud.sentinel.transport.dashboard=gulimall-sentinel.gulimall:8333
spring.cloud.nacos.discovery.server-addr=gulimall-nacos2.gulimall:8848
spring.zipkin.base-url=http://gulimall-zipkin.gulimall:9411/
spring:datasource:username: rootpassword: 123456url: jdbc:mysql://gulimall-mysql-master.gulimall:3306/gulimail_pms?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaidriver-class-name: com.mysql.cj.jdbc.Driver

4、创建微服务Dockerfile

  • 操作

使用Deckerfile可以为每一个微服务打包成一个镜像,进而上传到dockerHub仓库中。

gulimall-common是一个基础包,Maven在运行打包、编译等命令前,依赖的东西要么在远程仓库,要么在本地仓库,我们写的代码没有在仓库里面

(1)运行打包指令

依赖会安装到本地仓库中,聚合关系会被解析。

# 安装并跳过测试
clean install -Dmaven test skip-true

(2)打包成镜像

# 将dockerfile同目录下的jar打成镜像
docker buil -f Dockerfile -t docker.io/likunlun/admin:1.0 .

有了这个镜像,我们可以在后台启动这个容器了。加入每一个微服务都有一个Dockerfile的话,使用Jenkinsfile将其推送到远程仓库,流水线就比较容易实现。

(3)Dockerfile文件解析

# 依赖的基础镜像是java8
FROM java:8
# jar包启动之后暴露的是8080端口,该容器可以对外再进行一个暴露。
EXPOSE 8080# 工作数据挂载的目录
VOLUME /tmp
# 类似cp,将jar包复制到 /app.jar 中
ADD target/*.jar  /app.jar
# 修改jar包创建时间(可加可不加)
RUN bash -c 'touch /app.jar'
# 容器启动,默认运行的命令
ENTRYPOINT ["java","-jar","/app.jar","--spring.profiles.active=prod"]
# 下面是限制内存的启动
ENTRYPOINT ["java","-jar","-Xms128m","-Xmx300m","/app.jar","--spring.profiles.active=prod"]

5、创建微服务K8S部署描述文件

  • 操作

为每个微服务添加deploy部署文件:

kind: Deployment   # 资源类型,定义成pod
apiVersion: apps/v1
metadata:labels:app: gulimall-productname: gulimall-productnamespace: gulimall # 对应项目中名称空间
spec: # 规格replicas: 1selector:matchLabels: #匹配app: gulimall-producttemplate:metadata:labels:app: gulimall-productspec:containers: # 容器名为微服务名 docker run --name- name: gulimall-productimage: $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:latest # dockerHub镜像地址,动态,从Jenkins中取值ports:- containerPort: 8080 # 每一个容器都是这个protocol: TCPresource:limits:cpu: 1000mmemory: 500mirequests:cpu: 10mmemory: 10miterminationMessagePath: /dev/termination-logterminationMessagePolicy: FileimagePullPolicy: IfNotPresent # 镜像拉取策略restartPolicy: Always # 停机重启terminationGracePeriodSeconds: 30strategy:type: RollingUpdate  # 滚动更新rollingUpdate:maxUnavailable: 25%maxSurge: 25%revisionHistoryLimit: 10 # 保留历史版本数量progressDeadlineSeconds: 600---
kind: Service  # 资源类型-service(暴露信息让外界访问)
apiVersion: v1
metadata:labels:app: gulimall-productname: gulimall-productnamespace: gulimall
spec: # 规格ports:- name: httpprotocol: TCPport: 8080 # 服务端口targetPort: 8080 # 容器端口nodePort: 30013 # 代理端口(编排的端口号)selector:app: gulimall-producttype: NodePortsessionAffinty: None

6、流水线文件

①gitee拉取代码

  • 参数化构建
parameters {string(name: 'PROJECT_VERSION', defaultValue: 'v0.0Beta', description: '')string(name: 'PROJECT_NAME', defaultValue: '', description: '')
}

parameters可以接收传递过来的参数,PROJECT_NAME可以在外面定义参数的值类型

  • 环境变量
  environment {DOCKER_CREDENTIAL_ID = 'dockerhub-id'GITEE_CREDENTIAL_ID = 'gitee-id'KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'REGISTRY = 'docker.io'DOCKERHUB_NAMESPACE = 'docker账号'GITEE_ACCOUNT = '码云账号'SONAR_CREDENTIAL_ID = 'sonar-qube'BRANCH_NAME = 'master'}
  • 拉取代码
  stages {stage('拉取代码') {steps {git(credentialsId: 'gitee-id', url: '码云地址', branch: 'master', changelog: true, poll: false)sh 'echo 正在构建 $PROJECT_NAME  版本号: $PROJECT_VERSION 将会提交给 $REGISTRY 镜像仓库'container('maven') {sh 'mvn clean install -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml'}}}

编辑流水线参数:


②Sonar代码质量分析

  • 操作

(1)代码

stage('sonar代码质量分析') {steps {container('maven') {withCredentials([string(credentialsId: "$SONAR_CREDENTIAL_ID", variable: 'SONAR_TOKEN')]) {withSonarQubeEnv('sonar') {sh 'echo 当前目录 `pwd`'sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.branch=$BRANCH_NAME -Dsonar.login=$SONAR_TOKEN"}}timeout(time: 1, unit: 'HOURS') {waitForQualityGate true}}}}

(2)线上环境使用下面阿里云镜像和JDK1.8配置

<settings><mirrors><mirror><id>nexus-aliyun</id><mirrorOf>central</mirrorOf><name>Nexus aliyun</name><url>https://maven.aliyun.com/nexus/content/groups/public</url></mirror></mirrors><profiles><profile><id>jdk-1.8</id><activation><activeByDefault>true</activeByDefault><jdk>1.8</jdk></activation><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion></properties></profile></profiles>
</settings>

(3)gulimall父项目pom文件中添加sonar插件

    <properties><!-- Sonar --><!-- 部署时使用sonar代码质量分析需要的 值填${PWD}/./target/jacoco.exec--><sonar.jacoco.reportPaths></sonar.jacoco.reportPaths><sonar.groovy.binaries>target/classes</sonar.groovy.binaries></properties><!--sonar插件--><build><plugins><plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>0.8.2</version><configuration><append>true</append></configuration><executions><execution><id>agent-for-ut</id><goals><goal>prepare-agent</goal></goals></execution><execution><id>agent-for-it</id><goals><goal>prepare-agent-integration</goal></goals></execution><execution><id>jacoco-site</id><phase>verify</phase><goals><goal>report</goal></goals></execution></executions></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><fork>true</fork></configuration></plugin><plugin><groupId>org.sonarsource.scanner.maven</groupId><artifactId>sonar-maven-plugin</artifactId><version>3.6.0.1398</version></plugin></plugins></build>

③构建和推送镜像

  • 操作

(1)代码

    stage('构建镜像-推送镜像') {steps {container('maven') {sh 'mvn -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml clean package'sh 'cd $PROJECT_NAME && docker build -f Dockerfile -t $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME' ,credentialsId : "$DOCKER_CREDENTIAL_ID" ,)]) {sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'sh 'docker tag  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:latest 'sh 'docker push  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:latest '}}}}

先进行打包,然后推动到远程DockerHub仓库。首先构建要给快照镜像,之后推送一个最新镜像。


④构建完成

  • 操作

(1)部署到k8s

stage('部署到k8s') {steps {input(id: 'deploy-to-dev-$PROJECT_NAME', message: '是否将$PROJECT_NAME 部署到集群中?')kubernetesDeploy(configs: '$PROJECT_NAME/deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")}
}

(2)给github生成发布版标签

stage('发布版本'){when{expression{return params.PROJECT_VERSION =~ /v.*/}}steps {container ('maven') {input(id: 'release-image-with-tag', message: '发布当前版本镜像吗?')withCredentials([usernamePassword(credentialsId: "$GITEE_CREDENTIAL_ID", passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {sh 'git config --global user.email "484613733@qq.com" 'sh 'git config --global user.name "wei-xhh" 'sh 'git tag -a $PROJECT_VERSION -m "$PROJECT_VERSION" 'sh 'git push http://$GIT_USERNAME:$GIT_PASSWORD@gitee.com/$GITEE_ACCOUNT/gulimall.git --tags --ipv4'}sh 'docker tag  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION 'sh 'docker push  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION '}}}

总文件:

pipeline {agent {node {label 'maven'}}stages {stage('拉取代码') {steps {git(credentialsId: 'gitee-id', url: '码云地址', branch: 'master', changelog: true, poll: false)sh 'echo 正在构建 $PROJECT_NAME  版本号: $PROJECT_VERSION 将会提交给 $REGISTRY 镜像仓库'container('maven') {sh 'mvn clean install -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml'}}}stage('sonar代码质量分析') {steps {container('maven') {withCredentials([string(credentialsId: "$SONAR_CREDENTIAL_ID", variable: 'SONAR_TOKEN')]) {withSonarQubeEnv('sonar') {sh 'echo 当前目录 `pwd`'sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.branch=$BRANCH_NAME -Dsonar.login=$SONAR_TOKEN"}}timeout(time: 1, unit: 'HOURS') {waitForQualityGate true}}}}stage('构建镜像-推送镜像') {steps {container('maven') {sh 'mvn -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml clean package'sh 'cd $PROJECT_NAME && docker build -f Dockerfile -t $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME' ,credentialsId : "$DOCKER_CREDENTIAL_ID" ,)]) {sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'sh 'docker tag  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:latest 'sh 'docker push  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:latest '}}}}stage('部署到k8s') {steps {input(id: 'deploy-to-dev-$PROJECT_NAME', message: '是否将$PROJECT_NAME 部署到集群中?')kubernetesDeploy(configs: '$PROJECT_NAME/deploy/**', enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")}}stage('发布版本'){when{expression{return params.PROJECT_VERSION =~ /v.*/}}steps {container ('maven') {input(id: 'release-image-with-tag', message: '发布当前版本镜像吗?')withCredentials([usernamePassword(credentialsId: "$GITEE_CREDENTIAL_ID", passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {sh 'git config --global user.email "484613733@qq.com" 'sh 'git config --global user.name "wei-xhh" 'sh 'git tag -a $PROJECT_VERSION -m "$PROJECT_VERSION" 'sh 'git push http://$GIT_USERNAME:$GIT_PASSWORD@gitee.com/$GITEE_ACCOUNT/gulimall.git --tags --ipv4'}sh 'docker tag  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION 'sh 'docker push  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION '}}}}environment {DOCKER_CREDENTIAL_ID = 'dockerhub-id'GITEE_CREDENTIAL_ID = 'gitee-id'KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'REGISTRY = 'docker.io'DOCKERHUB_NAMESPACE = 'docker账号'GITEE_ACCOUNT = '码云账号'SONAR_CREDENTIAL_ID = 'sonar-qube'BRANCH_NAME = 'master'}parameters {string(name: 'PROJECT_VERSION', defaultValue: 'v0.0Beta', description: '')string(name: 'PROJECT_NAME', defaultValue: '', description: '')}
}

⑤、迁移数据库

  • 暴露给外网访问

(1)给mysql-master指定工作负载

目前mysql-master作为有状态服务没有开启外网访问,如下所示:

因此,需要将其能够进行外网访问,以便迁移数据库:

下一步进行开启nodeport外网访问即可,此时通过下面的30986可以访问mysql:

  • 操作

(1)新建数据库和表

renrenfast的数据库配置为:

spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedruid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://gulimall-mysql-master.gulimall:3306/gulimall_admin?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456

这样才能读取数据库gulimall_admin中的内容。

7、部署

①Docker镜像操作

  • 操作

(1)结合k8s配置修改nginx上游服务器。进行负载均衡

(2)推送镜像到DockerHub

但是比较慢,下面推送镜像到阿里云仓库。


②、整合阿里云镜像仓库

sudo docker login --username=武汉小伦 registry.cn-beijing.aliyuncs.com
sudo docker pull registry.cn-beijing.aliyuncs.com/xiaoun-atguigumall/gulimall-nginx:[镜像版本号]
sudo docker push registry.cn-beijing.aliyuncs.com/xiaoun-atguigumall/gulimall-nginx:[镜像版本号]

③、Jenkins修改阿里云镜像仓库

之前Jenkinsfile文件中推送给DockerHub仓库,全部变成阿里云仓库

DOCKER_CREDENTIAL_ID = 'dockerhub-id'
REGISTRY = 'docker.io' #镜像前置地址变成阿里云
DOCKERHUB_NAMESPACE = 'docker账号'

8、部署微服务

①部署相关微服务

  • 操作

(1)部署gateway、auth-server、cart、coupon等12个微服务:

(2)动态获取配置文件中的值

package com.xiaolun.gulimall.seckill.config;@Bean(destroyMethod="shutdown")
public RedissonClient redisson(@Value("${spring.redis.host}") String url) throws IOException {

(3)修改阿里云镜像仓库为公有仓库

  • 第一前置部署Nginx

(1)上传nginx镜像

使用docker commit对nginx进行打包时,外部的挂载文件打包不进来:

因此,将下面文件放到同一个目录下,进行打包nginx:

Deckerfile文件内容:

FROM nginx
MAINTAINER leifengyang
ADD html.tar.gz /usr/share/nginx/html
ADD conf.tar.gz /etc/nginx
EXPOSE 80
ENTRYPOINT nginx -g "daemon off;"

压缩包可以快速上传,and指令可以解压压缩包。

执行下面指令进行构建镜像:

docker build -t mynginx:v1.2 -f Dockerfile .

(2)配置阿里云镜像仓库密钥

阿里云账户禁止有中文名

(3)添加上传到阿里云中的镜像

从阿里云镜像仓库中拉取。全部使用默认。无pvc。


②、创建网关与应用路由

需要管理员首先开启创建网关路由。

(1)创建负载均衡方式

(2)创建路由规则

所有的域名gulimall.com都交给gulimall-nginx服务进行代理(80服务端口)。

在删除nginx服务进行重新部署的时候,首先要删除关联nginx的应用路由,再删除nginx服务。

(3)配置映射

请求访问gulimall.com域名,请求可以到Kubernetes的任何一条机器上,需要其他节点上安装Ingress的机器

之后,添加成下面的域名方案:

无论访问那个域名下的,全部转给IngressController(39.96.78.4),IngressController按照域名进行匹配。接下来,就需要在gulimall-com应用路由中编辑更多的路由规则:

当我们执行下面请求访问时,请求会打到商品服务:

gulimall.com

但是,由于项目部署到阿里云服务器上,该域名没有进行备案,在内网部署时可以访问,外网时无法访问。这是内网部署时,配置的相关域名:

192.168.10.11 gulimall.com
192.168.10.11 search.gulimall.com
192.168.10.11 item.gulimall.com
192.168.10.11 auth.gulimall.com
192.168.10.11 cart.gulimall.com
192.168.10.11 order.gulimall.com
192.168.10.11 member.gulimall.com
192.168.10.11 seckill.gulimall.com

我使用续断为自己的电脑绑定了内网穿透地址,

并将外网域名放到了nginx的拦截请求里,但是未能奏效:

测试1:

可以看到静态资源文件已经存在。


③、商品系统上线

(1)nginx重新打包

docker commit命令只能打包最原生的镜像,外面挂载文件无法打进来。

使用下面的Dockerfile文件指令打包镜像(压缩包比较好上传):

# 从官方镜像拉取nginx
FROM nginx
MAINTAINER leifengyang
# 将html.tar.gz放到/usr/share/nginx/html中
ADD html.tar.gz /usr/share/nginx/html
ADD conf.tar.gz /etc/nginx
EXPOSE 80
ENTRYPOINT nginx -g "daemon off;"

打包指令:

将上面生成的镜像上传到阿里云。


④、测试

(1)部署完gulimall-gateway后进行测试

出现下面界面,表示搭建成功:


9、部署Vue项目

①操作

(1)打包

npm run build

会有一个dist文件夹,里面就是我们打包的文件,点击index.html,输入验证码进行访问,此时验证码请求发送地址为:

http://demo.open.renren.io/renren-fast-server/captcha.jpg?uuid=03e5e584-ff18-4805-8914-07fb85d5d4a1

(2)更改环境配置

使验证码请求给网关发送。将static/config/index-prod.js路径地址进行更改,然后重新打包上传:

  // api接口请求地址// window.SITE_CONFIG['baseUrl'] = 'http://demo.open.renren.io/renren-fast-server';window.SITE_CONFIG['baseUrl'] = 'http://39.96.92.23:30007/api';

(3)打包镜像

FROM nginx
MAINTAINER leifengyang
# 将静态资源放到nginx中,可以直接访问
ADD dist.tar.gz /usr/share/nginx/html
EXPOSE 80
ENTRYPOINT nginx -g "daemon off;"

之后将镜像推送给阿里云。

让其能够外网访问。

(3)测试1

通过访问vue前端,验证码能够返回,说明vue的访问请求可以通过网关gateway转给renrenfast服务。

点击相关菜单,可以进入相关界面,说明该项目打通了数据库:

执行下面品牌管理访问请求:

http://39.96.92.23:31004/api/product/brand/list?t=1619493398348&page=1&limit=10&key=

返回结果:

{"msg":"success","code":0,"page":{"totalCount":4,"pageSize":10,"totalPage":1,"currPage":1,"list":[{"brandId":9,"name":"华为","logo":"https://gulimall-hello.oss-cn-beijing.aliyuncs.com/2019-11-18/de2426bd-a689-41d0-865a-d45d1afa7cde_huawei.png","descript":"华为","showStatus":1,"firstLetter":"H","sort":1},{"brandId":10,"name":"小米","logo":"https://gulimall-hello.oss-cn-beijing.aliyuncs.com/2019-11-18/1f9e6968-cf92-462e-869a-4c2331a4113f_xiaomi.png","descript":"小米","showStatus":1,"firstLetter":"M","sort":1},{"brandId":11,"name":"oppo","logo":"https://gulimall-hello.oss-cn-beijing.aliyuncs.com/2019-11-18/5c8303f2-8b0c-4a5b-89a6-86513133d758_oppo.png","descript":"oppo","showStatus":1,"firstLetter":"O","sort":1},{"brandId":12,"name":"Apple","logo":"https://gulimall-hello.oss-cn-beijing.aliyuncs.com/2019-11-18/819bb0b1-3ed8-4072-8304-78811a289781_apple.png","descript":"苹果","showStatus":1,"firstLetter":"A","sort":1}]}
}

②测试滚动更新

(1)对镜像内容修改后,重新上传镜像到阿里云

(2)版本更新

进入该服务后,再进入工作负载,进行修改镜像:

(3)查看


10、线上预警与监控

  • 邮件通知

(1)QQ中开启访问权限

(2)配置邮件服务器

(3)配置规则

执行下面品牌管理访问请求:

http://39.96.92.23:31004/api/product/brand/list?t=1619493398348&page=1&limit=10&key=

返回结果:

{"msg":"success","code":0,"page":{"totalCount":4,"pageSize":10,"totalPage":1,"currPage":1,"list":[{"brandId":9,"name":"华为","logo":"https://gulimall-hello.oss-cn-beijing.aliyuncs.com/2019-11-18/de2426bd-a689-41d0-865a-d45d1afa7cde_huawei.png","descript":"华为","showStatus":1,"firstLetter":"H","sort":1},{"brandId":10,"name":"小米","logo":"https://gulimall-hello.oss-cn-beijing.aliyuncs.com/2019-11-18/1f9e6968-cf92-462e-869a-4c2331a4113f_xiaomi.png","descript":"小米","showStatus":1,"firstLetter":"M","sort":1},{"brandId":11,"name":"oppo","logo":"https://gulimall-hello.oss-cn-beijing.aliyuncs.com/2019-11-18/5c8303f2-8b0c-4a5b-89a6-86513133d758_oppo.png","descript":"oppo","showStatus":1,"firstLetter":"O","sort":1},{"brandId":12,"name":"Apple","logo":"https://gulimall-hello.oss-cn-beijing.aliyuncs.com/2019-11-18/819bb0b1-3ed8-4072-8304-78811a289781_apple.png","descript":"苹果","showStatus":1,"firstLetter":"A","sort":1}]}
}

就此谷粒商城结束了!!!感谢你能看到这里!!!

Day442443444445446447448.K8s -谷粒商城相关推荐

  1. 谷粒商城学习笔记——第一期:项目简介

    一.项目简介 1. 项目背景 市面上有5种常见的电商模式 B2B.B2C.C2B.C2C.O2O B2B 模式(Business to Business),是指商家和商家建立的商业关系.如阿里巴巴 B ...

  2. 谷粒商城分布式基础篇1-个人版

    基础篇 1 项目简介 1.1 项目背景 1.2 电商模式 市面上有5种常见的电商模式 B2B.B2C.C2B.C2C.O2O 1.2.1 B2B 模式 B2B(Business to Business ...

  3. 分布式项目-谷粒商城。

    分布式项目 一,分布图 二,环境搭建 1.安装linux 2.安装docker 1 卸载系统之前的docker sudo yum remove docker \docker-client \docke ...

  4. 谷粒商城项目总结(一)-基础篇

    谷粒商城基础篇高级篇,跟着看,也敲了部分代码,但是感觉后续随着业务增加代码部分敲了也记不住,就想着应该重视解决问题的思路,理清思路比代码更重要,写这篇文章,是在看完后在从第一到高级篇,少部分集群篇总结 ...

  5. 【谷粒商城】框架扩充篇(3/4)

    gitee个人代码:https://gitee.com/HanFerm/gulimall 笔记-基础篇-1(P1-P28):https://blog.csdn.net/hancoder/article ...

  6. 谷粒商城一介绍及基本架构todo

    项目进度 前言 工作两年,技术依然在小白附近徘徊,即使有一些进步,但也不值一提 两年的工作内容,几乎就是cv加一些简单的百度,从细节方面说,经历的细节不算多,从架构方面讲,自己远远达不到那个级别. 谷 ...

  7. 从前慢-谷粒商城篇章1

    分布式基础篇 1 项目简介 1.1 项目背景 1.2 电商模式 市面上有5种常见的电商模式 B2B.B2C.C2B.C2C.O2O 1.2.1 B2B 模式 B2B(Business to Busin ...

  8. 谷粒商城电商项目 高可用集群篇

    更多视频,JAVA收徒 QQ:987115885谷粒商城电商项目 高可用集群篇339.k8s-简介.mp4340.k8s-架构原理&核心概念.mp4341.k8s-集群搭建-环境准备.mp43 ...

  9. 1.谷粒商城1-5文字版

    01.简介-项目介绍 我这个架构图呢 我先快速的给大家过一遍 大家知道将会学到什么就行了 ,那我们后来呢会有详细的去来介绍, 首先呢,我们除了常规的业务开发 , 比如我们开发后台管理系统也好,开发其他 ...

最新文章

  1. nginx 停止服务方法
  2. 初学者如何学习Vim
  3. 对SetViewportOrg和SetWindowOrg的理解
  4. C++ class实现顺序栈(完整代码)
  5. tomcat防cc_浅析Tomcat防止资料被锁的方式
  6. 海德堡大学 BMCV 组博士招生,生物医学图像分析领域​
  7. ShardingSphere(四) 垂直分库配置搭建,实现写入读取
  8. Java多张图片合成PDF
  9. Linux socket程序演示
  10. 操作系统之多道程序设计
  11. 360竞价开户推广,让营销更聪明!
  12. element表格样式修改
  13. 蚂蚁金服十年自研分布式中间件,成就世界级新金融科技平台
  14. 一个心理医生和一个心理不正常的小孩的冷笑话
  15. WZOI-277白细胞计数
  16. Android 仿网易云音乐App
  17. 【Spring MVC】mvc详解
  18. android framework实战车机手机系统开发环境相关问题补充
  19. java picked up,抑制“Picked up _JAVA_OPTIONS”信息
  20. NVIDIA Jetson Xavier性能首测:AI性能碾压苹果A12,自研CPU架构看齐骁龙84

热门文章

  1. latex 矩阵分块(block matrix)
  2. security+真的没有那么难考,我的信息安全分享
  3. 如何确定抽样的样本数量
  4. 用signalr实现简单的网页实时聊天
  5. 微生物组测序方法比较
  6. Python项目:基于Python+Django实现药品管理系统
  7. 【报错解决】为Blender构建Python模块
  8. list remove 失效的解决方式
  9. 【语音识别】语言模型LM
  10. 新浪微博定位页面代码解析