<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>k8up | 伪架构师</title>
    <link>/tags/k8up/</link>
      <atom:link href="/tags/k8up/index.xml" rel="self" type="application/rss+xml" />
    <description>k8up</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh</language><lastBuildDate>Sat, 04 Jan 2020 22:04:14 +0800</lastBuildDate>
    <image>
      <url>/img/logo-wide.png</url>
      <title>k8up</title>
      <link>/tags/k8up/</link>
    </image>
    
    <item>
      <title>用 k8up 把 PVC 备份到 S3</title>
      <link>/post/backup-pvc-2-s3/</link>
      <pubDate>Sat, 04 Jan 2020 22:04:14 +0800</pubDate>
      <guid>/post/backup-pvc-2-s3/</guid>
      <description>

&lt;p&gt;&lt;a href=&#34;https://k8up.io/&#34; target=&#34;_blank&#34;&gt;k8up&lt;/a&gt; 是一个基于 &lt;a href=&#34;https://github.com/restic/restic&#34; target=&#34;_blank&#34;&gt;Restic&lt;/a&gt; 的备份工具，可以一次性的或者周期性的把指定的 PVC 备份到 S3 协议的对象存储上去，备份内容还可以使用 Restic 恢复到 S3 或者 PVC 上。除了 PVC，后续还可以用命令的方式，例如 &lt;code&gt;mysqldump&lt;/code&gt;，把数据库等内容备份出来。&lt;/p&gt;

&lt;h2 id=&#34;安装和初始化&#34;&gt;安装和初始化&lt;/h2&gt;

&lt;p&gt;Helm 安装即可：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;helm repo add appuio https://charts.appuio.ch
helm repo update
helm install appuio/k8up
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;安装过程会生成一系列的 CRD，会在后续步骤中使用。&lt;/p&gt;

&lt;p&gt;后续过程中需要两个 Secret，分别用来加密备份和访问 S3：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl create secret generic s3secret --from-literal token=[hidden] \
    --from-literal key=[hidden]
secret/s3secret created
$ kubectl create secret generic backup --from-literal password=PassW0rd
secret/backup created
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;备份-pvc&#34;&gt;备份 PVC&lt;/h2&gt;

&lt;p&gt;k8up 会选择命名空间中注解为 &lt;code&gt;appuio.ch/backup: &amp;quot;true&amp;quot;&lt;/code&gt; 的 PVC 进行备份，我们用下文的工作负载生成两个 PVC，运行起来之后，两个 PVC 分别挂载到容器的 &lt;code&gt;/data1&lt;/code&gt; 和 &lt;code&gt;/data2&lt;/code&gt; 目录中，可以登录到 Pod，在其中生成文件：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl exec -it debugger-7b8f654484-hrcg9 bash
bash-4.4# echo &amp;quot;Hello world&amp;quot; &amp;gt; /data/data.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;创建一次性任务：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: backup.appuio.ch/v1alpha1
kind: Backup
metadata:
  name: backup-now
spec:
  keepJobs: 4
  backend:
    repoPasswordSecretRef:
      name: backup
      key: password
    s3:
      endpoint: https://s3.amazonaws.com
      bucket: dustise
      accessKeyIDSecretRef:
        name: s3secret
        key: token
      secretAccessKeySecretRef:
        name: s3secret
        key: key
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;查看 Pod 日志：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl logs -f k8up-1578112449-84d7d4d6cc-q6qsh
2020/01/04 14:30:10 [INFO] New backup job received backup-now in namespace default
2020/01/04 14:30:10 [INFO] Listing all PVCs with annotation appuio.ch/backup in namespace default
2020/01/04 14:30:10 [INFO] Adding data to list
...
2020/01/04 14:30:29 [INFO] default/backupjob-1578148210 is running
2020/01/04 14:30:37 [INFO] default/backupjob-1578148210 finished successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;两个卷的备份均已完成，查看 S3 的情况：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ s3cmd la
                       DIR   s3://dustise/data/
                       DIR   s3://dustise/index/
                       DIR   s3://dustise/keys/
                       DIR   s3://dustise/snapshots/
2020-01-04 14:30       155   s3://dustise/config
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;发现已经初始化了一个备份结构。&lt;/p&gt;

&lt;h2 id=&#34;还原&#34;&gt;还原&lt;/h2&gt;

&lt;p&gt;备份成功之后，我们希望还原一下，看看备份的内容。&lt;/p&gt;

&lt;p&gt;新建一个 PVC 用作还原目标：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: restore
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;创建一个还原命令：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: backup.appuio.ch/v1alpha1
kind: Restore
metadata:
  name: restore2pvc
  namespace: default
spec:
  backend:
    repoPasswordSecretRef:
      key: password
      name: backup
    s3:
      accessKeyIDSecretRef:
        key: token
        name: s3secret
      bucket: dustise
      endpoint: https://s3.amazonaws.com
      secretAccessKeySecretRef:
        key: key
        name: s3secret
  restoreMethod:
    folder:
      claimName: restore
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;查看运行日志：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ kubectl logs -f k8up-1578112449-84d7d4d6cc-q6qsh
2020/01/04 14:43:45 [INFO] Received restore job restore-now in namespace default
2020/01/04 14:43:45 [INFO] default/restorejob-1578149025 is running
2020/01/04 14:43:45 [INFO] default/restorejob-1578149025 is running
2020/01/04 14:43:59 [INFO] default/restorejob-1578149025 is running
2020/01/04 14:44:15 [INFO] default/restorejob-1578149025 finished successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;查看该卷内容，会发现其中有一个 &lt;code&gt;data/data&lt;/code&gt; 目录，包含了我们的备份内容。&lt;/p&gt;

&lt;h2 id=&#34;附录&#34;&gt;附录&lt;/h2&gt;

&lt;h3 id=&#34;连接&#34;&gt;连接&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;https://k8up.io/&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;https://github.com/restic/restic&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;源码&#34;&gt;源码&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: debugger
  name: debugger
spec:
  replicas: 1
  selector:
    matchLabels:
      app: debugger
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: debugger
    spec:
      containers:
      - image: dustise/sleep
        name: sleep
        resources: {}
        volumeMounts:
        - name: data
          mountPath: /data
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: data
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: data
  annotations:
    appuio.ch/backup: &amp;quot;true&amp;quot;
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
  </channel>
</rss>
