本文依然是通过 staffjoy 来学习和实践微服务和云原生相关内容。上篇文章着重于学习微服务相关的概念、原理,各个中间件的知识以及具体的代码实现。承接上文,本文重点学习云原生部分的内容,以及如何将项目正确部署。
微服务+云原生实践(Spring + K8s)

本地开发环境部署

本地开发环境部署时,要给每个服务开放一个端口,在 IDEA 里启动后都是一个个进程
截屏2021-12-17 13.18.48.png

软件安装

SwitchHosts

因为整个服务都是通过域名访问的,所以需要一个域名解析工具,下载地址:
https://github.com/oldj/SwitchHosts/releases

SkyWalking

用于数据监控,下载 6. 1.0 版本,下载地址:
http://archive.apache.org/dist/skywalking/
文档地址为:
https://skywalking.apache.org/docs/skywalking-java/latest/en/setup/service-agent/java-agent/readme/

MySQL

本来是想下载经典的 5.7 版本,但是由于电脑是 M1 芯片的 Mac,为了防止有适配问题,直接下载了 M1 的适配版本
https://dev.mysql.com/downloads/mysql/
截屏2021-12-17 15.14.33.png
安装之后需要配置环境变量:
在 ~/.bash_profile 文件中添加

  1. export PATH=$PATH:/usr/local/mysql/bin
  2. export PATH=$PATH:/usr/local/mysql/support-files

在从命令行输入 mysql -u root -p 指令时,可能会出现报错信息:

zsh: command not found: mysql

这时修改 ~/.bashrc 文件,在其中添加

  1. alias mysql=/usr/local/mysql/bin/mysql

然后 source 一下这个文件即可。

本地部署(IDEA 环境)

清理内存

服务众多,至少保证空闲内存在 4GB 以上

部署 MySQL 数据库

本项目主要用到两个数据库,一个是 account,另外一个是 company。它们的 sql 文件分别在 account-svc 和 company-svc 的 resources 中。
account 有一个表:

  1. CREATE TABLE IF NOT EXISTS account (
  2. id VARCHAR(255),
  3. email VARCHAR(255) NOT NULL,
  4. name VARCHAR(255) NOT NULL default '',
  5. phone_number VARCHAR(255) NOT NULL,
  6. confirmed_and_active BOOLEAN NOT NULL DEFAULT false,
  7. member_since TIMESTAMP NOT NULL default current_timestamp,
  8. password_hash VARCHAR(100) default '',
  9. photo_url VARCHAR(255) NOT NULL,
  10. support BOOLEAN NOT NULL DEFAULT false,
  11. PRIMARY KEY (id),
  12. key ix_account_email (email), -- TODO use unique key
  13. key ix_account_phone_number (phone_number) -- TODO use unique key
  14. ) ENGINE=InnoDB;

company 有七个表:

  1. CREATE TABLE IF NOT EXISTS company (
  2. id VARCHAR(255),
  3. name VARCHAR(255) NOT NULL DEFAULT '',
  4. archived boolean DEFAULT false,
  5. default_timezone VARCHAR(255) NOT NULL DEFAULT '',
  6. default_day_week_starts VARCHAR(20) NOT NULL DEFAULT 'Monday',
  7. PRIMARY KEY (id)
  8. ) ENGINE=InnoDB;
  9. CREATE TABLE IF NOT EXISTS directory (
  10. id VARCHAR(255),
  11. company_id VARCHAR(255) NOT NULL,
  12. user_id VARCHAR(255) NOT NULL,
  13. internal_id VARCHAR(255) NOT NULL,
  14. PRIMARY KEY (id),
  15. key ix_directory_company_id (company_id),
  16. key ix_directory_user_id (user_id),
  17. key ix_directory_internal_id (internal_id),
  18. UNIQUE key ix_directory_company_user_internal_id (company_id, user_id, internal_id)
  19. ) ENGINE=InnoDB;
  20. CREATE TABLE IF NOT EXISTS admin (
  21. id VARCHAR(255),
  22. company_id VARCHAR(255) NOT NULL,
  23. user_id VARCHAR(255) NOT NULL,
  24. PRIMARY KEY (id),
  25. KEY ix_admin_company_id (company_id),
  26. KEY ix_admin_user_id (user_id),
  27. UNIQUE KEY ix_admin_company_user_id (company_id, user_id)
  28. ) ENGINE=InnoDB;
  29. CREATE TABLE IF NOT EXISTS team (
  30. id VARCHAR(255) NOT NULL,
  31. company_id VARCHAR(255) NOT NULL DEFAULT '',
  32. name VARCHAR(255) NOT NULL DEFAULT '',
  33. archived boolean NOT NULL DEFAULT false,
  34. timezone VARCHAR(255) NOT NULL DEFAULT '',
  35. day_week_starts VARCHAR(20) NOT NULL DEFAULT 'Monday',
  36. color VARCHAR(10) NOT NULL DEFAULT '#48B7AB',
  37. PRIMARY KEY (`id`),
  38. KEY ix_team_company_id (company_id)
  39. ) ENGINE=InnoDB;
  40. CREATE TABLE IF NOT EXISTS worker (
  41. id VARCHAR(255),
  42. team_id VARCHAR(255) NOT NULL,
  43. user_id VARCHAR(255) NOT NULL,
  44. PRIMARY KEY (id),
  45. KEY ix_team_team_id (team_id),
  46. KEY ix_team_user_id (user_id),
  47. UNIQUE KEY ix_worker_team_user_id (team_id, user_id)
  48. ) ENGINE=InnoDB;
  49. CREATE TABLE IF NOT EXISTS job (
  50. id VARCHAR(255) NOT NULL,
  51. team_id VARCHAR(255) NOT NULL DEFAULT '',
  52. name VARCHAR(255) NOT NULL DEFAULT '',
  53. archived boolean NOT NULL DEFAULT false,
  54. color VARCHAR(10) NOT NULL DEFAULT '#48B7AB',
  55. PRIMARY KEY (id),
  56. KEY ix_job_team_id (team_id)
  57. ) ENGINE=InnoDB;
  58. CREATE TABLE IF NOT EXISTS shift (
  59. id VARCHAR(255) NOT NULL,
  60. team_id VARCHAR(255) NOT NULL DEFAULT '',
  61. job_id VARCHAR(255) NOT NULL DEFAULT '',
  62. user_id VARCHAR(255) NOT NULL DEFAULT '',
  63. published boolean NOT NULL DEFAULT false,
  64. start TIMESTAMP NOT NULL DEFAULT current_timestamp,
  65. stop TIMESTAMP NOT NULL DEFAULT current_timestamp,
  66. PRIMARY KEY (id),
  67. KEY ix_job_shift_id (`job_id`),
  68. KEY ix_job_user_id (`user_id`)
  69. ) ENGINE=InnoDB;

SkyWalking

将下载好的 SkyWalking 解压到合适的位置,从终端中进入对应的目录,执行以下指令:

  1. macos@macosdeMacBook-Pro apache-skywalking-apm-bin % bin/startup.sh
  2. SkyWalking OAP started successfully!
  3. SkyWalking Web Application started successfully!

这样买点程序以及 web 端的 dashboard 都已经启动成功。
因为 SkyWalking 是通过字节码注入的方式运行的,所以微服务要使用这些功能在 IDEA 中也要进行一些相应的配置:
在 Run > Edit Configurations 中进行配置虚拟机选项,以及给每个服务通过环境变量的方式传入服务名。
image.png
其中的 SW_AGENT_NAME 对应的 SkyWalking 源文件中 /agent/config/agent.config 中的相应变量。
image.png

部署服务

1. 本机机密数据配置

在目录 /config/application.yml 文件中,因为涉密所以不能上传到 github 上,在 .gitignore
image.png

  1. # store your development credentials for spring app here
  2. # this file should and will not be checked into version control
  3. staffjoy:
  4. common:
  5. sentry-dsn: https://80bbf4ae778b525f9fe72e2813cd5246@sentry.io/1271087
  6. signing-secret: YOUR-SIGNING-SECRET
  7. intercom-access-token: YOUR-INTERCOM-ACCESS-TOKEN
  8. aliyun-access-key: YOUR-ALIYUN-ACCESS-KEY
  9. aliyun-access-secret: YOUR-ALIYUN-ACCESS-SECRET
  10. aliyun-sms-sign-name: YOUR-ALIYUN-SMS-SIGN-NAME
  11. intercom-app-id: YOUR-INTERCOM-APP-ID
  12. intercom-signing-secret: YOUR-INTERCOM-SIGNING-SECRET
  13. recaptcha-public: YOUR-RECAPTCHA-PUBLIC
  14. recaptcha-private: YOUR-RECAPTCHA-PRIVATE

需要将真实数据填入后将 .example 后缀去掉。在根目录下的 /config 目录下的文件,Spring 会认出来是配置文件

2. Faraday 配置 Review

Faraday 的配置文件在对应模块的 resources/application-dev.yml 文件中。包含的路由映射表为:

  1. mappings:
  2. -
  3. name: faraday_route
  4. host: faraday.staffjoy-v2.local
  5. destinations: httpbin.org
  6. -
  7. name: account_route
  8. host: account.staffjoy-v2.local
  9. destinations: localhost:8081
  10. -
  11. name: company_route
  12. host: company.staffjoy-v2.local
  13. destinations: localhost:8082
  14. -
  15. name: ical_route
  16. host: ical.staffjoy-v2.local
  17. destinations: localhost:8083
  18. -
  19. name: whoami_route
  20. host: whoami.staffjoy-v2.local
  21. destinations: localhost:8084
  22. timeout:
  23. connect: 10000
  24. read: 10000
  25. -
  26. name: superpowers_route
  27. host: superpowers.staffjoy-v2.local
  28. destinations: localhost:8085
  29. -
  30. name: www_route
  31. host: www.staffjoy-v2.local
  32. destinations: localhost:8086
  33. -
  34. name: myaccount_route
  35. host: myaccount.staffjoy-v2.local
  36. destinations: localhost:9000
  37. -
  38. name: app_route
  39. host: app.staffjoy-v2.local
  40. destinations: localhost:9001

3. 启动服务

启动顺序为:
mail-svc -> bot-svc -> account-svc -> company-svc -> whoami-svc -> www-svc -> faraday-svc
接下来是两个单页应用,通过终端去运行:
首先进入目录 /frontend/myaccount,然后输入指令

  1. // 加载依赖
  2. macos@macosdeMacBook-Pro myaccount % npm install
  3. // 启动服务
  4. macos@macosdeMacBook-Pro myaccount % npm start

然后是目录 /frontend/app, 输入同样的指令

  1. // 加载依赖
  2. macos@macosdeMacBook-Pro myaccount % npm install
  3. // 启动服务
  4. macos@macosdeMacBook-Pro myaccount % npm start

配置 StructHosts
截屏2021-12-18 00.49.39.png

  1. # My hosts
  2. 127.0.0.1 account.staffjoy-v2.local
  3. 127.0.0.1 faraday.staffjoy-v2.local
  4. 127.0.0.1 company.staffjoy-v2.local
  5. 127.0.0.1 ical.staffjoy-v2.local
  6. 127.0.0.1 whoami.staffjoy-v2.local
  7. 127.0.0.1 www.staffjoy-v2.local
  8. 127.0.0.1 app.staffjoy-v2.local
  9. 127.0.0.1 myaccount.staffjoy-v2.local
  10. 127.0.0.1 staffjoy-v2.local

至此,前后端服务都已经启动完成,可以通过浏览器输入网址进行访问了。

4. skywalking dashboard

默认页面为 localhost:8080

Docker 部署

容器概念

image.png
image.png
虚拟机通过引入 Hypervisor 层来做硬件的虚拟映射,在此基础上再运行 Guest OS。虚拟机具有强隔离性,但是重量级比较大,容器是软件级别的隔离,能够达到秒级的启动。
image.png
image.png
容器的镜像可以理解成为固化的操作系统,容器的操作系统只包含文件系统和二进制库,跟虚拟机的完整操作系统相比缺少内核,因为容器共享宿主机操作系统的内核。容器镜像采用分层的机制,好处就是能够做到镜像的重用。如果两个镜像的底层环境相同,那么可以公用底层镜像层。
image.png
image.png
Docker Compose 用于本地开发或者测试环境,可以进行容器的编排,提供一键部署和一键销毁应用的功能。

镜像构建 & Dockerfile 剖析

服务端以 bot-svc 为例,dockerfile 为:

  1. FROM java:8-jdk-alpine
  2. COPY ./target/bot-svc-1.0.0.jar /usr/app/
  3. WORKDIR /usr/app
  4. RUN sh -c 'touch bot-svc-1.0.0.jar'
  5. ENTRYPOINT ["java", "-jar", "bot-svc-1.0.0.jar"]

单页应用的 dockerfile 内容为:

  1. FROM node:alpine as builder
  2. WORKDIR '/build'
  3. COPY myaccount ./myaccount
  4. COPY resources ./resources
  5. COPY third_party ./third_party
  6. WORKDIR '/build/myaccount'
  7. RUN npm install
  8. RUN npm rebuild node-sass
  9. RUN npm run build
  10. RUN ls /build/myaccount/dist
  11. FROM nginx
  12. EXPOSE 80
  13. COPY --from=builder /build/myaccount/dist /usr/share/nginx/html

每一个 springboot 服务以及每一个单页应用都需要编写一个 dockerfile。

Docker Compose File 剖析

image.png
需要注意的是不同于本地开发环境部署,这里每个服务的端口号都是 80。这是因为容器中的网络是公用的,只需要一个容器入口端口即可。
在 staffjoy 根目录下有 docker compose 文件:

  1. version: '3.7'
  2. services:
  3. account-service:
  4. build: ./account-svc
  5. image: boboweike/account-svc
  6. environment:
  7. - SPRING_PROFILES_ACTIVE
  8. - SERVER_PORT
  9. - SIGNING_SECRET
  10. - SENTRY_DSN
  11. - EMAIL_SERVICE_ENDPOINT
  12. - COMPANY_SERVICE_ENDPOINT
  13. - BOT_SERVICE_ENDPOINT
  14. - INTERCOM_ACCESS_TOKEN
  15. - ACCOUNT_DATASOURCE_URL
  16. - ACCOUNT_DATASOURCE_USERNAME
  17. - ACCOUNT_DATASOURCE_PASSWORD
  18. depends_on:
  19. - bot-service
  20. - email-service
  21. networks:
  22. - internal_access
  23. - external_access # db access
  24. company-service:
  25. build: ./company-svc
  26. image: boboweike/company-svc
  27. environment:
  28. - SPRING_PROFILES_ACTIVE
  29. - SERVER_PORT
  30. - SIGNING_SECRET
  31. - SENTRY_DSN
  32. - EMAIL_SERVICE_ENDPOINT
  33. - ACCOUNT_SERVICE_ENDPOINT
  34. - BOT_SERVICE_ENDPOINT
  35. - COMPANY_DATASOURCE_URL
  36. - COMPANY_DATASOURCE_USERNAME
  37. - COMPANY_DATASOURCE_PASSWORD
  38. depends_on:
  39. - bot-service
  40. - email-service
  41. networks:
  42. - internal_access
  43. - external_access # db access
  44. bot-service:
  45. build: ./bot-svc
  46. image: boboweike/bot-svc
  47. environment:
  48. - SPRING_PROFILES_ACTIVE
  49. - SERVER_PORT
  50. - SENTRY_DSN
  51. - EMAIL_SERVICE_ENDPOINT
  52. - ACCOUNT_SERVICE_ENDPOINT
  53. - COMPANY_SERVICE_ENDPOINT
  54. - SMS_SERVICE_ENDPOINT
  55. depends_on:
  56. - email-service
  57. # - sms-svc # commented for demo
  58. networks:
  59. - internal_access
  60. email-service:
  61. build: ./mail-svc
  62. image: boboweike/mail-svc
  63. environment:
  64. - SPRING_PROFILES_ACTIVE
  65. - SERVER_PORT
  66. - SENTRY_DSN
  67. - ALIYUN_ACCESS_KEY
  68. - ALIYUN_ACCESS_SECRET
  69. networks:
  70. - internal_access
  71. - external_access # aliyun access
  72. # commented for demo
  73. # sms-service:
  74. # build: ./sms-svc
  75. # image: sms-svc
  76. # environment:
  77. # - SPRING_PROFILES_ACTIVE=test
  78. whoami-service:
  79. build: ./whoami-svc
  80. image: boboweike/whoami-svc
  81. environment:
  82. - SPRING_PROFILES_ACTIVE
  83. - SERVER_PORT
  84. - SENTRY_DSN
  85. - INTERCOM_APP_ID
  86. - INTERCOM_SIGNING_SECRET
  87. - ACCOUNT_SERVICE_ENDPOINT
  88. - COMPANY_SERVICE_ENDPOINT
  89. depends_on:
  90. - account-service
  91. - company-service
  92. networks:
  93. - internal_access
  94. # commented for demo
  95. # ical-service:
  96. # build: ./ical-svc
  97. # image: ical-svc
  98. # environment:
  99. # - SPRING_PROFILES_ACTIVE=test
  100. # depends_on:
  101. # - company-service
  102. www-service:
  103. build: ./web-app
  104. image: boboweike/www-svc
  105. environment:
  106. - SPRING_PROFILES_ACTIVE
  107. - SERVER_PORT
  108. - SENTRY_DSN
  109. - SIGNING_SECRET
  110. - ACCOUNT_SERVICE_ENDPOINT
  111. - COMPANY_SERVICE_ENDPOINT
  112. - EMAIL_SERVICE_ENDPOINT
  113. - RECAPTCHA_PUBLIC
  114. - RECAPTCHA_PRIVATE
  115. depends_on:
  116. - account-service
  117. - company-service
  118. - email-service
  119. networks:
  120. - internal_access
  121. faraday-service:
  122. build: ./faraday
  123. image: boboweike/faraday-svc
  124. ports:
  125. - 80:80
  126. environment:
  127. - SPRING_PROFILES_ACTIVE
  128. - SERVER_PORT
  129. - SENTRY_DSN
  130. - SIGNING_SECRET
  131. depends_on:
  132. - account-service
  133. - company-service
  134. - www-service
  135. - whoami-service
  136. # - ical-service # commented for demo
  137. - myaccount-service
  138. - app-service
  139. networks:
  140. - internal_access
  141. - external_access
  142. myaccount-service:
  143. build:
  144. context: ./frontend
  145. dockerfile: myaccount/Dockerfile
  146. image: boboweike/myaccount-spa
  147. networks:
  148. - internal_access
  149. app-service:
  150. build:
  151. context: ./frontend
  152. dockerfile: app/Dockerfile
  153. image: boboweike/app-spa
  154. networks:
  155. - internal_access
  156. networks:
  157. internal_access:
  158. internal: true
  159. external_access:

因为具体的配置数据涉密,所以将具体的配置值写在另外一个 .env 文件中:
image.png
当然在根目录的 .gitignore 文件中要明确该文件不能上传
image.png
docker-compose.yml 文件的具体结构主要分为三部分:

  • version
  • services
  • networks

对于每个 service 要配置一下内容:

  • build: 服务 dockerfile 的路径
  • image: 用户名/镜像名称
  • environment: 传入所需的环境变量
  • depends_on: 服务关系的指定,决定了启动服务的顺序
  • networks: 网络配置

    镜像构建

    在根目录下执行打包指令:
    mvn clean package -DskipTests
    
    执行 docker compose 指令:
    docker-compose build
    
    构建好之后通过 docker images 指令可以查看镜像情况,也可以通过 docker desktop 查看:
    macos@macosdeMBP staffjoy % docker images
    REPOSITORY                TAG       IMAGE ID       CREATED          SIZE
    boboweike/faraday-svc     latest    cf0bd503a720   11 seconds ago   227MB
    boboweike/app-spa         latest    7dcc1d2696f0   15 seconds ago   141MB
    boboweike/myaccount-spa   latest    c00841ffd14b   2 minutes ago    139MB
    boboweike/www-svc         latest    5818df8564c6   44 minutes ago   249MB
    boboweike/whoami-svc      latest    a246411a7f5d   44 minutes ago   220MB
    boboweike/account-svc     latest    4f5e959b8936   44 minutes ago   263MB
    boboweike/company-svc     latest    9172bfeadfb8   44 minutes ago   262MB
    boboweike/bot-svc         latest    7b6e24081427   44 minutes ago   220MB
    boboweike/mail-svc        latest    594794ff2e36   44 minutes ago   220MB
    docker/getting-started    latest    720f449e5af2   2 weeks ago      27.2MB
    
    image.png

    部署 MySQL

    因为在之前的本地开发环境部署过程中已经起过 MySQL 服务,这里略过,只需要让 docker 环境中的服务连接到数据库即可

    部署 staffjoy 服务

    在 staffjoy 根目录下使用指令:
    docker-compose up
    
    查看服务运行情况: ```bash macos@macosdeMBP staffjoy % docker-compose ps
          Name                          Command               State         Ports       
    

staffjoy_account-service_1 java -jar account-svc-1.0. … Up
staffjoy_app-service_1 /docker-entrypoint.sh ngin … Up
staffjoy_bot-service_1 java -jar bot-svc-1.0.0.jar Up
staffjoy_company-service_1 java -jar company-svc-1.0. … Up
staffjoy_email-service_1 java -jar mail-svc-1.0.0.jar Up
staffjoy_faraday-service_1 java -jar faraday-1.0.0.jar Up 0.0.0.0:80->80/tcp staffjoy_myaccount-service_1 /docker-entrypoint.sh ngin … Up
staffjoy_whoami-service_1 java -jar whoami-svc-1.0.0.jar Up
staffjoy_www-service_1 java -jar web-app-1.0.0.jar Up

<a name="d7dMq"></a>
### 启用 SwitchHosts
![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640080636461-d72759b2-7ee1-475d-b258-1f1a031a8a76.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=480&id=ucf988359&margin=%5Bobject%20Object%5D&name=image.png&originHeight=960&originWidth=1600&originalType=binary&ratio=1&rotation=0&showTitle=false&size=151380&status=done&style=none&taskId=ue64d337b-0264-4160-a9e1-c6765c78621&title=&width=800)<br />之后就可以通过 web 验证 
<a name="JjqAg"></a>
# 阿里云环境部署
<a name="a1Trf"></a>
## 云原生
定义为:基于微服务原理而开发的应用,以容器方式打包。在运行时,容器由运行于云基础设施之上的平台进行调度。应用开发采用持续交付和 DevOps 实践。
<a name="SJJeJ"></a>
## K8s
![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640095481723-08a1a1f1-f910-49e5-a9cc-157dbbc5ae75.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=554&id=u541f579e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1108&originWidth=1862&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1324949&status=done&style=none&taskId=ufeaa5ba3-2344-40a5-ad9e-3410f0a2043&title=&width=931)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640101343822-d35534e0-e6db-4364-b2a9-884ae034ee7d.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=650&id=u25064e37&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1300&originWidth=2362&originalType=binary&ratio=1&rotation=0&showTitle=false&size=999368&status=done&style=none&taskId=ud24c177c-c8a9-487f-a6b4-52a41a22ace&title=&width=1181)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640101665557-b98421cb-98f2-45d5-9ce0-3e5af8e54a27.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=580&id=u3ec6f307&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1160&originWidth=2054&originalType=binary&ratio=1&rotation=0&showTitle=false&size=378626&status=done&style=none&taskId=ue6126db4-1590-4aa0-8911-11ea5209526&title=&width=1027)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640101730845-11d2d7d5-fd57-4908-b3c6-98ef47a8d215.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=579&id=u5404c388&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1158&originWidth=2086&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1648635&status=done&style=none&taskId=u21c0738a-54ad-4b10-9e2c-c1c52e29ebd&title=&width=1043)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640101783214-92f04ad0-8af6-47a0-86b4-595b7118d88a.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=572&id=ueaa5671a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1144&originWidth=2110&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1304661&status=done&style=none&taskId=u94f7627a-e183-4bfa-97ec-c1fd0e077de&title=&width=1055)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640102255657-a9ceea03-a22e-4554-a49b-fea4a825b0ff.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=590&id=u30008271&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1180&originWidth=1796&originalType=binary&ratio=1&rotation=0&showTitle=false&size=444616&status=done&style=none&taskId=ue956fadb-63ea-49e1-947f-36997200073&title=&width=898)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640102327742-7ebcc90c-3000-447b-aabe-c7897c11df57.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=573&id=uf302e5a8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1146&originWidth=1940&originalType=binary&ratio=1&rotation=0&showTitle=false&size=481806&status=done&style=none&taskId=u5bf6da6a-5cf4-4fce-ba89-fa084159f80&title=&width=970)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640102570912-6cc93d78-624d-44c7-af45-0630691b1655.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=597&id=u8e3b727d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1194&originWidth=1728&originalType=binary&ratio=1&rotation=0&showTitle=false&size=484858&status=done&style=none&taskId=ubfd42ad9-ba42-4dcb-b73f-1ad9294240b&title=&width=864)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640102695812-dc3a9a7f-eda5-4fa6-96e0-ac1b98eebf35.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=562&id=u8e8bce5c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1124&originWidth=2250&originalType=binary&ratio=1&rotation=0&showTitle=false&size=495839&status=done&style=none&taskId=u1472debd-137c-4dc1-acd4-99cda31bed6&title=&width=1125)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640102749063-a67109b2-1a58-4d5b-8b17-1557ae403a0b.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=504&id=ud07f64d2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1008&originWidth=2286&originalType=binary&ratio=1&rotation=0&showTitle=false&size=454122&status=done&style=none&taskId=u84814dd1-8860-474c-b006-3622407efe6&title=&width=1143)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640103104615-1a78459f-9f6b-4d65-81b9-b588e3fae538.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=556&id=u14491f88&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1112&originWidth=1948&originalType=binary&ratio=1&rotation=0&showTitle=false&size=714230&status=done&style=none&taskId=u9d1815a9-0b27-438c-96fe-e6a2bb712e5&title=&width=974)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640103205784-9a007fa7-db16-4a9c-b04e-5409124d3364.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=529&id=u5e2f4590&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1058&originWidth=2062&originalType=binary&ratio=1&rotation=0&showTitle=false&size=302385&status=done&style=none&taskId=u3dd210fa-073f-4aef-b857-fb597356323&title=&width=1031)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640151463295-ac4a8045-a57e-4c2d-8124-6d02e47705b9.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=581&id=u12e52fda&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1162&originWidth=2164&originalType=binary&ratio=1&rotation=0&showTitle=false&size=477085&status=done&style=none&taskId=ua0b2d672-e21c-4425-b734-e68b4c9e71b&title=&width=1082)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640155173750-eaadc58e-b764-4a13-87ab-fdf2f5fddf2e.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=619&id=ubfe50e73&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1238&originWidth=1786&originalType=binary&ratio=1&rotation=0&showTitle=false&size=478012&status=done&style=none&taskId=u07cc802f-9d2f-4dee-b31b-924f18915e1&title=&width=893)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640155381648-12612b52-987c-4fcd-96b6-81cf993bc637.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=566&id=u1646e3ae&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1132&originWidth=1926&originalType=binary&ratio=1&rotation=0&showTitle=false&size=354702&status=done&style=none&taskId=u15a92f71-a38f-4c11-80d2-35a7cddfe24&title=&width=963)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640155399969-7515e657-1f24-4630-85d0-b135081df5e1.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=534&id=u6921ecd2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1068&originWidth=1874&originalType=binary&ratio=1&rotation=0&showTitle=false&size=315725&status=done&style=none&taskId=u237cf21b-c932-41e2-94f6-4d60920127a&title=&width=937)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640155622257-d18a8125-fd84-4f5e-8e56-ddbe83702d5a.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=594&id=u95157c87&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1188&originWidth=1958&originalType=binary&ratio=1&rotation=0&showTitle=false&size=394860&status=done&style=none&taskId=ud5290b08-a1b6-44f3-a712-506387a223d&title=&width=979)<br />k8s 给每个 Node 都搭建一个虚拟网桥(图中红色显示),然后给每个 pod 分配一个 ip 地址,同个 pod 内的容器之间通过 Localhost 就可以访问,添加 pod 以后会自动分配新的 ip 地址。<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640160659003-577898d3-c69b-4582-810b-ab73b4265c62.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=614&id=u6c7a88f8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1228&originWidth=2196&originalType=binary&ratio=1&rotation=0&showTitle=false&size=621536&status=done&style=none&taskId=u0587f367-8fe0-4d9b-a930-346dff5dfa9&title=&width=1098)<br />引入 service 来解决以下问题:

1. 各个 pod 是动态变化的,所以 ip 地址也是变化的,如何正确寻址?
1. 如何做负载均衡?

Service 可以屏蔽 pod 的地址变化,同时实现对目标 pod 的负载均衡和访问。客户端只需要访问 service,通过 service name 即可访问到目标服务。<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640161059938-c3dfbc10-bc86-42f0-b73b-b3d72d46f060.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=652&id=ucf5ae100&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1304&originWidth=1882&originalType=binary&ratio=1&rotation=0&showTitle=false&size=471538&status=done&style=none&taskId=uc11e3550-b005-4011-9a31-215c56b8976&title=&width=941)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640162053740-dbf132f2-8659-42d2-9d8a-5086580bad43.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=671&id=u4eecddb0&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1342&originWidth=1888&originalType=binary&ratio=1&rotation=0&showTitle=false&size=409390&status=done&style=none&taskId=u55081ce8-8b94-4e29-a0fb-cd60c9abf59&title=&width=944)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640162223701-50fe25a3-1218-4739-a434-aecd4f2a022a.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=627&id=u8c6d35ed&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1254&originWidth=1928&originalType=binary&ratio=1&rotation=0&showTitle=false&size=584041&status=done&style=none&taskId=ub5fdd824-6a4f-4110-afd8-68451389b36&title=&width=964)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640162461655-2ae37ebd-bfd5-4499-b1b9-fb6152e4c31d.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=608&id=ub35c441d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1216&originWidth=1654&originalType=binary&ratio=1&rotation=0&showTitle=false&size=507515&status=done&style=none&taskId=ue796abff-29b1-4dc6-8aea-0def4b1ed42&title=&width=827)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640162503650-d77423ef-3c3a-4397-aafb-7e44921767b1.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=669&id=u462edc00&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1338&originWidth=1664&originalType=binary&ratio=1&rotation=0&showTitle=false&size=555354&status=done&style=none&taskId=u555ca2e1-1fb0-4fef-9fa6-5f9c99cffc5&title=&width=832)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640162572560-7447ce7f-c850-4900-b0a5-5910b1103473.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=603&id=ueafa523e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1206&originWidth=1728&originalType=binary&ratio=1&rotation=0&showTitle=false&size=483875&status=done&style=none&taskId=u25dc7833-ece7-4559-bd9f-03910d39a7b&title=&width=864)
<a name="Yc3oL"></a>
## 本地 k8s 部署
![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640162973950-2fb029e2-71c4-420b-b009-c7cb1df122df.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=669&id=u7c5db81a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1338&originWidth=2056&originalType=binary&ratio=1&rotation=0&showTitle=false&size=866839&status=done&style=none&taskId=udf6d50b6-fded-45c9-96a5-e55f2ecf5b3&title=&width=1028)
<a name="s0J6R"></a>
### 配置文件
![image.png](https://cdn.nlark.com/yuque/0/2021/png/2194774/1640246013513-7a2a445b-dea7-4e37-b739-4efb9ae04a00.png#clientId=u65b246ec-2667-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=308&id=u100b6626&margin=%5Bobject%20Object%5D&name=image.png&originHeight=317&originWidth=280&originalType=binary&ratio=1&rotation=0&showTitle=false&size=24596&status=done&style=none&taskId=u96b08c96-1eba-437b-9cde-f31701a9eed&title=&width=272)<br />其中的 config.yaml 写入涉密信息<br />各个服务的配置文件中需要填入两部分内容,分别是 deployment 和 service,以 account-svc 为例:
```yaml
# https://matthewpalmer.net/kubernetes-app-developer/articles/kubernetes-apiversion-definition-guide.html
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: account-svc-deployment
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: account-svc
        env: test
    spec:
      containers:
        - name: account-svc
          image: boboweike/account-svc
          imagePullPolicy: Never
          ports:
            - name: http-port
              containerPort: 80
          envFrom:
            - configMapRef:
                name: common-config
---
apiVersion: v1
kind: Service
metadata:
  name: account-service
spec:
  selector:
    app: account-svc
    env: test
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

安装 k8s 环境

直接在 docker desktop 勾选即可。
image.png
安装 k8s 可视化服务
终端中输入:

macos@macosdeMacBook-Pro ~ % kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommended.yaml

安装好后使用代理登录:

macos@macosdeMacBook-Pro ~ % kubectl proxy                                                                                             
Starting to serve on 127.0.0.1:8001

点击以下链接:
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
首次登录的页面为:
image.png
在终端中输入指令:

macos@macosdeMacBook-Pro ~ % kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk'{print $1}')

把 token 字符串粘贴进去即可,页面如下:
image.png

镜像构建

  • mvn clean package -DskipTests
  • docker-compose build
  • docker images

    部署 MySQL 数据库

    主要就是将 mysql 服务设置为任何 ip 主机都可以访问并建立连接
    登录 MySQL ```bash mysql -u root -p

mysql> update user set host = ‘%’ where user = ‘root’; mysql> select user, host from user; +—————————+—————-+ | user | host | +—————————+—————-+ | root | % | | mysql.infoschema | localhost | | mysql.session | localhost | | mysql.sys | localhost | +—————————+—————-+

<a name="VZ5aN"></a>
### 部署 staffjoy (k8s)
在 ./k8s/test/config/ 目录下,执行指令:
```bash
macos@macosdeMBP config % kubectl apply -f config.yaml 
configmap/common-config created

可以通过指令查看配置情况:

macos@macosdeMBP config % kubectl get configmaps
NAME               DATA   AGE
common-config      22     9m18s
kube-root-ca.crt   1      163m

端口转发

查询faraday pod 名:

macos@macosdeMacBook-Pro config % kubectl get pods   
NAME                                        READY   STATUS    RESTARTS      AGE
account-svc-deployment-66d996748b-2gv6x     1/1     Running   1 (45s ago)   27h
app-spa-deployment-788c64bc7c-vstgm         1/1     Running   1 (45s ago)   27h
bot-svc-deployment-6bb664885b-vkkqn         1/1     Running   1 (45s ago)   27h
company-svc-deployment-67594649f8-8lc87     1/1     Running   1 (45s ago)   27h
email-svc-deployment-576b99d6d9-fc8px       1/1     Running   1 (45s ago)   27h
faraday-svc-deployment-7f56896ddf-jn5dd     1/1     Running   1 (45s ago)   27h
myaccount-spa-deployment-6cc5846895-gwcl8   1/1     Running   1 (45s ago)   27h
whoami-svc-deployment-7cfd774b5d-7gtd9      1/1     Running   1 (45s ago)   27h
www-web-deployment-b74c45dd6-fcvgp          1/1     Running   1 (45s ago)   27h

然后配置端口转发:

macos@macosdeMacBook-Pro config % sudo kubectl port-forward faraday-svc-deployment-7f56896ddf-jn5dd 80:80
Password:
Forwarding from 127.0.0.1:80 -> 80
Forwarding from [::1]:80 -> 80

命令行验证

macos@macosdeMacBook-Pro config % kubectl get pods -o wide
NAME                                        READY   STATUS    RESTARTS        AGE   IP          NODE             NOMINATED NODE   READINESS GATES
account-svc-deployment-66d996748b-2gv6x     1/1     Running   1 (3m41s ago)   27h   10.1.0.21   docker-desktop   <none>           <none>
app-spa-deployment-788c64bc7c-vstgm         1/1     Running   1 (3m41s ago)   27h   10.1.0.17   docker-desktop   <none>           <none>
bot-svc-deployment-6bb664885b-vkkqn         1/1     Running   1 (3m41s ago)   27h   10.1.0.18   docker-desktop   <none>           <none>
company-svc-deployment-67594649f8-8lc87     1/1     Running   1 (3m41s ago)   27h   10.1.0.27   docker-desktop   <none>           <none>
email-svc-deployment-576b99d6d9-fc8px       1/1     Running   1 (3m41s ago)   27h   10.1.0.20   docker-desktop   <none>           <none>
faraday-svc-deployment-7f56896ddf-jn5dd     1/1     Running   1 (3m41s ago)   27h   10.1.0.31   docker-desktop   <none>           <none>
myaccount-spa-deployment-6cc5846895-gwcl8   1/1     Running   1 (3m41s ago)   27h   10.1.0.23   docker-desktop   <none>           <none>
whoami-svc-deployment-7cfd774b5d-7gtd9      1/1     Running   1 (3m41s ago)   27h   10.1.0.22   docker-desktop   <none>           <none>
www-web-deployment-b74c45dd6-fcvgp          1/1     Running   1 (3m41s ago)   27h   10.1.0.30   docker-desktop   <none>           <none>
macos@macosdeMacBook-Pro config % kubectl get services
NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
account-service     ClusterIP   10.101.119.92    <none>        80/TCP         28h
app-service         ClusterIP   10.111.114.253   <none>        80/TCP         28h
bot-service         ClusterIP   10.101.245.172   <none>        80/TCP         28h
company-service     ClusterIP   10.110.159.235   <none>        80/TCP         28h
email-service       ClusterIP   10.105.117.193   <none>        80/TCP         28h
faraday-service     NodePort    10.102.219.97    <none>        80:30001/TCP   28h
kubernetes          ClusterIP   10.96.0.1        <none>        443/TCP        31h
myaccount-service   ClusterIP   10.108.247.178   <none>        80/TCP         28h
mysql-svc           ClusterIP   10.97.213.40     <none>        3306/TCP       28h
whoami-service      ClusterIP   10.100.236.242   <none>        80/TCP         28h
www-service         ClusterIP   10.107.100.198   <none>        80/TCP         28h
macos@macosdeMacBook-Pro config % kubectl get deployments
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
account-svc-deployment     1/1     1            1           27h
app-spa-deployment         1/1     1            1           27h
bot-svc-deployment         1/1     1            1           27h
company-svc-deployment     1/1     1            1           27h
email-svc-deployment       1/1     1            1           27h
faraday-svc-deployment     1/1     1            1           27h
myaccount-spa-deployment   1/1     1            1           27h
whoami-svc-deployment      1/1     1            1           27h
www-web-deployment         1/1     1            1           27h

清除服务

通过一下指令删除服务:

macos@macosdeMacBook-Pro config % kubectl delete deployments --all         
deployment.apps "account-svc-deployment" deleted
deployment.apps "app-spa-deployment" deleted
deployment.apps "bot-svc-deployment" deleted
deployment.apps "company-svc-deployment" deleted
deployment.apps "email-svc-deployment" deleted
deployment.apps "faraday-svc-deployment" deleted
deployment.apps "myaccount-spa-deployment" deleted
deployment.apps "whoami-svc-deployment" deleted
deployment.apps "www-web-deployment" deleted
macos@macosdeMacBook-Pro config % kubectl delete services --all
service "account-service" deleted
service "app-service" deleted
service "bot-service" deleted
service "company-service" deleted
service "email-service" deleted
service "faraday-service" deleted
service "kubernetes" deleted
service "myaccount-service" deleted
service "mysql-svc" deleted
service "whoami-service" deleted
service "www-service" deleted
macos@macosdeMacBook-Pro config % kubectl delete configmaps --all
configmap "common-config" deleted
configmap "kube-root-ca.crt" deleted