开发者学堂课程【企业级运维之云原生与 Kubernets 实战课程:深入剖析 linux 容器 & Pod(上) 】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/913/detail/14532
深入剖析 linux 容器 & Pod(上)
本章目标
Ÿ 理解容器和 pod 的基本原理以及差异
Ÿ 理解 pod 创建的过程
Ÿ 理解各个控制器的作用
Ÿ 理解 ack 集群的网络原理以及 coredns 的原理
本章目录
Ÿ 深入剖析 linux 容器 & Pod
Ÿ 集群创建 Pod 的过程
Ÿ 阿里云 ACK 集群控制器
Ÿ 阿里云 ACK 集群网络
第三章第1讲 深入剖析linux容器&Pod(上)
目录
Ÿ 什么是容器
Ÿ 资源隔离( namespace )
Ÿ 资源限制( cgroup )
Ÿ Init 容器
Ÿ Pause 容器
Ÿ 最佳实践
一、什么是容器
容器提供了一种逻辑打包机制,以这种机制打包的应用,可以脱离其实际运行的环境。
传统OS上应用的特点:
Ÿ 应用进程可以互相看到,互相通信,意味着进程可以相互攻击;
Ÿ 进程使用的同一个文件系统,可以对其他进程的文件进行增删改查;除此之外,进程间的依赖也可能会存在冲突;
Ÿ 使用相同的宿主机资源,存在资源抢占的问题。
容器具有视图隔离、资源可限制、独立文件系统等特点,容器中用到的主要技术是命名空间隔离 Namespace 和控制器组 Cgroup。
二、命名空间隔离( namespace )
1. 什么是命名空间隔离
命名空间是对全局资源的一种抽象,命名空间使得一些进程只能看到自己相关的资源,但是对于命名空间外的其它进程是不可见的。使用命名空间隔离技术的一个例子就是容器。
2. Namespace 类型
Linux 内核实现了 6 种 Namespace:
Ÿ mount:隔离文件系统挂载点
Ÿ Network:隔离网络资源
Ÿ PID:隔离进程 ID
Ÿ UTS:隔离主机名和域名
Ÿ User:隔离用户和用户组
Ÿ IPC:进程间通信隔离
问题:不同的 Pod 之间资源是隔离的,而在同一个 Pod 里,多个容器间哪些资源是共享的?哪些是隔离的呢?
3. Pod 中共享的命名空间
UTS:hostname 和 NIS 域名;IPC:进程间通信。
Yaml 文件示例:
Pod 编排文件,Pod 中创建了 nginx 和 busybox 两个容器:
apiversion:apps/v1
kind: Deployment
metadata:
labels:
app: multi-containers
name: multi-containers
spec:
replicas:1
selector:
matchLabels:
app:multi-containers
template:
metadata:
labels:
app:multi-containers
spec:
containers:
- command:
- sleep
- '36000'
image: 'nginx:1.7.9'
imagePullPolicy: IfNotPresent
name: nginx
- command:
- sleep
- '360000'
image: 'busybox:latest'
imagePullPolicy: Always
name: busybox
a. Pod 中共享 UTS 命名空间
一个 pod 里,有多个 containers,他们之间共享 hostname。
UTS:最简单的 namespace,只作用 hostname 和 NIS 域名两个资源。
示例:
# kubectl get deployments.apps multi-containers
切换到 nginx 的 hostname:
# kubectl exec -it multi-containers-6695d87b75-dsxgn -c nginx -- bash
# hostname
切换到 busybox 的 hostname:
# kubectl exec -it multi-containers-6695d87b75-dsxgn -c busybox -- bash
# hostname
b. Pod 中共享 IPC 命名空间
IPC:进程间通信,只有同一个 namespace 的进程之间才能够通信,常用于MessageQ。
c. Pod 中共享 NET 命名空间
Net:网络相关资源隔离,如网络设备、路由表、防火墙( iptables )、 socket ( ss、netstat )等等。
在排查问题时,经常会出现网络丢包、连接不上、解析不了等各种各样的问题,如何通过抓包找到问题,这个将在后续介绍。
示例:
# netstat -antpl
d. 非共享 USER 命名空间
USER :在不同的 namespace 中用户可以有相同的 UID 和 GID ,它们之间互相不影响。
e. Pod 中非共享 pid 命名空间
PID:隔离进程的 pid 属性,即不同的 namespace 中的进程可以有相同的 pid,相同的 namespace 可以看到其他进程的 pid。
f. Pod 中非共享 mnt 命名空间
MNT:隔离的是 mount points (挂载点) ,即不同 namespace 下面的进程看到的文件系统结构是不同的。不同的 containers 依赖不同的环境,mnt 去共享,会存在冲突。
非共享 MNT 示例:
示例:
# kubectl exec -it multi-containers-6695d87b75-dsxgn -c nginx -- bash
# ls -l
# kubectl exec -it multi-containers-6695d87b75-dsxgn -c busybox -- sh
# ls -l
g. 超好用的 command:lsns
lsns:列出有关所有当前可访问的名称空间或给定名称空间的信息。命名空间标识符是一个索引节点号。
常用参数:
-J 使用 JSON 输出格式
-l 使用列表格式的输出
-n 不打印标题
-r 使用原生输出格式
-u 不截断列中的文本
-t 名字空间类型( mnt, net, ipc, user, pid, uts, cgroup )
示例:
# lsns
# lsns -t net
# lsns -t mnt
# ps -ef |grep tomcat
# ps -ef |grep 1208542
# ps -ef |grep 1208523
# pstree -sp 1208608
# ps -ef |grep 1208523
h. 超好用的 command:nsenter
nsenter:在指定进程的指定命令空间下运行指定程序的命令,它最典型的用途就是进入容器的网络命令空间。
用法:
nsenter [options] <program> [<argument>...]
Run a program with namespaces of other processes.
选项:
-t, --target <pid>
要获取名字空间的目标进程
-m, --mount[=<file>]
enter mount namespace
-u, --uts[=<file>]
enter UTS namespace (hostname etc)
-i, --ipc[=<file>]
enter System V IPC namespace
-n, --net[=<file>]
enter network namespace
-p, --pid[=<file>]
enter pid namespace
-U, --user[=<file>]
enter user namespace
-S, --setuid <uid>
set uid in entered namespace
-G, --setgid <gid>
set gid in entered namespace
--preserve-credentials do not touch uids or gids
-r, --root[=<dir>]
set the root directory
-w, --wd[=<dir>]
set the working directory
-F, --no-fork
执行 <程序> 前不 fork
-Z, --follow-context
set SELinux context according to --target PID
-h, --help
显示此帮助并退出
-V, --version
输出版本信息并退出
命令解析:
演示示例:
# ipconfig eth0
# kubectl get pods multi- containers-6695d87b75-dsxgn -o wide
# docker ps |grep multi
# docker inspect 0683e462045a |grep -i -pid
# lsns -p 905215
# nsenter -n -t 905215
# tcpdump -i any host 223.5.5.5 -nnvv -xxx & [1]1015386
# pkill tcpdump
# lsns -p 905215
# nsenter -p -m -t 905215
# nsenter -p -m -i -u -n -t 905215
# ps -ef