1. docker
Docker 是一个应用容器引擎,说简单点就是将你的应用里三层外三层打包成一个镜像,然后用一条命令将镜像跑起来,本质上它就是一个进程而已,只不过使用了一些隔离技术(cgroups 、namespace、rootfs、setns)让其“隐藏”起来,从而感觉上它是一个容器,而且是一个独立的系统。docker和虚拟机有着本质的区别,虚拟机会占用更多的物理资源,虚拟机比较笨重,重建或释放都比较费时。例如有个1000平的大房子,如果隔成10个甚至20个小房间都没问题,而且可以随时拆掉再隔;但如果在里面盖房子的话,可能盖5间就不错了。
image.png
用以下命令揭示“容器”的真实身份
# 查看 a776ea6f142d2819 容器的进程号
[root@node1 ~]# docker inspect --format '{{ .State.Pid }}' a776ea6f142d
2819
# 发现容器在宿主机中进程
[root@node1 ~]# ps -aux |grep 2819
root 22819 0.0 0.0 109096 6604 ? Sl Apr28 3:40 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/a2b9a823d8451eaa32c92330599e7167dc69b46930746b536ec018ca91e30914 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc -systemd-cgroup
2. kubernetes
Kubernetes是Google开源的一个容器编排引擎,随着docker的流行,当运行数百、数千个容器时,人们就不得不考虑一个问题,如何让容器更高效的运行、以及如何在分布式环境下运行容器等。这是k8s就横空出世了,它简化了大规模部署的容器管理问题,而在k8s流行之前,docker公司就有三剑客的另外两个产品:docker-compose、swarm。swarm是docker公司主推的容器编排工具,也是和k8s一决高下的产品,但最终用户用脚投票,k8s以完胜收场,这里不得不提的一个大牛就是Tower(高塔),作为k8s的布道师功不可没。
一、架构
image.png(1) kubectl
集群的客户端命令行工具,请求apiserver的rest接口,查看和维护集群,kubectl需要一个配置文件: kubeconfig,此文件包含用户、集群上下文、命名空间、认证机制信息等,kubectl可以同时管理多个集群,在请求apiserver需要认证信息。kubectl可以同时管理多个集群。
(2) kube-apiserver
API Server提供了资源对象的唯一操作入口,其他所有组件都必须通过它提供的API来操作资源数据,只有API Server与存储通信,其他模块通过API Server访问集群状态。以RESTFul接口方式提供给外部客户和内部组件进行同一调用。
(3) kube-controller-manager
实现集群故障检测和恢复的自动化工作,负责执行各种控制器,主要有:
-
endpoint-controller:定期刷新service和pod(关联信息由endpoint对象维护)的关联关系,保证service到pod的映射总是最新的。
-
replication-controller:定期检查replicationController(新版叫ReplicaSet)中配置的pod数量和实际运行数量是否一致,如果不一致会自动启动或停止pod。
(4) kube-scheduler
Scheduler收集和分析当前Kubernetes集群中所有Work节点的资源(内存、CPU)负载情况,然后分发Pod到集群中可用的节点上,并实时监测集群中未分发和已分发的所有运行的Pod,将已分发的pod信息写回到API Server。为了避免频繁查询,Scheduler会缓存一份最新的信息在本地。
(5) etcd
和Zookeeper类似,负责存储各个组件的共享数据,保证集群高可用。
(6) kube-proxy
负责接收并转发请求。Kube-proxy的核心功能是将到达Service的访问请求转发到后台的某个具体的Pod。无论是通过ClusterIP+Port的方式还是NodeIP+NodePort的方式访问Service,最终都会被节点的Iptables规则(新版本是通过LVS转发)重定向到Kube-proxy监听服务代理端口,该代理端口实际上就是SocketServer在本地随机打开的一个端口,SocketServer是Kube-proxy为每一个服务都会创建的“服务代理对象”的一部分。当Kube-proxy监听到Service的访问请求后,它会找到最适合的Endpoints,然后将请求转发过去。具体的路由选择依据Round Robin算法及Service的Session会话保持这两个特性。
(7) kubelet
运行在每个work节点上,作为agent,负责分配该Node上的Pods任务、启动Pod、管理容器、周期性获取容器状态等,反馈给kube-apiserver。注意:kubelet 与 kube-apiserver 之间的通信是双向的, kubelet 既需要访问 kube-apiserver 获取分配到自己节点上的 pod 信息, kube-apiserver 也需要主动访问 kubelet 拉取日志, 状态, 监控数据等信息, 所以对两个组件来说, 认证是双向的, kube-apiserver 需要持有 kubelet 的客户端证书, 以完成 kubelet 对自己身份的校验; kubelet 也需要持有 kube-apiserver 的客户端证书, 完成 kube-apiserver 对自己身份的认证。
通过kubeadm安装时,Kubelet是唯一一个运行在宿主机上的服务,因为它负责启动容器,如果它也运行在容器中,那就成了它在容器中启动其他容器啦,这样会有很多不方便。
(8) kube-DNS
一个可选的DNS服务,用于为每个Service对象创建DNS记录,这样所有的Pod就可以通过DNS访问服务了。
(9) CRI
CRI是k8s对容器操作的统一抽象,在1.20版本之前,k8s直接调用docker的API,所以搞了一个 dockershim的适配器来完成,之前比较热的话题k8s要废弃docker,其实是废弃这个东西。目前k8s最新版对容器操作直接对接OCI(容器统一的开发标准)来完成,这样的好处不言而喻,不管什么容器厂家,只要实现了OCI标准,就能和k8s无缝对接,详细请看我的文章《docker的陨落》。
二、安装
使用kubeadm安装k8s非常简单,但经常失败,大致失败的原因有几点:
- 镜像下载不下来,使用阿里云镜像,但版本比较老
- 虚拟机,云主机等多网卡环境,需指定advertiseAddress,calico插件需要指定通信的网卡
- pod网段和service网段和系统网段冲突
- 浮动IP问题
- OpenStack环境下容器跨节点无法通行问题,可尝试关闭port-security来解决
- 编写kubeadm配置文件: kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: InitConfiguration
# kubeadm 使用 eth0 的默认网络接口(通常是内网IP,在virtualbox一般是10.0.2.15)做为 Master节点的advertise address
# 如果是通过虚拟机安装k8s,那么必须设置advertiseAddress地址,否则导致其他节点无法正常和master通信
localAPIEndpoint:
# 不能绑定浮动IP
advertiseAddress: 10.0.2.24
bindPort: 6443
---
# 开启Kube-proxy代理规则为ipvs,默认是Iptables
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
---
apiVersion: "kubeadm.k8s.io/v1beta2"
kind: ClusterConfiguration
kubernetesVersion: v1.17.4
controlPlaneEndpoint: "apiserver:6443"
apiServer:
extraArgs:
service-node-port-range: 1000-40000
certSANs:
- 10.0.2.24
- 127.0.0.1
networking:
# podSubnet相当于--pod-network-cidr 参数
podSubnet: 192.244.0.0/16
# serviceSubnet相当于--service-network-cidr 参数
serviceSubnet: 10.96.0.0/16
- 执行kubeadm初始化操作
# 加上此参数:--upload-certs ,其他节点加入时可以自动获取证书
$ kubeadm init --config=kubeadm-config.yaml --upload-certs
- 安装客户端,执行节点加入操作等
- 安装网络插件,推荐安装 calico 插件。
3. 应用部署
k8s内置了多种资源类型,如pod是k8s中最小的单元, ReplicaSet管理pod的多个副本,Deployment 是无状态应用。
下面是部署一个nginx到k8s集群,并设置有pod有3个副本
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
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: registry.cn-hangzhou.aliyuncs.com/moobox/nginx
ports:
- containerPort: 80---
#service
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: ClusterIP
$ kubectl apply -f nginx.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-6c84b7494d-gj5qk 1/1 Running 0 4m11s
nginx-deployment-6c84b7494d-j8fhz 1/1 Running 0 4m11s
nginx-deployment-6c84b7494d-xbvdf 1/1 Running 0 4m11s
4. 高级
一、监控
使用prometheus + Grafana监控k8s集群,支持operator的话,可下载kube-prometheus v0.5.0 版(最新版有一个镜像拉取不了)进行安装。安装完如果没有监控数据,可能是:
问题1: 时间不同步,时区不对,设置为本地时区和当前时间,查看
prometheus主页发现有警告,可通过timedatectl和date 命令修改
问题2:Grafana 的prometheus数据源,默认配置的是k8s内部域名地址,所以外部无法访问,数据源需要修改为外部的地址: http://192.168.x.x:39090/
二、蓝绿部署
k8s默认就支持滚动升级,蓝绿部署也是支持的,加入有个服务之前的版本是V1,新部署了一个版本是V2,那我们就可以通过两个service来实现一个简单的蓝绿部署
#service
apiVersion: v1
kind: Service
metadata:
name: web-bluegreen-v1
namespace: dev
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
# 通过选择不同版本的webapp,来切换流量
selector:
app: webapp
version: v1.0 #version: v2.0
type: ClusterIP
#service
apiVersion: v1
kind: Service
metadata:
name: web-bluegreen-v2
namespace: dev
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
# 通过选择不同版本的webapp,来切换流量
selector:
app: webapp
version: v2.0
type: ClusterIP
k8s默认是不支持灰度发布的,想要实现灰度发布,可使用其他组件,如istio
三、自动扩容
HPA(Horizontal Pod Autoscaler)是k8s的一个资源对象,利用prometheus获取该资源对象的监控指标,可实现Pod自动伸缩。但有几点必须要注意:
- pod一定要设置资源限制request、limit等,才能开启HPA
- HPA控制器的时间窗口默认是15秒,即每隔15s拉取一次监控指标,可通过–horizontal-pod-autoscaler-sync-period参数设定
kubernetes集群需要配置好metrics server - 目前是v1版本,从k8s v1.18 支持 v2beta2版本,可支持基于内存的伸缩指标,可自定义伸缩指标
基于内存/CPU的自动伸缩
下面我们对一个xxx应用进行自动伸缩,当CPU使用超过60%时,会自动增加pod,但不会超过6个
$ kubectl autoscale deployment xxx --cpu-percent=60 --min=2 --max=6
QPS的自动伸缩
下面创建一个HPA来实现 一个QPS的 自动伸缩:
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: blog-web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: blog-web
minReplicas: 2
maxReplicas: 8
metrics:
- type: Pods
pods:
metric:
name: http_requests_received
target:
type: AverageValue
averageValue: 10
网友评论