Docker

kubernetes部署mysql8

月盾

虽然很多文章说不建议将数据库部署在容器中,因为有性能问题。但我觉得这事还是要看具体使用场景来决定,而不是全盘否定。开发的过程中并不只有性能是最重要的,还有效率,易用性等也很重要。

对于测试环境来说,数据库部署在容器中肯定是可以的。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: mysql
  name: mysql
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: mysql
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
      labels:
        app: mysql
    spec:
      containers:
      - env:
        - name: MYSQL_ROOT_PASSWORD
          value: xxx
        image: mysql:8.0.33
        imagePullPolicy: IfNotPresent
        name: mysql
        ports:
        - containerPort: 3306
          name: mysql
          protocol: TCP
        resources:
          limits:
            cpu: "4"
            memory: 8Gi
        volumeMounts:
        - mountPath: /var/lib/mysql
          name: data
        - mountPath: /etc/mysql/conf.d/
          name: mysql-config
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: mysql
      - configMap:
          defaultMode: 420
          name: mysql-config
        name: mysql-config

---

apiVersion: v1
kind: ConfigMap
data:
  my.cnf: |-
    [client]
    default-character-set = utf8mb4
    [mysql]
    default-character-set=utf8mb4
    [mysqld]
    character-set-server=utf8mb4
    collation_server=utf8mb4_unicode_ci
    gtid_mode=ON
    enforce_gtid_consistency=ON
    lower_case_table_names=1
    open_files_limit=65535
    slow_query_log = ON
    long_query_time = 2
    max_heap_table_size = 32M
    tmp_table_size = 2M
    log-bin = mysql-bin
    binlog_cache_size = 32K
    max_binlog_cache_size = 1G
    max_binlog_size = 1G
    binlog-format = ROW
    sync_binlog = 1
    log-slave-updates = 1
    expire_logs_days = 7
    default-time_zone = +8:00
    max_connect_errors = 65535
    max_allowed_packet = 536870912
    max_connections = 5120
    innodb_buffer_pool_instances = 1
    innodb_buffer_pool_size = 6442450944
    innodb_temp_data_file_path = ibtmp1:12M:autoextend:max:15G
    server_id = 100
metadata:
  name: mysql-config

再聊docker和nodejs

月盾

上一篇写到了如何在docker中运行nodejs,运行方式是在docker中安装了pm2来保证node服务宕机重启,这种方式更像是把docker当做虚拟机来使用。其实,既然使用了docker的话就可以不使用pm2来管理进程,因为docker自身可以充当守护进程,在node进程退出时进行重启。只要在启动docker容器时加上–restart=always参数即可。例如:docker run -d --restart=always -p 3000:3000 mynode:1

没有pm2如何开启多进程

使用pm2可以开启多node进程,并且自带负载均衡,但是有个限制,pm2可以开启的进程数是CPU最大核心数。而使用docker的话就不会受限于此了,开启几十个上百个node服务都可以,然后通过nginx实现负载均衡。不过要手动开启几十上百个docker容器那怎么行?让我手动开启3个都很烦了,这时候就需要用到docker编排工具了,比如:Docker Swarm、Kubernetes、docker compose等,可以一键开启多个容器。但是使用编排工具启动docker端口就不确定了,是由编排工具随机开启服务端口的,这又要做到服务注册发现,所以这些工具结合起来使用。

哪一种部署方式支持并发高?

使用jmeter在本机上进行了简单的并发测试,服务端进行简单的10万次hash计算,使用pm2开启4个实例,docker开启5个实例。docker使用Nginx做负载均衡,单次访问响应时间在1.2s~1.4s之间不等,在200个并发的情况下,两种模式响应时间相差不大,docker模式响应时间略占优势,大概快了0.1s。当并发数在300以上时两者的响应时间都有增加,此时docker部署方式出现了响应失败的情况,pm2就比较稳定了,虽然响应时间增加,但是并未出现过响应失败。 所以在单机上低并发docker还是有点优势,如果在高并发情况下还是pm2更稳定一些。(以上测试是单机上进行,准确性并不高)

在docker中运行nodejs

月盾

首先看项目目录:

项目目录

再看Dockerfile文件内容:

# 以最新的node为基础镜像
FROM hub.c.163.com/library/node:latest
# 工作目录为app
WORKDIR /app
# 拷贝当前所在项目根目录到app目录
COPY . /app
# 全局安装pm2
RUN npm install pm2 -g

EXPOSE 8081
#使用pm2启动nodejs,如果没有--no-daemon参数docker启动后就退出
CMD ["pm2-runtime", "dest/server.js", "--no-daemon"]
# ENTRYPOINT ["node", "server.js"]

或者在Dockerfile中不添加CMD命令,可以在启动docker时执行命令:

docker run --name ks -ti -p 8081:8081 kser:pm2 pm2-runtime dest/server.js

如果是后台运行的docker:

docker run --name ks -d -p 8081:8081 kser:pm2 pm2-runtime dest/server.js

-d选项是后台运行

需要进入到docker查看pm2运行情况 ,可以通过docker exec -ti ks /bin/sh查看运行的容器内部情况 pm2运行情况

要不要在docker中使用pm2运行nodejs

  • pm2可以监控nodejs进程,如果进程挂了,可以自动重启
  • pm2可以设置启动的nodejs进程个数,提高服务性能
  • pm2可以设置日志记录
  • pm2可以设置端口,避免端口冲突

docker已经提供了自动重启的功能,可以这样启动nodejs服务:

docker run --name ks -d --restart=always -p 8081:8081 kser:pm2 pm2-runtime dest/server.js

Dockerfile CMD命令没有执行npm start

月盾

Dockerfile

FROM hub.c.163.com/public/nodejs:6.11.0

WORKDIR /app

COPY . /app

RUN npm install

EXPOSE 3000

# CMD ["npm", "start"]
ENTRYPOINT ["npm", "start"]

docker ps:

CONTAINER ID    IMAGE  COMMAND                  
59988bd90894    myfd   "/bin/sh -c '/usr/..."   

在Dockerfile中配置了CMD ["npm", "start"],docker ps后显示COMMAND为"/bin/sh -c '/usr/..." 改为ENTRYPOINT ["npm", "start"]就可以了