本文介绍如何在kubernetes集群中部署一个nginx服务,并且能够对其进行访问。介绍Namespace、Pod、Label、Deployment、Service五大常用资源
Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。
默认情况下,kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中,可能不想让两个Pod之间进行互相的访问,那此时就可以将两个Pod划分到不同的namespace下。kubernetes通过将集群内部的资源分配到不同的Namespace中,可以形成逻辑上的"组",以方便不同的组的资源进行隔离使用和管理。
可以通过kubernetes的授权机制,将不同的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离。此时还能结合kubernetes的资源配额机制,限定不同租户能占用的资源,例如CPU使用量、内存使用量等等,来实现租户可用资源的管理。
kubernetes在集群启动之后,会默认创建几个namespace
kubectl get namespace
【说明】:
default:所有未指定Namespace的对象都会被分配在default命名空间
kube-node-lease:集群节点之间的心跳维护,v1.13开始引入
kube-public:此命名空间下的资源可以被所有人访问(包括未认证用户)
kube-system:所有由Kubernetes系统创建的资源都处于这个命名空间
(介绍命令行方式,yaml配置文件方式后面介绍)
2.1、查看
查看所有的namespace,命令:kubectl get ns
kubectl get ns
查看指定的ns,命令:kubectl get ns [ns名称]
kubectl get ns default
指定输出格式,命令:kubectl get ns [ns名称] -o 格式参数
# kubernetes支持的格式有很多,比较常见的是wide、json、yaml
kubectl get ns default -o yaml
查看ns详情,命令:kubectl describe ns [ns名称]
kubectl describe ns default
【其中】:
Status的Active表示命名空间正在使用中,Terminating表示正在删除命名空间;
resource quota表示针对namcespace做的资源限制
LimitRange针对namespace中的每个组件做的资源限制
2.2、创建
创建namespace
kubectl create ns dev
2.3、删除
删除namespace
kubectl delete ns dev
2.4、配置方式
首先准备一个yaml文件,ns-dev.yaml
apiVersion: v1
kind: Namespace
metadata:
name: dev
然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f ns-dev.yaml
删除:kubectl delete -f ns-dev.yaml
Pod是kubernetes集群进行管理的最小单元,程序要运行必须部署在容器中,而容器必须存在于Pod中。
Pod可以认为是容器的封装,一个Pod中可以存在一个或者多个容器。
kubernetes在集群启动之后,集群中的各个组件也都是以Pod方式运行的。可以通过下面命令查看:
# Kubernetes系统创建的资源都处于kube-system命名空间
kubectl get pod -n kube-system
kubernetes没有提供单独运行Pod的命令,都是通过Pod控制器来实现的
# 命令格式: kubectl run (pod控制器名称) [参数]
# --image 指定Pod的镜像
# --port 指定端口
# --namespace 指定namespace
kubectl run nginx --image=nginx:latest --port=80 --namespace dev
【命令说明】:
使用kubectl基于nginx:latest镜像(镜像不存在会自动下载)创建一个名为nginx的pod控制器(而不是Pod),并生成pod容器,并配置80端口映射,该pod位于dev namespace下。
查看Pod基本信息
kubectl get pods -n dev
查看Pod详细信息
#不指定namespace会默认到default去查,会查不到
kubectl describe pod nginx -n dev
【其中】:Events表示整个Pod创建过程,先通过scheduler调度分配给node2节点,然后开始pull nginx:latest镜像,然后创建nginx容器,最后启动nginx容器。
获取Pod IP
kubectl get pods -n dev -o wide
访问Pod
curl http://10.244.2.12
删除指定Pod
kubectl delete pod nginx-dd6b5d745-69vfh -n dev
此时,显示删除Pod成功,但是再查询,发现又新产生了一个
kubectl get pods -n dev
这是因为当前Pod是由Pod控制器创建的,Pod控制器会监控Pod状况,一旦发现Pod死亡,会立即重建。此时要想删除Pod,必须要删除Pod控制器。
查询当前namespace下的Pod控制器
kubectl get deploy -n dev
删除Pod控制器
kubectl delete deploy nginx -n dev
稍等片刻,再查询Pod,发现Pod被删除了
kubectl get pods -n dev
创建一个pod-nginx.yaml,内容如下:
apiVersion: v1
kind: Pod
metadata:
name: nginx #此时这是pod名称,而不是pod控制器名称
namespace: dev
spec:
containers:
- image: nginx:latest
name: pod
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
创建:
kubectl create -f pod-nginx.yaml
删除:
kubectl delete -f pod-nginx.yaml
Label是kubernetes系统中的一个重要概念。它的作用就是在资源上添加标识,用来对它们进行区分和选择。
Label的特点:
一个Label会以key/value键值对的形式附加到各种对象上,如Node、Pod、Service等等
一个资源对象可以定义任意数量的Label ,同一个Label也可以被添加到任意数量的资源对象上去
Label通常在资源对象定义时确定,当然也可以在对象创建后动态添加或者删除
可以通过Label实现资源的多维度分组,以便灵活、方便地进行资源分配、调度、配置、部署等管理工作。
一些常用的Label 示例如下:
版本标签:"version":"release", "version":"stable"......
环境标签:"environment":"dev","environment":"test","environment":"pro"
架构标签:"tier":"frontend","tier":"backend"
标签定义完毕之后,还要考虑到标签的选择,这就要使用到Label Selector(标签选择器),即:
Label用于给某个资源对象定义标识
Label Selector用于查询和筛选拥有某些标签的资源对象
当前有两种Label Selector:
基于等式的Label Selector
name = slave: 选择所有包含Label中key="name"且value="slave"的对象
env != production: 选择所有包括Label中的key="env"且value不等于"production"的对象
基于集合的Label Selector
name in (master, slave): 选择所有包含Label中的key="name"且value="master"或"slave"的对象
name not in (frontend): 选择所有包含Label中的key="name"且value不等于"frontend"的对象
标签的选择条件可以使用多个,此时将多个Label Selector进行组合,使用逗号","进行分隔即可。例如:
name=slave,env!=production
name not in (frontend),env!=production
步骤1:使用上面的pod-nginx.yaml先创建一个不带label标签的pod
kubectl create -f pod-nginx.yaml #使用yaml创建pod
kubectl get pod -n dev #查看已创建pod
kubectl get pod -n dev --show-labels #查看已创建pod的标签信息,按照pod-nginx.yaml内容是没有创建label的
步骤2:对已创建的pod打label标签
kubectl label pod nginx -n dev version=1.0 #给nginx pod加上版本号1.0标签
kubectl get pod -n dev --show-labels #查看label标签信息
步骤3:给已创建的已有标签的pod追加标签信息
kubectl label pod nginx -n dev tier=back #追加架构标签
kubectl get pod -n dev --show-labels
步骤4:更新修改已存在标签
# 修改已存在标签内容必须加上overwrite参数,不然会报错
kubectl label pod nginx -n dev version=2.0 --overwrite
kubectl get pod -n dev --show-labels
步骤5:筛选标签
为了方便实验效果,需要再创建一个pod nginx1,复制pod-nginx.yaml,并修改一下内容,修改后如下:
#pod-nginx1.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx1 #name不能重复,将原来的nginx改成nginx1
namespace: dev
spec:
containers:
- image: nginx:latest
name: pod
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
kubectl create -f pod-nginx1.yaml #新增一个nginx1 pod
kubectl get pods -n dev
# 给nginx1 pod打上版本1.0标签
kubectl label pod nginx1 -n dev version=1.0
kubectl get pods -n dev --show-labels
如上图现在有两个pod,一个pod版本标签是1.0,一个是2.0,现在通过标签选择器去进行标签筛选pod:
# -l是筛选标签参数,后面跟具体的需要筛选的标签名称
kubectl get pods -l "version=2.0" -n dev --show-labels #筛选出2.0版本pod
# 也可以反向筛选,选出版本号不等于2.0标签
kubectl get pods -l "version!=2.0" -n dev --show-labels
步骤6:删除标签
# 在标签名后面加上一个减号,就是删除该标签
kubectl label pod nginx -n dev tier-
kubectl get pods nginx -n dev --show-labels
场景1:在创建pod的时候在yaml文件中添加label参数
将pod-nginx.yaml复制为pod-nginx3.yaml,并修改内容如下:
# pod-nginx2.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx3 #更改名称
namespace: dev
labels: #新增标签配置
version: "3.0"
env: "test"
spec:
containers:
- image: nginx:latest
name: pod
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
kubectl create -f pod-nginx3.yaml
kubectl get pods -n dev --show-labels
场景2:对于已存在的pod,修改yaml配置来修改已存在pod的标签参数
比如已nginx pod为例,修改创建nginx pod的yaml文件pod-nginx.yaml如下:
# pod-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: dev
labels: #修改标签内容
version: "3.0"
env: "test"
spec:
containers:
- image: nginx:latest
name: pod
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
#提交修改后的yaml配置文件来更新pod标签内容,apply是更新pod
kubectl apply -f pod-nginx.yaml
kubectl get pods -n dev --show-labels
在kubernetes中,Pod是最小的控制单元,但是kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成的。Pod控制器用于pod的管理,确保pod资源符合预期的状态,当pod的资源出现故障时,会尝试进行重启或重建pod。
在kubernetes中Pod控制器的种类有很多,本章节只介绍一种:Deployment。
如上图,pod控制器deployment带有pod选择器seletor,可以管理带env=dev标签的pod
2.1、命令格式
kubectl run [deployment名称] [参数]
--image:指定pod的镜像
--port:指定端口
--replicas:指定创建pod数量
--namespace:指定namespace
2.2、创建deployment
# 创建前,避免干扰,先删除之前创建的dev namespace空间
kubectl delete ns dev
# 创建一个新的dev namespace
kubectl create ns dev
# 查看dev命名空间下的deploy和pod信息,正常的新建的应该是什么都没有
kubectl get deployment,pods -n dev
# 第一个nginx是创建名为nginx的deploy控制器,replicas=3是副本数3,即创建3个pod
kubectl run nginx --image=nginx:1.17.1 --port=80 --replicas=3 --namespace=dev
#同时查看dev下面的deploy控制器和pod
kubectl get deployment,pods -n dev
如下图,上面是deploy控制器列表,下面是pod列表:
2.3、查看depoly控制器信息
# 查看控制器详细信息
kubectl describe deploy nginx -n dev
#也可以用下面两个命令查看简要信息
kubectl get deploy -n dev
kubectl get deploy -n dev -o wide
如上可以看到nginx控制器的标签选择器是run=nginx,那么可以推测生成的pods也是有run=nginx这个标签:
kubectl get pods -n dev --show-labels
2.4、删除deploy控制器
# 将控制器删除后,控制器下面所属的pod也会被全部删除
kubectl delete deploy nginx -n dev
kubectl get pods -n dev
创建一个deploy-nginx.yaml,内容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: dev
spec:
replicas: 3
selector:
matchLabels:
run: nginx
template:
metadata:
labels:
run: nginx
spec:
containers:
- image: nginx:latest
name: nginx
ports:
- containerPort: 80
protocol: TCP
deploy-nginx.yaml内容解释如下图:
# 创建
kubectl create -f deploy-nginx.yaml
# 查看deploy控制器和pods
kubectl get deployment,pods -n dev
# 删除
kubectl delete -f deploy-nginx.yaml
通过前面的介绍,已经能够利用Deployment来创建一组Pod来提供具有高可用性的服务。
虽然每个Pod都会分配一个单独的Pod IP,然而却存在如下两问题:
这样对于访问这个服务带来了难度。因此,kubernetes设计了Service来解决这个问题。
Service可以看作是一组同类Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。service也是基于标签选择器来管理对于标签的pod。如下图,外部有访问请求,会先访问Service,Service再根据标签选择器seletor找到对应同类标签的Pod,并可以自动实现负载均衡将请求分发给对应的pod。
步骤1:
先使用上文的deploy-nginx.yaml文件创建deploy控制器和一组pod
kubectl create -f deploy-nginx.yaml
kubectl get deployment,pods -n dev -o wide
步骤2:创建service
#主要意思:暴露service
# expose deploy是指通过deploy控制器来暴露,因为pod是由deploy控制器来管理的
# --name=srv-nginx1是定义service名称,自定义
# --type=ClusterIP是设置type类型为集群ip,type名称非自定义,严格遵循大小写
# --port=80是Service对外端口
# --target-port=80是对应pod的端口,这里是nginx服务,所以默认是80
# -n dev一定要指定namespace,不然默认就跑到default namespace了
kubectl expose deploy nginx --name=svc-nginx1 --type=ClusterIP --port=80 --target-port=80 -n dev
查看service
kubectl get service -n dev # service可以简写成svc
如上图,这里产生了一个CLUSTER-IP,这就是service的IP,在Service的生命周期中,这个地址是不会变动的 ,可以通过这个IP访问当前service对应的POD,注意只能在集群内部节点访问。
步骤1:
# 跟上文创建内部访问的service命令一样,只不过将--type改成NodePort,service名称为避免冲突换成srv-nginx2
kubectl expose deploy nginx --name=svc-nginx2 --type=NodePort --port=80 --target-port=80 -n dev
# 查看创建的service svc-nginx2
kubectl get svc svc-nginx2 -n dev -o wide
如上图可以看到出现了NodePort类型的Service,而且有一对Port(80:31928/TCP),接下来就可以通过集群外的主机访问 节点IP:31928访问服务了(80是pod端口,31928是宿主机端口)。
先获取service名称:
kubectl get svc -n dev
根据名称删除指定service:
kubectl delete svc svc-nginx2 -n dev
创建一个svc-nginx.yaml文件,内容如下:
apiVersion: v1
kind: Service
metadata:
name: svc-nginx
namespace: dev
spec:
clusterIP: 10.109.179.231 #固定svc的内网ip,不指定会随机分配
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: nginx
type: ClusterIP
# 创建
kubectl create -f svc-nginx.yaml
#查询
kubectl get svc -n dev -o wide
#删除
kubectl delete -f svc-nginx.yaml