K8s里的API对象
在K8s里,YAML用来声明API对象的,那么API对象都有哪些?我们之前接触过的pod、deployment、service、node都是,当然还有好多,可以这样查看:
kubectl api-resources
资源对象:pod
# 获取pod列表
kubectl get pods
# 运行一个pod
kubectl run pod-demo --image=busybox
# 查看pod详情
kubectl describe pod pod-demo
# 从已知Pod导出YAML文件
kubectl get pod pod-demo -o yaml -o yaml > pod-demo.yaml
pod yaml示例
四个核心部分:apiVersion、Kind、metadata、spec
其他部分可以不用管,也可以删掉
vim testpod.yaml
#手动创建一个pod,直接复制下面内容
apiVersion: v1
kind: Pod
metadata:
name: ngx-pod
namespace: linyi
labels: ## labels字段非常关键,它可以添加任意数量的Key-Value,目的是为了让pod的信息更加详细
env: dev
spec: ##用来定义该pod更多的资源信息,比如contain, volume, storage
containers: ##定义容器属性
- image: nginx:1.23.2
imagePullPolicy: IfNotPresent ##镜像拉取策略,三种:Always/Never/IfNotPresent,一般默认是IfNotPresent,也就是说只有本地不存在才会远程拉取镜像,可以减少网络消耗。
name: ngx
env: ##定义变量,类似于Dockerfile里面的ENV指令
- name: os
value: "Rocky Linux"
ports:
- containerPort: 80
# 上述配置文件中的namespace没有的话,需要创建,不然会报错
kubectl create namespace linyi
# 使用yaml文件创建pod
kubectl apply -f testpod.yaml
# 查看pod(po为简写)
[root@linyi k8s]# kubectl get po -n linyi
NAME READY STATUS RESTARTS AGE
ngx-pod 1/1 Running 0 102s
# 查看pod详情。(这里有个问题,如果在虚拟机做测试,虚拟机长期挂起会导致这个pod启动有问题,重启k8s解决或重启k8s后删除这个pod重新创建)
kubectl describe po ngx-pod -n linyi
# 删除pod
kubectl delete pod ngx-pod
# 删除namespace
kubectl delete namespace linyi
资源对象:Job
可以理解成一次性运行后就退出的Pod。
先来生成一个YAML文件:
kubectl create job job-demo --image=busybox --dry-run=client -o yaml > job-demo.yaml
# 编辑此配置
vim job-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: job-demo
spec:
template: ##模板,基于此模板来创建pod,它用来定义pod的属性,比如container
spec:
restartPolicy: OnFailure ##定义Pod运行失败时的策略,可以是OnFailure和Never,其中OnFailure表示失败的话需要重启容器,Never表示失败的话不重启容器,而是重新生成一个新的Pod
containers:
- image: busybox
name: job-demo
command: ["/bin/echo"]
args: ["hellow", "world"]
# 创建job
kubectl apply -f job-demo.yaml
# 查看job
kubectl get job,pod
# 查看job详情
kubectl describe job job-demo
# 删除job
kubectl delete job job-demo
可以看到该容器运行完成后状态就变成了Completed。
对于Job,还有几个特殊字段:
activeDeadlineSeconds,设置 Pod 运行的超时时间。
backoffLimit,设置 Pod 的失败重试次数。
completions,Job 完成需要运行多少个 Pod,默认是 1 个。
parallelism,它与 completions 相关,表示允许并发运行的 Pod 数量,避免过多占用资源。
vi myjob.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: sleep-job
spec:
activeDeadlineSeconds: 15 #15s就超时
backoffLimit: 2 #失败重试2次就放弃
completions: 4 #要运行4个pod,才算完成
parallelism: 2 #允许并发运行2个pod
template:
spec:
restartPolicy: OnFailure
containers:
- image: busybox
name: echo-job
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- sleep $(($RANDOM % 10 + 1)) && echo done ##$(($RANDOM % 10 + 1))表示取1-10任意一个数字
# 创建job,并查看job情况
kubectl apply -f myjob.yaml ; kubectl get pod -w
资源对象:CronJob
CronJob简称(cj)是一种周期运行的Pod,比如有些任务需要每天执行一次,就可以使用CronJob。
先来生成一个YAML文件:
kubectl create cj cj-demo --image=busybox --schedule="" --dry-run=client -o yaml > cj-demo.yaml
# 编辑此配置
vim cj-demo.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: cj-demo
spec:
schedule: '*/1 * * * *'
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- image: busybox
name: cj-demo
imagePullPolicy: IfNotPresent
command: ["/bin/echo"]
args: ["hello", "world"]
# 运行并查看
kubectl apply -f cj-demo.yaml
kubectl get cj
kubectl get pod
资源对象:ConfigMap
ConfigMap(简称cm)用来存储配置信息,比如服务端口、运行参数、文件路径等等。
示例:
# 编辑配置
vim mycm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mycm
data:
DATABASE: 'db'
USER: 'wp'
PASSWORD: '123123'
ROOT_PASSWORD: '123123'
# 创建cm
kubectl apply -f mycm.yaml
# 查看cm
kubectl get cm
# 查看cm详情
kubectl describe cm mycm
# 删除cm
kubectl delete cm mycm
在其它pod里引用ConfigMap:
# 编辑配置
vim testpod.yaml
apiVersion: v1
kind: Pod
metadata:
name: testpod
labels:
app: testpod
spec:
containers:
- image: mariadb:10
name: maria
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
envFrom: ##将cm里的字段全部导入该pod
- prefix: 'MARIADB_' ##将导入的字段名前面自动加上前缀,例如MARIADB_DATABASE, MARIADB_USER
configMapRef: ##定义哪个cm
name: mycm
验证:
kubectl exec -it testpod -- bash
## 进入pod,查看变量$MARIADB_DATABASE
资源对象:Secret
Secret和cm的结构和用法很类似,不过在 K8s里Secret 对象又细分出很多类,比如:
访问私有镜像仓库的认证信息
身份识别的凭证信息
HTTPS 通信的证书和私钥
一般的机密信息(格式由用户自行解释)
前几种我们现在暂时用不到,所以就只使用最后一种。
示例:
# 编辑配置
vim mysecret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
data:
user: YW1pbmc= ## echo -n "linyi"|base64
passwd: bGludXgxMjM= ## echo -n "test123"|base64
查看
kubectl apply -f mysecret.yaml
kubectl get secret
kubectl describe secret mysecret
在其它pod里引用Secret
# 编辑配置
vim testpod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: testpod2
spec:
containers:
- image: busybox
name: busy
imagePullPolicy: IfNotPresent
command: ["/bin/sleep", "300"]
env:
- name: USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: user
- name: PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: passwd
查看
kubectl exec -it testpod2 -- sh
## 进去后可以 echo $PASSWORD查看变量值
资源对象:Deployment
示例
vim ng-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: myng
name: ng-deploy
spec:
replicas: 2 ##副本数
selector:
matchLabels:
app: myng
template:
metadata:
labels:
app: myng
spec:
containers:
- name: myng
image: nginx:1.23.2
ports:
- name: myng-port
containerPort: 80
matchLabels和labels之间的关系:
# 使用YAML创建deploy
kubectl apply -f ng-deploy.yaml
# 查看deploy
kubectl get deploy
# 查看deploy详情
kubectl describe deploy ng-deploy
# 查看pod
kubectl get pod
# 删除deploy
kubectl delete deploy ng-deploy
资源对象:Service
Service(简称svc)是K8s集群中的一种资源对象,它定义了Pod的逻辑集合和访问该集合的策略。
示例:
# 编辑配置
vim ng-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: ngx-svc
spec:
selector:
app: myng
ports:
- protocol: TCP
port: 80
targetPort: 80
# 使用YAML创建service
kubectl apply -f ng-svc.yaml
# 查看service
kubectl get svc
# 查看service详情
kubectl describe svc ngx-svc
# 删除service
kubectl delete svc ngx-svc
资源对象:Daemonset
有些场景需要在每一个node上运行Pod(比如,网络插件calico、监控、日志收集),Deployment无法做到,而Daemonset(简称ds)可以。Deamonset的目标是,在集群的每一个节点上运行且只运行一个Pod。
Daemonset不支持使用kubectl create获取YAML模板,所以只能照葫芦画瓢了,参考Deployment的YAML编写,其实Daemonset和Deployment的差异很小,除了Kind不一样,还需要去掉replica配置。
示例:
# 编辑配置
vim ds-demo.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
app: ds-demo
name: ds-demo
spec:
selector:
matchLabels:
app: ds-demo
template:
metadata:
labels:
app: ds-demo
spec:
containers:
- name: ds-demo
image: nginx:1.23.2
ports:
- name: mysql-port
containerPort: 80
# 使用YAML创建ds
kubectl apply -f ds-demo.yaml
# 查看ds
kubectl get ds
# 查看ds详情
kubectl describe ds ds-demo
# 查看pod
kubectl get pod
# 删除ds
kubectl delete ds ds-demo
但只在两个node节点上启动了pod,没有在master上启动,这是因为默认master有限制。
kubectl describe node k8s01 |grep -i 'taint'
Taints: node-role.kubernetes.io/control-plane:NoSchedule
说明:
Taint叫做污点,如果某一个节点上有污点,则不会被调度运行pod。
但是这个还得取决于Pod自己的一个属性:toleration(容忍),即这个Pod是否能够容忍目标节点是否有污点。
为了解决此问题,我们可以在Pod上增加toleration属性,
下面改一下YAML配置:# 编辑配置 vim ds-demo.yaml apiVersion: apps/v1 kind: DaemonSet metadata: labels: app: ds-demo name: ds-demo spec: selector: matchLabels: app: ds-demo template: metadata: labels: app: ds-demo spec: # 新增容忍污点 tolerations: - key: node-role.kubernetes.io/control-plane effect: NoSchedule containers: - name: ds-demo image: nginx:1.23.2 ports: - name: mysql-port containerPort: 80 # 再次应用此YAML kubectl apply -f ds-demo.yaml
资源对象:Ingress/IngressClass
有了Service之后,我们可以访问这个Service的IP(clusterIP)来请求对应的Pod,但是这只能是在集群内部访问,要想实现外部访问,还需要额外的组件。
要想让外部用户访问此资源,可以使用NodePort,即在node节点上暴漏一个端口出来,但是这个非常不灵活。为了解决此问题,K8s引入了一个新的API资源对象Ingress,它是一个七层的负载均衡器,类似于Nginx。
三个概念:Ingress、Ingress Controller、IngressClass
Ingress用来定义具体的路由规则,要实现什么样的访问效果;
Ingress Controller是实现Ingress定义具体规则的工具或者叫做服务,在K8s里就是具体的Pod;
IngressClass是介于Ingress和Ingress Controller之间的一个协调者,它存在的意义在于,当有多个Ingress Controller时,可以让Ingress和Ingress Controller彼此独立,不直接关联,而是通过IngressClass实现关联。

Ingress YAML示例:
# 编辑配置
vim mying.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mying ##ingress名字
spec:
ingressClassName: myingc ##定义关联的IngressClass
rules: ##定义具体的规则
- host: linyi.com ##访问的目标域名
http:
paths:
- path: /
pathType: Exact
backend: ##定义后端的service对象
service:
name: ngx-svc
port:
number: 80
# 查看ingress
kubectl get ing
kubectl describe ing mying
IngressClassYAML示例:
# 编辑配置
vim myingc.yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: myingc
spec:
controller: nginx.org/ingress-controller ##定义要使用哪个controller
# 查看ingressclass
kubectl get ingressclass
kubectl describe ingressclass myingc
安装ingress-controller
使用Nginx官方提供的ingress-controller
首先做一下前置工作
curl -O 'https://gitee.com/aminglinux/linux_study/raw/master/k8s/ingress.tar.gz'
tar zxf ingress.tar.gz
cd ingress
./setup.sh
##说明,执行这个脚本会部署几个ingress相关资源,包括namespace、configmap、secrect等
# 编辑配置
vim ingress-controller.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ngx-ing
namespace: nginx-ingress
spec:
replicas: 1
selector:
matchLabels:
app: ngx-ing
template:
metadata:
labels:
app: ngx-ing
#annotations:
#prometheus.io/scrape: "true"
#prometheus.io/port: "9113"
#prometheus.io/scheme: http
spec:
serviceAccountName: nginx-ingress
containers:
#- image: nginx/nginx-ingress:2.2.0
- image: nginx/nginx-ingress:2.2-alpine
imagePullPolicy: IfNotPresent
name: ngx-ing
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
- name: readiness-port
containerPort: 8081
- name: prometheus
containerPort: 9113
readinessProbe:
httpGet:
path: /nginx-ready
port: readiness-port
periodSeconds: 1
securityContext:
allowPrivilegeEscalation: true
runAsUser: 101 #nginx
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
args:
- -ingress-class=myingc
- -health-status
- -ready-status
- -nginx-status
- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
- -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
# 应用YAML
kubectl apply -f ingress-controller.yaml
# 查看pod、deployment
kubectl get po -n nginx-ingress
kubectl get deploy -n nginx-ingress
测试:
# 将ingress对应的pod端口映射到master上临时测试
kubectl port-forward -n nginx-ingress ngx-ing-547d6575c7-fhdtt 8888:80 &
# 测试前,可以修改ng-deploy对应的两个pod里的/usr/share/nginx/html/index.html文件内容,用于区分两个pod
# 测试访问
curl -x127.0.0.1:8888 linyi.com
## 或者:
curl -H 'Host:linyi.com' http://127.0.0.1:8888
API资源对象PersistentVolume/PersistentVolumeClaim/StorageClass
持久化相关
三个概念:
PersistentVolume(pv):
是对具体存储资源的描述,比如NFS、Ceph、GlusterFS等,通过pv可以访问到具体的存储资源;
PersistentVolumeClaim(pvc):
Pod想要使用具体的存储资源需要对接到pvc,pvc里会定义好pod希望使用存储的属性,通过pvc再去申请合适的存储资源(pv),匹配到合适的资源后pvc和pv会进行绑定,它们两者是一一对应的;
StorageClass(sc):
pv可以手动创建,也可以自动创建,当pv需求量非常大时,如果靠手动创建pv就非常麻烦了,sc可以实现自动创建pv,并且会将pvc和pv绑定。
sc对象会定义两部分内容:①pv的属性,比如存储类型、大小;②创建该pv需要用到的存储插件(provisioner),这个provisioner是实现自动创建pv的关键。
案例一(pv手动创建):
PV YAML示例:
vi testpv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: testpv
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 500Mi ##提供500Mi空间
hostPath:
path: /tmp/testpv/
说明: accessModes定义该pv的访问权限模式,有三种:
ReadWriteOnce:存储卷可读可写,但只能被一个节点上的 Pod 挂载;
ReadOnlyMany:存储卷只读不可写,可以被任意节点上的 Pod 多次挂载;
ReadWriteMany:存储卷可读可写,也可以被任意节点上的 Pod 多次挂载;
capacity 定义该存储大小。 hostPath 定义该存储访问路径。
PVC YAML示例:
vi testpvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: testpvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi ##期望申请100Mi空间
# 应用pv和pvc的YAML
kubectl apply -f testpv.yaml -f testpvc.yaml
# 查看状态
kubectl get pv,pvc
实验: 将testpvc的期望100Mi改为1000Mi,查看pv的STATUS