1. go 语言
《Go 程序设计语言》,《the way to go》
- 2. Docker
- 2.1 Dockerfile
命令 格式 说明
FROM FROM :
2.2 多阶段构建
多个镜像构建过程写一个 Dockerfile 文件.
2.3 打包
镜像 docker save
docker load
容器 docker export
docker import
2.4 镜像
2.4.1 镜像特点
1)分层
镜像由一系列镜像层组成, 镜像层分为只读层和读写层. 分层使不同镜像之间共享镜像层, 使 docker 镜像轻量.
2)写时复制
Copy-On-Write 策略, 使多个容器之间可以共享镜像. 每个容器启动时, 将所有镜像层挂载到一个挂载点, 再覆盖一个可读写的容器层. 减少磁盘占用和容器启动时间.
3)内容寻址
根据文件内容来索引 (sha256 哈希值) 镜像和镜像层, 最为镜像层的唯一标志.
4)联合挂载
联合挂载技术: 在一个挂载点同时挂载多个文件系统, 整合挂载内容, 使得最终可见的的文件系统包含各层文件和目录.
联合文件系统(union filesystem): 实现联合挂载技术的文件系统.
联合挂载, 用于将多个镜像层的文件系统挂载到一个挂载点来实现一个统一文件系统.
2.4.2 镜像元数据
2.4.2.1 registry
registry 用于保存 Docker 镜像, 其中还包括镜像层次结构和关于镜像的元数据. Docker 从 registry 中下载镜像保存在宿主机上, 然后启动容器.
1)公有 registry
Docker Hub:Docker 官方维护的公共仓库;
阿里云 docker 仓库
2)私有 registry
Docker Registry: 官方提供的工具, 用于构建私有的镜像仓库;
Docker Harbor:an open source trusted cloud native registry project that stores, sings, and scans content. 一般作为企业级 Registry 服务;
2.4.2.2 repository
repository 是由具有某个功能的 Docker 镜像的所有迭代版本构成的镜像组.
registry 是 repository 的集合, repository 是 image 的集合.
2.4.2.3 manifest
manifest(描述文件), 存在于 registry 中作为镜像的元数据文件. 镜像被 pull 到宿主机时, 自动转化为镜像配置文件.
2.4.2.4 image/layer
image: 存储镜像相关的元数据信息;
layer: 镜像层;
2.4.3 仓库
参考 1.4.2.1 registry 章节
2.5 数据卷
为什么使用数据卷?
联合挂载导致容器中的文件在宿主机上存在形式复杂, 不能方便的对容器中的文件访问;
多个容器之间的数据无法共享;
删除容器时, 数据丢失;
什么是数据卷?
数据卷(Volume): 存在于一个或多个容器中的特定文件或文件夹, 存在于宿主机上, 并为数据的共享和持久化提供便利.
容器创建时初始化, 运行时可使用文件;
容器间共享;
持久化;
数据卷的使用
docker volume 命令;
共享 volume(--volumes-from 参数与已有容器共享 volume);
Dockfile 中的匿名数据卷;
2.6 Docker 网络管理
2.6.1 libnetwork 网络库
Docker daemon 通过调用 libnetwork 网络库的 API 完成网络的创建和管理等功能.
端点: 一个端点只属于一个网络, 并且只属于一个沙盒, 端点的实现可以是 veth pair,Open vSwitch 内部端口或者相似设备;
网络: 一个网络是一组可以直接互相连通的端点;
沙盒: 一个沙盒可以有多个端点和多个网络;
libnetwork 实现了 5 种内置驱动, 以 bridge/host 驱动为例:
bridge driver:Docker 的默认驱动, 容器连接到 Docker 网桥 (Docker0) 上, 与外界通信需要使用 NAT(network address translation, 网络地址转换);
host driver: 容器不进行 network namespace 网络隔离, 容器中的进程处于宿主机的网络环境, 使用宿主机的网卡, ip 和端口. host 模式解决了容器与外界通信的地址转换, 可以直接使用宿主机的 IP.
2.6.2 docker network 命令
- $ docker network -h
- Commands:
- connect Connect a container to a network
- create Create a network
- disconnect Disconnect a container from a network
- inspect Display detailed information on one or more networks
- ls List networks
- prune Remove all unused networks
- rm Remove one or more networks
- 2.6.3 iptables
- // TODO
2.7 Docker 背后的内核知识
Docker 容器实质上是宿主机上的进程. Docker 通过 namespace 实现了资源隔离, 通过 cgroups 实现了资源限制, 通过写时复制实现了高效的文件操作.
2.7.1 namespace 资源隔离
Linux 内核实现 namespace 的一个主要目的, 就是实现轻量级虚拟化服务. 在同一个 namespace 下的进程可以感知彼此的变化, 而对外界的进程一无所知. 这样就可以让容器中的进程产生错觉, 仿佛置身于一个独立的系统环境中, 以达到独立和隔离的目的.
namespace 的 6 项隔离
namespace 系统调用参数 隔离内容
UTS CLONE_NEWUTS 主机名与域名
IPC CLONE_NEWIPC 信号量, 消息队列, 共享内存
PID CLONE_NEWPID 进程编号
Network CLONE_NEWNET 网络设备, 网络栈, 端口等
Mount CLONE_NEWNS 挂载点(文件系统根目录)
User CLONE_NEWUSER 用户和用户组
2.7.2 cgroups 资源限制
cgroups 是 Linux 内核提供的一种机制, 可以根据需求把一系列系统任务及其子任务按资源划分等级的不同组内, 从未为系统资源管理提供一个统一的框架.
cgroups 限制, 记录任务组所使用的物理资源(CPU,Memory,IO), 为容器实现虚拟化提供了基本保证, 是构建 Docker 等一系列虚拟化管理工具的基石.
3. kubernetes
3.1 什么是 kubernetes
Kubernetes 脱胎于 Google 的大规模集群管理工具 Borg, 管理跨主机 Docker 容器, 实现了应用部署, 高可用管理和弹性伸缩功能, 并封装了一套 RESTful API 对外提供服务.
Kubernetes 设计哲学之一, 维护应用容器集群一直处于用户所期望的状态.
3.2 核心概念
3.2.1 pod
kubernetes 中, 能够被创建, 调度和管理的最小单元是 pod, 而非单个容器. 一个 pod 是由若干个 Docker 容器构成的容器组(pod 意为豆荚, 容纳多个豆子, 很形象).
同一个 pod 中的容器有两个特性:
通过 kubernetes volume 机制, 在容器间共享存储;
通过 localhost 直接访问另一个容器;
3.2.2 label 和 label selector
当系统运行着大量的 pod 时, 用户如何有效的定位与组织这些 pod?kubernetes 的解决方案是 label. 每个 pod 都一个属性 "labels":
- "labels":{
- "key1":"value1",
- "key2":"value2"
- }
- $ kubectl get pods -n root -l name=nginx
kubernetes 中的其他对象, 如 deployment,service, 同样可以根据 label 对 pod 进行定位和组织.
在 kubernetes 中, label 是一种重要的且被广泛应用的组织, 分类和选择 kubernetes 对象的机制.
labels 属性是一组绑定到 kubernetes 对象 (如 pod) 上的键值对, 同一个对象 labels 属性的 key 必须独一无二.
label 不直接作为系统内部唯一标识 kubernetes 对象的依据, 因为不同于对象名和 uuid,label 并不保证唯一性.
label selector 是 kubernetes 核心的分组机制, 通过 label selector 能够识别一组有共同属性的 kubernetes 对象. 有两种 label selector 查询条件:
基于值相等的查询条件;= !=
基于子集的查询条件; in notin
3.2.3 replication controller
replication controller(副本控制器)决定了一个 pod 有多少个同时运行的副本, 并保证这些副本的当前状态与期望状态一致.
RC 的典型场景:
重调度. 当 pod 异常, kubernetes 会进行相应 pod 重调度;
弹性伸缩. 手动或自动修改副本数 replicas 字段;
滚动更新(灰度发布). 逐个替换 pod 进行更新;
多版本 release 追踪. 利用 labels 和 label selector 机制;
replica set
新一代副本控制器, 也是用于保证与 label selector 匹配的 pod 数量维持在期望状态.
replica set 和 replication controller 区别在于: replication controller 仅支持基于值相等的 selector 查询, replica set 引入了基于子集的 selector 查询条件;
Deployment
Deployment 用于 为 pod 和 replica set 提供更新, 并可以方便的跟踪观察其所属的 replica set 或者 pod 数量以及状态的变化. 即, deployment 是为了应用的更新而设计的.
3.2.4 service
为什么需要 service?
由于重调度, pod 在 kubernetes 中的 IP 地址不是固定的, 因此需要一个代理来确保需要使用 pod 的应用不需要知晓 pod 的真实 ip 地址;
当使用 RC 创建多个 pod 的副本时, 需要一个代理来为 pod 做负载均衡;
什么是 service?
service 主要由一个固定 IP 地址和一个 label selector 组成. 通过创建 service, 可以为一组具有相同功能的容器应用提供一个统一的入口地址, 并将请求进行负载均衡到后端的各个容器应用上.
如何定义一个 service?
代理一个 pod 集
前提: 有一个 pod 集, 其中的所有 pod 均被贴上一个相同的 labels:{"app":"nginx"}, 且所有容器均对外暴露一个端口 8080;
service 对象的配置信息: 指定后端服务的 "selector","ports" 属性.
- "spec":{
- "selector":{
- "app":"nginx"
- },
- "ports":[
- {
- "protocol":"TCP",
- "port":80,
- "targetPort":8080
- }]
- }
该 service 会将外部流量转发到所有匹配 selector 的 pod 的 targetPort 端口上;
service 的入口地址: 系统分配一个虚拟 IP+port 端口, 也可以在配置信息 spec.clusterIP 字段手动指定 service 的虚拟 IP;
当 service 对象被创建后, 系统会随之创建一个同名的 Endpoints 对象, 保存了所有匹配 label selector 的后端 pod 的 IP 和端口;
代理外部服务
外部服务没有 labels 属性, service 也就没有 label selector, 系统也不会自动创建 Endpoints 对象, 显式的将 service 映射到一个或多个后端服务(外部服务).
3.2.5 Pod,RC,Service 之间的关系
Pod,RC,Service 的关系图
3.3 kubectl 集群管理工具
3.4 YAML 文件语法
3.5 应用实例
通过实例学习一下操作:
Pod 创建, 内存, CPU 限制
2 V, PV,PVC
Service,deployment 创建
- 4 AutoScale
- 3.5.1 nginx
nginx 实例
3.5.2 Redis
k8s 上使用 StatefulSet 进行 Redis 集群的部署
3.6 kubernetes 各大组件
APIServer
APIServer 负责对外提供 kubernetes API 服务, 作为系统管理指令的统一入口, 统揽全局, 任何对资源进行 ACID 操作都交个 APIServer 处理后才能提交给 etcd.
scheduler
scheduler 根据特定的调度算法将 pod 调度到指定的工作节点上(即绑定 bind).
controller manager
controller manager 管理集中的各种控制器(如 replication controller,node controller), 负责控制管理对应的资源, 确保资源保持在用于预期的状态.
kubelet
kubelet 是 kubernetes 集群的工作节点上最为重要的组件进程, 负责管理和维护在这台主机上运行着的所有容器, 使得 pod 的运行状态 status 与期望值 spec 一致.
kube-proxy
kube-proxy 是 kubernetes 服务发现和反向代理服务的底层实现.
服务发现: kube-proxy 使用 etcd 的 watch 机制, 监控集群中 service 和 endpint 对象数据的动态变化, 并维护一个从 service 到 endpoint 的映射关系, 从而保证了后端 pod 的 ip 变化不会对访问者造成影响.
方向代理: kube-proxy 支持 TCP/UDP 连接转发, 默认使用 Round Robin 算法 (依次从可用工作节点列表中选取一个工作节点) 将流量转发到与 service 对应的一组后端 pod.
3.7 各大组件协作
创建 pod
创建 RC
创建 service
来源: http://www.bubuko.com/infodetail-2965527.html