应用和应用环境的云化 - 从虚拟化到容器化
信息技术里最直观的产品其实就是应用,因为应用代表着逻辑流程的实现,我们日常的各种活动都可以被视为具体的流程,早期的流程都是由人(Manual)来实现,随着技术的加持开始实现自动化(Automatic),到如今人工智能技术的快速发展则开始逐渐智能化(Intelligent)。
信息系统里的应用构建于网络和终端之上,早期存在着各种不同的网络和终端,而随着计算机网络和技术逐渐成为通用的信息技术范式,信息网络开始逐渐统一为IP网络,而信息终端则趋近于计算机终端,电话和电视也逐渐演化为计算机网络和终端上一种应用形态,所以毫不夸张的说,计算机系统的发展在一定程度上影响着其他信息技术的演进方向。
- Application
- Terminal
- Network
传统环境
早期的计算机类终端就是由硬件和软件构成,作为应用的软件直接和硬件(HW)进行交互,这个时期基本上就是一台终端承载单个应用,而随着承载应用的需求增加,需要发展出更加通用的依赖层来实现复用,所以操作系统内核(Kernel)开始成为应用和硬件之间的中介,而内核的接口虽然比直接使用二进制码和硬件交互容易很多,但还是过于庞杂和细碎,于是运行时(Runtime)便构建于系统内核之上提供更加方便和拟人化的接口,早期的浏览器承载的前端Web,解释器承载的脚本语言比如perl等都比调用系统内核接口实现功能的C和C++简单易懂很多。
- Code Package
- HW - OS Kernel - Runtime
所以传统应用环境构建的主要流程首先是组装硬件,然后安装系统,最后配置运行环境,而应用得开发部署就是代码打包然后在运行环境上执行,这套流程依旧是信息系统构建最常规的步骤,但这套流程对于硬件指数级扩张之后的硬件集群(Cluster)就会出现构建瓶颈。
现代数据中心里终端主要是服务器集群的数量已经超出我们的想象,上述的流程即使通过运维自动化(Ops Automation)也显得力不从心,所以从内核层级和运行时层级相应发展出了虚拟化技术(Virtualization)和容器技术(Container)。
云化环境
不甚严谨的说,虚拟化技术就是在一台终端上共享硬件给多台虚拟机运行彼此独立的系统内核,容器技术则是共享系统内核给多个容器运行彼此独立的运行时环境,而通过相应的虚拟机编排系统和容器编排系统,可以无感知的在硬件集群上构建虚拟机以及在操作系统集群上构建容器。
当然最常规的使用场景就是单台硬件的虚拟化和单个操作系统的容器化,这种非集群场景就无需分布式的编排系统,只需要hypervisor和容器运行时即可。
而无论是虚拟化还是容器化带来的变化就是底层的无关性,对于构建其上的应用而言就不是简单代码打包而是基于代码的镜像构建,这些其实都是广义里平台和应用云化的概念。
- App Image
- Containerd + Worker Node - K8S Master -> K8S Cluster
- Hypervisor + Worker Node - Hyperviosr Cluster Master -> Hypervisor Cluster
- HW -> HW Cluster
常用的虚拟化和容器化工具如下所示
| Type | Single Node/Standalone | Cluster |
| VM | VMware / VirtualBox / KVM | Hypervisor Cluster (OpenStack, vSphere) |
| Container | docker | K8S cluster |
DevOps Pipeline
不得不说云化之后的虚机和容器编排系统操作上手门槛较高,但是随之而来就是实现标准的流程化更加可行,传统的代码到应用包的CI和环境构建,应用部署和运行的CD在云化环境下可以实现更加高效的流水线操作,而如果是构建快速原型,使用传统环境反倒更为灵活。
独立的运行时环境
运行时就是应用运行的底层基础,其实容器技术的优势之一也是解决了为应用提供独立的运行时环境的需求,在《脚本语言的代码层级》中提及过在早期系统中运行时为不同应用共用,随着模块化引用逐渐成为主流趋势,运行时环境下的包依赖也越来越复杂,共用运行时很容易导致不同的应用因为包依赖的版本不同出现冲突,所以对独立的运行时环境的需求越来越高。
无论是python还是node.js都提供区别于global的本地独立运行时机制,但是容器技术里的容器直接就包含了独立的运行时环境,所以就无需在系统上另行构建运行时环境,构建应用镜像的过程中就是实现了其独立运行时环境的构建。
有一个有趣的事情就是浏览器其实也能视为一个运行时,支撑运行其上的HTML,CSS和Javascript,浏览器也是web前端技术的底层基础设施,其重要作用类似于java,python等语言的解释器环境,而现在node.js可以视为从传统浏览器脱离出来的JS运行时,基于Google的V8引擎,所以JS也开始作为跨平台语言扩展到了后端甚至前端桌面应用。
应用的接口
一般而言一个完整的应用会提供服务和配置两种接口,传统的调用和配置方式就是本地组件加载和配置文件配置,而随着网络的可用性和成熟度的提升,远端调用和配置慢慢成为主流,远端接口则是要通过网络通信协议来实现交互,比如常见的基于http/https的REST API和基于netconf的配置服务。
- Service Interface
- Local - Load Component 《本地调用和远端调用》
- Remote - REST API
- Configuration Interface
- Local - Configuration File
- Remote - netconf protocol
docker
前面提到过容器技术主要实现提供独立运行时的容器,而docker就是实现容器技术的一个平台系统,其架构是典型的 Client - Server - Resource 的网络应用形态,其中CLI就是命令行形式的客户端工具用于发送请求;Dockerd是服务监听进程,用于响应请求并和容器运行时交互;容器运行时则是实现容器的构建;镜像仓库是镜像的远端存放点,Dockerd会和镜像仓库进行交互实现镜像的pull和push;此外docker使用Dockerfile来构建镜像。
- Docker CLI
- Dockerd (docker deamon)
- Containerd (container runtime)
- Image Registry
Docker service
systemctl status docker
systemctl start docker
docker run hello-world
docker --version
docker info
docker version
Image
docker pull <image>[:tag]
docker images
docker image ls
docker rmi <image_id>
docker image rm <image_id>
docker history <image>
docker push <repository>/<image>:<tag>
docker build -t <image:tag> <dockerfile directory>
docker commit [OPTIONS] <container_id> <new_image_name>:<tag>
docker export <container_id> > container.tar
docker import container.tar <new_image_name>:<tag>
Container
docker run [options] <image> [command]
docker run -dit --name apache-httpd -p 9080:80 -v /workspace/apache/www:/usr/local/apache2/htdocs/ httpd
docker run -it ubuntu /bin/bash
docker ps
docker ps -a
docker stop <container_id>
docker kill <container_id>
docker rm <container_id>
docker exec -it <container_id> /bin/bash
sudo docker exec -it b8a261cdb746 /bin/bash
docker attach <container_id>
docker start <container_id>
docker restart <container_id>
docker logs <container_id>
docker cp [OPTIONS] <src> <dest>
sudo docker cp b8a261cdb746:/usr/local/apache2/conf/httpd.conf ~/httpd.conf
sudo docker cp ~/httpd.conf b8a261cdb746:/usr/local/apache2/conf/httpd.conf
"runlike" to reverse-engineer docker run command
reverse-engineer a running Docker container and print the complete docker run command needed to re-create an identical copy.
首先拉取工具镜像
sudo docker pull assaflavie/runlike
运行以下命令导出指定容器的重建命令
sudo docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike nginx_proxy
然后会输出一条非常完整的docker run命令
docker run -d \
--name=nginx_proxy \
-p 443:443 \
-v /etc/nginx/conf.d:/etc/nginx/conf.d \
-v /etc/nginx/ssl:/etc/nginx/ssl \
--network bridge \
nginx:latest
Docker Compose
docker compose如果和K8S相比类似于本地的多容器编排工具,主要是多容器得启动和停止,而K8S则是针对操作系统集群的容器编排工具,功能强大并且复杂。
docker-compose.yml
docker compose ls
docker compose images
docker compose up
docker compose down
Prune
docker container prune -f
docker image prune -af
Docker registry mirror
官方的docker镜像仓库存在网络连通性问题,所以使用备用的镜像地址。
Add /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io"]
}
K8S
Kubernetes是一个基于操作系统集群的容器编排系统,所以其架构就是典型的分布式 Client - Master - Workers 形态,其中kubectl就是命令行形式的客户端工具用于发送请求;Master Node作为管理节点,其上运行kube-apiserver用于监听和响应客户端请求以及和工作节点进行交互;Worker Node作为工作节点,其上运行kubelet用于监听和响应管理节点的请求并且和节点的容器运行时交互用于容器的启动和停止。
- Kubectl
- Master Node
- Kube-apiserver
- Kube-controller-manager
- Kube-scheduler
- Worker Nodes
- kubelet
- Container-runtime
- containerd
- cri-o
- Container-runtime
- kubelet
Kubernetes官方的部署工具有单系统用于快速搭建环境的minikube和用于系统集群环境搭建的Kubeadm,但由于网络访问的限制,部署起来可能会遇到意想不到的问题
Minikube start: minikube start | minikube
minikube start --image-mirror-country='cn'
minikube status
K8S资源颗粒
Kubernetes的资源颗粒是Pod也就是容器组,其实以一种好理解得方式的来说Pod就是其内的容器会分配统一的IP和端口资源,所以不同容器之间应用可以通过本地网络来相互通信。
Helm
此外比较重要得就是K8S的包管理工具helm, 其管理的包chart其实就是yaml格式文件定义的容器编排声明,其功能定位可类比为集群环境下的Docker Compose。
更多推荐
所有评论(0)