完全没有基础的建议先看一下我另外一篇文章
https://blog.csdn.net/weixin_45012003/article/details/109015382?spm=1001.2014.3001.5501
发一波福利好吧,因为是直接导入,图片太麻烦,需要的话私聊我留下联系方式我发给你们。
很多为手敲,出现错误,或者导入有误的欢迎指正
常用命令:
$ kubectl exec kubia-7nogl -- curl -s http: //10 .111. 249 .153
$ kubectl exec kubia-7nogl env #查看pod的环境变量
$ kubectl explain pod #查看pod包含的属性,deployment等资源也可用
$ kubectl explain pod.spec #深入一层查看
集群内部地址:案例:mysql.ops.svc.cluster.local
查看集群信息
kubectl cluster-info #查看集群信息
介绍Metrics-Server之前,必须要提一下Metrics API的概念
Metrics API相比于之前的监控采集方式(hepaster)是一种新的思路,官方希望核心指标的监控应该是稳定的,版本可控的,且可以直接被用户访问(例如通过使用 kubectl top 命令),或由集群中的控制器使用(如HPA),和其他的Kubernetes APIs一样。
kubectl explain pod #查看pod包含的属性,deployment等资源也可用
kubectl explain pod.spec #深入一层查看
标签
$ kubectl get pod --show-labels #查看标签
$ kubectl label node node-name gpu=true #添加标签
node "node-name" labeled
$ kubectl get node -l topology.kubernetes.io/zone=cn-shenzhen-e
#列出包含topology.kubernetes.io/zone=cn-shenzhen-e标签的node
NAME STATUS ROLES AGE VERSION cn-shenzhen.192.168.70.72 Ready <none> 153d v1.20.11-aliyun.1 cn-shenzhen.192.168.70.73 Ready <none> 153d v1.20.11-aliyun.1
$ kubectl delete pod -l label_method=manual #根据标签删除pod
存活探针
可以通过存活探针(liveness probe)检查容器是否还在运行。
场景:确保异常容器自动重启来保持应用程序的正常运行。
三种机制:
-
HTTP GET
针对容器的IP地址(你指定的端口和路径)执行HTTP GET
请求,响应码为2XX 3XX
为成功,服务器返回错误或者没有响应则为失败。
-
TCP套接字探针尝试与容器指定端口建议tcp连接,如果连接成功建立,则探测成功,否则,容器重新启动。
livenessProbe: tcpSocket: path: / port: http
-
EXec探针在容器内执行任意命令,并检查命令的退出状态码,如果状态码为0,则探测成功,其他状态码则都为失败。
就绪探针
场景:不要将请求转发到正在启动的 pod中,直到完全准备就绪。pod可能需要时间来加载配置或数据,或者可能需要执行预热过程以防止第一个用请求时间太长影响了用户体验。
Readiness Probe同样是周期性的检测Pod,然后根据响应来判断Pod是否就绪,与存活探针(Liveness Probe)相同,就绪探针也支持如下三种类型。
-
Exec:Probe执行容器中的命令并检查命令退出的状态码,如果状态码为0则说明已经就绪。
readinessProbe: exec: command: - ls - /var/ready
-
HTTP GET:往容器的IP:Port发送HTTP GET请求,如果Probe收到
2xx或3xx
,说明已经就绪。readinessProbe: tcpSocket: path: / port: http
-
TCP Socket:尝试与容器建立TCP连接,如果能建立连接说明已经就绪。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gB64gFJ4-1651545533498)(.\image\image-20220422110957689.png)]
headless发现独立的pod
apiVersion: vl
kind: Service
metadata:
name: kubia-headless
spec:
clusterIP: None #clusterIP设置为none,使得服务成为headless
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
创建只会,会发现svc服务没有集群IP。
$ kubectl exec dnsutils nslookup kubia-headless #使用新创建的pod执行DNS查找
...
Name: kubia-headless.default.svc.cluster.local
Address: 10.108.1.4
Name: kubia-headless.default.svc.cluster.local
Address: 10.108.2.5
#FQDN返回两个不同的IP。 这些是报告准备就绪的两个pod的IP。可以通过使用 kubectl get pods -o wide 列出 pod 来确认此问题,该清单显示了pod的IP。
注意:headless 服务仍然提供跨 pod 的负载平衡, 但是通过 DNS 轮询机制不是通过服务代理。
水平缩放
$ kubectl scale rc kubia --replicas=lO #修改副本数为10
$ kubectl edit rc kubia #进入文本编辑器修改参数。
job
apiVersion: batch/vl
kind: Job
metadata:
name: batch-job
spec:
template:
metadata:
labels:
app: batch-job
spec:
restartPolicy: OnFailure #job不能使用Always为默认重新启动策略
containers:
- name: main
image: luksa/batch-job
这是通过pod配置的属性restartPolicy完成的, 默认为Always。 Jobpod不能使用默认策略, 因为它们不是要无限期地运行 。 因此, 需要明确地将重启策略设置为OnFa辽ure或Never。 此设置防止容器在完成任务时重新启动(pod被Job管理时并不是这样的)。
命令
$ kubectl get jobs
$ kubectl get pod
$ kubect1 get po -a
#pod将不再出现在pod列表中,工作将被标记为已完成。默认情况下,除非使用--show-all (或-a)开关, 否则在列出pod时不显示已完成的pod
一个job执行多次
apiVersion: batch/vl
kind: Job
metadata:
name: multi-completion-batch-job
spec:
completions: 5 #将completions设置为5,将使此作业顺序运行五个pod
parallelism: 2 #最多两个pod可以并行运行
template:
metadata:
labels:
app: batch-job
spec:
restartPolicy: OnFailure #job不能使用Always为默认重新启动策略
containers:
- name: main
image: luksa/batch-job
Cronjob
apiVersion: batch/v1beta1
kind: Crontab
metadata:
name: batch-cronjob
spec:
schedule: "0,15,30,45 * * * *" #这项工作应该每天在每小时0,15,30和45分钟运行 对应分时日月周
startingDeadlineSeconds: 15 #pod最迟必须在预定时间后15秒开始运行
jobTemplata:
spec:
template:
metadata:
labels:
app: periodic-batch-job
spec:
restartPolicy: OnFailure
containers:
- name: main
image: luksa/batch-job
svc (service)
apiVersion : vl
kind: Service
spec:
ports:
- name: http
port: 80
targetPort: http #将端口80映射到容器中被称为http的端口
- name: https
port: 443
targetPort: https #将端口443映射到容器中被称为https的端口
Endpoint
endpoint不是一种属性,而是一种资源,可以拿来连接外部服务。
kubectl describe svc sidecar -n slo-dev
Name: sidecar
Namespace: slo-dev
Labels: app=micro-rpc-proxy
version=v1.10.0
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"micro-rpc-proxy","version":"v1.10.0"},"name":"sidecar","...
Selector: app=micro-rpc-proxy
Type: ClusterIP
IP: 172.16.6.239
Port: http 9051/TCP
TargetPort: http/TCP
Endpoints: 192.168.70.12:9051,192.168.70.33:9051,192.168.70.213:9051 #代表svc绑定的pod的ip和端口列表
Session Affinity: None
Events: <none>
$ kubectl get endpoints sidecar -n slope-dev
NAME ENDPOINTS AGE
sidecar 192.168.70.123:9051 156d
endpoint是资源,可以被创建
apiVersion: vl
kind: Service
metadata:
name: external-service #服务的名字必须和Endpoint对象的名字相匹配
spec: #服务中没有定义选择器
ports:
- port: 80
由于创建的资源中并不包含选择器,相关的Endpoints 资源并没有自动创建,所以必须手动创建。如下所示的代码清单中列出了
apiVersion: vl
kind: EndpointS
metadata:
name: external-service #Endpoint的名称必须和服务的名称相匹配(上面配置)
subsets:
- addresses:
- ip: 11.11.11.11 #服务将连接重定向到endpoint的IP地址
- ip: 22.22.22.22
ports:
-port: 80 #endpoint的目标端口
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YP0I9ep7-1651545533499)(.\image\image-20220421195355721.png)]
ExternalName类型的服务
apiVersion: vl
kind: Service
metadata:
name: external-service
spec:
type: ExternalName #代码的type被设置成ExternalName
externalName: someapi.somecompany.com #实际服务的完全限定域名
ports:
- port: 80
- 服务创建 完成后,pod可以 通 过external-service.default.svc.cluster.local域名(甚至是external-service)连接到外部服务,而不是使用服务的实际FQDN。这隐藏了实际的服务名称及其使用该服务的pod 的位置,允许修改服务定义,并且在以后如果将其指向不同的服务,只需简单地修改externalName属性,或者将类型重新变回ClusterIP并为服务创建Endpoint无论是手动创建,还是对服务上指定标签选择器使其自动创建。
- ExternalName服务仅在DNS级别实施一为服务创建了简单的CNAME DNS记录。 因此, 连接到服务的客户端将直接连接到外部服务, 完全绕过服务代理。 出于这个原因, 这些类型的服务甚至不会获得集群 IP。
注意CNAME记录指向完全限定的域名而不是数字 **IP**地址。
将服务暴露给外部客户端
有几种方式可以在外部访问服务:
- 将服务的类型设置成NodePort-每个集群节点都会在节点上打 开 一个端口, 对于NodePort服务, 每个集群节点在节点本身(因此得名叫NodePort)上打开一个端口,并将在该端口上接收到的流量重定向到基础服务。该服务仅在内部集群 IP 和端口上才可访间, 但也可通过所有节点上的专用端口访问。
- 将服务的类型设置成LoadBalance, NodePort类型的一种扩展——这使得服务可以通过一个专用的负载均衡器来访问, 这是由Kubernetes中正在运行的云基础设施提供的。 负载均衡器将流量重定向到跨所有节点的节点端口。客户端通过负载均衡器的 IP 连接到服务。
- 创建一 个Ingress资源, 这是一 个完全不同的机制, 通过一 个IP地址公开多个服务——它运行在 HTTP 层(网络协议第7 层)上, 因此可以提供比工作在第4层的服务更多的功能。
NodePort类型
apiVersion: vl
kind: Service
metadata:
name: kubia-nodeport
spec:
type: NodePort
ports:
- port: 80 #服务集群ip的端口号
targetPort: 8080 #背后pod的目标端口号
nodePort: 30123
#通过集群节点的30123端口可以访问该服务,指定端口不是强制性的。 如果忽略它,Kubemetes将选择一个随机端口。
selector:
app: kubia
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gfIby5mU-1651545533500)(.\image\image-20220421201825564.png)]
LoadBalance类型
负载均衡器将服务暴露
如果Kubemetes在不支持Load Badancer服务的环境中运行, 则不会调配负载平衡器, 但该服务仍将表现得像一个NodePort服务。这是因为LoadBadancer服务是NodePo江服务的扩展。
apiVersion: vl
kind: Service
metadata:
name: kubia-loadbalancer
spec:
type: LoadBalancer #该服务从kubernetes集群的基础架构获取负载均衡器。
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
LoadBalancer类型的服务是一个具有额外的基础设施提供的 负载平衡器NodePort服务。 如果使用kubectl describe 来显示有关该服务的 其他信息, 则会看到为该服务选择了 一个节点端口。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Hff29gD-1651545533500)(.\image\image-20220421203006034.png)]
ingress类型
是每个 LoadBalancer 服务都需要自己的负载均衡器, 以及独有的公有 IP 地址, 而 Ingress 只需要一个公网 IP 就能为许多服务提供访问。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DuKF8udV-1651545533500)(.\image\image-20220422095906594.png)]
Ingress 在网络栈 (HTTP) 的应用层操作, 并且可以提供一些服务不能实现的功能, 诸如基于 cookie 的会话亲和性 (session affinity) 等功能。
普通配置方式
apiVersion: extensions/vlbetal
kind: Ingress
metadata:
name: kubia
spec:
rules:
- host: kubia.example.com #ingress将域名Kubia.example.com映射到你的服务
http:
- paths: / #将所有的请求发送到kubia-nodeport服务的80端口
backend:
serviceName: kubia-nodeport
servicePort: 80
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-APtuVVAg-1651545533501)(.\image\image-20220422102711830.png)]
相同域名不同path路径
...
- host: kubia.example.com
http:
paths:
- path: /kubia #对kubia.example.com/kubia的请求将会转发至kubia服务
backend:
serviceName: kubia
servicePort: 80
- path: /foo #对kubia.example.com/bar的请求将会转发至bar服务
backend:
serviceName: bar
servicePort: 80
不同域名
spec:
rules:
- host: foo.example.com #对foo.example.com的请求将会转发至foo服务
http:
paths:
- path: /
backend:
serviceName: foo
servicePort: 80
- host: bar.example.com #对bar.example.com的请求将会转发至bar服务
http:
paths:
- path: /
backend:
serviceName: bar
sercicePort: 80
配置tls
当客户端创建到 Ingress 控制器的 TLS 连接时,控制器将终止 TLS 连接。客户端和控制器之间的通信是加密的,而控制器和后端 pod 之间的通信 不是 。运行在pod 上的应用程序不需要支持 TLS
例如,如果 pod 运行 we 务器,则它 只能接TTP 通信,并让 Ingress 控制器负责处理与 TL 关的所有内容。要使控制器能够这样做,需要将证书和私钥附加到 Ingress 。这两个必需资源存储在称为 Secret的Kubernetes 资源 中,然后在Ingress manifest 中引用它
首先需要有证书和私钥,将其用base64
加密填入。(注意换行符加密导致的没生效)
apiVersion: v1
kind: Secret
metadata:
name: tls-secret.example.com #配置ingress可被引用
namespace: tls
type: kubernetes.io/tls
data:
tls.crt: |
LS0tLS1CRUdVXd3ZGdU5iWApyL3oreVYvQjd1WUNJQjNmMFhx...
tls.key: |
LS0tLS1CRUdVXhfdhdU5iWApyL3oreVYvQjd1WUNJQvdbdwlG...
在ingress中应用证书。
apiVersion: extensions/vlbetal
kind: Ingress
metadata:
name: kubia
spec:
tls:
- hosts:
- kubia.exmaple.com
secretName: tls-secret.example.com #引用对应的证书secret,看上面配置
rules:
- host: kubia.example.com
http:
paths: /
backend:
serviceName: kubia-nodeport
servicePort: 80
排除服务故障
(书中5.7讲到)
如果无法通过服务访问pod, 应该根据下面的列表进行排查:
- 首先, 确保从集群内连接到服务的集群IP,而不是从外部。
- 不要通过ping服务IP 来判断服务是否可 访问(请记住, 服务的集群IP 是虚拟IP, 是无法ping通的)。
- 如果已经定义了就绪探针, 请确保 它返回成功;否则该pod不会成为服务的一部分 。
- 要确认某个容器是服务的一部分, 请使用kubectl ge七 endpoints来检查相应的端点对象。
- 如果尝试通过FQDN或其 中一部 分来访问服务(例如,myservice.mynamespace.svc.cluster.local.myservice.mynamespace), 但并不起作用, 请查看是否可以使用其集群IP而不是FQDN来访问服务 。
- 检查是否连接到服务公开的端口,而不是目标端口 。
- 尝试直接连接到podIP以确认pod正在接收正确端口上的 连接。
- 如果甚至无法通过pod的IP 访问应用, 请确保应用不是仅绑定 到本地主机。
卷
-
emptyDir:用于存储临时数据的简单空目录。
-
hostPath:用于将目录从工作节点的文件系统挂载到pod中。
-
gitRepo:通过检出Git仓库的内容来初始化的卷。
-
nfs:挂载到pod中的NFS共享卷。
-
gcePersistentD sk (Google 高效能型存储磁盘卷)、 awsElasticBlockStore (AmazonWeb 服务弹性块存储卷)、 azureDisk (MicrosoAzure 磁盘卷)一一用于挂载云服务商提供的特定存储类型。
-
cinder、cephfs 、iscsi、flocker、 glusterfs、 quobyte、 rbdflexVolume、 vsphere-Volume 、photoPersistentDisk、 scaleIO 用于挂载其他类型的网络存储。
-
persistentVolumeClaim 一一 种使用预置或者动态配置的持久存储类型
emptyDir
场景:各个pod之间有需要共享的目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6he4ICPN-1651545533501)(.\image\image-20220422123323276.png)]
apiVersion: vl
kind: Pod
metadata:
name: fortune
spec:
containers:
- image: luksa/fortune
name: html-generator
volumeMounts:
- name: html #名为html的卷挂载在容器的/var/htdocs中
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts :
- name: html #与上面相同的卷挂载在/usr/share/nginx/html上,设为只读
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
emptyDir: {}
作为卷来使用的 emptyDir ,是在承载 pod 工作节点的实际磁盘上创建的,因此其性能取决于节点的磁盘类型,但我们可以通知 Kubemete tmfs文件系统存在 (内存而非硬盘)创建 emptyDir。因此,将emptyDir的medium 设置Memory:
volumes:
- name: html
emptyDir:
medium: Memory #emptyDir的文件将会存储在内存中
gitRepo
我们可以使用 Git 仓库来存放网站的静态 HTML 文件,并创建 个包含web服务器容器和 gitRepo 卷的 pod 。每当 pod 建时,它会拉取网站的最新版本并开始托管网站。唯一的缺点是,每次将更改推送到 gitRepo 时,都需要删除 pod才能托管新版本的网站。
感觉不实用,不写了。 哈哈哈
hostPath
hostPath卷指向节点文件系统上的特定文件或目录。在同一个节点上运行并在其hostPath卷中使用相同路径的pod可以看到相同的文件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mlEJy429-1651545533502)(.\image\image-20220422161837958.png)]
卷的内容存储在特定节点的文件系统中, 所以当数据库 pod被重新安排在另 一个节点时, 会找不到数据。 这解释了为什么对常规 pod 使用 hostPath 卷不是一个好主意, 因为这会使 pod对预定规划的节点很敏感。
Name: fluentd-cloud-logging-gke-kubia-defaul七-pool-4ebc2fle-9a3e
Narnespace: kube-system
...
Volumes:
varlog:
Type: HostPath
Path: /var/log
varlibdockercontainers:
Type: HostPath
Path: /var/lib/docker/con七ainers
pv 和pvc
pv
apiVersion: vl
kind: PersistentVolume
metadata:
name: mongodb-pv
spec:
capacity:
storage: 1Gi #定义PersistentVolume的大小
accessModes:
- ReadWriteOnce #可以被单个客户端挂载为只读模式
- ReadOnlyMany #或者被多个客户端挂载为只读模式
persistentVolumeReclaimPolicy: Retain #当声明被释放后,pv将被保留(不清理和删除)
gcePersistentDisk:
pdName: mongodb
fsType: ext4
和集群节点一样,持久卷(pv)不属于任何命名空间,区别于pod和持久卷声明,用kubectl get pv 可看到所有的pv
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h9HMXohZ-1651545533502)(.\image\image-20220422184406433.png)]
pvc
apiVersion: vl
kind: PersistentVolumeClaim
metadata:
name: mongodb-pvc #声明的名称--将声明当作pod的卷使用时需要用到
spec:
resources:
requests:
storage: 1Gi #申请1GiB的存储空间
accessModes:
- ReadWriteOnce #允许单个客户端访问(同时支持读取和写入操作)
storageClassName: ""
#动态配置,存储类,将空字符串指定为存储类名可确保pvc绑定到预先的pv,而不是动态配置新的pv。如果尚未将 storageClassName 属性设置为空字符串, 则尽管已存在适当的预配置待久卷, 但动态卷置备程序仍将配置新的持久卷。
状态:
- RWO:ReadWriteOnce,仅允许单个节点挂载读写。
- ROX:ReadOnlyMany,允许多个节点挂载只读。
- RWX:ReadWriteMany,允许多个节点挂载读写这个卷。
kubectl get pv
看到pv状态已经是Bound,不再是Available,代表已经使用。
pod中使用持久话卷声明(pvc)
apiVersion: v1
kind: Pod
metadata:
name: mongodb
spec:
containers:
- image: mongo
name: mongodb
volumeMounts:
- name: mongodb-data
mountPath: /data/db
ports:
- containerPort: 27017
protocol: TCP
volumes:
- name: mongodb-data
persistentVolumeClam:
claimName: mongodb-pvc #在pod卷中通过名称引用持久卷声明
注意:这时候当我们把pod,pvc删除了,重新再创建pvc时,不会创建成功
$ kubectl get pvc #此时pvc为Pending状态
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
mogodb-pvc Pending 13s
$ kubectl get pv #此时pv为Released状态
NAME CAPACITY ACCESSMODES STATUS CLAIM REASON AGE
rnongodb-pv lGi RWO,ROX Released default/rnongodb-pvc 5m
原因在于之前己经使用过这个卷,所以它可能包含前 个声明人的数据,如果集群管理员还没来得及清理,那么不应该将这个卷绑定到全新的声明中。除此之外,通过使用相同的持久卷,新pod可以读取由前一个pod存放的数据,即使声明和pod 是在不同的命名间中创建的(因此有可能属于不同的集群租户)
手动回收持久卷
通过将 persistentVolumeReclaimPolicy
设置为 Retain
从而通知到Kubemetes 在创建持久卷后将其持久化,让Kubemetes 可以在持久卷从持久卷声明中释放后仍然能保留它的卷和数据内容,据我所知,手动回收持久卷并使其恢可用的唯一方法是删除和新创建持久卷资源 ,当这样操作时,你将决定如何处理底层存储中的文件 可以删除这些文件,也可以闲置不用,以便在下pod中复用它们(注意:pv与pvc的操作不会影响磁盘中的数据)
自动回收持久卷
存在两种其他可行的回收策略 Recycle Delete 第一种删除卷的内容并使卷可用于再次声明,通过这种方式,持久卷可以被不同的持久卷声明和 pod 反复使用。而另一边,Delete 策略删除底层存储。有的(GCE)无法使用Recycle 选项。这种类型的持久卷只支持 Reta Delete 策略,其他类型的持久磁盘可能支持这些选项,也可能不支持这些选项。因此,在创建自己的持久卷之前, 定要检查卷中所用到的特定底层存储支持什么回收策略
提示:可以在现有的持久卷上更改持久卷回收策 比如,如果最初将其设直为Delete 则可以轻松地将其更改为 Reta in ,以防止丢失有价值的数据
StorageClass
- 持久卷的动态卷配置,与持久卷类似, StorageClass 资源并非命名空间。
- Kubernetes 包括最流行的云服务提供商置备程序 provisioner ,所以管理员并不总是需要创建一个置备程序。 但是如果Kubernetes 署在本地,则需要配置定制的置备程序。
apiVersion: storage.k8s.io/vl
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/gce-pd #用于配置持久卷的卷插件
parameters:
type: pd-ssd #传递给parameters的参数
zone: europe-west-b
$ kubectl get sc
直接pvc申请。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongodb-pvc
namespace: ops
spec:
storageClassName: fast #朝上面sc请求
resources:
requests:
storage: 100Mi
accessModes:
- ReadWriteOnce
$ kubectl get sc 命令 -o yaml
#会看到存储类定义会包含一个注释,这会使其成为默认的存储类 如果持久卷声明没有明确指出要使用哪个存储类, 默认存储类会用于动态提供持久卷的内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-snXSeo01-1651545533503)(image\image-20220422201856576.png)]
NFS服务器
后端存储(NFS)—pv—pvc—pod
# 操作节点为NFS服务器
# 安装nfs
yum -y install nfs-utils rpcbind
# 创建nfs目录
mkdir -p /nfs/data/
mkdir -p /nfs/data/k8s
# 授予权限
chmod -R 777 /nfs/data
# 编辑export文件
# vim /etc/exports
/nfs/data *(rw,no_root_squash,sync) # 这里给的是root权限---生产环境不推荐
# 或者/nfs/data 0.0.0.0/0(rw,sync,all_squash) # 所有用户权限被映射成服务端上的普通用户nobody,权限被压缩
# 使得配置生效
exportfs -r
# 查看生效
exportfs
# 启动rpcbind、nfs服务
systemctl start rpcbind && systemctl enable rpcbind #端口是111
systemctl start nfs && systemctl enable nfs # 端口是 2049
# 查看rpc服务的注册情况
rpcinfo -p localhost
# showmount测试
showmount -e ip(ip地址)
NFS配置参数说明:
-
root_squash:
在登入 NFS 主机使用分享之目录的使用者如果是 root 时,那么这个使用者的权限将被压缩成为匿名使用者,通常他的 UID 与 GID 都会变成 nobody 那个系统账号的身份。
-
no_root_squash:
登入 NFS 主机使用分享目录的使用者,如果是 root 的话,那么对于这个分享的目录来说,他就具有 root 的权限!这个项目『极不安全』,不建议使用!
-
all_squash:
登入 NFS 主机使用分享目录的使用者,所有用户均被压缩成为匿名使用者,即以nobody用户的身份登录。
-
anonuid和anongid:
明确指定匿名使用者使用指定的id值用户的权限,访问分享的目录。
-
secure:
限制客户端只能从小于1024的tcp/ip端口连接nfs服务器(默认设置)。
-
insecure:
允许客户端从大于1024的tcp/ip端口连接服务器。
#在K8S集群所有node节点上安装NFS客户端
yum -y install nfs-utils rpcbind
# systemctl start nfs && systemctl enable nfs
pv,pvc关联NFS
#定义PV
apiVersion: v1
kind: PersistentVolume #类型为PV
metadata:
name: nginx-pv #pv的名称
spec:
accessModes: #访问模式
- ReadWriteMany #PV以read-write挂载到多个节点
capacity: #容量
storage: 2Gi #pv可用的大小
nfs:
path: /nfs/data/ #NFS的路径
server: 10.0.0.16 #NFS服务器地址
---
#定义PVC,用于消费PV
apiVersion: v1
kind: PersistentVolumeClaim #类型
metadata:
name: nginx-pvc #PVC的名称
namespace: dev
spec:
accessModes: #访问模式
- ReadWriteMany #PVC以read-write挂载到多个节点
resources:
requests:
storage: 2Gi #PVC允许申请的大小
ConfigMap与Secret
与容器的命令和参数设置相同,环境变量列表无法在pod创建后被修改。
Docker | Kubernetes | 描述 |
---|---|---|
ENTRYPO!NT | command | 容器中运行的可执行文件 |
CMD | args | 传给可执行文件的参数 |
fortune.sh
#!/bin/bash
trap "exit" SIGINT
INTERVAL=$1
echo Configured to generate new fortune every $INTERVAL seconds
mkdir -p /var/htdocs
while
do
echo $(date) Writing fortune to /var/htdocs/index.html
/usr/games/fortune > /var/htdocs/index.html
sleep $INTERVAL
done
FROM ubuntu:latest
RUN apt-get update ; apt-get -y install fortune
ADD fortuneloop.sh /bin/fortuneloop.sh
ENTRYPOINT ["/bin/fortuneloop.sh"] #exec形式的ENTRUPOINT指令
CMD ["10"] #可执行程序的默认参数
$ docker build -t docker.io/luksa/fortune:args .
$ docker push docker.io/luksa/fortune:args
kind: Pod
spec:
containers:
- image: some/image
command: ["/bin/ command" l
args: ["argl", "arg2", "arg3"]
apiVersion: vl
kind: Pod
metadata:
name: fortune2s
spec:
containers:
- image: luksa/fortune:args #fortune:latest替换为fortune:args
args: ["2"] #该参数值使得脚本每隔两秒生成一个新fortune
name: html-generator
volumeMounts:
- name: html
mountPath: /var/htdocs
指定环境变量
#!/bin/bash
trap "exit" SIGINT
echo Configured to generate new fortune every $INTERVAL seconds
mkdir -p /var/htdocs
while :
do
echo $(date) Writing fortune to /var/htdocs/index.html
/usr/games/fortune > /var/htdocs/index.html
sleep $INTERVAL
done
kind: Pod
spec:
containers:
- image: luksa/fortune:env
env:
- name: INTERVAL #在环境中添加一个新变量
value: "30"
name: html-generator
env:
- name: FIRST_VAR
value: "foo"
- name: SECOND_VAR
value: "$(FIEST_VAR)bar" #在环境变量值中引用另一个变量
ConfigMap
本质上就是一个键值对映射,值可以是短字面 ,也可以是完整的配置文件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vT8pLWzU-1651545533503)(.\image\image-20220424193636966.png)]
$ kubectl create configmap fortune-config --from-literal=sleep-interval=25
#通过这条命令创建了个叫作fortune-config的ConfigMap,仅包含单映射条目sleep-interval=25.
$ kubectl create configmap myconfigmap --from-literal=foo=bar --from-literal=bar=baz --from-literal=one=two
#通过添加多个 -- from literal 参数可创建包含多条目的 ConfigMap:
$ kubectl get configmap fortune-config -o yaml
apiVersion: vl
data:
sleep-interval: "25" #映射中的唯一条目
kind: ConfigMap
metadata:
creationTimestamp: 2016-08-11T20 : 31:08Z
name: fortune-config #映射的名称(通过这个名称引用ConfigMap)
namespace: default
resourceVersion: "910025"
selfLink: /api/vl/namespaces/default/configmaps/fortune-config
uid: 88c4167e-6002-lle6-a50d-42010af00237
$ kubectl create configmap my-config --from-file=config-file.conf
#运行上述命令时,kubectl 会在当前目录下查找config-file.conf文件,并将文件内容存储在ConfigMap中以 co nfig-file.conf 为键名的条目下 。当然也可以手动指定键名:
$ kubectl create configmap my-config --from-file=customkey=config-file.conf
$ kubectl create configmap my-config
--from-file=foo.json #单独的文件
--from-file=bar=foobar.conf #自定义键名条目下的文件
--from-file=config-opts/ #完整的文件夹
--from-literal=some=thing #字面量
kubectl create --save-config configmap prometheus-config -n kube-ops --from-file ./prometheus/config -o yaml --dry-run | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: fortune-env-from-configmap
spec:
containers:
- image: luksa/fortune:env
env:
- name: INTERVAL #设置环境变量
valueFrom:
configMapKeyRef: #用configmap初始化,不设定固定值
name: fortune-config #引用的configmap名称
key: sleep-interval #环境变量值被设置为configMap下对应键的值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZquRUtNI-1651545533503)(.\image\image-20220424201655667.png)]
注意:引用不存在的configmap的容器回启动失败,可以标记对 ConfigMap 的引用是可选的(设直 configMapKeyRef.optional: true 这样,即使 ConfigMap 存在,容器也能正常启动。
#pod包含来源于ConfigMap所有条目的环境变量
spec:
containers:
- image: some-image
envFrom: #使用envFrom字段而还不是env字段
- prefix: CONFIG_ #所有环境变量均包含前缀CONFIG_
configMapRef:
name: my-config-map #引用名为my-config-map的ConfigMap
#前缀设置是可选的,若不设直前缀佳,环境变量的名称与 ConfigMap中的键名相同
apiVersion: vl
kind: Pod
metadata:
name: fortune-args-from-configmap
spec:
containers:
- image: luksa/fortune:args
env:
- name: INTERVAL
valueFrom:
configMapKeyRef:
name: fortune-config
key : sleep-interval
args: ["$(INTERVAL)"] #在参数设置中引用环境变量
nginx.conf应用于configmap
$ kubectl create configmap nginx-config --from-file=nginx.conf
$ kubectl get configmap nginx-config -o yaml
apiVersion: vl
data:
my-nginx-config.conf: | #条目中包含了Nginx配置文件的内容
server {
listen 80;
server_name www.kubia-example.com;
gzip on;
gzip_types text/plain application/xml;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
sleep-interval: | #条目 sleep-interval,会作为环境变量传递给容器而不是以卷的方式。
25
kind: ConfigMap
...
在卷中使用ConfigMap的条目
apiVersion: vl
kind: Pod
metadata:
name: fortune-configmap-volume
spec:
containers:
- images: nginx:alpine
name: web-server
volumeMount:
...
- name: config
mountPath: /etc/nginx/config.d #ConfigMap挂在这个位置
readOnly: true
...
volumes:
...
- name: config
configMap:
name: nginx-config #引用创建好的configMap
...
subPath
上述挂载都会将原本的文件覆盖,如何挂载configmap对应的文件,同时不会隐藏现有文件,volumeMount额外的subPath字段可以被用作挂载卷中的某个独立文件或者是文件夹
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cg2KHJn0-1651545533504)(.\image\image-20220430134624515.png)]
spec:
containers:
- image: some/image
volumeMounts:
- name: myvolume
mountPath: /etc/someconfig.conf #挂载至某一文件,而不是文件夹
subPath: myconfig.conf #仅挂载指定的条目myconfig.conf.并非完整的卷
为configMap卷中的文件设置权限
volumes:
- name: config
configMap:
name: nginx-config
defaultMode: "6600" #设置所有文件的权限为-rw-rw------
Secret
作用:给容器传递敏感数据
$ kubectl get secret fortune-https -o yaml
apiVersion: vl
metadata:
name: fortune-https
data:
foo: YmFyCg==;
https.cert: LSOtLSlCRUdJTiBDRVJUSUZJQOFURSOtLSOtCklJSURCekNDQ ...
https.key: LSO七LSlCRUdJTiBSUOEgUFJJVkFURSBLRVktLSOtLQpNSUlFcE ..
kind: Secret
可以使用stringData添加纯文本条目值
kind: Secret
apiVersion: v1
metadata:
name: fortune-https
stringData: #stringData可用来设置非二进制数据
foo: plain text #值并未被base64编码
data:
https.cert: LSOtLSlCRUdJTiBDRVJUSUZJQOFURSOtLSOtCklJSURCekNDQ...
https.key: LSOtLSlCRUdJTiBSUOEgUFJJVkFURSBLRVktLSOtLQpNSUlFcE...
stringData字段是只写的。用kubectl get -o yaml
不会显示stringData字段,stringData所有条目会被base64编码之后展示在data字段中
使用secret挂载pod中
apiVersion: v1
kind: Pod
metadata:
name: fortune-https-web
spec:
containers:
- image: luksa/fortune:env
name: html-generator
env:
- name: INTERVAL
valueFrom:
configMaxKeyRef:
name : fortune-config
key: sleep-interval
volurneMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/ share/nginx/html
readOnly: true
- name: config
mountPath : /etc/nginx/conf.d
readOnly: true
- name: certs #需要将secret卷挂载在此
mountPath: /etc/nginx/certs/
readOnly: true
ports:
- containerPort: 80
- containerPort: 443
volumes:
- name: html
emptyDir: {}
- name: config
configMap:
name: fortune-config
items:
- key: my-nginx-config.conf
path: https.conf
- name: certs #引用对应的secret
secret:
secretName: fortune-https
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5U3RXool-1651545533504)(.\image\image-20220430144305433.png)]
Secret暴露为环境变量
env:
- name: FOO_SECRET
valueFrom:
secretKeyRef: #通过secret设置环境变量
name: fortune-https #secret的名臣
key: foo #secret的键
指定镜像拉去secret的pod定义
apiVersion: vl
kind: Pod
metadata:
name: private-pod
spec:
imagePullSecrets: #能够从私有镜像仓库拉取镜像
- name: mydockerhubsecret
containers:
- image: username/private:tag
name: main
onfig
key: sleep-interval
volurneMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:- name: html
mountPath: /usr/ share/nginx/html
readOnly: true - name: config
mountPath : /etc/nginx/conf.d
readOnly: true - name: certs #需要将secret卷挂载在此
mountPath: /etc/nginx/certs/
readOnly: true
ports: - containerPort: 80
- containerPort: 443
volumes:
- name: html
- name: html
emptyDir: {} - name: config
configMap:
name: fortune-config
items:- key: my-nginx-config.conf
path: https.conf
- key: my-nginx-config.conf
- name: certs #引用对应的secret
secret:
secretName: fortune-https
[外链图片转存中...(img-5U3RXool-1651545533504)]
Secret暴露为环境变量
```yaml
env:
- name: FOO_SECRET
valueFrom:
secretKeyRef: #通过secret设置环境变量
name: fortune-https #secret的名臣
key: foo #secret的键
指定镜像拉去secret的pod定义
apiVersion: vl
kind: Pod
metadata:
name: private-pod
spec:
imagePullSecrets: #能够从私有镜像仓库拉取镜像
- name: mydockerhubsecret
containers:
- image: username/private:tag
name: main