k8s核心概念与高级特性
# 一、K8S 核心概念
K8S中还有一些高级特性有必要学习下:弹性扩缩应用(见上文)、滚动更新与回滚(见上文)、配置管理、存储卷、网关路由等。我们先看一些核心概念。
# 3.1、Deployment
Deployment负责创建和更新应用程序的实例。创建Deployment后,Kubernetes Master 将应用程序实例调度到集群中的各个节点上。如果托管实例的节点关闭或被删除,Deployment控制器会将该实例替换为群集中另一个节点上的实例。这提供了一种自我修复机制来解决机器故障维护问题。
# 3.2、Pod
Pod相当于逻辑主机的概念,负责托管应用实例。包括一个或多个应用程序容器(如 Docker),以及这些容器的一些共享资源(共享存储、网络、运行信息等)。
# 3.3、Service
Service是一个抽象层,它定义了一组Pod的逻辑集,并为这些Pod支持外部流量暴露、负载均衡和服务发现。
尽管每个Pod 都有一个唯一的IP地址,但是如果没有Service,这些IP不会暴露在群集外部。Service允许您的应用程序接收流量。Service也可以用在ServiceSpec标记type的方式暴露,type类型如下:
ClusterIP(默认):在集群的内部IP上公开Service。这种类型使得Service只能从集群内访问。
NodePort:使用NAT在集群中每个选定Node的相同端口上公开Service。使用 : 从集群外部访问Service。是ClusterIP的超集。
LoadBalancer:在当前云中创建一个外部负载均衡器(如果支持的话),并为Service分配一个固定的外部IP。是NodePort的超集。
ExternalName:通过返回带有该名称的CNAME记录,使用任意名称(由spec中的externalName指定)公开Service。不使用代理。
# 3.4、ReplicaSet
ReplicaSet确保任何时间都有指定数量的Pod副本在运行。通常用来保证给定数量的、完全相同的Pod的可用性。建议使用Deployment来管理ReplicaSet,而不是直接使用ReplicaSet。
# 3.5、ConfigMap
ConfigMap是一种API对象,用来将非机密性的数据保存到键值对中。使用时,Pod可以将其用作环境变量、命令行参数或者存储卷中的配置文件。使用ConfigMap可以将你的配置数据和应用程序代码分开。
# 3.6、Volume
Volume指的是存储卷,包含可被Pod中容器访问的数据目录。容器中的文件在磁盘上是临时存放的,当容器崩溃时文件会丢失,同时无法在多个Pod中共享文件,通过使用存储卷可以解决这两个问题。
常用的存储卷有如下几种:
- configMap:configMap卷提供了向Pod注入配置数据的方法。ConfigMap对象中存储的数据可以被configMap类型的卷引用,然后被Pod中运行的容器化应用使用。
- emptyDir:emptyDir卷可用于存储缓存数据。当Pod分派到某个Node上时,emptyDir卷会被创建,并且Pod在该节点上运行期间,卷一直存在。当Pod被从节点上删除时emptyDir卷中的数据也会被永久删除。
- hostPath:hostPath卷能将主机节点文件系统上的文件或目录挂载到你的Pod中。在Minikube中的主机指的是Minikube所在虚拟机。
- local:local卷所代表的是某个被挂载的本地存储设备,例如磁盘、分区或者目录。local卷只能用作静态创建的持久卷,尚不支持动态配置。
- nfs:nfs卷能将NFS(网络文件系统)挂载到你的Pod中。
- persistentVolumeClaim:persistentVolumeClaim卷用来将持久卷(PersistentVolume)挂载到Pod中。持久卷(PV)是集群中的一块存储,可以由管理员事先供应,或者使用存储类(Storage Class)来动态供应,持久卷是集群资源类似于节点。
# 3.7、Ingress
通过K8S的Ingress资源可以实现类似Nginx的基于域名访问,从而实现Pod的负载均衡访问
# 二、K8S 高级特性
# 2.1、配置管理
ConfigMap允许你将配置文件与镜像文件分离,以使容器化的应用程序具有可移植性。接下来我们演示下如何将ConfigMap的的属性注入到Pod的环境变量中去。
- 添加配置文件
nginx-config.yaml
用于创建ConfigMap,ConfigMap名称为nginx-config,配置信息存放在data节点下
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
nginx_env: "test"
ui_properties_file_name: "user-interface.properties"
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
user-interface.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 应用 nginx-config.yaml 文件创建ConfigMap
kubectl create -f nginx-config.yaml
- 获取所有ConfigMap
[root@k8s-master ~]# kubectl get configmaps
NAME DATA AGE
game-demo 4 7m17s
nginx-config 4 8s
2
3
4
- 通过yaml格式查看ConfigMap中的内容
kubectl get configmaps nginx-config -o yaml
- 添加配置文件
nginx-deployment.yaml
用于创建Deployment,部署一个Nginx服务,在Nginx的环境变量中引用ConfigMap中的属性:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.10
ports:
- containerPort: 80
env:
- name: NGINX_ENV # 在Nginx中设置环境变量
valueFrom:
configMapKeyRef:
name: nginx-config # 设置ConfigMap的名称
key: nginx-env # 需要取值的键
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
- 应用配置文件文件创建Deployment
kubectl apply -f nginx-deployment.yaml
- 创建成功后查看Pod中的环境变量,发现NGINX_ENV变量已经被注入
kubectl exec deployments/nginx-deployment -- env
......
NGINX_ENV=test
2
3
# 2.2、存储卷使用
通过存储卷,我们可以把外部数据挂载到容器中去,供容器中的应用访问,这样就算容器崩溃了,数据依然可以存在。
- 之前我们使用Docker部署软件时是可以挂载文件的
docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx:1.10
2
3
4
5
- K8S也可以挂载文件,添加配置文件nginx-volume-deployment.yaml用于创建Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-volume-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.10
ports:
- containerPort: 80
volumeMounts:
- mountPath: /usr/share/nginx/html
name: html-volume
- mountPath: /var/log/nginx
name: logs-volume
- mountPath: /etc/nginx
name: conf-volume
volumes:
- name: html-volume
hostPath:
path: /home/docker/mydata/nginx/html
type: Directory
- name: logs-volume
hostPath:
path: /home/docker/mydata/nginx/logs
type: Directory
- name: conf-volume
hostPath:
path: /home/docker/mydata/nginx/conf
type: Directory
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
35
36
37
38
39
40
41
# 2.3、网关路由
进入页面 (opens new window),将里面内容复制,保存到k8s master机器上的一个文件ingress-controller.yaml里,里面的镜像地址需要修改下,也可以直接使用这个地址:http://media.ruanyou.top/blog/config/ingress-controller-zg.yaml
安装ingress,执行如下命令
[root@k8s-master ~]# kubectl apply -f http://media.ruanyou.top/blog/config/ingress-controller-zg.yaml
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
daemonset.apps/nginx-ingress-controller created
service/ingress-nginx created
2
3
4
5
6
7
8
9
10
11
12
查看是否安装成功
[root@k8s-master ~]# kubectl get pods -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ingress-controller-gswbk 1/1 Running 0 2m7s 172.16.93.7 k8s-node2 <none> <none>
nginx-ingress-controller-jg2g4 1/1 Running 0 2m7s 172.16.93.6 k8s-node1 <none> <none>
2
3
4
配置ingress访问规则(就是类似配置nginx的代理转发配置),让ingress将域名tomcat.yuanyue.com
转发给后端的tomcat-service-yaml 服务,新建一个文件ingress-tomcat.yaml
,内容如下:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: web-ingress
spec:
rules:
- host: tomcat.yuanyue.com #转发域名
http:
paths:
- path: /
backend:
serviceName: tomcat-service-yaml
servicePort: 80 #service的端口
2
3
4
5
6
7
8
9
10
11
12
13
执行如下命令生效规则:
kubectl apply -f ingress-tomcat.yaml
查看生效的ingress规则:
[root@k8s-master ~]# kubectl get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
web-ingress <none> tomcat.yuanyue.com 80 6s
2
3
在访问机器里增加如下host(ingress部署的机器ip对应访问的域名)
172.16.93.6 tomcat.yuanyue.com
172.16.93.7 tomcat.yuanyue.com
2
配置完后直接在客户机浏览器访问http://tomcat.yuanyue.com/,能正常访问tomcat。
# 2.4、总结
Service 是 K8S 服务的核心,屏蔽了服务细节,统一对外暴露服务接口,真正做到了“微服务”。
举个例子,我们的一个服务 A,部署了 3 个备份,也就是 3 个 Pod;对于用户来说,只需要关注一个 Service 的入口就可以,而不需要操心究竟应该请求哪一个 Pod。优势非常明显:一方面外部用户不需要感知因为 Pod 上服务的意外崩溃、K8S 重新拉起 Pod 而造成的 IP 变更,外部用户也不需要感知因升级、变更服务带来的 Pod 替换而造成的 IP 变化,另一方面,Service 还可以做流量负载均衡。
但是,Service 主要负责 K8S 集群内部的网络拓扑。集群外部需要用 Ingress 。Ingress 是整个 K8S 集群的接入层,负责集群内外通讯。
Ingress 和 Service 的网络拓扑关系图如下: