1.把它们放到kubernetes集群运行我们要考虑什么问题?
- 哪些服务适合单独成为一个pod?哪些服务适合在一个pod中?
- 在一个pod里面的服务如何彼此访问?他们的服务如何对外提供服务?
- 单独的pod如何对外提供服务?
- 哪个服务作为整个服务的入口,入口服务如何对外提供服务?
2. 搞定配置
配置的模板已经为大家准备好了,但是还需要大家做一下处理才能使用哦,参考下面脚本:
$ cd ~/kubernetes-starter/service-config/
$ ls
api-gateway.yaml message-service.yaml
course-service.yaml user-service.yaml
#替换变量 - (hub.mooc.com:8080是我的环境的镜像仓库地址,大家修改为各自的仓库)
$ sed -i 's/{{HUB}}/hub.haojing.com:8080/g' *
3. 部署服务
部署前准备:
- 要过一遍我们现有的代码配置,看看是否有需要修改的,修改后需要新生成镜像
- 要启动好微服务依赖的服务,像zookeeper,mysql,registry等
目前镜像是这样的:
目前的话,一个pod分一个服务先将基础组件的mysql服务起来,在node1的节点上
首先部署eureka服务,
eureka服务的yml文件:
server:
port: 8000
eureka:
instance:
# hostname: ${host.name}
hostname: localhost
prefer-ip-address: true
instance-id: ${spring.cloud.client.ipAddress}:${server.port}
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# defaultZone: http://localhost:8000/eureka/
k8s上的部署yaml文件:
这个文件会起一个servcies和一个deployment,他的服务端口是8000,他的容器端口是8000,对外提供访问的端口nodeport是8000
apiVersion: v1
kind: Service
metadata:
labels:
app: eureka-service
name: eureka-service
spec:
ports:
- port: 8000
protocol: TCP
targetPort: 8000
nodePort: 8000
selector:
app: eureka-service
type: NodePort
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: eureka-service-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: eureka-service
spec:
containers:
- name: eureka-service
image: hub.haojing.com/haojing/eureka-app:1.0
ports:
- containerPort: 8000
imagePullSecrets:
- name: regsecret
kubectl apply -f eureka-service.yaml
在启动的时候有端口的限制,我们改一下api-server:
修改配置后我们重新启动api-server服务
systemctl daemon-reload
service kube-apiserver restart
访问:
刚刚开始部署的时候他无法拉取镜像,在工作节点上手动拉取了镜像才能部署成功,工作节点的docker 必须要登陆,因为要拉的是私库的镜像,按照道理来说master节点是不需要拉取镜像的,所以他可以不用登陆吧,
网关服务的yml文件,service port是服务端口,服务端口是80,容器端口是8080,对外的nodeport特使80,然后还定义了一个
deployment
apiVersion: v1
kind: Service
metadata:
labels:
app: api-gateway
name: api-gateway
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
nodePort: 80
selector:
app: api-gateway
type: NodePort
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: api-gateway-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: api-gateway
spec:
containers:
- name: api-gateway
image: hub.haojing.com/haojing/api-app:1.0
ports:
- containerPort: 8080
项目的yml文件:
spring:
application:
name: api-gateway
datasource:
driver-class-name: com.mysql.jdbc.Driver
# url: jdbc:mysql://${mysql.address}:3306/sys-user?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
url: jdbc:mysql://192.168.237.129:3306/sys-user?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
username: root
password: 133309
eureka:
client:
serviceUrl:
defaultZone: http://eureka-service:8000/eureka/
# defaultZone: http://${eureka.host}:8000/eureka/
# defaultZone: http://localhost:8000/eureka/
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ipAddress}:${server.port}
server:
port: 8080
#zuul:
## prefix: /cloud-action
# ignored-services: "*"
# routes:
# user-service: /user-service/**
# ls-prevention-check: /prevention-check/**
zuul:
host:
connect-timeout-millis: 15000
socket-timeout-millis: 60000
routes:
user-service:
path: /user-service/**
serviceId: user-service
# url: http://user-service:8002
sensitiveHeaders:
customSensitiveHeaders: true
add-proxy-headers: true
retryable: true
# blog-service:
# path: /blogapi/**
# serviceId: blog-service
# sensitiveHeaders:
ribbon:
ConnectTimeout: 250 # 连接超时时间(ms)
ReadTimeout: 2000 # 通信超时时间(ms)
OkToRetryOnAllOperations: true # 是否对所有操作重试
MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数
MaxAutoRetries: 1 # 同一实例的重试次数
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000 # 熔断超时时长:6000ms
出现同样的错误,无法自动拉取私库的镜像,是不是master 上的docker 没有登陆的原因。把master也登陆上去吧
还是不行。
直接查看docker的日志:
journalctl -u docker -f
拉取镜像失败
然后百度了一下发现自己踩坑了,k8s拉取私有仓库需要额外的配置
对于公司内部的项目, 我们不可能使用公有开放的镜像仓库, 一般情况可能会花钱买 docker
私仓服务, 或者说自己在服务器上搭建自己的私仓, 但不管怎样, 我们如何让k8s
能够拉取私有仓库的镜像
1. 登录docker
镜像仓库,这个在任意的node节点上登陆就行了。如果报443端口的错误就要配置daemon.json文件了
docker login hub.haojing.com
之后输入密码就可以了, 这个时候我们可以在配置文件中查看登录情况
cat ~/.docker/config.json
这个时候我们虽然可以通过docker pull
命令拉取镜像, 但无法通过k8s
创建pod
方式拉取
2. 生成密钥secret
kubectl create secret docker-registry regsecret --docker-server=hub.haojing.com --docker-username=admin --docker-password=xxxx --docker-email=wanglove@qq.com
其中:
regsecret: 指定密钥的键名称, 可自行定义
--docker-server: 指定docker
仓库地址
--docker-username: 指定docker
仓库账号
--docker-password: 指定docker
仓库密码
--docker-email: 指定邮件地址(选填)
可以看到密钥生成了
可以看到当前除了默认的密钥, 还有我们刚才生成的. 另外要注意的是, 该密钥只能在对应namespace
使用, 也就是这里的default
, 如果需要用到其他namespace
, 比如说test
, 就需要在生成的时候指定参数 -n test
yml
文件加入密钥参数
其中imagePullSecrets
是声明拉取镜像时需要指定密钥, regsecret
必须和上面生成密钥的键名一致, 另外检查一下pod
和密钥是否在同一个namespace
, 之后k8s
便可以拉取镜像
第二种方法(我用的是这种方法)
将登陆后生成的~/.docker/config.json配置文件进行编码:
base64 -w 0 ~/.docker/config.json
创建Secret:
### vim secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: regsecret
namespace: default
data:
.dockerconfigjson: ewoJImF1dGhzIjogewoJCSJodWIuaGFvamluZy5jb20iOiB7CgkJCSJhdXRoIjogIllXUnRhVzQ2TVRNek16QTUiCgkJfQoJfSwKCSJIdHRwSGVhZGVycyI6IHsKCQkiVXNlci1BZ2VudCI6ICJEb2NrZXItQ2xpZW50LzE5LjAzLjIgKGxpbnV4KSIKCX0KfQ==
type: kubernetes.io/dockerconfigjson
kubectl create -f secret.yaml
ok,在创建部署的文件里面给他加上密钥配置就好了
然后部署:
ok,没有问题
下面继续部署user服务
部署的yml文件:注意这个user服务属于内部服务,不需要指定nodeport供外部访问
apiVersion: v1
kind: Service
metadata:
labels:
app: user-service
name: user-service
namespace: default
spec:
ports:
- name: user-service-port
port: 8082
protocol: TCP
targetPort: 8082
selector:
app: user-service
sessionAffinity: None
type: ClusterIP
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: user-service-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: hub.haojing.com/haojing/user-app:1.0
ports:
- containerPort: 8082
imagePullSecrets:
- name: regsecret
项目的yml文件:
eureka:
client:
serviceUrl:
# defaultZone: http://${eureka.host}:8000/eureka/
defaultZone: http://eureka-service:8000/eureka/
# defaultZone: http://localhost:8000/eureka/
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ipAddress}:${server.port}
spring:
application:
name: user-service
cloud:
loadbalancer:
retry:
enabled: true
datasource:
driver-class-name: com.mysql.jdbc.Driver
# url: jdbc:mysql://${mysql.address}:3306/sys-user?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
url: jdbc:mysql://192.168.237.129:3306/sys-user?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
username: root
password: 133309
mybatis:
mapper-locations: classpath:mapper/*
type-aliases-package: com.wx.userservice.domain.*
mapper:
mappers: com.wx.userservice.utils.IBaseDao
identity: MYSQL
server:
port: 8002
ribbon:
ConnectTimeout: 250 # 连接超时时间(ms)
ReadTimeout: 2000 # 通信超时时间(ms)
OkToRetryOnAllOperations: true # 是否对所有操作重试
MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数
MaxAutoRetries: 1 # 同一实例的重试次数
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000 # 熔断超时时长:6000ms
ok,部署
每个服务都能跑起来,但是调用服务之间的调用就会出错,他会去拿eureka上默认分配的名字去调用,而不是我们事先定好的application的名字
这是什么原因呢?因为如果请求经过zuul网关转发到后台的服务提供者的话,
如果服务提供者和zuul网关在同一台机器上,大家都是localhost的域名,那就没问题,能发现服务;
如果服务提供者和zuul网关不在同一台机器上,会报一个没找到服务的异常,原因是根据localhost和端口没有找到相应的服务。
此时,一种解决方法是让服务提供者上报自己的 ip地址,并显示在Eureka的注册列表中。
然后重新部署;
可以看到拿的使IP了,swagger也能访问了
进入到pod中
kubectl exec -it api-gateway-deployment-86dbbcbc5c-dpnwr -n default /bin/bash
看看网关的路由功能是否能用
好的,能调到user服务的接口,继续部署uaa服务
部署yml文件:
apiVersion: v1
kind: Service
metadata:
labels:
app: uaa-service
name: uaa-service
spec:
ports:
- port: 8081
protocol: TCP
targetPort: 8081
selector:
app: uaa-service
type: ClusterIP
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: uaa-service-deployment
spec:
replicas: 1
template:
metadata:
labels:
app: uaa-service
spec:
containers:
- name: uaa-service
image: hub.haojing.com/haojing/uaa-app:1.0
ports:
- containerPort: 8081
imagePullSecrets:
- name: regsecret
项目的yml:
spring:
application:
name: uaa-service
datasource:
driver-class-name: com.mysql.jdbc.Driver
# url: jdbc:mysql://${mysql.address}:3306/sys-user?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
url: jdbc:mysql://192.168.237.129:3306/sys-user?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
username: root
password: 133309
mybatis:
mapper-locations: classpath:mapper/*
type-aliases-package: com.wx.uaaservice.domain.*
mapper:
mappers: com.wx.uaaservice.utils.IBaseDao
identity: MYSQL
server:
port: 8001
eureka:
client:
serviceUrl:
# defaultZone: http://${eureka.host}:8000/eureka/
defaultZone: http://eureka-service:8000/eureka/
# defaultZone: http://localhost:8000/eureka/
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ipAddress}:${server.port}
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 5000