01-预习篇·小鲸鱼大事记(一):初出茅庐
- 本质都是使用cgroups和namespace技术
- docker好用的就是在于镜像
- 提供了便利的打包机制,因为操作系统也在里面
02-预习篇·小鲸鱼大事记(二):崭露头角
- docker给了打包的完美解决方案
03-预习篇·小鲸鱼大事记(三):群雄并起
- 后来该名成Docker公司,推出了swarm
- docker收购了fig成为现在的compose
- 大数据是计算密集型离线业务
- 2014年kubernetes项目诞生
04-预习篇·小鲸鱼大事记(四):尘埃落定
- k8s在编排领域的落定
- CNCF一些基础设施平台层的开源社区对抗Docker
05-白话容器基础(一):从进程说开去
- 容器技术的兴起来源于paas技术的普及
- docker项目通过“容器镜像"解决应用打包的难题
- cgroups技术是用来制造约束,namespace技术是用来修改进程视图的主要方法
- 在docker中执行ps会发现 /bin/sh 的PID为1,代表了这个docker已经被隔离,就是linux的namesapce机制
- linux创建进程的系统调用是clone,里面有个参数CLONE_NEWPID,就是使用的namespace技术
- 就是在创建docker进程的时候指定了一组namespace参数,这样容器就只能看见所限定的资源、文件等配置
- 容器就是一种特殊的进程
- 就是被操作系统做了限制
06-白话容器基础(二):隔离与限制
- 虚拟机必须要hypervisor创建虚拟机,在里面运行完整的os,占用的资源比较大
- docker隔离的不够彻底,因为共享宿主机内核,所以在windows宿主机上运行linux容器是不行的
- 有些资源是不能被namespace化的
- 但是作为一个进程他是和其他普通的进程一样可以占用宿主机所有资源的,基于这个问题用cgroups来解决,限制一个进程组能够使用资源的上限
- /sys/fs/cgroup/cpu:文件中指定了一些参数
docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash
cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_period_us
cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_quota_us
- 应该希望容器和应用程序同生命周期,就是不能出现容器跑的很好,里面的应用程序挂了
- /proc文件存储的是当前内核运行状态的文件,也是top命令的数据来源
- 在容器中执行top显示的是宿主机的资源信息,并不是容器的怎么解决?
1 之前遇到过,但是没有考虑如何解决,临时抱佛脚,查了 lxcfs,尝试回答一下。top 是从 /prof/stats 目录下获取数据,所以道理上来讲,容器不挂载宿主机的该目录就可以了。lxcfs就是来实现这个功能的,做法是把宿主机的 /var/lib/lxcfs/proc/memoinfo 文件挂载到Docker容器的/proc/meminfo位置后。容器中进程读取相应文件内容时,LXCFS的FUSE实现会从容器对应的Cgroup中读取正确的内存限制。从而使得应用获得正确的资源约束设定。kubernetes环境下,也能用,以ds 方式运行 lxcfs ,自动给容器注入争取的 proc 信息。
2 用的是vanilla kubernetes,遇到的主要挑战就是性能损失和多租户隔离问题,性能损失目前没想到好办法,可能的方案是用ipvs 替换iptables ,以及用 RPC 替换 rest。多租户隔离也没有很好的方法,现在是让不同的namespace调度到不同的物理机上。也许 rancher和openshift已经多租户隔离。
07-白话容器基础(三):深入理解容器镜像
- namespace是隔离,cgroups是限制
- mount namespace基于chroot(切换系统根目录的能力)
- 挂载早容器根目录上为容器提供隔离后执行环境的文件系统就是镜像
- 只是挂载了文件系统
- 联合文件系统的layer实现
- docker的文件都在/var/lib/docker文件中查看到
08-白话容器基础(四):重新认识Docker容器
- docker tag xxx 镜像仓库名称/app:v1
- docker push 镜像仓库名称/app:v1
- 还可以将正在运行的容器提交到镜像仓库
- docker commit 4ddf4638572d 镜像仓库名称/app:v1
- 在企业内部也可以搭建一个Docker Hb的系统,Harbor
09-从容器到容器云:谈谈Kubernetes的本质
- 容器就是由Linux Namespace Linux Cgroups和rootfs三种技术构建出来的隔离环境
- 挂载的部分称为容器镜像rootfs
- 由namespace和cgroups构成的隔离环境称为容器的运行时
- 通过master和node架构,master包含api server,负责调度的kube-scheduler,和负责编排的controller,数据存储在etcd中
- node节点的核心部分是kubelet的插件,负责跟容器运行时打交道
- k8s不关心容器运行时,使用什么技术栈,只要可以运行标准的容器镜像,就可以实现CRI接入到k8s中
- kubelet还负责调用网络插件配置和持久化存储,CNI和CSI
- kubernetes是给pod绑定一个service服务,用来代理pod对外暴露固定的ip
- 数据库密码通过etcd中的secret方式获取
- k8s定义了一些编排对象,Pod(大数据任务),Job(维持一个实例的守护进程),CronJob(定时任务)等,这种方法使用声明式API
- 基于这种声明式的API来实现强大的编排功能
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:- containerPort: 80
kubectl create -f nginx-deployment.yaml
-
主体是template:使用Nginx的Pod镜像,replicas副本是2
-
将一个容器按照某种规则放置在最佳节点上运行起来,这种功能叫做调度
-
k8s擅长的是按照用户的意愿和规则,自动化的处理好容器之间的各种关系,就是我们经常听到的:编排
-
k8s真真的价值是提供了一套基于容器构建分布式系统的基础依赖
-
评论区的精品回答:
从微服务架构来讲,多个独立功能内聚的服务带来了整体的灵活性,但是同时也带来了部署运维的复杂度提升,这时Docker配合Devops带来了不少的便利(轻量、隔离、一致性、CI、CD等)解决了不少问题,再配合compose,看起来一切都很美了,为什么还需要K8s?可以试着这样理解么?把微服务理解为人,那么服务治理其实就是人之间的沟通而已,人太多了就需要生存空间和沟通方式的优化,这就需要集群和编排了。Docker Compose,swarm,可以解决少数人之间的关系,比如把手机号给你,你就可以方便的找到我,但是如果手机号变更的时候就会麻烦,人多了也会麻烦。而k8s是站在上帝视角俯视芸芸众生后的高度抽象,他看到了大概有哪些类人(组织)以及不同组织有什么样的特点(Job、CornJob、Autoscaler、StatefulSet、DaemonSet…),不同组织之间交流可能需要什么(ConfigMap,Secret…),这样比价紧密的人们在相同pod中,通过Service-不会变更的手机号,来和不同的组织进行沟通,Deployment、RC则可以帮组人们快速构建组织。Dokcer 后出的swarm mode,有类似的视角抽象(比如Service),不过相对来说并不完善。
10-Kubernetes一键部署利器:kubeadm
- k8s强大的地方在于他的声明式API的抽象,可以处理很多的复杂业务场景,在常规的java web和MySQL之间的通信用compose也可以处理的很好,但是如果遇到部署一个Cassandra集群,哪些容器是主,哪些容器是从,他们是如何自动发现和通信的等等,只有k8s才能解决
- 用docker部署k8s可以吗,会遇到kubelet的问题,需要访问宿主机
- 解决方案是将kubelet单独部署,使用容器部署其他组件
- 通过kubeadm init部署master节点,可以自定义配置文件–config kubeadm.yaml
- kubeadm部署时先会做一系列的检查,然后生成证书,放在/etc/kubernetes/pki文件下
- 然后为组件生成配置文件
$ ls /etc/kubernetes/manifests/
etcd.yaml kube-apiserver.yaml kube-controller-manager.yaml kube-scheduler.yaml
- kubeadm能用于生产环境吗?不能,不能做到高可用
- kubectl get nodes
- kubectl describe查看节点的详细信息
- kubectl apply -f安装各种插件
- k8s这种松耦合架构可以使用很多的插件,Rook是基于Ceph进行封装是一个生产级别的容器存储插件
- Rook是一个很有潜力的项目
- 部署文档:click me
12-牛刀小试:我的第一个容器化应用
- deployment是定义多个副本应用的对象,会将label中携带app:nginx标签的Pod识别为被管理的对象,并且保证严格的数量
- 主体分为Metadata和Sepc来那个部分,前者存放元数据,后者用来描述他要表达的功能
- 通过kubectl create -f xxx.yaml启动定义的文件
- kubectl replace来更新版本也可以统一用apply
- 运维可以用git diff来查看更改变化
- 还可以进入到Pod中查看
$ kubectl exec -it nginx-deployment-5c678cfb6d-lg9lw -- /bin/bash
# ls /usr/share/nginx/html
- 删除操作
$ kubectl delete -f nginx-deployment.yaml
- 总结:
- Kubernetes API对象,往往由Metadata和Spec两部分组成,其中Metadata里的Labels字段是Kubernetes过滤对象的主要手段。
- 在这些字段里面,容器想要使用的数据卷,也就是Volume,正是Pod的Spec字段的一部分。而Pod里的每个容器,则需要显式的声明自己要挂载哪个Volume。
- 通过yaml来实现就尽量不要碰docker命令行了
13-为什么我们需要Pod?
- ps tree -g:Linux进程树
- 进程不是独自运行的,是通过进程组的方式运行
-
在k8s项目中,Pod的实现需要一个容器中间件,叫Infra容器,这个Pod永远都是第一个创建的,通过join方式和infra容器关联在一起
-
infra容器用汇编语言编写目的是hold住network namespace
-
容器的设计模式:经典的例子,war包和 tomcat容器,将war包挂载到tomcat容器中
-
将他们作为一个pod里的两个容器组合在一起
apiVersion: v1
kind: Pod
metadata:
name: javaweb-2
spec:
initContainers:
- image: geektime/sample:v2
name: war
command: ["cp", "/sample.war", "/app"]
volumeMounts:
- mountPath: /app
name: app-volume
containers:
- image: geektime/tomcat:7.0
name: tomcat
command: ["sh","-c","/root/apache-tomcat-7.0.42-v2/bin/start.sh"]
volumeMounts:
- mountPath: /root/apache-tomcat-7.0.42-v2/webapps
name: app-volume
ports:
- containerPort: 8080
hostPort: 8001
volumes:
- name: app-volume
emptyDir: {}
- init container会启动之后执行拷贝操作之后退出
- 这种容器的设计模式叫sidecar,在Pod中启动一个辅助容器,完成一些独立于主进程之外的工作
- 例2:需要将/var/log目录中的日志记录下来,同样可以启动一个sidecar容器不断的从/var/log目录中读取日志文件转发到mongo或者es中存储起来
- 还可以将Pod网络相关配置和管理交给sidecar完成,就是Istio项目
- 同行一个docker容器中只跑一个进程
- 不要docker in docker这么套娃
14-深入解析Pod对象(一):基本概念
- 将pod看成机器,里面的容器看成应用程序
- 凡是调度、网络、存储,以及安全相关的属性,基本上是Pod 级别的
- Pod API的子段:
- pass
15-深入解析Pod对象(二):使用进阶
- Pod API中包含了丰富的信息,有个概念:Projected Volume
- 支持的共有4中:Secret;ConfigMap;Downward API;ServiceAccountToken
- Secret可以将访问加密的数据放在etcd中