kubernetes 核心概念之 Controller

在集群上管理和运行容器的对象

Pod 和 Controller 的关系

  • Pod 是通过 Controller 实现应用的运维: 比如伸缩、滚动升级等
  • 俩者之间通过 label 标签建立关系

Deployment 控制器应用场景

web 服务、微服务…

  • 部署无状态的应用
  • 管理 Pod 和 ReplicaSet
  • 部署、滚动升级 等

使用 deployment 通过 yaml 部署应用

1
2
3
4
5
6
7
8
9
10
spec:
selector:
matchLabels:
app: web

template:
metadata:
creationTimestamp: null
labels:
app: web

导出 yaml 文件

1
kubectl create deployment web --image=nginx --dry-run -o yaml > web.yaml

使用 yaml 文件部署应用

1
kubectl apply -f web.yaml

对外发布( 暴露对外端口号 )

1
2
3
kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=web1 -o yaml > web1.yaml
kubectl apply -f web1.yaml
kubectl get pods,svc

升级回滚

1
2
3
4
5
6
7
8
9
10
# 应用升级
kubectl set image deployment web nginx=nginx:1.15
# 查看升级版本
kubectl rollout history deployment web
# 查看升级状态
kubectl rollout status deployment web
# 回滚到上一个版本
kubectl rollout undo deployment web
# 回滚到指定版本
kubectl rollout undo deployment web --to-revision=?

弹性伸缩

1
kubectl scale deployment web --replicas=10

无状态和有状态的部署应用

通过 Deployment 部署的都是无状态的,无状态的应用有以下特点:

  • Pod 都是一样的
  • 没有顺序要求
  • 不用考虑在 node 执行
  • 随意进行伸缩和扩展

有状态的应用则有以下特点:

  • 无状态特点的相反
  • 每个 Pod 都是独立的,保持 Pod 的启动顺序和唯一性
    • 通过唯一网络标识符、持久存储确定唯一性
    • 有序,比如 mysql 的主从

部署有状态的应用

无头 Service

ClusterIP 值等于 <none>,访问都是通过特定域名进行访问。

通过 SatefulSet 部署有状态应用

statefulset.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
## 部署一个无头的 Service
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx

---

## StatefulSet 部署应用

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx-statefulset
namespace: default
spec:
serviceName: nginx
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14
ports:
- containerPort: 80

部署

1
kubectl apply -f statefulset.yaml

查看

1
2
3
4
## 查看 pods
kubectl get pods
## 查看 service
kubectl get svc

deployment 和 statefulset 的区别:

statefulset 有唯一标识

  • 根据主机名 + 按照一定规则生成域名
    • 每个 pod 有唯一的主机名
    • 唯一域名( 格式: 主机名称.service名称.名称空间.svc.cluster.local )(比如上面案例中 nginx-statefulset-0 这个 pod 对应的域名就是: nginx-statefulset-0.nginx.default.svc.cluster.local)

DaemonSet

一个 DaemonSet 对象能确保其创建的 Pod 在集群中的每一台(或指定)Node 上都运行一个副本。

如果集群中动态加入了新的 node, DaemonSet 的 Pod 也会被添加到新加入 Node 中运行。删除 DaemonSet 对象也会级联删除所有其创建的 Pod。

daemonset-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
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ds-test
labels:
app: filebeat
spec:
selector:
matchLabels:
app: filebeat
template:
metadata:
labels:
app: filebeat
spec:
containers:
- name: logs
image: nginx:1.14
ports:
- containerPort: 80
volumeMounts:
- name: varlog
mountPath: /tmp/log
volumes:
- name: varlog
hostPath:
path: /var/log

部署

1
kubectl apply -f daemonset.yaml

查看

1
kubectl get pods

尝试上下线节点,查看变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## 添加节点
### master
kubeadm token create --print-join-command
### node3
#### 把 master 执行后的结果拷贝到 k8s-node3 执行,将 node3 加入集群中
$>

## 删除节点
kubectl cordon k8s-node3
kubectl drain k8s-node3 --ignore-daemonsets
kubectl delete node k8s-node3

## 查看的指令
kubectl get nodes
kubectl get pods

一次性任务(job)和定时任务(cronjob)

一次性任务

job.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbgnum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
## 失败后尝试重来几次
backoffLimit: 4

部署 / 查看 / 删除

1
2
3
4
5
6
7
kubectl create -f job.yaml

kubectl get pods -o wide
kubectl get jobs
kubectl logs <pod-name>

kubectl delete -f job.yaml

执行完,pod 会变成 Completed 的状态

定时任务

cronjob.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure

部署 / 查看 / 删除

1
2
3
4
5
6
7
kubectl apply -f cronjob.yaml

kubectl get pods -o wide
kubectl get cronjobs
kubectl logs <pod-name>

kubectl delete -f cronjob.yaml

执行完,pod 会变成 Completed 的状态