6 Kubernetes-存储
一、configmap
1)应用场景
传统运维的配置中心:批量修改受管机的配置文件:
客户端监听配置文件服务端的config变化,从而实现修改变化
云计算运维:pod通过监听apiversion,从 ETCD 中注入式传输配置文件到 pod
注意:注入与共享
注入: 每次触发,仅传输一次,传输时有磁盘 I/O;无并发压力。
共享: 按需请求,每次请求都有磁盘 I/O;有并发压力
2)ConfigMap的创建
1、使用目录创建
在目录中访问文件。文件内部若需要声明环境变量(格式为: key=value)
文件内部若无需声明环境变量,仅传递值到pod中(格式: value)
文件每行最后没有空格
采用命令创建configmap(避免yaml需要指定的文件过繁)
核心选项: --from-file= <Dir>
# 在目录中创建文件
[root@k8s-master01 ~]# mkdir 7;cd 7
[root@k8s-master01 7]# vim game.file
[root@k8s-master01 7]# cat game.file
version=1.17
name=dave
age=18
[root@k8s-master01 7]# vim ui.properties
[root@k8s-master01 7]# cat ui.properties
level=2
color=yellow
[root@k8s-master01 7]# pwd
/root/7
# 使用目录创建ConfigMap
[root@k8s-master01 7]# kubectl create configmap game-config --from-file=/root/7/
#查看创建configmap
[root@k8s-master01 7]# kubectl get configmap
NAME DATA AGE
game-config 2 11m
查看 configmap 中的信息:(对应指定路径下的文件内容)
2、使用文件创建
仅指定文件创建 ConfigMap 。核心选项: --from-file=<fileName>
[root@k8s-master01 7]# kubectl create configmap ui-config --from-file=/root/7/ui.properties
configmap/ui-config created
[root@k8s-master01 7]# kubectl get cm ui-config
NAME DATA AGE
ui-config 1 9s
[root@k8s-master01 7]# kubectl get cm ui-config -o yaml
apiVersion: v1
data:
ui.properties: |
level=2
color=yellow
kind: ConfigMap
metadata:
creationTimestamp: "2023-02-02T12:45:37Z"
name: ui-config
namespace: default
resourceVersion: "1160730"
selfLink: /api/v1/namespaces/default/configmaps/ui-config
uid: 75e79970-45bc-44e0-8a85-51f780ba974c
[root@k8s-master01 7]# kubectl describe cm ui-config
Name: ui-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
ui.properties:
----
level=2
color=yellow
Events: <none>
3、使用字面值创建
仅指定单独 key 和 value 创建 ConfigMap
3)pod 中使用 configmap
将 configmap 的环境变量应用到 pod 中
1、使用 ConfigMap 来代替环境变量
情况1:envFrom 选项。将指定的 ConfigMap 的环境变量直接应用到 pod 中
情况2:env 选项。更改变量的 key,仍用 ConfigMap 中定义的环境变量的值
# 1.configmap.yaml 文件详解
apiVersion: v1 #使用 核心组v1版
kind: ConfigMap #资源对象为 configmap
metadata: #定义资源对象中的元数据信息
name: literal-config #定义资源对象的名称为: literal-config
namespace: default #定义资源对象所在名字空间为:default,若不指定,默认也在default中
data: #定义资源对象中的存储信息
name: dave #key=name;value=dave
password: pass #key=password;value=pass
# 2.configmap.yaml 文件详解
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO #key=log_level;value=INFO
Ⅰ、创建两个 configmap
[root@k8s-master01 7]# kubectl delete cm --all
[root@k8s-master01 7]# vim 1.configmap.yaml
[root@k8s-master01 7]# cat 1.configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: literal-config
namespace: default
data:
name: dave
password: pass
[root@k8s-master01 7]# kubectl apply -f 1.configmap.yaml
configmap/literal-config created
[root@k8s-master01 7]# vim 2.configmap.yaml
[root@k8s-master01 7]# cat 2.configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
[root@k8s-master01 7]# kubectl apply -f 2.configmap.yaml
configmap/env-config created
[root@k8s-master01 7]# kubectl get cm
NAME DATA AGE
env-config 1 3s
literal-config 2 24s
# 3.cm-pod.yaml 文件详解
apiVersion: v1 #使用api版本为 core/v1
kind: Pod #指定创建的资源对象为 pod
metadata: #定义资源对象的元数据信息
name: cm-env-test-pod #定义pod的名称为 cm-env-test-pod
spec: #定义pod的期望
containers: #指定容器的期望
- name: test-container #定义容器名
image: wangyanglinux/myapp:v1 #定义容器创建使用的镜像
command: [ "/bin/sh", "-c", "env" ] #定义容器启动的命令,启动时执行命令: env
env: #定义容器中的env环境变量(能更改key)
- name: USERNAME #一个的key为 USERNAME
valueFrom: #一个value的来源
configMapKeyRef: #来源于configmap的其中的key的定义
name: literal-config #来源configmpa的名称
key: name #来源configmap的key
- name: PASSWORD #另一个的key为 PASSWORD
valueFrom: #另一个value的来源
configMapKeyRef: #来源于configmap的其中的key的定义
name: literal-config #来源configmap的名称
key: password #来源configmap的key
envFrom: #定义容器中env环境变量(直接使用configmap中的定义)
- configMapRef: #来源于configmap定义
name: env-config #来源configmap的名称
restartPolicy: Never
Ⅱ、使用 configmap 代替 pod中的环境变量
[root@k8s-master01 7]# vim 3.cm-pod.yaml
[root@k8s-master01 7]# cat 3.cm-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: cm-env-test-pod
spec:
containers:
- name: test-container
image: wangyanglinux/myapp:v1
command: [ "/bin/sh", "-c", "env" ]
env:
- name: USERNAME
valueFrom:
configMapKeyRef:
name: literal-config
key: name
- name: PASSWORD
valueFrom:
configMapKeyRef:
name: literal-config
key: password
envFrom:
- configMapRef:
name: env-config
restartPolicy: Never
[root@k8s-master01 7]# kubectl apply -f 3.cm-pod.yaml
Ⅲ、查看pod中的环境变量定义成功
[root@k8s-master01 7]# kubectl get cm,pod
NAME DATA AGE
configmap/env-config 1 2m2s
configmap/literal-config 2 2m2s
NAME READY STATUS RESTARTS AGE
pod/cm-env-test-pod 0/1 Completed 0 2m2s
# 容器中成功定义环境变量,来源于configmap
[root@k8s-master01 7]# kubectl logs cm-env-test-pod |egrep "USERNAME|PASSWORD|log_level"
USERNAME=dave
log_level=INFO
PASSWORD=pass
2、用 ConfigMap 设置命令行参数
环境变量可以当成启动命令被调用
# 4.cm-pod.yaml 文件详解
apiVersion: v1
kind: Pod
metadata:
name: cm-command-dapi-test-pod
spec:
containers:
- name: test-container
image: wangyanglinux/myapp:v1
command: [ "/bin/sh", "-c", "echo $(USERNAME) $(PASSWORD)" ] #定义启动命令为 输出环境变量
env: #定义容器中的环境变量(更改key)
- name: USERNAME #定义的key
valueFrom: #值来源
configMapKeyRef: #来源configmap
name: literal-config #configmap名称
key: name #configmap的key
- name: PASSWORD
valueFrom:
configMapKeyRef:
name: literal-config
key: password
restartPolicy: Never #定义pod重启策略:无论成功失败都不重启
Ⅰ、根据4.cm-pod.yaml 创建pod
[root@k8s-master01 7]# vim 4.cm-pod.yaml
[root@k8s-master01 7]# cat 4.cm-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: cm-command-dapi-test-pod
spec:
containers:
- name: test-container
image: wangyanglinux/myapp:v1
command: [ "/bin/sh", "-c", "echo $(USERNAME) $(PASSWORD)" ]
env:
- name: USERNAME
valueFrom:
configMapKeyRef:
name: literal-config
key: name
- name: PASSWORD
valueFrom:
configMapKeyRef:
name: literal-config
key: password
restartPolicy: Never
[root@k8s-master01 7]# kubectl apply -f 4.cm-pod.yaml
Ⅱ、命令调用环境变量成功
3、通过数据卷插件使用 ConfigMap
volume + volumeMounts 将文件填入数据卷,在这个文件中 key 为文件名,value 为文件内容
在 pod 的容器中实现挂载
# 5.cm-volume-pod.yaml 文件详解
apiVersion: v1
kind: Pod
metadata:
name: cm-volume-test-pod
spec:
containers:
- name: test-container
image: wangyanglinux/myapp:v1
volumeMounts: # pod期望中,容器中使用数据卷插件挂载
- name: config-volume # 数据卷名为 config-volume
mountPath: /etc/config # 挂载到容器中位置 /etc/config
volumes: # pod期望中,定义数据卷
- name: config-volume # 数据卷名 config-volume
configMap: # 使用configmap
name: literal-config # configmap的名称
restartPolicy: Never # 重启策略:无论成功与否,都不重启
Ⅰ、依据 5.cm-volume-pod.yaml 创建pod
[root@k8s-master01 7]# vim 5.cm-volume-pod.yaml
[root@k8s-master01 7]# cat 5.cm-volume-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: cm-volume-test-pod
spec:
containers:
- name: test-container
image: wangyanglinux/myapp:v1
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: literal-config
restartPolicy: Never
[root@k8s-master01 7]# kubectl apply -f 5.cm-volume-pod.yaml
Ⅱ、进入 pod 的容器,检查挂载
[root@k8s-master01 7]# kubectl exec -it cm-volume-test-pod -- /bin/sh
/ # ls /etc/config
name password
/ # ls -l /etc/config
total 0
lrwxrwxrwx 1 root root 11 Feb 2 15:06 name -> ..data/name
lrwxrwxrwx 1 root root 15 Feb 2 15:06 password -> ..data/password
/ # cat /etc/config/name
dave/ #
/ # cat /etc/config/password
pass/ #
4)ConfigMap 热更新
pod 无需挂掉,即可实现更新(通过数据卷插件使用 ConfigMap 实现)
Ⅰ、使用 default.conf 文件创建 configmap
[root@k8s-master01 7]# vim default.conf
[root@k8s-master01 7]#
[root@k8s-master01 7]# cat default.conf
server {
listen 80 default_server;
server_name example.com www.example.com;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
[root@k8s-master01 7]# kubectl create configmap default-nginx --from-file=default.conf --dry-run -o yaml > 6.configmap.yaml
[root@k8s-master01 7]# cat 6.configmap.yaml
apiVersion: v1
data:
default.conf: |
server {
listen 80 default_server;
server_name example.com www.example.com;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
kind: ConfigMap
metadata:
creationTimestamp: null
name: default-nginx
[root@k8s-master01 7]# kubectl apply -f 6.configmap.yaml
configmap/default-nginx created
Ⅱ、创建 deployment 控制器
定义副本模板,通过数据卷插件实现将 ConfigMap 存储在pod中挂载
[root@k8s-master01 7]# vim 7.deployment.yaml
[root@k8s-master01 7]# cat 7.deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-test
name: nginx-test
spec:
replicas: 4
selector:
matchLabels:
app: nginx-test
template:
metadata:
labels:
app: nginx-test
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d/
volumes:
- name: config-volume
configMap:
name: default-nginx
[root@k8s-master01 7]# kubectl apply -f 7.deployment.yaml
deployment.apps/nginx-test created
测试访问nginx:
进入pod中的容器查看挂载:
[root@k8s-master01 7]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-test-65cd59dccb-7kj9k 1/1 Running 0 50s
nginx-test-65cd59dccb-mttkf 1/1 Running 0 50s
nginx-test-65cd59dccb-trvnn 1/1 Running 0 50s
nginx-test-65cd59dccb-wvbbz 1/1 Running 0 50s
[root@k8s-master01 7]# kubectl exec -it nginx-test-65cd59dccb-7kj9k -- /bin/sh
# cat /etc/nginx/conf.d/default.conf
server {
listen 80 default_server;
server_name example.com www.example.com;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
#
Ⅲ、修改 ConfigMap
$ kubectl edit configmap default-nginx
# 此处也可以通过 yaml 文件进行修改
[root@k8s-master01 7]# cp -a 6.configmap.yaml 8.configmap.yaml
[root@k8s-master01 7]# vim 8.configmap.yaml
[root@k8s-master01 7]# cat 6.configmap.yaml |grep 80
listen 80 default_server;
[root@k8s-master01 7]# cat 8.configmap.yaml |grep 80
listen 8080 default_server;
[root@k8s-master01 7]# kubectl apply -f 8.configmap.yaml
configmap/default-nginx configured
等待一段时间后(大约十几秒)进入pod中的容器查看挂载:
# cat /etc/nginx/conf.d/default.conf
server {
listen 8080 default_server;
server_name example.com www.example.com;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
Ⅳ、ConfigMap 更新后滚动更新 pod
由于仅修改了配置文件,而未触发nginx的重启。configmap 更新后,还需要滚动更新pod
打补丁。核心选项:.spec.template.metadata.annotations 中的 version/config
每次通过修改 version/config 来触发滚动更新
1、查看默认情况下控制器信息:
2、打补丁:
kubectl patch deployment nginx-test --patch '{"spec": {"template": {"metadata": {"annotations": {"version/config": "20190411" }}}}}'
3、再次查看控制器信息:
4、打补丁之前到打补丁之后,实现了滚动更新
5、测试访问
[root@k8s-master01 7]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-test-6ddcdb857d-45mrl 1/1 Running 0 17m 172.100.2.164 k8s-node02 <none> <none>
nginx-test-6ddcdb857d-pcj5d 1/1 Running 0 17m 172.100.1.144 k8s-node01 <none> <none>
nginx-test-6ddcdb857d-pvrgb 1/1 Running 0 17m 172.100.1.143 k8s-node01 <none> <none>
nginx-test-6ddcdb857d-xwsgp 1/1 Running 0 17m 172.100.2.165 k8s-node02 <none> <none>
[root@k8s-master01 7]# curl 172.100.2.164
curl: (7) Failed connect to 172.100.2.164:80; 拒绝连接
[root@k8s-master01 7]# curl 172.100.2.164:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
拓展:K8S 中的镜像下载策略
默认情况下:imagePullPolicy: Always
Always:若指定的镜像为 latest 版,则每次构建容器都会进行镜像下载(无论本地有无此镜像)(
Never:若指定的镜像,本地没有 latest 版,则不使用
IfNotPresent:若指定的镜像,本地没有 latest 版,则进行下载;本地有 latest 版,则不进行下载。
总结:镜像的版本号,尽量不要用 latest 定义版本
二、secret
为解决配置文件中存在敏感信息的问题(加密)
三种类型:
-
Service Account: 用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod 的
/run/secrets/kubernetes.io/serviceaccount目录中 -
Opaque Secret: base64编码格式的 Secret ,以此存储密码、密钥等
拓展:base64编码加密、解密
- Kubernetes.io/dockerconfigjson:用于存储私有仓库信息
类型详解和实验:
1)Service Account
Service Account 用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod的 /run/secrets/kubernetes.io/serviceaccount 目录中
$ kubectl run nginx --image nginx
deployment "nginx" created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-3137573019-md1u2 1/1 Running 0 13s
$ kubectl exec nginx-3137573019-md1u2 ls /run/secrets/kubernetes.io/serviceaccount
ca.crt
namespace
token
2)Opaque Secret
Ⅰ、创建 Secret 对象
注意:key 为明文,value 必须为加密密文
#生成加密信息
[root@k8s-master01 7]# pwd
/root/7
[root@k8s-master01 7]# mkdir 2;cd 2
[root@k8s-master01 2]# echo -n "admin" | base64
YWRtaW4=
[root@k8s-master01 2]# echo -n "123456" | base64
MTIzNDU2
根据 1.secret.yaml 创建secret
# 1.secret.yaml 文件详解
apiVersion: v1 #使用api版本 core/v1
kind: Secret #指定创建的资源对象为 Secret
metadata: #元数据信息
name: mysecret #创建的secret名称为 mysecret
type: Opaque #创建的类型为 Opaque
data: #指定信息
password: MTIzNDU2
username: YWRtaW4=
[root@k8s-master01 2]# kubectl delete deployment --all
[root@k8s-master01 2]# vim 1.secret.yaml
[root@k8s-master01 2]# cat 1.secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: MTIzNDU2
username: YWRtaW4=
[root@k8s-master01 2]# kubectl apply -f 1.secret.yaml
secret/mysecret created
查看创建的 secret
[root@k8s-master01 2]# kubectl get secret mysecret
NAME TYPE DATA AGE
mysecret Opaque 2 2m42s
[root@k8s-master01 2]# kubectl describe secret mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations:
Type: Opaque
Data
====
password: 6 bytes
username: 5 bytes
[root@k8s-master01 2]# kubectl get secret mysecret -o yaml
apiVersion: v1
data:
password: MTIzNDU2
username: YWRtaW4=
kind: Secret
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","data":{"password":"MTIzNDU2","username":"YWRtaW4="},"kind":"Secret","metadata":{"annotations":{},"name":"mysecret","namespace":"default"},"type":"Opaque"}
creationTimestamp: "2023-02-03T01:33:18Z"
name: mysecret
namespace: default
resourceVersion: "1182319"
selfLink: /api/v1/namespaces/default/secrets/mysecret
uid: a5f2344d-9bb5-42f0-ad59-a479fbf1590c
type: Opaque
[root@k8s-master01 2]# echo -n "MTIzNDU2" | base64 -d
123456[root@k8s-master01 2]#
[root@k8s-master01 2]# echo -n "YWRtaW4=" | base64 -d
admin[root@k8s-master01 2]#
Ⅱ、使用 Secret 方式
1、Secret 挂载到 volume中(数据卷实现)
volume+volumeMounts 基于 secret 挂载,会自动解码,且不可关闭(value必须为加密)
创建 pod ,将secret 挂载到 volume 中
[root@k8s-master01 2]# vim 2.pod.yaml
[root@k8s-master01 2]# cat 2.pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
name: secret-test
name: secret-test
spec:
volumes:
- name: volumes12
secret:
secretName: mysecret
containers:
- image: wangyanglinux/myapp:v1
name: db
volumeMounts:
- name: volumes12
mountPath: "/data"
[root@k8s-master01 2]# kubectl apply -f 2.pod.yaml
进入 pod 检查挂载
[root@k8s-master01 2]# kubectl get pod
NAME READY STATUS RESTARTS AGE
secret-test 1/1 Running 0 12s
[root@k8s-master01 2]# kubectl exec -it secret-test -- /bin/sh
/ # cd /data
/data # ls
password username
/data # cat password
123456/data #
/data # cat username
2、Secret 导出到 pod 的环境变量中
env 中的 valueFrom 实现
创建pod,将secret导出到pod的环境变量中
[root@k8s-master01 2]# vim 3.pod.yaml
[root@k8s-master01 2]# cat 3.pod.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: pod-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: pod-deployment
spec:
containers:
- name: pod-1
image: wangyanglinux/myapp:v1
ports:
- containerPort: 80
env:
- name: TEST_USER
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: TEST_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
[root@k8s-master01 2]# kubectl apply -f 3.pod.yaml
进入pod的容器中查看环境变量
[root@k8s-master01 2]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod-deployment-747f78bc67-k2mvf 1/1 Running 0 20s
pod-deployment-747f78bc67-vhb9n 1/1 Running 0 20s
secret-test 1/1 Running 0 5m18s
[root@k8s-master01 2]# kubectl exec -it pod-deployment-747f78bc67-k2mvf -- /bin/sh
/ # env |egrep "TEST_USER|TEST_PASSWORD"
TEST_PASSWORD=123456
TEST_USER=admin
3)dockerconfigjson
封装仓库认证信息,在下载私有仓库中的镜像时,自动认证
Ⅰ、准备新的虚拟机安装私有仓库---harbor
前提准备:
配置harbor网络,仅留一张网卡,加入ikuai路由
ikuai地址为 192.168.20.199
[root@localhost network-scripts]# vim ifcfg-ens33
[root@localhost network-scripts]# tail -n 5 ifcfg-ens33
IPADDR=192.168.20.206
PREFIX=24
GATEWAY=192.168.20.199
DNS1=114.114.114.114
DNS2=8.8.8.8
[root@localhost network-scripts]# vim ifcfg-ens34
[root@localhost network-scripts]# cat ifcfg-ens34|grep ONBOOT
ONBOOT=no
[root@localhost network-scripts]# systemctl restart network
[root@localhost network-scripts]# ping www.baidu.com
PING www.a.shifen.com (110.242.68.4) 56(84) bytes of data.
64 bytes from 110.242.68.4 (110.242.68.4): icmp_seq=1 ttl=127 time=11.2 ms
^C
--- www.a.shifen.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 11.253/11.253/11.253/0.000 ms
# 设置主机名
$ hostnamectl set-hostname harbor.yq.com
$ reboot
每个节点的docker配置文件中,有信任的私有仓库信息字段
# master01节点中
[root@k8s-master01 ~]# cat /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"insecure-registries": ["harbor.yq.com"],
"registry-mirrors": ["https://kfp63jaj.mirror.aliyuncs.com"]
}
# node01节点中
[root@k8s-node01 ~]# cat /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"insecure-registries": ["harbor.yq.com"],
"registry-mirrors": ["https://kfp63jaj.mirror.aliyuncs.com"]
}
# node02节点中
[root@k8s-node02 ~]# cat /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"insecure-registries": ["harbor.yq.com"],
"registry-mirrors": ["https://kfp63jaj.mirror.aliyuncs.com"]
}
检查每个节点的hosts解析
[root@k8s-master01 ~]# vim /etc/hosts
[root@k8s-master01 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.20.201 k8s-master01 m1
192.168.20.202 k8s-node01 n1
192.168.20.203 k8s-node02 n2
192.168.20.206 harbor.yq.com harbor
[root@k8s-master01 ~]# scp /etc/hosts root@n1:/etc/
[root@k8s-master01 ~]# scp /etc/hosts root@n2:/etc/
[root@k8s-master01 ~]# scp /etc/hosts root@harbor:/etc/
每个节点访问测试
1、上传所需文件到harbor
2、本地安装docker
[root@harbor ~]# ls
anaconda-ks.cfg docker-compose
docker-ce-17.03.0.ce-1.el7.centos.x86_64.rpm harbor-offline-installer-v1.2.0.tgz
docker-ce-selinux-17.03.0.ce-1.el7.centos.noarch.rpm harbor.zip
[root@harbor ~]#
[root@harbor ~]#
[root@harbor ~]# yum -y install docker-c*
3、配置docker
拓展:br_netfilter 内核模块
让经过网桥的流量必须经过防火墙处理(加上此模块节点不用重启,即可让docker运行)
[root@harbor ~]# modprobe br_netfilter # 开启br_netfilter模块
[root@harbor ~]# mkdir /etc/docker # 从n1节点配置docker配置文件
[root@harbor ~]# scp root@n1:/etc/docker/daemon.json /etc/docker/
[root@harbor ~]# systemctl enable docker --now #运行docker
4、安装harbor
# 配置docker-compose命令
[root@harbor ~]# mv docker-compose /usr/local/bin/
[root@harbor ~]# chmod a+x /usr/local/bin/docker-compose
# 修改harbor配置文件(主机名、https协议)
[root@harbor ~]# tar -xf harbor-offline-installer-v1.2.0.tgz
[root@harbor ~]# mv harbor /usr/local/ ; cd /usr/local/harbor
[root@harbor harbor]# pwd
/usr/local/harbor
[root@harbor harbor]# vim harbor.cfg
[root@harbor harbor]# cat harbor.cfg |egrep "^hostname|ui_url_protocol"
hostname = harbor.yq.com
ui_url_protocol = https
# 根据harbor配置文件,在指定的证书位置创建证书
[root@harbor harbor]# mkdir -p /data/cert
[root@harbor harbor]# cd !$
cd /data/cert
# 创建证书
[root@harbor cert]# openssl genrsa -des3 -out server.key 2048
[root@harbor cert]# openssl req -new -key server.key -out server.csr
[root@harbor cert]# cp -a server.key server.key.org
[root@harbor cert]# openssl rsa -in server.key.org -out server.key
[root@harbor cert]# openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
# 安装harbor
[root@harbor cert]# cd -
/usr/local/harbor
[root@harbor harbor]# ./install.sh
6、检查windows的hosts解析,浏览器访问
7、harbor创建私有仓库
docker tag SOURCE_IMAGE[:TAG] harbor.yq.com/dev/IMAGE[:TAG]
docker push harbor.yq.com/dev/IMAGE[:TAG]
8、在harbor中导入镜像到私有仓库
# 从官方下载镜像到本地
[root@harbor harbor]# docker pull wangyanglinux/myapp:v6
# 重新标记镜像
[root@harbor harbor]# docker tag wangyanglinux/myapp:v6 harbor.yq.com/dev/myapp:v6
# 登录私有仓库,并上传镜像
[root@harbor harbor]# docker login harbor.yq.com
Username: admin
Password:
Login Succeeded
[root@harbor harbor]# docker push harbor.yq.com/dev/myapp:v6
harbor中存在私有仓库的镜像
9、未加入认证信息的选项使用私有仓库的镜像
[root@k8s-master01 2]# ls
1.secret.yaml 2.pod.yaml 3.pod.yaml
[root@k8s-master01 2]# pwd
/root/7/2
[root@k8s-master01 2]# cp -a 3.pod.yaml 4.pod.yaml
[root@k8s-master01 2]# vim 4.pod.yaml
[root@k8s-master01 2]# cat 4.pod.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: dockerconfigjson
spec:
replicas: 2
template:
metadata:
labels:
app: pod-deployment
spec:
containers:
- name: pod-1
image: harbor.yq.com/dev/myapp:v6
ports:
- containerPort: 80
env:
- name: TEST_USER
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: TEST_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
# 清理
[root@k8s-master01 2]# kubectl delete deployment --all
[root@k8s-master01 2]# kubectl delete pod --all
# 创建pod发现镜像下载失败。因为没有认证信息
[root@k8s-master01 2]# kubectl apply -f 4.pod.yaml
deployment.extensions/dockerconfigjson created
[root@k8s-master01 2]# kubectl get pod
NAME READY STATUS RESTARTS AGE
dockerconfigjson-755598986f-bt5cn 0/1 ImagePullBackOff 0 17s
dockerconfigjson-755598986f-zb5fq 0/1 ImagePullBackOff 0 17s
Ⅱ、创建dockerconfigjson
命令模板:
kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
$ kubectl create secret docker-registry myregistrykey --docker-server=harbor.yq.com --docker-username=admin --docker-password=Harbor12345 --docker-email=yq@qq.com
Ⅲ、创建控制器
实现:根据认证信息的认证,从私有仓库下载镜像
加入认证信息的选项使用私有仓库的镜像
[root@k8s-master01 2]# vim 5.pod.yaml
[root@k8s-master01 2]# cat 5.pod.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: dockerconfigjson-1
spec:
replicas: 2
template:
metadata:
labels:
app: pod-deployment
spec:
imagePullSecrets:
- name: myregistrykey
containers:
- name: pod-1
image: harbor.yq.com/dev/myapp:v6
ports:
- containerPort: 80
env:
- name: TEST_USER
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: TEST_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
[root@k8s-master01 2]# kubectl apply -f 5.pod.yaml
[root@k8s-master01 2]# kubectl get pod
NAME READY STATUS RESTARTS AGE
dockerconfigjson-1-67476858d7-ctttj 1/1 Running 0 5s
dockerconfigjson-1-67476858d7-n22tz 1/1 Running 0 5s
注意:在使用 imagePullSecrets 时可以使用多个认证信息的 dockerconfigjson
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
- name: foo
image: hub.hongfu.com/wangyang/myapp:v1
imagePullSecrets:
- name: myregistrykey
- name: yqregistrykey
- name: xxhfregistrykey
三、volume
拓展:mfs 对接到 K8S 集群
mfs 挂载到 K8S 集群中,利用 hostpath 的方式
1)卷的类型
Kubernetes 支持以下类型的卷:
awsElasticBlockStoreazureDiskazureFilecephfscsidownwardAPIemptyDirfcflockergcePersistentDiskgitRepoglusterfshostPathiscsilocalnfspersistentVolumeClaimprojectedportworxVolumequobyterbdscaleIOsecretstorageosvsphereVolume
2)emptyDir
临时卷
生命周期==pod生命周期
应用场景:a.容器间的共享存储
b.恢复点,暂存空间
实验:实现暂存空间
核心部分:
Ⅰ、创建
[root@k8s-master01 2]# vim 6.job.yaml
[root@k8s-master01 2]# cat 6.job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: jobs-empty
spec:
template:
spec:
restartPolicy: Never
initContainers:
- name: job-1
image: busybox:1.34.1
command:
- 'sh'
- '-c'
- >
for i in 1 2 3;
do
echo "job-1 `date`";
sleep 1s;
done;
echo job-1 GG > /srv/input/code
volumeMounts:
- mountPath: /srv/input/
name: input
- name: job-2
image: busybox:1.34.1
command:
- 'sh'
- '-c'
- >
for i in 1 2 3;
do
echo "job-2 `date`";
sleep 1s;
done;
cat /srv/input/code &&
echo job-2 GG > /srv/input/output/file
volumeMounts:
- mountPath: /srv/input/
name: input
- mountPath: /srv/input/output/
name: output
containers:
- name: job-3
image: busybox:1.34.1
command:
- 'sh'
- '-c'
- >
echo "job-1 and job-2 completed";
sleep 3s;
cat /srv/output/file
volumeMounts:
- mountPath: /srv/output/
name: output
volumes:
- name: input
emptyDir: {}
- name: output
emptyDir: {}
[root@k8s-master01 2]# kubectl apply -f 6.job.yaml
Ⅱ、验证
[root@k8s-master01 2]# kubectl get pod
NAME READY STATUS RESTARTS AGE
dockerconfigjson-1-67476858d7-ctttj 1/1 Running 0 10m
dockerconfigjson-1-67476858d7-n22tz 1/1 Running 0 10m
dockerconfigjson-755598986f-5q5bb 1/1 Running 0 9m51s
dockerconfigjson-755598986f-m4jb6 1/1 Running 0 9m51s
jobs-empty-tgv7v 0/1 Completed 0 55s
[root@k8s-master01 2]# kubectl logs jobs-empty-tgv7v -c job-1
job-1 Fri Feb 3 03:49:24 UTC 2023
job-1 Fri Feb 3 03:49:25 UTC 2023
job-1 Fri Feb 3 03:49:26 UTC 2023
[root@k8s-master01 2]# kubectl logs jobs-empty-tgv7v -c job-2
job-2 Fri Feb 3 03:49:28 UTC 2023
job-2 Fri Feb 3 03:49:29 UTC 2023
job-2 Fri Feb 3 03:49:30 UTC 2023
job-1 GG
[root@k8s-master01 2]# kubectl logs jobs-empty-tgv7v -c job-3
job-1 and job-2 completed
job-2 GG
3)hostpath
主机中的路径,挂载到集群中
hostpath 的用途:
- 运行的容器,需要访问 docker 中其他的容器。使用
/var/lib/docker的hostpath - 在容器中运行 cAdvisor(猫头鹰)监控。
/dev/cgroup的hostpath - 存在的 hostpath,创建 pod时,是否在运行pod之前运行hostpath,是否应该创建,创建的 hostpath 形式
除了所需的 path 属性之外,用户还可以为 hostPath 卷指定 type
| 值 | 行为 |
|---|---|
| 空字符串(默认)用于向后兼容,这意味着在挂载 hostPath 卷之前不会执行任何检查。 | |
DirectoryOrCreate |
如果在给定的路径上没有任何东西存在,那么将根据需要在那里创建一个空目录,权限设置为 0755,与 Kubelet 具有相同的组和所有权。 |
Directory |
给定的路径下必须存在目录 |
FileOrCreate |
如果在给定的路径上没有任何东西存在,那么会根据需要创建一个空文件,权限设置为 0644,与 Kubelet 具有相同的组和所有权。 |
File |
给定的路径下必须存在文件 |
Socket |
给定的路径下必须存在 UNIX 套接字 |
CharDevice |
给定的路径下必须存在字符设备 |
BlockDevice |
给定的路径下必须存在块设备 |
注意:
a、hostpath 声明的节点主机路径,若在每个节点中路径下内容不同,即使其他配置相同,也可能会导致 pod 的行为不同
b、若 Kubernetes 按照计划,添加资源感知调度时,将无法考虑 hostpath 使用的资源(挂载的位置控制无法判断)
c、确认主机路径的权限,能否被容器所调用
实验:使用hostpath挂载
[root@k8s-master01 2]# vim 7.pod.yaml
[root@k8s-master01 2]# cat 7.pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: wangyanglinux/myapp:v1
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /data
type: DirectoryOrCreate
[root@k8s-master01 2]# kubectl apply -f 7.pod.yaml
pod/test-pd configured
[root@k8s-master01 2]# kubectl get pod
NAME READY STATUS RESTARTS AGE
dockerconfigjson-1-67476858d7-ctttj 1/1 Running 0 21m
dockerconfigjson-1-67476858d7-n22tz 1/1 Running 0 21m
dockerconfigjson-755598986f-5q5bb 1/1 Running 0 20m
dockerconfigjson-755598986f-m4jb6 1/1 Running 0 20m
jobs-empty-tgv7v 0/1 Completed 0 11m
test-pd
四、PersistentVolume(PV)
1)概念
1、PersistentVolume (PV):由管理员设置的存储
2、PersistentVolumeClain (PVC):用户存储的请求
3、PV 分类:
静态pv:存储工程师提前创建好了 PV ,业务工程师后期创建 PVC直接进行绑定
动态pv:由云供应商提供,云供应商的对象存储,根据业务工程师创建PVC的需求创建PV
4、对象与过程
面对对象:更偏向模块的使用
面对过程:更偏向最底层开始,进行使用
5、PVC 与 PV 进行绑定
- 容量
- 读写策略( PV 访问模式)(一 一匹配)(并非所有存储服务都有这三个,对应后面的 PVC指出的插件类型)
- 单节点读写---ReadWriteOnce---RWO
- 多节点读写---ReadWriteMany---RWX
- 多节点只读---ReadOnlyMany---ROX
- 类(一 一匹配)
- 回收策略
- 保留---Retain---手动回收
- 回收---Recycle---基本擦除(
rm -rf /thevolume/*) - 删除---Delete---关联的存储资产将被删除
6、PVC 支持的插件类型
| Volume 插件 | ReadWriteOnce | ReadOnlyMany | ReadWriteMany |
|---|---|---|---|
| AWSElasticBlockStoreAWSElasticBlockStore | ✓ | - | - |
| AzureFile | ✓ | ✓ | ✓ |
| AzureDisk | ✓ | - | - |
| CephFS | ✓ | ✓ | ✓ |
| Cinder | ✓ | - | - |
| FC | ✓ | ✓ | - |
| FlexVolume | ✓ | ✓ | - |
| Flocker | ✓ | - | - |
| GCEPersistentDisk | ✓ | ✓ | - |
| Glusterfs | ✓ | ✓ | ✓ |
| HostPath | ✓ | - | - |
| iSCSI | ✓ | ✓ | - |
| PhotonPersistentDisk | ✓ | - | - |
| Quobyte | ✓ | ✓ | ✓ |
| NFS | ✓ | ✓ | ✓ |
| RBD | ✓ | ✓ | - |
| VsphereVolume | ✓ | - | - (当 pod 并列时有效) |
| PortworxVolume | ✓ | - | ✓ |
| ScaleIO | ✓ | ✓ | - |
| StorageOS | ✓ | - | - |
7、状态
-
卷可以处于以下的某种状态:
-
Available(可用)——一块空闲资源还没有被任何声明绑定
-
Bound(已绑定)——卷已经被声明绑定
-
Released(已释放)——声明被删除,但是资源还未被集群重新声明(不能被别的 PVC 绑定,需要修复)
-
Failed(失败)——该卷的自动回收失败
命令行会显示绑定到 PV 的 PVC 的名称
8、持久化卷声明的保护(PVC保护)
若pod存储在,PVC 无法删除
2)实验
1、在 harbor 中部署 NFS
NFS 工作原理: rpc服务端启动
nfs服务端启动,并向rpc服务端注册端口信息
nfs客户端启动rpc,向rpc服务端获取nfs信息
nfs客户端获取nfs信息后,建立连接
/etc/exports 中的 sync:同步共享
async:异步共享
# 安装软件包
[root@harbor ~]# yum -y install nfs-common nfs-utils rpcbind
# 配置存储位置、文件
[root@harbor ~]# mkdir /nfsdata
[root@harbor nfsdata]# for i in {1..10};do mkdir $i;echo "yangqin---$i"> $i/index.html ; done
[root@harbor nfsdata]# for i in {1..10};do cat $i/index.html;done
yangqin---1
yangqin---2
yangqin---3
yangqin---4
yangqin---5
yangqin---6
yangqin---7
yangqin---8
yangqin---9
yangqin---10
# 设置权限相关、启动服务
# 此处一般为666,为了避免K8S集群中反复调整权限,所以给777(生产环境中需要严格设置权限)
[root@harbor nfsdata]# chmod -R 777 /nfsdata/
[root@harbor nfsdata]# chown -R nfsnobody /nfsdata/
[root@harbor nfsdata]# vim /etc/exports
[root@harbor nfsdata]# cat /etc/exports
/nfsdata/1 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/2 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/3 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/4 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/5 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/6 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/7 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/8 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/9 *(rw,no_root_squash,no_all_squash,sync)
/nfsdata/10 *(rw,no_root_squash,no_all_squash,sync)
# 重启服务
[root@harbor nfsdata]# systemctl restart nfs rpcbind
# 在每一个节点中都安装nfs的客户端
$ yum -y install nfs-common nfs-utils rpcbind
2、节点测试 NFS 挂载
[root@k8s-master01 ~]# mkdir /test
[root@k8s-master01 ~]# mount -t nfs 192.168.20.206:/nfsdata/1/ /test/
[root@k8s-master01 ~]# cd /test/;ls
index.html
[root@k8s-master01 test]# cat index.html
yangqin---1
[root@k8s-master01 test]# echo yangqin >> index.html ;cat index.html
yangqin---1
yangqin
[root@k8s-master01 test]# cd ;umount /test;rm -rf /test/
3、K8S 中创建 PV
# 1.pv.yaml 文件模板详解
apiVersion: v1 # 使用接口组版本为 core/v1
kind: PersistentVolume # 资源对象为 PersistentVolume
metadata: # 定义资源对象的元数据
name: nfspv1 # 定义资源对象名称为 nfspv1
spec: # 资源对象的期望
capacity: # 指定容量
storage: 1Gi # 指定存储容量为 1G
accessModes: # 指定读写策略
- ReadWriteOnce # 读写策略为 单节点读写
persistentVolumeReclaimPolicy: Retain # 指定回收策略为 保留
storageClassName: nfs # 指定存储类 nfs
nfs: # nfs相关
path: /nfsdata/1 # nfs服务端路径
server: 192.168.20.206 # nfs服务端地址
[root@k8s-master01 ~]# mkdir 8;cd 8
# 确定nfs服务端的路径,在 1.pv.yaml 中写入
[root@k8s-master01 8]# showmount -e 192.168.20.206
Export list for 192.168.20.206:
/nfsdata/10 *
/nfsdata/9 *
/nfsdata/8 *
/nfsdata/7 *
/nfsdata/6 *
/nfsdata/5 *
/nfsdata/4 *
/nfsdata/3 *
/nfsdata/2 *
/nfsdata/1 *
[root@k8s-master01 8]# vim 1.pv.yaml
[root@k8s-master01 8]# kubectl apply -f 1.pv.yaml
[root@k8s-master01 8]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfspv1 1Gi RWO Retain Available nfs 4s
nfspv10 1Gi RWO Retain Available nfs 4s
nfspv2 1Gi RWX Retain Available nfs 4s
nfspv3 1Gi RWO Retain Available mfs 4s
nfspv4 2Gi RWO Retain Available nfs 4s
nfspv5 1Gi RWO Retain Available nfs 4s
nfspv6 1Gi RWO Retain Available nfs 4s
nfspv7 1Gi RWO Retain Available nfs 4s
nfspv8 1Gi RWO Retain Available nfs 4s
nfspv9 1Gi RWO Retain Available nfs 4s
1.pv.yaml 文件详细内容:
4、结合 statefulSet 控制器创建 PVC
- 拓展:statefulSet 控制器(针对有状态服务部署的控制器)
特性:1.有序创建;有序删除
2.具备稳定的存储卷存储
3.有稳定的网络访问(基于域名)
- 结合
statefulSet控制器。核心选项:VolumeClaimTemplates
ClusterIp: None:无头服务,不具备调度功能,可提供域名解析
- pod命名:
控制器名-数字(数字从0开始)
PVC 命名:卷名-PV名
2.headless.yaml、3.statefulset.yaml文件详解:
实验步骤
Ⅰ、创建无头服务的service
[root@k8s-master01 8]# vim 2.headless.yaml
[root@k8s-master01 8]# kubectl apply -f 2.headless.yaml
service/nginx created
[root@k8s-master01 8]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24d
nginx ClusterIP None <none> 80/TCP 3s
[root@k8s-master01 8]# vim 3.statefulSet.yaml
Ⅱ、创建statefulSet控制器
创建完成以后,马上查看pod变化,验证 statefulSet控制器的有序创建
删除statefulSet控制器,验证有序删除
再次创建statefulSet控制器
5、查看 PV ,验证 PVC 与 PV 的绑定规则
依据:容量、读写策略、类、回收策略
# 查看statefulset控制器信息(由此可以确定控制器中的pod命名)
[root@k8s-master01 8]# kubectl get statefulset
NAME READY AGE
web 3/3 4m31s
# 查看pv信息,由此可以验证:pv与pvc的绑定需要依据: 容量(可以超过、最好相等)
读写策略(一 一匹配)
类(一 一匹配)
[root@k8s-master01 8]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfspv1 1Gi RWO Retain Available nfs 49m
nfspv10 1Gi RWO Retain Available nfs 49m
nfspv2 1Gi RWX Retain Available nfs 49m
nfspv3 1Gi RWO Retain Available mfs 49m
nfspv4 2Gi RWO Retain Available nfs 49m
nfspv5 1Gi RWO Retain Bound default/www-web-0 nfs 49m
nfspv6 1Gi RWO Retain Available nfs 49m
nfspv7 1Gi RWO Retain Bound default/www-web-1 nfs 49m
nfspv8 1Gi RWO Retain Bound default/www-web-2 nfs 49m
nfspv9 1Gi RWO Retain Available nfs 49m
[root@k8s-master01 8]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound nfspv5 1Gi RWO nfs 13m
www-web-1 Bound nfspv7 1Gi RWO nfs 13m
www-web-2 Bound nfspv8 1Gi RWO nfs 13m
# 扩容statefulset控制器的副本数量为10
[root@k8s-master01 8]# cp -a 3.statefulSet.yaml 4.statefulSet.yaml
[root@k8s-master01 8]# vim 4.statefulSet.yaml
[root@k8s-master01 8]# kubectl apply -f 4.statefulSet.yaml
# 查看pv和pvc绑定数量为8,剩下两个pv并没有和pvc绑定。进一步验证了绑定规则
[root@k8s-master01 8]# kubectl get pv |grep -i bound |wc -l
8
6、测试statefulSet控制器的稳定持久存储
将控制器创建的pod删除后,虽然更改pod地址,但是仍然会创建同名的pod,并且存在稳定的持久存储。
# 删除pod,重建pod后,持久存储
[root@k8s-master01 8]# kubectl get pod -o wide |grep web-0
web-0 1/1 Running 0 27s 172.100.1.173 k8s-node01 <none> <none>
[root@k8s-master01 8]# curl 172.100.1.173
yangqin---5
[root@k8s-master01 8]# kubectl delete pod web-0
pod "web-0" deleted
[root@k8s-master01 8]# kubectl get pod -o wide |grep web-0
web-0 1/1 Running 0 2s 172.100.1.174 k8s-node01 <none> <none>
[root@k8s-master01 8]# curl 172.100.1.174
yangqin---5
# 进入pod的容器中,改变文件,再次删除pod,重建pod后,持久存储
[root@k8s-master01 8]# kubectl exec -it web-0 -- /bin/sh
/ # echo "yangqin" >> /usr/share/nginx/html/index.html
/ # exit
[root@k8s-master01 8]# kubectl delete pod web-0
pod "web-0" deleted
[root@k8s-master01 8]# kubectl get pod -o wide |grep web-0
web-0 1/1 Running 0 7s 172.100.1.175 k8s-node01 <none> <none>
[root@k8s-master01 8]# curl 172.100.1.175
yangqin---5
yangqin
[root@k8s-master01 8]# kubectl delete pod web-0
pod "web-0" deleted
[root@k8s-master01 8]# kubectl get pod -o wide |grep web-0
web-0 1/1 Running 0 6s 172.100.1.176 k8s-node01 <none> <none>
[root@k8s-master01 8]# curl 172.100.1.176
yangqin---5
yangqin
(根据上一个实验的特性,结合service的无头服务,可以实现域名的持久访问)
7、测试 statefulSet 控制器的稳定地址访问
当 web-0 删除后,会自动创建,仍能用域名访问
测试1: dig 命令进行域名解析
测试2:新建一个其他pod,实现域名访问
- 此处的域名
pod名.service名.名字空间名.svc.K8S集群域名.
podName.headlessServiceName.namespace.svc.domainName.
==
statefulSetName-num(0).headlessServiceName.namespace.svc.domainName.
实验步骤
dns命令解析:
# 获取K8S中的dns地址
[root@k8s-master01 8]# ipvsadm -Ln |grep :53
TCP 10.96.0.10:53 rr
-> 172.100.1.151:53 Masq 1 0 0
-> 172.100.1.152:53 Masq 1 0 0
UDP 10.96.0.10:53 rr
-> 172.100.1.151:53 Masq 1 0 0
-> 172.100.1.152:53 Masq 1 0 0
# 进行dns解析(解析的地址都是pod中的web-0,若pod重建,dns解析会实时更改。从而实现了域名的稳定访问)
[root@k8s-master01 8]# dig -t A web-0.nginx.default.svc.cluster.local. @10.96.0.10|grep ^web-0
web-0.nginx.default.svc.cluster.local. 29 IN A 172.100.1.177
[root@k8s-master01 8]# kubectl delete pod web-0
pod "web-0" deleted
[root@k8s-master01 8]# dig -t A web-0.nginx.default.svc.cluster.local. @10.96.0.10|grep ^web-0
web-0.nginx.default.svc.cluster.local. 30 IN A 172.100.1.178
新建一个pod,实现域名对web-0的持久访问:
[root@k8s-master01 8]# vim 5.pod.yaml
[root@k8s-master01 8]# cat 5.pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: test
spec:
containers:
- image: wangyanglinux/myapp:v1
name: nginx
[root@k8s-master01 8]# kubectl apply -f 5.pod.yaml
[root@k8s-master01 8]# kubectl exec -it test -- /bin/sh
/ #
/ # wget web-0.nginx.default.svc.cluster.local./index.html && cat index.html && rm -rf index.html
Connecting to web-0.nginx.default.svc.cluster.local. (172.100.1.178:80)
index.html 100% |********************************************************| 20 0:00:00 ETA
yangqin---5
yangqin
/ #
/ # exit
[root@k8s-master01 8]# kubectl delete pod web-0
pod "web-0" deleted
[root@k8s-master01 8]# kubectl exec -it test -- /bin/sh
/ # wget web-0.nginx.default.svc.cluster.local./index.html && cat index.html && rm -rf index.html
Connecting to web-0.nginx.default.svc.cluster.local. (172.100.1.180:80)
index.html 100% |********************************************************| 20 0:00:00 ETA
yangqin---5
yangqin
- 注意:若删除 statefulSet 控制器,PVC 仍然存在,再次运行相同的yaml文件的控制器,仍然能够使用挂载
因为删除控制器后,pv和pvc仍然处于绑定状态
[root@k8s-master01 8]# kubectl delete statefulset --all
[root@k8s-master01 8]# kubectl apply -f 4.statefulSet.yaml
[root@k8s-master01 8]# kubectl get pvc
[root@k8s-master01 8]# kubectl get pod -o wide |grep web-0
web-0 1/1 Running 0 52s 172.100.2.184 k8s-node02 <none> <none>
[root@k8s-master01 8]# curl 172.100.2.184
yangqin---5
yangqin
若删除pvc以后,pv处于释放状态(不可绑定状态,可以在存储位置进行数据备份)
若备份完成,需要修复后才能处于可绑定状态
[root@k8s-master01 8]# kubectl delete pvc --all
[root@k8s-master01 8]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfspv1 1Gi RWO Retain Released default/www-web-5 nfs 105m
nfspv10 1Gi RWO Retain Released default/www-web-6 nfs 105m
nfspv2 1Gi RWX Retain Available nfs 105m
nfspv3 1Gi RWO Retain Available mfs 105m
nfspv4 2Gi RWO Retain Released default/www-web-7 nfs 105m
nfspv5 1Gi RWO Retain Released default/www-web-0 nfs 105m
nfspv6 1Gi RWO Retain Released default/www-web-3 nfs 105m
nfspv7 1Gi RWO Retain Released default/www-web-1 nfs 105m
nfspv8 1Gi RWO Retain Released default/www-web-2 nfs 105m
nfspv9 1Gi RWO Retain Released default/www-web-4 nfs 105m
8、已经释放后,修复 PV 为可用
可以:删除pv,重新构建相同的pv
推荐使用:删除 PV 中的 ClaimRef 项



















