本文记录将极客时间,杨波,Spring Boot 与 Kubernetes 云原生微服务实践 专栏的示例项目 Staffjoy, 部署到本地 Kubernetes 环境的过程。
环境:
CPU: Intel(R) Core(TM) i5-10400 CPU @ 2.90GHz 2.90 GHz
内存: 16.0 GB
操作系统: Windows 10 专业版,21H2,19044.1645
Docker Desktop For Windows: 4.8.1 (78998)
Kubernetes: v1.24.0
1 配置 k8s
本节配置 k8s/test 目录下的文件,本文中的 k8s 配置文件路径默认为相对 k8s/test 目录的路径
1)config/config.yaml
复制 config/config.yaml.example 文件为 config/config.yaml 文件,然后修改其内容,如下所示:
apiVersion: v1kind: ConfigMapmetadata:name: common-configdata:SPRING_PROFILES_ACTIVE: testSERVER_PORT: "80"EMAIL_SERVICE_ENDPOINT: http://email-serviceCOMPANY_SERVICE_ENDPOINT: http://company-serviceACCOUNT_SERVICE_ENDPOINT: http://account-serviceBOT_SERVICE_ENDPOINT: http://bot-serviceSMS_SERVICE_ENDPOINT: http://sms-serviceSENTRY_DSN: https://80aaf4ae889b414f9fe72e3904cd5246@sentry.io/1380198SIGNING_SECRET: your_signing_secretINTERCOM_ACCESS_TOKEN: YOUR_INTERCOM_ACCESS_TOKENINTERCOM_APP_ID: TBDINTERCOM_SIGNING_SECRET: TBDALIYUN_ACCESS_KEY: YOUR_ALIYUN_ACCESS_KEYALIYUN_ACCESS_SECRET: YOUR_ALIYUN_ACCESS_SECRETRECAPTCHA_PUBLIC: test-recaptcha-publicRECAPTCHA_PRIVATE: test-recaptcha-privateACCOUNT_DATASOURCE_URL: jdbc:mysql://mysql-svc/staffjoy_account?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8ACCOUNT_DATASOURCE_USERNAME: rootACCOUNT_DATASOURCE_PASSWORD: "12345678"COMPANY_DATASOURCE_URL: jdbc:mysql://mysql-svc/staffjoy_company?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8COMPANY_DATASOURCE_USERNAME: rootCOMPANY_DATASOURCE_PASSWORD: "12345678"
2)mysql-svc.yaml
# https://cloud.google.com/blog/products/gcp/kubernetes-best-practices-mapping-external-serviceskind: ServiceapiVersion: v1metadata:name: mysql-svcspec:type: ClusterIPports:- port: 3306targetPort: 3306---# https://confluence.atlassian.com/jirakb/configuring-database-connection-results-in-error-host-xxxxxxx-is-not-allowed-to-connect-to-this-mysql-server-358908249.htmlkind: EndpointsapiVersion: v1metadata:name: mysql-svcsubsets:- addresses:- ip: 127.0.0.1 # UPDATE TO YOUR MYSQL IP ADDRESSports:- port: 3306
2 本地 Kubernetes 环境搭建
本文使用 Docker Desktop for Windows 的 Kubernetes 搭建本地 kubernetes 环境。
2.1 安装 Docker Desktop for Windows 及 Kubernetes
Docker Desktop for Windows 下载地址: https://docs.docker.com/desktop/windows/install/

Docker Desktop 及 Kubernetes 版本
安装并启动 Docker Desktop 后,点击【设置>Kubernetes>Enable Kubernetes】,启用 Kubernetes。
Docker Desktop 启用 Kubernetes
2.2 校验 Kubernetes 安装
1) Docker Desktop 启用 Kubernetes Context
Doccker Desktop 可能安装多个 Kubernetes Context,在使用 Kubernetes 前,确保 Docker Desktop 当前运行的 Kubernetes Context 是我们想要的,本文使用的 Kubernetes Context 为 docker-desktop。
Docker Desktop 设置 Kubernetes Context 为 docker-desktop
2) 查看 Kubernetes 版本
命令: kubectl version —output=yaml
执行结果:
clientVersion:buildDate: "2022-05-03T13:46:05Z"compiler: gcgitCommit: 4ce5a8954017644c5420bae81d72b09b735c21f0gitTreeState: cleangitVersion: v1.24.0goVersion: go1.18.1major: "1"minor: "24"platform: windows/amd64kustomizeVersion: v4.5.4serverVersion:buildDate: "2022-05-03T13:38:19Z"compiler: gcgitCommit: 4ce5a8954017644c5420bae81d72b09b735c21f0gitTreeState: cleangitVersion: v1.24.0goVersion: go1.18.1major: "1"minor: "24"platform: linux/amd64
3) 查看当前 Kubernetes Context
命令: kubectl config current-context
执行结果:
docker-desktop
4) 查看 Kubernetes cluster 信息
命令: kubectl cluster-info
执行结果:
Kubernetes control plane is running at https://kubernetes.docker.internal:6443CoreDNS is running at https://kubernetes.docker.internal:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxyTo further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
5) 查看 Kubernetes node 信息
命令: kubectl get nodes
执行结果:
NAME STATUS ROLES AGE VERSIONdocker-desktop Ready control-plane 39m v1.24.0
2.3 【失败,搁置】安装和访问 Kubernetes Dashboard
访问 Kubernetes 有命令行(kubectl)和 图形界面(Kubernetes Dashboard)2 种方式,为便于使用 Kubernetes,安装 Kubernetes Dashboard。
Kubernetes Dashboard is a general purpose, web-based UI for Kubernetes clusters. It allows users to manage applications running in the cluster and troubleshoot them, as well as manage the cluster itself.
1) 安装 Kubernetes Dashboard
命令:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.1/aio/deploy/recommended.yaml
执行结果:
namespace/kubernetes-dashboard createdserviceaccount/kubernetes-dashboard createdservice/kubernetes-dashboard createdsecret/kubernetes-dashboard-certs createdsecret/kubernetes-dashboard-csrf createdsecret/kubernetes-dashboard-key-holder createdconfigmap/kubernetes-dashboard-settings createdrole.rbac.authorization.k8s.io/kubernetes-dashboard createdclusterrole.rbac.authorization.k8s.io/kubernetes-dashboard createdrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard createdclusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard createddeployment.apps/kubernetes-dashboard createdservice/dashboard-metrics-scraper createddeployment.apps/dashboard-metrics-scraper created
3 构建 Docker 镜像
- mvn clean package -DskipTests
- docker-compose build
-
4 部署mysql数据库
staffjoy_account
- staffjoy_company
授予ip访问权限:
use mysql;grant all privileges on *.* to root@10.9.30.122 identified by '12345678' with grant option;
5 部署Staffjoy(k8s/test)
cd k8s/test
- kubectl apply -f .\config\config.yaml
- kubectl apply -f .
6 端口转发
1)查看 faraday-svc-deployment 的 pod 名称
命令:kubectl get pods
执行结果:
2)启用 faraday-svc-deployment 端口转发NAME READY STATUS RESTARTS AGEaccount-svc-deployment-966756658-qcpsg 1/1 Running 22 (8m9s ago) 93mapp-spa-deployment-64746d8ddf-s22mt 0/1 ErrImageNeverPull 0 4m46sbot-svc-deployment-d8979c94d-bgt7c 1/1 Running 0 4m46scompany-svc-deployment-ff9cfdd78-kfm64 1/1 Running 3 (3m35s ago) 4m46semail-svc-deployment-88579d685-4tvsv 1/1 Running 0 4m46sfaraday-svc-deployment-7d6798cbf7-8ntg7 1/1 Running 0 4m46smyaccount-spa-deployment-5c964c788c-hz5fd 0/1 ErrImageNeverPull 0 4m46swhoami-svc-deployment-8455464c58-p55tm 1/1 Running 0 4m46swww-web-deployment-745984b974-xbh99 1/1 Running 0 4m46s
命令:kubectl port-forward faraday-svc-deployment-7d6798cbf7-8ntg7 80:80
执行结果:Forwarding from 127.0.0.1:80 -> 80Forwarding from [::1]:80 -> 80
7 启用 SwitchHosts
8 Kubernetes 命令行校验
1) 查看 pods
命令: kubectl get pods -o wide
执行结果:NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESaccount-svc-deployment-966756658-qcpsg 1/1 Running 22 (33m ago) 118m 10.1.0.14 docker-desktop <none> <none>app-spa-deployment-64746d8ddf-s22mt 0/1 ErrImageNeverPull 0 29m 10.1.0.16 docker-desktop <none> <none>bot-svc-deployment-d8979c94d-bgt7c 1/1 Running 0 29m 10.1.0.15 docker-desktop <none> <none>company-svc-deployment-ff9cfdd78-kfm64 1/1 Running 3 (28m ago) 29m 10.1.0.18 docker-desktop <none> <none>email-svc-deployment-88579d685-4tvsv 1/1 Running 0 29m 10.1.0.17 docker-desktop <none> <none>faraday-svc-deployment-7d6798cbf7-8ntg7 1/1 Running 0 29m 10.1.0.20 docker-desktop <none> <none>myaccount-spa-deployment-5c964c788c-hz5fd 0/1 ErrImageNeverPull 0 29m 10.1.0.23 docker-desktop <none> <none>whoami-svc-deployment-8455464c58-p55tm 1/1 Running 0 29m 10.1.0.21 docker-desktop <none> <none>www-web-deployment-745984b974-xbh99 1/1 Running 0 29m 10.1.0.22 docker-desktop <none> <none>
可以看到 app-spa-deployment 和 myaccount-spa-deployment 2 个 deployment 没有部署成功。
2)查看 services
命令: kubectl get services
执行结果:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEaccount-service ClusterIP 10.108.154.240 <none> 80/TCP 3h8mapp-service ClusterIP 10.98.87.248 <none> 80/TCP 3h8mbot-service ClusterIP 10.96.205.124 <none> 80/TCP 3h8mcompany-service ClusterIP 10.106.6.147 <none> 80/TCP 3h8memail-service ClusterIP 10.99.105.209 <none> 80/TCP 3h8mfaraday-service NodePort 10.110.85.46 <none> 80:30001/TCP 3h8mkubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5h51mmyaccount-service ClusterIP 10.98.23.240 <none> 80/TCP 3h8mmysql-svc ClusterIP 10.101.216.158 <none> 3306/TCP 3h8mwhoami-service ClusterIP 10.98.48.102 <none> 80/TCP 3h8mwww-service ClusterIP 10.110.232.73 <none> 80/TCP 3h8m
3)查看 deployments
命令: kubectl get deployments
执行结果:
NAME READY UP-TO-DATE AVAILABLE AGEaccount-svc-deployment 1/1 1 1 121mapp-spa-deployment 0/1 1 0 33mbot-svc-deployment 1/1 1 1 33mcompany-svc-deployment 1/1 1 1 33memail-svc-deployment 1/1 1 1 33mfaraday-svc-deployment 1/1 1 1 33mmyaccount-spa-deployment 0/1 1 0 33mwhoami-svc-deployment 1/1 1 1 33mwww-web-deployment 1/1 1 1 33m
可以看到 app-spa-deployment 和 myaccount-spa-deployment 2 个 deployment 没有部署成功。
9 Kubetnetes Dashboard 校验
10 Staffjoy 校验
在浏览器访问 http://www.staffjoy-v2.local/(或 http://www.staffjoy-v2.local:30001/),输入邮箱 zixiu@jskillcloud.com,然后点击【SIGN UP FOR FREE】,跳转到注册确认页

在Staffjoy Web 主页(http://www.staffjoy-v2.local/)注册账号

注册确认页
查看 staffjoy_account 数据库,account 表,发现新增了 1 条记录,说明 Staffjoy 的 mysql-svc 正常运行。

注册账号后,staffjoy_account.account 表新增了 1 条记录
11 清理
1)kubectl delete deployments —all
执行结果:
deployment.apps "account-svc-deployment" deleteddeployment.apps "app-spa-deployment" deleteddeployment.apps "bot-svc-deployment" deleteddeployment.apps "company-svc-deployment" deleteddeployment.apps "email-svc-deployment" deleteddeployment.apps "faraday-svc-deployment" deleteddeployment.apps "myaccount-spa-deployment" deleteddeployment.apps "whoami-svc-deployment" deleteddeployment.apps "www-web-deployment" deleted
2)kubectl delete services —all
执行结果:
service "account-service" deletedservice "app-service" deletedservice "bot-service" deletedservice "company-service" deletedservice "email-service" deletedservice "faraday-service" deletedservice "kubernetes" deletedservice "myaccount-service" deletedservice "mysql-svc" deletedservice "whoami-service" deletedservice "www-service" deleted
3)kubectl delete configmaps —all
执行结果:
configmap "common-config" deleted
configmap "kube-root-ca.crt" deleted
12 除障记录
12.1 config/config.yaml 文件中数字类型属性值要用引号包围
12.1.1 问题描述
config/config.yaml 文件中,数字类型属性值若写成:
ACCOUNT_DATASOURCE_PASSWORD: 12345678
则,执行命令: kubectl apply -f .\config\config.yaml,会出错:
Error from server (BadRequest): error when creating ".\\config\\config.yaml": ConfigMap in version "v1" cannot be handled as a ConfigMap: json: cannot unmarshal number into Go struct field ConfigMap.data o
f type string
12.1.2 解法
将数字类型属性值用引号包围起来:
ACCOUNT_DATASOURCE_PASSWORD: “12345678”
12.2 mysql-svc Endpoints 的 ip 不能为环回地址
12.2.1 问题描述
mysql-svc.yaml 文件:
# https://cloud.google.com/blog/products/gcp/kubernetes-best-practices-mapping-external-services
kind: Service
apiVersion: v1
metadata:
name: mysql-svc
spec:
type: ClusterIP
ports:
- port: 3306
targetPort: 3306
---
# https://confluence.atlassian.com/jirakb/configuring-database-connection-results-in-error-host-xxxxxxx-is-not-allowed-to-connect-to-this-mysql-server-358908249.html
kind: Endpoints
apiVersion: v1
metadata:
name: mysql-svc
subsets:
- addresses:
- ip: 127.0.0.1 # UPDATE TO YOUR MYSQL IP ADDRESS
ports:
- port: 3306
此时执行命令: “kubectl apply -f .”,会出错:
Error from server (Invalid): error when creating "mysql-svc.yaml": Endpoints "mysql-svc" is invalid: subsets[0].addresses[0].ip: Invalid value: "127.0.0.1": may not be in the loopback range (127.0.0.0/8, :
:1/128)
12.2.2 解法
用 ipconfig 命令查看本地 ip 地址,然后 Endpoints 的 ip 设置成本地 ip 地址。

用 ipconfig 命令查看本地 ipv4 地址
修改后的 mysql-svc.yaml 文件:
# https://cloud.google.com/blog/products/gcp/kubernetes-best-practices-mapping-external-services
kind: Service
apiVersion: v1
metadata:
name: mysql-svc
spec:
type: ClusterIP
ports:
- port: 3306
targetPort: 3306
---
# https://confluence.atlassian.com/jirakb/configuring-database-connection-results-in-error-host-xxxxxxx-is-not-allowed-to-connect-to-this-mysql-server-358908249.html
kind: Endpoints
apiVersion: v1
metadata:
name: mysql-svc
subsets:
- addresses:
- ip: 10.9.30.122 # UPDATE TO YOUR MYSQL IP ADDRESS
ports:
- port: 3306
12.3 Deployment 配置与 Kubernetes API 版本不兼容
12.3.1 问题描述
以 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
此时执行命令: “kubectl apply -f .”,会出错:
resource mapping not found for name: "account-svc-deployment" namespace: "" from "account-svc.yaml": no matches for kind "Deployment" in version "extensions/v1beta1"
ensure CRDs are installed first
12.3.2 原因
这个问题是 account-svc-deployment 这个 Deployment 的配置与当前运行的 Kubernetes API 版本不兼容导致的。
12.3.3 解法
1)查看 Deployment 对应的 API 版本
命令:kubectl api-resources
执行结果:
从执行结果中找到 KIND 列为 Deployment 的行,该行的 APIVERSION 列为 apps/v1,将 account-svc.yaml 文件中 account-svc-deployment 的 apiVersion 字段值改成 apps/v1。
2)查找指定 API 版本的 Deployment 的配置文档,按文档修改 Deployment 配置
对于 apiVersion apps/v1 的 Deployment 的配置,需要增加 spec.selector 字段
3)最终的 account-svc.yaml 文件
最终的 account-svc.yaml 文件如下:
# https://matthewpalmer.net/kubernetes-app-developer/articles/kubernetes-apiversion-definition-guide.html
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
name: account-svc-deployment
spec:
replicas: 1
selector:
matchLabels:
app: account-svc
env: test
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
4) 其他服务配置文件参照 account-svc.yaml 文件修改
