一、部署wordpress+mysql(NodePort方式) (1)创建命名空间:wordpress1 2 3 [root@m ~] namespace/wordpress created [root@m ~]
附:查看命名空间命令 kubectl get namespace kubectl get ns
(2)创建wordpress-db.yaml文件(mysql)创建wordpress-db.yaml文件,这里以mysql作为wordpress的db:
yaml内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 apiVersion: apps/v1beta1 kind: Deployment metadata: name: mysql-deploy namespace: wordpress labels: app: mysql spec: template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:5.6 imagePullPolicy: IfNotPresent ports: - containerPort: 3306 name: dbport env : - name: MYSQL_ROOT_PASSWORD value: rootPassW0rd - name: MYSQL_DATABASE value: wordpress - name: MYSQL_USER value: wordpress - name: MYSQL_PASSWORD value: wordpress volumeMounts: - name: db mountPath: /var/lib/mysql volumes: - name: db hostPath: path: /var/lib/mysql --- apiVersion: v1 kind: Service metadata: name: mysql namespace: wordpress spec: selector: app: mysql ports: - name: mysqlport protocol: TCP port: 3306 targetPort: dbport
(3)创建pod:mysql数据库根据wordpress-db.yaml配置,创建资源mysql数据库:
1 2 3 4 5 6 7 8 9 10 11 [root@m ~] deployment.apps/mysql-deploy created service/mysql created [root@m ~] [root@m ~] NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES mysql-deploy-78cd6964bd-zlcwb 1/1 Running 0 23m 192.168.190.81 w1 <none> <none> [root@m ~]
yaml中MySQL配置说明: 用户:root 密码:rootPassW0rd 数据库名称:wordpress 用户:wordpress 密码:wordpress
其他命令: kubectl get svc mysql -n wordpress kubectl describe svc mysql -n wordpress
(4)创建wordpress.yaml文件说明: 查看pod的IP命令:kubectl get pods -n wordpress -o wide IP地址:192.168.190.81 分布节点:w1(workpress)
创建wordpress.yaml文件:
yaml内容(记得一定要修改其中mysql的IP地址):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 apiVersion: apps/v1beta1 kind: Deployment metadata: name: wordpress-deploy namespace: wordpress labels: app: wordpress spec: template: metadata: labels: app: wordpress spec: containers: - name: wordpress image: wordpress imagePullPolicy: IfNotPresent ports: - containerPort: 80 name: wdport env: - name: WORDPRESS_DB_HOST value: 192.168 .190 .81 :3306 - name: WORDPRESS_DB_USER value: wordpress - name: WORDPRESS_DB_PASSWORD value: wordpress --- apiVersion: v1 kind: Service metadata: name: wordpress namespace: wordpress spec: type: NodePort selector: app: wordpress ports: - name: wordpressport protocol: TCP port: 80 targetPort: wdport
注意: 除了修改其中mysql的IP地址,还可以使用service的name:3306,如:mysql:3306 。
支持将192.168.190.81:3306改为mysql:3306。
(5)创建pod:wordpress根据wordpress.yaml配置,创建wordpress资源:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [root@m ~] deployment.apps/wordpress-deploy created service/wordpress created [root@m ~] [root@m ~] NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES mysql-deploy-78cd6964bd-zlcwb 1/1 Running 0 33m 192.168.190.81 w1 <none> <none> wordpress-deploy-dbd949575-nmrpg 1/1 Running 0 3m24s 192.168.80.216 w2 <none> <none> [root@m ~] [root@m ~] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE mysql ClusterIP 10.103.56.247 <none> 3306/TCP 33m wordpress NodePort 10.109.75.209 <none> 80:30467/TCP 3m45s [root@m ~]
说明: 如上,查看service,获取转发后的端口:30467。
(6) 浏览器 访问,并继续安装访问集群中任意宿主机节点的IP:30467:
访问URL:http://192.168.116.170:30467
进入如下界面:
(7)更换wordpress.yaml中的IP测试(这里省略)修改wordpress.yaml中mysql的IP地址,使用service的name:3306,如改为:mysql:3306 。
将192.168.190.81:3306 改为 mysql:3306,删除相关资源,重新执行步骤(4)—>(5)—>(6),发现依然可以访问。
(8)删除测试资源1 2 3 4 5 6 7 8 9 10 [root@m ~] [root@m ~] [root@m ~] [root@m ~] [root@m ~]
二、部署 SpringBoot 项目 2.1、准备Spring Boot项目 (1)创建Spring Boot项目(springboot-demo)创建Spring Boot项目过程等操作这里就全部省略了,主要提供下测试核心代码pom.xml、K8SController.java。
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <?xml version="1.0" encoding="UTF-8" ?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.2.0.RELEASE</version > <relativePath /> </parent > <groupId > com.gupao</groupId > <artifactId > springboot-demo</artifactId > <version > 0.0.1-SNAPSHOT</version > <name > springboot-demo</name > <description > Demo project for Spring Boot</description > <properties > <java.version > 1.8</java.version > </properties > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > <scope > test</scope > <exclusions > <exclusion > <groupId > org.junit.vintage</groupId > <artifactId > junit-vintage-engine</artifactId > </exclusion > </exclusions > </dependency > </dependencies > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > </plugin > </plugins > </build > </project >
K8SController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.gupao.springbootdemo.controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController public class K8SController { @RequestMapping("/k8s") public String k8s () { return "<h1>Hello K8S ...</h1><br/><br/>测试成功!" ; } }
(2)启动测试项目启动测试项目,确保springBoot项目本身没有问题。
访问地址:http://localhost:8080/k8s
(3)本地打包项目(springboot-demo)在项目springboot-demo的根目录,执行以下打包命令:
mvn clean package
(4)将项目包生成镜像上传springboot-demo-0.0.1-SNAPSHOT.jar到linux,生成镜像,运行项目容器:
1 2 3 4 5 6 7 8 [root@m ~] [root@m ~] [root@m springboot-demo] 总用量 17140 -rw-r--r--. 1 root root 17547533 1月 10 13:40 springboot-demo-0.0.1-SNAPSHOT.jar
(5)为项目创建Dockerfile1 [root@m springboot-demo]
内容:
1 2 3 FROM openjdk:8-jre-alpine COPY springboot-demo-0.0.1-SNAPSHOT.jar /springboot-demo.jar ENTRYPOINT ["java" ,"-jar" ,"/springboot-demo.jar" ]
(6)根据Dockerfile创建image1 [root@m springboot-demo]
(7)使用docker run创建container1 2 3 [root@m springboot-demo] 19bd517788ce64807a411e2e3b431c1d4154e6117934a743635c9a4d1783feef [root@m springboot-demo]
附: 运行容器指定端口(-p参数): docker run -di --name=s1 -p 8080:8080 springboot-demo-image
(8)访问测试1 2 3 4 5 [root@m springboot-demo] [root@m springboot-demo]
(9)将镜像推送到私有仓库说明: 如果没有私有镜像仓库,可自行创建私有镜像仓库,参考博文:Docker搭建官方私有仓库registry及相关配置
需要注意:每个 虚拟机节点都要在/etc/docker/daemon.json 文件配置私有仓库,否则后续步骤pull镜像会失败。
(1)添加如下:
`{"insecure-registries":["192.168.116.161:5000"]}`
(2)然后重启服务:
[root@localhost java\]# systemctl daemon-reload
[root@localhost java\]# systemctl restart docker
① 标记镜像为私有仓库的镜像使用 docker tag 命令标记镜像,将其归入某一仓库。
1 2 [root@m springboot-demo] [root@m springboot-demo]
② 推送镜像到私有仓库1 2 3 4 5 6 7 8 [root@m springboot-demo] The push refers to repository [192.168.116.170:5000/springboot-demo-image] 2f28b827deb4: Pushed edd61588d126: Pushed 9b9b7f3d56a0: Pushed f1b5933fe4b5: Pushed v1.0: digest: sha256:ea7998365883f5ed9dedde32e85983aa47a848448827a3717b5cd4fd7329afc7 size: 1159 [root@m springboot-demo]
③ 浏览器查看私有仓库访问URL:http://192.168.116.170:5000/v2/_catalog
(10)创建nginx ingress controller ① 创建并编辑mandatory.yaml文件以Deployment方式创建Pod,该Pod为Ingress Nginx Controller,要想让外界访问,可以通过Service的NodePort或者HostPort方式,这里选择HostPort,比如指定worker01运行
创建并编辑mandatory.yaml文件:
mandatory.yaml内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 apiVersion: v1 kind: Namespace metadata: name: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx --- kind: ConfigMap apiVersion: v1 metadata: name: nginx-configuration namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx --- kind: ConfigMap apiVersion: v1 metadata: name: tcp-services namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx --- kind: ConfigMap apiVersion: v1 metadata: name: udp-services namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx --- apiVersion: v1 kind: ServiceAccount metadata: name: nginx-ingress-serviceaccount namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: nginx-ingress-clusterrole labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx rules: - apiGroups: - "" resources: - configmaps - endpoints - nodes - pods - secrets verbs: - list - watch - apiGroups: - "" resources: - nodes verbs: - get - apiGroups: - "" resources: - services verbs: - get - list - watch - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - "extensions" - "networking.k8s.io" resources: - ingresses verbs: - get - list - watch - apiGroups: - "extensions" - "networking.k8s.io" resources: - ingresses/status verbs: - update --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: Role metadata: name: nginx-ingress-role namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx rules: - apiGroups: - "" resources: - configmaps - pods - secrets - namespaces verbs: - get - apiGroups: - "" resources: - configmaps resourceNames: - "ingress-controller-leader-nginx" verbs: - get - update - apiGroups: - "" resources: - configmaps verbs: - create - apiGroups: - "" resources: - endpoints verbs: - get --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: RoleBinding metadata: name: nginx-ingress-role-nisa-binding namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: nginx-ingress-role subjects: - kind: ServiceAccount name: nginx-ingress-serviceaccount namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: nginx-ingress-clusterrole-nisa-binding labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: nginx-ingress-clusterrole subjects: - kind: ServiceAccount name: nginx-ingress-serviceaccount namespace: ingress-nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx-ingress-controller namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx template: metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx annotations: prometheus.io/port: "10254" prometheus.io/scrape: "true" spec: terminationGracePeriodSeconds: 300 serviceAccountName: nginx-ingress-serviceaccount hostNetwork: true nodeSelector: name: ingress kubernetes.io/os: linux containers: - name: nginx-ingress-controller image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1 args: - /nginx-ingress-controller - --configmap=$(POD_NAMESPACE)/nginx-configuration - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - --udp-services-configmap=$(POD_NAMESPACE)/udp-services - --publish-service=$(POD_NAMESPACE)/ingress-nginx - --annotations-prefix=nginx.ingress.kubernetes.io securityContext: allowPrivilegeEscalation: true capabilities: drop: - ALL add: - NET_BIND_SERVICE runAsUser: 33 env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace ports: - name: http containerPort: 80 - name: https containerPort: 443 livenessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 lifecycle: preStop: exec: command: - /wait-shutdown ---
说明: 在上面的mandatory.yaml中,
(1)使用HostPort方式运行,需要增加配置(上面已配置)hostNetwork: true (2)搜索nodeSelector,并且要确保w1(worker01)节点上的80和443端口没有被占用。 (3)需要注意,这里镜像拉取需要较长的时间。 ② 给worker01节点打lable在master节点,给worker01节点打lable,确保nginx-controller运行到w1节点上:
1 2 3 [root@m test ] node/w1 labeled [root@m test ]
③ 应用mandatory.yaml1 2 3 4 5 6 7 8 9 10 11 12 [root@m test ] namespace/ingress-nginx created configmap/nginx-configuration created configmap/tcp-services created configmap/udp-services created serviceaccount/nginx-ingress-serviceaccount created clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created role.rbac.authorization.k8s.io/nginx-ingress-role created rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created deployment.apps/nginx-ingress-controller created [root@m test ]
④ 查看所有资源/pod说明: 等待全部资源创建完成,需要等待时间很长。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@m test ] NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-ingress-controller-7c66dcdd6c-nttzp 1/1 Running 0 37m 192.168.116.171 w1 <none> <none> [root@m test ] [root@m test ] NAME READY STATUS RESTARTS AGE pod/nginx-ingress-controller-7c66dcdd6c-nttzp 1/1 Running 0 36m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx-ingress-controller 1/1 1 1 36m NAME DESIRED CURRENT READY AGE replicaset.apps/nginx-ingress-controller-7c66dcdd6c 1 1 1 36m [root@m test ]
⑤ 查看worker01节点的80和443端口在worker01节点,查看80和443端口使用情况(可看到nginx占用):
1 2 3 [root@w1 ~] [root@w1 ~]
(11)编写Kubernetes配置文件(springboot-demo.yaml,包含ingress规则)1 [root@m springboot-demo]
yaml内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 apiVersion: apps/v1 kind: Deployment metadata: name: springboot-demo spec: selector: matchLabels: app: springboot-demo replicas: 1 template: metadata: labels: app: springboot-demo spec: containers: - name: springboot-demo image: 192.168 .116 .170 :5000/springboot-demo-image:v1.0 ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: springboot-demo spec: ports: - port: 80 protocol: TCP targetPort: 8080 selector: app: springboot-demo --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: springboot-demo spec: rules: - host: k8s.demo.gper.club http: paths: - path: / backend: serviceName: springboot-demo servicePort: 80
(12)创建pod、service、ingress说明: 这里需要注意下,我们在每个节点可以尝试手动拉取下我们的项目镜像(加快速度、也是测试): [root@m ~]# docker pull 192.168.116.170:5000/springboot-demo-image:v1.0
1 2 3 4 5 [root@m springboot-demo] deployment.apps/springboot-demo created service/springboot-demo created ingress.extensions/springboot-demo created [root@m springboot-demo]
(13)查看pod相关 ① 查看pod1 2 3 [root@m springboot-demo] NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES springboot-demo-76c9685f5-4d2m5 1/1 Running 0 7m32s 192.168.190.84 w1 <none> <none>
① 集群内测试访问springboot-demo的pod注意: 命令中192.168.190.86为springboot-demo的pod的IP(非集群节点IP)。
1 2 3 [root@m springboot-demo] <h1>Hello K8S ...</h1><br/><br/>测试成功! [root@m springboot-demo]
① 查看service1 2 3 4 5 6 [root@m springboot-demo] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d15h springboot-demo ClusterIP 10.100.135.47 <none> 80/TCP 44m tomcat-service ClusterIP 10.110.130.134 <none> 80/TCP 74m [root@m springboot-demo]
(14)扩容测试(5个副本)1 [root@m springboot-demo]
(15)查看ingress1 2 3 4 5 [root@m springboot-demo] NAME HOSTS ADDRESS PORTS AGE nginx-ingress tomcat.jack.com 80 66m springboot-demo k8s.demo.gper.club 80 37m [root@m springboot-demo]
(15)外部浏览器测试(通过ingress配置的域名访问)① 修改hosts文件,配置域名解析
修改 windows 系统的hosts文件(C:\Windows\System32\drivers\etc\hosts),添加dns解析:
注: 其中,192.168.116.171为worker01节点IP,其他IP不可以,因为我们在创建时就指定了创建在worker01节点。
②浏览器访问
访问URL:http://k8s.demo.gper.club/k8s
(16)删除测试资源1 2 3 4 5 6 7 8 9 10 11 [root@m test ] [root@m test ] [root@m test ] [root@m test ] [root@m test ] [root@m test ]
三、部署Nacos+spring cloud项目 3.1、安装nacos参见博文:Linux(Centos7.0)安装nacos服务器
说明: nacos在这里的作用等效与zookeeper,负责服务注册与发现。
3.2、准备测试资源准备两个Spring Boot项目,工程名为user和order,表示两个服务。
3.2.1、user工程以下只提供核心代码资源:
(1)pom.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 <?xml version="1.0" encoding="UTF-8" ?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.2.1.RELEASE</version > <relativePath /> </parent > <groupId > com.gupao</groupId > <artifactId > user</artifactId > <version > 0.0.1-SNAPSHOT</version > <name > user</name > <description > Demo project for Spring Boot</description > <properties > <java.version > 1.8</java.version > </properties > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > <scope > test</scope > <exclusions > <exclusion > <groupId > org.junit.vintage</groupId > <artifactId > junit-vintage-engine</artifactId > </exclusion > </exclusions > </dependency > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-alibaba-nacos-discovery</artifactId > </dependency > </dependencies > <dependencyManagement > <dependencies > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-dependencies</artifactId > <version > Greenwich.SR1</version > <type > pom</type > <scope > import</scope > </dependency > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-alibaba-dependencies</artifactId > <version > 0.9.0.RELEASE</version > <type > pom</type > <scope > import</scope > </dependency > </dependencies > </dependencyManagement > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > </plugin > </plugins > </build > </project >
(2)application.yml1 2 3 4 5 6 7 8 9 10 11 spring: cloud: nacos: discovery: server-addr: 192.168 .116 .170 :8848 application: name: user server: port: 8080
(3)TestController.java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 package net.xiaof.user.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.discovery.DiscoveryClient;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.net.URI;import java.net.URL;import java.net.URLConnection;import java.util.List;@RestController @RequestMapping("/user") public class TestController { @Autowired private DiscoveryClient discoveryClient; @RequestMapping("/test") public List<ServiceInstance> findServiceInstance () throws Exception{ List<ServiceInstance> list=this .discoveryClient.getInstances("order" ); ServiceInstance serviceInstance=list.get(0 ); URI uri = serviceInstance.getUri(); System.out.println(uri.toString()); this .testUrl(uri.toString()); return list; } private void testUrl (String urlString) { URL url; try { url = new URL (urlString); URLConnection co = url.openConnection(); co.connect(); System.out.println("连接可用" ); } catch (Exception e1) { System.out.println("连接打不开!" ); url = null ; } } }
(4)启动类:UserApplication1 2 3 4 5 6 7 8 9 10 11 12 13 package net.xiaof.user;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class UserApplication { public static void main (String[] args) { SpringApplication.run(UserApplication.class, args); } }
3.2.2、order工程以下只提供核心代码资源:
(1)pom.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 <?xml version="1.0" encoding="UTF-8" ?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.2.1.RELEASE</version > <relativePath /> </parent > <groupId > com.gupao</groupId > <artifactId > order</artifactId > <version > 0.0.1-SNAPSHOT</version > <name > order</name > <description > Demo project for Spring Boot</description > <properties > <java.version > 1.8</java.version > </properties > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > <scope > test</scope > <exclusions > <exclusion > <groupId > org.junit.vintage</groupId > <artifactId > junit-vintage-engine</artifactId > </exclusion > </exclusions > </dependency > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-alibaba-nacos-discovery</artifactId > </dependency > </dependencies > <dependencyManagement > <dependencies > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-dependencies</artifactId > <version > Greenwich.SR1</version > <type > pom</type > <scope > import</scope > </dependency > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-alibaba-dependencies</artifactId > <version > 0.9.0.RELEASE</version > <type > pom</type > <scope > import</scope > </dependency > </dependencies > </dependencyManagement > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > </plugin > </plugins > </build > </project >
(2)application.yml1 2 3 4 5 6 7 8 9 10 11 spring: cloud: nacos: discovery: server-addr: 192.168 .116 .170 :8848 application: name: order server: port: 9090
(3)启动类:OrderApplication.javaorder工程核心只有启动类,目的是注册到nacos。
1 2 3 4 5 6 7 8 9 10 11 12 13 package net.xiaof.order;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class OrderApplication { public static void main (String[] args) { SpringApplication.run(OrderApplication.class, args); } }
3.3、传统方式部署本地测试user和order工程,和上传至linux服务器测试基本一样(这里省略上传至linux测试)。
(1)分别启动测试user和order工程(不分顺序) (2)查看nacos服务列表
(3)浏览器访问测试(成功)访问user服务,user服务会从nacos中找到order服务。
请求地址: http://localhost:8080/user/test
3.4、K8s方式部署 3.4.1、项目生成jar,并上传至linux (1)项目生成jar在user工程和order工程根目录,分别执行命令:
(2)上传jar至对应目录①上传user-0.0.1-SNAPSHOT.jar至user目录:
1 2 3 4 5 6 7 8 [root@w1 test ] [root@w1 test ] [root@w1 user] [root@w1 user] 总用量 32552 -rw-r--r--. 1 root root 33330501 1月 11 23:12 user-0.0.1-SNAPSHOT.jar [root@w1 user]
② 上传order-0.0.1-SNAPSHOT.jar至order目录:
1 2 3 4 5 6 7 8 [root@w1 test ] [root@w1 test ] [root@w1 order] [root@w1 order] 总用量 32552 -rw-r--r--. 1 root root 33330501 1月 11 23:12 order-0.0.1-SNAPSHOT.jar [root@w1 order]
3.4.2、分别创建Dockerfile,并将jar打成镜像分别在对应的目录,编写Dockerfile。
(1)在user目录创建Dockerfile① 创建Dockerfile
内容:
1 2 3 FROM openjdk:8-jre-alpine COPY user-0.0.1-SNAPSHOT.jar /user.jar ENTRYPOINT ["java" ,"-jar" ,"/user.jar" ]
② 根据Dockerfile创建image:
1 2 3 4 5 6 7 8 9 10 [root@m order] [root@m user] [root@m user] user-image v1.0 a4509b9e6a69 20 seconds ago 118MB [root@m user]
(2)在order目录创建Dockerfile:① 创建Dockerfile
内容:
1 2 3 FROM openjdk:8-jre-alpine COPY order-0.0.1-SNAPSHOT.jar /order.jar ENTRYPOINT ["java" ,"-jar" ,"/order.jar" ]
② 根据Dockerfile创建image:
1 2 3 4 5 6 7 8 9 10 [root@m order] [root@m order] [root@m order] order-image v1.0 ba6836f20aa5 16 seconds ago 118MB [root@m order]
3.4.3、启动docker私有仓库1 2 3 4 5 6 [root@m ~] registry [root@m ~] [root@m ~] 029261e06978 registry:latest "/entrypoint.sh /etc…" 34 hours ago Up 57 seconds 0.0.0.0:5000->5000/tcp registry [root@m ~]
3.4.4、上传镜像至docker私有仓库 (1)上传user镜像至私有仓库1 2 3 4 5 6 7 8 9 10 [root@m test ] [root@m test ] [root@m test ] The push refers to repository [192.168.116.170:5000/user-image] ad9d37a5f027: Pushed edd61588d126: Mounted from springboot-demo-image 9b9b7f3d56a0: Mounted from springboot-demo-image f1b5933fe4b5: Mounted from springboot-demo-image v1.0: digest: sha256:5c45150f4d0e5ab115c598d8e86d400bd680389480145c0cd6fcf74c4257b511 size: 1159 [root@m test ]
(2)上传order镜像至私有仓库1 2 3 4 5 [root@m test ] [root@m test ]
3.4.5、创建nginx ingress controller (1)创建并编辑mandatory.yaml文件以Deployment方式创建Pod,该Pod为Ingress Nginx Controller,要想让外界访问,可以通过Service的NodePort或者HostPort方式,这里选择HostPort,比如指定worker01运行
创建并编辑mandatory.yaml文件:
mandatory.yaml内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 apiVersion: v1 kind: Namespace metadata: name: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx --- kind: ConfigMap apiVersion: v1 metadata: name: nginx-configuration namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx --- kind: ConfigMap apiVersion: v1 metadata: name: tcp-services namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx --- kind: ConfigMap apiVersion: v1 metadata: name: udp-services namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx --- apiVersion: v1 kind: ServiceAccount metadata: name: nginx-ingress-serviceaccount namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: nginx-ingress-clusterrole labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx rules: - apiGroups: - "" resources: - configmaps - endpoints - nodes - pods - secrets verbs: - list - watch - apiGroups: - "" resources: - nodes verbs: - get - apiGroups: - "" resources: - services verbs: - get - list - watch - apiGroups: - "" resources: - events verbs: - create - patch - apiGroups: - "extensions" - "networking.k8s.io" resources: - ingresses verbs: - get - list - watch - apiGroups: - "extensions" - "networking.k8s.io" resources: - ingresses/status verbs: - update --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: Role metadata: name: nginx-ingress-role namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx rules: - apiGroups: - "" resources: - configmaps - pods - secrets - namespaces verbs: - get - apiGroups: - "" resources: - configmaps resourceNames: - "ingress-controller-leader-nginx" verbs: - get - update - apiGroups: - "" resources: - configmaps verbs: - create - apiGroups: - "" resources: - endpoints verbs: - get --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: RoleBinding metadata: name: nginx-ingress-role-nisa-binding namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: nginx-ingress-role subjects: - kind: ServiceAccount name: nginx-ingress-serviceaccount namespace: ingress-nginx --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: nginx-ingress-clusterrole-nisa-binding labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: nginx-ingress-clusterrole subjects: - kind: ServiceAccount name: nginx-ingress-serviceaccount namespace: ingress-nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx-ingress-controller namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx template: metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx annotations: prometheus.io/port: "10254" prometheus.io/scrape: "true" spec: terminationGracePeriodSeconds: 300 serviceAccountName: nginx-ingress-serviceaccount hostNetwork: true nodeSelector: name: ingress kubernetes.io/os: linux containers: - name: nginx-ingress-controller image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1 args: - /nginx-ingress-controller - --configmap=$(POD_NAMESPACE)/nginx-configuration - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - --udp-services-configmap=$(POD_NAMESPACE)/udp-services - --publish-service=$(POD_NAMESPACE)/ingress-nginx - --annotations-prefix=nginx.ingress.kubernetes.io securityContext: allowPrivilegeEscalation: true capabilities: drop: - ALL add: - NET_BIND_SERVICE runAsUser: 33 env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace ports: - name: http containerPort: 80 - name: https containerPort: 443 livenessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 readinessProbe: failureThreshold: 3 httpGet: path: /healthz port: 10254 scheme: HTTP periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 lifecycle: preStop: exec: command: - /wait-shutdown ---
说明: 在上面的mandatory.yaml中,
(1)使用HostPort方式运行,需要增加配置(上面已配置)hostNetwork: true (2)搜索nodeSelector,并且要确保w1(worker01)节点上的80和443端口没有被占用。 (3)需要注意,这里镜像拉取需要较长的时间。 (2)给worker01节点打lable在master节点,给worker01节点打lable,确保nginx-controller运行到w1节点上:
1 2 3 [root@m test ] node/w1 labeled [root@m test ]
(3)应用mandatory.yaml1 2 3 4 5 6 7 8 9 10 11 12 [root@m test ] namespace/ingress-nginx created configmap/nginx-configuration created configmap/tcp-services created configmap/udp-services created serviceaccount/nginx-ingress-serviceaccount created clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created role.rbac.authorization.k8s.io/nginx-ingress-role created rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created deployment.apps/nginx-ingress-controller created [root@m test ]
(4)查看所有资源/pod说明: 等待全部资源创建完成,需要等待时间很长。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@m test ] NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-ingress-controller-7c66dcdd6c-nttzp 1/1 Running 0 37m 192.168.116.171 w1 <none> <none> [root@m test ] [root@m test ] NAME READY STATUS RESTARTS AGE pod/nginx-ingress-controller-7c66dcdd6c-nttzp 1/1 Running 0 36m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx-ingress-controller 1/1 1 1 36m NAME DESIRED CURRENT READY AGE replicaset.apps/nginx-ingress-controller-7c66dcdd6c 1 1 1 36m [root@m test ]
(5)查看worker01节点的80和443端口1 2 3 4 5 在worker01节点,查看80和443端口使用情况(`可看到nginx占用`): [root@w1 ~] [root@w1 ~]
3.4.6、创建Kubernetes配置文件说明: 这里的user.yaml和order.yaml,不知道什么原因,在本地idea中启动测试可以正常注册到nacos(linux)中;但是部署到k8s集群中,创建的user和order的pod无法注册到nacos中,只有 当nacos和user、order的pod在k8s集群的同一节点的时候,才能正常注册到nacos中,但是k8s各集群节点又是互通的!!!
此外,我们也可以采用在user.yaml、order.yaml中开启hostNetwork(pod共享宿主机IP和端口,生产模式不推荐),即配置spec.template.metadata.spec.hostNetwork=true,这种配置下,不要求nacos和user、order的pod在同一k8s集群节点,依然可以注册到nacos中。
(1)为user创建yaml文件内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 apiVersion: apps/v1 kind: Deployment metadata: name: user spec: selector: matchLabels: app: user replicas: 1 template: metadata: labels: app: user spec: containers: - name: user image: 192.168 .116 .170 :5000/user-image:v1.0 ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: user spec: ports: - port: 80 protocol: TCP targetPort: 8080 selector: app: user --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: user spec: rules: - host: k8s.demo.gper.club http: paths: - path: / backend: serviceName: user servicePort: 80
(2)为order创建yaml文件内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 apiVersion: apps/v1 kind: Deployment metadata: name: order spec: selector: matchLabels: app: order replicas: 1 template: metadata: labels: app: order spec: containers: - name: order image: 192.168 .116 .170 :5000/order-image:v1.0 ports: - containerPort: 9090 --- apiVersion: v1 kind: Service metadata: name: order spec: ports: - port: 80 protocol: TCP targetPort: 9090 selector: app: order
3.4.7、创建并查看pod (0)删除nacos上之前本地测试的服务由于nacos服务没有重启,所以服务还在,需要手动删除服务,或者重启nacos服务器也可以。
(1)创建pod1 2 3 4 5 6 7 8 9 10 [root@m test ] deployment.apps/user created service/user created ingress.extensions/user created [root@m test ] [root@m test ] deployment.apps/order created service/order created [root@m test ]
(2)查看pod相关1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [root@m order] NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES order-b9c986677-5rms2 1/1 Running 0 75m 192.168.190.101 w1 <none> <none> user-6ffb6cb6b4-5ctrl 1/1 Running 0 140m 192.168.190.100 w1 <none> <none> [root@m order] [root@m order] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d13h order ClusterIP 10.98.28.100 <none> 80/TCP 69m user ClusterIP 10.107.38.198 <none> 80/TCP 135m [root@m order] [root@m user] NAME HOSTS ADDRESS PORTS AGE user k8s.demo.gper.club 80 4m49s [root@m user]
(3)查看nacos上的服务说明: 这里的user.yaml和order.yaml,不知道什么原因,在本地idea中启动测试可以正常注册到nacos(linux)中;但是部署到k8s集群中,创建的user和order的pod无法注册到nacos中,只有 当nacos和user、order的pod在k8s集群的同一节点的时候,才能正常注册到nacos中,但是k8s各集群节点又是互通的!!!
注意: 如果看不到服务,请查看相关日志:
(1)查看下pod创建日志:kubectl describe pod 容器name (2)查看下pod启动日志:kubectl logs 容器name (3)删除各节点镜像: docker rmi 192.168.116.170:5000/user-image:v1.0 docker rmi 192.168.116.170:5000/order-image:v1.0 nacos上的服务(这里的nacos和user、order的pod在k8s集群的同一节点):
(4)k8s集群内访问测试1 2 3 4 5 6 7 8 9 10 11 [root@m order] NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES order-b9c986677-5rms2 1/1 Running 0 75m 192.168.190.101 w1 <none> <none> user-6ffb6cb6b4-5ctrl 1/1 Running 0 140m 192.168.190.100 w1 <none> <none> [root@m order] [root@m order] [{"serviceId" :"order" ,"host" :"192.168.190.101" ,"port" :9090,"secure" :false ,"metadata" :{"nacos.instanceId" :"192.168.190.101#9090#DEFAULT#DEFAULT_GROUP@@order" ,"nacos.weight" :"1.0" ,"nacos.cluster" :"DEFAULT" ,"nacos.healthy" :"true" ,"preserved.register.source" :"SPRING_CLOUD" },"uri" :"http://192.168.190.101:9090" ,"instanceId" :null,"scheme" :null}] [root@m order]
3.4.8、外部浏览器测试(通过ingress配置的域名访问)① 修改hosts文件,配置域名解析
修改windows系统的hosts文件(C:\Windows\ System32 \drivers\etc\hosts),添加dns解析:
注: 其中,192.168.116.171为worker01节点IP,其他IP不可以,因为我们在创建时就指定了创建在worker01节点。
②浏览器访问(通过ingress规则里配置的域名访问)
访问URL:http://k8s.demo.gper.club/user/test
3.4.9、测试hostNetwork模式我们在这里user.yaml、order.yaml中开启hostNetwork(pod共享宿主机IP和端口,生产模式不推荐 ),即配置spec.template.metadata.spec.hostNetwork=true,这种配置下,不要求nacos和user、order的pod在同一k8s集群节点,依然可以注册到nacos中。
(1)删除user、order的pod及相关1 2 3 4 5 [root@m test ] [root@m test ] [root@m test ] [root@m test ]
(2)修改user.yaml、order.yaml在user.yaml、order.yaml中,分别添加如下配置:
1 spec.template.metadata.spec.hostNetwork=true
(3)再次依次执行3.4.7~3.4.8测试(成功)
3.4.10、删除测试资源1 2 3 4 5 6 7 8 9 10 11 12 13 [root@m test ] [root@m test ] [root@m test ] [root@m test ] [root@m test ] [root@m test ] [root@m test ] [root@m test ]