企业级运维之云原生与Kubernetes实战课程
第三章 Kubernetes集群原理深度解析
本章目标
- 理解容器和pod的基本原理以及差异
- 理解pod创建的过程
- 理解各个控制器的作用
- 理解ack集群的网络原理以及coredns的原理
本章目录
- 深入剖析linux容器&Pod
- 集群创建Pod的过程
- 阿里云ACK集群控制器
- 阿里云ACK集群网络
第三章第1讲 深入剖析linux容器&Pod(上)
视频地址:https://developer.aliyun.com/learning/course/913/detail/14532
目录
- 什么是容器
- 资源隔离(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