使用Kubesphere离线部署Nacos

通过以下步骤可在kubesphere上完整部署一个三节点的nacos集群,并且应该适用于k8s原生集群。请大家放心食用。

版本要求:

  • Nacos 1.3.1
  • KubeSphere 3.1.1
  • kubernetes: v1.18.6
  • 操作系统:ubuntu 18.04

步骤概要:

  1. 搭建一个NFS存储服务器,并在k8s集群的每一台机器上安装NFS Common组件
  2. 向私有化docker仓库导入nacos相关镜像
  3. 使用Nacos官网步骤,部署K8s集群
  4. 部署服务导出服务,使Nacos web可在集群外部访问

一. 实现NFS相关内容

1.在线部署时使用以下命令

  • 首先在预计搭建NFS Server的服务器上执行命令,将部署成功nfs server以及common相关组件
sudo apt install nfs-kernel-server
  • 安装common组件,由于k8s的集群调度策略,所以需要在k8s集群的每一台机器上执行命令

    sudo apt install nfs-common
    
  1. 离线安装NFS Server和Common组件
    下载安装包:ubuntu18.04-NFS.zip,点击下载:ubuntu18.04 nfs离线安装包,并发送到NFS Server和k8s集群内每一台服务器
    解压缩后,NFS Server端按照以下顺序安装组件

    sudo dpkg -i libnfsidmap2_0.25-5.1_amd64.deb
    sudo dpkg -i libtirpc1_0.2.5-1.2ubuntu0.1_amd64.deb
    sudo dpkg -i rpcbind_0.2.3-0.6ubuntu0.18.04.1_amd64.deb
    sudo dpkg -i keyutils_1.5.9-9.2ubuntu2_amd64.deb
    sudo dpkg -i nfs-common_1%3a1.3.4-2.1ubuntu5.5_amd64.deb
    sudo dpkg -i nfs-kernel-server_1%3a1.3.4-2.1ubuntu5.5_amd64.deb
    

    在K8s集群中安装NFS Common组件时,请不要安装最后一个deb包,即:nfs-kernel-server_1%3a1.3.4-2.1ubuntu5.5_amd64.deb

  2. 配置NFS Server
    创建NFS文件夹:mkdir -p /data/k8s-nfs
    修改 /etc/exports,在最后一行添加:/data/k8s-nfs *(rw,sync,no_root_squash,no_subtree_check)
    执行命令:sudo exportfs
    重启NFS服务:sudo /etc/init.d/nfs-kernel-server restart 或者 sudo systemctl restart nfs-server.service 均可

    在NFS Server和K8s集群内的任意一台服务上,检查NFS共享是否已生效

    image.png
    可使用命令尝试挂载,如果出现挂载后权限不足的问题,请将nfs共享的目录权限调整至777

    sudo mount -t nfs <NFS Server IP>:/data/k8s-nfs <挂载点文件夹>
    

二. 向私有化仓库导入Nacos相关镜像

由于离线搭建kubesphere时,已顺带搭建了一个docker registry:2镜像仓库,过程就不多赘述了,大家只要将以下镜像推入私有镜像仓库即可使用,记得请一定要验证好https推送和获取镜像哦。

镜像列表:

  1. quay.io/external_storage/nfs-client-provisioner:latest
  2. nacos/nacos-mysql:5.7
  3. nacos/nacos-peer-finder-plugin:1.1
  4. nacos/nacos-server:1.3.1

三. 部署Nacos集群

Nacos官网k8s环境部署说明

按照Nacos官网的说明,我们即将部署的Nacos集群为3节点集群,使用Mysql作为数据库,使用NFS PV作为Nacos存储日志和运行时文件

  1. 下载nacos-k8s仓库至任意k8s master节点,地址:https://github.com/nacos-group/nacos-k8s.git

  2. 修改nfs配置文件,并部署
    主要修改deploy/nfs/deployment.yaml文件,修改images部分为私有化仓库地址,填写NFS_PATH和nfs-client-root相关内容为上一步搭建的NFS Server

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: nfs-client-provisioner
    ---
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: nfs-client-provisioner
    spec:
      replicas: 1
      strategy:
        type: Recreate
      selector:
        matchLabels:
          app: nfs-client-provisioner
      template:
        metadata:
          labels:
            app: nfs-client-provisioner
        spec:
          serviceAccount: nfs-client-provisioner
          containers:
            - name: nfs-client-provisioner
              image: 10.196.12.170/quay.io/external_storage/nfs-client-provisioner:latest
              volumeMounts:
                - name: nfs-client-root
                  mountPath: /persistentvolumes
              env:
                - name: PROVISIONER_NAME
                  value: fuseim.pri/ifs
                - name: NFS_SERVER
                  value: 10.196.12.169
                - name: NFS_PATH
                  value: /data/k8s-nfs
          volumes:
            - name: nfs-client-root
              nfs:
                server: 10.196.12.169
                path: /data/k8s-nfs
    
  3. 按照Nacos官网步骤部署nfs pv部分内容

    kubectl create -f deploy/nfs/rbac.yaml
    kubectl create -f deploy/nfs/deployment.yaml
    kubectl create -f deploy/nfs/class.yaml
    

执行完成后,可通过命令验证是否部署成功:

kubectl get pod -l app=nfs-client-provisioner
  1. 部署Mysql数据库
    官网的文档上对于这一部分的说法,与实际拿取到的yaml文件是有出入的,按照最新的nacos-k8s仓库的部署文件来看,是否采用Mysql主从架构已不是必要的条件了,使用单库也可。
    修改配置文件:deploy/mysql/mysql-nfs.yaml,主要修改image为私有库地址,以及nfs部分,这里nfs共享虽然只共享到/data/k8s-nfs,但是可以采用预先在NFS Server创建相关目录的方法,例如:mkdir -p /data/k8s-nfs/nacos/mysql,这一步在后续执行时就不会报错了,不预先创建共享目录的话,会导致mysql在实际部署时,挂载不到目标目录。

    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: mysql
      labels:
        name: mysql
    spec:
      replicas: 1
      selector:
        name: mysql
      template:
        metadata:
          labels:
            name: mysql
        spec:
          containers:
          - name: mysql
            image: 10.196.12.170/nacos/nacos-mysql:5.7
            ports:
            - containerPort: 3306
            volumeMounts:
            - name: mysql-data
              mountPath: /var/lib/mysql
            env:
            - name: MYSQL_ROOT_PASSWORD
              value: "root"
            - name: MYSQL_DATABASE
              value: "nacos_devtest"
            - name: MYSQL_USER
              value: "nacos"
            - name: MYSQL_PASSWORD
              value: "nacos"
          volumes:
          - name: mysql-data
            nfs:
              server: 10.196.12.169
              path: /data/k8s-nfs/nacos/mysql
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: mysql
      labels:
        name: mysql
    spec:
      ports:
      - port: 3306
        targetPort: 3306
      selector:
        name: mysql
    

部署mysql

kubectl create -f deploy/mysql/mysql-nfs.yaml
  1. 部署Nacos
    前几部分全部执行完毕后,可在Kubesphere查看一下相关pod运行情况,没有其他问题后即可部署Nacos集群。
    修改配置文件:deploy/nacos/nacos-pvc-nfs.yaml,如果以上步骤完全按照默认配置进行的话,这个配置文件只需要修正2处image为私有化地址即可,其他部分默认即可。
---
apiVersion: v1
kind: Service
metadata:
  name: nacos-headless
  labels:
    app: nacos
  annotations:
    service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
        #  type: NodePort
  ports:
    - port: 8848
      name: server
      targetPort: 8848
      #      nodePort: 31848
    - port: 9848
      name: client-rpc
      targetPort: 9848
      # nodePort: 31849
    - port: 9849
      name: raft-rpc
      targetPort: 9849
      # nodePort: 31850
    ## 兼容1.4.x版本的选举端口
    - port: 7848
      name: old-raft-rpc
      targetPort: 7848
      #  nodePort: 31851
  clusterIP: None
  selector:
    app: nacos
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nacos-cm
data:
  mysql.db.name: "nacos_devtest"
  mysql.port: "3306"
  mysql.user: "nacos"
  mysql.password: "nacos"
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nacos
spec:
  serviceName: nacos-headless
  replicas: 3
  template:
    metadata:
      labels:
        app: nacos
      annotations:
        pod.alpha.kubernetes.io/initialized: "true"
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                      - nacos
              topologyKey: "kubernetes.io/hostname"
      serviceAccountName: nfs-client-provisioner
      initContainers:
        - name: peer-finder-plugin-install
          image: 10.196.12.170/nacos/nacos-peer-finder-plugin:1.1
          imagePullPolicy: Always
          volumeMounts:
            - mountPath: /home/nacos/plugins/peer-finder
              name: data
              subPath: peer-finder
      containers:
        - name: nacos
          imagePullPolicy: Always
          image: 10.196.12.170/nacos/nacos-server:1.3.1
          resources:
            requests:
              memory: "2Gi"
              cpu: "500m"
          ports:
            - containerPort: 8848
              name: client-port
            - containerPort: 9848
              name: client-rpc
            - containerPort: 9849
              name: raft-rpc
            - containerPort: 7848
              name: old-raft-rpc
          env:
            - name: NACOS_REPLICAS
              value: "3"
            - name: SERVICE_NAME
              value: "nacos-headless"
            - name: DOMAIN_NAME
              value: "cluster.local"
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
            - name: MYSQL_SERVICE_DB_NAME
              valueFrom:
                configMapKeyRef:
                  name: nacos-cm
                  key: mysql.db.name
            - name: MYSQL_SERVICE_PORT
              valueFrom:
                configMapKeyRef:
                  name: nacos-cm
                  key: mysql.port
            - name: MYSQL_SERVICE_USER
              valueFrom:
                configMapKeyRef:
                  name: nacos-cm
                  key: mysql.user
            - name: MYSQL_SERVICE_PASSWORD
              valueFrom:
                configMapKeyRef:
                  name: nacos-cm
                  key: mysql.password
            - name: NACOS_SERVER_PORT
              value: "8848"
            - name: NACOS_APPLICATION_PORT
              value: "8848"
            - name: PREFER_HOST_MODE
              value: "hostname"
          volumeMounts:
            - name: data
              mountPath: /home/nacos/plugins/peer-finder
              subPath: peer-finder
            - name: data
              mountPath: /home/nacos/data
              subPath: data
            - name: data
              mountPath: /home/nacos/logs
              subPath: logs
  volumeClaimTemplates:
    - metadata:
        name: data
        annotations:
          volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
      spec:
        accessModes: [ "ReadWriteMany" ]
        resources:
          requests:
            storage: 20Gi
  selector:
    matchLabels:
      app: nacos

部署Nacos集群:

kubectl create -f deploy/nacos/nacos-pvc-nfs.yaml

检查部署情况,如果3个节点全为Ready 1/1,部署即为成功:

kubectl get pod -l app=nacos

四. 部署Nacos导出服务,使外部可访问Nacos集群

这个步骤既可以使用yaml文件通过kubectl部署,也可在KubeSphere界面操作,比较简单
nacos-outside.default.service.yaml

kind: Service
apiVersion: v1
metadata:
  name: nacos-outside
  namespace: default
  labels:
    app: nacos-outside
  annotations:
    kubesphere.io/creator: luming
spec:
  ports:
    - name: nacos-console
      protocol: TCP
      port: 8848
      targetPort: 8848
      nodePort: 31848
  selector:
    app: nacos
  type: NodePort
  sessionAffinity: None
  externalTrafficPolicy: Cluster

通过KubeSphere界面创建这个服务时,注意第一次创建时生成的对外nodePort是随机的,可通过在更改服务配置文件并更新或重新部署的方式,将nodePort固定在需要的地址。

以上步骤完成后,可通过K8s任意master节点IP+nodePort访问Nacos页面,例如:http://10.196.12.170:31848/nacos,用户名密码均为nacos

五. 在微服务中使用k8s nacos

k8s集群内的所有service,均可通过名称进行访问,它们在容器内部时可自动根据k8s dns规则获取nacos master节点,并实现负载均衡。
在bootstrap.yml内只需写明:

  cloud:
    nacos:
      discovery:
        server-addr: nacos-headless.default:8848

其中nacos-headless为nacos集群的对内Service总入口,可在KubeSphere的集群管理中找到,default是nacos部署的namespace,如果在部署集群时将nacos部署到了其他namespace,这个参数需要对应进行修改。

在实践中发现,有时会有容器无法注册到nacos的情形,可通过以下方法排查和解决

  • 首先通过其他namespace的任意容器,使用ping命令确认nacos集群真实访问地址,在ping nacos-headless.default时,如果地址正确,则会返回nacos master地址,或slave地址。实际上,只要有虚拟ip返回,那么则证明地址是正确的,如果没有解析到任何地址,则证明名称或namespace是错误的。

  • 如果地址是通的情形下,依旧连接不到Nacos,那么一般认为是DNS解析有问题,这个问题一般发生在使用apline系列的base image时出现,由于apline镜像精简的关系,DNS相关组件可能也被删去了,但是在k8s中DNS组件是必须的,这里推荐使用KubeSphere官方的kubesphere/java-8-runtime:v2.1.0作为基础镜像构建。以下是Dockerfile:

FROM kubesphere/java-8-runtime:v2.1.0
ARG JAR_FILE
ADD target/${JAR_FILE} /opt/run-java/deployments/app.jar
ARG MAIN_CLASS
CMD JAVA_MAIN_CLASS=${MAIN_CLASS} sh /opt/run-java/run-java.sh

需要在POM文件或Gradle文件中,指定两个变量:
JAR_FILE指向编译结果,例如:xxx-xxx-xx-1.6.jar
MAIN_CLASS指向Spring Cloud或Boot的入口函数,例如:com.example.cloud.UserApplication


版权声明:本文为weixin_43944128原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>