1. 概念入门#
- master节点
- worker节点
Pod
Kubernetes最小管理单位,一个节点可以拥有多个Pod,一个Pod可以拥有多个容器
2. 安装#
2.1 minikube#
安装教程: https://minikube.sigs.k8s.io/docs/start/
2.2 腾讯云集群#
按步骤很容易起一个Kubernetes集群
3. 常用命令#
1
2
3
4
5
6
7
8
9
10
11
12
|
kubectl apply -f app.yaml # 部署应用
kubectl get deployment # 查看 deployment
kubectl get pod -o wide # 查看 pod
kubectl describe pod pod-name # 查看 pod 详情
kubectl logs pod-name # 查看 log
kubectl exec -it pod-name -- bash # 进入 Pod 容器终端, -c container-name 可以指定进入哪个容器。
kubectl scale deployment test-k8s --replicas=5 # 伸缩扩展副本
kubectl port-forward pod-name 8090:8080 # 把集群内端口映射到节点
kubectl rollout history deployment test-k8s # 查看历史
kubectl rollout undo deployment test-k8s # 回到上个版本
kubectl rollout undo deployment test-k8s --to-revision=2 # 回到指定版本
kubectl delete deployment test-k8s # 删除部署
|
4. Pod#
- 每个 Pod 都在每个地址族中获得一个唯一的 IP 地址。
- Pod 中的每个容器共享网络名字空间,包括 IP 地址和网络端口。 Pod 内 的容器可以使用 localhost 互相通信。
- Pod生命周期
- Pod 遵循一个预定义的生命周期,起始于 Pending 阶段,如果至少 其中有一个主要容器正常启动,则进入 Running,之后取决于 Pod 中是否有容器以 失败状态结束而进入 Succeeded 或者 Failed 阶段。
- 容器重启策略
- Pod 的 spec 中包含一个 restartPolicy 字段,其可能取值包括 Always、OnFailure 和 Never。默认值是 Always。
- 容器探针
- probe 是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 既可以在容器内执行代码,也可以发出一个网络请求。
- 探针的四种检查机制:exec、grpc、httpGet、tcpSocket
- 探测的结果:Success、Failure、Unknown
- 探测的类型:livenessProbe、readinessProbe、startupProbe
- Pod的终止
- 一般不应武断地使用 KILL 信号终止它们,导致这些进程没有机会 完成清理操作。
- 在存在强制关闭设施的前提下, kubelet 会尝试体面地终止 Pod。
- 通常情况下,容器运行时会发送一个 TERM 信号到每个容器中的主进程。 很多容器运行时都能够注意到容器镜像中 STOPSIGNAL 的值,并发送该信号而不是 TERM。 一旦超出了体面终止限期,容器运行时会向所有剩余进程发送 KILL 信号,之后 Pod 就会被从 API 服务器 上移除。如果 kubelet 或者容器运行时的管理服务在等待进程终止期间被重启, 集群会从头开始重试,赋予 Pod 完整的体面终止限期。
- Init 容器
- Init 容器是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本。
- Pod 可以有一个或多个先于应用容器启动的 Init 容器。
- Init 容器必须在应用容器启动之前运行完成,因此 Init 容器 提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。 一旦前置条件满足,Pod 内的所有的应用容器会并行启动。
- 如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。如果 Pod 对应的 restartPolicy 值为 “Never”,并且 Pod 的 Init 容器失败, 则 Kubernetes 会将整个 Pod 状态设置为失败。
- 为 Pod 设置 Init 容器需要添加 initContainers 字段
- 临时容器
- 当由于容器崩溃或容器镜像不包含调试工具而导致 kubectl exec 无用时, 临时容器对于交互式故障排查很有用。
4.1 一个简单的例子#
1
2
3
4
5
6
7
8
9
10
|
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
|
4.2 Pod template#
1
2
3
4
5
6
7
8
9
10
11
12
|
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
spec:
containers:
- name: hello
image: busybox:1.28
command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
restartPolicy: OnFailure
|
当某工作负载的 Pod 模板被改变时,控制器会基于更新的模板 创建新的 Pod 对象而不是对现有 Pod 执行更新或者修补操作。
4.3 一个Init容器的例子(先等待myservice启动,再等待mydb启动)#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
|
5. 工作负载资源分类#
Deployment
适合无状态应用,所有pod等价,可替代
StatefulSet
有状态的应用,适合数据库这种类型
DaemonSet
在每个节点上跑一个Pod,可以用来做节点监控、节点日志收集
Job & CronJob
Job用来表达的是一次性任务,而CronJob会根据其时间规划反复运行
5.1 Deployment#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
|
- selector 字段定义 Deployment 如何查找要管理的 Pods。 在这里,你选择在 Pod 模板中定义的标签(app: nginx)。 不过,更复杂的选择规则是也可能的,只要 Pod 模板本身满足所给规则即可。
- yaml编写,请参考Deployment编写规约
- 运行
kubectl get deployments
检查 Deployment 是否已创建
- 获取 Deployment 描述信息:
kubectl describe deployment
- 更新deployment:使用
kubectl set
和 kubectl edit
- 回滚deploymnet:
kubectl rollout undo
- 检查 Deployment 上线历史:
kubectl rollout history deployment_name
- 缩放 Deployment:
kubectl scale deployment_name --replicas=10
- 暂停 Deployment:
kubectl rollout pause
5.2 StatefulSet#
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
|
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mongodb
spec:
serviceName: mongodb
replicas: 3
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongo
image: mongo:4.4
# IfNotPresent 仅本地没有镜像时才远程拉,Always 永远都是从远程拉,Never 永远只用本地镜像,本地没有则报错
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: mongodb
spec:
selector:
app: mongodb
type: ClusterIP
# HeadLess
clusterIP: None
ports:
- port: 27017
targetPort: 27017
|
- StatefulSet 是用来管理有状态的应用,例如数据库。
- StatefulSet 特性
- Service 的
CLUSTER-IP
是空的,Pod
名字也是固定的。
- Pod 创建和销毁是有序的,创建是顺序的,销毁是逆序的。
- Pod 重建不会改变名字,除了IP,所以不要用IP直连
5.3 DaemonSet#
5.4 Job & CronJob#
6. 数据持久化#
- Storage Class (SC)
- 将存储卷划分为不同的种类,例如:SSD,普通磁盘,本地磁盘,按需使用
-
1
2
3
4
5
6
7
8
9
10
|
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: "10"
fsType: ext4
|
- Persistent Volumne (PV)
- 描述卷的具体信息,例如磁盘大小,访问模式
-
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
|
apiVersion: v1
kind: PersistentVolume
metadata:
name: mongodata
spec:
capacity:
storage: 2Gi
volumeMode: Filesystem # Filesystem(文件系统) Block(块)
accessModes:
- ReadWriteOnce # 卷可以被一个节点以读写方式挂载
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /root/data
nodeAffinity:
required:
# 通过 hostname 限定在某个节点创建存储卷
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node2
```
|
- Persistent Volumne Claim (PVC)
- 对存储需求的一个申明,可以理解为一个申请单,系统根据这个申请单去找一个合适的 PV。还可以根据 PVC 自动创建 PV。
-
1
2
3
4
5
6
7
8
9
10
|
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongodata
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "local-storage"
resources:
requests:
storage: 2Gi
|
例如在腾讯云上,编写PVC,会自动生成PV和SC,资源申请完成后,我们只需把磁盘挂载到对应的statefulset即可。
7 Service#
- Service管理一组pod,通过label关联对应的pod
- pod重建,不会导致service重建
- Service提供了负载均衡的功能,自动转发流量到不同的 Pod
- Service 可对集群外部提供访问端口
- Service 内部可以通过名字访问
7.1 Service相关命令#
1
2
3
|
kubectl get svc # 查看所有Service
kubectl describe svc svc_name # 查看Service详细
|
7.2 例子#
1
2
3
4
5
6
7
8
9
10
11
|
apiVersion: v1
kind: Service
metadata:
name test-k8s-service
spec:
selector:
app: test-k8s-service
type: ClusterIP # 可选项:NodePort, None, Loadbalancer
ports:
- port: 8080 # 本service端口
targetPort: 8080 # 容器端口
|
对外暴露服务
1
2
3
4
5
6
7
8
9
10
11
12
13
|
apiVersion: v1
kind: Service
metadata:
name: test-k8s
spec:
selector:
app: test-k8s
type: NodePort
ports:
- port: 8080 # 本 Service 的端口
targetPort: 8080 # 容器端口
nodePort: 31000 # 节点端口,范围固定 30000 ~ 32767
|
- type
- ClusterIP: 集群内可访问
- NodePort: 节点可访问
- LoadBalancer: 负载均衡模式(需要负载均衡器才可用)
- Headless:适合数据库,clusterIp 设置为 None 就变成 Headless 了,不会再分配 IP
8. ConfigMap & Secret#
ConfigMap和Secret这两种Kind的支持,使得我门更好的管理配置和秘钥
8.1 ConfigMap#
1
2
3
4
5
6
|
apiVersion: v1
kind: ConfigMap
metadata:
name: mongo-config
data:
mongoHost: mongodb-0.mongodb
|
- 查看configmap:
kubectl get configmap mongo-config -o yaml
8.2 Secret#
1
2
3
4
5
6
7
8
|
apiVersion: v1
kind: Secret
metadata:
name: mongo-secret
type: Opaque # Opaque 用户定义的任意数据
data:
mongo-username: bW9uZ291c2Vy # base64
mongo-password: bW9uZ29wYXNz
|
8.3 使用方法#
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
|
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mongodb
spec:
replicas: 3
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongo
image: mongo:4.4
imagePullPolicy: IfNotPresent
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-username
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
# Secret 的所有数据定义为容器的环境变量,Secret 中的键名称为 Pod 中的环境变量名称
# envFrom:
# - secretRef:
# name: mongo-secret
|
挂载为文件(更适合证书)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
|
9. Ingress#
- Ingress 为外部访问集群提供了一个 统一 入口,避免了对外暴露集群端口;
- Ingress 功能类似 Nginx,可以根据域名、路径把请求转发到不同的 Service。
- 可以配置 https
和Loadbalancer的区别:
- LoadBalancer 需要对外暴露端口,不安全;
- 无法根据域名、路径转发流量到不同 Service,多个 Service 则需要开多个 LoadBalancer;
- 功能单一,无法配置 https
要使用 Ingress,需要一个负载均衡器 + Ingress Controller。
如果是云服务商,会自动给你配置,否则你的外部 IP 会是 “pending” 状态,无法使用。
10. 包管理工具Helm#
- Helm是kubernetes下的包管理工具,每个包被称为chart。
- 使用helm,我们可以很方便搭建集群,如MySQL集群
10.1 helm的使用#
10.2 编写自己的chart#