API资源规范
核心资源类型
Kubernetes API Primitive
◼ 用于描述在Kubernetes上运行应用程序的基本组件,即俗称的Kubernetes对象(Object)
◼ 它们持久存储于API Server上,用于描述集群的状态
依据资源的主要功能作为分类标准,Kubernetes的API对象大体可分为如下几个类别
◼ 工作负载(Workload)
◼ 服务发现和负载均衡(Discovery & LB)
◼ 配置和存储(Config & Storage)
◼ 集群(Cluster)
◼ 元数据(Metadata)
“以应用为中心”
◼ Kubernetes API Primitive基本都是围绕一个核心目的而设计:如何更好地运行和丰富Pod资源,从而为容器化
应用提供更灵活和更完善的操作与管理组件
工作负载型资源负责应用编排
服务发现和负载均衡型资源完成服务注册、发现及流量调度
API资源规范
资源规范
◼ 绝大多数的Kubernetes对象都包含spec和status两个嵌套字段
◆ spec字段存储对象的期望状态(或称为应有状态)
⚫ 由用户在创建时提供,随后也可按需进行更新(但有些属性并不支持就地更新机制)
⚫ 不同资源类型的spec格式不尽相同
◆ status字段存储对象的实际状态(或称为当前状态)
⚫ 由Kubernetes系统控制平面相关的组件负责实时维护和更新
◼ 对象元数据
◆ 名称、标签、注解和隶属的名称空间(不包括集群级别的资源)等
◼ kind和apiVersion两个字段负责指明对象的类型(资源类型)元数据
◆ 前者用于指定类型标识
◆ 后者负责标明该类型所隶属的API群组(API Group)
例如:
apiVersion: <GROUP/VERSION> #定义资源群主及版本
kind: <RESOURCE KIND> #定义资源类型
metadata: #定义资源的元数据
name: ... #定义资源名称
namespace: ... #定义资源的名称空间
labels: { ... } #定义资源的标签
annotations: { ... } #定义资源的注解
spec: { ... } #定义资源的终态
API Server
◼ 基于HTTP(S)协议暴露了一个RESTful风格的API
◼ kubectl命令或其它UI通过该API查询或请求变更API对象的状态
◆ 施加于对象之上的基本操作包括增、删、改、查等
◆ 通过HTTP协议的GET、POST、DELETE和PUT等方法完成,而对应于kubectl命令,它们则是create、get、describe、
delete、patch和edit等子命令
API对象管理
◼ 创建对象时,必须向API Server提供描述其所需状态的对象规范、对象元数据及类型元数据
◼ 需要在请求报文的body中以JSON格式提供
◆ 用户也能够以YAML格式定义对象,提交给API Server后由其自行完成格式转换
资源规范的具体格式
◼ https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/
◼ 内建文档:kubectl explain 命令获取
◼ 参考现有资源对象:kubectl get TYPE/NAME -o {yaml|json}
应用编排
使用客户端程序,对API Server的REST服务端点发请求
◼ 请求的body部分要遵循API资源规范
kubectl命令提供了三种类型的对象管理机制
◼ 指令式命令(Imperative commands)
◆ 直接作用于集群上的活动对象(Live objects)
◆ 适合在开发环境中完成一次性的操作任务
◼ 指令式对象配置(Imperative object configuration)
◆ 基于资源配置文件执行对象管理操作,但只能独立引用每个配置清单文件
◆ 可用于生产环境的管理任务
◼ 声明式对象配置(Declarative object configuration)
◆ 基于配置文件执行对象管理操作
◆ 可直接引用目录下的所有配置清单文件,也可直接作用于单个配置文件
部署并访问应用
部署应用
◼ 依照编排需求,选定合适类型的工作负载型控制器
◼ 创建工作负载型控制器对象,由其确保运行合适数量的Pod对象
◼ 创建Service对象,为该组Pod对象提供固定的访问入口
编排应用
◼ 仅打印资源清单
◆ kubectl create deployment demoapp --image=ikubernetes/demoapp:v1.0 --port=80 --dry-run=client --replicas=3 -o yaml
◼ 创建deployment对象
◆ kubectl create deployment demoapp --image=ikubernetes/demoapp:v1.0 --port=80 --replicas=3
◆ Deployment控制器确保deployment/demoapp中定义,
◼ 了解完整的资源规范及状态
◆ kubectl get deployments [-o yaml|json]
◼ 了解Pod对象的相关信息
◆ kubectl get pods -l app=demoapp -o wide
创建Service对象
◼ 仅打印资源清单
◆ kubectl create service clusterip demoapp --tcp=80:80 --dry-run=client -o yaml
◼ 创建Service对象
◆ kubectl create service clusterip demoapp --tcp=80:80
◼ 了解Service的相关信息
◆ kubectl get services demoapp -o wide
◼ 访问Service
◆ demoappIP=$(kubectl get services demoapp -o jsonpath={.spec.clusterIP})
◆ curl $demoappIP
Service:
类型:
ClusterIP:仅支持集群内部的客户访问
NodePort:支持集群内部客户端访问;同时,支持集群外部的客户端通过任何一个的节点IP地址进行访问,但要使用特定端口分配的范围:30000-32768
示例:
kubectl create service nodeport demoapp --tcp=80:80
Service:
Client来源:
集群内部:ClusterIP
外部客户端:NodePort,超集
任何一个节点的IP地址,同一个NodePort
定义Pod资源
关于Pod
什么是Pod?
◼ 一个或多个容器的集合,因而也可称为容器集,但却是Kubernetes调度、部署和运行应用的原子单元
◼ 另外封装的内容:可被该组容器共享的存储资源、网络协议栈及容器的运行控制策略等
◼ 依赖于pause容器事先创建出可被各应用容器共享的基础环境,它默认共享Network、IPC和UTS名称空间给各容器,PID名称空间也可以共享,但需要用户显式定义
Pod的组成形式有两种
◼ 单容器Pod:仅含有单个容器
◼ 多容器Pod:含有多个具有“超亲密”关系的容器
◆ 同一Pod内的所有容器都将运行于由Scheduler选定的同一个节点上
一个极简的Pod定义,仅需要为其指定一个要运行的容器即可
◼ 给出该容器的名称和使用的Image
apiVersion:v1
kind: Pod
metadata:
name: ... # Pod的标识名,在名称空间中必须惟一;
namespace: ... # 该Pod所属的名称空间,省略时使用默认名称空间default;
spec:
containers: # 定义容器,它是一个列表对象,可包括多个容器的定义,至少得有一个;
- name: ... # 容器名称,必选字段,在当前Pod中必须惟一;
image: ... # 创建容器时使用的镜像
◼ pause容器无需定义
◼ 下面是一个简单的Pod资源示例
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
namespace: default
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
相近的资源类型,会被划分至同一个组中; 不同的功能,会被分类到不同的组合
每个的组的版本号,独立演进
alpha: 内测
beta:公测
stable:稳定
名称空间:因为所有的资源类型名字不能重复所有为了方便有了名称空间的概念
[root@master1 chapter4]#kubectl create namespace ppp #创建一个名称空间为ppp
namespace/ppp created
[root@master1 chapter4]#kubectl get namespace #查看名称空间
NAME STATUS AGE
default Active 26h
demo Active 26h
kube-node-lease Active 26h
kube-public Active 26h
kube-system Active 26h
ppp Active 11s
Pod的phase和重启策略
Pod的重启策略:决定了容器终止后是否应该重启
◼ Always:无论何种exit code,都要重启容器
◼ OnFailure:仅在exit code为非0值(即错误退出)时才重启容器
◼ Never:无论何种exit code,都不重启容器
#pod的相位
Pending #刚刚创建被调度之前的状态
Running #准备就绪
Succeeded #正常运行结束
Failed #错误运行结束
Unknown #kubelet无法正常连接pod
#容器的状态
Waiting #等待资源满足
Running #就绪
Terminatd #运行状态
kubernetes的基础命令
#查看所有的资源类型
[root@master1 ~]#kubectl api-resources
#查看对应资源的详细信息
[root@master1 ~]#kubectl explain pods
#使用explain 命令以此查看使用方法
[root@master1 ~]#kubectl explain pod.spec.volumes.vsphereVolume.volumePath
#查看资源信息以json或者yaml格式输出
[root@master1 ~]#kubectl get pod -o [ json | yaml ]
#查看资源的详细信息
[root@master1 ~]#kubectl describe deployment nginx
#查看pod的日志信息如果一个pod有多个容器则显示使用-c [ CONTAINER_NAME ] -n NAMESPACE
[root@master1 ~]#kubectl logs nginx-55f494c486-qk77v
#查看该名称空间下的pod资源
[root@master1 ~]# kubectl get pods -n namespace_name
#手动扩缩容(将指定的deployment的pod数量变为1个)
[root@master1 ~]#kubectl scale deployment/demoapp --replicas=1 -n demo
#手动扩缩容(将指定的deployment的pod数量变为100000个)
[root@master1 ~]#kubectl scale deployment/demoapp --replicas=100000 -n demo
#进入pod的交互式接口
kubectl exec -it demoapp-55c5f88dcb-zzwqr -n demo -- /bin/sh
#创建一个pod并进入交互式
kubectl run client-$RANDOM --image=ikubernetes/admin-box:v1.2 --restart=Never -it --rm --command -- /bin/bash
#更换pod内的镜像
kubectl set image deployment demoapp demoapp=ikubernetes/demoapp:v1.1 -n demo
#查看更新的历史信息
kubectl rollout history deployment -n demo
#回滚上一个版本
kubectl rollout undo deployment demoapp -n demo
#查看pod和容器之间的使用规范
Pod级别:
kubectl explain pods.spec.securityContext
容器级别:
kubectl explain pods.spec.containers.securityContext
#使用声明式配置指令文件
kubectl apply -f mysql-ephemeral/ -f wordpress-apache-ephemeral/
#创建一个pod的yaml文件如下
apiVersion: v1 #版本号
kind: Pod #资源类型
metadata: #元数据
name: demoapp-pod #这个资源的名字
namespace: default #运行在那个名称空间之下
spec: #定义资源类型的终态
containers: #对象列表
- name: demoapp #容器的名字
image: ikubernetes/demoapp:v1.0 #镜像的位置
[root@master1 test]# kubectl create --save-config=true -f test-1.yaml #指令式对像文件(启动)
#拉起一个pod干跑一下 可用于生成配置文件的框架
[root@master1 test]#kubectl run demoapp-pod-002 --image=ikubernetes/demoapp:v1.0 --restart=Never --dry-run=client -o yaml #pod和容器的名字叫demoapp-pod-002 镜像叫ikubernetes/demoapp:v1.0 --restart=Never的意思是不受任何控制器影响是一个单独的pod --dry-run=client的意思是就是干跑不创建-o yaml以yaml格式的文件生成显示
#容器的下载策略
imagePullPolicy:
1、IfNotPresent #当前的节点有就使用没有就下载
2、Always #无论有没有镜像总是去下载
3、Never #有就使用没有就不运行
[root@master1 test]#kubectl logs demoapp-pod -f #查看pod容器的容器加了-f就是不退出持续观看
#进入容器执行命令之后退出
[root@master1 chapter4]#kubectl exec demoapp-pod -- ps aux #查看容器内的进程
[root@master1 chapter4]#kubectl exec pod/pod-using-env -- netstat -tnl #查看容器的使用端口
#向容器内部传递变量,前提是容器支持的变量。
apiVersion: v1
kind: Pod
metadata:
name: pod-using-env
namespace: default
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
env:
- name: HOST #本容器支持HOST变量意思为监听的地址
value: "0.0.0.0" #值为0.0.0.0
- name: PORT #本容器支持的PORT变量,意思为监听的端口
value: "1234" #为1234
[root@master1 chapter4]#kubectl exec pod/pod-using-env -- netstat -tnl #查看pod的容监听端口和监听地址为指定的
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:1234 0.0.0.0:* LISTEN
#查看容器内支持的所有变量
[root@master1 chapter4]#kubectl exec pod-using-env -- printenv
#共享宿主机的名称空间
# Maintainer: MageEdu <mage@magedu.com>
# # URL: http://www.magedu.com
apiVersion: v1
kind: Pod
metadata:
name: pod-using-hostnetwork
namespace: default
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
hostNetwork: true #true就是共享宿主机的网络名称空间
配置Pod
环境变量是容器化应用的常用配置方式之一
在容器上嵌套使用env字段
◼ 每个环境变量需要通过name给出既定的名称
◼ 传递的值则定义在value字段上
#查看容器内支持的所有变量
[root@master1 chapter4]#kubectl exec pod_name -- printenv
实验
实验:利用env变量对接mysql+wordpress
#创建MySQL的svc的yaml配置文件
[root@master1 wordpress]# kubectl create svc clusterip mysql --tcp 3306:3306 --dry-run=client -o yaml > 01.svc.yaml #创建service的类型为clusterip,名字为mysql映射端口为3306,干跑不拉,使用yaml格式输出,重定向到01.svc.yaml文件中
[root@master1 wordpress]# vim mysql/01.svc.yaml #查看此文件
apiVersion: v1 #资源版本
kind: Service #资源类型
metadata: #定义元数据
creationTimestamp: null #当前时间
labels: #标签
app: mysql #标签名字
name: mysql #资源名字
spec: #定义终态
ports: #端口
- name: 3306-3306 #3306映射到3306
port: 3306 #svc端口
protocol: TCP
targetPort: 3306 #映射到容器的端口
selector: #标签选择器
app: mysql #标签为mysql
type: ClusterIP #定义为clusterip类型
#创建mysql的deployment的配置文件
[root@master1 wordpress]# kubectl create deployment mysql --image=mysql:8.0 --dry-run=client -o yaml > mysql/03-mysql.yaml #创建deployment工作负载型控制器资源名字为mysql 使用的镜像为mysql:8.0 干跑不创建 重定向输出到mysql/03-mysql.yaml文件中
[root@master1 wordpress]# vim ./mysql/02-mysql.yaml
apiVersion: apps/v1 #使用的资源版本
kind: Deployment #资源类型
metadata: #元数据
creationTimestamp: null
labels:
app: mysql
name: mysql
spec:
replicas: 1 #创建的数量
selector: #标签选择器
matchLabels: #匹配的标签为
app: mysql # mysql
strategy: {}
template: #使用的模板
metadata:
creationTimestamp: null
labels:
app: mysql
spec: #定定义pod的终态
containers: #定义资源对象
- image: mysql:8.0 #使用的镜像为mysql:8.0
name: mysql #定义的pod的名字
env:
- name: MYSQL_RANDOM_ROOT_PASSWORD #mysql的root密码为随机
value: "1"
- name: MYSQL_DATABASE #创建一个数据库为wordpress
value: "wordpress"
- name: MYSQL_USER #创建一个用户为wordpress
value: "wordpress"
- name: MYSQL_PASSWORD #为用户创建密码为123456
value: "123456"
#创建wordpress-svc资源
[root@master1 wordpress]# kubectl create svc nodeport wordpress --tcp 80:80 --dry-run=client -o yaml > wordpress/01.svc.yaml #创建一个svc资源类型为nodeport映射的端口为80 干跑一下重定向到wordpress/01.svc.yaml
[root@master1 wordpress]#vim wordpress/01.svc.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: wordpress
name: wordpress
spec:
ports:
- name: 80-80
port: 80
protocol: TCP
targetPort: 80
selector:
app: wordpress
type: NodePort
status:
loadBalancer: {}
#创建wordpress-deployment资源
[root@master1 wordpress]# kubectl create deployment wordpress --image=wordpress:5.7 --dry-run=client -o yaml > wordpress/02-wordpress.yaml #创建一个deployment资源镜像为wordpress:5.7 干跑一下 使用yaml格式输出
apiVersion: apps/v1 #资源版本号
kind: Deployment #资源类型
metadata: #元数据
creationTimestamp: null
labels:
app: wordpress #定义标签
name: wordpress #资源的名字
spec:
replicas: 1 #启动的pod的数量为1
selector: #选择器
matchLabels:
app: wordpress
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: wordpress
spec:
containers:
- image: wordpress:5.7
name: wordpress
env:
- name: WORDPRESS_DB_HOST #数据库指向为mysql刚刚创建的mysql资源的名字
value: "mysql"
- name: WORDPRESS_DB_NAME #数据库的名字为wordpress
value: "wordpress"
- name: WORDPRESS_DB_USER #连接的时候的名字
value: "wordpress"
- name: WORDPRESS_DB_PASSWORD #数据库密码
value: "123456"
[root@master1 wordpress]#ls
mysql wordpress
[root@master1 wordpress]#kubectl apply -f mysql/ -f wordpress/ #使用声明式配置
service/mysql configured
deployment.apps/mysql configured
service/wordpress configured
deployment.apps/wordpress configured
[root@master1 wordpress]#kubectl get deployment #查看deployment
NAME READY UP-TO-DATE AVAILABLE AGE
mysql 1/1 1 1 50m
wordpress 1/1 1 1 50m
[root@master1 wordpress]#kubectl get svc #查看svc资源
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 192.160.0.1 <none> 443/TCP 20h
mysql ClusterIP 192.168.158.174 <none> 3306/TCP 51m
wordpress NodePort 192.175.181.186 <none> 80:31929/TCP 51m
共享宿主机的网络空间
apiVersion: v1
kind: Pod
metadata:
name: pod-using-hostnetwork
namespace: default
labels:
app: demoapp
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
hostNetwork: true
应用监控
容器式运行的应用类似于“黑盒”,为了便于平台对其进行监测,云原生应用应该输出用于监视自身
API
◼ 包括健康状态、指标、分布式跟踪和日志等
◼ 至少应该提供用于健康状态监测的API
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-74JAIg6u-1670217519911)(kubernetes的基础概念和安装.assets/image-20221204234751834.png)]
Pod的健康状态监测机制
Pod支持的监测类型
startup Probe #启动调查 一般用于初始化的检测机制
liveness Probe #存活调查 失败的话会被重启
readiness Probe #就绪调查 就绪检查成功之前不会成为service成功调度的目标 失败的话service不会调度到他的身上
如果没有定义探针的话service被调度的依据是判断pod是否为running状态但是pod的running状态不一定就是可以对外提供服务
监测机制
◼ Exec Action: #根据指定命令的结果状态码判定
◼ TcpSocket Action: #根据相应TCP套接字连接建立状态判定
◼ HTTPGet Action: #根据指定https/http服务URL的响应结果判定
配置参数
initialDelaySeconds #延迟启动时间
periodSeconds #周期性检测时间
timeoutSeconds #超时时间
successThreshold #成功阈值
failureThreshold #失败阈值
实例:
同时定义了三种探针
◼ startup使用了Exec Action
◼ liveness和readiness使用HTTPGet Action
测试效果
◼ liveness
◆ URL “/livez” 支持以POST方法为livez参数设定不同值,
非OK值都以5xx响应码响应;
◼ readiness
◆ URL “/readyz” 支持以POST方法为readyz参数设定不同值,非OK值都以5xx响应码响应;
apiVersion: v1 #版本信息
kind: Pod #资源类型
metadata: #元数据
name: pod-probe-demo #资源名字
namespace: default #指定名称空间
spec: #定义终态
containers: #对象列表
- name: demo #容器名字
image: ikubernetes/demoapp:v1.0 #镜像名字
imagePullPolicy: IfNotPresent #拉取镜像的策略
startupProbe: #定义启动探针
exec: #使用根据指定的命令的状态码判断启动与否
command: ['/bin/sh','-c','test','"$(curl -s 127.0.0.1/livez)"=="OK"']
initialDelaySeconds: 0 #延迟启动时间
failureThreshold: 3 #失败阈值
periodSeconds: 2 #周期性检测时间
livenessProbe: #存活调查 失败的话会被重启
httpGet: #更根指定的HTTP/HTTPS服务URL的响应判断
path: '/livez' #指定的uri为/livez
port: 80 #指定的端口
scheme: HTTP #指定的协议
initialDelaySeconds: 3 #延时启动时间
timeoutSeconds: 2 #超时时间
readinessProbe: #就绪探针
httpGet: #使用更根指定的HTTP/HTTPS服务URL的响应判断
path: '/readyz' #指定的uri为/livez
port: 80 #指定的端口
scheme: HTTP #指定的协议
initialDelaySeconds: 15 #延时启动时间
timeoutSeconds: 2 #超时时间
restartPolicy: Always #指定重启策略
容器拉取的策略有:
#容器的下载策略
imagePullPolicy:
1、IfNotPresent #当前的节点有就使用没有就下载
2、Always #无论有没有镜像总是去下载
3、Never #有就使用没有就不运行
实验
活体探针实验1、使用状态码判断(存活探测):
[root@master1 chapter4]#vim liveness-exec-demo.yaml
apiVersion: v1 #资源版本
kind: Pod #资源类型
metadata: #元数据
name: liveness-exec-demo #资源名称
namespace: default #默认的名称空间
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" ]'] #判断curl -s 127.0.0.1/livez执行的结果是否为OK
initialDelaySeconds: 5 #延迟探针时间
timeoutSeconds: 1 #超时时间
periodSeconds: 5 #周期性间隔时间
[root@master1 chapter4]#kubectl apply -f liveness-exec-demo.yaml #使用声明式指令配置文件启动pod
[root@master1 chapter4]#kubectl get pods
NAME READY STATUS RESTARTS AGE
client-14486 1/1 Running 0 21h
demoapp-pod 1/1 Running 0 5h37m
liveness-exec-demo 1/1 Running 0 18m
#破环活体探针的文件
[root@master1 chapter4]# curl -XPOST -d livez=FAIL 192.168.154.9/livez #将/livez文件的值改为FAIL
#查看pod的详细信息
root@master1 chapter4]#kubectl describe pods liveness-exec-demo
#会看到最下面的Events:字段中的信息提示到检测服务失败然后是重启
[root@master1 chapter4]#kubectl get pods #查看pods的信息会看到liveness-exec-demo的 RESTARTS字段的次数变成1
NAME READY STATUS RESTARTS AGE
client-14486 1/1 Running 0 21h
demoapp-pod 1/1 Running 0 5h41m
liveness-exec-demo 1/1 Running 1 (10m ago) 23m
活体探针实验2、使用TCP套接字判断(存活探测):
[root@master1 chapter4]#vim liveness-tcpsocket-demo.yaml #创建一个资源对象
apiVersion: v1 #
kind: Pod
metadata:
name: liveness-tcpsocket-demo #资源的名字
namespace: default #名称空间
spec:
containers: #对象列表
- name: demo #容器名字
image: ikubernetes/demoapp:v1.0 #镜像
imagePullPolicy: IfNotPresent #镜像拉取策略
ports: #定义posts端口
- name: http #名字为http
containerPort: 80 #端口为80
securityContext: #安全上下文
capabilities: #功能
add: #添加
- NET_ADMIN #添加这个功能因为一会要使用iptables 所以添加
livenessProbe: #存活探针
tcpSocket: #使用TCP套接字连接探测
port: http #使用http
periodSeconds: 5 #周期为5s
initialDelaySeconds: 5 #启动延迟探测时间为5s
[root@master1 chapter4]#kubectl exec -it liveness-tcpsocket-demo -- iptables -A INPUT -p tcp --dport 80 -j REJECT
#此时查看pod的详细信息
[root@master1 chapter4]# kubectl describe pod liveness-tcpsocket-demo
#在Events字段中的Message中会看到
Liveness probe failed: dial tcp 192.168.154.10:80: i/o timeout #检测时间超时
Container demo failed liveness probe, will be restarted #pod重新启动
[root@master1 chapter4]#kubectl exec -it liveness-tcpsocket-demo -- iptables -F #清空pod的iptables规则
[root@master1 chapter4]#kubectl get pods #查看pod信息会发现RESTARTS字段的重启次数变成1
\NAME READY STATUS RESTARTS AGE
liveness-tcpsocket-demo 1/1 Running 1 (27s ago) 26m
活体探针实验3、使用http/https服务请求判断(存活探测):
[root@master1 chapter4]#vim liveness-httpget-demo.yaml
apiVersion: v1 #资源版本
kind: Pod #资源类型
metadata: #资源元数据
name: liveness-httpget-demo #资源名称
namespace: default #名称空间
spec: #定义终态
containers: #对象列表
- name: demo #容器名字
image: ikubernetes/demoapp:v1.0 #容器镜像
imagePullPolicy: IfNotPresent #拉取策略
livenessProbe: #存活性活体探针
httpGet: #使用http方式
path: '/livez' #访问/lives
port: 80 #80端口
scheme: HTTP #使用http
initialDelaySeconds: 5 #延迟探测时间
[root@master1 chapter4]#curl -XPOST -d 'livez=FAIL' 192.168.28.17/livez #修改livez的值为FAIL
[root@master1 chapter4]#kubectl get pods #查看pod的信息可以看到RESTARTS重启次数变成了1
NAME READY STATUS RESTARTS AGE
liveness-httpget-demo 1/1 Running 1 16m
[root@master1 chapter4]#curl -XPOST -d 'livez=OK' 192.168.28.17/livez #恢复正常
活体探针实验4、使用http/https服务请求判断(就绪探测)
注意:就绪探针不会导致重启只会导致service不去的调度 #此实验就是为了去证明此项
vim readiness-httpget-demo.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
name: readiness-httpget-demo #定义一个标签
name: readiness-httpget-demo
namespace: default
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
readinessProbe: #就绪探测
httpGet: #使用http服务探测
path: '/readyz' #探测的uri地址为/readyz
port: 80 #探测的端口为80
scheme: HTTP #使用的方式为http
initialDelaySeconds: 15 #探测延时时间
timeoutSeconds: 2 #超时时间
periodSeconds: 5 #周期时间
failureThreshold: 3 #失败阈值
restartPolicy: Always #重启策略为总是重启
[root@master1 chapter4]#kubectl apply -f readiness-httpget-demo.yaml #使用声明式配置指令启动
[root@master1 chapter4]#kubectl create svc clusterip readiness-httpget-demo --tcp 80:80 --dry-run=client -o yaml > readiness-prbe-service.yaml #创建一个readiness-prbe-service.yaml配置文件
apiVersion: v1
kind: Service
metadata:
name: readiness-httpget-demo
spec:
ports:
- name: 80-80
port: 80
protocol: TCP
targetPort: 80
selector:
name: readiness-httpget-demo
type: ClusterIP
[root@master1 chapter4]#kubectl apply -f readiness-prbe-service.yaml #使用声明式配置指令启动
[root@master1 chapter4]#kubectl describe svc readiness-httpget-demo
Name: readiness-httpget-demo
Namespace: default
Labels: <none>
Annotations: <none>
Selector: name=readiness-httpget-demo
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 192.164.21.190
IPs: 192.164.21.190
Port: 80-80 80/TCP
TargetPort: 80/TCP
Endpoints: 192.168.44.11:80 #匹配到的pod的IP地址
Session Affinity: None
Events: <none>
[root@master1 chapter4]#curl 192.164.21.190 #使用service地址访问可以正常访问
iKubernetes demoapp v1.0 !! ClientIP: 10.0.0.100, ServerName: readiness-httpget-demo, ServerIP: 192.168.44.11!
[root@master1 chapter4]#curl -XPOST -d 'readyz=FAIL' 192.168.44.11/readyz #更改/readyz的内容为FAIL
[root@master1 chapter4]#kubectl get pod #发现此时的状态已经不正常了
NAME READY STATUS RESTARTS AGE
readiness-httpget-demo 0/1 Running 0 28m
[root@master1 chapter4]#kubectl describe svc readiness-httpget-demo
Name: readiness-httpget-demo
Namespace: default
Labels: <none>
Annotations: <none>
Selector: name=readiness-httpget-demo
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 192.164.21.190
IPs: 192.164.21.190
Port: 80-80 80/TCP
TargetPort: 80/TCP
Endpoints: #此时已经没有匹配到的pod的IP地址了
Session Affinity: None
Events: <none>
[root@master1 chapter4]#curl 192.164.21.190 #再次使用svc地址检测
curl: (7) Failed to connect to 192.164.21.190 port 80: 拒绝连接 #已经失败了
[root@master1 chapter4]#curl -XPOST -d 'readyz=OK' 192.168.44.11/readyz #将故障恢复了
[root@master1 chapter4]#curl 192.164.21.190 #再次访问已正常
iKubernetes demoapp v1.0 !! ClientIP: 10.0.0.100, ServerName: readiness-httpget-demo, ServerIP: 192.168.44.11!
安全上下文
安全上下文的参数详细信息可以查看:https://man7.org/linux/man-pages/man7/capabilities.7.html
Pod及容器的安全上下文
◼ 一组用来决定容器是如何创建和运行的约束条件,这些条件代表创建和运行容器时使用的运行时参数
◼ 给了用户为Pod或容器定义特权和访问控制机制
Pod和容器的安全上下文设置主要包括以下几个方面
◼ 自主访问控制DAC
◼ 容器进程运行身份及资源访问权限
◼ Linux Capabilities #linux功能
◼ seccomp
◼ AppArmor
◼ SELinux
◼ Privilgege Mode
◼ Privilege Escalation
Kubernetes支持在Pod及容器级别分别使用安全上下文
阿里云知行实验室上的实验:“理解及使用Security Context”
实验
安全上下文实验1、(增加iptables能力和删除root权限):
[root@master1 chapter4]# vim securitycontext-capabilities-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: securitycontext-capabilities-demo
namespace: default
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c"] #执行命令
args: ["/sbin/iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80 && /usr/bin/python3 /usr/local/bin/demo.py"] #传递的参数
securityContext: #安全上下文
capabilities: #功能为
add: ['NET_ADMIN'] #怎加内核能力可以使用iptables
drop: ['CHOWN'] #删除内核能力root的权限
[root@master1 chapter4]#kubectl apply -f securitycontext-capabilities-demo.yaml #使用声明式配置指令启动
[root@master1 chapter4]#kubectl exec -it securitycontext-capabilities-demo -- /bin/sh #进入交互式接口
[root@securitycontext-capabilities-demo /]# iptables -t nat -nvL #在交互式接口中运行iptables命令
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 redir ports 80
[root@securitycontext-capabilities-demo /]# cp -a /etc/fstab/ .
[root@securitycontext-capabilities-demo /]# chown nobody. fstab
chown: fstab: Operation not permitted #提示没有权限
#将yaml配置文件的drop的选项注释了
[root@master1 chapter4]# vim securitycontext-capabilities-demo
apiVersion: v1
kind: Pod
metadata:
name: securitycontext-capabilities-demo
namespace: default
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c"]
args: ["/sbin/iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80 && /usr/bin/python3 /usr/local/bin/demo.py"]
securityContext:
capabilities:
add: ['NET_ADMIN']
#drop: ['CHOWN'] #注释此行让容器内的root获得真正root的权限
[root@master1 chapter4]#kubectl exec -it securitycontext-capabilities-demo -- /bin/sh #再次进入交互式接口
[root@securitycontext-capabilities-demo /]# chown nobody. fstab #执行成功
#进入没有授权可以使用iptables的pod
[root@master1 chapter4]#kubectl exec -it demoapp-pod -- /bin/sh
[root@demoapp-pod /]# iptables -nvL #没有权限执行
iptables v1.8.3 (legacy): can't initialize iptables table `filter': Permission denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.
安全上下文的实验2、(增加模块):
vim securitycontext-runasuser-demo.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: securitycontext-runasuser-demo
namespace: default
spec:
containers:
- name: demo
image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
securityContext: #安全上下文
runAsUser: 1001 #指定执行第一个守护进程的用户
runAsGroup: 1001 #指定执行第一个守护进程的组
capabilities: #功能增加
add: ['NET_BIND_SERVICE'] #增加可以时普通用户监听1024端口的功能
[root@master1 chapter4]#kubectl apply -f securitycontext-runasuser-demo.yaml
[root@master1 chapter4]#kubectl exec -it securitycontext-runasuser-demo -- ps aux #查看pod内的进程
PID USER TIME COMMAND
1 1001 0:00 python3 /usr/local/bin/demo.py
19 1001 0:00 ps aux
[root@master1 chapter4]#kubectl exec -it securitycontext-runasuser-demo -- ss -ntl #查看监听的端口
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
资源需求和限制
资源需求和资源限制
◼ 资源需求(requests)
◆ 定义需要系统预留给该容器使用的资源最小可用值
◆ 容器运行时可能用不到这些额度的资源,但用到时必须确保有相应数量的资源可用
◆ 资源需求的定义会影响调度器的决策
◼ 资源限制(limits)
◆ 定义该容器可以申请使用的资源最大可用值,超出该额度的资源使用请求将被拒绝
◆ 该限制需要大于等于requests的值,但系统在其某项资源紧张时,会从容器那里回收其使用的超出其requests值的那部分
requests和limits定义在容器级别,主要围绕cpu、memory和hugepages三种资源
Resource requests 和 limits
requests: #资源需求,影响调度器的调度决策,最少满足条件
limits: #资源限制,决不允许超出使用的资源范围
实验
资源限制和需求实验1、
[root@master1 chapter4]#vim pod-resources-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: stress-pod
spec:
containers:
- name: stress
image: ikubernetes/stress-ng
command: ["/usr/bin/stress-ng", "-c 1", "-m 1", "--metrics-brief"]
resources: #资源限制
requests: #资源需求为
memory: "128Mi" #128M内存
cpu: "200m" #占用一个核心cpu的百分之20
limits: #资源限制
memory: "512Mi" #最大使用内存为
cpu: "400m" #最大使用cpu为
1、手动配置Pod,通过环境变量生成默认配置;
额外为mydb和wordpress分别创建一个Service资源;
mydb的客户端只是wordpress,类型使用ClusterIP
kubectl create service clusterip mydb --tcp=3306:3306 --dry-run=client -o yaml
wordpress的客户端可能来自于集群外部,类型要使用NodePort
kubectl create service nodeport wordpress --tcp=80:80 --dry-run=client -o yaml
2、尝试为mydb和wordpress分别添加livenessProbe和readinessProbe,并测试其效果;
3、尝试为mydb和wordpress分别添加资源需求和资源限制;
#探针+资源限制和需求
[root@master1 wordpress]#vim mysql/02-mysql.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: mysql
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: mysql
spec:
containers:
- image: mysql:8.0
name: mysql
env:
- name: MYSQL_RANDOM_ROOT_PASSWORD
value: "1"
- name: MYSQL_DATABASE
value: "wordpress"
- name: MYSQL_USER
value: "wordpress"
- name: MYSQL_PASSWORD
value: "123456"
resources: #资源限制
requests: #资源需求为
memory: "128Mi" #128M内存
cpu: "200m" #占用一个核心cpu的百分之20
limits: #资源限制
memory: "512Mi" #最大使用内存为
cpu: "400m" #最大使用cpu为
livenessProbe: #存活探针
exec: #执行的命令
command: [ 'mysqladmin', '-uwordpress', '-p123456' ,'ping' ]
initialDelaySeconds: 5 #延迟探针时间
timeoutSeconds: 15 #超时时间
periodSeconds: 5 #周期性间隔时间
readinessProbe:
exec:
command: [ 'mysql','-uwordpress','-p123456' ]
initialDelaySeconds: 5 #延迟探针时间
timeoutSeconds: 15 #超时时间
periodSeconds: 5 #周期时间
#配置mysql的svc的clusterip类型
[root@master1 wordpress]# vim mysql/01.svc.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: mysql
name: mysql
spec:
ports:
- name: 3306-3306
port: 3306
protocol: TCP
targetPort: 3306
selector:
app: mysql
type: ClusterIP
status:
loadBalancer: {}
#配置wordpress的探针和资源需求及限制
[root@master1 wordpress]#vim wordpress/02-wordpress.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: wordpress
name: wordpress
spec:
replicas: 1
selector:
matchLabels:
app: wordpress
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: wordpress
spec:
containers:
- image: wordpress:5.7
name: wordpress
ports: #定义posts端口
- name: http #名字为http
containerPort: 80
env:
- name: WORDPRESS_DB_HOST
value: "mysql"
- name: WORDPRESS_DB_NAME
value: "wordpress"
- name: WORDPRESS_DB_USER
value: "wordpress"
- name: WORDPRESS_DB_PASSWORD
value: "123456"
resources: #资源限制
requests: #资源需求为
memory: "128Mi" #128M内存
cpu: "200m" #占用一个核心cpu的百分之20
limits: #资源限制
memory: "512Mi" #最大使用内存为
cpu: "400m" #最大使用cpu为
readinessProbe: #活体探针——就绪探针
httpGet:
path: /wp-admin/install.php
port: 80
scheme: HTTP
initialDelaySeconds: 3 #探测延时时间
timeoutSeconds: 10 #超时时间
periodSeconds: 5 #周期时间
failureThreshold: 3 #失败阈值
livenessProbe: #存活探针
tcpSocket: #使用TCP套接字连接探测
port: http #使用http
periodSeconds: 5 #周期为5s
initialDelaySeconds: 5 #启动延迟探测时间为5s
#配置wordpress的svc的nodeport类型
[root@master1 wordpress]#vim wordpress/01.svc.yaml
wordpress/01.svc.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: wordpress
name: wordpress
spec:
ports:
- name: 80-80
port: 80
protocol: TCP
targetPort: 80
selector:
app: wordpress
type: NodePort
status:
loadBalancer: {}