IPV6网络

今天无意间调通了家里的玩客云armbian系统内docker 运行的几个服务,也包含了armbian系统本身的公网访问,特别记录以下。

这里的意义在于,我使用的是移动的网络,路由器拨号后运营商给的地址非公网IPv4,而是内网地址,无法通过传统的IPv4内网穿透形式配置。

还好运营商内部、运营商之间的核心、接入层面都已经支持IPv6地址,所以我也是首次尝试使用IPv6地址绑定域名,结合lucky软路由实现了内网服务的域名+端口的访问内部多个服务。

IPv6地址分类

为了进一步了解IPv6 ,我又去翻了下中级的“网络工程师第五版”教程,记录下IPv6地址的分类

名称前缀(二级制)前缀(16进制)ip占比类比IPv4
保留0000 00001/256
单播00120-3F1/8公网IP
未分配010-1111 1110 040-FE7F
链路本地单播1111 1110 10FE80::/101/1024169.254.0.0/16
站点本地单播1111 1110 11FEC0::/101/1024私网192.168.0.0/16
组播1111 1111FF00::/81/256224.0.0.0/4
IPv6地址段划分:240e开头是电信,2408开头是联通,2409开头是移动,2001教育,FE80开头是内网地址

访问内网的实现

这里按我的理解,使用了IPv6后,是不需要任何的软路由、nat 、内网穿透,端口映射之类的技术。相当于我们设备有了IPv6单播地址后,接入运营商网络,就构成了一个大的没有围栏的互联网,他们之间都可以直接互访。
当然这里最重要的是保证拨号的光猫开启了IPv6,而且你的终端设备直连光猫。如果有无线路由器串在中间,那也要保证路由器开启了IPv6功能。比如我的小米3c路由器好像不支持。

当然直接使用IPv6地址是很不方便的,甚至浏览器直接输IPv6地址我测试也是不支持的。所以我们就要加一个域名,域名解析指向设备IPv6 。然后就可以通过域名访问设备的各个服务器了。

内网服务器设备参考

如果使用个人 PC来运行各种服务,7*24*365的运行,电费还是一个很大的制约。这几年小盒子的pc也越来越流行,但是动则1000+的rmb ,成本也是一个考量。

我是购买了2个小盒子硬件,玩客云WS1608,某鱼30入的,还有一个是某讯的N1 ,某鱼80.他们的优点是便宜、低功耗(2w),社区文档丰富、硬件刷机固件成熟,功能也基本满足家用服务的需求。

玩客云 晶晨S805 ,armv7架构,1G+8G的配置,会有些应用不支持armv7架构,但是刷个armbian(系统) +casaOS(web界面的应用商店+资源监控) ,

N1 晶晨S905, armv8架构, 2G+8G配置,比玩客云配置高些,可玩性更强

其实我觉得基本用用,玩客云也够了。一般应用推进 alist–网盘神器 ,lucky –内网服务的转发,其他看情况 openwrt .

应用还在进一步探索中。。。

不足

现在IPv6核心网络,各个运营商,云服务商技术上我觉的都已经支持了,但是在终端接入方面,可能有些没有开启。比如说企业的网络内,他们的防火墙、路由交换。

所以我现在只能是手机的4G 或5G网络直接访问我的域名才能连接到我内部服务器。公司网络全部都不行。

openldap

综述

使用openldap的目录功能实现一套账号关联登录多个应用,避免每个系统单独管理各自账号。测试已可实现的应用有grafana(10.2.3有bug,不要用20140116) .openvpn

基本概念

dc 域, uid 用户ID , cn 通用名称(通常 cn或uid可作为第三方系统的登录账号), sn 姓(一般可设置与cn相同) , ou 组织单元(可配置为部门),dn (全路径名称,如 cn=wjy,ou=users,dc=example,dc.org)

对象属性: 最终用户可以是 objectclass: inetOrgPerson , objectclass: posixAccount objectclass: top ,然后加上 cn ,sn , uid(非必须) ,uidnumber, gidnumber, userpassword , homedirectory ,homephone,mail
组用户 :objectclass: posixGroup , objectclass: top , 加上必须的cn , gidnumber , 组成员 memberuid:

搭建

用docker-compose 最简单,少了编译、配置,可以快速部署用于测试使用。当然生产还是要详细了解相关配置项
https://github.com/osixia/docker-openldap/blob/master/example/docker-compose.yml
此模板使用了openldap + phpadmin .可以快速建立web管理界面的ldap

我这里的搭建架构示例如上图。根目录是公司层,cn=java-dev 是组(也是部门),下面uid是用户,readonly是第三方应用接入的只读查询账号,这样可以最小化权限给到第三方

grafana 接入

首先在 grafana.ini 配置文件的

[auth.ldap]
enabled = true

再在ldap.toml中配置

[[servers]]
host = "192.168.0.14"
port = 389
bind_dn = "cn=readonly,dc=ywsco,dc=cn"
bind_password = '***'
search_filter = "(uid=%s)"   #这里也可以用cn
search_base_dns = ["dc=ywsco,dc=cn"]
group_search_filter = "(&(objectClass=posixGroup)(memberUid=%s))"
group_search_base_dns = ["dc=ywsco,dc=cn"]
group_search_filter_user_attribute = "uid"
[servers.attributes]
name = "givenName"
surname = "sn"
username = "uid"
member_of = "memberOf"
email = "mail"
[[servers.group_mappings]]
group_dn = "cn=tech-support,dc=ywsco,dc=cn"
org_role = "Admin"
grafana_admin = true
org_id = 1 
[[servers.group_mappings]]
group_dn = "cn=java-dev,dc=ywsco,dc=cn"
org_role = "Editor"
[[servers.group_mappings]]
group_dn = "*"
org_role = "Viewer"

zabbix监控

zabbix大版本6.4 ,agent直接装agent2,功能更强大。

1、redis监控

用官方template “Redis by Zabbix agent 2″即可监控

无密码redis无需其他配置,主机链接官方模板即可

redis 带密码的情况,需要在被监控redis的agent2配置文件增加如下两行,然后主机添加macros : {$REDIS.CONN.URI} Redis1即可监控

Plugins.Redis.Sessions.Redis1.Uri=tcp://127.0.0.1:6379
Plugins.Redis.Sessions.Redis1.Password=123456

odps表格创建操作

一个语句,创建和源表格式相同并且带字段注释的表格方法:create table [if not exists] <table_name> like <existing_table_name> [lifecycle <days>];

而这个语句create table [if not exists] <table_name> as <select_statement>; 会创建一个新表,但是不会将源表的元数据复制到新表中.元数据包括列名、列类型、列注释、分区等信息。因此,使用这种方式创建的新表只会继承源表的列名和列类型,而不会继承源表的列注释。但是他会把源表所有数据插入新的表格

示例:

CREATE TABLE IF NOT EXISTS table_name LIKE a.table_name;  

create table if not exists table_name as select * from a.table_name;

K8S部署文件的模板化

提前编写通用模板,和初始化python脚本,不同的部署包只需定义相应的变量文件就可以生成部署yaml文件,示例如下:

# 模板文件,保存为deployment.yml.j2
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ name }}
  namespace: {{ namespace }}
spec:
  replicas: {{ replicas }}
  selector:
    matchLabels:
      app: {{ name }}
  template:
    metadata:
      labels:
        app: {{ name }}
    spec:
      containers:
      - name: {{ name }}
        image: {{ image }}
        ports:
        - containerPort: {{ port }}
---
apiVersion: v1
kind: Service
metadata:
  name: {{ name }}-svc
  namespace: {{ namespace }}
spec:
  selector:
    app: {{ name }}
  type: NodePort
  ports:
  - protocol: TCP
    port: {{ port }}


# 配置文件,保存为variables.yml
name: myapp
namespace: default
replicas: 1
image: myapp:latest
port: 8080


# python 脚本createDep.py,最终生成部署文件 deployment_{appname}.yaml
# python2.7 安装yaml包 pip install pyyaml
from jinja2 import Environment, FileSystemLoader
import yaml

env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('deployment.yml.j2')
variables = yaml.safe_load(open('variables.yml'))

output = template.render(variables)
output_file = "deployment_" + variables["name"] + ".yaml"
with open(output_file, 'w') as f:
    f.write(output)

K8S踩坑集锦

1 节点arp缓存满

现象:通过coreDns解析域名,时而解析成功,时而解析超时;系统日志报错如下

arp_cache: neighbor table overflow!

解决办法

调整内核参数,将阈值调高

$ sysctl -a | grep net.ipv4.neigh.default.gc_thresh
net.ipv4.neigh.default.gc_thresh1 = 80000
net.ipv4.neigh.default.gc_thresh2 = 90000
net.ipv4.neigh.default.gc_thresh3 = 100000

注意:如果coreDns没有通过nodeSelector指定coreDns的pod调度到指定标签的节点上,就需要全部节点都要修改上文的内核参数;由于coreDns是非常重要的组件,还是建议通过nodeSelector将coreDns的pod调度到特定机器,并修改特定机器的内核参数,防止其他服务影响。

linux的iptables nat利用

场景说明:

A: 172.45.255.14:3389 要访问的目标windows主机
B: 172.45.255.11 linux代理
C: 172.45.211.22 客户机
B对C的访问没有限制,A和B在同一个网段可以互访,C无法直接访问A的远程桌面

决方案:

##在B上面操作
iptables -t nat -A PREROUTING -p tcp --dport 53388 -j DNAT --to 172.45.255.14:3389
iptables -t nat -A POSTROUTING -p tcp -d 172.45.255.14 --dport 3389 -j SNAT --to 172.45.255.11
sysctl -w net.ipv4.ip_forward=1

结果:

C可以通过B的53388端口访问A的远程桌面

其他扩展:

命令加错删除:

iptables -t nat -L PREROUTING num   #查看nat表中PREROUTING第几条num
iptables -t nat -D PREROUTING num   #删除第几条num

iptables -t nat -L POSTROUTING num   #查看nat表中POSTROUTING第几条num
iptables -t nat -D POSTROUTING num   #删除第几条num

Snat配置:

## X服务器有内外和公网两张网卡,两个IP,以下配置在X机器上面操作
iptables -t nat -I POSTROUTING -s 192.68.10.1/24 -j SNAT --to-source 211.136.11.11
#其中 192.168.10.0/24为内外IP段,211.136.11.11为X的公网IP,
#内网段的服务器需要配置默认路由指向X服务器的内外IP

Nginx的location匹配规则解析

情况1:

proxy_pass  http://IPaddr/    #删除匹配段,一般配置接口使用

访问 http://域名/abc/test.map 分下面两种情况
1)location /abc/
会转发到 http://IPaddr/test.map
2) location /abc
会转发成 http://IPaddr//test.map —————-linux //路径=/路径
所以也等价于 http://IPaddr/test.map 的访问

情况2:

proxy_pass  http://IPaddr    #匹配段和此地址段拼接

这个也分两种情况
1) location /abc
这种可以匹配 /abc 和 /abc/
2)location /abc/
这种只能匹配 /abc/ 匹配目录

容器中的JVM资源该如何被安全的限制

前言

Java与Docker的结合,虽然更好的解决了application的封装问题。但也存在着不兼容,比如Java并不能自动的发现Docker设置的内存限制,CPU限制。

这将导致JVM不能稳定服务业务!容器会杀死你JVM进程,而健康检查又将拉起你的JVM进程,进而导致你监控你的pod一天重启次数甚至能达到几百次。

我们希望当Java进程运行在容器中时,java能够自动识别到容器限制,获取到正确的内存和CPU信息,而不用每次都需要在kubernetes的yaml描述文件中显示的配置完容器,还需要配置JVM参数。

使用JVM MaxRAM参数或者解锁实验特性的JVM参数,升级JDK到10+,我们可以解决这个问题(也许吧~.~)。

首先Docker容器本质是是宿主机上的一个进程,它与宿主机共享一个/proc目录,也就是说我们在容器内看到的/proc/meminfo/proc/cpuinfo
与直接在宿主机上看到的一致,如下。

  • Hostcat /proc/meminfo MemTotal: 197869260 kB MemFree: 3698100 kB MemAvailable: 62230260 kB
  • 容器docker run -it --rm alpine cat /proc/meminfo MemTotal: 197869260 kB MemFree: 3677800 kB MemAvailable: 62210088 kB

那么Java是如何获取到Host的内存信息的呢?没错就是通过/proc/meminfo来获取到的。

默认情况下,JVM的Max Heap Size是系统内存的1/4,假如我们系统是8G,那么JVM将的默认Heap≈2G。

Docker通过CGroups完成的是对内存的限制,而/proc目录是已只读形式挂载到容器中的,由于默认情况下Java
压根就看不见CGroups的限制的内存大小,而默认使用/proc/meminfo中的信息作为内存信息进行启动,
这种不兼容情况会导致,如果容器分配的内存小于JVM的内存,JVM进程会被理解杀死。

内存限制不兼容

我们首先来看一组测试,这里我们采用一台内存为188G的物理机。

#free -g
              total        used        free      shared  buff/cache   available
Mem:            188         122           1           0          64          64

以下的测试中,我们将包含openjdk的hotspot虚拟机,IBM的openj9虚拟机。

以下测试中,我们把正确识别到限制的jdk,称之为安全(即不会超出容器限制不会被kill),反之称之为危险。

测试用例1(OPENJDK)

这一组测试我们使用最新的openjdk8-12,给容器限制内存为4G,看JDK默认参数下的最大堆为多少?看看我们默认参数下多少版本的JDK是安全的

  • 命令如下,如果你也想试试看,可以用一下命令。
   docker run -m 4GB  --rm  openjdk:8-jre-slim java  -XshowSettings:vm  -version
   docker run -m 4GB --rm  openjdk:9-jre-slim java  -XshowSettings:vm  -version
   docker run -m 4GB --rm  openjdk:10-jre-slim java -XshowSettings:vm  -version
   docker run -m 4GB --rm  openjdk:11-jre-slim java -XshowSettings:vm  -version
   docker run -m 4GB --rm  openjdk:12 java -XshowSettings:vm  -version
  • OpenJDK8(并没有识别容器限制,26.67G) 危险
[root@xiaoke-test ~]# docker run -m 4GB --rm  openjdk:8-jre-slim java  -XshowSettings:vm  -version

VM settings:
    Max. Heap Size (Estimated): 26.67G
    Ergonomics Machine Class: server
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-2~deb9u1-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)
  • OpenJDK8 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap (正确的识别容器限制,910.50M)安全
[root@xiaoke-test ~]# docker run -m 4GB --rm  openjdk:8-jre-slim java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XshowSettings:vm  -version
VM settings:
    Max. Heap Size (Estimated): 910.50M
    Ergonomics Machine Class: server
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-2~deb9u1-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)
  • OpenJDK 9(并没有识别容器限制,26.67G)危险
[root@xiaoke-test ~]# docker run -m 4GB --rm  openjdk:9-jre-slim java  -XshowSettings:vm  -version
VM settings:
    Max. Heap Size (Estimated): 29.97G
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "9.0.4"
OpenJDK Runtime Environment (build 9.0.4+12-Debian-4)
OpenJDK 64-Bit Server VM (build 9.0.4+12-Debian-4, mixed mode)
  • OpenJDK 9 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap (正确的识别容器限制,1G)安全
[root@xiaoke-test ~]# docker run -m 4GB --rm  openjdk:9-jre-slim java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XshowSettings:vm  -version
VM settings:
    Max. Heap Size (Estimated): 1.00G
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "9.0.4"
OpenJDK Runtime Environment (build 9.0.4+12-Debian-4)
OpenJDK 64-Bit Server VM (build 9.0.4+12-Debian-4, mixed mode)
  • OpenJDK 10(正确的识别容器限制,1G)安全
[root@xiaoke-test ~]# docker run -m 32GB --rm  openjdk:10-jre-slim java -XshowSettings:vm -XX:MaxRAMFraction=1  -version
VM settings:
    Max. Heap Size (Estimated): 1.00G
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "10.0.2" 2018-07-17
OpenJDK Runtime Environment (build 10.0.2+13-Debian-2)
OpenJDK 64-Bit Server VM (build 10.0.2+13-Debian-2, mixed mode)
  • OpenJDK 11(正确的识别容器限制,1G)安全
[root@xiaoke-test ~]# docker run -m 4GB --rm  openjdk:11-jre-slim java -XshowSettings:vm  -version
VM settings:
    Max. Heap Size (Estimated): 1.00G
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment (build 11.0.1+13-Debian-3)
OpenJDK 64-Bit Server VM (build 11.0.1+13-Debian-3, mixed mode, sharing)
  • OpenJDK 12(正确的识别容器限制,1G)安全
[root@xiaoke-test ~]# docker run -m 4GB --rm  openjdk:12 java -XshowSettings:vm  -version
VM settings:
    Max. Heap Size (Estimated): 1.00G
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "12-ea" 2019-03-19
OpenJDK Runtime Environment (build 12-ea+23)
OpenJDK 64-Bit Server VM (build 12-ea+23, mixed mode, sharing)

测试用例2(IBMOPENJ9)

docker run -m 4GB --rm  adoptopenjdk/openjdk8-openj9:alpine-slim  java -XshowSettings:vm  -version
docker run -m 4GB --rm  adoptopenjdk/openjdk9-openj9:alpine-slim  java -XshowSettings:vm  -version
docker run -m 4GB --rm  adoptopenjdk/openjdk10-openj9:alpine-slim  java -XshowSettings:vm  -version
docker run -m 4GB --rm  adoptopenjdk/openjdk11-openj9:alpine-slim  java -XshowSettings:vm  -version
  • openjdk8-openj9 (正确的识别容器限制,3G)安全
    [root@xiaoke-test ~]# docker run -m 4GB --rm  adoptopenjdk/openjdk8-openj9:alpine-slim  java -XshowSettings:vm  -version
    VM settings:
        Max. Heap Size (Estimated): 3.00G
        Ergonomics Machine Class: server
        Using VM: Eclipse OpenJ9 VM
    
    openjdk version "1.8.0_192"
    OpenJDK Runtime Environment (build 1.8.0_192-b12_openj9)
    Eclipse OpenJ9 VM (build openj9-0.11.0, JRE 1.8.0 Linux amd64-64-Bit Compressed References 20181107_95 (JIT enabled, AOT enabled)
    OpenJ9   - 090ff9dcd
    OMR      - ea548a66
    JCL      - b5a3affe73 based on jdk8u192-b12)
  • openjdk9-openj9 (正确的识别容器限制,3G)安全
    [root@xiaoke-test ~]# docker run -m 4GB --rm  adoptopenjdk/openjdk9-openj9:alpine-slim  java -XshowSettings:vm  -version
    VM settings:
        Max. Heap Size (Estimated): 3.00G
        Using VM: Eclipse OpenJ9 VM
    
    openjdk version "9.0.4-adoptopenjdk"
    OpenJDK Runtime Environment (build 9.0.4-adoptopenjdk+12)
    Eclipse OpenJ9 VM (build openj9-0.9.0, JRE 9 Linux amd64-64-Bit Compressed References 20180814_248 (JIT enabled, AOT enabled)
    OpenJ9   - 24e53631
    OMR      - fad6bf6e
    JCL      - feec4d2ae based on jdk-9.0.4+12)
  • openjdk10-openj9 (正确的识别容器限制,3G)安全
    [root@xiaoke-test ~]# docker run -m 4GB --rm  adoptopenjdk/openjdk10-openj9:alpine-slim  java -XshowSettings:vm  -version
    VM settings:
        Max. Heap Size (Estimated): 3.00G
        Using VM: Eclipse OpenJ9 VM
    
    openjdk version "10.0.2-adoptopenjdk" 2018-07-17
    OpenJDK Runtime Environment (build 10.0.2-adoptopenjdk+13)
    Eclipse OpenJ9 VM (build openj9-0.9.0, JRE 10 Linux amd64-64-Bit Compressed References 20180813_102 (JIT enabled, AOT enabled)
    OpenJ9   - 24e53631
    OMR      - fad6bf6e
    JCL      - 7db90eda56 based on jdk-10.0.2+13)
  • openjdk11-openj9(正确的识别容器限制,3G)安全
    [root@xiaoke-test ~]# docker run -m 4GB --rm  adoptopenjdk/openjdk11-openj9:alpine-slim  java -XshowSettings:vm  -version
    VM settings:
        Max. Heap Size (Estimated): 3.00G
        Using VM: Eclipse OpenJ9 VM
    
    openjdk version "11.0.1" 2018-10-16
    OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.1+13)
    Eclipse OpenJ9 VM AdoptOpenJDK (build openj9-0.11.0, JRE 11 Linux amd64-64-Bit Compressed References 20181020_70 (JIT enabled, AOT enabled)
    OpenJ9   - 090ff9dc
    OMR      - ea548a66
    JCL      - f62696f378 based on jdk-11.0.1+13)

分析

分析之前我们先了解这么一个情况:

JavaMemory (MaxRAM) = 元数据+线程+代码缓存+OffHeap+Heap...

一般我们都只配置Heap即使用-Xmx来指定JVM可使用的最大堆。而JVM默认会使用它获取到的最大内存的1/4作为堆的原因也是如此。

安全性(即不会超过容器限制被容器kill)

OpenJdk

OpenJdk8-12,都能保证这个安全性的特点(8和9需要特殊参数,-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap)。

OpenJ9

IbmOpenJ9所有的版本都能识别到容器限制。

资源利用率

OpenJdk

自动识别到容器限制后,OpenJdk把最大堆设置为了大概容器内存的1/4,对内存的浪费不可谓不大。

当然可以配合另一个JVM参数来配置最大堆。-XX:MaxRAMFraction=int。下面是我整理的一个常见内存设置的表格,
从中我们可以看到似乎JVM默认的最大堆的取值为MaxRAMFraction=4,随着内存的增加,堆的闲置空间越来越大,在16G容器内存时,java堆只有不到4G。

MaxRAMFraction取值堆占比容器内存=1G容器内存=2G容器内存=4G容器内存=8G容器内存=16G
1≈90%910.50M1.78G3.56G7.11G14.22G
2≈50%455.50M910.50M1.78G3.56G7.11G
3≈33%304.00M608.00M1.19G2.37G4.74G
4≈25%228.00M455.50M910.50M1.78G3.56G

OpenJ9

关于OpenJ9的的详细介绍你可以从这里了解更多
对于内存利用率OpenJ9的策略是优于OpenJdk的。以下是OpenJ9的策略表格

容器内存<size>最大Java堆大小
小于1 GB50%<size>
1 GB – 2 GB<size>– 512 MB
大于2 GB大于2 GB

结论

  • 注意:这里我们说的是容器内存限制,和物理机内存不同,

自动档

  • 如果你想要的是,不显示的指定-Xmx,让Java进程自动的发现容器限制。

1.如果你想要的是jvm进程在容器中安全稳定的运行,不被容器kiil,并且你的JDK版本小于10(大于等于JDK10的版本不需要设置,参考前面的测试)
你需要额外设置JVM参数-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap,即可保证你的Java进程不会因为内存问题被容器Kill。
当然这个方式使用起来简单,可靠,缺点也很明显,资源利用率过低(参考前面的表格MaxRAMFraction=4)。

2.如果想在基础上我还想提高一些内存资源利用率,并且容器内存为1 GB – 4 GB,我建议你设置-XX:MaxRAMFraction=2,在大于8G的可以尝试设置-XX:MaxRAMFraction=1(参考上表格)。

手动挡

  • 如果你想要的是手动挡的体验,更加进一步的利用内存资源,那么你可能需要回到手动配置时代-Xmx。
  • 手动挡部分,请可以完全忽略上面我的BB。
    1.上面的我们说到了自动挡的配置,用起来很简单很舒服,自动发现容器限制,无需担心和思考去配置-Xmx。
    2.比如你有内存1G那么我建议你的-Xmx750M,2G建议配置-Xmx1700M,4G建议配置-Xmx3500-3700M,8G建议设置-Xmx7500-7600M,
    总之就是至少保留300M以上的内存留给JVM的其他内存。如果堆特别大,可以预留到1G甚至2G。
    3.手动挡用起来就没有那么舒服了,当然资源利用率相对而言就更高了。

a tiny but valid `init` for containers

tini

Using Tini has several benefits:

  • It protects you from software that accidentally creates zombie processes, which can (over time!) starve your entire system for PIDs (and make it unusable).
  • It ensures that the default signal handlers work for the software you run in your Docker image. For example, with Tini, SIGTERM properly terminates your process even if you didn’t explicitly install a signal handler for it.
  • It does so completely transparently! Docker images that work without Tini will work with Tini without any changes.

In Docker, you will want to use an entrypoint so you don’t have to remember to manually invoke Tini:

# Add Tini
ENV TINI_VERSION v0.19.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
ENTRYPOINT ["/tini", "--"]

# Run your program under Tini
CMD ["/your/program", "-and", "-its", "arguments"]
# or docker run your-image /your/program ...