本篇文章主要从新手的角度熟悉一下docker k8s
2021.08.25 add docker 通俗理解
2023.01.20 add k8s InitContainer
新手看docker & k8s
[TOC]
references:
什么是 IaaS,PaaS,SaaS
IaaS:基础设施服务,Infrastructure-as-a-service
PaaS:平台服务,Platform-as-a-service
SaaS:软件服务,Software-as-a-service
以制作pizza为例子,三个item的区别可以如下图所示:
映射到software中可以这样看:
认识Docker
和微服务关联
更多微服务相关的知识可以参考我的另一篇博客 架构方面学习笔记(1)
虚拟机
虚拟机,类似于“子电脑”
在“子电脑”里,你可以和正常电脑一样运行程序,例如开QQ。如果你愿意,你可以变出好几个“子电脑”,里面都开上QQ。“子电脑”和“子电脑”之间,是相互隔离的,互不影响。
++虚拟机属于虚拟化技术。而Docker这样的容器技术,也是虚拟化技术,属于轻量级的虚拟化。++
虚拟机虽然可以隔离出很多“子电脑”,但占用空间更大,启动更慢,虚拟机软件可能还要花钱(例如VMWare)。
而容器技术恰好没有这些缺点。它不需要虚拟出整个操作系统,只需要虚拟一个小规模的环境(类似“沙箱”)。
下面这张图是虚拟机和容器的对比:
简单来说,虚拟机是系统级别的,而 Docker 这种的容器技术是进程级别的
Docker
Docker技术的三大核心概念,分别是:
-
镜像(Image)
-
容器(Container)
-
仓库(Repository)
Docker 是对Linux容器的一种封装,具有高性能,低开销,接口简单易用等特点。Docker镜像,是一个特殊的文件系统。它除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(例如环境变量)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
也就是说,每次变出房子,房子是一样的,但生活用品之类的,都是不管的。谁住谁负责添置。
负责对Docker镜像进行管理的,是Docker Registry服务(类似仓库管理员)
看了上面的描述是不是感觉太专业化,下面以通俗的语言来介绍一下 docker
docker 说白了就是一种容器技术,容器就是一个类似于集装箱一样的存在,而容器技术的出现就是为了抹平软件运行的环境差异
-
不同的应用程序可能会有不同的应用环境,当我们想在一个服务器上隔离不同的应用,我们当然可以使用虚拟机,但更推荐 docker 是因为它可以实现虚拟机隔离应用环境的功能,开销更少:虚拟机会占用空闲内存,但 docker 部署则可以将这些内存利用起来。
举个例子:比如.net开发的网站和php开发的网站依赖的软件就不一样,如果把他们依赖的软件都安装在一个服务器上就要调试很久,而且很麻烦,还会造成一些冲突。比如IIS和Apache访问端口冲突。这个时候你就要隔离.net开发的网站和php开发的网站。常规来讲,我们可以在服务器上创建不同的虚拟机在不同的虚拟机上放置不同的应用,但是虚拟机开销比较高。docker可以实现虚拟机隔离应用环境的功能,并且开销比虚拟机小,小就意味着省钱了。
-
将开发环境封装在 docker 中,方便了移植。你开发软件的时候用的是Ubuntu,但是运维管理的都是centos,运维在把你的软件从开发环境转移到生产环境的时候就会遇到一些Ubuntu转centos的问题,比如:有个特殊版本的数据库,只有Ubuntu支持,centos不支持,在转移的过程当中运维就得想办法解决这样的问题。这时候要是有docker你就可以把开发环境直接封装转移给运维,运维直接部署你给他的docker就可以了。而且部署速度快。
docker-compose
定义:
Compose 是用于定义和运行多容器 Docker 应用程序的工具。
具体使用:
- 通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
- 注意 mac 版 docker-desktop 中已经集成了 docker-compose 直接使用即可
栗子以及应用
可以参考 docker doc ,它可以带你实现
- 写一个 docker file
- 生成一个 node 应用的镜像(不包含 node_modules 哦)
docker build -t getting-started .
docker run -dp 3000:3000 getting-started
启动应用就可以了
- 更新应用,重新生成镜像,重新启动(重复上面的两个步骤即可)
- 在 docker hub 上创建仓库,并实现镜像的分享
写在这里:通过上面的教程可以发现,在本地根本没有产生任何 node_modules,可以说使用 docker 真的是很方便了
一些操作
# 进入到对应的 container 中 或者说直接通过 docker 控制台进来
docker exec -it containerIdxxx /bin/sh
# 在 docker 中查看 host,其中会包含 container ip
# 备注 有时我们在 docker 中起 Django 连接 docker 起的 MySQL 如果用 127.0.0.1 会报权限错误,此时换成 这里的 ip 会解决
cat /etc/hosts
# 解决 docker 中显示 vim: command not found
# 对于 debian 系统
apt-get update
apt-get -y install vim
K8S
脑图:https://naotu.baidu.com/file/f154eb52fe6663d5aa2820559424eb6d
创造者:Google
如果想要将Docker应用于具体的业务实现,是存在困难的——编排、管理和调度等各个方面,都不容易。于是,人们迫切需要一套管理系统,对Docker及容器进行更高级更灵活的管理。
就在这个时候,K8S出现了。
K8S,就是基于容器的集群管理平台,它的全称,是kubernetes。
一个K8S系统,通常称为一个K8S集群(Cluster)。
这个集群主要包括两个部分:
一个Master节点(主节点):
Master节点主要还是负责管理和控制。
一群Node节点(计算节点):Node节点是工作负载节点,里面是具体的容器。
Master节点包括API Server、Scheduler、Controller manager、etcd。
API Server是整个系统的对外接口,供客户端和其它组件调用,相当于“营业厅”。
Scheduler负责对集群内部的资源进行调度,相当于“调度室”。
Controller manager负责管理控制器,相当于“大总管”。
Node节点包括Docker、kubelet、kube-proxy、Fluentd、kube-dns(可选),还有就是Pod。
Pod是Kubernetes最基本的操作单元。一个Pod代表着集群中运行的一个进程,它内部封装了一个或多个紧密相关的容器。除了Pod之外,K8S还有一个Service的概念,一个Service可以看作一组提供相同服务的Pod的对外访问接口.
Docker,不用说了,创建容器的。
Kubelet,主要负责监视指派到它所在Node上的Pod,包括创建、修改、监控、删除等。
Kube-proxy,主要负责为Pod对象提供代理。
Fluentd,主要负责日志收集、存储与查询。
initContainer 的使用
工作中有个需求:在 initContainer 中执行一个 job 进行一些数据初始化操作,执行完 job 之后再去创建应用容器。
为了实现这个需求使用到的资源:job,使用到的配置:deployment->initContainer
使用 k8s-wait-for 来等待一个 k8s job 是否进入到所需状态,注意其需要获取使用 kube api 的权限,因此需要设置 role 和 rolebinding 来进行权限分配。
稍微深入了解Docker
docker架构
调度问题
references:
详解一个 docker file
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。 Docker通过读取 Dockerfile 中的指令自动生成镜像。
Dockerfile 可以使用在命令行中调用任何命令。
Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。
# 定制的镜像都是基于 FROM 的镜像
FROM python:3.9-slim
# Label 用来给镜像添加一些元信息
LABEL maintainer="liulin <lynnwonder@163.com>" \
python="3.9" \
project="https://github.com/LynnWonder/python_prac"
# ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
ARG REPO=xxx.org
ARG PYPI=https://pypi.Python.org/simple/
# 设置 Python 解释器不生成字节码 pyc 文件
ENV PYTHONDONTWRITEBYTECODE 1
# 设置 python 的 stdout 为无缓存模式
ENV PYTHONUNBUFFERED 1
# WORKDIR 用于为它的下一个 Command 设置工作目录
WORKDIR /app
# Install dependencies
# COPY [--chown=<user>:<group>] <源路径1>... <目标路径>
COPY requirements.txt .
# RUN 执行后面跟着的命令行命令
# dpkg 用来安装 .deb 文件时,不会解决模块的依赖关系,且不会关心 ubuntu 的软件仓库内的软件,可以用于安装本地的deb文件。
# apt-get:会解决和安装模块的依赖问题,但不会安装本地的deb文件,主要用于自动从互联网的软件仓库中搜索、安装、升级、卸载软件或操作系统,apt-get是建立在dpkg之上的软件管理工具。
RUN set -ex \
# configure apt
# sed stream editor,向 /etc/apt/sources.list 中添加一行
# /etc/apt/sources.list 是包管理工具 apt 所用的记录软件包仓库位置的配置文件
&& sed -i "s|deb.debian.org|${REPO}|g" /etc/apt/sources.list \
&& sed -i "s|security.debian.org|${REPO}|g" /etc/apt/sources.list \
\
# --no-install-recommends 不安装推荐的文件
# install packages for building and runtime
# build-essential 是编译软件所必需的元包
# default-libmysqlclient-dev 是 mysql client 依赖的元包
&& apt update && apt install -y --no-install-recommends \
build-essential \
default-libmysqlclient-dev \
\
# install python packages
&& pip install --no-cache-dir -r requirements.txt -i ${PYPI} \
\
# clean up
&& apt remove -y \
build-essential \
# 删除最近卸载程序时下载的依赖项
&& apt autoremove -y \
# apt-get update 更新本地包缓存时下载的东西会存在如下目录中,可以删掉
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /tmp/*
# Application
COPY . .
# -e 当命令发生错误的时候,停止脚本的执行。
# -x 将将要运行的命令用一个 + 标注以后,再在下一行展示运行结果
RUN set -ex \
# 在工作目录下创建 /log
&& mkdir -p /app/log \
# 让 entrypoint.sh 可执行
&& chmod +x entrypoint.sh
# ENTRYPOINT 通常用于设置容器镜像的主程序,同时结合 CMD 设置一些默认的参数(可以读 cmd 传进来的参数)
ENTRYPOINT ["./entrypoint.sh"]
# 设置容器运行时监听的端口,仅仅是声明,真正的端口监听是在容器启动的时候进行的,会映射宿主机的端口到容器的端口
EXPOSE 32345
CMD ["gunicorn", "--preload", "--config", "etc/gunicorn.py", "python_prac.wsgi:application"]
docker container 连接宿主机服务
docker run -d -p local_port:container_port --net=host --name=container_name image_url
- 直接通过修改配置文件中连接 mysql 的 host 为宿主机上 docker0 的地址