Kubernetes VS Docker:有什么区别?用例子解释

2020年12月30日10:50:35 发表评论 38 次浏览

本文概述

如今, 开发人员工具箱中的两个基本工具是Docker和Kubernetes。两者都允许开发人员将应用程序打包到容器中以在不同的环境中运行它们。

尽管使用这两种方法都可以实现相似的目的, 但实际上它们的用法不同。

在本文中, 你将对Docker和Kubernetes进行解释, 并构建示例NodeJS Web应用程序并使用这两种技术进行部署。

什么是Docker?

人们在Wikipedia上定义Docker的方法如下:

" Docker可以将应用程序及其依赖项打包在任何Linux服务器上运行的虚拟容器中。这使应用程序可以在各种位置(例如本地, 公共云和/或私有云)中运行。 Docker使用Linux内核的资源隔离功能(例如cgroups和内核名称空间)和具有联合能力的文件系统(例如OverlayFS)来允许容器在单个Linux实例中运行, 从而避免了启动和维护虚拟机的开销。" —维基百科

简而言之, Docker是一个平台, 可以在所需的机器上运行以接近本机性能封装的不可变容器。

Docker的替代品具有类似的属性, 例如LC, rkt或容器式。 Docker只是最受欢迎的一种。

什么是Kubernetes?

人们在Wikipedia上定义Kubernetes的方法如下:

Kubernetes定义了一组构建块("原语"), 它们共同提供了基于CPU, 内存或自定义指标来部署, 维护和扩展应用程序的机制。 Kubernetes是松散耦合的, 并且可以扩展以满足不同的工作负载。 Kubernetes API在很大程度上提供了这种可扩展性, 它由内部组件以及在Kubernetes上运行的扩展和容器使用。该平台通过将资源定义为对象来施加对计算和存储资源的控制权, 然后可以对其进行管理。 —维基百科

简而言之, Kubernetes管理多个主机并将容器部署到它们。在这些主机上运行容器的最常用的容器技术是Docker。

够了, 让我们动手实践, 亲身体验不同之处。

如何使用Docker和Kubernetes构建和部署NodeJS Web应用程序。

如果尚未安装Docker, 则应这样做。从以下位置签出并安装Dockerhttps://docs.docker.com/get-docker/.

$ docker --version

Docker version 19.03.13, build 4484c46d9d

让我们创建一个NodeJS包文件, 并添加一个名为表现.

// file: package.json

{
  "name": "docker-vs-k8s", "version": "1.0.0", "description": "", "main": "server.js", "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1", "start": "node server.js"
  }, "author": "", "license": "ISC", "dependencies": {
    "express": "^4.17.1"
  }
}

此外, 我们需要启动Web服务器并定义一个端点。

// file: server.js

const express = require('express');

// Constants
const PORT = 8080;
const HOST = '0.0.0.0';

// App
const app = express();
app.get('/', (req, res) => {
  res.send('Hello World');
});

app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);

仅供参考:如果你未安装NodeJS, 则可以跳过下一步。下一步骤将使用随需使用的Node环境随附的Docker映像。

如果本地PC上安装了NodeJS, 则可以尝试使用纯NodeJS运行该应用程序。

$ npm install
$ node server.js 

Running on http://0.0.0.0:8080

打开http://本地主机:8080, 你会看到自己的世界问候。

让我们找到一个基本的Docker镜像来运行我们的应用程序

公众Docker中心是一个很好的来源。如果你搜索"节点", 你将很快找到一个法师已被使用超过十亿次.

容器需要从其基础组装。我们从一个包含可立即使用的NodeJS环境的基础映像开始。它通常基于简单的Linux映像。我们将所有必需的文件复制到容器中。

之后, 我们执行命令, 例如, 获取所有必需的依赖项。最后一步是告诉容器启动容器时要运行什么命令。

# file: 'Dockerfile'

# lts-alpine means long term support and alpine is a very small Linux 
# distribution that is a lot smaller than the default one (node:lts).
# smaller images mean faster builds and startup time that is very handy 
# when it comes to scaling containers for production up and down
FROM node:lts-alpine

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
COPY package*.json ./

# Install all dependencies
RUN npm install

# Copy sources
COPY server.js server.js

CMD [ "node", "server.js" ]

现在, 让我们构建图像:

docker build -t node-web-app .

我们可以通过以下方式运行Docker容器:

$ docker run --name my_container -p 8080:8080 node-web-app

Running on http://0.0.0.0:8080

打开http://本地主机:8080在浏览器中, 你将看到hello world页面。这次, 它在容器中隔离运行。

你甚至不需要NodeJS或其他任何东西来构建和运行此容器。一切都被封装, 并且由于Docker的特性, 它以本机性能运行。

让我们停止可能仍在后台运行的容器:

$ docker rm -f my_container

仅供参考:只有Linux主机才有接近100%的本机性能。对于Mac OS和Windows, 需要进行一些转换和虚拟化, 但会导致性能下降。对于开发, 应该没问题。最重要的是, 生产服务器通常运行可与Docker完美配合的本机Linux。

接下来, 让我们在Kubernetes集群中使用我们先前构建的容器。在本教程中, 我们将专注于本地集群。如果你偏远, 则非常相似。

在远程设置中, 还需要将映像推送到公共可用的注册表, 该注册表使远程群集可以访问该映像。

如果人们要求的话, 我将来可能会写另一篇关于它的博客文章。

在Kubernetes中运行你的Web应用

你的Docker已经带有Kubernetes集成。打开Docker应用程序, 转到设置-> Kubernetes并启用Kubernetes。

应用更改可能需要一段时间。 Docker应用程序底部栏中的Kubernetes状态为绿色后, 你就可以准备就绪。

如果有任何问题, 请转到故障排除(右上角的小错误图标), 然后按重置为出厂默认值。之后, Docker应该重新启动, 你需要再次激活Kubernetes。

让我们安装kubectl, 这是与Kubernetes集群进行交互的最重要工具之一。请按照以下指南进行安装:https://kubernetes.io/docs/tasks/tools/install-kubectl/.

现在, 我们可以检查所有设置是否正确:

$ kubectl get services

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3m14s

让我们在集群中部署Docker容器:

# file 'application/deployment.yaml'

apiVersion: apps/v1
kind: Deployment
metadata:
  name: node-web-app
spec:
  selector:
    matchLabels:
      app: node-web-app
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: node-web-app
    spec:
      containers:
        - name: node-web-app
          image: node-web-app
          
          # only use this to for local development
          # we never pushed our image to a remote registry
          # and by default Kubernetes pulls images
          # this property forces kubernetes to always use 
          # the local image that is not a good practice in production
          imagePullPolicy: Never
          ports:
            - containerPort: 8080

deployment.yaml是一个文件, 描述了要执行的部署。我们可以通过以下方式执行它:

$ kubectl apply -f application/deployment.yaml

deployment.apps/node-web-app created

并检查容器是否正在运行:

$ kubectl get pods

NAME READY STATUS RESTARTS AGE
node-web-app-6788cfd6cc-bcbb2 1/1 Running 0 3s
node-web-app-6788cfd6cc-t5t6w 1/1 Running 0 3s

我们的Kubernetes管理一个包含单个主机的群集, 该主机是我们的本地计算机。在远程群集上, 可能有数百个节点承载不同的部署。

它在我们的环境中部署了两个容器。这些容器在隔离的网络中运行。否则, 将不可能两次公开相同的端口。

那么我们如何访问实际的容器?你可以通过定义所谓的服务来访问已部署的容器。每个公共应用程序都需要在前面定义公开的公共端口的服务。

# file 'application/service.yaml'

apiVersion: v1
kind: Service
metadata:
  name: my-service-for-my-webapp
spec:
  type: LoadBalancer
  selector:
    app: my-example-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

我们将容器端口8080映射到公共可用端口80。该服务充当负载平衡器。它在容器之间分配请求。

让我们部署我们的服务:

$ kubectl apply -f ./application/service.yaml 

service/my-service-for-my-webapp created

我们可以检查我们的服务是否正在运行:

$ kubectl describe svc my-service-for-my-webapp

Name: my-service-for-my-webapp
Namespace: default
Labels: <none>
Annotations: Selector: app=my-example-app
Type: LoadBalancer
IP: 10.104.18.24
LoadBalancer Ingress: localhost
Port: <unset> 80/TCP
TargetPort: 8080/TCP
NodePort: <unset> 32114/TCP
Endpoints: 10.1.0.17:8080, 10.1.0.18:8080
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>

输出非常具有描述性, 并确认了我们想要实现的目标。它使用来自两个已部署容器的端点(在Kubernetes中称为Pod)。

现在, 你可以打开http://本地主机:80

而已!你创建了一个Docker容器并在Kubernetes集群中使用了它。此设置功能强大, 是当今许多可扩展产品和业务的基础。

整理起来

让我们整理一下实验空间:

$ kubectl delete -f ./application/service.yaml 

service "my-service-for-my-webapp" deleted

$ kubectl delete -f application/deployment.yaml

deployment.apps "node-web-app" deleted

为了保持设备的资源自由, 我们还应该停止Docker的Kubernetes功能。

我希望你喜欢这个动手的例子。激发周围的Google兴趣, 查看其他示例, 部署容器, 连接它们并使用它们。

将来, 你将学习许多很酷的功能, 使你可以轻松, 可重用和可扩展的方式将应用程序交付生产。

一如既往, 我感谢任何反馈和意见。说谢谢在Twitter上关注我并分享给其他人。我写博客文章以非常"动手"的方式分享我的知识, 以培养动力, 热情和激动。

Dockering!

参考文献

  • https://en.wikipedia.org/wiki/Kubernetes
  • https://zh.wikipedia.org/wiki/Docker_(软件)
  • https://labs.play-with-docker.com/
  • https://labs.play-with-k8s.com/
  • https://nodejs.org/en/docs/guides/nodejs-docker-webapp/
一盏木

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: