docker

k8s中的command和docker的entrypoint区别

Docker Entrypoint & Cmd
先回顾下CMD指令的含义,CMD指令可以指定容器启动时要执行的命令,但它可以被docker run命令的参数覆盖掉。

ENTRYPOINT 指令和CMD类似,它也可用户指定容器启动时要执行的命令,但如果dockerfile中也有CMD指令,CMD中的参数会被附加到ENTRYPOINT 指令的后面。 如果这时docker run命令带了参数,这个参数会覆盖掉CMD指令的参数,并也会附加到ENTRYPOINT 指令的后面。这样当容器启动后,会执行ENTRYPOINT 指令的参数部分。

可以看出,相对来说ENTRYPOINT指令优先级更高。我们来看个例子,下面是Dockerfile的内容:

### test
FROM ubuntu
MAINTAINER hello
RUN echo hello1 > test1.txt
RUN echo hello2 > /test2.txt
EXPOSE 80
ENTRYPOINT [“echo”]
CMD [“defaultvalue”]

假设通过该Dockerfile构建的镜像名为 myimage。

当运行 docker run myimage 输出的内容是 defaultvalue,可以看出CMD指令的参数得确是被添加到ENTRYPOINT指令的后面,然后被执行。
当运行docker run myimage hello world 输出的内容是 hello world ,可以看出docker run命令的参数得确是被添加到ENTRYPOINT指令的后面,然后被执行,这时CMD指令被覆盖了。
另外我们可以在docker run命令中通过 –entrypoint 覆盖dockerfile文件中的ENTRYPOINT设置,如:
docker run –entrypoint=”echo” myimage good 结果输出good
注意,不管是哪种方式,创建容器后,通过 docker ps –no-trunc查看容器信息时,COMMAND列会显示最终生效的启动命令。

此外,很多的数据库软件的docker镜像,一般在entrypoint的位置会设置一个docker-entrypoint.sh文件,此文件位于/usr/local/bin位置,用于在容器初次启动的时候进行数据库的初始化操作。
Kubernetes Command & args
下表总结了Docker和Kubernetes使用的字段名称:

当你覆盖默认的Entrypoint和Cmd时,将应用以下规则:

如果不为容器提供command或args参数,则使用Docker镜像中定义的默认值。
如果提供command但没有提供args参数,则仅使用提供的command。Docker镜像中定义的默认EntryPoint和默认Cmd将被忽略。
如果仅为容器提供args,则Docker镜像中定义的默认Entrypoint将与您提供的args一起运行。
如果提供command和args,则将忽略Docker镜像中定义的默认Entrypoint和默认Cmd。 您的command与 args一起运行。
可以看到,k8s利用了Dockerfile的覆盖机制,使用command和args参数有选择性的覆盖了Docker镜像中的Entrypoint和Cmd启动参数,下面是一些例子:

 

使用command和args的例子:

apiVersion: v1
kind: Pod
metadata:
name: command-demo
labels:
purpose: demonstrate-command
spec:
containers:
– name: command-demo-container
image: debian
command: [“printenv”]
args: [“HOSTNAME”, “KUBERNETES_PORT”]
restartPolicy: OnFailure
参考资料:
https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/

修改Docker默认的网段

背景

一同事在研究他的安全大业,需要在AWS服务器上部署他的秘密武器,秘密武器通过Docker来部署;在部署前可以通过跳板机的内外网ssh登录上这台服务器;部署后只能通过外网ssh登录这台服务器…….;症状就是这么个症状,怎么下药就得看医术了…..

排查心里路程

1、部署秘密武器之前,可以内外网;部署后,只能外网,看这么个症状就是网络防火墙问题,于是乎~~~
     1)iptables -F
     2)setenforce 0
     3)在AWS上把此服务器的安全组入站0.0.0.0(这纯粹是为了测试,正式环境千万别~~~)
2、这ssh不通难道是ssh的配置文件修改了,因为改了端口,难道ssh的配置文件里有控制内外网是否可以登录的配置?于是乎~~~
      vim /etc/ssh/sshd_config   一顿瞎改(这里就体现了对ssh的认识不足,对配置文件不熟悉,得学习)
3、这什么玩意儿,网络是可以的,安全组没问题,不知为什么脑袋里面想到了路由,route -n 先看看,哇~~噢,这么多条路由,看到这些路由的时候,其中有一条172.29.0.0(我们跳板机的网段跟这个很像),就隐隐约约觉得这里有问题(女人的直觉不只在判断男朋友是否在外面有狗,还爱不爱上;在这里直觉也还是挺准,哈哈);于是乎~~~
     route -n
     route del -net 172.22.32.0 netmask 255.255.255.0
     route del -net 172.23.32.0 netmask 255.255.255.0
     ……
     只要是与容器有关的路由全部干掉,然后再从跳板机去内网ssh登录,哇~~~哇~~~可以了耶,好激动好激动噢~~~~
4、确定了,就是那一条路由的问题,这个容器分配的网段与跳板机的网段冲突了,于是乎~~~~
     route add -net 172.22.32.0 netmask 255.255.255.0
     ……
     把刚刚删了的路由除了那一条冲突的,又傻不拉几的加上,接下来就是解决这个问题的时候了

当时的解决办法

想了想,既然冲突了,那我肯定就是把这个容器的网段给改了,怎么改呢,用了一个及其愚蠢的办法,我把这个容器停掉删除,重新用docker-compose重启启动了一个,就重新分配了一个新的网段,就不冲突了。

根本解决办法

在启动容器之前就把整个docker的网络改为与我们自己的网段不冲突的,这样docker永远只分配我们给他设置的
操作步骤:修改docker.json,使得整个docker的网络网段都改掉,原来是172网段,现在我要改为192
1)vim /etc/docker/daemon.json(这里没有这个文件的话,自行创建)
{
    "bip":"192.168.0.1/24"
}

 

2)重启docker
systemctl restart docker

 

3)在重新看网段
注:在使用docker容器最初规划的时候就要想到这一点,要规划好使用什么样的网段;上面的这种办法得重启docker,重启容器的;

疑问

有其他更好的办法呢,在不停止容器不删除容器的前提下,修改网段?(待我研究好了,再来补充)

总结

1:对ssh的配置文件不熟悉(这个得找个时间系统的过一遍)
2:对网络这块熟悉,尤其是路由这些,说实在的,到现在还是说不出路由的具体作用,只可意会的那种,只知道没他不行(等这段时间把PMP考完了,开始看思科那几本书,不说考证,先把那几本书好好看看,加强网络)
3:对Docker网络模式不熟悉(接下来这段时间好好看Dokcer网络部分的官方文档)
下次再见~~~

Docker之/etc/profile不生效得问题

配置案例

export JAVA_HOME=/usr/local/jdk/
export JRE_HOME=/usr/local/jdk/jre
export CLASSPATH=.:$CLASSPATH:$JAVA_HOME/lib:$JRE_HOME/lib
export M2_HOME=/usr/local/maven
export MYSQL_HOME=/usr/local/mysql

export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin:$M2_HOME/bin:$MYSQL_HOME/bin

 

可以将环境变量放到 /root/.bashrc 这个里面,下次启动容器也生效

localedef增加中文支持

#查看语言支持列表
localedef --list-archive
#精简locale
cd /usr/lib/locale/
mv locale-archive locale-archive.old
localedef -i en_US -f UTF-8 en_US.UTF-8
# 添加中文支持(可选)
localedef -i zh_CN -f UTF-8 zh_CN.UTF-8
localedef -i zh_CN -f GB2312 zh_CN
localedef -i zh_CN -f GB2312 zh_CN.GB2312
localedef -i zh_CN -f GBK zh_CN.GBK
#下面这些也是可选的,可以丰富中文支持(香港/台湾/新加坡)
localedef -f UTF-8 -i zh_HK zh_HK.UTF-8
localedef -f UTF-8 -i zh_TW zh_TW.UTF-8
localedef -f UTF-8 -i zh_SG zh_SG.UTF-8

CentOS docker镜像支持中文

通过docker pull centos获取的docker镜像不支持中文,需要通过docker exec -it 容器id /bin/sh方式注入到docker容器内:

执行如下操作:

yum -y install kde-l10n-Chinese telnet && \
yum -y reinstall glibc-common &&\
yum clean all && \
localedef -c -f UTF-8 -i zh_CN zh_CN.utf8

此时,如果执行locale

[root@f8be61cc6c81 /]# locale
LANG=
LC_CTYPE=”POSIX”
LC_NUMERIC=”POSIX”
LC_TIME=”POSIX”
LC_COLLATE=”POSIX”
LC_MONETARY=”POSIX”
LC_MESSAGES=”POSIX”
LC_PAPER=”POSIX”
LC_NAME=”POSIX”
LC_ADDRESS=”POSIX”
LC_TELEPHONE=”POSIX”
LC_MEASUREMENT=”POSIX”
LC_IDENTIFICATION=”POSIX”
LC_ALL=

说明中文字符还没启用,此时再执行:

export LC_ALL=”zh_CN.UTF-8″

再次执行locale显示:

[root@f8be61cc6c81 /]# locale
LANG=
LC_CTYPE=”zh_CN.UTF-8″
LC_NUMERIC=”zh_CN.UTF-8″
LC_TIME=”zh_CN.UTF-8″
LC_COLLATE=”zh_CN.UTF-8″
LC_MONETARY=”zh_CN.UTF-8″
LC_MESSAGES=”zh_CN.UTF-8″
LC_PAPER=”zh_CN.UTF-8″
LC_NAME=”zh_CN.UTF-8″
LC_ADDRESS=”zh_CN.UTF-8″
LC_TELEPHONE=”zh_CN.UTF-8″
LC_MEASUREMENT=”zh_CN.UTF-8″
LC_IDENTIFICATION=”zh_CN.UTF-8″
LC_ALL=zh_CN.UTF-8

如果需要一劳永逸的解决问题,可以将

export LC_ALL=”zh_CN.UTF-8″

写入/etc/profile文件中,执行source /etc/profile
————————————————
版权声明:本文为CSDN博主「vah101」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/vah101/article/details/86744740

Centos添加环境变量(~/.bash_profile、/etc/profile、/etc/profile.d)

环境变量

bash shell用一个叫做环境变量的特性来存储有关shell会话和工作环境的信息。即允许在内存中存储数据,使得在程序或shell中运行的脚本能够访问到它们。

Linux中环境变量分为三种:

全局环境变量:对于shell会话和所有生成的子shell都是可见的
局部环境变量:只对创建它的shell可见,即当前创建的用户可见
用户定义变量:只对当前会话生效

创建全局环境变量

在/etc/profile文件中创建全局环境变量
/etc/profile文件:
**当一个用户登录Linux系统或使用su -命令切换到另一个用户时,也就是Login shell 启动时,首先要确保执行的启动脚本就是 /etc/profile 。**只有Login shell 启动时才会运行 /etc/profile 这个脚本,而Non-login shell 不会调用这个脚本。
一些重要的变量就是在这个脚本文件中设置的,含义如下:

PATH: 预设可执行文件或命令的搜索路径。
USER: 用户登录时使用的用户名。
LOGNAME: 其值为$USER。
HOSTNAME: 所使用的主机名。
MAIL: 存放用户电子邮件的邮箱(实际上是一个ASCII码文件)。
HISTSIZE: 历史记录的行数。
INPUTRC: 存放的是针对键盘热键的信息(也是一个ASCII码文件)。

打开/etc/profile文件,PATH=$PATH:/usr/local/php/sapi/fpm就是定义了一个全局变量

PATH=$PATH:/usr/local/php/sapi/fpm
PATH=$PATH:/usr/local/openresty/nginx/sbin
PATH=$PATH:/usr/local/php/bin
PATH=$PATH:/usr/local/mysql/bin:/usr/local/mysql/lib
#PATH=$PATH:/usr/local/apache24/bin/
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL

1
2
3
4
5
6

执行source /etc/profile后生效
创建局部环境变量

打开 ~/.bash_profile文件添加PATH:

# User specific environment and startup programs

PATH=$PATH:$HOME/bin
PATH=$PATH:/usr/local/apache24/bin

export PATH
#也可以通过这种方式给环境变量起别名
alias nginx2=/usr/local/nginx/sbin/nginx

1
2
3
4
5
6
7
8

执行source ~/.bash_profile后生效
创建用户定义变量

export PATH=$PATH:/usr/local/apache24/bin

1

/etc/profile文件和/etc/profile.d目录的区别

/etc/profile文件中存放的变量上面已经做过说明。

在/etc/profile.d 目录中存放的是一些应用程序所需的启动脚本,其中包括了颜色、语言、less、vim及which等命令的一些附加设置。
这些脚本文件之所以能够 被自动执行,是因为在/etc/profile 中使用一个for循环语句来调用这些脚本。而这些脚本文件是用来设置一些变量和运行一些初始化过程的。
在/etc/profile.d目录下创建全局变量

在/etc/profile.d目录下创建的变量也是全局变量,方法如下:

vim /etc/profile.d/httpd.sh

APACHE_HOME=/usr/local/apache24
PATH=$APACHE_HOME/bin:$PATH
export APACHE_HOME PATH

1
2
3
4
5

重新打开shell后生效

查看pod启动失败原因

Focusing specifically on the example showed in the question.

The setup is following:

  • 1 GKE node with: 1 vCPU and 3.75 GB of RAM

The resources scheduled onto this single node cluster:

  • 4 Deployments where each have following fields:
        resources:
          requests: # <-- IMPORTANT
            cpu: "100m" # <-- IMPORTANT
            memory: "128Mi"
          limits:
            cpu: "100m"
            memory: "128Mi"

For an example I tried to replicate setup as close as possible to the one in the question:

  • $ kubectl get pods
NAME                           READY   STATUS    RESTARTS   AGE
nginx-four-99d88fccb-v664b     0/1     Pending   0          51m
nginx-one-8584c66446-rcw4p     1/1     Running   0          53m
nginx-three-5bcb988986-jp22f   1/1     Running   0          51m
nginx-two-6c9545d7d4-mrpw6     1/1     Running   0          52m

As you can see there is a Pod that is in Pending state. Further investigation implies:

  • $ kubectl describe pod/nginx-four-99d88fccb-v664b

A lot of information will show about the Pod but the part that needs to be checked is Events:

Events:
  Type     Reason            Age                From               Message
  ----     ------            ----               ----               -------
  Warning  FailedScheduling  56m (x2 over 56m)  default-scheduler  0/1 nodes are available: 1 Insufficient cpu.
  Normal   Scheduled         56m                default-scheduler  Successfully assigned default/nginx-two-6c9545d7d4-mrpw6 to gke-gke-old-default-pool-641f10b7-36qb
  Normal   Pulling           56m                kubelet            Pulling image "nginx"
  Normal   Pulled            56m                kubelet            Successfully pulled image "nginx"
  Normal   Created           56m                kubelet            Created container nginx
  Normal   Started           56m                kubelet            Started container nginx

As you can see from above output:

  • FailedScheduling: ... 0/1 nodes are available: 1 Insufficient cpu

As posted in the question:

I keep getting not having enough cpu availability even the node is using only 9% cpu at the same time.

docker容器定时自动重启

群晖下我使用的人人影视的镜像是 auska/docker-rrshareweb 和LEDE下用的一样

但有个bug,我也不知道怎么回事。运行该镜像1~2天后,CPU占用率奇高,重启才能恢复。

于是就想着每天凌晨2点重启一次人人影视的容器,解决其CPU占用高的问题。

以下方法同样适用于LEDE,而且LEDE的定时任务(crontab)在WEB端很好管理,就不再啰嗦。

切换到root

登录SSH,输入

sudo -i

输入群晖密码即可切换到root身份

获取容器ID(CONTAINER ID)

docker ps -a

如上图所示,83cbcb1a5766 即为人人影视的容器ID,重启该容器命令则为

注:容器ID均不一样,不要复制下面的,请按步骤自行获取

docker restart 83cbcb1a5766

添加定时任务

两种方法

1.WEB端

按下图顺序,添加一个定时任务,每6个小时执行重启,添加完保存即可生效

2.直接编辑crontab

群晖下并不能像其他Linux系统一样,直接使用 crontab -e 来管理定时任务

不过可以使用shell下的vi\vim编辑工具来编辑管理定时任务,

群晖的crontab格式为:

minute hour mday month wday who command

所以每天凌晨2点执行重启人人docker容器的crontab规则为

0 2 * * * root docker restart 83cbcb1a5766

vi/vim的使用方法不再啰嗦

vim /etc/crontab

也可以使用WinSCP软件直接编辑该文件

使定时任务生效

将群晖的crontab服务重启一下就可以了

synoservice -restart crond

Docker容器无法被stop or kill问题

问题过程

某环境一个mysql容器无法被stop or kill or rm

sudo docker ps | grep mysql 查看该容器

7844250860f8 mysql:5.7.22   "/.r/r docker-entr..."   41 minutes ago   Up 8 minutes   r-dlrel-mysql-1-66df8f33

使用docker stop / docker kill / docker rm -f 等命令处理后,容器立马自动重启

立即查看容器,运行时间为:Up Less than a second,说明容器立马启动了

7844250860f8  mysql:5.7.22   "/.r/r docker-entr..."   42 minutes ago  Up Less than a second   r-dlrel-mysql-1-66df8f33

kill该容器对应的物理进程,依然自动重启

获取物理进程方式:1.docker inspect中的 State.Pid字段为物理进程ID; 2.ps 命令

查看容器restart policy,策略为no,即不会自动重启

如果需要更新运行中容器的restart策略,可以使用该命令:docker update –restart=no my-container

"RestartPolicy": {
    "Name": "no",
    "MaximumRetryCount": 0
},

程序员之间神奇的问题解决方式

你是否出现过这种场景:

  • 百思不得其解的问题,当走到同事面前,刚把问题说清楚,自己就恍然大悟了
  • 问题明明很简单,但程序运行就是出问题,然后找个同事帮忙检查下基础配置,自己又顿悟了。

这次我属于第一种,刚把问题说完,立马想起:擦,是容器编排工具Rancher在做调度,容器挂了之后会自动重启

登录rancher一看,果然如此,”乌龙”问题。虽这次不是问题,但Docker确实有无法stop的问题,资料也很多。

拓展阅读: Docker Restart Policy

解决过程中了解了很多Docker Restart Policy知识和Bug,这篇文章写的简单易懂:Ensuring Containers Are Always Running with Docker’s Restart Policy

这里仅做下记录,学习下Docker的四种Restart Policy。

no

no是默认策略,在任何情况下都不会restart容器

on-failure

on-failure表示如果容器 exit code异常时将restart,如果容器exit code正常将不做任何处理。

sudo docker run -d --name testing_restarts --restart on-failure:5 testing_restarts
85ff2f096bac9965a9b8cffbb73c1642bf7b64a2173bbd145961231861b95819

on-failure:max-retries,max-retries表示最大重启次数。

on-failure的好处是:如果容器以正常exit code终止,将不会 restart

always

无论容器exit code是什么,都会自动restart。列举几个场景:

  • 容器以非正常状态码终止(如应用内存不足导致终止)
  • 容器被正常 stopped,然后机器重启或Docker服务重启
  • 容器在宕机在正常运行,然后重启机器或Docker服务重启

以上情况always侧露都会restart容器,但是如果是 on-failure和no策略,机器被重启之后容器将无法restart。

###unless-stopped

unless-stoppedalways 基本一样,只有一个场景 unless-stopped有点特殊:

如果容器正常stopped,然后机器重启或docker服务重启,这种情况下容器将不会被restart