美文网首页Kubernetes
五、Kubernetes 实战项目搭建

五、Kubernetes 实战项目搭建

作者: Suny____ | 来源:发表于2020-04-03 16:48 被阅读0次

    1、步骤梳理

    本章节将主要围绕实战搭建项目为主,既然是实战,就得考虑好需要准备哪些东西,所有的准备都做好了,才能正确的往下进行。本章节目的在于把之前学习的知识点进行一次串联,加深一下映像!

    本次实战准备了三个案例:

    • WordPress + MySQL
    • Spring Boot项目
    • Nacos服务注册与发现

    每个案例都会以不同的通信方式去部署。

    1.1、服务搭建步骤

    • 确定自己当前的服务有哪些
    • 服务是官方的还是自定义的
      • 若是自定义则需要编写Dockerfile
      • 自定义的镜像上传镜像仓库 【可选】
    • 服务隔离【可选】
      • 服务很多的情况下,为了方便管理,一般会创建一个独立的命名空间为这个项目使用
    • 创建服务所需的 YAML 文件
    • 服务发现的策略
      • 通过 Service NodePort实现集群内部通信
      • 通过 Ingress 实现集群内外通信
    • 服务监控、日志收集等 【暂不实现】
      • 本章不演示,因为目前还没有开始学习到这部分,等到后面再慢慢分享!

    2、项目搭建

    2.1、WordPress + MySQL

    2.1.1 搭建说明

    • 2个服务都使用官方 image,所以无需编写Dockerfile
    • 创建命名空间
    • 编写 YAML 文件
      • mysql 服务我们只给wordpress访问,所以直接用 ClusterIP方式实现集群内通信即可。
      • wordpress 服务需要外部访问,使用NodePort方式进行通信。

    2.1.2 服务搭建

    • 创建 WordPress 命名空间

      [root@master-kubeadm-k8s wordpress]# kubectl create namespace wordpress
      namespace/wordpress created
      
    • 创建 wordpress-db.yaml 文件

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: mysql-deploy
        namespace: wordpress                                  # 指定命名空间
        labels:
          app: mysql
      spec:
        selector:
          matchLabels:
            app: mysql
        template:
          metadata:
            labels:
              app: mysql
          spec:
            nodeSelector: 
              name: ingress                 # 这里增加 节点选择器 , 前面章节我们为 worker01 节点创建了 name: ingress 标签,这里用一下
            containers:
            - name: mysql
              image: mysql:5.6
              imagePullPolicy: IfNotPresent   # 拉取策略,本地有则使用本地镜像,不拉取
              ports:
              - containerPort: 3306
                name: dbport
              env:
              - name: MYSQL_ROOT_PASSWORD             # 定义mysql root用户密码
                value: root
              - name: MYSQL_DATABASE                  # 创建一个数据库 名为 wordpress
                value: wordpress
              - name: MYSQL_USER                              # wordpress数据库的用户名
                value: wordpress
              - name: MYSQL_PASSWORD                  # wordpress数据库的密码
                value: wordpress
              volumeMounts:                                   # 指定容器的映射目录
              - name: db
                mountPath: /var/lib/mysql
            volumes:                                                  # 指定宿主机的映射目录
            - name: db
              hostPath:
                path: /var/lib/mysql
      ---
      # 定义 Service 资源
      apiVersion: v1
      kind: Service
      metadata:
        name: mysql
        namespace: wordpress
      spec:
        type: NodePort
        selector:
          app: mysql
        ports:
        - name: mysqlport
          protocol: TCP
          port: 3306
          targetPort: dbport
      
    • 创建 wordpress.yaml 文件

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: wordpress-deploy
        namespace: wordpress
        labels:
          app: wordpress
      spec:
        selector:
          matchLabels:
            app: wordpress
        template:
          metadata:
            labels:
              app: wordpress
          spec:
            containers:
            - name: wordpress
              image: wordpress
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 80
                name: wdport
              env:
              - name: WORDPRESS_DB_HOST         # 指定数据库ip:port
                value: 10.104.83.208:3306        # 这里用mysql的service的ip、名称或pod的ip都可以
              - name: WORDPRESS_DB_USER         # 指定数据库用户名
                value: wordpress
              - name: WORDPRESS_DB_PASSWORD     # 指定数据库密码
                value: wordpress
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: wordpress
        namespace: wordpress
      spec:
        type: NodePort                          # 指定 Service 网络模式
        selector:
          app: wordpress
        ports:
        - name: wordpressport
          protocol: TCP
          port: 80
          targetPort: wdport
      
    • 创建资源

      # 创建 wordpress-db
      [root@master-kubeadm-k8s wordpress]# kubectl apply -f wordpress-db.yaml
      deployment.apps/mysql-deploy created
      service/mysql created
      
      # 创建 wordpress
      [root@master-kubeadm-k8s wordpress]# kubectl apply -f wordpress.yaml
      deployment.apps/wordpress-deploy created
      service/wordpress created
      
      # 查看 Pod
      [root@master-kubeadm-k8s wordpress]# kubectl get pods -n wordpress
      NAME                                READY   STATUS    RESTARTS   AGE
      mysql-deploy-868f4cbd7b-chkw5       1/1     Running   0          4m10s
      wordpress-deploy-5c898774dc-8kckq   1/1     Running   0          2m55s
      
      # 查看 Service,得到 nodePort 32731
      [root@master-kubeadm-k8s wordpress]# kubectl get svc -n wordpress
      NAME        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
      mysql       ClusterIP   10.104.83.208    <none>        3306/TCP       3m14s
      wordpress   NodePort    10.100.137.131   <none>        80:32731/TCP   2m56s
      
    • 测试

      访问宿主机 ip:32731

      image.png

    若出现访问不通的情况, 可以在宿主机执行 iptables -P FORWARD ACCEPT 命令就可以解决

    2.2、Spring Boot 项目部署

    2.2.1 搭建说明

    • 准备服务,生成 Jar 文件并上传服务器
    • 服务是自己的项目代码,需要编写Dockerfile
    • 镜像上传镜像仓库
    • 编写 YAML 文件
      • 为了供外部访问,采用 Ingress controller方式进行通信

    2.2.2 服务搭建

    • 准备服务

      image.png
    • 准备 Jar 包并上传至服务器

    • 编写Dockerfile并生成 image

      FROM openjdk:8-jre-alpine
      COPY springboot-demo-0.0.1-SNAPSHOT.jar /springboot-demo.jar
      ENTRYPOINT ["java","-jar","/springboot-demo.jar"]
      
      [root@master-kubeadm-k8s k8s-springboot-demo]# vi Dockerfile
      
      # 生成 springboot-demo-image
      [root@master-kubeadm-k8s k8s-springboot-demo]# docker build -t springboot-demo-image .
      Sending build context to Docker daemon   17.6MB
      Step 1/3 : FROM openjdk:8-jre-alpine
      8-jre-alpine: Pulling from library/openjdk
      e7c96db7181b: Pull complete
      f910a506b6cb: Pull complete
      b6abafe80f63: Pull complete
      Digest: sha256:f362b165b870ef129cbe730f29065ff37399c0aa8bcab3e44b51c302938c9193
      Status: Downloaded newer image for openjdk:8-jre-alpine
       ---> f7a292bbb70c
      Step 2/3 : COPY springboot-demo-0.0.1-SNAPSHOT.jar /springboot-demo.jar
       ---> 40cbd786e301
      Step 3/3 : ENTRYPOINT ["java","-jar","/springboot-demo.jar"]
       ---> Running in 79f29aff270c
      Removing intermediate container 79f29aff270c
       ---> 845f0d0b2d7f
      Successfully built 845f0d0b2d7f
      Successfully tagged springboot-demo-image:latest
      
    • 上传至阿里云镜像仓库

      # 1、登录阿里云镜像仓库
      [root@master-kubeadm-k8s k8s-springboot-demo]# sudo docker login --username=【用户名】 registry.cn-hangzhou.aliyuncs.com
      Password:
      WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
      Configure a credential helper to remove this warning. See
      https://docs.docker.com/engine/reference/commandline/login/#credentials-store
      Login Succeeded
      
      # 2、打 tag
      docker tag springboot-demo-image registry.cn-hangzhou.aliyuncs.com/【命名空间】/springboot-demo-image:v1.0
      
      # 3、上传镜像
      [root@master-kubeadm-k8s k8s-springboot-demo]# docker push registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image:v1.0
      The push refers to repository [registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image]
      2b85a76d2ba6: Pushed
      edd61588d126: Pushed
      9b9b7f3d56a0: Pushed
      f1b5933fe4b5: Pushed
      v1.0: digest: sha256:d9cd5f2ebd86c3e0c01064156c508c9ea557a8e8df0ae2f79be190844bb4b980 size: 1159
      
      image.png
    • 编写 YAML 文件

      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
              image: registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image:v1.0
              ports: 
              - containerPort: 8080
      ---
      # 创建Pod的Service
      apiVersion: v1
      kind: Service
      metadata: 
        name: springboot-demo
      spec: 
        ports: 
        - port: 80
          protocol: TCP
          targetPort: 8080
        selector: 
          app: springboot-demo
      ---
      # 创建Ingress,定义访问规则,一定要记得提前创建好nginx ingress controller
      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress
      metadata: 
        name: springboot-demo
      spec: 
        rules: 
        - host: tomcat.sunny.com    # windows hosts中配置了与宿主机ip对应的域名
          http: 
            paths: 
            - path: /
              backend: 
                serviceName: springboot-demo
                servicePort: 80
      

      因为在之前的章节演示中,我们已经创建好了 Ingress Controller,所以这里直接写 Ingress规则即可

    • 创建资源

      # 创建资源
      [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl apply -f springboot-demo.yaml
      deployment.apps/springboot-demo created
      service/springboot-demo created
      ingress.networking.k8s.io/springboot-demo created
      
      # 查看 Pod, 发现还没创建好
      [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl get pods
      NAME                               READY   STATUS              RESTARTS   AGE
      springboot-demo-5f6f5c9696-66vvm   0/1     ContainerCreating   0          8s
      
      # 看下 Pod 描述, 看当前在做什么
      [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl describe pod springboot-demo-5f6f5c9696-5gj9k
      # ...省略...
      
      # ===================== 发现拉取镜像失败了 ======================
      Events:
        Type     Reason     Age   From                           Message
        ----     ------     ----  ----                           -------
        Normal   Scheduled  57s   default-scheduler              Successfully assigned default/springboot-demo-5f6f5c9696-5gj9k to worker01-kubeadm-k8s
        Normal   Pulling    55s   kubelet, worker01-kubeadm-k8s  Pulling image "registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image:v1.0"
        Warning  Failed     5s    kubelet, worker01-kubeadm-k8s  Failed to pull image "registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image:v1.0": rpc error: code = Unknown desc = Error response from daemon: pull access denied for registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image, repository does not exist or may require 'docker login'
        Warning  Failed     5s    kubelet, worker01-kubeadm-k8s  Error: ErrImagePull
        Normal   BackOff    4s    kubelet, worker01-kubeadm-k8s  Back-off pulling image "registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image:v1.0"
        Warning  Failed     4s    kubelet, worker01-kubeadm-k8s  Error: ImagePullBackOff
      

      其实这是权限问题,K8S需要有一个认证才能从私有仓库拉取镜像,可以创建 Secret 解决

      如果是公开库就可以正常拉取,不会出现这种问题

      • 解决K8S拉取不了私有镜像仓库的问题

         # 在集群中创建保存授权令牌的 Secret
        [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl create secret docker-registry [自定义secret名称] --docker-server=registry.cn-hangzhou.aliyuncs.com --docker-username=[用户名] --docker-password=[密码] --docker-email=[邮箱]
        secret/registry-aliyun created
              
        # 检查 Secret
        [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl get secret registry-aliyun --output=yaml
        apiVersion: v1
        data:
          .dockerconfigjson: eyJhdXRocyI6eyJyZWdpc3RyeS5jbi1oYW5nemhvdS5hbGl5dW5jcy5jb20iOnsidXNlcm5hbWUiOiJ5enlfemhhb3lhbmdAMTYzLmNvbSIsInBdkjhasjdhksabdkajaksddasdaWwiOiJ5enlfemhhb3lhbmdAMTYzLmNvbSIsImF1dGgiOiJlWHAkcjnhkcnhamoewr3242309jdsjaldj092qeGIxbEJUa2MxTmpJMU5ERTQifX19
        kind: Secret
        metadata:
          creationTimestamp: "2020-04-03T16:50:24Z"
          name: registry-aliyun
          namespace: default
          resourceVersion: "109789"
          selfLink: /api/v1/namespaces/default/secrets/registry-aliyun
          uid: 368a54cd-22ggb-11ea-28ty-5254008afee6
        type: kubernetes.io/dockerconfigjson
        
        • 修改 YAML 文件,增加 Secret认证

          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
                  image: registry.cn-hangzhou.aliyuncs.com/sunny95/springboot-demo-image:v1.0
                  ports: 
                  - containerPort: 8080
                  #=========增加 Secret===========
                imagePullSecrets:
                - name: registry-aliyun   # 注意名称要与创建时指定的名称一致
                  #=========增加 Secret===========
          ---
          # 创建Pod的Service
          apiVersion: v1
          kind: Service
          metadata: 
            name: springboot-demo
          spec: 
            ports: 
            - port: 80
              protocol: TCP
              targetPort: 8080
            selector: 
              app: springboot-demo
          ---
          # 创建Ingress,定义访问规则,一定要记得提前创建好nginx ingress controller
          apiVersion: networking.k8s.io/v1beta1
          kind: Ingress
          metadata: 
            name: springboot-demo
          spec: 
            rules: 
            - host: tomcat.sunny.com    # windows hosts中配置了与宿主机ip对应的域名
              http: 
                paths: 
                - path: /
                  backend: 
                    serviceName: springboot-demo
                    servicePort: 80
          
      • 重新创建资源

        # 创建资源
        [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl apply -f springboot-demo.yaml
        deployment.apps/springboot-demo created
        service/springboot-demo created
        ingress.networking.k8s.io/springboot-demo created
        
        # 已经创建完成
        [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl get pods
        NAME                               READY   STATUS    RESTARTS   AGE
        springboot-demo-75f846fd48-zpwtw   1/1     Running   0          2m2s
        
    • 查看资源

      # 查看 Service
      [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl get svc
      NAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
      kubernetes        ClusterIP   10.96.0.1        <none>        443/TCP   10d
      springboot-demo   ClusterIP   10.109.134.133   <none>        80/TCP    4m27s
      
      # 查看 ingress
      [root@master-kubeadm-k8s k8s-springboot-demo]# kubectl get ingress
      NAME              HOSTS              ADDRESS   PORTS   AGE
      springboot-demo   tomcat.sunny.com             80      4m40s
      
    • 测试

      image.png

    测试成功访问到 SpringBoot 服务

    2.3、Nacos 服务注册与发行

    2.3.1 搭建说明

    • 准备Nacos注册中心
    • 准备两个服务,一个服务依赖另一个服务
      • user、order服务
    • 服务注册至 Nacos
    • 编写两个服务的Dockerfile
    • 编写 YAML 文件
      • Nacos注册中心这里不通过容器部署,所以就不写 YAML 文件了

    2.3.2 服务搭建

    • 准备 Nacos 注册中心

      注册中心的选择是自定义的,这里只是选择了Nacos作为演示,你也可以选择其他的注册中心去测试!

      以单机模式启动 nacos

      image.png

    访问物理机 ip:8848/nacos 即可访问注册中心

    nacos 默认的用户名:nacos,密码:nacos

    image.png
    • 准备user、order项目并验证
      • POM 依赖

        注意:Cloud生态对版本依赖还是挺大的,如果SpringBoot版本与SpringCloud版本不匹配可能会出现问题的

        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.1.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        
        <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-web</artifactId>
                </dependency>
        
                <!--引入nacos client依赖-->
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                </dependency>
            </dependencies>
        
            <dependencyManagement>
                <dependencies>
                    <!--加入Spring Cloud依赖-->
                    <dependency>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-dependencies</artifactId>
                        <version>Greenwich.SR1</version>
                        <type>pom</type>
                        <scope>import</scope>
                    </dependency>
        
                    <!--加入Spring Cloud Alibaba依赖-->
                    <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>
        
      • user 服务

        • 配置文件

          spring:
            cloud:
              nacos:
                discovery:
                  #指定nacos server的地址
                  server-addr: 101.55.33.23:8848
            application:
              name: user
          
          server:
            port: 8080
          
        • controller

          @RestController
          @RequestMapping("/user")
          public class TestController {
          
              @Autowired
              private DiscoveryClient discoveryClient;
          
              /**
               * 通过Cloud提供的 DiscoveryClient 来发现服务
               */
              @RequestMapping("/test")
              public Map<String, Object> findServiceInstance() throws Exception{
                  //查询指定服务名称下的所有实例的信息
                  List<ServiceInstance> list=this.discoveryClient.getInstances("order");
                  ServiceInstance serviceInstance=list.get(0);
                  URI uri = serviceInstance.getUri();
          
                  String testResult = this.testUrl(uri.toString());
          
                  Map<String, Object> map = new HashMap<>();
                  map.put("service", list);
                  map.put("uri", uri.toString());
                  
                  //保存 能否 ping 通 order 服务的结果
                  map.put("testResult", testResult);
          
                  return map;
              }
          
              /**
               * 测试user服务能否 ping 通order服务的ip
               *
               * @param urlString order服务所在机器的ip
               */
              public String testUrl(String urlString){
                  URL url;
                  try {
                      url = new URL(urlString);
                      URLConnection co =  url.openConnection();
                      co.connect();
                      return "连接可用";
                  } catch (Exception e1) {
                      return "连接打不开!";
                  }
              }
          }
          
      • order 服务

        order我们不提供服务接口,我们只通过user服务来访问order服务所在机器的ip判断是否可以连通。

        • 配置文件

          spring:
            cloud:
              nacos:
                discovery:
                  #指定nacos server的地址
                  server-addr: 101.55.33.23:8848
            application:
              name: order
          
          server:
            port: 9090
          
      • 启动服务后即可注册到Nacos

        image.png
    + user服务地址
    
      ![image.png](https://img.haomeiwen.com/i11383008/5e92e3cfa4cf5fd9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    
    + order 服务地址
    
      ![image.png](https://img.haomeiwen.com/i11383008/a15edf4b1e23b76f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    • 本地测试服务

      访问 user 服务,可以正常获取到 order 服务的地址信息

      image.png
    • 编写 2 个项目的 Dockerfile

      • user 服务

        FROM openjdk:8-jre-alpine
        COPY user-0.0.1-SNAPSHOT.jar /user.jar
        ENTRYPOINT ["java","-jar","/user.jar"]
        
      • order 服务

        FROM openjdk:8-jre-alpine
        COPY order-0.0.1-SNAPSHOT.jar /order.jar
        ENTRYPOINT ["java","-jar","/order.jar"]
        
    • 获取 2 个项目的 Jar 包与Dockerfile一起上传服务器

      [root@master-kubeadm-k8s nacos]# ll
      total 0
      drwxr-xr-x. 2 root root 56 Apr  4 06:05 order
      drwxr-xr-x. 2 root root 55 Apr  4 06:05 user
      
      # order 服务
      [root@master-kubeadm-k8s nacos]# ll ./order/
      total 32552
      -rw-r--r--. 1 root root      107 Apr  4 06:05 Dockerfile
      -rw-r--r--. 1 root root 33328956 Apr  4 06:04 order-0.0.1-SNAPSHOT.jar
      
      # user 服务
      [root@master-kubeadm-k8s nacos]# ll ./user/
      total 32556
      -rw-r--r--. 1 root root      104 Apr  4 06:05 Dockerfile
      -rw-r--r--. 1 root root 33330518 Apr  4 06:04 user-0.0.1-SNAPSHOT.jar
      
    • 生成 image 镜像

      # 生成 user-image
      [root@master-kubeadm-k8s user]# docker build -t user-image .
      Sending build context to Docker daemon  33.33MB
      Step 1/3 : FROM openjdk:8-jre-alpine
       ---> f7a292bbb70c
      Step 2/3 : COPY user-0.0.1-SNAPSHOT.jar /user.jar
       ---> cdcf57ffcd9e
      Step 3/3 : ENTRYPOINT ["java","-jar","/user.jar"]
       ---> Running in fcebef970173
      Removing intermediate container fcebef970173
       ---> c791a8564979
      Successfully built c791a8564979
      Successfully tagged user-image:latest
      
      # 生成 order-image
      [root@master-kubeadm-k8s order]# docker build -t order-image .
      Sending build context to Docker daemon  33.33MB
      Step 1/3 : FROM openjdk:8-jre-alpine
       ---> f7a292bbb70c
      Step 2/3 : COPY order-0.0.1-SNAPSHOT.jar /order.jar
       ---> 60d8a5f1f8d1
      Step 3/3 : ENTRYPOINT ["java","-jar","/order.jar"]
       ---> Running in ca058de2b8a0
      Removing intermediate container ca058de2b8a0
       ---> e27b4f1bfce9
      Successfully built e27b4f1bfce9
      Successfully tagged order-image:latest
      
    • 上传 image 到镜像仓库

      一般K8S要使用镜像都需要上传到镜像仓库,让它从网上去下载镜像,因为K8S在创建Pod不是只在固定的节点创建的,它会分配到不同的节点上。

      如果不想将 image 上传镜像仓库,那只能在所有节点中都创建出 image才行

      # 为 user-image 打 tag
      [root@master-kubeadm-k8s user]# docker tag user-image registry.cn-hangzhou.aliyuncs.com/zhao_yang/user-image:v1.0
      
      # 上传 user-image 到镜像仓库
      [root@master-kubeadm-k8s user]# docker push registry.cn-hangzhou.aliyuncs.com/zhao_yang/user-image:v1.0
      The push refers to repository [registry.cn-hangzhou.aliyuncs.com/zhao_yang/user-image]
      bc5590316af2: Pushed
      edd61588d126: Pushed
      9b9b7f3d56a0: Pushed
      f1b5933fe4b5: Pushed
      v1.0: digest: sha256:837894b2657b7084bdc64ggfddf347afc27ae1a8dfg324bdd238aa108c3464 size: 1159
      
      # 为 order-image 打 tag
      [root@master-kubeadm-k8s user]# docker tag order-image registry.cn-hangzhou.aliyuncs.com/zhao_yang/order-image:v1.0
      
      [root@master-kubeadm-k8s ~]# docker push registry.cn-hangzhou.aliyuncs.com/zhao_yang/order-image:v1.0
      The push refers to repository [registry.cn-hangzhou.aliyuncs.com/zhao_yang/order-image]
      0b5a4e8a7fda: Pushed
      edd61588d126: Pushed
      9b9b7f3d56a0: Pushed
      f1b5933fe4b5: Pushed
      v1.0: digest: sha256:896088772c5f1c187db2645e29fsdghdfg4328c8c94dd783ddfg32ab7618d50 size: 1159
      
    • 编写 YAML 文件

      • user 服务

        # 以Deployment部署Pod
        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: registry.cn-hangzhou.aliyuncs.com/zhao_yang/user-image:v1.0
                imagePullPolicy: IfNotPresent
                ports: 
                - containerPort: 8080
        ---
        # 创建Pod的Service
        apiVersion: v1
        kind: Service
        metadata: 
          name: user
        spec: 
          ports: 
          - port: 80
            protocol: TCP
            targetPort: 8080
          selector: 
            app: user
        ---
        # 创建Ingress,定义访问规则
        apiVersion: networking.k8s.io/v1beta1
        kind: Ingress
        metadata: 
          name: user
        spec: 
          rules: 
          - host: tomcat.sunny.com
            http: 
              paths: 
              - path: /
                backend: 
                  serviceName: user
                  servicePort: 80
        
      • order 服务

        order 服务无需对外开放,所以不需要编写 Ingress 规则

        # 以Deployment部署Pod
        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: registry.cn-hangzhou.aliyuncs.com/zhao_yang/order-image:v1.0
                imagePullPolicy: IfNotPresent
                ports: 
                - containerPort: 9090
        ---
        # 创建Pod的Service
        apiVersion: v1
        kind: Service
        metadata: 
          name: order
        spec: 
          ports: 
          - port: 80
            protocol: TCP
            targetPort: 9090
          selector: 
            app: order
        
    • 创建资源

      # 创建 user 资源
      [root@master-kubeadm-k8s user]# kubectl apply -f nacos-user.yaml
      deployment.apps/user created
      service/user created
      ingress.networking.k8s.io/user created
      
      # 创建 order 资源
      [root@master-kubeadm-k8s order]# kubectl apply -f nacos-order.yaml
      deployment.apps/order created
      service/order created
      
    • 查看资源

      # 服务都正常运行了
      [root@master-kubeadm-k8s order]# kubectl get pods
      NAME                    READY   STATUS    RESTARTS   AGE
      order-d5f8d8b44-2p4m4   1/1     Running   0          4m30s
      user-54b8fccd67-9925h   1/1     Running   0          7m2s
      
      # 查看 Ingress
      [root@master-kubeadm-k8s order]# kubectl get ingress
      NAME   HOSTS              ADDRESS   PORTS   AGE
      user   tomcat.sunny.com             80      7m52s
      
    • 查看Nacos注册中心

      服务正常注册

      image.png
    • 验证访问

      测试成功

      image.png

    2.3.3 服务注册可能存在的坑

    现在的情况是 user 与 order 服务都部署在集群内,通信是肯定没问题的。

    如果 user 服务是运行在外部的,以现在的配置,user 服务肯定是无法访问到 集群内的 order 服务的,因为他们注册到 Nacos 的 IP 不是在同一个网段的,所以肯定无法连通!

    • user

      image.png
    • order

      image.png
    • 测试

      image.png
    • 解决办法

      因为 order 服务注册到 Nacos 的IP是用于集群内通信的,那我们只要想办法把这个IP换掉,换成外部服务可以 ping 通的 IP 不就可以了?

      以我们现在学习过的网络知识,我们知道外部服务要访问集群内的服务,目前有两种方式:

      • NodePort
      • HostPort

      由于NodePort会在集群内所有节点都开放一个端口,所以我们不推荐使用。

      而 HostPort 仅仅是在Pod所在节点开放端口,其实 HostPort 就是 Docker 中的 Host 网络模式,它是共享宿主机的 IP 与 端口的。这种方式也是现在比较推荐的做法!

      使用HostPort网络模式的情况下,如果服务高可用会有端口冲突问题

      可以使用 Pod 的调度策略,尽可能在高可用的情况下,不将pod分配到同一个Worker Node中

    • 修改 order 服务的 YAML 文件

      # 以Deployment部署Pod
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: order
      spec:
        selector:
          matchLabels:
            app: order
        replicas: 1
        template:
          metadata:
            labels:
              app: order
          spec:
            # ============修改为HostPort模式=============
            hostNetwork: true
            # ============修改为HostPort模式=============
            containers:
            - name: order
              image: registry.cn-hangzhou.aliyuncs.com/zhao_yang/order-image:v1.0
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 9090
      ---
      # 创建Pod的Service
      apiVersion: v1
      kind: Service
      metadata:
        name: order
      spec:
        ports:
        - port: 80
          protocol: TCP
          targetPort: 9090
        selector:
          app: order
      
    • 重新创建资源并查看 Nacos 中 order 服务的地址信息

    image.png

    结果发现这并不是我想要的IP,我们检查一下这个容器使用的网卡信息。

    image.png

    从这里发现原因,它是把 eth0 网卡的IP注册上去了,这个IP是没法通过外部来访问的,我们要修改让它使用 eth1 网卡才行。

    • Nacos解决方案

      • 通过查看文档,可以选择配置不同的网卡或者IP

        (参考org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties的配置)

      • 选择固定网卡配置项

        • 在 order 项目的配置文件中增加配置

          spring:
            cloud:
              nacos:
                discovery:
                  #指定nacos server的地址
                  server-addr: 101.111.45.23:8848
                  # 指定网卡配置项
                  network-interface: eth1
            application:
              name: order
          
          server:
            port: 9090
          
      • 重新生成 Jar、image,重新创建资源

      • 查看Nacos中 order 服务的地址信息

        image.png

    现在这个IP是我们想要的了

    • 测试

      image.png
    至此,三个案例就都演示完成了!中间也是遇到了不少坑,花了不少时间解决错误,希望这个笔记也能帮到大家少碰到一些坑吧!!

    相关文章

      网友评论

        本文标题:五、Kubernetes 实战项目搭建

        本文链接:https://www.haomeiwen.com/subject/czmjphtx.html