《每天5分钟玩转Kubernetes》

一、先把Kubernetes跑起来

1.2 创建kubernetes集群

命令 操作
minikube start 启动minikube
minikube status 查看minikube状态
kubectl get nodes 查看集群节点
kubectl cluster-info 查看集群信息

1.3 部署应用

1
2
3
kubectl run kubernetes-bootcamp \
    --image=docker.io/jocatalin/kubernetes-bootcamp:v1 \
    --port=8080
选项 说明
--image 指定镜像
--port 设置应用对外服务的端口

关键概念

概念 说明 备注
Deployment 可以理解为应用
Pod 一个或多个容器的集合,同一个Pod中所有容器共享IP地址和Port空间 Kubernetes中最小的调度单元
1
2
# 查看所有Pods
kubectl get pods

修正,书籍直接创建pod,本笔记修正为创建deployment,应该使用

1
k create deployment kubernetes-bootcamp --image=docker.io/jocatalin/kubernetes-bootcamp:v1  --replicas=2

1.4 访问应用

默认情况下所有Pod只能在集群内部访问,需要通过Service暴露服务

1
2
3
kubectl expose deployment/kubernetes-bootcamp \
    --type="NodePort" \
    --port 8080

使用命令kubectl get services查看服务

名称 说明
kubernetes 集群的默认服务
kubernetes-bootcamp 通过kubectl expose创建的服务,8080是暴露的端口,另外一个是随机份配的

1.5 Scale应用

1
kubectl scale deployments/kubernetes-bootcamp --replicas=3

1.6 滚动更新

当前应用使用的是v1版本,现在需要更新为v2版本

1
kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2

回退到v1版本

1
kubectl rollout undo deployments/kubernetes-bootcamp

二、重要概念

概念 说明
Cluster 是计算、存储和网络资源的集合,K8S利用这些资源云星宇各种基于容器的应用
Master 是集群的大脑,负责调度应用,维护集群状态,实现集群伸缩等功能
Node 职责是运行容器的应用,Node由Master管理,Node负责监控并汇报容器的状态,同时根据Master的要求管理容器的生命周期
Pod 是Kubernetes中最小的调度单元,一个Pod中可以包含一个或多个容器,Pod中的容器共享IP地址和Port空间,可以通过localhost通信
Controller 通常K8S不直接创建Pod,而是通过Controller管理Pod,例如Deployment、ReplicaSet、DaemonSet、StatefulSet、Job等
Service 是Pod的抽象,可以将一组Pod封装成一个Service,Service定义了外接方位一组特定Pod的方式,Service有自己的IP和端口,为Pod提供了负载均衡
Namespace 将一个物理的Cluster逻辑上分为多个虚拟Cluster,可使用kubectl get namespaces查看所有namespace

K8S中Pod的解读

概念 说明
目的 K8S引入Pod的目的是为了解决容器间通信的问题
使用方式 运行单一容器(一个Pod运行 一个容器,但K8S管理的还是Pod,而不是容器)
、运行多个容器
放到一Pod中的容器 通常是紧密耦合的容器,并且需要直接共享资源,比如一个容器负责应用,另一个容器负责日志收集

K8S中的Controller解读

概念 说明
Deployment 最常见的Controller,可以管理Pod的多个副本
ReplicaSet 实现了Pod的多副本管理,使用Deployment会自动创建ReplicaSet,通常不直接使用ReplicaSet
DaemonSet 用于每个Node最多只能运行一个Pod的场景,比如运行日志收集器
StatefulSet 能够保证Pod的每个副本在整个生命周期中名称是不变的
Job 用于运行一次性任务,比如批处理任务

三、部署K8S Cluster

3.1 安装Docker

所有节点都需要安装Docker

1
apt update && apt install -y docker.io

3.2 安装kubelet、kubeadm、kubectl

工具 功能 部署节点
kubelet 运行在每个Node上,负责Pod的创建、启停等功能 所有Node
kubeadm 用于初始化集群 Master
kubectl 用于管理集群 Master

书籍资料不作为参考,请自行查找部署方案

3.3 初始化Master

3.3.1 初始化Master

1
kubeadm init --apiserver-advertise-address 192.168.56.105
参数 说明
–apiserver-advertise-address 指定Master的的哪个interface与Cluster的其他节点通信
–pod-network-cidr 指定Pod的IP地址范围,Pod的IP地址将从这个范围中分配

3.3.3 安装Pod网络

要让Cluster中的Pod能够互相通信,需要安装Pod网络,Pod网络是一种特殊的网络,它为Pod提供了一个IP地址,使得Pod能够互相通信

1
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

3.3.4 添加k8s-node1和k8s-node2

1
kubeadm join --token 8f2b6a.6b0b0b0b0b0b0b0b 192.168.56.105:6443

token是kubeadm init生成的,可以通过kubeadm token list查看

四、Kubernetes架构

4.1 Master节点

包含如下组件

组件名称 别称 说明
API Server kube-apiserver 提供HTTP Rest接口,是集群控制的入口,所有资源的增删改查都是通过它来完成的,它会把资源的状态保存到etcd中
Scheduler kube-scheduler 负责Pod的调度,它会根据资源的使用情况和其他约束条件将Pod调度到合适的Node上运行,调度策略是可配置的
Controller Manager kube-controller-manager 负责维护集群的状态,比如故障检测、自动扩展、滚动更新等,它是一个Master中的Daemon,每个Daemon都是一个独立的控制器,分别负责不同的功能
etcd etcd 分布式键值存储,用于保存集群的状态,比如Pod的状态、Service的状态等,etcd是一个独立的进程,它可以单独部署,也可以和Master部署在一起
Pod网络 Pod能互相通信的基础,flannel是其中一个可选方案

4.2 Node节点

包含如下组件

组件名称 说明
kubelet 当Scheduler确定在某个Node上运行Pod后,会将Pod的具体配置信息(image、volume等)发送给该节点的kubelet,kubelet负责Pod的创建、启停等操作
Proxy 负责为Service提供cluster内部的服务发现和负载均衡,它会监控Service和Endpoint的变化,并根据变化更新规则,从而保证Service的访问质量
Pod网络 Pod能互相通信的基础,flannel是其中一个可选方案

4.3 完整的架构图

几乎所有的Kubernetes组件本身也运行在Pod中,通过如下命令查看(其中kube-dns组件为Cluster提供DNS服务)

kubelet是唯一没有以容器形式运行的Kubernetes组件,它在Ubuntu中通过Systemd服务运行

1
kubectl get pods --all-namespaces -o wide

4.4 用例子把它们串起来

1
kubectl run httpd-app --image=httpd --replicas=2

修正,应该为kubectl create deployment httpd-app --image=httpd --replicas=2

kubectlAPI ServerControllerSchedulerPod网络kubeletDocker

五、运行应用

5.1 Deployment

5.1.1 运行Deployment

1
kubectl run nginx-deployment --image=nginx:1.7.9 --replicas=2

修正,应该为kubectl create deployment nginx-deployment --image=nginx:1.7.9 --replicas=2

1
2
3
4
5
kubectl get deployments # 查看Deployment
kubectl get deployment nginx-deployment -o yaml  # 查看Deployment的配置信息
kubectl describe deployment nginx-deployment  # 查看Deployment的详细信息
kubectl get replicaset # 查看ReplicaSet
kubectl describe replicaset nginx-deployment-5c7588df5b # 查看ReplicaSet的详细信息

kubectl创建Deployment后,会自动创建ReplicaSet,ReplicaSet会根据Deployment的配置信息创建Pod

5.1.2 命令VS配置文件

K8S支持两种创建资源的方式

命令 配置文件
使用方式 kubectl [command] kubectl apply -f file
可实现范围 创建资源、对资源更新、查看状态 创建资源、对资源更新
载体 命令 配置文件
优点 方便快捷 描述最终的状态、能够重复部署、方便管理
缺点 不利于管理 配置文件比较繁琐

5.1.3 Deployment配置文件简介

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
      image: nginx:1.7.9
      ports:
        - containerPort: 80
字段名称 说明
apiVersion API版本,Deployment的API版本为apps/v1,可以通过kubectl api-versions查看
kind 资源类型,Deployment的资源类型为Deployment,可以通过kubectl api-resources查看
metadata 元数据,包含Deployment的名称、标签、注释等信息,可以通过kubectl describe deployment nginx-deployment查看
spec 规格,包含Deployment的配置信息,包括Pod的副本数、Pod的模板、Pod的配置信息等,可以通过kubectl get deployment nginx-deployment -o yaml查看
replicas Pod的副本数,可以通过kubectl scale deployment nginx-deployment --replicas=3修改
template Pod的模板,包含Pod的元数据和规格,可以通过kubectl get deployment nginx-deployment -o yaml查看
metadata Pod的元数据,包含Pod的名称、标签、注释等信息,可以通过kubectl describe pod nginx-deployment-5c7588df5b-2q9q2查看
spec Pod的规格,包含Pod的配置信息,包括容器的镜像、容器的端口、容器的命令等,可以通过kubectl get pod nginx-deployment-5c7588df5b-2q9q2 -o yaml查看

执行kubectl apply -f nginx.yaml创建Deployment; 执行kubectl delete -f nginx.yaml删除Deployment

5.1.4 伸缩

伸缩是指在线增加或减少Pod的副本数

修改Deployment的配置文件,将replicas的值修改为3,然后执行kubectl apply -f nginx.yaml,即可实现伸缩

默认K8S不会将Pod调度到Master节点

5.1.5 FailOver

模拟k8s-node2故障,K8S会自动调度维持总副本数

5.1.6 用Label控制Pod的位置

label是key-value对

1
2
3
4
5
6
7
8
# 设置label
kubectl label node k8s-node1 disktype=ssd

# 查看label
kubectl get nodes --show-labels

# 删除label,不会触发重新部署,需要重新执行kubectl apply -f nginx.yaml
kubectl label node k8s-node1 disktype-

使用label控制Pod的位置,只需要在Deployment的配置文件中添加nodeSelector字段即可,disktype=ssd表示只将Pod调度到标签中包含disktype=ssd的节点上

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  template:
    metadata:
    labels:
      app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.7.9
      nodeSelector:
        disktype: ssd

5.2 DaemonSet

Controller类型 说明
Deployment 部署的副本Pod会分布在各个Node上,每个Node都可能运行好几个副本
DaemonSet 部署的副本Pod会运行在每个Node上,但每个Node只运行一个副本

使用DaemonSet的场景:日志收集、监控、存储、守护进程等,例如k8s中本身用DaemonSet运行的系统组件:kubectl get daemonset --namespace=kube-system

5.3 Job

容器按照持续运行的时间可分为两类:服务类容器和工作类容器。

容器类型 说明 举例 对应Controller类型
服务类容器 需要一直运行 Web应用、数据库、缓存等 Deployment、ReplicaSet和DaemonSet
工作类容器 运行一次或定时运行 数据处理、定时任务、批处理等 Job

5.3.1 Pod失败的情况

restartPolicy字段配置失败的处理策略

restartPolicy 说明 失败的处理
OnFailure 只有在容器退出状态码非0时才重启容器,一般用于工作类容器,如数据处理、定时任务、批处理等 只会创建一个Pod,体现在RESTARTS上
Never 无论何种原因终止,都不重启容器,一般用于一次性容器,如数据处理、定时任务、批处理等 会创建多个Pod,直到SUCCESS

5.3.2 Job的并行性

通过parallelism设置运行同时运行多个Pod,如下配置为:每次运行两个pod,直到总共6个Pod成功完成

1
2
3
spec:
  parallelism: 2
  completions: 6

5.3.3 定时Job

默认apiServer没有开启定时任务,需要在启动apiServer时添加--runtime-config=batch/v2alpha1=true 参数,然后重启kubelet服务systemctl restart kubelet.service

通过schedule字段设置定时任务,如下配置为:每分钟运行一次(创建一个新的Pod),直到总共6个Pod成功完成

1
2
3
spec:
  schedule: "*/1 * * * *"
  completions: 6

六、通过Service访问Pod

Pod是脆弱的,但应用是健壮的。

6.1 创建Service

创建Deployment

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd
spec:
  selector:
    matchLabels:
      run: httpd
  replicas: 3
  template:
    metadata:
      labels:
        run: httpd
    spec:
      containers:
        - name: httpd
          image: httpd
          ports:
            - containerPort: 80

创建Service

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: v1
kind: Service
metadata:
  name: httpd-svc
spec:
  selector:
    run: httpd
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80

查看Service与Pod的对应关系:Endpoints

1
kubectl describe service httpd-svc

6.2 Cluster IP底层实现

Cluster IP是虚拟IP,不是真实存在的IP,是kube-proxy进程通过iptables实现的

6.3 DNS访问Service

除了可以通过Cluster IP访问Service,还可以通过DNS访问Service

Cluster中的Pod可以通过<SERVICE_NAME>.<NAMESPACE_NAME>访问Service,例如:httpd-svc.default

tips1:同一namespace可忽略namespace_name

tips2: 不同namespace可通过<SERVICE_NAME>.<NAMESPACE_NAME>.svc.cluster.local 访问Service,例如:httpd-svc.default.svc.cluster.local

tips3: 一个yaml中可以同时定义多个资源,使用---分割

6.4 外网如何访问Service

Service类型

类型 说明
ClusterIP 默认类型,只能在集群内部访问,外部无法访问,一般用于内部服务访问
NodePort 在ClusterIP的基础上,绑定每个Node的端口,外部可以通过NodeIP:NodePort访问
LoadBalancer 在NodePort的基础上,通过云服务商提供的负载均衡器,外部可以通过LoadBalancer的IP访问

配置为NodePort类型

需要注意发布了NodePort方式的Service依然无法访问:解决Windows/Mac版Desktop Docker中自带的K8s无法访问pod ipMac使用minikube发布,本地访问Service失败问题解决

1
2
3
4
5
6
7
apiVersion: v1
kind: Service
metadata:
  name: httpd-svc
spec:
  type: NodePort
...

七、Rolling Update

7.1 实践

通过httpd:2.2.31版本升级为httpd:2.2.32版本演示k8s升级

7.2 回滚

关键操作及属性 说明
kubectl apply 每次更新应用,k8s都会记录下当前的配置,保存为一个revision
Deployment配置文件的revisionHistoryLimit 设置保存的revision数量,默认为10
kubectl apply * –record 记录每次更新的操作
kubectl rollout history deployment 查看Deployment的更新历史
kubectl rollout undo deployment 回滚到上一个版本

八、Health Check

0%