使用Kubesphere离线部署Nacos
通过以下步骤可在kubesphere上完整部署一个三节点的nacos集群,并且应该适用于k8s原生集群。请大家放心食用。
版本要求:
- Nacos 1.3.1
- KubeSphere 3.1.1
- kubernetes: v1.18.6
- 操作系统:ubuntu 18.04
步骤概要:
- 搭建一个NFS存储服务器,并在k8s集群的每一台机器上安装NFS Common组件
- 向私有化docker仓库导入nacos相关镜像
- 使用Nacos官网步骤,部署K8s集群
- 部署服务导出服务,使Nacos web可在集群外部访问
一. 实现NFS相关内容
1.在线部署时使用以下命令
- 首先在预计搭建NFS Server的服务器上执行命令,将部署成功nfs server以及common相关组件
sudo apt install nfs-kernel-server
-
安装common组件,由于k8s的集群调度策略,所以需要在k8s集群的每一台机器上执行命令
sudo apt install nfs-common
-
离线安装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
-
配置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共享是否已生效
可使用命令尝试挂载,如果出现挂载后权限不足的问题,请将nfs共享的目录权限调整至777sudo mount -t nfs <NFS Server IP>:/data/k8s-nfs <挂载点文件夹>
二. 向私有化仓库导入Nacos相关镜像
由于离线搭建kubesphere时,已顺带搭建了一个docker registry:2镜像仓库,过程就不多赘述了,大家只要将以下镜像推入私有镜像仓库即可使用,记得请一定要验证好https推送和获取镜像哦。
镜像列表:
- quay.io/external_storage/nfs-client-provisioner:latest
- nacos/nacos-mysql:5.7
- nacos/nacos-peer-finder-plugin:1.1
- nacos/nacos-server:1.3.1
三. 部署Nacos集群
按照Nacos官网的说明,我们即将部署的Nacos集群为3节点集群,使用Mysql作为数据库,使用NFS PV作为Nacos存储日志和运行时文件
-
下载nacos-k8s仓库至任意k8s master节点,地址:https://github.com/nacos-group/nacos-k8s.git
-
修改nfs配置文件,并部署
主要修改deploy/nfs/deployment.yaml文件,修改images部分为私有化仓库地址,填写NFS_PATH和nfs-client-root相关内容为上一步搭建的NFS ServerapiVersion: 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
-
按照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
-
部署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
- 部署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