前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2024程序员容器化上云之旅-第7集大结局-Ubuntu-WSL2-Windows11版:获得重生

2024程序员容器化上云之旅-第7集大结局-Ubuntu-WSL2-Windows11版:获得重生

原创
作者头像
程序员吾真本
发布2024-02-29 17:38:18
2861
发布2024-02-29 17:38:18
举报
文章被收录于专栏:2024程序员容器化上云之旅

故事梗概

Java程序员马意浓在互联网公司维护老旧电商后台系统。

渴望学习新技术的他在工作中无缘Docker和K8s。

他开始自学Vue3并使用SpringBoot3完成了一个前后端分离的Web应用系统,并打算将其用Docker容器化后用K8s上云。

8.4 无意中用小黄鸭调试法解决k8s中前后端分离web应用的CORS问题

在k8s中解决前后端分离的web应用的CORS问题的思路清楚了。

马意浓接下来要面对的,是如何实现这个思路。

马意浓在网上找不到在k8s中部署前后端web应用时deployment配置和service配置的现成代码样例,所以他只能靠不断问AIGC,一点点尝试和摸索。

这时,昔日的同事全绽园的微信蹦了出来。

「意浓,我在朋友圈里看到你发的求助帖了。你打算怎么解决?」

「我也没想好。要是你有兴趣,后天中午咱们远程视频一下?」

「好的。」

马意浓为了能把所面临的问题,跟全绽园说清楚,在接下来的时间里,就仔细梳理所编写的配置和思路。

到了第三天早上,他还没有梳理完,就跟全绽园说,原订中午的视频会议推迟。等他梳理完了,再喊他。

到了第五天晚上,马意浓凭借仔细梳理配置和思路,以及AIGC的帮助,竟然自己把问题解决了!

他双手握拳,兴奋地高喊:「欧耶!」

他迫不及待地给全绽园发微信:「已经把ingress nginx controller配置对了!那个CORS问题搞定了!😃」

过了一会儿,全绽园回复:「恭喜啊!👏」

「为了把问题给你讲清楚,仔细研究了一下问题,结果就找到解决方案了。😂」

「哈哈!我幸运地充当了小黄鸭。🐥」

马意浓很开心自己能有这么一位乐于助人的好兄弟。他高兴地发了一条朋友圈。

「亲历了一次小黄鸭调试法。刚知道他们管这叫小黄鸭。」

✅「小黄鸭调试法(Rubber Duck Debugging),是一种常用的调试方法。」

「当你遇到问题无法解决时,尝试对着一只橡皮鸭子逐步讲解。通常在讲解问题的过程中,你会得到解决方案。」如图1。

图1 马意浓在全绽园的帮助下无意中用小黄鸭调试法解决了大难题
图1 马意浓在全绽园的帮助下无意中用小黄鸭调试法解决了大难题

8.5 在k8s集群中的软件架构

马意浓趁着现在思路清晰,赶紧记录了一些重要的笔记。

他在vscode中,用PlantUML插件,画了这个前后端分离的web应用部署到k8s中的架构图。如图2。

图2 前后端分离的web应用部署到k8s中的架构图
图2 前后端分离的web应用部署到k8s中的架构图

8.6 新增k8s的deployment、service和ingress配置文件以便将postgres、shopping-list-api、shopping-list-front-end三个微服务和ingress部署到k8s上

马意浓把这次web应用成功部署到k8s的所有代码改动,推送到github的wubin28账号下的shopping-list-web-app-2024-for-wsl2代码库中的for-docker-desktop-k8s分支里。

通过代码对比,他在笔记中记录了这次代码改动的三部分内容。

8.6.1 back-end文件夹中的代码改动

📙在back-end文件夹的ShoppingListApplicationConfig.java文件中,将.allowedOrigins("[hxxp://localhost:8080](<http://localhost:8080/>)") ,改为.allowedOrigins(System.getenv("ALLOWED_ORIGIN"))

其中环境变量ALLOWED_ORIGIN 的值,在deployment-shopping-list-api.yml文件中配置。

📙在back-end文件夹的application.properties文件中,将spring.datasource.url=jdbc:postgresql://localhost:5432/shoppingList ,改为spring.datasource.url=jdbc:postgresql://${DB_HOST}:5432/shoppingList

其中环境变量${DB_HOST}的值,也在deployment-shopping-list-api.yml文件中配置。

8.6.2 front-end文件夹中的代码改动

📙在front-end文件夹的ShoppingList.vue文件中,将[hxxp://localhost:8081](<http://localhost:8081/>) ,改为%%API_URL%%

其中环境变量%%API_URL%%的值,在deployment-shopping-list-front-end.yml文件中配置。

📙为了让环境变量%%API_URL%%在前端app中生效,对front-end文件夹中的Dockerfile也做了一些改动。另外也增加了entrypoint.sh文件。

8.6.3 infrastructure文件夹中的代码改动

在infrastructure文件夹中增加了postgres、shopping-list-api和shopping-list-front-end这三个微服务的deployment和service配置文件。

最后增加了ingress nginx controller的配置文件ingress.yml。

代码语言:javascript
复制
deployment-postgres.yml           
service-postgres.yml  
deployment-shopping-list-api.yml       
service-shopping-list-api.yml
deployment-shopping-list-front-end.yml  
service-shopping-list-front-end.yml
ingress.yml           

马意浓在笔记上,将之前运行过的命令记录下来,以便以后再次运行。

8.7 构建后端app的docker image并推送到docker hub

代码语言:javascript
复制
# check out the branch with updated code for k8s
git clone hxxps://github.com/wubin28/shopping-list-web-app-2024-for-wsl2.git
git checkout for-docker-desktop-k8s

# start up db
cd ../infrastructure
docker compose up postgres pgadmin

# generate the jar
cd ../back-end
export DB_HOST=localhost
./gradlew clean build

# build back-end docker image
docker buildx build --build-arg JAR_FILE=build/libs/shoppinglist-0.0.1-SNAPSHOT.jar -t <docker-hub-username>/shopping-list-api:v1.1.local.k8s .
docker image ls

# push the back-end docker image to docker hub
docker push <docker-hub-username>/shopping-list-api:v1.1.local.k8s

8.8 在git代码库打同名的tag以对应刚刚构建的docker image版本

代码语言:javascript
复制
# 若将来后端app的v1.1.local.k8s版本出现问题时,为便于查看所对应的代码,运行命令在git代码库打同名tag
git tag -a v1.1.local.k8s -m "v1.1.local.k8s"

8.9 构建前端app的docker image并推送到docker hub

代码语言:javascript
复制
cd ../front-end
docker buildx build --platform linux/amd64 -t <docker-hub-username>/shopping-list-front-end:v1.1.local.k8s.amd64 .
docker image ls
docker inspect <docker-hub-username>/shopping-list-front-end:v1.1.local.k8s.amd64 | grep "Architecture"

# push the front-end docker image to docker hub
docker push <docker-hub-username>/shopping-list-front-end:v1.1.local.k8s.amd64

8.10 在k8s集群上配置postgres、shopping-list-api和shopping-list-front-end三个微服务和ingress并运行

与在Ubuntu中用sdkman安装不同版本的jdk一样,在k8s中,可以使用包管理器helm安装ingress-nginx。

在命令中使用$NAMESPACE的好处,是将来清理现场时,能方便地用一行命令,来删除之前在k8s上创建的所有与购物清单web应用相关的资源。

代码语言:javascript
复制
# run the web app on k8s
export NAMESPACE=shopping-list-web-app
kubectl create namespace $NAMESPACE

# install package manager helm on k8s. please enter password when installing it
curl hxxps://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
sudo apt-get install apt-transport-https --yes
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] <https://baltocdn.com/helm/stable/debian/> all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm

# install ingress-nginx using helm
helm repo add ingress-nginx-repo <https://kubernetes.github.io/ingress-nginx>
helm repo update
helm install ingress-nginx-release ingress-nginx-repo/ingress-nginx \\
 -n $NAMESPACE \\
 --set controller.service.annotations."service\\.beta\\.kubernetes\\.io/azure-load-balancer-health-probe-request-path"=/healthz

# check the installed ingress-nginx in helm
helm list -n $NAMESPACE

# check the external ip of the ingress-nginx-release-controller
kubectl get services -o wide -n $NAMESPACE

# watch the status of the ingress-nginx-release-controller
kubectl get service -n $NAMESPACE ingress-nginx-release-controller --output wide --watch

cd ../infrastructure

# 部署postgres的deployment
kubectl apply -f ./deployment-postgres.yml --namespace $NAMESPACE
# 验证image是否正确:
kubectl get deployments -o wide -n $NAMESPACE
# 验证pod是否正常启动
kubectl get pods -o wide -n $NAMESPACE
# 如果pod启动异常查看出错信息
kubectl describe pod <pod name, such as first-pod> -n $NAMESPACE
# 如果pod启动异常查看最后一个container的出错信息
kubectl logs <pod name, such as first-pod> --previous -n $NAMESPACE
# 部署postgres的service
kubectl apply -f ./service-postgres.yml --namespace $NAMESPACE
# 验证服务是否正常启动
kubectl get services -o wide -n $NAMESPACE

# 部署shopping-list-api的deployment
kubectl apply -f ./deployment-shopping-list-api.yml --namespace $NAMESPACE
# 验证image是否正确
kubectl get deployments -o wide -n $NAMESPACE
# 验证pod是否正常启动
kubectl get pods -o wide -n $NAMESPACE
# 部署shopping-list-api的service
kubectl apply -f ./service-shopping-list-api.yml --namespace $NAMESPACE
# 验证服务是否正常启动
kubectl get services -o wide -n $NAMESPACE

# 部署shopping-list-front-end的deployment
kubectl apply -f ./deployment-shopping-list-front-end.yml --namespace $NAMESPACE
# 验证image是否正确
kubectl get deployments -o wide -n $NAMESPACE
# 验证pod是否正常启动
kubectl get pods -o wide -n $NAMESPACE
# 部署shopping-list-front-end的service
kubectl apply -f ./service-shopping-list-front-end.yml --namespace $NAMESPACE
# 验证服务是否正常启动
kubectl get services -o wide -n $NAMESPACE

# 部署ingress
kubectl apply -f ./ingress.yml --namespace $NAMESPACE
# 查看ingress的状态
kubectl get ingresses -n $NAMESPACE
# 查看ingress的详情
kubectl describe ingress shopping-list-ingress -n $NAMESPACE

# Check external ip and port of ingress nginx controller: localhost
kubectl get services -o wide -n $NAMESPACE

8.11 在k8s上运行购物清单web应用

等运行完上面的命令,将web应用部署到k8s后,马意浓终于可以打开浏览器,要在k8s上使用购物清单web应用了。

他在浏览器地址栏输入localhost,按下回车。

网页显示出购物清单页面。他添加了一个购物项a banana,并按Add按钮。

但这个购物项还是没有如愿显示在屏幕下方。

他打开浏览器的Developer Tools,发现CORS错误又出现了。

Access to XMLHttpRequest at 'hxxp://20.72.130.209/api/v1/shopping-items' from origin 'hxxp://localhost' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

他在出错信息中,看到了20.72.130.209这个地址。这是他以前在某个云厂商那里试用k8s时配置上的。

现在,他已经把前后端分离的web应用,部署到本地Docker Desktop里,所以这个IP地址,应该改为localhost

他查看了一下代码,先把deployment-shopping-list-front-end.yml文件中的API_URL值,改为localhost

然后他又把deployment-shopping-list-api.yml文字中的ALLOWED_ORIGIN的值,改为localhost

因为改了配置文件,所以需要重新apply这两个deployment配置。

不过,相对应的service配置因为没有改变,所以无须重新apply。

从这一点,就能看出k8s将微服务的部署分为deployment配置和service配置这两步的好处。

代码语言:javascript
复制
# 部署shopping-list-api的deployment
kubectl apply -f ./deployment-shopping-list-api.yml --namespace $NAMESPACE
# 验证image是否正确
kubectl get deployments -o wide -n $NAMESPACE
# 验证pod是否正常启动
kubectl get pods -o wide -n $NAMESPACE
# 部署shopping-list-front-end的deployment
kubectl apply -f ./deployment-shopping-list-front-end.yml -n $NAMESPACE
# 验证image是否正确
kubectl get deployments -o wide -n $NAMESPACE
# 验证pod是否正常启动
kubectl get pods -o wide -n $NAMESPACE

运行完这些命令后,马意浓又在浏览器地址栏输入localhost,按下回车。

CORS错误依旧显示出来。

✅之前的经验告诉他,这应该是浏览器缓存在捣乱。

他把Chrome浏览器的cache清除了一下。然后再次刷新网页。

🎉🎉🎉这次,CORS错误消失了!购物清单web应用终于在k8s里成功运行!

8.12 运行kubectl命令以查看k8s概念

马意浓没有忘记,在成功部署web应用后,他又运行kubectl命令,回顾了一下context、cluster、node、pod和container这些k8s的概念。

代码语言:javascript
复制
# check out the k8s concepts
# contexts
kubectl config get-contexts
kubectl config current-context
# clusters
kubectl config get-clusters
# nodes
kubectl get nodes
kubectl describe nodes
# pods
kubectl get pods -n <namespace>
kubectl get pods --all-namespaces
# containers
# Kubectl itself doesn't provide a direct way to list all containers across all pods, but you can use it to get pod details, which include container information. For a specific pod:
kubectl describe pod <pod-name> -n <namespace>

8.13 清理现场

因为之前在k8s里,执行为购物清单web应用创建资源的kubectl命令,都带有-n $NAMESPACE参数,所以在清理现场时,马意浓就可以用一条命令删除所有相关资源。

在运行那行删除资源的命令之前和之后,他还没忘了运行了查看资源的命令,以验证资源真的被删除干净了。

代码语言:javascript
复制
# check all resources in the namespace before tearing down
kubectl get namespace $NAMESPACE
kubectl api-resources --verbs=list --namespaced=true -o name | xargs -n 1 kubectl get -n $NAMESPACE
# Tear down
kubectl delete namespace $NAMESPACE
# make sure all resources in the namespace have been deleted
kubectl get namespace $NAMESPACE
kubectl api-resources --verbs=list --namespaced=true -o name | xargs -n 1 kubectl get -n $NAMESPACE

9 取经归来

当最终把前后端分离的web应用成功部署到Docker Desktopk8s集群上,并能顺利使用后,马意浓把整个容器化上云之旅,写成系列文章,分享给其他程序员,作为对包括全绽园在内的所有帮过他的人的感谢。🙏🙏🙏

全文完。


❤️欲读系列故事的全集内容,可搜用户“程序员吾真本”,找到“2024程序员容器化上云之旅”专栏阅读。

😃你能否跟着马意浓一步步做下来?在阅读中有任何疑问,欢迎在留言区留言。我会一一回复

❤️如果喜欢本文,那么点赞留言,并转发给身边有需要的朋友,就是对我的最大支持😃🤝🙏。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 故事梗概
    • 8.4 无意中用小黄鸭调试法解决k8s中前后端分离web应用的CORS问题
      • 8.5 在k8s集群中的软件架构
        • 8.6 新增k8s的deployment、service和ingress配置文件以便将postgres、shopping-list-api、shopping-list-front-end三个微服务和ingress部署到k8s上
          • 8.6.1 back-end文件夹中的代码改动
          • 8.6.2 front-end文件夹中的代码改动
          • 8.6.3 infrastructure文件夹中的代码改动
        • 8.7 构建后端app的docker image并推送到docker hub
          • 8.8 在git代码库打同名的tag以对应刚刚构建的docker image版本
            • 8.9 构建前端app的docker image并推送到docker hub
              • 8.10 在k8s集群上配置postgres、shopping-list-api和shopping-list-front-end三个微服务和ingress并运行
                • 8.11 在k8s上运行购物清单web应用
                  • 8.12 运行kubectl命令以查看k8s概念
                    • 8.13 清理现场
                    • 9 取经归来
                    相关产品与服务
                    容器服务
                    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档