原文内容:https://gitee.com/dev-99cloud/training-kubernetes ,在此基础上有新增。
Lesson 01:LXC & Docker
1.1 什么是 Linux 容器?
-
开发技术的演进
-
演进(虚拟化和容器技术)是为了解决什么问题?资源隔离 & 资源限制
-
什么是 Linux 容器?namespace & cgroup
-
什么是 lxc namespace?
-
什么是 CGroup?
-
Mac 和 Win 上 有容器技术么?
1.2 容器和虚拟机有何区别?
- 原理
- 一个 KVM 虚拟机就是一个 KVM 进程,N Core 就是 N 个线程
- 一个容器是一组被 LXC API 隔离+限制约束的进程组,容器中的进程就是宿主机操作系统中的进程,一一对应
- 应用场景
- 不同的内核
- 不同的操作系统
- 不同的 CPU 指令集
1.3 Docker 和容器技术有什么关系?
-
什么是 Docker( QuickStart )?
-
Docker 和容器有什么关系( why Linus don't care docker )?
1.4 Docker 的架构和概念空间是怎样的?
-
概念空间
-
模块架构
1.5 什么是所谓的安全容器技术?
-
容器的天然不安全与天然安全
-
竞争者:gVisor / firecracker / rustVM
1.6 实验:Docker Quick Start
1.6.1 centos 7
-
在 centos 7
# 移除旧的 docker 版本 yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine yum install -y yum-utils yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin # 设置为开机启动并且立刻启动服务 systemctl enable docker --now # run hello-world docker run hello-world
1.6.1.1 在 centos7 上构建镜像
-
如何创建一个镜像?如何启动和调试容器?Github 或 Gitee
$ mkdir ~/test $ cd ~/test $ wget https://gitee.com/dev-99cloud/lab-openstack/raw/master/src/docker-quickstart/app.py $ wget https://gitee.com/dev-99cloud/lab-openstack/raw/master/src/docker-quickstart/requirements.txt $ wget https://gitee.com/dev-99cloud/lab-openstack/raw/master/src/docker-quickstart/Dockerfile # 如果是 CentOS 7.x 需要安装下 python3 $ yum install python3 python3-pip # pip3 install -r requirements.txt $ pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt $ python3 app.py * Running on http://0.0.0.0:80/ (Press CTRL+C to quit) # 此时可以从浏览器访问 http://<ip>/ $ docker build --tag=friendlyhello . # 可以看一下本地镜像列表 $ docker images # 删除已存在的 testFlask 容器 $ docker rm testFlask 2>/dev/null # 以 99cloud/friendlyhello:3.9.6 镜像启动 testFlask 容器,容器内的 80 端口映射到宿主机的 4000 端口 # 如果带 --rm 参数,stop 之后,就会直接 rm 容器 $ docker run -p 4000:80 --name=testFlask 99cloud/friendlyhello:3.9.6 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit) # 此时可以从浏览器访问 http://<ip>:4000 # 如果要跑在后台,可以加 -d 参数 $ docker run -d -p 4000:80 --name=testFlask 99cloud/friendlyhello:3.9.6 # 进入容器调试 $ docker exec -it testFlask /bin/bash root@4224b69e7ee3:/app# env HOSTNAME=4224b69e7ee3 PWD=/app HOME=/root NAME=World ... root@4224b69e7ee3:/app# ps -ef # 查看容器日志 $ docker logs -f testFlask # 结束容器 $ docker stop testFlask # 启动容器 $ docker start testFlask # 从容器生成新的镜像 $ docker stop testFlask $ docker commit testFlask test-new # 删除容器 $ docker rm testFlask # 删除镜像 $ docker rmi friendlyhello $ docker rmi 99cloud/friendlyhello:3.9.6
1.6.2 ubuntu Ubuntu 18.04 / Ubuntu 20.04
-
在 Ubuntu 18.04 / Ubuntu 20.04
# 更新依赖仓库 apt-get update -y || yum update -y # 安装 Docker apt-get install docker.io -y || yum install docker -y systemctl enable docker systemctl start docker # 检查 docker 服务状态 systemctl status docker # ubuntu 中需要把 docker 的 cgroup driver 改成 systemd # !! centos 老版本的 docker 1.13 默认就是 systemd,不要修改这个文件,改了 docker 会起不来,保持 {} 就好,新版本的 docker 24+ 需要改 vi /etc/docker/daemon.json { "exec-opts": ["native.cgroupdriver=systemd"] } systemctl restart docker # run hello-world docker run hello-world
Note:2021 年 7 月之后,ubuntu 环境 kubeadmin 默认都是 1.22+ 版本,因此需要将 docker 的 cgroup driver 改成 systemd(原来是 cgroup)。如果不改,后续 kubeadm init 时,会报错:
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp [::1]:10248: connect: connection refused.
检查 journalctl -x -u kubelet,可以看到:
Aug 07 15:10:45 ckalab2 kubelet[11394]: E0807 15:10:45.179485 11394 server.go:294] "Failed to run kubelet" err="failed to run Kubelet: misconfiguration: kubelet cgroup driver: \"systemd\" is different from docker cgroup driver: \"cgroupfs\""
看官方文档:https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/configure-cgroup-driver/:
In v1.22, if the user is not setting the cgroupDriver field under KubeletConfiguration, kubeadm will default it to systemd.
所以我们需要把 docker 的 cgroup driver 改成 systemd
修改步骤参考:https://stackoverflow.com/questions/43794169/docker-change-cgroup-driver-to-systemd
修改完成后,检查一下 docker cgroup,确保 docker cgroup 是 systemd 了:
sudo docker info | grep -i cgroup
1.7 Docker 的网络模型
-
Bridge 模式
# docker 容器实现没有把 network namespaces 放到标准路径 `/var/run/netns` 下,所以 `ip netns list` 命令看不到 # 但是可以看 `ll /proc/<pid>/ns`,两个进程的 namespaces id 相同说明在同一个 namespaces [root@cloud025 ns]# ll /proc/2179/ns/ total 0 lrwxrwxrwx 1 root root 0 Aug 10 11:58 ipc -> ipc:[4026531839] lrwxrwxrwx 1 root root 0 Aug 10 11:58 mnt -> mnt:[4026531840] lrwxrwxrwx 1 root root 0 Aug 10 11:58 net -> net:[4026531956] lrwxrwxrwx 1 root root 0 Aug 10 11:58 pid -> pid:[4026531836] lrwxrwxrwx 1 root root 0 Aug 10 11:58 user -> user:[4026531837] lrwxrwxrwx 1 root root 0 Aug 10 11:58 uts -> uts:[4026531838] # 做个软链接,就可以看到 netns 了 [root@cloud025 ns]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 07297a3ac7ea nginx:latest "/docker-entrypoin..." 29 minutes ago Up 29 minutes 80/tcp devtest 0935b08509a4 test-new "python app.py" 35 minutes ago Up 35 minutes 0.0.0.0:5000->80/tcp testNew c23c76dd779c 99cloud/friendlyhello:3.9.6 "python app.py" 37 minutes ago Up 36 minutes 0.0.0.0:4000->80/tcp testFlask [root@cloud025 ns]# docker inspect testFlask | grep -i pid "Pid": 1159, "PidMode": "", "PidsLimit": 0, [root@cloud025 ns]# mkdir -p /var/run/netns [root@cloud025 ns]# ln -s /proc/1159/ns/net /var/run/netns/testFlask [root@cloud025 ns]# ip netns list testFlask (id: 0) devtest (id: 2) testNew (id: 1) # 进入对应的 namespaces,看 ip,pod namespace 里虚拟网卡的 link-netnsid 始终等于 0 [root@cloud025 ns]# ip netns exec testNew ip a ... 44: eth0@if45: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.3/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::42:acff:fe11:3/64 scope link valid_lft forever preferred_lft forever # 在 root namespaces 中 ip a,可以看到 link-netnsid = 1,1 是前面 ip netns list 里的 namespaces id [root@cloud025 ns]# ip a 45: vethb6d08be@if44: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 0e:d9:14:d1:86:98 brd ff:ff:ff:ff:ff:ff link-netnsid 1 inet6 fe80::cd9:14ff:fed1:8698/64 scope link valid_lft forever preferred_lft forever # 这是一对 veth pair,看他们的序号和 if 可以发现 # 看网桥,可以看到这个 root namespaces 的虚拟网卡绑在 docker0 网桥上 # 在 CentOS 上,需要安装一下:yum install bridge-utils [root@cloud025 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.02428c25c112 no vethb6d08be virbr0 8000.525400d583b9 yes virbr0-nic
-
Host 模式
-
CNM
1.8 Docker 的存储模型
-
[root@cka-studenta-1 ~]# mkdir testhaha [root@cka-studenta-1 ~]# docker run -d -it --name devtest -v "$(pwd)"/testhaha:/app nginx:latest Unable to find image 'nginx:latest' locally Trying to pull repository docker.io/library/nginx ... latest: Pulling from docker.io/library/nginx ... 7897813b7065a0390db335656443782895155655f263de6ee8264a6f2185fe16 [root@cka-studenta-1 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7897813b7065 nginx:latest "/docker-entrypoin..." 6 seconds ago Up 4 seconds 80/tcp devtest b667b8e2f90b 99cloud/friendlyhello:3.9.6 "python app.py" 3 hours ago Up 3 hours 0.0.0.0:4000->80/tcp testFlask [root@cka-studenta-1 ~]# docker exec -it 7897813b7065 /bin/sh # ls app bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var # cd app # ls # echo fsdfasfdasdfsa > xxxxxxxx.txt # exit [root@cka-studenta-1 ~]# ls test testhaha [root@cka-studenta-1 ~]# cd testhaha/ [root@cka-studenta-1 testhaha]# ls xxxxxxxx.txt [root@cka-studenta-1 testhaha]# cat xxxxxxxx.txt fsdfasfdasdfsa
-
Volumn 模式
评论