将网站部署在 Kubernetes 上
将自己的博客网站发布到自己的 Kubernetes 集群上。
Kubernetes 环境 Link to heading
之前在 阿里云主机搭建-k8s-集群 这篇文章介绍了如何在阿里云环境快速搭建一个 Kubernetes 环境,按照文章的步骤,可以快速搭建一个可用的 Kubernetes 集群。
网站 Link to heading
同样在 Build Blog With Hugo 这边文章中,介绍了怎么使用 hugo 快速搭建一个自己的个人博客。
容器化 Link to heading
我的项目 hugo-dcos 包含了容器化一个 hugo 网站项目所需的一些脚本和 Dockerfile, 可以参考本项目自行容器化自己的项目。
项目使用了webhook接收 github 的通知,并在github上配置项目maoqide.github.io的 Webhooks, 当本项目有更新时,会调用 webhook 服务触发操作,拉取最新的代码。
部署 Link to heading
本文介绍如何将自己的个人博客通过 Kubernetes 发布到公网,让大家可以访问。
当然,最简单的发布方法是通过 Github Pages, 直接将 hugo 生成的 publish 文件夹上传到自己 github 的命名为 your-username.github.io 的仓库下,即可以通过 https://your-username.github.io 访问到自己的网站。
准备 Link to heading
- 域名
- 云服务器
创建 Deployment & Service Link to heading
首先创建 Deployment 和 Service。
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysite
spec:
selector:
matchLabels:
app: site
replicas: 1
template:
metadata:
labels:
app: site
spec:
containers:
- name: mysite
image: maoqide/site:v1.1
env:
- name: GITHUB_HOOK_SECRET
value: MY_SECRET
ports:
- containerPort: 80
- containerPort: 9000
livenessProbe:
httpGet:
# scheme: HTTPS
path: /
port: 80
initialDelaySeconds: 15
timeoutSeconds: 1
---
kind: Service
apiVersion: v1
metadata:
name: mysite
spec:
selector:
app: site
ports:
- name: nginx
protocol: TCP
port: 80
targetPort: 80
- name: webhook
protocol: TCP
port: 9000
targetPort: 9000
创建 ingress-controller Link to heading
为了能够从外部访问,还需要创建 Ingress。
这里使用nginx ingress,首先要创建 nginx-ingress-controller。
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: tcp-services
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: udp-services
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-ingress-serviceaccount
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- "extensions"
resources:
- ingresses/status
verbs:
- update
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: nginx-ingress-role
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
# Defaults to "<election-id>-<ingress-class>"
# Here: "<ingress-controller-leader>-<nginx>"
# This has to be adapted if you change either parameter
# when launching the nginx-ingress-controller.
- "ingress-controller-leader-nginx"
verbs:
- get
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: nginx-ingress-role-nisa-binding
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: nginx-ingress-role
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: nginx-ingress-clusterrole-nisa-binding
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nginx-ingress-clusterrole
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: default
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-ingress-controller
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
annotations:
prometheus.io/port: "10254"
prometheus.io/scrape: "true"
spec:
serviceAccountName: nginx-ingress-serviceaccount
containers:
- name: nginx-ingress-controller
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.21.0
args:
- /nginx-ingress-controller
- --configmap=$(POD_NAMESPACE)/nginx-configuration
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
- --publish-service=$(POD_NAMESPACE)/ingress-nginx
- --annotations-prefix=nginx.ingress.kubernetes.io
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 33
runAsUser: 33
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
livenessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
---
以上 yaml 创建了一个 nginx-ingress-controller 的 Deployment,并赋给 Deployment 下的 Pod 对 Ingress 等集群内资源的 API 访问权限。
接着要为 nginx-ingress-controller 创建 Node port 类型的 Service,让我们可以通过云服务器的公网地址访问到 ingress:
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
- name: https
port: 443
targetPort: 443
protocol: TCP
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
创建 Ingress Link to heading
创建 Ingress 策略。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: site-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- http:
paths:
- path: /_hook
backend:
serviceName: mysite
servicePort: 9000
- path: /
backend:
serviceName: mysite
servicePort: 80
配置域名 Link to heading
上述步骤完成,已经可以通过云服务器公网IP= https://IP:ingress_svc-port 访问网站了。
为了访问方便,还可以给站点配置一个域名,直接在阿里云购买一个域名,然后通过绑定一个 A 类型的域名解析,解析到阿里云公网IP,就可以通过域名加端口访问了。
如果不想访问的时候加上端口,还需要再配置一个 隐性URL 的域名解析(需要先将域名备案)。
附件 Link to heading
以下是上面用到的 yaml 文件: