服务运行从Docker到k8s

21,229 阅读8分钟

一:服务宿主历史

image.png

[虚拟化技术]演进

1.1 物理机时代

物理机时代:多个应用程序可能会跑在一台机器上。 image.png

1.2 虚拟机时代

虚拟机时代:一台物理机器安装多个虚拟机(VM),一个虚拟机跑多个程序。

image.png

1.3 容器时代

容器时代:一台物理机可以安装多台容器实例(container), 一个容器跑多个程序。

image.png

容器化解决了软件开发过程中一个令人非常头疼的问题,用一段对话描述:

测试人员:你这个功能有问题。

开发人员:我本地是好的啊。

二:Docker和k8s怎么用

2.0 Docker怎么用?

其实大多数人谈论 Docker 时说的是 Docker Engine,这只是一个构建和运行的容器。

在运行容器前需要编写Docker File,通过 dockerFile 生成镜像,然后才能运行 Docker 容器。

Docker File 定义了运行镜像(image)所需的所有内容,包括操作系统和软件安装位置。一般情况下都不需要从头开始编写 Docker File,在 Docker Hub 中有来自世界各地的工程师编写好的镜像,你可以基于此修改。

2.1 编排系统的需求催生 k8s

尽管Docker为容器化的应用程序提供了开放标准,但随着容器越来越多出现了一系列新问题:

  • 如何协调和调度这些容器?
  • 如何在升级应用程序时不会中断服务?
  • 如何监视应用程序的运行状况?
  • 如何批量重新启动容器里的程序?

解决这些问题需要容器编排技术,可以将众多机器抽象,对外呈现出一台超大机器。现在业界比较流行的有:k8s、Mesos、Docker Swarm。

在业务发展初期只有几个微服务,这时用 Docker 就足够了,但随着业务规模逐渐扩大,容器越来越多,运维人员的工作越来越复杂,这个时候就需要编排系统解救opers。

2.2 k8s是做什么用的?

K8s是Google研发的容器协调器,已捐赠给CNCF,现已开源。

Google 利用在容器管理多年的经验和专业知识推出了 k8s,主要用于自动化部署应用程序容器,可以支持众多容器化工具包括现在非常流行的Docker。

目前k8s 是容器编排市场的领导者,开源并公布了一系列标准化方法,主流的公有云平台都宣布支持。

2.3 Docker与k8s 难舍难分

Docker 和 k8s 在业界非常流行,都已经是事实上的标准。

Docker 是用于构建、分发、运行容器的平台和工具。

而 k8s 实际上是一个使用 Docker 容器进行编排的系统,主要围绕 pods 进行工作。Pods 是 k8s 生态中最小的调度单位,可以包含一个或多个容器。

Docker 和 k8s 是根本上不同的技术,两者可以很好的协同工作。

2.4 开发实践,灵魂追问

(1)没有 k8s 可以使用 docker 吗?

可以。实际上一些小型公司,在业务不太复杂的情况下都是直接使用 Docker。尽管 k8s 有很多好处,但是众所周知它非常复杂,业务比较简单可以放弃使用 k8s。

(2)没有 Docker 可以使用 k8s 吗?

k8s 只是一个容器编排器,没有容器拿什么编排?!

k8s 经常与 Docker 进行搭配使用,但是也可以使用其他容器,如RunC、Containerted 等。

三:常见docker 命令

//运行一个容器
docker run -it -p 8088:8088 -p 8089:8089 -p 8090:9090 -v /root/soft/docker:/root/soft/docker
命令的格式:
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
-i, --interactive=false 打开STDIN,用于控制台交互
-P: 是容器内部端口随机映射到主机的高端口。
-p: 是容器内部端口绑定到指定的主机端口。
-d, --detach=false 指定容器运行于前台还是后台
--net=bridge:使用docker daemon指定的网桥
--net=host: 容器使用主机的网络
--net=container:NAME_or_ID:使用其他容器的网路,共享IPPORT等网络资源
--net=none:容器使用自己的网络(类似--net=bridge),但是不进行配置
-v, --volume=[] 给容器挂载存储卷,挂载到容器的某个目录

//关闭运行中的容器
docker stop 容器ID

//启动一个已经停止的容器
docker start 容器ID

//重启一个容器
docker restart 容器ID

//进入一个运行中的容器
docker attach 容器ID

//显示全部容器
docker ps -a

//显示当前运行的容器
docker ps

//查看本地镜像
docker images

//删除所有镜像,awk每行按空格或TAB分割,输出文本中的第3项,grep -v 显示不包含匹配文本的所有行
docker rmi $(docker images | grep -v RESPOSITORY | awk '{print $3}')

//构建容器
docker build -t 镜像名称 Dockerfile存放的文件夹

//建立映像文件。–rm 选项是告诉Docker,在构建完成后删除临时的Container,
//Dockerfile的每一行指令都会创建一个临时的Container,一般这些临时生成的Container是不需要的
docker build --rm=true -t loen/lamp .

//删除容器
docker rm 容器ID

//删除所有容器
docker rm $(docker ps -a) 

//查看历史
docker history 镜像ID

//若是只想备份images,使用save、load即可
//若是在启动容器后(比如删除一个文件),容器内容有变化,需要备份,则使用export、import
//导出容器
docker export 容器ID > xxx.tar

//把 mynewimage 镜像保存成 tar 文件
docker save myimage | bzip2 -9 -c> /home/save.tar.bz2

//加载 myimage 镜像
bzip2 -d -c < /home/save.tar.bz2 | docker load

四:实战篇

4.1 docker 部署前端项目

4.1.1 项目打包

npm run build

运行上边命令,此时工程项目文件夹下会生成一个 Dist文件夹:

image.png

如果将该dist目录整个传到服务器上,部署成静态资源站点就能直接访问到该项目。

接下来就来构建一个这样的静态资源站点。

4.1.2 构建vue应用镜像

nginx 是一个高性能的HTTP和反向代理服务器,此处我们选用 nginx 镜像作为基础来构建我们的vue应用镜像。

docker pull nginx
  • docker镜像(Image)一个特殊的文件系统。Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 镜像不包含任何动态数据,其内容在构建之后也不会被改变。

  • docker 镜像相关操作有: 搜索镜像docker search [REPOSITORY[:TAG]]、拉取镜像docker pull [REPOSITORY[:TAG]] 、查看镜像列表docker image ls、删除镜像:docker image rm [REPOSITORY[:TAG]] / docker rmi [REPOSITORY[:TAG]] 等等。

  • docker 镜像名称由REPOSITORY和TAG组成 [REPOSITORY[:TAG]],TAG默认为latest

4.1.3 创建 nginx config配置文件

在项目根目录下创建nginx文件夹,该文件夹下新建文件nginx.conf

image.png

# nginx/nginx.conf
server {
  listen       80;
  listen  [::]:80;
  # 开启日志记录
  access_log  /var/log/nginx/host.access.log  main;

  location / {
    root   /usr/home/nginx/html;
    index  index.html index.htm;
  }

  location /api/ {
    proxy_pass: http://localhost/
  }

  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   /usr/home/nginx/html;
  }
}

该配置文件定义了首页的指向为 /usr/home/nginx/html/index.html, 所以我们可以一会把构建出来的index.html文件和相关的静态资源放到/usr/home/nginx/html目录下。

4.1.4 创建 Dockerfile 文件

image.png

# # 新建构建阶段build-stage,指定node为基础镜像,该阶段用于生成前端制品文件
# FROM node:14-alpine as build-stage
# # 指定工作目录/app用于存放前端制品,以便在COPY,RUN以及下一个构建阶段中使用。
# WORKDIR /app
# # 复制package.json、package-lock.json、yarn.lock到工作目录里,COPY最后一个参数dest如果是相对路径,则会以工作目录有作为基准,复制到WORKDIR/<dest>里
# COPY package*.json yarn.lock ./
# # 下载依赖
# RUN yarn install
# COPY . .
# # 生成制品
# RUN yarn build

# 新建构建阶段deploy-stage,指定nginx为基础镜像,该阶段用于配置和运行nginx
FROM nginx:latest
# 把build-stage阶段中的前端制品和nginx.conf配置文件复制到nginx的指定路径里
# 这样子就可以设置nginx的配置文件,而配置文件中的默认匹配路径是/home/nginx/html,也就是存放前端制品的路径
COPY dist/ /home/share/nginx/html
COPY nginx/nginx.conf /home/nginx/conf.d/default.conf
# 指定容器在运行过程时监听80端口
EXPOSE 80
# 指定在容器开启运行时,通过运行以下命令行指令开启nignx
CMD ["nginx", "-g", "daemon off;"]
  • 自定义构建镜像的时候基于Dockerfile来构建。

  • FROM nginx 命令的意思该镜像是基于 nginx:latest 镜像而构建的。

  • COPY dist/ /home/share/nginx/html 命令的意思是将项目根目录下dist文件夹下的所有文件复制到镜像中 /home/share/nginx/html 目录下。

  • COPY ginx/nginx.conf /home/nginx/conf.d/default.conf 命令的意思是将nginx目录下的nginx.conf 复制到 /home/nginx/conf.d/default.conf,用本地的 nginx.conf 配置来替换nginx镜像里的默认配置

4.1.5 基于DockerFile 构建Vue镜像

运行命令 (注意不要少了最后的“.”)

docker build -t vuenginxcontainer .

-t 是给镜像命名,. 是基于当前目录的DockerFile来构建镜像

查看本地镜像命令:

docker image ls | grep vuenginxcontainer

image.png

到此时我们的 vue 应用镜像 vuenginxcontainer 已经成功创建。接下来,我们基于该镜像启动一个docker容器。

4.1.6 启动 vue app 容器

Docker 容器Container: 镜像运行时的实体。镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等 。

基于 vuenginxcontainer 镜像启动容器,运行命令:

docker run \
-p 6000:80 \
-d --name vueApp \
vuenginxcontainer
  • docker run 基于镜像启动一个容器
  • -p 6000:80 端口映射,将宿主的6000端口映射到容器的80端口
  • -d 后台方式运行
  • --name 容器名 查看 docker 进程
docker ps

image.png

可以发现名为 vueApp的容器已经运行起来。此时访问 [http://localhost:6000] 应该就能访问到该vue应用.