谷粒商城(三) 部署

 

环境搭建和基本介绍

使用vagrant快速创建linux虚拟机

安装virtualbox

https://www.virtualbox.org/wiki/Downloads

下载安装vagrant

https://www.vagrantup.com/downloads.html

 本人使用3个Centos7虚拟机,每台内存20G

 

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

虚拟化部署时代: 作为解决方案,引入了虚拟化功能,它允许您在单个物理服务器的 CPU 上运行多个虚拟机(VM)。虚拟化功能允许应用程序在 VM 之间隔离,并提供安全级别,因为一个应用程序的信息不能被另一应用程序自由地访问。

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

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

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

下面列出了容器的一些好处:

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

 

容器时代,容器管理的需求凸显。

 

Kubernetes 为您提供:

  • 服务发现和负载均衡
    Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果到容器的流量很大,Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。
  • 存储编排
    Kubernetes 允许您自动挂载您选择的存储系统,例如本地存储、公共云提供商等。
  • 自动部署和回滚
    您可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态更改为所需状态。例如,您可以自动化 Kubernetes 来为您的部署创建新容器,删除现有容器并将它们的所有资源用于新容器。
  • 自动二进制打包
    Kubernetes 允许您指定每个容器所需 CPU 和内存(RAM)。当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源。
  • 自我修复
    Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器,并且在准备好服务之前不将其通告给客户端。
  • 密钥与配置管理  Kubernetes 允许您存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。您可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

 

K8S架构

一个K8S集群由两部分构成 master节点和node节点。

master节点主要负责集群的控制,对pod进行调度,已经令牌管理等等功能。

node节点主要是负责干活,启动容器、管理容器。

master节点和node节点一般不要部署在一台机器上。

下面一个master,两个node。

 

 

将这张图抽象一下,大约是这个样子:

 

 

master节点中有很多组件

 

 

 

 

 

 

 

 

 

 

 

 

 

 

为什么k8s使用Pod在容器之上再封装一层呢?一个很重要的原因是Docker容器之间的通信受到docker网络机制的限制。在Docker的世界中,一个容器需要通过link方式才能访问另一个容器提供的服务(端口)。大量容器之间的link将是一个非常繁重的工作。通过Pod的概念将多个容器组合在一个虚拟的“主机”内,可以实现容器之间仅需通过Localhost就能相互通信了。

一个Pod中的应用容器共享同一组资源:

(1)PID命名空间:Pod中的不同应用程序可以看见其他应用程序的进程ID

(2)网络命名空间:Pod中的多个容器能访问同一个IP和端口范围

(3)IPC命名空间:Pod中的多个容器能够使用SystemV IPC或POSIX消息队列进行通信

(4)UTS命名空间:Pod中的多个容器共享一个主机名

(5)Volumes(共享存储卷):Pod中的各个容器可以访问在Pod级别定义的Volumes。容器运行的过程中会产生数据,这些数据就保存在Volume中

 

每个节点运行着docker,docker中运行着容器,这些容器被kubelet组合成pod,pod负责创建销毁维护声明周期。将pod暴露出去后,提供一个访问地址,访问该地址,kube-proxy会解析地址最终访问到指定的容器,kube-proxy还能进行负载均衡。

Kubernetes提供了多种Controller,Controllers是更高层次的对象,部署和管理pod,包括:
  • ReplicaSet:确保预期的pod副本数量
  • Deployent:无状态应用部署。

     Deployment是Kubernetes v1.2引入的概念,引入的目的是为了更好地解决Pod的编排问题。为此,Deployment在内部使用了Replica Set来实现目的,无论从Deployment的作用与目的,它的YAML定义,还是从它的具体命令行操作来看,我们都可以把它看作RC的一次升级,两者相似度超过90%。

     Deployment相对于RC的一个最大升级是我们随时知道当前Pod“部署”的进度。实际上由于一个Pod的创建、调度、绑定节点及在目标Node上启动对应的容器这一完整过程需要一定的时间,所以我们期待系统启动N个Pod副本的目标状态,实际上是一个连续变化的“部署过程”导致的最终状态。

     Deployment的典型使用场景有以下几个。

    • 创建一个Deployment对象来生成对应的Replica Set并完成Pod副本的创建过程。
    • 检查Deployment的状态来看部署动作是否完成(Pod副本的数量是否达到预期的值)。
    • 更新Deployment以创建新的Pod(比如镜像升级)。
    • 如果当前Deployment不稳定,则回滚到一个早先的Deployment版本。
    • 暂停Deployment以便于一次性修改多个PodTemplateSpec的配置项,之后再恢复Deployment,进行新的发布。
    • 扩展Deployment以应对高负载。
    • 查看Deployment的状态,以此作为发布是否成功的指标。
    • 清理不再需要的旧版本ReplicaSets。
  • StatefulSet:有状态应用部署。

     在Kubernetes系统中,Pod的管理对象RC、Deployment、DaemonSet和Job都是面向无状态的服务。但现实中有很多服务是有状态的,特别是一些复杂的中间件集群,例如MySQL集群、MongoDB集群、Kafka集群、Zookeeper集群等,这些应用集群有以下一些共同点。

    每个节点都有固定的身份ID,通过这个ID,集群中的成员可以相互发现并且通信。

    集群的规模是比较固定的,集群规模不能随意变动。

    集群里的每个节点都是有状态的,通常会持久化数据到永久存储中。

    如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。

     如果用RC/Deployment控制Pod副本数的方式来实现上述有状态的集群,则我们会发现第一点是无法满足的,因为Pod的名字是随机产生的,Pod的IP地址也是在运行期才确定且可能有变动的,我们事先无法为每个Pod确定唯一不变的ID,为了能够在其他节点上恢复某个失败的节点,这种集群中的Pod需要挂接某种共享存储,为了解决这个问题,Kubernetes从v1.4版本开始引入了PetSet这个新的资源对象,并且在v1.5版本时更名为StatefulSet,StatefulSet从本质上来说,可以看作Deployment/RC的一个特殊变种,它有如下一些特性。

    StatefulSet里的每个Pod都有稳定、唯一的网络标识,可以用来发现集群内的其他成员。假设StatefulSet的名字叫kafka,那么第一个Pod叫kafak-0,第二个Pod叫kafak-1,以此类推。

    StatefulSet控制的Pod副本的启停顺序是受控的,操作第n个Pod时,前n-1个Pod已经时运行且准备好的状态。

    StatefulSet里的Pod采用稳定的持久化存储卷,通过PV/PVC来实现,删除Pod时默认不会删除与StatefulSet相关的存储卷(为了保证数据的安全)。

  • Job:一次性任务
  • Cronjob:定时任务

 

Service

定义一组pod访问策略

pod的负载均衡,提供一个或多个pod的稳定访问地址

Kubernetes的Service定义了一个服务的访问入口地址,前端的应用通过这个入口地址访问其背后的一组由Pod副本组成的集群实例,Service与其后端Pod副本集群之间则是通过Label Selector来实现“无缝对接”的。而RC的作用实际上是保证Service的服务能力和服务质量始终处于预期的标准。

 

pod组合一些controller,service又挑出一些pod进行组合,提供负载均衡,比如想访问购物车功能,只访问service即可,service会知道组合的pod在哪些服务器中,访问一个即可。一次部署就是将pod部署到各个节点,Deployment产生pod,service对pod进行组合。

 

Label

Label是Kubernetes系统中另外一个核心概念。一个Label是一个key=value的键值对,其中key与vaue由用户自己指定。Label可以附加到各种资源对象上,例如Node、Pod、Service、RC等,一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去,Label通常在资源对象定义时确定,也可以在对象创建后动态添加或者删除。

 我们可以通过指定的资源对象捆绑一个或多个不同的Label来实现多维度的资源分组管理功能,以便于灵活、方便地进行资源分配、调度、配置、部署等管理工作。例如:部署不同版本的应用到不同的环境中;或者监控和分析应用(日志记录、监控、告警)等。一些常用等label示例如下。

  • 版本标签:"release" : "stable" , "release" : "canary"...
  • 环境标签:"environment" : "dev" , "environment" : "production"
  • 架构标签:"tier" : "frontend" , "tier" : "backend" , "tier" : "middleware"
  • 分区标签:"partition" : "customerA" , "partition" : "customerB"...
  • 质量管控标签:"track" : "daily" , "track" : "weekly"

 Label相当于我们熟悉的“标签”,給某个资源对象定义一个Label,就相当于給它打了一个标签,随后可以通过Label Selector(标签选择器)查询和筛选拥有某些Label的资源对象,Kubernetes通过这种方式实现了类似SQL的简单又通用的对象查询机制。

 

namespace

命名空间,用于隔离

 

 

 

 

 

通过kubectl提交一个创建RC的请求,请求通过API Server被写入etcd中

此时,Controller Manager通过API server的监听自由变化的接口监听到此RC事件

发现当前集群中没有它所对应的pod实例

根据RC里的pod模板定义生成一个pod对象,通过API Server写入etcd

此事件被Scheduler发现,它立即执行一个复杂的调度流程,为这个新pod选定一个落户的node,然后通过API Server将这一结果写入到etcd中

目标node上运行的kubelet进程通过API Server监测到这个新生的pod,并按照它的定义,启动该pod并一直对其负责直到生命结束

随后,kubetcl提交一个新的映射到该pod的service的创建请求

Controller Manager通过Label标签查询到关联的pod实例,然后生成service的Endpoints信息,并通过API Service写入到etcd中

接下来,所有node上运行的proxy进程通过API Server查询并监听Service对象与其对应的Endpoints信息,建立一个软件方式的负载均衡器来实现Service访问到后端pod的流量转发功能 

 

k8s中所有资源对象都可以采用yaml或JSON格式的文件定义或描述

 

 

 

集群安装

kubeadm是快速部署k8s集群的工具

创建一个master节点

kubeadm init

一个node节点加入集群

kubeadm join <master节点ip和端口>

 

 

一个maser,两个node

 

步骤:

  • 所有节点安装docker和kubeadm
  • 部署master
  • 部署容器网络插件
  • 部署node,将节点加入k8s集群
  • 部署web界面,可视化k8s资源

 

关闭防火墙、selinux

关闭swap

添加主机名和ip对应关系

将桥接的ipv4流量传递到iptables的链

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

 

docker依赖

yum install -y yum-utils device-mapper-persistent-data lvm2

设置docker的yum源

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

安装docker以及docker-cli

yum install -y docker-ce docker-ce-cli containerd.io

配置docker加速

mkdir -p /etc/docker
tee /etc/docker/daemon.json <<- 'EOF'
{
    "registry-mirrors":["https://82m9ar63.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker

开机启动

systemctl enable docker

添加阿里云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 list|grep kube

yum install -y kubelet-1.17.3 kubectl-1.17.3 kubeadm-1.17.3

 

开机启动

systemctl enable kubelet
systemctl start kubelet

 

 

./master_images.sh 下载节点镜像

#!/bin/bash

images=(
    kube-apiserver:v1.17.3
    kube-proxy:v1.17.3
    kube-controller-manager:v1.17.3
    kube-scheduler:v1.17.3
    coredns:1.6.5
    etcd:3.4.3-0
    pause:3.1
)

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
done

 

master节点初始化

kubeadm init \
--apiserver-advertise-address=192.168.147.8 \          apiserver是master的组件,因此就是master的地址
--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

 

下面会出一些命令,根据命令完成后面的步骤

 mkdir -p $HOME/.kube

sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

sudo chown $(id -u):$(id -g) $HOME/.kube/config

 

安装pod网络插件

kubectl apply -f kube-flannel.yml

 

---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: psp.flannel.unprivileged
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default
    seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default
    apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
    apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
spec:
  privileged: false
  volumes:
    - configMap
    - secret
    - emptyDir
    - hostPath
  allowedHostPaths:
    - pathPrefix: "/etc/cni/net.d"
    - pathPrefix: "/etc/kube-flannel"
    - pathPrefix: "/run/flannel"
  readOnlyRootFilesystem: false
  # Users and groups
  runAsUser:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  # Privilege Escalation
  allowPrivilegeEscalation: false
  defaultAllowPrivilegeEscalation: false
  # Capabilities
  allowedCapabilities: ['NET_ADMIN']
  defaultAddCapabilities: []
  requiredDropCapabilities: []
  # Host namespaces
  hostPID: false
  hostIPC: false
  hostNetwork: true
  hostPorts:
  - min: 0
    max: 65535
  # SELinux
  seLinux:
    # SELinux is unused in CaaSP
    rule: 'RunAsAny'
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: flannel
rules:
  - apiGroups: ['extensions']
    resources: ['podsecuritypolicies']
    verbs: ['use']
    resourceNames: ['psp.flannel.unprivileged']
  - 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",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds-amd64
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: beta.kubernetes.io/os
                    operator: In
                    values:
                      - linux
                  - key: beta.kubernetes.io/arch
                    operator: In
                    values:
                      - amd64
      hostNetwork: true
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.11.0-amd64
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        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.11.0-amd64
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
            add: ["NET_ADMIN"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
        - name: run
          hostPath:
            path: /run/flannel
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: flannel-cfg
          configMap:
            name: kube-flannel-cfg
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds-arm64
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: beta.kubernetes.io/os
                    operator: In
                    values:
                      - linux
                  - key: beta.kubernetes.io/arch
                    operator: In
                    values:
                      - arm64
      hostNetwork: true
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.11.0-arm64
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        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.11.0-arm64
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
             add: ["NET_ADMIN"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
        - name: run
          hostPath:
            path: /run/flannel
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: flannel-cfg
          configMap:
            name: kube-flannel-cfg
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds-arm
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: beta.kubernetes.io/os
                    operator: In
                    values:
                      - linux
                  - key: beta.kubernetes.io/arch
                    operator: In
                    values:
                      - arm
      hostNetwork: true
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.11.0-arm
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        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.11.0-arm
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
             add: ["NET_ADMIN"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
        - name: run
          hostPath:
            path: /run/flannel
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: flannel-cfg
          configMap:
            name: kube-flannel-cfg
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds-ppc64le
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: beta.kubernetes.io/os
                    operator: In
                    values:
                      - linux
                  - key: beta.kubernetes.io/arch
                    operator: In
                    values:
                      - ppc64le
      hostNetwork: true
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.11.0-ppc64le
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        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.11.0-ppc64le
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
             add: ["NET_ADMIN"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
        - name: run
          hostPath:
            path: /run/flannel
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: flannel-cfg
          configMap:
            name: kube-flannel-cfg
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds-s390x
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        tier: node
        app: flannel
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: beta.kubernetes.io/os
                    operator: In
                    values:
                      - linux
                  - key: beta.kubernetes.io/arch
                    operator: In
                    values:
                      - s390x
      hostNetwork: true
      tolerations:
      - operator: Exists
        effect: NoSchedule
      serviceAccountName: flannel
      initContainers:
      - name: install-cni
        image: quay.io/coreos/flannel:v0.11.0-s390x
        command:
        - cp
        args:
        - -f
        - /etc/kube-flannel/cni-conf.json
        - /etc/cni/net.d/10-flannel.conflist
        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.11.0-s390x
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
          limits:
            cpu: "100m"
            memory: "50Mi"
        securityContext:
          privileged: false
          capabilities:
             add: ["NET_ADMIN"]
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: run
          mountPath: /run/flannel
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      volumes:
        - name: run
          hostPath:
            path: /run/flannel
        - name: cni
          hostPath:
            path: /etc/cni/net.d
        - name: flannel-cfg
          configMap:
            name: kube-flannel-cfg

查看名称空间

kubectl get ns

获取所有命名空间的pod

kubectl get pods --all-namespaces

kube-flannel-ds-amd64-m4wln 状态为running,再继续下面的步骤

 

获取节点

kubectl get nodes

有一个节点是master,状态是ready

 

node2节点

 kubeadm join 10.0.2.5:6443 --token qy7chp.d1qvqk6slfpsl284     --discovery-token-ca-cert-hash sha256:9e75c53992ae8803fa727ea5d537c387fa42aec4ddc6ed934c146e665cec5de3

node3节点也一样

[root@k8s-node1 k8s]# kubectl get nodes
NAME        STATUS   ROLES    AGE   VERSION
k8s-node1   Ready    master   41d   v1.17.3
k8s-node2   Ready    <none>   41d   v1.17.3
k8s-node3   Ready    <none>   41d   v1.17.3

 

入门操作k8s集群

部署一个tomcat

kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8

查看所有资源

kubectl get all

查看pod详细信息

kubectl get pods -o wide

暴露nginx访问

kubectl expose deployment tomcat6 --port=80 --target-port=8080 --type=NodePort

pod的80映射容器的8080,service会代理pod的80

查看service详细信息

[root@k8s-node1 k8s]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 41d <none>
tomcat6 NodePort 10.96.57.43 <none> 80:32311/TCP 41d app=tomcat6

tomcat暴露了32311端口

可以访问

 

 动态扩容,扩容3份

[root@k8s-node1 k8s]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
tomcat6-5f7ccf4cb9-2bghn 1/1 Running 10 41d 10.244.1.13 k8s-node2 <none> <none>

 

[root@k8s-node1 k8s]# kubectl scale --replicas=3 deployment tomcat6
deployment.apps/tomcat6 scaled

 


[root@k8s-node1 k8s]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
tomcat6-5f7ccf4cb9-2bghn 1/1 Running 10 41d 10.244.1.13 k8s-node2 <none> <none>
tomcat6-5f7ccf4cb9-4vmv7 1/1 Running 0 4s 10.244.2.3 k8s-node3 <none> <none>
tomcat6-5f7ccf4cb9-7grgq 1/1 Running 0 4s 10.244.2.4 k8s-node3 <none> <none>

访问任意节点的上述端口都可以访问tomcat

也可以缩容

[root@k8s-node1 k8s]# kubectl scale --replicas=1 deployment tomcat6
deployment.apps/tomcat6 scaled


[root@k8s-node1 k8s]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
tomcat6-5f7ccf4cb9-2bghn 1/1 Running 10 41d 10.244.1.13 k8s-node2 <none> <none>
tomcat6-5f7ccf4cb9-4vmv7 1/1 Terminating 0 66s 10.244.2.3 k8s-node3 <none> <none>
tomcat6-5f7ccf4cb9-7grgq 1/1 Terminating 0 66s 10.244.2.4 k8s-node3 <none> <none>

查看service、deployment及副本等信息,删除部署,也可以删除service

[root@k8s-node1 k8s]# kubectl get all
NAME                           READY   STATUS    RESTARTS   AGE
pod/tomcat6-5f7ccf4cb9-2bghn   1/1     Running   10         41d

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        41d
service/tomcat6      NodePort    10.96.57.43   <none>        80:32311/TCP   41d

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/tomcat6   1/1     1            1           41d

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/tomcat6-5f7ccf4cb9   1         1         1       41d

[root@k8s
-node1 k8s]# kubectl delete deployment.apps/tomcat6

 

 

Kubectl

https://kubernetes.io/zh/docs/reference/kubectl/overview/

 

Kubectl 是一个命令行接口,用于对 Kubernetes 集群运行命令。kubectl 在 $HOME/.kube 目录中寻找一个名为 config 的文件。您可以通过设置环境变量 KUBECONFIG 或设置 --kubeconfig 参数指定其它 kubeconfig 文件。

使用以下语法 kubectl 从终端窗口运行命令:

kubectl [command] [TYPE] [NAME] [flags]

其中 commandTYPENAME 和 flags 分别是:

  • command:指定要对一个或多个资源执行的操作,例如 creategetdescribedelete

  • TYPE:指定资源类型。资源类型不区分大小写,可以指定单数、复数或缩写形式。例如,以下命令输出相同的结果:

    ```shell
    kubectl get pod pod1
    kubectl get pods pod1
    kubectl get po pod1
    ```
  • NAME:指定资源的名称。名称区分大小写。如果省略名称,则显示所有资源的详细信息 kubectl get pods

    在对多个资源执行操作时,您可以按类型和名称指定每个资源,或指定一个或多个文件:

  • 要按类型和名称指定资源:

    • 要对所有类型相同的资源进行分组,请执行以下操作:TYPE1 name1 name2 name<#>
      例子:kubectl get pod example-pod1 example-pod2

    • 分别指定多个资源类型:TYPE1/name1 TYPE1/name2 TYPE2/name3 TYPE<#>/name<#>
      例子:kubectl get pod/example-pod1 replicationcontroller/example-rc1

  • 用一个或多个文件指定资源:-f file1 -f file2 -f file<#>

    • 使用 YAML 而不是 JSON 因为 YAML 更容易使用,特别是用于配置文件时。
      例子:kubectl get pod -f ./pod.yaml
  • flags: 指定可选的参数。例如,可以使用 -s 或 -server 参数指定 Kubernetes API 服务器的地址和端口。

警告:

从命令行指定的参数会覆盖默认值和任何相应的环境变量。

如果您需要帮助,只需从终端窗口运行 kubectl help 即可

 

yml

yml模板

 

 使用apply命令可以使用yml文件

kubectl apply -f example.yaml

可以将之前部署tomcat格式化为yml信息

[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: null
  labels:
    app: tomcat6
  name: tomcat6
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tomcat6
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: tomcat6
    spec:
      containers:
      - image: tomcat:6.0.53-jre8
        name: tomcat
        resources: {}
status: {}

将其保存为tomcat6.yaml

可以使用该文件

kubectl apply -f tomcat6.yaml

 

入门操作

Pod是个啥

Pod和Controller

控制器可以创建和管理多个Pod,管理副本和上线,并在集群范围内提供自修复能力。如,一个节点识别,控制器可以在不同的节点上调度一样的替身来自动替换Pod。

包含一个或多个Pod的控制器的一些示例:

  • Deployment
  • StatefulSet
  • DaemonSet

控制器通常使用您提供的Pod模板来创建它所负责的Pod

 

Services

将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。

使用Kubernetes,您无需修改应用程序即可使用不熟悉的服务发现机制。 Kubernetes为Pods提供自己的IP地址和一组Pod的单个DNS名称,并且可以在它们之间进行负载平衡。

Kubernetes Pods 是有生命周期的。他们可以被创建,而且销毁不会再启动。 如果您使用 Deployment 来运行您的应用程序,则它可以动态创建和销毁 Pod。

每个 Pod 都有自己的 IP 地址,但是在 Deployment 中,在同一时刻运行的 Pod 集合可能与稍后运行该应用程序的 Pod 集合不同。

这导致了一个问题: 如果一组 Pod(称为“后端”)为群集内的其他 Pod(称为“前端”)提供功能,那么前端如何找出并跟踪要连接的 IP 地址,以便前端可以使用工作量的后端部分?

Kubernetes Service 定义了这样一种抽象:逻辑上的一组 Pod,一种可以访问它们的策略 —— 通常称为微服务。 这一组 Pod 能够被 Service 访问到,通常是通过 selector (查看下面了解,为什么你可能需要没有 selector 的 Service)实现的。

 

重新部署下tomcat服务,删除之前的资源

[root@k8s-node1 k8s]# kubectl get all
NAME                           READY   STATUS    RESTARTS   AGE
pod/tomcat6-5f7ccf4cb9-2bghn   1/1     Running   10         41d

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP        41d
service/tomcat6      NodePort    10.96.57.43   <none>        80:32311/TCP   41d

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/tomcat6   1/1     1            1           41d

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/tomcat6-5f7ccf4cb9   1         1         1       41d
[root@k8s-node1 k8s]# kubectl delete deployment.apps/tomcat6
deployment.apps "tomcat6" deleted

[root@k8s-node1 k8s]# kubectl delete pod/tomcat6-5f7ccf4cb9-2bghn
Error from server (NotFound): pods "tomcat6-5f7ccf4cb9-2bghn" not found

[root@k8s-node1 k8s]# kubectl delete service/tomcat6
service "tomcat6" deleted

 

生成yaml文件,去掉不必要的内容

[root@k8s-node1 k8s]# kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8 --dry-run -o yaml > tomcat6-deployment.yaml
[root@k8s-node1 k8s]# vi tomcat6-deployment.yaml

 

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: tomcat6
  name: tomcat6
spec:
  replicas: 3
  selector:
    matchLabels:
      app: tomcat6
  template:
    metadata:
      labels:
        app: tomcat6
    spec:
      containers:
      - image: tomcat:6.0.53-jre8
        name: tomcat

进行Deployment,会产生Pod

[root@k8s-node1 k8s]# kubectl apply -f tomcat6-deployment.yaml
deployment.apps/tomcat6 created
[root@k8s
-node1 k8s]# kubectl get all NAME READY STATUS RESTARTS AGE pod/tomcat6-5f7ccf4cb9-542xn 1/1 Running 0 12s pod/tomcat6-5f7ccf4cb9-c7599 1/1 Running 0 12s pod/tomcat6-5f7ccf4cb9-sffzb 1/1 Running 0 12s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 41d NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/tomcat6 3/3 3 3 12s NAME DESIRED CURRENT READY AGE replicaset.apps/tomcat6-5f7ccf4cb9 3 3 3 12s

 

暴露服务

[root@k8s-node1 k8s]# kubectl expose deployment tomcat6 --port=80 --target-port=8080 --type=NodePort --dry-run -o yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: tomcat6
  name: tomcat6
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: tomcat6
  type: NodePort
status:
  loadBalancer: {}

我们可以将这个yaml复制到上一个yaml进行合并

[root@k8s-node1 k8s]# vi tomcat6-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: tomcat6
  name: tomcat6
spec:
  replicas: 3
  selector:
    matchLabels:
      app: tomcat6
  template:
    metadata:
      labels:
        app: tomcat6
    spec:
      containers:
      - image: tomcat:6.0.53-jre8
        name: tomcat
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: tomcat6
  name: tomcat6
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: tomcat6
  type: NodePort

删除之前的部署

[root@k8s-node1 k8s]# kubectl get all
NAME                           READY   STATUS    RESTARTS   AGE
pod/tomcat6-5f7ccf4cb9-542xn   1/1     Running   0          5m34s
pod/tomcat6-5f7ccf4cb9-c7599   1/1     Running   0          5m34s
pod/tomcat6-5f7ccf4cb9-sffzb   1/1     Running   0          5m34s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   41d

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/tomcat6   3/3     3            3           5m34s

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/tomcat6-5f7ccf4cb9   3         3         3       5m34s
[root@k8s
-node1 k8s]# kubectl delete deployment.apps/tomcat6 deployment.apps "tomcat6" deleted [root@k8s-node1 k8s]# kubectl get all NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 41d

 

现在一次进行部署和暴露

[root@k8s-node1 k8s]# kubectl apply -f tomcat6-deployment.yaml
deployment.apps/tomcat6 created
service/tomcat6 created

[root@k8s-node1 k8s]# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/tomcat6-5f7ccf4cb9-g74gl 1/1 Running 0 24s
pod/tomcat6-5f7ccf4cb9-hz6md 1/1 Running 0 24s
pod/tomcat6-5f7ccf4cb9-pb2bx 1/1 Running 0 24s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 41d
service/tomcat6 NodePort 10.96.21.159 <none> 80:31871/TCP 24s

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/tomcat6 3/3 3 3 24s

NAME DESIRED CURRENT READY AGE
replicaset.apps/tomcat6-5f7ccf4cb9 3 3 3 24s

 

Ingress

通过Service发现Pod进行关联,基于域名访问

通过Ingress Controller实现Pod负载均衡

支持TCP/UDP 4层负载均衡和HTTP 7层负载均衡

步骤:

  • 部署Ingress Controller
[root@k8s-node1 k8s]# kubectl apply -f ingress-controller.yaml
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
daemonset.apps/nginx-ingress-controller created
service/ingress-nginx created

[root@k8s-node1 k8s]# kubectl get pods --all-namespaces
NAMESPACE       NAME                                READY   STATUS              RESTARTS   AGE
default         tomcat6-5f7ccf4cb9-g74gl            1/1     Running             0          7m13s
default         tomcat6-5f7ccf4cb9-hz6md            1/1     Running             0          7m13s
default         tomcat6-5f7ccf4cb9-pb2bx            1/1     Running             0          7m13s
ingress-nginx   nginx-ingress-controller-v28sn      0/1     ContainerCreating   0          80s
ingress-nginx   nginx-ingress-controller-w8qng      0/1     ContainerCreating   0          80s
kube-system     coredns-7f9c544f75-lvsrk            1/1     Running             14         41d
kube-system     coredns-7f9c544f75-xlk4v            1/1     Running             14         41d
kube-system     etcd-k8s-node1                      1/1     Running             15         41d
kube-system     kube-apiserver-k8s-node1            1/1     Running             15         41d
kube-system     kube-controller-manager-k8s-node1   1/1     Running             65         41d
kube-system     kube-flannel-ds-amd64-ktbfz         1/1     Running             12         41d
kube-system     kube-flannel-ds-amd64-lh9fl         1/1     Running             10         41d
kube-system     kube-flannel-ds-amd64-m99gh         1/1     Running             16         41d
kube-system     kube-proxy-dwmnm                    1/1     Running             12         41d
kube-system     kube-proxy-kxcpw                    1/1     Running             14         41d
kube-system     kube-proxy-mnj6q                    1/1     Running             10         41d
kube-system     kube-scheduler-k8s-node1            1/1     Running             59         41d

 

 

apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    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 "<election-id>-<ingress-class>"
      # Here: "<ingress-controller-leader>-<nginx>"
      # This has to be adapted if you change either parameter
      # when launching the nginx-ingress-controller.
      - "ingress-controller-leader-nginx"
    verbs:
      - get
      - update
  - apiGroups:
      - ""
    resources:
      - configmaps
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - get

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: nginx-ingress-role-nisa-binding
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nginx-ingress-role
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: nginx-ingress-clusterrole-nisa-binding
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nginx-ingress-clusterrole
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---

apiVersion: apps/v1
kind: DaemonSet 
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      hostNetwork: true
      serviceAccountName: nginx-ingress-serviceaccount
      containers:
        - name: nginx-ingress-controller
          image: siriuszg/nginx-ingress-controller:0.20.0
          args:
            - /nginx-ingress-controller
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
            - --annotations-prefix=nginx.ingress.kubernetes.io
          securityContext:
            allowPrivilegeEscalation: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 33
            runAsUser: 33
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
            - name: https
              containerPort: 443
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10

---
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
spec:
  #type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
  - name: https
    port: 443
    targetPort: 443
    protocol: TCP
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
  • 创建Ingress规则
vi ingress-tomcat6.yaml

 

kind: Ingress
metadata:
  name: web
spec:
  rules:
  - host: example.aidata.com
    http:
      paths:
        - backend:
           serviceName: tomcat6
           servicePort: 80

windows的hosts文件里

192.168.56.101 example.aidata.com

浏览器直接访问,不用端口

 

 

部署dashboard

[root@k8s-node1 k8s]# kubectl apply -f kubernetes-dashboard.yaml
secret/kubernetes-dashboard-certs created
serviceaccount/kubernetes-dashboard created
role.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created
deployment.apps/kubernetes-dashboard created
service/kubernetes-dashboard created

 

# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# ------------------- Dashboard Secret ------------------- #

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-certs
  namespace: kube-system
type: Opaque

---
# ------------------- Dashboard Service Account ------------------- #

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system

---
# ------------------- Dashboard Role & Role Binding ------------------- #

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: kubernetes-dashboard-minimal
  namespace: kube-system
rules:
  # Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret.
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["create"]
  # Allow Dashboard to create 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["create"]
  # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
- apiGroups: [""]
  resources: ["secrets"]
  resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"]
  verbs: ["get", "update", "delete"]
  # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["kubernetes-dashboard-settings"]
  verbs: ["get", "update"]
  # Allow Dashboard to get metrics from heapster.
- apiGroups: [""]
  resources: ["services"]
  resourceNames: ["heapster"]
  verbs: ["proxy"]
- apiGroups: [""]
  resources: ["services/proxy"]
  resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
  verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: kubernetes-dashboard-minimal
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kubernetes-dashboard-minimal
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kube-system

---
# ------------------- Dashboard Deployment ------------------- #

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kubernetes-dashboard
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
    spec:
      containers:
      - name: kubernetes-dashboard
        image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1
        ports:
        - containerPort: 8443
          protocol: TCP
        args:
          - --auto-generate-certificates
          # Uncomment the following line to manually specify Kubernetes API server Host
          # If not specified, Dashboard will attempt to auto discover the API server and connect
          # to it. Uncomment only if the default does not work.
          # - --apiserver-host=http://my-address:port
        volumeMounts:
        - name: kubernetes-dashboard-certs
          mountPath: /certs
          # Create on-disk volume to store exec logs
        - mountPath: /tmp
          name: tmp-volume
        livenessProbe:
          httpGet:
            scheme: HTTPS
            path: /
            port: 8443
          initialDelaySeconds: 30
          timeoutSeconds: 30
      volumes:
      - name: kubernetes-dashboard-certs
        secret:
          secretName: kubernetes-dashboard-certs
      - name: tmp-volume
        emptyDir: {}
      serviceAccountName: kubernetes-dashboard
      # Comment the following tolerations if Dashboard must not be deployed on master
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule

---
# ------------------- Dashboard Service ------------------- #

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  ports:
    - port: 443
      targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard

 

KuberSphere

比dashboard更加强大

https://kubesphere.com.cn/docs/zh-CN/installation/prerequisites/

 

安装helm

[root@k8s-node1 k8s]# curl -L https://git.io/get_helm.sh | bash

get_helm.sh

#!/usr/bin/env bash

# Copyright The Helm Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# The install script is based off of the MIT-licensed script from glide,
# the package manager for Go: https://github.com/Masterminds/glide.sh/blob/master/get

PROJECT_NAME="helm"
TILLER_NAME="tiller"

: ${USE_SUDO:="true"}
: ${HELM_INSTALL_DIR:="/usr/local/bin"}

# initArch discovers the architecture for this system.
initArch() {
  ARCH=$(uname -m)
  case $ARCH in
    armv5*) ARCH="armv5";;
    armv6*) ARCH="armv6";;
    armv7*) ARCH="arm";;
    aarch64) ARCH="arm64";;
    x86) ARCH="386";;
    x86_64) ARCH="amd64";;
    i686) ARCH="386";;
    i386) ARCH="386";;
  esac
}

# initOS discovers the operating system for this system.
initOS() {
  OS=$(echo `uname`|tr '[:upper:]' '[:lower:]')

  case "$OS" in
    # Minimalist GNU for Windows
    mingw*) OS='windows';;
  esac
}

# runs the given command as root (detects if we are root already)
runAsRoot() {
  local CMD="$*"

  if [ $EUID -ne 0 -a $USE_SUDO = "true" ]; then
    CMD="sudo $CMD"
  fi

  $CMD
}

# verifySupported checks that the os/arch combination is supported for
# binary builds.
verifySupported() {
  local supported="darwin-386\ndarwin-amd64\nlinux-386\nlinux-amd64\nlinux-arm\nlinux-arm64\nlinux-ppc64le\nwindows-386\nwindows-amd64"
  if ! echo "${supported}" | grep -q "${OS}-${ARCH}"; then
    echo "No prebuilt binary for ${OS}-${ARCH}."
    echo "To build from source, go to https://github.com/helm/helm"
    exit 1
  fi

  if ! type "curl" > /dev/null && ! type "wget" > /dev/null; then
    echo "Either curl or wget is required"
    exit 1
  fi
}

# checkDesiredVersion checks if the desired version is available.
checkDesiredVersion() {
  if [ "x$DESIRED_VERSION" == "x" ]; then
    # Get tag from release URL
    local release_url="https://github.com/helm/helm/releases"
    if type "curl" > /dev/null; then

      TAG=$(curl -Ls $release_url | grep 'href="/helm/helm/releases/tag/v2.' | grep -v no-underline | head -n 1 | cut -d '"' -f 2 | awk '{n=split($NF,a,"/");print a[n]}' | awk 'a !~ $0{print}; {a=$0}')
    elif type "wget" > /dev/null; then
      TAG=$(wget $release_url -O - 2>&1 | grep 'href="/helm/helm/releases/tag/v2.' | grep -v no-underline | head -n 1 | cut -d '"' -f 2 | awk '{n=split($NF,a,"/");print a[n]}' | awk 'a !~ $0{print}; {a=$0}')
    fi
  else
    TAG=$DESIRED_VERSION
  fi
}

# checkHelmInstalledVersion checks which version of helm is installed and
# if it needs to be changed.
checkHelmInstalledVersion() {
  if [[ -f "${HELM_INSTALL_DIR}/${PROJECT_NAME}" ]]; then
    local version=$("${HELM_INSTALL_DIR}/${PROJECT_NAME}" version -c | grep '^Client' | cut -d'"' -f2)
    if [[ "$version" == "$TAG" ]]; then
      echo "Helm ${version} is already ${DESIRED_VERSION:-latest}"
      return 0
    else
      echo "Helm ${TAG} is available. Changing from version ${version}."
      return 1
    fi
  else
    return 1
  fi
}

# downloadFile downloads the latest binary package and also the checksum
# for that binary.
downloadFile() {
  HELM_DIST="helm-$TAG-$OS-$ARCH.tar.gz"
  DOWNLOAD_URL="https://get.helm.sh/$HELM_DIST"
  CHECKSUM_URL="$DOWNLOAD_URL.sha256"
  HELM_TMP_ROOT="$(mktemp -dt helm-installer-XXXXXX)"
  HELM_TMP_FILE="$HELM_TMP_ROOT/$HELM_DIST"
  HELM_SUM_FILE="$HELM_TMP_ROOT/$HELM_DIST.sha256"
  echo "Downloading $DOWNLOAD_URL"
  if type "curl" > /dev/null; then
    curl -SsL "$CHECKSUM_URL" -o "$HELM_SUM_FILE"
  elif type "wget" > /dev/null; then
    wget -q -O "$HELM_SUM_FILE" "$CHECKSUM_URL"
  fi
  if type "curl" > /dev/null; then
    curl -SsL "$DOWNLOAD_URL" -o "$HELM_TMP_FILE"
  elif type "wget" > /dev/null; then
    wget -q -O "$HELM_TMP_FILE" "$DOWNLOAD_URL"
  fi
}

# installFile verifies the SHA256 for the file, then unpacks and
# installs it.
installFile() {
  HELM_TMP="$HELM_TMP_ROOT/$PROJECT_NAME"
  local sum=$(openssl sha1 -sha256 ${HELM_TMP_FILE} | awk '{print $2}')
  local expected_sum=$(cat ${HELM_SUM_FILE})
  if [ "$sum" != "$expected_sum" ]; then
    echo "SHA sum of ${HELM_TMP_FILE} does not match. Aborting."
    exit 1
  fi

  mkdir -p "$HELM_TMP"
  tar xf "$HELM_TMP_FILE" -C "$HELM_TMP"
  HELM_TMP_BIN="$HELM_TMP/$OS-$ARCH/$PROJECT_NAME"
  TILLER_TMP_BIN="$HELM_TMP/$OS-$ARCH/$TILLER_NAME"
  echo "Preparing to install $PROJECT_NAME and $TILLER_NAME into ${HELM_INSTALL_DIR}"
  runAsRoot cp "$HELM_TMP_BIN" "$HELM_INSTALL_DIR"
  echo "$PROJECT_NAME installed into $HELM_INSTALL_DIR/$PROJECT_NAME"
  if [ -x "$TILLER_TMP_BIN" ]; then
    runAsRoot cp "$TILLER_TMP_BIN" "$HELM_INSTALL_DIR"
    echo "$TILLER_NAME installed into $HELM_INSTALL_DIR/$TILLER_NAME"
  else
    echo "info: $TILLER_NAME binary was not found in this release; skipping $TILLER_NAME installation"
  fi
}

# fail_trap is executed if an error occurs.
fail_trap() {
  result=$?
  if [ "$result" != "0" ]; then
    if [[ -n "$INPUT_ARGUMENTS" ]]; then
      echo "Failed to install $PROJECT_NAME with the arguments provided: $INPUT_ARGUMENTS"
      help
    else
      echo "Failed to install $PROJECT_NAME"
    fi
    echo -e "\tFor support, go to https://github.com/helm/helm."
  fi
  cleanup
  exit $result
}

# testVersion tests the installed client to make sure it is working.
testVersion() {
  set +e
  HELM="$(which $PROJECT_NAME)"
  if [ "$?" = "1" ]; then
    echo "$PROJECT_NAME not found. Is $HELM_INSTALL_DIR on your "'$PATH?'
    exit 1
  fi
  set -e
  echo "Run '$PROJECT_NAME init' to configure $PROJECT_NAME."
}

# help provides possible cli installation arguments
help () {
  echo "Accepted cli arguments are:"
  echo -e "\t[--help|-h ] ->> prints this help"
  echo -e "\t[--version|-v <desired_version>]"
  echo -e "\te.g. --version v2.4.0  or -v latest"
  echo -e "\t[--no-sudo]  ->> install without sudo"
}

# cleanup temporary files to avoid https://github.com/helm/helm/issues/2977
cleanup() {
  if [[ -d "${HELM_TMP_ROOT:-}" ]]; then
    rm -rf "$HELM_TMP_ROOT"
  fi
}

# Execution

#Stop execution on any error
trap "fail_trap" EXIT
set -e

# Parsing input arguments (if any)
export INPUT_ARGUMENTS="${@}"
set -u
while [[ $# -gt 0 ]]; do
  case $1 in
    '--version'|-v)
       shift
       if [[ $# -ne 0 ]]; then
           export DESIRED_VERSION="${1}"
       else
           echo -e "Please provide the desired version. e.g. --version v2.4.0 or -v latest"
           exit 0
       fi
       ;;
    '--no-sudo')
       USE_SUDO="false"
       ;;
    '--help'|-h)
       help
       exit 0
       ;;
    *) exit 1
       ;;
  esac
  shift
done
set +u

initArch
initOS
verifySupported
checkDesiredVersion
if ! checkHelmInstalledVersion; then
  downloadFile
  installFile
fi
testVersion
cleanup

 

配置权限

创建helm-rbac.yaml文件创建helm-rbac.yaml文件

apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system

 

[root@k8s-node1 k8s]# kubectl apply -f helm-rbac.yaml
serviceaccount/tiller created
clusterrolebinding.rbac.authorization.k8s.io/tiller created

初始化

helm init --service-account=tiller --tiller-image=sapcc/tiller:v2.16.3   --history-max 300

--tiller-image指定镜像,否则会被墙

 

安装 OpenEBS 创建 LocalPV 存储类型  https://kubesphere.com.cn/docs/zh-CN/appendix/install-openebs/

[root@k8s-node1 k8s]# kubectl get node -o wide
NAME        STATUS   ROLES    AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION               CONTAINER-RUNTIME
k8s-node1   Ready    master   41d   v1.17.3   10.0.2.5      <none>        CentOS Linux 7 (Core)   3.10.0-957.12.2.el7.x86_64   docker://19.3.8
k8s-node2   Ready    <none>   41d   v1.17.3   10.0.2.4      <none>        CentOS Linux 7 (Core)   3.10.0-957.12.2.el7.x86_64   docker://19.3.8
k8s-node3   Ready    <none>   41d   v1.17.3   10.0.2.15     <none>        CentOS Linux 7 (Core)   3.10.0-957.12.2.el7.x86_64   docker://19.3.8
[root@k8s-node1 k8s]# kubectl describe node k8s-node1 | grep Taint Taints: node-role.kubernetes.io/master:NoSchedule
[root@k8s
-node1 k8s]# kubectl taint nodes k8s-node1 node-role.kubernetes.io/master:NoSchedule- node/k8s-node1 untainted
[root@k8s
-node1 k8s]# kubectl describe node k8s-node1 | grep Taint Taints: <none> [root@k8s-node1 k8s]# kubectl create ns openebs namespace/openebs created
[root@k8s
-node1 k8s]# helm install --namespace openebs --name openebs stable/openebs --version 1.5.0 NAME: openebs LAST DEPLOYED: Mon Jun 8 10:10:50 2020 NAMESPACE: openebs STATUS: DEPLOYED RESOURCES: ==> v1/ClusterRole NAME AGE openebs 4s ==> v1/ClusterRoleBinding NAME AGE openebs 4s ==> v1/ConfigMap NAME AGE openebs-ndm-config 4s ==> v1/DaemonSet NAME AGE openebs-ndm 4s ==> v1/Deployment NAME AGE openebs-admission-server 4s openebs-apiserver 4s openebs-localpv-provisioner 4s openebs-ndm-operator 4s openebs-provisioner 4s openebs-snapshot-operator 4s ==> v1/Pod(related) NAME AGE openebs-admission-server-5cf6864fbf-ttntv 4s openebs-apiserver-bc55cd99b-8sbh7 4s openebs-localpv-provisioner-85ff89dd44-h9qzh 4s openebs-ndm-cdqc5 4s openebs-ndm-cvgpf 4s openebs-ndm-operator-87df44d9-849cd 3s openebs-ndm-sc779 4s openebs-provisioner-7f86c6bb64-94pxj 4s openebs-snapshot-operator-54b9c886bf-bsj6f 3s ==> v1/Service NAME AGE openebs-apiservice 4s ==> v1/ServiceAccount NAME AGE openebs 4s NOTES: The OpenEBS has been installed. Check its status by running: $ kubectl get pods -n openebs For dynamically creating OpenEBS Volumes, you can either create a new StorageClass or use one of the default storage classes provided by OpenEBS. Use `kubectl get sc` to see the list of installed OpenEBS StorageClasses. A sample PVC spec using `openebs-jiva-default` StorageClass is given below:" --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: demo-vol-claim spec: storageClassName: openebs-jiva-default accessModes: - ReadWriteOnce resources: requests: storage: 5G --- For more information, please visit http://docs.openebs.io/. Please note that, OpenEBS uses iSCSI for connecting applications with the OpenEBS Volumes and your nodes should have the iSCSI initiator installed. [root@k8s-node1 k8s]# kubectl get pods --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE default tomcat6-5f7ccf4cb9-g74gl 1/1 Running 0 117m default tomcat6-5f7ccf4cb9-hz6md 1/1 Running 0 117m default tomcat6-5f7ccf4cb9-pb2bx 1/1 Running 0 117m ingress-nginx nginx-ingress-controller-q5dzl 1/1 Running 0 3m47s ingress-nginx nginx-ingress-controller-v28sn 1/1 Running 0 111m ingress-nginx nginx-ingress-controller-w8qng 1/1 Running 0 111m kube-system coredns-7f9c544f75-lvsrk 1/1 Running 14 41d kube-system coredns-7f9c544f75-xlk4v 1/1 Running 14 41d kube-system etcd-k8s-node1 1/1 Running 15 41d kube-system kube-apiserver-k8s-node1 1/1 Running 15 41d kube-system kube-controller-manager-k8s-node1 1/1 Running 65 41d kube-system kube-flannel-ds-amd64-ktbfz 1/1 Running 12 41d kube-system kube-flannel-ds-amd64-lh9fl 1/1 Running 10 41d kube-system kube-flannel-ds-amd64-m99gh 1/1 Running 16 41d kube-system kube-proxy-dwmnm 1/1 Running 12 41d kube-system kube-proxy-kxcpw 1/1 Running 14 41d kube-system kube-proxy-mnj6q 1/1 Running 10 41d kube-system kube-scheduler-k8s-node1 1/1 Running 59 41d kube-system kubernetes-dashboard-7c54d59f66-48g9z 0/1 ImagePullBackOff 0 75m kube-system tiller-deploy-5fdc6844fb-kjps5 1/1 Running 0 8m8s openebs openebs-admission-server-5cf6864fbf-ttntv 1/1 Running 0 2m16s openebs openebs-apiserver-bc55cd99b-8sbh7 1/1 Running 3 2m16s openebs openebs-localpv-provisioner-85ff89dd44-h9qzh 1/1 Running 0 2m16s openebs openebs-ndm-cdqc5 1/1 Running 0 2m16s openebs openebs-ndm-cvgpf 1/1 Running 0 2m16s openebs openebs-ndm-operator-87df44d9-849cd 1/1 Running 1 2m15s openebs openebs-ndm-sc779 1/1 Running 0 2m16s openebs openebs-provisioner-7f86c6bb64-94pxj 1/1 Running 0 2m16s openebs openebs-snapshot-operator-54b9c886bf-bsj6f 2/2 Running 0 2m15s
[root@k8s
-node1 k8s]# kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE openebs-device openebs.io/local Delete WaitForFirstConsumer false 21s openebs-hostpath openebs.io/local Delete WaitForFirstConsumer false 21s openebs-jiva-default openebs.io/provisioner-iscsi Delete Immediate false 23s openebs-snapshot-promoter volumesnapshot.external-storage.k8s.io/snapshot-promoter Delete Immediate false 21s
[root@k8s
-node1 k8s]# kubectl patch storageclass openebs-hostpath -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' storageclass.storage.k8s.io/openebs-hostpath patched [root@k8s-node1 k8s]# kubectl taint nodes k8s-node1 node-role.kubernetes.io=master:NoSchedule node/k8s-node1 tainted

 

安装KubeSphere的前置条件至此完成,安装KubeSphere

[root@k8s-node1 k8s]# vi kubesphere-minimal.yaml
[root@k8s-node1 k8s]# kubectl apply -f kubesphere-minimal.yaml

 

 kubesphere-minimal.yaml 最小安装

---
apiVersion: v1
kind: Namespace
metadata:
  name: kubesphere-system

---
apiVersion: v1
data:
  ks-config.yaml: |
    ---
    persistence:
      storageClass: ""
    etcd:
      monitoring: False
      endpointIps: 192.168.0.7,192.168.0.8,192.168.0.9
      port: 2379
      tlsEnable: True
    common:
      mysqlVolumeSize: 20Gi
      minioVolumeSize: 20Gi
      etcdVolumeSize: 20Gi
      openldapVolumeSize: 2Gi
      redisVolumSize: 2Gi
    metrics_server:
      enabled: False
    console:
      enableMultiLogin: False  # enable/disable multi login
      port: 30880
    monitoring:
      prometheusReplicas: 1
      prometheusMemoryRequest: 400Mi
      prometheusVolumeSize: 20Gi
      grafana:
        enabled: False
    logging:
      enabled: False
      elasticsearchMasterReplicas: 1
      elasticsearchDataReplicas: 1
      logsidecarReplicas: 2
      elasticsearchMasterVolumeSize: 4Gi
      elasticsearchDataVolumeSize: 20Gi
      logMaxAge: 7
      elkPrefix: logstash
      containersLogMountedPath: ""
      kibana:
        enabled: False
    openpitrix:
      enabled: False
    devops:
      enabled: False
      jenkinsMemoryLim: 2Gi
      jenkinsMemoryReq: 1500Mi
      jenkinsVolumeSize: 8Gi
      jenkinsJavaOpts_Xms: 512m
      jenkinsJavaOpts_Xmx: 512m
      jenkinsJavaOpts_MaxRAM: 2g
      sonarqube:
        enabled: False
        postgresqlVolumeSize: 8Gi
    servicemesh:
      enabled: False
    notification:
      enabled: False
    alerting:
      enabled: False
kind: ConfigMap
metadata:
  name: ks-installer
  namespace: kubesphere-system

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ks-installer
  namespace: kubesphere-system

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  creationTimestamp: null
  name: ks-installer
rules:
- apiGroups:
  - ""
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - apps
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - extensions
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - batch
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - rbac.authorization.k8s.io
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - apiregistration.k8s.io
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - apiextensions.k8s.io
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - tenant.kubesphere.io
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - certificates.k8s.io
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - devops.kubesphere.io
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - monitoring.coreos.com
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - logging.kubesphere.io
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - jaegertracing.io
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - storage.k8s.io
  resources:
  - '*'
  verbs:
  - '*'
- apiGroups:
  - admissionregistration.k8s.io
  resources:
  - '*'
  verbs:
  - '*'

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: ks-installer
subjects:
- kind: ServiceAccount
  name: ks-installer
  namespace: kubesphere-system
roleRef:
  kind: ClusterRole
  name: ks-installer
  apiGroup: rbac.authorization.k8s.io

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ks-installer
  namespace: kubesphere-system
  labels:
    app: ks-install
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ks-install
  template:
    metadata:
      labels:
        app: ks-install
    spec:
      serviceAccountName: ks-installer
      containers:
      - name: installer
        image: kubesphere/ks-installer:v2.1.1
        imagePullPolicy: "Always"

监控安装过程

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

最后出现下面信息

Console: http://192.168.10.100:30880
Account: admin
Password: P@88w0rd

 

 包括了登录账号和密码

kubectl get pods --all-namespaces

所有都running后就可以浏览器访问了

 

 

添加功能

  1. 通过修改 ks-installer 的 configmap 可以选装组件,执行以下命令。
$ kubectl edit cm -n kubesphere-system ks-installer

参考如下修改 ConfigMap

···
metrics-server:
     enabled: True    

 

    devops:
      enabled: True
      jenkinsMemoryLim: 2Gi
      jenkinsMemoryReq: 1500Mi
      jenkinsVolumeSize: 8Gi
      jenkinsJavaOpts_Xms: 512m
      jenkinsJavaOpts_Xmx: 512m
      jenkinsJavaOpts_MaxRAM: 2g
      sonarqube:
        enabled: True
        postgresqlVolumeSize: 8Gi
    servicemesh:
      enabled: False
    notification:
      enabled: True
    alerting:
      enabled: True

监控安装进度

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

 

 

多租户管理快速入门

 

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

 

 

 

 

 

 

选 平台角色

自定义角色,点新建

 

 赋予权限

 

 点 账户管理

点创建,填写信息,确定

 

 我们可以使用atguigu-hr登录

创建账户

 

 

 

 

 

 

 

退出,ws-manager登录

创建企业空间

 

 可以创建企业空间,也可以邀请成员,邀请ws-admin进企业空间,并指定为管理员

 

 ws-admin登录

管理企业空间

 

 邀请project-admin,指定为worksapce-viewer

邀请project-regular,指定为workspace-regular

 

project-amdin 登录

创建资源项目

 

 

 

 

 

 邀请project-regular,指定为operator

 

 这是项目的开发人员

 

创建DevOps工程

 

 邀请project-regular,指定为maintain

 

 

 

 

登录project-regular

进入项目

配置中心,密钥,创建密钥

 

 

 默认,添加数据

 

 

 

 输入key和value

上,创建一个 WordPress 密钥,Data 键值对填写 WORDPRESS_DB_PASSWORD和 123456。此时两个密钥都创建完成。

 

 创建存储卷

  1. 在当前项目下左侧菜单栏的 存储卷,点击 创建,基本信息如下。
  • 名称:wordpress-pvc
  • 别名:Wordpress 持久化存储卷
  • 描述信息:Wordpress PVC

 

 

 

 

 

 同理,创建mysql-pvc

 

 应用

部署新应用

 

 下拉,添加容器镜像

输入mysql:5.6,使用默认端口

 

 内存要大于1000M

 

下拉

 

 引用配置文件或密钥

 

 点对号

添加存储卷

 

 

 

 点对号

点对号

继续添加组件

 

 

 

 

 

 

 

 点击创建

等待

外网访问

 

 

 

 

 

 访问任意节点30110端口

 

 

基于Spring Boot项目构建流水线

DevOps

Dev:怎么开发

Ops:怎么运维

高并发:怎么承担高并发

高可用:怎么做到高可用

CI&CD

持续集成

持续部署

 

前提条件

  • 开启安装了 DevOps 功能组件,参考 安装 DevOps 系统
  • 本示例以 GitHub 和 DockerHub 为例,参考前确保已创建了 GitHub 和 DockerHub 账号;
  • 已创建了企业空间和 DevOps 工程并且创建了项目普通用户 project-regular 的账号,若还未创建请参考 多租户管理快速入门
  • 使用项目管理员 project-admin邀请项目普通用户 project-regular加入 DevOps 工程并授予 maintainer角色,若还未邀请请参考 多租户管理快速入门 - 邀请成员
  • 参考 配置 ci 节点 为流水线选择执行构建的节点。

 

 

 

 

流程说明:

  • 阶段一. Checkout SCM: 拉取 GitHub 仓库代码
  • 阶段二. Unit test: 单元测试,如果测试通过了才继续下面的任务
  • 阶段三. SonarQube analysis:sonarQube 代码质量检测
  • 阶段四. Build & push snapshot image: 根据行为策略中所选择分支来构建镜像,并将 tag 为 SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER推送至 Harbor (其中 $BUILD_NUMBER为 pipeline 活动列表的运行序号)。
  • 阶段五. Push latest image: 将 master 分支打上 tag 为 latest,并推送至 DockerHub。
  • 阶段六. Deploy to dev: 将 master 分支部署到 Dev 环境,此阶段需要审核。
  • 阶段七. Push with tag: 生成 tag 并 release 到 GitHub,并推送到 DockerHub。
  • 阶段八. Deploy to production: 将发布的 tag 部署到 Production 环境。

创建凭证

登录project-regular,创建凭证

创建 DockerHub 凭证

1、点击 创建,创建一个用于 DockerHub 登录的凭证;

  • 凭证 ID:必填,此 ID 将用于仓库中的 Jenkinsfile,此示例中可命名为 dockerhub-id
  • 类型:选择 账户凭证
  • 用户名:填写您个人的 DockerHub 的用户名
  • token / 密码:您个人的 DockerHub 的密码
  • 描述信息:介绍凭证,比如此处可以备注为 DockerHub 登录凭证

2、完成后点击 确定。

 

 

 

 

 

 

创建 GitHub 凭证

同上,创建一个用于 GitHub 的凭证,凭证 ID 可命名为 github-id,类型选择 账户凭证,输入您个人的 GitHub 用户名和密码,备注描述信息,完成后点击 确定。

注意:若用户的凭证信息如账号或密码中包含了 @$这类特殊符号,可能在运行时无法识别而报错,这类情况需要用户在创建凭证时对密码进行 urlencode 编码,可通过一些第三方网站进行转换 (比如 http://tool.chinaz.com/tools/urlencode.aspx),然后再将转换后的输出粘贴到对应的凭证信息中。

 

 

 

创建 kubeconfig 凭证

同上,在 凭证 下点击 创建,创建一个类型为 kubeconfig的凭证,凭证 ID 可命名为 demo-kubeconfig,完成后点击 确定。

说明:kubeconfig 类型的凭证用于访问接入正在运行的 Kubernetes 集群,在流水线部署步骤将用到该凭证。注意,此处的 Content 将自动获取当前 KubeSphere 中的 kubeconfig 文件内容,若部署至当前 KubeSphere 中则无需修改,若部署至其它 Kubernetes 集群,则需要将其 kubeconfig 文件的内容粘贴至 Content 中。

 

 

 

 

 

 

创建 SonarQube Token

访问 SonarQube

master 节点

[root@node01 ~]# kubectl get svc --all-namespaces
NAMESPACE                      NAME                               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
default                        kubernetes                         ClusterIP   10.96.0.1       <none>        443/TCP                  16h
gulimall                       mysql                              ClusterIP   None            <none>        3306/TCP                 11h
gulimall                       wordpress                          NodePort    10.96.31.243    <none>        80:30110/TCP             11h
ingress-nginx                  ingress-nginx                      ClusterIP   10.96.96.80     <none>        80/TCP,443/TCP           16h
kube-system                    kube-controller-manager-headless   ClusterIP   None            <none>        10252/TCP                15h
kube-system                    kube-dns                           ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP,9153/TCP   16h
kube-system                    kube-scheduler-headless            ClusterIP   None            <none>        10251/TCP                15h
kube-system                    kubelet                            ClusterIP   None            <none>        10250/TCP                15h
kube-system                    tiller-deploy                      ClusterIP   10.96.244.191   <none>        44134/TCP                15h
kubesphere-alerting-system     alerting-client-server             ClusterIP   10.96.66.239    <none>        9200/TCP                 15h
kubesphere-alerting-system     alerting-manager-server            ClusterIP   10.96.162.207   <none>        9201/TCP,9200/TCP        15h
kubesphere-alerting-system     notification                       ClusterIP   10.96.162.106   <none>        9201/TCP,9200/TCP        15h
kubesphere-controls-system     default-http-backend               ClusterIP   10.96.168.235   <none>        80/TCP                   15h
kubesphere-devops-system       ks-jenkins                         NodePort    10.96.205.17    <none>        80:30180/TCP             15h
kubesphere-devops-system       ks-jenkins-agent                   ClusterIP   10.96.101.100   <none>        50000/TCP                15h
kubesphere-devops-system       ks-sonarqube-postgresql            ClusterIP   10.96.150.29    <none>        5432/TCP                 15h
kubesphere-devops-system       ks-sonarqube-sonarqube             NodePort    10.96.3.13      <none>        9000:31426/TCP           15h
kubesphere-devops-system       s2ioperator                        ClusterIP   10.96.191.165   <none>        443/TCP                  15h
kubesphere-devops-system       s2ioperator-metrics-service        ClusterIP   10.96.217.230   <none>        8080/TCP                 15h
kubesphere-devops-system       uc-jenkins-update-center           ClusterIP   10.96.96.70     <none>        80/TCP                   15h
kubesphere-devops-system       webhook-server-service             ClusterIP   10.96.91.21     <none>        443/TCP                  15h
kubesphere-monitoring-system   kube-state-metrics                 ClusterIP   None            <none>        8443/TCP,9443/TCP        15h
kubesphere-monitoring-system   node-exporter                      ClusterIP   None            <none>        9100/TCP                 15h
kubesphere-monitoring-system   prometheus-k8s                     ClusterIP   None            <none>        9090/TCP                 15h
kubesphere-monitoring-system   prometheus-k8s-system              ClusterIP   None            <none>        9090/TCP                 15h
kubesphere-monitoring-system   prometheus-operated                ClusterIP   None            <none>        9090/TCP                 15h
kubesphere-monitoring-system   prometheus-operator                ClusterIP   None            <none>        8080/TCP                 15h
kubesphere-system              etcd                               ClusterIP   10.96.139.180   <none>        2379/TCP                 15h
kubesphere-system              ks-account                         ClusterIP   10.96.151.87    <none>        80/TCP                   15h
kubesphere-system              ks-apigateway                      ClusterIP   10.96.164.101   <none>        80/TCP                   15h
kubesphere-system              ks-apiserver                       ClusterIP   10.96.76.72     <none>        80/TCP                   15h
kubesphere-system              ks-console                         NodePort    10.96.213.199   <none>        80:30880/TCP             15h
kubesphere-system              minio                              ClusterIP   10.96.42.56     <none>        9000/TCP                 15h
kubesphere-system              mysql                              ClusterIP   10.96.111.25    <none>        3306/TCP                 15h
kubesphere-system              openldap                           ClusterIP   None            <none>        389/TCP                  15h
kubesphere-system              redis                              ClusterIP   10.96.20.135    <none>        6379/TCP                 15h
openebs                        admission-server-svc               ClusterIP   10.96.208.248   <none>        443/TCP                  15h
openebs                        openebs-apiservice                 ClusterIP   10.96.233.170   <none>        5656/TCP                 15h

访问31426端口

 

 

使用默认账号 admin/admin登入 sonar

输入 name,然后点击 Generate

 复制token,保存  

点击 Continue

选择 Language Java,选择 build technology 为 Maven,复制 token。点击 Finish this tutorial即可。

 

 

 

Provide a token
gulimall-token: 606a3b04c649631669516c21f6235b81b039d519
The token is used to identify you when an analysis is performed. If it has been compromised, you can revoke it at any point of time in your user account.

新建一个凭证

 

修改 Jenkinsfile

第一步:Fork项目

登录 GitHub,将本示例用到的 GitHub 仓库 devops-java-sample Fork 至您个人的 GitHub。

 

 

 

第二步:修改 Jenkinsfile

1、Fork 至您个人的 GitHub 后,在 根目录 进入 Jenkinsfile-online。

jenkins-online

2、在 GitHub UI 点击编辑图标,需要修改如下环境变量 (environment) 的值。

image-20190409121802459

修改项含义
DOCKER_CREDENTIAL_ID dockerhub-id 填写创建凭证步骤中的 DockerHub 凭证 ID,用于登录您的 DockerHub
GITHUB_CREDENTIAL_ID github-id 填写创建凭证步骤中的 GitHub 凭证 ID,用于推送 tag 到 GitHub 仓库
KUBECONFIG_CREDENTIAL_ID demo-kubeconfig kubeconfig 凭证 ID,用于访问接入正在运行的 Kubernetes 集群
REGISTRY docker.io 默认为 docker.io 域名,用于镜像的推送
DOCKERHUB_NAMESPACE your-dockerhub-account 替换为您的 DockerHub 账号名
(它也可以是账户下的 Organization 名称)
GITHUB_ACCOUNT your-github-account 替换为您的 GitHub 账号名,例如 https://github.com/kubesphere/则填写 kubesphere(它也可以是账户下的 Organization 名称)
APP_NAME devops-java-sample 应用名称
SONAR_CREDENTIAL_ID sonar-token 填写创建凭证步骤中的 SonarQube token凭证 ID,用于代码质量检测

注:master分支 Jenkinsfile 中 mvn命令的参数 -o,表示开启离线模式。本示例为适应某些环境下网络的干扰,以及避免在下载依赖时耗时太长,已事先完成相关依赖的下载,默认开启离线模式。

去掉文件中的-o参数,修改环境

  environment {
        DOCKER_CREDENTIAL_ID = 'dockerhub-id'
        GITHUB_CREDENTIAL_ID = 'github-id'
        KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
        REGISTRY = 'docker.io'
        DOCKERHUB_NAMESPACE = 'zhao750456695'
        GITHUB_ACCOUNT = 'zhao750456695'
        APP_NAME = 'devops-java-sample'
        SONAR_CREDENTIAL_ID = 'sonar-qube'
    }

3、修改以上的环境变量后,点击 Commit changes,将更新提交到当前的 master 分支。

提交更新

4、若需要测试缓存,需要切换至 dependency分支,对 dependency分支下的 Jenkinsfile-online 做类似的修改,否则该分支的流水线将构建失败。

创建项目

CI/CD 流水线会根据示例项目的 yaml 模板文件,最终将示例分别部署到 kubesphere-sample-dev和 kubesphere-sample-prod这两个项目 (Namespace) 环境中,这两个项目需要预先在控制台依次创建,参考如下步骤创建该项目。

第一步:创建第一个项目

提示:项目管理员 project-admin账号已在 多租户管理快速入门 中创建。

1、使用项目管理员 project-admin账号登录 KubeSphere,在之前创建的企业空间 (demo-workspace) 下,点击 项目 → 创建,创建一个 资源型项目,作为本示例的开发环境,填写该项目的基本信息,完成后点击 下一步。

  • 名称:固定为 kubesphere-sample-dev,若需要修改项目名称则需在 yaml 模板文件 中修改 namespace
  • 别名:可自定义,比如 开发环境
  • 描述信息:可简单介绍该项目,方便用户进一步了解

 

 

 

2、本示例暂无资源请求和限制,因此高级设置中无需修改默认值,点击 创建,项目可创建成功。

第二步:邀请成员

第一个项目创建完后,还需要项目管理员 project-admin邀请当前的项目普通用户 project-regular进入 kubesphere-sample-dev项目,进入「项目设置」→「项目成员」,点击「邀请成员」选择邀请 project-regular并授予 operator角色,若对此有疑问可参考 多租户管理快速入门 - 邀请成员 。

第三步:创建第二个项目

同上,参考以上两步创建一个名称为 kubesphere-sample-prod的项目作为生产环境,并邀请普通用户 project-regular进入 kubesphere-sample-prod项目并授予 operator角色。

说明:当 CI/CD 流水线后续执行成功后,在 kubesphere-sample-dev和 kubesphere-sample-prod项目中将看到流水线创建的部署 (Deployment) 和服务 (Service)。

project

创建流水线

登录project-regular

第一步:填写基本信息

1、进入已创建的 DevOps 工程,选择左侧菜单栏的 流水线,然后点击 创建。

create-pipeline

2、在弹出的窗口中,输入流水线的基本信息。

  • 名称:为创建的流水线起一个简洁明了的名称,便于理解和搜索
  • 描述信息:简单介绍流水线的主要特性,帮助进一步了解流水线的作用
  • 代码仓库:点击选择代码仓库,代码仓库需已存在 Jenkinsfile

basic_info

第二步:添加仓库

1、点击代码仓库,以添加 Github 仓库为例。

2、点击弹窗中的 获取 Token

git_input

3、在 GitHub 的 access token 页面填写 Token description,简单描述该 token,如 DevOps demo,在 Select scopes 中无需任何修改,点击 Generate token,GitHub 将生成一串字母和数字组成的 token 用于访问当前账户下的 GitHub repo。

access-token

4、复制生成的 token,在 KubeSphere Token 框中输入该 token 然后点击保存。

5、验证通过后,右侧会列出此 Token 关联用户的所有代码库,选择其中一个带有 Jenkinsfile 的仓库。比如此处选择准备好的示例仓库 devops-java-sample,点击 选择此仓库,完成后点击 下一步。

image-20190409122653070

第三步:高级设置

完成代码仓库相关设置后,进入高级设置页面,高级设置支持对流水线的构建记录、行为策略、定期扫描等设置的定制化,以下对用到的相关配置作简单释义。

1、分支设置中,勾选 丢弃旧的分支,此处的 保留分支的天数 和 保留分支的最大个数 默认为 -1。

说明:

分支设置的保留分支的天数和保持分支的最大个数两个选项可以同时对分支进行作用,只要某个分支的保留天数和个数不满足任何一个设置的条件,则将丢弃该分支。假设设置的保留天数和个数为 2 和 3,则分支的保留天数一旦超过 2 或者保留个数超过 3,则将丢弃该分支。默认两个值为 -1,表示将会丢弃已经被删除的分支。

丢弃旧的分支将确定何时应丢弃项目的分支记录。分支记录包括控制台输出,存档工件以及与特定分支相关的其他元数据。保持较少的分支可以节省 Jenkins 所使用的磁盘空间,我们提供了两个选项来确定应何时丢弃旧的分支:

  • 保留分支的天数:如果分支达到一定的天数,则丢弃分支。
  • 保留分支的个数:如果已经存在一定数量的分支,则丢弃最旧的分支。

2、行为策略中,KubeSphere 默认添加了三种策略。由于本示例还未用到 从 Fork 仓库中发现 PR 这条策略,此处可以删除该策略,点击右侧删除按钮。

advance

说明:

支持添加三种类型的发现策略。需要说明的是,在 Jenkins 流水线被触发时,开发者提交的 PR (Pull Request) 也被视为一个单独的分支。

发现分支:

  • 排除也作为 PR 提交的分支:选择此项表示 CI 将不会扫描源分支 (比如 Origin 的 master branch),也就是需要被 merge 的分支
  • 只有被提交为 PR 的分支:仅扫描 PR 分支
  • 所有分支:拉取的仓库 (origin) 中所有的分支

从原仓库中发现 PR:

  • PR 与目标分支合并后的源代码版本:一次发现操作,基于 PR 与目标分支合并后的源代码版本创建并运行流水线
  • PR 本身的源代码版本:一次发现操作,基于 PR 本身的源代码版本创建并运行流水线
  • 当 PR 被发现时会创建两个流水线,一个流水线使用 PR 本身的源代码版本,一个流水线使用 PR 与目标分支合并后的源代码版本:两次发现操作,将分别创建两条流水线,第一条流水线使用 PR 本身的源代码版本,第二条流水线使用 PR 与目标分支合并后的源代码版本

3、默认的 脚本路径 为 Jenkinsfile,请将其修改为 Jenkinsfile-online

注:路径是 Jenkinsfile 在代码仓库的路径,表示它在示例仓库的根目录,若文件位置变动则需修改其脚本路径。

4、在 扫描 Repo Trigger 勾选 如果没有扫描触发,则定期扫描,扫描时间间隔可根据团队习惯设定,本示例设置为 5 minutes

说明:定期扫描是设定一个周期让流水线周期性地扫描远程仓库,根据 行为策略 查看仓库有没有代码更新或新的 PR。

Webhook 推送:

Webhook 是一种高效的方式可以让流水线发现远程仓库的变化并自动触发新的运行,GitHub 和 Git (如 Gitlab) 触发 Jenkins 自动扫描应该以 Webhook 为主,以上一步在 KubeSphere 设置定期扫描为辅。在本示例中,可以通过手动运行流水线,如需设置自动扫描远端分支并触发运行,详见 设置自动触发扫描 - GitHub SCM

完成高级设置后点击 创建。

第四步:运行流水线

流水线创建后,点击浏览器的 刷新 按钮,可见两条自动触发远程分支后的运行记录,分别为 master和 dependency分支的构建记录。 

1、点击右侧 运行,将根据上一步的 行为策略 自动扫描代码仓库中的分支,在弹窗选择需要构建流水线的 master分支,系统将根据输入的分支加载 Jenkinsfile-online (默认是根目录下的 Jenkinsfile)。

2、由于仓库的 Jenkinsfile-online 中 TAG_NAME: defaultValue没有设置默认值,因此在这里的 TAG_NAME可以输入一个 tag 编号,比如输入 v0.0.1。

3、点击 确定,将新生成一条流水线活动开始运行。

说明: tag 用于在 Github 和DockerHub 中分别生成带有 tag 的 release 和镜像。 注意: 在主动运行流水线以发布 release 时,TAG_NAME不应与之前代码仓库中所存在的 tag名称重复,如果重复会导致流水线的运行失败。

运行流水线

至此,流水线 已完成创建并开始运行。

注:点击 分支 切换到分支列表,查看流水线具体是基于哪些分支运行,这里的分支则取决于上一步 行为策略 的发现分支策略。

查看流水线

第五步:审核流水线

为方便演示,此处默认用当前账户来审核,当流水线执行至 input步骤时状态将暂停,需要手动点击 继续,流水线才能继续运行。注意,在 Jenkinsfile-online 中分别定义了三个阶段 (stage) 用来部署至 Dev 环境和 Production 环境以及推送 tag,因此在流水线中依次需要对 deploy to dev, push with tag, deploy to production这三个阶段审核 3次,若不审核或点击 终止 则流水线将不会继续运行。

审核流水线

说明:在实际的开发生产场景下,可能需要更高权限的管理员或运维人员来审核流水线和镜像,并决定是否允许将其推送至代码或镜像仓库,以及部署至开发或生产环境。Jenkinsfile 中的 input步骤支持指定用户审核流水线,比如要指定用户名为 project-admin 的用户来审核,可以在 Jenkinsfile 的 input 函数中追加一个字段,如果是多个用户则通过逗号分隔,如下所示:

···
input(id: 'release-image-with-tag', message: 'release image with tag?', submitter: 'project-admin,project-admin1')
···

 

 

集群部署

集群形式

主从式

主从复制,同步方式

主从调度,控制方式

 

分片式

数据分片存储,片区之间备份

 

选主式

为了容灾选主

为了调度选主

 

集群目标

高可用

突破数据量限制

数据备份容灾

压力分担

 

MYSQL集群

 

MMM

1.1 简介

MMM是Master-Master Manager for MySQL(mysql主从复制的简称),是Google开源项目(Perl脚本)。MMM基于MySQL Replication做的扩展架构,主要用来监控mysql主主复制并做失败转移。

其原理是将真实真实数据库节点的IP(RIP)映射为虚拟IP(VIP)集。

有个监管端,会提供多个虚拟IP(VIP),包括一个可写VIP,多个可读VIP,通过监管的管理,这些IP会绑定在可用mysql上,当某一台mysql宕机时,监管会将VIP迁移至其他mysql。

整个监管过程中,需要在mysql中添加相关授权用户,以便让mysql可以支持监管机的维护。授权的用户包括一个mmm_monitor用户和一个mmm_agent用户,如果想使用mmm的备份工具还要添加一个mmm_tools用户。

MMM 是一套支持双主故障切换以及双主日常管理的第三方软件。MMM 由 Perl 开发,用来管理和监控双主复制,虽然是双主架构,但是业务上同一时间只允许一个节点进行写入操作。

MMM 包含两类角色: writer 和 reader, 分别对应读写节点和只读节点。

使用 MMM 管理双主节点的情况下,当 writer 节点出现宕机(假定是 master1),程序会自动移除该节点上的读写 VIP,切换到 Master2 ,并设置 Master2 为 read_only = 0, 同时,所有 Slave 节点会指向 Master2

除了管理双主节点,MMM 也会管理 Slave 节点,在出现宕机、复制延迟或复制错误,MMM 会移除该节点的 VIP,直到节点恢复正常。

 

进行IP漂移,将master的IP指向备用的节点,该节点就成了master。但是该节点可能没拿到全部数据,一致性方面存在问题。

 

1.2 组件

MMM 由两类程序组成

  • monitor: 监控集群内数据库的状态,在出现异常时发布切换命令,一般和数据库分开部署
  • agent: 运行在每个 MySQL 服务器上的代理进程,monitor 命令的执行者,完成监控的探针工作和具体服务设置,例如设置 VIP、指向新同步节点

其架构如下:
MySQL mmm

1.3 切换流程

以上述架构为例,描述一下故障转移的流程,现在假设 Master1 宕机

  1. Monitor 检测到 Master1 连接失败
  2. Monitor 发送 set_offline 指令到 Master1 的 Agent
  3. Master1 Agent 如果存活,下线写 VIP,尝试把 Master1 设置为 read_only=1
  4. Moniotr 发送 set_online 指令到 Master2
  5. Master2 Agent 接收到指令,执行 select master_pos_wait() 等待同步完毕
  6. Master2 Agent 上线写 VIP,把 Master2 节点设为 read_only=0
  7. Monitor 发送更改同步对象的指令到各个 Slave 节点的 Agent
  8. 各个 Slave 节点向新 Master 同步数据

从整个流程可以看到,如果主节点出现故障,MMM 会自动实现切换,不需要人工干预,同时我们也能看出一些问题,就是数据库挂掉后,只是做了切换,不会主动补齐丢失的数据,所以 MMM 会有数据不一致性的风险。

 

MHA

简介

 MHA(Master HA)是一款开源的 MySQL 的高可用程序,它为 MySQL 主从复制架构提供了 automating master failover 功能。MHA 在监控到 master 节点故障时,会提升其中拥有最新数据的 slave 节点成为新的master 节点,在此期间,MHA 会通过于其它从节点获取额外信息来避免一致性方面的问题。MHA 还提供了 master 节点的在线切换功能,即按需切换 master/slave 节点。
  MHA 是由日本人 yoshinorim(原就职于DeNA现就职于FaceBook)开发的比较成熟的 MySQL 高可用方案。MHA 能够在30秒内实现故障切换,并能在故障切换中,最大可能的保证数据一致性。目前淘宝也正在开发相似产品 TMHA, 目前已支持一主一从。

MHA 服务

服务角色

  MHA 服务有两种角色, MHA Manager(管理节点)和 MHA Node(数据节点):
MHA Manager:
  通常单独部署在一台独立机器上管理多个 master/slave 集群(组),每个 master/slave 集群称作一个 application,用来管理统筹整个集群。
MHA node:
  运行在每台 MySQL 服务器上(master/slave/manager),它通过监控具备解析和清理 logs 功能的脚本来加快故障转移。
  主要是接收管理节点所发出指令的代理,代理需要运行在每一个 mysql 节点上。简单讲 node 就是用来收集从节点服务器上所生成的 bin-log 。对比打算提升为新的主节点之上的从节点的是否拥有并完成操作,如果没有发给新主节点在本地应用后提升为主节点。

  由上图我们可以看出,每个复制组内部和 Manager 之间都需要ssh实现无密码互连,只有这样,在 Master 出故障时, Manager 才能顺利的连接进去,实现主从切换功能。

提供的工具

  MHA会提供诸多工具程序, 其常见的如下所示:
Manager节点:
  masterha_check_ssh:MHA 依赖的 ssh 环境监测工具;
  masterha_check_repl:MYSQL 复制环境检测工具;
  masterga_manager:MHA 服务主程序;
  masterha_check_status:MHA 运行状态探测工具;
  masterha_master_monitor:MYSQL master 节点可用性监测工具;
  masterha_master_swith:master:节点切换工具;
  masterha_conf_host:添加或删除配置的节点;
  masterha_stop:关闭 MHA 服务的工具。
Node节点:(这些工具通常由MHA Manager的脚本触发,无需人为操作)
  save_binary_logs:保存和复制 master 的二进制日志;
  apply_diff_relay_logs:识别差异的中继日志事件并应用于其他 slave;
  purge_relay_logs:清除中继日志(不会阻塞 SQL 线程);
  自定义扩展:
  secondary_check_script:通过多条网络路由检测master的可用性;
  master_ip_failover_script:更新application使用的masterip;
  report_script:发送报告;
  init_conf_load_script:加载初始配置参数;
  master_ip_online_change_script;更新master节点ip地址。

工作原理


MHA工作原理总结为以下几条:
(1) 从宕机崩溃的 master 保存二进制日志事件(binlog events);
(2) 识别含有最新更新的 slave ;
(3) 应用差异的中继日志(relay log) 到其他 slave ;
(4) 应用从 master 保存的二进制日志事件(binlog events);
(5) 提升一个 slave 为新 master ;
(6) 使用其他的 slave 连接新的 master 进行复制。

 

InnoDB Cluster

 InnoDB Cluster主要由MySQL Shell、MySQL Router和MySQL服务器集群组成,三者协同工作,共同为MySQL提供完整的高可用性解决方案。下图所示为InnoDB Cluster的整体架构。

InnoDB Cluster架构

        InnoDB Cluster以组复制为基础,集群中的每个MySQL服务器实例都是组复制的成员,提供了在InnoDB Cluster内复制数据的机制,并且具有内置的故障转移功能。MySQL Shell在InnoDB Cluster中充当控制台角色,使用它包含的AdminAPI,可以使安装、配置、管理、维护多个MySQL组复制实例的工作更加轻松。通过AdminAPI的几条交互指令就可自动完成组复制配置。MySQL Router可以根据集群部署信息自动生成配置,将客户端应用程序透明地连接到MySQL服务器实例。如果服务器实例意外故障,群集将自动重新配置。在默认的单主模式下,InnoDB Cluster 具有单个读写主服务器实例。多个辅助服务器实例是主服务器实例的副本。如果主服务器出现故障,则辅助服务器将自动升级为主服务器。MySQL Router可以检测到这种情况并将客户端应用程序自动转发到新的主服务器。

 

Docker安装模拟MySQL主从复制集群

下载mysql镜像

[root@localhost ~]# docker pull mysql:5.7

创建master实例并启动

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

-v 挂载文件

创建slave实例并启动

docker run -p 3317:3306 --name mysql-slaver-01 -v /bigdata/mysql/slaver/log:/var/log/mysql -v /bigdata/mysql/slaver/data:/var/lib/mysql -v /bigdata/mysql/slaver/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7

 

修改master基本配置

创建 /bigdata/mysql/master/conf/my.cnf

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

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

init_connect通常用于:当一个连接进来时,做一些操作,比如设置autocommit为0,比如记录当前连接的ip来源和用户等信息到一个新表里,当做登陆日志信息。

init_connect 是可以动态在线调整的,这样就有了一些其他的用处。 
经过测试init_connect 是用户登录到数据库上之后,在执行第一次查询之前执行 里面的内容的。 
如果init_connect  的内容有语法错误,导致执行失败,会导致用户无法执行查询,从mysql 退出。 
init_connect 对具有super  权限的用户是无效的。

collation大致的意思就是字符序。首先字符本来是不分大小的,那么对字符的>, = , < 操作就需要有个字符序的规则。collation做的就是这个事情,你可以对表进行字符序的设置,也可以单独对某个字段进行字符序的设置。一个字符类型,它的字符序有多个。以_ci(表示大小写不敏感),以_cs(表示大小写敏感),以_bin(表示用编码值进行比较)。

skip-character-set-client-handshake=1 跳过mysql程序起动时的字符参数设置 ,使用服务器端字符集设置

skip_name_resolve 禁止域名解析

同理,/bigdata/mysql/slaver/conf/my.cnf也复制上面配置

 

添加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_admin

replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema

 

slaver

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_admin

replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema

 

重启两个mysql

[root@localhost conf]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
f8028c6dbf7d        mysql:5.7           "docker-entrypoint.s…"   3 hours ago         Up 3 hours          33060/tcp, 0.0.0.0:3317->3306/tcp   mysql-slaver-01
00c17fb98652        mysql:5.7           "docker-entrypoint.s…"   3 hours ago         Up 3 hours          33060/tcp, 0.0.0.0:3307->3306/tcp   mysql-master
[root@localhost conf]# docker restart mysql-master mysql-slaver-01

 

bridge网卡,无法连接docker mysql的问题

 

为master授权用户来它的同步数据

连接master

添加用来同步的用户

授权一个用户可以访问主节点,进行日志复制

mysql> GRANT REPLICATION SLAVE ON *.* TO 'backup'@'%' identified by 'root';
Query OK, 0 rows affected (0.00 sec)

 

配置slaver同步master数据

连接slaver

告诉mysql,需要同步哪个主节点

mysql> change master to master_host='192.168.10.100',master_user='backup',master_password='root',master_log_file='mysql-bin.000001',master_log_pos=0,master_port=3307;
Query OK, 0 rows affected (0.03 sec)
mysql> start slave;

 

master上新建gulimall_oms数据库,表中运行sql文件

/*
Navicat MySQL Data Transfer

Source Server         : 192.168.56.10_3306
Source Server Version : 50727
Source Host           : 192.168.56.10:3306
Source Database       : gulimall_oms

Target Server Type    : MYSQL
Target Server Version : 50727
File Encoding         : 65001

Date: 2020-03-11 17:36:38
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for mq_message
-- ----------------------------
DROP TABLE IF EXISTS `mq_message`;
CREATE TABLE `mq_message` (
  `message_id` char(32) NOT NULL,
  `content` text,
  `to_exchane` varchar(255) DEFAULT NULL,
  `routing_key` varchar(255) DEFAULT NULL,
  `class_type` varchar(255) DEFAULT NULL,
  `message_status` int(1) DEFAULT '0' COMMENT '0-新建 1-已发送 2-错误抵达 3-已抵达',
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`message_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of mq_message
-- ----------------------------

-- ----------------------------
-- Table structure for oms_order
-- ----------------------------
DROP TABLE IF EXISTS `oms_order`;
CREATE TABLE `oms_order` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `member_id` bigint(20) DEFAULT NULL COMMENT 'member_id',
  `order_sn` char(64) DEFAULT NULL COMMENT '订单号',
  `coupon_id` bigint(20) DEFAULT NULL COMMENT '使用的优惠券',
  `create_time` datetime DEFAULT NULL COMMENT 'create_time',
  `member_username` varchar(200) DEFAULT NULL COMMENT '用户名',
  `total_amount` decimal(18,4) DEFAULT NULL COMMENT '订单总额',
  `pay_amount` decimal(18,4) DEFAULT NULL COMMENT '应付总额',
  `freight_amount` decimal(18,4) DEFAULT NULL COMMENT '运费金额',
  `promotion_amount` decimal(18,4) DEFAULT NULL COMMENT '促销优化金额(促销价、满减、阶梯价)',
  `integration_amount` decimal(18,4) DEFAULT NULL COMMENT '积分抵扣金额',
  `coupon_amount` decimal(18,4) DEFAULT NULL COMMENT '优惠券抵扣金额',
  `discount_amount` decimal(18,4) DEFAULT NULL COMMENT '后台调整订单使用的折扣金额',
  `pay_type` tinyint(4) DEFAULT NULL COMMENT '支付方式【1->支付宝;2->微信;3->银联; 4->货到付款;】',
  `source_type` tinyint(4) DEFAULT NULL COMMENT '订单来源[0->PC订单;1->app订单]',
  `status` tinyint(4) DEFAULT NULL COMMENT '订单状态【0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单】',
  `delivery_company` varchar(64) DEFAULT NULL COMMENT '物流公司(配送方式)',
  `delivery_sn` varchar(64) DEFAULT NULL COMMENT '物流单号',
  `auto_confirm_day` int(11) DEFAULT NULL COMMENT '自动确认时间(天)',
  `integration` int(11) DEFAULT NULL COMMENT '可以获得的积分',
  `growth` int(11) DEFAULT NULL COMMENT '可以获得的成长值',
  `bill_type` tinyint(4) DEFAULT NULL COMMENT '发票类型[0->不开发票;1->电子发票;2->纸质发票]',
  `bill_header` varchar(255) DEFAULT NULL COMMENT '发票抬头',
  `bill_content` varchar(255) DEFAULT NULL COMMENT '发票内容',
  `bill_receiver_phone` varchar(32) DEFAULT NULL COMMENT '收票人电话',
  `bill_receiver_email` varchar(64) DEFAULT NULL COMMENT '收票人邮箱',
  `receiver_name` varchar(100) DEFAULT NULL COMMENT '收货人姓名',
  `receiver_phone` varchar(32) DEFAULT NULL COMMENT '收货人电话',
  `receiver_post_code` varchar(32) DEFAULT NULL COMMENT '收货人邮编',
  `receiver_province` varchar(32) DEFAULT NULL COMMENT '省份/直辖市',
  `receiver_city` varchar(32) DEFAULT NULL COMMENT '城市',
  `receiver_region` varchar(32) DEFAULT NULL COMMENT '',
  `receiver_detail_address` varchar(200) DEFAULT NULL COMMENT '详细地址',
  `note` varchar(500) DEFAULT NULL COMMENT '订单备注',
  `confirm_status` tinyint(4) DEFAULT NULL COMMENT '确认收货状态[0->未确认;1->已确认]',
  `delete_status` tinyint(4) DEFAULT NULL COMMENT '删除状态【0->未删除;1->已删除】',
  `use_integration` int(11) DEFAULT NULL COMMENT '下单时使用的积分',
  `payment_time` datetime DEFAULT NULL COMMENT '支付时间',
  `delivery_time` datetime DEFAULT NULL COMMENT '发货时间',
  `receive_time` datetime DEFAULT NULL COMMENT '确认收货时间',
  `comment_time` datetime DEFAULT NULL COMMENT '评价时间',
  `modify_time` datetime DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `order_sn` (`order_sn`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单';

-- ----------------------------
-- Records of oms_order
-- ----------------------------

-- ----------------------------
-- Table structure for oms_order_item
-- ----------------------------
DROP TABLE IF EXISTS `oms_order_item`;
CREATE TABLE `oms_order_item` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `order_id` bigint(20) DEFAULT NULL COMMENT 'order_id',
  `order_sn` char(64) DEFAULT NULL COMMENT 'order_sn',
  `spu_id` bigint(20) DEFAULT NULL COMMENT 'spu_id',
  `spu_name` varchar(255) DEFAULT NULL COMMENT 'spu_name',
  `spu_pic` varchar(500) DEFAULT NULL COMMENT 'spu_pic',
  `spu_brand` varchar(200) DEFAULT NULL COMMENT '品牌',
  `category_id` bigint(20) DEFAULT NULL COMMENT '商品分类id',
  `sku_id` bigint(20) DEFAULT NULL COMMENT '商品sku编号',
  `sku_name` varchar(255) DEFAULT NULL COMMENT '商品sku名字',
  `sku_pic` varchar(500) DEFAULT NULL COMMENT '商品sku图片',
  `sku_price` decimal(18,4) DEFAULT NULL COMMENT '商品sku价格',
  `sku_quantity` int(11) DEFAULT NULL COMMENT '商品购买的数量',
  `sku_attrs_vals` varchar(500) DEFAULT NULL COMMENT '商品销售属性组合(JSON)',
  `promotion_amount` decimal(18,4) DEFAULT NULL COMMENT '商品促销分解金额',
  `coupon_amount` decimal(18,4) DEFAULT NULL COMMENT '优惠券优惠分解金额',
  `integration_amount` decimal(18,4) DEFAULT NULL COMMENT '积分优惠分解金额',
  `real_amount` decimal(18,4) DEFAULT NULL COMMENT '该商品经过优惠后的分解金额',
  `gift_integration` int(11) DEFAULT NULL COMMENT '赠送积分',
  `gift_growth` int(11) DEFAULT NULL COMMENT '赠送成长值',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单项信息';

-- ----------------------------
-- Records of oms_order_item
-- ----------------------------

-- ----------------------------
-- Table structure for oms_order_operate_history
-- ----------------------------
DROP TABLE IF EXISTS `oms_order_operate_history`;
CREATE TABLE `oms_order_operate_history` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `order_id` bigint(20) DEFAULT NULL COMMENT '订单id',
  `operate_man` varchar(100) DEFAULT NULL COMMENT '操作人[用户;系统;后台管理员]',
  `create_time` datetime DEFAULT NULL COMMENT '操作时间',
  `order_status` tinyint(4) DEFAULT NULL COMMENT '订单状态【0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单】',
  `note` varchar(500) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单操作历史记录';

-- ----------------------------
-- Records of oms_order_operate_history
-- ----------------------------

-- ----------------------------
-- Table structure for oms_order_return_apply
-- ----------------------------
DROP TABLE IF EXISTS `oms_order_return_apply`;
CREATE TABLE `oms_order_return_apply` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `order_id` bigint(20) DEFAULT NULL COMMENT 'order_id',
  `sku_id` bigint(20) DEFAULT NULL COMMENT '退货商品id',
  `order_sn` char(32) DEFAULT NULL COMMENT '订单编号',
  `create_time` datetime DEFAULT NULL COMMENT '申请时间',
  `member_username` varchar(64) DEFAULT NULL COMMENT '会员用户名',
  `return_amount` decimal(18,4) DEFAULT NULL COMMENT '退款金额',
  `return_name` varchar(100) DEFAULT NULL COMMENT '退货人姓名',
  `return_phone` varchar(20) DEFAULT NULL COMMENT '退货人电话',
  `status` tinyint(1) DEFAULT NULL COMMENT '申请状态[0->待处理;1->退货中;2->已完成;3->已拒绝]',
  `handle_time` datetime DEFAULT NULL COMMENT '处理时间',
  `sku_img` varchar(500) DEFAULT NULL COMMENT '商品图片',
  `sku_name` varchar(200) DEFAULT NULL COMMENT '商品名称',
  `sku_brand` varchar(200) DEFAULT NULL COMMENT '商品品牌',
  `sku_attrs_vals` varchar(500) DEFAULT NULL COMMENT '商品销售属性(JSON)',
  `sku_count` int(11) DEFAULT NULL COMMENT '退货数量',
  `sku_price` decimal(18,4) DEFAULT NULL COMMENT '商品单价',
  `sku_real_price` decimal(18,4) DEFAULT NULL COMMENT '商品实际支付单价',
  `reason` varchar(200) DEFAULT NULL COMMENT '原因',
  `description述` varchar(500) DEFAULT NULL COMMENT '描述',
  `desc_pics` varchar(2000) DEFAULT NULL COMMENT '凭证图片,以逗号隔开',
  `handle_note` varchar(500) DEFAULT NULL COMMENT '处理备注',
  `handle_man` varchar(200) DEFAULT NULL COMMENT '处理人员',
  `receive_man` varchar(100) DEFAULT NULL COMMENT '收货人',
  `receive_time` datetime DEFAULT NULL COMMENT '收货时间',
  `receive_note` varchar(500) DEFAULT NULL COMMENT '收货备注',
  `receive_phone` varchar(20) DEFAULT NULL COMMENT '收货电话',
  `company_address` varchar(500) DEFAULT NULL COMMENT '公司收货地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单退货申请';

-- ----------------------------
-- Records of oms_order_return_apply
-- ----------------------------

-- ----------------------------
-- Table structure for oms_order_return_reason
-- ----------------------------
DROP TABLE IF EXISTS `oms_order_return_reason`;
CREATE TABLE `oms_order_return_reason` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(200) DEFAULT NULL COMMENT '退货原因名',
  `sort` int(11) DEFAULT NULL COMMENT '排序',
  `status` tinyint(1) DEFAULT NULL COMMENT '启用状态',
  `create_time` datetime DEFAULT NULL COMMENT 'create_time',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='退货原因';

-- ----------------------------
-- Records of oms_order_return_reason
-- ----------------------------

-- ----------------------------
-- Table structure for oms_order_setting
-- ----------------------------
DROP TABLE IF EXISTS `oms_order_setting`;
CREATE TABLE `oms_order_setting` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `flash_order_overtime` int(11) DEFAULT NULL COMMENT '秒杀订单超时关闭时间(分)',
  `normal_order_overtime` int(11) DEFAULT NULL COMMENT '正常订单超时时间(分)',
  `confirm_overtime` int(11) DEFAULT NULL COMMENT '发货后自动确认收货时间(天)',
  `finish_overtime` int(11) DEFAULT NULL COMMENT '自动完成交易时间,不能申请退货(天)',
  `comment_overtime` int(11) DEFAULT NULL COMMENT '订单完成后自动好评时间(天)',
  `member_level` tinyint(2) DEFAULT NULL COMMENT '会员等级【0-不限会员等级,全部通用;其他-对应的其他会员等级】',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单配置信息';

-- ----------------------------
-- Records of oms_order_setting
-- ----------------------------

-- ----------------------------
-- Table structure for oms_payment_info
-- ----------------------------
DROP TABLE IF EXISTS `oms_payment_info`;
CREATE TABLE `oms_payment_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `order_sn` char(64) DEFAULT NULL COMMENT '订单号(对外业务号)',
  `order_id` bigint(20) DEFAULT NULL COMMENT '订单id',
  `alipay_trade_no` varchar(50) DEFAULT NULL COMMENT '支付宝交易流水号',
  `total_amount` decimal(18,4) DEFAULT NULL COMMENT '支付总金额',
  `subject` varchar(200) DEFAULT NULL COMMENT '交易内容',
  `payment_status` varchar(20) DEFAULT NULL COMMENT '支付状态',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `confirm_time` datetime DEFAULT NULL COMMENT '确认时间',
  `callback_content` varchar(4000) DEFAULT NULL COMMENT '回调内容',
  `callback_time` datetime DEFAULT NULL COMMENT '回调时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `order_sn` (`order_sn`) USING BTREE,
  UNIQUE KEY `alipay_trade_no` (`alipay_trade_no`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付信息表';

-- ----------------------------
-- Records of oms_payment_info
-- ----------------------------

-- ----------------------------
-- Table structure for oms_refund_info
-- ----------------------------
DROP TABLE IF EXISTS `oms_refund_info`;
CREATE TABLE `oms_refund_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `order_return_id` bigint(20) DEFAULT NULL COMMENT '退款的订单',
  `refund` decimal(18,4) DEFAULT NULL COMMENT '退款金额',
  `refund_sn` varchar(64) DEFAULT NULL COMMENT '退款交易流水号',
  `refund_status` tinyint(1) DEFAULT NULL COMMENT '退款状态',
  `refund_channel` tinyint(4) DEFAULT NULL COMMENT '退款渠道[1-支付宝,2-微信,3-银联,4-汇款]',
  `refund_content` varchar(5000) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='退款信息';

-- ----------------------------
-- Records of oms_refund_info
-- ----------------------------

-- ----------------------------
-- Table structure for undo_log
-- ----------------------------
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of undo_log
-- ----------------------------

此时,你会发现slaver中也有了该数据库和表

 

 分库分表,读写分离

ShardingSphere

Sharding-Proxy

透明

 

 下载二进制压缩包 https://www.apache.org/dyn/closer.cgi/shardingsphere/4.1.1/apache-shardingsphere-4.1.1-sharding-proxy-bin.tar.gz

如果后端连接 MySQL 数据库,需要下载 MySQL Connector/J, 解压缩后,将 mysql-connector-java-5.1.47.jar 拷贝到 %SHARDINGSPHERE_PROXY_HOME%\lib 目录。

配置下载文件conf中的server.yaml

配置认证信息,配置了root和sharding用户,sharing用户只能访问sharding_db

authentication:
  users:
    root:
      password: root
    sharding:
      password: sharding 
      authorizedSchemas: sharding_db
#
props:
#  max.connections.size.per.query: 1
#  acceptor.size: 16  # The default value is available processors count * 2.
  executor.size: 16  # Infinite by default.
#  proxy.frontend.flush.threshold: 128  # The default value is 128.
#    # LOCAL: Proxy will run with LOCAL transaction.
#    # XA: Proxy will run with XA transaction.
#    # BASE: Proxy will run with B.A.S.E transaction.
#  proxy.transaction.type: LOCAL
#  proxy.opentracing.enabled: false
#  proxy.hint.enabled: false
#  query.with.cipher.column: true
  sql.show: false

配置分库分表,读写分离 config-sharding.yaml

数据库名字 sharding_db,映射了真实数据库demo_ds_0和demo_ds_1,我们操作sharding_db,数据实际写到两个数据库中

demo_ds_0和demo_ds_1中有两个表t_order_0和t_order_1,t_order_item_0和t_order_item_1,都用order_id分表

绑定表可以两张表联系起来,查询快

根据user_id分库

schemaName: sharding_db
#
dataSources:
  ds_0:
    url: jdbc:mysql://192.168.10.100:3307/demo_ds_0?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
  ds_1:
    url: jdbc:mysql://192.168.10.100:3307/demo_ds_1?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
#
shardingRule:
  tables:
    t_order:
      actualDataNodes: ds_${0..1}.t_order_${0..1} 
      tableStrategy:
        inline:
          shardingColumn: order_id # 用订单id分表
          algorithmExpression: t_order_${order_id % 2} # 余数为0在t_order_0表,否则在1表
      keyGenerator:
        type: SNOWFLAKE # 使用雪花算法
        column: order_id
    t_order_item:
      actualDataNodes: ds_${0..1}.t_order_item_${0..1}
      tableStrategy:
        inline:
          shardingColumn: order_id
          algorithmExpression: t_order_item_${order_id % 2}
      keyGenerator:
        type: SNOWFLAKE
        column: order_item_id
  bindingTables:
    - t_order,t_order_item # 绑定表
  defaultDatabaseStrategy:
    inline:
      shardingColumn: user_id # 分库策略
      algorithmExpression: ds_${user_id % 2}
  defaultTableStrategy:
    none:

读写分离,config-master_slave.xml

主数据源

从数据源

有两个库,配置两个主从

schemaName: sharding_db_1
#
dataSources:
  master_0_ds:
    url: jdbc:mysql://192.168.10.100:3307/demo_ds_0?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
  slave_ds_0:
    url: jdbc:mysql://192.168.10.100:3317/demo_ds_0?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
#
masterSlaveRule:
  name: ms_ds_0
  masterDataSourceName: master_0_ds
  slaveDataSourceNames:
    - slave_ds_0

config-master_slave_2.xml

schemaName: sharding_db_2
#
dataSources:
  master_1_ds:
    url: jdbc:mysql://192.168.10.100:3307/demo_ds_1?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
  slave_ds_1:
    url: jdbc:mysql://192.168.10.100:3317/demo_ds_1?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
#
masterSlaveRule:
  name: ms_ds_1
  masterDataSourceName: master_1_ds
  slaveDataSourceNames:
    - slave_ds_1

 

修改docker mysql配置文件

master和slaver都添加

binlog-do-db=demo_ds_0
binlog-do-db=demo_ds_1

创建demo_ds_0和1库

 

windows的话一定要用cmd命令行连接,navicat等连接可能会出各种错。

 

 

Redis集群

客户端分区

代理分区

redis-cluster

redis-cluster

一组Redis Cluster由多个Redis实例组成,官方推荐使用6实例,其中3个为主节点,3个为从节点。

把所有数据划分为16384个不同的槽位,可以根据机器的性能把不同的槽位分配给不同的Redis实例,对于Redis实例来说,它们只会存储部分的Redis数据。槽的数据是可以迁移的,不同实例之间,可以通过一定的协议,进行数据迁移。

 

创建6个redis节点

3主,3从

 

 使用脚本搭建docker的redis-cluster

for port in $(seq 7001 7006); \
do \
mkdir -p /bigdata/redis/node-${port}/conf
touch /bigdata/redis/node-${port}/conf/redis.conf
cat << EOF > /bigdata/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.10.101
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 /bigdata/redis/node-${port}/data:/data \
-v /bigdata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d redis:5.0.7 redis-server /etc/redis/redis.conf; \
done

使用redis建立集群

进入一个docker

docker exec -it redis-7001 bash

三台主节点,三个从节点

redis-cli --cluster create 192.168.10.101:7001 192.168.10.101:7002  192.168.10.101:7003 192.168.10.101:7004 192.168.10.101:7005 192.168.10.101:7006 --cluster-replicas 1

 --cluster-replicas 1 每个主节点必须有一个副本节点,

[root@node02 redis]# docker exec -it redis-7001 bash
root@57e92e2ffa4c:/data# redis-cli --cluster create 192.168.10.101:7001 192.168.10.101:7002  192.168.10.101:7003 192.168.10.101:7004 192.168.10.101:7005 192.168.10.101:7006 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.10.101:7005 to 192.168.10.101:7001
Adding replica 192.168.10.101:7006 to 192.168.10.101:7002
Adding replica 192.168.10.101:7004 to 192.168.10.101:7003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: aa624181696765f568bee0e650c4af216ba83c23 192.168.10.101:7001
   slots:[0-5460] (5461 slots) master
M: 825835dcfc9c34bc5d9f6cdc9d6afca45302e4a6 192.168.10.101:7002
   slots:[5461-10922] (5462 slots) master
M: 08b1626502539c77ec469e2032e693718649f69d 192.168.10.101:7003
   slots:[10923-16383] (5461 slots) master
S: 153c705b38fd253594a08989d49425d5ca4ee87f 192.168.10.101:7004
   replicates 825835dcfc9c34bc5d9f6cdc9d6afca45302e4a6
S: 4c30599c2cabbb20eafc8b4eb9d4d93c597b20cc 192.168.10.101:7005
   replicates 08b1626502539c77ec469e2032e693718649f69d
S: e62234ef3c5206770ce29580c0309efb09a98429 192.168.10.101:7006
   replicates aa624181696765f568bee0e650c4af216ba83c23
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
>>> Performing Cluster Check (using node 192.168.10.101:7001)
M: aa624181696765f568bee0e650c4af216ba83c23 192.168.10.101:7001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 4c30599c2cabbb20eafc8b4eb9d4d93c597b20cc 192.168.10.101:7005
   slots: (0 slots) slave
   replicates 08b1626502539c77ec469e2032e693718649f69d
M: 08b1626502539c77ec469e2032e693718649f69d 192.168.10.101:7003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 153c705b38fd253594a08989d49425d5ca4ee87f 192.168.10.101:7004
   slots: (0 slots) slave
   replicates 825835dcfc9c34bc5d9f6cdc9d6afca45302e4a6
M: 825835dcfc9c34bc5d9f6cdc9d6afca45302e4a6 192.168.10.101:7002
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: e62234ef3c5206770ce29580c0309efb09a98429 192.168.10.101:7006
   slots: (0 slots) slave
   replicates aa624181696765f568bee0e650c4af216ba83c23
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

M是主,S是从

发现会自动保存数据到不同节点

root@57e92e2ffa4c:/data# redis-cli -c -h 192.168.10.101 -p 7001
192.168.10.101:7001> set 1 2
-> Redirected to slot [9842] located at 192.168.10.101:7002
OK
192.168.10.101:7002> get 1
"2"
192.168.10.101:7002> set 3 6
-> Redirected to slot [1584] located at 192.168.10.101:7001
OK
192.168.10.101:7001> set u 8
-> Redirected to slot [11826] located at 192.168.10.101:7003
OK


192.168.10.101:7003> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:3
cluster_stats_messages_ping_sent:800
cluster_stats_messages_pong_sent:808
cluster_stats_messages_meet_sent:5
cluster_stats_messages_sent:1613
cluster_stats_messages_ping_received:808
cluster_stats_messages_pong_received:805
cluster_stats_messages_received:1613


192.168.10.101:7003> CLUSTER NODES
e62234ef3c5206770ce29580c0309efb09a98429 192.168.10.101:7006@17006 slave aa624181696765f568bee0e650c4af216ba83c23 0 1592193713000 6 connected
153c705b38fd253594a08989d49425d5ca4ee87f 192.168.10.101:7004@17004 slave 825835dcfc9c34bc5d9f6cdc9d6afca45302e4a6 0 1592193712000 4 connected
aa624181696765f568bee0e650c4af216ba83c23 192.168.10.101:7001@17001 master - 0 1592193712000 1 connected 0-5460
825835dcfc9c34bc5d9f6cdc9d6afca45302e4a6 192.168.10.101:7002@17002 master - 0 1592193714003 2 connected 5461-10922
08b1626502539c77ec469e2032e693718649f69d 192.168.10.101:7003@17003 myself,master - 0 1592193711000 3 connected 10923-16383
4c30599c2cabbb20eafc8b4eb9d4d93c597b20cc 192.168.10.101:7005@17005 slave 08b1626502539c77ec469e2032e693718649f69d 0 1592193712995 5 connected

 

Elasticsearch集群

一个运行中的ES实例称为一个节点,而集群是由一个或多个拥有相同cluster.name配置的节点组成,它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群会重新平均分布所有的数据。

当一个节点被选举为主节点时,它将负责管理集群范围内的所有变更,例如增加、删除索引,增加、删除节点等。主节点不需要涉及到文档级别的变更和搜索等操作。任何节点都可以成为主节点。

作为用户,我们可以将请求发送到集群中的任何节点,包括主节点。每个节点都知道任意文档的位置,并且能将我们的请求直接转发到存储我们所需文档的节点。

 

集群健康是集群监控信息最重要的一项,status字段包括green、yellow或red。

分片

 

创建网络

[root@node03 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
11642c8df0a1        bridge              bridge              local
f3824fdf854e        host                host                local
3f3b1d92bc78        none                null                local
[root@node03 ~]# docker network create --driver bridge --subnet=172.18.12.0/16 --gateway=172.18.1.1 mynet
60cbe8c50aa1cda30cf36571f8609bc7989d0040701932deba51c64a77796b49
[root@node03 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
11642c8df0a1        bridge              bridge              local
f3824fdf854e        host                host                local
60cbe8c50aa1        mynet               bridge              local
3f3b1d92bc78        none                null                local
[root@node03 ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "60cbe8c50aa1cda30cf36571f8609bc7989d0040701932deba51c64a77796b49",
        "Created": "2020-06-15T14:13:23.198137749+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.12.0/16",
                    "Gateway": "172.18.1.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

修改虚拟内存,否则会报

max virutal memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

1、切换到root用户修改配置sysctl.conf
vi /etc/sysctl.conf
添加下面配置:
vm.max_map_count=655360
并执行命令:
sysctl -p

 

创建master节点 

for port in $(seq 1 3); \
do \
mkdir -p /bigdata/elasticsearch/master-${port}/config
mkdir -p /bigdata/elasticsearch/master-${port}/data
chmod -R 777 /bigdata/elasticsearch/master-${port}
touch /bigdata/elasticsearch/master-${port}/config/elasticsearch.yml
cat << EOF > /bigdata/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:9301","172.18.12.23:9301"] # 设置集群中的master节点的初始列表,看通过这些节点自动发现其他新加入集群的节点,es7新配置
 cluster.initial_master_nodes: ["172.18.12.21"] # 新集群初始时的候选主节点,es7新增
EOF
docker run -p 920${port}:920${port} -p 930${port}:930${port} --name elasticsearch-node-${port} \
--network=mynet --ip 172.18.12.2${port} \
-e ES_JAVA_OPTS="-Xms300m -Xmx300m" \
-v /bigdata/elasticsearch/master-${port}/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /bigdata/elasticsearch/master-${port}/data:/usr/share/elasticsearch/data \
-v /bigdata/elasticsearch/master-${port}/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2; \
done

node节点

for port in $(seq 4 6); \
do \
mkdir -p /bigdata/elasticsearch/node-${port}/config
mkdir -p /bigdata/elasticsearch/node-${port}/data
chmod -R 777 /bigdata/elasticsearch/node-${port}
touch /bigdata/elasticsearch/node-${port}/config/elasticsearch.yml
cat << EOF > /bigdata/elasticsearch/node-${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:9301","172.18.12.23:9301"] # 设置集群中的master节点的初始列表,看通过这些节点自动发现其他新加入集群的节点,es7新配置
 cluster.initial_master_nodes: ["172.18.12.21"] # 新集群初始时的候选主节点,es7新增
EOF
docker run -p 920${port}:920${port} -p 930${port}:930${port} --name elasticsearch-node-${port} \
--network=mynet --ip 172.18.12.2${port} \
-e ES_JAVA_OPTS="-Xms300m -Xmx300m" \
-v /bigdata/elasticsearch/node-${port}/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /bigdata/elasticsearch/node-${port}/data:/usr/share/elasticsearch/data \
-v /bigdata/elasticsearch/node-${port}/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2; \
done

查看节点 http://192.168.10.102:9206/_cat/nodes

 标星号的为master

查看集群健康状况 http://192.168.10.102:9206/_cluster/health?pretty

 

RebbitMQ集群

 RabbitMQ是用Erlang开发的,集群非常方便,Erlang天生就是分布式语言,当其本身不支持负载均衡。

包括内存节点(RAM)、磁盘节点(Disk,消息持久化),至少有一个Disk节点。

 普通模式

  • 生产环境一般不用

镜像模式

  • 各节点同步 

集群搭建

mkdir /bigdata/rabbitmq
cd /bigdata/rabbitmq
mkdir rabbitmq01 rabbitmq02 rabbitmq03

docker run -d --hostname rabbitmq01 --name rabbitmq01 -v /bigdata/rabbitmq/rabbitmq01:/var/lib/rabbitmq -p 15673:15672 -p 5673:5672 -e RABBITMQ_ERLANG_COOKIE='atguigu' rabbitmq:management

docker run -d --hostname rabbitmq02 --name rabbitmq02 -v /bigdata/rabbitmq/rabbitmq01:/var/lib/rabbitmq -p 15674:15672 -p 5674:5672 -e RABBITMQ_ERLANG_COOKIE='atguigu'  --link rabbitmq01:rabbitmq01 rabbitmq:management

docker run -d --hostname rabbitmq03 --name rabbitmq03 -v /bigdata/rabbitmq/rabbitmq01:/var/lib/rabbitmq -p 15675:15672 -p 5675:5672 -e RABBITMQ_ERLANG_COOKIE='atguigu' --link rabbitmq01:rabbitmq01 --link rabbitmq02:rabbitmq02 rabbitmq:management

第一个节点

[root@node03 rabbitmq]# docker exec -it rabbitmq01 /bin/bash
root@rabbitmq01:/# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbitmq01 ...
root@rabbitmq01:/# rabbitmqctl reset
Resetting node rabbit@rabbitmq01 ...
root@rabbitmq01:/# rabbitmqctl start_app
Starting node rabbit@rabbitmq01 ...
root@rabbitmq01:/# exit
exit

第二个节点

[root@node03 rabbitmq]# docker exec -it rabbitmq02 /bin/bash
root@rabbitmq02:/# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbitmq02 ...
root@rabbitmq02:/# rabbitmqctl reset
Resetting node rabbit@rabbitmq02 ...
root@rabbitmq02:/# rabbitmqctl join_cluster --ram rabbit@rabbitmq01
Clustering node rabbit@rabbitmq02 with rabbit@rabbitmq01
root@rabbitmq02:/# rabbitmqctl start_app
Starting node rabbit@rabbitmq02 ...
root@rabbitmq02:/# exit
exit

第三节点

[root@node03 rabbitmq]# docker exec -it rabbitmq03 /bin/bash
root@rabbitmq03:/# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbitmq03 ...
^[[Aroot@rabbitmq03rabbitmqctl reset
Resetting node rabbit@rabbitmq03 ...
root@rabbitmq03:/# rabbitmqctl join_cluster --ram rabbit@rabbitmq01
Clustering node rabbit@rabbitmq03 with rabbit@rabbitmq01
root@rabbitmq03:/# rabbitmqctl start_app
Starting node rabbit@rabbitmq03 ...
root@rabbitmq03:/# exit
exit

实现镜像集群

随便进入一个节点

[root@node03 rabbitmq]# docker exec -it rabbitmq01 bash

ha策略

root@rabbitmq01:/# rabbitmqctl set_policy -p / ha  "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'
Setting policy "ha" for pattern "^" to "{"ha-mode":"all","ha-sync-mode":"automatic"}" with priority "0" for vhost "/" ...

/ 当前主机

查看策略

root@rabbitmq01:/# rabbitmqctl list_policies -p /
Listing policies for vhost "/" ...
vhost   name    pattern apply-to        definition      priority
/       ha      ^       all     {"ha-mode":"all","ha-sync-mode":"automatic"}    0

01中添加一个队列

 

 

 

发现03中也有该队列

 

 

 K8S部署MySQL集群

  • 有状态服务抽取配置为ConfigMap
  • 有状态服务必须使用pvc持久数据
  • 服务集群内访问使用DNS提供的稳定域名

登录project-regular

进入项目

配置,创建配置

 下一步,添加数据

 

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

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

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_admin

replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema

 

 创建

存储卷

创建

 

 

 

 

 

点 应用负载,点 服务,创建 有状态服务

 

 

 

 

 

 

 

 容器组分散部署,添加容器镜像

 

 

 

 

 使用默认端口

 

 

 点 高级设置

 

 

 环境变量,引用配置文件或密钥

 

 

 

挂载配置文件或密钥

 

 

 

 添加存储卷

 创建

 

 slaver

 

 

 

 

 

 

 

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

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

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_admin

replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema

 

 

进入master容器

 

 打开命令行

 

# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.30-log MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> GRANT REPLICATION SLAVE ON *.* TO 'backup'@'%' identified by '123456';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show master status;
+------------------+----------+---------------------------------------------------------------------------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB                                                                    | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+---------------------------------------------------------------------------------+------------------+-------------------+
| mysql-bin.000003 |      439 | gulimall_ums,gulimall_pms,gulimall_oms,gulimall_sms,gulimall_wms,gulimall_admin |         |                   |
+------------------+----------+---------------------------------------------------------------------------------+------------------+-------------------+
1 row in set (0.00 sec)

 

 

 

# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.30-log MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> change master to master_host='mysql-master.gulimall',master_user='backup',master_password='123456',master_log_file='mysql-bin.000003',master_log_pos=0,master_port=3306;
Query OK, 0 rows affected, 2 warnings (0.02 sec)

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

关键:

  • 有状态服务
  •  挂载配置文件和PVC
  • IP都用域名

 

Redis

创建配置

 

 创建pvc

 创建有状态服务

redis:5.0.7镜像

没有环境变量但是要修改启动命令

 

 

 

 

ElasticSearch

 

 

 

 elasticsearch-pvc

 

创建有状态服务

 

 

 创建kibana

 

 

 

 RabitMQ

存储卷

有状态服务

 

 部署nacos

创建pvc

 

zipkin

 

sentinel

 

 

K8S部署应用

  •  为每个项目准备一个Dockerfile,Docker按照这个Dockerfile将项目制作成镜像
  • 为每个项目生成k8s的描述文件
  • Jenkins编写好Jenkinsfile

 

 

posted on 2020-06-16 10:54  AI数据  阅读(1795)  评论(3编辑  收藏  举报

导航