1.前言
在日常 Kubernetes 的构建与运维的过程中,存储的使用通常是混合模式。也就是K8S 管理者,既会使用支持云原生存储模式,象是 flexvolume
或 CSI - Container Storage Interface
的存储方式,又会使用一些非云原生的存储(例如,本地 SSD
、NAS
等),这时我们应意识到,有些存储类是不支持快照功能
与在线容量扩展
的。如果要对部署在非云原生的存储上的应用进行应保护,那么我们应该采用什么的方式去实现呢?利用 Kasten K10 的通用存储备份与恢复功能,我们可以通过极小的应用程序修改,以高效和透明的方式对应用进行备份、恢复和迁移的数据操作,而不必去考虑复杂的存储环境。
在之前的实战系列中我们曾经提供了一个完整的示例,该示例说明了如何使用 Kasten 的通用卷备份实现通用的云原生应用备份,Kasten k10
将向您的现有的应用程序部署的 Pod
中添加一个 Kanister sidecar
,Sidecar
可以挂载应用程序数据卷,以实现数据操作的能力。详细情况见如下文档:
Kasten K10 实战系列 11 - Kasten K10 通用存储备份和恢复方法
https://www.data2clouds.com/?p=80
我们发现日常运维过程中,有些时候只用 Namespace
做为标签还是有些不方便,比如客户的系统中有几百个 Services
与 Pods
是通过不同的 Deployments
来部署的。使用 Namespace
将会造成大范围的作用域。如何进行细粒度的选择,而缩小作用域的范围呢?这时就可以利用 ObjectSelector
参数, 使用这个方法我们可以轻松的实现动态的将 Kanister sidecar
注入到生产的 Pod
中,从而避免对整个、 Namespace
中的所有 Pod
注入 Sidecar
的麻烦。
2. 用对象选择器部署 Kanister Sidecar
2.1. 方法1: 在 K10 部署时选择 key=vaule
的形式
在K10部署时选择 key=vaule
的形式,注意以下文中的k10backup=true
是可以自行定义的,关于参数如下:
--set injectKanisterSidecar.enabled=true
--set-string injectKanisterSidecar.objectSelector.matchLabels.k10backup=true
$ helm install k10 k10-4.0.11.tgz --namespace kasten-io --set global.airgapped.repository=ccr.ccs.tencentyun.com/kasten-k10 \
--set auth.basicAuth.enabled=true \
--set auth.basicAuth.htpasswd='mars:$apr1$Cgu1sGVZ$w/8aLHZkVT73OqYZ06C0v.' \
--set metering.mode=airgap \
--set injectKanisterSidecar.enabled=true \
--set-string injectKanisterSidecar.objectSelector.matchLabels.k10backup=true \
--set prometheus.server.persistentVolume.enabled=false \
--set ingress.create=true \
--set ingress.class=nginx \
--set global.persistence.storageClass=csi-hostpath-sc
2.2. 方法2: helm upgrade 更新现有参数
用 helm 升级的现有参数的方法如下:
# 导出当前配置
$ helm get values k10 --output yaml --namespace=kasten-io > k10_val.yaml
# 加入升级的配置
$ helm upgrade k10 k10-4.0.11.tgz --namespace=kasten-io -f k10_val.yaml \
--set-string injectKanisterSidecar.objectSelector.matchLabels.k10backup=true
3. 动态部署 Kanister Sidecar 到现有的应用
- 我们以一个 Alpine 应用为例,查看当前环境,当前 Pod 中 只有一个 Contianer
$ kubectl get po -n alpine
NAME READY STATUS RESTARTS AGE
demo-app-696f676d47-lqcsb 1/1 Running 0 7s
- 查看 K10 的参数,确认
objectSelector
方式已经被启用
$ helm get values k10 -n kasten-io
USER-SUPPLIED VALUES:
auth:
basicAuth:
enabled: true
htpasswd: mars:$apr1$Cgu1sGVZ$w/8aLHZkVT73OqYZ06C0v.
global:
airgapped:
repository: ccr.ccs.tencentyun.com/kasten-k10
persistence:
storageClass: csi-hostpath-sc
ingress:
class: nginx
create: true
injectKanisterSidecar:
enabled: true
objectSelector:
matchLabels:
k10backup: "true"
metering:
mode: airgap
prometheus:
server:
persistentVolume:
enabled: false
- 查看当前的
Deployment
$ kubectl get deployment -n alpine
NAME READY UP-TO-DATE AVAILABLE AGE
demo-app 1/1 1 1 43s
4. Label
当前的 Deployment
触发 Sidecar
注入的机制
$ kubectl label deployment demo-app k10backup=true -n alpine
deployment.apps/demo-app labeled
- 动态观察当前的
Namespace
中Pod
状态
label
后触发了 Sidecar
注入的机制,这时 K8S 会启动一个新的 Pod
包括原有容器与Sidecar
,接着 K8S 会Terminate
原有的 Pod
,形成滚动发布的方式。
# label 后触发了 Sidecar 注入的机制,k8s 启动了一个新的 Pod 包括 Sidecar, 并
$ kubectl get po -n alpine
NAME READY STATUS RESTARTS AGE
demo-app-66dbf75795-tkx2t 2/2 Running 0 4s
demo-app-696f676d47-lqcsb 1/1 Terminating 0 81s
#
$ kubectl get po -n alpine
NAME READY STATUS RESTARTS AGE
demo-app-66dbf75795-tkx2t 2/2 Running 0 61s
- 确认 Kansiter sidecar 已经注入成功
$ kubectl describe po demo-app-66dbf75795-tkx2t -n alpine
Name: demo-app-66dbf75795-tkx2t
Namespace: alpine
Priority: 0
Node: minikube/192.168.99.103
Start Time: Tue, 21 Sep 2021 16:20:49 +0800
Labels: app=demo
pod-template-hash=66dbf75795
Annotations: <none>
Status: Running
IP: 172.17.0.31
IPs:
IP: 172.17.0.31
Controlled By: ReplicaSet/demo-app-66dbf75795
Containers:
demo-container:
Container ID: docker://1666bf583534940bfd508085701a2c2daf3c0fdcb3d38349a4cc01517833ec5f
Image: alpine:3.7
Image ID: docker-pullable://alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10
Port: <none>
Host Port: <none>
Command:
tail
Args:
-f
/dev/null
State: Running
Started: Tue, 21 Sep 2021 16:20:51 +0800
Ready: True
Restart Count: 0
Requests:
cpu: 100m
memory: 256Mi
Environment: <none>
Mounts:
/data from data (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-4v77s (ro)
kanister-sidecar:
Container ID: docker://1ac8759bdd026b0565d539c26178157417df3c966509c91bee8eace7466c738a
Image: ccr.ccs.tencentyun.com/kasten-k10/kanister-tools:k10-0.66.0
Image ID: docker-pullable://ccr.ccs.tencentyun.com/kasten-k10/kanister-tools@sha256:0c8568439d2e928366193fb11b62e9a19887107eb26c0dfd5fcc61e8b539ce47
Port: <none>
Host Port: <none>
Command:
bash
-c
Args:
tail -f /dev/null
State: Running
Started: Tue, 21 Sep 2021 16:20:51 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/data/data from data (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-4v77s (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
data:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: demo-pvc
ReadOnly: false
kube-api-access-4v77s:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events: <none>
4. 总结
本文通过一个简单的实验,说明了 Kasten K10
用对象选择器部署 Kanister sidecar
的方式,比起用 NameSpace
的方式,能更加灵活的触发 Sidecar
的注入,从而利用 Kasten K10
的通用存储备份与恢复功能,以高效和透明的方式对应用进行备份、恢复和迁移的数据操作。
5. 参考链接
Kasten Generic Storage Backup and Restore
https://docs.kasten.io/latest/install/generic.htmlAlpine Quick reference
https://hub.docker.com/_/alpineKasten K10 实战系列 11 - Kasten K10 通用存储备份和恢复方法
https://www.data2clouds.com/?p=80
6. 欢迎关注
MarsZhang @ 云端数据管理
www.data2.clouds.com