上一节学习了Nacos的基本概念,Nacos是一个用于构建云原生应用的动态服务发现、配置管理和服务管理平台。

在学习如何使用Nacos之前,需要先完成Nacos的部署,Nacos支持多种不同的部署模式,虽然我们这里是以学习为目的的。 但既然Nacos是用于帮助我们构建云原生应用的,那么我们今天就一步到位,在K8S集群上部署一套生产可用的Nacos集群。

Nacos的部署模式

Nacos支持三种部署模式:

  • 单机模式: 用于测试和单机使用
  • 集群模式: 用于生产环境,确保高可用
  • 多集群模式: 用于多数据中心场景

我们本节的目标是在K8S集群上部署一套生产可用的Nacos集群,属于第二种集群部署模式。

nacos-k8s项目

https://github.com/nacos-group/nacos-k8s项目是Nacos官方项目。 该项目包含了一个可构建的Nacos Docker Image,提供并支持以k8s manifest yaml file, Helm Chart, Operator三种方式在K8S上部署Nacos。 部署的Nacos集群在K8S中以StatefulSet存在。

nacos-k8s当前对于以k8s manifest yaml file方式部署提供了以下4个yaml文件(https://github.com/nacos-group/nacos-k8s/tree/master/deploy/nacos):

  • nacos-no-pvc-ingress.yaml
  • nacos-pvc-ceph.yaml
  • nacos-pvc-nfs.yaml
  • nacos-quick-start.yaml

这里选择MySQL作为Nacos的数据库,上面4个yaml文件选择使用的是nacos-no-pvc-ingress.yaml

在k8s集群中部署Nacos

首先进行准备工作,在MySQL数据库提前创建好nacos的数据库和用户,使用https://github.com/alibaba/nacos/blob/develop/distribution/conf/nacos-mysql.sql这个SQL文件创建好nacos数据库的表结构和初始化数据。

接下来编辑nacos-no-pvc-ingress.yaml,针对我们的部署环境做定制化配置,主要有以下几个方面:

  • 定制各个k8s资源部署的k8s namespace (nacos-no-pvc-ingress.yaml中默认的是default namespace)
  • 修改nacos-cm这个ConfigMap中关于MySQL的地址、端口、数据库名、用户名、密码等信息
  • 修改nacos这个StatefulSet中的Nacos镜像的版本,例如部署最新的2.0.4版本。建议将nacos/nacos-server:v2.0.4镜像缓存到本地的私有镜像库例如harbor.youcomany.com/library/nacos/nacos-server:v2.0.4
  • 以StatefulSet部署的nacos集群的各个节点之间是使用headless service进行通信的,如果前面定制了个k8s namespace,注意调整SatefulSet Pod模板中的NACOS_SERVERS环境变量的值。
  • nacos-no-pvc-ingress.yaml中使用了Ingress将nacos的Web控制后台暴露到K8S集群外部,但当前它的Ingress使用的apiVersion: extensions/v1beta1,如果你的K8S版本比较新的话,需要修改Ingress的配置,使其满足apiVersion: networking.k8s.io/v1

以下是本文对nacos-no-pvc-ingress.yaml定制配置的例子,这个例子将nacos集群部署到了k8s的nacos namespace中:

  1###使用自建数据库;使用Ingress发布配置后台###
  2---
  3apiVersion: v1
  4kind: Service
  5metadata:
  6  name: nacos-headless
  7  namespace: nacos
  8  labels:
  9    app: nacos-headless
 10spec:
 11  type: ClusterIP
 12  clusterIP: None
 13  ports:
 14    - port: 8848
 15      name: server
 16      targetPort: 8848
 17    - port: 9848
 18      name: client-rpc
 19      targetPort: 9848
 20    - port: 9849
 21      name: raft-rpc
 22      targetPort: 9849
 23      ## 兼容1.4.x版本的选举端口
 24    - port: 7848
 25      name: old-raft-rpc
 26      targetPort: 7848
 27  selector:
 28    app: nacos
 29---
 30apiVersion: v1
 31kind: ConfigMap
 32metadata:
 33  name: nacos-cm
 34  namespace: nacos
 35data:
 36  mysql.host: "192.168.100.21"
 37  mysql.db.name: "nacos"
 38  mysql.port: "3306"
 39  mysql.user: "nacos"
 40  mysql.password: "nacospass"
 41---
 42apiVersion: apps/v1
 43kind: StatefulSet
 44metadata:
 45  name: nacos
 46  namespace: nacos
 47spec:
 48  serviceName: nacos-headless
 49  replicas: 3
 50  template:
 51    metadata:
 52      labels:
 53        app: nacos
 54      annotations:
 55        pod.alpha.kubernetes.io/initialized: "true"
 56    spec:
 57      affinity:
 58        podAntiAffinity:
 59          requiredDuringSchedulingIgnoredDuringExecution:
 60            - labelSelector:
 61                matchExpressions:
 62                  - key: "app"
 63                    operator: In
 64                    values:
 65                      - nacos
 66              topologyKey: "kubernetes.io/hostname"
 67      imagePullSecrets: 
 68        - name: regsecret
 69      containers:
 70        - name: k8snacos
 71          imagePullPolicy: IfNotPresent
 72          image: harbor.youcomany.com/library/nacos/nacos-server:v2.0.4
 73          resources:
 74            requests:
 75              memory: "2Gi"
 76              cpu: "500m"
 77          ports:
 78            - containerPort: 8848
 79              name: client
 80            - containerPort: 9848
 81              name: client-rpc
 82            - containerPort: 9849
 83              name: raft-rpc
 84            - containerPort: 7848
 85              name: old-raft-rpc
 86          env:
 87            - name: NACOS_REPLICAS
 88              value: "3"
 89            - name: MYSQL_SERVICE_HOST
 90              valueFrom:
 91                configMapKeyRef:
 92                  name: nacos-cm
 93                  key: mysql.host
 94            - name: MYSQL_SERVICE_DB_NAME
 95              valueFrom:
 96                configMapKeyRef:
 97                  name: nacos-cm
 98                  key: mysql.db.name
 99            - name: MYSQL_SERVICE_PORT
100              valueFrom:
101                configMapKeyRef:
102                  name: nacos-cm
103                  key: mysql.port
104            - name: MYSQL_SERVICE_USER
105              valueFrom:
106                configMapKeyRef:
107                  name: nacos-cm
108                  key: mysql.user
109            - name: MYSQL_SERVICE_PASSWORD
110              valueFrom:
111                configMapKeyRef:
112                  name: nacos-cm
113                  key: mysql.password
114            - name: MODE
115              value: "cluster"
116            - name: NACOS_SERVER_PORT
117              value: "8848"
118            - name: PREFER_HOST_MODE
119              value: "hostname"
120            - name: NACOS_SERVERS
121              value: "nacos-0.nacos-headless.nacos.svc.cluster.local:8848 nacos-1.nacos-headless.nacos.svc.cluster.local:8848 nacos-2.nacos-headless.nacos.svc.cluster.local:8848"
122  selector:
123    matchLabels:
124      app: nacos
125
126
127
128
129---
130# ------------------- App Ingress ------------------- #
131apiVersion: networking.k8s.io/v1
132kind: Ingress
133metadata:
134  name: nacos-headless
135  namespace: nacos
136spec:
137  rules:
138  - host: nacos.youcomany.com
139    http:
140      paths:
141      - path: /
142        pathType: ImplementationSpecific
143        backend:
144          service:
145            name: nacos-headless
146            port:
147              number: 8848

部署成功后,查看nacos在k8s中各个资源的状态:

1kubectl get service,configmap,ingress,statefulset,pod -n nacos | grep nacos
2service/nacos-headless             ClusterIP      None             <none>        8848/TCP,9848/TCP,9849/TCP,7848/TCP   2h
3configmap/nacos-cm                              5      2h
4ingress.networking.k8s.io/nacos-headless          nginx   nacos.youcomany.com                    80, 443      2h
5statefulset.apps/nacos                 3/3     2h
6pod/nacos-0                                  1/1     Running   0              2h
7pod/nacos-1                                  1/1     Running   0              2h
8pod/nacos-2                                  1/1     Running   0              2h

部署成功后,使用https://nacos.youcomany.com/nacos打开nacos的Web控制台,并以默认的用户名密码(nacos/nacos)登录,

nacos-console.png

到这里,我们完成了在K8S集群中部署Nacos集群。

最后,需要注意Nacos被设计为一个在IDC内部使用的应用组件,而非面向公网环境的产品,因此需要在内部隔离网络中使用。 本文的示例中将Nacos的Web控制台和API以Ingress (nacos.youcomany.com)的形式暴露到了k8s集群外部,便于从外部测试和访问,实际部署时一定要针对这点做好网络策略控制。

参考