1 K8S介绍

回顾应用的部署历程:


  • 传统部署:物理服务器上运行应用程序。
  • 虚拟机部署:物理服务器上安装虚拟机,在虚拟机上运行应用程序。
  • 容器部署:物理服务器上安装容器运行时,使用容器运行应用程序。



请问大家,还存在什么问题嘛?


Kubernetes 是谷歌开源容器集群管理的系统。

  • 基于容器的应用部署、维护和滚动升级
  • 负载均衡和服务发现
  • 跨机器和跨地区的集群调度
  • 自动伸缩,自我修复
  • 无状态服务和有状态服务
  • 广泛的存储支持
  • 广泛的网络支持
  • 插件机制保证扩展性


只要应用可以在容器中运行,那么它就可以很好的在 Kubernetes 上运行,并被管理。

2 K8S架构


Kubernetes 集群包含如下核心组件:

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

比如典型的创建产线服务的流程:


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

  • kube-dns 负责为整个集群提供 DNS 服务
  • Ingress Controller 为服务提供外部入口
  • Heapster or Metric Server 提供资源监控
  • Dashboard 提供 Web UI
  • Federation 提供跨可用区的集群
  • ……

Kubernetes 设计理念和功能是一个分层架构:


从上到下依次是:

  • 接口层:kubectl 命令行工具、客户端 SDK
  • 管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩缩容、动态供给等)以及策略管理(RBAC、SA、PSP、NetworkPolicy 等)
  • 应用层:部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS 解析等)
  • 核心层:Kubernetes 最核心的功能,对外提供 API 构建高层的应用,对内提供插件式应用执行环境

在这个分层体系的周边催生出了异常强大的生态系统 CNCF(Cloud Native Computing Foundation,中文译为“云原生计算基金会”):https://landscape.cncf.io/

3 常用资源对象

Kubernetes 的资源对象有很多,这里介绍一部分。更多定义请参考:https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/

3.1 Node & Pod

Node 是 Pod 真正运行的主机,可以是物理机,也可以是虚拟机。为了管理 Pod,每个 Node 节点上至少要运行 container runtime(比如 docker 或者 rkt)、​​kubelet​​​ 和 ​​kube-proxy​​ 服务。

Pod 是一组紧密关联的容器集合,它们共享 IPC(Inter-Process Communication,进程间通信) , Network namespace 和 文件存储(需挂载到容器),是 Kubernetes 调度的基本单位。



apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx

3.2 Namespace

Namespace 是对一组资源和对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组。常见的 pods, services, replication controllers 和 deployments 等都是属于某一个 namespace 的(默认是 default),而 node, persistentVolumes 等则不属于任何 namespace。

apiVersion: v1
kind: Namespace
metadata:
name: test

3.3 ConfigMap

ConfigMap 用于保存配置数据的键值对,可以用来保存单个属性,也可以用来保存配置文件。

apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
special.type: charm
game.properties: |
enemies=aliens
lives=3
secret.code.allowed=true
secret.code.lives=30
ui.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

3.4 Deployment

Deployment 为无状态 Pod 提供便利的声明式管理,可以定义 Pod 的副本数量,调度策略等,为最常用的资源对象之一,一般将 Pod 的定义内置在 Deployment 中。

apiVersion: apps/v1
kind: Deployment
metadata:
name: {{name}}
namespace: {{namespace}}
spec:
replicas: 2
selector:
matchLabels:
k8s-app: {{name}}
template:
metadata:
labels:
k8s-app: {{name}}
spec:
terminationGracePeriodSeconds: 10
nodeSelector:
k8s-meeting: true # 按需调整
volumes:
- name: log
hostPath:
path: /var/log/quanshi/{{name}}
type: DirectoryOrCreate
- name: conf
configMap:
name: {{name}}
containers:
- name: {{name}}
image: {{image}}
env:
- name: NODE_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
resources:
limits:
cpu: 2000m
memory: 4000Mi
requests:
cpu: 100m
memory: 150Mi
securityContext:
privileged: false
volumeMounts:
- name: log
mountPath: /var/log/quanshi
- name: conf
mountPath: /mnt/conf

3.5 DaemonSet

DaemonSet 保证在每个 Node 上都运行一个容器副本,常用来部署一些集群的日志、监控或者其他系统管理应用。

apiVersion: apps/v1
kind: DaemonSet

3.6 StatefulSet

StatefulSet 是为了解决有状态服务的问题,Pod 重新调度后其 PodName 和 HostName 不变,有序部署,有序扩展,即 Pod 是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依序进行(即从 0 到 N-1,在下一个 Pod 运行之前所有之前的 Pod 必须都是 Running 和 Ready 状态)。

apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx

3.7 Service

Service 是应用服务的抽象,为应用提供负载均衡和服务发现。匹配 Pod IP 和端口列表组成 endpoints,由 kube-proxy 负责将服务 IP 负载均衡到这些 endpoints 上。

每个 Service 都会自动分配一个 cluster IP(仅在集群内部可访问的虚拟地址)和 DNS 名,其他容器可以通过该地址或 DNS 来访问服务,而不需要了解后端容器的运行。


kind: Service
apiVersion: v1
metadata:
name: {{name}}
namespace: {{namespace}}
spec:
selector:
k8s-app: {{name}}
ports:
- name: serviceport
protocol: TCP
port: 8081
targetPort: 8081

3.8 Ingress

Ingress 就是为进入集群的请求提供路由规则的集合。


apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: s1
servicePort: 80
- host: bar.foo.com
http:
paths:
- backend:
serviceName: s2
servicePort: 80

3.9 HPA

Horizontal Pod Autoscaling (HPA) 可以根据 CPU 使用率或应用自定义 metrics 自动扩展 Pod 数量。

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource # 系统资源指标
resource:
name: cpu
targetAverageUtilization: 50
- type: Pods # 自定义指标
pods:
metricName: packets-per-second
targetAverageValue: 1k
- type: Object # 扩展组件暴露的指标
object:
metricName: requests-per-second
target:
apiVersion: extensions/v1beta1
kind: Ingress
name: main-route
targetValue: 10k

Cluster AutoScaler 可以和 Horizontal Pod Autoscaler(HPA)配合使用,更高效的扩缩容。

​https://github.com/kubernetes/autoscaler​


4 集群环境

随着用户的增加,生态的完善,功能在不断的增加增强,同时便利性也同步得到了提升,目前已经跨过了第一波的踩坑期,大家可以放心大胆的去 Try it.

4.1 集群的搭建

快速体验:用别人的玩玩

  • play-with-k8s:提供了一个免费的 Kubernetes 体验环境,可以使用 kubeadm 来创建 Kubernetes 集群。注意,每次创建的集群最长可以使用 4 小时。
  • Katacoda playground:提供了一个免费的 2 节点 Kubernetes 体验环境,并且会自动部署整个集群。

单机部署:自己弄个小的试试

  • minikube:创建 Kubernetes cluster(单机版)最简单的方法。
  • kind:以 Docker 容器的方式运行 Kubernetes 集群。
  • kubeasz:国内网络环境下也可以考虑使用 kubeasz 的 AllInOne 部署。

集群部署:用于生产环境

5 常用命令(一个栗子)

​https://kubernetes.io/docs/reference/kubectl/overview/​

kubectl [command] [TYPE] [NAME] [flags]


常用命令:
#查看所有名称空间
kubectl get ns
#获取所有的pod
kubectl get pods --all-namespaces -o wide
#查看meeting 名称空间中pod
kubectl get pods -n meeting
#查看名称空间下deployment状态
kubectl get deployment -n meeting
#查看实时日志
kubectl logs -f pc3joinmeeting-c9cbcd4b6-9n98c -n meeting
#进入指定容器
kubectl exec -it -n default pre-live-web-5ddbbc68d-j25sv /bin/bash
#查看svc组成员所处node
kubectl get svc -n meeting
#安装/更新 部署服务
kubectl apply -f service-deploy.yaml
#查看组中成员状态以及对应到node的节点上
kubectl get pod -o wide -n meeting
#获取指定命名空间的服务
kubectl get svc -n meeting
#使用yaml文件创建pod
kubectl create -f YAML_FILE.yaml
#使用yaml文件删除pod
kubectl delete -f YAML_FILE.yaml
#查看存在的标签
kubectl get nodes --show-labels
#删除pod
kubectl delete pod pod-status-test -n meeting