容器本可以成为轻量级虚拟机的替代品。但是,由于 Docker/OCI 的标准化,最广泛使用的容器形式是每个容器只有一个进程服务。这种方法有很多优点——增加隔离性、简化水平扩展、更高的可重用性等。但是,它也有一个很大的缺点——正常情况下,虚拟(或物理)机器很少只运行一个服务。虽然 Docker 试图提供一些变通方法来创建多服务容器,但 Kubernetes 迈出了更大胆的一步,并选择了一组称为 Pod 的内聚容器作为最小的可部署单元。几年前,当我偶然发现 Kubernetes 时,我之前的虚拟机和裸机经验让我很快就了解了 Pod。刚开始接触 Kubernetes 时,你学到的第一件事就是每个 Pod 都有一个唯一的 IP 和主机名,并且在同一个 Pod 中,容器可以通过 localhost 相互通信。所以,显而易见,一个 Pod 就像一个微型的服务器。但是,过段时间,你会发现 Pod 中的每个容器都有一个隔离的文件系统,并且从一个容器内部,你看不到在同一 Pod 的其他容器中运行的进程。好吧!也许 Pod 不是一个微型的服务器,而只是一组具有共享网络堆栈的容器。但随后你会了解到,Pod 中的容器可以通过共享内存进行通信!所以,在容器之间,网络命名空间不是唯一可以共享的东西……
基于最后的发现,所以,我决定深入了解:
在此过程中,我希望它能帮助我巩固我的 Linux、Docker 和 Kubernetes 技能。
1、探索 Container
OCI 运行时规范并不将容器实现仅限于 Linux 容器,即使用 namespace 和 cgroup 实现的容器。但是,除非另有明确说明,否则本文中的容器一词指的是这种相当传统的形式。
设置实验环境(playground)
在了解构成容器的 namespace 和 cgroups 之前,让我们快速设置一个实验环境:
1 $ cat > Vagrantfile <<EOF
2 # -*- mode: ruby -*-
3 # vi: set ft=ruby :
4
5 Vagrant.configure("2") do |config|
6 config.vm.box = "debian/buster64"
7 config.vm.hostname = "docker-host"
8 config.vm.define "docker-host"
9 config.vagrant.plugins = ['vagrant-vbguest']
10
11 config.vm.provider "virtualbox" do |vb|
12 vb.cpus = 2
13 vb.memory = "2048"
14 end
15
16 config.vm.provision "shell", inline: <<-SHELL
17 apt-get update
18 apt-get install -y curl vim
19 SHELL
20
21 config.vm.provision "docker"
22 end
23 EOF
24
25 $ vagrant up
26 $ vagrant ssh