背景
之前做了 GitOps 的实验,现在准备在已创建好的集群中增加一个纯前端应用。计划使用 React + Typescript 的方式做一个应用示例。
前端应用准备
1. 首先从 NodeJs 官方网站下载一个稳定版本,安装
2. 安装 yarn,这里使用它作为包管理工具
npm install -g yarn
3. 参考 Ant Design of React 这篇文章,创建一个应用。应用是什么内容无所谓,本次动手实验是把这个应用部署到 K8S 中
本地打包镜像文件
1. 本地安装 Docker Desktop 这个工具,先在本地尝试将前端应用进行打包
2. 在项目根目录下增加一个 Dockerfile 文件,注意这个文件并没有后缀名
FROM node:16.17 AS build-env
# Copy package
COPY package.json yarn.lock ./
# Restore as distinct layers
RUN yarn install
COPY . ./
# Build and publish a release
RUN yarn build
# Build runtime image
FROM nginx:1.22
## Remove default nginx website
RUN rm -rf /usr/share/nginx/html/
COPY nginx/default.conf /etc/nginx/conf.d/
COPY --from=build-env /build /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
这里解释一下,首先我们这里用到了2个基础镜像,一个是 node:16.17,另一个是 nginx:1.22 。首先我们在 build-env(node:16.17)镜像中进行项目编译,然后通过 COPY 的方式(--from-build-env)将编译好的结果直接复制到我们要运行的环境,这里我们用 nginx 做了纯前端应用的宿主。另外考虑到每次编译的时候都需要还原包,所以先将 package.json 和 yarn.lock 文件 COPY 到 build-env 中进行包的还原。如果不修改包或者增加包,我们就可以在本地利用 Docker build 时的Cache 减少编译时间。
3. 这里还准备了一下 Nginx 的配置文件,没有什么太多要说明的。唯一要注意的就是这里利用 try_files 来实现跳转。对于这种单页面程序,即使用户没有从入口地址进入,依靠这个配置依然可以正常使用。
server {
listen 80;
sendfile on;
default_type application/octet-stream;
gzip on;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.";
gzip_min_length 256;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_comp_level 9;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/ /index.html =404;
}
}
4. 本地执行打包命令,这里要注意最后是一位的点别丢掉。 大概解释一下就是 -t 告诉这个新制作的镜像名字叫什么,版本号是多少。点是表示上下文路径(build context path),如果没有通过 -f 指明,默认找到这个路径下的 Dockerfile 文件。如果需要多个 Dockerfile 文件,这里可以通过增加 -f 参数。
docker build -t daprdemo.azurecr.io/mcs-dapr-poc-frontend:v0.0.1 .
5. 本地可以尝试运行一下,不想输入命令可以尝试用 UI 来控制。
命令如下(未加 -d 参数):
docker run --name frontend -p 8088:80 daprdemo.azurecr.io/mcs-dapr-poc-frontend:v0.0.1
UI操作如下:
6. 打开浏览器访问 http://localhost:8088 可以看到我们的应用运行成功。
使用 Github Actions CI
签入代码到 Github 中,在 Actions 新建一个 workflow
name: POC Frontend Image CI
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build the Docker image
run: docker build . --file Dockerfile --tag daprdemo.azurecr.io/mcs-dapr-poc-frontend:${{ github.run_id }}
- name: Login Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Login Azure ACR & push image
run: |
az acr login --name daprdemo
docker push daprdemo.azurecr.io/mcs-dapr-poc-frontend:${{ github.run_id }}
解释一下:
(1) 首先使用 actions/checkout@3 来获取代码
(2) 执行docker build 命令来完成镜像的打包,版本号使用 ${{ github.run_id }} ,run_id 每次运行(不包括重新运行) workflow 都会变化
(3) 登录 Azure,因为我的镜像需要放到 Azure Container Registry 中
(4) 登录 acr , 并且执行 docker push 将镜像推送到 ACR中
部署到 kubernetes
1. 准备一个部署文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcs-dapr-poc-frontend
namespace: new-namespace
spec:
replicas: 2
selector:
matchLabels:
app: mcs-dapr-poc-frontend
template:
metadata:
labels:
app: mcs-dapr-poc-frontend
spec:
containers:
- name: mcs-dapr-poc-frontend-image
image: daprdemo.azurecr.io/mcs-dapr-poc-frontend:3111349226
ports:
- containerPort: 80
protocol: TCP
2. 为这个部署的 Pods 提供 Service
apiVersion: v1
kind: Service
metadata:
name: mcs-dapr-poc-frontend
namespace: new-namespace
spec:
selector:
app: mcs-dapr-poc-frontend
ports:
- protocol: TCP
port: 80
targetPort: 80
3. 准备一个 Ingress ,这里用的是 Azure Application Gateway,前面的文章有介绍过
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: application-gateway
namespace: new-namespace
annotations:
kubernetes.io/ingress.class: azure/application-gateway
spec:
rules:
- http:
paths:
- path: /
backend:
service:
name: mcs-dapr-poc-frontend
port:
number: 80
pathType: Exact
4. 执行命令进行部署,我这里namespace 换了一个名字 spark-namespace 。
集成到 GitOps 中
1. 增加一个 source
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: spark-poc
namespace: flux-system
spec:
interval: 30s
ref:
branch: main
url: https://github.com/<your repos>
2. 增加一个 Kustomization
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: mcs-dapr-poc-frontend
namespace: flux-system
spec:
interval: 5m0s
path: ./mcs-dapr-poc-frontend/kubernetes
prune: true
sourceRef:
kind: GitRepository
name: spark-poc
targetNamespace: spark-namespace