Kubernetes学习笔记(5):Namespace, Resources和Label

Namespace

查看某一个Namespace下的pod

默认情况下,所有的pod都是运行在default这个namespace下的。

1
kubectl get pods -n default

创建一个Namespace

namespace-dev.yaml

1
2
3
4
apiVersion: v1
kind: Namespace
metadata:
name: dev

在Namespace下创建资源

web-dev.yaml

1
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
42
43
44
45
46
47
48
49
50
51
52
53
#deploy
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-demo
namespace: dev
spec:
selector:
matchLabels:
app: web-demo
replicas: 1
template:
metadata:
labels:
app: web-demo
spec:
containers:
- name: web-demo
image: hub.mooc.com/kubernetes/web:v1
ports:
- containerPort: 8080
---
#service
apiVersion: v1
kind: Service
metadata:
name: web-demo
namespace: dev
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: web-demo
type: ClusterIP

---
#ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web-demo
namespace: dev
spec:
rules:
- host: web-dev.mooc.com
http:
paths:
- path: /
backend:
serviceName: web-demo
servicePort: 80

1
kubectl get all -n dev

Namespace的隔离性

同一个Namespace下的资源访问

随便找一个pod,进入到其容器中。

比如要测试同一个namespace下的另一个pod上的服务是否可以解析,可以执行ping命令。

用curl, wget也可以验证。

不同Namespace下的资源访问

进入到dev这个namespace下(必须制定-n参数,否则访问的还是default namespace)

通过DNS无法访问

通过ping访问服务,可以看到无法访问,说明通过DNS层是隔离的。

通过服务IP可以访问

尝试通过服务IP访问另一个namespace下的服务,事实上是可以访问到的。

通过pod + port可以访问

可以看到,通过pod + 端口的方式也是可以访问的。

由此可知,k8s的隔离是DNS解析的隔离,通过服务IP或pod + 端口的方式仍然可以互访。

对上下文限定Namespace

可以通过设置上下文,实现对namespace的限定。

创建kubeconfig

比如:创建一个名叫ctx-dev的上下文,namespace限定为dev

1
2
3
4
5
kubectl config set-context ctx-dev \
--cluster=kubernetes \
--user=admin \
--namespace=dev \
--kubconfig=/root/.kube/config

设置默认上下文

1
kubectl config use-context ctx-dev --kubeconfig=/root/.kube/config

此时运行kubectl get all, 也只能看到dev namespace下的所有资源。

Resources

Resources 主要包括:CPU, 内存, GPU, 持久化存储等。

查看k8s节点资源

1
2
kubectl get nodes
kubectl describe node <节点名>

对k8s服务进行资源限制

  • memory: 100Mi //限制100MB内存
  • cpu: 100m //限制只能使用0.1核CPU

这里有两个地方都有CPU和内存的设置。requests设置的是必须的最小要求,如果超出硬件最大配置,则容器启动时会一直卡在Pending状态。
而limits限制的是最大的内存,即使设置成超出硬件配置,启动时还是可以起来。

可以通过以下命令查看pod详细失败原因。

1
kubectl describe pod <pod名称>

部署到k8s

1
kubectl apply -f web-dev.yaml

每次部署后,如果查看节点的状态,可以看到k8s会新启动一个服务,然后把旧服务停掉,因为k8s的资源隔离本质上是利用的docker的资源隔离机制。

1
kubectl get pods -n dev

可以切换到容器运行的那台节点上,看看对应的docker容器的情况。

1
docker ps | grep web-demo

查看该容器详细信息

1
docker inspect <容器id>

参数解读:

  • CpuShares: 之前在yaml文件里配置的值是100m,docker会将该值转化为0.1核,之后再乘以1024,就得到这里的102了。这个值在docker里代表相对权重,但发生资源不足时,docker会尝试根据这个权重分配资源。
  • Memory: 这个值就是我们在yaml文件中指定的内存。
  • CpuQuota: yaml文件里设置的最大CPU核数。
  • CpuPeriod: docker默认值,默认值是100000ns。

修改yaml文件,测试k8s调度策略

requests.memorylimits.memory都设置成100Mi。

如果docker实例里使用的内存超过了限定内存最大值,则k8s会自动将“有问题的进程”杀掉,但不会终止docker容器。
如果是CPU超过限定,则会限定在最大值,因为CPU是可压缩资源,而内存不是。

如果将实例数(replicas)改成3, 每个内存改成10GB(服务器硬件一共24GB内存)。

部署服务后可以看到,k8s只允许两个实例启动,第三个一直处于Pending状态。

实验说明,requests要求的配置是要“预留”的,即使实际上还没用到。

测试结论(最佳实践)

设置yaml配置时,

  • 如果requests == limits:此时是最可靠的,推荐使用;
  • 如果不设置:最不可靠,不推荐;
  • 如果requests > limits:超过时,k8s会根据优先级来分配资源;

使用LimitRange限制资源请求

limits-test.yamlpodcontainer 分别限定了资源。

1
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
apiVersion: v1
kind: LimitRange
metadata:
name: test-limits
spec:
limits:
- max:
cpu: 4000m
memory: 2Gi
min:
cpu: 100m
memory: 100Mi
maxLimitRequestRatio:
cpu: 3
memory: 2
type: Pod
- default:
cpu: 300m
memory: 200Mi
defaultRequest:
cpu: 200m
memory: 100Mi
max:
cpu: 2000m
memory: 1Gi
min:
cpu: 100m
memory: 100Mi
maxLimitRequestRatio:
cpu: 5
memory: 4
type: Container

新建一个命名空间,将limits-test.yaml部署到k8s新的namespace下,观察其资源占用情况。

1
2
3
4
5
6
7
8
# 新建一个test命名空间
kubectl create ns test

# 将将`limits-test.yaml`部署到test 命名空间下
kubectl create -f limits-test.yaml -n test

# 查看test命名空间资源占用
kubectl describe limits -n test

在test命名空间下部署一个新的deployment (web-test.yaml),不限制资源。

web-test.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#deploy
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-demo
namespace: test
spec:
selector:
matchLabels:
app: web-demo
replicas: 1
template:
metadata:
labels:
app: web-demo
spec:
containers:
- name: web-demo
image: hub.mooc.com/kubernetes/web:v1
ports:
- containerPort: 8080

可以通过以下命令查看deploy的详细信息;

1
kubectl get deploy -n test -o yaml

多个团队间的资源配额限制

compute-resource.yaml: 对CPU和内存的限制。

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: ResourceQuota
metadata:
name: resource-quota
spec:
hard:
pods: 4
requests.cpu: 2000m
requests.memory: 4Gi
limits.cpu: 4000m
limits.memory: 8Gi

object-count.yaml: 更多资源限制。

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-counts
spec:
hard:
configmaps: 10
persistentvolumeclaims: 4
replicationcontrollers: 20
secrets: 10
services: 10
1
2
3
4
5
# 对test命名空间限制资源配额
kubectl apply -f object-count.yaml -n test

# 检查资源配额
kubectl describe quota object-counts -n test

Pod驱逐策略 - Evition

soft策略

--eviction-soft=memory.available<1.5Gi --eviction-soft-grace-period=memory.available=1m30s

soft策略配合使用,效果:当内存持续1分30秒小于1.5G时,执行驱逐。

hard策略

--eviction-hard=memory.available<100Mi,nodefs.avaiblable<1Gi,nodefs.inodesFree<5%

hard策略:当满足任意一个条件时,立刻执行;

磁盘紧缺

  • 删掉死掉的pod、容器;
  • 删除没用的镜像;
  • 按优先级、资源占用情况驱逐pod;

内存紧缺

  • 驱逐不可靠的pod;
  • 驱逐基本可靠的pod(实际使用内存超过正常的);
  • 驱逐可靠的pod;

Label

key-value值对,可以“贴”到任何资源上。

web-dev.yaml: 在metadata里定义了label,之后就可以用selector/matchLabels选择标签了。

1
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
42
43
44
45
46
47
48
49
50
51
52
53
#deploy
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-demo
namespace: dev
spec:
selector:
matchLabels:
app: web-demo
replicas: 1
template:
metadata:
labels:
app: web-demo
spec:
containers:
- name: web-demo
image: hub.mooc.com/kubernetes/web:v1
ports:
- containerPort: 8080
---
#service
apiVersion: v1
kind: Service
metadata:
name: web-demo
namespace: dev
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: web-demo
type: ClusterIP

---
#ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web-demo
namespace: dev
spec:
rules:
- host: web-dev.mooc.com
http:
paths:
- path: /
backend:
serviceName: web-demo
servicePort: 80

不同的deployment的同名label是不冲突的,因为分属不同的实例。

根据label过滤资源

1
2
3
kubectl get pods -l app=web-demo,group=dev -n dev

kubectl get pods -l 'group not in (dev, test)'

在node上指定label

比如,实现在node上打个标签

1
kubectl label node <节点名> disktype=ssd

在yaml文件里指定node label,disktype:ssd

王方钢 / Kenny Wang wechat
0%