所有分类
  • 所有分类
  • 未分类

Docker、Docker Compose、Docker Swarm、K8S的区别

简介

说明

本文介绍Docker、Docker Compose、Docker Swarm、K8S的区别。

官网

官网:http://kubernetes.io

Github:https://github.com/kubernetes/kubernetes

简要对比

应用有如下几种部署方式:

  1. 传统方式
    1. 手动安装MySQL、Nginx,运行应用等
    2. 缺点:麻烦
  2. docker
    1. 优点:
      • 安装过程只需要拉取镜像,启动即可,而不用关心软件的配置,版本等信息。
    2. 缺点:
      1. 通过命令方式启动,不方便修改配置。
      2. 容器应用之间的依赖关系、网络通信、数据持久化、状态等很难处理。
  3. docker-compose
    1. 优点:
      • 更方便地使用docker:用配置文件方式启动,方便修改配置。
      • 解决了容器应用间的依赖关系、网络通信、数据持久化、状态等问题。
    2. 缺点:
      • 只能单机编排容器,不能实现多机编排。可以认为是一个单机版“操作系统”。
  4. Docker swarm
    1. 支持分布式下环境下的容器编排
    2. 缺点:
      1. 只有分布式编排这一个功能,没有动态伸缩、可视化等功能
  5. K8S
    1. 支持分布式下环境下的容器编排。
    2. 优点:
      1. 功能很多。

对比实例

我们看一个简单的场景,来理解为什么编排能力才是我们更看重的东西。

我们以部署一个wordpress博客网站进行示例。

方式1:最传统的方式

你需要用二进制等方式安装配置mysql, 安装nginx服务器,以及wordpress程序等等…

仅仅部署几个应用,你就能觉得它的复杂,配置的繁琐。可以想象,如果是几十上百个应用,自动化的过程不可避免。

方式2:独立的Docker容器

#1.拉取镜像
docker pull mysql
docker pull wordpress
#2.启动mysql
docker run --name w-mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql
#3.启动wordpress,并连接mysql
docker run --name w-wordpress --link w-mysql:db -p 80:80 -d wordpress:latest

可以看到,安装过程只需要拉取镜像,启动即可,而不用关心软件的配置,版本等信息。

简化了不少,但是还是手动去启动,拉取镜像等。

真实的业务场景下,容器应用间的依赖关系,网络通信,数据持久化,状态等非常复杂,用这种方式处理起来非常棘手。

方式3:docker-compose 轻量编排

示例

定义一个docker-compose-wordpress.yml

version: '3.3'
services:
  db:
    image: mysql:5.7
    container_name: mysql
    security_opt:
      - seccomp:unconfined
    ports:
     - 3306:3306
    volumes:
      - /opt/module/mysql/conf:/etc/mysql/conf.d
      - /opt/module/mysql/data:/var/lib/mysql
      - /opt/module/mysql/logs:/var/log/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: wordpress
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    ports:
      - "80:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: root
      WORDPRESS_DB_PASSWORD: 123456
      WORDPRESS_DB_NAME: wordpress

这里的配置文件虽然看着很多,其实它的层次很清楚。services我们可以认为是一组应用,是一种抽象,具体到这里可以认为是博客服务。

博客服务需要mysql和wordpress两个容器配合,所以紧接着db(名称可以自定义)指的就是mysql,在后边则描述了对应的镜像,端口等信息。

而wordpress,有一个关键字depends_on,则描述了它和db的依赖关系。

这样一个文件,用的是yaml文件的语法,相信开发过java微服务的肯定很熟悉,我们的配置文件大多都是用这种方式配置。

然后我们只需要执行如下命令,即可启动对应的容器,并且相互关联:

#docker-compose指令 
docker-compose -f docker-compose-wordpress.yml up -d

此时查看容器运行情况:

[root@VM_0_13_centos module]# docker-compose ps
Name                     Command               State                 Ports
-----------------------------------------------------------------------------------------------
module_wordpress_1   docker-entrypoint.sh apach ...   Up      0.0.0.0:80->80/tcp
mysql                docker-entrypoint.sh mysqld      Up      0.0.0.0:3306->3306/tcp, 33060/tcp

或者直接用docker命令查看:

[root@VM_0_13_centos module]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
64153ac017a3        wordpress:latest    "docker-entrypoint..."   3 weeks ago         Up 3 weeks          0.0.0.0:80->80/tcp                  module_wordpress_1
fde105317ddd        mysql:5.7           "docker-entrypoint..."   3 weeks ago         Up 7 days           0.0.0.0:3306->3306/tcp, 33060/tcp   mysql

可以看到docker-compose其实为我们做了三件事

  1. 根据yaml定义去拉取相关镜像文件(如果本地没有)
  2. 启动相关容器
  3. 建立容器关联关系:这里就是连接mysql

从上边这个例子,我们可以看到,面对复杂的容器运维工作,你只需要告诉编排工具你需要什么(定义yaml)其他的工作就交给等编排工具去做就行。当然部署一个wordpress这样一个轻量级的应用,用docker或者docker-compose就完全够用,如果用k8s去做,又是怎样一番场景,我们继续往下看。

方式4:K8S

从前面可以发现docker-compose其实就是在以容器为基本单位,帮我们部署应用。但在K8S里,编排调度的最小单位并不是容器,而是Pod。有了Docker容器,为什么还需要一个Pod? Docker容器相当于操作系统中的应用,K8S相当于操作系统,Pod相当于进程组:即Pod是对一组容器(一个或多个)的抽象。之所以做这样一层抽象,是因为在 Borg 项目的开发和实践过程中,Google 公司的工程师们发现,他们部署的应用,往往都存在着类似于“进程和进程组”的关系。在同一个Pod中,可以直接通过localhost通信,并且可以共享网络栈和Volume

如果用Pod描述上面的博客应用,yaml如下:

apiVersion: v1
kind: Pod
metadata:
  name: wordpress
  namespace: blog
spec:
  containers:
    - name: wordpress
      image: wordpress
      ports:
        - containerPort: 80
          name: wdport
        env:
        - name: WORDPRESS_DB_HOST
          value: localhost:3306
        - name: WORDPRESS_DB_USER
          value: root
        - name: WORDPRESS_DB_PASSWORD
          value: root@123
    - name: mysql
      image: mysql:5.7
      imagePullPolicy: IfNotPresent
      args:  # 新版本镜像有更新,需要使用下面的认证插件环境变量配置才会生效
        - --default_authentication_plugin=mysql_native_password
        - --character-set-server=utf8mb4
        - --collation-server=utf8mb4_unicode_ci
      ports:
        - containerPort: 3306
          name: dbport
      env:
        - name: MYSQL_ROOT_PASSWORD
          value: root@123
        - name: MYSQL_DATABASE
          value: wordpress
        - name: MYSQL_USER
          value: wordpress
        - name: MYSQL_PASSWORD
          value: wordpress
      volumeMounts:
        - name: db
          mountPath: /var/lib/mysql
    volumes:
      - name: db
        hostPath:
          path: /var/lib/mysql

像这样的一个 YAML 文件,对应到 K8S 中,就是一个 API Object(API 对象),Pod是最基本的一个API对象。Pod是 K8S 项目中的最小编排单位。容器(Container)是 Pod 属性里的一个普通的字段。

这个Pod里 containers字段就是来定义容器的。volumes:定义了一个数据卷,指向了宿主机的/var/lib/mysql,而容器里则用volumeMounts字段来做关联挂载。

Deployment是更高层次的一种API对象,它可以直接控制Pod。比如:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

这里我们定义了一个Deployment对象,它控制的Pod数量是两个,而Pod的具体属性,又通过template这个模板去生成。即描述的是一个Nginx。这样K8S通过控制循环,始终保证有两个nginx Pod实例运行。

Deployment是一个定义多副本应用(即多个副本 Pod)的对象。Deployment 扮演的是 Pod 的控制器的角色。这样的每一个 API 对象都有一个叫作 Metadata 的字段,这个字段就是 API 对象的“标识”,即元数据,它也是我们从 Kubernetes 里找到这个对象的主要依据。这其中最主要使用到的字段是 Labels。

像 Deployment 这样的控制器对象,就可以通过这个 Labels 字段从 Kubernetes 中过滤出它所关心的被控制对象。比如,在上面这个 YAML 文件中,Deployment 会把所有正在运行的、携带“app: nginx”标签的 Pod 识别为被管理的对象,并确保这些 Pod 的总数严格等于两个。

这个过滤规则的定义,是在 Deployment 的“spec.selector.matchLabels”字段。我们一般称之为:Label Selector。

一个 K8S 的 API 对象的定义,大多可以分为 Metadata 和 Spec 两个部分。前者存放的是这个对象的元数据,对所有 API 对象来说,这一部分的字段和格式基本上是一样的;后者存放的是属于这个对象独有的定义,用来描述它所要表达的功能。 ​

6

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录