Kubernetes概述
Kubernetes是Google开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。在生产环境中部署一个应用程序时,通常要部署该应用的多个实例以便对应用请求进行负载均衡。
在Kubernetes中,我们可以创建多个容器,每个容器里面运行一个应用实例,然后通过内置的负载均衡策略,实现对这一组应用实例的管理、发现、访问,而这些细节都不需要运维人员去进行复杂的手工配置和处理。
Kubernetes 特点
可移植: 支持公有云,私有云,混合云,多重云(multi-cloud)
可扩展: 模块化,插件化,可挂载,可组合
自动化: 自动部署,自动重启,自动复制,自动伸缩/扩展
一,两种创建资源的方法
1. 基于命令的方式:
- 简单直观快捷,上手快。
- 适合临时测试或实验。
2. 基于配置清单的方式:
- 配置文件描述了
What
,即应用最终要达到的状态。 - 配置文件提供了创建资源的模板,能够重复部署。
- 可以像管理代码一样管理部署。
- 适合正式的、跨环境的、规模化部署。
- 这种方式要求熟悉配置文件的语法,有一定难度。
环境介绍
主机 | IP地址 | 服务 |
---|
master | 192.168.1.21 | k8s |
node01 | 192.168.1.22 | k8s |
node02 | 192.168.1.23 | k8s |
二. 配置清单(yam,yaml)
在k8s中,一般使用yaml格式的文件来创建符合我们预期期望的pod,这样的yaml文件我们一般称为资源清单
/etc/kubernetes/manifests/ k8s存放(yam、yaml)文件的地方
**kubectl explain deployment(通过explain参数加上资源类别就能看到该资源应该怎么定义)
kubectl explain deployment.metadata 通过资源类别加上带有Object标记的字段,我们就可以看到一级字段下二级字段的内容有那些怎么去定义等
kubectl explain deployment.metadata.ownerReferences 通过加上不同级别的字段名称来看下字段下的内容,而且前面的[]号代表对象列表
1.常见yaml文件写法,以及字段的作用
(1) apiVersion:api版本信息
(用来定义当前属于哪个组和那个版本,这个直接关系到最终提供使用的是那个版本)
[root@master manifests]# kubectl api-versions
//查看到当前所有api的版本
(2) kind: 资源对象的类别
(用来定义创建的对象是属于什么类别,是pod,service,还是deployment等对象,可以按照其固定的语法格式来自定义。)
(3) metadata: 元数据 名称字段(必写)
提供以下几个字段:
creationTimestamp: "2019-06-24T12:18:48Z"
generateName: myweb-5b59c8b9d-
labels: (对象标签)
pod-template-hash: 5b59c8b9d
run: myweb
name: myweb-5b59c8b9d-gwzz5 (pods对象的名称,同一个类别当中的pod对象名称是唯一的,不能重复)
namespace: default (对象所属的名称空间,同一名称空间内可以重复,这个名称空间也是k8s级别的名称空间,不和容器的名称空间混淆)
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: ReplicaSet
name: myweb-5b59c8b9d
uid: 37f38f64-967a-11e9-8b4b-000c291028e5
resourceVersion: "943"
selfLink: /api/v1/namespaces/default/pods/myweb-5b59c8b9d-gwzz5
uid: 37f653a6-967a-11e9-8b4b-000c291028e5
annotations(资源注解,这个需要提前定义,默认是没有的)
通过这些标识定义了每个资源引用的path:即/api/group/version/namespaces/名称空间/资源类别/对象名称
(4) spec: 用户期望的状态
(这个字段最重要,因为spec是用来定义目标状态的‘disired state’,而且资源不通导致spec所嵌套的字段也各不相同,也就因为spec重要且字段不相同,k8s在内部自建了一个spec的说明用于查询)
(5) status:资源现在处于什么样的状态
(当前状态,’current state‘,这个字段有k8s集群来生成和维护,不能自定义,属于一个只读字段)
2.编写一个yaml文件
[root@master ~]# vim web.yaml
kind: Deployment #资源对象是控制器
apiVersion: extensions/v1beta1 #api的版本
metadata: #描述kind(资源类型)
name: web #定义控制器名称
spec:
replicas: 2 #副本数量
template: #模板
metadata:
labels: #标签
app: web_server
spec:
containers: #指定容器
- name: nginx #容器名称
image: nginx #使用的镜像
执行一下
[root@master ~]# kubectl apply -f web.yaml
查看一下
[root@master ~]# kubectl get deployments. -o wide
//查看控制器信息
[root@master ~]# kubectl get pod -o wide
//查看pod节点信息
3.编写一个service.yaml文件
[root@master ~]# vim web-svc.yaml
kind: Service #资源对象是副本
apiVersion: v1 #api的版本
metadata:
name: web-svc
spec:
selector: #标签选择器
app: web-server #须和web.yaml的标签一致
ports: #端口
- protocol: TCP
port: 80 #宿主机的端口
targetPort: 80 #容器的端口
使用相同标签和标签选择器内容,使两个资源对象相互关联。
创建的service资源对象,默认的type为ClusterIP,意味着集群内任意节点都可访问。它的作用是为后端真正服务的pod提供一个统一的接口。如果想要外网能够访问服务,应该把type改为NodePort
(1)执行一下
[root@master ~]# kubectl apply -f web-svc.yaml
(2)查看一下
[root@master ~]# kubectl get svc
//查看控制器信息
(3)访问一下
[root@master ~]# curl 10.111.193.168
4.外网能够访问服务
(1)修改web-svc.yaml文件
kind: Service #资源对象是副本
apiVersion: v1 #api的版本
metadata:
name: web-svc
spec:
type: NodePort #添加 更改网络类型
selector: #标签选择器
app: web_server #须和web.yaml的标签一致
ports: #端口
- protocol: TCP
port: 80 #宿主机的端口
targetPort: 80 #容器的端口
nodePort: 30086 #指定群集映射端口,范围是30000-32767
(2)刷新一下
[root@master ~]# kubectl apply -f web-svc.yaml
(3)查看一下
[root@master ~]# kubectl get svc
(4)浏览器测试
三、小实验
基于上一篇博客实验继续进行
1.使用yaml文件的方式创建一个Deployment资源对象,要求镜像使用个人私有镜像v1版本。replicas为3个。
编写yaml文件
[root@master ~]# vim www.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: xgp
spec:
replicas: 3
template:
metadata:
labels:
app: www_server
spec:
containers:
- name: web
image: 192.168.1.21:5000/web:v1
(1)执行一下
[root@master ~]# kubectl apply -f web-svc.yaml
(2)查看一下
[root@master ~]# kubectl get deployments. -o wide
//查看控制器信息
[root@master ~]# kubectl get pod -o wide
//查看pod节点信息
(3)访问一下
2. 使用yaml文件的方式创建一个Service资源对象,要与上述Deployment资源对象关联,type类型为: NodePort,端口为:30123.
编写service文件
[root@master ~]# vim www-svc.yaml
kind: Service
apiVersion: v1
metadata:
name: www-svc
spec:
type: NodePort
selector:
app: www_server
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30123
执行一下
[root@master ~]# kubectl apply -f www-svc.yaml
查看一下
[root@master ~]# kubectl get svc
访问一下
四. 总结
1. Pod的作用
在k8s中pod是最小的管理单位,在一个pod中通常会包含一个或多个容器。大多数情况下,一个Pod内只有一个Container容器。
在每一个Pod中都有一个特殊的Pause容器和一个或多个业务容器,Pause来源于pause-amd64镜像,Pause容器在Pod中具有非常重要的作用:
- Pause容器作为Pod容器的根容器,其本地于业务容器无关,它的状态代表了整个pod的状态。
- Pod里的多个业务容器共享Pause容器的IP,每个Pod被分配一个独立的IP地址,Pod中的每个容器共享网络命名空间,包括IP地址和网络端口。Pod内的容器可以使用localhost相互通信。k8s支持底层网络集群内任意两个Pod之间进行通信。
- Pod中的所有容器都可以访问共享volumes,允许这些容器共享数据。volumes还用于Pod中的数据持久化,以防其中一个容器需要重新启动而丢失数据。
2. Service的作用
Service 是后端真实服务的抽象,一个 Service 可以代表多个相同的后端服务
Service 为 POD 控制器控制的 POD 集群提供一个固定的访问端点,Service 的工作还依赖于 K8s 中的一个附件,就是 CoreDNS ,它将 Service 地址提供一个域名解析。
NodePort 类型的 service
clusterIP:指定 Service 处于 service 网络的哪个 IP,默认为动态分配
NodePort 是在 ClusterIP 类型上增加了一个暴露在了 node 的网络命名空间上的一个 nodePort,所以用户可以从集群外部访问到集群了,因而用户的请求流程是:Client -> NodeIP:NodePort -> ClusterIP:ServicePort -> PodIP:ContainerPort。
可以理解为 NodePort 增强了 ClusterIP 的功能,让客户端可以在每个集群外部访问任意一个 nodeip 从而访问到 clusterIP,再由 clusterIP 进行负载均衡至 POD。
3.流量走向
我们在创建完成一个服务之后,用户首先应该访问的是nginx反向代理的ip,然后通过nginx访问到后端的k8s服务器(master节点)的“NodePort暴露IP 及 映射的端口“,通过”master节点“的“ip+映射端口”访问到后端k8s节点的信息。