启用 K3s 了
感谢某位朋友给我 cloudcone 的优惠信息,我得到了一台 1C2G 每月 3 刀的 VPS。
然后我就开始了把网站全面容器化的想法,其实总的来说迁移还是比较顺利的,但是有一些小问题需要解决一波,这里记录一下好了。
Traefik 自动申请证书
在安装 K3s 的时候,由于没考虑那么多,也就导致一开始我没有搞定 HTTPS 证书,然后我根据 helm 上的一些信息,自己研究出了如何打补丁,并且也启用了 dashboard
apiVersion: v1
kind: Secret
metadata:
name: traefik-dnsprovider-config
namespace: kube-system
labels:
app: traefik
chart: traefik-1.77.1
heritage: Tiller
release: traefik
type: Opaque
data:
CLOUDFLARE_EMAIL: "base64 编码的邮箱地址"
CLOUDFLARE_API_KEY: "base64 编码的 API KEY"
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
labels:
app: traefik
chart: traefik-1.77.1
heritage: Tiller
release: traefik
name: traefik-dashboard
spec:
rules:
- host: traefik.wetofu.top
http:
paths:
- backend:
serviceName: traefik-dashboard
servicePort: dashboard-http
tls:
- hosts:
- traefik.wetofu.top
---
apiVersion: v1
kind: Service
metadata:
labels:
app: traefik
chart: traefik-1.77.1
heritage: Tiller
release: traefik
name: traefik-dashboard
spec:
type: "ClusterIP"
selector:
app: traefik
release: traefik
ports:
- name: dashboard-http
port: 80
targetPort: 8080
---
apiVersion: v1
data:
traefik.toml: |
# traefik.toml
logLevel = "info"
defaultEntryPoints = ["http","https"]
[entryPoints]
[entryPoints.traefik]
address = ":8080"
[entryPoints.traefik.auth]
[entryPoints.traefik.auth.basic]
users = [
"使用htpasswd生成"
]
[entryPoints.http]
address = ":80"
compress = true
[entryPoints.http.redirect]
regex = "^http://(.*)"
replacement = "https://$1"
permanent = true
[entryPoints.https]
address = ":443"
compress = true
[entryPoints.https.tls]
[ping]
entryPoint = "http"
[kubernetes]
[kubernetes.ingressEndpoint]
hostname = "wetofu.top"
publishedService = "kube-system/traefik"
[traefikLog]
format = "json"
[metrics]
[metrics.prometheus]
entryPoint = "traefik"
[acme]
acmeLogging = true
KeyType = "RSA4096"
email = "邮箱地址"
storage = "/acme/acme.json"
entryPoint = "https"
onHostRule = true
[acme.dnsChallenge]
provider = "cloudflare"
resolvers = [
"1.1.1.1:53",
"8.8.8.8:53"
]
[[acme.domains]]
main = "*.wetofu.top"
sans = [
"wetofu.top"
]
[api]
entryPoint = "traefik"
dashboard = true
kind: ConfigMap
metadata:
labels:
app: traefik
chart: traefik-1.77.1
heritage: Tiller
release: traefik
name: traefik
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
labels:
app: traefik
chart: traefik-1.77.1
heritage: Tiller
release: traefik
name: traefik
namespace: kube-system
spec:
clusterIP: 10.43.251.13
externalTrafficPolicy: Cluster
ports:
- name: http
nodePort: 32180
port: 80
protocol: TCP
targetPort: http
- name: https
nodePort: 32631
port: 443
protocol: TCP
targetPort: https
- name: metrics
nodePort: 31043
port: 8080
protocol: TCP
targetPort: dash
selector:
app: traefik
release: traefik
sessionAffinity: None
type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: traefik
chart: traefik-1.77.1
heritage: Tiller
release: traefik
name: traefik
namespace: kube-system
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: traefik
release: traefik
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
annotations:
checksum/config: 5072e2b9911158c04b7b76568f0c4f477d59793d52d6a44d35a4910b5e15527c
creationTimestamp: null
labels:
app: traefik
chart: traefik-1.77.1
heritage: Tiller
release: traefik
spec:
containers:
- args:
- --configfile=/config/traefik.toml
env:
- name: CLOUDFLARE_EMAIL
valueFrom:
secretKeyRef:
key: CLOUDFLARE_EMAIL
name: traefik-dnsprovider-config
- name: CLOUDFLARE_API_KEY
valueFrom:
secretKeyRef:
key: CLOUDFLARE_API_KEY
name: traefik-dnsprovider-config
image: traefik:1.7.14
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /ping
port: 80
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 2
name: traefik
ports:
- containerPort: 80
name: http
protocol: TCP
- containerPort: 8880
name: httpn
protocol: TCP
- containerPort: 443
name: https
protocol: TCP
- containerPort: 8080
name: dash
protocol: TCP
readinessProbe:
failureThreshold: 1
httpGet:
path: /ping
port: 80
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 2
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /config
name: config
- mountPath: /acme
name: acme
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: traefik
serviceAccountName: traefik
terminationGracePeriodSeconds: 60
volumes:
- configMap:
defaultMode: 420
name: traefik
name: config
- hostPath:
path: /app/tls # 证书存放于本机目录
type: Directory
name: acme
目前这个方案可以获取 https 证书,但是我还没研究出来如何使用证书,这个留待日后再谈。
本博客的更新方法
使用 bashttpd 配合 socat
命令,做一个 webhook 暴露给 docker hub,别打什么坏主意,有白名单的。
原理很简单,就是看看现在博客所在的 pod 是哪个,然后重启,配合拉取镜像策略为 Always
就可以更新了。
这样我每次打完镜像,推送之后就可以自动更新,而且我有足够的时间可以研究和调试新的界面主题了。
只是,调整以后,我如果想写文章,大概就只能用 hugo new post/filename.md
了,有点不习惯……
另外就是更新过程中会出现短暂的 Service Unavailable
……