1.资源隔离相关
大部分的隔离问题都是,容器内默认读取了宿主机的资源所导致的
1.1、容器内指定的核数,不指定将使用主机的cpu核数,会导致影响其他的容器资源,导致gc的时间变长
XX:ParallelGCThreads=8,
1.2、CPU和内存的限制,大量应用跑在容器平台上或者实时发布,如果没有完善的隔离机制,将会对运行态容器生产影响,特别影响客户的感知。
对于JVM的堆计算和GC默认是按照宿主机的资源计算的,需主动指定JVM的对内存大小。
1.在JDK1.7之前可以通过显式指定堆大小实现:-Xmx512m,
可以在打包镜像是动态计算方式JVM的可用堆大小:
#!/bin/bash
limit_in_bytes=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)
if [ "$limit_in_bytes" -ne "9223372036854771712" ]
then
limit_in_megabytes=$(expr $limit_in_bytes \/ 1048576)
heap_size=$(expr $limit_in_megabytes - $RESERVED_MEGABYTES)
export JAVA_OPTS="-Xmx${heap_size}m $JAVA_OPTS "
#ParallelGCThreads = (ncpus < 8 )? 3 : (ncpus *5)/8 +3
export JAVA_OPTS="-XX:ParallelGCThreads数量计算m $JAVA_OPTS "
echo JAVA_OPTS=$JAVA_OPTS
fi
exec catalina.sh run
2.在JDK1.7之后可以通过设置是否对cgroups敏感来处理,通过环境变量处理:-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:ParallelGCThreads
以下是前后的测试结果
设置前 设置后3.JVM GC
影响:
- JVM根据CPU创建ParallelGC数量
- ParallelGCThreads = (ncpus < 8 )? 3 : (ncpus *5)/8 +3
- GC线程数和想限制的数量不一致,影响其他容器
- JVM中GC的Threads数量是调用sysconf获取的,此为宿主机的 数量
解决办法:
显示指定JVM参数,参考第二点
基础镜像使用hack过的glibc
修改kernel ,是容器拿到的数据准确
1.3、Nginx (容器内看到的Nginx worker进程数没有隔离的问题)
在物理机上配置Nginx时通常会将Nginx的worker进程数配置为CPU核心数并且会将每个worker绑定到特定CPU上,这可以有效提升进程的Cache命中率,从而减少内存访问损耗。然后Nginx配置中一般指定worker_processes指令的参数为auto,来自动检测系统的CPU核心数从而启动相应个数的worker进程。在Linux系统上Nginx获取CPU核心数是通过系统调用 sysconf(_SC_NPROCESSORS_ONLN) 来获取的,对于容器来说目前还只是一个轻量级的隔离环境,它并不是一个真正的操作系统,所以容器内也是通过系统调用sysconf(_SC_NPROCESSORS_ONLN)来获取的,这就导致在容器内,使用Nginx如果worker_processes配置为auto,看到的也是宿主机的CPU核心数。
解决的方式是:劫持系统调用sysconf,在类Unix系统上可以通过LD_PRELOAD这种机制预先加载个人编写的的动态链接库,在动态链接库中劫持系统调用sysconf并根据cgroup信息动态计算出可用的CPU核心数。
1.4、容器中的乱码
遇到docker的中文乱码问题有两处
- vi打开文件发现中文乱码,修改
cat << EOF > /root/.vimrc
:set encoding=utf-8
:set fileencodings=ucs-bom,utf-8,cp936
:set fileencoding=gb2312
:set termencoding=utf-8
EOF
- 导入数据库发现中文乱码修改修改数据库文件,指定编码格式为中文编码
echo "set names utf8;" >> abc.sql
3.修改系统为中文编码
echo "export.UTF-8" >> /etc/profilesource /etc/profile
4.必要时重新打镜像、
5.安装 en_US.UTF-8 并配置环境
RUN locale-gen en_US.UTF-8 ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
locale-gen一般用于ubuntu,localedef一般用于centos。
yum remove glibc-common -y
yum install glibc-common -y
localedef -v -c -i en_US -f UTF-8 en_US.UTF-8
localelocale -a
也就是说,docker的镜像都是阉割版,很多功能都被删除阉割了。
localedef是绑定在 glibc-common 中的,阉割版的镜像中是没有这个命令的,我们需要重新安装glibc-common,首先卸载glibc-common,然后重新安装glibc-common,最后下载自己需要的语言包。
localedef -v -c -i en_US.UTF-8为了使得镜像以后不再出现此坑,要制作镜像的时候指定环境变量
vim /root/cjm/flume/Dockerfile
ROM flume_v1.0
MAINTAINER by cgls
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
CMD ["/root/start.sh"]
docker build -t flume_v2.0 /root/cjm/flume/.
2.数据库的容器化
2.1、数据不安全
即使你要把 Docker 数据放在主机来存储 ,它依然不能保证不丢数据。 Docker volumes 的设计围绕 Union FS 镜像层提供持久存储,但它仍然缺乏保证。
使用当前的存储驱动程序,Docker 仍然存在不可靠的风险。 如果容器崩溃并数据库未正确关闭,则可能会损坏数据。
2.2、运行数据库的环境需求
数据库对IO的要求很高,需要有专门的环境,尽量不和其他的混用。
网络层面,容器的网络是在宿主机上有包了一层,就吞吐量上肯定是效率会下降。
隔离越多系统开销越大
3.容器内使用root权限privileged=true
缺点:容器能够看到所在服务器上所有容器的磁盘,导致了安全问题和性能问题
不使用的弊端:很多调用系统给的导致一些系统调用失败。可以默认给容器额外增加了sys_ptrace和sys_admin两个权限,让容器可以运行GDB和更改主机名。如果有特例容器需要更多的权限,可以在我们的平台上按服务粒度进行配置
Linux有两种IO:Direct IO和Buffered IO。Direct IO直接写磁盘,Duffered IO会先写到缓存再写磁盘,大部分场景下都是Buffered IO。
网友评论