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




---
# ------------------- App Ingress ------------------- #
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nacos-headless
  namespace: nacos
spec:
  rules:
  - host: nacos.youcomany.com
    http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: nacos-headless
            port:
              number: 8848

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

1
2
3
4
5
6
7
8
kubectl get service,configmap,ingress,statefulset,pod -n nacos | grep nacos
service/nacos-headless             ClusterIP      None             <none>        8848/TCP,9848/TCP,9849/TCP,7848/TCP   2h
configmap/nacos-cm                              5      2h
ingress.networking.k8s.io/nacos-headless          nginx   nacos.youcomany.com                    80, 443      2h
statefulset.apps/nacos                 3/3     2h
pod/nacos-0                                  1/1     Running   0              2h
pod/nacos-1                                  1/1     Running   0              2h
pod/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集群外部,便于从外部测试和访问,实际部署时一定要针对这点做好网络策略控制。

参考