0%

k8s 资源使用说明

主要用于工作便利

ConfigMap

创建

1
2
3
4
5
## 命令式参数创建ConfigMap
kubectl create configmap configmap_name --from-literal=key-1=value-1 …

## 命令行加载文件创建ConfigMap,键名即为文件的基名,“|”是键名及多行键值的分割符,多行键值要进行固定缩进
kubectl create configmap nginx-confs --from-file=./nginx-conf.d/myserver.conf --from-file=status.cfg=./nginx-conf.d/myserver-status.cfg

通过环境变量引用ConfigMap键值

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
apiVersion: v1
kind: ConfigMap
metadata:
name: demoapp-config
data:
demoapp.port: "8080"
demoapp.host: 0.0.0.0
---
apiVersion: v1
kind: Pod
metadata:
name: configmaps-env-demo
spec:
containers:
- image: xxx/xxx
name: demoapp
env:
- name: PORT
valueFrom:
configMapKeyRef:
name: demoapp-config
key: demoapp.port
optional: false
- name: HOST
valueFrom:
configMapKeyRef:
name: demoapp-config
key: demoapp.host
optional: true

ConfigMap存储卷

基于configMap卷插件关联至Pod资源上的ConfigMap对象可由内部的容器挂载为一个目录,该ConfigMap对象的每个键名将转为容器挂载点路径下的一个文件名,键值则映射为相应文件的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Pod
metadata:
name: configmaps-volume-demo
spec:
containers:
- image: nginx:alpine
name: nginx-server
volumeMounts:
- name: ngxconfs
mountPath: /etc/nginx/conf.d/
readOnly: true
volumes:
- name: ngxconfs
configMap:
name: nginx-config-files
optional: false

ResourceQuota

ResourceQuota资源能够定义名称空间级别的资源配额,从而在名称空间上限制聚合资源消耗的边界,它支持以资源类型为类型来限制用户可在本地名称空间中创建的相关资源类型的对象数量,以及这些对象可消耗的计算资源总量等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: ResourceQuota
metadata:
name: resourcequota-demo
spec:
hard:
pods: "5"
count/services: "5"
count/configmaps: "5"
count/secrets: "5"
count/cronjobs.batch: "2"
requests.cpu: "2"
requests.memory: "4Gi"
limits.cpu: "4"
limits.memory: "8Gi"
count/deployments.apps: "2"
count/statefulsets.apps: "2"
persistentvolumeclaims: "6"
requests.storage: "20Gi"
1
kubectl describe resourcequotas/resourcequota-demo

Secret

根据其存储格式及用途的不同,Secret对象会划分为如下三种大的类别。

  • generic:基于本地文件、目录或字面量值创建的Secret,一般用来存储密码、密钥、信息、证书等数据;
  • docker-registry:专用于认证到Docker Registry的Secret,以使用私有容器镜像;
  • tls:基于指定的公钥/私钥对创建TLS Secret,专用于TLS通信中;指定公钥和私钥必须事先存在,公钥证书必须采用PEM编码,且应该与指定的私钥相匹配;
1
2
3
4
5
6
7
8
9
## generic
kubectl create secret generic mysql-root-authn --from-literal=username=root --from-literal=password=xxxxxx

## tls
openssl rand -writerand $HOME/.rnd
kubectl create secret tls nginx-ssl-secret --key=./nginx.key --cert=./nginx.crt

## docker-registry
kubectl create secret docker-registry local-registry --docker-username=Ops --docker-password=Opspass --docker-email=123@qq.com

Secret存储卷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1
kind: Pod
metadata:
name: secrets-volume-demo
spec:
containers:
- image: nginx:alpine
name: ngxserver
volumeMounts:
- name: nginxcerts
mountPath: /etc/nginx/certs/
readOnly: true
- name: nginxconfs
mountPath: /etc/nginx/conf.d/
readOnly: true
volumes:
- name: nginxcerts
secret:
secretName: nginx-ssl-secret
- name: nginxconfs
configMap:
name: nginx-sslvhosts-confs
optional: false

存活探针\就绪探针

容器exec存活探针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec-demo
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
livenessProbe:
exec:
command: ['/bin/sh', '-c', '[ "$(curl -s 127.0.0.1/livez)" == "OK" ]']
initialDelaySeconds: 5
periodSeconds: 5
1
2
## 手动将/livez的响应内容修改为OK之外的其他值,例如FAIL,以便于测试健康探针失败的后果
kubectl exec liveness-exec-demo -- curl -s -X POST -d 'livez=FAIL' 127.0.0.1/livez

容器httpGet存活探针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget-demo
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: '/livez' # 请求的主机地址,默认为pod IP;也可以在httpHeaders使用“Host: ”来定义
port: 80 # 请求的端口,必选字段
scheme: HTTP # 建立连接使用的协议,仅可为HTTP或HTTPS,默认为HTTP
initialDelaySeconds: 5
1
2
## 为了测试存活状态检测的效果,同样可以手动将/livez的响应内容修改为OK之外的其他值,例如FAIL。
kubectl exec liveness-httpget-demo -- curl -s -X POST -d 'livez=FAIL' 127.0.0.1/livez

容器tcpSocket存活探针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: v1
kind: Pod
metadata:
name: liveness-tcpsocket-demo
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
securityContext:
capabilities:
add:
- NET_ADMIN
livenessProbe:
tcpSocket:
port: http
periodSeconds: 5
initialDelaySeconds: 20
1
2
## 为了测试效果,可使用下面的命令在Pod的Network名称空间中设置iptables规则以阻止对80端口的请求
kubectl exec liveness-tcpsocket-demo -- iptables -A INPUT -p tcp --dport 80 -j REJECT

容器的httpGet就绪探针

就绪状态探测是用来判断容器应用就绪与否周期性(默认周期为10秒钟)操作,它用于探测容器是否已经初始化完成并可服务于客户端请求。与存活探针触发的操作不同,探测失败时,就绪探针不会杀死或重启容器来确保其健康状态,而仅仅是通知其尚未就绪,并触发依赖于其就绪状态的其他操作(例如从Service对象中移除此Pod对象)以确保不会有客户端请求接入此pod对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: Pod
metadata:
name: readiness-httpget-demo
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
path: '/readyz'
port: 80
scheme: HTTP
initialDelaySeconds: 15
timeoutSeconds: 2
periodSeconds: 5
failureThreshold: 3
restartPolicy: Always
1
2
## 为了测试就绪状态探测效果,下面修改/readyz响应以非‘OK’内容。
kubectl exec readiness-httpget-demo -- curl -s -X POST -d 'readyz=FAIL' 127.0.0.1/readyz

preStart和postStop钩子

容器生命周期钩子使它能够感知其自身生命周期管理中的事件,并在相应的时刻到来时运行由用户指定的处理程序代码。kubernetes为容器提供了PostStart和PreStop两种生命周期挂钩。postStart和preStop处理器定义在容器的lifecycle字段中,其内部一次仅支持嵌套使用一种处理器类型。

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
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
securityContext:
capabilities:
add:
- NET_ADMIN
livenessProbe:
httpGet:
path: '/livez'
port: 80
scheme: HTTP
initialDelaySeconds: 5
lifecycle:
postStart:
exec:
command: ['/bin/sh','-c','iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-ports 80']
preStop:
exec:
command: ['/bin/sh','-c','while killall python3; do sleep 1; done']
restartPolicy: Always

Deployment

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
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-demo
spec:
strategy: # 自定义更新策略;
rollingUpdate:
maxSurge: 1 # 允许超出期望值1个;
maxUnavailable: 0 # 不允许低于期望值;
type: RollingUpdate
replicas: 4
selector:
matchLabels:
app: demoapp
release: stable
template:
metadata:
labels:
app: demoapp
release: stable
spec:
containers:
- name: demoapp
image: ikubernetes/demoapp:v1.1
ports:
- containerPort: 80
name: http
livenessProbe:
httpGet:
path: '/livez'
port: 80
initialDelaySeconds: 5
readinessProbe:
httpGet:
path: '/readyz'
port: 80
initialDelaySeconds: 15
---
apiVersion: v1
kind: Service
metadata:
name: demoapp
spec:
type: ClusterIP
selector: # 将发往该服务的请求流量调度至由replicaset-demo管控的Pod副本之上;
app: demoapp
release: stable
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
1
2
3
4
5
## 创建一个临时的客户端Pod以发起持续性的请求测试,以验证单批次更新过程中是否会发生服务中断
kubectl run pod-$RANDOM --image=ikubernetes/admin-box:v1.2 -it --restart=Never --rm --command -- /bin/bash

## 临时Pod的交互式接口中运行如下循环进行请求测试
while true; do curl --connect-timeout 1 demoapp; sleep .5; done

Job

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: batch/v1
kind: Job
metadata:
name: job-demo
spec:
template:
spec:
containers:
- name: myjob
image: ikubernetes/admin-toolbox:v1.0
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "sleep 60"]
restartPolicy: Never
completions: 3
ttlSecondsAfterFinished: 3600 # Job的留存时长,超过该时长将被自动删除;
backoffLimit: 3 # 将作业标记为失败状态之前的重试次数,默认值为6;
activeDeadlineSeconds: 300 # Job的最大活动时长,超过该时长仍未成功结束时将被标记为失败;
1
2
## 动态修改Job资源的作业并行度,改变parallelism属性的值提升作业并行度即可实现Job资源扩容之目的
kubectl patch jobs/job-para-demo -p '{"spec":{"parallelism":5}}'

Cronjob

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
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: cronjob-demo
spec:
schedule: "*/2 * * * *"
jobTemplate:
metadata:
labels:
app: mycronjob-jobs
spec:
parallelism: 1
completions: 1
ttlSecondsAfterFinished: 3600
backoffLimit: 3
activeDeadlineSeconds: 60
template:
metadata:
labels:
app: cronjob-demo-pod
spec:
containers:
- name: myjob
image: "ikubernetes/admin-toolbox:v1.0"
command:
- /bin/sh
- -c
- date; echo Hello from CronJob, sleep a while…; sleep 10;
restartPolicy: OnFailure
startingDeadlineSeconds: 300

由CronJob资源通过模板创建的Job对象的名称以CronJob自身的名称为前缀,以Job创建时的时间戳为后缀,而各Job对象相关的Pod对象的名称则随机生成。已完成的CronJob资源相关Pod的状态为Completed,而失败的作业状态则存在RunContainerError、CrashLoopBackOff 或其他表示失败的状态。

1
2
3
4
## 下面的命令将会得到几个已经完成的作业的Pod

$ kubectl get pods | awk '/^cronjob-demo/{print $0}'
cronjob-demo-1624409400-nm5wx 0/1 Completed 0 38s

自Kubernetes v1.21版开始,由CronJob资源通过模板创建的Job对象的名称以CronJob自身的名称为前缀,以Job创建时的时间戳和5个随机字符为后缀。

DNS

Kubernetes支持如下DNS解析策略,它们定义在spec.dnsPolicy字段上。

  • Default:从运行在的节点继承DNS名称解析相关的配置;
  • ClusterFirst:于集群DNS服务上解析集群域内的名称,其他域名的解析则交由从节点继承而来的上游名称服务器;
  • ClusterFirstWithHostNet:专用于在设置了hostNetwork的Pod对象上使用的ClusterFirst策略,任何配置了hostNetwork的Pod对象都应该显式使用该策略;
  • None:用于忽略Kubernetes集群的默认设定,而仅使用由dnsConfig自定义的配置;

Pod资源的自定义DNS配置要通过嵌套于spec.dnsConfig字段中

  • nameservers <[]string>:DNS名称服务器列表,它附加于由dnsPolicy生成的DNS名称服务器之后;
  • searches <[]string>:DNS名称解析时的搜索域,它附加由于dnsPolicy生成的搜索域之后;
  • options <[]Object>:DNS解析选项列表,它将会同dnsPolicy生成的解析选项合并成最终生效的定义;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: Pod
metadata:
name: pod-with-customed-dnspolicy
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
dnsPolicy: None
dnsConfig:
nameservers:
- 172.21.0.10
searches:
- svc.cluster.local
- cluster.local
options:
- name: ndots
value: "5"

Service

External Service

Kubernetes将那些ClusterIP字段值为“None”的Service资源称为Headless Service,该类Service的请求流量无须kube-proxy处理,也不会有负载均衡和路由相关的iptables或ipvs规则。至于ClusterDNS如何自动配置Headless Service,则取决于Service标签选择器的定义。

  • 配置有标签选择器:由端点控制器自动创建与Service同名的Endpoint资源,而ClusterDNS则将Service名称的A记录直接解析为后端各端点的IP而非ClusterIP;
  • 无标签选择器: ClusterDNS的配置分为两种情形:对ExternalName类型的服务(配置了spec.externalName字段)创建CNAME记录,而对于存在与该Service同名的Endpoint对象上的每个端点创建一个A记录。

通常,我们把无标签选择器的第一种情形(使用CNAME记录)的Headless Service当作一种独立的Service类型使用,即ExternalName Service,而将那些把Service名称使用A记录解析为端点IP地的情况则统一称为Headless Service。

ExternalName Service是一种特殊类型的Service资源,它不需要使用标签选择器关联任何的Pod对象,也无须定义任何端口或Endpoints,但必须要使用spec.externalName属性定义一个CNAME记录用于返回真正提供服务的服务名称的别名。

1
2
3
4
5
6
7
8
9
10
11
12
kind: Service
apiVersion: v1
metadata:
name: externalname
spec:
type: ExternalName
externalName: www.xxx.com
ports:
- protocol: TCP
port: 80
targetPort: 80
selector: {}

Headless Service

除了为每个Service资源对象在创建时自动指派一个遵循..svc.格式的DNS名称,ClusterDNS还会为Headless Service中的每个端点指派一个遵循...svc.格式的DNS名称。定义Service资源时,只需要将其ClusterIP字段的值显式设置为None即可将其定义为Headless 类型

1
2
3
4
5
6
7
8
9
10
11
12
kind: Service
apiVersion: v1
metadata:
name: demoapp-headless-svc
spec:
clusterIP: None
selector:
app: demoapp
ports:
- port: 80
targetPort: 80
name: http
1
2
3
4
5
6
7
8
## 开启一个pod
kubectl run pod-$RANDOM --image="ikubernetes/admin-box:v1.2" --restart=Never --rm -it --command -- /bin/bash

## Headless Service的名称会解析为其后端各端点的IP地址。
nslookup -query=A demoapp-headless-svc

## 而各端点的IP地址,将反解为端点自己的名称标识,每个端点将拥有独立的标识,格式为“<hostname>.<service>.<namespace>.svc.cluster.local”。
for ip in $(host -t A demoapp-headless-svc | awk '{print $4}'); do host -t PTR $ip; done

Exit Code

1
2
3
Last State:     Terminated
Reason: Error
Exit Code: 137

退出码为137的错误信息,它表示进程是被外部信号所终止。137事实上由两部分数字之和生成:128+signum,其中signum是导致进程终止的信号的数字标识,9表示SIGKILL,这意味着进程是被强行终止。