[TOC]
## 四、资源的基础操作
```
本章节将介绍如何在kubernetes集群中部署一个nginx服务,并且能够对其进行访问。
```
### 1. namespace

```
namespace是kubernetes中一种非常重要的资源,它的主要作用是用来实现多套环境的资源隔离和多租户的资源隔离。
a.多套环境的资源隔离
默认情况下,kubernetes集群中的所有pod都是可以互相访问的,但是实际应用中可能不想让两个pod之间互相访问,那么此时就可以将两个pod划分到不同的namespace下。
kubenetes通过将集群内部的资源分配到不同的namespace中可以形成逻辑上的“组”,以方便对不同组的资源进行隔离使用和管理。
b.多租户的资源隔离
可通过kubenetes的授权机制将不同的namespace交给不同租户进行管理,这样就实现了多租户的资源隔离,此时还能结合kubernetes的资源配额机制限定不同租户占用的资源,
例如,cpu使用量、内存使用量等等,来实现租户可用资源的管理。
```
> kubernetes在集群启动之后会默认创建几个namespace
```
[root@master ~]# kubectl get namespace
NAME STATUS AGE
default Active 7d21h
kube-flannel Active 7d21h
kube-node-lease Active 7d21h
kube-public Active 7d21h
kube-system Active 7d21h
说明:
default 所有未指定namespace的对象都会分配在default命名空间
kube-node-lease 集群节点之间的心跳维护,v1.13开始引入
kube-public 此命名空间下的资源可以被所有人访问(包括未认证用户)
kube-system 所有由kubernetes系统创建的资源都处于这个命名空间
```
> namespace资源的具体操作:查看、创建、删除等。
#### 1.1 查看
```
1.查看所有的命名空间
a.语法:kubectl get namespace #其中的namespace可简写为ns
b.举例:查看所有的命名空间
[root@master ~]# kubectl get ns
2.查看指定的命名空间
a.语法:kubectl get ns ns名称
kubectl get ns/ns名称
b.举例:查看命名空间kube-system。
[root@master ~]# kubectl get ns kube-system
NAME STATUS AGE
kube-system Active 13d
3.查看命名空间时指定输出格式
a.语法:kubectl get ns ns名称 -o 格式参数
kubectl get ns/ns名称 -o 格式参数
b.格式参数:
yaml 以yaml格式展示
json 以json格式展示
wide 以详细信息展示
c.举例:查看命名空间kube-system且以yaml格式展示。
[root@master ~]# kubectl get ns kube-system -o yaml
apiVersion: v1
kind: Namespace
metadata:
4.显示指定命名空间的详细信息
a.语法:kubectl describe ns ns名称
kubectl describe ns/ns名称
b.举例:显示kube-system的详细信息。
[root@master ~]# kubectl describe ns kube-system
Name: kube-system
Labels: <none>
Annotations: <none>
Status: Active #Active 命名空间正在使用中 Terminating 正在删除命名空间
No resource quota.
No LimitRange resource.
# resource quota 针对namespace做的资源限制
# LimitRange 针对namespace中的每个组件做的资源限制
```
#### 1.2 创建
```
1.语法:
kubectl create namespace/ns ns名称
2.范例
#创建命名空间dev
[root@master ~]# kubectl create ns dev
```
#### 1.3 删除
```
1.语法:
kubectl delete namespace/ns ns名称
2.范例
#删除命名空间dev
[root@master ~]# kubectl delete ns dev
```
#### 1.4 配置方式
```
1.首先准备一个yaml文件:ns-dev.yaml
apiVersion: v1
kind: Namespace
metadata:
name: dev
meta /ˈmetə/ n.元
metadata n.元数据
2.然后就可以执行对应的创建和删除命令了
创建namespace:kubectl create -f ns-dev.yaml
删除namespace:kubectl delete -f ns-dev.yaml
```
### 2. pod
```
1.pod是kubenetes集群进行管理的最小单元,程序要运行必须部署在容器中,而容器必须存在于pod中。
pod可以认为是容器的封装,一个pod中可以存在一个或多个容器。
2.kubenetes在集群启动之后,集群中的各个组件也都是以pod的方式运行的,如下:
[root@master ~]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-6955765f44-mzrvr 1/1 Running 3 38d
coredns-6955765f44-p5frx 1/1 Running 3 38d
etcd-master 1/1 Running 3 38d
kube-apiserver-master 1/1 Running 3 38d
kube-controller-manager-master 1/1 Running 3 38d
kube-proxy-4h2bb 1/1 Running 2 38d
kube-proxy-9h28d 1/1 Running 2 38d
kube-proxy-cpzv7 1/1 Running 3 38d
kube-scheduler-master 1/1 Running 3 38d
```
#### 2.1 创建并运行
```
kubecetes没有提供单独运行pod的命令,都是通过pod控制器来实现的。
1.语法:
kubectl run (pod控制器名称) [参数]
参数:
--image 指定pod的镜像
--port 指定端口
--namespace 指定namespace
2.范例
2.1 使用nginx:latest镜像在dev命名空间中创建一个pod
[root@master ~]# kubectl run nginx --image=nginx:latest --port=80 --namespace=dev
2.2 使用nginx:latest镜像在dev命名空间中创建一个具有3个副本的deployment
[root@master ~]# kubectl run nginx --image=nginx:latest --port=80 --replicas=3 --namespace=dev
```
#### 2.2 查看
```
1.查看pod基本信息
[root@master ~]# kubectl get pod -n dev
[root@master ~]# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
volume-emptydir 2/2 Running 0 11m 10.244.2.150 node1 <none> <none>
# 注释:
NAME: pod的名称
READY: 表示pod中已经准备好的容器数和总容器数(如1/2表示共有两个容器但仅有一个容器准备好)。
STATUS: pod的当前状态,如Running、Pending、Failed等。
RESTART: pod中所有容器重启次数的总和。
AGE: pod已经创建了多长时间
IP: pod的ip地址
NODE: 运行pod的节点
NOMINATED NODE: 被提名用于运行 Pod 的节点名称,通常为空。
READINESS GATES:列出了Pod是否达到了就绪状态所需的所有条件。
2.查看pod详细信息
[root@master ~]# kubectl describe pod -n dev
3.查看命名空间dev下的所有资源(包括pod、svc、deployment等)
[root@master ~]# kubectl get all -n dev
```
#### 2.3 访问
```
1.获取pod的ip
[root@master ~]# kubectl get pod -n dev -o wide
2.访问pod
[root@master ~]# curl -I 10.244.1.2:80
```
#### 2.4 删除
```
1.删除指定pod
[root@master ~]# kubectl delete pod nginx-dd6b5d745-sdsmn -n dev
pod "nginx-dd6b5d745-sdsmn" deleted
[root@master ~]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
nginx-dd6b5d745-rp7c9 1/1 Running 0 14s
说明:显示删除pod成功,但是再查询发现又产生一个(如上所示),
这是因为当前pod是由pod控制器创建的,控制器会监控pod的状态,一旦发现pod死亡会立即重建,此时要想删除pod则必须删除pod控制器。
#先查看当前namespace下的pod控制器
[root@master ~]# kubectl get deploy -n dev
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 1/1 1 1 36m
#接下来删除此pod控制器
[root@master ~]# kubectl delete deploy nginx -n dev
#待pod控制器被删除后再查看pod发现pod已经被删除了
[root@master ~]# kubectl get pod -n dev
No resources found in dev namespace
```
#### 2.5 配置操作
```
1.创建一个pod-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: dev
spec:
containers:
- image: nginx:latest
name: pod
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
2.然后就可以执行对应的创建和删除命令了
创建:[root@master ~]# kubectl create -f pod-nginx.yaml
删除:[root@master ~]# kubectl delete -f pod-nginx.yaml
```
### 3. label
```
1.label的功能:
label是kubenetes系统中的一个重要概念。它的作用就是在资源上添加标识,用来对他们进行区分和选择。
2.label的特点:
a.一个label会以key/value键值对的形式附加到各种对象上,如node、pod、service等。
b.一个资源对象可以定义任意数量的label,同一个label也可以被添加到任意数量的资源对象上去。
c.label通常在资源对象定义时确定,当然也可以在对象创建后动态添加或者删除。
3.可以通过label实现资源的多维度分组,以便灵活、方便地进行资源分配、调度、配置、部署等管理工作。
一些常用的label示例如下:
版本标签:"version":"release", "version":"stable"...
环境标签:"environment":"dev","environment":"test","environment":"pro"
架构标签:"tier":"frontend","tier":"backend"
4.标签选择器
标签定义完之后,还要考虑标签的选择,这就要使用到label selector,当前有两种label selector:
a.基于等式的label selector
name = slave 即选择所有包含label中key="name"且value="slave"的对象。
env != production 即选择所有包括label中key="env"且value不等于"production"的对象。
b.基于集合的label selector
name in (master, slave) 即选择所有包含Label中的key="name"且value="master"或"slave"的对象。
name notin (frontend) 即选择所有包含Label中的key="name"且value不等于"frontend"的对象。
说明:标签的选择条件可以使用多个,此时将多个label selector进行组合,使用逗号','进行分割即可,例如:
name=slave,env!=production
name notin (frontend),env!=production
```
#### 3.1 打标签
```
1.语法:
Kubectl label 资源类型 资源名称 -n 命名空间 标签键=键值[,标签键=键值...]
2.范例:
[root@master ~]# kubectl label pod nginx1 -n dev version=1.0
[root@master ~]# kubectl label pod nginx2 -n dev version=2.0,tier=bak
```
#### 3.2 查看标签
```
1.语法:
kubectl get 资源类型 -n 命名空间 --show-labels
注释:--show-labels 在最后一列显示资源的所有标签。
2.范例:
[root@master ~]# kubectl get pod -n dev --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 0 2m47s version=1.0
```
#### 3.3 更新标签
```
1.语法:
Kubectl label 资源类型 资源名称 -n 命名空间 标签键=键值[,标签键=键值...] --overwrite
注释:--overwrite 覆盖现有标签。
2.范例:
[root@master ~]# kubectl label pod nginx -n dev version=2.0 --overwrite
[root@master ~]# kubectl get pod -n dev --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 0 92s version=2.0
```
#### 3.4 筛选标签
```
1.语法:
kubectl get 资源类型 -n 命名空间 [--show-labels] -l 标签键=键值[,标签键=键值...]
注释:-l 筛选标签,支持'='、'=='和'!='。
2.范例:
[root@master ~]# kubectl get pod -n dev --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 0 70m version=2.0
nginx1 1/1 Running 0 5m22s version=1.0
[root@master ~]# kubectl get pod -n dev --show-labels -l version!=2.0
NAME READY STATUS RESTARTS AGE LABELS
nginx1 1/1 Running 0 13m version=1.0
[root@master ~]# kubectl get pod -n dev --show-labels -l run!=nginx2,'version notin (latest,1.24.0)'
NAME READY STATUS RESTARTS AGE LABELS
nginx-dd6b5d745-6mvmt 1/1 Running 0 22m pod-template-hash=dd6b5d745,run=nginx,version=2.0
```
#### 3.5 删除标签
```
1.语法:
kubectl label 资源类型 资源名称 -n 命名空间 标签键-
2.范例:
[root@master ~]# kubectl label pod nginx -n dev version-
```
#### 3.6 配置方式
```
1.首先准备一个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
2.然后就可以执行对应的更新命令了
kubectl apply -f pod-nginx.yaml
```
### 4. delpoyment
> pod控制器介绍
```
1.在kubernetes中,pod是最小控制单元,但是kubernetes很少直接控制pod,一般都是通过pod控制器来完成。
2.Pod控制器是管理pod的中间层,使用Pod控制器之后,只需要告诉Pod控制器,想要多少个什么样的Pod就可以了,
它会创建出满足条件的Pod并确保每一个Pod资源处于用户期望的目标状态,如果Pod资源在运行中出现故障,它会基于指定策略重新编排Pod。
在kubernetes中,有很多类型的pod控制器,每种都有自己的适合的场景,常见的有下面这些:
> ReplicationController:比较原始的pod控制器,已经被废弃,由ReplicaSet替代
> ReplicaSet:保证副本数量一直维持在期望值,并支持pod数量扩缩容,镜像版本升级
> Deployment:通过控制ReplicaSet来控制Pod,并支持滚动升级、回退版本
> Horizontal Pod Autoscaler:可以根据集群负载自动水平调整Pod的数量,实现削峰填谷
> DaemonSet:在集群中的指定Node上运行且仅运行一个副本,一般用于守护进程类的任务
> Job:它创建出来的pod只要完成任务就立即退出,不需要重启或重建,用于执行一次性任务
> Cronjob:它创建的Pod负责周期性任务控制,不需要持续后台运行
> StatefulSet:管理有状态应用
```
> deployment介绍
```
1.kubernetes这种控制器并不直接管理pod,而是通过管理ReplicaSet来间接管理Pod,
即:Deployment管理ReplicaSet,ReplicaSet管理Pod,所以Deployment比ReplicaSet功能更加强大。
2.在Kubernetes中,Deployment是一种用于定义和更新Pod的控制器,Deployment确保了在指定的pod副本数量,并提供了一些扩展功能,如滚动更新和回滚。
Deployment的核心功能是使用滚动更新来更改Pod模板中的镜像或参数,以及提供滚动更新过程中的一些策略保证,如最大不可用Pod数量、更新的速率等。
3.在kubenetes中pod控制器的种类很多,本章只介绍一种:deployment
```

#### 4.1 创建
```
1.语法:
kubectl run deployment名称 [参数]
#参数
--image 指定pod的镜像
--port 指定暴露在cluster ip上的端口
--replicas 副本数,即指定创建pod数量 /ˈreplɪkə/ n.副本
--namespace 指定namespace
2.范例:
2.1 使用nginx:1.24.0镜像在dev命名空间中创建一个pod
[root@master ~]# kubectl run nginx --image=nginx:1.24.0 --port=80 -n dev
2.2 使用nginx:1.24.0镜像在dev命名空间中创建一个具有3个副本的deployment
[root@master ~]# kubectl run nginx --image=nginx:1.24.0 --port=80 --replicas=3 -n dev
【适用于 Kubernetes 1.9 版本及以后的版本】
在命名空间dev中创建名为nginx,副本数为3的deployment
[root@master ~]# kubectl create deployment nginx --image=nginx:1.24.0 --port=80 --replicas=3 -n dev
```
> 【kubectl run 和 kubectl create deployment的区别】
```
kubectl run 和 kubectl create deployment 都可以用来创建部署对象,但它们的行为有一些微妙的区别:
1.kubectl run:
> 在 Kubernetes 1.8 版本及以后的版本中,kubectl run 默认创建的是一个 Deployment 对象,而不是 ReplicationController。
> 在较早的版本中,如果不指定 --generator=deployment/apps.v1 参数,它会创建 ReplicationController。
> 可以通过 --restart 参数来指定 Pod 的重启策略,默认是 Always。
2.kubectl create deployment:
> 这个命令是专门用来创建 Deployment 对象的。
> 创建的是一个 Deployment 对象,而不是 ReplicationController。
> 可以直接指定副本数量(replicas)。
在你提供的命令中,kubectl run nginx --image=nginx:1.24.0 --port=80 --replicas=3 -n dev 使用了 kubectl run,
而 kubectl create deployment nginx --image=nginx:1.24.0 --port=80 --replicas=3 -n dev 使用了 kubectl create deployment,
但它们最终都会创建一个名为 nginx 的 Deployment 对象,并且都会有 3 个副本,使用的镜像也都是 nginx:1.24.0,放置在 dev 命名空间中。
```
#### 4.2 查看
```
1.查看dev中的deployment(deployment可简写为deploy)。
[root@master ~]# kubectl get deployment -n dev
2.查看dev中的deployment和pod。
[root@master ~]# kubectl get deployment,pod -n dev
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 3/3 3 3 3m41s
NAME READY STATUS RESTARTS AGE
pod/nginx-68dd66f787-97s9n 1/1 Running 0 3m41s
pod/nginx-68dd66f787-dsqf2 1/1 Running 0 3m41s
pod/nginx-68dd66f787-f47ld 1/1 Running 0 3m41s
# UP-TO-DATE:成功升级的副本数量
# AVAILABLE:可用副本的数量
3.查看deployment的详细信息
[root@master ~]# kubectl describe deployment nginx -n dev
```
#### 4.3 删除
```
1.语法:
kubectl delete deployment 要删除的deployment名称 -n 命名空间
2.范例:
[root@master ~]# kubectl delete deployment nginx -n dev
```
#### 4.4 配置操作
```
1.创建一个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
2.然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f deploy-nginx.yaml
删除:kubectl delete -f deploy-nginx.yaml
```
### 5. service
```
通过以上内容的学习,我们已经能够利用deployment来创建一组pod用来提供具有高性能的服务。虽然每个pod都会分配一个独立的pod ip,但是却存在以下这个问题:
1.pod ip会随着pod的重建产生变化。
2.pod ip仅仅是集群内可使用的虚拟ip,外部无法访问。
以上两个问题的存在给这个服务的访问带来了困难,因此,k8s设计了service来解决这个问题。
service可以看作是一组同类pod对外的访问接口,借助service应用方便地实现服务发现和负载均衡。
参考文档:https://baijiahao.baidu.com/s?id=1681303264708121640&wfr=spider&for=pc
```

#### 5.1 创建集群内部可访问的service
```
1.语法:
kubectl expose deployment <deployment-name> --name=<service-name> --type=service类型 --port=暴露的端口 --target-port=目标端口 -n 命名空间
说明:
--name 指service的名字,可自定义。
--type 指service类型,有ClusterIP、NodePort、LoadBalancer、ExternalName
ClusterIP:默认类型,自动分配一个仅集群内部可以访问的虚拟ip。
NodePort: 在ClusterIP基础上为service在每台机器上绑定一个端口,这样就可以通过NodePort来访问该服务。
LoadBalancer:
ExternalName:
--port 指service使用的端口(可自定义,不被占用即可,仅集群内部使用,外部访问不能使用该端口。)
--target-port 通过service的端口转发到容器的端口(pod使用的端口)。
2.范例:
[root@master ~]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
nginx-68dd66f787-lp5kd 1/1 Running 0 6m32s
nginx-68dd66f787-mxsw7 1/1 Running 0 6m32s
nginx-68dd66f787-r4khm 1/1 Running 0 6m32s
# 将通过service的81端口转发到容器的80端口(即pod使用的端口,在kubectl run时--port参数指定的端口)。
[root@master ~]# kubectl expose deployment nginx --name=svc-nginx1 --type=ClusterIP --port=81 --target-port=80 -n dev
[root@master ~]# kubectl get svc -n dev -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
svc-nginx1 ClusterIP 10.98.101.238 <none> 81/TCP 9s run=nginx
说明:此时无论pod怎么重建,我们在集群内部都可以通过10.98.101.238:81来访问这三个pod,而外部不能访问。
```
#### 5.2 创建集群外部也可访问的service
```
1.说明:
上面创建的service的type类型为ClusterIP,这个ip地址仅集群内部可访问,如果需要创建集群外部也可以访问的service,需要修改type为NodePort。
2.范例:
[root@master ~]# kubectl expose deployment nginx --name=svc-nginx2 --type=NodePort --port=82 --target-port=80 -n dev
[root@master ~]# kubectl get svc -n dev -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
svc-nginx1 ClusterIP 10.98.101.238 <none> 81/TCP 85s run=nginx
svc-nginx2 NodePort 10.103.83.167 <none> 82:30520/TCP 8s run=nginx
说明:
首先,我们知道'NodePort是在ClusterIP基础上为service在每台机器(即集群中的每一台服务器)上绑定一个端口',
所以,上面svc-nginx2中的10.103.83.167是产生的集群内部的虚拟ip,82:30520/TCP中的82是暴露的集群内部的端口,
而这个82端口被绑定到本机的30520/tcp端口,故,外部可通过 http://master(或node)的ip:30520 来访问。
```
#### 5.3 service的三种端口
```
参考连接https://www.cnblogs.com/-wenli/p/13641534.html
1.port
说明:此处的port是kubectl expose中的--port参数指定的端口,而不是kubectl run中的--port参数指定的端口。
port是暴露在cluster ip上的端口,port提供了集群内部客户端访问service的入口,即clusterip:port。
2.nodePort
NodePort是一种Service类型,NodePort是将外部流量导入到Service的一种方式。K8s会在集群中的每个节点上打开一个高端口(30000-32767范围内),
并将该端口映射到Service的port和targetPort上,这样,外部就可以通过任何节点的ip:NodePort来访问Service。
比如,外部要访问k8s集群中的nginx服务,那么我们可以配置service的type=NodePort(如上),外部就可以通过浏览器http://master(集群ip):30520访问到nginx服务。
而数据库等服务可能不需要被外界访问,只需被内部服务访问即可,那么我们就设置service=ClusterIP。
3.targetPort
targetPort是pod上的端口(即kubectl run中--port参数指定的端口),从port/nodePort上来的数据,经过kube-proxy流入到后端pod的targetPort上,最后进入容器。
4.containerPort
containerPort是在pod控制器中定义的、pod中的容器需要暴露的端口。
5.port、nodePort总结:
总的来说,port和nodePort都是service的端口,前者暴露给集群内客户访问服务,后者暴露给集群外客户访问服务。
从这两个端口到来的数据都需要经过反向代理kube-proxy流入后端pod的targetPod,从而到达pod上的容器内。
```
#### 5.4 删除service
```
1.语法:
kubectl delete service/svc <service-name> -n 命名空间
2.范例:
[root@master ~]# kubectl delete svc svc-nginx1 -n dev
```
#### 5.5 配置方式
```
1.创建一个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
2.然后就可以执行对应的创建和删除命令了:
创建:kubectl create -f svc-nginx.yaml
删除:kubectl delete -f svc-nginx.yaml
```
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




