dockerfile指令

1.FROM

1
2
#指定所创建镜像的基础镜像,如果本地不存在,则默认去镜像仓库下载指定镜像  
FROM <image>:<tag>

2.MAINTAINER

1
2
#指定维护者信息  
MAINTAINER [xxx@xxx.com](mailto:xxx@xxx.com)

3.RUN

1
2
3
4
#镜像制作过程中,在可写层执行指定命令  
RUN <command>
#默认在 shell 终端中运行命令,即 /bin/sh -c;
#RUN ["executable","param1","param2"] 会被解析成Json数组,因此必须要用"",可指定使用其他终端类型,如 RUN ["/bin/bash","-c","echo helloworld"]

4.CMD

1
2
3
4
5
6
7
#指定启动容器时默认执行的命令,一般用于执行服务启动脚本。每个 Dockerfile 只能有一条 CMD 指令,如果指定了多条,只有最后一条会生效,并且 docker run 接的命令会覆盖掉 CMD 指令的内容。支持三种格式:  
CMD ["executable","param1","param2"]
#使用 exec 执行
CMD command param1 param2
#在 /bin/sh 中执行,提供给需要交互的应用
CMD ["param1","param2"]
#提供给 ENTRYPOINT 的默认参数

docker常用容器管理命令

1.创建容器

1
2
3
4
5
6
7
docker create [OPTIONS] CONTAINER_NAME[:TAG]

options:

-t #将容器的标准输出绑定到一个伪终端

-i #交互

2.启动容器

1
docker start CONTAINER_ID

3.运行容器(相当于docker create + docker start)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
docker run [OPTIONS] NAME[:TAG]

options:

-d #在后台运行容器

-t #将容器的标准输出绑定到一个伪终端

-i #交互

-c,--cpu-shares [=0] #调整容器使用 CPU 的权重

-m,--memory [=MEMORY] #调整容器使用 Memory 的大小

#执行 docker run,Docker 服务端在后台运行的操作如下:

#1.检查本地是否存在指定的镜像,不存在就从公有仓库下载;

#2.利用镜像创建并启动一个容器;

#3.分配一个文件系统,并在只读的镜像层外面挂在一层可读层;

#4.从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中;

#5.从地址池配置一个IP地址给容器;

#6.执行用户指定的应用程序;

#7.执行完毕后容器被终止。

prometheus监控k8s集群

1.整体概述

本文主要讲述如何使用prometheus,结合kube-state-metrics,cAdvisor,Grafana对k8s集群进行监控和报警,和监控大盘的整体展示。

2.环境描述

  • Kubernetes:v1.12.5
  • Prometheus:v2.3.1
  • kube-state-metrics:v1.3.1(收集k8s集群内资源对象数据)
  • cAdvisor(已经在k8s内部集成,不需要重新安装,收集资源使用情况)
  • Grafana:v5.3.4

3.监控组件部署

3.1 kube-state-metrics部署

kube-state-metrics安装有以下配置文件,可以把kube-state-metrics-deployment.yaml里面的镜像路径改成内网的镜像路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#把配置文件都放在kube-state-metrics,执行这个命令即可部署
kubectl -f kube-state-metrics/
#kube-state-metrics目录里面的配置信息
kube-state-metrics
├── kube-state-metrics-cluster-role-binding.yaml
├── kube-state-metrics-cluster-role.yaml
├── kube-state-metrics-deployment.yaml
├── kube-state-metrics-role-binding.yaml
├── kube-state-metrics-role.yaml
├── kube-state-metrics-service-account.yaml
└── kube-state-metrics-service.yaml

#查看kube-state-metrics是否已经起来
kubectl get pod -n kube-system -o wide |grep "kube-state-metrics"
#如果启动部署成功,信息如下:
kube-state-metrics-7fd5dcc9b6-kpxmm 2/2 Running 4 526d 10.244.3.39 wx-2-centos53 <none>

k8s 1.13.4升级到1.14.6

1.镜像准备

镜像准备(注意,提前在所有节点都下载好镜像,不然coredns kube-proxy 这些pod会自动安装安装不上 )

master节点粘贴下面脚本,下载镜像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
registry_host=reg.qingye.info
version=v1.14.6
pause_version=3.1
etcd_version=3.3.10
coredns_version=1.3.1
#镜像下载
docker pull $registry_host/library/kube-apiserver:$version
docker pull $registry_host/library/kube-controller-manager:$version
docker pull $registry_host/library/kube-scheduler:$version
docker pull $registry_host/library/kube-proxy:$version
docker pull $registry_host/library/pause:$pause_version
docker pull $registry_host/library/etcd:$etcd_version
docker pull $registry_host/library/coredns:$coredns_version
#镜像打tag
docker tag $registry_host/library/kube-apiserver:$version k8s.gcr.io/kube-apiserver:$version
docker tag $registry_host/library/kube-controller-manager:$version k8s.gcr.io/kube-controller-manager:$version
docker tag $registry_host/library/kube-scheduler:$version k8s.gcr.io/kube-scheduler:$version
docker tag $registry_host/library/kube-proxy:$version k8s.gcr.io/kube-proxy:$version
docker tag $registry_host/library/pause:$pause_version k8s.gcr.io/pause:$pause_version
docker tag $registry_host/library/etcd:$etcd_version k8s.gcr.io/etcd:$etcd_version
docker tag $registry_host/library/coredns:$coredns_version k8s.gcr.io/coredns:$coredns_version

node节点粘贴下面脚本,下载镜像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
registry_host=reg.qingye.info
version=v1.14.6
pause_version=3.1
etcd_version=3.3.10
coredns_version=1.3.1
#镜像下载
docker pull $registry_host/library/kube-proxy:$version
docker pull $registry_host/library/pause:$pause_version
docker pull $registry_host/library/etcd:$etcd_version
docker pull $registry_host/library/coredns:$coredns_version
#镜像打tag
docker tag $registry_host/library/kube-proxy:$version k8s.gcr.io/kube-proxy:$version
docker tag $registry_host/library/pause:$pause_version k8s.gcr.io/pause:$pause_version
docker tag $registry_host/library/etcd:$etcd_version k8s.gcr.io/etcd:$etcd_version
docker tag $registry_host/library/coredns:$coredns_version k8s.gcr.io/coredns:$coredns_version

利用LXCFS提升容器资源可见性

由于默认情况下容器挂载的是宿主机的硬件配置信息,导致有些应用根据这些信息来决定启动内存等的大小,导致应用内存溢出等问题。

LXCFS简介

社区中常见的做法是利用 lxcfs来提供容器中的资源可见性。lxcfs 是一个开源的FUSE(用户态文件系统)实现来支持LXC容器,它也可以支持Docker容器。

LXCFS通过用户态文件系统,在容器中提供下列 procfs 的文件。

1
2
3
4
5
6
/proc/cpuinfo
/proc/diskstats
/proc/meminfo
/proc/stat
/proc/swaps
/proc/uptime

LXCFS的示意图如下:

LXCFS的示意图

比如,把宿主机的 /var/lib/lxcfs/proc/memoinfo 文件挂载到Docker容器的/proc/meminfo位置后。容器中进程读取相应文件内容时,LXCFS的FUSE实现会从容器对应的Cgroup中读取正确的内存限制。从而使得应用获得正确的资源约束设定。

安装lxcfs ,先安装需要使用的依赖包:

yum install http://mirror.centos.org/centos/7/os/x86_64/Packages/fuse-libs-2.9.2-10.el7.x86_64.rpm

用deamonset方式在每个节点启动一个lxcfs,lxcfs-daemonset.yaml配置如下:

nginx-ingress-controller部署

1.打标签

由于nginx要部署到指定节点上,所以需要对node打个label,通过nodeSelector调度到节点上,同时要确保部署节点主机的80、443、18080、10254端口没有被占用。
kubectl label node ss-1-centos221 nginx-ingress=nginx
kubectl label node ss-1-centos221-2 nginx-ingress=nginx

2.准备nginx-ingress-controller部署文件

2.1 nginx-ingress-controller-rbac.yaml :设置rabc权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-ingress-serviceaccount
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- "extensions"
resources:
- ingresses/status
verbs:
- update
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: nginx-ingress-role
namespace: kube-system
rules:
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
# Defaults to "<election-id>-<ingress-class>"
# Here: "<ingress-controller-leader>-<nginx>"
# This has to be adapted if you change either parameter
# when launching the nginx-ingress-controller.
- "ingress-controller-leader-nginx"
verbs:
- get
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: nginx-ingress-role-nisa-binding
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: nginx-ingress-role
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: nginx-ingress-clusterrole-nisa-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nginx-ingress-clusterrole
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: kube-system

k8s+dubbo架构集群内外网络通讯解决方案

1.问题

k8s有自己的一套网络管理机制,集群内的容器和容器之间是可以相互通信的。

但是在容器化升级改造的过程中,不可能一步到位的将所有的服务全部迁移到k8s的容器当中来,毕竟新的技术在没有经过实践趟坑时,肯定不能轻易的全面铺开升级。

那么就涉及到集群外的服务访问集群内的服务,集群内容器中的ip都是k8s管理的IP,dubbo服务注册的也是获取的容器内分配的IP。

比如宿主机ip是10.201.7.xx,容器内的ip就是172.66.4.x。群外的和宿主主机同网段的服务通过拿到dubbo的注册的172.66.4.x也根本没法访问容器内的dubbo服务。

2.分析

k8s是通过Service来暴露集群内的服务,假如dubbo服务注册的是Service暴露的端口和宿主的IP那么集群外的服务就可以直接访问集群内容器中的服务了。

该方案主要有两个难点:

1.如何获取Service暴露的端口和宿主机的IP注入到POD环境变量;

2.Dubbo服务如何从环境变量获取IP和端口注册到ZK;

关于难点1:

通过downward-api的方式向Pod内注入NodeIP的env;

通过给Pod注入env的方式将NodePort注入到Pod内;(要求先创建Service)

关于难点2:

Dubbo在启动阶段提供两对系统属性,用于设置外部通信的IP和端口地址。

DUBBO_IP_TO_REGISTRY — 注册到注册中心的IP地址
DUBBO_PORT_TO_REGISTRY — 注册到注册中心的端口
DUBBO_IP_TO_BIND — 监听IP地址
DUBBO_PORT_TO_BIND — 监听端口

深刻理解Docker镜像大小

1.docker镜像分析

是否还记得第一个接触Docker的时候,你从Docker Hub下拉的那个镜像呢?在那个处女镜像的基础上,你运行了容器生涯的处女容器。镜像的基石作用已经很明显,在Docker的世界里,可以说是:No Image,No Container。

再进一步思考Docker镜像,大家可能很快就会联想到以下几类镜像:

1.系统级镜像:如Ubuntu镜像,CentOS镜像以及Debian容器等;

2.工具栈镜像:如Golang镜像,Flask镜像,Tomcat镜像等;

3.服务级镜像:如MySQL镜像,MongoDB镜像,RabbitMQ镜像等;

4.应用级镜像:如WordPress镜像,DockerRegistry镜像等。

镜像林林总总,想要运行Docker容器,必须要有Docker镜像;想要有Docker镜像,必须要先下载Docker镜像;既然涉及到下载Docker镜像,自然会存在Docker镜像存储。谈到Docker镜像存储,那我们首先来聊聊Docker镜像大小方面的知识。

以下将从三个角度来分析Docker镜像的大小问题:Dockerfile与镜像、联合文件系统以及镜像共享关系。

Dockerfile与镜像
Dockerfile由多条指令构成,随着深入研究Dockerfile与镜像的关系,很快大家就会发现,Dockerfile中的每一条指令都会对应于Docker镜像中的一层。

继续以如下Dockerfile为例:

1
2
3
4
FROM ubuntu:14.04
ADD run.sh /
VOLUME /data
CMD ["./run.sh"]

k8s常见问题解决

1.基础镜像制作规范和使用

1.1 时区修改
官网下载centos镜像默认时区是国外的时区,需要把它修改成上海时区。运维提供提一个基础的镜像给业务部门下载使用。

1.2 规范docker运行程序的用户
基于安全和规范的考虑,docker统一使用一个uid为1001的,用户名为pub的普通账号运行程序,需要在镜像和容器的宿主机上面同时新建。这个也是运维在初始化基础镜像和容器宿主机上面统一创建。

1.3 规范每个容器的cpu和内存(每个容器分配1核2G内存,视情况而定)

2.镜像下载策略

2.1 默认的镜像拉取策略是“IfNotPresent”,在镜像已经存在的情况下,kubelet将不在去拉取镜像。 如果总是想要拉取镜像,必须设置拉取策略为“Always”或者设置镜像标签为“:latest”。

如果没有指定镜像的标签,它会被假定为“:latest”,同时拉取策略为“Always”。

3.增加k8s各个命名空间的服务账号 default 的自定义权限(RABC)

首先,了解下什么是RABC:

基于角色的访问控制(Role-Based Access Control, 即”RBAC”)使用”rbac.authorization.k8s.io” API Group实现授权决策,允许管理员通过Kubernetes API动态配置策略。

在RBAC API中,一个角色包含了一套表示一组权限的规则。 权限以纯粹的累加形式累积(没有”否定”的规则)。 角色可以由命名空间(namespace)内的Role对象定义,而整个Kubernetes集群范围内有效的角色则通过ClusterRole对象实现

比如授予default命名空间的default ServiceAccount账号能够”get”, “watch”, “list”, “patch” default 命名空间里面的pod资源

3.1 定义role,一个Role对象只能用于授予对某一单一命名空间中资源的访问权限。 以下示例描述了”default”命名空间中的一个Role对象的定义,用于授予对pod的读访问权限:

1
2
3
4
5
6
7
8
9
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # 空字符串""表明使用core API group
resources: ["pods"]
verbs: ["get", "watch", "list", "patch"]

:D 一言句子获取中...