Kubernetes之yaml文件详解

[TOC]

一、YAML基础

YAML是专门用来写配置文件的语言,非常简洁和强大,使用比json更方便。它实质上是一种通用的数据串行化格式。

YAML语法规则:

1
2
3
4
5
6
7
8
9
10
大小写敏感
使用缩进表示层级关系
缩进时不允许使用Tal键,只允许使用空格
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
”#” 表示注释,从这个字符一直到行尾,都会被解析器忽略  
在Kubernetes中,只需要知道两种结构类型即可:

Lists
Maps
123456789

1.1 YAML Maps

Map顾名思义指的是字典,即一个Key:Value 的键值对信息。例如:

1
2
3
4
apiVersion: v1
kind: Pod
  注:---为可选的分隔符 ,当需要在一个文件中定义多个结构的时候需要使用。上述内容表示有两个键apiVersion和kind,分别对应的值为v1和Pod。
123

Maps的value既能够对应字符串也能够对应一个Maps。例如:

1
2
3
4
5
6
7
apiVersion: v1
kind: Pod
metadata:
name: kube100-site
labels:
app: web
123456

注:上述的YAML文件中,metadata这个KEY对应的值为一个Maps,而嵌套的labels这个KEY的值又是一个Map。实际使用中可视情况进行多层嵌套。

YAML处理器根据行缩进来知道内容之间的关联。上述例子中,使用两个空格作为缩进,但空格的数据量并不重要,只是至少要求一个空格并且所有缩进保持一致的空格数 。例如,name和labels是相同缩进级别,因此YAML处理器知道他们属于同一map;它知道app是lables的值因为app的缩进更大。

注意:在YAML文件中绝对不要使用tab键

1.2 YAML Lists

List即列表,说白了就是数组,例如:

1
2
3
4
5
6
args
-beijing
-shanghai
-shenzhen
-guangzhou
12345

可以指定任何数量的项在列表中,每个项的定义以破折号(-)开头,并且与父元素之间存在缩进。在JSON格式中,表示如下:

1
2
3
4
{
"args": ["beijing", "shanghai", "shenzhen", "guangzhou"]
}
123

当然Lists的子项也可以是Maps,Maps的子项也可以是List,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: v1
kind: Pod
metadata:
name: kube100-site
labels:
app: web
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
- name: flaskapp-demo
image: jcdemo/flaskapp
ports: 8080
123456789101112131415

如上述文件所示,定义一个containers的List对象,每个子项都由name、image、ports组成,每个ports都有一个KEY为containerPort的Map组成,转成JSON格式文件:

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
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "kube100-site",
"labels": {
"app": "web"
},

},
"spec": {
"containers": [{
"name": "front-end",
"image": "nginx",
"ports": [{
"containerPort": "80"
}]
}, {
"name": "flaskapp-demo",
"image": "jcdemo/flaskapp",
"ports": [{
"containerPort": "5000"
}]
}]
}
}
1234567891011121314151617181920212223242526

二、说明

定义配置时,指定最新稳定版API
配置文件应该存储在集群之外的版本控制仓库中。如果需要,可以快速回滚配置、重新创建和恢复
应该使用YAML格式编写配置文件,而不是json。YAML对用户更加友好
可以将相关对象组合成单个文件,通常会更容易管理
不要没必要指定默认值,简单和最小配置减小错误
在注释中说明一个对象描述更好维护

三、使用YAML创建Pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Pod
metadata:
name: kube100-site
labels:
app: web
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
- name: flaskapp-demo
image: jcdemo/flaskapp
ports:
- containerPort: 5000 
12345678910111213141516

apiVersion:此处值是v1,这个版本号需要根据安装的Kubernetes版本和资源类型进行变化,记住不是写死的。
kind:此处创建的是Pod,根据实际情况,此处资源类型可以是Deployment、Job、Ingress、Service等。
metadata:包含Pod的一些meta信息,比如名称、namespace、标签等信息。
spec:包括一些container,storage,volume以及其他Kubernetes需要的参数,以及诸如是否在容器失败时重新启动容器的属性。可在特定Kubernetes API找到完整的Kubernetes Pod的属性。
  (1)查看apiVersion

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
# kubectl api-versions
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
apps/v1beta1
apps/v1beta2
authentication.k8s.io/v1
authentication.k8s.io/v1beta1
authorization.k8s.io/v1
authorization.k8s.io/v1beta1
autoscaling/v1
autoscaling/v2beta1
batch/v1
batch/v1beta1
certificates.k8s.io/v1beta1
events.k8s.io/v1beta1
extensions/v1beta1
networking.k8s.io/v1
policy/v1beta1
rbac.authorization.k8s.io/v1
rbac.authorization.k8s.io/v1beta1
storage.k8s.io/v1
storage.k8s.io/v1beta1
v1
1234567891011121314151617181920212223242526

(2)下面是一个典型的容器定义:

1
2
3
4
5
6
7
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
123456

上述例子只是一个简单的最小定义:一个名字(front-end)、基于nginx的镜像,以及容器将会监听的指定端口号(80)。

除了上述的基本属性外,还能够指定复杂的属性,包括容器启动运行的命令、使用的参数、工作目录以及每次实例化是否拉取新的副本。 还可以指定更深入的信息,例如容器的退出日志的位置。容器可选的设置属性包括:

name、image、command、args、workingDir、ports、env、resource、volumeMounts、livenessProbe、readinessProbe、livecycle、terminationMessagePath、imagePullPolicy、securityContext、stdin、stdinOnce、tty

(3)kubectl创建Pod

1
2
3
# kubectl create -f test_pod.yaml
pod "kube100-site" created
12

(4)查看Pod状态

1
2
3
4
5
6
# kubectl get pod

NAME READY STATUS RESTARTS AGE
kube100-site 2/2 Running 0 2m
  
12345

四、创建Deployment

名词解释

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
#test-pod 
apiVersion: v1 #指定api版本,此值必须在kubectl apiversion中
kind: Pod #指定创建资源的角色/类型
metadata: #资源的元数据/属性
name: test-pod #资源的名字,在同一个namespace中必须唯一
labels: #设定资源的标签
k8s-app: apache
version: v1
kubernetes.io/cluster-service: "true"
annotations: #自定义注解列表
- name: String #自定义注解名字
spec: #specification of the resource content 指定该资源的内容
restartPolicy: Always #表明该容器一直运行,默认k8s的策略,在此容器退出后,会立即创建一个相同的容器
nodeSelector: #节点选择,先给主机打标签kubectl label nodes kube-node1 zone=node1
zone: node1
containers:
- name: test-pod #容器的名字
image: 10.192.21.18:5000/test/chat:latest #容器使用的镜像地址
imagePullPolicy: Never #三个选择Always、Never、IfNotPresent,每次启动时检查和更新(从registery)images的策略,
# Always,每次都检查
# Never,每次都不检查(不管本地是否有)
# IfNotPresent,如果本地有就不检查,如果没有就拉取
command: ['sh'] #启动容器的运行命令,将覆盖容器中的Entrypoint,对应Dockefile中的ENTRYPOINT
args: ["$(str)"] #启动容器的命令参数,对应Dockerfile中CMD参数
env: #指定容器中的环境变量
- name: str #变量的名字
value: "/etc/run.sh" #变量的值
resources: #资源管理
requests: #容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行
cpu: 0.1 #CPU资源(核数),两种方式,浮点数或者是整数+m,0.1=100m,最少值为0.001核(1m)
memory: 32Mi #内存使用量
limits: #资源限制
cpu: 0.5
memory: 1000Mi
ports:
- containerPort: 80 #容器开发对外的端口
name: httpd #名称
protocol: TCP
livenessProbe: #pod内容器健康检查的设置
httpGet: #通过httpget检查健康,返回200-399之间,则认为容器正常
path: / #URI地址
port: 80
#host: 127.0.0.1 #主机地址
scheme: HTTP
initialDelaySeconds: 180 #表明第一次检测在容器启动后多长时间后开始
timeoutSeconds: 5 #检测的超时时间
periodSeconds: 15 #检查间隔时间
#也可以用这种方法
#exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常
# command:
# - cat
# - /tmp/health
#也可以用这种方法
#tcpSocket: //通过tcpSocket检查健康
# port: number
lifecycle: #生命周期管理
postStart: #容器运行之前运行的任务
exec:
command:
- 'sh'
- 'yum upgrade -y'
preStop:#容器关闭之前运行的任务
exec:
command: ['service httpd stop']
volumeMounts: #挂载持久存储卷
- name: volume #挂载设备的名字,与volumes[*].name 需要对应
mountPath: /data #挂载到容器的某个路径下
readOnly: True
volumes: #定义一组挂载设备
- name: volume #定义一个挂载设备的名字
#meptyDir: {}
hostPath:
path: /opt #挂载设备类型为hostPath,路径为宿主机下的/opt,这里设备类型支持很多种
#nfs
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374

(1)创建一个yaml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.10
ports:
- containerPort: 80
12345678910111213141516171819

(2)创建deployment

1
2
3
4
5
6
7
8
9
10
11
[root@master-01 YAML_k8s]# kubectl create -f nginx-deployment.yaml
deployment.apps "nginx-deployment" created
[root@master-01 YAML_k8s]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-deployment-6b7b4d57b4-26wzj 1/1 Running 0 2m 10.20.184.83 master-01
nginx-deployment-6b7b4d57b4-9w7tm 1/1 Running 0 2m 10.20.190.60 node-01
nginx-deployment-6b7b4d57b4-mhh8t 1/1 Running 0 2m 10.20.254.108 node-03
[root@master-01 YAML_k8s]# kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 2m
12345678910

(3)查看标签

1
2
3
4
5
6
[root@master-01 YAML_k8s]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-deployment-6b7b4d57b4-26wzj 1/1 Running 0 3m app=nginx,pod-template-hash=2636081360
nginx-deployment-6b7b4d57b4-9w7tm 1/1 Running 0 3m app=nginx,pod-template-hash=2636081360
nginx-deployment-6b7b4d57b4-mhh8t 1/1 Running 0 3m app=nginx,pod-template-hash=2636081360
12345

(4)通过标签查找Pod

1
2
3
4
5
6
[root@master-01 YAML_k8s]# kubectl get pod -l app=nginx
NAME READY STATUS RESTARTS AGE
nginx-deployment-6b7b4d57b4-26wzj 1/1 Running 0 6m
nginx-deployment-6b7b4d57b4-9w7tm 1/1 Running 0 6m
nginx-deployment-6b7b4d57b4-mhh8t 1/1 Running 0 6m
12345

(5)deployment创建过程

Deployment 管理的是replicaset-controller,RC会创建Pod。Pod自身会下载镜像并启动镜像

1
2
3
4
5
6
7
8
9
10
11
[root@master-01 YAML_k8s]# kubectl describe rs nginx-deployment
...
...
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 33m replicaset-controller Created pod: nginx-deployment-6b7b4d57b4-9w7tm
Normal SuccessfulCreate 33m replicaset-controller Created pod: nginx-deployment-6b7b4d57b4-26wzj
Normal SuccessfulCreate 33m replicaset-controller Created pod: nginx-deployment-6b7b4d57b4-mhh8t
12345678910
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@master-01 YAML_k8s]# kubectl describe pod nginx-deployment-6b7b4d57b4-26wzj

...
...
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 36m default-scheduler Successfully assigned nginx-deployment-6b7b4d57b4-26wzj to master-01
Normal SuccessfulMountVolume 36m kubelet, master-01 MountVolume.SetUp succeeded for volume "default-token-v5vw9"
Normal Pulled 36m kubelet, master-01 Container image "nginx:1.10" already present on machine
Normal Created 36m kubelet, master-01 Created container
Normal Started 36m kubelet, master-01 Started container
12345678910111213

(6)升级镜像(nginx1.10–>nginx1.11)

1
2
3
4
5
6
7
[root@master-01 YAML_k8s]# kubectl set image deploy/nginx-deployment nginx=nginx:1.11
deployment.apps "nginx-deployment" image updated

[root@master-01 YAML_k8s]# kubectl exec -it nginx-deployment-b96c97dc-2pxjf bash
root@nginx-deployment-b96c97dc-2pxjf:/# nginx -V
nginx version: nginx/1.11.13
123456

升级镜像的过程是逐步进行的,pod不会一下子全部关闭,而是一个一个升级

(7)查看发布状态

1
2
3
[root@master-01 ~]# kubectl rollout status deploy/nginx-deployment
deployment "nginx-deployment" successfully rolled out
12

(8)查看deployment历史修订版本

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
[root@master-01 ~]# kubectl rollout history deploy/nginx-deployment
deployments "nginx-deployment"
REVISION CHANGE-CAUSE
1 <none>
2 <none>

# 显示历史有两个版本

[root@master-01 ~]# kubectl rollout history deploy/nginx-deployment --revision=1
deployments "nginx-deployment" with revision #1
Pod Template:
Labels: app=nginx
pod-template-hash=2636081360
Containers:
nginx:
Image: nginx:1.10
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>

[root@master-01 ~]# kubectl rollout history deploy/nginx-deployment --revision=2
deployments "nginx-deployment" with revision #2
Pod Template:
Labels: app=nginx
pod-template-hash=65275387
Containers:
nginx:
Image: nginx:1.11
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
1234567891011121314151617181920212223242526272829303132333435

(8)编辑deployment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@master-01 ~]# kubectl edit deploy/nginx-deployment


# 将nginx版本改为1.12
...
...
...
spec:
containers:
- image: nginx:1.12
imagePullPolicy: IfNotPresent
name: nginx
ports:
- containerPort: 80
1234567891011121314

升级过程:

1
2
3
4
5
6
7
8
9
10
11
[root@master-01 ~]# kubectl rollout status deploy/nginx-deployment
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
deployment "nginx-deployment" successfully rolled out
12345678910

(10)扩容/缩容(指定–replicas的数量)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@master-01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-6b47cf4878-8mjkr 1/1 Running 0 1m
nginx-deployment-6b47cf4878-kr978 1/1 Running 0 1m
nginx-deployment-6b47cf4878-tvhvl 1/1 Running 0 1m

[root@master-01 ~]# kubectl scale deploy/nginx-deployment --replicas=5
deployment.extensions "nginx-deployment" scaled

[root@master-01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-6b47cf4878-6r5dz 0/1 ContainerCreating 0 4s
nginx-deployment-6b47cf4878-7sjtt 0/1 ContainerCreating 0 4s
nginx-deployment-6b47cf4878-8mjkr 1/1 Running 0 2m
nginx-deployment-6b47cf4878-kr978 1/1 Running 0 2m
nginx-deployment-6b47cf4878-tvhvl 1/1 Running 0 2m
12345678910111213141516

(11)创建Service提供对外访问的接口

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
apiVersion: v1
kind: Service
metadata:
name: nginx-service
labels:
app: nginx
spec:
ports:
- port: 88
targetPort: 80
selector:
app: nginx

####
apiVersion: 指定版本

kind: 类型

name: 指定服务名称

labels: 标签

port: Service 服务暴露的端口

targetPort: 容器暴露的端口

seletor: 关联的Pod的标签
123456789101112131415161718192021222324252627

创建service

1
2
# kubectl create -f nginx-service.yaml
1

查看service(访问Pod是有负载均衡的)

1
2
3
4
[root@master-01 YAML_k8s]# kubectl get svc/nginx-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service ClusterIP 10.254.131.176 <none> 88/TCP 1m
123
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
# curl 10.254.131.176:88
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
1234567891011121314151617181920212223242526

对service的描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# kubectl describe svc/nginx-service
Name: nginx-service
Namespace: default
Labels: app=nginx
Annotations: <none>
Selector: app=nginx
Type: ClusterIP
IP: 10.254.131.176
Port: <unset> 88/TCP
TargetPort: 80/TCP
Endpoints: 10.20.184.19:80,10.20.184.84:80,10.20.190.62:80 + 2 more...
Session Affinity: None
Events: <none>
12345678910111213

(12)回滚到以前的版本

1
2
3
4
5
6
7
# kubectl rollout history deploy/nginx-deployment
deployments "nginx-deployment"
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>
123456
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# kubectl rollout history deploy/nginx-deployment --revision=3
deployments "nginx-deployment" with revision #3
Pod Template:
Labels: app=nginx
pod-template-hash=2603790434
Containers:
nginx:
Image: nginx:1.12
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
12345678910111213
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 回滚到上一个版本
# kubectl rollout undo deploy/nginx-deployment
deployment.apps "nginx-deployment"


# 查看版本
# kubectl describe deploy/nginx-deployment
...
...
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.11
12345678910111213

(13)回滚到指定版本

1
2
3
4
5
6
7
8
9
10
11
# kubectl rollout history deploy/nginx-deployment
deployments "nginx-deployment"
REVISION CHANGE-CAUSE
1 <none>
3 <none>
4 <none>

# 指定版本
# kubectl rollout undo deploy/nginx-deployment --to-revision=1
deployment.apps "nginx-deployment"
12345678910

附上一个具体的yaml解释文件:

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
# yaml格式的pod定义文件完整内容:
apiVersion: v1 #必选,版本号,例如v1
kind: Pod #必选,Pod
metadata: #必选,元数据
name: string #必选,Pod名称
namespace: string #必选,Pod所属的命名空间
labels: #自定义标签
- name: string #自定义标签名字
annotations: #自定义注释列表
- name: string
spec: #必选,Pod中容器的详细定义
containers: #必选,Pod中容器列表
- name: string #必选,容器名称
image: string #必选,容器的镜像名称
imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令
args: [string] #容器的启动命令参数列表
workingDir: string #容器的工作目录
volumeMounts: #挂载到容器内部的存储卷配置
- name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符
readOnly: boolean #是否为只读模式
ports: #需要暴露的端口库号列表
- name: string #端口号名称
containerPort: int #容器需要监听的端口号
hostPort: int #容器所在主机需要监听的端口号,默认与Container相同
protocol: string #端口协议,支持TCP和UDP,默认TCP
env: #容器运行前需设置的环境变量列表
- name: string #环境变量名称
value: string #环境变量的值
resources: #资源限制和请求的设置
limits: #资源限制的设置
cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
requests: #资源请求的设置
cpu: string #Cpu请求,容器启动的初始可用数量
memory: string #内存清楚,容器启动的初始可用数量
livenessProbe: #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可
exec: #对Pod容器内检查方式设置为exec方式
command: [string] #exec方式需要制定的命令或脚本
httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
path: string
port: number
host: string
scheme: string
HttpHeaders:
- name: string
value: string
tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式
port: number
initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒
timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
successThreshold: 0
failureThreshold: 0
securityContext:
privileged:false
restartPolicy: [Always | Never | OnFailure]#Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
- name: string
hostNetwork:false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
volumes: #在该pod上定义共享存储卷列表
- name: string #共享存储卷名称 (volumes类型有很多种)
emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
path: string #Pod所在宿主机的目录,将被用于同期中mount的目录
secret: #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
scretname: string
items:
- key: string
path: string
configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
name: string
items:
- key: string

k8s 常见问题

[TOC]

自己在搭建k8s集群的时候遇到的问题,和解决方法记录下来.

1.etcd服务

kubernetes和flannel存储数据等,单台etcd不稳定,最好是搭建集群。搭建集群的时候,集群之间通信如果要添加认证的话,需要签署证书。同时把证书拷贝到制定文件目录,在etcd.service中制定证书文件。

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
cat > etcd-csr.json <<EOF
{
"CN": "etcd",
"hosts": [
"127.0.0.1",
"${NODE_IP}"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF

cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
-ca-key=/etc/kubernetes/ssl/ca-key.pem \
-config=/etc/kubernetes/ssl/ca-config.json \
-profile=kubernetes etcd-csr.json | cfssljson -bare etcd

mkdir -p /etc/etcd/ssl
cp etcd*.pem /etc/etcd/ssl

cd
mkdir -p /var/lib/etcd
cat > etcd.service <<EOF
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
ExecStart=/root/local/bin/etcd \\
--name=${NODE_NAME} \\
--cert-file=/etc/etcd/ssl/etcd.pem \\
--key-file=/etc/etcd/ssl/etcd-key.pem \\
--peer-cert-file=/etc/etcd/ssl/etcd.pem \\
--peer-key-file=/etc/etcd/ssl/etcd-key.pem \\
--trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\
--peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\
--initial-advertise-peer-urls=https://${NODE_IP}:2380 \\
--listen-peer-urls=https://${NODE_IP}:2380 \\
--listen-client-urls=https://${NODE_IP}:2379,http://127.0.0.1:2379 \\
--advertise-client-urls=https://${NODE_IP}:2379 \\
--initial-cluster-token=etcd-cluster-0 \\
--initial-cluster=${ETCD_NODES} \\
--initial-cluster-state=new \\
--data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

cp etcd.service /etc/systemd/system/

2.flannel网络

flannel网络也可以添加认证

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
cat > flanneld-csr.json <<EOF
{
"CN": "flanneld",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF

cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
-ca-key=/etc/kubernetes/ssl/ca-key.pem \
-config=/etc/kubernetes/ssl/ca-config.json \
-profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld

mkdir -p /etc/flanneld/ssl
cp flanneld*.pem /etc/flanneld/ssl

#只需一次
--------------------------------------------------------------------------
/root/local/bin/etcdctl \
--endpoints=${ETCD_ENDPOINTS} \
--ca-file=/etc/kubernetes/ssl/ca.pem \
--cert-file=/etc/flanneld/ssl/flanneld.pem \
--key-file=/etc/flanneld/ssl/flanneld-key.pem \
set ${FLANNEL_ETCD_PREFIX}/config '{"Network":"'${CLUSTER_CIDR}'", "SubnetLen": 24, "Backend": {"Type": "vxlan"}}'
--------------------------------------------------------------------------

mkdir /atlas/backup/kubernetes-1.6.10/flannel
tar xf /atlas/backup/kubernetes-1.6.10/flannel-v0.7.1-linux-amd64.tar.gz -C /atlas/backup/kubernetes-1.6.10/flannel
cp /atlas/backup/kubernetes-1.6.10/flannel/{flanneld,mk-docker-opts.sh} /root/local/bin

cd
cat > flanneld.service << EOF

[Unit]
Description=Flanneld overlay address etcd agent
After=network.target
After=network-online.target
Wants=network-online.target
After=etcd.service
Before=docker.service

[Service]
Type=notify
ExecStart=/root/local/bin/flanneld \\
-etcd-cafile=/etc/kubernetes/ssl/ca.pem \\
-etcd-certfile=/etc/flanneld/ssl/flanneld.pem \\
-etcd-keyfile=/etc/flanneld/ssl/flanneld-key.pem \\
-etcd-endpoints=${ETCD_ENDPOINTS} \\
-etcd-prefix=${FLANNEL_ETCD_PREFIX}
ExecStartPost=/root/local/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker
Restart=on-failure

[Install]
WantedBy=multi-user.target
RequiredBy=docker.service

EOF

cp flanneld.service /etc/systemd/system/

docker

在设置网络断的时候注意,yum安装的flannel,记得添加配置文件。启动flannel之前要先把之前docker启动的docker0 网络给删除。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ip link delete docker0

cat > /etc/sysconfig/flanneld <<EOF

FLANNEL_ETCD_ENDPOINTS="http://172.16.10.17:2379,http://172.16.10.13:2379,http://172.16.10.14:2379"
FLANNEL_ETCD_PREFIX="/flannel/network"
FLANNEL_OPTIONS="--iface=eth0"
EOF

etcdctl \
--endpoints=${ETCD_ENDPOINTS} \
--ca-file=/etc/kubernetes/ssl/ca.pem \
--cert-file=/etc/flanneld/ssl/flanneld.pem \
--key-file=/etc/flanneld/ssl/flanneld-key.pem \
set ${FLANNEL_ETCD_PREFIX}/config '{"Network":"'${CLUSTER_CIDR}'", "SubnetLen": 24, "Backend": {"Type": "vxlan"}}'

#查询
etcdctl \
--endpoints=${ETCD_ENDPOINTS} \
--ca-file=/etc/kubernetes/ssl/ca.pem \
--cert-file=/etc/flanneld/ssl/flanneld.pem \
--key-file=/etc/flanneld/ssl/flanneld-key.pem \
ls ${FLANNEL_ETCD_PREFIX}/subnets

在向etcd中写入pod网段信息的时候设置endpoints的时候,如果etcd启用认证,就需要加https,同时指定证书文件,否则只需使用http。

另外一个docker要注意的地方,在使用docker启动gitlab,如果要实现ldap认证用户登录,那么就不要用flannel网络将这个docker管理起来,用flannel设置的网络访问不了ldap的端口。所以集群上目前没有把login节点设置成一个node的原因。

docker.service中,最好是禁用掉iptables,加上--iptables=false 即可,如果不禁用掉则需要在kubelete服务中添加防火墙规则。yum安装的flannel要在docker中加入如下命令,以添加网络管理配置。

1
2
3
4
5
6
7
8
9
EnvironmentFile=-/run/flannel/docker
#清空防火墙
iptables -F
iptables -P FORWARD ACCEPT #添加防火墙默认规则
#kubelete添加防火墙规则
ExecStartPost=/sbin/iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 4194 -j ACCEPT
ExecStartPost=/sbin/iptables -A INPUT -s 172.16.0.0/12 -p tcp --dport 4194 -j ACCEPT
ExecStartPost=/sbin/iptables -A INPUT -s 192.168.0.0/16 -p tcp --dport 4194 -j ACCEPT
ExecStartPost=/sbin/iptables -A INPUT -p tcp --dport 4194 -j DROP

kubelet bootstrapping kubeconfig 文件,kube-proxy kubeconfig 文件。在一处创建之后,可以用在所有node节点。

集群上的kube-apiserver服务启用了rbac。

在kubedns 和kube-dashboard中,用到的images已经在配置中修改到国内的images上了。

一个培训机构的kubernetes学习课程,用来参考做学习:

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
Chapter 1:课程介绍
理解 Kubernetes 设计原则、原理
了解 Kubernetes 的过去、现在和未来
了解并学会使用 Kubernetes 最重要的资源 -- API
学会如何创建和管理应用,并配置应用外部访问
理解 Kubernetes 网络、存储
掌握 Kubernetes 调度的原理和策略
Kubernetes 一些新功能的概念
了解 Kubernetes 的日志、监控方案
具备基本的故障排查的运维能力

Chapter 2:Kubernetes 基本概念
了解什么是 Kubernetes
了解 Kubernetes 的主要特性
理解为什么需要 Kubernetes
了解 Kubernetes 的过去、现在和未来
了解目前 Kubernetes 社区的情况和被采用情况
了解 Kubernetes 的基本架构
获得一些学习资料推荐

Chapter 3:Kubernetes 架构及原理
理解 Kubernetes 设计原则
深入理解 Kubernetes 集群中的组件及功能
了解 Kubernetes 集群对网络的预置要求
深入理解 Kubernetes 的工作原理
深入理解 Kubernetes 中 Pod 的设计思想


Chapter 4:Kubernetes 安装和配置
了解部署 Kubernetes 的多种方式
可以单机部署 Kubernetes(学习演示使用)
可以在宿主机部署一套 Kubernetes 集群(非生产使用)


Chapter 5:Kubernetes API 及集群访问
了解 Kubernetes 的 API
理解 Kubernetes 中 API 资源的结构定义
了解 kubectl 工具的使用
了解 Kubernetes 中 API 之外的其他资源


Chapter 6:ReplicaController,ReplicaSets 和 Deployments
理解 RC
理解 label 和 selector 的作用
理解 RS
理解 Deployments 并且可操作 Deployments
理解 rolling update 和 rollback

Chapter 7:Volume、配置文件及密钥
了解 Kubernetes 存储的管理,支持存储类型
理解 Pod 使用 volume 的多种工作流程以及演化
理解 pv 和 pvc 的原理
理解 storage class 的原理
理解 configmaps 的作用和使用方法
理解 secrets 的作用和使用方法资源结构

Chapter 8:Service 及服务发现
了解 Docker 网络和 Kubernetes 网络
了解 Flannel 和 Calico 网络方案
理解 Pod 在 Kubernetes 网络中的工作原理
理解 Kubernetes 中的 Service
理解 Service 在 Kubernetes 网络中的工作原理
理解 Kubernetes 中的服务发现
掌握 Kubernetes 中外部访问的几种方式

Chapter 9:Ingress 及负载均衡
理解 Ingress 和 Ingress controller 的工作原理
掌握如何创建 Ingress 规则
掌握如何部署 Ingress controller

Chapter 10:DaemonSets,StatefulSets,Jobs,HPA,RBAC
了解 DaemonSet 资源和功能
了解 StatefulSet 资源和功能
了解 Jobs 资源和功能
了解 HPA 资源和功能
了解 RBAC 资源和功能

Chapter 11:Kubernetes 调度
理解 Pod 调度的相关概念
深度理解 Kubernetes 调度策略和算法
深度理解调度时的 Node 亲和性
深度理解调度时的 Pod 亲和性和反亲和性
深度理解污点和容忍对调度的影响
深度理解强制调度 Pod 的方法

Chapter 12:日志、监控、Troubleshooting
理解 Kubernetes 集群的日志方案
理解 Kubernetes 集群的监控方案
了解相关开源项目:Heapster,Fluentd,Prometheus 等
掌握常用的集群,Pod,Service 等故障排查和运维手段

Chapter 13:自定义资源 CRD
理解和掌握 Kubernetes 中如何自定义 API 资源
可以通过 kubectl 管理 API 资源
了解用于自定义资源的 Controller 及相关使用示例
了解 TPR 和 CRD

Chapter 14:Kubernetes Federation
了解 Kubernetes 中 Federation 的作用和原理
了解 Federation 的创建过程
了解 Federation 支持的 API 资源
了解集群间平衡 Pod 副本的方法

Chapter 15:应用编排 Helm,Chart
了解 Kubernetes 中如何进行应用编排
了解 Helm 的作用和工作原理
了解 Tiller 的作用和工作原理
了解 Charts 的作用和工作原理

Chapter 16:Kubernetes 安全
了解 Kubernetes 中 API 访问过程
了解 Kubernetes 中的 Authentication
了解 Kubernetes 中的 Authorization
了解 ABAC 和 RBAC 两种授权方式
了解 Kubernetes 中的 Admission
了解 Pod 和容器的操作权限安全策略
了解 Network Policy 的作用和资源配置方法

k8s学习内容汇总

[TOC]

根据马哥教育k8s教程学习。

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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
k8s学习大纲
- 基础大纲
- 集群部署及陈述式命令管理
- 资源类型及配置清单
- pod资源
- pod 控制器
- service资源
- 存储卷
- configmap与secret资源
- statefulset控制器
- 认证、授权及准入控制
- 网络模型及网络策略
- pod资源调度
- crd、自定义资源、自定义控制器及自定义API server, cni=Custom/Container Network Interface, crd=CustomResourceDefinition, CRI=Container Runtime Interface
- 资源指标与HPA控制器
- Helm管理器
- 高可用kubernetes


Cloud Native Apps: 云原生应用,程序开发出来就是运行在云平台上,而非单机上的应用。
Serverless: 与云原生应用组合,成为新的发展趋势,FaaS。 Knative。

单体应用程序: 亦称巨石应用,牵一发而动全身。
分成架构服务: 每个团队维护一个层次。(比如用户,商品,支付)
微服务(Microservice): 服务拆分成多个小功能,单独运行。
- 服务注册和服务发现: 分布式和微服务存在的问题
- 三五个程序运行支撑的服务转变为 三五十个微型服务,服务之间的调用成为网状结构。
- 非静态配置,动态服务发现,服务总线
- 服务编排系统: 解决运维部署难的问题
- 容器编排系统: 解决系统异构,服务依赖环境各不相同。 服务编排系统 --> 容器编排系统


容器编排系统: (主流: k8s, Borg, Docker Swarm, Apache Mesos Marathon DC/OS )
what is container orchestration?
- container orchestration is all about managing the lifecycles of containers, especially in large, dynamic environments.
- software teams use container orchestration to control and automade many task:
- provisioning and deployment of containers
- redundancy and availability of containers
- scaling up or removing containers to spread application load evently across host infrastructure
- movement of containers from one host to another if there is a shortage of resources in host, or if a host dies.
- allocation of resources between containers
- exteral exposure of services running in a container with the outside world
- load balancing of service discovery between containers
- heath monitoring of containers and hosts
- configuration of an application in relation to the containers runing it


简单来说,容器编排是指容器应用的自动布局、协同及管理,它主要负责完成以下具体内容:
service discovery
load balancing
secrets/configuration/storage management
heath checks
auto-[scaling/restart/healing] of containers and nodes
zero-downtime deploys

- pod资源

- pod 控制器:
pod创建方式:
- 自助式pod: 直接创建pod
- 由控制器管理pod: 创建deployment,service等

ReplicationControler:

ReplicaSet/rs:
- 副本数
- 标签选择
- pod资源摸版

- kubectl explain rs
- kubectl explain rs.spec
- replicas
- selector
- template

Deployment: 无状态任务,关注群体行为. 只关注数量,不关注个体.
- kubectl explain deploy.spec
- replicas
- selector
- template
- strategy: 更新策略
- rollingUpdate
- maxSurge: 最多超出目标pod数量 1/20%
- maxUnavailable: 最多不可用数量. 1/80%
- type
- Recreate
- rollingUpdate

- minReadySeconds
- revisionHistoryLimit: 保存历史版本数量限制

DaemonSet/ds: 每个node节点只运行一个,eg:ELK.
- kubectl explain ds.spec
- selector
- template

- minReadySeconds
- revisionHistoryLimit: 保存历史版本数量限制
- updateStrategy

Service:
工作模式: userspace, iptables, ipvs. (kube-proxy)
userspace: 1.1-
iptables: 1.10-
ipvs: 1.11+

- NodePort/ClusterIP : client --> NodeIP:NodePort --> ClusterIP:ServicePort --> PodIP:containerPort
- LBAAS(LoadBalancerAsAService): 公有云环境中.
- LoadBalancer
- ExternalName
- FQDN
- CNAME -> FQDN
- No ClusterIP: Headless Service
- ServiceName -> PodIP


- kubectl explain svc
- type: ExternalName, ClusterIP, NodePort, LoadBalancer
- port:
- NodePort # type=NodePort 时 可用. client --> NodeIP:NodePort --> ClusterIP:ServicePort --> PodIP:containerPort
- LBAAS(LoadBalancerAsAService): 公有云环境中.
- LoadBalancer
- ExternalName
- FQDN
- CNAME -> FQDN
-
- port
- targetPort

Ingress:
Service: ingress-nginx (NodePort, DaemonSet - HostNetwork)
IngressController: ingress-nginx
Ingress:
- site1.ikubernetes.io (virtual host)
- site2.ikubernetes.io (virtual host)
- example.com/path1
- example.com/path2

- Service: site1
- pod1
- pod2

- Service: site2
- pod3
- pod4

- 存储卷
- emptyDir
- 临时目录, 内存使用, 没有持久性
- gitRepo

- hostPath

- 共享存储
- SAN: iSCSI
- NAS: nfs, cifs, http
- 分布式存储:
- glusterfs
- ceph: rbd
- cephfs:
- 云存储
- EBS
- Azure Disk
- pvc: persistentVolumeClaim
- pv
- pvc
- pod - volumes -

- secret
base64 的 configmap

- configmap: 配置中心
配置容器化应用的方式:
1. 自定义命令行参数;
args: []
2.把配置文件直接copy进镜像
3.环境变量
1.Cloud Native的应用程序一般可直接通过环境变量加载配置
2.通过entrypoint.sh脚本来预处理变量为配置文件中的配置信息
4.存储卷

- 变量注入 --> pod 读取变量
- 挂载存储卷 --> pod 读取配置
- 自定义命令行参数

- StatefulSet:
PetSet -> StatefulSet
应对有以下要求的服务:
1.稳定且唯一的网络标识符
2.稳定且持久的存储
3.有序平滑的部署和扩展
4.有序平滑的删除和终止
5.有序的滚动更新

三个组件:
- headless service: clusterIP: None
- StatefulSet
- volumeClaimTemplate

- 认证、授权及准入控制
- Authentication
- restful API: token
- tls: 双向认证
- user/password

- Authorization
- rbac
- role
- rolebinding
- ClusterRole
- ClusterRoleBinding

- webhook
- abac

- Admission Control


client --> API Server
pod --> api server
- ServiceAccount?
- secret
- ServiceAccountName
kubectl get secret
kubectl get sa | serviceaccount
kubectl create serviceaccount my-sa -o yaml --dry-run
kubectl get pods myapp -o yaml --export

API request path: http://IP:port/apis/apps/v1/namespaces/default/deployments/myapp-deploy/
http request ver:
get, post, put, delete
http request --> API requests verb:
get, list, create, update, patch, watch, proxy, redirect, delete, delectcollection
Resource:
Subresource:
Namespace:
API group:

- ServiceAccount:
alex.crt
(umask 077; openssl genrsa -out alex.key 2048)
openssl req -new -key alex.key -out alex.csr -subj "/CN=alex"
openssl x509 -req -in alex.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out alex.crt -days 3650
openssl x509 -in alex.crt -text -noout

kubectl config set-cluster alex-cluster --server="https://192.168.137.131:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --kubeconfig=/tmp/alex.conf
kubectl config set-credentials admin \
--client-certificate=datasets/work/admin/admin.pem \
--client-key=datasets/work/admin/admin-key.pem \
--embed-certs=true \
--kubeconfig=/tmp/alex.conf

kubectl config set-context alex@kubernetes --cluster=kubernetes --user=admin --kubeconfig=/tmp/alex.conf
kubectl config use-context kubernetes --kubeconfig=/tmp/alex.conf
kubectl get pods --kubeconfig=/tmp/alex.conf (error from server forbidden)

- RBAC
- role, clusterrole
object:
resource group
resource
non-resource url

action:
get, list, watch, patch, delete, deletecollection, ...

- rolebinding, clusterrolebinding
subject:
user
group
serviceaccount

role:


- role:
- operations
- objects

- rolebinding:
- user account or service account
- role

- clusterrole

- clusterrolebinding


# kubectl create role --help
# kubectl create rolebinding --help
# kubectl create role pods-reader --verb=get,list,watch --resource=pods --dry-run=client -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: pods-reader
namespace: default
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
# kubectl create rolebinding alex-read-pods --role=pods-reader --user=alex --dry-run=client -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: alex-read-pods
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pods-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: alex

# 接着上面 ServiceAccount 的例子
# kubectl config use-context kubernetes --kubeconfig=/tmp/alex.conf
# kubectl get pods --kubeconfig=/tmp/alex.conf
# kubectl get pods -n kube-system --kubeconfig=/tmp/alex.conf (error from server forbidden)


# kubectl create clusterrole --help
# kubectl create clusterrolebinding --help


- Kubernetes Dashboard
- helm install kubernetes-dashboard/kubernetes-dashboard --version 2.3.0 --name=k8s-dashboard [--namespaces=dashboard]
- helm fetch kubernetes-dashboard/kubernetes-dashboard --version 2.3.0
- tar xf kubernetes-dashboard-2.3.0.tgz
- vim kubernetes-dashboard/values.yaml
- helm install kubernetes-dashboard/kubernetes-dashboard --version 2.3.0 --name=k8s-dashboard -f kubernetes-dashboard/values.yaml [--namespaces=dashboard]
- kubectl create clusterrolebinding k8s-dashboard-admin --clusterrole=cluster-admin --serviceaccount=default:k8s-dashboard / [--serviceaccount=dashboard:k8s-dashboard]
- kubectl describe sa k8s-dashboard [-n dashboard]
- kubectl describe secret k8s-dashboard-token-xxxx [-n dashboard]

- 网络模型及网络策略
flannel
kubectl get daemonset -n kube-system
kubectl get pods -o wide -n kube-system |grep -i kube-flannel
kubectl get configmap -n kube-system
kubectl get configmap kube-flannel-cfg -o json -n kube-system

from 10.244.1.59 ping 10.244.2.76
tcpdump -i cni0 -nn icmp
tcpdump -i flannel.1 -nn
tcpdump -i ens32 -nn host 192.168.137.131
overlay otv

calico

- pod资源调度
调度器:
预选策略:
优先函数:

节点选择器: nodeSelector, nodeName
节点亲和调度: nodeAffinity
taint的effect定义对Pod排斥效果:
NoSchedule:仅影响调度过程,对现存的Pod对象不产生影响;
NoExecute:既影响调度过程,也影响现在的Pod对象;不容忍的Pod对象将被驱逐;
PreferNoSchedule:

- crd、自定义资源、自定义控制器及自定义API server
- HeapSter (数据采集)
- cAdvisor (数据指标检测)
- InfluxDB (历史数据记录: 时序数据库系统)
- Grafana (数据展示)
- RBAC

资源指标:
metrics-server: k8s资源聚合器

自定义指标:
- prometheus
- k8s-prometheus-adapter

- MertricServer
- PrometheusOperator
- NodeExporter
- kubeStateMetrics
- Prometheus
- Grafana


新一代架构:
核心指标流水线:
由kubelet、metrics-server以及由API server提供的api组成;CPU累积使用率、内存实时使用率、Pod的资源占用率及容器的磁盘占用率;
监控流水线:
用于从系统收集各种指标数据并提供终端用户、存储系统以及HPA,它们包含核心指标及许多非核心指标。非核心指标本身不能被k8s所解析,

metrics-server:
API server

- Helm管理器: chart repository
Tiller:
chart:
- 配置清单
- 模板文件
-
helm install mem1 stable/memcached

# kubectl explain ingress.spec
FIELDS:
backend <Object>
resource <Object>
serviceName <string>
servicePort <string>

ingressClassName <string>

rules <[]Object>
host <string>
http <Object>
paths <[]Object> -required-
backend <Object> -required-
path <string>
pathType <string>

tls <[]Object>


Ingress Controller:
- Nginx
- Traefik
- Envoy

namespace: ingress-nginx




Job: 一次性任务
Cronjob: 周期性任务

StatefulSet: 关注个体. 对
EDR: Custom Defined Resources, 1.8+
Operator: etcd

example:
- # ReplicaSet
- vim rs-demo.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: canary
template:
metadata:
name: myapp-pod
labels:
app: myapp
release: canary
environments: qa
sepe:
containers:
- name: myapp-container
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
- kubectl create -f rs-demo.yaml
- kubectl edit rs myapp --> replicas: 5
- kubectl get pods
- kubectl edit rs myapp --> image: ikubernetes/myapp:v2
- kubectl get rs -o wide
- curl xx.xx.xxx.xx # 只有重建的pod会使用新的image

- # Deployment
- vim deploy-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: canary
template:
metadata:
name: myapp-pod
labels:
app: myapp
release: canary
environments: qa
sepe:
containers:
- name: myapp-container
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
- kubectl apply -f deploy-demo.yaml
- kubectl get deploy
- kubectl get rs -o wide
myapp-deploy-69b47bc96d --> 模板的hash值
- kubectl get pods
- kubectl get pods -l app=myapp -w # 新开窗口
- vim deploy-demo.yaml --> image: ikubernetes/myapp:v2
- kubectl apply -f deploy-demo.yaml
- kubectl get rs -o wide
- kubectl rollout history deployment myapp-deploy
# 打补丁方式增加pod
- kubectl patch deployment myapp-deploy -p '{"spec":{"replicas":5}}'
- kubectl get pods

- kubectl patch deployment myapp-deploy -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'
- kubectl describe deployment myapp-deploy
- kubectl get pods -l app=myapp -w # 新开窗口-1
- kubectl set image deployment myapp-deploy myapp=ikubernetes/myapp:v3 && kubectl rollout pause deployment myapp-deploy # 暂停rollout, 金丝雀发布
- kubectl rollout status deployment myapp-deploy # 新开窗口-2
- kubectl rollout resume deployment myapp-deploy --> # 查看新开窗口 1, 2
- kubectl rollout history deployment myapp-deploy # 查看历史版本
- kubectl get rs -o wide

# 回滚版本
- kubectl rollout undo --help
- kubectl rollout undo deployment myapp-deploy --to-revision=1
- kubectl rollout history deployment myapp-deploy # 查看历史版本

- # DaemonSet
- vim ds-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespaces: default
spec:
replicas: 1
selector:
matchLabels:
app: redis
role: logstor
template:
metadata:
labels:
app: redis
role: logstor
spec:
containers:
- name: redis
image: redis:4.0-alpine
ports:
- name: redis
containerPort: 6379
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: filebeat-ds
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: filebeat
release: stable
template:
metadata:
name: filebeat-pod
labels:
app: filebeat
release: stable
sepe:
containers:
- name: filebeat
image: ikubernetes/filebeat:5.6.5-alphine
env:
- name: REDIS_HOST
value: redis.default.svc.cluster.local
- name: REDIS_LOG_LEVEL
value: info
- kubectl apply -f ds-demo.yaml
- kubectl get pods
- kubectl expose deployment redis --port=6379
- kubect get svc
- kubectl exec -it redist-5bxxxx-xxx -- /bin/sh
# netstat -tnl
# nslookup redis.default.svc.cluster.local
# redis-cli -h redis.default.svc.cluster.local
# kyes *

# DaemonSet 滚动更新
- kubectl set image demonsets filebeat-ds filebeat=ikubernets/filebeat-5.6.6-alphine
- kubectl get pods -w # 一个一个的更新.

- # Service
- vim redis-svc.yaml
apiVersion: v1
kind: Service
medatada:
name: redis
namespace: default
spec:
selector:
app: redis
role: logstor
# clusterIP: 10.96.96.96
type: ClusterIP
port:
- port: 6349
targetPort: 6379
- kubectl apply -f redis-svc.yaml
- kubectl get svc
- kubectl describe svc redis
-


- curl xx.xx.xxx.xx # 只有重建的pod会使用新的image


- service资源


Helm: like Linux yum/apt/apk ...




k8s Server
Master
API Server
- port: 6443
- auth: 双向认证, /etc/kubernetes/pki
- config: ~/.kube/config
- kubectl config view
- restful api
- kubectl api-versions
- json
- kubectl get pod == curl https://master:6443/v1/...

- communicate with all the service
- kubectl
- kube-controller-manager
- kube-scheduler
- etcd
- kubelet
- kube-proxy

- api 接口中的资源分成多个逻辑组合 apiVersion
- 和解循环(Reconciliation Loop): status --> spec


Scheduler


Controller
- 和解循环(Reconciliation Loop): status --> spec

Node:
- pod
- service -> iptables/ipvs -> kube-proxy
- kube-proxy

Resource
资源有两个级别:
- 集群级别
- Node
- Namespace
- Role
- ClusterRole
- RoleBinding
- ClusterRoleBinding
- PersistentVolume

- 名称空间级别
- pod
- service
- deploy

- 元数据型资源
- HPA
- PodTemplate
- LimitRange

资源组成部分:
- apiVersion: group/version (kubectl api-versions)
- kind: 资源类别
- metadata
- spec: 资源期望状态
- labels/tag: kubectl label
- annotations: kubectl annotate
- initContainers: kubectl explain pods.spec.initContainers: 容器初始化, 运行前, 运行后, 运行时 (存活检测, 就绪检测)
- lifecycle
- livenessProbe
- readinessProbe
- startupProbe
-
- Containers: kubectl explain pods.spec.Containers: 容器初始化, 运行前, 运行后, 运行时 (存活检测, 就绪检测)
- lifecycle: preStart hook, preStop hook
- livenessProbe
- readinessProbe
- startupProbe

- name:
- command: ["/bin/bash" "-c" "sleep 3600"]
- args:
- image:
- imagePullPolicy:
- Never
- Always
- IfNotPresent
- port:
- name:
- hostIP:
- hostPort:
- protocol
- containerPort



- status: 资源当前状态

资源引用Object URL:
/apis/<GROUP>/<VERSION>/namespaces/<NAMESPACE_NAME>/<KIND>[/OBJECT_ID]/
- /api/GROUP/VERSION/namespaces/NAMESPACE/TYPE/NAME
- kubectl get pod/nginx-ds-s4hpn
- selfLink: /api/v1/namespaces/default/pods/nginx-ds-s4hpn

资源记录:
SVC_NAME.NS_NAME.DOMAIN.LTD.

redis.default.svc.cluster.local

- Pod
- Pod Controller
- Deployment: 类型 --> ngx-deploy --> nginx pod
- Service
- nginx-svc --> 关联到 nginx pod


kubeadm




kubectl
- kubectl explain pods.spec.initContainers
- kubectl -h
- basic commands beginner
- create
- expose
- run
- set

- basic commands intermediate
- explan
- get
- edit
- delete

- deploy commands
- rollout
- scale
- autoscale

- cluster management commands
- certificate
- cluster-info
- top
- cordon
- uncordon
- drain
- taint

- troubleshooting and debugging commands
- describe
- logs
- attach
- exec: kubectl exec -it PodName -c ContainerName -- /bin/sh
- port-forward


- kubectl config view [-o wide/json/yaml]
# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.137.131:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED


- kubectl api-resources: 支持的资源类型 以及缩写
- kubectl get [-o wide/json/yaml] [-n default/kube-system/...] [-L label-name] [-l label-name ==/!= label-value]
- all
- nodes
- pods
- ns/namespace
- default
- kube-public
- kube-system
- deploy
- svc/service


- kubectl create [ -f file]
- job
- namespace
- kubectl create namespace testing
- kubectl create namespace prod
- kubectl create namespace develop
- kubectl get ns
- kubectl delete namespace testing
- kubectl delete ns/prod ns/develop

- deployment
- kubectl create deployment nginx-deploy --image=nginx:1.14-alpine
- kubectl get all -o wide
- pod/nginx-deploy-xxxx (ip: 10.244.1.2)
- deployment.apps/nginx-deploy
- replicaset.apps/nginx-deploy-xxxx
- curl 10.244.1.2 ( welcome nginx!)
- kubectl delete pod/nginx-deploy-xxxx
- kubectl get all -o wide
- pod/nginx-deploy-xxxx (ip: 10.244.3.2)
...
- curl 10.244.3.2 ( welcome nginx!)

- service
- kubectl create service -h
- ClusterIP
- NodePort

- kubectl create service clusterip nginx-deploy --tcp=80:80 (名字和上面deploy保持一致,就会自动分配IP)
- kubectl get svc/nginx-deploy -o yaml
- clusterip: 10.110.129.64
- endpoints: 10.244.3.2

- kubectl describe svc/nginx-deploy

# 删除 pod 测试
- curl 10.110.129.64 ( welcome nginx!)
- kubectl delete pod/nginx-deploy-xxxx
- kubectl get all -o wide
- pod/nginx-deploy-xxxx (ip: 10.244.1.3)
...

- kubectl get svc/nginx-deploy -o yaml
- clusterip: 10.110.129.64
- endpoints: 10.244.1.3 (自动关联到最新的pod)

# 删除 service 测试
- curl nginx-deploy.default.svc.cluster.local. ( welcome nginx!)
- kubectl delete svc/nginx-deploy
- kubectl create service clusterip nginx-deploy --tcp=80:80 (名字和上面deploy保持一致,就会自动分配IP)
- kubectl describe svc/nginx-deploy -o yaml
- clusterip: 10.111.215.249
- endpoints: 10.244.3.2
- curl nginx-deploy.default.svc.cluster.local. ( welcome nginx!)

# 按需伸缩 pod 测试
- kubectl create deploy myapp --image=ikubernetes/myapp:v1
- kubectl get deploy
- kubectl get pods -o wide
- ip : 10.244.3.3
- curl 10.244.3.3
- curl 10.244.3.3/hostname.html (show the pod name: myapp-xxxx-yyyy)

- kubectl create service clusterip myapp --tcp=80:80
- kubectl describe svc/myapp
- IP 10.100.182.218
- Endpoints: 10.244.3.3

- curl nginx-deploy.default.svc.cluster.local. ( welcome myapp!)
- curl nginx-deploy.default.svc.cluster.local/hostname.html (show the pod name: myapp-xxxx-yyyy)
- kubectl scale --replicas=3 myapp (deploy name)

- kubectl describe svc/myapp
- IP 10.100.182.218
- Endpoints: 10.244.3.3, 10.244.1.4, 10.244.2.2

- curl nginx-deploy.default.svc.cluster.local/hostname.html (随机显示不同IP的pod name,多次重复执行查看效果)
- kubectl scale --replicas=2 myapp

- kubectl describe svc/myapp
- IP 10.100.182.218
- Endpoints: 10.244.3.3, 10.244.1.4

# nodeport 外网访问
- kubectl delete svc/myapp
- kubectl create service nodeport -h
- kubectl create service nodeport myapp --tcp=80:80
- kubectl get svc
- ports: 80:31996/TCP
- 集群外部访问所有nodes的 http://nodesip:31996/hostname.html
- 自动创建规则在每一个节点的iptables --> kube-proxy
- ssh nodes "iptables -t nat -vnL"

eg:

- kubectl expose

- kubectl set image deployment myapp myapp=ikubernetes/myapp:v2

- kubectl label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]
kubectl label pods -n dev-namespaces apptag=my-app release=stable deltag-

- kubectl api-versions


- kubectl describe


Network
- node network
- service network: service 注册/发现
- pod network

外网访问:
- Service: NodePort
- hostport:
- hostNetwork:

ipvs/iptables 4 层调度器 ingress 7 层调度器

k8s 安装

[TOC]

一、在master节点上的操作

众多需要下载和安装的包我都已经下载好了放在集群上,所以后面的安装等就是直接从集群backup目录拷贝过来直接用。

master节点配置的服务有,etcd,flannel,docker,kubectl,kube-apiserver,kube-controller-manager,kube-scheduler,kubelete,kube-proxy,kubedns(插件),kube-dashboard(插件)

1.首先设置环境变量

1
2
3
4
5
6
7
8
9
10
11
12
cat /atlas/backup/kubernetes-1.7.6/environment.sh
#!/usr/bin/bash

BOOTSTRAP_TOKEN="41f7e4ba8b7be874fcff18bf5cf41a7c"
SERVICE_CIDR="10.254.0.0/16"
CLUSTER_CIDR="172.30.0.0/16"
export NODE_PORT_RANGE="8400-9000"
export ETCD_ENDPOINTS="http://172.16.10.18:2379,http://172.16.10.10:2379"
export FLANNEL_ETCD_PREFIX="/flannel/network"
export CLUSTER_KUBERNETES_SVC_IP="10.254.0.1"
export CLUSTER_DNS_SVC_IP="10.254.0.2"
export CLUSTER_DNS_DOMAIN="cluster.local."

2.下载cfssl

后面使用cfssl来生成certificate authority

1
2
3
4
cd /atlas/backup/kubernetes-1.7.6/cfssl
cp cfssl_linux-amd64 /usr/local/bin/cfssl
cp cfssljson_linux-amd64 /usr/local/bin/cfssljson
cp cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo

3.创建CA配置文件ca-config.json和签名请求ca-csr.json

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
mkdir /atlas/backup/kubernetes-1.7.6/ssl 
cd /atlas/backup/kubernetes-1.7.6/ssl/
# vim /atlas/backup/kubernetes-1.7.6/ssl/ca-config.json
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "8760h"
}
}
}
}
EOF

# vim /atlas/backup/kubernetes-1.7.6/ssl/ca-csr.json
cat > ca-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF

4.生成证书和私钥

1
2
3
4
5
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
ls ca*
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
mkdir -pv /etc/kubernetes/ssl
cp /atlas/backup/kubernetes-1.7.6/ssl/ca* /etc/kubernetes/ssl

5.加载环境变量

1
2
3
4
5
export NODE_NAME=etcd-host0
export NODE_IP=172.16.10.10
export NODE_IPS="172.16.10.10 172.16.10.18"
export ETCD_NODES=etcd-host0=http://172.16.10.10:2380,etcd-host1=http://172.16.10.18:2380
source /atlas/backup/kubernetes-1.7.6/environment.sh

6.配置etcd服务

kuberntes 系统使用 etcd 存储所有数据,同时flannel网络服务也会把数据保存到etcd中,etcd服务集群只在login节点和master节点搭建。有些教程在etcd集群和flannel集群中加入了ca认证过程,这里为了简单就没有加密。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
yum install -y /atlas/backup/kubernetes-1.7.6/etcd3-3.0.14-2.el7.x86_64.rpm 

cat > /etc/etcd/etcd.conf <<EOF
ETCD_NAME=etcd1
ETCD_DATA_DIR="/var/lib/etcd/etcd1.etcd"
ETCD_LISTEN_PEER_URLS="http://172.16.10.10:2380"
ETCD_LISTEN_CLIENT_URLS="http://172.16.10.10:2379,http://127.0.0.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://172.16.10.10:2380"
ETCD_INITIAL_CLUSTER="etcd1=http://172.16.10.10:2380,etcd2=http://172.16.10.18:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="k8s-etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://172.16.10.10:2379"
EOF

sed -i 's/\\\"${ETCD_LISTEN_CLIENT_URLS}\\\"/\\\"${ETCD_LISTEN_CLIENT_URLS}\\\" --listen-client-urls=\\\"${ETCD_LISTEN_CLIENT_URLS}\\\" --advertise-client-urls=\\\"${ETCD_ADVERTISE_CLIENT_URLS}\\\" --initial-cluster-token=\\\"${ETCD_INITIAL_CLUSTER_TOKEN}\\\" --initial-cluster=\\\"${ETCD_INITIAL_CLUSTER}\\\" --initial-cluster-state=\\\"${ETCD_INITIAL_CLUSTER_STATE}\\\"/g' /usr/lib/systemd/system/etcd.service

7.启动并查看服务

1
2
3
4
systemctl daemon-reload
systemctl enable etcd
systemctl start etcd
systemctl status etcd

在start 的时候会等待一段时间(等待与其他节点的etcd服务通信),这个时候如果登录节点也同时起来了,就会很快。

8.检查etcd集群的健康状况

1
2
3
4
5
6
7
8
for ip in ${NODE_IPS}; do
ETCDCTL_API=3 etcdctl \
--endpoints=http://${ip}:2379 \
endpoint health; done

# 输出结果如下
http://172.16.10.10:2379 is healthy: successfully committed proposal: took = 15.749146ms
http://172.16.10.18:2379 is healthy: successfully committed proposal: took = 11.567679ms

9.配置flannel服务

kubernetes 要求集群内各节点能通过 Pod 网段互联互通,所以配置flannel服务用以解决网络的问题。

1
2
3
4
5
6
7
8
9
10
yum -y install /atlas/backup/kubernetes-1.7.6/flannel-0.7.1-2.el7.x86_64.rpm
# 删除掉docker中默认创建的docker0网络,这个网络之前已经分配了一个不能与其他互通的网络,所以要删除掉他,重启docker的时候会自动重新创建一个。
ip link delete docker0

# 这里配置flannel把数据保存到etcd服务中,同时设置flannel网络使用的网卡名称enp4s0f0(根据具体网卡名称修改)
cat > /etc/sysconfig/flanneld <<EOF
FLANNEL_ETCD_ENDPOINTS="http://172.16.10.10:2379,http://172.16.10.18:2379"
FLANNEL_ETCD_PREFIX="/flannel/network"
FLANNEL_OPTIONS="--iface=enp4s0f0"
EOF

10.启动服务查看状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
systemctl daemon-reload
systemctl enable flanneld
systemctl start flanneld
systemctl status flanneld
ournalctl -u flanneld |grep 'Lease acquired'

Oct 25 15:01:20 master flanneld-start[19831]: I1025 15:01:20.304394 19831 manager.go:250] Lease acquired: 172.30.40.0/24

ifconfig flannel.1
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
inet 172.30.40.0 netmask 255.255.255.255 broadcast 0.0.0.0
ether d2:d6:8b:be:2f:70 txqueuelen 0 (Ethernet)
RX packets 1989 bytes 862786 (842.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2560 bytes 207435 (202.5 KiB)
TX errors 0 dropped 11 overruns 0 carrier 0 collisions 0

11.检查flannel网络服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@master ~]#etcdctl \
> --endpoints=${ETCD_ENDPOINTS} \
> get ${FLANNEL_ETCD_PREFIX}/config
{"Network":"172.30.0.0/16", "SubnetLen": 24, "Backend": {"Type": "vxlan"}}
[root@master ~]#etcdctl \
> --endpoints=${ETCD_ENDPOINTS} \
> ls ${FLANNEL_ETCD_PREFIX}/subnets
/flannel/network/subnets/172.30.50.0-24
/flannel/network/subnets/172.30.68.0-24
/flannel/network/subnets/172.30.89.0-24
/flannel/network/subnets/172.30.7.0-24
/flannel/network/subnets/172.30.40.0-24
/flannel/network/subnets/172.30.34.0-24

# 这里显示了所有节点的flannel服务以及分配的ip段

安装配置docker,master节点也可以作为一个node。docker安装教程这里不再描述。在flannel服务的时候记得删除docker0 服务,如果忘记可以在重启docker前删除。

12.修改docker配置

安装好的docker只需要修改一下docker启动服务,在启动docker的时候加入/run/flannel/docker这个文件中的参数,同时 禁用掉了iptables

1
2
3
4
5
6
vim /usr/lib/systemd/system/docker.service

[Service]
...
EnvironmentFile=-/run/flannel/docker #添加这一行
ExecStart=/usr/bin/dockerd --log-level=error --iptables=false $DOCKER_NETWORK_OPTIONS #修改这一行

13.去掉防火墙

清空掉了iptables,centos7 防火墙默认是拒绝,所以加一条accept在最后。

1
2
3
4
5
iptables -F 
iptables -P FORWARD ACCEPT
systemctl daemon-reload
systemctl enable docker
systemctl start docker

14.kubectl配置

kubectl是一个客户端连接工具,kubectl 默认从 ~/.kube/config 配置文件获取访问 kube-apiserver 地址、证书、用户名等信息。

首先指明kube-apiserver地址,和下载kubectl客户端

1
2
3
4
5
export MASTER_IP=172.16.10.10
export KUBE_APISERVER="https://${MASTER_IP}:6443"
cp /atlas/backup/kubernetes-1.7.6/kubernetes/client/bin/kube* /usr/local/bin/
chmod a+x /usr/local/bin/kube*
chmod a+r /usr/local/bin/kube*

a.添加kubectl证书和秘钥

kubectl 与 kube-apiserver 的安全端口通信,需要为安全通信提供 TLS 证书和秘钥。

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
# vim admin-csr.json
cd /atlas/backup/kubernetes-1.7.6/ssl
cat > admin-csr.json <<EOF
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "system:masters",
"OU": "System"
}
]
}
EOF

cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
-ca-key=/etc/kubernetes/ssl/ca-key.pem \
-config=/etc/kubernetes/ssl/ca-config.json \
-profile=kubernetes admin-csr.json | cfssljson -bare admin

cp admin*.pem /etc/kubernetes/ssl/

创建 kubectl kubeconfig 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER}
# 设置客户端认证参数
kubectl config set-credentials admin \
--client-certificate=/etc/kubernetes/ssl/admin.pem \
--embed-certs=true \
--client-key=/etc/kubernetes/ssl/admin-key.pem
# 设置上下文参数
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=admin
# 设置默认上下文
kubectl config use-context kubernetes

生成的 kubeconfig 被保存到 ~/.kube/config ,拷贝到共享目录方便后面其他节点使用

1
cp -r /root/.kube/config /atlas/backup/kubernetes-1.7.6/.kube

15.配置server

首先拷贝可执行文件

1
cp -r /atlas/backup/kubernetes-1.7.6/kubernetes/server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kube-proxy,kubelet} /usr/local/bin/

证书和私钥

创建签名请求并创建证书和私钥,并放入到指定目录/etc/kubernetes/ssl/

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
cd /atlas/backup/kubernetes-1.7.6/ssl 
cat > kubernetes-csr.json <<EOF
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
"${MASTER_IP}",
"${CLUSTER_KUBERNETES_SVC_IP}",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF

cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
-ca-key=/etc/kubernetes/ssl/ca-key.pem \
-config=/etc/kubernetes/ssl/ca-config.json \
-profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes


mkdir -p /etc/kubernetes/ssl/
cp kubernetes*.pem /etc/kubernetes/ssl/

kubelet 首次启动时向 kube-apiserver 发送 TLS Bootstrapping 请求,kube-apiserver 验证 kubelet 请求中的 token 是否与它配置的 token.csv 一致,如果一致则自动为 kubelet生成证书和秘钥。

1
2
3
4
cat > token.csv <<EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF
mv token.csv /etc/kubernetes/

kube-apiserver

创建 kube-apiserver 的 systemd unit 文件,服务中指定了etcd服务,认证,以及开启rbac等。kube-apiserver提供Restful API,是整个集群管理和控制的入口。apiserver封装了资源对象的CRUD操作并持久化到etcd中,REST API提供给外部客户端和内部组件调用。

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
cat  > kube-apiserver.service <<EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
ExecStart=/usr/local/bin/kube-apiserver \\
--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \\
--advertise-address=${MASTER_IP} \\
--bind-address=${MASTER_IP} \\
--insecure-bind-address=${MASTER_IP} \\
--authorization-mode=RBAC \\
--runtime-config=rbac.authorization.k8s.io/v1alpha1 \\
--kubelet-https=true \\
--experimental-bootstrap-token-auth \\
--token-auth-file=/etc/kubernetes/token.csv \\
--service-cluster-ip-range=${SERVICE_CIDR} \\
--service-node-port-range=${NODE_PORT_RANGE} \\
--tls-cert-file=/etc/kubernetes/ssl/kubernetes.pem \\
--tls-private-key-file=/etc/kubernetes/ssl/kubernetes-key.pem \\
--client-ca-file=/etc/kubernetes/ssl/ca.pem \\
--service-account-key-file=/etc/kubernetes/ssl/ca-key.pem \\
--etcd-cafile=/etc/kubernetes/ssl/ca.pem \\
--etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem \\
--etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem \\
--etcd-servers=${ETCD_ENDPOINTS} \\
--enable-swagger-ui=true \\
--allow-privileged=true \\
--apiserver-count=3 \\
--audit-log-maxage=30 \\
--audit-log-maxbackup=3 \\
--audit-log-maxsize=100 \\
--audit-log-path=/var/lib/audit.log \\
--event-ttl=1h \\
--v=2
Restart=on-failure
RestartSec=5
Type=notify
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

启动服务kube-apiserver

1
2
3
4
5
cp kube-apiserver.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable kube-apiserver
systemctl start kube-apiserver
systemctl status kube-apiserver

kube-controller-manager

配置和启动kube-controller-manager服务,controller-manager是Kubernetes集群中所有资源的自动化控制中心

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
cat > kube-controller-manager.service <<EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-controller-manager \\
--address=127.0.0.1 \\
--master=http://${MASTER_IP}:8080 \\
--allocate-node-cidrs=true \\
--service-cluster-ip-range=${SERVICE_CIDR} \\
--cluster-cidr=${CLUSTER_CIDR} \\
--cluster-name=kubernetes \\
--cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \\
--cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \\
--service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \\
--root-ca-file=/etc/kubernetes/ssl/ca.pem \\
--leader-elect=true \\
--v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

cp kube-controller-manager.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable kube-controller-manager
systemctl start kube-controller-manager
systemctl status kube-controller-manager

kube-scheduler

配置和启动kube-scheduler服务,kube-scheduler是调度器,主要负责Pod调度,每个Pod最终被调度到哪台服务器上是由Scheduler决定的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cat > kube-scheduler.service <<EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-scheduler \\
--address=127.0.0.1 \\
--master=http://${MASTER_IP}:8080 \\
--leader-elect=true \\
--v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

cp kube-scheduler.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable kube-scheduler
systemctl start kube-scheduler
systemctl status kube-scheduler

16.配置node

由于master节点也作为一个node来用,所以也需要相关配置,但其他node配置都是做到openhpc里面,所以这里的配置和其他node的配置不同。

首先拷贝可执行文件

1
cp -r /atlas/backup/kubernetes-1.7.6/kubernetes/server/bin/{kube-proxy,kubelet} /usr/local/bin/

kubelet 启动时向 kube-apiserver 发送 TLS bootstrapping 请求,需要先将 bootstrap token 文件中的 kubelet-bootstrap 用户赋予 system:node-bootstrapper 角色,然后 kubelet 才有权限创建认证请求(certificate signing requests):

1
kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap

创建 kubelet bootstrapping kubeconfig 文件,拷贝到指定目录中/etc/kubernetes/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=bootstrap.kubeconfig
# 设置客户端认证参数
kubectl config set-credentials kubelet-bootstrap \
--token=${BOOTSTRAP_TOKEN} \
--kubeconfig=bootstrap.kubeconfig
# 设置上下文参数
kubectl config set-context default \
--cluster=kubernetes \
--user=kubelet-bootstrap \
--kubeconfig=bootstrap.kubeconfig
# 设置默认上下文
kubectl config use-context default --kubeconfig=bootstrap.kubeconfig
cp bootstrap.kubeconfig /etc/kubernetes/

这个文件在所有node都要用,所以拷贝到公共目录。

1
cp bootstrap.kubeconfig /atlas/backup/kubernetes-1.7.6/node 

创建 kubelet 的 systemd unit 文件,kubelet主要负责本节点Pod的生命周期管理,定期向Master上报本节点及Pod的基本信息。kubelet会从apiserver接收Pod的创建请求,启动和停止Pod。每个node的这个文件只是node_ip值不一样,其他都相同。

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
cat > kubelet.service <<EOF
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service

[Service]
WorkingDirectory=/var/lib/kubelet
ExecStart=/usr/local/bin/kubelet \\
--address=${NODE_IP} \\
--hostname-override=${NODE_IP} \\
--pod-infra-container-image=172.16.10.10:5000/pod-infrastructure:latest \\
--experimental-bootstrap-kubeconfig=/etc/kubernetes/bootstrap.kubeconfig \\
--kubeconfig=/etc/kubernetes/kubelet.kubeconfig \\
--require-kubeconfig \\
--cert-dir=/etc/kubernetes/ssl \\
--cluster-dns=${CLUSTER_DNS_SVC_IP} \\
--cluster-domain=${CLUSTER_DNS_DOMAIN} \\
--hairpin-mode promiscuous-bridge \\
--allow-privileged=true \\
--serialize-image-pulls=false \\
--logtostderr=true \\
--v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

在node节点首次启动时,会去下载pod-infrastructure镜像,由于集群下载该镜像很慢,所以把他做到了本地,修改了server配置文件。

1
2
3
4
5
6
7
[root@node7 dashboard]#docker images 
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.access.redhat.com/rhel7/pod-infrastructure latest 99965fb98423 7 weeks ago 209MB
172.16.10.10:5000/pod-infrastructure latest 1158bd68df6d 3 months ago 209MB
# 由于集群上下载pod-infrastructure 镜像较慢,因此把他做成本地repository
--pod-infra-container-image=172.16.10.10:5000/pod-infrastructure:latest \\
--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest \\

17.启动kubelete服务

1
2
3
4
5
cp kubelet.service /etc/systemd/system/kubelet.service
systemctl daemon-reload
systemctl enable kubelet
systemctl start kubelet
systemctl status kubelet

测试检验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
kubectl get csr
NAME AGE REQUESTOR CONDITION
csr-n62mb 18s kubelet-bootstrap Pending
# pending表示为未认证的,Approved,Issued表示已通过的
kubectl certificate approve csr-n62mb
certificatesigningrequest "csr-n62mb" approved
# 这样就可以看到加入进来的node
kubectl get nodes
NAME STATUS AGE VERSION
172.16.10.17 Ready 20s v1.6.10

kubectl get csr
NAME AGE REQUESTOR CONDITION
node-csr-2JEdaLskngS2xSbyM0vihsxKe0gliuXbtVgu5WSTxcY 2d kubelet-bootstrap Approved,Issued
node-csr-AXt9Sy1PgX9zOze6V6PxXwTCrxXNKBlKEdsgrN4I_k0 1d kubelet-bootstrap Approved,Issued

经过上面的测试检验,认证。node这边自动生成了 kubelet kubeconfig 文件和公私钥

1
2
3
4
5
6
7
8
ls -l /etc/kubernetes/kubelet.kubeconfig
-rw-------. 1 root root 2279 Oct 12 16:35 /etc/kubernetes/kubelet.kubeconfig

ls -l /etc/kubernetes/ssl/kubelet*
-rw-r--r--. 1 root root 1046 Oct 12 16:35 /etc/kubernetes/ssl/kubelet-client.crt
-rw-------. 1 root root 227 Oct 12 16:34 /etc/kubernetes/ssl/kubelet-client.key
-rw-r--r--. 1 root root 1111 Oct 12 16:35 /etc/kubernetes/ssl/kubelet.crt
-rw-------. 1 root root 1675 Oct 12 16:35 /etc/kubernetes/ssl/kubelet.key

18.kube-proxy服务

kube-proxy实现Kubernetes上Service的通信及负载均衡。配置kube-proxy 服务,证书请求,认证和私钥。创建 kube-proxy kubeconfig 文件,创建 kube-proxy 的 systemd unit 文件,并启动服务。一并写入下面

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
cd /atlas/backup/kubernetes-1.7.6/ssl/node/
cat > /atlas/backup/kubernetes-1.7.6/ssl/node/kube-proxy-csr.json <<EOF
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF

cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
-ca-key=/etc/kubernetes/ssl/ca-key.pem \
-config=/etc/kubernetes/ssl/ca-config.json \
-profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy

cp kube-proxy*.pem /etc/kubernetes/ssl/
cp kube-proxy*.pem /atlas/backup/kubernetes-1.7.6/ssl/node

# 设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=kube-proxy.kubeconfig
# 设置客户端认证参数
kubectl config set-credentials kube-proxy \
--client-certificate=/etc/kubernetes/ssl/kube-proxy.pem \
--client-key=/etc/kubernetes/ssl/kube-proxy-key.pem \
--embed-certs=true \
--kubeconfig=kube-proxy.kubeconfig
# 设置上下文参数
kubectl config set-context default \
--cluster=kubernetes \
--user=kube-proxy \
--kubeconfig=kube-proxy.kubeconfig
# 设置默认上下文
kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig

cp kube-proxy.kubeconfig /etc/kubernetes/
cp /atlas/backup/kubernetes-1.7.6/ssl/node/kube-proxy.kubeconfig /etc/kubernetes/

mkdir -p /var/lib/kube-proxy
cat > kube-proxy.service <<EOF
[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
WorkingDirectory=/var/lib/kube-proxy
ExecStart=/usr/local/bin/kube-proxy \\
--bind-address=${NODE_IP} \\
--hostname-override=${NODE_IP} \\
--cluster-cidr=${SERVICE_CIDR} \\
--kubeconfig=/etc/kubernetes/kube-proxy.kubeconfig \\
--logtostderr=true \\
--v=2
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

cp kube-proxy.service /etc/systemd/system/

systemctl daemon-reload
systemctl enable kube-proxy
systemctl start kube-proxy
systemctl status kube-proxy

19.kubedns

部署kubedns插件,这个插件有一个官方文件目录:kubernetes/cluster/addons/dns

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
mkdir /atlas/backup/kubernetes-1.7.6/dns 
cd /atlas/backup/kubernetes-1.7.6/kubernetes/cluster/addons/dns
cp *.yaml *.base /root/dns
cp kubedns-controller.yaml.base kubedns-controller.yaml
cp kubedns-svc.yaml.base kubedns-svc.yaml


diff kubedns-svc.yaml.base kubedns-svc.yaml
30c30
< clusterIP: __PILLAR__DNS__SERVER__
---
> clusterIP: 10.254.0.2




diff kubedns-controller.yaml.base kubedns-controller.yaml
58c58
< image: gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.4
---
> image: 172.16.10.10:5000/k8s-dns-kube-dns-amd64:v1.14.4
88c88
< - --domain=__PILLAR__DNS__DOMAIN__.
---
> - --domain=cluster.local.
92c92
< __PILLAR__FEDERATIONS__DOMAIN__MAP__
---
> #__PILLAR__FEDERATIONS__DOMAIN__MAP__
110c110
< image: gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.4
---
> image: 172.16.10.10:5000/k8s-dns-dnsmasq-nanny-amd64:v1.14.4
129c129
< - --server=/__PILLAR__DNS__DOMAIN__/127.0.0.1#10053
---
> - --server=/cluster.local./127.0.0.1#10053
148c148
< image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.4
---
> image: 172.16.10.10:5000/k8s-dns-sidecar-amd64:v1.14.4
161,162c161,162
< - --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.__PILLAR__DNS__DOMAIN__,5,A
< - --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.__PILLAR__DNS__DOMAIN__,5,A
---
> - --probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.cluster.local.,5,A
> - --probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.cluster.local.,5,A


ls /root/dns/*.yaml
kubedns-cm.yaml kubedns-controller.yaml kubedns-sa.yaml kubedns-svc.yaml
kubectl create -f .

主要是修改域名,和image。由于在集群上无法下载Google镜像,因此我提前把他下载到了集群,然后放在了私有仓库中,所以在这里就直接从私有仓库获取images。

检查kubedns

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
cat > my-nginx.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: 172.16.10.10:5000/nginx:1.7.9
ports:
- containerPort: 80
EOF
kubectl create -f my-nginx.yaml
kubectl expose deploy my-nginx
kubectl get services --all-namespaces |grep my-nginx
default my-nginx 10.254.189.4 <none> 80/TCP 14m


cat > pod-nginx.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: 172.16.10.10:5000/nginx:1.7.9
ports:
- containerPort: 80
EOF

kubectl create -f pod-nginx.yaml
kubectl exec nginx -i -t -- /bin/bash
root@nginx:/# cat /etc/resolv.conf
nameserver 10.254.0.2
search default.svc.cluster.local svc.cluster.local cluster.local tjwq01.ksyun.com
options ndots:5

root@nginx:/# ping my-nginx
PING my-nginx.default.svc.cluster.local (10.254.86.48): 48 data bytes

root@nginx:/# ping kubernetes
PING kubernetes.default.svc.cluster.local (10.254.0.1): 48 data bytes

root@nginx:/# ping kube-dns.kube-system.svc.cluster.local
PING kube-dns.kube-system.svc.cluster.local (10.254.0.2): 48 data bytes

20.dashboard

部署dashboard插件,官方文件目录:kubernetes/cluster/addons/dashboard

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
mkidr /atlas/backup/kubernetes-1.7.6/kubernetes/dashboard
cd /atlas/backup/kubernetes-1.7.6/kubernetes/cluster/addons/dashboard/
ls *.yaml
dashboard-controller.yaml dashboard-service.yaml
cp /atlas/backup/kubernetes-1.7.6/kubernetes/cluster/addons/dashboard/*.yaml /atlas/backup/kubernetes-1.7.6/dashboard

cat > dashboard-rbac.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: dashboard
namespace: kube-system

---

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1alpha1
metadata:
name: dashboard
subjects:
- kind: ServiceAccount
name: dashboard
namespace: kube-system
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
EOF



diff dashboard-service.yaml.orig dashboard-service.yaml
10a11
> type: NodePort

diff dashboard-controller.orig dashboard-controller
20a21
> serviceAccountName: dashboard
23c24
< image: gcr.io/google_containers/kubernetes-dashboard-amd64:v1.6.1
---
> image: 172.16.10.10:5000/kubernetes-dashboard-amd64:v1.6.1


ls *.yaml
dashboard-controller.yaml dashboard-rbac.yaml dashboard-service.yaml
kubectl create -f .

检验测试

1
2
3
4
5
6
7
8
9
10
11
kubectl get services kubernetes-dashboard -n kube-system
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes-dashboard 10.254.229.169 <nodes> 80:8895/TCP 2d

kubectl get deployment kubernetes-dashboard -n kube-system
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kubernetes-dashboard 1 1 1 1 2d
1 3m

kubectl get pods -n kube-system | grep dashboard
kubernetes-dashboard-3677875397-1zwhg 1/1 Running 0 2d

访问dashboard有三种方法

  1. kubernetes-dashboard 服务暴露了 NodePort,可以使用 http://NodeIP:nodePort 地址访问 dashboard;

  2. 通过 kube-apiserver 访问 dashboard;

  3. 通过 kubectl proxy 访问 dashboard:

通过 kubectl proxy 访问 dashboard

1
2
kubectl proxy --address='172.16.10.10' --port=8086 --accept-hosts='^*$'
Starting to serve on 172.16.10.10:8086

在浏览器中打开 http://172.16.10.10:8086/ui自动跳转到:http://172.16.10.10:8086/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard/#/workload?namespace=default

通过 kube-apiserver 访问dashboard

1
2
3
4
5
6
kubectl cluster-info
Kubernetes master is running at https://172.16.10.10:6443
KubeDNS is running at https://172.16.10.10:6443/api/v1/namespaces/kube-system/services/kube-dns/proxy
kubernetes-dashboard is running at https://172.16.10.10:6443/api/v1/namespaces/kube-system/services/kubernetes-dashboard/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

由于 kube-apiserver 开启了 RBAC 授权,而浏览器访问 kube-apiserver 的时候使用的是匿名证书,所以访问安全端口会导致授权失败。这里需要使用非安全端口访问 kube-apiserver:

浏览器访问 URL:http://172.16.10.10:8080/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard

1

由于缺少 Heapster 插件,当前 dashboard 不能展示 Pod、Nodes 的 CPU、内存等 metric 图形;

二、在login上的操作

login节点只需要配置etcd集群服务和kubectl客户端

首先加载环境变量

1
2
3
4
5
export NODE_NAME=etcd-host1
export NODE_IP=172.16.10.18、
export NODE_IPS="172.16.10.10 172.16.10.18"
export ETCD_NODES=etcd-host0=http://172.16.10.10:2380,etcd-host1=http://172.16.10.18:2380
source /atlas/backup/kubernetes-1.7.6/environment.sh
1
2
mkdir -pv /etc/kubernetes/ssl
cp /atlas/backup/kubernetes-1.7.6/ssl/ca* /etc/kubernetes/ssl

搭建etcd服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
yum install -y /atlas/backup/kubernetes-1.7.6/etcd3-3.0.14-2.el7.x86_64.rpm 

cat > /etc/etcd/etcd.conf <<EOF
ETCD_NAME=etcd1
ETCD_DATA_DIR="/var/lib/etcd/etcd1.etcd"
ETCD_LISTEN_PEER_URLS="http://172.16.10.18:2380"
ETCD_LISTEN_CLIENT_URLS="http://172.16.10.18:2379,http://127.0.0.1:2379"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://172.16.10.18:2380"
ETCD_INITIAL_CLUSTER="etcd1=http://172.16.10.10:2380,etcd2=http://172.16.10.18:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="k8s-etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://172.16.10.18:2379"
EOF

sed -i 's/\\\"${ETCD_LISTEN_CLIENT_URLS}\\\"/\\\"${ETCD_LISTEN_CLIENT_URLS}\\\" --listen-client-urls=\\\"${ETCD_LISTEN_CLIENT_URLS}\\\" --advertise-client-urls=\\\"${ETCD_ADVERTISE_CLIENT_URLS}\\\" --initial-cluster-token=\\\"${ETCD_INITIAL_CLUSTER_TOKEN}\\\" --initial-cluster=\\\"${ETCD_INITIAL_CLUSTER}\\\" --initial-cluster-state=\\\"${ETCD_INITIAL_CLUSTER_STATE}\\\"/g' /usr/lib/systemd/system/etcd.service


systemctl daemon-reload
systemctl enable etcd
systemctl start etcd
systemctl status etcd

kubectl

1
2
3
4
5
6
cp /atlas/backup/kubernetes-1.7.6/kubernetes/client/bin/kube* /usr/local/bin/
chmod a+x /usr/local/bin/kube*
chmod a+r /usr/local/bin/kube*
mkdir /root/.kube
cp -r /atlas/backup/kubernetes-1.7.6/.kube/config /root/.kube

三、在node节点的操作

node节点操作比较特殊,集群所有节点使用openhpc运行,由于直接在node配置kubernetes后,重启失效。所以必须要做到openhpc中。

首先把所有需要的安装包和二进制程序拷贝到openhpc中

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
cp /atlas/backup/kubernetes-1.7.6/environment.sh /atlas/os_images/compute_node_v0.2.0/usr/local/bin
cp /atlas/backup/kubernetes-1.7.6/ssl/ca* /atlas/os_images/compute_node_v0.2.0/etc/kubernetes/ssl
cp /atlas/backup/kubernetes-1.7.6/flannel-0.7.1-2.el7.x86_64.rpm /atlas/os_images/compute_node_v0.2.0/tmp

cat > /atlas/os_images/compute_node_v0.2.0/etc/sysconfig/flanneld <<EOF
FLANNEL_ETCD_ENDPOINTS="http://172.16.10.10:2379,http://172.16.10.18:2379"
FLANNEL_ETCD_PREFIX="/flannel/network"
FLANNEL_OPTIONS="--iface=eth0"
EOF

cp /atlas/backup/kubernetes-1.7.6/kubernetes/client/bin/kube* /atlas/os_images/compute_node_v0.2.0/usr/local/bin/
chmod a+x /atlas/os_images/compute_node_v0.2.0/usr/local/bin/kube*
chmod a+r /atlas/os_images/compute_node_v0.2.0/usr/local/bin/kube*

mkdir /atlas/os_images/compute_node_v0.2.0/root/.kube -pv
cp /atlas/backup/kubernetes-1.7.6/.kube/config /atlas/os_images/compute_node_v0.2.0/root/.kube

cp -r /atlas/backup/kubernetes-1.7.6/kubernetes/server/bin/{kube-proxy,kubelet} /atlas/os_images/compute_node_v0.2.0/usr/local/bin/

cp /atlas/backup/kubernetes-1.7.6/ssl/node/bootstrap.kubeconfig /atlas/os_images/compute_node_v0.2.0/etc/kubernetes/

mkdir /atlas/os_images/compute_node_v0.2.0/var/lib/kubelet

cp /atlas/backup/kubernetes-1.7.6/ssl/node/kube-proxy.kubeconfig /atlas/os_images/compute_node_v0.2.0/etc/kubernetes/

mkdir -p /atlas/os_images/compute_node_v0.2.0/var/lib/kube-proxy

chroot到openhpc中,安装flannel,修改docker配置,创建开机启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
chroot /atlas/os_images/compute_node_v0.2.0
yum install -y -q vim bash-completion tree /tmp/flannel-0.7.1-2.el7.x86_64.rpm

vim /usr/lib/systemd/system/docker.service

[Service]
...
EnvironmentFile=-/run/flannel/docker
ExecStart=/usr/bin/dockerd --log-level=error --iptables=false $DOCKER_NETWORK_OPTIONS

cd /etc/systemd/system/multi-user.target.wants
#systemctl enable flanneld
ln -sv /usr/lib/systemd/system/flanneld.service flanneld.service
#systemctl enable docker
ln -sv /usr/lib/systemd/system/docker.service docker.service

ln -sv /etc/systemd/system/kubelet.service kubelet.service
ln -sv /etc/systemd/system/kube-proxy.service kube-proxy.service
exit

由于每个node节点的kubelete服务和kube-proxy服务的unit文件不同,所以要通过openhpc的的特殊配置实现。首先是写好每个node的unit,拷贝到制定目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cd /opt/ohpc/pub/examples/network/centos

cp /atlas/backup/kubernetes-1.7.6/ssl/node1/kubelet.service node1-kubelet.service
cp /atlas/backup/kubernetes-1.7.6/ssl/node1/kube-proxy.service node1-kube-proxy.service

cp /atlas/backup/kubernetes-1.7.6/ssl/node2/kubelet.service node2-kubelet.service
cp /atlas/backup/kubernetes-1.7.6/ssl/node2/kube-proxy.service node2-kube-proxy.service

cp /atlas/backup/kubernetes-1.7.6/ssl/node3/kubelet.service node3-kubelet.service
cp /atlas/backup/kubernetes-1.7.6/ssl/node3/kube-proxy.service node3-kube-proxy.service

cp /atlas/backup/kubernetes-1.7.6/ssl/node4/kubelet.service node4-kubelet.service
cp /atlas/backup/kubernetes-1.7.6/ssl/node4/kube-proxy.service node4-kube-proxy.service

cp /atlas/backup/kubernetes-1.7.6/ssl/node5/kubelet.service node5-kubelet.service
cp /atlas/backup/kubernetes-1.7.6/ssl/node5/kube-proxy.service node5-kube-proxy.service

cp /atlas/backup/kubernetes-1.7.6/ssl/node6/kubelet.service node6-kubelet.service
cp /atlas/backup/kubernetes-1.7.6/ssl/node6/kube-proxy.service node6-kube-proxy.service

cp /atlas/backup/kubernetes-1.7.6/ssl/node7/kubelet.service node7-kubelet.service
cp /atlas/backup/kubernetes-1.7.6/ssl/node7/kube-proxy.service node7-kube-proxy.service

通过openhpc的wwsh命令 分配到每一个node节点

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
wwsh
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node1-kubelet.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node2-kubelet.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node3-kubelet.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node4-kubelet.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node5-kubelet.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node6-kubelet.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node7-kubelet.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node1-kube-proxy.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node2-kube-proxy.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node3-kube-proxy.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node4-kube-proxy.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node5-kube-proxy.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node6-kube-proxy.service
Warewulf> file import /opt/ohpc/pub/examples/network/centos/node7-kube-proxy.service

#一下省略了“Warewulf>”
file set node1-kube-proxy.service node2-kube-proxy.service node3-kube-proxy.service node4-kube-proxy.service node5-kube-proxy.service node6-kube-proxy.service node7-kube-proxy.service --path=/etc/systemd/system/kube-proxy.service

file set node1-kubelet.service node2-kubelet.service node3-kubelet.service node4-kubelet.service node5-kubelet.service node6-kubelet.service node7-kubelet.service --path=/etc/systemd/system/kubelet.service

provision set node1 --fileadd=node1-kube-proxy.service --fileadd=node1-kubelet.service
provision set node2 --fileadd=node2-kube-proxy.service --fileadd=node2-kubelet.service
provision set node3 --fileadd=node3-kube-proxy.service --fileadd=node3-kubelet.service
provision set node4 --fileadd=node4-kube-proxy.service --fileadd=node4-kubelet.service
provision set node5 --fileadd=node5-kube-proxy.service --fileadd=node5-kubelet.service
provision set node6 --fileadd=node6-kube-proxy.service --fileadd=node6-kubelet.service
provision set node7 --fileadd=node7-kube-proxy.service --fileadd=node7-kubelet.service
exit

最后将配置好的unit制作到container中。reboot所有node节点即可。

node节点在认证通过csr之后,自动生成了公钥和私钥,但是如果某一个node服务器宕机重启之后,还要重新认证。为了解决这个问题,我把生成的公私钥放到openhpc中,系统重启自动加载。操作步骤如下

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
#将node#节点的公私钥都拷贝出来
cp kubelet.kubeconfig ssl/* /atlas/backup/kubernetes-1.7.6/ssl/node#/

#master节点上,重命名所有的公私钥,加一个前缀
rename kube node1-kube ./*
cp -n ./* /opt/ohpc/pub/examples/network/centos/

rename kube node2-kube ./*
cp -n ./* /opt/ohpc/pub/examples/network/centos/

rename kube node3-kube ./*
cp -n ./* /opt/ohpc/pub/examples/network/centos/

rename kube node4-kube ./*
cp -n ./* /opt/ohpc/pub/examples/network/centos/

rename kube node5-kube ./*
cp -n ./* /opt/ohpc/pub/examples/network/centos/

rename kube node6-kube ./*
cp -n ./* /opt/ohpc/pub/examples/network/centos/

rename kube node7-kube ./*
cp -n ./* /opt/ohpc/pub/examples/network/centos/

#导入所有node的公私钥到openhpc中
wwsh
file import node1-kubelet-client.crt node1-kubelet-client.key node1-kubelet.crt node1-kubelet.key node1-kubelet.kubeconfig node2-kubelet-client.crt node2-kubelet-client.key node2-kubelet.crt node2-kubelet.key node2-kubelet.kubeconfig node3-kubelet-client.crt node3-kubelet-client.key node3-kubelet.crt node3-kubelet.key node3-kubelet.kubeconfig node4-kubelet-client.crt node4-kubelet-client.key node4-kubelet.crt node4-kubelet.key node4-kubelet.kubeconfig node5-kubelet-client.crt node5-kubelet-client.key node5-kubelet.crt node5-kubelet.key node5-kubelet.kubeconfig node6-kubelet-client.crt node6-kubelet-client.key node6-kubelet.crt node6-kubelet.key node6-kubelet.kubeconfig node7-kubelet-client.crt node7-kubelet-client.key node7-kubelet.crt node7-kubelet.key node7-kubelet.kubeconfig

#指定公私钥放入node节点的具体位置
file set node1-kubelet-client.crt node2-kubelet-client.crt node3-kubelet-client.crt node4-kubelet-client.crt node5-kubelet-client.crt node6-kubelet-client.crt node7-kubelet-client.crt --path=/etc/kubernetes/ssl/kubelet-client.crt
file set node1-kubelet-client.key node2-kubelet-client.key node3-kubelet-client.key node4-kubelet-client.key node5-kubelet-client.key node6-kubelet-client.key node7-kubelet-client.key --path=/etc/kubernetes/ssl/kubelet-client.key
file set node1-kubelet.crt node2-kubelet.crt node3-kubelet.crt node4-kubelet.crt node5-kubelet.crt node6-kubelet.crt node7-kubelet.crt --path=/etc/kubernetes/ssl/kubelet.crt
file set node1-kubelet.key node2-kubelet.key node3-kubelet.key node4-kubelet.key node5-kubelet.key node6-kubelet.key node7-kubelet.key --path=/etc/kubernetes/ssl/kubelet.key
file set node1-kubelet.kubeconfig node2-kubelet.kubeconfig node3-kubelet.kubeconfig node4-kubelet.kubeconfig node5-kubelet.kubeconfig node6-kubelet.kubeconfig node7-kubelet.kubeconfig --path=/etc/kubernetes/kubelet.kubeconfig

#不同节点添加不同的的公私钥
provision set node1 --fileadd=node1-kubelet-client.crt --fileadd=node1-kubelet-client.key --fileadd=node1-kubelet.crt --fileadd=node1-kubelet.key --fileadd=node1-kubelet.kubeconfig
provision set node2 --fileadd=node2-kubelet-client.crt --fileadd=node2-kubelet-client.key --fileadd=node2-kubelet.crt --fileadd=node2-kubelet.key --fileadd=node2-kubelet.kubeconfig
provision set node3 --fileadd=node3-kubelet-client.crt --fileadd=node3-kubelet-client.key --fileadd=node3-kubelet.crt --fileadd=node3-kubelet.key --fileadd=node3-kubelet.kubeconfig
provision set node4 --fileadd=node4-kubelet-client.crt --fileadd=node4-kubelet-client.key --fileadd=node4-kubelet.crt --fileadd=node4-kubelet.key --fileadd=node4-kubelet.kubeconfig
provision set node5 --fileadd=node5-kubelet-client.crt --fileadd=node5-kubelet-client.key --fileadd=node5-kubelet.crt --fileadd=node5-kubelet.key --fileadd=node5-kubelet.kubeconfig
provision set node6 --fileadd=node6-kubelet-client.crt --fileadd=node6-kubelet-client.key --fileadd=node6-kubelet.crt --fileadd=node6-kubelet.key --fileadd=node6-kubelet.kubeconfig
provision set node7 --fileadd=node7-kubelet-client.crt --fileadd=node7-kubelet-client.key --fileadd=node7-kubelet.crt --fileadd=node7-kubelet.key --fileadd=node7-kubelet.kubeconfig

file sync
wwsh file sync

01-Kubernetes 基础概念和架构解析

[TOC]

1.服务部署的发展

为什么我们需要Kubernetes? 我们先来看看服务部署的发展. 如下图:

![container_evolution](02-kubernetes concepts/container_evolution.svg)

1.1 传统部署时代

早期,组织在物理服务器上运行应用程序。无法为物理服务器中的应用程序定义资源边界,这会导致资源分配问题。例如,如果在物理服务器上运行多个应用程序,则可能会出现一个应用程序占用大部分资源的情况,结果可能导致其他应用程序的性能下降。一种解决方案是在不同的物理服务器上运行每个应用程序,但是由于资源利用不足而无法扩展,并且组织维护许多物理服务器的成本很高。

1.2 虚拟化部署时代

作为解决方案,引入了虚拟化功能,它允许您在单个物理服务器的 CPU 上运行多个虚拟机(VM)。于是有了xen, kvm, vmware 和 virualbox 等虚拟化应用的出现.

虚拟化功能允许应用程序在 VM 之间隔离,并提供安全级别,因为一个应用程序的信息不能被另一应用程序自由地访问。

因为虚拟化可以轻松地添加或更新应用程序、降低硬件成本等等,所以虚拟化可以更好地利用物理服务器中的资源,并可以实现更好的可伸缩性。

每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统。

1.3 容器部署时代

容器类似于 VM,但是它们具有轻量级的隔离属性,可以在应用程序之间共享操作系统(OS)。因此,容器被认为是轻量级的。容器与 VM 类似,具有自己的文件系统、CPU、内存、进程空间等。由于它们与基础架构分离,因此可以跨云和 OS 分发进行移植。

容器因具有许多优势而变得流行起来。于是docker闪亮登场, 下面列出了容器的一些好处:

  • 敏捷应用程序的创建和部署:与使用 VM 镜像相比,提高了容器镜像创建的简便性和效率。
  • 持续开发、集成和部署:通过快速简单的回滚(由于镜像不可变性),提供可靠且频繁的容器镜像构建和部署。
  • 关注开发与运维的分离:在构建/发布时而不是在部署时创建应用程序容器镜像,从而将应用程序与基础架构分离。
  • 可观察性不仅可以显示操作系统级别的信息和指标,还可以显示应用程序的运行状况和其他指标信号。
  • 跨开发、测试和生产的环境一致性:在便携式计算机上与在云中相同地运行。
  • 云和操作系统分发的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、Google Engine 和其他任何地方运行。
  • 以应用程序为中心的管理:提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序。
  • 松散耦合、分布式、弹性、解放的微服务:应用程序被分解成较小的独立部分,并且可以动态部署和管理 - 而不是在一台大型单机上整体运行。
  • 资源隔离:可预测的应用程序性能。
  • 资源利用:高效率和高密度。

容器是打包和运行应用程序的好方式。在生产环境中,您需要管理运行应用程序的容器,并确保不会停机。例如,如果一个容器发生故障,则需要启动另一个容器。如果系统处理此行为,会不会更容易?

这就是 Kubernetes 的救援方法!

2 Kubernetes简介

Kubernetes 是一个可移植的,可扩展的开源平台,用于管理容器化的工作负载和服务,方便了声明式配置和自动化。它拥有一个庞大且快速增长的生态系统。Kubernetes 的服务,支持和工具广泛可用。

2.1 Kubernetes 功能

Kubernetes 提供的功能:

  • 服务发现和负载均衡
    Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果到容器的流量很大,Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。

  • 存储编排
    Kubernetes 允许您自动挂载您选择的存储系统,例如本地存储、公共云提供商等。

  • 自动部署和回滚
    您可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态更改为所需状态。例如,您可以自动化 Kubernetes 来为您的部署创建新容器,删除现有容器并将它们的所有资源用于新容器。

  • 自动二进制打包
    Kubernetes 允许您指定每个容器所需 CPU 和内存(RAM)。当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源。

  • 自我修复
    Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器,并且在准备好服务之前不将其通告给客户端。

  • 密钥与配置管理
    Kubernetes 允许您存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。您可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

2.2 Kubernetes 不做哪些事情?

Kubernetes 不是传统的、包罗万象的 PaaS(平台即服务)系统。由于 Kubernetes 在容器级别而不是在硬件级别运行,因此它提供了 PaaS 产品共有的一些普遍适用的功能,例如部署、扩展、负载均衡、日志记录和监视。但是,Kubernetes 不是单一的,默认解决方案是可选和可插拔的。Kubernetes 提供了构建开发人员平台的基础,但是在重要的地方保留了用户的选择和灵活性。

Kubernetes:

  • Kubernetes 不限制支持的应用程序类型。Kubernetes 旨在支持极其多种多样的工作负载,包括无状态、有状态和数据处理工作负载。如果应用程序可以在容器中运行,那么它应该可以在 Kubernetes 上很好地运行。

  • Kubernetes 不部署源代码,也不构建您的应用程序。持续集成(CI)、交付和部署(CI/CD)工作流取决于组织的文化和偏好以及技术要求。

  • Kubernetes 不提供应用程序级别的服务作为内置服务,例如中间件(例如,消息中间件)、数据处理框架(例如,Spark)、数据库(例如,mysql)、缓存、集群存储系统(例如,Ceph)。这样的组件可以在 Kubernetes 上运行,并且/或者可以由运行在 Kubernetes 上的应用程序通过可移植机制来访问。

  • Kubernetes 不指定日志记录、监视或警报解决方案。它提供了一些集成作为概念证明,并提供了收集和导出指标的机制。

  • Kubernetes 不提供或不要求配置语言/系统(例如 jsonnet),它提供了声明性 API,该声明性 API 可以由任意形式的声明性规范所构成。

  • Kubernetes 不提供也不采用任何全面的机器配置、维护、管理或自我修复系统。

  • 此外,Kubernetes 不仅仅是一个编排系统,实际上它消除了编排的需要。编排的技术定义是执行已定义的工作流程:首先执行 A,然后执行 B,再执行 C。相比之下,Kubernetes 包含一组独立的、可组合的控制过程,这些过程连续地将当前状态驱动到所提供的所需状态。从 A 到 C 的方式无关紧要,也不需要集中控制,这使得系统更易于使用且功能更强大、健壮、弹性和可扩展性。

3. Kubernetes 组件

当你部署完 Kubernetes, 即拥有了一个完整的集群。

一个 Kubernetes 集群包含 集群由一组被称作节点的机器组成。这些节点上运行 Kubernetes 所管理的容器化应用。集群具有至少一个工作节点和至少一个主节点。

工作节点托管作为应用程序组件的 Pod 。主节点管理集群中的工作节点和 Pod 。多个主节点用于为集群提供故障转移和高可用性。

下图表展示了包含所有相互关联组件的 Kubernetes 集群。

![components-of-kubernetes](02-kubernetes concepts/components-of-kubernetes.png)

控制平面组件(Control Plane Components)

也叫master节点, 控制平面的组件对集群做出全局决策(比如调度),以及检测和响应集群事件。

kube-apiserver

主节点上负责提供 Kubernetes API 服务的组件;它是 Kubernetes 控制面的前端。

etcd

etcd 是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。

kube-scheduler

主节点上的组件,该组件监视那些新创建的未指定运行节点的 Pod,并选择节点让 Pod 在上面运行。

调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。

kube-controller-manager

在主节点上运行控制器的组件。

从逻辑上讲,每个控制器都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。

这些控制器包括:

  • 节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应。
  • 副本控制器(Replication Controller): 负责为系统中的每个副本控制器对象维护正确数量的 Pod。
  • 端点控制器(Endpoints Controller): 填充端点(Endpoints)对象(即加入 Service 与 Pod)。
  • 服务帐户和令牌控制器(Service Account & Token Controllers): 为新的命名空间创建默认帐户和 API 访问令牌.

cloud-controller-manager

云控制器管理器是 1.8 的 alpha 特性。在未来发布的版本中,这是将 Kubernetes 与任何其他云集成的最佳方式。

cloud-controller-manager 进运行特定于云平台的控制回路。 如果你在自己的环境中运行 Kubernetes,或者在本地计算机中运行学习环境, 所部属的环境中不需要云控制器管理器。

kube-controller-manager 类似,cloud-controller-manager 将若干逻辑上独立的 控制回路组合到同一个可执行文件中,供你以同一进程的方式运行。 你可以对其执行水平扩容(运行不止一个副本)以提升性能或者增强容错能力。

下面的控制器都包含对云平台驱动的依赖:

  • 节点控制器(Node Controller): 用于在节点终止响应后检查云提供商以确定节点是否已被删除
  • 路由控制器(Route Controller): 用于在底层云基础架构中设置路由
  • 服务控制器(Service Controller): 用于创建、更新和删除云提供商负载均衡器

Node 组件

节点组件在每个节点上运行,维护运行的 Pod 并提供 Kubernetes 运行环境。

kubelet

一个在集群中每个节点上运行的代理。它保证容器都运行在 Pod 中。

kube-proxy

kube-proxy 是集群中每个节点上运行的网络代理, kube-proxy 维护节点上的网络规则。

容器运行时(Container Runtime)

容器运行环境是负责运行容器的软件。

Kubernetes 支持多个容器运行环境: Docker、 containerd、cri-o、 rktlet 以及任何实现 Kubernetes CRI (容器运行环境接口)。

插件(Addons)

插件使用 Kubernetes 资源(DaemonSet、 Deployment等)实现集群功能。 因为这些插件提供集群级别的功能,插件中命名空间域的资源属于 kube-system 命名空间。

下面描述众多插件中的几种。

DNS

尽管其他插件都并非严格意义上的必需组件,但几乎所有 Kubernetes 集群都应该 有集群 DNS, 因为很多示例都需要 DNS 服务。

集群 DNS 是一个 DNS 服务器,和环境中的其他 DNS 服务器一起工作,它为 Kubernetes 服务提供 DNS 记录。

Kubernetes 启动的容器自动将此 DNS 服务器包含在其 DNS 搜索列表中。

Web 界面(仪表盘)

Dashboard 是K ubernetes 集群的通用的、基于 Web 的用户界面。 它使用户可以管理集群中运行的应用程序以及集群本身并进行故障排除。

容器资源监控

容器资源监控 将关于容器的一些常见的时间序列度量值保存到一个集中的数据库中,并提供用于浏览这些数据的界面。

集群层面日志

集群层面日志 机制负责将容器的日志数据 保存到一个集中的日志存储中,该存储能够提供搜索和浏览接口。

参考:

OpenStack架构简介

[TOC]

1.云计算

1
2
3
云计算是一种按使用量付费的模式,这种模式提供可用的、便捷的、按需的网络访问, 进入可配置的计算资源共享池(资源包括网络,服务器,存储,应用软件,服务),这些资源能够被快速提供,只需投入很少的管理工作,或与服务供应商进行很少的交互。


2.IT系统架构的发展到目前为止大致可以分为3个阶段:

物理机架构

这一阶段,应用部署和运行在物理机上。
比如企业要上一个ERP系统,如果规模不大,可以找3台物理机,分别部署Web服务器、应用服务器和数据库服务器。
如果规模大一点,各种服务器可以采用集群架构,但每个集群成员也还是直接部署在物理机上。
我见过的客户早期都是这种架构,一套应用一套服务器,通常系统的资源使用率都很低,达到20%的都是好的。

虚拟化架构
摩尔定律决定了物理服务器的计算能力越来越强,虚拟化技术的发展大大提高了物理服务器的资源使用率。
这个阶段,物理机上运行若干虚拟机,应用系统直接部署到虚拟机上。
虚拟化的好处还体现在减少了需要管理的物理机数量,同时节省了维护成本。

云计算架构

虚拟化提高了单台物理机的资源使用率,随着虚拟化技术的应用,IT环境中有越来越多的虚拟机,这时新的需求产生了:
如何对IT环境中的虚拟机进行统一和高效的管理。
有需求就有供给,云计算登上了历史舞台。

云平台是一个面向服务的架构,按照提供服务的不同分为 IaaS、PaaS 和 SaaS。
请看下图

img

IaaS(Infrastructure as a Service)提供的服务是虚拟机。
IaaS 负责管理虚机的生命周期,包括创建、修改、备份、启停、销毁等。
使用者从云平台得到的是一个已经安装好镜像(操作系统+其他预装软件)的虚拟机。
使用者需要关心虚机的类型(OS)和配置(CPU、内存、磁盘),并且自己负责部署上层的中间件和应用。
IaaS 的使用者通常是数据中心的系统管理员。
典型的 IaaS 例子有 AWS、Rackspace、阿里云等

PaaS(Platform as a Service)提供的服务是应用的运行环境和一系列中间件服务(比如数据库、消息队列等)。
使用者只需专注应用的开发,并将自己的应用和数据部署到PaaS环境中。
PaaS负责保证这些服务的可用性和性能。
PaaS的使用者通常是应用的开发人员。
典型的 PaaS 有 Google App Engine、IBM BlueMix 等

SaaS(Software as a Service)提供的是应用服务。
使用者只需要登录并使用应用,无需关心应用使用什么技术实现,也不需要关系应用部署在哪里。
SaaS的使用者通常是应用的最终用户。
典型的 SaaS 有 Google Gmail、Salesforce 等

3.OpenStack

OpenStack 对数据中心的计算、存储和网络资源进行统一管理。
由此可见,OpenStack 针对的是 IT 基础设施,是 IaaS 这个层次的云操作系统。

1.OpenStack 架构

img

中间菱形是虚拟机,围绕 VM 的那些长方形代表 OpenStack 不同的模块(OpenStack 叫服务,后面都用服务这个术语),下面来分别介绍。

Nova:管理 VM 的生命周期,是 OpenStack 中最核心的服务。

Neutron:为 OpenStack 提供网络连接服务,负责创建和管理L2、L3 网络,为 VM 提供虚拟网络和物理网络连接。

Glance:管理 VM 的启动镜像,Nova 创建 VM 时将使用 Glance 提供的镜像。

Cinder:为 VM 提供块存储服务。Cinder 提供的每一个 Volume 在 VM 看来就是一块虚拟硬盘,一般用作数据盘。

Swift:提供对象存储服务。VM 可以通过 RESTful API 存放对象数据。作为可选的方案,Glance 可以将镜像存放在 Swift 中;Cinder 也可以将 Volume 备份到 Swift 中。

Keystone:为 OpenStack 的各种服务提供认证和权限管理服务。简单的说,OpenStack 上的每一个操作都必须通过 Keystone 的审核。

Ceilometer:提供 OpenStac k监控和计量服务,为报警、统计或计费提供数据。

Horizon:为 OpenStack 用户提供一个 Web 的自服务 Portal。

2.OpenStack的核心服务

Nova 管理计算资源,是核心服务。
Neutron 管理网络资源,是核心服务。
Glance 为 VM 提供 OS 镜像,属于存储范畴,是核心服务。
Cinder 提供块存储,VM怎么也得需要数据盘吧,是核心服务。
Swift 提供对象存储,不是必须的,是可选服务。
Keystone 认证服务,没它 OpenStack 转不起来,是核心服务。
Ceilometer 监控服务,不是必须的,可选服务。
Horizon 大家都需要一个操作界面吧。

img

在 Logical Architecture 中,可以看到每个服务又由若干组件组成。
以 Neutron 为例,包含

img

Neutron Server、Neutron plugins 和 Neutron agents
Network provider
消息队列 Queue
数据库 Neutron Database

上面是 Logical Architecture,描述的是 Neutron 服务各个组成部分以及各组件之间的逻辑关系。
而在实际的部署方案上,各个组件可以部署到不同的物理节点上。

OpenStack 本身是一个分布式系统,不但各个服务可以分布部署,服务中的组件也可以分布部署。
这种分布式特性让 OpenStack 具备极大的灵活性、伸缩性和高可用性。

Kubernetes设计架构

[TOC]

Kubernetes设计架构

Kubernetes集群包含有节点代理kubelet和Master组件(APIs, scheduler, etc),一切都基于分布式的存储系统。下面这张图是Kubernetes的架构图。

k8s-architecture

Kubernetes主要由以下几个核心组件组成:

  • etcd保存了整个集群的状态;
  • apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;
  • controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
  • scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;
  • kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;
  • Container runtime负责镜像管理以及Pod和容器的真正运行(CRI);
  • kube-proxy负责为Service提供cluster内部的服务发现和负载均衡;

除了核心组件,还有一些推荐的Add-ons:

  • kube-dns负责为整个集群提供DNS服务
  • Ingress Controller为服务提供外网入口
  • Heapster提供资源监控
  • Dashboard提供GUI
  • Federation提供跨可用区的集群
  • Fluentd-elasticsearch提供集群日志采集、存储与查询

Kubernetes节点

一个培训机构的kubernetes学习课程,用来参考做学习:

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
Chapter 1:课程介绍
理解 Kubernetes 设计原则、原理
了解 Kubernetes 的过去、现在和未来
了解并学会使用 Kubernetes 最重要的资源 -- API
学会如何创建和管理应用,并配置应用外部访问
理解 Kubernetes 网络、存储
掌握 Kubernetes 调度的原理和策略
Kubernetes 一些新功能的概念
了解 Kubernetes 的日志、监控方案
具备基本的故障排查的运维能力

Chapter 2:Kubernetes 基本概念
了解什么是 Kubernetes
了解 Kubernetes 的主要特性
理解为什么需要 Kubernetes
了解 Kubernetes 的过去、现在和未来
了解目前 Kubernetes 社区的情况和被采用情况
了解 Kubernetes 的基本架构
获得一些学习资料推荐

Chapter 3:Kubernetes 架构及原理
理解 Kubernetes 设计原则
深入理解 Kubernetes 集群中的组件及功能
了解 Kubernetes 集群对网络的预置要求
深入理解 Kubernetes 的工作原理
深入理解 Kubernetes 中 Pod 的设计思想


Chapter 4:Kubernetes 安装和配置
了解部署 Kubernetes 的多种方式
可以单机部署 Kubernetes(学习演示使用)
可以在宿主机部署一套 Kubernetes 集群(非生产使用)


Chapter 5:Kubernetes API 及集群访问
了解 Kubernetes 的 API
理解 Kubernetes 中 API 资源的结构定义
了解 kubectl 工具的使用
了解 Kubernetes 中 API 之外的其他资源


Chapter 6:ReplicaController,ReplicaSets 和 Deployments
理解 RC
理解 label 和 selector 的作用
理解 RS
理解 Deployments 并且可操作 Deployments
理解 rolling update 和 rollback

Chapter 7:Volume、配置文件及密钥
了解 Kubernetes 存储的管理,支持存储类型
理解 Pod 使用 volume 的多种工作流程以及演化
理解 pv 和 pvc 的原理
理解 storage class 的原理
理解 configmaps 的作用和使用方法
理解 secrets 的作用和使用方法资源结构

Chapter 8:Service 及服务发现
了解 Docker 网络和 Kubernetes 网络
了解 Flannel 和 Calico 网络方案
理解 Pod 在 Kubernetes 网络中的工作原理
理解 Kubernetes 中的 Service
理解 Service 在 Kubernetes 网络中的工作原理
理解 Kubernetes 中的服务发现
掌握 Kubernetes 中外部访问的几种方式

Chapter 9:Ingress 及负载均衡
理解 Ingress 和 Ingress controller 的工作原理
掌握如何创建 Ingress 规则
掌握如何部署 Ingress controller

Chapter 10:DaemonSets,StatefulSets,Jobs,HPA,RBAC
了解 DaemonSet 资源和功能
了解 StatefulSet 资源和功能
了解 Jobs 资源和功能
了解 HPA 资源和功能
了解 RBAC 资源和功能

Chapter 11:Kubernetes 调度
理解 Pod 调度的相关概念
深度理解 Kubernetes 调度策略和算法
深度理解调度时的 Node 亲和性
深度理解调度时的 Pod 亲和性和反亲和性
深度理解污点和容忍对调度的影响
深度理解强制调度 Pod 的方法

Chapter 12:日志、监控、Troubleshooting
理解 Kubernetes 集群的日志方案
理解 Kubernetes 集群的监控方案
了解相关开源项目:Heapster,Fluentd,Prometheus 等
掌握常用的集群,Pod,Service 等故障排查和运维手段

Chapter 13:自定义资源 CRD
理解和掌握 Kubernetes 中如何自定义 API 资源
可以通过 kubectl 管理 API 资源
了解用于自定义资源的 Controller 及相关使用示例
了解 TPR 和 CRD

Chapter 14:Kubernetes Federation
了解 Kubernetes 中 Federation 的作用和原理
了解 Federation 的创建过程
了解 Federation 支持的 API 资源
了解集群间平衡 Pod 副本的方法

Chapter 15:应用编排 Helm,Chart
了解 Kubernetes 中如何进行应用编排
了解 Helm 的作用和工作原理
了解 Tiller 的作用和工作原理
了解 Charts 的作用和工作原理

Chapter 16:Kubernetes 安全
了解 Kubernetes 中 API 访问过程
了解 Kubernetes 中的 Authentication
了解 Kubernetes 中的 Authorization
了解 ABAC 和 RBAC 两种授权方式
了解 Kubernetes 中的 Admission
了解 Pod 和容器的操作权限安全策略
了解 Network Policy 的作用和资源配置方法

acme.sh配合letsencrypt配置泛域名

[TOC]

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

1. 安装 acme.sh

1
curl  https://get.acme.sh | sh

将会安装到 ~/.acme.sh/ 目录下,以后所有的配置默认也在这个目录下

2. 生成证书

acme.sh 实现了 acme 协议支持的所有验证协议. 一般有两种方式验证: http 和 dns 验证,这里仅介绍 DNS 方式

具体 dnsapi 链接), 这里以 阿里云 为例:

首先获取你的阿里云API Key: ak-console.aliyun.com/#/accesskey

之后在你的终端配置文件中设置:

1
2
export Ali_Key="Your AccessKey ID"
export Ali_Secret="Your Access Key Secret"

之后直接使用如下命令发起申请(注意这里第一个域名为顶级域名,后面个为泛域名。):

1
acme.sh --issue --dns dns_ali -d example.com -d *.example.com *.second.example.com
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

curl https://get.acme.sh | sh -s email=xxx@xx.com
exit
# tencent api token address:
# https://console.dnspod.cn/account/token

export DP_Id="xxx"
export DP_Key="xxx"
acme.sh --issue --dns dns_dp -d lsbgb.com -d *.lsbgb.com
acme.sh --issue --dns dns_dp -d lsbgb.com -d *.lsbgb.com --fullchain-file /etc/nginx/ssl/lsbgb.com/fullchain.cer --key-file /etc/nginx/ssl/lsbgb.com/lsbgb.com.key --dnssleep
acme.sh --issue --dns dns_dp -d k8s.lsbgb.com -d *.k8s.lsbgb.com
acme.sh --issue --dns dns_dp -d k8s.lsbgb.com -d *.k8s.lsbgb.com --fullchain-file /etc/nginx/ssl/k8s.lsbgb.com/fullchain.cer --key-file /etc/nginx/ssl/k8s.lsbgb.com/k8s.lsbgb.com.key --dnssleep

# crontab -l
# cat ~/.acme.sh/account.conf

三级域名申请

申请了顶级域名和二级域名,但在使用三级域名的时候还是会报不安全的错误,所以如果你想要用三级域名的话,也必须在申请的时候写上

1
acme.sh --issue --dns dns_ali -d example.com -d *.example.com *.second.example.com

如果你想单独的申请三级域名,并不想与顶级域名搞在一起,则可以使用如下方式:

1
acme.sh --issue --dns dns_ali -d second.example.com *.second.example.com

注意:这种方式需要在dns中指定二级域名到你申请的主机。

更新证书

证书有效期是90天,目前证书在 60 天以后会自动更新, 你无需任何操作,不过都是自动的, 你不用关心.

如果你关闭了更新证书功能,手动执行上面的命令就好了,会自动把之前的证书覆盖掉。

shadowsocks server

[TOC]

vultr的vps性价比越来越高了,带宽不限,5美刀的流量都有1024G/月 .废话不多说,直接开始说搭建。

首先连接上vultr的一个vps。

安装shadowsocks

ubuntu 18

1
apt install shadowsocks

其它系统

安装依赖shadowsocks依赖包

1
2
3
apt install python-pip python-m2crypto -y 
pip install setuptools
pip install wheel

安装shadowsocks

1
pip install shadowsocks

修改配置文件

1
2
3
4
5
6
7
8
9
10
11
cat /etc/shadowsocks.json
{
"server": "0.0.0.0",
"server_port": 55555, #设置你的ss服务端口
# "server_port": [55555, 44444], #开启多个端口
"password": "your_password", #设置ss服务连接密码
"timeout": 300,
"method": "aes-256-cfb",
"fast_open": false
}

开启ss服务

1
ssserver -c /etc/shadowsocks.json -d start

系统重启之后,自动开启

1
2
3
4
cat /etc/rc.local 

ulimit -n 51200
ssserver -c /etc/shadowsocks.json -d start

添加用户和端口

为什么要添加用户?

root用户密码太他喵的难敲了!一堆很长的随机字符串,各种配合shift的都有,登录一次贼费劲.

vultr

而且在console端不可以粘贴。所以换一个用户,帮助太大了。

vultr

操作如下

1
2
3
4
5
adduser superman
...

usermod -G sudo superman
#添加sudo权限

为什么要修改登录端口?

安全和性能考虑,我创建好的vps,不一会儿就有两个尝试登录我的vps。

vultr

登录默认使用22,如果不修改,每天都有大量的试图入侵的要尝试登录你的vps,你的vps要不断的验证身份,性能自然有所下降。万一还让他攻破了,那你就是裸奔了。修改登录端口之后,别人连端口都不知道,登录就无从说起了。操作如下:

1
2
3
4
5
6
7
cat /etc/ssh/sshd_config 
...
#Port 22
Port 60022 #自己定义一个端口 大于1024即可

systemctl restart ssh
#重启服务,登录服务生效,原来的22号端口就不能登录了哦

系统优化

vps启动自然有很多服务跟跟着启动,以及对文件数据网络等处理都有一个正常值的限制。那既然你的vps只是用来搭建shadowsocks server,那就可以针对这个做一下优化。

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
cat /etc/sysctl.d/local.conf

# max open files
fs.file-max = 51200
net.core.rmem_max = 67108864
net.core.wmem_max = 67108864
net.core.rmem_default = 65536
net.core.wmem_default = 65536
net.core.netdev_max_backlog = 4096
net.core.somaxconn = 4096
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.ip_local_port_range = 10000 65000
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_fastopen = 3
# TCP receive buffer
net.ipv4.tcp_rmem = 4096 87380 67108864
# TCP write buffer
net.ipv4.tcp_wmem = 4096 65536 67108864
net.ipv4.tcp_mtu_probing = 1
# net.ipv4.tcp_congestion_control = hybla #bbr 加速需要屏蔽掉这个

重新加载生效

1
sysctl --system

bbr 加速

bbr加速可以是你的访问更快。就酱。

bbr加速参考文档

1
wget --no-check-certificate https://github.com/teddysun/across/raw/master/bbr.sh && chmod +x bbr.sh && ./bbr.sh

安装完成后,重启生效。因为更换了较新的内核。

serverSpeeder 加速

锐速(serverSpeeder )的目的跟bbr一样,搞一个就可以了。不过bbr是升级内核,锐速是把内核改成固定的稳定版本。

锐速参考文档

1
wget --no-check-certificate -O appex.sh https://raw.githubusercontent.com/0oVicero0/serverSpeeser_Install/master/appex.sh && chmod +x appex.sh && bash appex.sh install

使用方法:
启动命令 /appex/bin/lotServer.sh start
状态查询 /appex/bin/lotServer.sh status
停止加速 /appex/bin/lotServer.sh stop

好了,这就是从搭建ss server,到方便登录到保证安全,以及系统优化,到最后加速的全部过程。

frp

[TOC]

frp

frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp 协议,为 http 和 https 应用协议提供了额外的能力,且尝试性支持了点对点穿透。

当然还有一些其他的内网穿透工具,比如 telebit ngrok . 但效果都不太理想.

首先telebit, 服务器在国外,国内使用延迟特别高,当然可以自己搭建 telebit-relay 但是坑特别多,我提issue想让作者处理一下,得到的回复是这样的:

1
2
3
4
5
Thanks for the report.

We don’t have update install instructions for the relay server yet and we don’t have time to update and test them right now, so you’ll have to use the official server https://telebit.cloud until we do.

Right now our efforts are focused on improving the Telebit Remote client.

于是果断放弃。

再说ngrok,这个也是老断,bug多,在https方面配置很麻烦,而且不能使用三级域名(至少目前不行)。最重要的一点是,2.x版本不开源了。1.x坑当然多啦。

1
2
3
ngrok 2.x is the successor to 1.x and the focus of all current development effort. Its source code is not available.

NOTE This repository contains the code for ngrok 1.x.

frp架构

architecture

使用示例

根据对应的操作系统及架构,从 Release 页面下载最新版本的程序。

frpsfrps.ini 放到具有公网 IP 的机器上。

frpcfrpc.ini 放到处于内网环境的机器上。

通过 ssh 访问公司内网机器

  1. 修改 frps.ini 文件,这里使用了最简化的配置:
1
2
3
# frps.ini
[common]
bind_port = 7000
  1. 启动 frps:
1
./frps -c ./frps.ini
  1. 修改 frpc.ini 文件,假设 frps 所在服务器的公网 IP 为 x.x.x.x;
1
2
3
4
5
6
7
8
9
10
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000

[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
  1. 启动 frpc:
1
./frpc -c ./frpc.ini
  1. 通过 ssh 访问内网机器,假设用户名为 test:
1
ssh -oPort=6000 test@x.x.x.x

通过自定义域名访问部署于内网的 web 服务

有时想要让其他人通过域名访问或者测试我们在本地搭建的 web 服务,但是由于本地机器没有公网 IP,无法将域名解析到本地的机器,通过 frp 就可以实现这一功能,以下示例为 http 服务,https 服务配置方法相同, vhost_http_port 替换为 vhost_https_port, type 设置为 https 即可。我一般都用nginx反向代理。

  1. 修改 frps.ini 文件,设置 http 访问端口为 8080:
1
2
3
4
# frps.ini
[common]
bind_port = 7000
vhost_http_port = 8080
  1. 启动 frps:
1
./frps -c ./frps.ini
  1. 修改 frpc.ini 文件,假设 frps 所在的服务器的 IP 为 x.x.x.x,local_port 为本地机器上 web 服务对应的端口, 绑定自定义域名 www.yourdomain.com:
1
2
3
4
5
6
7
8
9
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000

[web]
type = http
local_port = 80
custom_domains = www.yourdomain.com
  1. 启动 frpc:
1
./frpc -c ./frpc.ini
  1. www.yourdomain.com 的域名 A 记录解析到 IP x.x.x.x,如果服务器已经有对应的域名,也可以将 CNAME 记录解析到服务器原先的域名。
  2. 通过浏览器访问 http://www.yourdomain.com:8080 即可访问到处于内网机器上的 web 服务。

转发 DNS 查询请求

DNS 查询请求通常使用 UDP 协议,frp 支持对内网 UDP 服务的穿透,配置方式和 TCP 基本一致。

  1. 修改 frps.ini 文件:
1
2
3
# frps.ini
[common]
bind_port = 7000
  1. 启动 frps:
1
./frps -c ./frps.ini
  1. 修改 frpc.ini 文件,设置 frps 所在服务器的 IP 为 x.x.x.x,转发到 Google 的 DNS 查询服务器 8.8.8.8 的 udp 53 端口:
1
2
3
4
5
6
7
8
9
10
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000

[dns]
type = udp
local_ip = 8.8.8.8
local_port = 53
remote_port = 6000
  1. 启动 frpc:
1
./frpc -c ./frpc.ini
  1. 通过 dig 测试 UDP 包转发是否成功,预期会返回 www.google.com 域名的解析结果:
1
dig @x.x.x.x -p 6000 www.google.com

转发 Unix 域套接字

通过 tcp 端口访问内网的 unix域套接字(例如和 docker daemon 通信)。

frps 的部署步骤同上。

  1. 启动 frpc,启用 unix_domain_socket 插件,配置如下:
1
2
3
4
5
6
7
8
9
10
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000

[unix_domain_socket]
type = tcp
remote_port = 6000
plugin = unix_domain_socket
plugin_unix_path = /var/run/docker.sock
  1. 通过 curl 命令查看 docker 版本信息
1
curl http://x.x.x.x:6000/version

对外提供简单的文件访问服务

通过 static_file 插件可以对外提供一个简单的基于 HTTP 的文件访问服务。

frps 的部署步骤同上。

  1. 启动 frpc,启用 static_file 插件,配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000

[test_static_file]
type = tcp
remote_port = 6000
plugin = static_file
# 要对外暴露的文件目录
plugin_local_path = /tmp/file
# 访问 url 中会被去除的前缀,保留的内容即为要访问的文件路径
plugin_strip_prefix = static
plugin_http_user = abc
plugin_http_passwd = abc
  1. 通过浏览器访问 http://x.x.x.x:6000/static/ 来查看位于 /tmp/file 目录下的文件,会要求输入已设置好的用户名和密码。

为本地 HTTP 服务启用 HTTPS

通过 https2http 插件可以让本地 HTTP 服务转换成 HTTPS 服务对外提供。

  1. 启用 frpc,启用 https2http 插件,配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000

[test_htts2http]
type = https
custom_domains = test.yourdomain.com

plugin = https2http
plugin_local_addr = 127.0.0.1:80

# HTTPS 证书相关的配置
plugin_crt_path = ./server.crt
plugin_key_path = ./server.key
plugin_host_header_rewrite = 127.0.0.1
plugin_header_X-From-Where = frp
  1. 通过浏览器访问 https://test.yourdomain.com 即可。

注意:这样的https在chrome浏览器中一般都会提醒属于不安全的https,可以通过nginx做反向代理实现。然后frp只需要是正常的http即可。

1
2
3
4
5
6
7
8
9
10
11
12
#########################  frp  #################################################
server {
# SSL configuration
server_name *.frp.domain.com frp.domain.com;
listen 443 ssl ;
ssl_certificate /etc/nginx/ssl/frp.domain.com/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/frp.domain.com/frp.domain.com.key;

location / {
proxy_pass http://0.0.0.0:8080;
}
}

安全地暴露内网服务

对于某些服务来说如果直接暴露于公网上将会存在安全隐患。

使用 stcp(secret tcp) 类型的代理可以避免让任何人都能访问到要穿透的服务,但是访问者也需要运行另外一个 frpc。

以下示例将会创建一个只有自己能访问到的 ssh 服务代理。

frps 的部署步骤同上。

  1. 启动 frpc,转发内网的 ssh 服务,配置如下,不需要指定远程端口:
1
2
3
4
5
6
7
8
9
10
11
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000

[secret_ssh]
type = stcp
# 只有 sk 一致的用户才能访问到此服务
sk = abcdefg
local_ip = 127.0.0.1
local_port = 22
  1. 在要访问这个服务的机器上启动另外一个 frpc,配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000

[secret_ssh_visitor]
type = stcp
# stcp 的访问者
role = visitor
# 要访问的 stcp 代理的名字
server_name = secret_ssh
sk = abcdefg
# 绑定本地端口用于访问 ssh 服务
bind_addr = 127.0.0.1
bind_port = 6000
  1. 通过 ssh 访问内网机器,假设用户名为 test:
1
ssh -oPort=6000 test@127.0.0.1

点对点内网穿透

frp 提供了一种新的代理类型 xtcp 用于应对在希望传输大量数据且流量不经过服务器的场景。

使用方式同 stcp 类似,需要在两边都部署上 frpc 用于建立直接的连接。

目前处于开发的初级阶段,并不能穿透所有类型的 NAT 设备,所以穿透成功率较低。穿透失败时可以尝试 stcp 的方式。

  1. frps 除正常配置外需要额外配置一个 udp 端口用于支持该类型的客户端:
1
bind_udp_port = 7001
  1. 启动 frpc,转发内网的 ssh 服务,配置如下,不需要指定远程端口:
1
2
3
4
5
6
7
8
9
10
11
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000

[p2p_ssh]
type = xtcp
# 只有 sk 一致的用户才能访问到此服务
sk = abcdefg
local_ip = 127.0.0.1
local_port = 22
  1. 在要访问这个服务的机器上启动另外一个 frpc,配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000

[p2p_ssh_visitor]
type = xtcp
# xtcp 的访问者
role = visitor
# 要访问的 xtcp 代理的名字
server_name = p2p_ssh
sk = abcdefg
# 绑定本地端口用于访问 ssh 服务
bind_addr = 127.0.0.1
bind_port = 6000
  1. 通过 ssh 访问内网机器,假设用户名为 test:
1
ssh -oPort=6000 test@127.0.0.1

更多内容参考官方地址: frp